MDL-77470 editor_tiny: Apply upstream security fixes
[moodle.git] / lib / editor / tiny / js / tinymce / themes / silver / theme.js
blob7a062cadb428a5508e1bb9b67dfba67d5fb616d9
1 /**
2  * TinyMCE version 6.2.0 (2022-09-08)
3  */
5 (function () {
6     'use strict';
8     const getPrototypeOf$2 = Object.getPrototypeOf;
9     const hasProto = (v, constructor, predicate) => {
10       if (predicate(v, constructor.prototype)) {
11         return true;
12       } else {
13         return v.constructor?.name === constructor.name;
14       }
15     };
16     const typeOf = x => {
17       const t = typeof x;
18       if (x === null) {
19         return 'null';
20       } else if (t === 'object' && Array.isArray(x)) {
21         return 'array';
22       } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
23         return 'string';
24       } else {
25         return t;
26       }
27     };
28     const isType$1 = type => value => typeOf(value) === type;
29     const isSimpleType = type => value => typeof value === type;
30     const eq$1 = t => a => t === a;
31     const is$2 = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
32     const isString = isType$1('string');
33     const isObject = isType$1('object');
34     const isPlainObject = value => is$2(value, Object);
35     const isArray = isType$1('array');
36     const isNull = eq$1(null);
37     const isBoolean = isSimpleType('boolean');
38     const isUndefined = eq$1(undefined);
39     const isNullable = a => a === null || a === undefined;
40     const isNonNullable = a => !isNullable(a);
41     const isFunction = isSimpleType('function');
42     const isNumber = isSimpleType('number');
43     const isArrayOf = (value, pred) => {
44       if (isArray(value)) {
45         for (let i = 0, len = value.length; i < len; ++i) {
46           if (!pred(value[i])) {
47             return false;
48           }
49         }
50         return true;
51       }
52       return false;
53     };
55     const noop = () => {
56     };
57     const noarg = f => () => f();
58     const compose = (fa, fb) => {
59       return (...args) => {
60         return fa(fb.apply(null, args));
61       };
62     };
63     const compose1 = (fbc, fab) => a => fbc(fab(a));
64     const constant$1 = value => {
65       return () => {
66         return value;
67       };
68     };
69     const identity = x => {
70       return x;
71     };
72     const tripleEquals = (a, b) => {
73       return a === b;
74     };
75     function curry(fn, ...initialArgs) {
76       return (...restArgs) => {
77         const all = initialArgs.concat(restArgs);
78         return fn.apply(null, all);
79       };
80     }
81     const not = f => t => !f(t);
82     const die = msg => {
83       return () => {
84         throw new Error(msg);
85       };
86     };
87     const apply$1 = f => {
88       return f();
89     };
90     const never = constant$1(false);
91     const always = constant$1(true);
93     var global$a = tinymce.util.Tools.resolve('tinymce.ThemeManager');
95     class Optional {
96       constructor(tag, value) {
97         this.tag = tag;
98         this.value = value;
99       }
100       static some(value) {
101         return new Optional(true, value);
102       }
103       static none() {
104         return Optional.singletonNone;
105       }
106       fold(onNone, onSome) {
107         if (this.tag) {
108           return onSome(this.value);
109         } else {
110           return onNone();
111         }
112       }
113       isSome() {
114         return this.tag;
115       }
116       isNone() {
117         return !this.tag;
118       }
119       map(mapper) {
120         if (this.tag) {
121           return Optional.some(mapper(this.value));
122         } else {
123           return Optional.none();
124         }
125       }
126       bind(binder) {
127         if (this.tag) {
128           return binder(this.value);
129         } else {
130           return Optional.none();
131         }
132       }
133       exists(predicate) {
134         return this.tag && predicate(this.value);
135       }
136       forall(predicate) {
137         return !this.tag || predicate(this.value);
138       }
139       filter(predicate) {
140         if (!this.tag || predicate(this.value)) {
141           return this;
142         } else {
143           return Optional.none();
144         }
145       }
146       getOr(replacement) {
147         return this.tag ? this.value : replacement;
148       }
149       or(replacement) {
150         return this.tag ? this : replacement;
151       }
152       getOrThunk(thunk) {
153         return this.tag ? this.value : thunk();
154       }
155       orThunk(thunk) {
156         return this.tag ? this : thunk();
157       }
158       getOrDie(message) {
159         if (!this.tag) {
160           throw new Error(message ?? 'Called getOrDie on None');
161         } else {
162           return this.value;
163         }
164       }
165       static from(value) {
166         return isNonNullable(value) ? Optional.some(value) : Optional.none();
167       }
168       getOrNull() {
169         return this.tag ? this.value : null;
170       }
171       getOrUndefined() {
172         return this.value;
173       }
174       each(worker) {
175         if (this.tag) {
176           worker(this.value);
177         }
178       }
179       toArray() {
180         return this.tag ? [this.value] : [];
181       }
182       toString() {
183         return this.tag ? `some(${ this.value })` : 'none()';
184       }
185     }
186     Optional.singletonNone = new Optional(false);
188     const nativeSlice = Array.prototype.slice;
189     const nativeIndexOf = Array.prototype.indexOf;
190     const nativePush = Array.prototype.push;
191     const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
192     const indexOf = (xs, x) => {
193       const r = rawIndexOf(xs, x);
194       return r === -1 ? Optional.none() : Optional.some(r);
195     };
196     const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
197     const exists = (xs, pred) => {
198       for (let i = 0, len = xs.length; i < len; i++) {
199         const x = xs[i];
200         if (pred(x, i)) {
201           return true;
202         }
203       }
204       return false;
205     };
206     const range$2 = (num, f) => {
207       const r = [];
208       for (let i = 0; i < num; i++) {
209         r.push(f(i));
210       }
211       return r;
212     };
213     const chunk$1 = (array, size) => {
214       const r = [];
215       for (let i = 0; i < array.length; i += size) {
216         const s = nativeSlice.call(array, i, i + size);
217         r.push(s);
218       }
219       return r;
220     };
221     const map$2 = (xs, f) => {
222       const len = xs.length;
223       const r = new Array(len);
224       for (let i = 0; i < len; i++) {
225         const x = xs[i];
226         r[i] = f(x, i);
227       }
228       return r;
229     };
230     const each$1 = (xs, f) => {
231       for (let i = 0, len = xs.length; i < len; i++) {
232         const x = xs[i];
233         f(x, i);
234       }
235     };
236     const eachr = (xs, f) => {
237       for (let i = xs.length - 1; i >= 0; i--) {
238         const x = xs[i];
239         f(x, i);
240       }
241     };
242     const partition$3 = (xs, pred) => {
243       const pass = [];
244       const fail = [];
245       for (let i = 0, len = xs.length; i < len; i++) {
246         const x = xs[i];
247         const arr = pred(x, i) ? pass : fail;
248         arr.push(x);
249       }
250       return {
251         pass,
252         fail
253       };
254     };
255     const filter$2 = (xs, pred) => {
256       const r = [];
257       for (let i = 0, len = xs.length; i < len; i++) {
258         const x = xs[i];
259         if (pred(x, i)) {
260           r.push(x);
261         }
262       }
263       return r;
264     };
265     const foldr = (xs, f, acc) => {
266       eachr(xs, (x, i) => {
267         acc = f(acc, x, i);
268       });
269       return acc;
270     };
271     const foldl = (xs, f, acc) => {
272       each$1(xs, (x, i) => {
273         acc = f(acc, x, i);
274       });
275       return acc;
276     };
277     const findUntil = (xs, pred, until) => {
278       for (let i = 0, len = xs.length; i < len; i++) {
279         const x = xs[i];
280         if (pred(x, i)) {
281           return Optional.some(x);
282         } else if (until(x, i)) {
283           break;
284         }
285       }
286       return Optional.none();
287     };
288     const find$5 = (xs, pred) => {
289       return findUntil(xs, pred, never);
290     };
291     const findIndex$1 = (xs, pred) => {
292       for (let i = 0, len = xs.length; i < len; i++) {
293         const x = xs[i];
294         if (pred(x, i)) {
295           return Optional.some(i);
296         }
297       }
298       return Optional.none();
299     };
300     const flatten = xs => {
301       const r = [];
302       for (let i = 0, len = xs.length; i < len; ++i) {
303         if (!isArray(xs[i])) {
304           throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
305         }
306         nativePush.apply(r, xs[i]);
307       }
308       return r;
309     };
310     const bind$3 = (xs, f) => flatten(map$2(xs, f));
311     const forall = (xs, pred) => {
312       for (let i = 0, len = xs.length; i < len; ++i) {
313         const x = xs[i];
314         if (pred(x, i) !== true) {
315           return false;
316         }
317       }
318       return true;
319     };
320     const reverse = xs => {
321       const r = nativeSlice.call(xs, 0);
322       r.reverse();
323       return r;
324     };
325     const difference = (a1, a2) => filter$2(a1, x => !contains$2(a2, x));
326     const mapToObject = (xs, f) => {
327       const r = {};
328       for (let i = 0, len = xs.length; i < len; i++) {
329         const x = xs[i];
330         r[String(x)] = f(x, i);
331       }
332       return r;
333     };
334     const pure$2 = x => [x];
335     const sort = (xs, comparator) => {
336       const copy = nativeSlice.call(xs, 0);
337       copy.sort(comparator);
338       return copy;
339     };
340     const get$h = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
341     const head = xs => get$h(xs, 0);
342     const last$1 = xs => get$h(xs, xs.length - 1);
343     const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x);
344     const findMap = (arr, f) => {
345       for (let i = 0; i < arr.length; i++) {
346         const r = f(arr[i], i);
347         if (r.isSome()) {
348           return r;
349         }
350       }
351       return Optional.none();
352     };
354     const keys = Object.keys;
355     const hasOwnProperty$1 = Object.hasOwnProperty;
356     const each = (obj, f) => {
357       const props = keys(obj);
358       for (let k = 0, len = props.length; k < len; k++) {
359         const i = props[k];
360         const x = obj[i];
361         f(x, i);
362       }
363     };
364     const map$1 = (obj, f) => {
365       return tupleMap(obj, (x, i) => ({
366         k: i,
367         v: f(x, i)
368       }));
369     };
370     const tupleMap = (obj, f) => {
371       const r = {};
372       each(obj, (x, i) => {
373         const tuple = f(x, i);
374         r[tuple.k] = tuple.v;
375       });
376       return r;
377     };
378     const objAcc = r => (x, i) => {
379       r[i] = x;
380     };
381     const internalFilter = (obj, pred, onTrue, onFalse) => {
382       each(obj, (x, i) => {
383         (pred(x, i) ? onTrue : onFalse)(x, i);
384       });
385     };
386     const bifilter = (obj, pred) => {
387       const t = {};
388       const f = {};
389       internalFilter(obj, pred, objAcc(t), objAcc(f));
390       return {
391         t,
392         f
393       };
394     };
395     const filter$1 = (obj, pred) => {
396       const t = {};
397       internalFilter(obj, pred, objAcc(t), noop);
398       return t;
399     };
400     const mapToArray = (obj, f) => {
401       const r = [];
402       each(obj, (value, name) => {
403         r.push(f(value, name));
404       });
405       return r;
406     };
407     const find$4 = (obj, pred) => {
408       const props = keys(obj);
409       for (let k = 0, len = props.length; k < len; k++) {
410         const i = props[k];
411         const x = obj[i];
412         if (pred(x, i, obj)) {
413           return Optional.some(x);
414         }
415       }
416       return Optional.none();
417     };
418     const values = obj => {
419       return mapToArray(obj, identity);
420     };
421     const get$g = (obj, key) => {
422       return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
423     };
424     const has$2 = (obj, key) => hasOwnProperty$1.call(obj, key);
425     const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
427     const is$1 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
428     const equals = (lhs, rhs, comparator = tripleEquals) => lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
429     const cat = arr => {
430       const r = [];
431       const push = x => {
432         r.push(x);
433       };
434       for (let i = 0; i < arr.length; i++) {
435         arr[i].each(push);
436       }
437       return r;
438     };
439     const sequence = arr => {
440       const r = [];
441       for (let i = 0; i < arr.length; i++) {
442         const x = arr[i];
443         if (x.isSome()) {
444           r.push(x.getOrDie());
445         } else {
446           return Optional.none();
447         }
448       }
449       return Optional.some(r);
450     };
451     const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
452     const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
453     const mapFrom = (a, f) => a !== undefined && a !== null ? Optional.some(f(a)) : Optional.none();
454     const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
456     const addToEnd = (str, suffix) => {
457       return str + suffix;
458     };
459     const removeFromStart = (str, numChars) => {
460       return str.substring(numChars);
461     };
463     const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
464     const removeLeading = (str, prefix) => {
465       return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
466     };
467     const ensureTrailing = (str, suffix) => {
468       return endsWith(str, suffix) ? str : addToEnd(str, suffix);
469     };
470     const contains$1 = (str, substr, start = 0, end) => {
471       const idx = str.indexOf(substr, start);
472       if (idx !== -1) {
473         return isUndefined(end) ? true : idx + substr.length <= end;
474       } else {
475         return false;
476       }
477     };
478     const startsWith = (str, prefix) => {
479       return checkRange(str, prefix, 0);
480     };
481     const endsWith = (str, suffix) => {
482       return checkRange(str, suffix, str.length - suffix.length);
483     };
484     const blank = r => s => s.replace(r, '');
485     const trim$1 = blank(/^\s+|\s+$/g);
486     const isNotEmpty = s => s.length > 0;
487     const isEmpty = s => !isNotEmpty(s);
489     const isSupported$1 = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
491     const fromHtml$2 = (html, scope) => {
492       const doc = scope || document;
493       const div = doc.createElement('div');
494       div.innerHTML = html;
495       if (!div.hasChildNodes() || div.childNodes.length > 1) {
496         const message = 'HTML does not have a single root node';
497         console.error(message, html);
498         throw new Error(message);
499       }
500       return fromDom(div.childNodes[0]);
501     };
502     const fromTag = (tag, scope) => {
503       const doc = scope || document;
504       const node = doc.createElement(tag);
505       return fromDom(node);
506     };
507     const fromText = (text, scope) => {
508       const doc = scope || document;
509       const node = doc.createTextNode(text);
510       return fromDom(node);
511     };
512     const fromDom = node => {
513       if (node === null || node === undefined) {
514         throw new Error('Node cannot be null or undefined');
515       }
516       return { dom: node };
517     };
518     const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
519     const SugarElement = {
520       fromHtml: fromHtml$2,
521       fromTag,
522       fromText,
523       fromDom,
524       fromPoint
525     };
527     const Global = typeof window !== 'undefined' ? window : Function('return this;')();
529     const path$1 = (parts, scope) => {
530       let o = scope !== undefined && scope !== null ? scope : Global;
531       for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
532         o = o[parts[i]];
533       }
534       return o;
535     };
536     const resolve = (p, scope) => {
537       const parts = p.split('.');
538       return path$1(parts, scope);
539     };
541     const unsafe = (name, scope) => {
542       return resolve(name, scope);
543     };
544     const getOrDie$1 = (name, scope) => {
545       const actual = unsafe(name, scope);
546       if (actual === undefined || actual === null) {
547         throw new Error(name + ' not available on this browser');
548       }
549       return actual;
550     };
552     const getPrototypeOf$1 = Object.getPrototypeOf;
553     const sandHTMLElement = scope => {
554       return getOrDie$1('HTMLElement', scope);
555     };
556     const isPrototypeOf = x => {
557       const scope = resolve('ownerDocument.defaultView', x);
558       return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name));
559     };
561     const DOCUMENT = 9;
562     const DOCUMENT_FRAGMENT = 11;
563     const ELEMENT = 1;
564     const TEXT = 3;
566     const name$3 = element => {
567       const r = element.dom.nodeName;
568       return r.toLowerCase();
569     };
570     const type$1 = element => element.dom.nodeType;
571     const isType = t => element => type$1(element) === t;
572     const isHTMLElement = element => isElement$1(element) && isPrototypeOf(element.dom);
573     const isElement$1 = isType(ELEMENT);
574     const isText = isType(TEXT);
575     const isDocument = isType(DOCUMENT);
576     const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
577     const isTag = tag => e => isElement$1(e) && name$3(e) === tag;
579     const is = (element, selector) => {
580       const dom = element.dom;
581       if (dom.nodeType !== ELEMENT) {
582         return false;
583       } else {
584         const elem = dom;
585         if (elem.matches !== undefined) {
586           return elem.matches(selector);
587         } else if (elem.msMatchesSelector !== undefined) {
588           return elem.msMatchesSelector(selector);
589         } else if (elem.webkitMatchesSelector !== undefined) {
590           return elem.webkitMatchesSelector(selector);
591         } else if (elem.mozMatchesSelector !== undefined) {
592           return elem.mozMatchesSelector(selector);
593         } else {
594           throw new Error('Browser lacks native selectors');
595         }
596       }
597     };
598     const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
599     const all$3 = (selector, scope) => {
600       const base = scope === undefined ? document : scope.dom;
601       return bypassSelector(base) ? [] : map$2(base.querySelectorAll(selector), SugarElement.fromDom);
602     };
603     const one = (selector, scope) => {
604       const base = scope === undefined ? document : scope.dom;
605       return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
606     };
608     const eq = (e1, e2) => e1.dom === e2.dom;
609     const contains = (e1, e2) => {
610       const d1 = e1.dom;
611       const d2 = e2.dom;
612       return d1 === d2 ? false : d1.contains(d2);
613     };
615     const owner$4 = element => SugarElement.fromDom(element.dom.ownerDocument);
616     const documentOrOwner = dos => isDocument(dos) ? dos : owner$4(dos);
617     const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
618     const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
619     const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
620     const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
621     const offsetParent = element => Optional.from(element.dom.offsetParent).map(SugarElement.fromDom);
622     const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
623     const children = element => map$2(element.dom.childNodes, SugarElement.fromDom);
624     const child$2 = (element, index) => {
625       const cs = element.dom.childNodes;
626       return Optional.from(cs[index]).map(SugarElement.fromDom);
627     };
628     const firstChild = element => child$2(element, 0);
629     const spot = (element, offset) => ({
630       element,
631       offset
632     });
633     const leaf = (element, offset) => {
634       const cs = children(element);
635       return cs.length > 0 && offset < cs.length ? spot(cs[offset], 0) : spot(element, offset);
636     };
638     const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
639     const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
640     const isSupported = constant$1(supported);
641     const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
642     const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
643     const isInShadowRoot = e => getShadowRoot(e).isSome();
644     const getShadowRoot = e => {
645       const r = getRootNode(e);
646       return isShadowRoot(r) ? Optional.some(r) : Optional.none();
647     };
648     const getShadowHost = e => SugarElement.fromDom(e.dom.host);
649     const getOriginalEventTarget = event => {
650       if (isSupported() && isNonNullable(event.target)) {
651         const el = SugarElement.fromDom(event.target);
652         if (isElement$1(el) && isOpenShadowHost(el)) {
653           if (event.composed && event.composedPath) {
654             const composedPath = event.composedPath();
655             if (composedPath) {
656               return head(composedPath);
657             }
658           }
659         }
660       }
661       return Optional.from(event.target);
662     };
663     const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
665     const inBody = element => {
666       const dom = isText(element) ? element.dom.parentNode : element.dom;
667       if (dom === undefined || dom === null || dom.ownerDocument === null) {
668         return false;
669       }
670       const doc = dom.ownerDocument;
671       return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
672     };
673     const body = () => getBody(SugarElement.fromDom(document));
674     const getBody = doc => {
675       const b = doc.dom.body;
676       if (b === null || b === undefined) {
677         throw new Error('Body is not available yet');
678       }
679       return SugarElement.fromDom(b);
680     };
682     const rawSet = (dom, key, value) => {
683       if (isString(value) || isBoolean(value) || isNumber(value)) {
684         dom.setAttribute(key, value + '');
685       } else {
686         console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
687         throw new Error('Attribute value was not simple');
688       }
689     };
690     const set$9 = (element, key, value) => {
691       rawSet(element.dom, key, value);
692     };
693     const setAll$1 = (element, attrs) => {
694       const dom = element.dom;
695       each(attrs, (v, k) => {
696         rawSet(dom, k, v);
697       });
698     };
699     const get$f = (element, key) => {
700       const v = element.dom.getAttribute(key);
701       return v === null ? undefined : v;
702     };
703     const getOpt = (element, key) => Optional.from(get$f(element, key));
704     const has$1 = (element, key) => {
705       const dom = element.dom;
706       return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
707     };
708     const remove$7 = (element, key) => {
709       element.dom.removeAttribute(key);
710     };
711     const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
712       acc[attr.name] = attr.value;
713       return acc;
714     }, {});
716     const internalSet = (dom, property, value) => {
717       if (!isString(value)) {
718         console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
719         throw new Error('CSS value must be a string: ' + value);
720       }
721       if (isSupported$1(dom)) {
722         dom.style.setProperty(property, value);
723       }
724     };
725     const internalRemove = (dom, property) => {
726       if (isSupported$1(dom)) {
727         dom.style.removeProperty(property);
728       }
729     };
730     const set$8 = (element, property, value) => {
731       const dom = element.dom;
732       internalSet(dom, property, value);
733     };
734     const setAll = (element, css) => {
735       const dom = element.dom;
736       each(css, (v, k) => {
737         internalSet(dom, k, v);
738       });
739     };
740     const setOptions = (element, css) => {
741       const dom = element.dom;
742       each(css, (v, k) => {
743         v.fold(() => {
744           internalRemove(dom, k);
745         }, value => {
746           internalSet(dom, k, value);
747         });
748       });
749     };
750     const get$e = (element, property) => {
751       const dom = element.dom;
752       const styles = window.getComputedStyle(dom);
753       const r = styles.getPropertyValue(property);
754       return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
755     };
756     const getUnsafeProperty = (dom, property) => isSupported$1(dom) ? dom.style.getPropertyValue(property) : '';
757     const getRaw = (element, property) => {
758       const dom = element.dom;
759       const raw = getUnsafeProperty(dom, property);
760       return Optional.from(raw).filter(r => r.length > 0);
761     };
762     const getAllRaw = element => {
763       const css = {};
764       const dom = element.dom;
765       if (isSupported$1(dom)) {
766         for (let i = 0; i < dom.style.length; i++) {
767           const ruleName = dom.style.item(i);
768           css[ruleName] = dom.style[ruleName];
769         }
770       }
771       return css;
772     };
773     const isValidValue = (tag, property, value) => {
774       const element = SugarElement.fromTag(tag);
775       set$8(element, property, value);
776       const style = getRaw(element, property);
777       return style.isSome();
778     };
779     const remove$6 = (element, property) => {
780       const dom = element.dom;
781       internalRemove(dom, property);
782       if (is$1(getOpt(element, 'style').map(trim$1), '')) {
783         remove$7(element, 'style');
784       }
785     };
786     const reflow = e => e.dom.offsetWidth;
788     const Dimension = (name, getOffset) => {
789       const set = (element, h) => {
790         if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
791           throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
792         }
793         const dom = element.dom;
794         if (isSupported$1(dom)) {
795           dom.style[name] = h + 'px';
796         }
797       };
798       const get = element => {
799         const r = getOffset(element);
800         if (r <= 0 || r === null) {
801           const css = get$e(element, name);
802           return parseFloat(css) || 0;
803         }
804         return r;
805       };
806       const getOuter = get;
807       const aggregate = (element, properties) => foldl(properties, (acc, property) => {
808         const val = get$e(element, property);
809         const value = val === undefined ? 0 : parseInt(val, 10);
810         return isNaN(value) ? acc : acc + value;
811       }, 0);
812       const max = (element, value, properties) => {
813         const cumulativeInclusions = aggregate(element, properties);
814         const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
815         return absoluteMax;
816       };
817       return {
818         set,
819         get,
820         getOuter,
821         aggregate,
822         max
823       };
824     };
826     const api$2 = Dimension('height', element => {
827       const dom = element.dom;
828       return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
829     });
830     const get$d = element => api$2.get(element);
831     const getOuter$2 = element => api$2.getOuter(element);
832     const setMax$1 = (element, value) => {
833       const inclusions = [
834         'margin-top',
835         'border-top-width',
836         'padding-top',
837         'padding-bottom',
838         'border-bottom-width',
839         'margin-bottom'
840       ];
841       const absMax = api$2.max(element, value, inclusions);
842       set$8(element, 'max-height', absMax + 'px');
843     };
845     const r$1 = (left, top) => {
846       const translate = (x, y) => r$1(left + x, top + y);
847       return {
848         left,
849         top,
850         translate
851       };
852     };
853     const SugarPosition = r$1;
855     const boxPosition = dom => {
856       const box = dom.getBoundingClientRect();
857       return SugarPosition(box.left, box.top);
858     };
859     const firstDefinedOrZero = (a, b) => {
860       if (a !== undefined) {
861         return a;
862       } else {
863         return b !== undefined ? b : 0;
864       }
865     };
866     const absolute$3 = element => {
867       const doc = element.dom.ownerDocument;
868       const body = doc.body;
869       const win = doc.defaultView;
870       const html = doc.documentElement;
871       if (body === element.dom) {
872         return SugarPosition(body.offsetLeft, body.offsetTop);
873       }
874       const scrollTop = firstDefinedOrZero(win?.pageYOffset, html.scrollTop);
875       const scrollLeft = firstDefinedOrZero(win?.pageXOffset, html.scrollLeft);
876       const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
877       const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
878       return viewport$1(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
879     };
880     const viewport$1 = element => {
881       const dom = element.dom;
882       const doc = dom.ownerDocument;
883       const body = doc.body;
884       if (body === dom) {
885         return SugarPosition(body.offsetLeft, body.offsetTop);
886       }
887       if (!inBody(element)) {
888         return SugarPosition(0, 0);
889       }
890       return boxPosition(dom);
891     };
893     const api$1 = Dimension('width', element => element.dom.offsetWidth);
894     const set$7 = (element, h) => api$1.set(element, h);
895     const get$c = element => api$1.get(element);
896     const getOuter$1 = element => api$1.getOuter(element);
897     const setMax = (element, value) => {
898       const inclusions = [
899         'margin-left',
900         'border-left-width',
901         'padding-left',
902         'padding-right',
903         'border-right-width',
904         'margin-right'
905       ];
906       const absMax = api$1.max(element, value, inclusions);
907       set$8(element, 'max-width', absMax + 'px');
908     };
910     const cached = f => {
911       let called = false;
912       let r;
913       return (...args) => {
914         if (!called) {
915           called = true;
916           r = f.apply(null, args);
917         }
918         return r;
919       };
920     };
922     const DeviceType = (os, browser, userAgent, mediaMatch) => {
923       const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
924       const isiPhone = os.isiOS() && !isiPad;
925       const isMobile = os.isiOS() || os.isAndroid();
926       const isTouch = isMobile || mediaMatch('(pointer:coarse)');
927       const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
928       const isPhone = isiPhone || isMobile && !isTablet;
929       const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
930       const isDesktop = !isPhone && !isTablet && !iOSwebview;
931       return {
932         isiPad: constant$1(isiPad),
933         isiPhone: constant$1(isiPhone),
934         isTablet: constant$1(isTablet),
935         isPhone: constant$1(isPhone),
936         isTouch: constant$1(isTouch),
937         isAndroid: os.isAndroid,
938         isiOS: os.isiOS,
939         isWebView: constant$1(iOSwebview),
940         isDesktop: constant$1(isDesktop)
941       };
942     };
944     const firstMatch = (regexes, s) => {
945       for (let i = 0; i < regexes.length; i++) {
946         const x = regexes[i];
947         if (x.test(s)) {
948           return x;
949         }
950       }
951       return undefined;
952     };
953     const find$3 = (regexes, agent) => {
954       const r = firstMatch(regexes, agent);
955       if (!r) {
956         return {
957           major: 0,
958           minor: 0
959         };
960       }
961       const group = i => {
962         return Number(agent.replace(r, '$' + i));
963       };
964       return nu$d(group(1), group(2));
965     };
966     const detect$4 = (versionRegexes, agent) => {
967       const cleanedAgent = String(agent).toLowerCase();
968       if (versionRegexes.length === 0) {
969         return unknown$3();
970       }
971       return find$3(versionRegexes, cleanedAgent);
972     };
973     const unknown$3 = () => {
974       return nu$d(0, 0);
975     };
976     const nu$d = (major, minor) => {
977       return {
978         major,
979         minor
980       };
981     };
982     const Version = {
983       nu: nu$d,
984       detect: detect$4,
985       unknown: unknown$3
986     };
988     const detectBrowser$1 = (browsers, userAgentData) => {
989       return findMap(userAgentData.brands, uaBrand => {
990         const lcBrand = uaBrand.brand.toLowerCase();
991         return find$5(browsers, browser => lcBrand === browser.brand?.toLowerCase()).map(info => ({
992           current: info.name,
993           version: Version.nu(parseInt(uaBrand.version, 10), 0)
994         }));
995       });
996     };
998     const detect$3 = (candidates, userAgent) => {
999       const agent = String(userAgent).toLowerCase();
1000       return find$5(candidates, candidate => {
1001         return candidate.search(agent);
1002       });
1003     };
1004     const detectBrowser = (browsers, userAgent) => {
1005       return detect$3(browsers, userAgent).map(browser => {
1006         const version = Version.detect(browser.versionRegexes, userAgent);
1007         return {
1008           current: browser.name,
1009           version
1010         };
1011       });
1012     };
1013     const detectOs = (oses, userAgent) => {
1014       return detect$3(oses, userAgent).map(os => {
1015         const version = Version.detect(os.versionRegexes, userAgent);
1016         return {
1017           current: os.name,
1018           version
1019         };
1020       });
1021     };
1023     const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
1024     const checkContains = target => {
1025       return uastring => {
1026         return contains$1(uastring, target);
1027       };
1028     };
1029     const browsers = [
1030       {
1031         name: 'Edge',
1032         versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
1033         search: uastring => {
1034           return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
1035         }
1036       },
1037       {
1038         name: 'Chromium',
1039         brand: 'Chromium',
1040         versionRegexes: [
1041           /.*?chrome\/([0-9]+)\.([0-9]+).*/,
1042           normalVersionRegex
1043         ],
1044         search: uastring => {
1045           return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
1046         }
1047       },
1048       {
1049         name: 'IE',
1050         versionRegexes: [
1051           /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
1052           /.*?rv:([0-9]+)\.([0-9]+).*/
1053         ],
1054         search: uastring => {
1055           return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
1056         }
1057       },
1058       {
1059         name: 'Opera',
1060         versionRegexes: [
1061           normalVersionRegex,
1062           /.*?opera\/([0-9]+)\.([0-9]+).*/
1063         ],
1064         search: checkContains('opera')
1065       },
1066       {
1067         name: 'Firefox',
1068         versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
1069         search: checkContains('firefox')
1070       },
1071       {
1072         name: 'Safari',
1073         versionRegexes: [
1074           normalVersionRegex,
1075           /.*?cpu os ([0-9]+)_([0-9]+).*/
1076         ],
1077         search: uastring => {
1078           return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
1079         }
1080       }
1081     ];
1082     const oses = [
1083       {
1084         name: 'Windows',
1085         search: checkContains('win'),
1086         versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
1087       },
1088       {
1089         name: 'iOS',
1090         search: uastring => {
1091           return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
1092         },
1093         versionRegexes: [
1094           /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
1095           /.*cpu os ([0-9]+)_([0-9]+).*/,
1096           /.*cpu iphone os ([0-9]+)_([0-9]+).*/
1097         ]
1098       },
1099       {
1100         name: 'Android',
1101         search: checkContains('android'),
1102         versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
1103       },
1104       {
1105         name: 'macOS',
1106         search: checkContains('mac os x'),
1107         versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
1108       },
1109       {
1110         name: 'Linux',
1111         search: checkContains('linux'),
1112         versionRegexes: []
1113       },
1114       {
1115         name: 'Solaris',
1116         search: checkContains('sunos'),
1117         versionRegexes: []
1118       },
1119       {
1120         name: 'FreeBSD',
1121         search: checkContains('freebsd'),
1122         versionRegexes: []
1123       },
1124       {
1125         name: 'ChromeOS',
1126         search: checkContains('cros'),
1127         versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
1128       }
1129     ];
1130     const PlatformInfo = {
1131       browsers: constant$1(browsers),
1132       oses: constant$1(oses)
1133     };
1135     const edge = 'Edge';
1136     const chromium = 'Chromium';
1137     const ie = 'IE';
1138     const opera = 'Opera';
1139     const firefox = 'Firefox';
1140     const safari = 'Safari';
1141     const unknown$2 = () => {
1142       return nu$c({
1143         current: undefined,
1144         version: Version.unknown()
1145       });
1146     };
1147     const nu$c = info => {
1148       const current = info.current;
1149       const version = info.version;
1150       const isBrowser = name => () => current === name;
1151       return {
1152         current,
1153         version,
1154         isEdge: isBrowser(edge),
1155         isChromium: isBrowser(chromium),
1156         isIE: isBrowser(ie),
1157         isOpera: isBrowser(opera),
1158         isFirefox: isBrowser(firefox),
1159         isSafari: isBrowser(safari)
1160       };
1161     };
1162     const Browser = {
1163       unknown: unknown$2,
1164       nu: nu$c,
1165       edge: constant$1(edge),
1166       chromium: constant$1(chromium),
1167       ie: constant$1(ie),
1168       opera: constant$1(opera),
1169       firefox: constant$1(firefox),
1170       safari: constant$1(safari)
1171     };
1173     const windows = 'Windows';
1174     const ios = 'iOS';
1175     const android = 'Android';
1176     const linux = 'Linux';
1177     const macos = 'macOS';
1178     const solaris = 'Solaris';
1179     const freebsd = 'FreeBSD';
1180     const chromeos = 'ChromeOS';
1181     const unknown$1 = () => {
1182       return nu$b({
1183         current: undefined,
1184         version: Version.unknown()
1185       });
1186     };
1187     const nu$b = info => {
1188       const current = info.current;
1189       const version = info.version;
1190       const isOS = name => () => current === name;
1191       return {
1192         current,
1193         version,
1194         isWindows: isOS(windows),
1195         isiOS: isOS(ios),
1196         isAndroid: isOS(android),
1197         isMacOS: isOS(macos),
1198         isLinux: isOS(linux),
1199         isSolaris: isOS(solaris),
1200         isFreeBSD: isOS(freebsd),
1201         isChromeOS: isOS(chromeos)
1202       };
1203     };
1204     const OperatingSystem = {
1205       unknown: unknown$1,
1206       nu: nu$b,
1207       windows: constant$1(windows),
1208       ios: constant$1(ios),
1209       android: constant$1(android),
1210       linux: constant$1(linux),
1211       macos: constant$1(macos),
1212       solaris: constant$1(solaris),
1213       freebsd: constant$1(freebsd),
1214       chromeos: constant$1(chromeos)
1215     };
1217     const detect$2 = (userAgent, userAgentDataOpt, mediaMatch) => {
1218       const browsers = PlatformInfo.browsers();
1219       const oses = PlatformInfo.oses();
1220       const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
1221       const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
1222       const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
1223       return {
1224         browser,
1225         os,
1226         deviceType
1227       };
1228     };
1229     const PlatformDetection = { detect: detect$2 };
1231     const mediaMatch = query => window.matchMedia(query).matches;
1232     let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
1233     const detect$1 = () => platform();
1235     const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
1236       target,
1237       x,
1238       y,
1239       stop,
1240       prevent,
1241       kill,
1242       raw
1243     });
1244     const fromRawEvent$1 = rawEvent => {
1245       const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
1246       const stop = () => rawEvent.stopPropagation();
1247       const prevent = () => rawEvent.preventDefault();
1248       const kill = compose(prevent, stop);
1249       return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
1250     };
1251     const handle = (filter, handler) => rawEvent => {
1252       if (filter(rawEvent)) {
1253         handler(fromRawEvent$1(rawEvent));
1254       }
1255     };
1256     const binder = (element, event, filter, handler, useCapture) => {
1257       const wrapped = handle(filter, handler);
1258       element.dom.addEventListener(event, wrapped, useCapture);
1259       return { unbind: curry(unbind, element, event, wrapped, useCapture) };
1260     };
1261     const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
1262     const capture$1 = (element, event, filter, handler) => binder(element, event, filter, handler, true);
1263     const unbind = (element, event, handler, useCapture) => {
1264       element.dom.removeEventListener(event, handler, useCapture);
1265     };
1267     const before$1 = (marker, element) => {
1268       const parent$1 = parent(marker);
1269       parent$1.each(v => {
1270         v.dom.insertBefore(element.dom, marker.dom);
1271       });
1272     };
1273     const after$2 = (marker, element) => {
1274       const sibling = nextSibling(marker);
1275       sibling.fold(() => {
1276         const parent$1 = parent(marker);
1277         parent$1.each(v => {
1278           append$2(v, element);
1279         });
1280       }, v => {
1281         before$1(v, element);
1282       });
1283     };
1284     const prepend$1 = (parent, element) => {
1285       const firstChild$1 = firstChild(parent);
1286       firstChild$1.fold(() => {
1287         append$2(parent, element);
1288       }, v => {
1289         parent.dom.insertBefore(element.dom, v.dom);
1290       });
1291     };
1292     const append$2 = (parent, element) => {
1293       parent.dom.appendChild(element.dom);
1294     };
1295     const appendAt = (parent, element, index) => {
1296       child$2(parent, index).fold(() => {
1297         append$2(parent, element);
1298       }, v => {
1299         before$1(v, element);
1300       });
1301     };
1303     const append$1 = (parent, elements) => {
1304       each$1(elements, x => {
1305         append$2(parent, x);
1306       });
1307     };
1309     const empty = element => {
1310       element.dom.textContent = '';
1311       each$1(children(element), rogue => {
1312         remove$5(rogue);
1313       });
1314     };
1315     const remove$5 = element => {
1316       const dom = element.dom;
1317       if (dom.parentNode !== null) {
1318         dom.parentNode.removeChild(dom);
1319       }
1320     };
1322     const get$b = _DOC => {
1323       const doc = _DOC !== undefined ? _DOC.dom : document;
1324       const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
1325       const y = doc.body.scrollTop || doc.documentElement.scrollTop;
1326       return SugarPosition(x, y);
1327     };
1328     const to = (x, y, _DOC) => {
1329       const doc = _DOC !== undefined ? _DOC.dom : document;
1330       const win = doc.defaultView;
1331       if (win) {
1332         win.scrollTo(x, y);
1333       }
1334     };
1336     const get$a = _win => {
1337       const win = _win === undefined ? window : _win;
1338       if (detect$1().browser.isFirefox()) {
1339         return Optional.none();
1340       } else {
1341         return Optional.from(win.visualViewport);
1342       }
1343     };
1344     const bounds$1 = (x, y, width, height) => ({
1345       x,
1346       y,
1347       width,
1348       height,
1349       right: x + width,
1350       bottom: y + height
1351     });
1352     const getBounds$3 = _win => {
1353       const win = _win === undefined ? window : _win;
1354       const doc = win.document;
1355       const scroll = get$b(SugarElement.fromDom(doc));
1356       return get$a(win).fold(() => {
1357         const html = win.document.documentElement;
1358         const width = html.clientWidth;
1359         const height = html.clientHeight;
1360         return bounds$1(scroll.left, scroll.top, width, height);
1361       }, visualViewport => bounds$1(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height));
1362     };
1364     const getDocument = () => SugarElement.fromDom(document);
1366     const walkUp = (navigation, doc) => {
1367       const frame = navigation.view(doc);
1368       return frame.fold(constant$1([]), f => {
1369         const parent = navigation.owner(f);
1370         const rest = walkUp(navigation, parent);
1371         return [f].concat(rest);
1372       });
1373     };
1374     const pathTo = (element, navigation) => {
1375       const d = navigation.owner(element);
1376       const paths = walkUp(navigation, d);
1377       return Optional.some(paths);
1378     };
1380     const view = doc => {
1381       const element = doc.dom === document ? Optional.none() : Optional.from(doc.dom.defaultView?.frameElement);
1382       return element.map(SugarElement.fromDom);
1383     };
1384     const owner$3 = element => owner$4(element);
1386     var Navigation = /*#__PURE__*/Object.freeze({
1387         __proto__: null,
1388         view: view,
1389         owner: owner$3
1390     });
1392     const find$2 = element => {
1393       const doc = getDocument();
1394       const scroll = get$b(doc);
1395       const path = pathTo(element, Navigation);
1396       return path.fold(curry(absolute$3, element), frames => {
1397         const offset = viewport$1(element);
1398         const r = foldr(frames, (b, a) => {
1399           const loc = viewport$1(a);
1400           return {
1401             left: b.left + loc.left,
1402             top: b.top + loc.top
1403           };
1404         }, {
1405           left: 0,
1406           top: 0
1407         });
1408         return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
1409       });
1410     };
1412     const pointed = (point, width, height) => ({
1413       point,
1414       width,
1415       height
1416     });
1417     const rect = (x, y, width, height) => ({
1418       x,
1419       y,
1420       width,
1421       height
1422     });
1423     const bounds = (x, y, width, height) => ({
1424       x,
1425       y,
1426       width,
1427       height,
1428       right: x + width,
1429       bottom: y + height
1430     });
1431     const box$1 = element => {
1432       const xy = absolute$3(element);
1433       const w = getOuter$1(element);
1434       const h = getOuter$2(element);
1435       return bounds(xy.left, xy.top, w, h);
1436     };
1437     const absolute$2 = element => {
1438       const position = find$2(element);
1439       const width = getOuter$1(element);
1440       const height = getOuter$2(element);
1441       return bounds(position.left, position.top, width, height);
1442     };
1443     const win = () => getBounds$3(window);
1445     const value$4 = value => {
1446       const applyHelper = fn => fn(value);
1447       const constHelper = constant$1(value);
1448       const outputHelper = () => output;
1449       const output = {
1450         tag: true,
1451         inner: value,
1452         fold: (_onError, onValue) => onValue(value),
1453         isValue: always,
1454         isError: never,
1455         map: mapper => Result.value(mapper(value)),
1456         mapError: outputHelper,
1457         bind: applyHelper,
1458         exists: applyHelper,
1459         forall: applyHelper,
1460         getOr: constHelper,
1461         or: outputHelper,
1462         getOrThunk: constHelper,
1463         orThunk: outputHelper,
1464         getOrDie: constHelper,
1465         each: fn => {
1466           fn(value);
1467         },
1468         toOptional: () => Optional.some(value)
1469       };
1470       return output;
1471     };
1472     const error$1 = error => {
1473       const outputHelper = () => output;
1474       const output = {
1475         tag: false,
1476         inner: error,
1477         fold: (onError, _onValue) => onError(error),
1478         isValue: never,
1479         isError: always,
1480         map: outputHelper,
1481         mapError: mapper => Result.error(mapper(error)),
1482         bind: outputHelper,
1483         exists: never,
1484         forall: always,
1485         getOr: identity,
1486         or: identity,
1487         getOrThunk: apply$1,
1488         orThunk: apply$1,
1489         getOrDie: die(String(error)),
1490         each: noop,
1491         toOptional: Optional.none
1492       };
1493       return output;
1494     };
1495     const fromOption = (optional, err) => optional.fold(() => error$1(err), value$4);
1496     const Result = {
1497       value: value$4,
1498       error: error$1,
1499       fromOption
1500     };
1502     var SimpleResultType;
1503     (function (SimpleResultType) {
1504       SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
1505       SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
1506     }(SimpleResultType || (SimpleResultType = {})));
1507     const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
1508     const partition$2 = results => {
1509       const values = [];
1510       const errors = [];
1511       each$1(results, obj => {
1512         fold$1(obj, err => errors.push(err), val => values.push(val));
1513       });
1514       return {
1515         values,
1516         errors
1517       };
1518     };
1519     const mapError = (res, f) => {
1520       if (res.stype === SimpleResultType.Error) {
1521         return {
1522           stype: SimpleResultType.Error,
1523           serror: f(res.serror)
1524         };
1525       } else {
1526         return res;
1527       }
1528     };
1529     const map = (res, f) => {
1530       if (res.stype === SimpleResultType.Value) {
1531         return {
1532           stype: SimpleResultType.Value,
1533           svalue: f(res.svalue)
1534         };
1535       } else {
1536         return res;
1537       }
1538     };
1539     const bind$1 = (res, f) => {
1540       if (res.stype === SimpleResultType.Value) {
1541         return f(res.svalue);
1542       } else {
1543         return res;
1544       }
1545     };
1546     const bindError = (res, f) => {
1547       if (res.stype === SimpleResultType.Error) {
1548         return f(res.serror);
1549       } else {
1550         return res;
1551       }
1552     };
1553     const svalue = v => ({
1554       stype: SimpleResultType.Value,
1555       svalue: v
1556     });
1557     const serror = e => ({
1558       stype: SimpleResultType.Error,
1559       serror: e
1560     });
1561     const toResult$1 = res => fold$1(res, Result.error, Result.value);
1562     const fromResult$1 = res => res.fold(serror, svalue);
1563     const SimpleResult = {
1564       fromResult: fromResult$1,
1565       toResult: toResult$1,
1566       svalue,
1567       partition: partition$2,
1568       serror,
1569       bind: bind$1,
1570       bindError,
1571       map,
1572       mapError,
1573       fold: fold$1
1574     };
1576     const field$2 = (key, newKey, presence, prop) => ({
1577       tag: 'field',
1578       key,
1579       newKey,
1580       presence,
1581       prop
1582     });
1583     const customField$1 = (newKey, instantiator) => ({
1584       tag: 'custom',
1585       newKey,
1586       instantiator
1587     });
1588     const fold = (value, ifField, ifCustom) => {
1589       switch (value.tag) {
1590       case 'field':
1591         return ifField(value.key, value.newKey, value.presence, value.prop);
1592       case 'custom':
1593         return ifCustom(value.newKey, value.instantiator);
1594       }
1595     };
1597     const shallow$1 = (old, nu) => {
1598       return nu;
1599     };
1600     const deep = (old, nu) => {
1601       const bothObjects = isPlainObject(old) && isPlainObject(nu);
1602       return bothObjects ? deepMerge(old, nu) : nu;
1603     };
1604     const baseMerge = merger => {
1605       return (...objects) => {
1606         if (objects.length === 0) {
1607           throw new Error(`Can't merge zero objects`);
1608         }
1609         const ret = {};
1610         for (let j = 0; j < objects.length; j++) {
1611           const curObject = objects[j];
1612           for (const key in curObject) {
1613             if (has$2(curObject, key)) {
1614               ret[key] = merger(ret[key], curObject[key]);
1615             }
1616           }
1617         }
1618         return ret;
1619       };
1620     };
1621     const deepMerge = baseMerge(deep);
1622     const merge$1 = baseMerge(shallow$1);
1624     const required$2 = () => ({
1625       tag: 'required',
1626       process: {}
1627     });
1628     const defaultedThunk = fallbackThunk => ({
1629       tag: 'defaultedThunk',
1630       process: fallbackThunk
1631     });
1632     const defaulted$1 = fallback => defaultedThunk(constant$1(fallback));
1633     const asOption = () => ({
1634       tag: 'option',
1635       process: {}
1636     });
1637     const mergeWithThunk = baseThunk => ({
1638       tag: 'mergeWithThunk',
1639       process: baseThunk
1640     });
1641     const mergeWith = base => mergeWithThunk(constant$1(base));
1643     const mergeValues$1 = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge$1.apply(undefined, values))) : SimpleResult.svalue(base);
1644     const mergeErrors$1 = errors => compose(SimpleResult.serror, flatten)(errors);
1645     const consolidateObj = (objects, base) => {
1646       const partition = SimpleResult.partition(objects);
1647       return partition.errors.length > 0 ? mergeErrors$1(partition.errors) : mergeValues$1(partition.values, base);
1648     };
1649     const consolidateArr = objects => {
1650       const partitions = SimpleResult.partition(objects);
1651       return partitions.errors.length > 0 ? mergeErrors$1(partitions.errors) : SimpleResult.svalue(partitions.values);
1652     };
1653     const ResultCombine = {
1654       consolidateObj,
1655       consolidateArr
1656     };
1658     const formatObj = input => {
1659       return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
1660     };
1661     const formatErrors = errors => {
1662       const es = errors.length > 10 ? errors.slice(0, 10).concat([{
1663           path: [],
1664           getErrorInfo: constant$1('... (only showing first ten failures)')
1665         }]) : errors;
1666       return map$2(es, e => {
1667         return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
1668       });
1669     };
1671     const nu$a = (path, getErrorInfo) => {
1672       return SimpleResult.serror([{
1673           path,
1674           getErrorInfo
1675         }]);
1676     };
1677     const missingRequired = (path, key, obj) => nu$a(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
1678     const missingKey = (path, key) => nu$a(path, () => 'Choice schema did not contain choice key: "' + key + '"');
1679     const missingBranch = (path, branches, branch) => nu$a(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
1680     const unsupportedFields = (path, unsupported) => nu$a(path, () => 'There are unsupported fields: [' + unsupported.join(', ') + '] specified');
1681     const custom = (path, err) => nu$a(path, constant$1(err));
1683     const value$3 = validator => {
1684       const extract = (path, val) => {
1685         return SimpleResult.bindError(validator(val), err => custom(path, err));
1686       };
1687       const toString = constant$1('val');
1688       return {
1689         extract,
1690         toString
1691       };
1692     };
1693     const anyValue$1 = value$3(SimpleResult.svalue);
1695     const requiredAccess = (path, obj, key, bundle) => get$g(obj, key).fold(() => missingRequired(path, key, obj), bundle);
1696     const fallbackAccess = (obj, key, fallback, bundle) => {
1697       const v = get$g(obj, key).getOrThunk(() => fallback(obj));
1698       return bundle(v);
1699     };
1700     const optionAccess = (obj, key, bundle) => bundle(get$g(obj, key));
1701     const optionDefaultedAccess = (obj, key, fallback, bundle) => {
1702       const opt = get$g(obj, key).map(val => val === true ? fallback(obj) : val);
1703       return bundle(opt);
1704     };
1705     const extractField = (field, path, obj, key, prop) => {
1706       const bundle = av => prop.extract(path.concat([key]), av);
1707       const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
1708         const result = prop.extract(path.concat([key]), ov);
1709         return SimpleResult.map(result, Optional.some);
1710       });
1711       switch (field.tag) {
1712       case 'required':
1713         return requiredAccess(path, obj, key, bundle);
1714       case 'defaultedThunk':
1715         return fallbackAccess(obj, key, field.process, bundle);
1716       case 'option':
1717         return optionAccess(obj, key, bundleAsOption);
1718       case 'defaultedOptionThunk':
1719         return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
1720       case 'mergeWithThunk': {
1721           return fallbackAccess(obj, key, constant$1({}), v => {
1722             const result = deepMerge(field.process(obj), v);
1723             return bundle(result);
1724           });
1725         }
1726       }
1727     };
1728     const extractFields = (path, obj, fields) => {
1729       const success = {};
1730       const errors = [];
1731       for (const field of fields) {
1732         fold(field, (key, newKey, presence, prop) => {
1733           const result = extractField(presence, path, obj, key, prop);
1734           SimpleResult.fold(result, err => {
1735             errors.push(...err);
1736           }, res => {
1737             success[newKey] = res;
1738           });
1739         }, (newKey, instantiator) => {
1740           success[newKey] = instantiator(obj);
1741         });
1742       }
1743       return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
1744     };
1745     const valueThunk = getDelegate => {
1746       const extract = (path, val) => getDelegate().extract(path, val);
1747       const toString = () => getDelegate().toString();
1748       return {
1749         extract,
1750         toString
1751       };
1752     };
1753     const getSetKeys = obj => keys(filter$1(obj, isNonNullable));
1754     const objOfOnly = fields => {
1755       const delegate = objOf(fields);
1756       const fieldNames = foldr(fields, (acc, value) => {
1757         return fold(value, key => deepMerge(acc, { [key]: true }), constant$1(acc));
1758       }, {});
1759       const extract = (path, o) => {
1760         const keys = isBoolean(o) ? [] : getSetKeys(o);
1761         const extra = filter$2(keys, k => !hasNonNullableKey(fieldNames, k));
1762         return extra.length === 0 ? delegate.extract(path, o) : unsupportedFields(path, extra);
1763       };
1764       return {
1765         extract,
1766         toString: delegate.toString
1767       };
1768     };
1769     const objOf = values => {
1770       const extract = (path, o) => extractFields(path, o, values);
1771       const toString = () => {
1772         const fieldStrings = map$2(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
1773         return 'obj{\n' + fieldStrings.join('\n') + '}';
1774       };
1775       return {
1776         extract,
1777         toString
1778       };
1779     };
1780     const arrOf = prop => {
1781       const extract = (path, array) => {
1782         const results = map$2(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
1783         return ResultCombine.consolidateArr(results);
1784       };
1785       const toString = () => 'array(' + prop.toString() + ')';
1786       return {
1787         extract,
1788         toString
1789       };
1790     };
1791     const oneOf = (props, rawF) => {
1792       const f = rawF !== undefined ? rawF : identity;
1793       const extract = (path, val) => {
1794         const errors = [];
1795         for (const prop of props) {
1796           const res = prop.extract(path, val);
1797           if (res.stype === SimpleResultType.Value) {
1798             return {
1799               stype: SimpleResultType.Value,
1800               svalue: f(res.svalue)
1801             };
1802           }
1803           errors.push(res);
1804         }
1805         return ResultCombine.consolidateArr(errors);
1806       };
1807       const toString = () => 'oneOf(' + map$2(props, prop => prop.toString()).join(', ') + ')';
1808       return {
1809         extract,
1810         toString
1811       };
1812     };
1813     const setOf$1 = (validator, prop) => {
1814       const validateKeys = (path, keys) => arrOf(value$3(validator)).extract(path, keys);
1815       const extract = (path, o) => {
1816         const keys$1 = keys(o);
1817         const validatedKeys = validateKeys(path, keys$1);
1818         return SimpleResult.bind(validatedKeys, validKeys => {
1819           const schema = map$2(validKeys, vk => {
1820             return field$2(vk, vk, required$2(), prop);
1821           });
1822           return objOf(schema).extract(path, o);
1823         });
1824       };
1825       const toString = () => 'setOf(' + prop.toString() + ')';
1826       return {
1827         extract,
1828         toString
1829       };
1830     };
1831     const thunk = (_desc, processor) => {
1832       const getP = cached(processor);
1833       const extract = (path, val) => getP().extract(path, val);
1834       const toString = () => getP().toString();
1835       return {
1836         extract,
1837         toString
1838       };
1839     };
1840     const arrOfObj = compose(arrOf, objOf);
1842     const anyValue = constant$1(anyValue$1);
1843     const typedValue = (validator, expectedType) => value$3(a => {
1844       const actualType = typeof a;
1845       return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
1846     });
1847     const number = typedValue(isNumber, 'number');
1848     const string = typedValue(isString, 'string');
1849     const boolean = typedValue(isBoolean, 'boolean');
1850     const functionProcessor = typedValue(isFunction, 'function');
1851     const isPostMessageable = val => {
1852       if (Object(val) !== val) {
1853         return true;
1854       }
1855       switch ({}.toString.call(val).slice(8, -1)) {
1856       case 'Boolean':
1857       case 'Number':
1858       case 'String':
1859       case 'Date':
1860       case 'RegExp':
1861       case 'Blob':
1862       case 'FileList':
1863       case 'ImageData':
1864       case 'ImageBitmap':
1865       case 'ArrayBuffer':
1866         return true;
1867       case 'Array':
1868       case 'Object':
1869         return Object.keys(val).every(prop => isPostMessageable(val[prop]));
1870       default:
1871         return false;
1872       }
1873     };
1874     const postMessageable = value$3(a => {
1875       if (isPostMessageable(a)) {
1876         return SimpleResult.svalue(a);
1877       } else {
1878         return SimpleResult.serror('Expected value to be acceptable for sending via postMessage');
1879       }
1880     });
1882     const chooseFrom = (path, input, branches, ch) => {
1883       const fields = get$g(branches, ch);
1884       return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
1885     };
1886     const choose$2 = (key, branches) => {
1887       const extract = (path, input) => {
1888         const choice = get$g(input, key);
1889         return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
1890       };
1891       const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
1892       return {
1893         extract,
1894         toString
1895       };
1896     };
1898     const arrOfVal = () => arrOf(anyValue$1);
1899     const valueOf = validator => value$3(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
1900     const setOf = (validator, prop) => setOf$1(v => SimpleResult.fromResult(validator(v)), prop);
1901     const extractValue = (label, prop, obj) => {
1902       const res = prop.extract([label], obj);
1903       return SimpleResult.mapError(res, errs => ({
1904         input: obj,
1905         errors: errs
1906       }));
1907     };
1908     const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
1909     const getOrDie = extraction => {
1910       return extraction.fold(errInfo => {
1911         throw new Error(formatError(errInfo));
1912       }, identity);
1913     };
1914     const asRawOrDie$1 = (label, prop, obj) => getOrDie(asRaw(label, prop, obj));
1915     const formatError = errInfo => {
1916       return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
1917     };
1918     const choose$1 = (key, branches) => choose$2(key, map$1(branches, objOf));
1919     const thunkOf = (desc, schema) => thunk(desc, schema);
1921     const field$1 = field$2;
1922     const customField = customField$1;
1923     const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
1924     const required$1 = key => field$1(key, key, required$2(), anyValue());
1925     const requiredOf = (key, schema) => field$1(key, key, required$2(), schema);
1926     const requiredNumber = key => requiredOf(key, number);
1927     const requiredString = key => requiredOf(key, string);
1928     const requiredStringEnum = (key, values) => field$1(key, key, required$2(), validateEnum(values));
1929     const requiredBoolean = key => requiredOf(key, boolean);
1930     const requiredFunction = key => requiredOf(key, functionProcessor);
1931     const forbid = (key, message) => field$1(key, key, asOption(), value$3(_v => SimpleResult.serror('The field: ' + key + ' is forbidden. ' + message)));
1932     const requiredObjOf = (key, objSchema) => field$1(key, key, required$2(), objOf(objSchema));
1933     const requiredArrayOfObj = (key, objFields) => field$1(key, key, required$2(), arrOfObj(objFields));
1934     const requiredArrayOf = (key, schema) => field$1(key, key, required$2(), arrOf(schema));
1935     const option$3 = key => field$1(key, key, asOption(), anyValue());
1936     const optionOf = (key, schema) => field$1(key, key, asOption(), schema);
1937     const optionNumber = key => optionOf(key, number);
1938     const optionString = key => optionOf(key, string);
1939     const optionStringEnum = (key, values) => optionOf(key, validateEnum(values));
1940     const optionFunction = key => optionOf(key, functionProcessor);
1941     const optionArrayOf = (key, schema) => optionOf(key, arrOf(schema));
1942     const optionObjOf = (key, objSchema) => optionOf(key, objOf(objSchema));
1943     const optionObjOfOnly = (key, objSchema) => optionOf(key, objOfOnly(objSchema));
1944     const defaulted = (key, fallback) => field$1(key, key, defaulted$1(fallback), anyValue());
1945     const defaultedOf = (key, fallback, schema) => field$1(key, key, defaulted$1(fallback), schema);
1946     const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
1947     const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
1948     const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
1949     const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
1950     const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
1951     const defaultedPostMsg = (key, fallback) => defaultedOf(key, fallback, postMessageable);
1952     const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
1953     const defaultedObjOf = (key, fallback, objSchema) => defaultedOf(key, fallback, objOf(objSchema));
1955     const Cell = initial => {
1956       let value = initial;
1957       const get = () => {
1958         return value;
1959       };
1960       const set = v => {
1961         value = v;
1962       };
1963       return {
1964         get,
1965         set
1966       };
1967     };
1969     const generate$7 = cases => {
1970       if (!isArray(cases)) {
1971         throw new Error('cases must be an array');
1972       }
1973       if (cases.length === 0) {
1974         throw new Error('there must be at least one case');
1975       }
1976       const constructors = [];
1977       const adt = {};
1978       each$1(cases, (acase, count) => {
1979         const keys$1 = keys(acase);
1980         if (keys$1.length !== 1) {
1981           throw new Error('one and only one name per case');
1982         }
1983         const key = keys$1[0];
1984         const value = acase[key];
1985         if (adt[key] !== undefined) {
1986           throw new Error('duplicate key detected:' + key);
1987         } else if (key === 'cata') {
1988           throw new Error('cannot have a case named cata (sorry)');
1989         } else if (!isArray(value)) {
1990           throw new Error('case arguments must be an array');
1991         }
1992         constructors.push(key);
1993         adt[key] = (...args) => {
1994           const argLength = args.length;
1995           if (argLength !== value.length) {
1996             throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
1997           }
1998           const match = branches => {
1999             const branchKeys = keys(branches);
2000             if (constructors.length !== branchKeys.length) {
2001               throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
2002             }
2003             const allReqd = forall(constructors, reqKey => {
2004               return contains$2(branchKeys, reqKey);
2005             });
2006             if (!allReqd) {
2007               throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
2008             }
2009             return branches[key].apply(null, args);
2010           };
2011           return {
2012             fold: (...foldArgs) => {
2013               if (foldArgs.length !== cases.length) {
2014                 throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
2015               }
2016               const target = foldArgs[count];
2017               return target.apply(null, args);
2018             },
2019             match,
2020             log: label => {
2021               console.log(label, {
2022                 constructors,
2023                 constructor: key,
2024                 params: args
2025               });
2026             }
2027           };
2028         };
2029       });
2030       return adt;
2031     };
2032     const Adt = { generate: generate$7 };
2034     Adt.generate([
2035       {
2036         bothErrors: [
2037           'error1',
2038           'error2'
2039         ]
2040       },
2041       {
2042         firstError: [
2043           'error1',
2044           'value2'
2045         ]
2046       },
2047       {
2048         secondError: [
2049           'value1',
2050           'error2'
2051         ]
2052       },
2053       {
2054         bothValues: [
2055           'value1',
2056           'value2'
2057         ]
2058       }
2059     ]);
2060     const partition$1 = results => {
2061       const errors = [];
2062       const values = [];
2063       each$1(results, result => {
2064         result.fold(err => {
2065           errors.push(err);
2066         }, value => {
2067           values.push(value);
2068         });
2069       });
2070       return {
2071         errors,
2072         values
2073       };
2074     };
2076     const exclude$1 = (obj, fields) => {
2077       const r = {};
2078       each(obj, (v, k) => {
2079         if (!contains$2(fields, k)) {
2080           r[k] = v;
2081         }
2082       });
2083       return r;
2084     };
2086     const wrap$2 = (key, value) => ({ [key]: value });
2087     const wrapAll$1 = keyvalues => {
2088       const r = {};
2089       each$1(keyvalues, kv => {
2090         r[kv.key] = kv.value;
2091       });
2092       return r;
2093     };
2095     const exclude = (obj, fields) => exclude$1(obj, fields);
2096     const wrap$1 = (key, value) => wrap$2(key, value);
2097     const wrapAll = keyvalues => wrapAll$1(keyvalues);
2098     const mergeValues = (values, base) => {
2099       return values.length === 0 ? Result.value(base) : Result.value(deepMerge(base, merge$1.apply(undefined, values)));
2100     };
2101     const mergeErrors = errors => Result.error(flatten(errors));
2102     const consolidate = (objs, base) => {
2103       const partitions = partition$1(objs);
2104       return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : mergeValues(partitions.values, base);
2105     };
2107     const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
2108     const ancestor$2 = (scope, transform, isRoot) => {
2109       let element = scope.dom;
2110       const stop = ensureIsRoot(isRoot);
2111       while (element.parentNode) {
2112         element = element.parentNode;
2113         const el = SugarElement.fromDom(element);
2114         const transformed = transform(el);
2115         if (transformed.isSome()) {
2116           return transformed;
2117         } else if (stop(el)) {
2118           break;
2119         }
2120       }
2121       return Optional.none();
2122     };
2123     const closest$4 = (scope, transform, isRoot) => {
2124       const current = transform(scope);
2125       const stop = ensureIsRoot(isRoot);
2126       return current.orThunk(() => stop(scope) ? Optional.none() : ancestor$2(scope, transform, stop));
2127     };
2129     const isSource = (component, simulatedEvent) => eq(component.element, simulatedEvent.event.target);
2131     const defaultEventHandler = {
2132       can: always,
2133       abort: never,
2134       run: noop
2135     };
2136     const nu$9 = parts => {
2137       if (!hasNonNullableKey(parts, 'can') && !hasNonNullableKey(parts, 'abort') && !hasNonNullableKey(parts, 'run')) {
2138         throw new Error('EventHandler defined by: ' + JSON.stringify(parts, null, 2) + ' does not have can, abort, or run!');
2139       }
2140       return {
2141         ...defaultEventHandler,
2142         ...parts
2143       };
2144     };
2145     const all$2 = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc && f(handler).apply(undefined, args), true);
2146     const any = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc || f(handler).apply(undefined, args), false);
2147     const read$2 = handler => isFunction(handler) ? {
2148       can: always,
2149       abort: never,
2150       run: handler
2151     } : handler;
2152     const fuse$1 = handlers => {
2153       const can = all$2(handlers, handler => handler.can);
2154       const abort = any(handlers, handler => handler.abort);
2155       const run = (...args) => {
2156         each$1(handlers, handler => {
2157           handler.run.apply(undefined, args);
2158         });
2159       };
2160       return {
2161         can,
2162         abort,
2163         run
2164       };
2165     };
2167     const constant = constant$1;
2168     const touchstart = constant('touchstart');
2169     const touchmove = constant('touchmove');
2170     const touchend = constant('touchend');
2171     const touchcancel = constant('touchcancel');
2172     const mousedown = constant('mousedown');
2173     const mousemove = constant('mousemove');
2174     const mouseout = constant('mouseout');
2175     const mouseup = constant('mouseup');
2176     const mouseover = constant('mouseover');
2177     const focusin = constant('focusin');
2178     const focusout = constant('focusout');
2179     const keydown = constant('keydown');
2180     const keyup = constant('keyup');
2181     const input = constant('input');
2182     const change = constant('change');
2183     const click = constant('click');
2184     const transitioncancel = constant('transitioncancel');
2185     const transitionend = constant('transitionend');
2186     const transitionstart = constant('transitionstart');
2187     const selectstart = constant('selectstart');
2189     const prefixName = name => constant$1('alloy.' + name);
2190     const alloy = { tap: prefixName('tap') };
2191     const focus$4 = prefixName('focus');
2192     const postBlur = prefixName('blur.post');
2193     const postPaste = prefixName('paste.post');
2194     const receive = prefixName('receive');
2195     const execute$5 = prefixName('execute');
2196     const focusItem = prefixName('focus.item');
2197     const tap = alloy.tap;
2198     const longpress = prefixName('longpress');
2199     const sandboxClose = prefixName('sandbox.close');
2200     const typeaheadCancel = prefixName('typeahead.cancel');
2201     const systemInit = prefixName('system.init');
2202     const documentTouchmove = prefixName('system.touchmove');
2203     const documentTouchend = prefixName('system.touchend');
2204     const windowScroll = prefixName('system.scroll');
2205     const windowResize = prefixName('system.resize');
2206     const attachedToDom = prefixName('system.attached');
2207     const detachedFromDom = prefixName('system.detached');
2208     const dismissRequested = prefixName('system.dismissRequested');
2209     const repositionRequested = prefixName('system.repositionRequested');
2210     const focusShifted = prefixName('focusmanager.shifted');
2211     const slotVisibility = prefixName('slotcontainer.visibility');
2212     const changeTab = prefixName('change.tab');
2213     const dismissTab = prefixName('dismiss.tab');
2214     const highlight$1 = prefixName('highlight');
2215     const dehighlight$1 = prefixName('dehighlight');
2217     const emit = (component, event) => {
2218       dispatchWith(component, component.element, event, {});
2219     };
2220     const emitWith = (component, event, properties) => {
2221       dispatchWith(component, component.element, event, properties);
2222     };
2223     const emitExecute = component => {
2224       emit(component, execute$5());
2225     };
2226     const dispatch = (component, target, event) => {
2227       dispatchWith(component, target, event, {});
2228     };
2229     const dispatchWith = (component, target, event, properties) => {
2230       const data = {
2231         target,
2232         ...properties
2233       };
2234       component.getSystem().triggerEvent(event, target, data);
2235     };
2236     const retargetAndDispatchWith = (component, target, eventName, properties) => {
2237       const data = {
2238         ...properties,
2239         target
2240       };
2241       component.getSystem().triggerEvent(eventName, target, data);
2242     };
2243     const dispatchEvent = (component, target, event, simulatedEvent) => {
2244       component.getSystem().triggerEvent(event, target, simulatedEvent.event);
2245     };
2247     const derive$2 = configs => wrapAll(configs);
2248     const abort = (name, predicate) => {
2249       return {
2250         key: name,
2251         value: nu$9({ abort: predicate })
2252       };
2253     };
2254     const can = (name, predicate) => {
2255       return {
2256         key: name,
2257         value: nu$9({ can: predicate })
2258       };
2259     };
2260     const preventDefault = name => {
2261       return {
2262         key: name,
2263         value: nu$9({
2264           run: (component, simulatedEvent) => {
2265             simulatedEvent.event.prevent();
2266           }
2267         })
2268       };
2269     };
2270     const run$1 = (name, handler) => {
2271       return {
2272         key: name,
2273         value: nu$9({ run: handler })
2274       };
2275     };
2276     const runActionExtra = (name, action, extra) => {
2277       return {
2278         key: name,
2279         value: nu$9({
2280           run: (component, simulatedEvent) => {
2281             action.apply(undefined, [
2282               component,
2283               simulatedEvent
2284             ].concat(extra));
2285           }
2286         })
2287       };
2288     };
2289     const runOnName = name => {
2290       return handler => run$1(name, handler);
2291     };
2292     const runOnSourceName = name => {
2293       return handler => ({
2294         key: name,
2295         value: nu$9({
2296           run: (component, simulatedEvent) => {
2297             if (isSource(component, simulatedEvent)) {
2298               handler(component, simulatedEvent);
2299             }
2300           }
2301         })
2302       });
2303     };
2304     const redirectToUid = (name, uid) => {
2305       return run$1(name, (component, simulatedEvent) => {
2306         component.getSystem().getByUid(uid).each(redirectee => {
2307           dispatchEvent(redirectee, redirectee.element, name, simulatedEvent);
2308         });
2309       });
2310     };
2311     const redirectToPart = (name, detail, partName) => {
2312       const uid = detail.partUids[partName];
2313       return redirectToUid(name, uid);
2314     };
2315     const runWithTarget = (name, f) => {
2316       return run$1(name, (component, simulatedEvent) => {
2317         const ev = simulatedEvent.event;
2318         const target = component.getSystem().getByDom(ev.target).getOrThunk(() => {
2319           const closest = closest$4(ev.target, el => component.getSystem().getByDom(el).toOptional(), never);
2320           return closest.getOr(component);
2321         });
2322         f(component, target, simulatedEvent);
2323       });
2324     };
2325     const cutter = name => {
2326       return run$1(name, (component, simulatedEvent) => {
2327         simulatedEvent.cut();
2328       });
2329     };
2330     const stopper = name => {
2331       return run$1(name, (component, simulatedEvent) => {
2332         simulatedEvent.stop();
2333       });
2334     };
2335     const runOnSource = (name, f) => {
2336       return runOnSourceName(name)(f);
2337     };
2338     const runOnAttached = runOnSourceName(attachedToDom());
2339     const runOnDetached = runOnSourceName(detachedFromDom());
2340     const runOnInit = runOnSourceName(systemInit());
2341     const runOnExecute$1 = runOnName(execute$5());
2343     const fromHtml$1 = (html, scope) => {
2344       const doc = scope || document;
2345       const div = doc.createElement('div');
2346       div.innerHTML = html;
2347       return children(SugarElement.fromDom(div));
2348     };
2350     const get$9 = element => element.dom.innerHTML;
2351     const set$6 = (element, content) => {
2352       const owner = owner$4(element);
2353       const docDom = owner.dom;
2354       const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
2355       const contentElements = fromHtml$1(content, docDom);
2356       append$1(fragment, contentElements);
2357       empty(element);
2358       append$2(element, fragment);
2359     };
2360     const getOuter = element => {
2361       const container = SugarElement.fromTag('div');
2362       const clone = SugarElement.fromDom(element.dom.cloneNode(true));
2363       append$2(container, clone);
2364       return get$9(container);
2365     };
2367     const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
2368     const shallow = original => clone$1(original, false);
2370     const getHtml = element => {
2371       if (isShadowRoot(element)) {
2372         return '#shadow-root';
2373       } else {
2374         const clone = shallow(element);
2375         return getOuter(clone);
2376       }
2377     };
2379     const element = elem => getHtml(elem);
2381     const isRecursive = (component, originator, target) => eq(originator, component.element) && !eq(originator, target);
2382     const events$i = derive$2([can(focus$4(), (component, simulatedEvent) => {
2383         const event = simulatedEvent.event;
2384         const originator = event.originator;
2385         const target = event.target;
2386         if (isRecursive(component, originator, target)) {
2387           console.warn(focus$4() + ' did not get interpreted by the desired target. ' + '\nOriginator: ' + element(originator) + '\nTarget: ' + element(target) + '\nCheck the ' + focus$4() + ' event handlers');
2388           return false;
2389         } else {
2390           return true;
2391         }
2392       })]);
2394     var DefaultEvents = /*#__PURE__*/Object.freeze({
2395         __proto__: null,
2396         events: events$i
2397     });
2399     let unique = 0;
2400     const generate$6 = prefix => {
2401       const date = new Date();
2402       const time = date.getTime();
2403       const random = Math.floor(Math.random() * 1000000000);
2404       unique++;
2405       return prefix + '_' + random + unique + String(time);
2406     };
2408     const prefix$1 = constant$1('alloy-id-');
2409     const idAttr$1 = constant$1('data-alloy-id');
2411     const prefix = prefix$1();
2412     const idAttr = idAttr$1();
2413     const write = (label, elem) => {
2414       const id = generate$6(prefix + label);
2415       writeOnly(elem, id);
2416       return id;
2417     };
2418     const writeOnly = (elem, uid) => {
2419       Object.defineProperty(elem.dom, idAttr, {
2420         value: uid,
2421         writable: true
2422       });
2423     };
2424     const read$1 = elem => {
2425       const id = isElement$1(elem) ? elem.dom[idAttr] : null;
2426       return Optional.from(id);
2427     };
2428     const generate$5 = prefix => generate$6(prefix);
2430     const make$8 = identity;
2432     const NoContextApi = getComp => {
2433       const getMessage = event => `The component must be in a context to execute: ${ event }` + (getComp ? '\n' + element(getComp().element) + ' is not in context.' : '');
2434       const fail = event => () => {
2435         throw new Error(getMessage(event));
2436       };
2437       const warn = event => () => {
2438         console.warn(getMessage(event));
2439       };
2440       return {
2441         debugInfo: constant$1('fake'),
2442         triggerEvent: warn('triggerEvent'),
2443         triggerFocus: warn('triggerFocus'),
2444         triggerEscape: warn('triggerEscape'),
2445         broadcast: warn('broadcast'),
2446         broadcastOn: warn('broadcastOn'),
2447         broadcastEvent: warn('broadcastEvent'),
2448         build: fail('build'),
2449         buildOrPatch: fail('buildOrPatch'),
2450         addToWorld: fail('addToWorld'),
2451         removeFromWorld: fail('removeFromWorld'),
2452         addToGui: fail('addToGui'),
2453         removeFromGui: fail('removeFromGui'),
2454         getByUid: fail('getByUid'),
2455         getByDom: fail('getByDom'),
2456         isConnected: never
2457       };
2458     };
2459     const singleton$1 = NoContextApi();
2461     const markAsBehaviourApi = (f, apiName, apiFunction) => {
2462       const delegate = apiFunction.toString();
2463       const endIndex = delegate.indexOf(')') + 1;
2464       const openBracketIndex = delegate.indexOf('(');
2465       const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
2466       f.toFunctionAnnotation = () => ({
2467         name: apiName,
2468         parameters: cleanParameters(parameters.slice(0, 1).concat(parameters.slice(3)))
2469       });
2470       return f;
2471     };
2472     const cleanParameters = parameters => map$2(parameters, p => endsWith(p, '/*') ? p.substring(0, p.length - '/*'.length) : p);
2473     const markAsExtraApi = (f, extraName) => {
2474       const delegate = f.toString();
2475       const endIndex = delegate.indexOf(')') + 1;
2476       const openBracketIndex = delegate.indexOf('(');
2477       const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
2478       f.toFunctionAnnotation = () => ({
2479         name: extraName,
2480         parameters: cleanParameters(parameters)
2481       });
2482       return f;
2483     };
2484     const markAsSketchApi = (f, apiFunction) => {
2485       const delegate = apiFunction.toString();
2486       const endIndex = delegate.indexOf(')') + 1;
2487       const openBracketIndex = delegate.indexOf('(');
2488       const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
2489       f.toFunctionAnnotation = () => ({
2490         name: 'OVERRIDE',
2491         parameters: cleanParameters(parameters.slice(1))
2492       });
2493       return f;
2494     };
2496     const premadeTag = generate$6('alloy-premade');
2497     const premade$1 = comp => {
2498       Object.defineProperty(comp.element.dom, premadeTag, {
2499         value: comp.uid,
2500         writable: true
2501       });
2502       return wrap$1(premadeTag, comp);
2503     };
2504     const isPremade = element => has$2(element.dom, premadeTag);
2505     const getPremade = spec => get$g(spec, premadeTag);
2506     const makeApi = f => markAsSketchApi((component, ...rest) => f(component.getApis(), component, ...rest), f);
2508     const NoState = { init: () => nu$8({ readState: constant$1('No State required') }) };
2509     const nu$8 = spec => spec;
2511     const generateFrom$1 = (spec, all) => {
2512       const schema = map$2(all, a => optionObjOf(a.name(), [
2513         required$1('config'),
2514         defaulted('state', NoState)
2515       ]));
2516       const validated = asRaw('component.behaviours', objOf(schema), spec.behaviours).fold(errInfo => {
2517         throw new Error(formatError(errInfo) + '\nComplete spec:\n' + JSON.stringify(spec, null, 2));
2518       }, identity);
2519       return {
2520         list: all,
2521         data: map$1(validated, optBlobThunk => {
2522           const output = optBlobThunk.map(blob => ({
2523             config: blob.config,
2524             state: blob.state.init(blob.config)
2525           }));
2526           return constant$1(output);
2527         })
2528       };
2529     };
2530     const getBehaviours$3 = bData => bData.list;
2531     const getData$2 = bData => bData.data;
2533     const byInnerKey = (data, tuple) => {
2534       const r = {};
2535       each(data, (detail, key) => {
2536         each(detail, (value, indexKey) => {
2537           const chain = get$g(r, indexKey).getOr([]);
2538           r[indexKey] = chain.concat([tuple(key, value)]);
2539         });
2540       });
2541       return r;
2542     };
2544     const nu$7 = s => ({
2545       classes: isUndefined(s.classes) ? [] : s.classes,
2546       attributes: isUndefined(s.attributes) ? {} : s.attributes,
2547       styles: isUndefined(s.styles) ? {} : s.styles
2548     });
2549     const merge = (defnA, mod) => ({
2550       ...defnA,
2551       attributes: {
2552         ...defnA.attributes,
2553         ...mod.attributes
2554       },
2555       styles: {
2556         ...defnA.styles,
2557         ...mod.styles
2558       },
2559       classes: defnA.classes.concat(mod.classes)
2560     });
2562     const combine$2 = (info, baseMod, behaviours, base) => {
2563       const modsByBehaviour = { ...baseMod };
2564       each$1(behaviours, behaviour => {
2565         modsByBehaviour[behaviour.name()] = behaviour.exhibit(info, base);
2566       });
2567       const byAspect = byInnerKey(modsByBehaviour, (name, modification) => ({
2568         name,
2569         modification
2570       }));
2571       const combineObjects = objects => foldr(objects, (b, a) => ({
2572         ...a.modification,
2573         ...b
2574       }), {});
2575       const combinedClasses = foldr(byAspect.classes, (b, a) => a.modification.concat(b), []);
2576       const combinedAttributes = combineObjects(byAspect.attributes);
2577       const combinedStyles = combineObjects(byAspect.styles);
2578       return nu$7({
2579         classes: combinedClasses,
2580         attributes: combinedAttributes,
2581         styles: combinedStyles
2582       });
2583     };
2585     const sortKeys = (label, keyName, array, order) => {
2586       try {
2587         const sorted = sort(array, (a, b) => {
2588           const aKey = a[keyName];
2589           const bKey = b[keyName];
2590           const aIndex = order.indexOf(aKey);
2591           const bIndex = order.indexOf(bKey);
2592           if (aIndex === -1) {
2593             throw new Error('The ordering for ' + label + ' does not have an entry for ' + aKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
2594           }
2595           if (bIndex === -1) {
2596             throw new Error('The ordering for ' + label + ' does not have an entry for ' + bKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
2597           }
2598           if (aIndex < bIndex) {
2599             return -1;
2600           } else if (bIndex < aIndex) {
2601             return 1;
2602           } else {
2603             return 0;
2604           }
2605         });
2606         return Result.value(sorted);
2607       } catch (err) {
2608         return Result.error([err]);
2609       }
2610     };
2612     const uncurried = (handler, purpose) => ({
2613       handler,
2614       purpose
2615     });
2616     const curried = (handler, purpose) => ({
2617       cHandler: handler,
2618       purpose
2619     });
2620     const curryArgs = (descHandler, extraArgs) => curried(curry.apply(undefined, [descHandler.handler].concat(extraArgs)), descHandler.purpose);
2621     const getCurried = descHandler => descHandler.cHandler;
2623     const behaviourTuple = (name, handler) => ({
2624       name,
2625       handler
2626     });
2627     const nameToHandlers = (behaviours, info) => {
2628       const r = {};
2629       each$1(behaviours, behaviour => {
2630         r[behaviour.name()] = behaviour.handlers(info);
2631       });
2632       return r;
2633     };
2634     const groupByEvents = (info, behaviours, base) => {
2635       const behaviourEvents = {
2636         ...base,
2637         ...nameToHandlers(behaviours, info)
2638       };
2639       return byInnerKey(behaviourEvents, behaviourTuple);
2640     };
2641     const combine$1 = (info, eventOrder, behaviours, base) => {
2642       const byEventName = groupByEvents(info, behaviours, base);
2643       return combineGroups(byEventName, eventOrder);
2644     };
2645     const assemble = rawHandler => {
2646       const handler = read$2(rawHandler);
2647       return (component, simulatedEvent, ...rest) => {
2648         const args = [
2649           component,
2650           simulatedEvent
2651         ].concat(rest);
2652         if (handler.abort.apply(undefined, args)) {
2653           simulatedEvent.stop();
2654         } else if (handler.can.apply(undefined, args)) {
2655           handler.run.apply(undefined, args);
2656         }
2657       };
2658     };
2659     const missingOrderError = (eventName, tuples) => 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, c => c.name), null, 2)]);
2660     const fuse = (tuples, eventOrder, eventName) => {
2661       const order = eventOrder[eventName];
2662       if (!order) {
2663         return missingOrderError(eventName, tuples);
2664       } else {
2665         return sortKeys('Event: ' + eventName, 'name', tuples, order).map(sortedTuples => {
2666           const handlers = map$2(sortedTuples, tuple => tuple.handler);
2667           return fuse$1(handlers);
2668         });
2669       }
2670     };
2671     const combineGroups = (byEventName, eventOrder) => {
2672       const r = mapToArray(byEventName, (tuples, eventName) => {
2673         const combined = tuples.length === 1 ? Result.value(tuples[0].handler) : fuse(tuples, eventOrder, eventName);
2674         return combined.map(handler => {
2675           const assembled = assemble(handler);
2676           const purpose = tuples.length > 1 ? filter$2(eventOrder[eventName], o => exists(tuples, t => t.name === o)).join(' > ') : tuples[0].name;
2677           return wrap$1(eventName, uncurried(assembled, purpose));
2678         });
2679       });
2680       return consolidate(r, {});
2681     };
2683     const baseBehaviour = 'alloy.base.behaviour';
2684     const schema$z = objOf([
2685       field$1('dom', 'dom', required$2(), objOf([
2686         required$1('tag'),
2687         defaulted('styles', {}),
2688         defaulted('classes', []),
2689         defaulted('attributes', {}),
2690         option$3('value'),
2691         option$3('innerHtml')
2692       ])),
2693       required$1('components'),
2694       required$1('uid'),
2695       defaulted('events', {}),
2696       defaulted('apis', {}),
2697       field$1('eventOrder', 'eventOrder', mergeWith({
2698         [execute$5()]: [
2699           'disabling',
2700           baseBehaviour,
2701           'toggling',
2702           'typeaheadevents'
2703         ],
2704         [focus$4()]: [
2705           baseBehaviour,
2706           'focusing',
2707           'keying'
2708         ],
2709         [systemInit()]: [
2710           baseBehaviour,
2711           'disabling',
2712           'toggling',
2713           'representing'
2714         ],
2715         [input()]: [
2716           baseBehaviour,
2717           'representing',
2718           'streaming',
2719           'invalidating'
2720         ],
2721         [detachedFromDom()]: [
2722           baseBehaviour,
2723           'representing',
2724           'item-events',
2725           'tooltipping'
2726         ],
2727         [mousedown()]: [
2728           'focusing',
2729           baseBehaviour,
2730           'item-type-events'
2731         ],
2732         [touchstart()]: [
2733           'focusing',
2734           baseBehaviour,
2735           'item-type-events'
2736         ],
2737         [mouseover()]: [
2738           'item-type-events',
2739           'tooltipping'
2740         ],
2741         [receive()]: [
2742           'receiving',
2743           'reflecting',
2744           'tooltipping'
2745         ]
2746       }), anyValue()),
2747       option$3('domModification')
2748     ]);
2749     const toInfo = spec => asRaw('custom.definition', schema$z, spec);
2750     const toDefinition = detail => ({
2751       ...detail.dom,
2752       uid: detail.uid,
2753       domChildren: map$2(detail.components, comp => comp.element)
2754     });
2755     const toModification = detail => detail.domModification.fold(() => nu$7({}), nu$7);
2756     const toEvents = info => info.events;
2758     const read = (element, attr) => {
2759       const value = get$f(element, attr);
2760       return value === undefined || value === '' ? [] : value.split(' ');
2761     };
2762     const add$4 = (element, attr, id) => {
2763       const old = read(element, attr);
2764       const nu = old.concat([id]);
2765       set$9(element, attr, nu.join(' '));
2766       return true;
2767     };
2768     const remove$4 = (element, attr, id) => {
2769       const nu = filter$2(read(element, attr), v => v !== id);
2770       if (nu.length > 0) {
2771         set$9(element, attr, nu.join(' '));
2772       } else {
2773         remove$7(element, attr);
2774       }
2775       return false;
2776     };
2778     const supports = element => element.dom.classList !== undefined;
2779     const get$8 = element => read(element, 'class');
2780     const add$3 = (element, clazz) => add$4(element, 'class', clazz);
2781     const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
2783     const add$2 = (element, clazz) => {
2784       if (supports(element)) {
2785         element.dom.classList.add(clazz);
2786       } else {
2787         add$3(element, clazz);
2788       }
2789     };
2790     const cleanClass = element => {
2791       const classList = supports(element) ? element.dom.classList : get$8(element);
2792       if (classList.length === 0) {
2793         remove$7(element, 'class');
2794       }
2795     };
2796     const remove$2 = (element, clazz) => {
2797       if (supports(element)) {
2798         const classList = element.dom.classList;
2799         classList.remove(clazz);
2800       } else {
2801         remove$3(element, clazz);
2802       }
2803       cleanClass(element);
2804     };
2805     const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
2807     const add$1 = (element, classes) => {
2808       each$1(classes, x => {
2809         add$2(element, x);
2810       });
2811     };
2812     const remove$1 = (element, classes) => {
2813       each$1(classes, x => {
2814         remove$2(element, x);
2815       });
2816     };
2817     const hasAll = (element, classes) => forall(classes, clazz => has(element, clazz));
2818     const getNative = element => {
2819       const classList = element.dom.classList;
2820       const r = new Array(classList.length);
2821       for (let i = 0; i < classList.length; i++) {
2822         const item = classList.item(i);
2823         if (item !== null) {
2824           r[i] = item;
2825         }
2826       }
2827       return r;
2828     };
2829     const get$7 = element => supports(element) ? getNative(element) : get$8(element);
2831     const get$6 = element => element.dom.value;
2832     const set$5 = (element, value) => {
2833       if (value === undefined) {
2834         throw new Error('Value.set was undefined');
2835       }
2836       element.dom.value = value;
2837     };
2839     const determineObsoleted = (parent, index, oldObsoleted) => {
2840       const newObsoleted = child$2(parent, index);
2841       return newObsoleted.map(newObs => {
2842         const elemChanged = oldObsoleted.exists(o => !eq(o, newObs));
2843         if (elemChanged) {
2844           const oldTag = oldObsoleted.map(name$3).getOr('span');
2845           const marker = SugarElement.fromTag(oldTag);
2846           before$1(newObs, marker);
2847           return marker;
2848         } else {
2849           return newObs;
2850         }
2851       });
2852     };
2853     const ensureInDom = (parent, child, obsoleted) => {
2854       obsoleted.fold(() => append$2(parent, child), obs => {
2855         if (!eq(obs, child)) {
2856           before$1(obs, child);
2857           remove$5(obs);
2858         }
2859       });
2860     };
2861     const patchChildrenWith = (parent, nu, f) => {
2862       const builtChildren = map$2(nu, f);
2863       const currentChildren = children(parent);
2864       each$1(currentChildren.slice(builtChildren.length), remove$5);
2865       return builtChildren;
2866     };
2867     const patchSpecChild = (parent, index, spec, build) => {
2868       const oldObsoleted = child$2(parent, index);
2869       const childComp = build(spec, oldObsoleted);
2870       const obsoleted = determineObsoleted(parent, index, oldObsoleted);
2871       ensureInDom(parent, childComp.element, obsoleted);
2872       return childComp;
2873     };
2874     const patchSpecChildren = (parent, specs, build) => patchChildrenWith(parent, specs, (spec, index) => patchSpecChild(parent, index, spec, build));
2875     const patchDomChildren = (parent, nodes) => patchChildrenWith(parent, nodes, (node, index) => {
2876       const optObsoleted = child$2(parent, index);
2877       ensureInDom(parent, node, optObsoleted);
2878       return node;
2879     });
2881     const diffKeyValueSet = (newObj, oldObj) => {
2882       const newKeys = keys(newObj);
2883       const oldKeys = keys(oldObj);
2884       const toRemove = difference(oldKeys, newKeys);
2885       const toSet = bifilter(newObj, (v, k) => {
2886         return !has$2(oldObj, k) || v !== oldObj[k];
2887       }).t;
2888       return {
2889         toRemove,
2890         toSet
2891       };
2892     };
2893     const reconcileToDom = (definition, obsoleted) => {
2894       const {
2895         class: clazz,
2896         style,
2897         ...existingAttributes
2898       } = clone$2(obsoleted);
2899       const {
2900         toSet: attrsToSet,
2901         toRemove: attrsToRemove
2902       } = diffKeyValueSet(definition.attributes, existingAttributes);
2903       const updateAttrs = () => {
2904         each$1(attrsToRemove, a => remove$7(obsoleted, a));
2905         setAll$1(obsoleted, attrsToSet);
2906       };
2907       const existingStyles = getAllRaw(obsoleted);
2908       const {
2909         toSet: stylesToSet,
2910         toRemove: stylesToRemove
2911       } = diffKeyValueSet(definition.styles, existingStyles);
2912       const updateStyles = () => {
2913         each$1(stylesToRemove, s => remove$6(obsoleted, s));
2914         setAll(obsoleted, stylesToSet);
2915       };
2916       const existingClasses = get$7(obsoleted);
2917       const classesToRemove = difference(existingClasses, definition.classes);
2918       const classesToAdd = difference(definition.classes, existingClasses);
2919       const updateClasses = () => {
2920         add$1(obsoleted, classesToAdd);
2921         remove$1(obsoleted, classesToRemove);
2922       };
2923       const updateHtml = html => {
2924         set$6(obsoleted, html);
2925       };
2926       const updateChildren = () => {
2927         const children = definition.domChildren;
2928         patchDomChildren(obsoleted, children);
2929       };
2930       const updateValue = () => {
2931         const valueElement = obsoleted;
2932         const value = definition.value.getOrUndefined();
2933         if (value !== get$6(valueElement)) {
2934           set$5(valueElement, value ?? '');
2935         }
2936       };
2937       updateAttrs();
2938       updateClasses();
2939       updateStyles();
2940       definition.innerHtml.fold(updateChildren, updateHtml);
2941       updateValue();
2942       return obsoleted;
2943     };
2945     const introduceToDom = definition => {
2946       const subject = SugarElement.fromTag(definition.tag);
2947       setAll$1(subject, definition.attributes);
2948       add$1(subject, definition.classes);
2949       setAll(subject, definition.styles);
2950       definition.innerHtml.each(html => set$6(subject, html));
2951       const children = definition.domChildren;
2952       append$1(subject, children);
2953       definition.value.each(value => {
2954         set$5(subject, value);
2955       });
2956       return subject;
2957     };
2958     const attemptPatch = (definition, obsoleted) => {
2959       try {
2960         const e = reconcileToDom(definition, obsoleted);
2961         return Optional.some(e);
2962       } catch (err) {
2963         return Optional.none();
2964       }
2965     };
2966     const hasMixedChildren = definition => definition.innerHtml.isSome() && definition.domChildren.length > 0;
2967     const renderToDom = (definition, optObsoleted) => {
2968       const canBePatched = candidate => name$3(candidate) === definition.tag && !hasMixedChildren(definition) && !isPremade(candidate);
2969       const elem = optObsoleted.filter(canBePatched).bind(obsoleted => attemptPatch(definition, obsoleted)).getOrThunk(() => introduceToDom(definition));
2970       writeOnly(elem, definition.uid);
2971       return elem;
2972     };
2974     const getBehaviours$2 = spec => {
2975       const behaviours = get$g(spec, 'behaviours').getOr({});
2976       return bind$3(keys(behaviours), name => {
2977         const behaviour = behaviours[name];
2978         return isNonNullable(behaviour) ? [behaviour.me] : [];
2979       });
2980     };
2981     const generateFrom = (spec, all) => generateFrom$1(spec, all);
2982     const generate$4 = spec => {
2983       const all = getBehaviours$2(spec);
2984       return generateFrom(spec, all);
2985     };
2987     const getDomDefinition = (info, bList, bData) => {
2988       const definition = toDefinition(info);
2989       const infoModification = toModification(info);
2990       const baseModification = { 'alloy.base.modification': infoModification };
2991       const modification = bList.length > 0 ? combine$2(bData, baseModification, bList, definition) : infoModification;
2992       return merge(definition, modification);
2993     };
2994     const getEvents = (info, bList, bData) => {
2995       const baseEvents = { 'alloy.base.behaviour': toEvents(info) };
2996       return combine$1(bData, info.eventOrder, bList, baseEvents).getOrDie();
2997     };
2998     const build$2 = (spec, obsoleted) => {
2999       const getMe = () => me;
3000       const systemApi = Cell(singleton$1);
3001       const info = getOrDie(toInfo(spec));
3002       const bBlob = generate$4(spec);
3003       const bList = getBehaviours$3(bBlob);
3004       const bData = getData$2(bBlob);
3005       const modDefinition = getDomDefinition(info, bList, bData);
3006       const item = renderToDom(modDefinition, obsoleted);
3007       const events = getEvents(info, bList, bData);
3008       const subcomponents = Cell(info.components);
3009       const connect = newApi => {
3010         systemApi.set(newApi);
3011       };
3012       const disconnect = () => {
3013         systemApi.set(NoContextApi(getMe));
3014       };
3015       const syncComponents = () => {
3016         const children$1 = children(item);
3017         const subs = bind$3(children$1, child => systemApi.get().getByDom(child).fold(() => [], pure$2));
3018         subcomponents.set(subs);
3019       };
3020       const config = behaviour => {
3021         const b = bData;
3022         const f = isFunction(b[behaviour.name()]) ? b[behaviour.name()] : () => {
3023           throw new Error('Could not find ' + behaviour.name() + ' in ' + JSON.stringify(spec, null, 2));
3024         };
3025         return f();
3026       };
3027       const hasConfigured = behaviour => isFunction(bData[behaviour.name()]);
3028       const getApis = () => info.apis;
3029       const readState = behaviourName => bData[behaviourName]().map(b => b.state.readState()).getOr('not enabled');
3030       const me = {
3031         uid: spec.uid,
3032         getSystem: systemApi.get,
3033         config,
3034         hasConfigured,
3035         spec,
3036         readState,
3037         getApis,
3038         connect,
3039         disconnect,
3040         element: item,
3041         syncComponents,
3042         components: subcomponents.get,
3043         events
3044       };
3045       return me;
3046     };
3048     const buildSubcomponents = (spec, obsoleted) => {
3049       const components = get$g(spec, 'components').getOr([]);
3050       return obsoleted.fold(() => map$2(components, build$1), obs => map$2(components, (c, i) => {
3051         return buildOrPatch(c, child$2(obs, i));
3052       }));
3053     };
3054     const buildFromSpec = (userSpec, obsoleted) => {
3055       const {
3056         events: specEvents,
3057         ...spec
3058       } = make$8(userSpec);
3059       const components = buildSubcomponents(spec, obsoleted);
3060       const completeSpec = {
3061         ...spec,
3062         events: {
3063           ...DefaultEvents,
3064           ...specEvents
3065         },
3066         components
3067       };
3068       return Result.value(build$2(completeSpec, obsoleted));
3069     };
3070     const text$2 = textContent => {
3071       const element = SugarElement.fromText(textContent);
3072       return external$1({ element });
3073     };
3074     const external$1 = spec => {
3075       const extSpec = asRawOrDie$1('external.component', objOfOnly([
3076         required$1('element'),
3077         option$3('uid')
3078       ]), spec);
3079       const systemApi = Cell(NoContextApi());
3080       const connect = newApi => {
3081         systemApi.set(newApi);
3082       };
3083       const disconnect = () => {
3084         systemApi.set(NoContextApi(() => me));
3085       };
3086       const uid = extSpec.uid.getOrThunk(() => generate$5('external'));
3087       writeOnly(extSpec.element, uid);
3088       const me = {
3089         uid,
3090         getSystem: systemApi.get,
3091         config: Optional.none,
3092         hasConfigured: never,
3093         connect,
3094         disconnect,
3095         getApis: () => ({}),
3096         element: extSpec.element,
3097         spec,
3098         readState: constant$1('No state'),
3099         syncComponents: noop,
3100         components: constant$1([]),
3101         events: {}
3102       };
3103       return premade$1(me);
3104     };
3105     const uids = generate$5;
3106     const isSketchSpec$1 = spec => has$2(spec, 'uid');
3107     const buildOrPatch = (spec, obsoleted) => getPremade(spec).getOrThunk(() => {
3108       const userSpecWithUid = isSketchSpec$1(spec) ? spec : {
3109         uid: uids(''),
3110         ...spec
3111       };
3112       return buildFromSpec(userSpecWithUid, obsoleted).getOrDie();
3113     });
3114     const build$1 = spec => buildOrPatch(spec, Optional.none());
3115     const premade = premade$1;
3117     var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
3118       if (is(scope, a)) {
3119         return Optional.some(scope);
3120       } else if (isFunction(isRoot) && isRoot(scope)) {
3121         return Optional.none();
3122       } else {
3123         return ancestor(scope, a, isRoot);
3124       }
3125     };
3127     const ancestor$1 = (scope, predicate, isRoot) => {
3128       let element = scope.dom;
3129       const stop = isFunction(isRoot) ? isRoot : never;
3130       while (element.parentNode) {
3131         element = element.parentNode;
3132         const el = SugarElement.fromDom(element);
3133         if (predicate(el)) {
3134           return Optional.some(el);
3135         } else if (stop(el)) {
3136           break;
3137         }
3138       }
3139       return Optional.none();
3140     };
3141     const closest$3 = (scope, predicate, isRoot) => {
3142       const is = (s, test) => test(s);
3143       return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
3144     };
3145     const child$1 = (scope, predicate) => {
3146       const pred = node => predicate(SugarElement.fromDom(node));
3147       const result = find$5(scope.dom.childNodes, pred);
3148       return result.map(SugarElement.fromDom);
3149     };
3150     const descendant$1 = (scope, predicate) => {
3151       const descend = node => {
3152         for (let i = 0; i < node.childNodes.length; i++) {
3153           const child = SugarElement.fromDom(node.childNodes[i]);
3154           if (predicate(child)) {
3155             return Optional.some(child);
3156           }
3157           const res = descend(node.childNodes[i]);
3158           if (res.isSome()) {
3159             return res;
3160           }
3161         }
3162         return Optional.none();
3163       };
3164       return descend(scope.dom);
3165     };
3167     const closest$2 = (scope, predicate, isRoot) => closest$3(scope, predicate, isRoot).isSome();
3169     const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is(e, selector), isRoot);
3170     const child = (scope, selector) => child$1(scope, e => is(e, selector));
3171     const descendant = (scope, selector) => one(selector, scope);
3172     const closest$1 = (scope, selector, isRoot) => {
3173       const is$1 = (element, selector) => is(element, selector);
3174       return ClosestOrAncestor(is$1, ancestor, scope, selector, isRoot);
3175     };
3177     const attribute = 'aria-controls';
3178     const find$1 = queryElem => {
3179       const dependent = closest$3(queryElem, elem => {
3180         if (!isElement$1(elem)) {
3181           return false;
3182         }
3183         const id = get$f(elem, 'id');
3184         return id !== undefined && id.indexOf(attribute) > -1;
3185       });
3186       return dependent.bind(dep => {
3187         const id = get$f(dep, 'id');
3188         const dos = getRootNode(dep);
3189         return descendant(dos, `[${ attribute }="${ id }"]`);
3190       });
3191     };
3192     const manager = () => {
3193       const ariaId = generate$6(attribute);
3194       const link = elem => {
3195         set$9(elem, attribute, ariaId);
3196       };
3197       const unlink = elem => {
3198         remove$7(elem, attribute);
3199       };
3200       return {
3201         id: ariaId,
3202         link,
3203         unlink
3204       };
3205     };
3207     const isAriaPartOf = (component, queryElem) => find$1(queryElem).exists(owner => isPartOf$1(component, owner));
3208     const isPartOf$1 = (component, queryElem) => closest$2(queryElem, el => eq(el, component.element), never) || isAriaPartOf(component, queryElem);
3210     const unknown = 'unknown';
3211     var EventConfiguration;
3212     (function (EventConfiguration) {
3213       EventConfiguration[EventConfiguration['STOP'] = 0] = 'STOP';
3214       EventConfiguration[EventConfiguration['NORMAL'] = 1] = 'NORMAL';
3215       EventConfiguration[EventConfiguration['LOGGING'] = 2] = 'LOGGING';
3216     }(EventConfiguration || (EventConfiguration = {})));
3217     const eventConfig = Cell({});
3218     const makeEventLogger = (eventName, initialTarget) => {
3219       const sequence = [];
3220       const startTime = new Date().getTime();
3221       return {
3222         logEventCut: (_name, target, purpose) => {
3223           sequence.push({
3224             outcome: 'cut',
3225             target,
3226             purpose
3227           });
3228         },
3229         logEventStopped: (_name, target, purpose) => {
3230           sequence.push({
3231             outcome: 'stopped',
3232             target,
3233             purpose
3234           });
3235         },
3236         logNoParent: (_name, target, purpose) => {
3237           sequence.push({
3238             outcome: 'no-parent',
3239             target,
3240             purpose
3241           });
3242         },
3243         logEventNoHandlers: (_name, target) => {
3244           sequence.push({
3245             outcome: 'no-handlers-left',
3246             target
3247           });
3248         },
3249         logEventResponse: (_name, target, purpose) => {
3250           sequence.push({
3251             outcome: 'response',
3252             purpose,
3253             target
3254           });
3255         },
3256         write: () => {
3257           const finishTime = new Date().getTime();
3258           if (contains$2([
3259               'mousemove',
3260               'mouseover',
3261               'mouseout',
3262               systemInit()
3263             ], eventName)) {
3264             return;
3265           }
3266           console.log(eventName, {
3267             event: eventName,
3268             time: finishTime - startTime,
3269             target: initialTarget.dom,
3270             sequence: map$2(sequence, s => {
3271               if (!contains$2([
3272                   'cut',
3273                   'stopped',
3274                   'response'
3275                 ], s.outcome)) {
3276                 return s.outcome;
3277               } else {
3278                 return '{' + s.purpose + '} ' + s.outcome + ' at (' + element(s.target) + ')';
3279               }
3280             })
3281           });
3282         }
3283       };
3284     };
3285     const processEvent = (eventName, initialTarget, f) => {
3286       const status = get$g(eventConfig.get(), eventName).orThunk(() => {
3287         const patterns = keys(eventConfig.get());
3288         return findMap(patterns, p => eventName.indexOf(p) > -1 ? Optional.some(eventConfig.get()[p]) : Optional.none());
3289       }).getOr(EventConfiguration.NORMAL);
3290       switch (status) {
3291       case EventConfiguration.NORMAL:
3292         return f(noLogger());
3293       case EventConfiguration.LOGGING: {
3294           const logger = makeEventLogger(eventName, initialTarget);
3295           const output = f(logger);
3296           logger.write();
3297           return output;
3298         }
3299       case EventConfiguration.STOP:
3300         return true;
3301       }
3302     };
3303     const path = [
3304       'alloy/data/Fields',
3305       'alloy/debugging/Debugging'
3306     ];
3307     const getTrace = () => {
3308       const err = new Error();
3309       if (err.stack !== undefined) {
3310         const lines = err.stack.split('\n');
3311         return find$5(lines, line => line.indexOf('alloy') > 0 && !exists(path, p => line.indexOf(p) > -1)).getOr(unknown);
3312       } else {
3313         return unknown;
3314       }
3315     };
3316     const ignoreEvent = {
3317       logEventCut: noop,
3318       logEventStopped: noop,
3319       logNoParent: noop,
3320       logEventNoHandlers: noop,
3321       logEventResponse: noop,
3322       write: noop
3323     };
3324     const monitorEvent = (eventName, initialTarget, f) => processEvent(eventName, initialTarget, f);
3325     const noLogger = constant$1(ignoreEvent);
3327     const menuFields = constant$1([
3328       required$1('menu'),
3329       required$1('selectedMenu')
3330     ]);
3331     const itemFields = constant$1([
3332       required$1('item'),
3333       required$1('selectedItem')
3334     ]);
3335     constant$1(objOf(itemFields().concat(menuFields())));
3336     const itemSchema$3 = constant$1(objOf(itemFields()));
3338     const _initSize = requiredObjOf('initSize', [
3339       required$1('numColumns'),
3340       required$1('numRows')
3341     ]);
3342     const itemMarkers = () => requiredOf('markers', itemSchema$3());
3343     const tieredMenuMarkers = () => requiredObjOf('markers', [required$1('backgroundMenu')].concat(menuFields()).concat(itemFields()));
3344     const markers$1 = required => requiredObjOf('markers', map$2(required, required$1));
3345     const onPresenceHandler = (label, fieldName, presence) => {
3346       getTrace();
3347       return field$1(fieldName, fieldName, presence, valueOf(f => Result.value((...args) => {
3348         return f.apply(undefined, args);
3349       })));
3350     };
3351     const onHandler = fieldName => onPresenceHandler('onHandler', fieldName, defaulted$1(noop));
3352     const onKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, defaulted$1(Optional.none));
3353     const onStrictHandler = fieldName => onPresenceHandler('onHandler', fieldName, required$2());
3354     const onStrictKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, required$2());
3355     const output$1 = (name, value) => customField(name, constant$1(value));
3356     const snapshot = name => customField(name, identity);
3357     const initSize = constant$1(_initSize);
3359     const nu$6 = (x, y, bubble, direction, placement, boundsRestriction, labelPrefix, alwaysFit = false) => ({
3360       x,
3361       y,
3362       bubble,
3363       direction,
3364       placement,
3365       restriction: boundsRestriction,
3366       label: `${ labelPrefix }-${ placement }`,
3367       alwaysFit
3368     });
3370     const adt$a = Adt.generate([
3371       { southeast: [] },
3372       { southwest: [] },
3373       { northeast: [] },
3374       { northwest: [] },
3375       { south: [] },
3376       { north: [] },
3377       { east: [] },
3378       { west: [] }
3379     ]);
3380     const cata$2 = (subject, southeast, southwest, northeast, northwest, south, north, east, west) => subject.fold(southeast, southwest, northeast, northwest, south, north, east, west);
3381     const cataVertical = (subject, south, middle, north) => subject.fold(south, south, north, north, south, north, middle, middle);
3382     const cataHorizontal = (subject, east, middle, west) => subject.fold(east, west, east, west, middle, middle, east, west);
3383     const southeast$3 = adt$a.southeast;
3384     const southwest$3 = adt$a.southwest;
3385     const northeast$3 = adt$a.northeast;
3386     const northwest$3 = adt$a.northwest;
3387     const south$3 = adt$a.south;
3388     const north$3 = adt$a.north;
3389     const east$3 = adt$a.east;
3390     const west$3 = adt$a.west;
3392     const cycleBy = (value, delta, min, max) => {
3393       const r = value + delta;
3394       if (r > max) {
3395         return min;
3396       } else if (r < min) {
3397         return max;
3398       } else {
3399         return r;
3400       }
3401     };
3402     const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
3404     const getRestriction = (anchor, restriction) => {
3405       switch (restriction) {
3406       case 1:
3407         return anchor.x;
3408       case 0:
3409         return anchor.x + anchor.width;
3410       case 2:
3411         return anchor.y;
3412       case 3:
3413         return anchor.y + anchor.height;
3414       }
3415     };
3416     const boundsRestriction = (anchor, restrictions) => mapToObject([
3417       'left',
3418       'right',
3419       'top',
3420       'bottom'
3421     ], dir => get$g(restrictions, dir).map(restriction => getRestriction(anchor, restriction)));
3422     const adjustBounds = (bounds$1, restriction, bubbleOffset) => {
3423       const applyRestriction = (dir, current) => restriction[dir].map(pos => {
3424         const isVerticalAxis = dir === 'top' || dir === 'bottom';
3425         const offset = isVerticalAxis ? bubbleOffset.top : bubbleOffset.left;
3426         const comparator = dir === 'left' || dir === 'top' ? Math.max : Math.min;
3427         const newPos = comparator(pos, current) + offset;
3428         return isVerticalAxis ? clamp(newPos, bounds$1.y, bounds$1.bottom) : clamp(newPos, bounds$1.x, bounds$1.right);
3429       }).getOr(current);
3430       const adjustedLeft = applyRestriction('left', bounds$1.x);
3431       const adjustedTop = applyRestriction('top', bounds$1.y);
3432       const adjustedRight = applyRestriction('right', bounds$1.right);
3433       const adjustedBottom = applyRestriction('bottom', bounds$1.bottom);
3434       return bounds(adjustedLeft, adjustedTop, adjustedRight - adjustedLeft, adjustedBottom - adjustedTop);
3435     };
3437     const labelPrefix$2 = 'layout';
3438     const eastX$1 = anchor => anchor.x;
3439     const middleX$1 = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
3440     const westX$1 = (anchor, element) => anchor.x + anchor.width - element.width;
3441     const northY$2 = (anchor, element) => anchor.y - element.height;
3442     const southY$2 = anchor => anchor.y + anchor.height;
3443     const centreY$1 = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
3444     const eastEdgeX$1 = anchor => anchor.x + anchor.width;
3445     const westEdgeX$1 = (anchor, element) => anchor.x - element.width;
3446     const southeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), southY$2(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
3447       left: 1,
3448       top: 3
3449     }), labelPrefix$2);
3450     const southwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), southY$2(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
3451       right: 0,
3452       top: 3
3453     }), labelPrefix$2);
3454     const northeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), northY$2(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
3455       left: 1,
3456       bottom: 2
3457     }), labelPrefix$2);
3458     const northwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), northY$2(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
3459       right: 0,
3460       bottom: 2
3461     }), labelPrefix$2);
3462     const north$2 = (anchor, element, bubbles) => nu$6(middleX$1(anchor, element), northY$2(anchor, element), bubbles.north(), north$3(), 'north', boundsRestriction(anchor, { bottom: 2 }), labelPrefix$2);
3463     const south$2 = (anchor, element, bubbles) => nu$6(middleX$1(anchor, element), southY$2(anchor), bubbles.south(), south$3(), 'south', boundsRestriction(anchor, { top: 3 }), labelPrefix$2);
3464     const east$2 = (anchor, element, bubbles) => nu$6(eastEdgeX$1(anchor), centreY$1(anchor, element), bubbles.east(), east$3(), 'east', boundsRestriction(anchor, { left: 0 }), labelPrefix$2);
3465     const west$2 = (anchor, element, bubbles) => nu$6(westEdgeX$1(anchor, element), centreY$1(anchor, element), bubbles.west(), west$3(), 'west', boundsRestriction(anchor, { right: 1 }), labelPrefix$2);
3466     const all$1 = () => [
3467       southeast$2,
3468       southwest$2,
3469       northeast$2,
3470       northwest$2,
3471       south$2,
3472       north$2,
3473       east$2,
3474       west$2
3475     ];
3476     const allRtl$1 = () => [
3477       southwest$2,
3478       southeast$2,
3479       northwest$2,
3480       northeast$2,
3481       south$2,
3482       north$2,
3483       east$2,
3484       west$2
3485     ];
3486     const aboveOrBelow = () => [
3487       northeast$2,
3488       northwest$2,
3489       southeast$2,
3490       southwest$2,
3491       north$2,
3492       south$2
3493     ];
3494     const aboveOrBelowRtl = () => [
3495       northwest$2,
3496       northeast$2,
3497       southwest$2,
3498       southeast$2,
3499       north$2,
3500       south$2
3501     ];
3502     const belowOrAbove = () => [
3503       southeast$2,
3504       southwest$2,
3505       northeast$2,
3506       northwest$2,
3507       south$2,
3508       north$2
3509     ];
3510     const belowOrAboveRtl = () => [
3511       southwest$2,
3512       southeast$2,
3513       northwest$2,
3514       northeast$2,
3515       south$2,
3516       north$2
3517     ];
3519     const chooseChannels = (channels, message) => message.universal ? channels : filter$2(channels, ch => contains$2(message.channels, ch));
3520     const events$h = receiveConfig => derive$2([run$1(receive(), (component, message) => {
3521         const channelMap = receiveConfig.channels;
3522         const channels = keys(channelMap);
3523         const receivingData = message;
3524         const targetChannels = chooseChannels(channels, receivingData);
3525         each$1(targetChannels, ch => {
3526           const channelInfo = channelMap[ch];
3527           const channelSchema = channelInfo.schema;
3528           const data = asRawOrDie$1('channel[' + ch + '] data\nReceiver: ' + element(component.element), channelSchema, receivingData.data);
3529           channelInfo.onReceive(component, data);
3530         });
3531       })]);
3533     var ActiveReceiving = /*#__PURE__*/Object.freeze({
3534         __proto__: null,
3535         events: events$h
3536     });
3538     var ReceivingSchema = [requiredOf('channels', setOf(Result.value, objOfOnly([
3539         onStrictHandler('onReceive'),
3540         defaulted('schema', anyValue())
3541       ])))];
3543     const executeEvent = (bConfig, bState, executor) => runOnExecute$1(component => {
3544       executor(component, bConfig, bState);
3545     });
3546     const loadEvent = (bConfig, bState, f) => runOnInit((component, _simulatedEvent) => {
3547       f(component, bConfig, bState);
3548     });
3549     const create$5 = (schema, name, active, apis, extra, state) => {
3550       const configSchema = objOfOnly(schema);
3551       const schemaSchema = optionObjOf(name, [optionObjOfOnly('config', schema)]);
3552       return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
3553     };
3554     const createModes$1 = (modes, name, active, apis, extra, state) => {
3555       const configSchema = modes;
3556       const schemaSchema = optionObjOf(name, [optionOf('config', modes)]);
3557       return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
3558     };
3559     const wrapApi = (bName, apiFunction, apiName) => {
3560       const f = (component, ...rest) => {
3561         const args = [component].concat(rest);
3562         return component.config({ name: constant$1(bName) }).fold(() => {
3563           throw new Error('We could not find any behaviour configuration for: ' + bName + '. Using API: ' + apiName);
3564         }, info => {
3565           const rest = Array.prototype.slice.call(args, 1);
3566           return apiFunction.apply(undefined, [
3567             component,
3568             info.config,
3569             info.state
3570           ].concat(rest));
3571         });
3572       };
3573       return markAsBehaviourApi(f, apiName, apiFunction);
3574     };
3575     const revokeBehaviour = name => ({
3576       key: name,
3577       value: undefined
3578     });
3579     const doCreate = (configSchema, schemaSchema, name, active, apis, extra, state) => {
3580       const getConfig = info => hasNonNullableKey(info, name) ? info[name]() : Optional.none();
3581       const wrappedApis = map$1(apis, (apiF, apiName) => wrapApi(name, apiF, apiName));
3582       const wrappedExtra = map$1(extra, (extraF, extraName) => markAsExtraApi(extraF, extraName));
3583       const me = {
3584         ...wrappedExtra,
3585         ...wrappedApis,
3586         revoke: curry(revokeBehaviour, name),
3587         config: spec => {
3588           const prepared = asRawOrDie$1(name + '-config', configSchema, spec);
3589           return {
3590             key: name,
3591             value: {
3592               config: prepared,
3593               me,
3594               configAsRaw: cached(() => asRawOrDie$1(name + '-config', configSchema, spec)),
3595               initialConfig: spec,
3596               state
3597             }
3598           };
3599         },
3600         schema: constant$1(schemaSchema),
3601         exhibit: (info, base) => {
3602           return lift2(getConfig(info), get$g(active, 'exhibit'), (behaviourInfo, exhibitor) => {
3603             return exhibitor(base, behaviourInfo.config, behaviourInfo.state);
3604           }).getOrThunk(() => nu$7({}));
3605         },
3606         name: constant$1(name),
3607         handlers: info => {
3608           return getConfig(info).map(behaviourInfo => {
3609             const getEvents = get$g(active, 'events').getOr(() => ({}));
3610             return getEvents(behaviourInfo.config, behaviourInfo.state);
3611           }).getOr({});
3612         }
3613       };
3614       return me;
3615     };
3617     const derive$1 = capabilities => wrapAll(capabilities);
3618     const simpleSchema = objOfOnly([
3619       required$1('fields'),
3620       required$1('name'),
3621       defaulted('active', {}),
3622       defaulted('apis', {}),
3623       defaulted('state', NoState),
3624       defaulted('extra', {})
3625     ]);
3626     const create$4 = data => {
3627       const value = asRawOrDie$1('Creating behaviour: ' + data.name, simpleSchema, data);
3628       return create$5(value.fields, value.name, value.active, value.apis, value.extra, value.state);
3629     };
3630     const modeSchema = objOfOnly([
3631       required$1('branchKey'),
3632       required$1('branches'),
3633       required$1('name'),
3634       defaulted('active', {}),
3635       defaulted('apis', {}),
3636       defaulted('state', NoState),
3637       defaulted('extra', {})
3638     ]);
3639     const createModes = data => {
3640       const value = asRawOrDie$1('Creating behaviour: ' + data.name, modeSchema, data);
3641       return createModes$1(choose$1(value.branchKey, value.branches), value.name, value.active, value.apis, value.extra, value.state);
3642     };
3643     const revoke = constant$1(undefined);
3645     const Receiving = create$4({
3646       fields: ReceivingSchema,
3647       name: 'receiving',
3648       active: ActiveReceiving
3649     });
3651     const exhibit$6 = (base, posConfig) => nu$7({
3652       classes: [],
3653       styles: posConfig.useFixed() ? {} : { position: 'relative' }
3654     });
3656     var ActivePosition = /*#__PURE__*/Object.freeze({
3657         __proto__: null,
3658         exhibit: exhibit$6
3659     });
3661     const focus$3 = element => element.dom.focus();
3662     const blur$1 = element => element.dom.blur();
3663     const hasFocus = element => {
3664       const root = getRootNode(element).dom;
3665       return element.dom === root.activeElement;
3666     };
3667     const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
3668     const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
3670     const preserve$1 = (f, container) => {
3671       const dos = getRootNode(container);
3672       const refocus = active$1(dos).bind(focused => {
3673         const hasFocus = elem => eq(focused, elem);
3674         return hasFocus(container) ? Optional.some(container) : descendant$1(container, hasFocus);
3675       });
3676       const result = f(container);
3677       refocus.each(oldFocus => {
3678         active$1(dos).filter(newFocus => eq(newFocus, oldFocus)).fold(() => {
3679           focus$3(oldFocus);
3680         }, noop);
3681       });
3682       return result;
3683     };
3685     const NuPositionCss = (position, left, top, right, bottom) => {
3686       const toPx = num => num + 'px';
3687       return {
3688         position,
3689         left: left.map(toPx),
3690         top: top.map(toPx),
3691         right: right.map(toPx),
3692         bottom: bottom.map(toPx)
3693       };
3694     };
3695     const toOptions = position => ({
3696       ...position,
3697       position: Optional.some(position.position)
3698     });
3699     const applyPositionCss = (element, position) => {
3700       setOptions(element, toOptions(position));
3701     };
3703     const adt$9 = Adt.generate([
3704       { none: [] },
3705       {
3706         relative: [
3707           'x',
3708           'y',
3709           'width',
3710           'height'
3711         ]
3712       },
3713       {
3714         fixed: [
3715           'x',
3716           'y',
3717           'width',
3718           'height'
3719         ]
3720       }
3721     ]);
3722     const positionWithDirection = (posName, decision, x, y, width, height) => {
3723       const decisionRect = decision.rect;
3724       const decisionX = decisionRect.x - x;
3725       const decisionY = decisionRect.y - y;
3726       const decisionWidth = decisionRect.width;
3727       const decisionHeight = decisionRect.height;
3728       const decisionRight = width - (decisionX + decisionWidth);
3729       const decisionBottom = height - (decisionY + decisionHeight);
3730       const left = Optional.some(decisionX);
3731       const top = Optional.some(decisionY);
3732       const right = Optional.some(decisionRight);
3733       const bottom = Optional.some(decisionBottom);
3734       const none = Optional.none();
3735       return cata$2(decision.direction, () => NuPositionCss(posName, left, top, none, none), () => NuPositionCss(posName, none, top, right, none), () => NuPositionCss(posName, left, none, none, bottom), () => NuPositionCss(posName, none, none, right, bottom), () => NuPositionCss(posName, left, top, none, none), () => NuPositionCss(posName, left, none, none, bottom), () => NuPositionCss(posName, left, top, none, none), () => NuPositionCss(posName, none, top, right, none));
3736     };
3737     const reposition = (origin, decision) => origin.fold(() => {
3738       const decisionRect = decision.rect;
3739       return NuPositionCss('absolute', Optional.some(decisionRect.x), Optional.some(decisionRect.y), Optional.none(), Optional.none());
3740     }, (x, y, width, height) => {
3741       return positionWithDirection('absolute', decision, x, y, width, height);
3742     }, (x, y, width, height) => {
3743       return positionWithDirection('fixed', decision, x, y, width, height);
3744     });
3745     const toBox = (origin, element) => {
3746       const rel = curry(find$2, element);
3747       const position = origin.fold(rel, rel, () => {
3748         const scroll = get$b();
3749         return find$2(element).translate(-scroll.left, -scroll.top);
3750       });
3751       const width = getOuter$1(element);
3752       const height = getOuter$2(element);
3753       return bounds(position.left, position.top, width, height);
3754     };
3755     const viewport = (origin, getBounds) => getBounds.fold(() => origin.fold(win, win, bounds), b => origin.fold(b, b, () => {
3756       const bounds$1 = b();
3757       const pos = translate$2(origin, bounds$1.x, bounds$1.y);
3758       return bounds(pos.left, pos.top, bounds$1.width, bounds$1.height);
3759     }));
3760     const translate$2 = (origin, x, y) => {
3761       const pos = SugarPosition(x, y);
3762       const removeScroll = () => {
3763         const outerScroll = get$b();
3764         return pos.translate(-outerScroll.left, -outerScroll.top);
3765       };
3766       return origin.fold(constant$1(pos), constant$1(pos), removeScroll);
3767     };
3768     const cata$1 = (subject, onNone, onRelative, onFixed) => subject.fold(onNone, onRelative, onFixed);
3769     adt$9.none;
3770     const relative$1 = adt$9.relative;
3771     const fixed$1 = adt$9.fixed;
3773     const anchor = (anchorBox, origin) => ({
3774       anchorBox,
3775       origin
3776     });
3777     const box = (anchorBox, origin) => anchor(anchorBox, origin);
3779     const placementAttribute = 'data-alloy-placement';
3780     const setPlacement$1 = (element, placement) => {
3781       set$9(element, placementAttribute, placement);
3782     };
3783     const getPlacement = element => getOpt(element, placementAttribute);
3784     const reset$2 = element => remove$7(element, placementAttribute);
3786     const adt$8 = Adt.generate([
3787       { fit: ['reposition'] },
3788       {
3789         nofit: [
3790           'reposition',
3791           'visibleW',
3792           'visibleH',
3793           'isVisible'
3794         ]
3795       }
3796     ]);
3797     const determinePosition = (box, bounds) => {
3798       const {
3799         x: boundsX,
3800         y: boundsY,
3801         right: boundsRight,
3802         bottom: boundsBottom
3803       } = bounds;
3804       const {x, y, right, bottom, width, height} = box;
3805       const xInBounds = x >= boundsX && x <= boundsRight;
3806       const yInBounds = y >= boundsY && y <= boundsBottom;
3807       const originInBounds = xInBounds && yInBounds;
3808       const rightInBounds = right <= boundsRight && right >= boundsX;
3809       const bottomInBounds = bottom <= boundsBottom && bottom >= boundsY;
3810       const sizeInBounds = rightInBounds && bottomInBounds;
3811       const visibleW = Math.min(width, x >= boundsX ? boundsRight - x : right - boundsX);
3812       const visibleH = Math.min(height, y >= boundsY ? boundsBottom - y : bottom - boundsY);
3813       return {
3814         originInBounds,
3815         sizeInBounds,
3816         visibleW,
3817         visibleH
3818       };
3819     };
3820     const calcReposition = (box, bounds$1) => {
3821       const {
3822         x: boundsX,
3823         y: boundsY,
3824         right: boundsRight,
3825         bottom: boundsBottom
3826       } = bounds$1;
3827       const {x, y, width, height} = box;
3828       const maxX = Math.max(boundsX, boundsRight - width);
3829       const maxY = Math.max(boundsY, boundsBottom - height);
3830       const restrictedX = clamp(x, boundsX, maxX);
3831       const restrictedY = clamp(y, boundsY, maxY);
3832       const restrictedWidth = Math.min(restrictedX + width, boundsRight) - restrictedX;
3833       const restrictedHeight = Math.min(restrictedY + height, boundsBottom) - restrictedY;
3834       return bounds(restrictedX, restrictedY, restrictedWidth, restrictedHeight);
3835     };
3836     const calcMaxSizes = (direction, box, bounds) => {
3837       const upAvailable = constant$1(box.bottom - bounds.y);
3838       const downAvailable = constant$1(bounds.bottom - box.y);
3839       const maxHeight = cataVertical(direction, downAvailable, downAvailable, upAvailable);
3840       const westAvailable = constant$1(box.right - bounds.x);
3841       const eastAvailable = constant$1(bounds.right - box.x);
3842       const maxWidth = cataHorizontal(direction, eastAvailable, eastAvailable, westAvailable);
3843       return {
3844         maxWidth,
3845         maxHeight
3846       };
3847     };
3848     const attempt = (candidate, width, height, bounds$1) => {
3849       const bubble = candidate.bubble;
3850       const bubbleOffset = bubble.offset;
3851       const adjustedBounds = adjustBounds(bounds$1, candidate.restriction, bubbleOffset);
3852       const newX = candidate.x + bubbleOffset.left;
3853       const newY = candidate.y + bubbleOffset.top;
3854       const box = bounds(newX, newY, width, height);
3855       const {originInBounds, sizeInBounds, visibleW, visibleH} = determinePosition(box, adjustedBounds);
3856       const fits = originInBounds && sizeInBounds;
3857       const fittedBox = fits ? box : calcReposition(box, adjustedBounds);
3858       const isPartlyVisible = fittedBox.width > 0 && fittedBox.height > 0;
3859       const {maxWidth, maxHeight} = calcMaxSizes(candidate.direction, fittedBox, bounds$1);
3860       const reposition = {
3861         rect: fittedBox,
3862         maxHeight,
3863         maxWidth,
3864         direction: candidate.direction,
3865         placement: candidate.placement,
3866         classes: {
3867           on: bubble.classesOn,
3868           off: bubble.classesOff
3869         },
3870         layout: candidate.label,
3871         testY: newY
3872       };
3873       return fits || candidate.alwaysFit ? adt$8.fit(reposition) : adt$8.nofit(reposition, visibleW, visibleH, isPartlyVisible);
3874     };
3875     const attempts = (element, candidates, anchorBox, elementBox, bubbles, bounds) => {
3876       const panelWidth = elementBox.width;
3877       const panelHeight = elementBox.height;
3878       const attemptBestFit = (layout, reposition, visibleW, visibleH, isVisible) => {
3879         const next = layout(anchorBox, elementBox, bubbles, element, bounds);
3880         const attemptLayout = attempt(next, panelWidth, panelHeight, bounds);
3881         return attemptLayout.fold(constant$1(attemptLayout), (newReposition, newVisibleW, newVisibleH, newIsVisible) => {
3882           const improved = isVisible === newIsVisible ? newVisibleH > visibleH || newVisibleW > visibleW : !isVisible && newIsVisible;
3883           return improved ? attemptLayout : adt$8.nofit(reposition, visibleW, visibleH, isVisible);
3884         });
3885       };
3886       const abc = foldl(candidates, (b, a) => {
3887         const bestNext = curry(attemptBestFit, a);
3888         return b.fold(constant$1(b), bestNext);
3889       }, adt$8.nofit({
3890         rect: anchorBox,
3891         maxHeight: elementBox.height,
3892         maxWidth: elementBox.width,
3893         direction: southeast$3(),
3894         placement: 'southeast',
3895         classes: {
3896           on: [],
3897           off: []
3898         },
3899         layout: 'none',
3900         testY: anchorBox.y
3901       }, -1, -1, false));
3902       return abc.fold(identity, identity);
3903     };
3905     const singleton = doRevoke => {
3906       const subject = Cell(Optional.none());
3907       const revoke = () => subject.get().each(doRevoke);
3908       const clear = () => {
3909         revoke();
3910         subject.set(Optional.none());
3911       };
3912       const isSet = () => subject.get().isSome();
3913       const get = () => subject.get();
3914       const set = s => {
3915         revoke();
3916         subject.set(Optional.some(s));
3917       };
3918       return {
3919         clear,
3920         isSet,
3921         get,
3922         set
3923       };
3924     };
3925     const destroyable = () => singleton(s => s.destroy());
3926     const unbindable = () => singleton(s => s.unbind());
3927     const value$2 = () => {
3928       const subject = singleton(noop);
3929       const on = f => subject.get().each(f);
3930       return {
3931         ...subject,
3932         on
3933       };
3934     };
3936     const filter = always;
3937     const bind = (element, event, handler) => bind$2(element, event, filter, handler);
3938     const capture = (element, event, handler) => capture$1(element, event, filter, handler);
3939     const fromRawEvent = fromRawEvent$1;
3941     const properties = [
3942       'top',
3943       'bottom',
3944       'right',
3945       'left'
3946     ];
3947     const timerAttr = 'data-alloy-transition-timer';
3948     const isTransitioning$1 = (element, transition) => hasAll(element, transition.classes);
3949     const shouldApplyTransitionCss = (transition, decision, lastPlacement) => {
3950       return lastPlacement.exists(placer => {
3951         const mode = transition.mode;
3952         return mode === 'all' ? true : placer[mode] !== decision[mode];
3953       });
3954     };
3955     const hasChanges = (position, intermediate) => {
3956       const round = value => parseFloat(value).toFixed(3);
3957       return find$4(intermediate, (value, key) => {
3958         const newValue = position[key].map(round);
3959         const val = value.map(round);
3960         return !equals(newValue, val);
3961       }).isSome();
3962     };
3963     const getTransitionDuration = element => {
3964       const get = name => {
3965         const style = get$e(element, name);
3966         const times = style.split(/\s*,\s*/);
3967         return filter$2(times, isNotEmpty);
3968       };
3969       const parse = value => {
3970         if (isString(value) && /^[\d.]+/.test(value)) {
3971           const num = parseFloat(value);
3972           return endsWith(value, 'ms') ? num : num * 1000;
3973         } else {
3974           return 0;
3975         }
3976       };
3977       const delay = get('transition-delay');
3978       const duration = get('transition-duration');
3979       return foldl(duration, (acc, dur, i) => {
3980         const time = parse(delay[i]) + parse(dur);
3981         return Math.max(acc, time);
3982       }, 0);
3983     };
3984     const setupTransitionListeners = (element, transition) => {
3985       const transitionEnd = unbindable();
3986       const transitionCancel = unbindable();
3987       let timer;
3988       const isSourceTransition = e => {
3989         const pseudoElement = e.raw.pseudoElement ?? '';
3990         return eq(e.target, element) && isEmpty(pseudoElement) && contains$2(properties, e.raw.propertyName);
3991       };
3992       const transitionDone = e => {
3993         if (isNullable(e) || isSourceTransition(e)) {
3994           transitionEnd.clear();
3995           transitionCancel.clear();
3996           const type = e?.raw.type;
3997           if (isNullable(type) || type === transitionend()) {
3998             clearTimeout(timer);
3999             remove$7(element, timerAttr);
4000             remove$1(element, transition.classes);
4001           }
4002         }
4003       };
4004       const transitionStart = bind(element, transitionstart(), e => {
4005         if (isSourceTransition(e)) {
4006           transitionStart.unbind();
4007           transitionEnd.set(bind(element, transitionend(), transitionDone));
4008           transitionCancel.set(bind(element, transitioncancel(), transitionDone));
4009         }
4010       });
4011       const duration = getTransitionDuration(element);
4012       requestAnimationFrame(() => {
4013         timer = setTimeout(transitionDone, duration + 17);
4014         set$9(element, timerAttr, timer);
4015       });
4016     };
4017     const startTransitioning = (element, transition) => {
4018       add$1(element, transition.classes);
4019       getOpt(element, timerAttr).each(timerId => {
4020         clearTimeout(parseInt(timerId, 10));
4021         remove$7(element, timerAttr);
4022       });
4023       setupTransitionListeners(element, transition);
4024     };
4025     const applyTransitionCss = (element, origin, position, transition, decision, lastPlacement) => {
4026       const shouldTransition = shouldApplyTransitionCss(transition, decision, lastPlacement);
4027       if (shouldTransition || isTransitioning$1(element, transition)) {
4028         set$8(element, 'position', position.position);
4029         const rect = toBox(origin, element);
4030         const intermediatePosition = reposition(origin, {
4031           ...decision,
4032           rect
4033         });
4034         const intermediateCssOptions = mapToObject(properties, prop => intermediatePosition[prop]);
4035         if (hasChanges(position, intermediateCssOptions)) {
4036           setOptions(element, intermediateCssOptions);
4037           if (shouldTransition) {
4038             startTransitioning(element, transition);
4039           }
4040           reflow(element);
4041         }
4042       } else {
4043         remove$1(element, transition.classes);
4044       }
4045     };
4047     const elementSize = p => ({
4048       width: getOuter$1(p),
4049       height: getOuter$2(p)
4050     });
4051     const layout = (anchorBox, element, bubbles, options) => {
4052       remove$6(element, 'max-height');
4053       remove$6(element, 'max-width');
4054       const elementBox = elementSize(element);
4055       return attempts(element, options.preference, anchorBox, elementBox, bubbles, options.bounds);
4056     };
4057     const setClasses = (element, decision) => {
4058       const classInfo = decision.classes;
4059       remove$1(element, classInfo.off);
4060       add$1(element, classInfo.on);
4061     };
4062     const setHeight = (element, decision, options) => {
4063       const maxHeightFunction = options.maxHeightFunction;
4064       maxHeightFunction(element, decision.maxHeight);
4065     };
4066     const setWidth = (element, decision, options) => {
4067       const maxWidthFunction = options.maxWidthFunction;
4068       maxWidthFunction(element, decision.maxWidth);
4069     };
4070     const position$2 = (element, decision, options) => {
4071       const positionCss = reposition(options.origin, decision);
4072       options.transition.each(transition => {
4073         applyTransitionCss(element, options.origin, positionCss, transition, decision, options.lastPlacement);
4074       });
4075       applyPositionCss(element, positionCss);
4076     };
4077     const setPlacement = (element, decision) => {
4078       setPlacement$1(element, decision.placement);
4079     };
4081     const setMaxHeight = (element, maxHeight) => {
4082       setMax$1(element, Math.floor(maxHeight));
4083     };
4084     const anchored = constant$1((element, available) => {
4085       setMaxHeight(element, available);
4086       setAll(element, {
4087         'overflow-x': 'hidden',
4088         'overflow-y': 'auto'
4089       });
4090     });
4091     const expandable$1 = constant$1((element, available) => {
4092       setMaxHeight(element, available);
4093     });
4095     const defaultOr = (options, key, dephault) => options[key] === undefined ? dephault : options[key];
4096     const simple = (anchor, element, bubble, layouts, lastPlacement, getBounds, overrideOptions, transition) => {
4097       const maxHeightFunction = defaultOr(overrideOptions, 'maxHeightFunction', anchored());
4098       const maxWidthFunction = defaultOr(overrideOptions, 'maxWidthFunction', noop);
4099       const anchorBox = anchor.anchorBox;
4100       const origin = anchor.origin;
4101       const options = {
4102         bounds: viewport(origin, getBounds),
4103         origin,
4104         preference: layouts,
4105         maxHeightFunction,
4106         maxWidthFunction,
4107         lastPlacement,
4108         transition
4109       };
4110       return go(anchorBox, element, bubble, options);
4111     };
4112     const go = (anchorBox, element, bubble, options) => {
4113       const decision = layout(anchorBox, element, bubble, options);
4114       position$2(element, decision, options);
4115       setPlacement(element, decision);
4116       setClasses(element, decision);
4117       setHeight(element, decision, options);
4118       setWidth(element, decision, options);
4119       return {
4120         layout: decision.layout,
4121         placement: decision.placement
4122       };
4123     };
4125     const allAlignments = [
4126       'valignCentre',
4127       'alignLeft',
4128       'alignRight',
4129       'alignCentre',
4130       'top',
4131       'bottom',
4132       'left',
4133       'right',
4134       'inset'
4135     ];
4136     const nu$5 = (xOffset, yOffset, classes, insetModifier = 1) => {
4137       const insetXOffset = xOffset * insetModifier;
4138       const insetYOffset = yOffset * insetModifier;
4139       const getClasses = prop => get$g(classes, prop).getOr([]);
4140       const make = (xDelta, yDelta, alignmentsOn) => {
4141         const alignmentsOff = difference(allAlignments, alignmentsOn);
4142         return {
4143           offset: SugarPosition(xDelta, yDelta),
4144           classesOn: bind$3(alignmentsOn, getClasses),
4145           classesOff: bind$3(alignmentsOff, getClasses)
4146         };
4147       };
4148       return {
4149         southeast: () => make(-xOffset, yOffset, [
4150           'top',
4151           'alignLeft'
4152         ]),
4153         southwest: () => make(xOffset, yOffset, [
4154           'top',
4155           'alignRight'
4156         ]),
4157         south: () => make(-xOffset / 2, yOffset, [
4158           'top',
4159           'alignCentre'
4160         ]),
4161         northeast: () => make(-xOffset, -yOffset, [
4162           'bottom',
4163           'alignLeft'
4164         ]),
4165         northwest: () => make(xOffset, -yOffset, [
4166           'bottom',
4167           'alignRight'
4168         ]),
4169         north: () => make(-xOffset / 2, -yOffset, [
4170           'bottom',
4171           'alignCentre'
4172         ]),
4173         east: () => make(xOffset, -yOffset / 2, [
4174           'valignCentre',
4175           'left'
4176         ]),
4177         west: () => make(-xOffset, -yOffset / 2, [
4178           'valignCentre',
4179           'right'
4180         ]),
4181         insetNortheast: () => make(insetXOffset, insetYOffset, [
4182           'top',
4183           'alignLeft',
4184           'inset'
4185         ]),
4186         insetNorthwest: () => make(-insetXOffset, insetYOffset, [
4187           'top',
4188           'alignRight',
4189           'inset'
4190         ]),
4191         insetNorth: () => make(-insetXOffset / 2, insetYOffset, [
4192           'top',
4193           'alignCentre',
4194           'inset'
4195         ]),
4196         insetSoutheast: () => make(insetXOffset, -insetYOffset, [
4197           'bottom',
4198           'alignLeft',
4199           'inset'
4200         ]),
4201         insetSouthwest: () => make(-insetXOffset, -insetYOffset, [
4202           'bottom',
4203           'alignRight',
4204           'inset'
4205         ]),
4206         insetSouth: () => make(-insetXOffset / 2, -insetYOffset, [
4207           'bottom',
4208           'alignCentre',
4209           'inset'
4210         ]),
4211         insetEast: () => make(-insetXOffset, -insetYOffset / 2, [
4212           'valignCentre',
4213           'right',
4214           'inset'
4215         ]),
4216         insetWest: () => make(insetXOffset, -insetYOffset / 2, [
4217           'valignCentre',
4218           'left',
4219           'inset'
4220         ])
4221       };
4222     };
4223     const fallback = () => nu$5(0, 0, {});
4225     const nu$4 = identity;
4227     const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
4228     const getDirection = element => get$e(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
4230     var AttributeValue;
4231     (function (AttributeValue) {
4232       AttributeValue['TopToBottom'] = 'toptobottom';
4233       AttributeValue['BottomToTop'] = 'bottomtotop';
4234     }(AttributeValue || (AttributeValue = {})));
4235     const Attribute = 'data-alloy-vertical-dir';
4236     const isBottomToTopDir = el => closest$2(el, current => isElement$1(current) && get$f(current, 'data-alloy-vertical-dir') === AttributeValue.BottomToTop);
4238     const schema$y = () => optionObjOf('layouts', [
4239       required$1('onLtr'),
4240       required$1('onRtl'),
4241       option$3('onBottomLtr'),
4242       option$3('onBottomRtl')
4243     ]);
4244     const get$5 = (elem, info, defaultLtr, defaultRtl, defaultBottomLtr, defaultBottomRtl, dirElement) => {
4245       const isBottomToTop = dirElement.map(isBottomToTopDir).getOr(false);
4246       const customLtr = info.layouts.map(ls => ls.onLtr(elem));
4247       const customRtl = info.layouts.map(ls => ls.onRtl(elem));
4248       const ltr = isBottomToTop ? info.layouts.bind(ls => ls.onBottomLtr.map(f => f(elem))).or(customLtr).getOr(defaultBottomLtr) : customLtr.getOr(defaultLtr);
4249       const rtl = isBottomToTop ? info.layouts.bind(ls => ls.onBottomRtl.map(f => f(elem))).or(customRtl).getOr(defaultBottomRtl) : customRtl.getOr(defaultRtl);
4250       const f = onDirection(ltr, rtl);
4251       return f(elem);
4252     };
4254     const placement$4 = (component, anchorInfo, origin) => {
4255       const hotspot = anchorInfo.hotspot;
4256       const anchorBox = toBox(origin, hotspot.element);
4257       const layouts = get$5(component.element, anchorInfo, belowOrAbove(), belowOrAboveRtl(), aboveOrBelow(), aboveOrBelowRtl(), Optional.some(anchorInfo.hotspot.element));
4258       return Optional.some(nu$4({
4259         anchorBox,
4260         bubble: anchorInfo.bubble.getOr(fallback()),
4261         overrides: anchorInfo.overrides,
4262         layouts,
4263         placer: Optional.none()
4264       }));
4265     };
4266     var HotspotAnchor = [
4267       required$1('hotspot'),
4268       option$3('bubble'),
4269       defaulted('overrides', {}),
4270       schema$y(),
4271       output$1('placement', placement$4)
4272     ];
4274     const placement$3 = (component, anchorInfo, origin) => {
4275       const pos = translate$2(origin, anchorInfo.x, anchorInfo.y);
4276       const anchorBox = bounds(pos.left, pos.top, anchorInfo.width, anchorInfo.height);
4277       const layouts = get$5(component.element, anchorInfo, all$1(), allRtl$1(), all$1(), allRtl$1(), Optional.none());
4278       return Optional.some(nu$4({
4279         anchorBox,
4280         bubble: anchorInfo.bubble,
4281         overrides: anchorInfo.overrides,
4282         layouts,
4283         placer: Optional.none()
4284       }));
4285     };
4286     var MakeshiftAnchor = [
4287       required$1('x'),
4288       required$1('y'),
4289       defaulted('height', 0),
4290       defaulted('width', 0),
4291       defaulted('bubble', fallback()),
4292       defaulted('overrides', {}),
4293       schema$y(),
4294       output$1('placement', placement$3)
4295     ];
4297     const adt$7 = Adt.generate([
4298       { screen: ['point'] },
4299       {
4300         absolute: [
4301           'point',
4302           'scrollLeft',
4303           'scrollTop'
4304         ]
4305       }
4306     ]);
4307     const toFixed = pos => pos.fold(identity, (point, scrollLeft, scrollTop) => point.translate(-scrollLeft, -scrollTop));
4308     const toAbsolute = pos => pos.fold(identity, identity);
4309     const sum = points => foldl(points, (b, a) => b.translate(a.left, a.top), SugarPosition(0, 0));
4310     const sumAsFixed = positions => {
4311       const points = map$2(positions, toFixed);
4312       return sum(points);
4313     };
4314     const sumAsAbsolute = positions => {
4315       const points = map$2(positions, toAbsolute);
4316       return sum(points);
4317     };
4318     const screen = adt$7.screen;
4319     const absolute$1 = adt$7.absolute;
4321     const getOffset = (component, origin, anchorInfo) => {
4322       const win = defaultView(anchorInfo.root).dom;
4323       const hasSameOwner = frame => {
4324         const frameOwner = owner$4(frame);
4325         const compOwner = owner$4(component.element);
4326         return eq(frameOwner, compOwner);
4327       };
4328       return Optional.from(win.frameElement).map(SugarElement.fromDom).filter(hasSameOwner).map(absolute$3);
4329     };
4330     const getRootPoint = (component, origin, anchorInfo) => {
4331       const doc = owner$4(component.element);
4332       const outerScroll = get$b(doc);
4333       const offset = getOffset(component, origin, anchorInfo).getOr(outerScroll);
4334       return absolute$1(offset, outerScroll.left, outerScroll.top);
4335     };
4337     const getBox = (left, top, width, height) => {
4338       const point = screen(SugarPosition(left, top));
4339       return Optional.some(pointed(point, width, height));
4340     };
4341     const calcNewAnchor = (optBox, rootPoint, anchorInfo, origin, elem) => optBox.map(box => {
4342       const points = [
4343         rootPoint,
4344         box.point
4345       ];
4346       const topLeft = cata$1(origin, () => sumAsAbsolute(points), () => sumAsAbsolute(points), () => sumAsFixed(points));
4347       const anchorBox = rect(topLeft.left, topLeft.top, box.width, box.height);
4348       const layoutsLtr = anchorInfo.showAbove ? aboveOrBelow() : belowOrAbove();
4349       const layoutsRtl = anchorInfo.showAbove ? aboveOrBelowRtl() : belowOrAboveRtl();
4350       const layouts = get$5(elem, anchorInfo, layoutsLtr, layoutsRtl, layoutsLtr, layoutsRtl, Optional.none());
4351       return nu$4({
4352         anchorBox,
4353         bubble: anchorInfo.bubble.getOr(fallback()),
4354         overrides: anchorInfo.overrides,
4355         layouts,
4356         placer: Optional.none()
4357       });
4358     });
4360     const placement$2 = (component, anchorInfo, origin) => {
4361       const rootPoint = getRootPoint(component, origin, anchorInfo);
4362       return anchorInfo.node.filter(inBody).bind(target => {
4363         const rect = target.dom.getBoundingClientRect();
4364         const nodeBox = getBox(rect.left, rect.top, rect.width, rect.height);
4365         const elem = anchorInfo.node.getOr(component.element);
4366         return calcNewAnchor(nodeBox, rootPoint, anchorInfo, origin, elem);
4367       });
4368     };
4369     var NodeAnchor = [
4370       required$1('node'),
4371       required$1('root'),
4372       option$3('bubble'),
4373       schema$y(),
4374       defaulted('overrides', {}),
4375       defaulted('showAbove', false),
4376       output$1('placement', placement$2)
4377     ];
4379     const zeroWidth = '\uFEFF';
4380     const nbsp = '\xA0';
4382     const create$3 = (start, soffset, finish, foffset) => ({
4383       start,
4384       soffset,
4385       finish,
4386       foffset
4387     });
4388     const SimRange = { create: create$3 };
4390     const adt$6 = Adt.generate([
4391       { before: ['element'] },
4392       {
4393         on: [
4394           'element',
4395           'offset'
4396         ]
4397       },
4398       { after: ['element'] }
4399     ]);
4400     const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
4401     const getStart$1 = situ => situ.fold(identity, identity, identity);
4402     const before = adt$6.before;
4403     const on$1 = adt$6.on;
4404     const after$1 = adt$6.after;
4405     const Situ = {
4406       before,
4407       on: on$1,
4408       after: after$1,
4409       cata,
4410       getStart: getStart$1
4411     };
4413     const adt$5 = Adt.generate([
4414       { domRange: ['rng'] },
4415       {
4416         relative: [
4417           'startSitu',
4418           'finishSitu'
4419         ]
4420       },
4421       {
4422         exact: [
4423           'start',
4424           'soffset',
4425           'finish',
4426           'foffset'
4427         ]
4428       }
4429     ]);
4430     const exactFromRange = simRange => adt$5.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
4431     const getStart = selection => selection.match({
4432       domRange: rng => SugarElement.fromDom(rng.startContainer),
4433       relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
4434       exact: (start, _soffset, _finish, _foffset) => start
4435     });
4436     const domRange = adt$5.domRange;
4437     const relative = adt$5.relative;
4438     const exact = adt$5.exact;
4439     const getWin = selection => {
4440       const start = getStart(selection);
4441       return defaultView(start);
4442     };
4443     const range$1 = SimRange.create;
4444     const SimSelection = {
4445       domRange,
4446       relative,
4447       exact,
4448       exactFromRange,
4449       getWin,
4450       range: range$1
4451     };
4453     const setStart = (rng, situ) => {
4454       situ.fold(e => {
4455         rng.setStartBefore(e.dom);
4456       }, (e, o) => {
4457         rng.setStart(e.dom, o);
4458       }, e => {
4459         rng.setStartAfter(e.dom);
4460       });
4461     };
4462     const setFinish = (rng, situ) => {
4463       situ.fold(e => {
4464         rng.setEndBefore(e.dom);
4465       }, (e, o) => {
4466         rng.setEnd(e.dom, o);
4467       }, e => {
4468         rng.setEndAfter(e.dom);
4469       });
4470     };
4471     const relativeToNative = (win, startSitu, finishSitu) => {
4472       const range = win.document.createRange();
4473       setStart(range, startSitu);
4474       setFinish(range, finishSitu);
4475       return range;
4476     };
4477     const exactToNative = (win, start, soffset, finish, foffset) => {
4478       const rng = win.document.createRange();
4479       rng.setStart(start.dom, soffset);
4480       rng.setEnd(finish.dom, foffset);
4481       return rng;
4482     };
4483     const toRect = rect => ({
4484       left: rect.left,
4485       top: rect.top,
4486       right: rect.right,
4487       bottom: rect.bottom,
4488       width: rect.width,
4489       height: rect.height
4490     });
4491     const getFirstRect$1 = rng => {
4492       const rects = rng.getClientRects();
4493       const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
4494       return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
4495     };
4496     const getBounds$2 = rng => {
4497       const rect = rng.getBoundingClientRect();
4498       return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
4499     };
4501     const adt$4 = Adt.generate([
4502       {
4503         ltr: [
4504           'start',
4505           'soffset',
4506           'finish',
4507           'foffset'
4508         ]
4509       },
4510       {
4511         rtl: [
4512           'start',
4513           'soffset',
4514           'finish',
4515           'foffset'
4516         ]
4517       }
4518     ]);
4519     const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
4520     const getRanges = (win, selection) => selection.match({
4521       domRange: rng => {
4522         return {
4523           ltr: constant$1(rng),
4524           rtl: Optional.none
4525         };
4526       },
4527       relative: (startSitu, finishSitu) => {
4528         return {
4529           ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
4530           rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
4531         };
4532       },
4533       exact: (start, soffset, finish, foffset) => {
4534         return {
4535           ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
4536           rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
4537         };
4538       }
4539     });
4540     const doDiagnose = (win, ranges) => {
4541       const rng = ranges.ltr();
4542       if (rng.collapsed) {
4543         const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
4544         return reversed.map(rev => adt$4.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$4.ltr, rng));
4545       } else {
4546         return fromRange(win, adt$4.ltr, rng);
4547       }
4548     };
4549     const diagnose = (win, selection) => {
4550       const ranges = getRanges(win, selection);
4551       return doDiagnose(win, ranges);
4552     };
4553     const asLtrRange = (win, selection) => {
4554       const diagnosis = diagnose(win, selection);
4555       return diagnosis.match({
4556         ltr: (start, soffset, finish, foffset) => {
4557           const rng = win.document.createRange();
4558           rng.setStart(start.dom, soffset);
4559           rng.setEnd(finish.dom, foffset);
4560           return rng;
4561         },
4562         rtl: (start, soffset, finish, foffset) => {
4563           const rng = win.document.createRange();
4564           rng.setStart(finish.dom, foffset);
4565           rng.setEnd(start.dom, soffset);
4566           return rng;
4567         }
4568       });
4569     };
4570     adt$4.ltr;
4571     adt$4.rtl;
4573     const descendants = (scope, selector) => all$3(selector, scope);
4575     const makeRange = (start, soffset, finish, foffset) => {
4576       const doc = owner$4(start);
4577       const rng = doc.dom.createRange();
4578       rng.setStart(start.dom, soffset);
4579       rng.setEnd(finish.dom, foffset);
4580       return rng;
4581     };
4582     const after = (start, soffset, finish, foffset) => {
4583       const r = makeRange(start, soffset, finish, foffset);
4584       const same = eq(start, finish) && soffset === foffset;
4585       return r.collapsed && !same;
4586     };
4588     const getNativeSelection = win => Optional.from(win.getSelection());
4589     const readRange = selection => {
4590       if (selection.rangeCount > 0) {
4591         const firstRng = selection.getRangeAt(0);
4592         const lastRng = selection.getRangeAt(selection.rangeCount - 1);
4593         return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
4594       } else {
4595         return Optional.none();
4596       }
4597     };
4598     const doGetExact = selection => {
4599       if (selection.anchorNode === null || selection.focusNode === null) {
4600         return readRange(selection);
4601       } else {
4602         const anchor = SugarElement.fromDom(selection.anchorNode);
4603         const focus = SugarElement.fromDom(selection.focusNode);
4604         return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
4605       }
4606     };
4607     const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
4608     const getFirstRect = (win, selection) => {
4609       const rng = asLtrRange(win, selection);
4610       return getFirstRect$1(rng);
4611     };
4612     const getBounds$1 = (win, selection) => {
4613       const rng = asLtrRange(win, selection);
4614       return getBounds$2(rng);
4615     };
4617     const NodeValue = (is, name) => {
4618       const get = element => {
4619         if (!is(element)) {
4620           throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
4621         }
4622         return getOption(element).getOr('');
4623       };
4624       const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
4625       const set = (element, value) => {
4626         if (!is(element)) {
4627           throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
4628         }
4629         element.dom.nodeValue = value;
4630       };
4631       return {
4632         get,
4633         getOption,
4634         set
4635       };
4636     };
4638     const api = NodeValue(isText, 'text');
4639     const get$4 = element => api.get(element);
4641     const point = (element, offset) => ({
4642       element,
4643       offset
4644     });
4645     const descendOnce$1 = (element, offset) => {
4646       const children$1 = children(element);
4647       if (children$1.length === 0) {
4648         return point(element, offset);
4649       } else if (offset < children$1.length) {
4650         return point(children$1[offset], 0);
4651       } else {
4652         const last = children$1[children$1.length - 1];
4653         const len = isText(last) ? get$4(last).length : children(last).length;
4654         return point(last, len);
4655       }
4656     };
4658     const descendOnce = (element, offset) => isText(element) ? point(element, offset) : descendOnce$1(element, offset);
4659     const getAnchorSelection = (win, anchorInfo) => {
4660       const getSelection = anchorInfo.getSelection.getOrThunk(() => () => getExact(win));
4661       return getSelection().map(sel => {
4662         const modStart = descendOnce(sel.start, sel.soffset);
4663         const modFinish = descendOnce(sel.finish, sel.foffset);
4664         return SimSelection.range(modStart.element, modStart.offset, modFinish.element, modFinish.offset);
4665       });
4666     };
4667     const placement$1 = (component, anchorInfo, origin) => {
4668       const win = defaultView(anchorInfo.root).dom;
4669       const rootPoint = getRootPoint(component, origin, anchorInfo);
4670       const selectionBox = getAnchorSelection(win, anchorInfo).bind(sel => {
4671         const optRect = getBounds$1(win, SimSelection.exactFromRange(sel)).orThunk(() => {
4672           const x = SugarElement.fromText(zeroWidth);
4673           before$1(sel.start, x);
4674           const rect = getFirstRect(win, SimSelection.exact(x, 0, x, 1));
4675           remove$5(x);
4676           return rect;
4677         });
4678         return optRect.bind(rawRect => getBox(rawRect.left, rawRect.top, rawRect.width, rawRect.height));
4679       });
4680       const targetElement = getAnchorSelection(win, anchorInfo).bind(sel => isElement$1(sel.start) ? Optional.some(sel.start) : parentElement(sel.start));
4681       const elem = targetElement.getOr(component.element);
4682       return calcNewAnchor(selectionBox, rootPoint, anchorInfo, origin, elem);
4683     };
4684     var SelectionAnchor = [
4685       option$3('getSelection'),
4686       required$1('root'),
4687       option$3('bubble'),
4688       schema$y(),
4689       defaulted('overrides', {}),
4690       defaulted('showAbove', false),
4691       output$1('placement', placement$1)
4692     ];
4694     const labelPrefix$1 = 'link-layout';
4695     const eastX = anchor => anchor.x + anchor.width;
4696     const westX = (anchor, element) => anchor.x - element.width;
4697     const northY$1 = (anchor, element) => anchor.y - element.height + anchor.height;
4698     const southY$1 = anchor => anchor.y;
4699     const southeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), southY$1(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
4700       left: 0,
4701       top: 2
4702     }), labelPrefix$1);
4703     const southwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), southY$1(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
4704       right: 1,
4705       top: 2
4706     }), labelPrefix$1);
4707     const northeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), northY$1(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
4708       left: 0,
4709       bottom: 3
4710     }), labelPrefix$1);
4711     const northwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), northY$1(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
4712       right: 1,
4713       bottom: 3
4714     }), labelPrefix$1);
4715     const all = () => [
4716       southeast$1,
4717       southwest$1,
4718       northeast$1,
4719       northwest$1
4720     ];
4721     const allRtl = () => [
4722       southwest$1,
4723       southeast$1,
4724       northwest$1,
4725       northeast$1
4726     ];
4728     const placement = (component, submenuInfo, origin) => {
4729       const anchorBox = toBox(origin, submenuInfo.item.element);
4730       const layouts = get$5(component.element, submenuInfo, all(), allRtl(), all(), allRtl(), Optional.none());
4731       return Optional.some(nu$4({
4732         anchorBox,
4733         bubble: fallback(),
4734         overrides: submenuInfo.overrides,
4735         layouts,
4736         placer: Optional.none()
4737       }));
4738     };
4739     var SubmenuAnchor = [
4740       required$1('item'),
4741       schema$y(),
4742       defaulted('overrides', {}),
4743       output$1('placement', placement)
4744     ];
4746     var AnchorSchema = choose$1('type', {
4747       selection: SelectionAnchor,
4748       node: NodeAnchor,
4749       hotspot: HotspotAnchor,
4750       submenu: SubmenuAnchor,
4751       makeshift: MakeshiftAnchor
4752     });
4754     const TransitionSchema = [
4755       requiredArrayOf('classes', string),
4756       defaultedStringEnum('mode', 'all', [
4757         'all',
4758         'layout',
4759         'placement'
4760       ])
4761     ];
4762     const PositionSchema = [
4763       defaulted('useFixed', never),
4764       option$3('getBounds')
4765     ];
4766     const PlacementSchema = [
4767       requiredOf('anchor', AnchorSchema),
4768       optionObjOf('transition', TransitionSchema)
4769     ];
4771     const getFixedOrigin = () => {
4772       const html = document.documentElement;
4773       return fixed$1(0, 0, html.clientWidth, html.clientHeight);
4774     };
4775     const getRelativeOrigin = component => {
4776       const position = absolute$3(component.element);
4777       const bounds = component.element.dom.getBoundingClientRect();
4778       return relative$1(position.left, position.top, bounds.width, bounds.height);
4779     };
4780     const place = (component, origin, anchoring, getBounds, placee, lastPlace, transition) => {
4781       const anchor = box(anchoring.anchorBox, origin);
4782       return simple(anchor, placee.element, anchoring.bubble, anchoring.layouts, lastPlace, getBounds, anchoring.overrides, transition);
4783     };
4784     const position$1 = (component, posConfig, posState, placee, placementSpec) => {
4785       positionWithin(component, posConfig, posState, placee, placementSpec, Optional.none());
4786     };
4787     const positionWithin = (component, posConfig, posState, placee, placementSpec, boxElement) => {
4788       const boundsBox = boxElement.map(box$1);
4789       return positionWithinBounds(component, posConfig, posState, placee, placementSpec, boundsBox);
4790     };
4791     const positionWithinBounds = (component, posConfig, posState, placee, placementSpec, bounds) => {
4792       const placeeDetail = asRawOrDie$1('placement.info', objOf(PlacementSchema), placementSpec);
4793       const anchorage = placeeDetail.anchor;
4794       const element = placee.element;
4795       const placeeState = posState.get(placee.uid);
4796       preserve$1(() => {
4797         set$8(element, 'position', 'fixed');
4798         const oldVisibility = getRaw(element, 'visibility');
4799         set$8(element, 'visibility', 'hidden');
4800         const origin = posConfig.useFixed() ? getFixedOrigin() : getRelativeOrigin(component);
4801         const placer = anchorage.placement;
4802         const getBounds = bounds.map(constant$1).or(posConfig.getBounds);
4803         placer(component, anchorage, origin).each(anchoring => {
4804           const doPlace = anchoring.placer.getOr(place);
4805           const newState = doPlace(component, origin, anchoring, getBounds, placee, placeeState, placeeDetail.transition);
4806           posState.set(placee.uid, newState);
4807         });
4808         oldVisibility.fold(() => {
4809           remove$6(element, 'visibility');
4810         }, vis => {
4811           set$8(element, 'visibility', vis);
4812         });
4813         if (getRaw(element, 'left').isNone() && getRaw(element, 'top').isNone() && getRaw(element, 'right').isNone() && getRaw(element, 'bottom').isNone() && is$1(getRaw(element, 'position'), 'fixed')) {
4814           remove$6(element, 'position');
4815         }
4816       }, element);
4817     };
4818     const getMode = (component, pConfig, _pState) => pConfig.useFixed() ? 'fixed' : 'absolute';
4819     const reset$1 = (component, pConfig, posState, placee) => {
4820       const element = placee.element;
4821       each$1([
4822         'position',
4823         'left',
4824         'right',
4825         'top',
4826         'bottom'
4827       ], prop => remove$6(element, prop));
4828       reset$2(element);
4829       posState.clear(placee.uid);
4830     };
4832     var PositionApis = /*#__PURE__*/Object.freeze({
4833         __proto__: null,
4834         position: position$1,
4835         positionWithin: positionWithin,
4836         positionWithinBounds: positionWithinBounds,
4837         getMode: getMode,
4838         reset: reset$1
4839     });
4841     const init$g = () => {
4842       let state = {};
4843       const set = (id, data) => {
4844         state[id] = data;
4845       };
4846       const get = id => get$g(state, id);
4847       const clear = id => {
4848         if (isNonNullable(id)) {
4849           delete state[id];
4850         } else {
4851           state = {};
4852         }
4853       };
4854       return nu$8({
4855         readState: () => state,
4856         clear,
4857         set,
4858         get
4859       });
4860     };
4862     var PositioningState = /*#__PURE__*/Object.freeze({
4863         __proto__: null,
4864         init: init$g
4865     });
4867     const Positioning = create$4({
4868       fields: PositionSchema,
4869       name: 'positioning',
4870       active: ActivePosition,
4871       apis: PositionApis,
4872       state: PositioningState
4873     });
4875     const isConnected = comp => comp.getSystem().isConnected();
4876     const fireDetaching = component => {
4877       emit(component, detachedFromDom());
4878       const children = component.components();
4879       each$1(children, fireDetaching);
4880     };
4881     const fireAttaching = component => {
4882       const children = component.components();
4883       each$1(children, fireAttaching);
4884       emit(component, attachedToDom());
4885     };
4886     const virtualAttach = (parent, child) => {
4887       parent.getSystem().addToWorld(child);
4888       if (inBody(parent.element)) {
4889         fireAttaching(child);
4890       }
4891     };
4892     const virtualDetach = comp => {
4893       fireDetaching(comp);
4894       comp.getSystem().removeFromWorld(comp);
4895     };
4896     const attach$1 = (parent, child) => {
4897       append$2(parent.element, child.element);
4898     };
4899     const detachChildren$1 = component => {
4900       each$1(component.components(), childComp => remove$5(childComp.element));
4901       empty(component.element);
4902       component.syncComponents();
4903     };
4904     const replaceChildren = (component, newSpecs, buildNewChildren) => {
4905       const subs = component.components();
4906       detachChildren$1(component);
4907       const newChildren = buildNewChildren(newSpecs);
4908       const deleted = difference(subs, newChildren);
4909       each$1(deleted, comp => {
4910         fireDetaching(comp);
4911         component.getSystem().removeFromWorld(comp);
4912       });
4913       each$1(newChildren, childComp => {
4914         if (!isConnected(childComp)) {
4915           component.getSystem().addToWorld(childComp);
4916           attach$1(component, childComp);
4917           if (inBody(component.element)) {
4918             fireAttaching(childComp);
4919           }
4920         } else {
4921           attach$1(component, childComp);
4922         }
4923       });
4924       component.syncComponents();
4925     };
4926     const virtualReplaceChildren = (component, newSpecs, buildNewChildren) => {
4927       const subs = component.components();
4928       const existingComps = bind$3(newSpecs, spec => getPremade(spec).toArray());
4929       each$1(subs, childComp => {
4930         if (!contains$2(existingComps, childComp)) {
4931           virtualDetach(childComp);
4932         }
4933       });
4934       const newChildren = buildNewChildren(newSpecs);
4935       const deleted = difference(subs, newChildren);
4936       each$1(deleted, deletedComp => {
4937         if (isConnected(deletedComp)) {
4938           virtualDetach(deletedComp);
4939         }
4940       });
4941       each$1(newChildren, childComp => {
4942         if (!isConnected(childComp)) {
4943           virtualAttach(component, childComp);
4944         }
4945       });
4946       component.syncComponents();
4947     };
4949     const attach = (parent, child) => {
4950       attachWith(parent, child, append$2);
4951     };
4952     const attachWith = (parent, child, insertion) => {
4953       parent.getSystem().addToWorld(child);
4954       insertion(parent.element, child.element);
4955       if (inBody(parent.element)) {
4956         fireAttaching(child);
4957       }
4958       parent.syncComponents();
4959     };
4960     const doDetach = component => {
4961       fireDetaching(component);
4962       remove$5(component.element);
4963       component.getSystem().removeFromWorld(component);
4964     };
4965     const detach = component => {
4966       const parent$1 = parent(component.element).bind(p => component.getSystem().getByDom(p).toOptional());
4967       doDetach(component);
4968       parent$1.each(p => {
4969         p.syncComponents();
4970       });
4971     };
4972     const detachChildren = component => {
4973       const subs = component.components();
4974       each$1(subs, doDetach);
4975       empty(component.element);
4976       component.syncComponents();
4977     };
4978     const attachSystem = (element, guiSystem) => {
4979       attachSystemWith(element, guiSystem, append$2);
4980     };
4981     const attachSystemAfter = (element, guiSystem) => {
4982       attachSystemWith(element, guiSystem, after$2);
4983     };
4984     const attachSystemWith = (element, guiSystem, inserter) => {
4985       inserter(element, guiSystem.element);
4986       const children$1 = children(guiSystem.element);
4987       each$1(children$1, child => {
4988         guiSystem.getByDom(child).each(fireAttaching);
4989       });
4990     };
4991     const detachSystem = guiSystem => {
4992       const children$1 = children(guiSystem.element);
4993       each$1(children$1, child => {
4994         guiSystem.getByDom(child).each(fireDetaching);
4995       });
4996       remove$5(guiSystem.element);
4997     };
4999     const rebuild = (sandbox, sConfig, sState, data) => {
5000       sState.get().each(_data => {
5001         detachChildren(sandbox);
5002       });
5003       const point = sConfig.getAttachPoint(sandbox);
5004       attach(point, sandbox);
5005       const built = sandbox.getSystem().build(data);
5006       attach(sandbox, built);
5007       sState.set(built);
5008       return built;
5009     };
5010     const open$1 = (sandbox, sConfig, sState, data) => {
5011       const newState = rebuild(sandbox, sConfig, sState, data);
5012       sConfig.onOpen(sandbox, newState);
5013       return newState;
5014     };
5015     const setContent = (sandbox, sConfig, sState, data) => sState.get().map(() => rebuild(sandbox, sConfig, sState, data));
5016     const openWhileCloaked = (sandbox, sConfig, sState, data, transaction) => {
5017       cloak(sandbox, sConfig);
5018       open$1(sandbox, sConfig, sState, data);
5019       transaction();
5020       decloak(sandbox, sConfig);
5021     };
5022     const close$1 = (sandbox, sConfig, sState) => {
5023       sState.get().each(data => {
5024         detachChildren(sandbox);
5025         detach(sandbox);
5026         sConfig.onClose(sandbox, data);
5027         sState.clear();
5028       });
5029     };
5030     const isOpen$1 = (_sandbox, _sConfig, sState) => sState.isOpen();
5031     const isPartOf = (sandbox, sConfig, sState, queryElem) => isOpen$1(sandbox, sConfig, sState) && sState.get().exists(data => sConfig.isPartOf(sandbox, data, queryElem));
5032     const getState$2 = (_sandbox, _sConfig, sState) => sState.get();
5033     const store = (sandbox, cssKey, attr, newValue) => {
5034       getRaw(sandbox.element, cssKey).fold(() => {
5035         remove$7(sandbox.element, attr);
5036       }, v => {
5037         set$9(sandbox.element, attr, v);
5038       });
5039       set$8(sandbox.element, cssKey, newValue);
5040     };
5041     const restore = (sandbox, cssKey, attr) => {
5042       getOpt(sandbox.element, attr).fold(() => remove$6(sandbox.element, cssKey), oldValue => set$8(sandbox.element, cssKey, oldValue));
5043     };
5044     const cloak = (sandbox, sConfig, _sState) => {
5045       const sink = sConfig.getAttachPoint(sandbox);
5046       set$8(sandbox.element, 'position', Positioning.getMode(sink));
5047       store(sandbox, 'visibility', sConfig.cloakVisibilityAttr, 'hidden');
5048     };
5049     const hasPosition = element => exists([
5050       'top',
5051       'left',
5052       'right',
5053       'bottom'
5054     ], pos => getRaw(element, pos).isSome());
5055     const decloak = (sandbox, sConfig, _sState) => {
5056       if (!hasPosition(sandbox.element)) {
5057         remove$6(sandbox.element, 'position');
5058       }
5059       restore(sandbox, 'visibility', sConfig.cloakVisibilityAttr);
5060     };
5062     var SandboxApis = /*#__PURE__*/Object.freeze({
5063         __proto__: null,
5064         cloak: cloak,
5065         decloak: decloak,
5066         open: open$1,
5067         openWhileCloaked: openWhileCloaked,
5068         close: close$1,
5069         isOpen: isOpen$1,
5070         isPartOf: isPartOf,
5071         getState: getState$2,
5072         setContent: setContent
5073     });
5075     const events$g = (sandboxConfig, sandboxState) => derive$2([run$1(sandboxClose(), (sandbox, _simulatedEvent) => {
5076         close$1(sandbox, sandboxConfig, sandboxState);
5077       })]);
5079     var ActiveSandbox = /*#__PURE__*/Object.freeze({
5080         __proto__: null,
5081         events: events$g
5082     });
5084     var SandboxSchema = [
5085       onHandler('onOpen'),
5086       onHandler('onClose'),
5087       required$1('isPartOf'),
5088       required$1('getAttachPoint'),
5089       defaulted('cloakVisibilityAttr', 'data-precloak-visibility')
5090     ];
5092     const init$f = () => {
5093       const contents = value$2();
5094       const readState = constant$1('not-implemented');
5095       return nu$8({
5096         readState,
5097         isOpen: contents.isSet,
5098         clear: contents.clear,
5099         set: contents.set,
5100         get: contents.get
5101       });
5102     };
5104     var SandboxState = /*#__PURE__*/Object.freeze({
5105         __proto__: null,
5106         init: init$f
5107     });
5109     const Sandboxing = create$4({
5110       fields: SandboxSchema,
5111       name: 'sandboxing',
5112       active: ActiveSandbox,
5113       apis: SandboxApis,
5114       state: SandboxState
5115     });
5117     const dismissPopups = constant$1('dismiss.popups');
5118     const repositionPopups = constant$1('reposition.popups');
5119     const mouseReleased = constant$1('mouse.released');
5121     const schema$x = objOfOnly([
5122       defaulted('isExtraPart', never),
5123       optionObjOf('fireEventInstead', [defaulted('event', dismissRequested())])
5124     ]);
5125     const receivingChannel$1 = rawSpec => {
5126       const detail = asRawOrDie$1('Dismissal', schema$x, rawSpec);
5127       return {
5128         [dismissPopups()]: {
5129           schema: objOfOnly([required$1('target')]),
5130           onReceive: (sandbox, data) => {
5131             if (Sandboxing.isOpen(sandbox)) {
5132               const isPart = Sandboxing.isPartOf(sandbox, data.target) || detail.isExtraPart(sandbox, data.target);
5133               if (!isPart) {
5134                 detail.fireEventInstead.fold(() => Sandboxing.close(sandbox), fe => emit(sandbox, fe.event));
5135               }
5136             }
5137           }
5138         }
5139       };
5140     };
5142     const schema$w = objOfOnly([
5143       optionObjOf('fireEventInstead', [defaulted('event', repositionRequested())]),
5144       requiredFunction('doReposition')
5145     ]);
5146     const receivingChannel = rawSpec => {
5147       const detail = asRawOrDie$1('Reposition', schema$w, rawSpec);
5148       return {
5149         [repositionPopups()]: {
5150           onReceive: sandbox => {
5151             if (Sandboxing.isOpen(sandbox)) {
5152               detail.fireEventInstead.fold(() => detail.doReposition(sandbox), fe => emit(sandbox, fe.event));
5153             }
5154           }
5155         }
5156       };
5157     };
5159     const onLoad$5 = (component, repConfig, repState) => {
5160       repConfig.store.manager.onLoad(component, repConfig, repState);
5161     };
5162     const onUnload$2 = (component, repConfig, repState) => {
5163       repConfig.store.manager.onUnload(component, repConfig, repState);
5164     };
5165     const setValue$3 = (component, repConfig, repState, data) => {
5166       repConfig.store.manager.setValue(component, repConfig, repState, data);
5167     };
5168     const getValue$3 = (component, repConfig, repState) => repConfig.store.manager.getValue(component, repConfig, repState);
5169     const getState$1 = (component, repConfig, repState) => repState;
5171     var RepresentApis = /*#__PURE__*/Object.freeze({
5172         __proto__: null,
5173         onLoad: onLoad$5,
5174         onUnload: onUnload$2,
5175         setValue: setValue$3,
5176         getValue: getValue$3,
5177         getState: getState$1
5178     });
5180     const events$f = (repConfig, repState) => {
5181       const es = repConfig.resetOnDom ? [
5182         runOnAttached((comp, _se) => {
5183           onLoad$5(comp, repConfig, repState);
5184         }),
5185         runOnDetached((comp, _se) => {
5186           onUnload$2(comp, repConfig, repState);
5187         })
5188       ] : [loadEvent(repConfig, repState, onLoad$5)];
5189       return derive$2(es);
5190     };
5192     var ActiveRepresenting = /*#__PURE__*/Object.freeze({
5193         __proto__: null,
5194         events: events$f
5195     });
5197     const memory$1 = () => {
5198       const data = Cell(null);
5199       const readState = () => ({
5200         mode: 'memory',
5201         value: data.get()
5202       });
5203       const isNotSet = () => data.get() === null;
5204       const clear = () => {
5205         data.set(null);
5206       };
5207       return nu$8({
5208         set: data.set,
5209         get: data.get,
5210         isNotSet,
5211         clear,
5212         readState
5213       });
5214     };
5215     const manual = () => {
5216       const readState = noop;
5217       return nu$8({ readState });
5218     };
5219     const dataset = () => {
5220       const dataByValue = Cell({});
5221       const dataByText = Cell({});
5222       const readState = () => ({
5223         mode: 'dataset',
5224         dataByValue: dataByValue.get(),
5225         dataByText: dataByText.get()
5226       });
5227       const clear = () => {
5228         dataByValue.set({});
5229         dataByText.set({});
5230       };
5231       const lookup = itemString => get$g(dataByValue.get(), itemString).orThunk(() => get$g(dataByText.get(), itemString));
5232       const update = items => {
5233         const currentDataByValue = dataByValue.get();
5234         const currentDataByText = dataByText.get();
5235         const newDataByValue = {};
5236         const newDataByText = {};
5237         each$1(items, item => {
5238           newDataByValue[item.value] = item;
5239           get$g(item, 'meta').each(meta => {
5240             get$g(meta, 'text').each(text => {
5241               newDataByText[text] = item;
5242             });
5243           });
5244         });
5245         dataByValue.set({
5246           ...currentDataByValue,
5247           ...newDataByValue
5248         });
5249         dataByText.set({
5250           ...currentDataByText,
5251           ...newDataByText
5252         });
5253       };
5254       return nu$8({
5255         readState,
5256         lookup,
5257         update,
5258         clear
5259       });
5260     };
5261     const init$e = spec => spec.store.manager.state(spec);
5263     var RepresentState = /*#__PURE__*/Object.freeze({
5264         __proto__: null,
5265         memory: memory$1,
5266         dataset: dataset,
5267         manual: manual,
5268         init: init$e
5269     });
5271     const setValue$2 = (component, repConfig, repState, data) => {
5272       const store = repConfig.store;
5273       repState.update([data]);
5274       store.setValue(component, data);
5275       repConfig.onSetValue(component, data);
5276     };
5277     const getValue$2 = (component, repConfig, repState) => {
5278       const store = repConfig.store;
5279       const key = store.getDataKey(component);
5280       return repState.lookup(key).getOrThunk(() => store.getFallbackEntry(key));
5281     };
5282     const onLoad$4 = (component, repConfig, repState) => {
5283       const store = repConfig.store;
5284       store.initialValue.each(data => {
5285         setValue$2(component, repConfig, repState, data);
5286       });
5287     };
5288     const onUnload$1 = (component, repConfig, repState) => {
5289       repState.clear();
5290     };
5291     var DatasetStore = [
5292       option$3('initialValue'),
5293       required$1('getFallbackEntry'),
5294       required$1('getDataKey'),
5295       required$1('setValue'),
5296       output$1('manager', {
5297         setValue: setValue$2,
5298         getValue: getValue$2,
5299         onLoad: onLoad$4,
5300         onUnload: onUnload$1,
5301         state: dataset
5302       })
5303     ];
5305     const getValue$1 = (component, repConfig, _repState) => repConfig.store.getValue(component);
5306     const setValue$1 = (component, repConfig, _repState, data) => {
5307       repConfig.store.setValue(component, data);
5308       repConfig.onSetValue(component, data);
5309     };
5310     const onLoad$3 = (component, repConfig, _repState) => {
5311       repConfig.store.initialValue.each(data => {
5312         repConfig.store.setValue(component, data);
5313       });
5314     };
5315     var ManualStore = [
5316       required$1('getValue'),
5317       defaulted('setValue', noop),
5318       option$3('initialValue'),
5319       output$1('manager', {
5320         setValue: setValue$1,
5321         getValue: getValue$1,
5322         onLoad: onLoad$3,
5323         onUnload: noop,
5324         state: NoState.init
5325       })
5326     ];
5328     const setValue = (component, repConfig, repState, data) => {
5329       repState.set(data);
5330       repConfig.onSetValue(component, data);
5331     };
5332     const getValue = (component, repConfig, repState) => repState.get();
5333     const onLoad$2 = (component, repConfig, repState) => {
5334       repConfig.store.initialValue.each(initVal => {
5335         if (repState.isNotSet()) {
5336           repState.set(initVal);
5337         }
5338       });
5339     };
5340     const onUnload = (component, repConfig, repState) => {
5341       repState.clear();
5342     };
5343     var MemoryStore = [
5344       option$3('initialValue'),
5345       output$1('manager', {
5346         setValue,
5347         getValue,
5348         onLoad: onLoad$2,
5349         onUnload,
5350         state: memory$1
5351       })
5352     ];
5354     var RepresentSchema = [
5355       defaultedOf('store', { mode: 'memory' }, choose$1('mode', {
5356         memory: MemoryStore,
5357         manual: ManualStore,
5358         dataset: DatasetStore
5359       })),
5360       onHandler('onSetValue'),
5361       defaulted('resetOnDom', false)
5362     ];
5364     const Representing = create$4({
5365       fields: RepresentSchema,
5366       name: 'representing',
5367       active: ActiveRepresenting,
5368       apis: RepresentApis,
5369       extra: {
5370         setValueFrom: (component, source) => {
5371           const value = Representing.getValue(source);
5372           Representing.setValue(component, value);
5373         }
5374       },
5375       state: RepresentState
5376     });
5378     const field = (name, forbidden) => defaultedObjOf(name, {}, map$2(forbidden, f => forbid(f.name(), 'Cannot configure ' + f.name() + ' for ' + name)).concat([customField('dump', identity)]));
5379     const get$3 = data => data.dump;
5380     const augment = (data, original) => ({
5381       ...derive$1(original),
5382       ...data.dump
5383     });
5384     const SketchBehaviours = {
5385       field,
5386       augment,
5387       get: get$3
5388     };
5390     const _placeholder = 'placeholder';
5391     const adt$3 = Adt.generate([
5392       {
5393         single: [
5394           'required',
5395           'valueThunk'
5396         ]
5397       },
5398       {
5399         multiple: [
5400           'required',
5401           'valueThunks'
5402         ]
5403       }
5404     ]);
5405     const isSubstituted = spec => has$2(spec, 'uiType');
5406     const subPlaceholder = (owner, detail, compSpec, placeholders) => {
5407       if (owner.exists(o => o !== compSpec.owner)) {
5408         return adt$3.single(true, constant$1(compSpec));
5409       }
5410       return get$g(placeholders, compSpec.name).fold(() => {
5411         throw new Error('Unknown placeholder component: ' + compSpec.name + '\nKnown: [' + keys(placeholders) + ']\nNamespace: ' + owner.getOr('none') + '\nSpec: ' + JSON.stringify(compSpec, null, 2));
5412       }, newSpec => newSpec.replace());
5413     };
5414     const scan = (owner, detail, compSpec, placeholders) => {
5415       if (isSubstituted(compSpec) && compSpec.uiType === _placeholder) {
5416         return subPlaceholder(owner, detail, compSpec, placeholders);
5417       } else {
5418         return adt$3.single(false, constant$1(compSpec));
5419       }
5420     };
5421     const substitute = (owner, detail, compSpec, placeholders) => {
5422       const base = scan(owner, detail, compSpec, placeholders);
5423       return base.fold((req, valueThunk) => {
5424         const value = isSubstituted(compSpec) ? valueThunk(detail, compSpec.config, compSpec.validated) : valueThunk(detail);
5425         const childSpecs = get$g(value, 'components').getOr([]);
5426         const substituted = bind$3(childSpecs, c => substitute(owner, detail, c, placeholders));
5427         return [{
5428             ...value,
5429             components: substituted
5430           }];
5431       }, (req, valuesThunk) => {
5432         if (isSubstituted(compSpec)) {
5433           const values = valuesThunk(detail, compSpec.config, compSpec.validated);
5434           const preprocessor = compSpec.validated.preprocess.getOr(identity);
5435           return preprocessor(values);
5436         } else {
5437           return valuesThunk(detail);
5438         }
5439       });
5440     };
5441     const substituteAll = (owner, detail, components, placeholders) => bind$3(components, c => substitute(owner, detail, c, placeholders));
5442     const oneReplace = (label, replacements) => {
5443       let called = false;
5444       const used = () => called;
5445       const replace = () => {
5446         if (called) {
5447           throw new Error('Trying to use the same placeholder more than once: ' + label);
5448         }
5449         called = true;
5450         return replacements;
5451       };
5452       const required = () => replacements.fold((req, _) => req, (req, _) => req);
5453       return {
5454         name: constant$1(label),
5455         required,
5456         used,
5457         replace
5458       };
5459     };
5460     const substitutePlaces = (owner, detail, components, placeholders) => {
5461       const ps = map$1(placeholders, (ph, name) => oneReplace(name, ph));
5462       const outcome = substituteAll(owner, detail, components, ps);
5463       each(ps, p => {
5464         if (p.used() === false && p.required()) {
5465           throw new Error('Placeholder: ' + p.name() + ' was not found in components list\nNamespace: ' + owner.getOr('none') + '\nComponents: ' + JSON.stringify(detail.components, null, 2));
5466         }
5467       });
5468       return outcome;
5469     };
5470     const single$2 = adt$3.single;
5471     const multiple = adt$3.multiple;
5472     const placeholder = constant$1(_placeholder);
5474     const adt$2 = Adt.generate([
5475       { required: ['data'] },
5476       { external: ['data'] },
5477       { optional: ['data'] },
5478       { group: ['data'] }
5479     ]);
5480     const fFactory = defaulted('factory', { sketch: identity });
5481     const fSchema = defaulted('schema', []);
5482     const fName = required$1('name');
5483     const fPname = field$1('pname', 'pname', defaultedThunk(typeSpec => '<alloy.' + generate$6(typeSpec.name) + '>'), anyValue());
5484     const fGroupSchema = customField('schema', () => [option$3('preprocess')]);
5485     const fDefaults = defaulted('defaults', constant$1({}));
5486     const fOverrides = defaulted('overrides', constant$1({}));
5487     const requiredSpec = objOf([
5488       fFactory,
5489       fSchema,
5490       fName,
5491       fPname,
5492       fDefaults,
5493       fOverrides
5494     ]);
5495     const externalSpec = objOf([
5496       fFactory,
5497       fSchema,
5498       fName,
5499       fDefaults,
5500       fOverrides
5501     ]);
5502     const optionalSpec = objOf([
5503       fFactory,
5504       fSchema,
5505       fName,
5506       fPname,
5507       fDefaults,
5508       fOverrides
5509     ]);
5510     const groupSpec = objOf([
5511       fFactory,
5512       fGroupSchema,
5513       fName,
5514       required$1('unit'),
5515       fPname,
5516       fDefaults,
5517       fOverrides
5518     ]);
5519     const asNamedPart = part => {
5520       return part.fold(Optional.some, Optional.none, Optional.some, Optional.some);
5521     };
5522     const name$2 = part => {
5523       const get = data => data.name;
5524       return part.fold(get, get, get, get);
5525     };
5526     const asCommon = part => {
5527       return part.fold(identity, identity, identity, identity);
5528     };
5529     const convert = (adtConstructor, partSchema) => spec => {
5530       const data = asRawOrDie$1('Converting part type', partSchema, spec);
5531       return adtConstructor(data);
5532     };
5533     const required = convert(adt$2.required, requiredSpec);
5534     const external = convert(adt$2.external, externalSpec);
5535     const optional = convert(adt$2.optional, optionalSpec);
5536     const group = convert(adt$2.group, groupSpec);
5537     const original = constant$1('entirety');
5539     var PartType = /*#__PURE__*/Object.freeze({
5540         __proto__: null,
5541         required: required,
5542         external: external,
5543         optional: optional,
5544         group: group,
5545         asNamedPart: asNamedPart,
5546         name: name$2,
5547         asCommon: asCommon,
5548         original: original
5549     });
5551     const combine = (detail, data, partSpec, partValidated) => deepMerge(data.defaults(detail, partSpec, partValidated), partSpec, { uid: detail.partUids[data.name] }, data.overrides(detail, partSpec, partValidated));
5552     const subs = (owner, detail, parts) => {
5553       const internals = {};
5554       const externals = {};
5555       each$1(parts, part => {
5556         part.fold(data => {
5557           internals[data.pname] = single$2(true, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
5558         }, data => {
5559           const partSpec = detail.parts[data.name];
5560           externals[data.name] = constant$1(data.factory.sketch(combine(detail, data, partSpec[original()]), partSpec));
5561         }, data => {
5562           internals[data.pname] = single$2(false, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
5563         }, data => {
5564           internals[data.pname] = multiple(true, (detail, _partSpec, _partValidated) => {
5565             const units = detail[data.name];
5566             return map$2(units, u => data.factory.sketch(deepMerge(data.defaults(detail, u, _partValidated), u, data.overrides(detail, u))));
5567           });
5568         });
5569       });
5570       return {
5571         internals: constant$1(internals),
5572         externals: constant$1(externals)
5573       };
5574     };
5576     const generate$3 = (owner, parts) => {
5577       const r = {};
5578       each$1(parts, part => {
5579         asNamedPart(part).each(np => {
5580           const g = doGenerateOne(owner, np.pname);
5581           r[np.name] = config => {
5582             const validated = asRawOrDie$1('Part: ' + np.name + ' in ' + owner, objOf(np.schema), config);
5583             return {
5584               ...g,
5585               config,
5586               validated
5587             };
5588           };
5589         });
5590       });
5591       return r;
5592     };
5593     const doGenerateOne = (owner, pname) => ({
5594       uiType: placeholder(),
5595       owner,
5596       name: pname
5597     });
5598     const generateOne$1 = (owner, pname, config) => ({
5599       uiType: placeholder(),
5600       owner,
5601       name: pname,
5602       config,
5603       validated: {}
5604     });
5605     const schemas = parts => bind$3(parts, part => part.fold(Optional.none, Optional.some, Optional.none, Optional.none).map(data => requiredObjOf(data.name, data.schema.concat([snapshot(original())]))).toArray());
5606     const names = parts => map$2(parts, name$2);
5607     const substitutes = (owner, detail, parts) => subs(owner, detail, parts);
5608     const components$1 = (owner, detail, internals) => substitutePlaces(Optional.some(owner), detail, detail.components, internals);
5609     const getPart = (component, detail, partKey) => {
5610       const uid = detail.partUids[partKey];
5611       return component.getSystem().getByUid(uid).toOptional();
5612     };
5613     const getPartOrDie = (component, detail, partKey) => getPart(component, detail, partKey).getOrDie('Could not find part: ' + partKey);
5614     const getParts = (component, detail, partKeys) => {
5615       const r = {};
5616       const uids = detail.partUids;
5617       const system = component.getSystem();
5618       each$1(partKeys, pk => {
5619         r[pk] = constant$1(system.getByUid(uids[pk]));
5620       });
5621       return r;
5622     };
5623     const getAllParts = (component, detail) => {
5624       const system = component.getSystem();
5625       return map$1(detail.partUids, (pUid, _k) => constant$1(system.getByUid(pUid)));
5626     };
5627     const getAllPartNames = detail => keys(detail.partUids);
5628     const getPartsOrDie = (component, detail, partKeys) => {
5629       const r = {};
5630       const uids = detail.partUids;
5631       const system = component.getSystem();
5632       each$1(partKeys, pk => {
5633         r[pk] = constant$1(system.getByUid(uids[pk]).getOrDie());
5634       });
5635       return r;
5636     };
5637     const defaultUids = (baseUid, partTypes) => {
5638       const partNames = names(partTypes);
5639       return wrapAll(map$2(partNames, pn => ({
5640         key: pn,
5641         value: baseUid + '-' + pn
5642       })));
5643     };
5644     const defaultUidsSchema = partTypes => field$1('partUids', 'partUids', mergeWithThunk(spec => defaultUids(spec.uid, partTypes)), anyValue());
5646     var AlloyParts = /*#__PURE__*/Object.freeze({
5647         __proto__: null,
5648         generate: generate$3,
5649         generateOne: generateOne$1,
5650         schemas: schemas,
5651         names: names,
5652         substitutes: substitutes,
5653         components: components$1,
5654         defaultUids: defaultUids,
5655         defaultUidsSchema: defaultUidsSchema,
5656         getAllParts: getAllParts,
5657         getAllPartNames: getAllPartNames,
5658         getPart: getPart,
5659         getPartOrDie: getPartOrDie,
5660         getParts: getParts,
5661         getPartsOrDie: getPartsOrDie
5662     });
5664     const base = (partSchemas, partUidsSchemas) => {
5665       const ps = partSchemas.length > 0 ? [requiredObjOf('parts', partSchemas)] : [];
5666       return ps.concat([
5667         required$1('uid'),
5668         defaulted('dom', {}),
5669         defaulted('components', []),
5670         snapshot('originalSpec'),
5671         defaulted('debug.sketcher', {})
5672       ]).concat(partUidsSchemas);
5673     };
5674     const asRawOrDie = (label, schema, spec, partSchemas, partUidsSchemas) => {
5675       const baseS = base(partSchemas, partUidsSchemas);
5676       return asRawOrDie$1(label + ' [SpecSchema]', objOfOnly(baseS.concat(schema)), spec);
5677     };
5679     const single$1 = (owner, schema, factory, spec) => {
5680       const specWithUid = supplyUid(spec);
5681       const detail = asRawOrDie(owner, schema, specWithUid, [], []);
5682       return factory(detail, specWithUid);
5683     };
5684     const composite$1 = (owner, schema, partTypes, factory, spec) => {
5685       const specWithUid = supplyUid(spec);
5686       const partSchemas = schemas(partTypes);
5687       const partUidsSchema = defaultUidsSchema(partTypes);
5688       const detail = asRawOrDie(owner, schema, specWithUid, partSchemas, [partUidsSchema]);
5689       const subs = substitutes(owner, detail, partTypes);
5690       const components = components$1(owner, detail, subs.internals());
5691       return factory(detail, components, specWithUid, subs.externals());
5692     };
5693     const hasUid = spec => has$2(spec, 'uid');
5694     const supplyUid = spec => {
5695       return hasUid(spec) ? spec : {
5696         ...spec,
5697         uid: generate$5('uid')
5698       };
5699     };
5701     const isSketchSpec = spec => {
5702       return spec.uid !== undefined;
5703     };
5704     const singleSchema = objOfOnly([
5705       required$1('name'),
5706       required$1('factory'),
5707       required$1('configFields'),
5708       defaulted('apis', {}),
5709       defaulted('extraApis', {})
5710     ]);
5711     const compositeSchema = objOfOnly([
5712       required$1('name'),
5713       required$1('factory'),
5714       required$1('configFields'),
5715       required$1('partFields'),
5716       defaulted('apis', {}),
5717       defaulted('extraApis', {})
5718     ]);
5719     const single = rawConfig => {
5720       const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, singleSchema, rawConfig);
5721       const sketch = spec => single$1(config.name, config.configFields, config.factory, spec);
5722       const apis = map$1(config.apis, makeApi);
5723       const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
5724       return {
5725         name: config.name,
5726         configFields: config.configFields,
5727         sketch,
5728         ...apis,
5729         ...extraApis
5730       };
5731     };
5732     const composite = rawConfig => {
5733       const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, compositeSchema, rawConfig);
5734       const sketch = spec => composite$1(config.name, config.configFields, config.partFields, config.factory, spec);
5735       const parts = generate$3(config.name, config.partFields);
5736       const apis = map$1(config.apis, makeApi);
5737       const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
5738       return {
5739         name: config.name,
5740         partFields: config.partFields,
5741         configFields: config.configFields,
5742         sketch,
5743         parts,
5744         ...apis,
5745         ...extraApis
5746       };
5747     };
5749     const inside = target => isTag('input')(target) && get$f(target, 'type') !== 'radio' || isTag('textarea')(target);
5751     const getCurrent = (component, composeConfig, _composeState) => composeConfig.find(component);
5753     var ComposeApis = /*#__PURE__*/Object.freeze({
5754         __proto__: null,
5755         getCurrent: getCurrent
5756     });
5758     const ComposeSchema = [required$1('find')];
5760     const Composing = create$4({
5761       fields: ComposeSchema,
5762       name: 'composing',
5763       apis: ComposeApis
5764     });
5766     const nativeDisabled = [
5767       'input',
5768       'button',
5769       'textarea',
5770       'select'
5771     ];
5772     const onLoad$1 = (component, disableConfig, disableState) => {
5773       const f = disableConfig.disabled() ? disable : enable;
5774       f(component, disableConfig);
5775     };
5776     const hasNative = (component, config) => config.useNative === true && contains$2(nativeDisabled, name$3(component.element));
5777     const nativeIsDisabled = component => has$1(component.element, 'disabled');
5778     const nativeDisable = component => {
5779       set$9(component.element, 'disabled', 'disabled');
5780     };
5781     const nativeEnable = component => {
5782       remove$7(component.element, 'disabled');
5783     };
5784     const ariaIsDisabled = component => get$f(component.element, 'aria-disabled') === 'true';
5785     const ariaDisable = component => {
5786       set$9(component.element, 'aria-disabled', 'true');
5787     };
5788     const ariaEnable = component => {
5789       set$9(component.element, 'aria-disabled', 'false');
5790     };
5791     const disable = (component, disableConfig, _disableState) => {
5792       disableConfig.disableClass.each(disableClass => {
5793         add$2(component.element, disableClass);
5794       });
5795       const f = hasNative(component, disableConfig) ? nativeDisable : ariaDisable;
5796       f(component);
5797       disableConfig.onDisabled(component);
5798     };
5799     const enable = (component, disableConfig, _disableState) => {
5800       disableConfig.disableClass.each(disableClass => {
5801         remove$2(component.element, disableClass);
5802       });
5803       const f = hasNative(component, disableConfig) ? nativeEnable : ariaEnable;
5804       f(component);
5805       disableConfig.onEnabled(component);
5806     };
5807     const isDisabled = (component, disableConfig) => hasNative(component, disableConfig) ? nativeIsDisabled(component) : ariaIsDisabled(component);
5808     const set$4 = (component, disableConfig, disableState, disabled) => {
5809       const f = disabled ? disable : enable;
5810       f(component, disableConfig);
5811     };
5813     var DisableApis = /*#__PURE__*/Object.freeze({
5814         __proto__: null,
5815         enable: enable,
5816         disable: disable,
5817         isDisabled: isDisabled,
5818         onLoad: onLoad$1,
5819         set: set$4
5820     });
5822     const exhibit$5 = (base, disableConfig) => nu$7({ classes: disableConfig.disabled() ? disableConfig.disableClass.toArray() : [] });
5823     const events$e = (disableConfig, disableState) => derive$2([
5824       abort(execute$5(), (component, _simulatedEvent) => isDisabled(component, disableConfig)),
5825       loadEvent(disableConfig, disableState, onLoad$1)
5826     ]);
5828     var ActiveDisable = /*#__PURE__*/Object.freeze({
5829         __proto__: null,
5830         exhibit: exhibit$5,
5831         events: events$e
5832     });
5834     var DisableSchema = [
5835       defaultedFunction('disabled', never),
5836       defaulted('useNative', true),
5837       option$3('disableClass'),
5838       onHandler('onDisabled'),
5839       onHandler('onEnabled')
5840     ];
5842     const Disabling = create$4({
5843       fields: DisableSchema,
5844       name: 'disabling',
5845       active: ActiveDisable,
5846       apis: DisableApis
5847     });
5849     const dehighlightAllExcept = (component, hConfig, hState, skip) => {
5850       const highlighted = descendants(component.element, '.' + hConfig.highlightClass);
5851       each$1(highlighted, h => {
5852         const shouldSkip = exists(skip, skipComp => eq(skipComp.element, h));
5853         if (!shouldSkip) {
5854           remove$2(h, hConfig.highlightClass);
5855           component.getSystem().getByDom(h).each(target => {
5856             hConfig.onDehighlight(component, target);
5857             emit(target, dehighlight$1());
5858           });
5859         }
5860       });
5861     };
5862     const dehighlightAll = (component, hConfig, hState) => dehighlightAllExcept(component, hConfig, hState, []);
5863     const dehighlight = (component, hConfig, hState, target) => {
5864       if (isHighlighted(component, hConfig, hState, target)) {
5865         remove$2(target.element, hConfig.highlightClass);
5866         hConfig.onDehighlight(component, target);
5867         emit(target, dehighlight$1());
5868       }
5869     };
5870     const highlight = (component, hConfig, hState, target) => {
5871       dehighlightAllExcept(component, hConfig, hState, [target]);
5872       if (!isHighlighted(component, hConfig, hState, target)) {
5873         add$2(target.element, hConfig.highlightClass);
5874         hConfig.onHighlight(component, target);
5875         emit(target, highlight$1());
5876       }
5877     };
5878     const highlightFirst = (component, hConfig, hState) => {
5879       getFirst(component, hConfig).each(firstComp => {
5880         highlight(component, hConfig, hState, firstComp);
5881       });
5882     };
5883     const highlightLast = (component, hConfig, hState) => {
5884       getLast(component, hConfig).each(lastComp => {
5885         highlight(component, hConfig, hState, lastComp);
5886       });
5887     };
5888     const highlightAt = (component, hConfig, hState, index) => {
5889       getByIndex(component, hConfig, hState, index).fold(err => {
5890         throw err;
5891       }, firstComp => {
5892         highlight(component, hConfig, hState, firstComp);
5893       });
5894     };
5895     const highlightBy = (component, hConfig, hState, predicate) => {
5896       const candidates = getCandidates(component, hConfig);
5897       const targetComp = find$5(candidates, predicate);
5898       targetComp.each(c => {
5899         highlight(component, hConfig, hState, c);
5900       });
5901     };
5902     const isHighlighted = (component, hConfig, hState, queryTarget) => has(queryTarget.element, hConfig.highlightClass);
5903     const getHighlighted = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.highlightClass).bind(e => component.getSystem().getByDom(e).toOptional());
5904     const getByIndex = (component, hConfig, hState, index) => {
5905       const items = descendants(component.element, '.' + hConfig.itemClass);
5906       return Optional.from(items[index]).fold(() => Result.error(new Error('No element found with index ' + index)), component.getSystem().getByDom);
5907     };
5908     const getFirst = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.itemClass).bind(e => component.getSystem().getByDom(e).toOptional());
5909     const getLast = (component, hConfig, _hState) => {
5910       const items = descendants(component.element, '.' + hConfig.itemClass);
5911       const last = items.length > 0 ? Optional.some(items[items.length - 1]) : Optional.none();
5912       return last.bind(c => component.getSystem().getByDom(c).toOptional());
5913     };
5914     const getDelta$2 = (component, hConfig, hState, delta) => {
5915       const items = descendants(component.element, '.' + hConfig.itemClass);
5916       const current = findIndex$1(items, item => has(item, hConfig.highlightClass));
5917       return current.bind(selected => {
5918         const dest = cycleBy(selected, delta, 0, items.length - 1);
5919         return component.getSystem().getByDom(items[dest]).toOptional();
5920       });
5921     };
5922     const getPrevious = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, -1);
5923     const getNext = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, +1);
5924     const getCandidates = (component, hConfig, _hState) => {
5925       const items = descendants(component.element, '.' + hConfig.itemClass);
5926       return cat(map$2(items, i => component.getSystem().getByDom(i).toOptional()));
5927     };
5929     var HighlightApis = /*#__PURE__*/Object.freeze({
5930         __proto__: null,
5931         dehighlightAll: dehighlightAll,
5932         dehighlight: dehighlight,
5933         highlight: highlight,
5934         highlightFirst: highlightFirst,
5935         highlightLast: highlightLast,
5936         highlightAt: highlightAt,
5937         highlightBy: highlightBy,
5938         isHighlighted: isHighlighted,
5939         getHighlighted: getHighlighted,
5940         getFirst: getFirst,
5941         getLast: getLast,
5942         getPrevious: getPrevious,
5943         getNext: getNext,
5944         getCandidates: getCandidates
5945     });
5947     var HighlightSchema = [
5948       required$1('highlightClass'),
5949       required$1('itemClass'),
5950       onHandler('onHighlight'),
5951       onHandler('onDehighlight')
5952     ];
5954     const Highlighting = create$4({
5955       fields: HighlightSchema,
5956       name: 'highlighting',
5957       apis: HighlightApis
5958     });
5960     const BACKSPACE = [8];
5961     const TAB = [9];
5962     const ENTER = [13];
5963     const ESCAPE = [27];
5964     const SPACE = [32];
5965     const LEFT = [37];
5966     const UP = [38];
5967     const RIGHT = [39];
5968     const DOWN = [40];
5970     const cyclePrev = (values, index, predicate) => {
5971       const before = reverse(values.slice(0, index));
5972       const after = reverse(values.slice(index + 1));
5973       return find$5(before.concat(after), predicate);
5974     };
5975     const tryPrev = (values, index, predicate) => {
5976       const before = reverse(values.slice(0, index));
5977       return find$5(before, predicate);
5978     };
5979     const cycleNext = (values, index, predicate) => {
5980       const before = values.slice(0, index);
5981       const after = values.slice(index + 1);
5982       return find$5(after.concat(before), predicate);
5983     };
5984     const tryNext = (values, index, predicate) => {
5985       const after = values.slice(index + 1);
5986       return find$5(after, predicate);
5987     };
5989     const inSet = keys => event => {
5990       const raw = event.raw;
5991       return contains$2(keys, raw.which);
5992     };
5993     const and = preds => event => forall(preds, pred => pred(event));
5994     const isShift = event => {
5995       const raw = event.raw;
5996       return raw.shiftKey === true;
5997     };
5998     const isControl = event => {
5999       const raw = event.raw;
6000       return raw.ctrlKey === true;
6001     };
6002     const isNotShift = not(isShift);
6004     const rule = (matches, action) => ({
6005       matches,
6006       classification: action
6007     });
6008     const choose = (transitions, event) => {
6009       const transition = find$5(transitions, t => t.matches(event));
6010       return transition.map(t => t.classification);
6011     };
6013     const reportFocusShifting = (component, prevFocus, newFocus) => {
6014       const noChange = prevFocus.exists(p => newFocus.exists(n => eq(n, p)));
6015       if (!noChange) {
6016         emitWith(component, focusShifted(), {
6017           prevFocus,
6018           newFocus
6019         });
6020       }
6021     };
6022     const dom$2 = () => {
6023       const get = component => search(component.element);
6024       const set = (component, focusee) => {
6025         const prevFocus = get(component);
6026         component.getSystem().triggerFocus(focusee, component.element);
6027         const newFocus = get(component);
6028         reportFocusShifting(component, prevFocus, newFocus);
6029       };
6030       return {
6031         get,
6032         set
6033       };
6034     };
6035     const highlights = () => {
6036       const get = component => Highlighting.getHighlighted(component).map(item => item.element);
6037       const set = (component, element) => {
6038         const prevFocus = get(component);
6039         component.getSystem().getByDom(element).fold(noop, item => {
6040           Highlighting.highlight(component, item);
6041         });
6042         const newFocus = get(component);
6043         reportFocusShifting(component, prevFocus, newFocus);
6044       };
6045       return {
6046         get,
6047         set
6048       };
6049     };
6051     var FocusInsideModes;
6052     (function (FocusInsideModes) {
6053       FocusInsideModes['OnFocusMode'] = 'onFocus';
6054       FocusInsideModes['OnEnterOrSpaceMode'] = 'onEnterOrSpace';
6055       FocusInsideModes['OnApiMode'] = 'onApi';
6056     }(FocusInsideModes || (FocusInsideModes = {})));
6058     const typical = (infoSchema, stateInit, getKeydownRules, getKeyupRules, optFocusIn) => {
6059       const schema = () => infoSchema.concat([
6060         defaulted('focusManager', dom$2()),
6061         defaultedOf('focusInside', 'onFocus', valueOf(val => contains$2([
6062           'onFocus',
6063           'onEnterOrSpace',
6064           'onApi'
6065         ], val) ? Result.value(val) : Result.error('Invalid value for focusInside'))),
6066         output$1('handler', me),
6067         output$1('state', stateInit),
6068         output$1('sendFocusIn', optFocusIn)
6069       ]);
6070       const processKey = (component, simulatedEvent, getRules, keyingConfig, keyingState) => {
6071         const rules = getRules(component, simulatedEvent, keyingConfig, keyingState);
6072         return choose(rules, simulatedEvent.event).bind(rule => rule(component, simulatedEvent, keyingConfig, keyingState));
6073       };
6074       const toEvents = (keyingConfig, keyingState) => {
6075         const onFocusHandler = keyingConfig.focusInside !== FocusInsideModes.OnFocusMode ? Optional.none() : optFocusIn(keyingConfig).map(focusIn => run$1(focus$4(), (component, simulatedEvent) => {
6076           focusIn(component, keyingConfig, keyingState);
6077           simulatedEvent.stop();
6078         }));
6079         const tryGoInsideComponent = (component, simulatedEvent) => {
6080           const isEnterOrSpace = inSet(SPACE.concat(ENTER))(simulatedEvent.event);
6081           if (keyingConfig.focusInside === FocusInsideModes.OnEnterOrSpaceMode && isEnterOrSpace && isSource(component, simulatedEvent)) {
6082             optFocusIn(keyingConfig).each(focusIn => {
6083               focusIn(component, keyingConfig, keyingState);
6084               simulatedEvent.stop();
6085             });
6086           }
6087         };
6088         const keyboardEvents = [
6089           run$1(keydown(), (component, simulatedEvent) => {
6090             processKey(component, simulatedEvent, getKeydownRules, keyingConfig, keyingState).fold(() => {
6091               tryGoInsideComponent(component, simulatedEvent);
6092             }, _ => {
6093               simulatedEvent.stop();
6094             });
6095           }),
6096           run$1(keyup(), (component, simulatedEvent) => {
6097             processKey(component, simulatedEvent, getKeyupRules, keyingConfig, keyingState).each(_ => {
6098               simulatedEvent.stop();
6099             });
6100           })
6101         ];
6102         return derive$2(onFocusHandler.toArray().concat(keyboardEvents));
6103       };
6104       const me = {
6105         schema,
6106         processKey,
6107         toEvents
6108       };
6109       return me;
6110     };
6112     const create$2 = cyclicField => {
6113       const schema = [
6114         option$3('onEscape'),
6115         option$3('onEnter'),
6116         defaulted('selector', '[data-alloy-tabstop="true"]:not(:disabled)'),
6117         defaulted('firstTabstop', 0),
6118         defaulted('useTabstopAt', always),
6119         option$3('visibilitySelector')
6120       ].concat([cyclicField]);
6121       const isVisible = (tabbingConfig, element) => {
6122         const target = tabbingConfig.visibilitySelector.bind(sel => closest$1(element, sel)).getOr(element);
6123         return get$d(target) > 0;
6124       };
6125       const findInitial = (component, tabbingConfig) => {
6126         const tabstops = descendants(component.element, tabbingConfig.selector);
6127         const visibles = filter$2(tabstops, elem => isVisible(tabbingConfig, elem));
6128         return Optional.from(visibles[tabbingConfig.firstTabstop]);
6129       };
6130       const findCurrent = (component, tabbingConfig) => tabbingConfig.focusManager.get(component).bind(elem => closest$1(elem, tabbingConfig.selector));
6131       const isTabstop = (tabbingConfig, element) => isVisible(tabbingConfig, element) && tabbingConfig.useTabstopAt(element);
6132       const focusIn = (component, tabbingConfig, _tabbingState) => {
6133         findInitial(component, tabbingConfig).each(target => {
6134           tabbingConfig.focusManager.set(component, target);
6135         });
6136       };
6137       const goFromTabstop = (component, tabstops, stopIndex, tabbingConfig, cycle) => cycle(tabstops, stopIndex, elem => isTabstop(tabbingConfig, elem)).fold(() => tabbingConfig.cyclic ? Optional.some(true) : Optional.none(), target => {
6138         tabbingConfig.focusManager.set(component, target);
6139         return Optional.some(true);
6140       });
6141       const go = (component, _simulatedEvent, tabbingConfig, cycle) => {
6142         const tabstops = descendants(component.element, tabbingConfig.selector);
6143         return findCurrent(component, tabbingConfig).bind(tabstop => {
6144           const optStopIndex = findIndex$1(tabstops, curry(eq, tabstop));
6145           return optStopIndex.bind(stopIndex => goFromTabstop(component, tabstops, stopIndex, tabbingConfig, cycle));
6146         });
6147       };
6148       const goBackwards = (component, simulatedEvent, tabbingConfig) => {
6149         const navigate = tabbingConfig.cyclic ? cyclePrev : tryPrev;
6150         return go(component, simulatedEvent, tabbingConfig, navigate);
6151       };
6152       const goForwards = (component, simulatedEvent, tabbingConfig) => {
6153         const navigate = tabbingConfig.cyclic ? cycleNext : tryNext;
6154         return go(component, simulatedEvent, tabbingConfig, navigate);
6155       };
6156       const execute = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEnter.bind(f => f(component, simulatedEvent));
6157       const exit = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEscape.bind(f => f(component, simulatedEvent));
6158       const getKeydownRules = constant$1([
6159         rule(and([
6160           isShift,
6161           inSet(TAB)
6162         ]), goBackwards),
6163         rule(inSet(TAB), goForwards),
6164         rule(and([
6165           isNotShift,
6166           inSet(ENTER)
6167         ]), execute)
6168       ]);
6169       const getKeyupRules = constant$1([rule(inSet(ESCAPE), exit)]);
6170       return typical(schema, NoState.init, getKeydownRules, getKeyupRules, () => Optional.some(focusIn));
6171     };
6173     var AcyclicType = create$2(customField('cyclic', never));
6175     var CyclicType = create$2(customField('cyclic', always));
6177     const doDefaultExecute = (component, _simulatedEvent, focused) => {
6178       dispatch(component, focused, execute$5());
6179       return Optional.some(true);
6180     };
6181     const defaultExecute = (component, simulatedEvent, focused) => {
6182       const isComplex = inside(focused) && inSet(SPACE)(simulatedEvent.event);
6183       return isComplex ? Optional.none() : doDefaultExecute(component, simulatedEvent, focused);
6184     };
6185     const stopEventForFirefox = (_component, _simulatedEvent) => Optional.some(true);
6187     const schema$v = [
6188       defaulted('execute', defaultExecute),
6189       defaulted('useSpace', false),
6190       defaulted('useEnter', true),
6191       defaulted('useControlEnter', false),
6192       defaulted('useDown', false)
6193     ];
6194     const execute$4 = (component, simulatedEvent, executeConfig) => executeConfig.execute(component, simulatedEvent, component.element);
6195     const getKeydownRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => {
6196       const spaceExec = executeConfig.useSpace && !inside(component.element) ? SPACE : [];
6197       const enterExec = executeConfig.useEnter ? ENTER : [];
6198       const downExec = executeConfig.useDown ? DOWN : [];
6199       const execKeys = spaceExec.concat(enterExec).concat(downExec);
6200       return [rule(inSet(execKeys), execute$4)].concat(executeConfig.useControlEnter ? [rule(and([
6201           isControl,
6202           inSet(ENTER)
6203         ]), execute$4)] : []);
6204     };
6205     const getKeyupRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => executeConfig.useSpace && !inside(component.element) ? [rule(inSet(SPACE), stopEventForFirefox)] : [];
6206     var ExecutionType = typical(schema$v, NoState.init, getKeydownRules$5, getKeyupRules$5, () => Optional.none());
6208     const flatgrid$1 = () => {
6209       const dimensions = value$2();
6210       const setGridSize = (numRows, numColumns) => {
6211         dimensions.set({
6212           numRows,
6213           numColumns
6214         });
6215       };
6216       const getNumRows = () => dimensions.get().map(d => d.numRows);
6217       const getNumColumns = () => dimensions.get().map(d => d.numColumns);
6218       return nu$8({
6219         readState: () => dimensions.get().map(d => ({
6220           numRows: String(d.numRows),
6221           numColumns: String(d.numColumns)
6222         })).getOr({
6223           numRows: '?',
6224           numColumns: '?'
6225         }),
6226         setGridSize,
6227         getNumRows,
6228         getNumColumns
6229       });
6230     };
6231     const init$d = spec => spec.state(spec);
6233     var KeyingState = /*#__PURE__*/Object.freeze({
6234         __proto__: null,
6235         flatgrid: flatgrid$1,
6236         init: init$d
6237     });
6239     const useH = movement => (component, simulatedEvent, config, state) => {
6240       const move = movement(component.element);
6241       return use(move, component, simulatedEvent, config, state);
6242     };
6243     const west$1 = (moveLeft, moveRight) => {
6244       const movement = onDirection(moveLeft, moveRight);
6245       return useH(movement);
6246     };
6247     const east$1 = (moveLeft, moveRight) => {
6248       const movement = onDirection(moveRight, moveLeft);
6249       return useH(movement);
6250     };
6251     const useV = move => (component, simulatedEvent, config, state) => use(move, component, simulatedEvent, config, state);
6252     const use = (move, component, simulatedEvent, config, state) => {
6253       const outcome = config.focusManager.get(component).bind(focused => move(component.element, focused, config, state));
6254       return outcome.map(newFocus => {
6255         config.focusManager.set(component, newFocus);
6256         return true;
6257       });
6258     };
6259     const north$1 = useV;
6260     const south$1 = useV;
6261     const move$1 = useV;
6263     const isHidden$1 = dom => dom.offsetWidth <= 0 && dom.offsetHeight <= 0;
6264     const isVisible = element => !isHidden$1(element.dom);
6266     const locate = (candidates, predicate) => findIndex$1(candidates, predicate).map(index => ({
6267       index,
6268       candidates
6269     }));
6271     const locateVisible = (container, current, selector) => {
6272       const predicate = x => eq(x, current);
6273       const candidates = descendants(container, selector);
6274       const visible = filter$2(candidates, isVisible);
6275       return locate(visible, predicate);
6276     };
6277     const findIndex = (elements, target) => findIndex$1(elements, elem => eq(target, elem));
6279     const withGrid = (values, index, numCols, f) => {
6280       const oldRow = Math.floor(index / numCols);
6281       const oldColumn = index % numCols;
6282       return f(oldRow, oldColumn).bind(address => {
6283         const newIndex = address.row * numCols + address.column;
6284         return newIndex >= 0 && newIndex < values.length ? Optional.some(values[newIndex]) : Optional.none();
6285       });
6286     };
6287     const cycleHorizontal$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
6288       const onLastRow = oldRow === numRows - 1;
6289       const colsInRow = onLastRow ? values.length - oldRow * numCols : numCols;
6290       const newColumn = cycleBy(oldColumn, delta, 0, colsInRow - 1);
6291       return Optional.some({
6292         row: oldRow,
6293         column: newColumn
6294       });
6295     });
6296     const cycleVertical$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
6297       const newRow = cycleBy(oldRow, delta, 0, numRows - 1);
6298       const onLastRow = newRow === numRows - 1;
6299       const colsInRow = onLastRow ? values.length - newRow * numCols : numCols;
6300       const newCol = clamp(oldColumn, 0, colsInRow - 1);
6301       return Optional.some({
6302         row: newRow,
6303         column: newCol
6304       });
6305     });
6306     const cycleRight$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, +1);
6307     const cycleLeft$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, -1);
6308     const cycleUp$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, -1);
6309     const cycleDown$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, +1);
6311     const schema$u = [
6312       required$1('selector'),
6313       defaulted('execute', defaultExecute),
6314       onKeyboardHandler('onEscape'),
6315       defaulted('captureTab', false),
6316       initSize()
6317     ];
6318     const focusIn$3 = (component, gridConfig, _gridState) => {
6319       descendant(component.element, gridConfig.selector).each(first => {
6320         gridConfig.focusManager.set(component, first);
6321       });
6322     };
6323     const findCurrent$1 = (component, gridConfig) => gridConfig.focusManager.get(component).bind(elem => closest$1(elem, gridConfig.selector));
6324     const execute$3 = (component, simulatedEvent, gridConfig, _gridState) => findCurrent$1(component, gridConfig).bind(focused => gridConfig.execute(component, simulatedEvent, focused));
6325     const doMove$2 = cycle => (element, focused, gridConfig, gridState) => locateVisible(element, focused, gridConfig.selector).bind(identified => cycle(identified.candidates, identified.index, gridState.getNumRows().getOr(gridConfig.initSize.numRows), gridState.getNumColumns().getOr(gridConfig.initSize.numColumns)));
6326     const handleTab = (_component, _simulatedEvent, gridConfig) => gridConfig.captureTab ? Optional.some(true) : Optional.none();
6327     const doEscape$1 = (component, simulatedEvent, gridConfig) => gridConfig.onEscape(component, simulatedEvent);
6328     const moveLeft$3 = doMove$2(cycleLeft$1);
6329     const moveRight$3 = doMove$2(cycleRight$1);
6330     const moveNorth$1 = doMove$2(cycleUp$1);
6331     const moveSouth$1 = doMove$2(cycleDown$1);
6332     const getKeydownRules$4 = constant$1([
6333       rule(inSet(LEFT), west$1(moveLeft$3, moveRight$3)),
6334       rule(inSet(RIGHT), east$1(moveLeft$3, moveRight$3)),
6335       rule(inSet(UP), north$1(moveNorth$1)),
6336       rule(inSet(DOWN), south$1(moveSouth$1)),
6337       rule(and([
6338         isShift,
6339         inSet(TAB)
6340       ]), handleTab),
6341       rule(and([
6342         isNotShift,
6343         inSet(TAB)
6344       ]), handleTab),
6345       rule(inSet(SPACE.concat(ENTER)), execute$3)
6346     ]);
6347     const getKeyupRules$4 = constant$1([
6348       rule(inSet(ESCAPE), doEscape$1),
6349       rule(inSet(SPACE), stopEventForFirefox)
6350     ]);
6351     var FlatgridType = typical(schema$u, flatgrid$1, getKeydownRules$4, getKeyupRules$4, () => Optional.some(focusIn$3));
6353     const horizontal = (container, selector, current, delta) => {
6354       const isDisabledButton = candidate => name$3(candidate) === 'button' && get$f(candidate, 'disabled') === 'disabled';
6355       const tryCycle = (initial, index, candidates) => {
6356         const newIndex = cycleBy(index, delta, 0, candidates.length - 1);
6357         if (newIndex === initial) {
6358           return Optional.none();
6359         } else {
6360           return isDisabledButton(candidates[newIndex]) ? tryCycle(initial, newIndex, candidates) : Optional.from(candidates[newIndex]);
6361         }
6362       };
6363       return locateVisible(container, current, selector).bind(identified => {
6364         const index = identified.index;
6365         const candidates = identified.candidates;
6366         return tryCycle(index, index, candidates);
6367       });
6368     };
6370     const schema$t = [
6371       required$1('selector'),
6372       defaulted('getInitial', Optional.none),
6373       defaulted('execute', defaultExecute),
6374       onKeyboardHandler('onEscape'),
6375       defaulted('executeOnMove', false),
6376       defaulted('allowVertical', true)
6377     ];
6378     const findCurrent = (component, flowConfig) => flowConfig.focusManager.get(component).bind(elem => closest$1(elem, flowConfig.selector));
6379     const execute$2 = (component, simulatedEvent, flowConfig) => findCurrent(component, flowConfig).bind(focused => flowConfig.execute(component, simulatedEvent, focused));
6380     const focusIn$2 = (component, flowConfig, _state) => {
6381       flowConfig.getInitial(component).orThunk(() => descendant(component.element, flowConfig.selector)).each(first => {
6382         flowConfig.focusManager.set(component, first);
6383       });
6384     };
6385     const moveLeft$2 = (element, focused, info) => horizontal(element, info.selector, focused, -1);
6386     const moveRight$2 = (element, focused, info) => horizontal(element, info.selector, focused, +1);
6387     const doMove$1 = movement => (component, simulatedEvent, flowConfig, flowState) => movement(component, simulatedEvent, flowConfig, flowState).bind(() => flowConfig.executeOnMove ? execute$2(component, simulatedEvent, flowConfig) : Optional.some(true));
6388     const doEscape = (component, simulatedEvent, flowConfig) => flowConfig.onEscape(component, simulatedEvent);
6389     const getKeydownRules$3 = (_component, _se, flowConfig, _flowState) => {
6390       const westMovers = LEFT.concat(flowConfig.allowVertical ? UP : []);
6391       const eastMovers = RIGHT.concat(flowConfig.allowVertical ? DOWN : []);
6392       return [
6393         rule(inSet(westMovers), doMove$1(west$1(moveLeft$2, moveRight$2))),
6394         rule(inSet(eastMovers), doMove$1(east$1(moveLeft$2, moveRight$2))),
6395         rule(inSet(ENTER), execute$2),
6396         rule(inSet(SPACE), execute$2)
6397       ];
6398     };
6399     const getKeyupRules$3 = constant$1([
6400       rule(inSet(SPACE), stopEventForFirefox),
6401       rule(inSet(ESCAPE), doEscape)
6402     ]);
6403     var FlowType = typical(schema$t, NoState.init, getKeydownRules$3, getKeyupRules$3, () => Optional.some(focusIn$2));
6405     const toCell = (matrix, rowIndex, columnIndex) => Optional.from(matrix[rowIndex]).bind(row => Optional.from(row[columnIndex]).map(cell => ({
6406       rowIndex,
6407       columnIndex,
6408       cell
6409     })));
6410     const cycleHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
6411       const row = matrix[rowIndex];
6412       const colsInRow = row.length;
6413       const newColIndex = cycleBy(startCol, deltaCol, 0, colsInRow - 1);
6414       return toCell(matrix, rowIndex, newColIndex);
6415     };
6416     const cycleVertical = (matrix, colIndex, startRow, deltaRow) => {
6417       const nextRowIndex = cycleBy(startRow, deltaRow, 0, matrix.length - 1);
6418       const colsInNextRow = matrix[nextRowIndex].length;
6419       const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
6420       return toCell(matrix, nextRowIndex, nextColIndex);
6421     };
6422     const moveHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
6423       const row = matrix[rowIndex];
6424       const colsInRow = row.length;
6425       const newColIndex = clamp(startCol + deltaCol, 0, colsInRow - 1);
6426       return toCell(matrix, rowIndex, newColIndex);
6427     };
6428     const moveVertical = (matrix, colIndex, startRow, deltaRow) => {
6429       const nextRowIndex = clamp(startRow + deltaRow, 0, matrix.length - 1);
6430       const colsInNextRow = matrix[nextRowIndex].length;
6431       const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
6432       return toCell(matrix, nextRowIndex, nextColIndex);
6433     };
6434     const cycleRight = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, +1);
6435     const cycleLeft = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, -1);
6436     const cycleUp = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, -1);
6437     const cycleDown = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, +1);
6438     const moveLeft$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, -1);
6439     const moveRight$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, +1);
6440     const moveUp$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, -1);
6441     const moveDown$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, +1);
6443     const schema$s = [
6444       requiredObjOf('selectors', [
6445         required$1('row'),
6446         required$1('cell')
6447       ]),
6448       defaulted('cycles', true),
6449       defaulted('previousSelector', Optional.none),
6450       defaulted('execute', defaultExecute)
6451     ];
6452     const focusIn$1 = (component, matrixConfig, _state) => {
6453       const focused = matrixConfig.previousSelector(component).orThunk(() => {
6454         const selectors = matrixConfig.selectors;
6455         return descendant(component.element, selectors.cell);
6456       });
6457       focused.each(cell => {
6458         matrixConfig.focusManager.set(component, cell);
6459       });
6460     };
6461     const execute$1 = (component, simulatedEvent, matrixConfig) => search(component.element).bind(focused => matrixConfig.execute(component, simulatedEvent, focused));
6462     const toMatrix = (rows, matrixConfig) => map$2(rows, row => descendants(row, matrixConfig.selectors.cell));
6463     const doMove = (ifCycle, ifMove) => (element, focused, matrixConfig) => {
6464       const move = matrixConfig.cycles ? ifCycle : ifMove;
6465       return closest$1(focused, matrixConfig.selectors.row).bind(inRow => {
6466         const cellsInRow = descendants(inRow, matrixConfig.selectors.cell);
6467         return findIndex(cellsInRow, focused).bind(colIndex => {
6468           const allRows = descendants(element, matrixConfig.selectors.row);
6469           return findIndex(allRows, inRow).bind(rowIndex => {
6470             const matrix = toMatrix(allRows, matrixConfig);
6471             return move(matrix, rowIndex, colIndex).map(next => next.cell);
6472           });
6473         });
6474       });
6475     };
6476     const moveLeft = doMove(cycleLeft, moveLeft$1);
6477     const moveRight = doMove(cycleRight, moveRight$1);
6478     const moveNorth = doMove(cycleUp, moveUp$1);
6479     const moveSouth = doMove(cycleDown, moveDown$1);
6480     const getKeydownRules$2 = constant$1([
6481       rule(inSet(LEFT), west$1(moveLeft, moveRight)),
6482       rule(inSet(RIGHT), east$1(moveLeft, moveRight)),
6483       rule(inSet(UP), north$1(moveNorth)),
6484       rule(inSet(DOWN), south$1(moveSouth)),
6485       rule(inSet(SPACE.concat(ENTER)), execute$1)
6486     ]);
6487     const getKeyupRules$2 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
6488     var MatrixType = typical(schema$s, NoState.init, getKeydownRules$2, getKeyupRules$2, () => Optional.some(focusIn$1));
6490     const schema$r = [
6491       required$1('selector'),
6492       defaulted('execute', defaultExecute),
6493       defaulted('moveOnTab', false)
6494     ];
6495     const execute = (component, simulatedEvent, menuConfig) => menuConfig.focusManager.get(component).bind(focused => menuConfig.execute(component, simulatedEvent, focused));
6496     const focusIn = (component, menuConfig, _state) => {
6497       descendant(component.element, menuConfig.selector).each(first => {
6498         menuConfig.focusManager.set(component, first);
6499       });
6500     };
6501     const moveUp = (element, focused, info) => horizontal(element, info.selector, focused, -1);
6502     const moveDown = (element, focused, info) => horizontal(element, info.selector, focused, +1);
6503     const fireShiftTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveUp)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
6504     const fireTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveDown)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
6505     const getKeydownRules$1 = constant$1([
6506       rule(inSet(UP), move$1(moveUp)),
6507       rule(inSet(DOWN), move$1(moveDown)),
6508       rule(and([
6509         isShift,
6510         inSet(TAB)
6511       ]), fireShiftTab),
6512       rule(and([
6513         isNotShift,
6514         inSet(TAB)
6515       ]), fireTab),
6516       rule(inSet(ENTER), execute),
6517       rule(inSet(SPACE), execute)
6518     ]);
6519     const getKeyupRules$1 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
6520     var MenuType = typical(schema$r, NoState.init, getKeydownRules$1, getKeyupRules$1, () => Optional.some(focusIn));
6522     const schema$q = [
6523       onKeyboardHandler('onSpace'),
6524       onKeyboardHandler('onEnter'),
6525       onKeyboardHandler('onShiftEnter'),
6526       onKeyboardHandler('onLeft'),
6527       onKeyboardHandler('onRight'),
6528       onKeyboardHandler('onTab'),
6529       onKeyboardHandler('onShiftTab'),
6530       onKeyboardHandler('onUp'),
6531       onKeyboardHandler('onDown'),
6532       onKeyboardHandler('onEscape'),
6533       defaulted('stopSpaceKeyup', false),
6534       option$3('focusIn')
6535     ];
6536     const getKeydownRules = (component, simulatedEvent, specialInfo) => [
6537       rule(inSet(SPACE), specialInfo.onSpace),
6538       rule(and([
6539         isNotShift,
6540         inSet(ENTER)
6541       ]), specialInfo.onEnter),
6542       rule(and([
6543         isShift,
6544         inSet(ENTER)
6545       ]), specialInfo.onShiftEnter),
6546       rule(and([
6547         isShift,
6548         inSet(TAB)
6549       ]), specialInfo.onShiftTab),
6550       rule(and([
6551         isNotShift,
6552         inSet(TAB)
6553       ]), specialInfo.onTab),
6554       rule(inSet(UP), specialInfo.onUp),
6555       rule(inSet(DOWN), specialInfo.onDown),
6556       rule(inSet(LEFT), specialInfo.onLeft),
6557       rule(inSet(RIGHT), specialInfo.onRight),
6558       rule(inSet(SPACE), specialInfo.onSpace)
6559     ];
6560     const getKeyupRules = (component, simulatedEvent, specialInfo) => [
6561       ...specialInfo.stopSpaceKeyup ? [rule(inSet(SPACE), stopEventForFirefox)] : [],
6562       rule(inSet(ESCAPE), specialInfo.onEscape)
6563     ];
6564     var SpecialType = typical(schema$q, NoState.init, getKeydownRules, getKeyupRules, specialInfo => specialInfo.focusIn);
6566     const acyclic = AcyclicType.schema();
6567     const cyclic = CyclicType.schema();
6568     const flow = FlowType.schema();
6569     const flatgrid = FlatgridType.schema();
6570     const matrix = MatrixType.schema();
6571     const execution = ExecutionType.schema();
6572     const menu = MenuType.schema();
6573     const special = SpecialType.schema();
6575     var KeyboardBranches = /*#__PURE__*/Object.freeze({
6576         __proto__: null,
6577         acyclic: acyclic,
6578         cyclic: cyclic,
6579         flow: flow,
6580         flatgrid: flatgrid,
6581         matrix: matrix,
6582         execution: execution,
6583         menu: menu,
6584         special: special
6585     });
6587     const isFlatgridState = keyState => hasNonNullableKey(keyState, 'setGridSize');
6588     const Keying = createModes({
6589       branchKey: 'mode',
6590       branches: KeyboardBranches,
6591       name: 'keying',
6592       active: {
6593         events: (keyingConfig, keyingState) => {
6594           const handler = keyingConfig.handler;
6595           return handler.toEvents(keyingConfig, keyingState);
6596         }
6597       },
6598       apis: {
6599         focusIn: (component, keyConfig, keyState) => {
6600           keyConfig.sendFocusIn(keyConfig).fold(() => {
6601             component.getSystem().triggerFocus(component.element, component.element);
6602           }, sendFocusIn => {
6603             sendFocusIn(component, keyConfig, keyState);
6604           });
6605         },
6606         setGridSize: (component, keyConfig, keyState, numRows, numColumns) => {
6607           if (!isFlatgridState(keyState)) {
6608             console.error('Layout does not support setGridSize');
6609           } else {
6610             keyState.setGridSize(numRows, numColumns);
6611           }
6612         }
6613       },
6614       state: KeyingState
6615     });
6617     const withoutReuse = (parent, data) => {
6618       preserve$1(() => {
6619         replaceChildren(parent, data, () => map$2(data, parent.getSystem().build));
6620       }, parent.element);
6621     };
6622     const withReuse = (parent, data) => {
6623       preserve$1(() => {
6624         virtualReplaceChildren(parent, data, () => {
6625           return patchSpecChildren(parent.element, data, parent.getSystem().buildOrPatch);
6626         });
6627       }, parent.element);
6628     };
6630     const virtualReplace = (component, replacee, replaceeIndex, childSpec) => {
6631       virtualDetach(replacee);
6632       const child = patchSpecChild(component.element, replaceeIndex, childSpec, component.getSystem().buildOrPatch);
6633       virtualAttach(component, child);
6634       component.syncComponents();
6635     };
6636     const insert = (component, insertion, childSpec) => {
6637       const child = component.getSystem().build(childSpec);
6638       attachWith(component, child, insertion);
6639     };
6640     const replace = (component, replacee, replaceeIndex, childSpec) => {
6641       detach(replacee);
6642       insert(component, (p, c) => appendAt(p, c, replaceeIndex), childSpec);
6643     };
6644     const set$3 = (component, replaceConfig, replaceState, data) => {
6645       const replacer = replaceConfig.reuseDom ? withReuse : withoutReuse;
6646       return replacer(component, data);
6647     };
6648     const append = (component, replaceConfig, replaceState, appendee) => {
6649       insert(component, append$2, appendee);
6650     };
6651     const prepend = (component, replaceConfig, replaceState, prependee) => {
6652       insert(component, prepend$1, prependee);
6653     };
6654     const remove = (component, replaceConfig, replaceState, removee) => {
6655       const children = contents(component);
6656       const foundChild = find$5(children, child => eq(removee.element, child.element));
6657       foundChild.each(detach);
6658     };
6659     const contents = (component, _replaceConfig) => component.components();
6660     const replaceAt = (component, replaceConfig, replaceState, replaceeIndex, replacer) => {
6661       const children = contents(component);
6662       return Optional.from(children[replaceeIndex]).map(replacee => {
6663         replacer.fold(() => detach(replacee), r => {
6664           const replacer = replaceConfig.reuseDom ? virtualReplace : replace;
6665           replacer(component, replacee, replaceeIndex, r);
6666         });
6667         return replacee;
6668       });
6669     };
6670     const replaceBy = (component, replaceConfig, replaceState, replaceePred, replacer) => {
6671       const children = contents(component);
6672       return findIndex$1(children, replaceePred).bind(replaceeIndex => replaceAt(component, replaceConfig, replaceState, replaceeIndex, replacer));
6673     };
6675     var ReplaceApis = /*#__PURE__*/Object.freeze({
6676         __proto__: null,
6677         append: append,
6678         prepend: prepend,
6679         remove: remove,
6680         replaceAt: replaceAt,
6681         replaceBy: replaceBy,
6682         set: set$3,
6683         contents: contents
6684     });
6686     const Replacing = create$4({
6687       fields: [defaultedBoolean('reuseDom', true)],
6688       name: 'replacing',
6689       apis: ReplaceApis
6690     });
6692     const events$d = (name, eventHandlers) => {
6693       const events = derive$2(eventHandlers);
6694       return create$4({
6695         fields: [required$1('enabled')],
6696         name,
6697         active: { events: constant$1(events) }
6698       });
6699     };
6700     const config = (name, eventHandlers) => {
6701       const me = events$d(name, eventHandlers);
6702       return {
6703         key: name,
6704         value: {
6705           config: {},
6706           me,
6707           configAsRaw: constant$1({}),
6708           initialConfig: {},
6709           state: NoState
6710         }
6711       };
6712     };
6714     const focus$2 = (component, focusConfig) => {
6715       if (!focusConfig.ignore) {
6716         focus$3(component.element);
6717         focusConfig.onFocus(component);
6718       }
6719     };
6720     const blur = (component, focusConfig) => {
6721       if (!focusConfig.ignore) {
6722         blur$1(component.element);
6723       }
6724     };
6725     const isFocused = component => hasFocus(component.element);
6727     var FocusApis = /*#__PURE__*/Object.freeze({
6728         __proto__: null,
6729         focus: focus$2,
6730         blur: blur,
6731         isFocused: isFocused
6732     });
6734     const exhibit$4 = (base, focusConfig) => {
6735       const mod = focusConfig.ignore ? {} : { attributes: { tabindex: '-1' } };
6736       return nu$7(mod);
6737     };
6738     const events$c = focusConfig => derive$2([run$1(focus$4(), (component, simulatedEvent) => {
6739         focus$2(component, focusConfig);
6740         simulatedEvent.stop();
6741       })].concat(focusConfig.stopMousedown ? [run$1(mousedown(), (_, simulatedEvent) => {
6742         simulatedEvent.event.prevent();
6743       })] : []));
6745     var ActiveFocus = /*#__PURE__*/Object.freeze({
6746         __proto__: null,
6747         exhibit: exhibit$4,
6748         events: events$c
6749     });
6751     var FocusSchema = [
6752       onHandler('onFocus'),
6753       defaulted('stopMousedown', false),
6754       defaulted('ignore', false)
6755     ];
6757     const Focusing = create$4({
6758       fields: FocusSchema,
6759       name: 'focusing',
6760       active: ActiveFocus,
6761       apis: FocusApis
6762     });
6764     const SetupBehaviourCellState = initialState => {
6765       const init = () => {
6766         const cell = Cell(initialState);
6767         const get = () => cell.get();
6768         const set = newState => cell.set(newState);
6769         const clear = () => cell.set(initialState);
6770         const readState = () => cell.get();
6771         return {
6772           get,
6773           set,
6774           clear,
6775           readState
6776         };
6777       };
6778       return { init };
6779     };
6781     const updateAriaState = (component, toggleConfig, toggleState) => {
6782       const ariaInfo = toggleConfig.aria;
6783       ariaInfo.update(component, ariaInfo, toggleState.get());
6784     };
6785     const updateClass = (component, toggleConfig, toggleState) => {
6786       toggleConfig.toggleClass.each(toggleClass => {
6787         if (toggleState.get()) {
6788           add$2(component.element, toggleClass);
6789         } else {
6790           remove$2(component.element, toggleClass);
6791         }
6792       });
6793     };
6794     const set$2 = (component, toggleConfig, toggleState, state) => {
6795       const initialState = toggleState.get();
6796       toggleState.set(state);
6797       updateClass(component, toggleConfig, toggleState);
6798       updateAriaState(component, toggleConfig, toggleState);
6799       if (initialState !== state) {
6800         toggleConfig.onToggled(component, state);
6801       }
6802     };
6803     const toggle$2 = (component, toggleConfig, toggleState) => {
6804       set$2(component, toggleConfig, toggleState, !toggleState.get());
6805     };
6806     const on = (component, toggleConfig, toggleState) => {
6807       set$2(component, toggleConfig, toggleState, true);
6808     };
6809     const off = (component, toggleConfig, toggleState) => {
6810       set$2(component, toggleConfig, toggleState, false);
6811     };
6812     const isOn = (component, toggleConfig, toggleState) => toggleState.get();
6813     const onLoad = (component, toggleConfig, toggleState) => {
6814       set$2(component, toggleConfig, toggleState, toggleConfig.selected);
6815     };
6817     var ToggleApis = /*#__PURE__*/Object.freeze({
6818         __proto__: null,
6819         onLoad: onLoad,
6820         toggle: toggle$2,
6821         isOn: isOn,
6822         on: on,
6823         off: off,
6824         set: set$2
6825     });
6827     const exhibit$3 = () => nu$7({});
6828     const events$b = (toggleConfig, toggleState) => {
6829       const execute = executeEvent(toggleConfig, toggleState, toggle$2);
6830       const load = loadEvent(toggleConfig, toggleState, onLoad);
6831       return derive$2(flatten([
6832         toggleConfig.toggleOnExecute ? [execute] : [],
6833         [load]
6834       ]));
6835     };
6837     var ActiveToggle = /*#__PURE__*/Object.freeze({
6838         __proto__: null,
6839         exhibit: exhibit$3,
6840         events: events$b
6841     });
6843     const updatePressed = (component, ariaInfo, status) => {
6844       set$9(component.element, 'aria-pressed', status);
6845       if (ariaInfo.syncWithExpanded) {
6846         updateExpanded(component, ariaInfo, status);
6847       }
6848     };
6849     const updateSelected = (component, ariaInfo, status) => {
6850       set$9(component.element, 'aria-selected', status);
6851     };
6852     const updateChecked = (component, ariaInfo, status) => {
6853       set$9(component.element, 'aria-checked', status);
6854     };
6855     const updateExpanded = (component, ariaInfo, status) => {
6856       set$9(component.element, 'aria-expanded', status);
6857     };
6859     var ToggleSchema = [
6860       defaulted('selected', false),
6861       option$3('toggleClass'),
6862       defaulted('toggleOnExecute', true),
6863       onHandler('onToggled'),
6864       defaultedOf('aria', { mode: 'none' }, choose$1('mode', {
6865         pressed: [
6866           defaulted('syncWithExpanded', false),
6867           output$1('update', updatePressed)
6868         ],
6869         checked: [output$1('update', updateChecked)],
6870         expanded: [output$1('update', updateExpanded)],
6871         selected: [output$1('update', updateSelected)],
6872         none: [output$1('update', noop)]
6873       }))
6874     ];
6876     const Toggling = create$4({
6877       fields: ToggleSchema,
6878       name: 'toggling',
6879       active: ActiveToggle,
6880       apis: ToggleApis,
6881       state: SetupBehaviourCellState(false)
6882     });
6884     const pointerEvents = () => {
6885       const onClick = (component, simulatedEvent) => {
6886         simulatedEvent.stop();
6887         emitExecute(component);
6888       };
6889       return [
6890         run$1(click(), onClick),
6891         run$1(tap(), onClick),
6892         cutter(touchstart()),
6893         cutter(mousedown())
6894       ];
6895     };
6896     const events$a = optAction => {
6897       const executeHandler = action => runOnExecute$1((component, simulatedEvent) => {
6898         action(component);
6899         simulatedEvent.stop();
6900       });
6901       return derive$2(flatten([
6902         optAction.map(executeHandler).toArray(),
6903         pointerEvents()
6904       ]));
6905     };
6907     const hoverEvent = 'alloy.item-hover';
6908     const focusEvent = 'alloy.item-focus';
6909     const toggledEvent = 'alloy.item-toggled';
6910     const onHover = item => {
6911       if (search(item.element).isNone() || Focusing.isFocused(item)) {
6912         if (!Focusing.isFocused(item)) {
6913           Focusing.focus(item);
6914         }
6915         emitWith(item, hoverEvent, { item });
6916       }
6917     };
6918     const onFocus$1 = item => {
6919       emitWith(item, focusEvent, { item });
6920     };
6921     const onToggled = (item, state) => {
6922       emitWith(item, toggledEvent, {
6923         item,
6924         state
6925       });
6926     };
6927     const hover = constant$1(hoverEvent);
6928     const focus$1 = constant$1(focusEvent);
6929     const toggled = constant$1(toggledEvent);
6931     const getItemRole = detail => detail.toggling.map(toggling => toggling.exclusive ? 'menuitemradio' : 'menuitemcheckbox').getOr('menuitem');
6932     const getTogglingSpec = tConfig => ({
6933       aria: { mode: 'checked' },
6934       ...filter$1(tConfig, (_value, name) => name !== 'exclusive'),
6935       onToggled: (component, state) => {
6936         if (isFunction(tConfig.onToggled)) {
6937           tConfig.onToggled(component, state);
6938         }
6939         onToggled(component, state);
6940       }
6941     });
6942     const builder$2 = detail => ({
6943       dom: detail.dom,
6944       domModification: {
6945         ...detail.domModification,
6946         attributes: {
6947           'role': getItemRole(detail),
6948           ...detail.domModification.attributes,
6949           'aria-haspopup': detail.hasSubmenu,
6950           ...detail.hasSubmenu ? { 'aria-expanded': false } : {}
6951         }
6952       },
6953       behaviours: SketchBehaviours.augment(detail.itemBehaviours, [
6954         detail.toggling.fold(Toggling.revoke, tConfig => Toggling.config(getTogglingSpec(tConfig))),
6955         Focusing.config({
6956           ignore: detail.ignoreFocus,
6957           stopMousedown: detail.ignoreFocus,
6958           onFocus: component => {
6959             onFocus$1(component);
6960           }
6961         }),
6962         Keying.config({ mode: 'execution' }),
6963         Representing.config({
6964           store: {
6965             mode: 'memory',
6966             initialValue: detail.data
6967           }
6968         }),
6969         config('item-type-events', [
6970           ...pointerEvents(),
6971           run$1(mouseover(), onHover),
6972           run$1(focusItem(), Focusing.focus)
6973         ])
6974       ]),
6975       components: detail.components,
6976       eventOrder: detail.eventOrder
6977     });
6978     const schema$p = [
6979       required$1('data'),
6980       required$1('components'),
6981       required$1('dom'),
6982       defaulted('hasSubmenu', false),
6983       option$3('toggling'),
6984       SketchBehaviours.field('itemBehaviours', [
6985         Toggling,
6986         Focusing,
6987         Keying,
6988         Representing
6989       ]),
6990       defaulted('ignoreFocus', false),
6991       defaulted('domModification', {}),
6992       output$1('builder', builder$2),
6993       defaulted('eventOrder', {})
6994     ];
6996     const builder$1 = detail => ({
6997       dom: detail.dom,
6998       components: detail.components,
6999       events: derive$2([stopper(focusItem())])
7000     });
7001     const schema$o = [
7002       required$1('dom'),
7003       required$1('components'),
7004       output$1('builder', builder$1)
7005     ];
7007     const owner$2 = constant$1('item-widget');
7008     const parts$h = constant$1([required({
7009         name: 'widget',
7010         overrides: detail => {
7011           return {
7012             behaviours: derive$1([Representing.config({
7013                 store: {
7014                   mode: 'manual',
7015                   getValue: _component => {
7016                     return detail.data;
7017                   },
7018                   setValue: noop
7019                 }
7020               })])
7021           };
7022         }
7023       })]);
7025     const builder = detail => {
7026       const subs = substitutes(owner$2(), detail, parts$h());
7027       const components = components$1(owner$2(), detail, subs.internals());
7028       const focusWidget = component => getPart(component, detail, 'widget').map(widget => {
7029         Keying.focusIn(widget);
7030         return widget;
7031       });
7032       const onHorizontalArrow = (component, simulatedEvent) => inside(simulatedEvent.event.target) ? Optional.none() : (() => {
7033         if (detail.autofocus) {
7034           simulatedEvent.setSource(component.element);
7035           return Optional.none();
7036         } else {
7037           return Optional.none();
7038         }
7039       })();
7040       return {
7041         dom: detail.dom,
7042         components,
7043         domModification: detail.domModification,
7044         events: derive$2([
7045           runOnExecute$1((component, simulatedEvent) => {
7046             focusWidget(component).each(_widget => {
7047               simulatedEvent.stop();
7048             });
7049           }),
7050           run$1(mouseover(), onHover),
7051           run$1(focusItem(), (component, _simulatedEvent) => {
7052             if (detail.autofocus) {
7053               focusWidget(component);
7054             } else {
7055               Focusing.focus(component);
7056             }
7057           })
7058         ]),
7059         behaviours: SketchBehaviours.augment(detail.widgetBehaviours, [
7060           Representing.config({
7061             store: {
7062               mode: 'memory',
7063               initialValue: detail.data
7064             }
7065           }),
7066           Focusing.config({
7067             ignore: detail.ignoreFocus,
7068             onFocus: component => {
7069               onFocus$1(component);
7070             }
7071           }),
7072           Keying.config({
7073             mode: 'special',
7074             focusIn: detail.autofocus ? component => {
7075               focusWidget(component);
7076             } : revoke(),
7077             onLeft: onHorizontalArrow,
7078             onRight: onHorizontalArrow,
7079             onEscape: (component, simulatedEvent) => {
7080               if (!Focusing.isFocused(component) && !detail.autofocus) {
7081                 Focusing.focus(component);
7082                 return Optional.some(true);
7083               } else if (detail.autofocus) {
7084                 simulatedEvent.setSource(component.element);
7085                 return Optional.none();
7086               } else {
7087                 return Optional.none();
7088               }
7089             }
7090           })
7091         ])
7092       };
7093     };
7094     const schema$n = [
7095       required$1('uid'),
7096       required$1('data'),
7097       required$1('components'),
7098       required$1('dom'),
7099       defaulted('autofocus', false),
7100       defaulted('ignoreFocus', false),
7101       SketchBehaviours.field('widgetBehaviours', [
7102         Representing,
7103         Focusing,
7104         Keying
7105       ]),
7106       defaulted('domModification', {}),
7107       defaultUidsSchema(parts$h()),
7108       output$1('builder', builder)
7109     ];
7111     const itemSchema$2 = choose$1('type', {
7112       widget: schema$n,
7113       item: schema$p,
7114       separator: schema$o
7115     });
7116     const configureGrid = (detail, movementInfo) => ({
7117       mode: 'flatgrid',
7118       selector: '.' + detail.markers.item,
7119       initSize: {
7120         numColumns: movementInfo.initSize.numColumns,
7121         numRows: movementInfo.initSize.numRows
7122       },
7123       focusManager: detail.focusManager
7124     });
7125     const configureMatrix = (detail, movementInfo) => ({
7126       mode: 'matrix',
7127       selectors: {
7128         row: movementInfo.rowSelector,
7129         cell: '.' + detail.markers.item
7130       },
7131       focusManager: detail.focusManager
7132     });
7133     const configureMenu = (detail, movementInfo) => ({
7134       mode: 'menu',
7135       selector: '.' + detail.markers.item,
7136       moveOnTab: movementInfo.moveOnTab,
7137       focusManager: detail.focusManager
7138     });
7139     const parts$g = constant$1([group({
7140         factory: {
7141           sketch: spec => {
7142             const itemInfo = asRawOrDie$1('menu.spec item', itemSchema$2, spec);
7143             return itemInfo.builder(itemInfo);
7144           }
7145         },
7146         name: 'items',
7147         unit: 'item',
7148         defaults: (detail, u) => {
7149           return has$2(u, 'uid') ? u : {
7150             ...u,
7151             uid: generate$5('item')
7152           };
7153         },
7154         overrides: (detail, u) => {
7155           return {
7156             type: u.type,
7157             ignoreFocus: detail.fakeFocus,
7158             domModification: { classes: [detail.markers.item] }
7159           };
7160         }
7161       })]);
7162     const schema$m = constant$1([
7163       required$1('value'),
7164       required$1('items'),
7165       required$1('dom'),
7166       required$1('components'),
7167       defaulted('eventOrder', {}),
7168       field('menuBehaviours', [
7169         Highlighting,
7170         Representing,
7171         Composing,
7172         Keying
7173       ]),
7174       defaultedOf('movement', {
7175         mode: 'menu',
7176         moveOnTab: true
7177       }, choose$1('mode', {
7178         grid: [
7179           initSize(),
7180           output$1('config', configureGrid)
7181         ],
7182         matrix: [
7183           output$1('config', configureMatrix),
7184           required$1('rowSelector')
7185         ],
7186         menu: [
7187           defaulted('moveOnTab', true),
7188           output$1('config', configureMenu)
7189         ]
7190       })),
7191       itemMarkers(),
7192       defaulted('fakeFocus', false),
7193       defaulted('focusManager', dom$2()),
7194       onHandler('onHighlight'),
7195       onHandler('onDehighlight')
7196     ]);
7198     const focus = constant$1('alloy.menu-focus');
7200     const deselectOtherRadioItems = (menu, item) => {
7201       const checkedRadioItems = descendants(menu.element, '[role="menuitemradio"][aria-checked="true"]');
7202       each$1(checkedRadioItems, ele => {
7203         if (!eq(ele, item.element)) {
7204           menu.getSystem().getByDom(ele).each(c => {
7205             Toggling.off(c);
7206           });
7207         }
7208       });
7209     };
7210     const make$7 = (detail, components, _spec, _externals) => ({
7211       uid: detail.uid,
7212       dom: detail.dom,
7213       markers: detail.markers,
7214       behaviours: augment(detail.menuBehaviours, [
7215         Highlighting.config({
7216           highlightClass: detail.markers.selectedItem,
7217           itemClass: detail.markers.item,
7218           onHighlight: detail.onHighlight,
7219           onDehighlight: detail.onDehighlight
7220         }),
7221         Representing.config({
7222           store: {
7223             mode: 'memory',
7224             initialValue: detail.value
7225           }
7226         }),
7227         Composing.config({ find: Optional.some }),
7228         Keying.config(detail.movement.config(detail, detail.movement))
7229       ]),
7230       events: derive$2([
7231         run$1(focus$1(), (menu, simulatedEvent) => {
7232           const event = simulatedEvent.event;
7233           menu.getSystem().getByDom(event.target).each(item => {
7234             Highlighting.highlight(menu, item);
7235             simulatedEvent.stop();
7236             emitWith(menu, focus(), {
7237               menu,
7238               item
7239             });
7240           });
7241         }),
7242         run$1(hover(), (menu, simulatedEvent) => {
7243           const item = simulatedEvent.event.item;
7244           Highlighting.highlight(menu, item);
7245         }),
7246         run$1(toggled(), (menu, simulatedEvent) => {
7247           const {item, state} = simulatedEvent.event;
7248           if (state && get$f(item.element, 'role') === 'menuitemradio') {
7249             deselectOtherRadioItems(menu, item);
7250           }
7251         })
7252       ]),
7253       components,
7254       eventOrder: detail.eventOrder,
7255       domModification: { attributes: { role: 'menu' } }
7256     });
7258     const Menu = composite({
7259       name: 'Menu',
7260       configFields: schema$m(),
7261       partFields: parts$g(),
7262       factory: make$7
7263     });
7265     const transpose$1 = obj => tupleMap(obj, (v, k) => ({
7266       k: v,
7267       v: k
7268     }));
7269     const trace = (items, byItem, byMenu, finish) => get$g(byMenu, finish).bind(triggerItem => get$g(items, triggerItem).bind(triggerMenu => {
7270       const rest = trace(items, byItem, byMenu, triggerMenu);
7271       return Optional.some([triggerMenu].concat(rest));
7272     })).getOr([]);
7273     const generate$2 = (menus, expansions) => {
7274       const items = {};
7275       each(menus, (menuItems, menu) => {
7276         each$1(menuItems, item => {
7277           items[item] = menu;
7278         });
7279       });
7280       const byItem = expansions;
7281       const byMenu = transpose$1(expansions);
7282       const menuPaths = map$1(byMenu, (_triggerItem, submenu) => [submenu].concat(trace(items, byItem, byMenu, submenu)));
7283       return map$1(items, menu => get$g(menuPaths, menu).getOr([menu]));
7284     };
7286     const init$c = () => {
7287       const expansions = Cell({});
7288       const menus = Cell({});
7289       const paths = Cell({});
7290       const primary = value$2();
7291       const directory = Cell({});
7292       const clear = () => {
7293         expansions.set({});
7294         menus.set({});
7295         paths.set({});
7296         primary.clear();
7297       };
7298       const isClear = () => primary.get().isNone();
7299       const setMenuBuilt = (menuName, built) => {
7300         menus.set({
7301           ...menus.get(),
7302           [menuName]: {
7303             type: 'prepared',
7304             menu: built
7305           }
7306         });
7307       };
7308       const setContents = (sPrimary, sMenus, sExpansions, dir) => {
7309         primary.set(sPrimary);
7310         expansions.set(sExpansions);
7311         menus.set(sMenus);
7312         directory.set(dir);
7313         const sPaths = generate$2(dir, sExpansions);
7314         paths.set(sPaths);
7315       };
7316       const getTriggeringItem = menuValue => find$4(expansions.get(), (v, _k) => v === menuValue);
7317       const getTriggerData = (menuValue, getItemByValue, path) => getPreparedMenu(menuValue).bind(menu => getTriggeringItem(menuValue).bind(triggeringItemValue => getItemByValue(triggeringItemValue).map(triggeredItem => ({
7318         triggeredMenu: menu,
7319         triggeringItem: triggeredItem,
7320         triggeringPath: path
7321       }))));
7322       const getTriggeringPath = (itemValue, getItemByValue) => {
7323         const extraPath = filter$2(lookupItem(itemValue).toArray(), menuValue => getPreparedMenu(menuValue).isSome());
7324         return get$g(paths.get(), itemValue).bind(path => {
7325           const revPath = reverse(extraPath.concat(path));
7326           const triggers = bind$3(revPath, (menuValue, menuIndex) => getTriggerData(menuValue, getItemByValue, revPath.slice(0, menuIndex + 1)).fold(() => is$1(primary.get(), menuValue) ? [] : [Optional.none()], data => [Optional.some(data)]));
7327           return sequence(triggers);
7328         });
7329       };
7330       const expand = itemValue => get$g(expansions.get(), itemValue).map(menu => {
7331         const current = get$g(paths.get(), itemValue).getOr([]);
7332         return [menu].concat(current);
7333       });
7334       const collapse = itemValue => get$g(paths.get(), itemValue).bind(path => path.length > 1 ? Optional.some(path.slice(1)) : Optional.none());
7335       const refresh = itemValue => get$g(paths.get(), itemValue);
7336       const getPreparedMenu = menuValue => lookupMenu(menuValue).bind(extractPreparedMenu);
7337       const lookupMenu = menuValue => get$g(menus.get(), menuValue);
7338       const lookupItem = itemValue => get$g(expansions.get(), itemValue);
7339       const otherMenus = path => {
7340         const menuValues = directory.get();
7341         return difference(keys(menuValues), path);
7342       };
7343       const getPrimary = () => primary.get().bind(getPreparedMenu);
7344       const getMenus = () => menus.get();
7345       return {
7346         setMenuBuilt,
7347         setContents,
7348         expand,
7349         refresh,
7350         collapse,
7351         lookupMenu,
7352         lookupItem,
7353         otherMenus,
7354         getPrimary,
7355         getMenus,
7356         clear,
7357         isClear,
7358         getTriggeringPath
7359       };
7360     };
7361     const extractPreparedMenu = prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none();
7362     const LayeredState = {
7363       init: init$c,
7364       extractPreparedMenu
7365     };
7367     const onMenuItemHighlightedEvent = generate$6('tiered-menu-item-highlight');
7368     const onMenuItemDehighlightedEvent = generate$6('tiered-menu-item-dehighlight');
7370     var HighlightOnOpen;
7371     (function (HighlightOnOpen) {
7372       HighlightOnOpen[HighlightOnOpen['HighlightMenuAndItem'] = 0] = 'HighlightMenuAndItem';
7373       HighlightOnOpen[HighlightOnOpen['HighlightJustMenu'] = 1] = 'HighlightJustMenu';
7374       HighlightOnOpen[HighlightOnOpen['HighlightNone'] = 2] = 'HighlightNone';
7375     }(HighlightOnOpen || (HighlightOnOpen = {})));
7377     const make$6 = (detail, _rawUiSpec) => {
7378       const submenuParentItems = value$2();
7379       const buildMenus = (container, primaryName, menus) => map$1(menus, (spec, name) => {
7380         const makeSketch = () => Menu.sketch({
7381           ...spec,
7382           value: name,
7383           markers: detail.markers,
7384           fakeFocus: detail.fakeFocus,
7385           onHighlight: (menuComp, itemComp) => {
7386             const highlightData = {
7387               menuComp,
7388               itemComp
7389             };
7390             emitWith(menuComp, onMenuItemHighlightedEvent, highlightData);
7391           },
7392           onDehighlight: (menuComp, itemComp) => {
7393             const dehighlightData = {
7394               menuComp,
7395               itemComp
7396             };
7397             emitWith(menuComp, onMenuItemDehighlightedEvent, dehighlightData);
7398           },
7399           focusManager: detail.fakeFocus ? highlights() : dom$2()
7400         });
7401         return name === primaryName ? {
7402           type: 'prepared',
7403           menu: container.getSystem().build(makeSketch())
7404         } : {
7405           type: 'notbuilt',
7406           nbMenu: makeSketch
7407         };
7408       });
7409       const layeredState = LayeredState.init();
7410       const setup = container => {
7411         const componentMap = buildMenus(container, detail.data.primary, detail.data.menus);
7412         const directory = toDirectory();
7413         layeredState.setContents(detail.data.primary, componentMap, detail.data.expansions, directory);
7414         return layeredState.getPrimary();
7415       };
7416       const getItemValue = item => Representing.getValue(item).value;
7417       const getItemByValue = (_container, menus, itemValue) => findMap(menus, menu => {
7418         if (!menu.getSystem().isConnected()) {
7419           return Optional.none();
7420         }
7421         const candidates = Highlighting.getCandidates(menu);
7422         return find$5(candidates, c => getItemValue(c) === itemValue);
7423       });
7424       const toDirectory = _container => map$1(detail.data.menus, (data, _menuName) => bind$3(data.items, item => item.type === 'separator' ? [] : [item.data.value]));
7425       const setActiveMenu = Highlighting.highlight;
7426       const setActiveMenuAndItem = (container, menu) => {
7427         setActiveMenu(container, menu);
7428         Highlighting.getHighlighted(menu).orThunk(() => Highlighting.getFirst(menu)).each(item => {
7429           if (detail.fakeFocus) {
7430             Highlighting.highlight(menu, item);
7431           } else {
7432             dispatch(container, item.element, focusItem());
7433           }
7434         });
7435       };
7436       const getMenus = (state, menuValues) => cat(map$2(menuValues, mv => state.lookupMenu(mv).bind(prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none())));
7437       const closeOthers = (container, state, path) => {
7438         const others = getMenus(state, state.otherMenus(path));
7439         each$1(others, o => {
7440           remove$1(o.element, [detail.markers.backgroundMenu]);
7441           if (!detail.stayInDom) {
7442             Replacing.remove(container, o);
7443           }
7444         });
7445       };
7446       const getSubmenuParents = container => submenuParentItems.get().getOrThunk(() => {
7447         const r = {};
7448         const items = descendants(container.element, `.${ detail.markers.item }`);
7449         const parentItems = filter$2(items, i => get$f(i, 'aria-haspopup') === 'true');
7450         each$1(parentItems, i => {
7451           container.getSystem().getByDom(i).each(itemComp => {
7452             const key = getItemValue(itemComp);
7453             r[key] = itemComp;
7454           });
7455         });
7456         submenuParentItems.set(r);
7457         return r;
7458       });
7459       const updateAriaExpansions = (container, path) => {
7460         const parentItems = getSubmenuParents(container);
7461         each(parentItems, (v, k) => {
7462           const expanded = contains$2(path, k);
7463           set$9(v.element, 'aria-expanded', expanded);
7464         });
7465       };
7466       const updateMenuPath = (container, state, path) => Optional.from(path[0]).bind(latestMenuName => state.lookupMenu(latestMenuName).bind(menuPrep => {
7467         if (menuPrep.type === 'notbuilt') {
7468           return Optional.none();
7469         } else {
7470           const activeMenu = menuPrep.menu;
7471           const rest = getMenus(state, path.slice(1));
7472           each$1(rest, r => {
7473             add$2(r.element, detail.markers.backgroundMenu);
7474           });
7475           if (!inBody(activeMenu.element)) {
7476             Replacing.append(container, premade(activeMenu));
7477           }
7478           remove$1(activeMenu.element, [detail.markers.backgroundMenu]);
7479           setActiveMenuAndItem(container, activeMenu);
7480           closeOthers(container, state, path);
7481           return Optional.some(activeMenu);
7482         }
7483       }));
7484       let ExpandHighlightDecision;
7485       (function (ExpandHighlightDecision) {
7486         ExpandHighlightDecision[ExpandHighlightDecision['HighlightSubmenu'] = 0] = 'HighlightSubmenu';
7487         ExpandHighlightDecision[ExpandHighlightDecision['HighlightParent'] = 1] = 'HighlightParent';
7488       }(ExpandHighlightDecision || (ExpandHighlightDecision = {})));
7489       const buildIfRequired = (container, menuName, menuPrep) => {
7490         if (menuPrep.type === 'notbuilt') {
7491           const menu = container.getSystem().build(menuPrep.nbMenu());
7492           layeredState.setMenuBuilt(menuName, menu);
7493           return menu;
7494         } else {
7495           return menuPrep.menu;
7496         }
7497       };
7498       const expandRight = (container, item, decision = ExpandHighlightDecision.HighlightSubmenu) => {
7499         if (item.hasConfigured(Disabling) && Disabling.isDisabled(item)) {
7500           return Optional.some(item);
7501         } else {
7502           const value = getItemValue(item);
7503           return layeredState.expand(value).bind(path => {
7504             updateAriaExpansions(container, path);
7505             return Optional.from(path[0]).bind(menuName => layeredState.lookupMenu(menuName).bind(activeMenuPrep => {
7506               const activeMenu = buildIfRequired(container, menuName, activeMenuPrep);
7507               if (!inBody(activeMenu.element)) {
7508                 Replacing.append(container, premade(activeMenu));
7509               }
7510               detail.onOpenSubmenu(container, item, activeMenu, reverse(path));
7511               if (decision === ExpandHighlightDecision.HighlightSubmenu) {
7512                 Highlighting.highlightFirst(activeMenu);
7513                 return updateMenuPath(container, layeredState, path);
7514               } else {
7515                 Highlighting.dehighlightAll(activeMenu);
7516                 return Optional.some(item);
7517               }
7518             }));
7519           });
7520         }
7521       };
7522       const collapseLeft = (container, item) => {
7523         const value = getItemValue(item);
7524         return layeredState.collapse(value).bind(path => {
7525           updateAriaExpansions(container, path);
7526           return updateMenuPath(container, layeredState, path).map(activeMenu => {
7527             detail.onCollapseMenu(container, item, activeMenu);
7528             return activeMenu;
7529           });
7530         });
7531       };
7532       const updateView = (container, item) => {
7533         const value = getItemValue(item);
7534         return layeredState.refresh(value).bind(path => {
7535           updateAriaExpansions(container, path);
7536           return updateMenuPath(container, layeredState, path);
7537         });
7538       };
7539       const onRight = (container, item) => inside(item.element) ? Optional.none() : expandRight(container, item, ExpandHighlightDecision.HighlightSubmenu);
7540       const onLeft = (container, item) => inside(item.element) ? Optional.none() : collapseLeft(container, item);
7541       const onEscape = (container, item) => collapseLeft(container, item).orThunk(() => detail.onEscape(container, item).map(() => container));
7542       const keyOnItem = f => (container, simulatedEvent) => {
7543         return closest$1(simulatedEvent.getSource(), `.${ detail.markers.item }`).bind(target => container.getSystem().getByDom(target).toOptional().bind(item => f(container, item).map(always)));
7544       };
7545       const events = derive$2([
7546         run$1(focus(), (tmenu, simulatedEvent) => {
7547           const item = simulatedEvent.event.item;
7548           layeredState.lookupItem(getItemValue(item)).each(() => {
7549             const menu = simulatedEvent.event.menu;
7550             Highlighting.highlight(tmenu, menu);
7551             const value = getItemValue(simulatedEvent.event.item);
7552             layeredState.refresh(value).each(path => closeOthers(tmenu, layeredState, path));
7553           });
7554         }),
7555         runOnExecute$1((component, simulatedEvent) => {
7556           const target = simulatedEvent.event.target;
7557           component.getSystem().getByDom(target).each(item => {
7558             const itemValue = getItemValue(item);
7559             if (itemValue.indexOf('collapse-item') === 0) {
7560               collapseLeft(component, item);
7561             }
7562             expandRight(component, item, ExpandHighlightDecision.HighlightSubmenu).fold(() => {
7563               detail.onExecute(component, item);
7564             }, noop);
7565           });
7566         }),
7567         runOnAttached((container, _simulatedEvent) => {
7568           setup(container).each(primary => {
7569             Replacing.append(container, premade(primary));
7570             detail.onOpenMenu(container, primary);
7571             if (detail.highlightOnOpen === HighlightOnOpen.HighlightMenuAndItem) {
7572               setActiveMenuAndItem(container, primary);
7573             } else if (detail.highlightOnOpen === HighlightOnOpen.HighlightJustMenu) {
7574               setActiveMenu(container, primary);
7575             }
7576           });
7577         }),
7578         run$1(onMenuItemHighlightedEvent, (tmenuComp, se) => {
7579           detail.onHighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
7580         }),
7581         run$1(onMenuItemDehighlightedEvent, (tmenuComp, se) => {
7582           detail.onDehighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
7583         }),
7584         ...detail.navigateOnHover ? [run$1(hover(), (tmenu, simulatedEvent) => {
7585             const item = simulatedEvent.event.item;
7586             updateView(tmenu, item);
7587             expandRight(tmenu, item, ExpandHighlightDecision.HighlightParent);
7588             detail.onHover(tmenu, item);
7589           })] : []
7590       ]);
7591       const getActiveItem = container => Highlighting.getHighlighted(container).bind(Highlighting.getHighlighted);
7592       const collapseMenuApi = container => {
7593         getActiveItem(container).each(currentItem => {
7594           collapseLeft(container, currentItem);
7595         });
7596       };
7597       const highlightPrimary = container => {
7598         layeredState.getPrimary().each(primary => {
7599           setActiveMenuAndItem(container, primary);
7600         });
7601       };
7602       const extractMenuFromContainer = container => Optional.from(container.components()[0]).filter(comp => get$f(comp.element, 'role') === 'menu');
7603       const repositionMenus = container => {
7604         const maybeActivePrimary = layeredState.getPrimary().bind(primary => getActiveItem(container).bind(currentItem => {
7605           const itemValue = getItemValue(currentItem);
7606           const allMenus = values(layeredState.getMenus());
7607           const preparedMenus = cat(map$2(allMenus, LayeredState.extractPreparedMenu));
7608           return layeredState.getTriggeringPath(itemValue, v => getItemByValue(container, preparedMenus, v));
7609         }).map(triggeringPath => ({
7610           primary,
7611           triggeringPath
7612         })));
7613         maybeActivePrimary.fold(() => {
7614           extractMenuFromContainer(container).each(primaryMenu => {
7615             detail.onRepositionMenu(container, primaryMenu, []);
7616           });
7617         }, ({primary, triggeringPath}) => {
7618           detail.onRepositionMenu(container, primary, triggeringPath);
7619         });
7620       };
7621       const apis = {
7622         collapseMenu: collapseMenuApi,
7623         highlightPrimary,
7624         repositionMenus
7625       };
7626       return {
7627         uid: detail.uid,
7628         dom: detail.dom,
7629         markers: detail.markers,
7630         behaviours: augment(detail.tmenuBehaviours, [
7631           Keying.config({
7632             mode: 'special',
7633             onRight: keyOnItem(onRight),
7634             onLeft: keyOnItem(onLeft),
7635             onEscape: keyOnItem(onEscape),
7636             focusIn: (container, _keyInfo) => {
7637               layeredState.getPrimary().each(primary => {
7638                 dispatch(container, primary.element, focusItem());
7639               });
7640             }
7641           }),
7642           Highlighting.config({
7643             highlightClass: detail.markers.selectedMenu,
7644             itemClass: detail.markers.menu
7645           }),
7646           Composing.config({
7647             find: container => {
7648               return Highlighting.getHighlighted(container);
7649             }
7650           }),
7651           Replacing.config({})
7652         ]),
7653         eventOrder: detail.eventOrder,
7654         apis,
7655         events
7656       };
7657     };
7658     const collapseItem$1 = constant$1('collapse-item');
7660     const tieredData = (primary, menus, expansions) => ({
7661       primary,
7662       menus,
7663       expansions
7664     });
7665     const singleData = (name, menu) => ({
7666       primary: name,
7667       menus: wrap$1(name, menu),
7668       expansions: {}
7669     });
7670     const collapseItem = text => ({
7671       value: generate$6(collapseItem$1()),
7672       meta: { text }
7673     });
7674     const tieredMenu = single({
7675       name: 'TieredMenu',
7676       configFields: [
7677         onStrictKeyboardHandler('onExecute'),
7678         onStrictKeyboardHandler('onEscape'),
7679         onStrictHandler('onOpenMenu'),
7680         onStrictHandler('onOpenSubmenu'),
7681         onHandler('onRepositionMenu'),
7682         onHandler('onCollapseMenu'),
7683         defaulted('highlightOnOpen', HighlightOnOpen.HighlightMenuAndItem),
7684         requiredObjOf('data', [
7685           required$1('primary'),
7686           required$1('menus'),
7687           required$1('expansions')
7688         ]),
7689         defaulted('fakeFocus', false),
7690         onHandler('onHighlightItem'),
7691         onHandler('onDehighlightItem'),
7692         onHandler('onHover'),
7693         tieredMenuMarkers(),
7694         required$1('dom'),
7695         defaulted('navigateOnHover', true),
7696         defaulted('stayInDom', false),
7697         field('tmenuBehaviours', [
7698           Keying,
7699           Highlighting,
7700           Composing,
7701           Replacing
7702         ]),
7703         defaulted('eventOrder', {})
7704       ],
7705       apis: {
7706         collapseMenu: (apis, tmenu) => {
7707           apis.collapseMenu(tmenu);
7708         },
7709         highlightPrimary: (apis, tmenu) => {
7710           apis.highlightPrimary(tmenu);
7711         },
7712         repositionMenus: (apis, tmenu) => {
7713           apis.repositionMenus(tmenu);
7714         }
7715       },
7716       factory: make$6,
7717       extraApis: {
7718         tieredData,
7719         singleData,
7720         collapseItem
7721       }
7722     });
7724     const makeMenu = (detail, menuSandbox, placementSpec, menuSpec, getBounds) => {
7725       const lazySink = () => detail.lazySink(menuSandbox);
7726       const layouts = menuSpec.type === 'horizontal' ? {
7727         layouts: {
7728           onLtr: () => belowOrAbove(),
7729           onRtl: () => belowOrAboveRtl()
7730         }
7731       } : {};
7732       const isFirstTierSubmenu = triggeringPaths => triggeringPaths.length === 2;
7733       const getSubmenuLayouts = triggeringPaths => isFirstTierSubmenu(triggeringPaths) ? layouts : {};
7734       return tieredMenu.sketch({
7735         dom: { tag: 'div' },
7736         data: menuSpec.data,
7737         markers: menuSpec.menu.markers,
7738         highlightOnOpen: menuSpec.menu.highlightOnOpen,
7739         fakeFocus: menuSpec.menu.fakeFocus,
7740         onEscape: () => {
7741           Sandboxing.close(menuSandbox);
7742           detail.onEscape.map(handler => handler(menuSandbox));
7743           return Optional.some(true);
7744         },
7745         onExecute: () => {
7746           return Optional.some(true);
7747         },
7748         onOpenMenu: (tmenu, menu) => {
7749           Positioning.positionWithinBounds(lazySink().getOrDie(), menu, placementSpec, getBounds());
7750         },
7751         onOpenSubmenu: (tmenu, item, submenu, triggeringPaths) => {
7752           const sink = lazySink().getOrDie();
7753           Positioning.position(sink, submenu, {
7754             anchor: {
7755               type: 'submenu',
7756               item,
7757               ...getSubmenuLayouts(triggeringPaths)
7758             }
7759           });
7760         },
7761         onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
7762           const sink = lazySink().getOrDie();
7763           Positioning.positionWithinBounds(sink, primaryMenu, placementSpec, getBounds());
7764           each$1(submenuTriggers, st => {
7765             const submenuLayouts = getSubmenuLayouts(st.triggeringPath);
7766             Positioning.position(sink, st.triggeredMenu, {
7767               anchor: {
7768                 type: 'submenu',
7769                 item: st.triggeringItem,
7770                 ...submenuLayouts
7771               }
7772             });
7773           });
7774         }
7775       });
7776     };
7777     const factory$m = (detail, spec) => {
7778       const isPartOfRelated = (sandbox, queryElem) => {
7779         const related = detail.getRelated(sandbox);
7780         return related.exists(rel => isPartOf$1(rel, queryElem));
7781       };
7782       const setContent = (sandbox, thing) => {
7783         Sandboxing.setContent(sandbox, thing);
7784       };
7785       const showAt = (sandbox, thing, placementSpec) => {
7786         showWithin(sandbox, thing, placementSpec, Optional.none());
7787       };
7788       const showWithin = (sandbox, thing, placementSpec, boxElement) => {
7789         showWithinBounds(sandbox, thing, placementSpec, () => boxElement.map(elem => box$1(elem)));
7790       };
7791       const showWithinBounds = (sandbox, thing, placementSpec, getBounds) => {
7792         const sink = detail.lazySink(sandbox).getOrDie();
7793         Sandboxing.openWhileCloaked(sandbox, thing, () => Positioning.positionWithinBounds(sink, sandbox, placementSpec, getBounds()));
7794         Representing.setValue(sandbox, Optional.some({
7795           mode: 'position',
7796           config: placementSpec,
7797           getBounds
7798         }));
7799       };
7800       const showMenuAt = (sandbox, placementSpec, menuSpec) => {
7801         showMenuWithinBounds(sandbox, placementSpec, menuSpec, Optional.none);
7802       };
7803       const showMenuWithinBounds = (sandbox, placementSpec, menuSpec, getBounds) => {
7804         const menu = makeMenu(detail, sandbox, placementSpec, menuSpec, getBounds);
7805         Sandboxing.open(sandbox, menu);
7806         Representing.setValue(sandbox, Optional.some({
7807           mode: 'menu',
7808           menu
7809         }));
7810       };
7811       const hide = sandbox => {
7812         if (Sandboxing.isOpen(sandbox)) {
7813           Representing.setValue(sandbox, Optional.none());
7814           Sandboxing.close(sandbox);
7815         }
7816       };
7817       const getContent = sandbox => Sandboxing.getState(sandbox);
7818       const reposition = sandbox => {
7819         if (Sandboxing.isOpen(sandbox)) {
7820           Representing.getValue(sandbox).each(state => {
7821             switch (state.mode) {
7822             case 'menu':
7823               Sandboxing.getState(sandbox).each(tieredMenu.repositionMenus);
7824               break;
7825             case 'position':
7826               const sink = detail.lazySink(sandbox).getOrDie();
7827               Positioning.positionWithinBounds(sink, sandbox, state.config, state.getBounds());
7828               break;
7829             }
7830           });
7831         }
7832       };
7833       const apis = {
7834         setContent,
7835         showAt,
7836         showWithin,
7837         showWithinBounds,
7838         showMenuAt,
7839         showMenuWithinBounds,
7840         hide,
7841         getContent,
7842         reposition,
7843         isOpen: Sandboxing.isOpen
7844       };
7845       return {
7846         uid: detail.uid,
7847         dom: detail.dom,
7848         behaviours: augment(detail.inlineBehaviours, [
7849           Sandboxing.config({
7850             isPartOf: (sandbox, data, queryElem) => {
7851               return isPartOf$1(data, queryElem) || isPartOfRelated(sandbox, queryElem);
7852             },
7853             getAttachPoint: sandbox => {
7854               return detail.lazySink(sandbox).getOrDie();
7855             },
7856             onOpen: sandbox => {
7857               detail.onShow(sandbox);
7858             },
7859             onClose: sandbox => {
7860               detail.onHide(sandbox);
7861             }
7862           }),
7863           Representing.config({
7864             store: {
7865               mode: 'memory',
7866               initialValue: Optional.none()
7867             }
7868           }),
7869           Receiving.config({
7870             channels: {
7871               ...receivingChannel$1({
7872                 isExtraPart: spec.isExtraPart,
7873                 ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
7874               }),
7875               ...receivingChannel({
7876                 ...detail.fireRepositionEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({}),
7877                 doReposition: reposition
7878               })
7879             }
7880           })
7881         ]),
7882         eventOrder: detail.eventOrder,
7883         apis
7884       };
7885     };
7886     const InlineView = single({
7887       name: 'InlineView',
7888       configFields: [
7889         required$1('lazySink'),
7890         onHandler('onShow'),
7891         onHandler('onHide'),
7892         optionFunction('onEscape'),
7893         field('inlineBehaviours', [
7894           Sandboxing,
7895           Representing,
7896           Receiving
7897         ]),
7898         optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
7899         optionObjOf('fireRepositionEventInstead', [defaulted('event', repositionRequested())]),
7900         defaulted('getRelated', Optional.none),
7901         defaulted('isExtraPart', never),
7902         defaulted('eventOrder', Optional.none)
7903       ],
7904       factory: factory$m,
7905       apis: {
7906         showAt: (apis, component, anchor, thing) => {
7907           apis.showAt(component, anchor, thing);
7908         },
7909         showWithin: (apis, component, anchor, thing, boxElement) => {
7910           apis.showWithin(component, anchor, thing, boxElement);
7911         },
7912         showWithinBounds: (apis, component, anchor, thing, bounds) => {
7913           apis.showWithinBounds(component, anchor, thing, bounds);
7914         },
7915         showMenuAt: (apis, component, anchor, menuSpec) => {
7916           apis.showMenuAt(component, anchor, menuSpec);
7917         },
7918         showMenuWithinBounds: (apis, component, anchor, menuSpec, bounds) => {
7919           apis.showMenuWithinBounds(component, anchor, menuSpec, bounds);
7920         },
7921         hide: (apis, component) => {
7922           apis.hide(component);
7923         },
7924         isOpen: (apis, component) => apis.isOpen(component),
7925         getContent: (apis, component) => apis.getContent(component),
7926         setContent: (apis, component, thing) => {
7927           apis.setContent(component, thing);
7928         },
7929         reposition: (apis, component) => {
7930           apis.reposition(component);
7931         }
7932       }
7933     });
7935     var global$9 = tinymce.util.Tools.resolve('tinymce.util.Delay');
7937     const factory$l = detail => {
7938       const events = events$a(detail.action);
7939       const tag = detail.dom.tag;
7940       const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
7941       const getModAttributes = () => {
7942         if (tag === 'button') {
7943           const type = lookupAttr('type').getOr('button');
7944           const roleAttrs = lookupAttr('role').map(role => ({ role })).getOr({});
7945           return {
7946             type,
7947             ...roleAttrs
7948           };
7949         } else {
7950           const role = lookupAttr('role').getOr('button');
7951           return { role };
7952         }
7953       };
7954       return {
7955         uid: detail.uid,
7956         dom: detail.dom,
7957         components: detail.components,
7958         events,
7959         behaviours: SketchBehaviours.augment(detail.buttonBehaviours, [
7960           Focusing.config({}),
7961           Keying.config({
7962             mode: 'execution',
7963             useSpace: true,
7964             useEnter: true
7965           })
7966         ]),
7967         domModification: { attributes: getModAttributes() },
7968         eventOrder: detail.eventOrder
7969       };
7970     };
7971     const Button = single({
7972       name: 'Button',
7973       factory: factory$l,
7974       configFields: [
7975         defaulted('uid', undefined),
7976         required$1('dom'),
7977         defaulted('components', []),
7978         SketchBehaviours.field('buttonBehaviours', [
7979           Focusing,
7980           Keying
7981         ]),
7982         option$3('action'),
7983         option$3('role'),
7984         defaulted('eventOrder', {})
7985       ]
7986     });
7988     const record = spec => {
7989       const uid = isSketchSpec(spec) && hasNonNullableKey(spec, 'uid') ? spec.uid : generate$5('memento');
7990       const get = anyInSystem => anyInSystem.getSystem().getByUid(uid).getOrDie();
7991       const getOpt = anyInSystem => anyInSystem.getSystem().getByUid(uid).toOptional();
7992       const asSpec = () => ({
7993         ...spec,
7994         uid
7995       });
7996       return {
7997         get,
7998         getOpt,
7999         asSpec
8000       };
8001     };
8003     var global$8 = tinymce.util.Tools.resolve('tinymce.util.I18n');
8005     const rtlTransform = {
8006       'indent': true,
8007       'outdent': true,
8008       'table-insert-column-after': true,
8009       'table-insert-column-before': true,
8010       'paste-column-after': true,
8011       'paste-column-before': true,
8012       'unordered-list': true,
8013       'list-bull-circle': true,
8014       'list-bull-default': true,
8015       'list-bull-square': true
8016     };
8017     const defaultIconName = 'temporary-placeholder';
8018     const defaultIcon = icons => () => get$g(icons, defaultIconName).getOr('!not found!');
8019     const getIconName = (name, icons) => {
8020       const lcName = name.toLowerCase();
8021       if (global$8.isRtl()) {
8022         const rtlName = ensureTrailing(lcName, '-rtl');
8023         return has$2(icons, rtlName) ? rtlName : lcName;
8024       } else {
8025         return lcName;
8026       }
8027     };
8028     const lookupIcon = (name, icons) => get$g(icons, getIconName(name, icons));
8029     const get$2 = (name, iconProvider) => {
8030       const icons = iconProvider();
8031       return lookupIcon(name, icons).getOrThunk(defaultIcon(icons));
8032     };
8033     const getOr = (name, iconProvider, fallbackIcon) => {
8034       const icons = iconProvider();
8035       return lookupIcon(name, icons).or(fallbackIcon).getOrThunk(defaultIcon(icons));
8036     };
8037     const needsRtlTransform = iconName => global$8.isRtl() ? has$2(rtlTransform, iconName) : false;
8038     const addFocusableBehaviour = () => config('add-focusable', [runOnAttached(comp => {
8039         child(comp.element, 'svg').each(svg => set$9(svg, 'focusable', 'false'));
8040       })]);
8041     const renderIcon$2 = (spec, iconName, icons, fallbackIcon) => {
8042       const rtlIconClasses = needsRtlTransform(iconName) ? ['tox-icon--flip'] : [];
8043       const iconHtml = get$g(icons, getIconName(iconName, icons)).or(fallbackIcon).getOrThunk(defaultIcon(icons));
8044       return {
8045         dom: {
8046           tag: spec.tag,
8047           attributes: spec.attributes ?? {},
8048           classes: spec.classes.concat(rtlIconClasses),
8049           innerHtml: iconHtml
8050         },
8051         behaviours: derive$1([
8052           ...spec.behaviours ?? [],
8053           addFocusableBehaviour()
8054         ])
8055       };
8056     };
8057     const render$3 = (iconName, spec, iconProvider, fallbackIcon = Optional.none()) => renderIcon$2(spec, iconName, iconProvider(), fallbackIcon);
8058     const renderFirst = (iconNames, spec, iconProvider) => {
8059       const icons = iconProvider();
8060       const iconName = find$5(iconNames, name => has$2(icons, getIconName(name, icons)));
8061       return renderIcon$2(spec, iconName.getOr(defaultIconName), icons, Optional.none());
8062     };
8064     const notificationIconMap = {
8065       success: 'checkmark',
8066       error: 'warning',
8067       err: 'error',
8068       warning: 'warning',
8069       warn: 'warning',
8070       info: 'info'
8071     };
8072     const factory$k = detail => {
8073       const memBannerText = record({
8074         dom: {
8075           tag: 'p',
8076           innerHtml: detail.translationProvider(detail.text)
8077         },
8078         behaviours: derive$1([Replacing.config({})])
8079       });
8080       const renderPercentBar = percent => ({
8081         dom: {
8082           tag: 'div',
8083           classes: ['tox-bar'],
8084           styles: { width: `${ percent }%` }
8085         }
8086       });
8087       const renderPercentText = percent => ({
8088         dom: {
8089           tag: 'div',
8090           classes: ['tox-text'],
8091           innerHtml: `${ percent }%`
8092         }
8093       });
8094       const memBannerProgress = record({
8095         dom: {
8096           tag: 'div',
8097           classes: detail.progress ? [
8098             'tox-progress-bar',
8099             'tox-progress-indicator'
8100           ] : ['tox-progress-bar']
8101         },
8102         components: [
8103           {
8104             dom: {
8105               tag: 'div',
8106               classes: ['tox-bar-container']
8107             },
8108             components: [renderPercentBar(0)]
8109           },
8110           renderPercentText(0)
8111         ],
8112         behaviours: derive$1([Replacing.config({})])
8113       });
8114       const updateProgress = (comp, percent) => {
8115         if (comp.getSystem().isConnected()) {
8116           memBannerProgress.getOpt(comp).each(progress => {
8117             Replacing.set(progress, [
8118               {
8119                 dom: {
8120                   tag: 'div',
8121                   classes: ['tox-bar-container']
8122                 },
8123                 components: [renderPercentBar(percent)]
8124               },
8125               renderPercentText(percent)
8126             ]);
8127           });
8128         }
8129       };
8130       const updateText = (comp, text) => {
8131         if (comp.getSystem().isConnected()) {
8132           const banner = memBannerText.get(comp);
8133           Replacing.set(banner, [text$2(text)]);
8134         }
8135       };
8136       const apis = {
8137         updateProgress,
8138         updateText
8139       };
8140       const iconChoices = flatten([
8141         detail.icon.toArray(),
8142         detail.level.toArray(),
8143         detail.level.bind(level => Optional.from(notificationIconMap[level])).toArray()
8144       ]);
8145       const memButton = record(Button.sketch({
8146         dom: {
8147           tag: 'button',
8148           classes: [
8149             'tox-notification__dismiss',
8150             'tox-button',
8151             'tox-button--naked',
8152             'tox-button--icon'
8153           ]
8154         },
8155         components: [render$3('close', {
8156             tag: 'div',
8157             classes: ['tox-icon'],
8158             attributes: { 'aria-label': detail.translationProvider('Close') }
8159           }, detail.iconProvider)],
8160         action: comp => {
8161           detail.onAction(comp);
8162         }
8163       }));
8164       const notificationIconSpec = renderFirst(iconChoices, {
8165         tag: 'div',
8166         classes: ['tox-notification__icon']
8167       }, detail.iconProvider);
8168       const notificationBodySpec = {
8169         dom: {
8170           tag: 'div',
8171           classes: ['tox-notification__body']
8172         },
8173         components: [memBannerText.asSpec()],
8174         behaviours: derive$1([Replacing.config({})])
8175       };
8176       const components = [
8177         notificationIconSpec,
8178         notificationBodySpec
8179       ];
8180       return {
8181         uid: detail.uid,
8182         dom: {
8183           tag: 'div',
8184           attributes: { role: 'alert' },
8185           classes: detail.level.map(level => [
8186             'tox-notification',
8187             'tox-notification--in',
8188             `tox-notification--${ level }`
8189           ]).getOr([
8190             'tox-notification',
8191             'tox-notification--in'
8192           ])
8193         },
8194         behaviours: derive$1([
8195           Focusing.config({}),
8196           config('notification-events', [run$1(focusin(), comp => {
8197               memButton.getOpt(comp).each(Focusing.focus);
8198             })])
8199         ]),
8200         components: components.concat(detail.progress ? [memBannerProgress.asSpec()] : []).concat(!detail.closeButton ? [] : [memButton.asSpec()]),
8201         apis
8202       };
8203     };
8204     const Notification = single({
8205       name: 'Notification',
8206       factory: factory$k,
8207       configFields: [
8208         option$3('level'),
8209         required$1('progress'),
8210         option$3('icon'),
8211         required$1('onAction'),
8212         required$1('text'),
8213         required$1('iconProvider'),
8214         required$1('translationProvider'),
8215         defaultedBoolean('closeButton', true)
8216       ],
8217       apis: {
8218         updateProgress: (apis, comp, percent) => {
8219           apis.updateProgress(comp, percent);
8220         },
8221         updateText: (apis, comp, text) => {
8222           apis.updateText(comp, text);
8223         }
8224       }
8225     });
8227     var NotificationManagerImpl = (editor, extras, uiMothership) => {
8228       const sharedBackstage = extras.backstage.shared;
8229       const getBounds = () => {
8230         const contentArea = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
8231         const win$1 = win();
8232         const x = clamp(win$1.x, contentArea.x, contentArea.right);
8233         const y = clamp(win$1.y, contentArea.y, contentArea.bottom);
8234         const right = Math.max(contentArea.right, win$1.right);
8235         const bottom = Math.max(contentArea.bottom, win$1.bottom);
8236         return Optional.some(bounds(x, y, right - x, bottom - y));
8237       };
8238       const open = (settings, closeCallback) => {
8239         const close = () => {
8240           closeCallback();
8241           InlineView.hide(notificationWrapper);
8242         };
8243         const notification = build$1(Notification.sketch({
8244           text: settings.text,
8245           level: contains$2([
8246             'success',
8247             'error',
8248             'warning',
8249             'warn',
8250             'info'
8251           ], settings.type) ? settings.type : undefined,
8252           progress: settings.progressBar === true,
8253           icon: settings.icon,
8254           closeButton: settings.closeButton,
8255           onAction: close,
8256           iconProvider: sharedBackstage.providers.icons,
8257           translationProvider: sharedBackstage.providers.translate
8258         }));
8259         const notificationWrapper = build$1(InlineView.sketch({
8260           dom: {
8261             tag: 'div',
8262             classes: ['tox-notifications-container']
8263           },
8264           lazySink: sharedBackstage.getSink,
8265           fireDismissalEventInstead: {},
8266           ...sharedBackstage.header.isPositionedAtTop() ? {} : { fireRepositionEventInstead: {} }
8267         }));
8268         uiMothership.add(notificationWrapper);
8269         if (isNumber(settings.timeout) && settings.timeout > 0) {
8270           global$9.setEditorTimeout(editor, () => {
8271             close();
8272           }, settings.timeout);
8273         }
8274         const reposition = () => {
8275           const notificationSpec = premade(notification);
8276           const anchorOverrides = { maxHeightFunction: expandable$1() };
8277           const allNotifications = editor.notificationManager.getNotifications();
8278           if (allNotifications[0] === thisNotification) {
8279             const anchor = {
8280               ...sharedBackstage.anchors.banner(),
8281               overrides: anchorOverrides
8282             };
8283             InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor }, getBounds);
8284           } else {
8285             indexOf(allNotifications, thisNotification).each(idx => {
8286               const previousNotification = allNotifications[idx - 1].getEl();
8287               const nodeAnchor = {
8288                 type: 'node',
8289                 root: body(),
8290                 node: Optional.some(SugarElement.fromDom(previousNotification)),
8291                 overrides: anchorOverrides,
8292                 layouts: {
8293                   onRtl: () => [south$2],
8294                   onLtr: () => [south$2]
8295                 }
8296               };
8297               InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor: nodeAnchor }, getBounds);
8298             });
8299           }
8300         };
8301         const thisNotification = {
8302           close,
8303           reposition,
8304           text: nuText => {
8305             Notification.updateText(notification, nuText);
8306           },
8307           settings,
8308           getEl: () => notification.element.dom,
8309           progressBar: {
8310             value: percent => {
8311               Notification.updateProgress(notification, percent);
8312             }
8313           }
8314         };
8315         return thisNotification;
8316       };
8317       const close = notification => {
8318         notification.close();
8319       };
8320       const getArgs = notification => {
8321         return notification.settings;
8322       };
8323       return {
8324         open,
8325         close,
8326         getArgs
8327       };
8328     };
8330     var global$7 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
8332     var global$6 = tinymce.util.Tools.resolve('tinymce.EditorManager');
8334     var global$5 = tinymce.util.Tools.resolve('tinymce.Env');
8336     var ToolbarMode$1;
8337     (function (ToolbarMode) {
8338       ToolbarMode['default'] = 'wrap';
8339       ToolbarMode['floating'] = 'floating';
8340       ToolbarMode['sliding'] = 'sliding';
8341       ToolbarMode['scrolling'] = 'scrolling';
8342     }(ToolbarMode$1 || (ToolbarMode$1 = {})));
8343     var ToolbarLocation$1;
8344     (function (ToolbarLocation) {
8345       ToolbarLocation['auto'] = 'auto';
8346       ToolbarLocation['top'] = 'top';
8347       ToolbarLocation['bottom'] = 'bottom';
8348     }(ToolbarLocation$1 || (ToolbarLocation$1 = {})));
8349     const option$2 = name => editor => editor.options.get(name);
8350     const wrapOptional = fn => editor => Optional.from(fn(editor));
8351     const register$e = editor => {
8352       const isPhone = global$5.deviceType.isPhone();
8353       const isMobile = global$5.deviceType.isTablet() || isPhone;
8354       const registerOption = editor.options.register;
8355       const stringOrFalseProcessor = value => isString(value) || value === false;
8356       const stringOrNumberProcessor = value => isString(value) || isNumber(value);
8357       registerOption('skin', {
8358         processor: value => isString(value) || value === false,
8359         default: 'oxide'
8360       });
8361       registerOption('skin_url', { processor: 'string' });
8362       registerOption('height', {
8363         processor: stringOrNumberProcessor,
8364         default: Math.max(editor.getElement().offsetHeight, 400)
8365       });
8366       registerOption('width', {
8367         processor: stringOrNumberProcessor,
8368         default: global$7.DOM.getStyle(editor.getElement(), 'width')
8369       });
8370       registerOption('min_height', {
8371         processor: 'number',
8372         default: 100
8373       });
8374       registerOption('min_width', { processor: 'number' });
8375       registerOption('max_height', { processor: 'number' });
8376       registerOption('max_width', { processor: 'number' });
8377       registerOption('style_formats', { processor: 'object[]' });
8378       registerOption('style_formats_merge', {
8379         processor: 'boolean',
8380         default: false
8381       });
8382       registerOption('style_formats_autohide', {
8383         processor: 'boolean',
8384         default: false
8385       });
8386       registerOption('line_height_formats', {
8387         processor: 'string',
8388         default: '1 1.1 1.2 1.3 1.4 1.5 2'
8389       });
8390       registerOption('font_family_formats', {
8391         processor: 'string',
8392         default: 'Andale Mono=andale mono,monospace;' + 'Arial=arial,helvetica,sans-serif;' + 'Arial Black=arial black,sans-serif;' + 'Book Antiqua=book antiqua,palatino,serif;' + 'Comic Sans MS=comic sans ms,sans-serif;' + 'Courier New=courier new,courier,monospace;' + 'Georgia=georgia,palatino,serif;' + 'Helvetica=helvetica,arial,sans-serif;' + 'Impact=impact,sans-serif;' + 'Symbol=symbol;' + 'Tahoma=tahoma,arial,helvetica,sans-serif;' + 'Terminal=terminal,monaco,monospace;' + 'Times New Roman=times new roman,times,serif;' + 'Trebuchet MS=trebuchet ms,geneva,sans-serif;' + 'Verdana=verdana,geneva,sans-serif;' + 'Webdings=webdings;' + 'Wingdings=wingdings,zapf dingbats'
8393       });
8394       registerOption('font_size_formats', {
8395         processor: 'string',
8396         default: '8pt 10pt 12pt 14pt 18pt 24pt 36pt'
8397       });
8398       registerOption('block_formats', {
8399         processor: 'string',
8400         default: 'Paragraph=p;' + 'Heading 1=h1;' + 'Heading 2=h2;' + 'Heading 3=h3;' + 'Heading 4=h4;' + 'Heading 5=h5;' + 'Heading 6=h6;' + 'Preformatted=pre'
8401       });
8402       registerOption('content_langs', { processor: 'object[]' });
8403       registerOption('removed_menuitems', {
8404         processor: 'string',
8405         default: ''
8406       });
8407       registerOption('menubar', {
8408         processor: value => isString(value) || isBoolean(value),
8409         default: !isPhone
8410       });
8411       registerOption('menu', {
8412         processor: 'object',
8413         default: {}
8414       });
8415       registerOption('toolbar', {
8416         processor: value => {
8417           if (isBoolean(value) || isString(value) || isArray(value)) {
8418             return {
8419               value,
8420               valid: true
8421             };
8422           } else {
8423             return {
8424               valid: false,
8425               message: 'Must be a boolean, string or array.'
8426             };
8427           }
8428         },
8429         default: true
8430       });
8431       range$2(9, num => {
8432         registerOption('toolbar' + (num + 1), { processor: 'string' });
8433       });
8434       registerOption('toolbar_mode', {
8435         processor: 'string',
8436         default: isMobile ? 'scrolling' : 'floating'
8437       });
8438       registerOption('toolbar_groups', {
8439         processor: 'object',
8440         default: {}
8441       });
8442       registerOption('toolbar_location', {
8443         processor: 'string',
8444         default: ToolbarLocation$1.auto
8445       });
8446       registerOption('toolbar_persist', {
8447         processor: 'boolean',
8448         default: false
8449       });
8450       registerOption('toolbar_sticky', {
8451         processor: 'boolean',
8452         default: editor.inline
8453       });
8454       registerOption('toolbar_sticky_offset', {
8455         processor: 'number',
8456         default: 0
8457       });
8458       registerOption('fixed_toolbar_container', {
8459         processor: 'string',
8460         default: ''
8461       });
8462       registerOption('fixed_toolbar_container_target', { processor: 'object' });
8463       registerOption('file_picker_callback', { processor: 'function' });
8464       registerOption('file_picker_validator_handler', { processor: 'function' });
8465       registerOption('file_picker_types', { processor: 'string' });
8466       registerOption('typeahead_urls', {
8467         processor: 'boolean',
8468         default: true
8469       });
8470       registerOption('anchor_top', {
8471         processor: stringOrFalseProcessor,
8472         default: '#top'
8473       });
8474       registerOption('anchor_bottom', {
8475         processor: stringOrFalseProcessor,
8476         default: '#bottom'
8477       });
8478       registerOption('draggable_modal', {
8479         processor: 'boolean',
8480         default: false
8481       });
8482       registerOption('statusbar', {
8483         processor: 'boolean',
8484         default: true
8485       });
8486       registerOption('elementpath', {
8487         processor: 'boolean',
8488         default: true
8489       });
8490       registerOption('branding', {
8491         processor: 'boolean',
8492         default: true
8493       });
8494       registerOption('promotion', {
8495         processor: 'boolean',
8496         default: true
8497       });
8498       registerOption('resize', {
8499         processor: value => value === 'both' || isBoolean(value),
8500         default: !global$5.deviceType.isTouch()
8501       });
8502       registerOption('sidebar_show', { processor: 'string' });
8503     };
8504     const isReadOnly = option$2('readonly');
8505     const getHeightOption = option$2('height');
8506     const getWidthOption = option$2('width');
8507     const getMinWidthOption = wrapOptional(option$2('min_width'));
8508     const getMinHeightOption = wrapOptional(option$2('min_height'));
8509     const getMaxWidthOption = wrapOptional(option$2('max_width'));
8510     const getMaxHeightOption = wrapOptional(option$2('max_height'));
8511     const getUserStyleFormats = wrapOptional(option$2('style_formats'));
8512     const shouldMergeStyleFormats = option$2('style_formats_merge');
8513     const shouldAutoHideStyleFormats = option$2('style_formats_autohide');
8514     const getContentLanguages = option$2('content_langs');
8515     const getRemovedMenuItems = option$2('removed_menuitems');
8516     const getToolbarMode = option$2('toolbar_mode');
8517     const getToolbarGroups = option$2('toolbar_groups');
8518     const getToolbarLocation = option$2('toolbar_location');
8519     const fixedContainerSelector = option$2('fixed_toolbar_container');
8520     const fixedToolbarContainerTarget = option$2('fixed_toolbar_container_target');
8521     const isToolbarPersist = option$2('toolbar_persist');
8522     const getStickyToolbarOffset = option$2('toolbar_sticky_offset');
8523     const getMenubar = option$2('menubar');
8524     const getToolbar = option$2('toolbar');
8525     const getFilePickerCallback = option$2('file_picker_callback');
8526     const getFilePickerValidatorHandler = option$2('file_picker_validator_handler');
8527     const getFilePickerTypes = option$2('file_picker_types');
8528     const useTypeaheadUrls = option$2('typeahead_urls');
8529     const getAnchorTop = option$2('anchor_top');
8530     const getAnchorBottom = option$2('anchor_bottom');
8531     const isDraggableModal$1 = option$2('draggable_modal');
8532     const useStatusBar = option$2('statusbar');
8533     const useElementPath = option$2('elementpath');
8534     const useBranding = option$2('branding');
8535     const getResize = option$2('resize');
8536     const getPasteAsText = option$2('paste_as_text');
8537     const getSidebarShow = option$2('sidebar_show');
8538     const promotionEnabled = option$2('promotion');
8539     const isSkinDisabled = editor => editor.options.get('skin') === false;
8540     const isMenubarEnabled = editor => editor.options.get('menubar') !== false;
8541     const getSkinUrl = editor => {
8542       const skinUrl = editor.options.get('skin_url');
8543       if (isSkinDisabled(editor)) {
8544         return skinUrl;
8545       } else {
8546         if (skinUrl) {
8547           return editor.documentBaseURI.toAbsolute(skinUrl);
8548         } else {
8549           const skin = editor.options.get('skin');
8550           return global$6.baseURL + '/skins/ui/' + skin;
8551         }
8552       }
8553     };
8554     const getLineHeightFormats = editor => editor.options.get('line_height_formats').split(' ');
8555     const isToolbarEnabled = editor => {
8556       const toolbar = getToolbar(editor);
8557       const isToolbarString = isString(toolbar);
8558       const isToolbarObjectArray = isArray(toolbar) && toolbar.length > 0;
8559       return !isMultipleToolbars(editor) && (isToolbarObjectArray || isToolbarString || toolbar === true);
8560     };
8561     const getMultipleToolbarsOption = editor => {
8562       const toolbars = range$2(9, num => editor.options.get('toolbar' + (num + 1)));
8563       const toolbarArray = filter$2(toolbars, isString);
8564       return someIf(toolbarArray.length > 0, toolbarArray);
8565     };
8566     const isMultipleToolbars = editor => getMultipleToolbarsOption(editor).fold(() => {
8567       const toolbar = getToolbar(editor);
8568       return isArrayOf(toolbar, isString) && toolbar.length > 0;
8569     }, always);
8570     const isToolbarLocationBottom = editor => getToolbarLocation(editor) === ToolbarLocation$1.bottom;
8571     const fixedContainerTarget = editor => {
8572       if (!editor.inline) {
8573         return Optional.none();
8574       }
8575       const selector = fixedContainerSelector(editor) ?? '';
8576       if (selector.length > 0) {
8577         return descendant(body(), selector);
8578       }
8579       const element = fixedToolbarContainerTarget(editor);
8580       if (isNonNullable(element)) {
8581         return Optional.some(SugarElement.fromDom(element));
8582       }
8583       return Optional.none();
8584     };
8585     const useFixedContainer = editor => editor.inline && fixedContainerTarget(editor).isSome();
8586     const getUiContainer = editor => {
8587       const fixedContainer = fixedContainerTarget(editor);
8588       return fixedContainer.getOrThunk(() => getContentContainer(getRootNode(SugarElement.fromDom(editor.getElement()))));
8589     };
8590     const isDistractionFree = editor => editor.inline && !isMenubarEnabled(editor) && !isToolbarEnabled(editor) && !isMultipleToolbars(editor);
8591     const isStickyToolbar = editor => {
8592       const isStickyToolbar = editor.options.get('toolbar_sticky');
8593       return (isStickyToolbar || editor.inline) && !useFixedContainer(editor) && !isDistractionFree(editor);
8594     };
8595     const getMenus = editor => {
8596       const menu = editor.options.get('menu');
8597       return map$1(menu, menu => ({
8598         ...menu,
8599         items: menu.items
8600       }));
8601     };
8603     var Options = /*#__PURE__*/Object.freeze({
8604         __proto__: null,
8605         get ToolbarMode () { return ToolbarMode$1; },
8606         get ToolbarLocation () { return ToolbarLocation$1; },
8607         register: register$e,
8608         getSkinUrl: getSkinUrl,
8609         isReadOnly: isReadOnly,
8610         isSkinDisabled: isSkinDisabled,
8611         getHeightOption: getHeightOption,
8612         getWidthOption: getWidthOption,
8613         getMinWidthOption: getMinWidthOption,
8614         getMinHeightOption: getMinHeightOption,
8615         getMaxWidthOption: getMaxWidthOption,
8616         getMaxHeightOption: getMaxHeightOption,
8617         getUserStyleFormats: getUserStyleFormats,
8618         shouldMergeStyleFormats: shouldMergeStyleFormats,
8619         shouldAutoHideStyleFormats: shouldAutoHideStyleFormats,
8620         getLineHeightFormats: getLineHeightFormats,
8621         getContentLanguages: getContentLanguages,
8622         getRemovedMenuItems: getRemovedMenuItems,
8623         isMenubarEnabled: isMenubarEnabled,
8624         isMultipleToolbars: isMultipleToolbars,
8625         isToolbarEnabled: isToolbarEnabled,
8626         isToolbarPersist: isToolbarPersist,
8627         getMultipleToolbarsOption: getMultipleToolbarsOption,
8628         getUiContainer: getUiContainer,
8629         useFixedContainer: useFixedContainer,
8630         getToolbarMode: getToolbarMode,
8631         isDraggableModal: isDraggableModal$1,
8632         isDistractionFree: isDistractionFree,
8633         isStickyToolbar: isStickyToolbar,
8634         getStickyToolbarOffset: getStickyToolbarOffset,
8635         getToolbarLocation: getToolbarLocation,
8636         isToolbarLocationBottom: isToolbarLocationBottom,
8637         getToolbarGroups: getToolbarGroups,
8638         getMenus: getMenus,
8639         getMenubar: getMenubar,
8640         getToolbar: getToolbar,
8641         getFilePickerCallback: getFilePickerCallback,
8642         getFilePickerTypes: getFilePickerTypes,
8643         useTypeaheadUrls: useTypeaheadUrls,
8644         getAnchorTop: getAnchorTop,
8645         getAnchorBottom: getAnchorBottom,
8646         getFilePickerValidatorHandler: getFilePickerValidatorHandler,
8647         useStatusBar: useStatusBar,
8648         useElementPath: useElementPath,
8649         promotionEnabled: promotionEnabled,
8650         useBranding: useBranding,
8651         getResize: getResize,
8652         getPasteAsText: getPasteAsText,
8653         getSidebarShow: getSidebarShow
8654     });
8656     const autocompleteSelector = '[data-mce-autocompleter]';
8657     const detect = elm => closest$1(elm, autocompleteSelector);
8658     const findIn = elm => descendant(elm, autocompleteSelector);
8660     const setup$e = (api, editor) => {
8661       const redirectKeyToItem = (item, e) => {
8662         emitWith(item, keydown(), { raw: e });
8663       };
8664       const getItem = () => api.getMenu().bind(Highlighting.getHighlighted);
8665       editor.on('keydown', e => {
8666         const keyCode = e.which;
8667         if (!api.isActive()) {
8668           return;
8669         }
8670         if (api.isMenuOpen()) {
8671           if (keyCode === 13) {
8672             getItem().each(emitExecute);
8673             e.preventDefault();
8674           } else if (keyCode === 40) {
8675             getItem().fold(() => {
8676               api.getMenu().each(Highlighting.highlightFirst);
8677             }, item => {
8678               redirectKeyToItem(item, e);
8679             });
8680             e.preventDefault();
8681             e.stopImmediatePropagation();
8682           } else if (keyCode === 37 || keyCode === 38 || keyCode === 39) {
8683             getItem().each(item => {
8684               redirectKeyToItem(item, e);
8685               e.preventDefault();
8686               e.stopImmediatePropagation();
8687             });
8688           }
8689         } else {
8690           if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
8691             api.cancelIfNecessary();
8692           }
8693         }
8694       });
8695       editor.on('NodeChange', e => {
8696         if (api.isActive() && !api.isProcessingAction() && detect(SugarElement.fromDom(e.element)).isNone()) {
8697           api.cancelIfNecessary();
8698         }
8699       });
8700     };
8701     const AutocompleterEditorEvents = { setup: setup$e };
8703     var ItemResponse;
8704     (function (ItemResponse) {
8705       ItemResponse[ItemResponse['CLOSE_ON_EXECUTE'] = 0] = 'CLOSE_ON_EXECUTE';
8706       ItemResponse[ItemResponse['BUBBLE_TO_SANDBOX'] = 1] = 'BUBBLE_TO_SANDBOX';
8707     }(ItemResponse || (ItemResponse = {})));
8708     var ItemResponse$1 = ItemResponse;
8710     const navClass = 'tox-menu-nav__js';
8711     const selectableClass = 'tox-collection__item';
8712     const colorClass = 'tox-swatch';
8713     const presetClasses = {
8714       normal: navClass,
8715       color: colorClass
8716     };
8717     const tickedClass = 'tox-collection__item--enabled';
8718     const groupHeadingClass = 'tox-collection__group-heading';
8719     const iconClass = 'tox-collection__item-icon';
8720     const textClass = 'tox-collection__item-label';
8721     const accessoryClass = 'tox-collection__item-accessory';
8722     const caretClass = 'tox-collection__item-caret';
8723     const checkmarkClass = 'tox-collection__item-checkmark';
8724     const activeClass = 'tox-collection__item--active';
8725     const containerClass = 'tox-collection__item-container';
8726     const containerColumnClass = 'tox-collection__item-container--column';
8727     const containerRowClass = 'tox-collection__item-container--row';
8728     const containerAlignRightClass = 'tox-collection__item-container--align-right';
8729     const containerAlignLeftClass = 'tox-collection__item-container--align-left';
8730     const containerValignTopClass = 'tox-collection__item-container--valign-top';
8731     const containerValignMiddleClass = 'tox-collection__item-container--valign-middle';
8732     const containerValignBottomClass = 'tox-collection__item-container--valign-bottom';
8733     const classForPreset = presets => get$g(presetClasses, presets).getOr(navClass);
8735     const forMenu = presets => {
8736       if (presets === 'color') {
8737         return 'tox-swatches';
8738       } else {
8739         return 'tox-menu';
8740       }
8741     };
8742     const classes = presets => ({
8743       backgroundMenu: 'tox-background-menu',
8744       selectedMenu: 'tox-selected-menu',
8745       selectedItem: 'tox-collection__item--active',
8746       hasIcons: 'tox-menu--has-icons',
8747       menu: forMenu(presets),
8748       tieredMenu: 'tox-tiered-menu'
8749     });
8751     const markers = presets => {
8752       const menuClasses = classes(presets);
8753       return {
8754         backgroundMenu: menuClasses.backgroundMenu,
8755         selectedMenu: menuClasses.selectedMenu,
8756         menu: menuClasses.menu,
8757         selectedItem: menuClasses.selectedItem,
8758         item: classForPreset(presets)
8759       };
8760     };
8761     const dom$1 = (hasIcons, columns, presets) => {
8762       const menuClasses = classes(presets);
8763       return {
8764         tag: 'div',
8765         classes: flatten([
8766           [
8767             menuClasses.menu,
8768             `tox-menu-${ columns }-column`
8769           ],
8770           hasIcons ? [menuClasses.hasIcons] : []
8771         ])
8772       };
8773     };
8774     const components = [Menu.parts.items({})];
8775     const part = (hasIcons, columns, presets) => {
8776       const menuClasses = classes(presets);
8777       const d = {
8778         tag: 'div',
8779         classes: flatten([[menuClasses.tieredMenu]])
8780       };
8781       return {
8782         dom: d,
8783         markers: markers(presets)
8784       };
8785     };
8787     const schema$l = constant$1([
8788       option$3('data'),
8789       defaulted('inputAttributes', {}),
8790       defaulted('inputStyles', {}),
8791       defaulted('tag', 'input'),
8792       defaulted('inputClasses', []),
8793       onHandler('onSetValue'),
8794       defaulted('styles', {}),
8795       defaulted('eventOrder', {}),
8796       field('inputBehaviours', [
8797         Representing,
8798         Focusing
8799       ]),
8800       defaulted('selectOnFocus', true)
8801     ]);
8802     const focusBehaviours = detail => derive$1([Focusing.config({
8803         onFocus: !detail.selectOnFocus ? noop : component => {
8804           const input = component.element;
8805           const value = get$6(input);
8806           input.dom.setSelectionRange(0, value.length);
8807         }
8808       })]);
8809     const behaviours = detail => ({
8810       ...focusBehaviours(detail),
8811       ...augment(detail.inputBehaviours, [Representing.config({
8812           store: {
8813             mode: 'manual',
8814             ...detail.data.map(data => ({ initialValue: data })).getOr({}),
8815             getValue: input => {
8816               return get$6(input.element);
8817             },
8818             setValue: (input, data) => {
8819               const current = get$6(input.element);
8820               if (current !== data) {
8821                 set$5(input.element, data);
8822               }
8823             }
8824           },
8825           onSetValue: detail.onSetValue
8826         })])
8827     });
8828     const dom = detail => ({
8829       tag: detail.tag,
8830       attributes: {
8831         type: 'text',
8832         ...detail.inputAttributes
8833       },
8834       styles: detail.inputStyles,
8835       classes: detail.inputClasses
8836     });
8838     const factory$j = (detail, _spec) => ({
8839       uid: detail.uid,
8840       dom: dom(detail),
8841       components: [],
8842       behaviours: behaviours(detail),
8843       eventOrder: detail.eventOrder
8844     });
8845     const Input = single({
8846       name: 'Input',
8847       configFields: schema$l(),
8848       factory: factory$j
8849     });
8851     const refetchTriggerEvent = generate$6('refetch-trigger-event');
8852     const redirectMenuItemInteractionEvent = generate$6('redirect-menu-item-interaction');
8854     const menuSearcherClass = 'tox-menu__searcher';
8855     const findWithinSandbox = sandboxComp => {
8856       return descendant(sandboxComp.element, `.${ menuSearcherClass }`).bind(inputElem => sandboxComp.getSystem().getByDom(inputElem).toOptional());
8857     };
8858     const findWithinMenu = findWithinSandbox;
8859     const restoreState = (inputComp, searcherState) => {
8860       Representing.setValue(inputComp, searcherState.fetchPattern);
8861       inputComp.element.dom.selectionStart = searcherState.selectionStart;
8862       inputComp.element.dom.selectionEnd = searcherState.selectionEnd;
8863     };
8864     const saveState = inputComp => {
8865       const fetchPattern = Representing.getValue(inputComp);
8866       const selectionStart = inputComp.element.dom.selectionStart;
8867       const selectionEnd = inputComp.element.dom.selectionEnd;
8868       return {
8869         fetchPattern,
8870         selectionStart,
8871         selectionEnd
8872       };
8873     };
8874     const setActiveDescendant = (inputComp, active) => {
8875       getOpt(active.element, 'id').each(id => set$9(inputComp.element, 'aria-activedescendant', id));
8876     };
8877     const renderMenuSearcher = spec => {
8878       const handleByBrowser = (comp, se) => {
8879         se.cut();
8880         return Optional.none();
8881       };
8882       const handleByHighlightedItem = (comp, se) => {
8883         const eventData = {
8884           interactionEvent: se.event,
8885           eventType: se.event.raw.type
8886         };
8887         emitWith(comp, redirectMenuItemInteractionEvent, eventData);
8888         return Optional.some(true);
8889       };
8890       const customSearcherEventsName = 'searcher-events';
8891       return {
8892         dom: {
8893           tag: 'div',
8894           classes: [selectableClass]
8895         },
8896         components: [Input.sketch({
8897             inputClasses: [
8898               menuSearcherClass,
8899               'tox-textfield'
8900             ],
8901             inputAttributes: {
8902               ...spec.placeholder.map(placeholder => ({ placeholder: spec.i18n(placeholder) })).getOr({}),
8903               'type': 'search',
8904               'aria-autocomplete': 'list'
8905             },
8906             inputBehaviours: derive$1([
8907               config(customSearcherEventsName, [
8908                 run$1(input(), inputComp => {
8909                   emit(inputComp, refetchTriggerEvent);
8910                 }),
8911                 run$1(keydown(), (inputComp, se) => {
8912                   if (se.event.raw.key === 'Escape') {
8913                     se.stop();
8914                   }
8915                 })
8916               ]),
8917               Keying.config({
8918                 mode: 'special',
8919                 onLeft: handleByBrowser,
8920                 onRight: handleByBrowser,
8921                 onSpace: handleByBrowser,
8922                 onEnter: handleByHighlightedItem,
8923                 onEscape: handleByHighlightedItem,
8924                 onUp: handleByHighlightedItem,
8925                 onDown: handleByHighlightedItem
8926               })
8927             ]),
8928             eventOrder: {
8929               keydown: [
8930                 customSearcherEventsName,
8931                 Keying.name()
8932               ]
8933             }
8934           })]
8935       };
8936     };
8938     const searchResultsClass = 'tox-collection--results__js';
8939     const augmentWithAria = item => {
8940       if (item.dom) {
8941         return {
8942           ...item,
8943           dom: {
8944             ...item.dom,
8945             attributes: {
8946               ...item.dom.attributes ?? {},
8947               'id': generate$6('aria-item-search-result-id'),
8948               'aria-selected': 'false'
8949             }
8950           }
8951         };
8952       } else {
8953         return item;
8954       }
8955     };
8957     const chunk = (rowDom, numColumns) => items => {
8958       const chunks = chunk$1(items, numColumns);
8959       return map$2(chunks, c => ({
8960         dom: rowDom,
8961         components: c
8962       }));
8963     };
8964     const forSwatch = columns => ({
8965       dom: {
8966         tag: 'div',
8967         classes: [
8968           'tox-menu',
8969           'tox-swatches-menu'
8970         ]
8971       },
8972       components: [{
8973           dom: {
8974             tag: 'div',
8975             classes: ['tox-swatches']
8976           },
8977           components: [Menu.parts.items({
8978               preprocess: columns !== 'auto' ? chunk({
8979                 tag: 'div',
8980                 classes: ['tox-swatches__row']
8981               }, columns) : identity
8982             })]
8983         }]
8984     });
8985     const forToolbar = columns => ({
8986       dom: {
8987         tag: 'div',
8988         classes: [
8989           'tox-menu',
8990           'tox-collection',
8991           'tox-collection--toolbar',
8992           'tox-collection--toolbar-lg'
8993         ]
8994       },
8995       components: [Menu.parts.items({
8996           preprocess: chunk({
8997             tag: 'div',
8998             classes: ['tox-collection__group']
8999           }, columns)
9000         })]
9001     });
9002     const preprocessCollection = (items, isSeparator) => {
9003       const allSplits = [];
9004       let currentSplit = [];
9005       each$1(items, (item, i) => {
9006         if (isSeparator(item, i)) {
9007           if (currentSplit.length > 0) {
9008             allSplits.push(currentSplit);
9009           }
9010           currentSplit = [];
9011           if (has$2(item.dom, 'innerHtml') || item.components && item.components.length > 0) {
9012             currentSplit.push(item);
9013           }
9014         } else {
9015           currentSplit.push(item);
9016         }
9017       });
9018       if (currentSplit.length > 0) {
9019         allSplits.push(currentSplit);
9020       }
9021       return map$2(allSplits, s => ({
9022         dom: {
9023           tag: 'div',
9024           classes: ['tox-collection__group']
9025         },
9026         components: s
9027       }));
9028     };
9029     const insertItemsPlaceholder = (columns, initItems, onItem) => {
9030       return Menu.parts.items({
9031         preprocess: rawItems => {
9032           const enrichedItems = map$2(rawItems, onItem);
9033           if (columns !== 'auto' && columns > 1) {
9034             return chunk({
9035               tag: 'div',
9036               classes: ['tox-collection__group']
9037             }, columns)(enrichedItems);
9038           } else {
9039             return preprocessCollection(enrichedItems, (_item, i) => initItems[i].type === 'separator');
9040           }
9041         }
9042       });
9043     };
9044     const forCollection = (columns, initItems, _hasIcons = true) => ({
9045       dom: {
9046         tag: 'div',
9047         classes: [
9048           'tox-menu',
9049           'tox-collection'
9050         ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
9051       },
9052       components: [insertItemsPlaceholder(columns, initItems, identity)]
9053     });
9054     const forCollectionWithSearchResults = (columns, initItems, _hasIcons = true) => {
9055       const ariaControlsSearchResults = generate$6('aria-controls-search-results');
9056       return {
9057         dom: {
9058           tag: 'div',
9059           classes: [
9060             'tox-menu',
9061             'tox-collection',
9062             searchResultsClass
9063           ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid']),
9064           attributes: { id: ariaControlsSearchResults }
9065         },
9066         components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
9067       };
9068     };
9069     const forCollectionWithSearchField = (columns, initItems, searchField) => {
9070       const ariaControlsSearchResults = generate$6('aria-controls-search-results');
9071       return {
9072         dom: {
9073           tag: 'div',
9074           classes: [
9075             'tox-menu',
9076             'tox-collection'
9077           ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
9078         },
9079         components: [
9080           renderMenuSearcher({
9081             i18n: global$8.translate,
9082             placeholder: searchField.placeholder
9083           }),
9084           {
9085             dom: {
9086               tag: 'div',
9087               classes: [
9088                 ...columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'],
9089                 searchResultsClass
9090               ],
9091               attributes: { id: ariaControlsSearchResults }
9092             },
9093             components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
9094           }
9095         ]
9096       };
9097     };
9098     const forHorizontalCollection = (initItems, _hasIcons = true) => ({
9099       dom: {
9100         tag: 'div',
9101         classes: [
9102           'tox-collection',
9103           'tox-collection--horizontal'
9104         ]
9105       },
9106       components: [Menu.parts.items({ preprocess: items => preprocessCollection(items, (_item, i) => initItems[i].type === 'separator') })]
9107     });
9109     const menuHasIcons = xs => exists(xs, item => 'icon' in item && item.icon !== undefined);
9110     const handleError = error => {
9111       console.error(formatError(error));
9112       console.log(error);
9113       return Optional.none();
9114     };
9115     const createHorizontalPartialMenuWithAlloyItems = (value, _hasIcons, items, _columns, _menuLayout) => {
9116       const structure = forHorizontalCollection(items);
9117       return {
9118         value,
9119         dom: structure.dom,
9120         components: structure.components,
9121         items
9122       };
9123     };
9124     const createPartialMenuWithAlloyItems = (value, hasIcons, items, columns, menuLayout) => {
9125       const getNormalStructure = () => {
9126         if (menuLayout.menuType !== 'searchable') {
9127           return forCollection(columns, items);
9128         } else {
9129           return menuLayout.searchMode.searchMode === 'search-with-field' ? forCollectionWithSearchField(columns, items, menuLayout.searchMode) : forCollectionWithSearchResults(columns, items);
9130         }
9131       };
9132       if (menuLayout.menuType === 'color') {
9133         const structure = forSwatch(columns);
9134         return {
9135           value,
9136           dom: structure.dom,
9137           components: structure.components,
9138           items
9139         };
9140       } else if (menuLayout.menuType === 'normal' && columns === 'auto') {
9141         const structure = forCollection(columns, items);
9142         return {
9143           value,
9144           dom: structure.dom,
9145           components: structure.components,
9146           items
9147         };
9148       } else if (menuLayout.menuType === 'normal' || menuLayout.menuType === 'searchable') {
9149         const structure = getNormalStructure();
9150         return {
9151           value,
9152           dom: structure.dom,
9153           components: structure.components,
9154           items
9155         };
9156       } else if (menuLayout.menuType === 'listpreview' && columns !== 'auto') {
9157         const structure = forToolbar(columns);
9158         return {
9159           value,
9160           dom: structure.dom,
9161           components: structure.components,
9162           items
9163         };
9164       } else {
9165         return {
9166           value,
9167           dom: dom$1(hasIcons, columns, menuLayout.menuType),
9168           components: components,
9169           items
9170         };
9171       }
9172     };
9174     const type = requiredString('type');
9175     const name$1 = requiredString('name');
9176     const label = requiredString('label');
9177     const text$1 = requiredString('text');
9178     const title = requiredString('title');
9179     const icon = requiredString('icon');
9180     const value$1 = requiredString('value');
9181     const fetch$1 = requiredFunction('fetch');
9182     const getSubmenuItems = requiredFunction('getSubmenuItems');
9183     const onAction = requiredFunction('onAction');
9184     const onItemAction = requiredFunction('onItemAction');
9185     const onSetup = defaultedFunction('onSetup', () => noop);
9186     const optionalName = optionString('name');
9187     const optionalText = optionString('text');
9188     const optionalIcon = optionString('icon');
9189     const optionalTooltip = optionString('tooltip');
9190     const optionalLabel = optionString('label');
9191     const optionalShortcut = optionString('shortcut');
9192     const optionalSelect = optionFunction('select');
9193     const active = defaultedBoolean('active', false);
9194     const borderless = defaultedBoolean('borderless', false);
9195     const enabled = defaultedBoolean('enabled', true);
9196     const primary = defaultedBoolean('primary', false);
9197     const defaultedColumns = num => defaulted('columns', num);
9198     const defaultedMeta = defaulted('meta', {});
9199     const defaultedOnAction = defaultedFunction('onAction', noop);
9200     const defaultedType = type => defaultedString('type', type);
9201     const generatedName = namePrefix => field$1('name', 'name', defaultedThunk(() => generate$6(`${ namePrefix }-name`)), string);
9202     const generatedValue = valuePrefix => field$1('value', 'value', defaultedThunk(() => generate$6(`${ valuePrefix }-value`)), anyValue());
9204     const separatorMenuItemSchema = objOf([
9205       type,
9206       optionalText
9207     ]);
9208     const createSeparatorMenuItem = spec => asRaw('separatormenuitem', separatorMenuItemSchema, spec);
9210     const autocompleterItemSchema = objOf([
9211       defaultedType('autocompleteitem'),
9212       active,
9213       enabled,
9214       defaultedMeta,
9215       value$1,
9216       optionalText,
9217       optionalIcon
9218     ]);
9219     const createSeparatorItem = spec => asRaw('Autocompleter.Separator', separatorMenuItemSchema, spec);
9220     const createAutocompleterItem = spec => asRaw('Autocompleter.Item', autocompleterItemSchema, spec);
9222     const baseToolbarButtonFields = [
9223       enabled,
9224       optionalTooltip,
9225       optionalIcon,
9226       optionalText,
9227       onSetup
9228     ];
9229     const toolbarButtonSchema = objOf([
9230       type,
9231       onAction
9232     ].concat(baseToolbarButtonFields));
9233     const createToolbarButton = spec => asRaw('toolbarbutton', toolbarButtonSchema, spec);
9235     const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
9236     const toggleButtonSchema = objOf(baseToolbarToggleButtonFields.concat([
9237       type,
9238       onAction
9239     ]));
9240     const createToggleButton = spec => asRaw('ToggleButton', toggleButtonSchema, spec);
9242     const contextBarFields = [
9243       defaultedFunction('predicate', never),
9244       defaultedStringEnum('scope', 'node', [
9245         'node',
9246         'editor'
9247       ]),
9248       defaultedStringEnum('position', 'selection', [
9249         'node',
9250         'selection',
9251         'line'
9252       ])
9253     ];
9255     const contextButtonFields = baseToolbarButtonFields.concat([
9256       defaultedType('contextformbutton'),
9257       primary,
9258       onAction,
9259       customField('original', identity)
9260     ]);
9261     const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
9262       defaultedType('contextformbutton'),
9263       primary,
9264       onAction,
9265       customField('original', identity)
9266     ]);
9267     const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
9268     const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
9269     const toggleOrNormal = choose$1('type', {
9270       contextformbutton: contextButtonFields,
9271       contextformtogglebutton: contextToggleButtonFields
9272     });
9273     const contextFormSchema = objOf([
9274       defaultedType('contextform'),
9275       defaultedFunction('initValue', constant$1('')),
9276       optionalLabel,
9277       requiredArrayOf('commands', toggleOrNormal),
9278       optionOf('launch', choose$1('type', {
9279         contextformbutton: launchButtonFields,
9280         contextformtogglebutton: launchToggleButtonFields
9281       }))
9282     ].concat(contextBarFields));
9283     const createContextForm = spec => asRaw('ContextForm', contextFormSchema, spec);
9285     const contextToolbarSchema = objOf([
9286       defaultedType('contexttoolbar'),
9287       requiredString('items')
9288     ].concat(contextBarFields));
9289     const createContextToolbar = spec => asRaw('ContextToolbar', contextToolbarSchema, spec);
9291     const cardImageFields = [
9292       type,
9293       requiredString('src'),
9294       optionString('alt'),
9295       defaultedArrayOf('classes', [], string)
9296     ];
9297     const cardImageSchema = objOf(cardImageFields);
9299     const cardTextFields = [
9300       type,
9301       text$1,
9302       optionalName,
9303       defaultedArrayOf('classes', ['tox-collection__item-label'], string)
9304     ];
9305     const cardTextSchema = objOf(cardTextFields);
9307     const itemSchema$1 = valueThunk(() => choose$2('type', {
9308       cardimage: cardImageSchema,
9309       cardtext: cardTextSchema,
9310       cardcontainer: cardContainerSchema
9311     }));
9312     const cardContainerSchema = objOf([
9313       type,
9314       defaultedString('direction', 'horizontal'),
9315       defaultedString('align', 'left'),
9316       defaultedString('valign', 'middle'),
9317       requiredArrayOf('items', itemSchema$1)
9318     ]);
9320     const commonMenuItemFields = [
9321       enabled,
9322       optionalText,
9323       optionalShortcut,
9324       generatedValue('menuitem'),
9325       defaultedMeta
9326     ];
9328     const cardMenuItemSchema = objOf([
9329       type,
9330       optionalLabel,
9331       requiredArrayOf('items', itemSchema$1),
9332       onSetup,
9333       defaultedOnAction
9334     ].concat(commonMenuItemFields));
9335     const createCardMenuItem = spec => asRaw('cardmenuitem', cardMenuItemSchema, spec);
9337     const choiceMenuItemSchema = objOf([
9338       type,
9339       active,
9340       optionalIcon
9341     ].concat(commonMenuItemFields));
9342     const createChoiceMenuItem = spec => asRaw('choicemenuitem', choiceMenuItemSchema, spec);
9344     const baseFields = [
9345       type,
9346       requiredString('fancytype'),
9347       defaultedOnAction
9348     ];
9349     const insertTableFields = [defaulted('initData', {})].concat(baseFields);
9350     const colorSwatchFields = [defaultedObjOf('initData', {}, [
9351         defaultedBoolean('allowCustomColors', true),
9352         optionArrayOf('colors', anyValue())
9353       ])].concat(baseFields);
9354     const fancyMenuItemSchema = choose$1('fancytype', {
9355       inserttable: insertTableFields,
9356       colorswatch: colorSwatchFields
9357     });
9358     const createFancyMenuItem = spec => asRaw('fancymenuitem', fancyMenuItemSchema, spec);
9360     const menuItemSchema = objOf([
9361       type,
9362       onSetup,
9363       defaultedOnAction,
9364       optionalIcon
9365     ].concat(commonMenuItemFields));
9366     const createMenuItem = spec => asRaw('menuitem', menuItemSchema, spec);
9368     const nestedMenuItemSchema = objOf([
9369       type,
9370       getSubmenuItems,
9371       onSetup,
9372       optionalIcon
9373     ].concat(commonMenuItemFields));
9374     const createNestedMenuItem = spec => asRaw('nestedmenuitem', nestedMenuItemSchema, spec);
9376     const toggleMenuItemSchema = objOf([
9377       type,
9378       optionalIcon,
9379       active,
9380       onSetup,
9381       onAction
9382     ].concat(commonMenuItemFields));
9383     const createToggleMenuItem = spec => asRaw('togglemenuitem', toggleMenuItemSchema, spec);
9385     const detectSize = (comp, margin, selectorClass) => {
9386       const descendants$1 = descendants(comp.element, '.' + selectorClass);
9387       if (descendants$1.length > 0) {
9388         const columnLength = findIndex$1(descendants$1, c => {
9389           const thisTop = c.dom.getBoundingClientRect().top;
9390           const cTop = descendants$1[0].dom.getBoundingClientRect().top;
9391           return Math.abs(thisTop - cTop) > margin;
9392         }).getOr(descendants$1.length);
9393         return Optional.some({
9394           numColumns: columnLength,
9395           numRows: Math.ceil(descendants$1.length / columnLength)
9396         });
9397       } else {
9398         return Optional.none();
9399       }
9400     };
9402     const namedEvents = (name, handlers) => derive$1([config(name, handlers)]);
9403     const unnamedEvents = handlers => namedEvents(generate$6('unnamed-events'), handlers);
9404     const SimpleBehaviours = {
9405       namedEvents,
9406       unnamedEvents
9407     };
9409     const ExclusivityChannel = generate$6('tooltip.exclusive');
9410     const ShowTooltipEvent = generate$6('tooltip.show');
9411     const HideTooltipEvent = generate$6('tooltip.hide');
9413     const hideAllExclusive = (component, _tConfig, _tState) => {
9414       component.getSystem().broadcastOn([ExclusivityChannel], {});
9415     };
9416     const setComponents = (component, tConfig, tState, specs) => {
9417       tState.getTooltip().each(tooltip => {
9418         if (tooltip.getSystem().isConnected()) {
9419           Replacing.set(tooltip, specs);
9420         }
9421       });
9422     };
9424     var TooltippingApis = /*#__PURE__*/Object.freeze({
9425         __proto__: null,
9426         hideAllExclusive: hideAllExclusive,
9427         setComponents: setComponents
9428     });
9430     const events$9 = (tooltipConfig, state) => {
9431       const hide = comp => {
9432         state.getTooltip().each(p => {
9433           detach(p);
9434           tooltipConfig.onHide(comp, p);
9435           state.clearTooltip();
9436         });
9437         state.clearTimer();
9438       };
9439       const show = comp => {
9440         if (!state.isShowing()) {
9441           hideAllExclusive(comp);
9442           const sink = tooltipConfig.lazySink(comp).getOrDie();
9443           const popup = comp.getSystem().build({
9444             dom: tooltipConfig.tooltipDom,
9445             components: tooltipConfig.tooltipComponents,
9446             events: derive$2(tooltipConfig.mode === 'normal' ? [
9447               run$1(mouseover(), _ => {
9448                 emit(comp, ShowTooltipEvent);
9449               }),
9450               run$1(mouseout(), _ => {
9451                 emit(comp, HideTooltipEvent);
9452               })
9453             ] : []),
9454             behaviours: derive$1([Replacing.config({})])
9455           });
9456           state.setTooltip(popup);
9457           attach(sink, popup);
9458           tooltipConfig.onShow(comp, popup);
9459           Positioning.position(sink, popup, { anchor: tooltipConfig.anchor(comp) });
9460         }
9461       };
9462       return derive$2(flatten([
9463         [
9464           run$1(ShowTooltipEvent, comp => {
9465             state.resetTimer(() => {
9466               show(comp);
9467             }, tooltipConfig.delay);
9468           }),
9469           run$1(HideTooltipEvent, comp => {
9470             state.resetTimer(() => {
9471               hide(comp);
9472             }, tooltipConfig.delay);
9473           }),
9474           run$1(receive(), (comp, message) => {
9475             const receivingData = message;
9476             if (!receivingData.universal) {
9477               if (contains$2(receivingData.channels, ExclusivityChannel)) {
9478                 hide(comp);
9479               }
9480             }
9481           }),
9482           runOnDetached(comp => {
9483             hide(comp);
9484           })
9485         ],
9486         tooltipConfig.mode === 'normal' ? [
9487           run$1(focusin(), comp => {
9488             emit(comp, ShowTooltipEvent);
9489           }),
9490           run$1(postBlur(), comp => {
9491             emit(comp, HideTooltipEvent);
9492           }),
9493           run$1(mouseover(), comp => {
9494             emit(comp, ShowTooltipEvent);
9495           }),
9496           run$1(mouseout(), comp => {
9497             emit(comp, HideTooltipEvent);
9498           })
9499         ] : [
9500           run$1(highlight$1(), (comp, _se) => {
9501             emit(comp, ShowTooltipEvent);
9502           }),
9503           run$1(dehighlight$1(), comp => {
9504             emit(comp, HideTooltipEvent);
9505           })
9506         ]
9507       ]));
9508     };
9510     var ActiveTooltipping = /*#__PURE__*/Object.freeze({
9511         __proto__: null,
9512         events: events$9
9513     });
9515     var TooltippingSchema = [
9516       required$1('lazySink'),
9517       required$1('tooltipDom'),
9518       defaulted('exclusive', true),
9519       defaulted('tooltipComponents', []),
9520       defaulted('delay', 300),
9521       defaultedStringEnum('mode', 'normal', [
9522         'normal',
9523         'follow-highlight'
9524       ]),
9525       defaulted('anchor', comp => ({
9526         type: 'hotspot',
9527         hotspot: comp,
9528         layouts: {
9529           onLtr: constant$1([
9530             south$2,
9531             north$2,
9532             southeast$2,
9533             northeast$2,
9534             southwest$2,
9535             northwest$2
9536           ]),
9537           onRtl: constant$1([
9538             south$2,
9539             north$2,
9540             southeast$2,
9541             northeast$2,
9542             southwest$2,
9543             northwest$2
9544           ])
9545         }
9546       })),
9547       onHandler('onHide'),
9548       onHandler('onShow')
9549     ];
9551     const init$b = () => {
9552       const timer = value$2();
9553       const popup = value$2();
9554       const clearTimer = () => {
9555         timer.on(clearTimeout);
9556       };
9557       const resetTimer = (f, delay) => {
9558         clearTimer();
9559         timer.set(setTimeout(f, delay));
9560       };
9561       const readState = constant$1('not-implemented');
9562       return nu$8({
9563         getTooltip: popup.get,
9564         isShowing: popup.isSet,
9565         setTooltip: popup.set,
9566         clearTooltip: popup.clear,
9567         clearTimer,
9568         resetTimer,
9569         readState
9570       });
9571     };
9573     var TooltippingState = /*#__PURE__*/Object.freeze({
9574         __proto__: null,
9575         init: init$b
9576     });
9578     const Tooltipping = create$4({
9579       fields: TooltippingSchema,
9580       name: 'tooltipping',
9581       active: ActiveTooltipping,
9582       state: TooltippingState,
9583       apis: TooltippingApis
9584     });
9586     const escape = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
9588     const ReadOnlyChannel = 'silver.readonly';
9589     const ReadOnlyDataSchema = objOf([requiredBoolean('readonly')]);
9590     const broadcastReadonly = (uiComponents, readonly) => {
9591       const outerContainer = uiComponents.outerContainer;
9592       const target = outerContainer.element;
9593       if (readonly) {
9594         uiComponents.mothership.broadcastOn([dismissPopups()], { target });
9595         uiComponents.uiMothership.broadcastOn([dismissPopups()], { target });
9596       }
9597       uiComponents.mothership.broadcastOn([ReadOnlyChannel], { readonly });
9598       uiComponents.uiMothership.broadcastOn([ReadOnlyChannel], { readonly });
9599     };
9600     const setupReadonlyModeSwitch = (editor, uiComponents) => {
9601       editor.on('init', () => {
9602         if (editor.mode.isReadOnly()) {
9603           broadcastReadonly(uiComponents, true);
9604         }
9605       });
9606       editor.on('SwitchMode', () => broadcastReadonly(uiComponents, editor.mode.isReadOnly()));
9607       if (isReadOnly(editor)) {
9608         editor.mode.set('readonly');
9609       }
9610     };
9611     const receivingConfig = () => Receiving.config({
9612       channels: {
9613         [ReadOnlyChannel]: {
9614           schema: ReadOnlyDataSchema,
9615           onReceive: (comp, data) => {
9616             Disabling.set(comp, data.readonly);
9617           }
9618         }
9619       }
9620     });
9622     const item = disabled => Disabling.config({
9623       disabled,
9624       disableClass: 'tox-collection__item--state-disabled'
9625     });
9626     const button = disabled => Disabling.config({ disabled });
9627     const splitButton = disabled => Disabling.config({
9628       disabled,
9629       disableClass: 'tox-tbtn--disabled'
9630     });
9631     const toolbarButton = disabled => Disabling.config({
9632       disabled,
9633       disableClass: 'tox-tbtn--disabled',
9634       useNative: false
9635     });
9636     const DisablingConfigs = {
9637       item,
9638       button,
9639       splitButton,
9640       toolbarButton
9641     };
9643     const runWithApi = (info, comp) => {
9644       const api = info.getApi(comp);
9645       return f => {
9646         f(api);
9647       };
9648     };
9649     const onControlAttached = (info, editorOffCell) => runOnAttached(comp => {
9650       const run = runWithApi(info, comp);
9651       run(api => {
9652         const onDestroy = info.onSetup(api);
9653         if (isFunction(onDestroy)) {
9654           editorOffCell.set(onDestroy);
9655         }
9656       });
9657     });
9658     const onControlDetached = (getApi, editorOffCell) => runOnDetached(comp => runWithApi(getApi, comp)(editorOffCell.get()));
9660     const onMenuItemExecute = (info, itemResponse) => runOnExecute$1((comp, simulatedEvent) => {
9661       runWithApi(info, comp)(info.onAction);
9662       if (!info.triggersSubmenu && itemResponse === ItemResponse$1.CLOSE_ON_EXECUTE) {
9663         if (comp.getSystem().isConnected()) {
9664           emit(comp, sandboxClose());
9665         }
9666         simulatedEvent.stop();
9667       }
9668     });
9669     const menuItemEventOrder = {
9670       [execute$5()]: [
9671         'disabling',
9672         'alloy.base.behaviour',
9673         'toggling',
9674         'item-events'
9675       ]
9676     };
9678     const componentRenderPipeline = cat;
9679     const renderCommonItem = (spec, structure, itemResponse, providersBackstage) => {
9680       const editorOffCell = Cell(noop);
9681       return {
9682         type: 'item',
9683         dom: structure.dom,
9684         components: componentRenderPipeline(structure.optComponents),
9685         data: spec.data,
9686         eventOrder: menuItemEventOrder,
9687         hasSubmenu: spec.triggersSubmenu,
9688         itemBehaviours: derive$1([
9689           config('item-events', [
9690             onMenuItemExecute(spec, itemResponse),
9691             onControlAttached(spec, editorOffCell),
9692             onControlDetached(spec, editorOffCell)
9693           ]),
9694           DisablingConfigs.item(() => !spec.enabled || providersBackstage.isDisabled()),
9695           receivingConfig(),
9696           Replacing.config({})
9697         ].concat(spec.itemBehaviours))
9698       };
9699     };
9700     const buildData = source => ({
9701       value: source.value,
9702       meta: {
9703         text: source.text.getOr(''),
9704         ...source.meta
9705       }
9706     });
9708     const convertText = source => {
9709       const isMac = global$5.os.isMacOS() || global$5.os.isiOS();
9710       const mac = {
9711         alt: '\u2325',
9712         ctrl: '\u2303',
9713         shift: '\u21E7',
9714         meta: '\u2318',
9715         access: '\u2303\u2325'
9716       };
9717       const other = {
9718         meta: 'Ctrl',
9719         access: 'Shift+Alt'
9720       };
9721       const replace = isMac ? mac : other;
9722       const shortcut = source.split('+');
9723       const updated = map$2(shortcut, segment => {
9724         const search = segment.toLowerCase().trim();
9725         return has$2(replace, search) ? replace[search] : segment;
9726       });
9727       return isMac ? updated.join('') : updated.join('+');
9728     };
9730     const renderIcon$1 = (name, icons, classes = [iconClass]) => render$3(name, {
9731       tag: 'div',
9732       classes
9733     }, icons);
9734     const renderText = text => ({
9735       dom: {
9736         tag: 'div',
9737         classes: [textClass]
9738       },
9739       components: [text$2(global$8.translate(text))]
9740     });
9741     const renderHtml = (html, classes) => ({
9742       dom: {
9743         tag: 'div',
9744         classes,
9745         innerHtml: html
9746       }
9747     });
9748     const renderStyledText = (style, text) => ({
9749       dom: {
9750         tag: 'div',
9751         classes: [textClass]
9752       },
9753       components: [{
9754           dom: {
9755             tag: style.tag,
9756             styles: style.styles
9757           },
9758           components: [text$2(global$8.translate(text))]
9759         }]
9760     });
9761     const renderShortcut = shortcut => ({
9762       dom: {
9763         tag: 'div',
9764         classes: [accessoryClass]
9765       },
9766       components: [text$2(convertText(shortcut))]
9767     });
9768     const renderCheckmark = icons => renderIcon$1('checkmark', icons, [checkmarkClass]);
9769     const renderSubmenuCaret = icons => renderIcon$1('chevron-right', icons, [caretClass]);
9770     const renderDownwardsCaret = icons => renderIcon$1('chevron-down', icons, [caretClass]);
9771     const renderContainer = (container, components) => {
9772       const directionClass = container.direction === 'vertical' ? containerColumnClass : containerRowClass;
9773       const alignClass = container.align === 'left' ? containerAlignLeftClass : containerAlignRightClass;
9774       const getValignClass = () => {
9775         switch (container.valign) {
9776         case 'top':
9777           return containerValignTopClass;
9778         case 'middle':
9779           return containerValignMiddleClass;
9780         case 'bottom':
9781           return containerValignBottomClass;
9782         }
9783       };
9784       return {
9785         dom: {
9786           tag: 'div',
9787           classes: [
9788             containerClass,
9789             directionClass,
9790             alignClass,
9791             getValignClass()
9792           ]
9793         },
9794         components
9795       };
9796     };
9797     const renderImage = (src, classes, alt) => ({
9798       dom: {
9799         tag: 'img',
9800         classes,
9801         attributes: {
9802           src,
9803           alt: alt.getOr('')
9804         }
9805       }
9806     });
9808     const renderColorStructure = (item, providerBackstage, fallbackIcon) => {
9809       const colorPickerCommand = 'custom';
9810       const removeColorCommand = 'remove';
9811       const itemText = item.ariaLabel;
9812       const itemValue = item.value;
9813       const iconSvg = item.iconContent.map(name => getOr(name, providerBackstage.icons, fallbackIcon));
9814       const getDom = () => {
9815         const common = colorClass;
9816         const icon = iconSvg.getOr('');
9817         const attributes = itemText.map(text => ({ title: providerBackstage.translate(text) })).getOr({});
9818         const baseDom = {
9819           tag: 'div',
9820           attributes,
9821           classes: [common]
9822         };
9823         if (itemValue === colorPickerCommand) {
9824           return {
9825             ...baseDom,
9826             tag: 'button',
9827             classes: [
9828               ...baseDom.classes,
9829               'tox-swatches__picker-btn'
9830             ],
9831             innerHtml: icon
9832           };
9833         } else if (itemValue === removeColorCommand) {
9834           return {
9835             ...baseDom,
9836             classes: [
9837               ...baseDom.classes,
9838               'tox-swatch--remove'
9839             ],
9840             innerHtml: icon
9841           };
9842         } else if (isNonNullable(itemValue)) {
9843           return {
9844             ...baseDom,
9845             attributes: {
9846               ...baseDom.attributes,
9847               'data-mce-color': itemValue
9848             },
9849             styles: { 'background-color': itemValue }
9850           };
9851         } else {
9852           return baseDom;
9853         }
9854       };
9855       return {
9856         dom: getDom(),
9857         optComponents: []
9858       };
9859     };
9860     const renderItemDomStructure = ariaLabel => {
9861       const domTitle = ariaLabel.map(label => ({ attributes: { title: global$8.translate(label) } })).getOr({});
9862       return {
9863         tag: 'div',
9864         classes: [
9865           navClass,
9866           selectableClass
9867         ],
9868         ...domTitle
9869       };
9870     };
9871     const renderNormalItemStructure = (info, providersBackstage, renderIcons, fallbackIcon) => {
9872       const iconSpec = {
9873         tag: 'div',
9874         classes: [iconClass]
9875       };
9876       const renderIcon = iconName => render$3(iconName, iconSpec, providersBackstage.icons, fallbackIcon);
9877       const renderEmptyIcon = () => Optional.some({ dom: iconSpec });
9878       const leftIcon = renderIcons ? info.iconContent.map(renderIcon).orThunk(renderEmptyIcon) : Optional.none();
9879       const checkmark = info.checkMark;
9880       const textRender = Optional.from(info.meta).fold(() => renderText, meta => has$2(meta, 'style') ? curry(renderStyledText, meta.style) : renderText);
9881       const content = info.htmlContent.fold(() => info.textContent.map(textRender), html => Optional.some(renderHtml(html, [textClass])));
9882       const menuItem = {
9883         dom: renderItemDomStructure(info.ariaLabel),
9884         optComponents: [
9885           leftIcon,
9886           content,
9887           info.shortcutContent.map(renderShortcut),
9888           checkmark,
9889           info.caret
9890         ]
9891       };
9892       return menuItem;
9893     };
9894     const renderItemStructure = (info, providersBackstage, renderIcons, fallbackIcon = Optional.none()) => {
9895       if (info.presets === 'color') {
9896         return renderColorStructure(info, providersBackstage, fallbackIcon);
9897       } else {
9898         return renderNormalItemStructure(info, providersBackstage, renderIcons, fallbackIcon);
9899       }
9900     };
9902     const tooltipBehaviour = (meta, sharedBackstage) => get$g(meta, 'tooltipWorker').map(tooltipWorker => [Tooltipping.config({
9903         lazySink: sharedBackstage.getSink,
9904         tooltipDom: {
9905           tag: 'div',
9906           classes: ['tox-tooltip-worker-container']
9907         },
9908         tooltipComponents: [],
9909         anchor: comp => ({
9910           type: 'submenu',
9911           item: comp,
9912           overrides: { maxHeightFunction: expandable$1 }
9913         }),
9914         mode: 'follow-highlight',
9915         onShow: (component, _tooltip) => {
9916           tooltipWorker(elm => {
9917             Tooltipping.setComponents(component, [external$1({ element: SugarElement.fromDom(elm) })]);
9918           });
9919         }
9920       })]).getOr([]);
9921     const encodeText = text => global$7.DOM.encode(text);
9922     const replaceText = (text, matchText) => {
9923       const translated = global$8.translate(text);
9924       const encoded = encodeText(translated);
9925       if (matchText.length > 0) {
9926         const escapedMatchRegex = new RegExp(escape(matchText), 'gi');
9927         return encoded.replace(escapedMatchRegex, match => `<span class="tox-autocompleter-highlight">${ match }</span>`);
9928       } else {
9929         return encoded;
9930       }
9931     };
9932     const renderAutocompleteItem = (spec, matchText, useText, presets, onItemValueHandler, itemResponse, sharedBackstage, renderIcons = true) => {
9933       const structure = renderItemStructure({
9934         presets,
9935         textContent: Optional.none(),
9936         htmlContent: useText ? spec.text.map(text => replaceText(text, matchText)) : Optional.none(),
9937         ariaLabel: spec.text,
9938         iconContent: spec.icon,
9939         shortcutContent: Optional.none(),
9940         checkMark: Optional.none(),
9941         caret: Optional.none(),
9942         value: spec.value
9943       }, sharedBackstage.providers, renderIcons, spec.icon);
9944       return renderCommonItem({
9945         data: buildData(spec),
9946         enabled: spec.enabled,
9947         getApi: constant$1({}),
9948         onAction: _api => onItemValueHandler(spec.value, spec.meta),
9949         onSetup: constant$1(noop),
9950         triggersSubmenu: false,
9951         itemBehaviours: tooltipBehaviour(spec.meta, sharedBackstage)
9952       }, structure, itemResponse, sharedBackstage.providers);
9953     };
9955     const render$2 = (items, extras) => map$2(items, item => {
9956       switch (item.type) {
9957       case 'cardcontainer':
9958         return renderContainer(item, render$2(item.items, extras));
9959       case 'cardimage':
9960         return renderImage(item.src, item.classes, item.alt);
9961       case 'cardtext':
9962         const shouldHighlight = item.name.exists(name => contains$2(extras.cardText.highlightOn, name));
9963         const matchText = shouldHighlight ? Optional.from(extras.cardText.matchText).getOr('') : '';
9964         return renderHtml(replaceText(item.text, matchText), item.classes);
9965       }
9966     });
9967     const renderCardMenuItem = (spec, itemResponse, sharedBackstage, extras) => {
9968       const getApi = component => ({
9969         isEnabled: () => !Disabling.isDisabled(component),
9970         setEnabled: state => {
9971           Disabling.set(component, !state);
9972           each$1(descendants(component.element, '*'), elm => {
9973             component.getSystem().getByDom(elm).each(comp => {
9974               if (comp.hasConfigured(Disabling)) {
9975                 Disabling.set(comp, !state);
9976               }
9977             });
9978           });
9979         }
9980       });
9981       const structure = {
9982         dom: renderItemDomStructure(spec.label),
9983         optComponents: [Optional.some({
9984             dom: {
9985               tag: 'div',
9986               classes: [
9987                 containerClass,
9988                 containerRowClass
9989               ]
9990             },
9991             components: render$2(spec.items, extras)
9992           })]
9993       };
9994       return renderCommonItem({
9995         data: buildData({
9996           text: Optional.none(),
9997           ...spec
9998         }),
9999         enabled: spec.enabled,
10000         getApi,
10001         onAction: spec.onAction,
10002         onSetup: spec.onSetup,
10003         triggersSubmenu: false,
10004         itemBehaviours: Optional.from(extras.itemBehaviours).getOr([])
10005       }, structure, itemResponse, sharedBackstage.providers);
10006     };
10008     const renderChoiceItem = (spec, useText, presets, onItemValueHandler, isSelected, itemResponse, providersBackstage, renderIcons = true) => {
10009       const getApi = component => ({
10010         setActive: state => {
10011           Toggling.set(component, state);
10012         },
10013         isActive: () => Toggling.isOn(component),
10014         isEnabled: () => !Disabling.isDisabled(component),
10015         setEnabled: state => Disabling.set(component, !state)
10016       });
10017       const structure = renderItemStructure({
10018         presets,
10019         textContent: useText ? spec.text : Optional.none(),
10020         htmlContent: Optional.none(),
10021         ariaLabel: spec.text,
10022         iconContent: spec.icon,
10023         shortcutContent: useText ? spec.shortcut : Optional.none(),
10024         checkMark: useText ? Optional.some(renderCheckmark(providersBackstage.icons)) : Optional.none(),
10025         caret: Optional.none(),
10026         value: spec.value
10027       }, providersBackstage, renderIcons);
10028       return deepMerge(renderCommonItem({
10029         data: buildData(spec),
10030         enabled: spec.enabled,
10031         getApi,
10032         onAction: _api => onItemValueHandler(spec.value),
10033         onSetup: api => {
10034           api.setActive(isSelected);
10035           return noop;
10036         },
10037         triggersSubmenu: false,
10038         itemBehaviours: []
10039       }, structure, itemResponse, providersBackstage), {
10040         toggling: {
10041           toggleClass: tickedClass,
10042           toggleOnExecute: false,
10043           selected: spec.active,
10044           exclusive: true
10045         }
10046       });
10047     };
10049     const parts$f = generate$3(owner$2(), parts$h());
10051     const hexColour = value => ({ value });
10052     const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
10053     const longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
10054     const isHexString = hex => shorthandRegex.test(hex) || longformRegex.test(hex);
10055     const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
10056     const fromString$1 = hex => isHexString(hex) ? Optional.some({ value: normalizeHex(hex) }) : Optional.none();
10057     const getLongForm = hex => {
10058       const hexString = hex.value.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
10059       return { value: hexString };
10060     };
10061     const extractValues = hex => {
10062       const longForm = getLongForm(hex);
10063       const splitForm = longformRegex.exec(longForm.value);
10064       return splitForm === null ? [
10065         'FFFFFF',
10066         'FF',
10067         'FF',
10068         'FF'
10069       ] : splitForm;
10070     };
10071     const toHex = component => {
10072       const hex = component.toString(16);
10073       return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
10074     };
10075     const fromRgba = rgbaColour => {
10076       const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
10077       return hexColour(value);
10078     };
10080     const min = Math.min;
10081     const max = Math.max;
10082     const round$1 = Math.round;
10083     const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
10084     const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
10085     const rgbaColour = (red, green, blue, alpha) => ({
10086       red,
10087       green,
10088       blue,
10089       alpha
10090     });
10091     const isRgbaComponent = value => {
10092       const num = parseInt(value, 10);
10093       return num.toString() === value && num >= 0 && num <= 255;
10094     };
10095     const fromHsv = hsv => {
10096       let r;
10097       let g;
10098       let b;
10099       const hue = (hsv.hue || 0) % 360;
10100       let saturation = hsv.saturation / 100;
10101       let brightness = hsv.value / 100;
10102       saturation = max(0, min(saturation, 1));
10103       brightness = max(0, min(brightness, 1));
10104       if (saturation === 0) {
10105         r = g = b = round$1(255 * brightness);
10106         return rgbaColour(r, g, b, 1);
10107       }
10108       const side = hue / 60;
10109       const chroma = brightness * saturation;
10110       const x = chroma * (1 - Math.abs(side % 2 - 1));
10111       const match = brightness - chroma;
10112       switch (Math.floor(side)) {
10113       case 0:
10114         r = chroma;
10115         g = x;
10116         b = 0;
10117         break;
10118       case 1:
10119         r = x;
10120         g = chroma;
10121         b = 0;
10122         break;
10123       case 2:
10124         r = 0;
10125         g = chroma;
10126         b = x;
10127         break;
10128       case 3:
10129         r = 0;
10130         g = x;
10131         b = chroma;
10132         break;
10133       case 4:
10134         r = x;
10135         g = 0;
10136         b = chroma;
10137         break;
10138       case 5:
10139         r = chroma;
10140         g = 0;
10141         b = x;
10142         break;
10143       default:
10144         r = g = b = 0;
10145       }
10146       r = round$1(255 * (r + match));
10147       g = round$1(255 * (g + match));
10148       b = round$1(255 * (b + match));
10149       return rgbaColour(r, g, b, 1);
10150     };
10151     const fromHex = hexColour => {
10152       const result = extractValues(hexColour);
10153       const red = parseInt(result[1], 16);
10154       const green = parseInt(result[2], 16);
10155       const blue = parseInt(result[3], 16);
10156       return rgbaColour(red, green, blue, 1);
10157     };
10158     const fromStringValues = (red, green, blue, alpha) => {
10159       const r = parseInt(red, 10);
10160       const g = parseInt(green, 10);
10161       const b = parseInt(blue, 10);
10162       const a = parseFloat(alpha);
10163       return rgbaColour(r, g, b, a);
10164     };
10165     const fromString = rgbaString => {
10166       if (rgbaString === 'transparent') {
10167         return Optional.some(rgbaColour(0, 0, 0, 0));
10168       }
10169       const rgbMatch = rgbRegex.exec(rgbaString);
10170       if (rgbMatch !== null) {
10171         return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
10172       }
10173       const rgbaMatch = rgbaRegex.exec(rgbaString);
10174       if (rgbaMatch !== null) {
10175         return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
10176       }
10177       return Optional.none();
10178     };
10179     const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
10180     const red = rgbaColour(255, 0, 0, 1);
10182     const fireSkinLoaded$1 = editor => {
10183       editor.dispatch('SkinLoaded');
10184     };
10185     const fireSkinLoadError$1 = (editor, error) => {
10186       editor.dispatch('SkinLoadError', error);
10187     };
10188     const fireResizeEditor = editor => {
10189       editor.dispatch('ResizeEditor');
10190     };
10191     const fireResizeContent = (editor, e) => {
10192       editor.dispatch('ResizeContent', e);
10193     };
10194     const fireScrollContent = (editor, e) => {
10195       editor.dispatch('ScrollContent', e);
10196     };
10197     const fireTextColorChange = (editor, data) => {
10198       editor.dispatch('TextColorChange', data);
10199     };
10200     const fireAfterProgressState = (editor, state) => {
10201       editor.dispatch('AfterProgressState', { state });
10202     };
10203     const fireResolveName = (editor, node) => editor.dispatch('ResolveName', {
10204       name: node.nodeName.toLowerCase(),
10205       target: node
10206     });
10208     const hsvColour = (hue, saturation, value) => ({
10209       hue,
10210       saturation,
10211       value
10212     });
10213     const fromRgb = rgbaColour => {
10214       let h = 0;
10215       let s = 0;
10216       let v = 0;
10217       const r = rgbaColour.red / 255;
10218       const g = rgbaColour.green / 255;
10219       const b = rgbaColour.blue / 255;
10220       const minRGB = Math.min(r, Math.min(g, b));
10221       const maxRGB = Math.max(r, Math.max(g, b));
10222       if (minRGB === maxRGB) {
10223         v = minRGB;
10224         return hsvColour(0, 0, v * 100);
10225       }
10226       const d = r === minRGB ? g - b : b === minRGB ? r - g : b - r;
10227       h = r === minRGB ? 3 : b === minRGB ? 1 : 5;
10228       h = 60 * (h - d / (maxRGB - minRGB));
10229       s = (maxRGB - minRGB) / maxRGB;
10230       v = maxRGB;
10231       return hsvColour(Math.round(h), Math.round(s * 100), Math.round(v * 100));
10232     };
10234     const hexToHsv = hex => fromRgb(fromHex(hex));
10235     const hsvToHex = hsv => fromRgba(fromHsv(hsv));
10236     const anyToHex = color => fromString$1(color).orThunk(() => fromString(color).map(fromRgba)).getOrThunk(() => {
10237       const canvas = document.createElement('canvas');
10238       canvas.height = 1;
10239       canvas.width = 1;
10240       const canvasContext = canvas.getContext('2d');
10241       canvasContext.clearRect(0, 0, canvas.width, canvas.height);
10242       canvasContext.fillStyle = '#FFFFFF';
10243       canvasContext.fillStyle = color;
10244       canvasContext.fillRect(0, 0, 1, 1);
10245       const rgba = canvasContext.getImageData(0, 0, 1, 1).data;
10246       const r = rgba[0];
10247       const g = rgba[1];
10248       const b = rgba[2];
10249       const a = rgba[3];
10250       return fromRgba(rgbaColour(r, g, b, a));
10251     });
10253     var global$4 = tinymce.util.Tools.resolve('tinymce.util.LocalStorage');
10255     const storageName = 'tinymce-custom-colors';
10256     const ColorCache = (max = 10) => {
10257       const storageString = global$4.getItem(storageName);
10258       const localstorage = isString(storageString) ? JSON.parse(storageString) : [];
10259       const prune = list => {
10260         const diff = max - list.length;
10261         return diff < 0 ? list.slice(0, max) : list;
10262       };
10263       const cache = prune(localstorage);
10264       const add = key => {
10265         indexOf(cache, key).each(remove);
10266         cache.unshift(key);
10267         if (cache.length > max) {
10268           cache.pop();
10269         }
10270         global$4.setItem(storageName, JSON.stringify(cache));
10271       };
10272       const remove = idx => {
10273         cache.splice(idx, 1);
10274       };
10275       const state = () => cache.slice(0);
10276       return {
10277         add,
10278         state
10279       };
10280     };
10282     const colorCache = ColorCache(10);
10283     const calcCols = colors => Math.max(5, Math.ceil(Math.sqrt(colors)));
10284     const mapColors = colorMap => {
10285       const colors = [];
10286       for (let i = 0; i < colorMap.length; i += 2) {
10287         colors.push({
10288           text: colorMap[i + 1],
10289           value: '#' + anyToHex(colorMap[i]).value,
10290           type: 'choiceitem'
10291         });
10292       }
10293       return colors;
10294     };
10295     const option$1 = name => editor => editor.options.get(name);
10296     const register$d = editor => {
10297       const registerOption = editor.options.register;
10298       registerOption('color_map', {
10299         processor: value => {
10300           if (isArrayOf(value, isString)) {
10301             return {
10302               value: mapColors(value),
10303               valid: true
10304             };
10305           } else {
10306             return {
10307               valid: false,
10308               message: 'Must be an array of strings.'
10309             };
10310           }
10311         },
10312         default: [
10313           '#BFEDD2',
10314           'Light Green',
10315           '#FBEEB8',
10316           'Light Yellow',
10317           '#F8CAC6',
10318           'Light Red',
10319           '#ECCAFA',
10320           'Light Purple',
10321           '#C2E0F4',
10322           'Light Blue',
10323           '#2DC26B',
10324           'Green',
10325           '#F1C40F',
10326           'Yellow',
10327           '#E03E2D',
10328           'Red',
10329           '#B96AD9',
10330           'Purple',
10331           '#3598DB',
10332           'Blue',
10333           '#169179',
10334           'Dark Turquoise',
10335           '#E67E23',
10336           'Orange',
10337           '#BA372A',
10338           'Dark Red',
10339           '#843FA1',
10340           'Dark Purple',
10341           '#236FA1',
10342           'Dark Blue',
10343           '#ECF0F1',
10344           'Light Gray',
10345           '#CED4D9',
10346           'Medium Gray',
10347           '#95A5A6',
10348           'Gray',
10349           '#7E8C8D',
10350           'Dark Gray',
10351           '#34495E',
10352           'Navy Blue',
10353           '#000000',
10354           'Black',
10355           '#ffffff',
10356           'White'
10357         ]
10358       });
10359       registerOption('color_cols', {
10360         processor: 'number',
10361         default: calcCols(getColors$2(editor).length)
10362       });
10363       registerOption('custom_colors', {
10364         processor: 'boolean',
10365         default: true
10366       });
10367     };
10368     const getColorCols$1 = option$1('color_cols');
10369     const hasCustomColors$1 = option$1('custom_colors');
10370     const getColors$2 = option$1('color_map');
10371     const getCurrentColors = () => map$2(colorCache.state(), color => ({
10372       type: 'choiceitem',
10373       text: color,
10374       value: color
10375     }));
10376     const addColor = color => {
10377       colorCache.add(color);
10378     };
10380     const fallbackColor = '#000000';
10381     const hasStyleApi = node => isNonNullable(node.style);
10382     const getCurrentColor = (editor, format) => {
10383       let color;
10384       editor.dom.getParents(editor.selection.getStart(), elm => {
10385         const value = hasStyleApi(elm) ? elm.style[format === 'forecolor' ? 'color' : 'backgroundColor'] : null;
10386         if (value) {
10387           color = color ? color : value;
10388         }
10389       });
10390       return Optional.from(color);
10391     };
10392     const applyFormat = (editor, format, value) => {
10393       editor.undoManager.transact(() => {
10394         editor.focus();
10395         editor.formatter.apply(format, { value });
10396         editor.nodeChanged();
10397       });
10398     };
10399     const removeFormat = (editor, format) => {
10400       editor.undoManager.transact(() => {
10401         editor.focus();
10402         editor.formatter.remove(format, { value: null }, undefined, true);
10403         editor.nodeChanged();
10404       });
10405     };
10406     const registerCommands = editor => {
10407       editor.addCommand('mceApplyTextcolor', (format, value) => {
10408         applyFormat(editor, format, value);
10409       });
10410       editor.addCommand('mceRemoveTextcolor', format => {
10411         removeFormat(editor, format);
10412       });
10413     };
10414     const getAdditionalColors = hasCustom => {
10415       const type = 'choiceitem';
10416       const remove = {
10417         type,
10418         text: 'Remove color',
10419         icon: 'color-swatch-remove-color',
10420         value: 'remove'
10421       };
10422       const custom = {
10423         type,
10424         text: 'Custom color',
10425         icon: 'color-picker',
10426         value: 'custom'
10427       };
10428       return hasCustom ? [
10429         remove,
10430         custom
10431       ] : [remove];
10432     };
10433     const applyColor = (editor, format, value, onChoice) => {
10434       if (value === 'custom') {
10435         const dialog = colorPickerDialog(editor);
10436         dialog(colorOpt => {
10437           colorOpt.each(color => {
10438             addColor(color);
10439             editor.execCommand('mceApplyTextcolor', format, color);
10440             onChoice(color);
10441           });
10442         }, fallbackColor);
10443       } else if (value === 'remove') {
10444         onChoice('');
10445         editor.execCommand('mceRemoveTextcolor', format);
10446       } else {
10447         onChoice(value);
10448         editor.execCommand('mceApplyTextcolor', format, value);
10449       }
10450     };
10451     const getColors$1 = (colors, hasCustom) => colors.concat(getCurrentColors().concat(getAdditionalColors(hasCustom)));
10452     const getFetch$1 = (colors, hasCustom) => callback => {
10453       callback(getColors$1(colors, hasCustom));
10454     };
10455     const setIconColor = (splitButtonApi, name, newColor) => {
10456       const id = name === 'forecolor' ? 'tox-icon-text-color__color' : 'tox-icon-highlight-bg-color__color';
10457       splitButtonApi.setIconFill(id, newColor);
10458     };
10459     const registerTextColorButton = (editor, name, format, tooltip, lastColor) => {
10460       editor.ui.registry.addSplitButton(name, {
10461         tooltip,
10462         presets: 'color',
10463         icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
10464         select: value => {
10465           const optCurrentRgb = getCurrentColor(editor, format);
10466           return optCurrentRgb.bind(currentRgb => fromString(currentRgb).map(rgba => {
10467             const currentHex = fromRgba(rgba).value;
10468             return contains$1(value.toLowerCase(), currentHex);
10469           })).getOr(false);
10470         },
10471         columns: getColorCols$1(editor),
10472         fetch: getFetch$1(getColors$2(editor), hasCustomColors$1(editor)),
10473         onAction: _splitButtonApi => {
10474           applyColor(editor, format, lastColor.get(), noop);
10475         },
10476         onItemAction: (_splitButtonApi, value) => {
10477           applyColor(editor, format, value, newColor => {
10478             lastColor.set(newColor);
10479             fireTextColorChange(editor, {
10480               name,
10481               color: newColor
10482             });
10483           });
10484         },
10485         onSetup: splitButtonApi => {
10486           setIconColor(splitButtonApi, name, lastColor.get());
10487           const handler = e => {
10488             if (e.name === name) {
10489               setIconColor(splitButtonApi, e.name, e.color);
10490             }
10491           };
10492           editor.on('TextColorChange', handler);
10493           return () => {
10494             editor.off('TextColorChange', handler);
10495           };
10496         }
10497       });
10498     };
10499     const registerTextColorMenuItem = (editor, name, format, text) => {
10500       editor.ui.registry.addNestedMenuItem(name, {
10501         text,
10502         icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
10503         getSubmenuItems: () => [{
10504             type: 'fancymenuitem',
10505             fancytype: 'colorswatch',
10506             onAction: data => {
10507               applyColor(editor, format, data.value, noop);
10508             }
10509           }]
10510       });
10511     };
10512     const colorPickerDialog = editor => (callback, value) => {
10513       let isValid = false;
10514       const onSubmit = api => {
10515         const data = api.getData();
10516         const hex = data.colorpicker;
10517         if (isValid) {
10518           callback(Optional.from(hex));
10519           api.close();
10520         } else {
10521           editor.windowManager.alert(editor.translate([
10522             'Invalid hex color code: {0}',
10523             hex
10524           ]));
10525         }
10526       };
10527       const onAction = (_api, details) => {
10528         if (details.name === 'hex-valid') {
10529           isValid = details.value;
10530         }
10531       };
10532       const initialData = { colorpicker: value };
10533       editor.windowManager.open({
10534         title: 'Color Picker',
10535         size: 'normal',
10536         body: {
10537           type: 'panel',
10538           items: [{
10539               type: 'colorpicker',
10540               name: 'colorpicker',
10541               label: 'Color'
10542             }]
10543         },
10544         buttons: [
10545           {
10546             type: 'cancel',
10547             name: 'cancel',
10548             text: 'Cancel'
10549           },
10550           {
10551             type: 'submit',
10552             name: 'save',
10553             text: 'Save',
10554             primary: true
10555           }
10556         ],
10557         initialData,
10558         onAction,
10559         onSubmit,
10560         onClose: noop,
10561         onCancel: () => {
10562           callback(Optional.none());
10563         }
10564       });
10565     };
10566     const register$c = editor => {
10567       registerCommands(editor);
10568       const lastForeColor = Cell(fallbackColor);
10569       const lastBackColor = Cell(fallbackColor);
10570       registerTextColorButton(editor, 'forecolor', 'forecolor', 'Text color', lastForeColor);
10571       registerTextColorButton(editor, 'backcolor', 'hilitecolor', 'Background color', lastBackColor);
10572       registerTextColorMenuItem(editor, 'forecolor', 'forecolor', 'Text color');
10573       registerTextColorMenuItem(editor, 'backcolor', 'hilitecolor', 'Background color');
10574     };
10576     const createPartialChoiceMenu = (value, items, onItemValueHandler, columns, presets, itemResponse, select, providersBackstage) => {
10577       const hasIcons = menuHasIcons(items);
10578       const presetItemTypes = presets !== 'color' ? 'normal' : 'color';
10579       const alloyItems = createChoiceItems(items, onItemValueHandler, columns, presetItemTypes, itemResponse, select, providersBackstage);
10580       const menuLayout = { menuType: presets };
10581       return createPartialMenuWithAlloyItems(value, hasIcons, alloyItems, columns, menuLayout);
10582     };
10583     const createChoiceItems = (items, onItemValueHandler, columns, itemPresets, itemResponse, select, providersBackstage) => cat(map$2(items, item => {
10584       if (item.type === 'choiceitem') {
10585         return createChoiceMenuItem(item).fold(handleError, d => Optional.some(renderChoiceItem(d, columns === 1, itemPresets, onItemValueHandler, select(d.value), itemResponse, providersBackstage, menuHasIcons(items))));
10586       } else {
10587         return Optional.none();
10588       }
10589     }));
10591     const deriveMenuMovement = (columns, presets) => {
10592       const menuMarkers = markers(presets);
10593       if (columns === 1) {
10594         return {
10595           mode: 'menu',
10596           moveOnTab: true
10597         };
10598       } else if (columns === 'auto') {
10599         return {
10600           mode: 'grid',
10601           selector: '.' + menuMarkers.item,
10602           initSize: {
10603             numColumns: 1,
10604             numRows: 1
10605           }
10606         };
10607       } else {
10608         const rowClass = presets === 'color' ? 'tox-swatches__row' : 'tox-collection__group';
10609         return {
10610           mode: 'matrix',
10611           rowSelector: '.' + rowClass
10612         };
10613       }
10614     };
10615     const deriveCollectionMovement = (columns, presets) => {
10616       if (columns === 1) {
10617         return {
10618           mode: 'menu',
10619           moveOnTab: false,
10620           selector: '.tox-collection__item'
10621         };
10622       } else if (columns === 'auto') {
10623         return {
10624           mode: 'flatgrid',
10625           selector: '.' + 'tox-collection__item',
10626           initSize: {
10627             numColumns: 1,
10628             numRows: 1
10629           }
10630         };
10631       } else {
10632         return {
10633           mode: 'matrix',
10634           selectors: {
10635             row: presets === 'color' ? '.tox-swatches__row' : '.tox-collection__group',
10636             cell: presets === 'color' ? `.${ colorClass }` : `.${ selectableClass }`
10637           }
10638         };
10639       }
10640     };
10642     const renderColorSwatchItem = (spec, backstage) => {
10643       const items = getColorItems(spec, backstage);
10644       const columns = backstage.colorinput.getColorCols();
10645       const presets = 'color';
10646       const menuSpec = createPartialChoiceMenu(generate$6('menu-value'), items, value => {
10647         spec.onAction({ value });
10648       }, columns, presets, ItemResponse$1.CLOSE_ON_EXECUTE, never, backstage.shared.providers);
10649       const widgetSpec = {
10650         ...menuSpec,
10651         markers: markers(presets),
10652         movement: deriveMenuMovement(columns, presets)
10653       };
10654       return {
10655         type: 'widget',
10656         data: { value: generate$6('widget-id') },
10657         dom: {
10658           tag: 'div',
10659           classes: ['tox-fancymenuitem']
10660         },
10661         autofocus: true,
10662         components: [parts$f.widget(Menu.sketch(widgetSpec))]
10663       };
10664     };
10665     const getColorItems = (spec, backstage) => {
10666       const useCustomColors = spec.initData.allowCustomColors && backstage.colorinput.hasCustomColors();
10667       return spec.initData.colors.fold(() => getColors$1(backstage.colorinput.getColors(), useCustomColors), colors => colors.concat(getAdditionalColors(useCustomColors)));
10668     };
10670     const cellOverEvent = generate$6('cell-over');
10671     const cellExecuteEvent = generate$6('cell-execute');
10672     const makeCell = (row, col, labelId) => {
10673       const emitCellOver = c => emitWith(c, cellOverEvent, {
10674         row,
10675         col
10676       });
10677       const emitExecute = c => emitWith(c, cellExecuteEvent, {
10678         row,
10679         col
10680       });
10681       const onClick = (c, se) => {
10682         se.stop();
10683         emitExecute(c);
10684       };
10685       return build$1({
10686         dom: {
10687           tag: 'div',
10688           attributes: {
10689             role: 'button',
10690             ['aria-labelledby']: labelId
10691           }
10692         },
10693         behaviours: derive$1([
10694           config('insert-table-picker-cell', [
10695             run$1(mouseover(), Focusing.focus),
10696             run$1(execute$5(), emitExecute),
10697             run$1(click(), onClick),
10698             run$1(tap(), onClick)
10699           ]),
10700           Toggling.config({
10701             toggleClass: 'tox-insert-table-picker__selected',
10702             toggleOnExecute: false
10703           }),
10704           Focusing.config({ onFocus: emitCellOver })
10705         ])
10706       });
10707     };
10708     const makeCells = (labelId, numRows, numCols) => {
10709       const cells = [];
10710       for (let i = 0; i < numRows; i++) {
10711         const row = [];
10712         for (let j = 0; j < numCols; j++) {
10713           row.push(makeCell(i, j, labelId));
10714         }
10715         cells.push(row);
10716       }
10717       return cells;
10718     };
10719     const selectCells = (cells, selectedRow, selectedColumn, numRows, numColumns) => {
10720       for (let i = 0; i < numRows; i++) {
10721         for (let j = 0; j < numColumns; j++) {
10722           Toggling.set(cells[i][j], i <= selectedRow && j <= selectedColumn);
10723         }
10724       }
10725     };
10726     const makeComponents = cells => bind$3(cells, cellRow => map$2(cellRow, premade));
10727     const makeLabelText = (row, col) => text$2(`${ col }x${ row }`);
10728     const renderInsertTableMenuItem = spec => {
10729       const numRows = 10;
10730       const numColumns = 10;
10731       const sizeLabelId = generate$6('size-label');
10732       const cells = makeCells(sizeLabelId, numRows, numColumns);
10733       const emptyLabelText = makeLabelText(0, 0);
10734       const memLabel = record({
10735         dom: {
10736           tag: 'span',
10737           classes: ['tox-insert-table-picker__label'],
10738           attributes: { id: sizeLabelId }
10739         },
10740         components: [emptyLabelText],
10741         behaviours: derive$1([Replacing.config({})])
10742       });
10743       return {
10744         type: 'widget',
10745         data: { value: generate$6('widget-id') },
10746         dom: {
10747           tag: 'div',
10748           classes: ['tox-fancymenuitem']
10749         },
10750         autofocus: true,
10751         components: [parts$f.widget({
10752             dom: {
10753               tag: 'div',
10754               classes: ['tox-insert-table-picker']
10755             },
10756             components: makeComponents(cells).concat(memLabel.asSpec()),
10757             behaviours: derive$1([
10758               config('insert-table-picker', [
10759                 runOnAttached(c => {
10760                   Replacing.set(memLabel.get(c), [emptyLabelText]);
10761                 }),
10762                 runWithTarget(cellOverEvent, (c, t, e) => {
10763                   const {row, col} = e.event;
10764                   selectCells(cells, row, col, numRows, numColumns);
10765                   Replacing.set(memLabel.get(c), [makeLabelText(row + 1, col + 1)]);
10766                 }),
10767                 runWithTarget(cellExecuteEvent, (c, _, e) => {
10768                   const {row, col} = e.event;
10769                   spec.onAction({
10770                     numRows: row + 1,
10771                     numColumns: col + 1
10772                   });
10773                   emit(c, sandboxClose());
10774                 })
10775               ]),
10776               Keying.config({
10777                 initSize: {
10778                   numRows,
10779                   numColumns
10780                 },
10781                 mode: 'flatgrid',
10782                 selector: '[role="button"]'
10783               })
10784             ])
10785           })]
10786       };
10787     };
10789     const fancyMenuItems = {
10790       inserttable: renderInsertTableMenuItem,
10791       colorswatch: renderColorSwatchItem
10792     };
10793     const renderFancyMenuItem = (spec, backstage) => get$g(fancyMenuItems, spec.fancytype).map(render => render(spec, backstage));
10795     const renderNestedItem = (spec, itemResponse, providersBackstage, renderIcons = true, downwardsCaret = false) => {
10796       const caret = downwardsCaret ? renderDownwardsCaret(providersBackstage.icons) : renderSubmenuCaret(providersBackstage.icons);
10797       const getApi = component => ({
10798         isEnabled: () => !Disabling.isDisabled(component),
10799         setEnabled: state => Disabling.set(component, !state)
10800       });
10801       const structure = renderItemStructure({
10802         presets: 'normal',
10803         iconContent: spec.icon,
10804         textContent: spec.text,
10805         htmlContent: Optional.none(),
10806         ariaLabel: spec.text,
10807         caret: Optional.some(caret),
10808         checkMark: Optional.none(),
10809         shortcutContent: spec.shortcut
10810       }, providersBackstage, renderIcons);
10811       return renderCommonItem({
10812         data: buildData(spec),
10813         getApi,
10814         enabled: spec.enabled,
10815         onAction: noop,
10816         onSetup: spec.onSetup,
10817         triggersSubmenu: true,
10818         itemBehaviours: []
10819       }, structure, itemResponse, providersBackstage);
10820     };
10822     const renderNormalItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
10823       const getApi = component => ({
10824         isEnabled: () => !Disabling.isDisabled(component),
10825         setEnabled: state => Disabling.set(component, !state)
10826       });
10827       const structure = renderItemStructure({
10828         presets: 'normal',
10829         iconContent: spec.icon,
10830         textContent: spec.text,
10831         htmlContent: Optional.none(),
10832         ariaLabel: spec.text,
10833         caret: Optional.none(),
10834         checkMark: Optional.none(),
10835         shortcutContent: spec.shortcut
10836       }, providersBackstage, renderIcons);
10837       return renderCommonItem({
10838         data: buildData(spec),
10839         getApi,
10840         enabled: spec.enabled,
10841         onAction: spec.onAction,
10842         onSetup: spec.onSetup,
10843         triggersSubmenu: false,
10844         itemBehaviours: []
10845       }, structure, itemResponse, providersBackstage);
10846     };
10848     const renderSeparatorItem = spec => ({
10849       type: 'separator',
10850       dom: {
10851         tag: 'div',
10852         classes: [
10853           selectableClass,
10854           groupHeadingClass
10855         ]
10856       },
10857       components: spec.text.map(text$2).toArray()
10858     });
10860     const renderToggleMenuItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
10861       const getApi = component => ({
10862         setActive: state => {
10863           Toggling.set(component, state);
10864         },
10865         isActive: () => Toggling.isOn(component),
10866         isEnabled: () => !Disabling.isDisabled(component),
10867         setEnabled: state => Disabling.set(component, !state)
10868       });
10869       const structure = renderItemStructure({
10870         iconContent: spec.icon,
10871         textContent: spec.text,
10872         htmlContent: Optional.none(),
10873         ariaLabel: spec.text,
10874         checkMark: Optional.some(renderCheckmark(providersBackstage.icons)),
10875         caret: Optional.none(),
10876         shortcutContent: spec.shortcut,
10877         presets: 'normal',
10878         meta: spec.meta
10879       }, providersBackstage, renderIcons);
10880       return deepMerge(renderCommonItem({
10881         data: buildData(spec),
10882         enabled: spec.enabled,
10883         getApi,
10884         onAction: spec.onAction,
10885         onSetup: spec.onSetup,
10886         triggersSubmenu: false,
10887         itemBehaviours: []
10888       }, structure, itemResponse, providersBackstage), {
10889         toggling: {
10890           toggleClass: tickedClass,
10891           toggleOnExecute: false,
10892           selected: spec.active
10893         }
10894       });
10895     };
10897     const autocomplete = renderAutocompleteItem;
10898     const separator$3 = renderSeparatorItem;
10899     const normal = renderNormalItem;
10900     const nested = renderNestedItem;
10901     const toggle$1 = renderToggleMenuItem;
10902     const fancy = renderFancyMenuItem;
10903     const card = renderCardMenuItem;
10905     const getCoupled = (component, coupleConfig, coupleState, name) => coupleState.getOrCreate(component, coupleConfig, name);
10906     const getExistingCoupled = (component, coupleConfig, coupleState, name) => coupleState.getExisting(component, coupleConfig, name);
10908     var CouplingApis = /*#__PURE__*/Object.freeze({
10909         __proto__: null,
10910         getCoupled: getCoupled,
10911         getExistingCoupled: getExistingCoupled
10912     });
10914     var CouplingSchema = [requiredOf('others', setOf(Result.value, anyValue()))];
10916     const init$a = () => {
10917       const coupled = {};
10918       const lookupCoupled = (coupleConfig, coupledName) => {
10919         const available = keys(coupleConfig.others);
10920         if (available.length === 0) {
10921           throw new Error('Cannot find any known coupled components');
10922         } else {
10923           return get$g(coupled, coupledName);
10924         }
10925       };
10926       const getOrCreate = (component, coupleConfig, name) => {
10927         return lookupCoupled(coupleConfig, name).getOrThunk(() => {
10928           const builder = get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
10929           const spec = builder(component);
10930           const built = component.getSystem().build(spec);
10931           coupled[name] = built;
10932           return built;
10933         });
10934       };
10935       const getExisting = (component, coupleConfig, name) => {
10936         return lookupCoupled(coupleConfig, name).orThunk(() => {
10937           get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
10938           return Optional.none();
10939         });
10940       };
10941       const readState = constant$1({});
10942       return nu$8({
10943         readState,
10944         getExisting,
10945         getOrCreate
10946       });
10947     };
10949     var CouplingState = /*#__PURE__*/Object.freeze({
10950         __proto__: null,
10951         init: init$a
10952     });
10954     const Coupling = create$4({
10955       fields: CouplingSchema,
10956       name: 'coupling',
10957       apis: CouplingApis,
10958       state: CouplingState
10959     });
10961     const nu$3 = baseFn => {
10962       let data = Optional.none();
10963       let callbacks = [];
10964       const map = f => nu$3(nCallback => {
10965         get(data => {
10966           nCallback(f(data));
10967         });
10968       });
10969       const get = nCallback => {
10970         if (isReady()) {
10971           call(nCallback);
10972         } else {
10973           callbacks.push(nCallback);
10974         }
10975       };
10976       const set = x => {
10977         if (!isReady()) {
10978           data = Optional.some(x);
10979           run(callbacks);
10980           callbacks = [];
10981         }
10982       };
10983       const isReady = () => data.isSome();
10984       const run = cbs => {
10985         each$1(cbs, call);
10986       };
10987       const call = cb => {
10988         data.each(x => {
10989           setTimeout(() => {
10990             cb(x);
10991           }, 0);
10992         });
10993       };
10994       baseFn(set);
10995       return {
10996         get,
10997         map,
10998         isReady
10999       };
11000     };
11001     const pure$1 = a => nu$3(callback => {
11002       callback(a);
11003     });
11004     const LazyValue = {
11005       nu: nu$3,
11006       pure: pure$1
11007     };
11009     const errorReporter = err => {
11010       setTimeout(() => {
11011         throw err;
11012       }, 0);
11013     };
11014     const make$5 = run => {
11015       const get = callback => {
11016         run().then(callback, errorReporter);
11017       };
11018       const map = fab => {
11019         return make$5(() => run().then(fab));
11020       };
11021       const bind = aFutureB => {
11022         return make$5(() => run().then(v => aFutureB(v).toPromise()));
11023       };
11024       const anonBind = futureB => {
11025         return make$5(() => run().then(() => futureB.toPromise()));
11026       };
11027       const toLazy = () => {
11028         return LazyValue.nu(get);
11029       };
11030       const toCached = () => {
11031         let cache = null;
11032         return make$5(() => {
11033           if (cache === null) {
11034             cache = run();
11035           }
11036           return cache;
11037         });
11038       };
11039       const toPromise = run;
11040       return {
11041         map,
11042         bind,
11043         anonBind,
11044         toLazy,
11045         toCached,
11046         toPromise,
11047         get
11048       };
11049     };
11050     const nu$2 = baseFn => {
11051       return make$5(() => new Promise(baseFn));
11052     };
11053     const pure = a => {
11054       return make$5(() => Promise.resolve(a));
11055     };
11056     const Future = {
11057       nu: nu$2,
11058       pure
11059     };
11061     const suffix = constant$1('sink');
11062     const partType$1 = constant$1(optional({
11063       name: suffix(),
11064       overrides: constant$1({
11065         dom: { tag: 'div' },
11066         behaviours: derive$1([Positioning.config({ useFixed: always })]),
11067         events: derive$2([
11068           cutter(keydown()),
11069           cutter(mousedown()),
11070           cutter(click())
11071         ])
11072       })
11073     }));
11075     const getAnchor = (detail, component) => {
11076       const hotspot = detail.getHotspot(component).getOr(component);
11077       const type = 'hotspot';
11078       const overrides = detail.getAnchorOverrides();
11079       return detail.layouts.fold(() => ({
11080         type,
11081         hotspot,
11082         overrides
11083       }), layouts => ({
11084         type,
11085         hotspot,
11086         overrides,
11087         layouts
11088       }));
11089     };
11090     const fetch = (detail, mapFetch, component) => {
11091       const fetcher = detail.fetch;
11092       return fetcher(component).map(mapFetch);
11093     };
11094     const openF = (detail, mapFetch, anchor, component, sandbox, externals, highlightOnOpen) => {
11095       const futureData = fetch(detail, mapFetch, component);
11096       const getLazySink = getSink(component, detail);
11097       return futureData.map(tdata => tdata.bind(data => Optional.from(tieredMenu.sketch({
11098         ...externals.menu(),
11099         uid: generate$5(''),
11100         data,
11101         highlightOnOpen,
11102         onOpenMenu: (tmenu, menu) => {
11103           const sink = getLazySink().getOrDie();
11104           Positioning.position(sink, menu, { anchor });
11105           Sandboxing.decloak(sandbox);
11106         },
11107         onOpenSubmenu: (tmenu, item, submenu) => {
11108           const sink = getLazySink().getOrDie();
11109           Positioning.position(sink, submenu, {
11110             anchor: {
11111               type: 'submenu',
11112               item
11113             }
11114           });
11115           Sandboxing.decloak(sandbox);
11116         },
11117         onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
11118           const sink = getLazySink().getOrDie();
11119           Positioning.position(sink, primaryMenu, { anchor });
11120           each$1(submenuTriggers, st => {
11121             Positioning.position(sink, st.triggeredMenu, {
11122               anchor: {
11123                 type: 'submenu',
11124                 item: st.triggeringItem
11125               }
11126             });
11127           });
11128         },
11129         onEscape: () => {
11130           Focusing.focus(component);
11131           Sandboxing.close(sandbox);
11132           return Optional.some(true);
11133         }
11134       }))));
11135     };
11136     const open = (detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen) => {
11137       const anchor = getAnchor(detail, hotspot);
11138       const processed = openF(detail, mapFetch, anchor, hotspot, sandbox, externals, highlightOnOpen);
11139       return processed.map(tdata => {
11140         tdata.fold(() => {
11141           if (Sandboxing.isOpen(sandbox)) {
11142             Sandboxing.close(sandbox);
11143           }
11144         }, data => {
11145           Sandboxing.cloak(sandbox);
11146           Sandboxing.open(sandbox, data);
11147           onOpenSync(sandbox);
11148         });
11149         return sandbox;
11150       });
11151     };
11152     const close = (detail, mapFetch, component, sandbox, _externals, _onOpenSync, _highlightOnOpen) => {
11153       Sandboxing.close(sandbox);
11154       return Future.pure(sandbox);
11155     };
11156     const togglePopup = (detail, mapFetch, hotspot, externals, onOpenSync, highlightOnOpen) => {
11157       const sandbox = Coupling.getCoupled(hotspot, 'sandbox');
11158       const showing = Sandboxing.isOpen(sandbox);
11159       const action = showing ? close : open;
11160       return action(detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen);
11161     };
11162     const matchWidth = (hotspot, container, useMinWidth) => {
11163       const menu = Composing.getCurrent(container).getOr(container);
11164       const buttonWidth = get$c(hotspot.element);
11165       if (useMinWidth) {
11166         set$8(menu.element, 'min-width', buttonWidth + 'px');
11167       } else {
11168         set$7(menu.element, buttonWidth);
11169       }
11170     };
11171     const getSink = (anyInSystem, sinkDetail) => anyInSystem.getSystem().getByUid(sinkDetail.uid + '-' + suffix()).map(internalSink => () => Result.value(internalSink)).getOrThunk(() => sinkDetail.lazySink.fold(() => () => Result.error(new Error('No internal sink is specified, nor could an external sink be found')), lazySinkFn => () => lazySinkFn(anyInSystem)));
11172     const doRepositionMenus = sandbox => {
11173       Sandboxing.getState(sandbox).each(tmenu => {
11174         tieredMenu.repositionMenus(tmenu);
11175       });
11176     };
11177     const makeSandbox$1 = (detail, hotspot, extras) => {
11178       const ariaControls = manager();
11179       const onOpen = (component, menu) => {
11180         const anchor = getAnchor(detail, hotspot);
11181         ariaControls.link(hotspot.element);
11182         if (detail.matchWidth) {
11183           matchWidth(anchor.hotspot, menu, detail.useMinWidth);
11184         }
11185         detail.onOpen(anchor, component, menu);
11186         if (extras !== undefined && extras.onOpen !== undefined) {
11187           extras.onOpen(component, menu);
11188         }
11189       };
11190       const onClose = (component, menu) => {
11191         ariaControls.unlink(hotspot.element);
11192         if (extras !== undefined && extras.onClose !== undefined) {
11193           extras.onClose(component, menu);
11194         }
11195       };
11196       const lazySink = getSink(hotspot, detail);
11197       return {
11198         dom: {
11199           tag: 'div',
11200           classes: detail.sandboxClasses,
11201           attributes: {
11202             id: ariaControls.id,
11203             role: 'listbox'
11204           }
11205         },
11206         behaviours: SketchBehaviours.augment(detail.sandboxBehaviours, [
11207           Representing.config({
11208             store: {
11209               mode: 'memory',
11210               initialValue: hotspot
11211             }
11212           }),
11213           Sandboxing.config({
11214             onOpen,
11215             onClose,
11216             isPartOf: (container, data, queryElem) => {
11217               return isPartOf$1(data, queryElem) || isPartOf$1(hotspot, queryElem);
11218             },
11219             getAttachPoint: () => {
11220               return lazySink().getOrDie();
11221             }
11222           }),
11223           Composing.config({
11224             find: sandbox => {
11225               return Sandboxing.getState(sandbox).bind(menu => Composing.getCurrent(menu));
11226             }
11227           }),
11228           Receiving.config({
11229             channels: {
11230               ...receivingChannel$1({ isExtraPart: never }),
11231               ...receivingChannel({ doReposition: doRepositionMenus })
11232             }
11233           })
11234         ])
11235       };
11236     };
11237     const repositionMenus = comp => {
11238       const sandbox = Coupling.getCoupled(comp, 'sandbox');
11239       doRepositionMenus(sandbox);
11240     };
11242     const sandboxFields = () => [
11243       defaulted('sandboxClasses', []),
11244       SketchBehaviours.field('sandboxBehaviours', [
11245         Composing,
11246         Receiving,
11247         Sandboxing,
11248         Representing
11249       ])
11250     ];
11252     const schema$k = constant$1([
11253       required$1('dom'),
11254       required$1('fetch'),
11255       onHandler('onOpen'),
11256       onKeyboardHandler('onExecute'),
11257       defaulted('getHotspot', Optional.some),
11258       defaulted('getAnchorOverrides', constant$1({})),
11259       schema$y(),
11260       field('dropdownBehaviours', [
11261         Toggling,
11262         Coupling,
11263         Keying,
11264         Focusing
11265       ]),
11266       required$1('toggleClass'),
11267       defaulted('eventOrder', {}),
11268       option$3('lazySink'),
11269       defaulted('matchWidth', false),
11270       defaulted('useMinWidth', false),
11271       option$3('role')
11272     ].concat(sandboxFields()));
11273     const parts$e = constant$1([
11274       external({
11275         schema: [
11276           tieredMenuMarkers(),
11277           defaulted('fakeFocus', false)
11278         ],
11279         name: 'menu',
11280         defaults: detail => {
11281           return { onExecute: detail.onExecute };
11282         }
11283       }),
11284       partType$1()
11285     ]);
11287     const factory$i = (detail, components, _spec, externals) => {
11288       const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
11289       const switchToMenu = sandbox => {
11290         Sandboxing.getState(sandbox).each(tmenu => {
11291           tieredMenu.highlightPrimary(tmenu);
11292         });
11293       };
11294       const togglePopup$1 = (dropdownComp, onOpenSync, highlightOnOpen) => {
11295         return togglePopup(detail, identity, dropdownComp, externals, onOpenSync, highlightOnOpen);
11296       };
11297       const action = component => {
11298         const onOpenSync = switchToMenu;
11299         togglePopup$1(component, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
11300       };
11301       const apis = {
11302         expand: comp => {
11303           if (!Toggling.isOn(comp)) {
11304             togglePopup$1(comp, noop, HighlightOnOpen.HighlightNone).get(noop);
11305           }
11306         },
11307         open: comp => {
11308           if (!Toggling.isOn(comp)) {
11309             togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
11310           }
11311         },
11312         refetch: comp => {
11313           const optSandbox = Coupling.getExistingCoupled(comp, 'sandbox');
11314           return optSandbox.fold(() => {
11315             return togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
11316           }, sandboxComp => {
11317             return open(detail, identity, comp, sandboxComp, externals, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
11318           });
11319         },
11320         isOpen: Toggling.isOn,
11321         close: comp => {
11322           if (Toggling.isOn(comp)) {
11323             togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
11324           }
11325         },
11326         repositionMenus: comp => {
11327           if (Toggling.isOn(comp)) {
11328             repositionMenus(comp);
11329           }
11330         }
11331       };
11332       const triggerExecute = (comp, _se) => {
11333         emitExecute(comp);
11334         return Optional.some(true);
11335       };
11336       return {
11337         uid: detail.uid,
11338         dom: detail.dom,
11339         components,
11340         behaviours: augment(detail.dropdownBehaviours, [
11341           Toggling.config({
11342             toggleClass: detail.toggleClass,
11343             aria: { mode: 'expanded' }
11344           }),
11345           Coupling.config({
11346             others: {
11347               sandbox: hotspot => {
11348                 return makeSandbox$1(detail, hotspot, {
11349                   onOpen: () => Toggling.on(hotspot),
11350                   onClose: () => Toggling.off(hotspot)
11351                 });
11352               }
11353             }
11354           }),
11355           Keying.config({
11356             mode: 'special',
11357             onSpace: triggerExecute,
11358             onEnter: triggerExecute,
11359             onDown: (comp, _se) => {
11360               if (Dropdown.isOpen(comp)) {
11361                 const sandbox = Coupling.getCoupled(comp, 'sandbox');
11362                 switchToMenu(sandbox);
11363               } else {
11364                 Dropdown.open(comp);
11365               }
11366               return Optional.some(true);
11367             },
11368             onEscape: (comp, _se) => {
11369               if (Dropdown.isOpen(comp)) {
11370                 Dropdown.close(comp);
11371                 return Optional.some(true);
11372               } else {
11373                 return Optional.none();
11374               }
11375             }
11376           }),
11377           Focusing.config({})
11378         ]),
11379         events: events$a(Optional.some(action)),
11380         eventOrder: {
11381           ...detail.eventOrder,
11382           [execute$5()]: [
11383             'disabling',
11384             'toggling',
11385             'alloy.base.behaviour'
11386           ]
11387         },
11388         apis,
11389         domModification: {
11390           attributes: {
11391             'aria-haspopup': 'true',
11392             ...detail.role.fold(() => ({}), role => ({ role })),
11393             ...detail.dom.tag === 'button' ? { type: lookupAttr('type').getOr('button') } : {}
11394           }
11395         }
11396       };
11397     };
11398     const Dropdown = composite({
11399       name: 'Dropdown',
11400       configFields: schema$k(),
11401       partFields: parts$e(),
11402       factory: factory$i,
11403       apis: {
11404         open: (apis, comp) => apis.open(comp),
11405         refetch: (apis, comp) => apis.refetch(comp),
11406         expand: (apis, comp) => apis.expand(comp),
11407         close: (apis, comp) => apis.close(comp),
11408         isOpen: (apis, comp) => apis.isOpen(comp),
11409         repositionMenus: (apis, comp) => apis.repositionMenus(comp)
11410       }
11411     });
11413     const identifyMenuLayout = searchMode => {
11414       switch (searchMode.searchMode) {
11415       case 'no-search': {
11416           return { menuType: 'normal' };
11417         }
11418       default: {
11419           return {
11420             menuType: 'searchable',
11421             searchMode
11422           };
11423         }
11424       }
11425     };
11426     const handleRefetchTrigger = originalSandboxComp => {
11427       const dropdown = Representing.getValue(originalSandboxComp);
11428       const optSearcherState = findWithinSandbox(originalSandboxComp).map(saveState);
11429       Dropdown.refetch(dropdown).get(() => {
11430         const newSandboxComp = Coupling.getCoupled(dropdown, 'sandbox');
11431         optSearcherState.each(searcherState => findWithinSandbox(newSandboxComp).each(inputComp => restoreState(inputComp, searcherState)));
11432       });
11433     };
11434     const handleRedirectToMenuItem = (sandboxComp, se) => {
11435       getActiveMenuItemFrom(sandboxComp).each(activeItem => {
11436         retargetAndDispatchWith(sandboxComp, activeItem.element, se.event.eventType, se.event.interactionEvent);
11437       });
11438     };
11439     const getActiveMenuItemFrom = sandboxComp => {
11440       return Sandboxing.getState(sandboxComp).bind(Highlighting.getHighlighted).bind(Highlighting.getHighlighted);
11441     };
11442     const getSearchResults = activeMenuComp => {
11443       return has(activeMenuComp.element, searchResultsClass) ? Optional.some(activeMenuComp.element) : descendant(activeMenuComp.element, '.' + searchResultsClass);
11444     };
11445     const updateAriaOnHighlight = (tmenuComp, menuComp, itemComp) => {
11446       findWithinMenu(tmenuComp).each(inputComp => {
11447         setActiveDescendant(inputComp, itemComp);
11448         const optActiveResults = getSearchResults(menuComp);
11449         optActiveResults.each(resultsElem => {
11450           getOpt(resultsElem, 'id').each(controlledId => set$9(inputComp.element, 'aria-controls', controlledId));
11451         });
11452       });
11453       set$9(itemComp.element, 'aria-selected', 'true');
11454     };
11455     const updateAriaOnDehighlight = (tmenuComp, menuComp, itemComp) => {
11456       set$9(itemComp.element, 'aria-selected', 'false');
11457     };
11458     const focusSearchField = tmenuComp => {
11459       findWithinMenu(tmenuComp).each(searcherComp => Focusing.focus(searcherComp));
11460     };
11461     const getSearchPattern = dropdownComp => {
11462       const optSandboxComp = Coupling.getExistingCoupled(dropdownComp, 'sandbox');
11463       return optSandboxComp.bind(findWithinSandbox).map(saveState).map(state => state.fetchPattern).getOr('');
11464     };
11466     var FocusMode;
11467     (function (FocusMode) {
11468       FocusMode[FocusMode['ContentFocus'] = 0] = 'ContentFocus';
11469       FocusMode[FocusMode['UiFocus'] = 1] = 'UiFocus';
11470     }(FocusMode || (FocusMode = {})));
11471     const createMenuItemFromBridge = (item, itemResponse, backstage, menuHasIcons, isHorizontalMenu) => {
11472       const providersBackstage = backstage.shared.providers;
11473       const parseForHorizontalMenu = menuitem => !isHorizontalMenu ? menuitem : {
11474         ...menuitem,
11475         shortcut: Optional.none(),
11476         icon: menuitem.text.isSome() ? Optional.none() : menuitem.icon
11477       };
11478       switch (item.type) {
11479       case 'menuitem':
11480         return createMenuItem(item).fold(handleError, d => Optional.some(normal(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
11481       case 'nestedmenuitem':
11482         return createNestedMenuItem(item).fold(handleError, d => Optional.some(nested(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons, isHorizontalMenu)));
11483       case 'togglemenuitem':
11484         return createToggleMenuItem(item).fold(handleError, d => Optional.some(toggle$1(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
11485       case 'separator':
11486         return createSeparatorMenuItem(item).fold(handleError, d => Optional.some(separator$3(d)));
11487       case 'fancymenuitem':
11488         return createFancyMenuItem(item).fold(handleError, d => fancy(d, backstage));
11489       default: {
11490           console.error('Unknown item in general menu', item);
11491           return Optional.none();
11492         }
11493       }
11494     };
11495     const createAutocompleteItems = (items, matchText, onItemValueHandler, columns, itemResponse, sharedBackstage, highlightOn) => {
11496       const renderText = columns === 1;
11497       const renderIcons = !renderText || menuHasIcons(items);
11498       return cat(map$2(items, item => {
11499         switch (item.type) {
11500         case 'separator':
11501           return createSeparatorItem(item).fold(handleError, d => Optional.some(separator$3(d)));
11502         case 'cardmenuitem':
11503           return createCardMenuItem(item).fold(handleError, d => Optional.some(card({
11504             ...d,
11505             onAction: api => {
11506               d.onAction(api);
11507               onItemValueHandler(d.value, d.meta);
11508             }
11509           }, itemResponse, sharedBackstage, {
11510             itemBehaviours: tooltipBehaviour(d.meta, sharedBackstage),
11511             cardText: {
11512               matchText,
11513               highlightOn
11514             }
11515           })));
11516         case 'autocompleteitem':
11517         default:
11518           return createAutocompleterItem(item).fold(handleError, d => Optional.some(autocomplete(d, matchText, renderText, 'normal', onItemValueHandler, itemResponse, sharedBackstage, renderIcons)));
11519         }
11520       }));
11521     };
11522     const createPartialMenu = (value, items, itemResponse, backstage, isHorizontalMenu, searchMode) => {
11523       const hasIcons = menuHasIcons(items);
11524       const alloyItems = cat(map$2(items, item => {
11525         const itemHasIcon = i => isHorizontalMenu ? !has$2(i, 'text') : hasIcons;
11526         const createItem = i => createMenuItemFromBridge(i, itemResponse, backstage, itemHasIcon(i), isHorizontalMenu);
11527         if (item.type === 'nestedmenuitem' && item.getSubmenuItems().length <= 0) {
11528           return createItem({
11529             ...item,
11530             enabled: false
11531           });
11532         } else {
11533           return createItem(item);
11534         }
11535       }));
11536       const menuLayout = identifyMenuLayout(searchMode);
11537       const createPartial = isHorizontalMenu ? createHorizontalPartialMenuWithAlloyItems : createPartialMenuWithAlloyItems;
11538       return createPartial(value, hasIcons, alloyItems, 1, menuLayout);
11539     };
11540     const createTieredDataFrom = partialMenu => tieredMenu.singleData(partialMenu.value, partialMenu);
11541     const createInlineMenuFrom = (partialMenu, columns, focusMode, presets) => {
11542       const movement = deriveMenuMovement(columns, presets);
11543       const menuMarkers = markers(presets);
11544       return {
11545         data: createTieredDataFrom({
11546           ...partialMenu,
11547           movement,
11548           menuBehaviours: SimpleBehaviours.unnamedEvents(columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
11549               detectSize(comp, 4, menuMarkers.item).each(({numColumns, numRows}) => {
11550                 Keying.setGridSize(comp, numRows, numColumns);
11551               });
11552             })])
11553         }),
11554         menu: {
11555           markers: markers(presets),
11556           fakeFocus: focusMode === FocusMode.ContentFocus
11557         }
11558       };
11559     };
11561     const getAutocompleterRange = (dom, initRange) => {
11562       return detect(SugarElement.fromDom(initRange.startContainer)).map(elm => {
11563         const range = dom.createRng();
11564         range.selectNode(elm.dom);
11565         return range;
11566       });
11567     };
11568     const register$b = (editor, sharedBackstage) => {
11569       const processingAction = Cell(false);
11570       const activeState = Cell(false);
11571       const autocompleter = build$1(InlineView.sketch({
11572         dom: {
11573           tag: 'div',
11574           classes: ['tox-autocompleter']
11575         },
11576         components: [],
11577         fireDismissalEventInstead: {},
11578         inlineBehaviours: derive$1([config('dismissAutocompleter', [run$1(dismissRequested(), () => cancelIfNecessary())])]),
11579         lazySink: sharedBackstage.getSink
11580       }));
11581       const isMenuOpen = () => InlineView.isOpen(autocompleter);
11582       const isActive = activeState.get;
11583       const hideIfNecessary = () => {
11584         if (isMenuOpen()) {
11585           InlineView.hide(autocompleter);
11586         }
11587       };
11588       const getMenu = () => InlineView.getContent(autocompleter).bind(tmenu => {
11589         return get$h(tmenu.components(), 0);
11590       });
11591       const cancelIfNecessary = () => editor.execCommand('mceAutocompleterClose');
11592       const getCombinedItems = matches => {
11593         const columns = findMap(matches, m => Optional.from(m.columns)).getOr(1);
11594         return bind$3(matches, match => {
11595           const choices = match.items;
11596           return createAutocompleteItems(choices, match.matchText, (itemValue, itemMeta) => {
11597             const nr = editor.selection.getRng();
11598             getAutocompleterRange(editor.dom, nr).each(range => {
11599               const autocompleterApi = {
11600                 hide: () => cancelIfNecessary(),
11601                 reload: fetchOptions => {
11602                   hideIfNecessary();
11603                   editor.execCommand('mceAutocompleterReload', false, { fetchOptions });
11604                 }
11605               };
11606               processingAction.set(true);
11607               match.onAction(autocompleterApi, range, itemValue, itemMeta);
11608               processingAction.set(false);
11609             });
11610           }, columns, ItemResponse$1.BUBBLE_TO_SANDBOX, sharedBackstage, match.highlightOn);
11611         });
11612       };
11613       const display = (lookupData, items) => {
11614         findIn(SugarElement.fromDom(editor.getBody())).each(element => {
11615           const columns = findMap(lookupData, ld => Optional.from(ld.columns)).getOr(1);
11616           InlineView.showMenuAt(autocompleter, {
11617             anchor: {
11618               type: 'node',
11619               root: SugarElement.fromDom(editor.getBody()),
11620               node: Optional.from(element)
11621             }
11622           }, createInlineMenuFrom(createPartialMenuWithAlloyItems('autocompleter-value', true, items, columns, { menuType: 'normal' }), columns, FocusMode.ContentFocus, 'normal'));
11623         });
11624         getMenu().each(Highlighting.highlightFirst);
11625       };
11626       const updateDisplay = lookupData => {
11627         const combinedItems = getCombinedItems(lookupData);
11628         if (combinedItems.length > 0) {
11629           display(lookupData, combinedItems);
11630         } else {
11631           hideIfNecessary();
11632         }
11633       };
11634       editor.on('AutocompleterStart', ({lookupData}) => {
11635         activeState.set(true);
11636         processingAction.set(false);
11637         updateDisplay(lookupData);
11638       });
11639       editor.on('AutocompleterUpdate', ({lookupData}) => updateDisplay(lookupData));
11640       editor.on('AutocompleterEnd', () => {
11641         hideIfNecessary();
11642         activeState.set(false);
11643         processingAction.set(false);
11644       });
11645       const autocompleterUiApi = {
11646         cancelIfNecessary,
11647         isMenuOpen,
11648         isActive,
11649         isProcessingAction: processingAction.get,
11650         getMenu
11651       };
11652       AutocompleterEditorEvents.setup(autocompleterUiApi, editor);
11653     };
11654     const Autocompleter = { register: register$b };
11656     const closest = (scope, selector, isRoot) => closest$1(scope, selector, isRoot).isSome();
11658     const DelayedFunction = (fun, delay) => {
11659       let ref = null;
11660       const schedule = (...args) => {
11661         ref = setTimeout(() => {
11662           fun.apply(null, args);
11663           ref = null;
11664         }, delay);
11665       };
11666       const cancel = () => {
11667         if (ref !== null) {
11668           clearTimeout(ref);
11669           ref = null;
11670         }
11671       };
11672       return {
11673         cancel,
11674         schedule
11675       };
11676     };
11678     const SIGNIFICANT_MOVE = 5;
11679     const LONGPRESS_DELAY = 400;
11680     const getTouch = event => {
11681       const raw = event.raw;
11682       if (raw.touches === undefined || raw.touches.length !== 1) {
11683         return Optional.none();
11684       }
11685       return Optional.some(raw.touches[0]);
11686     };
11687     const isFarEnough = (touch, data) => {
11688       const distX = Math.abs(touch.clientX - data.x);
11689       const distY = Math.abs(touch.clientY - data.y);
11690       return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
11691     };
11692     const monitor = settings => {
11693       const startData = value$2();
11694       const longpressFired = Cell(false);
11695       const longpress$1 = DelayedFunction(event => {
11696         settings.triggerEvent(longpress(), event);
11697         longpressFired.set(true);
11698       }, LONGPRESS_DELAY);
11699       const handleTouchstart = event => {
11700         getTouch(event).each(touch => {
11701           longpress$1.cancel();
11702           const data = {
11703             x: touch.clientX,
11704             y: touch.clientY,
11705             target: event.target
11706           };
11707           longpress$1.schedule(event);
11708           longpressFired.set(false);
11709           startData.set(data);
11710         });
11711         return Optional.none();
11712       };
11713       const handleTouchmove = event => {
11714         longpress$1.cancel();
11715         getTouch(event).each(touch => {
11716           startData.on(data => {
11717             if (isFarEnough(touch, data)) {
11718               startData.clear();
11719             }
11720           });
11721         });
11722         return Optional.none();
11723       };
11724       const handleTouchend = event => {
11725         longpress$1.cancel();
11726         const isSame = data => eq(data.target, event.target);
11727         return startData.get().filter(isSame).map(_data => {
11728           if (longpressFired.get()) {
11729             event.prevent();
11730             return false;
11731           } else {
11732             return settings.triggerEvent(tap(), event);
11733           }
11734         });
11735       };
11736       const handlers = wrapAll([
11737         {
11738           key: touchstart(),
11739           value: handleTouchstart
11740         },
11741         {
11742           key: touchmove(),
11743           value: handleTouchmove
11744         },
11745         {
11746           key: touchend(),
11747           value: handleTouchend
11748         }
11749       ]);
11750       const fireIfReady = (event, type) => get$g(handlers, type).bind(handler => handler(event));
11751       return { fireIfReady };
11752     };
11754     const isDangerous = event => {
11755       const keyEv = event.raw;
11756       return keyEv.which === BACKSPACE[0] && !contains$2([
11757         'input',
11758         'textarea'
11759       ], name$3(event.target)) && !closest(event.target, '[contenteditable="true"]');
11760     };
11761     const setup$d = (container, rawSettings) => {
11762       const settings = {
11763         stopBackspace: true,
11764         ...rawSettings
11765       };
11766       const pointerEvents = [
11767         'touchstart',
11768         'touchmove',
11769         'touchend',
11770         'touchcancel',
11771         'gesturestart',
11772         'mousedown',
11773         'mouseup',
11774         'mouseover',
11775         'mousemove',
11776         'mouseout',
11777         'click'
11778       ];
11779       const tapEvent = monitor(settings);
11780       const simpleEvents = map$2(pointerEvents.concat([
11781         'selectstart',
11782         'input',
11783         'contextmenu',
11784         'change',
11785         'transitionend',
11786         'transitioncancel',
11787         'drag',
11788         'dragstart',
11789         'dragend',
11790         'dragenter',
11791         'dragleave',
11792         'dragover',
11793         'drop',
11794         'keyup'
11795       ]), type => bind(container, type, event => {
11796         tapEvent.fireIfReady(event, type).each(tapStopped => {
11797           if (tapStopped) {
11798             event.kill();
11799           }
11800         });
11801         const stopped = settings.triggerEvent(type, event);
11802         if (stopped) {
11803           event.kill();
11804         }
11805       }));
11806       const pasteTimeout = value$2();
11807       const onPaste = bind(container, 'paste', event => {
11808         tapEvent.fireIfReady(event, 'paste').each(tapStopped => {
11809           if (tapStopped) {
11810             event.kill();
11811           }
11812         });
11813         const stopped = settings.triggerEvent('paste', event);
11814         if (stopped) {
11815           event.kill();
11816         }
11817         pasteTimeout.set(setTimeout(() => {
11818           settings.triggerEvent(postPaste(), event);
11819         }, 0));
11820       });
11821       const onKeydown = bind(container, 'keydown', event => {
11822         const stopped = settings.triggerEvent('keydown', event);
11823         if (stopped) {
11824           event.kill();
11825         } else if (settings.stopBackspace && isDangerous(event)) {
11826           event.prevent();
11827         }
11828       });
11829       const onFocusIn = bind(container, 'focusin', event => {
11830         const stopped = settings.triggerEvent('focusin', event);
11831         if (stopped) {
11832           event.kill();
11833         }
11834       });
11835       const focusoutTimeout = value$2();
11836       const onFocusOut = bind(container, 'focusout', event => {
11837         const stopped = settings.triggerEvent('focusout', event);
11838         if (stopped) {
11839           event.kill();
11840         }
11841         focusoutTimeout.set(setTimeout(() => {
11842           settings.triggerEvent(postBlur(), event);
11843         }, 0));
11844       });
11845       const unbind = () => {
11846         each$1(simpleEvents, e => {
11847           e.unbind();
11848         });
11849         onKeydown.unbind();
11850         onFocusIn.unbind();
11851         onFocusOut.unbind();
11852         onPaste.unbind();
11853         pasteTimeout.on(clearTimeout);
11854         focusoutTimeout.on(clearTimeout);
11855       };
11856       return { unbind };
11857     };
11859     const derive = (rawEvent, rawTarget) => {
11860       const source = get$g(rawEvent, 'target').getOr(rawTarget);
11861       return Cell(source);
11862     };
11864     const fromSource = (event, source) => {
11865       const stopper = Cell(false);
11866       const cutter = Cell(false);
11867       const stop = () => {
11868         stopper.set(true);
11869       };
11870       const cut = () => {
11871         cutter.set(true);
11872       };
11873       return {
11874         stop,
11875         cut,
11876         isStopped: stopper.get,
11877         isCut: cutter.get,
11878         event,
11879         setSource: source.set,
11880         getSource: source.get
11881       };
11882     };
11883     const fromExternal = event => {
11884       const stopper = Cell(false);
11885       const stop = () => {
11886         stopper.set(true);
11887       };
11888       return {
11889         stop,
11890         cut: noop,
11891         isStopped: stopper.get,
11892         isCut: never,
11893         event,
11894         setSource: die('Cannot set source of a broadcasted event'),
11895         getSource: die('Cannot get source of a broadcasted event')
11896       };
11897     };
11899     const adt$1 = Adt.generate([
11900       { stopped: [] },
11901       { resume: ['element'] },
11902       { complete: [] }
11903     ]);
11904     const doTriggerHandler = (lookup, eventType, rawEvent, target, source, logger) => {
11905       const handler = lookup(eventType, target);
11906       const simulatedEvent = fromSource(rawEvent, source);
11907       return handler.fold(() => {
11908         logger.logEventNoHandlers(eventType, target);
11909         return adt$1.complete();
11910       }, handlerInfo => {
11911         const descHandler = handlerInfo.descHandler;
11912         const eventHandler = getCurried(descHandler);
11913         eventHandler(simulatedEvent);
11914         if (simulatedEvent.isStopped()) {
11915           logger.logEventStopped(eventType, handlerInfo.element, descHandler.purpose);
11916           return adt$1.stopped();
11917         } else if (simulatedEvent.isCut()) {
11918           logger.logEventCut(eventType, handlerInfo.element, descHandler.purpose);
11919           return adt$1.complete();
11920         } else {
11921           return parent(handlerInfo.element).fold(() => {
11922             logger.logNoParent(eventType, handlerInfo.element, descHandler.purpose);
11923             return adt$1.complete();
11924           }, parent => {
11925             logger.logEventResponse(eventType, handlerInfo.element, descHandler.purpose);
11926             return adt$1.resume(parent);
11927           });
11928         }
11929       });
11930     };
11931     const doTriggerOnUntilStopped = (lookup, eventType, rawEvent, rawTarget, source, logger) => doTriggerHandler(lookup, eventType, rawEvent, rawTarget, source, logger).fold(always, parent => doTriggerOnUntilStopped(lookup, eventType, rawEvent, parent, source, logger), never);
11932     const triggerHandler = (lookup, eventType, rawEvent, target, logger) => {
11933       const source = derive(rawEvent, target);
11934       return doTriggerHandler(lookup, eventType, rawEvent, target, source, logger);
11935     };
11936     const broadcast = (listeners, rawEvent, _logger) => {
11937       const simulatedEvent = fromExternal(rawEvent);
11938       each$1(listeners, listener => {
11939         const descHandler = listener.descHandler;
11940         const handler = getCurried(descHandler);
11941         handler(simulatedEvent);
11942       });
11943       return simulatedEvent.isStopped();
11944     };
11945     const triggerUntilStopped = (lookup, eventType, rawEvent, logger) => triggerOnUntilStopped(lookup, eventType, rawEvent, rawEvent.target, logger);
11946     const triggerOnUntilStopped = (lookup, eventType, rawEvent, rawTarget, logger) => {
11947       const source = derive(rawEvent, rawTarget);
11948       return doTriggerOnUntilStopped(lookup, eventType, rawEvent, rawTarget, source, logger);
11949     };
11951     const eventHandler = (element, descHandler) => ({
11952       element,
11953       descHandler
11954     });
11955     const broadcastHandler = (id, handler) => ({
11956       id,
11957       descHandler: handler
11958     });
11959     const EventRegistry = () => {
11960       const registry = {};
11961       const registerId = (extraArgs, id, events) => {
11962         each(events, (v, k) => {
11963           const handlers = registry[k] !== undefined ? registry[k] : {};
11964           handlers[id] = curryArgs(v, extraArgs);
11965           registry[k] = handlers;
11966         });
11967       };
11968       const findHandler = (handlers, elem) => read$1(elem).bind(id => get$g(handlers, id)).map(descHandler => eventHandler(elem, descHandler));
11969       const filterByType = type => get$g(registry, type).map(handlers => mapToArray(handlers, (f, id) => broadcastHandler(id, f))).getOr([]);
11970       const find = (isAboveRoot, type, target) => get$g(registry, type).bind(handlers => closest$4(target, elem => findHandler(handlers, elem), isAboveRoot));
11971       const unregisterId = id => {
11972         each(registry, (handlersById, _eventName) => {
11973           if (has$2(handlersById, id)) {
11974             delete handlersById[id];
11975           }
11976         });
11977       };
11978       return {
11979         registerId,
11980         unregisterId,
11981         filterByType,
11982         find
11983       };
11984     };
11986     const Registry = () => {
11987       const events = EventRegistry();
11988       const components = {};
11989       const readOrTag = component => {
11990         const elem = component.element;
11991         return read$1(elem).getOrThunk(() => write('uid-', component.element));
11992       };
11993       const failOnDuplicate = (component, tagId) => {
11994         const conflict = components[tagId];
11995         if (conflict === component) {
11996           unregister(component);
11997         } else {
11998           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');
11999         }
12000       };
12001       const register = component => {
12002         const tagId = readOrTag(component);
12003         if (hasNonNullableKey(components, tagId)) {
12004           failOnDuplicate(component, tagId);
12005         }
12006         const extraArgs = [component];
12007         events.registerId(extraArgs, tagId, component.events);
12008         components[tagId] = component;
12009       };
12010       const unregister = component => {
12011         read$1(component.element).each(tagId => {
12012           delete components[tagId];
12013           events.unregisterId(tagId);
12014         });
12015       };
12016       const filter = type => events.filterByType(type);
12017       const find = (isAboveRoot, type, target) => events.find(isAboveRoot, type, target);
12018       const getById = id => get$g(components, id);
12019       return {
12020         find,
12021         filter,
12022         register,
12023         unregister,
12024         getById
12025       };
12026     };
12028     const factory$h = detail => {
12029       const {attributes, ...domWithoutAttributes} = detail.dom;
12030       return {
12031         uid: detail.uid,
12032         dom: {
12033           tag: 'div',
12034           attributes: {
12035             role: 'presentation',
12036             ...attributes
12037           },
12038           ...domWithoutAttributes
12039         },
12040         components: detail.components,
12041         behaviours: get$3(detail.containerBehaviours),
12042         events: detail.events,
12043         domModification: detail.domModification,
12044         eventOrder: detail.eventOrder
12045       };
12046     };
12047     const Container = single({
12048       name: 'Container',
12049       factory: factory$h,
12050       configFields: [
12051         defaulted('components', []),
12052         field('containerBehaviours', []),
12053         defaulted('events', {}),
12054         defaulted('domModification', {}),
12055         defaulted('eventOrder', {})
12056       ]
12057     });
12059     const takeover = root => {
12060       const isAboveRoot = el => parent(root.element).fold(always, parent => eq(el, parent));
12061       const registry = Registry();
12062       const lookup = (eventName, target) => registry.find(isAboveRoot, eventName, target);
12063       const domEvents = setup$d(root.element, {
12064         triggerEvent: (eventName, event) => {
12065           return monitorEvent(eventName, event.target, logger => triggerUntilStopped(lookup, eventName, event, logger));
12066         }
12067       });
12068       const systemApi = {
12069         debugInfo: constant$1('real'),
12070         triggerEvent: (eventName, target, data) => {
12071           monitorEvent(eventName, target, logger => triggerOnUntilStopped(lookup, eventName, data, target, logger));
12072         },
12073         triggerFocus: (target, originator) => {
12074           read$1(target).fold(() => {
12075             focus$3(target);
12076           }, _alloyId => {
12077             monitorEvent(focus$4(), target, logger => {
12078               triggerHandler(lookup, focus$4(), {
12079                 originator,
12080                 kill: noop,
12081                 prevent: noop,
12082                 target
12083               }, target, logger);
12084               return false;
12085             });
12086           });
12087         },
12088         triggerEscape: (comp, simulatedEvent) => {
12089           systemApi.triggerEvent('keydown', comp.element, simulatedEvent.event);
12090         },
12091         getByUid: uid => {
12092           return getByUid(uid);
12093         },
12094         getByDom: elem => {
12095           return getByDom(elem);
12096         },
12097         build: build$1,
12098         buildOrPatch: buildOrPatch,
12099         addToGui: c => {
12100           add(c);
12101         },
12102         removeFromGui: c => {
12103           remove(c);
12104         },
12105         addToWorld: c => {
12106           addToWorld(c);
12107         },
12108         removeFromWorld: c => {
12109           removeFromWorld(c);
12110         },
12111         broadcast: message => {
12112           broadcast$1(message);
12113         },
12114         broadcastOn: (channels, message) => {
12115           broadcastOn(channels, message);
12116         },
12117         broadcastEvent: (eventName, event) => {
12118           broadcastEvent(eventName, event);
12119         },
12120         isConnected: always
12121       };
12122       const addToWorld = component => {
12123         component.connect(systemApi);
12124         if (!isText(component.element)) {
12125           registry.register(component);
12126           each$1(component.components(), addToWorld);
12127           systemApi.triggerEvent(systemInit(), component.element, { target: component.element });
12128         }
12129       };
12130       const removeFromWorld = component => {
12131         if (!isText(component.element)) {
12132           each$1(component.components(), removeFromWorld);
12133           registry.unregister(component);
12134         }
12135         component.disconnect();
12136       };
12137       const add = component => {
12138         attach(root, component);
12139       };
12140       const remove = component => {
12141         detach(component);
12142       };
12143       const destroy = () => {
12144         domEvents.unbind();
12145         remove$5(root.element);
12146       };
12147       const broadcastData = data => {
12148         const receivers = registry.filter(receive());
12149         each$1(receivers, receiver => {
12150           const descHandler = receiver.descHandler;
12151           const handler = getCurried(descHandler);
12152           handler(data);
12153         });
12154       };
12155       const broadcast$1 = message => {
12156         broadcastData({
12157           universal: true,
12158           data: message
12159         });
12160       };
12161       const broadcastOn = (channels, message) => {
12162         broadcastData({
12163           universal: false,
12164           channels,
12165           data: message
12166         });
12167       };
12168       const broadcastEvent = (eventName, event) => {
12169         const listeners = registry.filter(eventName);
12170         return broadcast(listeners, event);
12171       };
12172       const getByUid = uid => registry.getById(uid).fold(() => Result.error(new Error('Could not find component with uid: "' + uid + '" in system.')), Result.value);
12173       const getByDom = elem => {
12174         const uid = read$1(elem).getOr('not found');
12175         return getByUid(uid);
12176       };
12177       addToWorld(root);
12178       return {
12179         root,
12180         element: root.element,
12181         destroy,
12182         add,
12183         remove,
12184         getByUid,
12185         getByDom,
12186         addToWorld,
12187         removeFromWorld,
12188         broadcast: broadcast$1,
12189         broadcastOn,
12190         broadcastEvent
12191       };
12192     };
12194     const renderBar = (spec, backstage) => ({
12195       dom: {
12196         tag: 'div',
12197         classes: [
12198           'tox-bar',
12199           'tox-form__controls-h-stack'
12200         ]
12201       },
12202       components: map$2(spec.items, backstage.interpreter)
12203     });
12205     const schema$j = constant$1([
12206       defaulted('prefix', 'form-field'),
12207       field('fieldBehaviours', [
12208         Composing,
12209         Representing
12210       ])
12211     ]);
12212     const parts$d = constant$1([
12213       optional({
12214         schema: [required$1('dom')],
12215         name: 'label'
12216       }),
12217       optional({
12218         factory: {
12219           sketch: spec => {
12220             return {
12221               uid: spec.uid,
12222               dom: {
12223                 tag: 'span',
12224                 styles: { display: 'none' },
12225                 attributes: { 'aria-hidden': 'true' },
12226                 innerHtml: spec.text
12227               }
12228             };
12229           }
12230         },
12231         schema: [required$1('text')],
12232         name: 'aria-descriptor'
12233       }),
12234       required({
12235         factory: {
12236           sketch: spec => {
12237             const excludeFactory = exclude(spec, ['factory']);
12238             return spec.factory.sketch(excludeFactory);
12239           }
12240         },
12241         schema: [required$1('factory')],
12242         name: 'field'
12243       })
12244     ]);
12246     const factory$g = (detail, components, _spec, _externals) => {
12247       const behaviours = augment(detail.fieldBehaviours, [
12248         Composing.config({
12249           find: container => {
12250             return getPart(container, detail, 'field');
12251           }
12252         }),
12253         Representing.config({
12254           store: {
12255             mode: 'manual',
12256             getValue: field => {
12257               return Composing.getCurrent(field).bind(Representing.getValue);
12258             },
12259             setValue: (field, value) => {
12260               Composing.getCurrent(field).each(current => {
12261                 Representing.setValue(current, value);
12262               });
12263             }
12264           }
12265         })
12266       ]);
12267       const events = derive$2([runOnAttached((component, _simulatedEvent) => {
12268           const ps = getParts(component, detail, [
12269             'label',
12270             'field',
12271             'aria-descriptor'
12272           ]);
12273           ps.field().each(field => {
12274             const id = generate$6(detail.prefix);
12275             ps.label().each(label => {
12276               set$9(label.element, 'for', id);
12277               set$9(field.element, 'id', id);
12278             });
12279             ps['aria-descriptor']().each(descriptor => {
12280               const descriptorId = generate$6(detail.prefix);
12281               set$9(descriptor.element, 'id', descriptorId);
12282               set$9(field.element, 'aria-describedby', descriptorId);
12283             });
12284           });
12285         })]);
12286       const apis = {
12287         getField: container => getPart(container, detail, 'field'),
12288         getLabel: container => getPart(container, detail, 'label')
12289       };
12290       return {
12291         uid: detail.uid,
12292         dom: detail.dom,
12293         components,
12294         behaviours,
12295         events,
12296         apis
12297       };
12298     };
12299     const FormField = composite({
12300       name: 'FormField',
12301       configFields: schema$j(),
12302       partFields: parts$d(),
12303       factory: factory$g,
12304       apis: {
12305         getField: (apis, comp) => apis.getField(comp),
12306         getLabel: (apis, comp) => apis.getLabel(comp)
12307       }
12308     });
12310     const exhibit$2 = (base, tabConfig) => nu$7({
12311       attributes: wrapAll([{
12312           key: tabConfig.tabAttr,
12313           value: 'true'
12314         }])
12315     });
12317     var ActiveTabstopping = /*#__PURE__*/Object.freeze({
12318         __proto__: null,
12319         exhibit: exhibit$2
12320     });
12322     var TabstopSchema = [defaulted('tabAttr', 'data-alloy-tabstop')];
12324     const Tabstopping = create$4({
12325       fields: TabstopSchema,
12326       name: 'tabstopping',
12327       active: ActiveTabstopping
12328     });
12330     var global$3 = tinymce.util.Tools.resolve('tinymce.html.Entities');
12332     const renderFormFieldWith = (pLabel, pField, extraClasses, extraBehaviours) => {
12333       const spec = renderFormFieldSpecWith(pLabel, pField, extraClasses, extraBehaviours);
12334       return FormField.sketch(spec);
12335     };
12336     const renderFormField = (pLabel, pField) => renderFormFieldWith(pLabel, pField, [], []);
12337     const renderFormFieldSpecWith = (pLabel, pField, extraClasses, extraBehaviours) => ({
12338       dom: renderFormFieldDomWith(extraClasses),
12339       components: pLabel.toArray().concat([pField]),
12340       fieldBehaviours: derive$1(extraBehaviours)
12341     });
12342     const renderFormFieldDom = () => renderFormFieldDomWith([]);
12343     const renderFormFieldDomWith = extraClasses => ({
12344       tag: 'div',
12345       classes: ['tox-form__group'].concat(extraClasses)
12346     });
12347     const renderLabel$2 = (label, providersBackstage) => FormField.parts.label({
12348       dom: {
12349         tag: 'label',
12350         classes: ['tox-label']
12351       },
12352       components: [text$2(providersBackstage.translate(label))]
12353     });
12355     const formChangeEvent = generate$6('form-component-change');
12356     const formCloseEvent = generate$6('form-close');
12357     const formCancelEvent = generate$6('form-cancel');
12358     const formActionEvent = generate$6('form-action');
12359     const formSubmitEvent = generate$6('form-submit');
12360     const formBlockEvent = generate$6('form-block');
12361     const formUnblockEvent = generate$6('form-unblock');
12362     const formTabChangeEvent = generate$6('form-tabchange');
12363     const formResizeEvent = generate$6('form-resize');
12365     const renderCollection = (spec, providersBackstage, initialData) => {
12366       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
12367       const runOnItem = f => (comp, se) => {
12368         closest$1(se.event.target, '[data-collection-item-value]').each(target => {
12369           f(comp, se, target, get$f(target, 'data-collection-item-value'));
12370         });
12371       };
12372       const setContents = (comp, items) => {
12373         const htmlLines = map$2(items, item => {
12374           const itemText = global$8.translate(item.text);
12375           const textContent = spec.columns === 1 ? `<div class="tox-collection__item-label">${ itemText }</div>` : '';
12376           const iconContent = `<div class="tox-collection__item-icon">${ item.icon }</div>`;
12377           const mapItemName = {
12378             '_': ' ',
12379             ' - ': ' ',
12380             '-': ' '
12381           };
12382           const ariaLabel = itemText.replace(/\_| \- |\-/g, match => mapItemName[match]);
12383           const disabledClass = providersBackstage.isDisabled() ? ' tox-collection__item--state-disabled' : '';
12384           return `<div class="tox-collection__item${ disabledClass }" tabindex="-1" data-collection-item-value="${ global$3.encodeAllRaw(item.value) }" title="${ ariaLabel }" aria-label="${ ariaLabel }">${ iconContent }${ textContent }</div>`;
12385         });
12386         const chunks = spec.columns !== 'auto' && spec.columns > 1 ? chunk$1(htmlLines, spec.columns) : [htmlLines];
12387         const html = map$2(chunks, ch => `<div class="tox-collection__group">${ ch.join('') }</div>`);
12388         set$6(comp.element, html.join(''));
12389       };
12390       const onClick = runOnItem((comp, se, tgt, itemValue) => {
12391         se.stop();
12392         if (!providersBackstage.isDisabled()) {
12393           emitWith(comp, formActionEvent, {
12394             name: spec.name,
12395             value: itemValue
12396           });
12397         }
12398       });
12399       const collectionEvents = [
12400         run$1(mouseover(), runOnItem((comp, se, tgt) => {
12401           focus$3(tgt);
12402         })),
12403         run$1(click(), onClick),
12404         run$1(tap(), onClick),
12405         run$1(focusin(), runOnItem((comp, se, tgt) => {
12406           descendant(comp.element, '.' + activeClass).each(currentActive => {
12407             remove$2(currentActive, activeClass);
12408           });
12409           add$2(tgt, activeClass);
12410         })),
12411         run$1(focusout(), runOnItem(comp => {
12412           descendant(comp.element, '.' + activeClass).each(currentActive => {
12413             remove$2(currentActive, activeClass);
12414           });
12415         })),
12416         runOnExecute$1(runOnItem((comp, se, tgt, itemValue) => {
12417           emitWith(comp, formActionEvent, {
12418             name: spec.name,
12419             value: itemValue
12420           });
12421         }))
12422       ];
12423       const iterCollectionItems = (comp, applyAttributes) => map$2(descendants(comp.element, '.tox-collection__item'), applyAttributes);
12424       const pField = FormField.parts.field({
12425         dom: {
12426           tag: 'div',
12427           classes: ['tox-collection'].concat(spec.columns !== 1 ? ['tox-collection--grid'] : ['tox-collection--list'])
12428         },
12429         components: [],
12430         factory: { sketch: identity },
12431         behaviours: derive$1([
12432           Disabling.config({
12433             disabled: providersBackstage.isDisabled,
12434             onDisabled: comp => {
12435               iterCollectionItems(comp, childElm => {
12436                 add$2(childElm, 'tox-collection__item--state-disabled');
12437                 set$9(childElm, 'aria-disabled', true);
12438               });
12439             },
12440             onEnabled: comp => {
12441               iterCollectionItems(comp, childElm => {
12442                 remove$2(childElm, 'tox-collection__item--state-disabled');
12443                 remove$7(childElm, 'aria-disabled');
12444               });
12445             }
12446           }),
12447           receivingConfig(),
12448           Replacing.config({}),
12449           Representing.config({
12450             store: {
12451               mode: 'memory',
12452               initialValue: initialData.getOr([])
12453             },
12454             onSetValue: (comp, items) => {
12455               setContents(comp, items);
12456               if (spec.columns === 'auto') {
12457                 detectSize(comp, 5, 'tox-collection__item').each(({numRows, numColumns}) => {
12458                   Keying.setGridSize(comp, numRows, numColumns);
12459                 });
12460               }
12461               emit(comp, formResizeEvent);
12462             }
12463           }),
12464           Tabstopping.config({}),
12465           Keying.config(deriveCollectionMovement(spec.columns, 'normal')),
12466           config('collection-events', collectionEvents)
12467         ]),
12468         eventOrder: {
12469           [execute$5()]: [
12470             'disabling',
12471             'alloy.base.behaviour',
12472             'collection-events'
12473           ]
12474         }
12475       });
12476       const extraClasses = ['tox-form__group--collection'];
12477       return renderFormFieldWith(pLabel, pField, extraClasses, []);
12478     };
12480     const ariaElements = [
12481       'input',
12482       'textarea'
12483     ];
12484     const isAriaElement = elem => {
12485       const name = name$3(elem);
12486       return contains$2(ariaElements, name);
12487     };
12488     const markValid = (component, invalidConfig) => {
12489       const elem = invalidConfig.getRoot(component).getOr(component.element);
12490       remove$2(elem, invalidConfig.invalidClass);
12491       invalidConfig.notify.each(notifyInfo => {
12492         if (isAriaElement(component.element)) {
12493           set$9(component.element, 'aria-invalid', false);
12494         }
12495         notifyInfo.getContainer(component).each(container => {
12496           set$6(container, notifyInfo.validHtml);
12497         });
12498         notifyInfo.onValid(component);
12499       });
12500     };
12501     const markInvalid = (component, invalidConfig, invalidState, text) => {
12502       const elem = invalidConfig.getRoot(component).getOr(component.element);
12503       add$2(elem, invalidConfig.invalidClass);
12504       invalidConfig.notify.each(notifyInfo => {
12505         if (isAriaElement(component.element)) {
12506           set$9(component.element, 'aria-invalid', true);
12507         }
12508         notifyInfo.getContainer(component).each(container => {
12509           set$6(container, text);
12510         });
12511         notifyInfo.onInvalid(component, text);
12512       });
12513     };
12514     const query = (component, invalidConfig, _invalidState) => invalidConfig.validator.fold(() => Future.pure(Result.value(true)), validatorInfo => validatorInfo.validate(component));
12515     const run = (component, invalidConfig, invalidState) => {
12516       invalidConfig.notify.each(notifyInfo => {
12517         notifyInfo.onValidate(component);
12518       });
12519       return query(component, invalidConfig).map(valid => {
12520         if (component.getSystem().isConnected()) {
12521           return valid.fold(err => {
12522             markInvalid(component, invalidConfig, invalidState, err);
12523             return Result.error(err);
12524           }, v => {
12525             markValid(component, invalidConfig);
12526             return Result.value(v);
12527           });
12528         } else {
12529           return Result.error('No longer in system');
12530         }
12531       });
12532     };
12533     const isInvalid = (component, invalidConfig) => {
12534       const elem = invalidConfig.getRoot(component).getOr(component.element);
12535       return has(elem, invalidConfig.invalidClass);
12536     };
12538     var InvalidateApis = /*#__PURE__*/Object.freeze({
12539         __proto__: null,
12540         markValid: markValid,
12541         markInvalid: markInvalid,
12542         query: query,
12543         run: run,
12544         isInvalid: isInvalid
12545     });
12547     const events$8 = (invalidConfig, invalidState) => invalidConfig.validator.map(validatorInfo => derive$2([run$1(validatorInfo.onEvent, component => {
12548         run(component, invalidConfig, invalidState).get(identity);
12549       })].concat(validatorInfo.validateOnLoad ? [runOnAttached(component => {
12550         run(component, invalidConfig, invalidState).get(noop);
12551       })] : []))).getOr({});
12553     var ActiveInvalidate = /*#__PURE__*/Object.freeze({
12554         __proto__: null,
12555         events: events$8
12556     });
12558     var InvalidateSchema = [
12559       required$1('invalidClass'),
12560       defaulted('getRoot', Optional.none),
12561       optionObjOf('notify', [
12562         defaulted('aria', 'alert'),
12563         defaulted('getContainer', Optional.none),
12564         defaulted('validHtml', ''),
12565         onHandler('onValid'),
12566         onHandler('onInvalid'),
12567         onHandler('onValidate')
12568       ]),
12569       optionObjOf('validator', [
12570         required$1('validate'),
12571         defaulted('onEvent', 'input'),
12572         defaulted('validateOnLoad', true)
12573       ])
12574     ];
12576     const Invalidating = create$4({
12577       fields: InvalidateSchema,
12578       name: 'invalidating',
12579       active: ActiveInvalidate,
12580       apis: InvalidateApis,
12581       extra: {
12582         validation: validator => {
12583           return component => {
12584             const v = Representing.getValue(component);
12585             return Future.pure(validator(v));
12586           };
12587         }
12588       }
12589     });
12591     const exhibit$1 = () => nu$7({
12592       styles: {
12593         '-webkit-user-select': 'none',
12594         'user-select': 'none',
12595         '-ms-user-select': 'none',
12596         '-moz-user-select': '-moz-none'
12597       },
12598       attributes: { unselectable: 'on' }
12599     });
12600     const events$7 = () => derive$2([abort(selectstart(), always)]);
12602     var ActiveUnselecting = /*#__PURE__*/Object.freeze({
12603         __proto__: null,
12604         events: events$7,
12605         exhibit: exhibit$1
12606     });
12608     const Unselecting = create$4({
12609       fields: [],
12610       name: 'unselecting',
12611       active: ActiveUnselecting
12612     });
12614     const renderPanelButton = (spec, sharedBackstage) => Dropdown.sketch({
12615       dom: spec.dom,
12616       components: spec.components,
12617       toggleClass: 'mce-active',
12618       dropdownBehaviours: derive$1([
12619         DisablingConfigs.button(sharedBackstage.providers.isDisabled),
12620         receivingConfig(),
12621         Unselecting.config({}),
12622         Tabstopping.config({})
12623       ]),
12624       layouts: spec.layouts,
12625       sandboxClasses: ['tox-dialog__popups'],
12626       lazySink: sharedBackstage.getSink,
12627       fetch: comp => Future.nu(callback => spec.fetch(callback)).map(items => Optional.from(createTieredDataFrom(deepMerge(createPartialChoiceMenu(generate$6('menu-value'), items, value => {
12628         spec.onItemAction(comp, value);
12629       }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, never, sharedBackstage.providers), { movement: deriveMenuMovement(spec.columns, spec.presets) })))),
12630       parts: { menu: part(false, 1, spec.presets) }
12631     });
12633     const colorInputChangeEvent = generate$6('color-input-change');
12634     const colorSwatchChangeEvent = generate$6('color-swatch-change');
12635     const colorPickerCancelEvent = generate$6('color-picker-cancel');
12636     const renderColorInput = (spec, sharedBackstage, colorInputBackstage, initialData) => {
12637       const pField = FormField.parts.field({
12638         factory: Input,
12639         inputClasses: ['tox-textfield'],
12640         data: initialData,
12641         onSetValue: c => Invalidating.run(c).get(noop),
12642         inputBehaviours: derive$1([
12643           Disabling.config({ disabled: sharedBackstage.providers.isDisabled }),
12644           receivingConfig(),
12645           Tabstopping.config({}),
12646           Invalidating.config({
12647             invalidClass: 'tox-textbox-field-invalid',
12648             getRoot: comp => parentElement(comp.element),
12649             notify: {
12650               onValid: comp => {
12651                 const val = Representing.getValue(comp);
12652                 emitWith(comp, colorInputChangeEvent, { color: val });
12653               }
12654             },
12655             validator: {
12656               validateOnLoad: false,
12657               validate: input => {
12658                 const inputValue = Representing.getValue(input);
12659                 if (inputValue.length === 0) {
12660                   return Future.pure(Result.value(true));
12661                 } else {
12662                   const span = SugarElement.fromTag('span');
12663                   set$8(span, 'background-color', inputValue);
12664                   const res = getRaw(span, 'background-color').fold(() => Result.error('blah'), _ => Result.value(inputValue));
12665                   return Future.pure(res);
12666                 }
12667               }
12668             }
12669           })
12670         ]),
12671         selectOnFocus: false
12672       });
12673       const pLabel = spec.label.map(label => renderLabel$2(label, sharedBackstage.providers));
12674       const emitSwatchChange = (colorBit, value) => {
12675         emitWith(colorBit, colorSwatchChangeEvent, { value });
12676       };
12677       const onItemAction = (comp, value) => {
12678         memColorButton.getOpt(comp).each(colorBit => {
12679           if (value === 'custom') {
12680             colorInputBackstage.colorPicker(valueOpt => {
12681               valueOpt.fold(() => emit(colorBit, colorPickerCancelEvent), value => {
12682                 emitSwatchChange(colorBit, value);
12683                 addColor(value);
12684               });
12685             }, '#ffffff');
12686           } else if (value === 'remove') {
12687             emitSwatchChange(colorBit, '');
12688           } else {
12689             emitSwatchChange(colorBit, value);
12690           }
12691         });
12692       };
12693       const memColorButton = record(renderPanelButton({
12694         dom: {
12695           tag: 'span',
12696           attributes: { 'aria-label': sharedBackstage.providers.translate('Color swatch') }
12697         },
12698         layouts: {
12699           onRtl: () => [
12700             southwest$2,
12701             southeast$2,
12702             south$2
12703           ],
12704           onLtr: () => [
12705             southeast$2,
12706             southwest$2,
12707             south$2
12708           ]
12709         },
12710         components: [],
12711         fetch: getFetch$1(colorInputBackstage.getColors(), colorInputBackstage.hasCustomColors()),
12712         columns: colorInputBackstage.getColorCols(),
12713         presets: 'color',
12714         onItemAction
12715       }, sharedBackstage));
12716       return FormField.sketch({
12717         dom: {
12718           tag: 'div',
12719           classes: ['tox-form__group']
12720         },
12721         components: pLabel.toArray().concat([{
12722             dom: {
12723               tag: 'div',
12724               classes: ['tox-color-input']
12725             },
12726             components: [
12727               pField,
12728               memColorButton.asSpec()
12729             ]
12730           }]),
12731         fieldBehaviours: derive$1([config('form-field-events', [
12732             run$1(colorInputChangeEvent, (comp, se) => {
12733               memColorButton.getOpt(comp).each(colorButton => {
12734                 set$8(colorButton.element, 'background-color', se.event.color);
12735               });
12736               emitWith(comp, formChangeEvent, { name: spec.name });
12737             }),
12738             run$1(colorSwatchChangeEvent, (comp, se) => {
12739               FormField.getField(comp).each(field => {
12740                 Representing.setValue(field, se.event.value);
12741                 Composing.getCurrent(comp).each(Focusing.focus);
12742               });
12743             }),
12744             run$1(colorPickerCancelEvent, (comp, _se) => {
12745               FormField.getField(comp).each(_field => {
12746                 Composing.getCurrent(comp).each(Focusing.focus);
12747               });
12748             })
12749           ])])
12750       });
12751     };
12753     const labelPart = optional({
12754       schema: [required$1('dom')],
12755       name: 'label'
12756     });
12757     const edgePart = name => optional({
12758       name: '' + name + '-edge',
12759       overrides: detail => {
12760         const action = detail.model.manager.edgeActions[name];
12761         return action.fold(() => ({}), a => ({
12762           events: derive$2([
12763             runActionExtra(touchstart(), (comp, se, d) => a(comp, d), [detail]),
12764             runActionExtra(mousedown(), (comp, se, d) => a(comp, d), [detail]),
12765             runActionExtra(mousemove(), (comp, se, det) => {
12766               if (det.mouseIsDown.get()) {
12767                 a(comp, det);
12768               }
12769             }, [detail])
12770           ])
12771         }));
12772       }
12773     });
12774     const tlEdgePart = edgePart('top-left');
12775     const tedgePart = edgePart('top');
12776     const trEdgePart = edgePart('top-right');
12777     const redgePart = edgePart('right');
12778     const brEdgePart = edgePart('bottom-right');
12779     const bedgePart = edgePart('bottom');
12780     const blEdgePart = edgePart('bottom-left');
12781     const ledgePart = edgePart('left');
12782     const thumbPart = required({
12783       name: 'thumb',
12784       defaults: constant$1({ dom: { styles: { position: 'absolute' } } }),
12785       overrides: detail => {
12786         return {
12787           events: derive$2([
12788             redirectToPart(touchstart(), detail, 'spectrum'),
12789             redirectToPart(touchmove(), detail, 'spectrum'),
12790             redirectToPart(touchend(), detail, 'spectrum'),
12791             redirectToPart(mousedown(), detail, 'spectrum'),
12792             redirectToPart(mousemove(), detail, 'spectrum'),
12793             redirectToPart(mouseup(), detail, 'spectrum')
12794           ])
12795         };
12796       }
12797     });
12798     const spectrumPart = required({
12799       schema: [customField('mouseIsDown', () => Cell(false))],
12800       name: 'spectrum',
12801       overrides: detail => {
12802         const modelDetail = detail.model;
12803         const model = modelDetail.manager;
12804         const setValueFrom = (component, simulatedEvent) => model.getValueFromEvent(simulatedEvent).map(value => model.setValueFrom(component, detail, value));
12805         return {
12806           behaviours: derive$1([
12807             Keying.config({
12808               mode: 'special',
12809               onLeft: spectrum => model.onLeft(spectrum, detail),
12810               onRight: spectrum => model.onRight(spectrum, detail),
12811               onUp: spectrum => model.onUp(spectrum, detail),
12812               onDown: spectrum => model.onDown(spectrum, detail)
12813             }),
12814             Focusing.config({})
12815           ]),
12816           events: derive$2([
12817             run$1(touchstart(), setValueFrom),
12818             run$1(touchmove(), setValueFrom),
12819             run$1(mousedown(), setValueFrom),
12820             run$1(mousemove(), (spectrum, se) => {
12821               if (detail.mouseIsDown.get()) {
12822                 setValueFrom(spectrum, se);
12823               }
12824             })
12825           ])
12826         };
12827       }
12828     });
12829     var SliderParts = [
12830       labelPart,
12831       ledgePart,
12832       redgePart,
12833       tedgePart,
12834       bedgePart,
12835       tlEdgePart,
12836       trEdgePart,
12837       blEdgePart,
12838       brEdgePart,
12839       thumbPart,
12840       spectrumPart
12841     ];
12843     const _sliderChangeEvent = 'slider.change.value';
12844     const sliderChangeEvent = constant$1(_sliderChangeEvent);
12845     const isTouchEvent$2 = evt => evt.type.indexOf('touch') !== -1;
12846     const getEventSource = simulatedEvent => {
12847       const evt = simulatedEvent.event.raw;
12848       if (isTouchEvent$2(evt)) {
12849         const touchEvent = evt;
12850         return touchEvent.touches !== undefined && touchEvent.touches.length === 1 ? Optional.some(touchEvent.touches[0]).map(t => SugarPosition(t.clientX, t.clientY)) : Optional.none();
12851       } else {
12852         const mouseEvent = evt;
12853         return mouseEvent.clientX !== undefined ? Optional.some(mouseEvent).map(me => SugarPosition(me.clientX, me.clientY)) : Optional.none();
12854       }
12855     };
12857     const t = 'top', r = 'right', b = 'bottom', l = 'left';
12858     const minX = detail => detail.model.minX;
12859     const minY = detail => detail.model.minY;
12860     const min1X = detail => detail.model.minX - 1;
12861     const min1Y = detail => detail.model.minY - 1;
12862     const maxX = detail => detail.model.maxX;
12863     const maxY = detail => detail.model.maxY;
12864     const max1X = detail => detail.model.maxX + 1;
12865     const max1Y = detail => detail.model.maxY + 1;
12866     const range = (detail, max, min) => max(detail) - min(detail);
12867     const xRange = detail => range(detail, maxX, minX);
12868     const yRange = detail => range(detail, maxY, minY);
12869     const halfX = detail => xRange(detail) / 2;
12870     const halfY = detail => yRange(detail) / 2;
12871     const step = detail => detail.stepSize;
12872     const snap = detail => detail.snapToGrid;
12873     const snapStart = detail => detail.snapStart;
12874     const rounded = detail => detail.rounded;
12875     const hasEdge = (detail, edgeName) => detail[edgeName + '-edge'] !== undefined;
12876     const hasLEdge = detail => hasEdge(detail, l);
12877     const hasREdge = detail => hasEdge(detail, r);
12878     const hasTEdge = detail => hasEdge(detail, t);
12879     const hasBEdge = detail => hasEdge(detail, b);
12880     const currentValue = detail => detail.model.value.get();
12882     const xyValue = (x, y) => ({
12883       x,
12884       y
12885     });
12886     const fireSliderChange$3 = (component, value) => {
12887       emitWith(component, sliderChangeEvent(), { value });
12888     };
12889     const setToTLEdgeXY = (edge, detail) => {
12890       fireSliderChange$3(edge, xyValue(min1X(detail), min1Y(detail)));
12891     };
12892     const setToTEdge = (edge, detail) => {
12893       fireSliderChange$3(edge, min1Y(detail));
12894     };
12895     const setToTEdgeXY = (edge, detail) => {
12896       fireSliderChange$3(edge, xyValue(halfX(detail), min1Y(detail)));
12897     };
12898     const setToTREdgeXY = (edge, detail) => {
12899       fireSliderChange$3(edge, xyValue(max1X(detail), min1Y(detail)));
12900     };
12901     const setToREdge = (edge, detail) => {
12902       fireSliderChange$3(edge, max1X(detail));
12903     };
12904     const setToREdgeXY = (edge, detail) => {
12905       fireSliderChange$3(edge, xyValue(max1X(detail), halfY(detail)));
12906     };
12907     const setToBREdgeXY = (edge, detail) => {
12908       fireSliderChange$3(edge, xyValue(max1X(detail), max1Y(detail)));
12909     };
12910     const setToBEdge = (edge, detail) => {
12911       fireSliderChange$3(edge, max1Y(detail));
12912     };
12913     const setToBEdgeXY = (edge, detail) => {
12914       fireSliderChange$3(edge, xyValue(halfX(detail), max1Y(detail)));
12915     };
12916     const setToBLEdgeXY = (edge, detail) => {
12917       fireSliderChange$3(edge, xyValue(min1X(detail), max1Y(detail)));
12918     };
12919     const setToLEdge = (edge, detail) => {
12920       fireSliderChange$3(edge, min1X(detail));
12921     };
12922     const setToLEdgeXY = (edge, detail) => {
12923       fireSliderChange$3(edge, xyValue(min1X(detail), halfY(detail)));
12924     };
12926     const reduceBy = (value, min, max, step) => {
12927       if (value < min) {
12928         return value;
12929       } else if (value > max) {
12930         return max;
12931       } else if (value === min) {
12932         return min - 1;
12933       } else {
12934         return Math.max(min, value - step);
12935       }
12936     };
12937     const increaseBy = (value, min, max, step) => {
12938       if (value > max) {
12939         return value;
12940       } else if (value < min) {
12941         return min;
12942       } else if (value === max) {
12943         return max + 1;
12944       } else {
12945         return Math.min(max, value + step);
12946       }
12947     };
12948     const capValue = (value, min, max) => Math.max(min, Math.min(max, value));
12949     const snapValueOf = (value, min, max, step, snapStart) => snapStart.fold(() => {
12950       const initValue = value - min;
12951       const extraValue = Math.round(initValue / step) * step;
12952       return capValue(min + extraValue, min - 1, max + 1);
12953     }, start => {
12954       const remainder = (value - start) % step;
12955       const adjustment = Math.round(remainder / step);
12956       const rawSteps = Math.floor((value - start) / step);
12957       const maxSteps = Math.floor((max - start) / step);
12958       const numSteps = Math.min(maxSteps, rawSteps + adjustment);
12959       const r = start + numSteps * step;
12960       return Math.max(start, r);
12961     });
12962     const findOffsetOf = (value, min, max) => Math.min(max, Math.max(value, min)) - min;
12963     const findValueOf = args => {
12964       const {min, max, range, value, step, snap, snapStart, rounded, hasMinEdge, hasMaxEdge, minBound, maxBound, screenRange} = args;
12965       const capMin = hasMinEdge ? min - 1 : min;
12966       const capMax = hasMaxEdge ? max + 1 : max;
12967       if (value < minBound) {
12968         return capMin;
12969       } else if (value > maxBound) {
12970         return capMax;
12971       } else {
12972         const offset = findOffsetOf(value, minBound, maxBound);
12973         const newValue = capValue(offset / screenRange * range + min, capMin, capMax);
12974         if (snap && newValue >= min && newValue <= max) {
12975           return snapValueOf(newValue, min, max, step, snapStart);
12976         } else if (rounded) {
12977           return Math.round(newValue);
12978         } else {
12979           return newValue;
12980         }
12981       }
12982     };
12983     const findOffsetOfValue$2 = args => {
12984       const {min, max, range, value, hasMinEdge, hasMaxEdge, maxBound, maxOffset, centerMinEdge, centerMaxEdge} = args;
12985       if (value < min) {
12986         return hasMinEdge ? 0 : centerMinEdge;
12987       } else if (value > max) {
12988         return hasMaxEdge ? maxBound : centerMaxEdge;
12989       } else {
12990         return (value - min) / range * maxOffset;
12991       }
12992     };
12994     const top = 'top', right = 'right', bottom = 'bottom', left = 'left', width = 'width', height = 'height';
12995     const getBounds = component => component.element.dom.getBoundingClientRect();
12996     const getBoundsProperty = (bounds, property) => bounds[property];
12997     const getMinXBounds = component => {
12998       const bounds = getBounds(component);
12999       return getBoundsProperty(bounds, left);
13000     };
13001     const getMaxXBounds = component => {
13002       const bounds = getBounds(component);
13003       return getBoundsProperty(bounds, right);
13004     };
13005     const getMinYBounds = component => {
13006       const bounds = getBounds(component);
13007       return getBoundsProperty(bounds, top);
13008     };
13009     const getMaxYBounds = component => {
13010       const bounds = getBounds(component);
13011       return getBoundsProperty(bounds, bottom);
13012     };
13013     const getXScreenRange = component => {
13014       const bounds = getBounds(component);
13015       return getBoundsProperty(bounds, width);
13016     };
13017     const getYScreenRange = component => {
13018       const bounds = getBounds(component);
13019       return getBoundsProperty(bounds, height);
13020     };
13021     const getCenterOffsetOf = (componentMinEdge, componentMaxEdge, spectrumMinEdge) => (componentMinEdge + componentMaxEdge) / 2 - spectrumMinEdge;
13022     const getXCenterOffSetOf = (component, spectrum) => {
13023       const componentBounds = getBounds(component);
13024       const spectrumBounds = getBounds(spectrum);
13025       const componentMinEdge = getBoundsProperty(componentBounds, left);
13026       const componentMaxEdge = getBoundsProperty(componentBounds, right);
13027       const spectrumMinEdge = getBoundsProperty(spectrumBounds, left);
13028       return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
13029     };
13030     const getYCenterOffSetOf = (component, spectrum) => {
13031       const componentBounds = getBounds(component);
13032       const spectrumBounds = getBounds(spectrum);
13033       const componentMinEdge = getBoundsProperty(componentBounds, top);
13034       const componentMaxEdge = getBoundsProperty(componentBounds, bottom);
13035       const spectrumMinEdge = getBoundsProperty(spectrumBounds, top);
13036       return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
13037     };
13039     const fireSliderChange$2 = (spectrum, value) => {
13040       emitWith(spectrum, sliderChangeEvent(), { value });
13041     };
13042     const findValueOfOffset$1 = (spectrum, detail, left) => {
13043       const args = {
13044         min: minX(detail),
13045         max: maxX(detail),
13046         range: xRange(detail),
13047         value: left,
13048         step: step(detail),
13049         snap: snap(detail),
13050         snapStart: snapStart(detail),
13051         rounded: rounded(detail),
13052         hasMinEdge: hasLEdge(detail),
13053         hasMaxEdge: hasREdge(detail),
13054         minBound: getMinXBounds(spectrum),
13055         maxBound: getMaxXBounds(spectrum),
13056         screenRange: getXScreenRange(spectrum)
13057       };
13058       return findValueOf(args);
13059     };
13060     const setValueFrom$2 = (spectrum, detail, value) => {
13061       const xValue = findValueOfOffset$1(spectrum, detail, value);
13062       const sliderVal = xValue;
13063       fireSliderChange$2(spectrum, sliderVal);
13064       return xValue;
13065     };
13066     const setToMin$2 = (spectrum, detail) => {
13067       const min = minX(detail);
13068       fireSliderChange$2(spectrum, min);
13069     };
13070     const setToMax$2 = (spectrum, detail) => {
13071       const max = maxX(detail);
13072       fireSliderChange$2(spectrum, max);
13073     };
13074     const moveBy$2 = (direction, spectrum, detail) => {
13075       const f = direction > 0 ? increaseBy : reduceBy;
13076       const xValue = f(currentValue(detail), minX(detail), maxX(detail), step(detail));
13077       fireSliderChange$2(spectrum, xValue);
13078       return Optional.some(xValue);
13079     };
13080     const handleMovement$2 = direction => (spectrum, detail) => moveBy$2(direction, spectrum, detail).map(always);
13081     const getValueFromEvent$2 = simulatedEvent => {
13082       const pos = getEventSource(simulatedEvent);
13083       return pos.map(p => p.left);
13084     };
13085     const findOffsetOfValue$1 = (spectrum, detail, value, minEdge, maxEdge) => {
13086       const minOffset = 0;
13087       const maxOffset = getXScreenRange(spectrum);
13088       const centerMinEdge = minEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(minOffset);
13089       const centerMaxEdge = maxEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
13090       const args = {
13091         min: minX(detail),
13092         max: maxX(detail),
13093         range: xRange(detail),
13094         value,
13095         hasMinEdge: hasLEdge(detail),
13096         hasMaxEdge: hasREdge(detail),
13097         minBound: getMinXBounds(spectrum),
13098         minOffset,
13099         maxBound: getMaxXBounds(spectrum),
13100         maxOffset,
13101         centerMinEdge,
13102         centerMaxEdge
13103       };
13104       return findOffsetOfValue$2(args);
13105     };
13106     const findPositionOfValue$1 = (slider, spectrum, value, minEdge, maxEdge, detail) => {
13107       const offset = findOffsetOfValue$1(spectrum, detail, value, minEdge, maxEdge);
13108       return getMinXBounds(spectrum) - getMinXBounds(slider) + offset;
13109     };
13110     const setPositionFromValue$2 = (slider, thumb, detail, edges) => {
13111       const value = currentValue(detail);
13112       const pos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
13113       const thumbRadius = get$c(thumb.element) / 2;
13114       set$8(thumb.element, 'left', pos - thumbRadius + 'px');
13115     };
13116     const onLeft$2 = handleMovement$2(-1);
13117     const onRight$2 = handleMovement$2(1);
13118     const onUp$2 = Optional.none;
13119     const onDown$2 = Optional.none;
13120     const edgeActions$2 = {
13121       'top-left': Optional.none(),
13122       'top': Optional.none(),
13123       'top-right': Optional.none(),
13124       'right': Optional.some(setToREdge),
13125       'bottom-right': Optional.none(),
13126       'bottom': Optional.none(),
13127       'bottom-left': Optional.none(),
13128       'left': Optional.some(setToLEdge)
13129     };
13131     var HorizontalModel = /*#__PURE__*/Object.freeze({
13132         __proto__: null,
13133         setValueFrom: setValueFrom$2,
13134         setToMin: setToMin$2,
13135         setToMax: setToMax$2,
13136         findValueOfOffset: findValueOfOffset$1,
13137         getValueFromEvent: getValueFromEvent$2,
13138         findPositionOfValue: findPositionOfValue$1,
13139         setPositionFromValue: setPositionFromValue$2,
13140         onLeft: onLeft$2,
13141         onRight: onRight$2,
13142         onUp: onUp$2,
13143         onDown: onDown$2,
13144         edgeActions: edgeActions$2
13145     });
13147     const fireSliderChange$1 = (spectrum, value) => {
13148       emitWith(spectrum, sliderChangeEvent(), { value });
13149     };
13150     const findValueOfOffset = (spectrum, detail, top) => {
13151       const args = {
13152         min: minY(detail),
13153         max: maxY(detail),
13154         range: yRange(detail),
13155         value: top,
13156         step: step(detail),
13157         snap: snap(detail),
13158         snapStart: snapStart(detail),
13159         rounded: rounded(detail),
13160         hasMinEdge: hasTEdge(detail),
13161         hasMaxEdge: hasBEdge(detail),
13162         minBound: getMinYBounds(spectrum),
13163         maxBound: getMaxYBounds(spectrum),
13164         screenRange: getYScreenRange(spectrum)
13165       };
13166       return findValueOf(args);
13167     };
13168     const setValueFrom$1 = (spectrum, detail, value) => {
13169       const yValue = findValueOfOffset(spectrum, detail, value);
13170       const sliderVal = yValue;
13171       fireSliderChange$1(spectrum, sliderVal);
13172       return yValue;
13173     };
13174     const setToMin$1 = (spectrum, detail) => {
13175       const min = minY(detail);
13176       fireSliderChange$1(spectrum, min);
13177     };
13178     const setToMax$1 = (spectrum, detail) => {
13179       const max = maxY(detail);
13180       fireSliderChange$1(spectrum, max);
13181     };
13182     const moveBy$1 = (direction, spectrum, detail) => {
13183       const f = direction > 0 ? increaseBy : reduceBy;
13184       const yValue = f(currentValue(detail), minY(detail), maxY(detail), step(detail));
13185       fireSliderChange$1(spectrum, yValue);
13186       return Optional.some(yValue);
13187     };
13188     const handleMovement$1 = direction => (spectrum, detail) => moveBy$1(direction, spectrum, detail).map(always);
13189     const getValueFromEvent$1 = simulatedEvent => {
13190       const pos = getEventSource(simulatedEvent);
13191       return pos.map(p => {
13192         return p.top;
13193       });
13194     };
13195     const findOffsetOfValue = (spectrum, detail, value, minEdge, maxEdge) => {
13196       const minOffset = 0;
13197       const maxOffset = getYScreenRange(spectrum);
13198       const centerMinEdge = minEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(minOffset);
13199       const centerMaxEdge = maxEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
13200       const args = {
13201         min: minY(detail),
13202         max: maxY(detail),
13203         range: yRange(detail),
13204         value,
13205         hasMinEdge: hasTEdge(detail),
13206         hasMaxEdge: hasBEdge(detail),
13207         minBound: getMinYBounds(spectrum),
13208         minOffset,
13209         maxBound: getMaxYBounds(spectrum),
13210         maxOffset,
13211         centerMinEdge,
13212         centerMaxEdge
13213       };
13214       return findOffsetOfValue$2(args);
13215     };
13216     const findPositionOfValue = (slider, spectrum, value, minEdge, maxEdge, detail) => {
13217       const offset = findOffsetOfValue(spectrum, detail, value, minEdge, maxEdge);
13218       return getMinYBounds(spectrum) - getMinYBounds(slider) + offset;
13219     };
13220     const setPositionFromValue$1 = (slider, thumb, detail, edges) => {
13221       const value = currentValue(detail);
13222       const pos = findPositionOfValue(slider, edges.getSpectrum(slider), value, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
13223       const thumbRadius = get$d(thumb.element) / 2;
13224       set$8(thumb.element, 'top', pos - thumbRadius + 'px');
13225     };
13226     const onLeft$1 = Optional.none;
13227     const onRight$1 = Optional.none;
13228     const onUp$1 = handleMovement$1(-1);
13229     const onDown$1 = handleMovement$1(1);
13230     const edgeActions$1 = {
13231       'top-left': Optional.none(),
13232       'top': Optional.some(setToTEdge),
13233       'top-right': Optional.none(),
13234       'right': Optional.none(),
13235       'bottom-right': Optional.none(),
13236       'bottom': Optional.some(setToBEdge),
13237       'bottom-left': Optional.none(),
13238       'left': Optional.none()
13239     };
13241     var VerticalModel = /*#__PURE__*/Object.freeze({
13242         __proto__: null,
13243         setValueFrom: setValueFrom$1,
13244         setToMin: setToMin$1,
13245         setToMax: setToMax$1,
13246         findValueOfOffset: findValueOfOffset,
13247         getValueFromEvent: getValueFromEvent$1,
13248         findPositionOfValue: findPositionOfValue,
13249         setPositionFromValue: setPositionFromValue$1,
13250         onLeft: onLeft$1,
13251         onRight: onRight$1,
13252         onUp: onUp$1,
13253         onDown: onDown$1,
13254         edgeActions: edgeActions$1
13255     });
13257     const fireSliderChange = (spectrum, value) => {
13258       emitWith(spectrum, sliderChangeEvent(), { value });
13259     };
13260     const sliderValue = (x, y) => ({
13261       x,
13262       y
13263     });
13264     const setValueFrom = (spectrum, detail, value) => {
13265       const xValue = findValueOfOffset$1(spectrum, detail, value.left);
13266       const yValue = findValueOfOffset(spectrum, detail, value.top);
13267       const val = sliderValue(xValue, yValue);
13268       fireSliderChange(spectrum, val);
13269       return val;
13270     };
13271     const moveBy = (direction, isVerticalMovement, spectrum, detail) => {
13272       const f = direction > 0 ? increaseBy : reduceBy;
13273       const xValue = isVerticalMovement ? currentValue(detail).x : f(currentValue(detail).x, minX(detail), maxX(detail), step(detail));
13274       const yValue = !isVerticalMovement ? currentValue(detail).y : f(currentValue(detail).y, minY(detail), maxY(detail), step(detail));
13275       fireSliderChange(spectrum, sliderValue(xValue, yValue));
13276       return Optional.some(xValue);
13277     };
13278     const handleMovement = (direction, isVerticalMovement) => (spectrum, detail) => moveBy(direction, isVerticalMovement, spectrum, detail).map(always);
13279     const setToMin = (spectrum, detail) => {
13280       const mX = minX(detail);
13281       const mY = minY(detail);
13282       fireSliderChange(spectrum, sliderValue(mX, mY));
13283     };
13284     const setToMax = (spectrum, detail) => {
13285       const mX = maxX(detail);
13286       const mY = maxY(detail);
13287       fireSliderChange(spectrum, sliderValue(mX, mY));
13288     };
13289     const getValueFromEvent = simulatedEvent => getEventSource(simulatedEvent);
13290     const setPositionFromValue = (slider, thumb, detail, edges) => {
13291       const value = currentValue(detail);
13292       const xPos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value.x, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
13293       const yPos = findPositionOfValue(slider, edges.getSpectrum(slider), value.y, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
13294       const thumbXRadius = get$c(thumb.element) / 2;
13295       const thumbYRadius = get$d(thumb.element) / 2;
13296       set$8(thumb.element, 'left', xPos - thumbXRadius + 'px');
13297       set$8(thumb.element, 'top', yPos - thumbYRadius + 'px');
13298     };
13299     const onLeft = handleMovement(-1, false);
13300     const onRight = handleMovement(1, false);
13301     const onUp = handleMovement(-1, true);
13302     const onDown = handleMovement(1, true);
13303     const edgeActions = {
13304       'top-left': Optional.some(setToTLEdgeXY),
13305       'top': Optional.some(setToTEdgeXY),
13306       'top-right': Optional.some(setToTREdgeXY),
13307       'right': Optional.some(setToREdgeXY),
13308       'bottom-right': Optional.some(setToBREdgeXY),
13309       'bottom': Optional.some(setToBEdgeXY),
13310       'bottom-left': Optional.some(setToBLEdgeXY),
13311       'left': Optional.some(setToLEdgeXY)
13312     };
13314     var TwoDModel = /*#__PURE__*/Object.freeze({
13315         __proto__: null,
13316         setValueFrom: setValueFrom,
13317         setToMin: setToMin,
13318         setToMax: setToMax,
13319         getValueFromEvent: getValueFromEvent,
13320         setPositionFromValue: setPositionFromValue,
13321         onLeft: onLeft,
13322         onRight: onRight,
13323         onUp: onUp,
13324         onDown: onDown,
13325         edgeActions: edgeActions
13326     });
13328     const SliderSchema = [
13329       defaulted('stepSize', 1),
13330       defaulted('onChange', noop),
13331       defaulted('onChoose', noop),
13332       defaulted('onInit', noop),
13333       defaulted('onDragStart', noop),
13334       defaulted('onDragEnd', noop),
13335       defaulted('snapToGrid', false),
13336       defaulted('rounded', true),
13337       option$3('snapStart'),
13338       requiredOf('model', choose$1('mode', {
13339         x: [
13340           defaulted('minX', 0),
13341           defaulted('maxX', 100),
13342           customField('value', spec => Cell(spec.mode.minX)),
13343           required$1('getInitialValue'),
13344           output$1('manager', HorizontalModel)
13345         ],
13346         y: [
13347           defaulted('minY', 0),
13348           defaulted('maxY', 100),
13349           customField('value', spec => Cell(spec.mode.minY)),
13350           required$1('getInitialValue'),
13351           output$1('manager', VerticalModel)
13352         ],
13353         xy: [
13354           defaulted('minX', 0),
13355           defaulted('maxX', 100),
13356           defaulted('minY', 0),
13357           defaulted('maxY', 100),
13358           customField('value', spec => Cell({
13359             x: spec.mode.minX,
13360             y: spec.mode.minY
13361           })),
13362           required$1('getInitialValue'),
13363           output$1('manager', TwoDModel)
13364         ]
13365       })),
13366       field('sliderBehaviours', [
13367         Keying,
13368         Representing
13369       ]),
13370       customField('mouseIsDown', () => Cell(false))
13371     ];
13373     const sketch$2 = (detail, components, _spec, _externals) => {
13374       const getThumb = component => getPartOrDie(component, detail, 'thumb');
13375       const getSpectrum = component => getPartOrDie(component, detail, 'spectrum');
13376       const getLeftEdge = component => getPart(component, detail, 'left-edge');
13377       const getRightEdge = component => getPart(component, detail, 'right-edge');
13378       const getTopEdge = component => getPart(component, detail, 'top-edge');
13379       const getBottomEdge = component => getPart(component, detail, 'bottom-edge');
13380       const modelDetail = detail.model;
13381       const model = modelDetail.manager;
13382       const refresh = (slider, thumb) => {
13383         model.setPositionFromValue(slider, thumb, detail, {
13384           getLeftEdge,
13385           getRightEdge,
13386           getTopEdge,
13387           getBottomEdge,
13388           getSpectrum
13389         });
13390       };
13391       const setValue = (slider, newValue) => {
13392         modelDetail.value.set(newValue);
13393         const thumb = getThumb(slider);
13394         refresh(slider, thumb);
13395       };
13396       const changeValue = (slider, newValue) => {
13397         setValue(slider, newValue);
13398         const thumb = getThumb(slider);
13399         detail.onChange(slider, thumb, newValue);
13400         return Optional.some(true);
13401       };
13402       const resetToMin = slider => {
13403         model.setToMin(slider, detail);
13404       };
13405       const resetToMax = slider => {
13406         model.setToMax(slider, detail);
13407       };
13408       const choose = slider => {
13409         const fireOnChoose = () => {
13410           getPart(slider, detail, 'thumb').each(thumb => {
13411             const value = modelDetail.value.get();
13412             detail.onChoose(slider, thumb, value);
13413           });
13414         };
13415         const wasDown = detail.mouseIsDown.get();
13416         detail.mouseIsDown.set(false);
13417         if (wasDown) {
13418           fireOnChoose();
13419         }
13420       };
13421       const onDragStart = (slider, simulatedEvent) => {
13422         simulatedEvent.stop();
13423         detail.mouseIsDown.set(true);
13424         detail.onDragStart(slider, getThumb(slider));
13425       };
13426       const onDragEnd = (slider, simulatedEvent) => {
13427         simulatedEvent.stop();
13428         detail.onDragEnd(slider, getThumb(slider));
13429         choose(slider);
13430       };
13431       return {
13432         uid: detail.uid,
13433         dom: detail.dom,
13434         components,
13435         behaviours: augment(detail.sliderBehaviours, [
13436           Keying.config({
13437             mode: 'special',
13438             focusIn: slider => {
13439               return getPart(slider, detail, 'spectrum').map(Keying.focusIn).map(always);
13440             }
13441           }),
13442           Representing.config({
13443             store: {
13444               mode: 'manual',
13445               getValue: _ => {
13446                 return modelDetail.value.get();
13447               },
13448               setValue
13449             }
13450           }),
13451           Receiving.config({ channels: { [mouseReleased()]: { onReceive: choose } } })
13452         ]),
13453         events: derive$2([
13454           run$1(sliderChangeEvent(), (slider, simulatedEvent) => {
13455             changeValue(slider, simulatedEvent.event.value);
13456           }),
13457           runOnAttached((slider, _simulatedEvent) => {
13458             const getInitial = modelDetail.getInitialValue();
13459             modelDetail.value.set(getInitial);
13460             const thumb = getThumb(slider);
13461             refresh(slider, thumb);
13462             const spectrum = getSpectrum(slider);
13463             detail.onInit(slider, thumb, spectrum, modelDetail.value.get());
13464           }),
13465           run$1(touchstart(), onDragStart),
13466           run$1(touchend(), onDragEnd),
13467           run$1(mousedown(), onDragStart),
13468           run$1(mouseup(), onDragEnd)
13469         ]),
13470         apis: {
13471           resetToMin,
13472           resetToMax,
13473           setValue,
13474           refresh
13475         },
13476         domModification: { styles: { position: 'relative' } }
13477       };
13478     };
13480     const Slider = composite({
13481       name: 'Slider',
13482       configFields: SliderSchema,
13483       partFields: SliderParts,
13484       factory: sketch$2,
13485       apis: {
13486         setValue: (apis, slider, value) => {
13487           apis.setValue(slider, value);
13488         },
13489         resetToMin: (apis, slider) => {
13490           apis.resetToMin(slider);
13491         },
13492         resetToMax: (apis, slider) => {
13493           apis.resetToMax(slider);
13494         },
13495         refresh: (apis, slider) => {
13496           apis.refresh(slider);
13497         }
13498       }
13499     });
13501     const fieldsUpdate = generate$6('rgb-hex-update');
13502     const sliderUpdate = generate$6('slider-update');
13503     const paletteUpdate = generate$6('palette-update');
13505     const sliderFactory = (translate, getClass) => {
13506       const spectrum = Slider.parts.spectrum({
13507         dom: {
13508           tag: 'div',
13509           classes: [getClass('hue-slider-spectrum')],
13510           attributes: { role: 'presentation' }
13511         }
13512       });
13513       const thumb = Slider.parts.thumb({
13514         dom: {
13515           tag: 'div',
13516           classes: [getClass('hue-slider-thumb')],
13517           attributes: { role: 'presentation' }
13518         }
13519       });
13520       return Slider.sketch({
13521         dom: {
13522           tag: 'div',
13523           classes: [getClass('hue-slider')],
13524           attributes: { role: 'presentation' }
13525         },
13526         rounded: false,
13527         model: {
13528           mode: 'y',
13529           getInitialValue: constant$1(0)
13530         },
13531         components: [
13532           spectrum,
13533           thumb
13534         ],
13535         sliderBehaviours: derive$1([Focusing.config({})]),
13536         onChange: (slider, _thumb, value) => {
13537           emitWith(slider, sliderUpdate, { value });
13538         }
13539       });
13540     };
13542     const owner$1 = 'form';
13543     const schema$i = [field('formBehaviours', [Representing])];
13544     const getPartName$1 = name => '<alloy.field.' + name + '>';
13545     const sketch$1 = fSpec => {
13546       const parts = (() => {
13547         const record = [];
13548         const field = (name, config) => {
13549           record.push(name);
13550           return generateOne$1(owner$1, getPartName$1(name), config);
13551         };
13552         return {
13553           field,
13554           record: constant$1(record)
13555         };
13556       })();
13557       const spec = fSpec(parts);
13558       const partNames = parts.record();
13559       const fieldParts = map$2(partNames, n => required({
13560         name: n,
13561         pname: getPartName$1(n)
13562       }));
13563       return composite$1(owner$1, schema$i, fieldParts, make$4, spec);
13564     };
13565     const toResult = (o, e) => o.fold(() => Result.error(e), Result.value);
13566     const make$4 = (detail, components) => ({
13567       uid: detail.uid,
13568       dom: detail.dom,
13569       components,
13570       behaviours: augment(detail.formBehaviours, [Representing.config({
13571           store: {
13572             mode: 'manual',
13573             getValue: form => {
13574               const resPs = getAllParts(form, detail);
13575               return map$1(resPs, (resPThunk, pName) => resPThunk().bind(v => {
13576                 const opt = Composing.getCurrent(v);
13577                 return toResult(opt, new Error(`Cannot find a current component to extract the value from for form part '${ pName }': ` + element(v.element)));
13578               }).map(Representing.getValue));
13579             },
13580             setValue: (form, values) => {
13581               each(values, (newValue, key) => {
13582                 getPart(form, detail, key).each(wrapper => {
13583                   Composing.getCurrent(wrapper).each(field => {
13584                     Representing.setValue(field, newValue);
13585                   });
13586                 });
13587               });
13588             }
13589           }
13590         })]),
13591       apis: {
13592         getField: (form, key) => {
13593           return getPart(form, detail, key).bind(Composing.getCurrent);
13594         }
13595       }
13596     });
13597     const Form = {
13598       getField: makeApi((apis, component, key) => apis.getField(component, key)),
13599       sketch: sketch$1
13600     };
13602     const validInput = generate$6('valid-input');
13603     const invalidInput = generate$6('invalid-input');
13604     const validatingInput = generate$6('validating-input');
13605     const translatePrefix = 'colorcustom.rgb.';
13606     const rgbFormFactory = (translate, getClass, onValidHexx, onInvalidHexx) => {
13607       const invalidation = (label, isValid) => Invalidating.config({
13608         invalidClass: getClass('invalid'),
13609         notify: {
13610           onValidate: comp => {
13611             emitWith(comp, validatingInput, { type: label });
13612           },
13613           onValid: comp => {
13614             emitWith(comp, validInput, {
13615               type: label,
13616               value: Representing.getValue(comp)
13617             });
13618           },
13619           onInvalid: comp => {
13620             emitWith(comp, invalidInput, {
13621               type: label,
13622               value: Representing.getValue(comp)
13623             });
13624           }
13625         },
13626         validator: {
13627           validate: comp => {
13628             const value = Representing.getValue(comp);
13629             const res = isValid(value) ? Result.value(true) : Result.error(translate('aria.input.invalid'));
13630             return Future.pure(res);
13631           },
13632           validateOnLoad: false
13633         }
13634       });
13635       const renderTextField = (isValid, name, label, description, data) => {
13636         const helptext = translate(translatePrefix + 'range');
13637         const pLabel = FormField.parts.label({
13638           dom: {
13639             tag: 'label',
13640             attributes: { 'aria-label': description }
13641           },
13642           components: [text$2(label)]
13643         });
13644         const pField = FormField.parts.field({
13645           data,
13646           factory: Input,
13647           inputAttributes: {
13648             type: 'text',
13649             ...name === 'hex' ? { 'aria-live': 'polite' } : {}
13650           },
13651           inputClasses: [getClass('textfield')],
13652           inputBehaviours: derive$1([
13653             invalidation(name, isValid),
13654             Tabstopping.config({})
13655           ]),
13656           onSetValue: input => {
13657             if (Invalidating.isInvalid(input)) {
13658               const run = Invalidating.run(input);
13659               run.get(noop);
13660             }
13661           }
13662         });
13663         const comps = [
13664           pLabel,
13665           pField
13666         ];
13667         const concats = name !== 'hex' ? [FormField.parts['aria-descriptor']({ text: helptext })] : [];
13668         const components = comps.concat(concats);
13669         return {
13670           dom: {
13671             tag: 'div',
13672             attributes: { role: 'presentation' }
13673           },
13674           components
13675         };
13676       };
13677       const copyRgbToHex = (form, rgba) => {
13678         const hex = fromRgba(rgba);
13679         Form.getField(form, 'hex').each(hexField => {
13680           if (!Focusing.isFocused(hexField)) {
13681             Representing.setValue(form, { hex: hex.value });
13682           }
13683         });
13684         return hex;
13685       };
13686       const copyRgbToForm = (form, rgb) => {
13687         const red = rgb.red;
13688         const green = rgb.green;
13689         const blue = rgb.blue;
13690         Representing.setValue(form, {
13691           red,
13692           green,
13693           blue
13694         });
13695       };
13696       const memPreview = record({
13697         dom: {
13698           tag: 'div',
13699           classes: [getClass('rgba-preview')],
13700           styles: { 'background-color': 'white' },
13701           attributes: { role: 'presentation' }
13702         }
13703       });
13704       const updatePreview = (anyInSystem, hex) => {
13705         memPreview.getOpt(anyInSystem).each(preview => {
13706           set$8(preview.element, 'background-color', '#' + hex.value);
13707         });
13708       };
13709       const factory = () => {
13710         const state = {
13711           red: Cell(Optional.some(255)),
13712           green: Cell(Optional.some(255)),
13713           blue: Cell(Optional.some(255)),
13714           hex: Cell(Optional.some('ffffff'))
13715         };
13716         const copyHexToRgb = (form, hex) => {
13717           const rgb = fromHex(hex);
13718           copyRgbToForm(form, rgb);
13719           setValueRgb(rgb);
13720         };
13721         const get = prop => state[prop].get();
13722         const set = (prop, value) => {
13723           state[prop].set(value);
13724         };
13725         const getValueRgb = () => get('red').bind(red => get('green').bind(green => get('blue').map(blue => rgbaColour(red, green, blue, 1))));
13726         const setValueRgb = rgb => {
13727           const red = rgb.red;
13728           const green = rgb.green;
13729           const blue = rgb.blue;
13730           set('red', Optional.some(red));
13731           set('green', Optional.some(green));
13732           set('blue', Optional.some(blue));
13733         };
13734         const onInvalidInput = (form, simulatedEvent) => {
13735           const data = simulatedEvent.event;
13736           if (data.type !== 'hex') {
13737             set(data.type, Optional.none());
13738           } else {
13739             onInvalidHexx(form);
13740           }
13741         };
13742         const onValidHex = (form, value) => {
13743           onValidHexx(form);
13744           const hex = hexColour(value);
13745           set('hex', Optional.some(value));
13746           const rgb = fromHex(hex);
13747           copyRgbToForm(form, rgb);
13748           setValueRgb(rgb);
13749           emitWith(form, fieldsUpdate, { hex });
13750           updatePreview(form, hex);
13751         };
13752         const onValidRgb = (form, prop, value) => {
13753           const val = parseInt(value, 10);
13754           set(prop, Optional.some(val));
13755           getValueRgb().each(rgb => {
13756             const hex = copyRgbToHex(form, rgb);
13757             emitWith(form, fieldsUpdate, { hex });
13758             updatePreview(form, hex);
13759           });
13760         };
13761         const isHexInputEvent = data => data.type === 'hex';
13762         const onValidInput = (form, simulatedEvent) => {
13763           const data = simulatedEvent.event;
13764           if (isHexInputEvent(data)) {
13765             onValidHex(form, data.value);
13766           } else {
13767             onValidRgb(form, data.type, data.value);
13768           }
13769         };
13770         const formPartStrings = key => ({
13771           label: translate(translatePrefix + key + '.label'),
13772           description: translate(translatePrefix + key + '.description')
13773         });
13774         const redStrings = formPartStrings('red');
13775         const greenStrings = formPartStrings('green');
13776         const blueStrings = formPartStrings('blue');
13777         const hexStrings = formPartStrings('hex');
13778         return deepMerge(Form.sketch(parts => ({
13779           dom: {
13780             tag: 'form',
13781             classes: [getClass('rgb-form')],
13782             attributes: { 'aria-label': translate('aria.color.picker') }
13783           },
13784           components: [
13785             parts.field('red', FormField.sketch(renderTextField(isRgbaComponent, 'red', redStrings.label, redStrings.description, 255))),
13786             parts.field('green', FormField.sketch(renderTextField(isRgbaComponent, 'green', greenStrings.label, greenStrings.description, 255))),
13787             parts.field('blue', FormField.sketch(renderTextField(isRgbaComponent, 'blue', blueStrings.label, blueStrings.description, 255))),
13788             parts.field('hex', FormField.sketch(renderTextField(isHexString, 'hex', hexStrings.label, hexStrings.description, 'ffffff'))),
13789             memPreview.asSpec()
13790           ],
13791           formBehaviours: derive$1([
13792             Invalidating.config({ invalidClass: getClass('form-invalid') }),
13793             config('rgb-form-events', [
13794               run$1(validInput, onValidInput),
13795               run$1(invalidInput, onInvalidInput),
13796               run$1(validatingInput, onInvalidInput)
13797             ])
13798           ])
13799         })), {
13800           apis: {
13801             updateHex: (form, hex) => {
13802               Representing.setValue(form, { hex: hex.value });
13803               copyHexToRgb(form, hex);
13804               updatePreview(form, hex);
13805             }
13806           }
13807         });
13808       };
13809       const rgbFormSketcher = single({
13810         factory,
13811         name: 'RgbForm',
13812         configFields: [],
13813         apis: {
13814           updateHex: (apis, form, hex) => {
13815             apis.updateHex(form, hex);
13816           }
13817         },
13818         extraApis: {}
13819       });
13820       return rgbFormSketcher;
13821     };
13823     const paletteFactory = (_translate, getClass) => {
13824       const spectrumPart = Slider.parts.spectrum({
13825         dom: {
13826           tag: 'canvas',
13827           attributes: { role: 'presentation' },
13828           classes: [getClass('sv-palette-spectrum')]
13829         }
13830       });
13831       const thumbPart = Slider.parts.thumb({
13832         dom: {
13833           tag: 'div',
13834           attributes: { role: 'presentation' },
13835           classes: [getClass('sv-palette-thumb')],
13836           innerHtml: `<div class=${ getClass('sv-palette-inner-thumb') } role="presentation"></div>`
13837         }
13838       });
13839       const setColour = (canvas, rgba) => {
13840         const {width, height} = canvas;
13841         const ctx = canvas.getContext('2d');
13842         if (ctx === null) {
13843           return;
13844         }
13845         ctx.fillStyle = rgba;
13846         ctx.fillRect(0, 0, width, height);
13847         const grdWhite = ctx.createLinearGradient(0, 0, width, 0);
13848         grdWhite.addColorStop(0, 'rgba(255,255,255,1)');
13849         grdWhite.addColorStop(1, 'rgba(255,255,255,0)');
13850         ctx.fillStyle = grdWhite;
13851         ctx.fillRect(0, 0, width, height);
13852         const grdBlack = ctx.createLinearGradient(0, 0, 0, height);
13853         grdBlack.addColorStop(0, 'rgba(0,0,0,0)');
13854         grdBlack.addColorStop(1, 'rgba(0,0,0,1)');
13855         ctx.fillStyle = grdBlack;
13856         ctx.fillRect(0, 0, width, height);
13857       };
13858       const setPaletteHue = (slider, hue) => {
13859         const canvas = slider.components()[0].element.dom;
13860         const hsv = hsvColour(hue, 100, 100);
13861         const rgba = fromHsv(hsv);
13862         setColour(canvas, toString(rgba));
13863       };
13864       const setPaletteThumb = (slider, hex) => {
13865         const hsv = fromRgb(fromHex(hex));
13866         Slider.setValue(slider, {
13867           x: hsv.saturation,
13868           y: 100 - hsv.value
13869         });
13870       };
13871       const factory = _detail => {
13872         const getInitialValue = constant$1({
13873           x: 0,
13874           y: 0
13875         });
13876         const onChange = (slider, _thumb, value) => {
13877           emitWith(slider, paletteUpdate, { value });
13878         };
13879         const onInit = (_slider, _thumb, spectrum, _value) => {
13880           setColour(spectrum.element.dom, toString(red));
13881         };
13882         const sliderBehaviours = derive$1([
13883           Composing.config({ find: Optional.some }),
13884           Focusing.config({})
13885         ]);
13886         return Slider.sketch({
13887           dom: {
13888             tag: 'div',
13889             attributes: { role: 'presentation' },
13890             classes: [getClass('sv-palette')]
13891           },
13892           model: {
13893             mode: 'xy',
13894             getInitialValue
13895           },
13896           rounded: false,
13897           components: [
13898             spectrumPart,
13899             thumbPart
13900           ],
13901           onChange,
13902           onInit,
13903           sliderBehaviours
13904         });
13905       };
13906       const saturationBrightnessPaletteSketcher = single({
13907         factory,
13908         name: 'SaturationBrightnessPalette',
13909         configFields: [],
13910         apis: {
13911           setHue: (_apis, slider, hue) => {
13912             setPaletteHue(slider, hue);
13913           },
13914           setThumb: (_apis, slider, hex) => {
13915             setPaletteThumb(slider, hex);
13916           }
13917         },
13918         extraApis: {}
13919       });
13920       return saturationBrightnessPaletteSketcher;
13921     };
13923     const makeFactory = (translate, getClass) => {
13924       const factory = detail => {
13925         const rgbForm = rgbFormFactory(translate, getClass, detail.onValidHex, detail.onInvalidHex);
13926         const sbPalette = paletteFactory(translate, getClass);
13927         const hueSliderToDegrees = hue => (100 - hue) / 100 * 360;
13928         const hueDegreesToSlider = hue => 100 - hue / 360 * 100;
13929         const state = {
13930           paletteRgba: Cell(red),
13931           paletteHue: Cell(0)
13932         };
13933         const memSlider = record(sliderFactory(translate, getClass));
13934         const memPalette = record(sbPalette.sketch({}));
13935         const memRgb = record(rgbForm.sketch({}));
13936         const updatePalette = (anyInSystem, _hex, hue) => {
13937           memPalette.getOpt(anyInSystem).each(palette => {
13938             sbPalette.setHue(palette, hue);
13939           });
13940         };
13941         const updateFields = (anyInSystem, hex) => {
13942           memRgb.getOpt(anyInSystem).each(form => {
13943             rgbForm.updateHex(form, hex);
13944           });
13945         };
13946         const updateSlider = (anyInSystem, _hex, hue) => {
13947           memSlider.getOpt(anyInSystem).each(slider => {
13948             Slider.setValue(slider, hueDegreesToSlider(hue));
13949           });
13950         };
13951         const updatePaletteThumb = (anyInSystem, hex) => {
13952           memPalette.getOpt(anyInSystem).each(palette => {
13953             sbPalette.setThumb(palette, hex);
13954           });
13955         };
13956         const updateState = (hex, hue) => {
13957           const rgba = fromHex(hex);
13958           state.paletteRgba.set(rgba);
13959           state.paletteHue.set(hue);
13960         };
13961         const runUpdates = (anyInSystem, hex, hue, updates) => {
13962           updateState(hex, hue);
13963           each$1(updates, update => {
13964             update(anyInSystem, hex, hue);
13965           });
13966         };
13967         const onPaletteUpdate = () => {
13968           const updates = [updateFields];
13969           return (form, simulatedEvent) => {
13970             const value = simulatedEvent.event.value;
13971             const oldHue = state.paletteHue.get();
13972             const newHsv = hsvColour(oldHue, value.x, 100 - value.y);
13973             const newHex = hsvToHex(newHsv);
13974             runUpdates(form, newHex, oldHue, updates);
13975           };
13976         };
13977         const onSliderUpdate = () => {
13978           const updates = [
13979             updatePalette,
13980             updateFields
13981           ];
13982           return (form, simulatedEvent) => {
13983             const hue = hueSliderToDegrees(simulatedEvent.event.value);
13984             const oldRgb = state.paletteRgba.get();
13985             const oldHsv = fromRgb(oldRgb);
13986             const newHsv = hsvColour(hue, oldHsv.saturation, oldHsv.value);
13987             const newHex = hsvToHex(newHsv);
13988             runUpdates(form, newHex, hue, updates);
13989           };
13990         };
13991         const onFieldsUpdate = () => {
13992           const updates = [
13993             updatePalette,
13994             updateSlider,
13995             updatePaletteThumb
13996           ];
13997           return (form, simulatedEvent) => {
13998             const hex = simulatedEvent.event.hex;
13999             const hsv = hexToHsv(hex);
14000             runUpdates(form, hex, hsv.hue, updates);
14001           };
14002         };
14003         return {
14004           uid: detail.uid,
14005           dom: detail.dom,
14006           components: [
14007             memPalette.asSpec(),
14008             memSlider.asSpec(),
14009             memRgb.asSpec()
14010           ],
14011           behaviours: derive$1([
14012             config('colour-picker-events', [
14013               run$1(fieldsUpdate, onFieldsUpdate()),
14014               run$1(paletteUpdate, onPaletteUpdate()),
14015               run$1(sliderUpdate, onSliderUpdate())
14016             ]),
14017             Composing.config({ find: comp => memRgb.getOpt(comp) }),
14018             Keying.config({ mode: 'acyclic' })
14019           ])
14020         };
14021       };
14022       const colourPickerSketcher = single({
14023         name: 'ColourPicker',
14024         configFields: [
14025           required$1('dom'),
14026           defaulted('onValidHex', noop),
14027           defaulted('onInvalidHex', noop)
14028         ],
14029         factory
14030       });
14031       return colourPickerSketcher;
14032     };
14034     const self = () => Composing.config({ find: Optional.some });
14035     const memento$1 = mem => Composing.config({ find: mem.getOpt });
14036     const childAt = index => Composing.config({ find: comp => child$2(comp.element, index).bind(element => comp.getSystem().getByDom(element).toOptional()) });
14037     const ComposingConfigs = {
14038       self,
14039       memento: memento$1,
14040       childAt
14041     };
14043     const processors = objOf([
14044       defaulted('preprocess', identity),
14045       defaulted('postprocess', identity)
14046     ]);
14047     const memento = (mem, rawProcessors) => {
14048       const ps = asRawOrDie$1('RepresentingConfigs.memento processors', processors, rawProcessors);
14049       return Representing.config({
14050         store: {
14051           mode: 'manual',
14052           getValue: comp => {
14053             const other = mem.get(comp);
14054             const rawValue = Representing.getValue(other);
14055             return ps.postprocess(rawValue);
14056           },
14057           setValue: (comp, rawValue) => {
14058             const newValue = ps.preprocess(rawValue);
14059             const other = mem.get(comp);
14060             Representing.setValue(other, newValue);
14061           }
14062         }
14063       });
14064     };
14065     const withComp = (optInitialValue, getter, setter) => Representing.config({
14066       store: {
14067         mode: 'manual',
14068         ...optInitialValue.map(initialValue => ({ initialValue })).getOr({}),
14069         getValue: getter,
14070         setValue: setter
14071       }
14072     });
14073     const withElement = (initialValue, getter, setter) => withComp(initialValue, c => getter(c.element), (c, v) => setter(c.element, v));
14074     const domValue = optInitialValue => withElement(optInitialValue, get$6, set$5);
14075     const domHtml = optInitialValue => withElement(optInitialValue, get$9, set$6);
14076     const memory = initialValue => Representing.config({
14077       store: {
14078         mode: 'memory',
14079         initialValue
14080       }
14081     });
14082     const RepresentingConfigs = {
14083       memento,
14084       withElement,
14085       withComp,
14086       domValue,
14087       domHtml,
14088       memory
14089     };
14091     const english = {
14092       'colorcustom.rgb.red.label': 'R',
14093       'colorcustom.rgb.red.description': 'Red component',
14094       'colorcustom.rgb.green.label': 'G',
14095       'colorcustom.rgb.green.description': 'Green component',
14096       'colorcustom.rgb.blue.label': 'B',
14097       'colorcustom.rgb.blue.description': 'Blue component',
14098       'colorcustom.rgb.hex.label': '#',
14099       'colorcustom.rgb.hex.description': 'Hex color code',
14100       'colorcustom.rgb.range': 'Range 0 to 255',
14101       'aria.color.picker': 'Color Picker',
14102       'aria.input.invalid': 'Invalid input'
14103     };
14104     const translate$1 = providerBackstage => key => {
14105       return providerBackstage.translate(english[key]);
14106     };
14107     const renderColorPicker = (_spec, providerBackstage, initialData) => {
14108       const getClass = key => 'tox-' + key;
14109       const colourPickerFactory = makeFactory(translate$1(providerBackstage), getClass);
14110       const onValidHex = form => {
14111         emitWith(form, formActionEvent, {
14112           name: 'hex-valid',
14113           value: true
14114         });
14115       };
14116       const onInvalidHex = form => {
14117         emitWith(form, formActionEvent, {
14118           name: 'hex-valid',
14119           value: false
14120         });
14121       };
14122       const memPicker = record(colourPickerFactory.sketch({
14123         dom: {
14124           tag: 'div',
14125           classes: [getClass('color-picker-container')],
14126           attributes: { role: 'presentation' }
14127         },
14128         onValidHex,
14129         onInvalidHex
14130       }));
14131       return {
14132         dom: { tag: 'div' },
14133         components: [memPicker.asSpec()],
14134         behaviours: derive$1([
14135           RepresentingConfigs.withComp(initialData, comp => {
14136             const picker = memPicker.get(comp);
14137             const optRgbForm = Composing.getCurrent(picker);
14138             const optHex = optRgbForm.bind(rgbForm => {
14139               const formValues = Representing.getValue(rgbForm);
14140               return formValues.hex;
14141             });
14142             return optHex.map(hex => '#' + hex).getOr('');
14143           }, (comp, newValue) => {
14144             const pattern = /^#([a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?)/;
14145             const valOpt = Optional.from(pattern.exec(newValue)).bind(matches => get$h(matches, 1));
14146             const picker = memPicker.get(comp);
14147             const optRgbForm = Composing.getCurrent(picker);
14148             optRgbForm.fold(() => {
14149               console.log('Can not find form');
14150             }, rgbForm => {
14151               Representing.setValue(rgbForm, { hex: valOpt.getOr('') });
14152               Form.getField(rgbForm, 'hex').each(hexField => {
14153                 emit(hexField, input());
14154               });
14155             });
14156           }),
14157           ComposingConfigs.self()
14158         ])
14159       };
14160     };
14162     var global$2 = tinymce.util.Tools.resolve('tinymce.Resource');
14164     const isOldCustomEditor = spec => has$2(spec, 'init');
14165     const renderCustomEditor = spec => {
14166       const editorApi = value$2();
14167       const memReplaced = record({ dom: { tag: spec.tag } });
14168       const initialValue = value$2();
14169       return {
14170         dom: {
14171           tag: 'div',
14172           classes: ['tox-custom-editor']
14173         },
14174         behaviours: derive$1([
14175           config('custom-editor-events', [runOnAttached(component => {
14176               memReplaced.getOpt(component).each(ta => {
14177                 (isOldCustomEditor(spec) ? spec.init(ta.element.dom) : global$2.load(spec.scriptId, spec.scriptUrl).then(init => init(ta.element.dom, spec.settings))).then(ea => {
14178                   initialValue.on(cvalue => {
14179                     ea.setValue(cvalue);
14180                   });
14181                   initialValue.clear();
14182                   editorApi.set(ea);
14183                 });
14184               });
14185             })]),
14186           RepresentingConfigs.withComp(Optional.none(), () => editorApi.get().fold(() => initialValue.get().getOr(''), ed => ed.getValue()), (component, value) => {
14187             editorApi.get().fold(() => initialValue.set(value), ed => ed.setValue(value));
14188           }),
14189           ComposingConfigs.self()
14190         ]),
14191         components: [memReplaced.asSpec()]
14192       };
14193     };
14195     var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
14197     const filterByExtension = (files, providersBackstage) => {
14198       const allowedImageFileTypes = global$1.explode(providersBackstage.getOption('images_file_types'));
14199       const isFileInAllowedTypes = file => exists(allowedImageFileTypes, type => endsWith(file.name.toLowerCase(), `.${ type.toLowerCase() }`));
14200       return filter$2(from(files), isFileInAllowedTypes);
14201     };
14202     const renderDropZone = (spec, providersBackstage, initialData) => {
14203       const stopper = (_, se) => {
14204         se.stop();
14205       };
14206       const sequence = actions => (comp, se) => {
14207         each$1(actions, a => {
14208           a(comp, se);
14209         });
14210       };
14211       const onDrop = (comp, se) => {
14212         if (!Disabling.isDisabled(comp)) {
14213           const transferEvent = se.event.raw;
14214           handleFiles(comp, transferEvent.dataTransfer?.files);
14215         }
14216       };
14217       const onSelect = (component, simulatedEvent) => {
14218         const input = simulatedEvent.event.raw.target;
14219         handleFiles(component, input.files);
14220       };
14221       const handleFiles = (component, files) => {
14222         if (files) {
14223           Representing.setValue(component, filterByExtension(files, providersBackstage));
14224           emitWith(component, formChangeEvent, { name: spec.name });
14225         }
14226       };
14227       const memInput = record({
14228         dom: {
14229           tag: 'input',
14230           attributes: {
14231             type: 'file',
14232             accept: 'image/*'
14233           },
14234           styles: { display: 'none' }
14235         },
14236         behaviours: derive$1([config('input-file-events', [
14237             cutter(click()),
14238             cutter(tap())
14239           ])])
14240       });
14241       const renderField = s => ({
14242         uid: s.uid,
14243         dom: {
14244           tag: 'div',
14245           classes: ['tox-dropzone-container']
14246         },
14247         behaviours: derive$1([
14248           RepresentingConfigs.memory(initialData.getOr([])),
14249           ComposingConfigs.self(),
14250           Disabling.config({}),
14251           Toggling.config({
14252             toggleClass: 'dragenter',
14253             toggleOnExecute: false
14254           }),
14255           config('dropzone-events', [
14256             run$1('dragenter', sequence([
14257               stopper,
14258               Toggling.toggle
14259             ])),
14260             run$1('dragleave', sequence([
14261               stopper,
14262               Toggling.toggle
14263             ])),
14264             run$1('dragover', stopper),
14265             run$1('drop', sequence([
14266               stopper,
14267               onDrop
14268             ])),
14269             run$1(change(), onSelect)
14270           ])
14271         ]),
14272         components: [{
14273             dom: {
14274               tag: 'div',
14275               classes: ['tox-dropzone'],
14276               styles: {}
14277             },
14278             components: [
14279               {
14280                 dom: { tag: 'p' },
14281                 components: [text$2(providersBackstage.translate('Drop an image here'))]
14282               },
14283               Button.sketch({
14284                 dom: {
14285                   tag: 'button',
14286                   styles: { position: 'relative' },
14287                   classes: [
14288                     'tox-button',
14289                     'tox-button--secondary'
14290                   ]
14291                 },
14292                 components: [
14293                   text$2(providersBackstage.translate('Browse for an image')),
14294                   memInput.asSpec()
14295                 ],
14296                 action: comp => {
14297                   const inputComp = memInput.get(comp);
14298                   inputComp.element.dom.click();
14299                 },
14300                 buttonBehaviours: derive$1([
14301                   Tabstopping.config({}),
14302                   DisablingConfigs.button(providersBackstage.isDisabled),
14303                   receivingConfig()
14304                 ])
14305               })
14306             ]
14307           }]
14308       });
14309       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
14310       const pField = FormField.parts.field({ factory: { sketch: renderField } });
14311       return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
14312     };
14314     const renderGrid = (spec, backstage) => ({
14315       dom: {
14316         tag: 'div',
14317         classes: [
14318           'tox-form__grid',
14319           `tox-form__grid--${ spec.columns }col`
14320         ]
14321       },
14322       components: map$2(spec.items, backstage.interpreter)
14323     });
14325     const beforeObject = generate$6('alloy-fake-before-tabstop');
14326     const afterObject = generate$6('alloy-fake-after-tabstop');
14327     const craftWithClasses = classes => {
14328       return {
14329         dom: {
14330           tag: 'div',
14331           styles: {
14332             width: '1px',
14333             height: '1px',
14334             outline: 'none'
14335           },
14336           attributes: { tabindex: '0' },
14337           classes
14338         },
14339         behaviours: derive$1([
14340           Focusing.config({ ignore: true }),
14341           Tabstopping.config({})
14342         ])
14343       };
14344     };
14345     const craft = spec => {
14346       return {
14347         dom: {
14348           tag: 'div',
14349           classes: ['tox-navobj']
14350         },
14351         components: [
14352           craftWithClasses([beforeObject]),
14353           spec,
14354           craftWithClasses([afterObject])
14355         ],
14356         behaviours: derive$1([ComposingConfigs.childAt(1)])
14357       };
14358     };
14359     const triggerTab = (placeholder, shiftKey) => {
14360       emitWith(placeholder, keydown(), {
14361         raw: {
14362           which: 9,
14363           shiftKey
14364         }
14365       });
14366     };
14367     const onFocus = (container, targetComp) => {
14368       const target = targetComp.element;
14369       if (has(target, beforeObject)) {
14370         triggerTab(container, true);
14371       } else if (has(target, afterObject)) {
14372         triggerTab(container, false);
14373       }
14374     };
14375     const isPseudoStop = element => {
14376       return closest(element, [
14377         '.' + beforeObject,
14378         '.' + afterObject
14379       ].join(','), never);
14380     };
14382     const getDynamicSource = initialData => {
14383       const cachedValue = Cell(initialData.getOr(''));
14384       return {
14385         getValue: _frameComponent => cachedValue.get(),
14386         setValue: (frameComponent, html) => {
14387           if (cachedValue.get() !== html) {
14388             set$9(frameComponent.element, 'srcdoc', html);
14389           }
14390           cachedValue.set(html);
14391         }
14392       };
14393     };
14394     const renderIFrame = (spec, providersBackstage, initialData) => {
14395       const isSandbox = spec.sandboxed;
14396       const isTransparent = spec.transparent;
14397       const baseClass = 'tox-dialog__iframe';
14398       const attributes = {
14399         ...spec.label.map(title => ({ title })).getOr({}),
14400         ...initialData.map(html => ({ srcdoc: html })).getOr({}),
14401         ...isSandbox ? { sandbox: 'allow-scripts allow-same-origin' } : {}
14402       };
14403       const sourcing = getDynamicSource(initialData);
14404       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
14405       const factory = newSpec => craft({
14406         uid: newSpec.uid,
14407         dom: {
14408           tag: 'iframe',
14409           attributes,
14410           classes: isTransparent ? [baseClass] : [
14411             baseClass,
14412             `${ baseClass }--opaque`
14413           ]
14414         },
14415         behaviours: derive$1([
14416           Tabstopping.config({}),
14417           Focusing.config({}),
14418           RepresentingConfigs.withComp(initialData, sourcing.getValue, sourcing.setValue)
14419         ])
14420       });
14421       const pField = FormField.parts.field({ factory: { sketch: factory } });
14422       return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
14423     };
14425     const image = image => new Promise((resolve, reject) => {
14426       const loaded = () => {
14427         destroy();
14428         resolve(image);
14429       };
14430       const listeners = [
14431         bind(image, 'load', loaded),
14432         bind(image, 'error', () => {
14433           destroy();
14434           reject('Unable to load data from image: ' + image.dom.src);
14435         })
14436       ];
14437       const destroy = () => each$1(listeners, l => l.unbind());
14438       if (image.dom.complete) {
14439         loaded();
14440       }
14441     });
14443     const calculateImagePosition = (panelWidth, panelHeight, imageWidth, imageHeight, zoom) => {
14444       const width = imageWidth * zoom;
14445       const height = imageHeight * zoom;
14446       const left = Math.max(0, panelWidth / 2 - width / 2);
14447       const top = Math.max(0, panelHeight / 2 - height / 2);
14448       return {
14449         left: left.toString() + 'px',
14450         top: top.toString() + 'px',
14451         width: width.toString() + 'px',
14452         height: height.toString() + 'px'
14453       };
14454     };
14455     const zoomToFit = (panel, width, height) => {
14456       const panelW = get$c(panel);
14457       const panelH = get$d(panel);
14458       return Math.min(panelW / width, panelH / height, 1);
14459     };
14460     const renderImagePreview = (spec, initialData) => {
14461       const cachedData = Cell(initialData.getOr({ url: '' }));
14462       const memImage = record({
14463         dom: {
14464           tag: 'img',
14465           classes: ['tox-imagepreview__image'],
14466           attributes: initialData.map(data => ({ src: data.url })).getOr({})
14467         }
14468       });
14469       const memContainer = record({
14470         dom: {
14471           tag: 'div',
14472           classes: ['tox-imagepreview__container'],
14473           attributes: { role: 'presentation' }
14474         },
14475         components: [memImage.asSpec()]
14476       });
14477       const setValue = (frameComponent, data) => {
14478         const translatedData = { url: data.url };
14479         data.zoom.each(z => translatedData.zoom = z);
14480         data.cachedWidth.each(z => translatedData.cachedWidth = z);
14481         data.cachedHeight.each(z => translatedData.cachedHeight = z);
14482         cachedData.set(translatedData);
14483         const applyFramePositioning = () => {
14484           const {cachedWidth, cachedHeight, zoom} = translatedData;
14485           if (!isUndefined(cachedWidth) && !isUndefined(cachedHeight)) {
14486             if (isUndefined(zoom)) {
14487               const z = zoomToFit(frameComponent.element, cachedWidth, cachedHeight);
14488               translatedData.zoom = z;
14489             }
14490             const position = calculateImagePosition(get$c(frameComponent.element), get$d(frameComponent.element), cachedWidth, cachedHeight, translatedData.zoom);
14491             memContainer.getOpt(frameComponent).each(container => {
14492               setAll(container.element, position);
14493             });
14494           }
14495         };
14496         memImage.getOpt(frameComponent).each(imageComponent => {
14497           const img = imageComponent.element;
14498           if (data.url !== get$f(img, 'src')) {
14499             set$9(img, 'src', data.url);
14500             remove$2(frameComponent.element, 'tox-imagepreview__loaded');
14501           }
14502           applyFramePositioning();
14503           image(img).then(img => {
14504             if (frameComponent.getSystem().isConnected()) {
14505               add$2(frameComponent.element, 'tox-imagepreview__loaded');
14506               translatedData.cachedWidth = img.dom.naturalWidth;
14507               translatedData.cachedHeight = img.dom.naturalHeight;
14508               applyFramePositioning();
14509             }
14510           });
14511         });
14512       };
14513       const styles = {};
14514       spec.height.each(h => styles.height = h);
14515       const fakeValidatedData = initialData.map(d => ({
14516         url: d.url,
14517         zoom: Optional.from(d.zoom),
14518         cachedWidth: Optional.from(d.cachedWidth),
14519         cachedHeight: Optional.from(d.cachedHeight)
14520       }));
14521       return {
14522         dom: {
14523           tag: 'div',
14524           classes: ['tox-imagepreview'],
14525           styles,
14526           attributes: { role: 'presentation' }
14527         },
14528         components: [memContainer.asSpec()],
14529         behaviours: derive$1([
14530           ComposingConfigs.self(),
14531           RepresentingConfigs.withComp(fakeValidatedData, () => cachedData.get(), setValue)
14532         ])
14533       };
14534     };
14536     const renderLabel$1 = (spec, backstageShared) => {
14537       const label = {
14538         dom: {
14539           tag: 'label',
14540           classes: ['tox-label']
14541         },
14542         components: [text$2(backstageShared.providers.translate(spec.label))]
14543       };
14544       const comps = map$2(spec.items, backstageShared.interpreter);
14545       return {
14546         dom: {
14547           tag: 'div',
14548           classes: ['tox-form__group']
14549         },
14550         components: [
14551           label,
14552           ...comps
14553         ],
14554         behaviours: derive$1([
14555           ComposingConfigs.self(),
14556           Replacing.config({}),
14557           RepresentingConfigs.domHtml(Optional.none()),
14558           Keying.config({ mode: 'acyclic' })
14559         ])
14560       };
14561     };
14563     const internalToolbarButtonExecute = generate$6('toolbar.button.execute');
14564     const onToolbarButtonExecute = info => runOnExecute$1((comp, _simulatedEvent) => {
14565       runWithApi(info, comp)(itemApi => {
14566         emitWith(comp, internalToolbarButtonExecute, { buttonApi: itemApi });
14567         info.onAction(itemApi);
14568       });
14569     });
14570     const toolbarButtonEventOrder = {
14571       [execute$5()]: [
14572         'disabling',
14573         'alloy.base.behaviour',
14574         'toggling',
14575         'toolbar-button-events'
14576       ]
14577     };
14579     const renderIcon = (iconName, iconsProvider, behaviours) => render$3(iconName, {
14580       tag: 'span',
14581       classes: [
14582         'tox-icon',
14583         'tox-tbtn__icon-wrap'
14584       ],
14585       behaviours
14586     }, iconsProvider);
14587     const renderIconFromPack = (iconName, iconsProvider) => renderIcon(iconName, iconsProvider, []);
14588     const renderReplaceableIconFromPack = (iconName, iconsProvider) => renderIcon(iconName, iconsProvider, [Replacing.config({})]);
14589     const renderLabel = (text, prefix, providersBackstage) => ({
14590       dom: {
14591         tag: 'span',
14592         classes: [`${ prefix }__select-label`]
14593       },
14594       components: [text$2(providersBackstage.translate(text))],
14595       behaviours: derive$1([Replacing.config({})])
14596     });
14598     const updateMenuText = generate$6('update-menu-text');
14599     const updateMenuIcon = generate$6('update-menu-icon');
14600     const renderCommonDropdown = (spec, prefix, sharedBackstage) => {
14601       const editorOffCell = Cell(noop);
14602       const optMemDisplayText = spec.text.map(text => record(renderLabel(text, prefix, sharedBackstage.providers)));
14603       const optMemDisplayIcon = spec.icon.map(iconName => record(renderReplaceableIconFromPack(iconName, sharedBackstage.providers.icons)));
14604       const onLeftOrRightInMenu = (comp, se) => {
14605         const dropdown = Representing.getValue(comp);
14606         Focusing.focus(dropdown);
14607         emitWith(dropdown, 'keydown', { raw: se.event.raw });
14608         Dropdown.close(dropdown);
14609         return Optional.some(true);
14610       };
14611       const role = spec.role.fold(() => ({}), role => ({ role }));
14612       const tooltipAttributes = spec.tooltip.fold(() => ({}), tooltip => {
14613         const translatedTooltip = sharedBackstage.providers.translate(tooltip);
14614         return {
14615           'title': translatedTooltip,
14616           'aria-label': translatedTooltip
14617         };
14618       });
14619       const iconSpec = render$3('chevron-down', {
14620         tag: 'div',
14621         classes: [`${ prefix }__select-chevron`]
14622       }, sharedBackstage.providers.icons);
14623       const memDropdown = record(Dropdown.sketch({
14624         ...spec.uid ? { uid: spec.uid } : {},
14625         ...role,
14626         dom: {
14627           tag: 'button',
14628           classes: [
14629             prefix,
14630             `${ prefix }--select`
14631           ].concat(map$2(spec.classes, c => `${ prefix }--${ c }`)),
14632           attributes: { ...tooltipAttributes }
14633         },
14634         components: componentRenderPipeline([
14635           optMemDisplayIcon.map(mem => mem.asSpec()),
14636           optMemDisplayText.map(mem => mem.asSpec()),
14637           Optional.some(iconSpec)
14638         ]),
14639         matchWidth: true,
14640         useMinWidth: true,
14641         onOpen: (anchor, dropdownComp, tmenuComp) => {
14642           if (spec.searchable) {
14643             focusSearchField(tmenuComp);
14644           }
14645         },
14646         dropdownBehaviours: derive$1([
14647           ...spec.dropdownBehaviours,
14648           DisablingConfigs.button(() => spec.disabled || sharedBackstage.providers.isDisabled()),
14649           receivingConfig(),
14650           Unselecting.config({}),
14651           Replacing.config({}),
14652           config('dropdown-events', [
14653             onControlAttached(spec, editorOffCell),
14654             onControlDetached(spec, editorOffCell)
14655           ]),
14656           config('menubutton-update-display-text', [
14657             run$1(updateMenuText, (comp, se) => {
14658               optMemDisplayText.bind(mem => mem.getOpt(comp)).each(displayText => {
14659                 Replacing.set(displayText, [text$2(sharedBackstage.providers.translate(se.event.text))]);
14660               });
14661             }),
14662             run$1(updateMenuIcon, (comp, se) => {
14663               optMemDisplayIcon.bind(mem => mem.getOpt(comp)).each(displayIcon => {
14664                 Replacing.set(displayIcon, [renderReplaceableIconFromPack(se.event.icon, sharedBackstage.providers.icons)]);
14665               });
14666             })
14667           ])
14668         ]),
14669         eventOrder: deepMerge(toolbarButtonEventOrder, {
14670           mousedown: [
14671             'focusing',
14672             'alloy.base.behaviour',
14673             'item-type-events',
14674             'normal-dropdown-events'
14675           ]
14676         }),
14677         sandboxBehaviours: derive$1([
14678           Keying.config({
14679             mode: 'special',
14680             onLeft: onLeftOrRightInMenu,
14681             onRight: onLeftOrRightInMenu
14682           }),
14683           config('dropdown-sandbox-events', [
14684             run$1(refetchTriggerEvent, (originalSandboxComp, se) => {
14685               handleRefetchTrigger(originalSandboxComp);
14686               se.stop();
14687             }),
14688             run$1(redirectMenuItemInteractionEvent, (sandboxComp, se) => {
14689               handleRedirectToMenuItem(sandboxComp, se);
14690               se.stop();
14691             })
14692           ])
14693         ]),
14694         lazySink: sharedBackstage.getSink,
14695         toggleClass: `${ prefix }--active`,
14696         parts: {
14697           menu: {
14698             ...part(false, spec.columns, spec.presets),
14699             fakeFocus: spec.searchable,
14700             onHighlightItem: updateAriaOnHighlight,
14701             onCollapseMenu: (tmenuComp, itemCompCausingCollapse, nowActiveMenuComp) => {
14702               Highlighting.getHighlighted(nowActiveMenuComp).each(itemComp => {
14703                 updateAriaOnHighlight(tmenuComp, nowActiveMenuComp, itemComp);
14704               });
14705             },
14706             onDehighlightItem: updateAriaOnDehighlight
14707           }
14708         },
14709         fetch: comp => Future.nu(curry(spec.fetch, comp))
14710       }));
14711       return memDropdown.asSpec();
14712     };
14714     const isMenuItemReference = item => isString(item);
14715     const isSeparator$2 = item => item.type === 'separator';
14716     const isExpandingMenuItem = item => has$2(item, 'getSubmenuItems');
14717     const separator$2 = { type: 'separator' };
14718     const unwrapReferences = (items, menuItems) => {
14719       const realItems = foldl(items, (acc, item) => {
14720         if (isMenuItemReference(item)) {
14721           if (item === '') {
14722             return acc;
14723           } else if (item === '|') {
14724             return acc.length > 0 && !isSeparator$2(acc[acc.length - 1]) ? acc.concat([separator$2]) : acc;
14725           } else if (has$2(menuItems, item.toLowerCase())) {
14726             return acc.concat([menuItems[item.toLowerCase()]]);
14727           } else {
14728             return acc;
14729           }
14730         } else {
14731           return acc.concat([item]);
14732         }
14733       }, []);
14734       if (realItems.length > 0 && isSeparator$2(realItems[realItems.length - 1])) {
14735         realItems.pop();
14736       }
14737       return realItems;
14738     };
14739     const getFromExpandingItem = (item, menuItems) => {
14740       const submenuItems = item.getSubmenuItems();
14741       const rest = expand(submenuItems, menuItems);
14742       const newMenus = deepMerge(rest.menus, { [item.value]: rest.items });
14743       const newExpansions = deepMerge(rest.expansions, { [item.value]: item.value });
14744       return {
14745         item,
14746         menus: newMenus,
14747         expansions: newExpansions
14748       };
14749     };
14750     const generateValueIfRequired = item => {
14751       const itemValue = get$g(item, 'value').getOrThunk(() => generate$6('generated-menu-item'));
14752       return deepMerge({ value: itemValue }, item);
14753     };
14754     const expand = (items, menuItems) => {
14755       const realItems = unwrapReferences(isString(items) ? items.split(' ') : items, menuItems);
14756       return foldr(realItems, (acc, item) => {
14757         if (isExpandingMenuItem(item)) {
14758           const itemWithValue = generateValueIfRequired(item);
14759           const newData = getFromExpandingItem(itemWithValue, menuItems);
14760           return {
14761             menus: deepMerge(acc.menus, newData.menus),
14762             items: [
14763               newData.item,
14764               ...acc.items
14765             ],
14766             expansions: deepMerge(acc.expansions, newData.expansions)
14767           };
14768         } else {
14769           return {
14770             ...acc,
14771             items: [
14772               item,
14773               ...acc.items
14774             ]
14775           };
14776         }
14777       }, {
14778         menus: {},
14779         expansions: {},
14780         items: []
14781       });
14782     };
14784     const getSearchModeForField = settings => {
14785       return settings.search.fold(() => ({ searchMode: 'no-search' }), searchSettings => ({
14786         searchMode: 'search-with-field',
14787         placeholder: searchSettings.placeholder
14788       }));
14789     };
14790     const getSearchModeForResults = settings => {
14791       return settings.search.fold(() => ({ searchMode: 'no-search' }), _ => ({ searchMode: 'search-with-results' }));
14792     };
14793     const build = (items, itemResponse, backstage, settings) => {
14794       const primary = generate$6('primary-menu');
14795       const data = expand(items, backstage.shared.providers.menuItems());
14796       if (data.items.length === 0) {
14797         return Optional.none();
14798       }
14799       const mainMenuSearchMode = getSearchModeForField(settings);
14800       const mainMenu = createPartialMenu(primary, data.items, itemResponse, backstage, settings.isHorizontalMenu, mainMenuSearchMode);
14801       const submenuSearchMode = getSearchModeForResults(settings);
14802       const submenus = map$1(data.menus, (menuItems, menuName) => createPartialMenu(menuName, menuItems, itemResponse, backstage, false, submenuSearchMode));
14803       const menus = deepMerge(submenus, wrap$1(primary, mainMenu));
14804       return Optional.from(tieredMenu.tieredData(primary, menus, data.expansions));
14805     };
14807     const isSingleListItem = item => !has$2(item, 'items');
14808     const dataAttribute = 'data-value';
14809     const fetchItems = (dropdownComp, name, items, selectedValue) => map$2(items, item => {
14810       if (!isSingleListItem(item)) {
14811         return {
14812           type: 'nestedmenuitem',
14813           text: item.text,
14814           getSubmenuItems: () => fetchItems(dropdownComp, name, item.items, selectedValue)
14815         };
14816       } else {
14817         return {
14818           type: 'togglemenuitem',
14819           text: item.text,
14820           value: item.value,
14821           active: item.value === selectedValue,
14822           onAction: () => {
14823             Representing.setValue(dropdownComp, item.value);
14824             emitWith(dropdownComp, formChangeEvent, { name });
14825             Focusing.focus(dropdownComp);
14826           }
14827         };
14828       }
14829     });
14830     const findItemByValue = (items, value) => findMap(items, item => {
14831       if (!isSingleListItem(item)) {
14832         return findItemByValue(item.items, value);
14833       } else {
14834         return someIf(item.value === value, item);
14835       }
14836     });
14837     const renderListBox = (spec, backstage, initialData) => {
14838       const providersBackstage = backstage.shared.providers;
14839       const initialItem = initialData.bind(value => findItemByValue(spec.items, value)).orThunk(() => head(spec.items).filter(isSingleListItem));
14840       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
14841       const pField = FormField.parts.field({
14842         dom: {},
14843         factory: {
14844           sketch: sketchSpec => renderCommonDropdown({
14845             uid: sketchSpec.uid,
14846             text: initialItem.map(item => item.text),
14847             icon: Optional.none(),
14848             tooltip: spec.label,
14849             role: Optional.none(),
14850             fetch: (comp, callback) => {
14851               const items = fetchItems(comp, spec.name, spec.items, Representing.getValue(comp));
14852               callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
14853                 isHorizontalMenu: false,
14854                 search: Optional.none()
14855               }));
14856             },
14857             onSetup: constant$1(noop),
14858             getApi: constant$1({}),
14859             columns: 1,
14860             presets: 'normal',
14861             classes: [],
14862             dropdownBehaviours: [
14863               Tabstopping.config({}),
14864               RepresentingConfigs.withComp(initialItem.map(item => item.value), comp => get$f(comp.element, dataAttribute), (comp, data) => {
14865                 findItemByValue(spec.items, data).each(item => {
14866                   set$9(comp.element, dataAttribute, item.value);
14867                   emitWith(comp, updateMenuText, { text: item.text });
14868                 });
14869               })
14870             ]
14871           }, 'tox-listbox', backstage.shared)
14872         }
14873       });
14874       const listBoxWrap = {
14875         dom: {
14876           tag: 'div',
14877           classes: ['tox-listboxfield']
14878         },
14879         components: [pField]
14880       };
14881       return FormField.sketch({
14882         dom: {
14883           tag: 'div',
14884           classes: ['tox-form__group']
14885         },
14886         components: flatten([
14887           pLabel.toArray(),
14888           [listBoxWrap]
14889         ]),
14890         fieldBehaviours: derive$1([Disabling.config({
14891             disabled: constant$1(!spec.enabled),
14892             onDisabled: comp => {
14893               FormField.getField(comp).each(Disabling.disable);
14894             },
14895             onEnabled: comp => {
14896               FormField.getField(comp).each(Disabling.enable);
14897             }
14898           })])
14899       });
14900     };
14902     const renderPanel = (spec, backstage) => ({
14903       dom: {
14904         tag: 'div',
14905         classes: spec.classes
14906       },
14907       components: map$2(spec.items, backstage.shared.interpreter)
14908     });
14910     const factory$f = (detail, _spec) => {
14911       const options = map$2(detail.options, option => ({
14912         dom: {
14913           tag: 'option',
14914           value: option.value,
14915           innerHtml: option.text
14916         }
14917       }));
14918       const initialValues = detail.data.map(v => wrap$1('initialValue', v)).getOr({});
14919       return {
14920         uid: detail.uid,
14921         dom: {
14922           tag: 'select',
14923           classes: detail.selectClasses,
14924           attributes: detail.selectAttributes
14925         },
14926         components: options,
14927         behaviours: augment(detail.selectBehaviours, [
14928           Focusing.config({}),
14929           Representing.config({
14930             store: {
14931               mode: 'manual',
14932               getValue: select => {
14933                 return get$6(select.element);
14934               },
14935               setValue: (select, newValue) => {
14936                 const found = find$5(detail.options, opt => opt.value === newValue);
14937                 if (found.isSome()) {
14938                   set$5(select.element, newValue);
14939                 }
14940               },
14941               ...initialValues
14942             }
14943           })
14944         ])
14945       };
14946     };
14947     const HtmlSelect = single({
14948       name: 'HtmlSelect',
14949       configFields: [
14950         required$1('options'),
14951         field('selectBehaviours', [
14952           Focusing,
14953           Representing
14954         ]),
14955         defaulted('selectClasses', []),
14956         defaulted('selectAttributes', {}),
14957         option$3('data')
14958       ],
14959       factory: factory$f
14960     });
14962     const renderSelectBox = (spec, providersBackstage, initialData) => {
14963       const translatedOptions = map$2(spec.items, item => ({
14964         text: providersBackstage.translate(item.text),
14965         value: item.value
14966       }));
14967       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
14968       const pField = FormField.parts.field({
14969         dom: {},
14970         ...initialData.map(data => ({ data })).getOr({}),
14971         selectAttributes: { size: spec.size },
14972         options: translatedOptions,
14973         factory: HtmlSelect,
14974         selectBehaviours: derive$1([
14975           Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
14976           Tabstopping.config({}),
14977           config('selectbox-change', [run$1(change(), (component, _) => {
14978               emitWith(component, formChangeEvent, { name: spec.name });
14979             })])
14980         ])
14981       });
14982       const chevron = spec.size > 1 ? Optional.none() : Optional.some(render$3('chevron-down', {
14983         tag: 'div',
14984         classes: ['tox-selectfield__icon-js']
14985       }, providersBackstage.icons));
14986       const selectWrap = {
14987         dom: {
14988           tag: 'div',
14989           classes: ['tox-selectfield']
14990         },
14991         components: flatten([
14992           [pField],
14993           chevron.toArray()
14994         ])
14995       };
14996       return FormField.sketch({
14997         dom: {
14998           tag: 'div',
14999           classes: ['tox-form__group']
15000         },
15001         components: flatten([
15002           pLabel.toArray(),
15003           [selectWrap]
15004         ]),
15005         fieldBehaviours: derive$1([
15006           Disabling.config({
15007             disabled: () => !spec.enabled || providersBackstage.isDisabled(),
15008             onDisabled: comp => {
15009               FormField.getField(comp).each(Disabling.disable);
15010             },
15011             onEnabled: comp => {
15012               FormField.getField(comp).each(Disabling.enable);
15013             }
15014           }),
15015           receivingConfig()
15016         ])
15017       });
15018     };
15020     const schema$h = constant$1([
15021       defaulted('field1Name', 'field1'),
15022       defaulted('field2Name', 'field2'),
15023       onStrictHandler('onLockedChange'),
15024       markers$1(['lockClass']),
15025       defaulted('locked', false),
15026       SketchBehaviours.field('coupledFieldBehaviours', [
15027         Composing,
15028         Representing
15029       ])
15030     ]);
15031     const getField = (comp, detail, partName) => getPart(comp, detail, partName).bind(Composing.getCurrent);
15032     const coupledPart = (selfName, otherName) => required({
15033       factory: FormField,
15034       name: selfName,
15035       overrides: detail => {
15036         return {
15037           fieldBehaviours: derive$1([config('coupled-input-behaviour', [run$1(input(), me => {
15038                 getField(me, detail, otherName).each(other => {
15039                   getPart(me, detail, 'lock').each(lock => {
15040                     if (Toggling.isOn(lock)) {
15041                       detail.onLockedChange(me, other, lock);
15042                     }
15043                   });
15044                 });
15045               })])])
15046         };
15047       }
15048     });
15049     const parts$c = constant$1([
15050       coupledPart('field1', 'field2'),
15051       coupledPart('field2', 'field1'),
15052       required({
15053         factory: Button,
15054         schema: [required$1('dom')],
15055         name: 'lock',
15056         overrides: detail => {
15057           return {
15058             buttonBehaviours: derive$1([Toggling.config({
15059                 selected: detail.locked,
15060                 toggleClass: detail.markers.lockClass,
15061                 aria: { mode: 'pressed' }
15062               })])
15063           };
15064         }
15065       })
15066     ]);
15068     const factory$e = (detail, components, _spec, _externals) => ({
15069       uid: detail.uid,
15070       dom: detail.dom,
15071       components,
15072       behaviours: SketchBehaviours.augment(detail.coupledFieldBehaviours, [
15073         Composing.config({ find: Optional.some }),
15074         Representing.config({
15075           store: {
15076             mode: 'manual',
15077             getValue: comp => {
15078               const parts = getPartsOrDie(comp, detail, [
15079                 'field1',
15080                 'field2'
15081               ]);
15082               return {
15083                 [detail.field1Name]: Representing.getValue(parts.field1()),
15084                 [detail.field2Name]: Representing.getValue(parts.field2())
15085               };
15086             },
15087             setValue: (comp, value) => {
15088               const parts = getPartsOrDie(comp, detail, [
15089                 'field1',
15090                 'field2'
15091               ]);
15092               if (hasNonNullableKey(value, detail.field1Name)) {
15093                 Representing.setValue(parts.field1(), value[detail.field1Name]);
15094               }
15095               if (hasNonNullableKey(value, detail.field2Name)) {
15096                 Representing.setValue(parts.field2(), value[detail.field2Name]);
15097               }
15098             }
15099           }
15100         })
15101       ]),
15102       apis: {
15103         getField1: component => getPart(component, detail, 'field1'),
15104         getField2: component => getPart(component, detail, 'field2'),
15105         getLock: component => getPart(component, detail, 'lock')
15106       }
15107     });
15108     const FormCoupledInputs = composite({
15109       name: 'FormCoupledInputs',
15110       configFields: schema$h(),
15111       partFields: parts$c(),
15112       factory: factory$e,
15113       apis: {
15114         getField1: (apis, component) => apis.getField1(component),
15115         getField2: (apis, component) => apis.getField2(component),
15116         getLock: (apis, component) => apis.getLock(component)
15117       }
15118     });
15120     const formatSize = size => {
15121       const unitDec = {
15122         '': 0,
15123         'px': 0,
15124         'pt': 1,
15125         'mm': 1,
15126         'pc': 2,
15127         'ex': 2,
15128         'em': 2,
15129         'ch': 2,
15130         'rem': 2,
15131         'cm': 3,
15132         'in': 4,
15133         '%': 4
15134       };
15135       const maxDecimal = unit => unit in unitDec ? unitDec[unit] : 1;
15136       let numText = size.value.toFixed(maxDecimal(size.unit));
15137       if (numText.indexOf('.') !== -1) {
15138         numText = numText.replace(/\.?0*$/, '');
15139       }
15140       return numText + size.unit;
15141     };
15142     const parseSize = sizeText => {
15143       const numPattern = /^\s*(\d+(?:\.\d+)?)\s*(|cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|%)\s*$/;
15144       const match = numPattern.exec(sizeText);
15145       if (match !== null) {
15146         const value = parseFloat(match[1]);
15147         const unit = match[2];
15148         return Result.value({
15149           value,
15150           unit
15151         });
15152       } else {
15153         return Result.error(sizeText);
15154       }
15155     };
15156     const convertUnit = (size, unit) => {
15157       const inInch = {
15158         '': 96,
15159         'px': 96,
15160         'pt': 72,
15161         'cm': 2.54,
15162         'pc': 12,
15163         'mm': 25.4,
15164         'in': 1
15165       };
15166       const supported = u => has$2(inInch, u);
15167       if (size.unit === unit) {
15168         return Optional.some(size.value);
15169       } else if (supported(size.unit) && supported(unit)) {
15170         if (inInch[size.unit] === inInch[unit]) {
15171           return Optional.some(size.value);
15172         } else {
15173           return Optional.some(size.value / inInch[size.unit] * inInch[unit]);
15174         }
15175       } else {
15176         return Optional.none();
15177       }
15178     };
15179     const noSizeConversion = _input => Optional.none();
15180     const ratioSizeConversion = (scale, unit) => size => convertUnit(size, unit).map(value => ({
15181       value: value * scale,
15182       unit
15183     }));
15184     const makeRatioConverter = (currentFieldText, otherFieldText) => {
15185       const cValue = parseSize(currentFieldText).toOptional();
15186       const oValue = parseSize(otherFieldText).toOptional();
15187       return lift2(cValue, oValue, (cSize, oSize) => convertUnit(cSize, oSize.unit).map(val => oSize.value / val).map(r => ratioSizeConversion(r, oSize.unit)).getOr(noSizeConversion)).getOr(noSizeConversion);
15188     };
15190     const renderSizeInput = (spec, providersBackstage) => {
15191       let converter = noSizeConversion;
15192       const ratioEvent = generate$6('ratio-event');
15193       const makeIcon = iconName => render$3(iconName, {
15194         tag: 'span',
15195         classes: [
15196           'tox-icon',
15197           'tox-lock-icon__' + iconName
15198         ]
15199       }, providersBackstage.icons);
15200       const pLock = FormCoupledInputs.parts.lock({
15201         dom: {
15202           tag: 'button',
15203           classes: [
15204             'tox-lock',
15205             'tox-button',
15206             'tox-button--naked',
15207             'tox-button--icon'
15208           ],
15209           attributes: { title: providersBackstage.translate(spec.label.getOr('Constrain proportions')) }
15210         },
15211         components: [
15212           makeIcon('lock'),
15213           makeIcon('unlock')
15214         ],
15215         buttonBehaviours: derive$1([
15216           Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
15217           receivingConfig(),
15218           Tabstopping.config({})
15219         ])
15220       });
15221       const formGroup = components => ({
15222         dom: {
15223           tag: 'div',
15224           classes: ['tox-form__group']
15225         },
15226         components
15227       });
15228       const getFieldPart = isField1 => FormField.parts.field({
15229         factory: Input,
15230         inputClasses: ['tox-textfield'],
15231         inputBehaviours: derive$1([
15232           Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
15233           receivingConfig(),
15234           Tabstopping.config({}),
15235           config('size-input-events', [
15236             run$1(focusin(), (component, _simulatedEvent) => {
15237               emitWith(component, ratioEvent, { isField1 });
15238             }),
15239             run$1(change(), (component, _simulatedEvent) => {
15240               emitWith(component, formChangeEvent, { name: spec.name });
15241             })
15242           ])
15243         ]),
15244         selectOnFocus: false
15245       });
15246       const getLabel = label => ({
15247         dom: {
15248           tag: 'label',
15249           classes: ['tox-label']
15250         },
15251         components: [text$2(providersBackstage.translate(label))]
15252       });
15253       const widthField = FormCoupledInputs.parts.field1(formGroup([
15254         FormField.parts.label(getLabel('Width')),
15255         getFieldPart(true)
15256       ]));
15257       const heightField = FormCoupledInputs.parts.field2(formGroup([
15258         FormField.parts.label(getLabel('Height')),
15259         getFieldPart(false)
15260       ]));
15261       return FormCoupledInputs.sketch({
15262         dom: {
15263           tag: 'div',
15264           classes: ['tox-form__group']
15265         },
15266         components: [{
15267             dom: {
15268               tag: 'div',
15269               classes: ['tox-form__controls-h-stack']
15270             },
15271             components: [
15272               widthField,
15273               heightField,
15274               formGroup([
15275                 getLabel(nbsp),
15276                 pLock
15277               ])
15278             ]
15279           }],
15280         field1Name: 'width',
15281         field2Name: 'height',
15282         locked: true,
15283         markers: { lockClass: 'tox-locked' },
15284         onLockedChange: (current, other, _lock) => {
15285           parseSize(Representing.getValue(current)).each(size => {
15286             converter(size).each(newSize => {
15287               Representing.setValue(other, formatSize(newSize));
15288             });
15289           });
15290         },
15291         coupledFieldBehaviours: derive$1([
15292           Disabling.config({
15293             disabled: () => !spec.enabled || providersBackstage.isDisabled(),
15294             onDisabled: comp => {
15295               FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.disable);
15296               FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.disable);
15297               FormCoupledInputs.getLock(comp).each(Disabling.disable);
15298             },
15299             onEnabled: comp => {
15300               FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.enable);
15301               FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.enable);
15302               FormCoupledInputs.getLock(comp).each(Disabling.enable);
15303             }
15304           }),
15305           receivingConfig(),
15306           config('size-input-events2', [run$1(ratioEvent, (component, simulatedEvent) => {
15307               const isField1 = simulatedEvent.event.isField1;
15308               const optCurrent = isField1 ? FormCoupledInputs.getField1(component) : FormCoupledInputs.getField2(component);
15309               const optOther = isField1 ? FormCoupledInputs.getField2(component) : FormCoupledInputs.getField1(component);
15310               const value1 = optCurrent.map(Representing.getValue).getOr('');
15311               const value2 = optOther.map(Representing.getValue).getOr('');
15312               converter = makeRatioConverter(value1, value2);
15313             })])
15314         ])
15315       });
15316     };
15318     const renderSlider = (spec, providerBackstage, initialData) => {
15319       const labelPart = Slider.parts.label({
15320         dom: {
15321           tag: 'label',
15322           classes: ['tox-label']
15323         },
15324         components: [text$2(providerBackstage.translate(spec.label))]
15325       });
15326       const spectrum = Slider.parts.spectrum({
15327         dom: {
15328           tag: 'div',
15329           classes: ['tox-slider__rail'],
15330           attributes: { role: 'presentation' }
15331         }
15332       });
15333       const thumb = Slider.parts.thumb({
15334         dom: {
15335           tag: 'div',
15336           classes: ['tox-slider__handle'],
15337           attributes: { role: 'presentation' }
15338         }
15339       });
15340       return Slider.sketch({
15341         dom: {
15342           tag: 'div',
15343           classes: ['tox-slider'],
15344           attributes: { role: 'presentation' }
15345         },
15346         model: {
15347           mode: 'x',
15348           minX: spec.min,
15349           maxX: spec.max,
15350           getInitialValue: constant$1(initialData.getOrThunk(() => (Math.abs(spec.max) - Math.abs(spec.min)) / 2))
15351         },
15352         components: [
15353           labelPart,
15354           spectrum,
15355           thumb
15356         ],
15357         sliderBehaviours: derive$1([
15358           ComposingConfigs.self(),
15359           Focusing.config({})
15360         ]),
15361         onChoose: (component, thumb, value) => {
15362           emitWith(component, formChangeEvent, {
15363             name: spec.name,
15364             value
15365           });
15366         }
15367       });
15368     };
15370     const renderTable = (spec, providersBackstage) => {
15371       const renderTh = text => ({
15372         dom: {
15373           tag: 'th',
15374           innerHtml: providersBackstage.translate(text)
15375         }
15376       });
15377       const renderHeader = header => ({
15378         dom: { tag: 'thead' },
15379         components: [{
15380             dom: { tag: 'tr' },
15381             components: map$2(header, renderTh)
15382           }]
15383       });
15384       const renderTd = text => ({
15385         dom: {
15386           tag: 'td',
15387           innerHtml: providersBackstage.translate(text)
15388         }
15389       });
15390       const renderTr = row => ({
15391         dom: { tag: 'tr' },
15392         components: map$2(row, renderTd)
15393       });
15394       const renderRows = rows => ({
15395         dom: { tag: 'tbody' },
15396         components: map$2(rows, renderTr)
15397       });
15398       return {
15399         dom: {
15400           tag: 'table',
15401           classes: ['tox-dialog__table']
15402         },
15403         components: [
15404           renderHeader(spec.header),
15405           renderRows(spec.cells)
15406         ],
15407         behaviours: derive$1([
15408           Tabstopping.config({}),
15409           Focusing.config({})
15410         ])
15411       };
15412     };
15414     const renderTextField = (spec, providersBackstage) => {
15415       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
15416       const baseInputBehaviours = [
15417         Disabling.config({ disabled: () => spec.disabled || providersBackstage.isDisabled() }),
15418         receivingConfig(),
15419         Keying.config({
15420           mode: 'execution',
15421           useEnter: spec.multiline !== true,
15422           useControlEnter: spec.multiline === true,
15423           execute: comp => {
15424             emit(comp, formSubmitEvent);
15425             return Optional.some(true);
15426           }
15427         }),
15428         config('textfield-change', [
15429           run$1(input(), (component, _) => {
15430             emitWith(component, formChangeEvent, { name: spec.name });
15431           }),
15432           run$1(postPaste(), (component, _) => {
15433             emitWith(component, formChangeEvent, { name: spec.name });
15434           })
15435         ]),
15436         Tabstopping.config({})
15437       ];
15438       const validatingBehaviours = spec.validation.map(vl => Invalidating.config({
15439         getRoot: input => {
15440           return parentElement(input.element);
15441         },
15442         invalidClass: 'tox-invalid',
15443         validator: {
15444           validate: input => {
15445             const v = Representing.getValue(input);
15446             const result = vl.validator(v);
15447             return Future.pure(result === true ? Result.value(v) : Result.error(result));
15448           },
15449           validateOnLoad: vl.validateOnLoad
15450         }
15451       })).toArray();
15452       const placeholder = spec.placeholder.fold(constant$1({}), p => ({ placeholder: providersBackstage.translate(p) }));
15453       const inputMode = spec.inputMode.fold(constant$1({}), mode => ({ inputmode: mode }));
15454       const inputAttributes = {
15455         ...placeholder,
15456         ...inputMode
15457       };
15458       const pField = FormField.parts.field({
15459         tag: spec.multiline === true ? 'textarea' : 'input',
15460         ...spec.data.map(data => ({ data })).getOr({}),
15461         inputAttributes,
15462         inputClasses: [spec.classname],
15463         inputBehaviours: derive$1(flatten([
15464           baseInputBehaviours,
15465           validatingBehaviours
15466         ])),
15467         selectOnFocus: false,
15468         factory: Input
15469       });
15470       const extraClasses = spec.flex ? ['tox-form__group--stretched'] : [];
15471       const extraClasses2 = extraClasses.concat(spec.maximized ? ['tox-form-group--maximize'] : []);
15472       const extraBehaviours = [
15473         Disabling.config({
15474           disabled: () => spec.disabled || providersBackstage.isDisabled(),
15475           onDisabled: comp => {
15476             FormField.getField(comp).each(Disabling.disable);
15477           },
15478           onEnabled: comp => {
15479             FormField.getField(comp).each(Disabling.enable);
15480           }
15481         }),
15482         receivingConfig()
15483       ];
15484       return renderFormFieldWith(pLabel, pField, extraClasses2, extraBehaviours);
15485     };
15486     const renderInput = (spec, providersBackstage, initialData) => renderTextField({
15487       name: spec.name,
15488       multiline: false,
15489       label: spec.label,
15490       inputMode: spec.inputMode,
15491       placeholder: spec.placeholder,
15492       flex: false,
15493       disabled: !spec.enabled,
15494       classname: 'tox-textfield',
15495       validation: Optional.none(),
15496       maximized: spec.maximized,
15497       data: initialData
15498     }, providersBackstage);
15499     const renderTextarea = (spec, providersBackstage, initialData) => renderTextField({
15500       name: spec.name,
15501       multiline: true,
15502       label: spec.label,
15503       inputMode: Optional.none(),
15504       placeholder: spec.placeholder,
15505       flex: true,
15506       disabled: !spec.enabled,
15507       classname: 'tox-textarea',
15508       validation: Optional.none(),
15509       maximized: spec.maximized,
15510       data: initialData
15511     }, providersBackstage);
15513     const events$6 = (streamConfig, streamState) => {
15514       const streams = streamConfig.stream.streams;
15515       const processor = streams.setup(streamConfig, streamState);
15516       return derive$2([
15517         run$1(streamConfig.event, processor),
15518         runOnDetached(() => streamState.cancel())
15519       ].concat(streamConfig.cancelEvent.map(e => [run$1(e, () => streamState.cancel())]).getOr([])));
15520     };
15522     var ActiveStreaming = /*#__PURE__*/Object.freeze({
15523         __proto__: null,
15524         events: events$6
15525     });
15527     const first = (fn, rate) => {
15528       let timer = null;
15529       const cancel = () => {
15530         if (!isNull(timer)) {
15531           clearTimeout(timer);
15532           timer = null;
15533         }
15534       };
15535       const throttle = (...args) => {
15536         if (isNull(timer)) {
15537           timer = setTimeout(() => {
15538             timer = null;
15539             fn.apply(null, args);
15540           }, rate);
15541         }
15542       };
15543       return {
15544         cancel,
15545         throttle
15546       };
15547     };
15548     const last = (fn, rate) => {
15549       let timer = null;
15550       const cancel = () => {
15551         if (!isNull(timer)) {
15552           clearTimeout(timer);
15553           timer = null;
15554         }
15555       };
15556       const throttle = (...args) => {
15557         cancel();
15558         timer = setTimeout(() => {
15559           timer = null;
15560           fn.apply(null, args);
15561         }, rate);
15562       };
15563       return {
15564         cancel,
15565         throttle
15566       };
15567     };
15569     const throttle = _config => {
15570       const state = Cell(null);
15571       const readState = () => ({ timer: state.get() !== null ? 'set' : 'unset' });
15572       const setTimer = t => {
15573         state.set(t);
15574       };
15575       const cancel = () => {
15576         const t = state.get();
15577         if (t !== null) {
15578           t.cancel();
15579         }
15580       };
15581       return nu$8({
15582         readState,
15583         setTimer,
15584         cancel
15585       });
15586     };
15587     const init$9 = spec => spec.stream.streams.state(spec);
15589     var StreamingState = /*#__PURE__*/Object.freeze({
15590         __proto__: null,
15591         throttle: throttle,
15592         init: init$9
15593     });
15595     const setup$c = (streamInfo, streamState) => {
15596       const sInfo = streamInfo.stream;
15597       const throttler = last(streamInfo.onStream, sInfo.delay);
15598       streamState.setTimer(throttler);
15599       return (component, simulatedEvent) => {
15600         throttler.throttle(component, simulatedEvent);
15601         if (sInfo.stopEvent) {
15602           simulatedEvent.stop();
15603         }
15604       };
15605     };
15606     var StreamingSchema = [
15607       requiredOf('stream', choose$1('mode', {
15608         throttle: [
15609           required$1('delay'),
15610           defaulted('stopEvent', true),
15611           output$1('streams', {
15612             setup: setup$c,
15613             state: throttle
15614           })
15615         ]
15616       })),
15617       defaulted('event', 'input'),
15618       option$3('cancelEvent'),
15619       onStrictHandler('onStream')
15620     ];
15622     const Streaming = create$4({
15623       fields: StreamingSchema,
15624       name: 'streaming',
15625       active: ActiveStreaming,
15626       state: StreamingState
15627     });
15629     const setValueFromItem = (model, input, item) => {
15630       const itemData = Representing.getValue(item);
15631       Representing.setValue(input, itemData);
15632       setCursorAtEnd(input);
15633     };
15634     const setSelectionOn = (input, f) => {
15635       const el = input.element;
15636       const value = get$6(el);
15637       const node = el.dom;
15638       if (get$f(el, 'type') !== 'number') {
15639         f(node, value);
15640       }
15641     };
15642     const setCursorAtEnd = input => {
15643       setSelectionOn(input, (node, value) => node.setSelectionRange(value.length, value.length));
15644     };
15645     const setSelectionToEnd = (input, startOffset) => {
15646       setSelectionOn(input, (node, value) => node.setSelectionRange(startOffset, value.length));
15647     };
15648     const attemptSelectOver = (model, input, item) => {
15649       if (!model.selectsOver) {
15650         return Optional.none();
15651       } else {
15652         const currentValue = Representing.getValue(input);
15653         const inputDisplay = model.getDisplayText(currentValue);
15654         const itemValue = Representing.getValue(item);
15655         const itemDisplay = model.getDisplayText(itemValue);
15656         return itemDisplay.indexOf(inputDisplay) === 0 ? Optional.some(() => {
15657           setValueFromItem(model, input, item);
15658           setSelectionToEnd(input, inputDisplay.length);
15659         }) : Optional.none();
15660       }
15661     };
15663     const itemExecute = constant$1('alloy.typeahead.itemexecute');
15665     const make$3 = (detail, components, spec, externals) => {
15666       const navigateList = (comp, simulatedEvent, highlighter) => {
15667         detail.previewing.set(false);
15668         const sandbox = Coupling.getCoupled(comp, 'sandbox');
15669         if (Sandboxing.isOpen(sandbox)) {
15670           Composing.getCurrent(sandbox).each(menu => {
15671             Highlighting.getHighlighted(menu).fold(() => {
15672               highlighter(menu);
15673             }, () => {
15674               dispatchEvent(sandbox, menu.element, 'keydown', simulatedEvent);
15675             });
15676           });
15677         } else {
15678           const onOpenSync = sandbox => {
15679             Composing.getCurrent(sandbox).each(highlighter);
15680           };
15681           open(detail, mapFetch(comp), comp, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
15682         }
15683       };
15684       const focusBehaviours$1 = focusBehaviours(detail);
15685       const mapFetch = comp => tdata => tdata.map(data => {
15686         const menus = values(data.menus);
15687         const items = bind$3(menus, menu => filter$2(menu.items, item => item.type === 'item'));
15688         const repState = Representing.getState(comp);
15689         repState.update(map$2(items, item => item.data));
15690         return data;
15691       });
15692       const getActiveMenu = sandboxComp => Composing.getCurrent(sandboxComp);
15693       const typeaheadCustomEvents = 'typeaheadevents';
15694       const behaviours = [
15695         Focusing.config({}),
15696         Representing.config({
15697           onSetValue: detail.onSetValue,
15698           store: {
15699             mode: 'dataset',
15700             getDataKey: comp => get$6(comp.element),
15701             getFallbackEntry: itemString => ({
15702               value: itemString,
15703               meta: {}
15704             }),
15705             setValue: (comp, data) => {
15706               set$5(comp.element, detail.model.getDisplayText(data));
15707             },
15708             ...detail.initialData.map(d => wrap$1('initialValue', d)).getOr({})
15709           }
15710         }),
15711         Streaming.config({
15712           stream: {
15713             mode: 'throttle',
15714             delay: detail.responseTime,
15715             stopEvent: false
15716           },
15717           onStream: (component, _simulatedEvent) => {
15718             const sandbox = Coupling.getCoupled(component, 'sandbox');
15719             const focusInInput = Focusing.isFocused(component);
15720             if (focusInInput) {
15721               if (get$6(component.element).length >= detail.minChars) {
15722                 const previousValue = getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu).map(Representing.getValue));
15723                 detail.previewing.set(true);
15724                 const onOpenSync = _sandbox => {
15725                   getActiveMenu(sandbox).each(activeMenu => {
15726                     previousValue.fold(() => {
15727                       if (detail.model.selectsOver) {
15728                         Highlighting.highlightFirst(activeMenu);
15729                       }
15730                     }, pv => {
15731                       Highlighting.highlightBy(activeMenu, item => {
15732                         const itemData = Representing.getValue(item);
15733                         return itemData.value === pv.value;
15734                       });
15735                       Highlighting.getHighlighted(activeMenu).orThunk(() => {
15736                         Highlighting.highlightFirst(activeMenu);
15737                         return Optional.none();
15738                       });
15739                     });
15740                   });
15741                 };
15742                 open(detail, mapFetch(component), component, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightJustMenu).get(noop);
15743               }
15744             }
15745           },
15746           cancelEvent: typeaheadCancel()
15747         }),
15748         Keying.config({
15749           mode: 'special',
15750           onDown: (comp, simulatedEvent) => {
15751             navigateList(comp, simulatedEvent, Highlighting.highlightFirst);
15752             return Optional.some(true);
15753           },
15754           onEscape: comp => {
15755             const sandbox = Coupling.getCoupled(comp, 'sandbox');
15756             if (Sandboxing.isOpen(sandbox)) {
15757               Sandboxing.close(sandbox);
15758               return Optional.some(true);
15759             }
15760             return Optional.none();
15761           },
15762           onUp: (comp, simulatedEvent) => {
15763             navigateList(comp, simulatedEvent, Highlighting.highlightLast);
15764             return Optional.some(true);
15765           },
15766           onEnter: comp => {
15767             const sandbox = Coupling.getCoupled(comp, 'sandbox');
15768             const sandboxIsOpen = Sandboxing.isOpen(sandbox);
15769             if (sandboxIsOpen && !detail.previewing.get()) {
15770               return getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu)).map(item => {
15771                 emitWith(comp, itemExecute(), { item });
15772                 return true;
15773               });
15774             } else {
15775               const currentValue = Representing.getValue(comp);
15776               emit(comp, typeaheadCancel());
15777               detail.onExecute(sandbox, comp, currentValue);
15778               if (sandboxIsOpen) {
15779                 Sandboxing.close(sandbox);
15780               }
15781               return Optional.some(true);
15782             }
15783           }
15784         }),
15785         Toggling.config({
15786           toggleClass: detail.markers.openClass,
15787           aria: { mode: 'expanded' }
15788         }),
15789         Coupling.config({
15790           others: {
15791             sandbox: hotspot => {
15792               return makeSandbox$1(detail, hotspot, {
15793                 onOpen: () => Toggling.on(hotspot),
15794                 onClose: () => Toggling.off(hotspot)
15795               });
15796             }
15797           }
15798         }),
15799         config(typeaheadCustomEvents, [
15800           runOnAttached(typeaheadComp => {
15801             detail.lazyTypeaheadComp.set(Optional.some(typeaheadComp));
15802           }),
15803           runOnDetached(_typeaheadComp => {
15804             detail.lazyTypeaheadComp.set(Optional.none());
15805           }),
15806           runOnExecute$1(comp => {
15807             const onOpenSync = noop;
15808             togglePopup(detail, mapFetch(comp), comp, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
15809           }),
15810           run$1(itemExecute(), (comp, se) => {
15811             const sandbox = Coupling.getCoupled(comp, 'sandbox');
15812             setValueFromItem(detail.model, comp, se.event.item);
15813             emit(comp, typeaheadCancel());
15814             detail.onItemExecute(comp, sandbox, se.event.item, Representing.getValue(comp));
15815             Sandboxing.close(sandbox);
15816             setCursorAtEnd(comp);
15817           })
15818         ].concat(detail.dismissOnBlur ? [run$1(postBlur(), typeahead => {
15819             const sandbox = Coupling.getCoupled(typeahead, 'sandbox');
15820             if (search(sandbox.element).isNone()) {
15821               Sandboxing.close(sandbox);
15822             }
15823           })] : []))
15824       ];
15825       const eventOrder = {
15826         [detachedFromDom()]: [
15827           Representing.name(),
15828           Streaming.name(),
15829           typeaheadCustomEvents
15830         ],
15831         ...detail.eventOrder
15832       };
15833       return {
15834         uid: detail.uid,
15835         dom: dom(deepMerge(detail, {
15836           inputAttributes: {
15837             'role': 'combobox',
15838             'aria-autocomplete': 'list',
15839             'aria-haspopup': 'true'
15840           }
15841         })),
15842         behaviours: {
15843           ...focusBehaviours$1,
15844           ...augment(detail.typeaheadBehaviours, behaviours)
15845         },
15846         eventOrder
15847       };
15848     };
15850     const schema$g = constant$1([
15851       option$3('lazySink'),
15852       required$1('fetch'),
15853       defaulted('minChars', 5),
15854       defaulted('responseTime', 1000),
15855       onHandler('onOpen'),
15856       defaulted('getHotspot', Optional.some),
15857       defaulted('getAnchorOverrides', constant$1({})),
15858       defaulted('layouts', Optional.none()),
15859       defaulted('eventOrder', {}),
15860       defaultedObjOf('model', {}, [
15861         defaulted('getDisplayText', itemData => itemData.meta !== undefined && itemData.meta.text !== undefined ? itemData.meta.text : itemData.value),
15862         defaulted('selectsOver', true),
15863         defaulted('populateFromBrowse', true)
15864       ]),
15865       onHandler('onSetValue'),
15866       onKeyboardHandler('onExecute'),
15867       onHandler('onItemExecute'),
15868       defaulted('inputClasses', []),
15869       defaulted('inputAttributes', {}),
15870       defaulted('inputStyles', {}),
15871       defaulted('matchWidth', true),
15872       defaulted('useMinWidth', false),
15873       defaulted('dismissOnBlur', true),
15874       markers$1(['openClass']),
15875       option$3('initialData'),
15876       field('typeaheadBehaviours', [
15877         Focusing,
15878         Representing,
15879         Streaming,
15880         Keying,
15881         Toggling,
15882         Coupling
15883       ]),
15884       customField('lazyTypeaheadComp', () => Cell(Optional.none)),
15885       customField('previewing', () => Cell(true))
15886     ].concat(schema$l()).concat(sandboxFields()));
15887     const parts$b = constant$1([external({
15888         schema: [tieredMenuMarkers()],
15889         name: 'menu',
15890         overrides: detail => {
15891           return {
15892             fakeFocus: true,
15893             onHighlightItem: (_tmenu, menu, item) => {
15894               if (!detail.previewing.get()) {
15895                 detail.lazyTypeaheadComp.get().each(input => {
15896                   if (detail.model.populateFromBrowse) {
15897                     setValueFromItem(detail.model, input, item);
15898                   }
15899                 });
15900               } else {
15901                 detail.lazyTypeaheadComp.get().each(input => {
15902                   attemptSelectOver(detail.model, input, item).fold(() => {
15903                     if (detail.model.selectsOver) {
15904                       Highlighting.dehighlight(menu, item);
15905                       detail.previewing.set(true);
15906                     } else {
15907                       detail.previewing.set(false);
15908                     }
15909                   }, selectOverTextInInput => {
15910                     selectOverTextInInput();
15911                     detail.previewing.set(false);
15912                   });
15913                 });
15914               }
15915             },
15916             onExecute: (_menu, item) => {
15917               return detail.lazyTypeaheadComp.get().map(typeahead => {
15918                 emitWith(typeahead, itemExecute(), { item });
15919                 return true;
15920               });
15921             },
15922             onHover: (menu, item) => {
15923               detail.previewing.set(false);
15924               detail.lazyTypeaheadComp.get().each(input => {
15925                 if (detail.model.populateFromBrowse) {
15926                   setValueFromItem(detail.model, input, item);
15927                 }
15928               });
15929             }
15930           };
15931         }
15932       })]);
15934     const Typeahead = composite({
15935       name: 'Typeahead',
15936       configFields: schema$g(),
15937       partFields: parts$b(),
15938       factory: make$3
15939     });
15941     const wrap = delegate => {
15942       const toCached = () => {
15943         return wrap(delegate.toCached());
15944       };
15945       const bindFuture = f => {
15946         return wrap(delegate.bind(resA => resA.fold(err => Future.pure(Result.error(err)), a => f(a))));
15947       };
15948       const bindResult = f => {
15949         return wrap(delegate.map(resA => resA.bind(f)));
15950       };
15951       const mapResult = f => {
15952         return wrap(delegate.map(resA => resA.map(f)));
15953       };
15954       const mapError = f => {
15955         return wrap(delegate.map(resA => resA.mapError(f)));
15956       };
15957       const foldResult = (whenError, whenValue) => {
15958         return delegate.map(res => res.fold(whenError, whenValue));
15959       };
15960       const withTimeout = (timeout, errorThunk) => {
15961         return wrap(Future.nu(callback => {
15962           let timedOut = false;
15963           const timer = setTimeout(() => {
15964             timedOut = true;
15965             callback(Result.error(errorThunk()));
15966           }, timeout);
15967           delegate.get(result => {
15968             if (!timedOut) {
15969               clearTimeout(timer);
15970               callback(result);
15971             }
15972           });
15973         }));
15974       };
15975       return {
15976         ...delegate,
15977         toCached,
15978         bindFuture,
15979         bindResult,
15980         mapResult,
15981         mapError,
15982         foldResult,
15983         withTimeout
15984       };
15985     };
15986     const nu$1 = worker => {
15987       return wrap(Future.nu(worker));
15988     };
15989     const value = value => {
15990       return wrap(Future.pure(Result.value(value)));
15991     };
15992     const error = error => {
15993       return wrap(Future.pure(Result.error(error)));
15994     };
15995     const fromResult = result => {
15996       return wrap(Future.pure(result));
15997     };
15998     const fromFuture = future => {
15999       return wrap(future.map(Result.value));
16000     };
16001     const fromPromise = promise => {
16002       return nu$1(completer => {
16003         promise.then(value => {
16004           completer(Result.value(value));
16005         }, error => {
16006           completer(Result.error(error));
16007         });
16008       });
16009     };
16010     const FutureResult = {
16011       nu: nu$1,
16012       wrap,
16013       pure: value,
16014       value,
16015       error,
16016       fromResult,
16017       fromFuture,
16018       fromPromise
16019     };
16021     const getMenuButtonApi = component => ({
16022       isEnabled: () => !Disabling.isDisabled(component),
16023       setEnabled: state => Disabling.set(component, !state),
16024       setActive: state => {
16025         const elm = component.element;
16026         if (state) {
16027           add$2(elm, 'tox-tbtn--enabled');
16028           set$9(elm, 'aria-pressed', true);
16029         } else {
16030           remove$2(elm, 'tox-tbtn--enabled');
16031           remove$7(elm, 'aria-pressed');
16032         }
16033       },
16034       isActive: () => has(component.element, 'tox-tbtn--enabled')
16035     });
16036     const renderMenuButton = (spec, prefix, backstage, role) => {
16037       return renderCommonDropdown({
16038         text: spec.text,
16039         icon: spec.icon,
16040         tooltip: spec.tooltip,
16041         searchable: spec.search.isSome(),
16042         role,
16043         fetch: (dropdownComp, callback) => {
16044           const fetchContext = { pattern: spec.search.isSome() ? getSearchPattern(dropdownComp) : '' };
16045           spec.fetch(items => {
16046             callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
16047               isHorizontalMenu: false,
16048               search: spec.search
16049             }));
16050           }, fetchContext);
16051         },
16052         onSetup: spec.onSetup,
16053         getApi: getMenuButtonApi,
16054         columns: 1,
16055         presets: 'normal',
16056         classes: [],
16057         dropdownBehaviours: [Tabstopping.config({})]
16058       }, prefix, backstage.shared);
16059     };
16060     const getFetch = (items, getButton, backstage) => {
16061       const getMenuItemAction = item => api => {
16062         const newValue = !api.isActive();
16063         api.setActive(newValue);
16064         item.storage.set(newValue);
16065         backstage.shared.getSink().each(sink => {
16066           getButton().getOpt(sink).each(orig => {
16067             focus$3(orig.element);
16068             emitWith(orig, formActionEvent, {
16069               name: item.name,
16070               value: item.storage.get()
16071             });
16072           });
16073         });
16074       };
16075       const getMenuItemSetup = item => api => {
16076         api.setActive(item.storage.get());
16077       };
16078       return success => {
16079         success(map$2(items, item => {
16080           const text = item.text.fold(() => ({}), text => ({ text }));
16081           return {
16082             type: item.type,
16083             active: false,
16084             ...text,
16085             onAction: getMenuItemAction(item),
16086             onSetup: getMenuItemSetup(item)
16087           };
16088         }));
16089       };
16090     };
16092     const renderCommonSpec = (spec, actionOpt, extraBehaviours = [], dom, components, providersBackstage) => {
16093       const action = actionOpt.fold(() => ({}), action => ({ action }));
16094       const common = {
16095         buttonBehaviours: derive$1([
16096           DisablingConfigs.button(() => !spec.enabled || providersBackstage.isDisabled()),
16097           receivingConfig(),
16098           Tabstopping.config({}),
16099           config('button press', [
16100             preventDefault('click'),
16101             preventDefault('mousedown')
16102           ])
16103         ].concat(extraBehaviours)),
16104         eventOrder: {
16105           click: [
16106             'button press',
16107             'alloy.base.behaviour'
16108           ],
16109           mousedown: [
16110             'button press',
16111             'alloy.base.behaviour'
16112           ]
16113         },
16114         ...action
16115       };
16116       const domFinal = deepMerge(common, { dom });
16117       return deepMerge(domFinal, { components });
16118     };
16119     const renderIconButtonSpec = (spec, action, providersBackstage, extraBehaviours = []) => {
16120       const tooltipAttributes = spec.tooltip.map(tooltip => ({
16121         'aria-label': providersBackstage.translate(tooltip),
16122         'title': providersBackstage.translate(tooltip)
16123       })).getOr({});
16124       const dom = {
16125         tag: 'button',
16126         classes: ['tox-tbtn'],
16127         attributes: tooltipAttributes
16128       };
16129       const icon = spec.icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons));
16130       const components = componentRenderPipeline([icon]);
16131       return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
16132     };
16133     const calculateClassesFromButtonType = buttonType => {
16134       switch (buttonType) {
16135       case 'primary':
16136         return ['tox-button'];
16137       case 'toolbar':
16138         return ['tox-tbtn'];
16139       case 'secondary':
16140       default:
16141         return [
16142           'tox-button',
16143           'tox-button--secondary'
16144         ];
16145       }
16146     };
16147     const renderButtonSpec = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
16148       const translatedText = providersBackstage.translate(spec.text);
16149       const icon = spec.icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons));
16150       const components = [icon.getOrThunk(() => text$2(translatedText))];
16151       const buttonType = spec.buttonType.getOr(!spec.primary && !spec.borderless ? 'secondary' : 'primary');
16152       const baseClasses = calculateClassesFromButtonType(buttonType);
16153       const classes = [
16154         ...baseClasses,
16155         ...icon.isSome() ? ['tox-button--icon'] : [],
16156         ...spec.borderless ? ['tox-button--naked'] : [],
16157         ...extraClasses
16158       ];
16159       const dom = {
16160         tag: 'button',
16161         classes,
16162         attributes: { title: translatedText }
16163       };
16164       return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
16165     };
16166     const renderButton = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
16167       const buttonSpec = renderButtonSpec(spec, Optional.some(action), providersBackstage, extraBehaviours, extraClasses);
16168       return Button.sketch(buttonSpec);
16169     };
16170     const getAction = (name, buttonType) => comp => {
16171       if (buttonType === 'custom') {
16172         emitWith(comp, formActionEvent, {
16173           name,
16174           value: {}
16175         });
16176       } else if (buttonType === 'submit') {
16177         emit(comp, formSubmitEvent);
16178       } else if (buttonType === 'cancel') {
16179         emit(comp, formCancelEvent);
16180       } else {
16181         console.error('Unknown button type: ', buttonType);
16182       }
16183     };
16184     const isMenuFooterButtonSpec = (spec, buttonType) => buttonType === 'menu';
16185     const isNormalFooterButtonSpec = (spec, buttonType) => buttonType === 'custom' || buttonType === 'cancel' || buttonType === 'submit';
16186     const renderFooterButton = (spec, buttonType, backstage) => {
16187       if (isMenuFooterButtonSpec(spec, buttonType)) {
16188         const getButton = () => memButton;
16189         const menuButtonSpec = spec;
16190         const fixedSpec = {
16191           ...spec,
16192           type: 'menubutton',
16193           search: Optional.none(),
16194           onSetup: api => {
16195             api.setEnabled(spec.enabled);
16196             return noop;
16197           },
16198           fetch: getFetch(menuButtonSpec.items, getButton, backstage)
16199         };
16200         const memButton = record(renderMenuButton(fixedSpec, 'tox-tbtn', backstage, Optional.none()));
16201         return memButton.asSpec();
16202       } else if (isNormalFooterButtonSpec(spec, buttonType)) {
16203         const action = getAction(spec.name, buttonType);
16204         const buttonSpec = {
16205           ...spec,
16206           borderless: false
16207         };
16208         return renderButton(buttonSpec, action, backstage.shared.providers, []);
16209       } else {
16210         console.error('Unknown footer button type: ', buttonType);
16211         throw new Error('Unknown footer button type');
16212       }
16213     };
16214     const renderDialogButton = (spec, providersBackstage) => {
16215       const action = getAction(spec.name, 'custom');
16216       return renderFormField(Optional.none(), FormField.parts.field({
16217         factory: Button,
16218         ...renderButtonSpec(spec, Optional.some(action), providersBackstage, [
16219           RepresentingConfigs.memory(''),
16220           ComposingConfigs.self()
16221         ])
16222       }));
16223     };
16225     const separator$1 = { type: 'separator' };
16226     const toMenuItem = target => ({
16227       type: 'menuitem',
16228       value: target.url,
16229       text: target.title,
16230       meta: { attach: target.attach },
16231       onAction: noop
16232     });
16233     const staticMenuItem = (title, url) => ({
16234       type: 'menuitem',
16235       value: url,
16236       text: title,
16237       meta: { attach: undefined },
16238       onAction: noop
16239     });
16240     const toMenuItems = targets => map$2(targets, toMenuItem);
16241     const filterLinkTargets = (type, targets) => filter$2(targets, target => target.type === type);
16242     const filteredTargets = (type, targets) => toMenuItems(filterLinkTargets(type, targets));
16243     const headerTargets = linkInfo => filteredTargets('header', linkInfo.targets);
16244     const anchorTargets = linkInfo => filteredTargets('anchor', linkInfo.targets);
16245     const anchorTargetTop = linkInfo => Optional.from(linkInfo.anchorTop).map(url => staticMenuItem('<top>', url)).toArray();
16246     const anchorTargetBottom = linkInfo => Optional.from(linkInfo.anchorBottom).map(url => staticMenuItem('<bottom>', url)).toArray();
16247     const historyTargets = history => map$2(history, url => staticMenuItem(url, url));
16248     const joinMenuLists = items => {
16249       return foldl(items, (a, b) => {
16250         const bothEmpty = a.length === 0 || b.length === 0;
16251         return bothEmpty ? a.concat(b) : a.concat(separator$1, b);
16252       }, []);
16253     };
16254     const filterByQuery = (term, menuItems) => {
16255       const lowerCaseTerm = term.toLowerCase();
16256       return filter$2(menuItems, item => {
16257         const text = item.meta !== undefined && item.meta.text !== undefined ? item.meta.text : item.text;
16258         const value = item.value ?? '';
16259         return contains$1(text.toLowerCase(), lowerCaseTerm) || contains$1(value.toLowerCase(), lowerCaseTerm);
16260       });
16261     };
16263     const getItems = (fileType, input, urlBackstage) => {
16264       const urlInputValue = Representing.getValue(input);
16265       const term = urlInputValue.meta.text !== undefined ? urlInputValue.meta.text : urlInputValue.value;
16266       const info = urlBackstage.getLinkInformation();
16267       return info.fold(() => [], linkInfo => {
16268         const history = filterByQuery(term, historyTargets(urlBackstage.getHistory(fileType)));
16269         return fileType === 'file' ? joinMenuLists([
16270           history,
16271           filterByQuery(term, headerTargets(linkInfo)),
16272           filterByQuery(term, flatten([
16273             anchorTargetTop(linkInfo),
16274             anchorTargets(linkInfo),
16275             anchorTargetBottom(linkInfo)
16276           ]))
16277         ]) : history;
16278       });
16279     };
16280     const errorId = generate$6('aria-invalid');
16281     const renderUrlInput = (spec, backstage, urlBackstage, initialData) => {
16282       const providersBackstage = backstage.shared.providers;
16283       const updateHistory = component => {
16284         const urlEntry = Representing.getValue(component);
16285         urlBackstage.addToHistory(urlEntry.value, spec.filetype);
16286       };
16287       const typeaheadSpec = {
16288         ...initialData.map(initialData => ({ initialData })).getOr({}),
16289         dismissOnBlur: true,
16290         inputClasses: ['tox-textfield'],
16291         sandboxClasses: ['tox-dialog__popups'],
16292         inputAttributes: {
16293           'aria-errormessage': errorId,
16294           'type': 'url'
16295         },
16296         minChars: 0,
16297         responseTime: 0,
16298         fetch: input => {
16299           const items = getItems(spec.filetype, input, urlBackstage);
16300           const tdata = build(items, ItemResponse$1.BUBBLE_TO_SANDBOX, backstage, {
16301             isHorizontalMenu: false,
16302             search: Optional.none()
16303           });
16304           return Future.pure(tdata);
16305         },
16306         getHotspot: comp => memUrlBox.getOpt(comp),
16307         onSetValue: (comp, _newValue) => {
16308           if (comp.hasConfigured(Invalidating)) {
16309             Invalidating.run(comp).get(noop);
16310           }
16311         },
16312         typeaheadBehaviours: derive$1([
16313           ...urlBackstage.getValidationHandler().map(handler => Invalidating.config({
16314             getRoot: comp => parentElement(comp.element),
16315             invalidClass: 'tox-control-wrap--status-invalid',
16316             notify: {
16317               onInvalid: (comp, err) => {
16318                 memInvalidIcon.getOpt(comp).each(invalidComp => {
16319                   set$9(invalidComp.element, 'title', providersBackstage.translate(err));
16320                 });
16321               }
16322             },
16323             validator: {
16324               validate: input => {
16325                 const urlEntry = Representing.getValue(input);
16326                 return FutureResult.nu(completer => {
16327                   handler({
16328                     type: spec.filetype,
16329                     url: urlEntry.value
16330                   }, validation => {
16331                     if (validation.status === 'invalid') {
16332                       const err = Result.error(validation.message);
16333                       completer(err);
16334                     } else {
16335                       const val = Result.value(validation.message);
16336                       completer(val);
16337                     }
16338                   });
16339                 });
16340               },
16341               validateOnLoad: false
16342             }
16343           })).toArray(),
16344           Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
16345           Tabstopping.config({}),
16346           config('urlinput-events', [
16347             run$1(input(), comp => {
16348               const currentValue = get$6(comp.element);
16349               const trimmedValue = currentValue.trim();
16350               if (trimmedValue !== currentValue) {
16351                 set$5(comp.element, trimmedValue);
16352               }
16353               if (spec.filetype === 'file') {
16354                 emitWith(comp, formChangeEvent, { name: spec.name });
16355               }
16356             }),
16357             run$1(change(), comp => {
16358               emitWith(comp, formChangeEvent, { name: spec.name });
16359               updateHistory(comp);
16360             }),
16361             run$1(postPaste(), comp => {
16362               emitWith(comp, formChangeEvent, { name: spec.name });
16363               updateHistory(comp);
16364             })
16365           ])
16366         ]),
16367         eventOrder: {
16368           [input()]: [
16369             'streaming',
16370             'urlinput-events',
16371             'invalidating'
16372           ]
16373         },
16374         model: {
16375           getDisplayText: itemData => itemData.value,
16376           selectsOver: false,
16377           populateFromBrowse: false
16378         },
16379         markers: { openClass: 'tox-textfield--popup-open' },
16380         lazySink: backstage.shared.getSink,
16381         parts: { menu: part(false, 1, 'normal') },
16382         onExecute: (_menu, component, _entry) => {
16383           emitWith(component, formSubmitEvent, {});
16384         },
16385         onItemExecute: (typeahead, _sandbox, _item, _value) => {
16386           updateHistory(typeahead);
16387           emitWith(typeahead, formChangeEvent, { name: spec.name });
16388         }
16389       };
16390       const pField = FormField.parts.field({
16391         ...typeaheadSpec,
16392         factory: Typeahead
16393       });
16394       const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
16395       const makeIcon = (name, errId, icon = name, label = name) => render$3(icon, {
16396         tag: 'div',
16397         classes: [
16398           'tox-icon',
16399           'tox-control-wrap__status-icon-' + name
16400         ],
16401         attributes: {
16402           'title': providersBackstage.translate(label),
16403           'aria-live': 'polite',
16404           ...errId.fold(() => ({}), id => ({ id }))
16405         }
16406       }, providersBackstage.icons);
16407       const memInvalidIcon = record(makeIcon('invalid', Optional.some(errorId), 'warning'));
16408       const memStatus = record({
16409         dom: {
16410           tag: 'div',
16411           classes: ['tox-control-wrap__status-icon-wrap']
16412         },
16413         components: [memInvalidIcon.asSpec()]
16414       });
16415       const optUrlPicker = urlBackstage.getUrlPicker(spec.filetype);
16416       const browseUrlEvent = generate$6('browser.url.event');
16417       const memUrlBox = record({
16418         dom: {
16419           tag: 'div',
16420           classes: ['tox-control-wrap']
16421         },
16422         components: [
16423           pField,
16424           memStatus.asSpec()
16425         ],
16426         behaviours: derive$1([Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() })])
16427       });
16428       const memUrlPickerButton = record(renderButton({
16429         name: spec.name,
16430         icon: Optional.some('browse'),
16431         text: spec.label.getOr(''),
16432         enabled: spec.enabled,
16433         primary: false,
16434         buttonType: Optional.none(),
16435         borderless: true
16436       }, component => emit(component, browseUrlEvent), providersBackstage, [], ['tox-browse-url']));
16437       const controlHWrapper = () => ({
16438         dom: {
16439           tag: 'div',
16440           classes: ['tox-form__controls-h-stack']
16441         },
16442         components: flatten([
16443           [memUrlBox.asSpec()],
16444           optUrlPicker.map(() => memUrlPickerButton.asSpec()).toArray()
16445         ])
16446       });
16447       const openUrlPicker = comp => {
16448         Composing.getCurrent(comp).each(field => {
16449           const componentData = Representing.getValue(field);
16450           const urlData = {
16451             fieldname: spec.name,
16452             ...componentData
16453           };
16454           optUrlPicker.each(picker => {
16455             picker(urlData).get(chosenData => {
16456               Representing.setValue(field, chosenData);
16457               emitWith(comp, formChangeEvent, { name: spec.name });
16458             });
16459           });
16460         });
16461       };
16462       return FormField.sketch({
16463         dom: renderFormFieldDom(),
16464         components: pLabel.toArray().concat([controlHWrapper()]),
16465         fieldBehaviours: derive$1([
16466           Disabling.config({
16467             disabled: () => !spec.enabled || providersBackstage.isDisabled(),
16468             onDisabled: comp => {
16469               FormField.getField(comp).each(Disabling.disable);
16470               memUrlPickerButton.getOpt(comp).each(Disabling.disable);
16471             },
16472             onEnabled: comp => {
16473               FormField.getField(comp).each(Disabling.enable);
16474               memUrlPickerButton.getOpt(comp).each(Disabling.enable);
16475             }
16476           }),
16477           receivingConfig(),
16478           config('url-input-events', [run$1(browseUrlEvent, openUrlPicker)])
16479         ])
16480       });
16481     };
16483     const renderAlertBanner = (spec, providersBackstage) => Container.sketch({
16484       dom: {
16485         tag: 'div',
16486         attributes: { role: 'alert' },
16487         classes: [
16488           'tox-notification',
16489           'tox-notification--in',
16490           `tox-notification--${ spec.level }`
16491         ]
16492       },
16493       components: [
16494         {
16495           dom: {
16496             tag: 'div',
16497             classes: ['tox-notification__icon']
16498           },
16499           components: [Button.sketch({
16500               dom: {
16501                 tag: 'button',
16502                 classes: [
16503                   'tox-button',
16504                   'tox-button--naked',
16505                   'tox-button--icon'
16506                 ],
16507                 innerHtml: get$2(spec.icon, providersBackstage.icons),
16508                 attributes: { title: providersBackstage.translate(spec.iconTooltip) }
16509               },
16510               action: comp => {
16511                 emitWith(comp, formActionEvent, {
16512                   name: 'alert-banner',
16513                   value: spec.url
16514                 });
16515               },
16516               buttonBehaviours: derive$1([addFocusableBehaviour()])
16517             })]
16518         },
16519         {
16520           dom: {
16521             tag: 'div',
16522             classes: ['tox-notification__body'],
16523             innerHtml: providersBackstage.translate(spec.text)
16524           }
16525         }
16526       ]
16527     });
16529     const set$1 = (element, status) => {
16530       element.dom.checked = status;
16531     };
16532     const get$1 = element => element.dom.checked;
16534     const renderCheckbox = (spec, providerBackstage, initialData) => {
16535       const toggleCheckboxHandler = comp => {
16536         comp.element.dom.click();
16537         return Optional.some(true);
16538       };
16539       const pField = FormField.parts.field({
16540         factory: { sketch: identity },
16541         dom: {
16542           tag: 'input',
16543           classes: ['tox-checkbox__input'],
16544           attributes: { type: 'checkbox' }
16545         },
16546         behaviours: derive$1([
16547           ComposingConfigs.self(),
16548           Disabling.config({ disabled: () => !spec.enabled || providerBackstage.isDisabled() }),
16549           Tabstopping.config({}),
16550           Focusing.config({}),
16551           RepresentingConfigs.withElement(initialData, get$1, set$1),
16552           Keying.config({
16553             mode: 'special',
16554             onEnter: toggleCheckboxHandler,
16555             onSpace: toggleCheckboxHandler,
16556             stopSpaceKeyup: true
16557           }),
16558           config('checkbox-events', [run$1(change(), (component, _) => {
16559               emitWith(component, formChangeEvent, { name: spec.name });
16560             })])
16561         ])
16562       });
16563       const pLabel = FormField.parts.label({
16564         dom: {
16565           tag: 'span',
16566           classes: ['tox-checkbox__label']
16567         },
16568         components: [text$2(providerBackstage.translate(spec.label))],
16569         behaviours: derive$1([Unselecting.config({})])
16570       });
16571       const makeIcon = className => {
16572         const iconName = className === 'checked' ? 'selected' : 'unselected';
16573         return render$3(iconName, {
16574           tag: 'span',
16575           classes: [
16576             'tox-icon',
16577             'tox-checkbox-icon__' + className
16578           ]
16579         }, providerBackstage.icons);
16580       };
16581       const memIcons = record({
16582         dom: {
16583           tag: 'div',
16584           classes: ['tox-checkbox__icons']
16585         },
16586         components: [
16587           makeIcon('checked'),
16588           makeIcon('unchecked')
16589         ]
16590       });
16591       return FormField.sketch({
16592         dom: {
16593           tag: 'label',
16594           classes: ['tox-checkbox']
16595         },
16596         components: [
16597           pField,
16598           memIcons.asSpec(),
16599           pLabel
16600         ],
16601         fieldBehaviours: derive$1([
16602           Disabling.config({
16603             disabled: () => !spec.enabled || providerBackstage.isDisabled(),
16604             disableClass: 'tox-checkbox--disabled',
16605             onDisabled: comp => {
16606               FormField.getField(comp).each(Disabling.disable);
16607             },
16608             onEnabled: comp => {
16609               FormField.getField(comp).each(Disabling.enable);
16610             }
16611           }),
16612           receivingConfig()
16613         ])
16614       });
16615     };
16617     const renderHtmlPanel = spec => {
16618       if (spec.presets === 'presentation') {
16619         return Container.sketch({
16620           dom: {
16621             tag: 'div',
16622             classes: ['tox-form__group'],
16623             innerHtml: spec.html
16624           }
16625         });
16626       } else {
16627         return Container.sketch({
16628           dom: {
16629             tag: 'div',
16630             classes: ['tox-form__group'],
16631             innerHtml: spec.html,
16632             attributes: { role: 'document' }
16633           },
16634           containerBehaviours: derive$1([
16635             Tabstopping.config({}),
16636             Focusing.config({})
16637           ])
16638         });
16639       }
16640     };
16642     const make$2 = render => {
16643       return (parts, spec, dialogData, backstage) => get$g(spec, 'name').fold(() => render(spec, backstage, Optional.none()), fieldName => parts.field(fieldName, render(spec, backstage, get$g(dialogData, fieldName))));
16644     };
16645     const makeIframe = render => (parts, spec, dialogData, backstage) => {
16646       const iframeSpec = deepMerge(spec, { source: 'dynamic' });
16647       return make$2(render)(parts, iframeSpec, dialogData, backstage);
16648     };
16649     const factories = {
16650       bar: make$2((spec, backstage) => renderBar(spec, backstage.shared)),
16651       collection: make$2((spec, backstage, data) => renderCollection(spec, backstage.shared.providers, data)),
16652       alertbanner: make$2((spec, backstage) => renderAlertBanner(spec, backstage.shared.providers)),
16653       input: make$2((spec, backstage, data) => renderInput(spec, backstage.shared.providers, data)),
16654       textarea: make$2((spec, backstage, data) => renderTextarea(spec, backstage.shared.providers, data)),
16655       label: make$2((spec, backstage) => renderLabel$1(spec, backstage.shared)),
16656       iframe: makeIframe((spec, backstage, data) => renderIFrame(spec, backstage.shared.providers, data)),
16657       button: make$2((spec, backstage) => renderDialogButton(spec, backstage.shared.providers)),
16658       checkbox: make$2((spec, backstage, data) => renderCheckbox(spec, backstage.shared.providers, data)),
16659       colorinput: make$2((spec, backstage, data) => renderColorInput(spec, backstage.shared, backstage.colorinput, data)),
16660       colorpicker: make$2((spec, backstage, data) => renderColorPicker(spec, backstage.shared.providers, data)),
16661       dropzone: make$2((spec, backstage, data) => renderDropZone(spec, backstage.shared.providers, data)),
16662       grid: make$2((spec, backstage) => renderGrid(spec, backstage.shared)),
16663       listbox: make$2((spec, backstage, data) => renderListBox(spec, backstage, data)),
16664       selectbox: make$2((spec, backstage, data) => renderSelectBox(spec, backstage.shared.providers, data)),
16665       sizeinput: make$2((spec, backstage) => renderSizeInput(spec, backstage.shared.providers)),
16666       slider: make$2((spec, backstage, data) => renderSlider(spec, backstage.shared.providers, data)),
16667       urlinput: make$2((spec, backstage, data) => renderUrlInput(spec, backstage, backstage.urlinput, data)),
16668       customeditor: make$2(renderCustomEditor),
16669       htmlpanel: make$2(renderHtmlPanel),
16670       imagepreview: make$2((spec, _, data) => renderImagePreview(spec, data)),
16671       table: make$2((spec, backstage) => renderTable(spec, backstage.shared.providers)),
16672       panel: make$2((spec, backstage) => renderPanel(spec, backstage))
16673     };
16674     const noFormParts = {
16675       field: (_name, spec) => spec,
16676       record: constant$1([])
16677     };
16678     const interpretInForm = (parts, spec, dialogData, oldBackstage) => {
16679       const newBackstage = deepMerge(oldBackstage, { shared: { interpreter: childSpec => interpretParts(parts, childSpec, dialogData, newBackstage) } });
16680       return interpretParts(parts, spec, dialogData, newBackstage);
16681     };
16682     const interpretParts = (parts, spec, dialogData, backstage) => get$g(factories, spec.type).fold(() => {
16683       console.error(`Unknown factory type "${ spec.type }", defaulting to container: `, spec);
16684       return spec;
16685     }, factory => factory(parts, spec, dialogData, backstage));
16686     const interpretWithoutForm = (spec, dialogData, backstage) => interpretParts(noFormParts, spec, dialogData, backstage);
16688     const labelPrefix = 'layout-inset';
16689     const westEdgeX = anchor => anchor.x;
16690     const middleX = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
16691     const eastEdgeX = (anchor, element) => anchor.x + anchor.width - element.width;
16692     const northY = anchor => anchor.y;
16693     const southY = (anchor, element) => anchor.y + anchor.height - element.height;
16694     const centreY = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
16695     const southwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), southY(anchor, element), bubbles.insetSouthwest(), northwest$3(), 'southwest', boundsRestriction(anchor, {
16696       right: 0,
16697       bottom: 3
16698     }), labelPrefix);
16699     const southeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), southY(anchor, element), bubbles.insetSoutheast(), northeast$3(), 'southeast', boundsRestriction(anchor, {
16700       left: 1,
16701       bottom: 3
16702     }), labelPrefix);
16703     const northwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), northY(anchor), bubbles.insetNorthwest(), southwest$3(), 'northwest', boundsRestriction(anchor, {
16704       right: 0,
16705       top: 2
16706     }), labelPrefix);
16707     const northeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), northY(anchor), bubbles.insetNortheast(), southeast$3(), 'northeast', boundsRestriction(anchor, {
16708       left: 1,
16709       top: 2
16710     }), labelPrefix);
16711     const north = (anchor, element, bubbles) => nu$6(middleX(anchor, element), northY(anchor), bubbles.insetNorth(), south$3(), 'north', boundsRestriction(anchor, { top: 2 }), labelPrefix);
16712     const south = (anchor, element, bubbles) => nu$6(middleX(anchor, element), southY(anchor, element), bubbles.insetSouth(), north$3(), 'south', boundsRestriction(anchor, { bottom: 3 }), labelPrefix);
16713     const east = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), centreY(anchor, element), bubbles.insetEast(), west$3(), 'east', boundsRestriction(anchor, { right: 0 }), labelPrefix);
16714     const west = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), centreY(anchor, element), bubbles.insetWest(), east$3(), 'west', boundsRestriction(anchor, { left: 1 }), labelPrefix);
16715     const lookupPreserveLayout = lastPlacement => {
16716       switch (lastPlacement) {
16717       case 'north':
16718         return north;
16719       case 'northeast':
16720         return northeast;
16721       case 'northwest':
16722         return northwest;
16723       case 'south':
16724         return south;
16725       case 'southeast':
16726         return southeast;
16727       case 'southwest':
16728         return southwest;
16729       case 'east':
16730         return east;
16731       case 'west':
16732         return west;
16733       }
16734     };
16735     const preserve = (anchor, element, bubbles, placee, bounds) => {
16736       const layout = getPlacement(placee).map(lookupPreserveLayout).getOr(north);
16737       return layout(anchor, element, bubbles, placee, bounds);
16738     };
16739     const lookupFlippedLayout = lastPlacement => {
16740       switch (lastPlacement) {
16741       case 'north':
16742         return south;
16743       case 'northeast':
16744         return southeast;
16745       case 'northwest':
16746         return southwest;
16747       case 'south':
16748         return north;
16749       case 'southeast':
16750         return northeast;
16751       case 'southwest':
16752         return northwest;
16753       case 'east':
16754         return west;
16755       case 'west':
16756         return east;
16757       }
16758     };
16759     const flip = (anchor, element, bubbles, placee, bounds) => {
16760       const layout = getPlacement(placee).map(lookupFlippedLayout).getOr(north);
16761       return layout(anchor, element, bubbles, placee, bounds);
16762     };
16764     const bubbleAlignments$2 = {
16765       valignCentre: [],
16766       alignCentre: [],
16767       alignLeft: [],
16768       alignRight: [],
16769       right: [],
16770       left: [],
16771       bottom: [],
16772       top: []
16773     };
16774     const getInlineDialogAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
16775       const bubbleSize = 12;
16776       const overrides = { maxHeightFunction: expandable$1() };
16777       const editableAreaAnchor = () => ({
16778         type: 'node',
16779         root: getContentContainer(getRootNode(contentAreaElement())),
16780         node: Optional.from(contentAreaElement()),
16781         bubble: nu$5(bubbleSize, bubbleSize, bubbleAlignments$2),
16782         layouts: {
16783           onRtl: () => [northeast],
16784           onLtr: () => [northwest]
16785         },
16786         overrides
16787       });
16788       const standardAnchor = () => ({
16789         type: 'hotspot',
16790         hotspot: lazyAnchorbar(),
16791         bubble: nu$5(-bubbleSize, bubbleSize, bubbleAlignments$2),
16792         layouts: {
16793           onRtl: () => [southeast$2],
16794           onLtr: () => [southwest$2]
16795         },
16796         overrides
16797       });
16798       return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
16799     };
16800     const getBannerAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
16801       const editableAreaAnchor = () => ({
16802         type: 'node',
16803         root: getContentContainer(getRootNode(contentAreaElement())),
16804         node: Optional.from(contentAreaElement()),
16805         layouts: {
16806           onRtl: () => [north],
16807           onLtr: () => [north]
16808         }
16809       });
16810       const standardAnchor = () => ({
16811         type: 'hotspot',
16812         hotspot: lazyAnchorbar(),
16813         layouts: {
16814           onRtl: () => [south$2],
16815           onLtr: () => [south$2]
16816         }
16817       });
16818       return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
16819     };
16820     const getCursorAnchor = (editor, bodyElement) => () => ({
16821       type: 'selection',
16822       root: bodyElement(),
16823       getSelection: () => {
16824         const rng = editor.selection.getRng();
16825         return Optional.some(SimSelection.range(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
16826       }
16827     });
16828     const getNodeAnchor$1 = bodyElement => element => ({
16829       type: 'node',
16830       root: bodyElement(),
16831       node: element
16832     });
16833     const getAnchors = (editor, lazyAnchorbar, isToolbarTop) => {
16834       const useFixedToolbarContainer = useFixedContainer(editor);
16835       const bodyElement = () => SugarElement.fromDom(editor.getBody());
16836       const contentAreaElement = () => SugarElement.fromDom(editor.getContentAreaContainer());
16837       const lazyUseEditableAreaAnchor = () => useFixedToolbarContainer || !isToolbarTop();
16838       return {
16839         inlineDialog: getInlineDialogAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
16840         banner: getBannerAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
16841         cursor: getCursorAnchor(editor, bodyElement),
16842         node: getNodeAnchor$1(bodyElement)
16843       };
16844     };
16846     const colorPicker = editor => (callback, value) => {
16847       const dialog = colorPickerDialog(editor);
16848       dialog(callback, value);
16849     };
16850     const hasCustomColors = editor => () => hasCustomColors$1(editor);
16851     const getColors = editor => () => getColors$2(editor);
16852     const getColorCols = editor => () => getColorCols$1(editor);
16853     const ColorInputBackstage = editor => ({
16854       colorPicker: colorPicker(editor),
16855       hasCustomColors: hasCustomColors(editor),
16856       getColors: getColors(editor),
16857       getColorCols: getColorCols(editor)
16858     });
16860     const isDraggableModal = editor => () => isDraggableModal$1(editor);
16861     const DialogBackstage = editor => ({ isDraggableModal: isDraggableModal(editor) });
16863     const HeaderBackstage = editor => {
16864       const mode = Cell(isToolbarLocationBottom(editor) ? 'bottom' : 'top');
16865       return {
16866         isPositionedAtTop: () => mode.get() === 'top',
16867         getDockingMode: mode.get,
16868         setDockingMode: mode.set
16869       };
16870     };
16872     const isNestedFormat = format => hasNonNullableKey(format, 'items');
16873     const isFormatReference = format => hasNonNullableKey(format, 'format');
16874     const defaultStyleFormats = [
16875       {
16876         title: 'Headings',
16877         items: [
16878           {
16879             title: 'Heading 1',
16880             format: 'h1'
16881           },
16882           {
16883             title: 'Heading 2',
16884             format: 'h2'
16885           },
16886           {
16887             title: 'Heading 3',
16888             format: 'h3'
16889           },
16890           {
16891             title: 'Heading 4',
16892             format: 'h4'
16893           },
16894           {
16895             title: 'Heading 5',
16896             format: 'h5'
16897           },
16898           {
16899             title: 'Heading 6',
16900             format: 'h6'
16901           }
16902         ]
16903       },
16904       {
16905         title: 'Inline',
16906         items: [
16907           {
16908             title: 'Bold',
16909             format: 'bold'
16910           },
16911           {
16912             title: 'Italic',
16913             format: 'italic'
16914           },
16915           {
16916             title: 'Underline',
16917             format: 'underline'
16918           },
16919           {
16920             title: 'Strikethrough',
16921             format: 'strikethrough'
16922           },
16923           {
16924             title: 'Superscript',
16925             format: 'superscript'
16926           },
16927           {
16928             title: 'Subscript',
16929             format: 'subscript'
16930           },
16931           {
16932             title: 'Code',
16933             format: 'code'
16934           }
16935         ]
16936       },
16937       {
16938         title: 'Blocks',
16939         items: [
16940           {
16941             title: 'Paragraph',
16942             format: 'p'
16943           },
16944           {
16945             title: 'Blockquote',
16946             format: 'blockquote'
16947           },
16948           {
16949             title: 'Div',
16950             format: 'div'
16951           },
16952           {
16953             title: 'Pre',
16954             format: 'pre'
16955           }
16956         ]
16957       },
16958       {
16959         title: 'Align',
16960         items: [
16961           {
16962             title: 'Left',
16963             format: 'alignleft'
16964           },
16965           {
16966             title: 'Center',
16967             format: 'aligncenter'
16968           },
16969           {
16970             title: 'Right',
16971             format: 'alignright'
16972           },
16973           {
16974             title: 'Justify',
16975             format: 'alignjustify'
16976           }
16977         ]
16978       }
16979     ];
16980     const isNestedFormats = format => has$2(format, 'items');
16981     const isBlockFormat = format => has$2(format, 'block');
16982     const isInlineFormat = format => has$2(format, 'inline');
16983     const isSelectorFormat = format => has$2(format, 'selector');
16984     const mapFormats = userFormats => foldl(userFormats, (acc, fmt) => {
16985       if (isNestedFormats(fmt)) {
16986         const result = mapFormats(fmt.items);
16987         return {
16988           customFormats: acc.customFormats.concat(result.customFormats),
16989           formats: acc.formats.concat([{
16990               title: fmt.title,
16991               items: result.formats
16992             }])
16993         };
16994       } else if (isInlineFormat(fmt) || isBlockFormat(fmt) || isSelectorFormat(fmt)) {
16995         const formatName = isString(fmt.name) ? fmt.name : fmt.title.toLowerCase();
16996         const formatNameWithPrefix = `custom-${ formatName }`;
16997         return {
16998           customFormats: acc.customFormats.concat([{
16999               name: formatNameWithPrefix,
17000               format: fmt
17001             }]),
17002           formats: acc.formats.concat([{
17003               title: fmt.title,
17004               format: formatNameWithPrefix,
17005               icon: fmt.icon
17006             }])
17007         };
17008       } else {
17009         return {
17010           ...acc,
17011           formats: acc.formats.concat(fmt)
17012         };
17013       }
17014     }, {
17015       customFormats: [],
17016       formats: []
17017     });
17018     const registerCustomFormats = (editor, userFormats) => {
17019       const result = mapFormats(userFormats);
17020       const registerFormats = customFormats => {
17021         each$1(customFormats, fmt => {
17022           if (!editor.formatter.has(fmt.name)) {
17023             editor.formatter.register(fmt.name, fmt.format);
17024           }
17025         });
17026       };
17027       if (editor.formatter) {
17028         registerFormats(result.customFormats);
17029       } else {
17030         editor.on('init', () => {
17031           registerFormats(result.customFormats);
17032         });
17033       }
17034       return result.formats;
17035     };
17036     const getStyleFormats = editor => getUserStyleFormats(editor).map(userFormats => {
17037       const registeredUserFormats = registerCustomFormats(editor, userFormats);
17038       return shouldMergeStyleFormats(editor) ? defaultStyleFormats.concat(registeredUserFormats) : registeredUserFormats;
17039     }).getOr(defaultStyleFormats);
17041     const isSeparator$1 = format => {
17042       const keys$1 = keys(format);
17043       return keys$1.length === 1 && contains$2(keys$1, 'title');
17044     };
17045     const processBasic = (item, isSelectedFor, getPreviewFor) => ({
17046       ...item,
17047       type: 'formatter',
17048       isSelected: isSelectedFor(item.format),
17049       getStylePreview: getPreviewFor(item.format)
17050     });
17051     const register$a = (editor, formats, isSelectedFor, getPreviewFor) => {
17052       const enrichSupported = item => processBasic(item, isSelectedFor, getPreviewFor);
17053       const enrichMenu = item => {
17054         const newItems = doEnrich(item.items);
17055         return {
17056           ...item,
17057           type: 'submenu',
17058           getStyleItems: constant$1(newItems)
17059         };
17060       };
17061       const enrichCustom = item => {
17062         const formatName = isString(item.name) ? item.name : generate$6(item.title);
17063         const formatNameWithPrefix = `custom-${ formatName }`;
17064         const newItem = {
17065           ...item,
17066           type: 'formatter',
17067           format: formatNameWithPrefix,
17068           isSelected: isSelectedFor(formatNameWithPrefix),
17069           getStylePreview: getPreviewFor(formatNameWithPrefix)
17070         };
17071         editor.formatter.register(formatName, newItem);
17072         return newItem;
17073       };
17074       const doEnrich = items => map$2(items, item => {
17075         if (isNestedFormat(item)) {
17076           return enrichMenu(item);
17077         } else if (isFormatReference(item)) {
17078           return enrichSupported(item);
17079         } else if (isSeparator$1(item)) {
17080           return {
17081             ...item,
17082             type: 'separator'
17083           };
17084         } else {
17085           return enrichCustom(item);
17086         }
17087       });
17088       return doEnrich(formats);
17089     };
17091     const init$8 = editor => {
17092       const isSelectedFor = format => () => editor.formatter.match(format);
17093       const getPreviewFor = format => () => {
17094         const fmt = editor.formatter.get(format);
17095         return fmt !== undefined ? Optional.some({
17096           tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
17097           styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
17098         }) : Optional.none();
17099       };
17100       const settingsFormats = Cell([]);
17101       const eventsFormats = Cell([]);
17102       const replaceSettings = Cell(false);
17103       editor.on('PreInit', _e => {
17104         const formats = getStyleFormats(editor);
17105         const enriched = register$a(editor, formats, isSelectedFor, getPreviewFor);
17106         settingsFormats.set(enriched);
17107       });
17108       editor.on('addStyleModifications', e => {
17109         const modifications = register$a(editor, e.items, isSelectedFor, getPreviewFor);
17110         eventsFormats.set(modifications);
17111         replaceSettings.set(e.replace);
17112       });
17113       const getData = () => {
17114         const fromSettings = replaceSettings.get() ? [] : settingsFormats.get();
17115         const fromEvents = eventsFormats.get();
17116         return fromSettings.concat(fromEvents);
17117       };
17118       return { getData };
17119     };
17121     const isElement = node => isNonNullable(node) && node.nodeType === 1;
17122     const trim = global$1.trim;
17123     const hasContentEditableState = value => {
17124       return node => {
17125         if (isElement(node)) {
17126           if (node.contentEditable === value) {
17127             return true;
17128           }
17129           if (node.getAttribute('data-mce-contenteditable') === value) {
17130             return true;
17131           }
17132         }
17133         return false;
17134       };
17135     };
17136     const isContentEditableTrue = hasContentEditableState('true');
17137     const isContentEditableFalse = hasContentEditableState('false');
17138     const create$1 = (type, title, url, level, attach) => ({
17139       type,
17140       title,
17141       url,
17142       level,
17143       attach
17144     });
17145     const isChildOfContentEditableTrue = node => {
17146       let tempNode = node;
17147       while (tempNode = tempNode.parentNode) {
17148         const value = tempNode.contentEditable;
17149         if (value && value !== 'inherit') {
17150           return isContentEditableTrue(tempNode);
17151         }
17152       }
17153       return false;
17154     };
17155     const select = (selector, root) => {
17156       return map$2(descendants(SugarElement.fromDom(root), selector), element => {
17157         return element.dom;
17158       });
17159     };
17160     const getElementText = elm => {
17161       return elm.innerText || elm.textContent;
17162     };
17163     const getOrGenerateId = elm => {
17164       return elm.id ? elm.id : generate$6('h');
17165     };
17166     const isAnchor = elm => {
17167       return elm && elm.nodeName === 'A' && (elm.id || elm.name) !== undefined;
17168     };
17169     const isValidAnchor = elm => {
17170       return isAnchor(elm) && isEditable(elm);
17171     };
17172     const isHeader = elm => {
17173       return elm && /^(H[1-6])$/.test(elm.nodeName);
17174     };
17175     const isEditable = elm => {
17176       return isChildOfContentEditableTrue(elm) && !isContentEditableFalse(elm);
17177     };
17178     const isValidHeader = elm => {
17179       return isHeader(elm) && isEditable(elm);
17180     };
17181     const getLevel = elm => {
17182       return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
17183     };
17184     const headerTarget = elm => {
17185       const headerId = getOrGenerateId(elm);
17186       const attach = () => {
17187         elm.id = headerId;
17188       };
17189       return create$1('header', getElementText(elm) ?? '', '#' + headerId, getLevel(elm), attach);
17190     };
17191     const anchorTarget = elm => {
17192       const anchorId = elm.id || elm.name;
17193       const anchorText = getElementText(elm);
17194       return create$1('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, noop);
17195     };
17196     const getHeaderTargets = elms => {
17197       return map$2(filter$2(elms, isValidHeader), headerTarget);
17198     };
17199     const getAnchorTargets = elms => {
17200       return map$2(filter$2(elms, isValidAnchor), anchorTarget);
17201     };
17202     const getTargetElements = elm => {
17203       const elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
17204       return elms;
17205     };
17206     const hasTitle = target => {
17207       return trim(target.title).length > 0;
17208     };
17209     const find = elm => {
17210       const elms = getTargetElements(elm);
17211       return filter$2(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
17212     };
17213     const LinkTargets = { find };
17215     const STORAGE_KEY = 'tinymce-url-history';
17216     const HISTORY_LENGTH = 5;
17217     const isHttpUrl = url => isString(url) && /^https?/.test(url);
17218     const isArrayOfUrl = a => isArray(a) && a.length <= HISTORY_LENGTH && forall(a, isHttpUrl);
17219     const isRecordOfUrlArray = r => isObject(r) && find$4(r, value => !isArrayOfUrl(value)).isNone();
17220     const getAllHistory = () => {
17221       const unparsedHistory = global$4.getItem(STORAGE_KEY);
17222       if (unparsedHistory === null) {
17223         return {};
17224       }
17225       let history;
17226       try {
17227         history = JSON.parse(unparsedHistory);
17228       } catch (e) {
17229         if (e instanceof SyntaxError) {
17230           console.log('Local storage ' + STORAGE_KEY + ' was not valid JSON', e);
17231           return {};
17232         }
17233         throw e;
17234       }
17235       if (!isRecordOfUrlArray(history)) {
17236         console.log('Local storage ' + STORAGE_KEY + ' was not valid format', history);
17237         return {};
17238       }
17239       return history;
17240     };
17241     const setAllHistory = history => {
17242       if (!isRecordOfUrlArray(history)) {
17243         throw new Error('Bad format for history:\n' + JSON.stringify(history));
17244       }
17245       global$4.setItem(STORAGE_KEY, JSON.stringify(history));
17246     };
17247     const getHistory = fileType => {
17248       const history = getAllHistory();
17249       return get$g(history, fileType).getOr([]);
17250     };
17251     const addToHistory = (url, fileType) => {
17252       if (!isHttpUrl(url)) {
17253         return;
17254       }
17255       const history = getAllHistory();
17256       const items = get$g(history, fileType).getOr([]);
17257       const itemsWithoutUrl = filter$2(items, item => item !== url);
17258       history[fileType] = [url].concat(itemsWithoutUrl).slice(0, HISTORY_LENGTH);
17259       setAllHistory(history);
17260     };
17262     const isTruthy = value => !!value;
17263     const makeMap = value => map$1(global$1.makeMap(value, /[, ]/), isTruthy);
17264     const getPicker = editor => Optional.from(getFilePickerCallback(editor));
17265     const getPickerTypes = editor => {
17266       const optFileTypes = Optional.from(getFilePickerTypes(editor)).filter(isTruthy).map(makeMap);
17267       return getPicker(editor).fold(never, _picker => optFileTypes.fold(always, types => keys(types).length > 0 ? types : false));
17268     };
17269     const getPickerSetting = (editor, filetype) => {
17270       const pickerTypes = getPickerTypes(editor);
17271       if (isBoolean(pickerTypes)) {
17272         return pickerTypes ? getPicker(editor) : Optional.none();
17273       } else {
17274         return pickerTypes[filetype] ? getPicker(editor) : Optional.none();
17275       }
17276     };
17277     const getUrlPicker = (editor, filetype) => getPickerSetting(editor, filetype).map(picker => entry => Future.nu(completer => {
17278       const handler = (value, meta) => {
17279         if (!isString(value)) {
17280           throw new Error('Expected value to be string');
17281         }
17282         if (meta !== undefined && !isObject(meta)) {
17283           throw new Error('Expected meta to be a object');
17284         }
17285         const r = {
17286           value,
17287           meta
17288         };
17289         completer(r);
17290       };
17291       const meta = {
17292         filetype,
17293         fieldname: entry.fieldname,
17294         ...Optional.from(entry.meta).getOr({})
17295       };
17296       picker.call(editor, handler, entry.value, meta);
17297     }));
17298     const getTextSetting = value => Optional.from(value).filter(isString).getOrUndefined();
17299     const getLinkInformation = editor => {
17300       if (!useTypeaheadUrls(editor)) {
17301         return Optional.none();
17302       }
17303       return Optional.some({
17304         targets: LinkTargets.find(editor.getBody()),
17305         anchorTop: getTextSetting(getAnchorTop(editor)),
17306         anchorBottom: getTextSetting(getAnchorBottom(editor))
17307       });
17308     };
17309     const getValidationHandler = editor => Optional.from(getFilePickerValidatorHandler(editor));
17310     const UrlInputBackstage = editor => ({
17311       getHistory,
17312       addToHistory,
17313       getLinkInformation: () => getLinkInformation(editor),
17314       getValidationHandler: () => getValidationHandler(editor),
17315       getUrlPicker: filetype => getUrlPicker(editor, filetype)
17316     });
17318     const init$7 = (lazySink, editor, lazyAnchorbar) => {
17319       const contextMenuState = Cell(false);
17320       const toolbar = HeaderBackstage(editor);
17321       const backstage = {
17322         shared: {
17323           providers: {
17324             icons: () => editor.ui.registry.getAll().icons,
17325             menuItems: () => editor.ui.registry.getAll().menuItems,
17326             translate: global$8.translate,
17327             isDisabled: () => editor.mode.isReadOnly() || !editor.ui.isEnabled(),
17328             getOption: editor.options.get
17329           },
17330           interpreter: s => interpretWithoutForm(s, {}, backstage),
17331           anchors: getAnchors(editor, lazyAnchorbar, toolbar.isPositionedAtTop),
17332           header: toolbar,
17333           getSink: lazySink
17334         },
17335         urlinput: UrlInputBackstage(editor),
17336         styles: init$8(editor),
17337         colorinput: ColorInputBackstage(editor),
17338         dialog: DialogBackstage(editor),
17339         isContextMenuOpen: () => contextMenuState.get(),
17340         setContextMenuState: state => contextMenuState.set(state)
17341       };
17342       return backstage;
17343     };
17345     const setup$b = (editor, mothership, uiMothership) => {
17346       const broadcastEvent = (name, evt) => {
17347         each$1([
17348           mothership,
17349           uiMothership
17350         ], ship => {
17351           ship.broadcastEvent(name, evt);
17352         });
17353       };
17354       const broadcastOn = (channel, message) => {
17355         each$1([
17356           mothership,
17357           uiMothership
17358         ], ship => {
17359           ship.broadcastOn([channel], message);
17360         });
17361       };
17362       const fireDismissPopups = evt => broadcastOn(dismissPopups(), { target: evt.target });
17363       const doc = getDocument();
17364       const onTouchstart = bind(doc, 'touchstart', fireDismissPopups);
17365       const onTouchmove = bind(doc, 'touchmove', evt => broadcastEvent(documentTouchmove(), evt));
17366       const onTouchend = bind(doc, 'touchend', evt => broadcastEvent(documentTouchend(), evt));
17367       const onMousedown = bind(doc, 'mousedown', fireDismissPopups);
17368       const onMouseup = bind(doc, 'mouseup', evt => {
17369         if (evt.raw.button === 0) {
17370           broadcastOn(mouseReleased(), { target: evt.target });
17371         }
17372       });
17373       const onContentClick = raw => broadcastOn(dismissPopups(), { target: SugarElement.fromDom(raw.target) });
17374       const onContentMouseup = raw => {
17375         if (raw.button === 0) {
17376           broadcastOn(mouseReleased(), { target: SugarElement.fromDom(raw.target) });
17377         }
17378       };
17379       const onContentMousedown = () => {
17380         each$1(editor.editorManager.get(), loopEditor => {
17381           if (editor !== loopEditor) {
17382             loopEditor.dispatch('DismissPopups', { relatedTarget: editor });
17383           }
17384         });
17385       };
17386       const onWindowScroll = evt => broadcastEvent(windowScroll(), fromRawEvent(evt));
17387       const onWindowResize = evt => {
17388         broadcastOn(repositionPopups(), {});
17389         broadcastEvent(windowResize(), fromRawEvent(evt));
17390       };
17391       const onEditorResize = () => broadcastOn(repositionPopups(), {});
17392       const onEditorProgress = evt => {
17393         if (evt.state) {
17394           broadcastOn(dismissPopups(), { target: SugarElement.fromDom(editor.getContainer()) });
17395         }
17396       };
17397       const onDismissPopups = event => {
17398         broadcastOn(dismissPopups(), { target: SugarElement.fromDom(event.relatedTarget.getContainer()) });
17399       };
17400       editor.on('PostRender', () => {
17401         editor.on('click', onContentClick);
17402         editor.on('tap', onContentClick);
17403         editor.on('mouseup', onContentMouseup);
17404         editor.on('mousedown', onContentMousedown);
17405         editor.on('ScrollWindow', onWindowScroll);
17406         editor.on('ResizeWindow', onWindowResize);
17407         editor.on('ResizeEditor', onEditorResize);
17408         editor.on('AfterProgressState', onEditorProgress);
17409         editor.on('DismissPopups', onDismissPopups);
17410       });
17411       editor.on('remove', () => {
17412         editor.off('click', onContentClick);
17413         editor.off('tap', onContentClick);
17414         editor.off('mouseup', onContentMouseup);
17415         editor.off('mousedown', onContentMousedown);
17416         editor.off('ScrollWindow', onWindowScroll);
17417         editor.off('ResizeWindow', onWindowResize);
17418         editor.off('ResizeEditor', onEditorResize);
17419         editor.off('AfterProgressState', onEditorProgress);
17420         editor.off('DismissPopups', onDismissPopups);
17421         onMousedown.unbind();
17422         onTouchstart.unbind();
17423         onTouchmove.unbind();
17424         onTouchend.unbind();
17425         onMouseup.unbind();
17426       });
17427       editor.on('detach', () => {
17428         detachSystem(mothership);
17429         detachSystem(uiMothership);
17430         mothership.destroy();
17431         uiMothership.destroy();
17432       });
17433     };
17435     const parts$a = AlloyParts;
17436     const partType = PartType;
17438     const schema$f = constant$1([
17439       defaulted('shell', false),
17440       required$1('makeItem'),
17441       defaulted('setupItem', noop),
17442       SketchBehaviours.field('listBehaviours', [Replacing])
17443     ]);
17444     const customListDetail = () => ({ behaviours: derive$1([Replacing.config({})]) });
17445     const itemsPart = optional({
17446       name: 'items',
17447       overrides: customListDetail
17448     });
17449     const parts$9 = constant$1([itemsPart]);
17450     const name = constant$1('CustomList');
17452     const factory$d = (detail, components, _spec, _external) => {
17453       const setItems = (list, items) => {
17454         getListContainer(list).fold(() => {
17455           console.error('Custom List was defined to not be a shell, but no item container was specified in components');
17456           throw new Error('Custom List was defined to not be a shell, but no item container was specified in components');
17457         }, container => {
17458           const itemComps = Replacing.contents(container);
17459           const numListsRequired = items.length;
17460           const numListsToAdd = numListsRequired - itemComps.length;
17461           const itemsToAdd = numListsToAdd > 0 ? range$2(numListsToAdd, () => detail.makeItem()) : [];
17462           const itemsToRemove = itemComps.slice(numListsRequired);
17463           each$1(itemsToRemove, item => Replacing.remove(container, item));
17464           each$1(itemsToAdd, item => Replacing.append(container, item));
17465           const builtLists = Replacing.contents(container);
17466           each$1(builtLists, (item, i) => {
17467             detail.setupItem(list, item, items[i], i);
17468           });
17469         });
17470       };
17471       const extra = detail.shell ? {
17472         behaviours: [Replacing.config({})],
17473         components: []
17474       } : {
17475         behaviours: [],
17476         components
17477       };
17478       const getListContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'items');
17479       return {
17480         uid: detail.uid,
17481         dom: detail.dom,
17482         components: extra.components,
17483         behaviours: augment(detail.listBehaviours, extra.behaviours),
17484         apis: { setItems }
17485       };
17486     };
17487     const CustomList = composite({
17488       name: name(),
17489       configFields: schema$f(),
17490       partFields: parts$9(),
17491       factory: factory$d,
17492       apis: {
17493         setItems: (apis, list, items) => {
17494           apis.setItems(list, items);
17495         }
17496       }
17497     });
17499     const schema$e = constant$1([
17500       required$1('dom'),
17501       defaulted('shell', true),
17502       field('toolbarBehaviours', [Replacing])
17503     ]);
17504     const enhanceGroups = () => ({ behaviours: derive$1([Replacing.config({})]) });
17505     const parts$8 = constant$1([optional({
17506         name: 'groups',
17507         overrides: enhanceGroups
17508       })]);
17510     const factory$c = (detail, components, _spec, _externals) => {
17511       const setGroups = (toolbar, groups) => {
17512         getGroupContainer(toolbar).fold(() => {
17513           console.error('Toolbar was defined to not be a shell, but no groups container was specified in components');
17514           throw new Error('Toolbar was defined to not be a shell, but no groups container was specified in components');
17515         }, container => {
17516           Replacing.set(container, groups);
17517         });
17518       };
17519       const getGroupContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'groups');
17520       const extra = detail.shell ? {
17521         behaviours: [Replacing.config({})],
17522         components: []
17523       } : {
17524         behaviours: [],
17525         components
17526       };
17527       return {
17528         uid: detail.uid,
17529         dom: detail.dom,
17530         components: extra.components,
17531         behaviours: augment(detail.toolbarBehaviours, extra.behaviours),
17532         apis: { setGroups },
17533         domModification: { attributes: { role: 'group' } }
17534       };
17535     };
17536     const Toolbar = composite({
17537       name: 'Toolbar',
17538       configFields: schema$e(),
17539       partFields: parts$8(),
17540       factory: factory$c,
17541       apis: {
17542         setGroups: (apis, toolbar, groups) => {
17543           apis.setGroups(toolbar, groups);
17544         }
17545       }
17546     });
17548     const setup$a = noop;
17549     const isDocked$2 = never;
17550     const getBehaviours$1 = constant$1([]);
17552     var StaticHeader = /*#__PURE__*/Object.freeze({
17553         __proto__: null,
17554         setup: setup$a,
17555         isDocked: isDocked$2,
17556         getBehaviours: getBehaviours$1
17557     });
17559     const getOffsetParent = element => {
17560       const isFixed = is$1(getRaw(element, 'position'), 'fixed');
17561       const offsetParent$1 = isFixed ? Optional.none() : offsetParent(element);
17562       return offsetParent$1.orThunk(() => {
17563         const marker = SugarElement.fromTag('span');
17564         return parent(element).bind(parent => {
17565           append$2(parent, marker);
17566           const offsetParent$1 = offsetParent(marker);
17567           remove$5(marker);
17568           return offsetParent$1;
17569         });
17570       });
17571     };
17572     const getOrigin = element => getOffsetParent(element).map(absolute$3).getOrThunk(() => SugarPosition(0, 0));
17574     const morphAdt = Adt.generate([
17575       { static: [] },
17576       { absolute: ['positionCss'] },
17577       { fixed: ['positionCss'] }
17578     ]);
17579     const appear = (component, contextualInfo) => {
17580       const elem = component.element;
17581       add$2(elem, contextualInfo.transitionClass);
17582       remove$2(elem, contextualInfo.fadeOutClass);
17583       add$2(elem, contextualInfo.fadeInClass);
17584       contextualInfo.onShow(component);
17585     };
17586     const disappear = (component, contextualInfo) => {
17587       const elem = component.element;
17588       add$2(elem, contextualInfo.transitionClass);
17589       remove$2(elem, contextualInfo.fadeInClass);
17590       add$2(elem, contextualInfo.fadeOutClass);
17591       contextualInfo.onHide(component);
17592     };
17593     const isPartiallyVisible = (box, viewport) => box.y < viewport.bottom && box.bottom > viewport.y;
17594     const isTopCompletelyVisible = (box, viewport) => box.y >= viewport.y;
17595     const isBottomCompletelyVisible = (box, viewport) => box.bottom <= viewport.bottom;
17596     const isVisibleForModes = (modes, box, viewport) => forall(modes, mode => {
17597       switch (mode) {
17598       case 'bottom':
17599         return isBottomCompletelyVisible(box, viewport);
17600       case 'top':
17601         return isTopCompletelyVisible(box, viewport);
17602       }
17603     });
17604     const getPrior = (elem, state) => state.getInitialPos().map(pos => bounds(pos.bounds.x, pos.bounds.y, get$c(elem), get$d(elem)));
17605     const storePrior = (elem, box, state) => {
17606       state.setInitialPos({
17607         style: getAllRaw(elem),
17608         position: get$e(elem, 'position') || 'static',
17609         bounds: box
17610       });
17611     };
17612     const revertToOriginal = (elem, box, state) => state.getInitialPos().bind(position => {
17613       state.clearInitialPos();
17614       switch (position.position) {
17615       case 'static':
17616         return Optional.some(morphAdt.static());
17617       case 'absolute':
17618         const offsetBox = getOffsetParent(elem).map(box$1).getOrThunk(() => box$1(body()));
17619         return Optional.some(morphAdt.absolute(NuPositionCss('absolute', get$g(position.style, 'left').map(_left => box.x - offsetBox.x), get$g(position.style, 'top').map(_top => box.y - offsetBox.y), get$g(position.style, 'right').map(_right => offsetBox.right - box.right), get$g(position.style, 'bottom').map(_bottom => offsetBox.bottom - box.bottom))));
17620       default:
17621         return Optional.none();
17622       }
17623     });
17624     const morphToOriginal = (elem, viewport, state) => getPrior(elem, state).filter(box => isVisibleForModes(state.getModes(), box, viewport)).bind(box => revertToOriginal(elem, box, state));
17625     const morphToFixed = (elem, viewport, state) => {
17626       const box = box$1(elem);
17627       if (!isVisibleForModes(state.getModes(), box, viewport)) {
17628         storePrior(elem, box, state);
17629         const winBox = win();
17630         const left = box.x - winBox.x;
17631         const top = viewport.y - winBox.y;
17632         const bottom = winBox.bottom - viewport.bottom;
17633         const isTop = box.y <= viewport.y;
17634         return Optional.some(morphAdt.fixed(NuPositionCss('fixed', Optional.some(left), isTop ? Optional.some(top) : Optional.none(), Optional.none(), !isTop ? Optional.some(bottom) : Optional.none())));
17635       } else {
17636         return Optional.none();
17637       }
17638     };
17639     const getMorph = (component, viewport, state) => {
17640       const elem = component.element;
17641       const isDocked = is$1(getRaw(elem, 'position'), 'fixed');
17642       return isDocked ? morphToOriginal(elem, viewport, state) : morphToFixed(elem, viewport, state);
17643     };
17644     const getMorphToOriginal = (component, state) => {
17645       const elem = component.element;
17646       return getPrior(elem, state).bind(box => revertToOriginal(elem, box, state));
17647     };
17649     const morphToStatic = (component, config, state) => {
17650       state.setDocked(false);
17651       each$1([
17652         'left',
17653         'right',
17654         'top',
17655         'bottom',
17656         'position'
17657       ], prop => remove$6(component.element, prop));
17658       config.onUndocked(component);
17659     };
17660     const morphToCoord = (component, config, state, position) => {
17661       const isDocked = position.position === 'fixed';
17662       state.setDocked(isDocked);
17663       applyPositionCss(component.element, position);
17664       const method = isDocked ? config.onDocked : config.onUndocked;
17665       method(component);
17666     };
17667     const updateVisibility = (component, config, state, viewport, morphToDocked = false) => {
17668       config.contextual.each(contextInfo => {
17669         contextInfo.lazyContext(component).each(box => {
17670           const isVisible = isPartiallyVisible(box, viewport);
17671           if (isVisible !== state.isVisible()) {
17672             state.setVisible(isVisible);
17673             if (morphToDocked && !isVisible) {
17674               add$1(component.element, [contextInfo.fadeOutClass]);
17675               contextInfo.onHide(component);
17676             } else {
17677               const method = isVisible ? appear : disappear;
17678               method(component, contextInfo);
17679             }
17680           }
17681         });
17682       });
17683     };
17684     const refreshInternal = (component, config, state) => {
17685       const viewport = config.lazyViewport(component);
17686       const isDocked = state.isDocked();
17687       if (isDocked) {
17688         updateVisibility(component, config, state, viewport);
17689       }
17690       getMorph(component, viewport, state).each(morph => {
17691         morph.fold(() => morphToStatic(component, config, state), position => morphToCoord(component, config, state, position), position => {
17692           updateVisibility(component, config, state, viewport, true);
17693           morphToCoord(component, config, state, position);
17694         });
17695       });
17696     };
17697     const resetInternal = (component, config, state) => {
17698       const elem = component.element;
17699       state.setDocked(false);
17700       getMorphToOriginal(component, state).each(morph => {
17701         morph.fold(() => morphToStatic(component, config, state), position => morphToCoord(component, config, state, position), noop);
17702       });
17703       state.setVisible(true);
17704       config.contextual.each(contextInfo => {
17705         remove$1(elem, [
17706           contextInfo.fadeInClass,
17707           contextInfo.fadeOutClass,
17708           contextInfo.transitionClass
17709         ]);
17710         contextInfo.onShow(component);
17711       });
17712       refresh$4(component, config, state);
17713     };
17714     const refresh$4 = (component, config, state) => {
17715       if (component.getSystem().isConnected()) {
17716         refreshInternal(component, config, state);
17717       }
17718     };
17719     const reset = (component, config, state) => {
17720       if (state.isDocked()) {
17721         resetInternal(component, config, state);
17722       }
17723     };
17724     const isDocked$1 = (component, config, state) => state.isDocked();
17725     const setModes = (component, config, state, modes) => state.setModes(modes);
17726     const getModes = (component, config, state) => state.getModes();
17728     var DockingApis = /*#__PURE__*/Object.freeze({
17729         __proto__: null,
17730         refresh: refresh$4,
17731         reset: reset,
17732         isDocked: isDocked$1,
17733         getModes: getModes,
17734         setModes: setModes
17735     });
17737     const events$5 = (dockInfo, dockState) => derive$2([
17738       runOnSource(transitionend(), (component, simulatedEvent) => {
17739         dockInfo.contextual.each(contextInfo => {
17740           if (has(component.element, contextInfo.transitionClass)) {
17741             remove$1(component.element, [
17742               contextInfo.transitionClass,
17743               contextInfo.fadeInClass
17744             ]);
17745             const notify = dockState.isVisible() ? contextInfo.onShown : contextInfo.onHidden;
17746             notify(component);
17747           }
17748           simulatedEvent.stop();
17749         });
17750       }),
17751       run$1(windowScroll(), (component, _) => {
17752         refresh$4(component, dockInfo, dockState);
17753       }),
17754       run$1(windowResize(), (component, _) => {
17755         reset(component, dockInfo, dockState);
17756       })
17757     ]);
17759     var ActiveDocking = /*#__PURE__*/Object.freeze({
17760         __proto__: null,
17761         events: events$5
17762     });
17764     var DockingSchema = [
17765       optionObjOf('contextual', [
17766         requiredString('fadeInClass'),
17767         requiredString('fadeOutClass'),
17768         requiredString('transitionClass'),
17769         requiredFunction('lazyContext'),
17770         onHandler('onShow'),
17771         onHandler('onShown'),
17772         onHandler('onHide'),
17773         onHandler('onHidden')
17774       ]),
17775       defaultedFunction('lazyViewport', win),
17776       defaultedArrayOf('modes', [
17777         'top',
17778         'bottom'
17779       ], string),
17780       onHandler('onDocked'),
17781       onHandler('onUndocked')
17782     ];
17784     const init$6 = spec => {
17785       const docked = Cell(false);
17786       const visible = Cell(true);
17787       const initialBounds = value$2();
17788       const modes = Cell(spec.modes);
17789       const readState = () => `docked:  ${ docked.get() }, visible: ${ visible.get() }, modes: ${ modes.get().join(',') }`;
17790       return nu$8({
17791         isDocked: docked.get,
17792         setDocked: docked.set,
17793         getInitialPos: initialBounds.get,
17794         setInitialPos: initialBounds.set,
17795         clearInitialPos: initialBounds.clear,
17796         isVisible: visible.get,
17797         setVisible: visible.set,
17798         getModes: modes.get,
17799         setModes: modes.set,
17800         readState
17801       });
17802     };
17804     var DockingState = /*#__PURE__*/Object.freeze({
17805         __proto__: null,
17806         init: init$6
17807     });
17809     const Docking = create$4({
17810       fields: DockingSchema,
17811       name: 'docking',
17812       active: ActiveDocking,
17813       apis: DockingApis,
17814       state: DockingState
17815     });
17817     const toolbarHeightChange = constant$1(generate$6('toolbar-height-change'));
17819     const visibility = {
17820       fadeInClass: 'tox-editor-dock-fadein',
17821       fadeOutClass: 'tox-editor-dock-fadeout',
17822       transitionClass: 'tox-editor-dock-transition'
17823     };
17824     const editorStickyOnClass = 'tox-tinymce--toolbar-sticky-on';
17825     const editorStickyOffClass = 'tox-tinymce--toolbar-sticky-off';
17826     const scrollFromBehindHeader = (e, containerHeader) => {
17827       const doc = owner$4(containerHeader);
17828       const win = defaultView(containerHeader);
17829       const viewHeight = win.dom.innerHeight;
17830       const scrollPos = get$b(doc);
17831       const markerElement = SugarElement.fromDom(e.elm);
17832       const markerPos = absolute$2(markerElement);
17833       const markerHeight = get$d(markerElement);
17834       const markerTop = markerPos.y;
17835       const markerBottom = markerTop + markerHeight;
17836       const editorHeaderPos = absolute$3(containerHeader);
17837       const editorHeaderHeight = get$d(containerHeader);
17838       const editorHeaderTop = editorHeaderPos.top;
17839       const editorHeaderBottom = editorHeaderTop + editorHeaderHeight;
17840       const editorHeaderDockedAtTop = Math.abs(editorHeaderTop - scrollPos.top) < 2;
17841       const editorHeaderDockedAtBottom = Math.abs(editorHeaderBottom - (scrollPos.top + viewHeight)) < 2;
17842       if (editorHeaderDockedAtTop && markerTop < editorHeaderBottom) {
17843         to(scrollPos.left, markerTop - editorHeaderHeight, doc);
17844       } else if (editorHeaderDockedAtBottom && markerBottom > editorHeaderTop) {
17845         const y = markerTop - viewHeight + markerHeight + editorHeaderHeight;
17846         to(scrollPos.left, y, doc);
17847       }
17848     };
17849     const isDockedMode = (header, mode) => contains$2(Docking.getModes(header), mode);
17850     const updateIframeContentFlow = header => {
17851       const getOccupiedHeight = elm => getOuter$2(elm) + (parseInt(get$e(elm, 'margin-top'), 10) || 0) + (parseInt(get$e(elm, 'margin-bottom'), 10) || 0);
17852       const elm = header.element;
17853       parentElement(elm).each(parentElem => {
17854         const padding = 'padding-' + Docking.getModes(header)[0];
17855         if (Docking.isDocked(header)) {
17856           const parentWidth = get$c(parentElem);
17857           set$8(elm, 'width', parentWidth + 'px');
17858           set$8(parentElem, padding, getOccupiedHeight(elm) + 'px');
17859         } else {
17860           remove$6(elm, 'width');
17861           remove$6(parentElem, padding);
17862         }
17863       });
17864     };
17865     const updateSinkVisibility = (sinkElem, visible) => {
17866       if (visible) {
17867         remove$2(sinkElem, visibility.fadeOutClass);
17868         add$1(sinkElem, [
17869           visibility.transitionClass,
17870           visibility.fadeInClass
17871         ]);
17872       } else {
17873         remove$2(sinkElem, visibility.fadeInClass);
17874         add$1(sinkElem, [
17875           visibility.fadeOutClass,
17876           visibility.transitionClass
17877         ]);
17878       }
17879     };
17880     const updateEditorClasses = (editor, docked) => {
17881       const editorContainer = SugarElement.fromDom(editor.getContainer());
17882       if (docked) {
17883         add$2(editorContainer, editorStickyOnClass);
17884         remove$2(editorContainer, editorStickyOffClass);
17885       } else {
17886         add$2(editorContainer, editorStickyOffClass);
17887         remove$2(editorContainer, editorStickyOnClass);
17888       }
17889     };
17890     const restoreFocus = (headerElem, focusedElem) => {
17891       const ownerDoc = owner$4(focusedElem);
17892       active$1(ownerDoc).filter(activeElm => !eq(focusedElem, activeElm)).filter(activeElm => eq(activeElm, SugarElement.fromDom(ownerDoc.dom.body)) || contains(headerElem, activeElm)).each(() => focus$3(focusedElem));
17893     };
17894     const findFocusedElem = (rootElm, lazySink) => search(rootElm).orThunk(() => lazySink().toOptional().bind(sink => search(sink.element)));
17895     const setup$9 = (editor, sharedBackstage, lazyHeader) => {
17896       if (!editor.inline) {
17897         if (!sharedBackstage.header.isPositionedAtTop()) {
17898           editor.on('ResizeEditor', () => {
17899             lazyHeader().each(Docking.reset);
17900           });
17901         }
17902         editor.on('ResizeWindow ResizeEditor', () => {
17903           lazyHeader().each(updateIframeContentFlow);
17904         });
17905         editor.on('SkinLoaded', () => {
17906           lazyHeader().each(comp => {
17907             Docking.isDocked(comp) ? Docking.reset(comp) : Docking.refresh(comp);
17908           });
17909         });
17910         editor.on('FullscreenStateChanged', () => {
17911           lazyHeader().each(Docking.reset);
17912         });
17913       }
17914       editor.on('AfterScrollIntoView', e => {
17915         lazyHeader().each(header => {
17916           Docking.refresh(header);
17917           const headerElem = header.element;
17918           if (isVisible(headerElem)) {
17919             scrollFromBehindHeader(e, headerElem);
17920           }
17921         });
17922       });
17923       editor.on('PostRender', () => {
17924         updateEditorClasses(editor, false);
17925       });
17926     };
17927     const isDocked = lazyHeader => lazyHeader().map(Docking.isDocked).getOr(false);
17928     const getIframeBehaviours = () => [Receiving.config({ channels: { [toolbarHeightChange()]: { onReceive: updateIframeContentFlow } } })];
17929     const getBehaviours = (editor, sharedBackstage) => {
17930       const focusedElm = value$2();
17931       const lazySink = sharedBackstage.getSink;
17932       const runOnSinkElement = f => {
17933         lazySink().each(sink => f(sink.element));
17934       };
17935       const onDockingSwitch = comp => {
17936         if (!editor.inline) {
17937           updateIframeContentFlow(comp);
17938         }
17939         updateEditorClasses(editor, Docking.isDocked(comp));
17940         comp.getSystem().broadcastOn([repositionPopups()], {});
17941         lazySink().each(sink => sink.getSystem().broadcastOn([repositionPopups()], {}));
17942       };
17943       const additionalBehaviours = editor.inline ? [] : getIframeBehaviours();
17944       return [
17945         Focusing.config({}),
17946         Docking.config({
17947           contextual: {
17948             lazyContext: comp => {
17949               const headerHeight = getOuter$2(comp.element);
17950               const container = editor.inline ? editor.getContentAreaContainer() : editor.getContainer();
17951               const box = box$1(SugarElement.fromDom(container));
17952               const boxHeight = box.height - headerHeight;
17953               const topBound = box.y + (isDockedMode(comp, 'top') ? 0 : headerHeight);
17954               return Optional.some(bounds(box.x, topBound, box.width, boxHeight));
17955             },
17956             onShow: () => {
17957               runOnSinkElement(elem => updateSinkVisibility(elem, true));
17958             },
17959             onShown: comp => {
17960               runOnSinkElement(elem => remove$1(elem, [
17961                 visibility.transitionClass,
17962                 visibility.fadeInClass
17963               ]));
17964               focusedElm.get().each(elem => {
17965                 restoreFocus(comp.element, elem);
17966                 focusedElm.clear();
17967               });
17968             },
17969             onHide: comp => {
17970               findFocusedElem(comp.element, lazySink).fold(focusedElm.clear, focusedElm.set);
17971               runOnSinkElement(elem => updateSinkVisibility(elem, false));
17972             },
17973             onHidden: () => {
17974               runOnSinkElement(elem => remove$1(elem, [visibility.transitionClass]));
17975             },
17976             ...visibility
17977           },
17978           lazyViewport: comp => {
17979             const win$1 = win();
17980             const offset = getStickyToolbarOffset(editor);
17981             const top = win$1.y + (isDockedMode(comp, 'top') ? offset : 0);
17982             const height = win$1.height - (isDockedMode(comp, 'bottom') ? offset : 0);
17983             return bounds(win$1.x, top, win$1.width, height);
17984           },
17985           modes: [sharedBackstage.header.getDockingMode()],
17986           onDocked: onDockingSwitch,
17987           onUndocked: onDockingSwitch
17988         }),
17989         ...additionalBehaviours
17990       ];
17991     };
17993     var StickyHeader = /*#__PURE__*/Object.freeze({
17994         __proto__: null,
17995         setup: setup$9,
17996         isDocked: isDocked,
17997         getBehaviours: getBehaviours
17998     });
18000     const renderHeader = spec => {
18001       const editor = spec.editor;
18002       const getBehaviours$2 = spec.sticky ? getBehaviours : getBehaviours$1;
18003       return {
18004         uid: spec.uid,
18005         dom: spec.dom,
18006         components: spec.components,
18007         behaviours: derive$1(getBehaviours$2(editor, spec.sharedBackstage))
18008       };
18009     };
18011     const groupToolbarButtonSchema = objOf([
18012       type,
18013       requiredOf('items', oneOf([
18014         arrOfObj([
18015           name$1,
18016           requiredArrayOf('items', string)
18017         ]),
18018         string
18019       ]))
18020     ].concat(baseToolbarButtonFields));
18021     const createGroupToolbarButton = spec => asRaw('GroupToolbarButton', groupToolbarButtonSchema, spec);
18023     const baseMenuButtonFields = [
18024       optionString('text'),
18025       optionString('tooltip'),
18026       optionString('icon'),
18027       defaultedOf('search', false, oneOf([
18028         boolean,
18029         objOf([optionString('placeholder')])
18030       ], x => {
18031         if (isBoolean(x)) {
18032           return x ? Optional.some({ placeholder: Optional.none() }) : Optional.none();
18033         } else {
18034           return Optional.some(x);
18035         }
18036       })),
18037       requiredFunction('fetch'),
18038       defaultedFunction('onSetup', () => noop)
18039     ];
18041     const MenuButtonSchema = objOf([
18042       type,
18043       ...baseMenuButtonFields
18044     ]);
18045     const createMenuButton = spec => asRaw('menubutton', MenuButtonSchema, spec);
18047     const splitButtonSchema = objOf([
18048       type,
18049       optionalTooltip,
18050       optionalIcon,
18051       optionalText,
18052       optionalSelect,
18053       fetch$1,
18054       onSetup,
18055       defaultedStringEnum('presets', 'normal', [
18056         'normal',
18057         'color',
18058         'listpreview'
18059       ]),
18060       defaultedColumns(1),
18061       onAction,
18062       onItemAction
18063     ]);
18064     const createSplitButton = spec => asRaw('SplitButton', splitButtonSchema, spec);
18066     const factory$b = (detail, spec) => {
18067       const setMenus = (comp, menus) => {
18068         const newMenus = map$2(menus, m => {
18069           const buttonSpec = {
18070             type: 'menubutton',
18071             text: m.text,
18072             fetch: callback => {
18073               callback(m.getItems());
18074             }
18075           };
18076           const internal = createMenuButton(buttonSpec).mapError(errInfo => formatError(errInfo)).getOrDie();
18077           return renderMenuButton(internal, 'tox-mbtn', spec.backstage, Optional.some('menuitem'));
18078         });
18079         Replacing.set(comp, newMenus);
18080       };
18081       const apis = {
18082         focus: Keying.focusIn,
18083         setMenus
18084       };
18085       return {
18086         uid: detail.uid,
18087         dom: detail.dom,
18088         components: [],
18089         behaviours: derive$1([
18090           Replacing.config({}),
18091           config('menubar-events', [
18092             runOnAttached(component => {
18093               detail.onSetup(component);
18094             }),
18095             run$1(mouseover(), (comp, se) => {
18096               descendant(comp.element, '.' + 'tox-mbtn--active').each(activeButton => {
18097                 closest$1(se.event.target, '.' + 'tox-mbtn').each(hoveredButton => {
18098                   if (!eq(activeButton, hoveredButton)) {
18099                     comp.getSystem().getByDom(activeButton).each(activeComp => {
18100                       comp.getSystem().getByDom(hoveredButton).each(hoveredComp => {
18101                         Dropdown.expand(hoveredComp);
18102                         Dropdown.close(activeComp);
18103                         Focusing.focus(hoveredComp);
18104                       });
18105                     });
18106                   }
18107                 });
18108               });
18109             }),
18110             run$1(focusShifted(), (comp, se) => {
18111               se.event.prevFocus.bind(prev => comp.getSystem().getByDom(prev).toOptional()).each(prev => {
18112                 se.event.newFocus.bind(nu => comp.getSystem().getByDom(nu).toOptional()).each(nu => {
18113                   if (Dropdown.isOpen(prev)) {
18114                     Dropdown.expand(nu);
18115                     Dropdown.close(prev);
18116                   }
18117                 });
18118               });
18119             })
18120           ]),
18121           Keying.config({
18122             mode: 'flow',
18123             selector: '.' + 'tox-mbtn',
18124             onEscape: comp => {
18125               detail.onEscape(comp);
18126               return Optional.some(true);
18127             }
18128           }),
18129           Tabstopping.config({})
18130         ]),
18131         apis,
18132         domModification: { attributes: { role: 'menubar' } }
18133       };
18134     };
18135     var SilverMenubar = single({
18136       factory: factory$b,
18137       name: 'silver.Menubar',
18138       configFields: [
18139         required$1('dom'),
18140         required$1('uid'),
18141         required$1('onEscape'),
18142         required$1('backstage'),
18143         defaulted('onSetup', noop)
18144       ],
18145       apis: {
18146         focus: (apis, comp) => {
18147           apis.focus(comp);
18148         },
18149         setMenus: (apis, comp, menus) => {
18150           apis.setMenus(comp, menus);
18151         }
18152       }
18153     });
18155     const promotionMessage = '\u26A1\ufe0fUpgrade';
18156     const promotionLink = 'https://www.tiny.cloud/tinymce-self-hosted-premium-features/?utm_source=TinyMCE&utm_medium=SPAP&utm_campaign=SPAP&utm_id=editorreferral';
18157     const renderPromotion = spec => {
18158       return {
18159         uid: spec.uid,
18160         dom: spec.dom,
18161         components: [{
18162             dom: {
18163               tag: 'a',
18164               attributes: {
18165                 'href': promotionLink,
18166                 'rel': 'noopener',
18167                 'target': '_blank',
18168                 'aria-hidden': 'true'
18169               },
18170               classes: ['tox-promotion-link'],
18171               innerHtml: promotionMessage
18172             }
18173           }]
18174       };
18175     };
18177     const getAnimationRoot = (component, slideConfig) => slideConfig.getAnimationRoot.fold(() => component.element, get => get(component));
18179     const getDimensionProperty = slideConfig => slideConfig.dimension.property;
18180     const getDimension = (slideConfig, elem) => slideConfig.dimension.getDimension(elem);
18181     const disableTransitions = (component, slideConfig) => {
18182       const root = getAnimationRoot(component, slideConfig);
18183       remove$1(root, [
18184         slideConfig.shrinkingClass,
18185         slideConfig.growingClass
18186       ]);
18187     };
18188     const setShrunk = (component, slideConfig) => {
18189       remove$2(component.element, slideConfig.openClass);
18190       add$2(component.element, slideConfig.closedClass);
18191       set$8(component.element, getDimensionProperty(slideConfig), '0px');
18192       reflow(component.element);
18193     };
18194     const setGrown = (component, slideConfig) => {
18195       remove$2(component.element, slideConfig.closedClass);
18196       add$2(component.element, slideConfig.openClass);
18197       remove$6(component.element, getDimensionProperty(slideConfig));
18198     };
18199     const doImmediateShrink = (component, slideConfig, slideState, _calculatedSize) => {
18200       slideState.setCollapsed();
18201       set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
18202       disableTransitions(component, slideConfig);
18203       setShrunk(component, slideConfig);
18204       slideConfig.onStartShrink(component);
18205       slideConfig.onShrunk(component);
18206     };
18207     const doStartShrink = (component, slideConfig, slideState, calculatedSize) => {
18208       const size = calculatedSize.getOrThunk(() => getDimension(slideConfig, component.element));
18209       slideState.setCollapsed();
18210       set$8(component.element, getDimensionProperty(slideConfig), size);
18211       reflow(component.element);
18212       const root = getAnimationRoot(component, slideConfig);
18213       remove$2(root, slideConfig.growingClass);
18214       add$2(root, slideConfig.shrinkingClass);
18215       setShrunk(component, slideConfig);
18216       slideConfig.onStartShrink(component);
18217     };
18218     const doStartSmartShrink = (component, slideConfig, slideState) => {
18219       const size = getDimension(slideConfig, component.element);
18220       const shrinker = size === '0px' ? doImmediateShrink : doStartShrink;
18221       shrinker(component, slideConfig, slideState, Optional.some(size));
18222     };
18223     const doStartGrow = (component, slideConfig, slideState) => {
18224       const root = getAnimationRoot(component, slideConfig);
18225       const wasShrinking = has(root, slideConfig.shrinkingClass);
18226       const beforeSize = getDimension(slideConfig, component.element);
18227       setGrown(component, slideConfig);
18228       const fullSize = getDimension(slideConfig, component.element);
18229       const startPartialGrow = () => {
18230         set$8(component.element, getDimensionProperty(slideConfig), beforeSize);
18231         reflow(component.element);
18232       };
18233       const startCompleteGrow = () => {
18234         setShrunk(component, slideConfig);
18235       };
18236       const setStartSize = wasShrinking ? startPartialGrow : startCompleteGrow;
18237       setStartSize();
18238       remove$2(root, slideConfig.shrinkingClass);
18239       add$2(root, slideConfig.growingClass);
18240       setGrown(component, slideConfig);
18241       set$8(component.element, getDimensionProperty(slideConfig), fullSize);
18242       slideState.setExpanded();
18243       slideConfig.onStartGrow(component);
18244     };
18245     const refresh$3 = (component, slideConfig, slideState) => {
18246       if (slideState.isExpanded()) {
18247         remove$6(component.element, getDimensionProperty(slideConfig));
18248         const fullSize = getDimension(slideConfig, component.element);
18249         set$8(component.element, getDimensionProperty(slideConfig), fullSize);
18250       }
18251     };
18252     const grow = (component, slideConfig, slideState) => {
18253       if (!slideState.isExpanded()) {
18254         doStartGrow(component, slideConfig, slideState);
18255       }
18256     };
18257     const shrink = (component, slideConfig, slideState) => {
18258       if (slideState.isExpanded()) {
18259         doStartSmartShrink(component, slideConfig, slideState);
18260       }
18261     };
18262     const immediateShrink = (component, slideConfig, slideState) => {
18263       if (slideState.isExpanded()) {
18264         doImmediateShrink(component, slideConfig, slideState);
18265       }
18266     };
18267     const hasGrown = (component, slideConfig, slideState) => slideState.isExpanded();
18268     const hasShrunk = (component, slideConfig, slideState) => slideState.isCollapsed();
18269     const isGrowing = (component, slideConfig, _slideState) => {
18270       const root = getAnimationRoot(component, slideConfig);
18271       return has(root, slideConfig.growingClass) === true;
18272     };
18273     const isShrinking = (component, slideConfig, _slideState) => {
18274       const root = getAnimationRoot(component, slideConfig);
18275       return has(root, slideConfig.shrinkingClass) === true;
18276     };
18277     const isTransitioning = (component, slideConfig, slideState) => isGrowing(component, slideConfig) || isShrinking(component, slideConfig);
18278     const toggleGrow = (component, slideConfig, slideState) => {
18279       const f = slideState.isExpanded() ? doStartSmartShrink : doStartGrow;
18280       f(component, slideConfig, slideState);
18281     };
18282     const immediateGrow = (component, slideConfig, slideState) => {
18283       if (!slideState.isExpanded()) {
18284         setGrown(component, slideConfig);
18285         set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
18286         disableTransitions(component, slideConfig);
18287         slideState.setExpanded();
18288         slideConfig.onStartGrow(component);
18289         slideConfig.onGrown(component);
18290       }
18291     };
18293     var SlidingApis = /*#__PURE__*/Object.freeze({
18294         __proto__: null,
18295         refresh: refresh$3,
18296         grow: grow,
18297         shrink: shrink,
18298         immediateShrink: immediateShrink,
18299         hasGrown: hasGrown,
18300         hasShrunk: hasShrunk,
18301         isGrowing: isGrowing,
18302         isShrinking: isShrinking,
18303         isTransitioning: isTransitioning,
18304         toggleGrow: toggleGrow,
18305         disableTransitions: disableTransitions,
18306         immediateGrow: immediateGrow
18307     });
18309     const exhibit = (base, slideConfig, _slideState) => {
18310       const expanded = slideConfig.expanded;
18311       return expanded ? nu$7({
18312         classes: [slideConfig.openClass],
18313         styles: {}
18314       }) : nu$7({
18315         classes: [slideConfig.closedClass],
18316         styles: wrap$1(slideConfig.dimension.property, '0px')
18317       });
18318     };
18319     const events$4 = (slideConfig, slideState) => derive$2([runOnSource(transitionend(), (component, simulatedEvent) => {
18320         const raw = simulatedEvent.event.raw;
18321         if (raw.propertyName === slideConfig.dimension.property) {
18322           disableTransitions(component, slideConfig);
18323           if (slideState.isExpanded()) {
18324             remove$6(component.element, slideConfig.dimension.property);
18325           }
18326           const notify = slideState.isExpanded() ? slideConfig.onGrown : slideConfig.onShrunk;
18327           notify(component);
18328         }
18329       })]);
18331     var ActiveSliding = /*#__PURE__*/Object.freeze({
18332         __proto__: null,
18333         exhibit: exhibit,
18334         events: events$4
18335     });
18337     var SlidingSchema = [
18338       required$1('closedClass'),
18339       required$1('openClass'),
18340       required$1('shrinkingClass'),
18341       required$1('growingClass'),
18342       option$3('getAnimationRoot'),
18343       onHandler('onShrunk'),
18344       onHandler('onStartShrink'),
18345       onHandler('onGrown'),
18346       onHandler('onStartGrow'),
18347       defaulted('expanded', false),
18348       requiredOf('dimension', choose$1('property', {
18349         width: [
18350           output$1('property', 'width'),
18351           output$1('getDimension', elem => get$c(elem) + 'px')
18352         ],
18353         height: [
18354           output$1('property', 'height'),
18355           output$1('getDimension', elem => get$d(elem) + 'px')
18356         ]
18357       }))
18358     ];
18360     const init$5 = spec => {
18361       const state = Cell(spec.expanded);
18362       const readState = () => 'expanded: ' + state.get();
18363       return nu$8({
18364         isExpanded: () => state.get() === true,
18365         isCollapsed: () => state.get() === false,
18366         setCollapsed: curry(state.set, false),
18367         setExpanded: curry(state.set, true),
18368         readState
18369       });
18370     };
18372     var SlidingState = /*#__PURE__*/Object.freeze({
18373         __proto__: null,
18374         init: init$5
18375     });
18377     const Sliding = create$4({
18378       fields: SlidingSchema,
18379       name: 'sliding',
18380       active: ActiveSliding,
18381       apis: SlidingApis,
18382       state: SlidingState
18383     });
18385     const owner = 'container';
18386     const schema$d = [field('slotBehaviours', [])];
18387     const getPartName = name => '<alloy.field.' + name + '>';
18388     const sketch = sSpec => {
18389       const parts = (() => {
18390         const record = [];
18391         const slot = (name, config) => {
18392           record.push(name);
18393           return generateOne$1(owner, getPartName(name), config);
18394         };
18395         return {
18396           slot,
18397           record: constant$1(record)
18398         };
18399       })();
18400       const spec = sSpec(parts);
18401       const partNames = parts.record();
18402       const fieldParts = map$2(partNames, n => required({
18403         name: n,
18404         pname: getPartName(n)
18405       }));
18406       return composite$1(owner, schema$d, fieldParts, make$1, spec);
18407     };
18408     const make$1 = (detail, components) => {
18409       const getSlotNames = _ => getAllPartNames(detail);
18410       const getSlot = (container, key) => getPart(container, detail, key);
18411       const onSlot = (f, def) => (container, key) => getPart(container, detail, key).map(slot => f(slot, key)).getOr(def);
18412       const onSlots = f => (container, keys) => {
18413         each$1(keys, key => f(container, key));
18414       };
18415       const doShowing = (comp, _key) => get$f(comp.element, 'aria-hidden') !== 'true';
18416       const doShow = (comp, key) => {
18417         if (!doShowing(comp)) {
18418           const element = comp.element;
18419           remove$6(element, 'display');
18420           remove$7(element, 'aria-hidden');
18421           emitWith(comp, slotVisibility(), {
18422             name: key,
18423             visible: true
18424           });
18425         }
18426       };
18427       const doHide = (comp, key) => {
18428         if (doShowing(comp)) {
18429           const element = comp.element;
18430           set$8(element, 'display', 'none');
18431           set$9(element, 'aria-hidden', 'true');
18432           emitWith(comp, slotVisibility(), {
18433             name: key,
18434             visible: false
18435           });
18436         }
18437       };
18438       const isShowing = onSlot(doShowing, false);
18439       const hideSlot = onSlot(doHide);
18440       const hideSlots = onSlots(hideSlot);
18441       const hideAllSlots = container => hideSlots(container, getSlotNames());
18442       const showSlot = onSlot(doShow);
18443       const apis = {
18444         getSlotNames,
18445         getSlot,
18446         isShowing,
18447         hideSlot,
18448         hideAllSlots,
18449         showSlot
18450       };
18451       return {
18452         uid: detail.uid,
18453         dom: detail.dom,
18454         components,
18455         behaviours: get$3(detail.slotBehaviours),
18456         apis
18457       };
18458     };
18459     const slotApis = map$1({
18460       getSlotNames: (apis, c) => apis.getSlotNames(c),
18461       getSlot: (apis, c, key) => apis.getSlot(c, key),
18462       isShowing: (apis, c, key) => apis.isShowing(c, key),
18463       hideSlot: (apis, c, key) => apis.hideSlot(c, key),
18464       hideAllSlots: (apis, c) => apis.hideAllSlots(c),
18465       showSlot: (apis, c, key) => apis.showSlot(c, key)
18466     }, value => makeApi(value));
18467     const SlotContainer = {
18468       ...slotApis,
18469       ...{ sketch }
18470     };
18472     const sidebarSchema = objOf([
18473       optionalIcon,
18474       optionalTooltip,
18475       defaultedFunction('onShow', noop),
18476       defaultedFunction('onHide', noop),
18477       onSetup
18478     ]);
18479     const createSidebar = spec => asRaw('sidebar', sidebarSchema, spec);
18481     const setup$8 = editor => {
18482       const {sidebars} = editor.ui.registry.getAll();
18483       each$1(keys(sidebars), name => {
18484         const spec = sidebars[name];
18485         const isActive = () => is$1(Optional.from(editor.queryCommandValue('ToggleSidebar')), name);
18486         editor.ui.registry.addToggleButton(name, {
18487           icon: spec.icon,
18488           tooltip: spec.tooltip,
18489           onAction: buttonApi => {
18490             editor.execCommand('ToggleSidebar', false, name);
18491             buttonApi.setActive(isActive());
18492           },
18493           onSetup: buttonApi => {
18494             buttonApi.setActive(isActive());
18495             const handleToggle = () => buttonApi.setActive(isActive());
18496             editor.on('ToggleSidebar', handleToggle);
18497             return () => {
18498               editor.off('ToggleSidebar', handleToggle);
18499             };
18500           }
18501         });
18502       });
18503     };
18504     const getApi = comp => ({ element: () => comp.element.dom });
18505     const makePanels = (parts, panelConfigs) => {
18506       const specs = map$2(keys(panelConfigs), name => {
18507         const spec = panelConfigs[name];
18508         const bridged = getOrDie(createSidebar(spec));
18509         return {
18510           name,
18511           getApi,
18512           onSetup: bridged.onSetup,
18513           onShow: bridged.onShow,
18514           onHide: bridged.onHide
18515         };
18516       });
18517       return map$2(specs, spec => {
18518         const editorOffCell = Cell(noop);
18519         return parts.slot(spec.name, {
18520           dom: {
18521             tag: 'div',
18522             classes: ['tox-sidebar__pane']
18523           },
18524           behaviours: SimpleBehaviours.unnamedEvents([
18525             onControlAttached(spec, editorOffCell),
18526             onControlDetached(spec, editorOffCell),
18527             run$1(slotVisibility(), (sidepanel, se) => {
18528               const data = se.event;
18529               const optSidePanelSpec = find$5(specs, config => config.name === data.name);
18530               optSidePanelSpec.each(sidePanelSpec => {
18531                 const handler = data.visible ? sidePanelSpec.onShow : sidePanelSpec.onHide;
18532                 handler(sidePanelSpec.getApi(sidepanel));
18533               });
18534             })
18535           ])
18536         });
18537       });
18538     };
18539     const makeSidebar = panelConfigs => SlotContainer.sketch(parts => ({
18540       dom: {
18541         tag: 'div',
18542         classes: ['tox-sidebar__pane-container']
18543       },
18544       components: makePanels(parts, panelConfigs),
18545       slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
18546     }));
18547     const setSidebar = (sidebar, panelConfigs, showSidebar) => {
18548       const optSlider = Composing.getCurrent(sidebar);
18549       optSlider.each(slider => {
18550         Replacing.set(slider, [makeSidebar(panelConfigs)]);
18551         const configKey = showSidebar?.toLowerCase();
18552         if (isString(configKey) && has$2(panelConfigs, configKey)) {
18553           Composing.getCurrent(slider).each(slotContainer => {
18554             SlotContainer.showSlot(slotContainer, configKey);
18555             Sliding.immediateGrow(slider);
18556             remove$6(slider.element, 'width');
18557           });
18558         }
18559       });
18560     };
18561     const toggleSidebar = (sidebar, name) => {
18562       const optSlider = Composing.getCurrent(sidebar);
18563       optSlider.each(slider => {
18564         const optSlotContainer = Composing.getCurrent(slider);
18565         optSlotContainer.each(slotContainer => {
18566           if (Sliding.hasGrown(slider)) {
18567             if (SlotContainer.isShowing(slotContainer, name)) {
18568               Sliding.shrink(slider);
18569             } else {
18570               SlotContainer.hideAllSlots(slotContainer);
18571               SlotContainer.showSlot(slotContainer, name);
18572             }
18573           } else {
18574             SlotContainer.hideAllSlots(slotContainer);
18575             SlotContainer.showSlot(slotContainer, name);
18576             Sliding.grow(slider);
18577           }
18578         });
18579       });
18580     };
18581     const whichSidebar = sidebar => {
18582       const optSlider = Composing.getCurrent(sidebar);
18583       return optSlider.bind(slider => {
18584         const sidebarOpen = Sliding.isGrowing(slider) || Sliding.hasGrown(slider);
18585         if (sidebarOpen) {
18586           const optSlotContainer = Composing.getCurrent(slider);
18587           return optSlotContainer.bind(slotContainer => find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name)));
18588         } else {
18589           return Optional.none();
18590         }
18591       });
18592     };
18593     const fixSize = generate$6('FixSizeEvent');
18594     const autoSize = generate$6('AutoSizeEvent');
18595     const renderSidebar = spec => ({
18596       uid: spec.uid,
18597       dom: {
18598         tag: 'div',
18599         classes: ['tox-sidebar'],
18600         attributes: { role: 'complementary' }
18601       },
18602       components: [{
18603           dom: {
18604             tag: 'div',
18605             classes: ['tox-sidebar__slider']
18606           },
18607           components: [],
18608           behaviours: derive$1([
18609             Tabstopping.config({}),
18610             Focusing.config({}),
18611             Sliding.config({
18612               dimension: { property: 'width' },
18613               closedClass: 'tox-sidebar--sliding-closed',
18614               openClass: 'tox-sidebar--sliding-open',
18615               shrinkingClass: 'tox-sidebar--sliding-shrinking',
18616               growingClass: 'tox-sidebar--sliding-growing',
18617               onShrunk: slider => {
18618                 const optSlotContainer = Composing.getCurrent(slider);
18619                 optSlotContainer.each(SlotContainer.hideAllSlots);
18620                 emit(slider, autoSize);
18621               },
18622               onGrown: slider => {
18623                 emit(slider, autoSize);
18624               },
18625               onStartGrow: slider => {
18626                 emitWith(slider, fixSize, { width: getRaw(slider.element, 'width').getOr('') });
18627               },
18628               onStartShrink: slider => {
18629                 emitWith(slider, fixSize, { width: get$c(slider.element) + 'px' });
18630               }
18631             }),
18632             Replacing.config({}),
18633             Composing.config({
18634               find: comp => {
18635                 const children = Replacing.contents(comp);
18636                 return head(children);
18637               }
18638             })
18639           ])
18640         }],
18641       behaviours: derive$1([
18642         ComposingConfigs.childAt(0),
18643         config('sidebar-sliding-events', [
18644           run$1(fixSize, (comp, se) => {
18645             set$8(comp.element, 'width', se.event.width);
18646           }),
18647           run$1(autoSize, (comp, _se) => {
18648             remove$6(comp.element, 'width');
18649           })
18650         ])
18651       ])
18652     });
18654     const block = (component, config, state, getBusySpec) => {
18655       set$9(component.element, 'aria-busy', true);
18656       const root = config.getRoot(component).getOr(component);
18657       const blockerBehaviours = derive$1([
18658         Keying.config({
18659           mode: 'special',
18660           onTab: () => Optional.some(true),
18661           onShiftTab: () => Optional.some(true)
18662         }),
18663         Focusing.config({})
18664       ]);
18665       const blockSpec = getBusySpec(root, blockerBehaviours);
18666       const blocker = root.getSystem().build(blockSpec);
18667       Replacing.append(root, premade(blocker));
18668       if (blocker.hasConfigured(Keying) && config.focus) {
18669         Keying.focusIn(blocker);
18670       }
18671       if (!state.isBlocked()) {
18672         config.onBlock(component);
18673       }
18674       state.blockWith(() => Replacing.remove(root, blocker));
18675     };
18676     const unblock = (component, config, state) => {
18677       remove$7(component.element, 'aria-busy');
18678       if (state.isBlocked()) {
18679         config.onUnblock(component);
18680       }
18681       state.clear();
18682     };
18684     var BlockingApis = /*#__PURE__*/Object.freeze({
18685         __proto__: null,
18686         block: block,
18687         unblock: unblock
18688     });
18690     var BlockingSchema = [
18691       defaultedFunction('getRoot', Optional.none),
18692       defaultedBoolean('focus', true),
18693       onHandler('onBlock'),
18694       onHandler('onUnblock')
18695     ];
18697     const init$4 = () => {
18698       const blocker = destroyable();
18699       const blockWith = destroy => {
18700         blocker.set({ destroy });
18701       };
18702       return nu$8({
18703         readState: blocker.isSet,
18704         blockWith,
18705         clear: blocker.clear,
18706         isBlocked: blocker.isSet
18707       });
18708     };
18710     var BlockingState = /*#__PURE__*/Object.freeze({
18711         __proto__: null,
18712         init: init$4
18713     });
18715     const Blocking = create$4({
18716       fields: BlockingSchema,
18717       name: 'blocking',
18718       apis: BlockingApis,
18719       state: BlockingState
18720     });
18722     const getAttrs = elem => {
18723       const attributes = elem.dom.attributes !== undefined ? elem.dom.attributes : [];
18724       return foldl(attributes, (b, attr) => {
18725         if (attr.name === 'class') {
18726           return b;
18727         } else {
18728           return {
18729             ...b,
18730             [attr.name]: attr.value
18731           };
18732         }
18733       }, {});
18734     };
18735     const getClasses = elem => Array.prototype.slice.call(elem.dom.classList, 0);
18736     const fromHtml = html => {
18737       const elem = SugarElement.fromHtml(html);
18738       const children$1 = children(elem);
18739       const attrs = getAttrs(elem);
18740       const classes = getClasses(elem);
18741       const contents = children$1.length === 0 ? {} : { innerHtml: get$9(elem) };
18742       return {
18743         tag: name$3(elem),
18744         classes,
18745         attributes: attrs,
18746         ...contents
18747       };
18748     };
18750     const getBusySpec$1 = providerBackstage => (_root, _behaviours) => ({
18751       dom: {
18752         tag: 'div',
18753         attributes: {
18754           'aria-label': providerBackstage.translate('Loading...'),
18755           'tabindex': '0'
18756         },
18757         classes: ['tox-throbber__busy-spinner']
18758       },
18759       components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
18760     });
18761     const focusBusyComponent = throbber => Composing.getCurrent(throbber).each(comp => focus$3(comp.element));
18762     const toggleEditorTabIndex = (editor, state) => {
18763       const tabIndexAttr = 'tabindex';
18764       const dataTabIndexAttr = `data-mce-${ tabIndexAttr }`;
18765       Optional.from(editor.iframeElement).map(SugarElement.fromDom).each(iframe => {
18766         if (state) {
18767           getOpt(iframe, tabIndexAttr).each(tabIndex => set$9(iframe, dataTabIndexAttr, tabIndex));
18768           set$9(iframe, tabIndexAttr, -1);
18769         } else {
18770           remove$7(iframe, tabIndexAttr);
18771           getOpt(iframe, dataTabIndexAttr).each(tabIndex => {
18772             set$9(iframe, tabIndexAttr, tabIndex);
18773             remove$7(iframe, dataTabIndexAttr);
18774           });
18775         }
18776       });
18777     };
18778     const toggleThrobber = (editor, comp, state, providerBackstage) => {
18779       const element = comp.element;
18780       toggleEditorTabIndex(editor, state);
18781       if (state) {
18782         Blocking.block(comp, getBusySpec$1(providerBackstage));
18783         remove$6(element, 'display');
18784         remove$7(element, 'aria-hidden');
18785         if (editor.hasFocus()) {
18786           focusBusyComponent(comp);
18787         }
18788       } else {
18789         const throbberFocus = Composing.getCurrent(comp).exists(busyComp => hasFocus(busyComp.element));
18790         Blocking.unblock(comp);
18791         set$8(element, 'display', 'none');
18792         set$9(element, 'aria-hidden', 'true');
18793         if (throbberFocus) {
18794           editor.focus();
18795         }
18796       }
18797     };
18798     const renderThrobber = spec => ({
18799       uid: spec.uid,
18800       dom: {
18801         tag: 'div',
18802         attributes: { 'aria-hidden': 'true' },
18803         classes: ['tox-throbber'],
18804         styles: { display: 'none' }
18805       },
18806       behaviours: derive$1([
18807         Replacing.config({}),
18808         Blocking.config({ focus: false }),
18809         Composing.config({ find: comp => head(comp.components()) })
18810       ]),
18811       components: []
18812     });
18813     const isFocusEvent = event => event.type === 'focusin';
18814     const isPasteBinTarget = event => {
18815       if (isFocusEvent(event)) {
18816         const node = event.composed ? head(event.composedPath()) : Optional.from(event.target);
18817         return node.map(SugarElement.fromDom).filter(isElement$1).exists(targetElm => has(targetElm, 'mce-pastebin'));
18818       } else {
18819         return false;
18820       }
18821     };
18822     const setup$7 = (editor, lazyThrobber, sharedBackstage) => {
18823       const throbberState = Cell(false);
18824       const timer = value$2();
18825       const stealFocus = e => {
18826         if (throbberState.get() && !isPasteBinTarget(e)) {
18827           e.preventDefault();
18828           focusBusyComponent(lazyThrobber());
18829           editor.editorManager.setActive(editor);
18830         }
18831       };
18832       if (!editor.inline) {
18833         editor.on('PreInit', () => {
18834           editor.dom.bind(editor.getWin(), 'focusin', stealFocus);
18835           editor.on('BeforeExecCommand', e => {
18836             if (e.command.toLowerCase() === 'mcefocus' && e.value !== true) {
18837               stealFocus(e);
18838             }
18839           });
18840         });
18841       }
18842       const toggle = state => {
18843         if (state !== throbberState.get()) {
18844           throbberState.set(state);
18845           toggleThrobber(editor, lazyThrobber(), state, sharedBackstage.providers);
18846           fireAfterProgressState(editor, state);
18847         }
18848       };
18849       editor.on('ProgressState', e => {
18850         timer.on(clearTimeout);
18851         if (isNumber(e.time)) {
18852           const timerId = global$9.setEditorTimeout(editor, () => toggle(e.state), e.time);
18853           timer.set(timerId);
18854         } else {
18855           toggle(e.state);
18856           timer.clear();
18857         }
18858       });
18859     };
18861     const generate$1 = (xs, f) => {
18862       const init = {
18863         len: 0,
18864         list: []
18865       };
18866       const r = foldl(xs, (b, a) => {
18867         const value = f(a, b.len);
18868         return value.fold(constant$1(b), v => ({
18869           len: v.finish,
18870           list: b.list.concat([v])
18871         }));
18872       }, init);
18873       return r.list;
18874     };
18876     const output = (within, extra, withinWidth) => ({
18877       within,
18878       extra,
18879       withinWidth
18880     });
18881     const apportion = (units, total, len) => {
18882       const parray = generate$1(units, (unit, current) => {
18883         const width = len(unit);
18884         return Optional.some({
18885           element: unit,
18886           start: current,
18887           finish: current + width,
18888           width
18889         });
18890       });
18891       const within = filter$2(parray, unit => unit.finish <= total);
18892       const withinWidth = foldr(within, (acc, el) => acc + el.width, 0);
18893       const extra = parray.slice(within.length);
18894       return {
18895         within,
18896         extra,
18897         withinWidth
18898       };
18899     };
18900     const toUnit = parray => map$2(parray, unit => unit.element);
18901     const fitLast = (within, extra, withinWidth) => {
18902       const fits = toUnit(within.concat(extra));
18903       return output(fits, [], withinWidth);
18904     };
18905     const overflow = (within, extra, overflower, withinWidth) => {
18906       const fits = toUnit(within).concat([overflower]);
18907       return output(fits, toUnit(extra), withinWidth);
18908     };
18909     const fitAll = (within, extra, withinWidth) => output(toUnit(within), [], withinWidth);
18910     const tryFit = (total, units, len) => {
18911       const divide = apportion(units, total, len);
18912       return divide.extra.length === 0 ? Optional.some(divide) : Optional.none();
18913     };
18914     const partition = (total, units, len, overflower) => {
18915       const divide = tryFit(total, units, len).getOrThunk(() => apportion(units, total - len(overflower), len));
18916       const within = divide.within;
18917       const extra = divide.extra;
18918       const withinWidth = divide.withinWidth;
18919       if (extra.length === 1 && extra[0].width <= len(overflower)) {
18920         return fitLast(within, extra, withinWidth);
18921       } else if (extra.length >= 1) {
18922         return overflow(within, extra, overflower, withinWidth);
18923       } else {
18924         return fitAll(within, extra, withinWidth);
18925       }
18926     };
18928     const setGroups$1 = (toolbar, storedGroups) => {
18929       const bGroups = map$2(storedGroups, g => premade(g));
18930       Toolbar.setGroups(toolbar, bGroups);
18931     };
18932     const findFocusedComp = comps => findMap(comps, comp => search(comp.element).bind(focusedElm => comp.getSystem().getByDom(focusedElm).toOptional()));
18933     const refresh$2 = (toolbar, detail, setOverflow) => {
18934       const builtGroups = detail.builtGroups.get();
18935       if (builtGroups.length === 0) {
18936         return;
18937       }
18938       const primary = getPartOrDie(toolbar, detail, 'primary');
18939       const overflowGroup = Coupling.getCoupled(toolbar, 'overflowGroup');
18940       set$8(primary.element, 'visibility', 'hidden');
18941       const groups = builtGroups.concat([overflowGroup]);
18942       const focusedComp = findFocusedComp(groups);
18943       setOverflow([]);
18944       setGroups$1(primary, groups);
18945       const availableWidth = get$c(primary.element);
18946       const overflows = partition(availableWidth, detail.builtGroups.get(), comp => get$c(comp.element), overflowGroup);
18947       if (overflows.extra.length === 0) {
18948         Replacing.remove(primary, overflowGroup);
18949         setOverflow([]);
18950       } else {
18951         setGroups$1(primary, overflows.within);
18952         setOverflow(overflows.extra);
18953       }
18954       remove$6(primary.element, 'visibility');
18955       reflow(primary.element);
18956       focusedComp.each(Focusing.focus);
18957     };
18959     const schema$c = constant$1([
18960       field('splitToolbarBehaviours', [Coupling]),
18961       customField('builtGroups', () => Cell([]))
18962     ]);
18964     const schema$b = constant$1([
18965       markers$1(['overflowToggledClass']),
18966       optionFunction('getOverflowBounds'),
18967       required$1('lazySink'),
18968       customField('overflowGroups', () => Cell([]))
18969     ].concat(schema$c()));
18970     const parts$7 = constant$1([
18971       required({
18972         factory: Toolbar,
18973         schema: schema$e(),
18974         name: 'primary'
18975       }),
18976       external({
18977         schema: schema$e(),
18978         name: 'overflow'
18979       }),
18980       external({ name: 'overflow-button' }),
18981       external({ name: 'overflow-group' })
18982     ]);
18984     const expandable = constant$1((element, available) => {
18985       setMax(element, Math.floor(available));
18986     });
18988     const schema$a = constant$1([
18989       markers$1(['toggledClass']),
18990       required$1('lazySink'),
18991       requiredFunction('fetch'),
18992       optionFunction('getBounds'),
18993       optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
18994       schema$y()
18995     ]);
18996     const parts$6 = constant$1([
18997       external({
18998         name: 'button',
18999         overrides: detail => ({
19000           dom: { attributes: { 'aria-haspopup': 'true' } },
19001           buttonBehaviours: derive$1([Toggling.config({
19002               toggleClass: detail.markers.toggledClass,
19003               aria: { mode: 'expanded' },
19004               toggleOnExecute: false
19005             })])
19006         })
19007       }),
19008       external({
19009         factory: Toolbar,
19010         schema: schema$e(),
19011         name: 'toolbar',
19012         overrides: detail => {
19013           return {
19014             toolbarBehaviours: derive$1([Keying.config({
19015                 mode: 'cyclic',
19016                 onEscape: comp => {
19017                   getPart(comp, detail, 'button').each(Focusing.focus);
19018                   return Optional.none();
19019                 }
19020               })])
19021           };
19022         }
19023       })
19024     ]);
19026     const toggle = (button, externals) => {
19027       const toolbarSandbox = Coupling.getCoupled(button, 'toolbarSandbox');
19028       if (Sandboxing.isOpen(toolbarSandbox)) {
19029         Sandboxing.close(toolbarSandbox);
19030       } else {
19031         Sandboxing.open(toolbarSandbox, externals.toolbar());
19032       }
19033     };
19034     const position = (button, toolbar, detail, layouts) => {
19035       const bounds = detail.getBounds.map(bounder => bounder());
19036       const sink = detail.lazySink(button).getOrDie();
19037       Positioning.positionWithinBounds(sink, toolbar, {
19038         anchor: {
19039           type: 'hotspot',
19040           hotspot: button,
19041           layouts,
19042           overrides: { maxWidthFunction: expandable() }
19043         }
19044       }, bounds);
19045     };
19046     const setGroups = (button, toolbar, detail, layouts, groups) => {
19047       Toolbar.setGroups(toolbar, groups);
19048       position(button, toolbar, detail, layouts);
19049       Toggling.on(button);
19050     };
19051     const makeSandbox = (button, spec, detail) => {
19052       const ariaControls = manager();
19053       const onOpen = (sandbox, toolbar) => {
19054         detail.fetch().get(groups => {
19055           setGroups(button, toolbar, detail, spec.layouts, groups);
19056           ariaControls.link(button.element);
19057           Keying.focusIn(toolbar);
19058         });
19059       };
19060       const onClose = () => {
19061         Toggling.off(button);
19062         Focusing.focus(button);
19063         ariaControls.unlink(button.element);
19064       };
19065       return {
19066         dom: {
19067           tag: 'div',
19068           attributes: { id: ariaControls.id }
19069         },
19070         behaviours: derive$1([
19071           Keying.config({
19072             mode: 'special',
19073             onEscape: comp => {
19074               Sandboxing.close(comp);
19075               return Optional.some(true);
19076             }
19077           }),
19078           Sandboxing.config({
19079             onOpen,
19080             onClose,
19081             isPartOf: (container, data, queryElem) => {
19082               return isPartOf$1(data, queryElem) || isPartOf$1(button, queryElem);
19083             },
19084             getAttachPoint: () => {
19085               return detail.lazySink(button).getOrDie();
19086             }
19087           }),
19088           Receiving.config({
19089             channels: {
19090               ...receivingChannel$1({
19091                 isExtraPart: never,
19092                 ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
19093               }),
19094               ...receivingChannel({
19095                 doReposition: () => {
19096                   Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
19097                     position(button, toolbar, detail, spec.layouts);
19098                   });
19099                 }
19100               })
19101             }
19102           })
19103         ])
19104       };
19105     };
19106     const factory$a = (detail, components, spec, externals) => ({
19107       ...Button.sketch({
19108         ...externals.button(),
19109         action: button => {
19110           toggle(button, externals);
19111         },
19112         buttonBehaviours: SketchBehaviours.augment({ dump: externals.button().buttonBehaviours }, [Coupling.config({
19113             others: {
19114               toolbarSandbox: button => {
19115                 return makeSandbox(button, spec, detail);
19116               }
19117             }
19118           })])
19119       }),
19120       apis: {
19121         setGroups: (button, groups) => {
19122           Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
19123             setGroups(button, toolbar, detail, spec.layouts, groups);
19124           });
19125         },
19126         reposition: button => {
19127           Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
19128             position(button, toolbar, detail, spec.layouts);
19129           });
19130         },
19131         toggle: button => {
19132           toggle(button, externals);
19133         },
19134         getToolbar: button => {
19135           return Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox'));
19136         },
19137         isOpen: button => {
19138           return Sandboxing.isOpen(Coupling.getCoupled(button, 'toolbarSandbox'));
19139         }
19140       }
19141     });
19142     const FloatingToolbarButton = composite({
19143       name: 'FloatingToolbarButton',
19144       factory: factory$a,
19145       configFields: schema$a(),
19146       partFields: parts$6(),
19147       apis: {
19148         setGroups: (apis, button, groups) => {
19149           apis.setGroups(button, groups);
19150         },
19151         reposition: (apis, button) => {
19152           apis.reposition(button);
19153         },
19154         toggle: (apis, button) => {
19155           apis.toggle(button);
19156         },
19157         getToolbar: (apis, button) => apis.getToolbar(button),
19158         isOpen: (apis, button) => apis.isOpen(button)
19159       }
19160     });
19162     const schema$9 = constant$1([
19163       required$1('items'),
19164       markers$1(['itemSelector']),
19165       field('tgroupBehaviours', [Keying])
19166     ]);
19167     const parts$5 = constant$1([group({
19168         name: 'items',
19169         unit: 'item'
19170       })]);
19172     const factory$9 = (detail, components, _spec, _externals) => ({
19173       uid: detail.uid,
19174       dom: detail.dom,
19175       components,
19176       behaviours: augment(detail.tgroupBehaviours, [Keying.config({
19177           mode: 'flow',
19178           selector: detail.markers.itemSelector
19179         })]),
19180       domModification: { attributes: { role: 'toolbar' } }
19181     });
19182     const ToolbarGroup = composite({
19183       name: 'ToolbarGroup',
19184       configFields: schema$9(),
19185       partFields: parts$5(),
19186       factory: factory$9
19187     });
19189     const buildGroups = comps => map$2(comps, g => premade(g));
19190     const refresh$1 = (toolbar, memFloatingToolbarButton, detail) => {
19191       refresh$2(toolbar, detail, overflowGroups => {
19192         detail.overflowGroups.set(overflowGroups);
19193         memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
19194           FloatingToolbarButton.setGroups(floatingToolbarButton, buildGroups(overflowGroups));
19195         });
19196       });
19197     };
19198     const factory$8 = (detail, components, spec, externals) => {
19199       const memFloatingToolbarButton = record(FloatingToolbarButton.sketch({
19200         fetch: () => Future.nu(resolve => {
19201           resolve(buildGroups(detail.overflowGroups.get()));
19202         }),
19203         layouts: {
19204           onLtr: () => [
19205             southwest$2,
19206             southeast$2
19207           ],
19208           onRtl: () => [
19209             southeast$2,
19210             southwest$2
19211           ],
19212           onBottomLtr: () => [
19213             northwest$2,
19214             northeast$2
19215           ],
19216           onBottomRtl: () => [
19217             northeast$2,
19218             northwest$2
19219           ]
19220         },
19221         getBounds: spec.getOverflowBounds,
19222         lazySink: detail.lazySink,
19223         fireDismissalEventInstead: {},
19224         markers: { toggledClass: detail.markers.overflowToggledClass },
19225         parts: {
19226           button: externals['overflow-button'](),
19227           toolbar: externals.overflow()
19228         }
19229       }));
19230       return {
19231         uid: detail.uid,
19232         dom: detail.dom,
19233         components,
19234         behaviours: augment(detail.splitToolbarBehaviours, [Coupling.config({
19235             others: {
19236               overflowGroup: () => {
19237                 return ToolbarGroup.sketch({
19238                   ...externals['overflow-group'](),
19239                   items: [memFloatingToolbarButton.asSpec()]
19240                 });
19241               }
19242             }
19243           })]),
19244         apis: {
19245           setGroups: (toolbar, groups) => {
19246             detail.builtGroups.set(map$2(groups, toolbar.getSystem().build));
19247             refresh$1(toolbar, memFloatingToolbarButton, detail);
19248           },
19249           refresh: toolbar => refresh$1(toolbar, memFloatingToolbarButton, detail),
19250           toggle: toolbar => {
19251             memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
19252               FloatingToolbarButton.toggle(floatingToolbarButton);
19253             });
19254           },
19255           isOpen: toolbar => memFloatingToolbarButton.getOpt(toolbar).map(FloatingToolbarButton.isOpen).getOr(false),
19256           reposition: toolbar => {
19257             memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
19258               FloatingToolbarButton.reposition(floatingToolbarButton);
19259             });
19260           },
19261           getOverflow: toolbar => memFloatingToolbarButton.getOpt(toolbar).bind(FloatingToolbarButton.getToolbar)
19262         },
19263         domModification: { attributes: { role: 'group' } }
19264       };
19265     };
19266     const SplitFloatingToolbar = composite({
19267       name: 'SplitFloatingToolbar',
19268       configFields: schema$b(),
19269       partFields: parts$7(),
19270       factory: factory$8,
19271       apis: {
19272         setGroups: (apis, toolbar, groups) => {
19273           apis.setGroups(toolbar, groups);
19274         },
19275         refresh: (apis, toolbar) => {
19276           apis.refresh(toolbar);
19277         },
19278         reposition: (apis, toolbar) => {
19279           apis.reposition(toolbar);
19280         },
19281         toggle: (apis, toolbar) => {
19282           apis.toggle(toolbar);
19283         },
19284         isOpen: (apis, toolbar) => apis.isOpen(toolbar),
19285         getOverflow: (apis, toolbar) => apis.getOverflow(toolbar)
19286       }
19287     });
19289     const schema$8 = constant$1([
19290       markers$1([
19291         'closedClass',
19292         'openClass',
19293         'shrinkingClass',
19294         'growingClass',
19295         'overflowToggledClass'
19296       ]),
19297       onHandler('onOpened'),
19298       onHandler('onClosed')
19299     ].concat(schema$c()));
19300     const parts$4 = constant$1([
19301       required({
19302         factory: Toolbar,
19303         schema: schema$e(),
19304         name: 'primary'
19305       }),
19306       required({
19307         factory: Toolbar,
19308         schema: schema$e(),
19309         name: 'overflow',
19310         overrides: detail => {
19311           return {
19312             toolbarBehaviours: derive$1([
19313               Sliding.config({
19314                 dimension: { property: 'height' },
19315                 closedClass: detail.markers.closedClass,
19316                 openClass: detail.markers.openClass,
19317                 shrinkingClass: detail.markers.shrinkingClass,
19318                 growingClass: detail.markers.growingClass,
19319                 onShrunk: comp => {
19320                   getPart(comp, detail, 'overflow-button').each(button => {
19321                     Toggling.off(button);
19322                     Focusing.focus(button);
19323                   });
19324                   detail.onClosed(comp);
19325                 },
19326                 onGrown: comp => {
19327                   Keying.focusIn(comp);
19328                   detail.onOpened(comp);
19329                 },
19330                 onStartGrow: comp => {
19331                   getPart(comp, detail, 'overflow-button').each(Toggling.on);
19332                 }
19333               }),
19334               Keying.config({
19335                 mode: 'acyclic',
19336                 onEscape: comp => {
19337                   getPart(comp, detail, 'overflow-button').each(Focusing.focus);
19338                   return Optional.some(true);
19339                 }
19340               })
19341             ])
19342           };
19343         }
19344       }),
19345       external({
19346         name: 'overflow-button',
19347         overrides: detail => ({
19348           buttonBehaviours: derive$1([Toggling.config({
19349               toggleClass: detail.markers.overflowToggledClass,
19350               aria: { mode: 'pressed' },
19351               toggleOnExecute: false
19352             })])
19353         })
19354       }),
19355       external({ name: 'overflow-group' })
19356     ]);
19358     const isOpen = (toolbar, detail) => getPart(toolbar, detail, 'overflow').map(Sliding.hasGrown).getOr(false);
19359     const toggleToolbar = (toolbar, detail) => {
19360       getPart(toolbar, detail, 'overflow-button').bind(() => getPart(toolbar, detail, 'overflow')).each(overf => {
19361         refresh(toolbar, detail);
19362         Sliding.toggleGrow(overf);
19363       });
19364     };
19365     const refresh = (toolbar, detail) => {
19366       getPart(toolbar, detail, 'overflow').each(overflow => {
19367         refresh$2(toolbar, detail, groups => {
19368           const builtGroups = map$2(groups, g => premade(g));
19369           Toolbar.setGroups(overflow, builtGroups);
19370         });
19371         getPart(toolbar, detail, 'overflow-button').each(button => {
19372           if (Sliding.hasGrown(overflow)) {
19373             Toggling.on(button);
19374           }
19375         });
19376         Sliding.refresh(overflow);
19377       });
19378     };
19379     const factory$7 = (detail, components, spec, externals) => {
19380       const toolbarToggleEvent = 'alloy.toolbar.toggle';
19381       const doSetGroups = (toolbar, groups) => {
19382         const built = map$2(groups, toolbar.getSystem().build);
19383         detail.builtGroups.set(built);
19384       };
19385       return {
19386         uid: detail.uid,
19387         dom: detail.dom,
19388         components,
19389         behaviours: augment(detail.splitToolbarBehaviours, [
19390           Coupling.config({
19391             others: {
19392               overflowGroup: toolbar => {
19393                 return ToolbarGroup.sketch({
19394                   ...externals['overflow-group'](),
19395                   items: [Button.sketch({
19396                       ...externals['overflow-button'](),
19397                       action: _button => {
19398                         emit(toolbar, toolbarToggleEvent);
19399                       }
19400                     })]
19401                 });
19402               }
19403             }
19404           }),
19405           config('toolbar-toggle-events', [run$1(toolbarToggleEvent, toolbar => {
19406               toggleToolbar(toolbar, detail);
19407             })])
19408         ]),
19409         apis: {
19410           setGroups: (toolbar, groups) => {
19411             doSetGroups(toolbar, groups);
19412             refresh(toolbar, detail);
19413           },
19414           refresh: toolbar => refresh(toolbar, detail),
19415           toggle: toolbar => toggleToolbar(toolbar, detail),
19416           isOpen: toolbar => isOpen(toolbar, detail)
19417         },
19418         domModification: { attributes: { role: 'group' } }
19419       };
19420     };
19421     const SplitSlidingToolbar = composite({
19422       name: 'SplitSlidingToolbar',
19423       configFields: schema$8(),
19424       partFields: parts$4(),
19425       factory: factory$7,
19426       apis: {
19427         setGroups: (apis, toolbar, groups) => {
19428           apis.setGroups(toolbar, groups);
19429         },
19430         refresh: (apis, toolbar) => {
19431           apis.refresh(toolbar);
19432         },
19433         toggle: (apis, toolbar) => {
19434           apis.toggle(toolbar);
19435         },
19436         isOpen: (apis, toolbar) => apis.isOpen(toolbar)
19437       }
19438     });
19440     const renderToolbarGroupCommon = toolbarGroup => {
19441       const attributes = toolbarGroup.title.fold(() => ({}), title => ({ attributes: { title } }));
19442       return {
19443         dom: {
19444           tag: 'div',
19445           classes: ['tox-toolbar__group'],
19446           ...attributes
19447         },
19448         components: [ToolbarGroup.parts.items({})],
19449         items: toolbarGroup.items,
19450         markers: { itemSelector: '*:not(.tox-split-button) > .tox-tbtn:not([disabled]), ' + '.tox-split-button:not([disabled]), ' + '.tox-toolbar-nav-js:not([disabled])' },
19451         tgroupBehaviours: derive$1([
19452           Tabstopping.config({}),
19453           Focusing.config({})
19454         ])
19455       };
19456     };
19457     const renderToolbarGroup = toolbarGroup => ToolbarGroup.sketch(renderToolbarGroupCommon(toolbarGroup));
19458     const getToolbarBehaviours = (toolbarSpec, modeName) => {
19459       const onAttached = runOnAttached(component => {
19460         const groups = map$2(toolbarSpec.initGroups, renderToolbarGroup);
19461         Toolbar.setGroups(component, groups);
19462       });
19463       return derive$1([
19464         DisablingConfigs.toolbarButton(toolbarSpec.providers.isDisabled),
19465         receivingConfig(),
19466         Keying.config({
19467           mode: modeName,
19468           onEscape: toolbarSpec.onEscape,
19469           selector: '.tox-toolbar__group'
19470         }),
19471         config('toolbar-events', [onAttached])
19472       ]);
19473     };
19474     const renderMoreToolbarCommon = toolbarSpec => {
19475       const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
19476       return {
19477         uid: toolbarSpec.uid,
19478         dom: {
19479           tag: 'div',
19480           classes: ['tox-toolbar-overlord']
19481         },
19482         parts: {
19483           'overflow-group': renderToolbarGroupCommon({
19484             title: Optional.none(),
19485             items: []
19486           }),
19487           'overflow-button': renderIconButtonSpec({
19488             name: 'more',
19489             icon: Optional.some('more-drawer'),
19490             enabled: true,
19491             tooltip: Optional.some('More...'),
19492             primary: false,
19493             buttonType: Optional.none(),
19494             borderless: false
19495           }, Optional.none(), toolbarSpec.providers)
19496         },
19497         splitToolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
19498       };
19499     };
19500     const renderFloatingMoreToolbar = toolbarSpec => {
19501       const baseSpec = renderMoreToolbarCommon(toolbarSpec);
19502       const overflowXOffset = 4;
19503       const primary = SplitFloatingToolbar.parts.primary({
19504         dom: {
19505           tag: 'div',
19506           classes: ['tox-toolbar__primary']
19507         }
19508       });
19509       return SplitFloatingToolbar.sketch({
19510         ...baseSpec,
19511         lazySink: toolbarSpec.getSink,
19512         getOverflowBounds: () => {
19513           const headerElem = toolbarSpec.moreDrawerData.lazyHeader().element;
19514           const headerBounds = absolute$2(headerElem);
19515           const docElem = documentElement(headerElem);
19516           const docBounds = absolute$2(docElem);
19517           const height = Math.max(docElem.dom.scrollHeight, docBounds.height);
19518           return bounds(headerBounds.x + overflowXOffset, docBounds.y, headerBounds.width - overflowXOffset * 2, height);
19519         },
19520         parts: {
19521           ...baseSpec.parts,
19522           overflow: {
19523             dom: {
19524               tag: 'div',
19525               classes: ['tox-toolbar__overflow'],
19526               attributes: toolbarSpec.attributes
19527             }
19528           }
19529         },
19530         components: [primary],
19531         markers: { overflowToggledClass: 'tox-tbtn--enabled' }
19532       });
19533     };
19534     const renderSlidingMoreToolbar = toolbarSpec => {
19535       const primary = SplitSlidingToolbar.parts.primary({
19536         dom: {
19537           tag: 'div',
19538           classes: ['tox-toolbar__primary']
19539         }
19540       });
19541       const overflow = SplitSlidingToolbar.parts.overflow({
19542         dom: {
19543           tag: 'div',
19544           classes: ['tox-toolbar__overflow']
19545         }
19546       });
19547       const baseSpec = renderMoreToolbarCommon(toolbarSpec);
19548       return SplitSlidingToolbar.sketch({
19549         ...baseSpec,
19550         components: [
19551           primary,
19552           overflow
19553         ],
19554         markers: {
19555           openClass: 'tox-toolbar__overflow--open',
19556           closedClass: 'tox-toolbar__overflow--closed',
19557           growingClass: 'tox-toolbar__overflow--growing',
19558           shrinkingClass: 'tox-toolbar__overflow--shrinking',
19559           overflowToggledClass: 'tox-tbtn--enabled'
19560         },
19561         onOpened: comp => {
19562           comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'opened' });
19563         },
19564         onClosed: comp => {
19565           comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'closed' });
19566         }
19567       });
19568     };
19569     const renderToolbar = toolbarSpec => {
19570       const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
19571       return Toolbar.sketch({
19572         uid: toolbarSpec.uid,
19573         dom: {
19574           tag: 'div',
19575           classes: ['tox-toolbar'].concat(toolbarSpec.type === ToolbarMode$1.scrolling ? ['tox-toolbar--scrolling'] : [])
19576         },
19577         components: [Toolbar.parts.groups({})],
19578         toolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
19579       });
19580     };
19582     const factory$6 = (detail, components, _spec) => {
19583       const apis = {
19584         getSocket: comp => {
19585           return parts$a.getPart(comp, detail, 'socket');
19586         },
19587         setSidebar: (comp, panelConfigs, showSidebar) => {
19588           parts$a.getPart(comp, detail, 'sidebar').each(sidebar => setSidebar(sidebar, panelConfigs, showSidebar));
19589         },
19590         toggleSidebar: (comp, name) => {
19591           parts$a.getPart(comp, detail, 'sidebar').each(sidebar => toggleSidebar(sidebar, name));
19592         },
19593         whichSidebar: comp => {
19594           return parts$a.getPart(comp, detail, 'sidebar').bind(whichSidebar).getOrNull();
19595         },
19596         getHeader: comp => {
19597           return parts$a.getPart(comp, detail, 'header');
19598         },
19599         getToolbar: comp => {
19600           return parts$a.getPart(comp, detail, 'toolbar');
19601         },
19602         setToolbar: (comp, groups) => {
19603           parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
19604             const renderedGroups = map$2(groups, renderToolbarGroup);
19605             toolbar.getApis().setGroups(toolbar, renderedGroups);
19606           });
19607         },
19608         setToolbars: (comp, toolbars) => {
19609           parts$a.getPart(comp, detail, 'multiple-toolbar').each(mToolbar => {
19610             const renderedToolbars = map$2(toolbars, g => map$2(g, renderToolbarGroup));
19611             CustomList.setItems(mToolbar, renderedToolbars);
19612           });
19613         },
19614         refreshToolbar: comp => {
19615           const toolbar = parts$a.getPart(comp, detail, 'toolbar');
19616           toolbar.each(toolbar => toolbar.getApis().refresh(toolbar));
19617         },
19618         toggleToolbarDrawer: comp => {
19619           parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
19620             mapFrom(toolbar.getApis().toggle, toggle => toggle(toolbar));
19621           });
19622         },
19623         isToolbarDrawerToggled: comp => {
19624           return parts$a.getPart(comp, detail, 'toolbar').bind(toolbar => Optional.from(toolbar.getApis().isOpen).map(isOpen => isOpen(toolbar))).getOr(false);
19625         },
19626         getThrobber: comp => {
19627           return parts$a.getPart(comp, detail, 'throbber');
19628         },
19629         focusToolbar: comp => {
19630           const optToolbar = parts$a.getPart(comp, detail, 'toolbar').orThunk(() => parts$a.getPart(comp, detail, 'multiple-toolbar'));
19631           optToolbar.each(toolbar => {
19632             Keying.focusIn(toolbar);
19633           });
19634         },
19635         setMenubar: (comp, menus) => {
19636           parts$a.getPart(comp, detail, 'menubar').each(menubar => {
19637             SilverMenubar.setMenus(menubar, menus);
19638           });
19639         },
19640         focusMenubar: comp => {
19641           parts$a.getPart(comp, detail, 'menubar').each(menubar => {
19642             SilverMenubar.focus(menubar);
19643           });
19644         }
19645       };
19646       return {
19647         uid: detail.uid,
19648         dom: detail.dom,
19649         components,
19650         apis,
19651         behaviours: detail.behaviours
19652       };
19653     };
19654     const partMenubar = partType.optional({
19655       factory: SilverMenubar,
19656       name: 'menubar',
19657       schema: [required$1('backstage')]
19658     });
19659     const toolbarFactory = spec => {
19660       if (spec.type === ToolbarMode$1.sliding) {
19661         return renderSlidingMoreToolbar;
19662       } else if (spec.type === ToolbarMode$1.floating) {
19663         return renderFloatingMoreToolbar;
19664       } else {
19665         return renderToolbar;
19666       }
19667     };
19668     const partMultipleToolbar = partType.optional({
19669       factory: {
19670         sketch: spec => CustomList.sketch({
19671           uid: spec.uid,
19672           dom: spec.dom,
19673           listBehaviours: derive$1([Keying.config({
19674               mode: 'acyclic',
19675               selector: '.tox-toolbar'
19676             })]),
19677           makeItem: () => renderToolbar({
19678             type: spec.type,
19679             uid: generate$6('multiple-toolbar-item'),
19680             cyclicKeying: false,
19681             initGroups: [],
19682             providers: spec.providers,
19683             onEscape: () => {
19684               spec.onEscape();
19685               return Optional.some(true);
19686             }
19687           }),
19688           setupItem: (_mToolbar, tc, data, _index) => {
19689             Toolbar.setGroups(tc, data);
19690           },
19691           shell: true
19692         })
19693       },
19694       name: 'multiple-toolbar',
19695       schema: [
19696         required$1('dom'),
19697         required$1('onEscape')
19698       ]
19699     });
19700     const partToolbar = partType.optional({
19701       factory: {
19702         sketch: spec => {
19703           const renderer = toolbarFactory(spec);
19704           const toolbarSpec = {
19705             type: spec.type,
19706             uid: spec.uid,
19707             onEscape: () => {
19708               spec.onEscape();
19709               return Optional.some(true);
19710             },
19711             cyclicKeying: false,
19712             initGroups: [],
19713             getSink: spec.getSink,
19714             providers: spec.providers,
19715             moreDrawerData: {
19716               lazyToolbar: spec.lazyToolbar,
19717               lazyMoreButton: spec.lazyMoreButton,
19718               lazyHeader: spec.lazyHeader
19719             },
19720             attributes: spec.attributes
19721           };
19722           return renderer(toolbarSpec);
19723         }
19724       },
19725       name: 'toolbar',
19726       schema: [
19727         required$1('dom'),
19728         required$1('onEscape'),
19729         required$1('getSink')
19730       ]
19731     });
19732     const partHeader = partType.optional({
19733       factory: { sketch: renderHeader },
19734       name: 'header',
19735       schema: [required$1('dom')]
19736     });
19737     const partPromotion = partType.optional({
19738       factory: { sketch: renderPromotion },
19739       name: 'promotion',
19740       schema: [required$1('dom')]
19741     });
19742     const partSocket = partType.optional({
19743       name: 'socket',
19744       schema: [required$1('dom')]
19745     });
19746     const partSidebar = partType.optional({
19747       factory: { sketch: renderSidebar },
19748       name: 'sidebar',
19749       schema: [required$1('dom')]
19750     });
19751     const partThrobber = partType.optional({
19752       factory: { sketch: renderThrobber },
19753       name: 'throbber',
19754       schema: [required$1('dom')]
19755     });
19756     var OuterContainer = composite({
19757       name: 'OuterContainer',
19758       factory: factory$6,
19759       configFields: [
19760         required$1('dom'),
19761         required$1('behaviours')
19762       ],
19763       partFields: [
19764         partHeader,
19765         partMenubar,
19766         partToolbar,
19767         partMultipleToolbar,
19768         partSocket,
19769         partSidebar,
19770         partPromotion,
19771         partThrobber
19772       ],
19773       apis: {
19774         getSocket: (apis, comp) => {
19775           return apis.getSocket(comp);
19776         },
19777         setSidebar: (apis, comp, panelConfigs, showSidebar) => {
19778           apis.setSidebar(comp, panelConfigs, showSidebar);
19779         },
19780         toggleSidebar: (apis, comp, name) => {
19781           apis.toggleSidebar(comp, name);
19782         },
19783         whichSidebar: (apis, comp) => {
19784           return apis.whichSidebar(comp);
19785         },
19786         getHeader: (apis, comp) => {
19787           return apis.getHeader(comp);
19788         },
19789         getToolbar: (apis, comp) => {
19790           return apis.getToolbar(comp);
19791         },
19792         setToolbar: (apis, comp, groups) => {
19793           apis.setToolbar(comp, groups);
19794         },
19795         setToolbars: (apis, comp, toolbars) => {
19796           apis.setToolbars(comp, toolbars);
19797         },
19798         refreshToolbar: (apis, comp) => {
19799           return apis.refreshToolbar(comp);
19800         },
19801         toggleToolbarDrawer: (apis, comp) => {
19802           apis.toggleToolbarDrawer(comp);
19803         },
19804         isToolbarDrawerToggled: (apis, comp) => {
19805           return apis.isToolbarDrawerToggled(comp);
19806         },
19807         getThrobber: (apis, comp) => {
19808           return apis.getThrobber(comp);
19809         },
19810         setMenubar: (apis, comp, menus) => {
19811           apis.setMenubar(comp, menus);
19812         },
19813         focusMenubar: (apis, comp) => {
19814           apis.focusMenubar(comp);
19815         },
19816         focusToolbar: (apis, comp) => {
19817           apis.focusToolbar(comp);
19818         }
19819       }
19820     });
19822     const defaultMenubar = 'file edit view insert format tools table help';
19823     const defaultMenus = {
19824       file: {
19825         title: 'File',
19826         items: 'newdocument restoredraft | preview | export print | deleteallconversations'
19827       },
19828       edit: {
19829         title: 'Edit',
19830         items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'
19831       },
19832       view: {
19833         title: 'View',
19834         items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'
19835       },
19836       insert: {
19837         title: 'Insert',
19838         items: 'image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents footnotes | mergetags | insertdatetime'
19839       },
19840       format: {
19841         title: 'Format',
19842         items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'
19843       },
19844       tools: {
19845         title: 'Tools',
19846         items: 'spellchecker spellcheckerlanguage | autocorrect capitalization | a11ycheck code wordcount'
19847       },
19848       table: {
19849         title: 'Table',
19850         items: 'inserttable | cell row column | advtablesort | tableprops deletetable'
19851       },
19852       help: {
19853         title: 'Help',
19854         items: 'help'
19855       }
19856     };
19857     const make = (menu, registry, editor) => {
19858       const removedMenuItems = getRemovedMenuItems(editor).split(/[ ,]/);
19859       return {
19860         text: menu.title,
19861         getItems: () => bind$3(menu.items, i => {
19862           const itemName = i.toLowerCase();
19863           if (itemName.trim().length === 0) {
19864             return [];
19865           } else if (exists(removedMenuItems, removedMenuItem => removedMenuItem === itemName)) {
19866             return [];
19867           } else if (itemName === 'separator' || itemName === '|') {
19868             return [{ type: 'separator' }];
19869           } else if (registry.menuItems[itemName]) {
19870             return [registry.menuItems[itemName]];
19871           } else {
19872             return [];
19873           }
19874         })
19875       };
19876     };
19877     const parseItemsString = items => {
19878       return items.split(' ');
19879     };
19880     const identifyMenus = (editor, registry) => {
19881       const rawMenuData = {
19882         ...defaultMenus,
19883         ...registry.menus
19884       };
19885       const userDefinedMenus = keys(registry.menus).length > 0;
19886       const menubar = registry.menubar === undefined || registry.menubar === true ? parseItemsString(defaultMenubar) : parseItemsString(registry.menubar === false ? '' : registry.menubar);
19887       const validMenus = filter$2(menubar, menuName => {
19888         const isDefaultMenu = has$2(defaultMenus, menuName);
19889         if (userDefinedMenus) {
19890           return isDefaultMenu || get$g(registry.menus, menuName).exists(menu => has$2(menu, 'items'));
19891         } else {
19892           return isDefaultMenu;
19893         }
19894       });
19895       const menus = map$2(validMenus, menuName => {
19896         const menuData = rawMenuData[menuName];
19897         return make({
19898           title: menuData.title,
19899           items: parseItemsString(menuData.items)
19900         }, registry, editor);
19901       });
19902       return filter$2(menus, menu => {
19903         const isNotSeparator = item => isString(item) || item.type !== 'separator';
19904         return menu.getItems().length > 0 && exists(menu.getItems(), isNotSeparator);
19905       });
19906     };
19908     const fireSkinLoaded = editor => {
19909       const done = () => {
19910         editor._skinLoaded = true;
19911         fireSkinLoaded$1(editor);
19912       };
19913       return () => {
19914         if (editor.initialized) {
19915           done();
19916         } else {
19917           editor.on('init', done);
19918         }
19919       };
19920     };
19921     const fireSkinLoadError = (editor, err) => () => fireSkinLoadError$1(editor, { message: err });
19923     const loadStylesheet = (editor, stylesheetUrl, styleSheetLoader) => {
19924       editor.on('remove', () => styleSheetLoader.unload(stylesheetUrl));
19925       return styleSheetLoader.load(stylesheetUrl);
19926     };
19927     const loadUiSkins = (editor, skinUrl) => {
19928       const skinUiCss = skinUrl + '/skin.min.css';
19929       return loadStylesheet(editor, skinUiCss, editor.ui.styleSheetLoader);
19930     };
19931     const loadShadowDomUiSkins = (editor, skinUrl) => {
19932       const isInShadowRoot$1 = isInShadowRoot(SugarElement.fromDom(editor.getElement()));
19933       if (isInShadowRoot$1) {
19934         const shadowDomSkinCss = skinUrl + '/skin.shadowdom.min.css';
19935         return loadStylesheet(editor, shadowDomSkinCss, global$7.DOM.styleSheetLoader);
19936       } else {
19937         return Promise.resolve();
19938       }
19939     };
19940     const loadSkin = (isInline, editor) => {
19941       const skinUrl = getSkinUrl(editor);
19942       if (skinUrl) {
19943         editor.contentCSS.push(skinUrl + (isInline ? '/content.inline' : '/content') + '.min.css');
19944       }
19945       if (!isSkinDisabled(editor) && isString(skinUrl)) {
19946         Promise.all([
19947           loadUiSkins(editor, skinUrl),
19948           loadShadowDomUiSkins(editor, skinUrl)
19949         ]).then(fireSkinLoaded(editor), fireSkinLoadError(editor, 'Skin could not be loaded'));
19950       } else {
19951         fireSkinLoaded(editor)();
19952       }
19953     };
19954     const iframe = curry(loadSkin, false);
19955     const inline = curry(loadSkin, true);
19957     const onSetupFormatToggle = (editor, name) => api => {
19958       const boundCallback = unbindable();
19959       const init = () => {
19960         api.setActive(editor.formatter.match(name));
19961         const binding = editor.formatter.formatChanged(name, api.setActive);
19962         boundCallback.set(binding);
19963       };
19964       editor.initialized ? init() : editor.once('init', init);
19965       return () => {
19966         editor.off('init', init);
19967         boundCallback.clear();
19968       };
19969     };
19970     const onSetupEvent = (editor, event, f) => api => {
19971       const handleEvent = () => f(api);
19972       const init = () => {
19973         f(api);
19974         editor.on(event, handleEvent);
19975       };
19976       editor.initialized ? init() : editor.once('init', init);
19977       return () => {
19978         editor.off('init', init);
19979         editor.off(event, handleEvent);
19980       };
19981     };
19982     const onActionToggleFormat$1 = editor => rawItem => () => {
19983       editor.undoManager.transact(() => {
19984         editor.focus();
19985         editor.execCommand('mceToggleFormat', false, rawItem.format);
19986       });
19987     };
19988     const onActionExecCommand = (editor, command) => () => editor.execCommand(command);
19990     const generateSelectItems = (_editor, backstage, spec) => {
19991       const generateItem = (rawItem, response, invalid, value) => {
19992         const translatedText = backstage.shared.providers.translate(rawItem.title);
19993         if (rawItem.type === 'separator') {
19994           return Optional.some({
19995             type: 'separator',
19996             text: translatedText
19997           });
19998         } else if (rawItem.type === 'submenu') {
19999           const items = bind$3(rawItem.getStyleItems(), si => validate(si, response, value));
20000           if (response === 0 && items.length <= 0) {
20001             return Optional.none();
20002           } else {
20003             return Optional.some({
20004               type: 'nestedmenuitem',
20005               text: translatedText,
20006               enabled: items.length > 0,
20007               getSubmenuItems: () => bind$3(rawItem.getStyleItems(), si => validate(si, response, value))
20008             });
20009           }
20010         } else {
20011           return Optional.some({
20012             type: 'togglemenuitem',
20013             text: translatedText,
20014             icon: rawItem.icon,
20015             active: rawItem.isSelected(value),
20016             enabled: !invalid,
20017             onAction: spec.onAction(rawItem),
20018             ...rawItem.getStylePreview().fold(() => ({}), preview => ({ meta: { style: preview } }))
20019           });
20020         }
20021       };
20022       const validate = (item, response, value) => {
20023         const invalid = item.type === 'formatter' && spec.isInvalid(item);
20024         if (response === 0) {
20025           return invalid ? [] : generateItem(item, response, false, value).toArray();
20026         } else {
20027           return generateItem(item, response, invalid, value).toArray();
20028         }
20029       };
20030       const validateItems = preItems => {
20031         const value = spec.getCurrentValue();
20032         const response = spec.shouldHide ? 0 : 1;
20033         return bind$3(preItems, item => validate(item, response, value));
20034       };
20035       const getFetch = (backstage, getStyleItems) => (comp, callback) => {
20036         const preItems = getStyleItems();
20037         const items = validateItems(preItems);
20038         const menu = build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
20039           isHorizontalMenu: false,
20040           search: Optional.none()
20041         });
20042         callback(menu);
20043       };
20044       return {
20045         validateItems,
20046         getFetch
20047       };
20048     };
20049     const createMenuItems = (editor, backstage, spec) => {
20050       const dataset = spec.dataset;
20051       const getStyleItems = dataset.type === 'basic' ? () => map$2(dataset.data, d => processBasic(d, spec.isSelectedFor, spec.getPreviewFor)) : dataset.getData;
20052       return {
20053         items: generateSelectItems(editor, backstage, spec),
20054         getStyleItems
20055       };
20056     };
20057     const createSelectButton = (editor, backstage, spec) => {
20058       const {items, getStyleItems} = createMenuItems(editor, backstage, spec);
20059       const getApi = comp => ({ getComponent: constant$1(comp) });
20060       const onSetup = onSetupEvent(editor, 'NodeChange', api => {
20061         const comp = api.getComponent();
20062         spec.updateText(comp);
20063       });
20064       return renderCommonDropdown({
20065         text: spec.icon.isSome() ? Optional.none() : spec.text,
20066         icon: spec.icon,
20067         tooltip: Optional.from(spec.tooltip),
20068         role: Optional.none(),
20069         fetch: items.getFetch(backstage, getStyleItems),
20070         onSetup,
20071         getApi,
20072         columns: 1,
20073         presets: 'normal',
20074         classes: spec.icon.isSome() ? [] : ['bespoke'],
20075         dropdownBehaviours: []
20076       }, 'tox-tbtn', backstage.shared);
20077     };
20079     const process = rawFormats => map$2(rawFormats, item => {
20080       let title = item, format = item;
20081       const values = item.split('=');
20082       if (values.length > 1) {
20083         title = values[0];
20084         format = values[1];
20085       }
20086       return {
20087         title,
20088         format
20089       };
20090     });
20091     const buildBasicStaticDataset = data => ({
20092       type: 'basic',
20093       data
20094     });
20095     var Delimiter;
20096     (function (Delimiter) {
20097       Delimiter[Delimiter['SemiColon'] = 0] = 'SemiColon';
20098       Delimiter[Delimiter['Space'] = 1] = 'Space';
20099     }(Delimiter || (Delimiter = {})));
20100     const split = (rawFormats, delimiter) => {
20101       if (delimiter === Delimiter.SemiColon) {
20102         return rawFormats.replace(/;$/, '').split(';');
20103       } else {
20104         return rawFormats.split(' ');
20105       }
20106     };
20107     const buildBasicSettingsDataset = (editor, settingName, delimiter) => {
20108       const rawFormats = editor.options.get(settingName);
20109       const data = process(split(rawFormats, delimiter));
20110       return {
20111         type: 'basic',
20112         data
20113       };
20114     };
20116     const alignMenuItems = [
20117       {
20118         title: 'Left',
20119         icon: 'align-left',
20120         format: 'alignleft',
20121         command: 'JustifyLeft'
20122       },
20123       {
20124         title: 'Center',
20125         icon: 'align-center',
20126         format: 'aligncenter',
20127         command: 'JustifyCenter'
20128       },
20129       {
20130         title: 'Right',
20131         icon: 'align-right',
20132         format: 'alignright',
20133         command: 'JustifyRight'
20134       },
20135       {
20136         title: 'Justify',
20137         icon: 'align-justify',
20138         format: 'alignjustify',
20139         command: 'JustifyFull'
20140       }
20141     ];
20142     const getSpec$4 = editor => {
20143       const getMatchingValue = () => find$5(alignMenuItems, item => editor.formatter.match(item.format));
20144       const isSelectedFor = format => () => editor.formatter.match(format);
20145       const getPreviewFor = _format => Optional.none;
20146       const updateSelectMenuIcon = comp => {
20147         const match = getMatchingValue();
20148         const alignment = match.fold(constant$1('left'), item => item.title.toLowerCase());
20149         emitWith(comp, updateMenuIcon, { icon: `align-${ alignment }` });
20150       };
20151       const dataset = buildBasicStaticDataset(alignMenuItems);
20152       const onAction = rawItem => () => find$5(alignMenuItems, item => item.format === rawItem.format).each(item => editor.execCommand(item.command));
20153       return {
20154         tooltip: 'Align',
20155         text: Optional.none(),
20156         icon: Optional.some('align-left'),
20157         isSelectedFor,
20158         getCurrentValue: Optional.none,
20159         getPreviewFor,
20160         onAction,
20161         updateText: updateSelectMenuIcon,
20162         dataset,
20163         shouldHide: false,
20164         isInvalid: item => !editor.formatter.canApply(item.format)
20165       };
20166     };
20167     const createAlignButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$4(editor));
20168     const createAlignMenu = (editor, backstage) => {
20169       const menuItems = createMenuItems(editor, backstage, getSpec$4(editor));
20170       editor.ui.registry.addNestedMenuItem('align', {
20171         text: backstage.shared.providers.translate('Align'),
20172         getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
20173       });
20174     };
20176     const findNearest = (editor, getStyles) => {
20177       const styles = getStyles();
20178       const formats = map$2(styles, style => style.format);
20179       return Optional.from(editor.formatter.closest(formats)).bind(fmt => find$5(styles, data => data.format === fmt)).orThunk(() => someIf(editor.formatter.match('p'), {
20180         title: 'Paragraph',
20181         format: 'p'
20182       }));
20183     };
20185     const getSpec$3 = editor => {
20186       const fallbackFormat = 'Paragraph';
20187       const isSelectedFor = format => () => editor.formatter.match(format);
20188       const getPreviewFor = format => () => {
20189         const fmt = editor.formatter.get(format);
20190         if (fmt) {
20191           return Optional.some({
20192             tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
20193             styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
20194           });
20195         } else {
20196           return Optional.none();
20197         }
20198       };
20199       const updateSelectMenuText = comp => {
20200         const detectedFormat = findNearest(editor, () => dataset.data);
20201         const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
20202         emitWith(comp, updateMenuText, { text });
20203       };
20204       const dataset = buildBasicSettingsDataset(editor, 'block_formats', Delimiter.SemiColon);
20205       return {
20206         tooltip: 'Blocks',
20207         text: Optional.some(fallbackFormat),
20208         icon: Optional.none(),
20209         isSelectedFor,
20210         getCurrentValue: Optional.none,
20211         getPreviewFor,
20212         onAction: onActionToggleFormat$1(editor),
20213         updateText: updateSelectMenuText,
20214         dataset,
20215         shouldHide: false,
20216         isInvalid: item => !editor.formatter.canApply(item.format)
20217       };
20218     };
20219     const createBlocksButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$3(editor));
20220     const createBlocksMenu = (editor, backstage) => {
20221       const menuItems = createMenuItems(editor, backstage, getSpec$3(editor));
20222       editor.ui.registry.addNestedMenuItem('blocks', {
20223         text: 'Blocks',
20224         getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
20225       });
20226     };
20228     const systemStackFonts = [
20229       '-apple-system',
20230       'Segoe UI',
20231       'Roboto',
20232       'Helvetica Neue',
20233       'sans-serif'
20234     ];
20235     const splitFonts = fontFamily => {
20236       const fonts = fontFamily.split(/\s*,\s*/);
20237       return map$2(fonts, font => font.replace(/^['"]+|['"]+$/g, ''));
20238     };
20239     const isSystemFontStack = fontFamily => {
20240       const matchesSystemStack = () => {
20241         const fonts = splitFonts(fontFamily.toLowerCase());
20242         return forall(systemStackFonts, font => fonts.indexOf(font.toLowerCase()) > -1);
20243       };
20244       return fontFamily.indexOf('-apple-system') === 0 && matchesSystemStack();
20245     };
20246     const getSpec$2 = editor => {
20247       const systemFont = 'System Font';
20248       const getMatchingValue = () => {
20249         const getFirstFont = fontFamily => fontFamily ? splitFonts(fontFamily)[0] : '';
20250         const fontFamily = editor.queryCommandValue('FontName');
20251         const items = dataset.data;
20252         const font = fontFamily ? fontFamily.toLowerCase() : '';
20253         const matchOpt = find$5(items, item => {
20254           const format = item.format;
20255           return format.toLowerCase() === font || getFirstFont(format).toLowerCase() === getFirstFont(font).toLowerCase();
20256         }).orThunk(() => {
20257           return someIf(isSystemFontStack(font), {
20258             title: systemFont,
20259             format: font
20260           });
20261         });
20262         return {
20263           matchOpt,
20264           font: fontFamily
20265         };
20266       };
20267       const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
20268       const getCurrentValue = () => {
20269         const {matchOpt} = getMatchingValue();
20270         return matchOpt;
20271       };
20272       const getPreviewFor = item => () => Optional.some({
20273         tag: 'div',
20274         styles: item.indexOf('dings') === -1 ? { 'font-family': item } : {}
20275       });
20276       const onAction = rawItem => () => {
20277         editor.undoManager.transact(() => {
20278           editor.focus();
20279           editor.execCommand('FontName', false, rawItem.format);
20280         });
20281       };
20282       const updateSelectMenuText = comp => {
20283         const {matchOpt, font} = getMatchingValue();
20284         const text = matchOpt.fold(constant$1(font), item => item.title);
20285         emitWith(comp, updateMenuText, { text });
20286       };
20287       const dataset = buildBasicSettingsDataset(editor, 'font_family_formats', Delimiter.SemiColon);
20288       return {
20289         tooltip: 'Fonts',
20290         text: Optional.some(systemFont),
20291         icon: Optional.none(),
20292         isSelectedFor,
20293         getCurrentValue,
20294         getPreviewFor,
20295         onAction,
20296         updateText: updateSelectMenuText,
20297         dataset,
20298         shouldHide: false,
20299         isInvalid: never
20300       };
20301     };
20302     const createFontFamilyButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$2(editor));
20303     const createFontFamilyMenu = (editor, backstage) => {
20304       const menuItems = createMenuItems(editor, backstage, getSpec$2(editor));
20305       editor.ui.registry.addNestedMenuItem('fontfamily', {
20306         text: backstage.shared.providers.translate('Fonts'),
20307         getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
20308       });
20309     };
20311     const legacyFontSizes = {
20312       '8pt': '1',
20313       '10pt': '2',
20314       '12pt': '3',
20315       '14pt': '4',
20316       '18pt': '5',
20317       '24pt': '6',
20318       '36pt': '7'
20319     };
20320     const keywordFontSizes = {
20321       'xx-small': '7pt',
20322       'x-small': '8pt',
20323       'small': '10pt',
20324       'medium': '12pt',
20325       'large': '14pt',
20326       'x-large': '18pt',
20327       'xx-large': '24pt'
20328     };
20329     const round = (number, precision) => {
20330       const factor = Math.pow(10, precision);
20331       return Math.round(number * factor) / factor;
20332     };
20333     const toPt = (fontSize, precision) => {
20334       if (/[0-9.]+px$/.test(fontSize)) {
20335         return round(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
20336       } else {
20337         return get$g(keywordFontSizes, fontSize).getOr(fontSize);
20338       }
20339     };
20340     const toLegacy = fontSize => get$g(legacyFontSizes, fontSize).getOr('');
20341     const getSpec$1 = editor => {
20342       const getMatchingValue = () => {
20343         let matchOpt = Optional.none();
20344         const items = dataset.data;
20345         const fontSize = editor.queryCommandValue('FontSize');
20346         if (fontSize) {
20347           for (let precision = 3; matchOpt.isNone() && precision >= 0; precision--) {
20348             const pt = toPt(fontSize, precision);
20349             const legacy = toLegacy(pt);
20350             matchOpt = find$5(items, item => item.format === fontSize || item.format === pt || item.format === legacy);
20351           }
20352         }
20353         return {
20354           matchOpt,
20355           size: fontSize
20356         };
20357       };
20358       const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
20359       const getCurrentValue = () => {
20360         const {matchOpt} = getMatchingValue();
20361         return matchOpt;
20362       };
20363       const getPreviewFor = constant$1(Optional.none);
20364       const onAction = rawItem => () => {
20365         editor.undoManager.transact(() => {
20366           editor.focus();
20367           editor.execCommand('FontSize', false, rawItem.format);
20368         });
20369       };
20370       const updateSelectMenuText = comp => {
20371         const {matchOpt, size} = getMatchingValue();
20372         const text = matchOpt.fold(constant$1(size), match => match.title);
20373         emitWith(comp, updateMenuText, { text });
20374       };
20375       const dataset = buildBasicSettingsDataset(editor, 'font_size_formats', Delimiter.Space);
20376       return {
20377         tooltip: 'Font sizes',
20378         text: Optional.some('12pt'),
20379         icon: Optional.none(),
20380         isSelectedFor,
20381         getPreviewFor,
20382         getCurrentValue,
20383         onAction,
20384         updateText: updateSelectMenuText,
20385         dataset,
20386         shouldHide: false,
20387         isInvalid: never
20388       };
20389     };
20390     const createFontSizeButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$1(editor));
20391     const createFontSizeMenu = (editor, backstage) => {
20392       const menuItems = createMenuItems(editor, backstage, getSpec$1(editor));
20393       editor.ui.registry.addNestedMenuItem('fontsize', {
20394         text: 'Font sizes',
20395         getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
20396       });
20397     };
20399     const getSpec = (editor, dataset) => {
20400       const fallbackFormat = 'Paragraph';
20401       const isSelectedFor = format => () => editor.formatter.match(format);
20402       const getPreviewFor = format => () => {
20403         const fmt = editor.formatter.get(format);
20404         return fmt !== undefined ? Optional.some({
20405           tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
20406           styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
20407         }) : Optional.none();
20408       };
20409       const updateSelectMenuText = comp => {
20410         const getFormatItems = fmt => {
20411           if (isNestedFormat(fmt)) {
20412             return bind$3(fmt.items, getFormatItems);
20413           } else if (isFormatReference(fmt)) {
20414             return [{
20415                 title: fmt.title,
20416                 format: fmt.format
20417               }];
20418           } else {
20419             return [];
20420           }
20421         };
20422         const flattenedItems = bind$3(getStyleFormats(editor), getFormatItems);
20423         const detectedFormat = findNearest(editor, constant$1(flattenedItems));
20424         const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
20425         emitWith(comp, updateMenuText, { text });
20426       };
20427       return {
20428         tooltip: 'Formats',
20429         text: Optional.some(fallbackFormat),
20430         icon: Optional.none(),
20431         isSelectedFor,
20432         getCurrentValue: Optional.none,
20433         getPreviewFor,
20434         onAction: onActionToggleFormat$1(editor),
20435         updateText: updateSelectMenuText,
20436         shouldHide: shouldAutoHideStyleFormats(editor),
20437         isInvalid: item => !editor.formatter.canApply(item.format),
20438         dataset
20439       };
20440     };
20441     const createStylesButton = (editor, backstage) => {
20442       const dataset = {
20443         type: 'advanced',
20444         ...backstage.styles
20445       };
20446       return createSelectButton(editor, backstage, getSpec(editor, dataset));
20447     };
20448     const createStylesMenu = (editor, backstage) => {
20449       const dataset = {
20450         type: 'advanced',
20451         ...backstage.styles
20452       };
20453       const menuItems = createMenuItems(editor, backstage, getSpec(editor, dataset));
20454       editor.ui.registry.addNestedMenuItem('styles', {
20455         text: 'Formats',
20456         getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
20457       });
20458     };
20460     const events$3 = (reflectingConfig, reflectingState) => {
20461       const update = (component, data) => {
20462         reflectingConfig.updateState.each(updateState => {
20463           const newState = updateState(component, data);
20464           reflectingState.set(newState);
20465         });
20466         reflectingConfig.renderComponents.each(renderComponents => {
20467           const newComponents = renderComponents(data, reflectingState.get());
20468           const replacer = reflectingConfig.reuseDom ? withReuse : withoutReuse;
20469           replacer(component, newComponents);
20470         });
20471       };
20472       return derive$2([
20473         run$1(receive(), (component, message) => {
20474           const receivingData = message;
20475           if (!receivingData.universal) {
20476             const channel = reflectingConfig.channel;
20477             if (contains$2(receivingData.channels, channel)) {
20478               update(component, receivingData.data);
20479             }
20480           }
20481         }),
20482         runOnAttached((comp, _se) => {
20483           reflectingConfig.initialData.each(rawData => {
20484             update(comp, rawData);
20485           });
20486         })
20487       ]);
20488     };
20490     var ActiveReflecting = /*#__PURE__*/Object.freeze({
20491         __proto__: null,
20492         events: events$3
20493     });
20495     const getState = (component, replaceConfig, reflectState) => reflectState;
20497     var ReflectingApis = /*#__PURE__*/Object.freeze({
20498         __proto__: null,
20499         getState: getState
20500     });
20502     var ReflectingSchema = [
20503       required$1('channel'),
20504       option$3('renderComponents'),
20505       option$3('updateState'),
20506       option$3('initialData'),
20507       defaultedBoolean('reuseDom', true)
20508     ];
20510     const init$3 = () => {
20511       const cell = Cell(Optional.none());
20512       const clear = () => cell.set(Optional.none());
20513       const readState = () => cell.get().getOr('none');
20514       return {
20515         readState,
20516         get: cell.get,
20517         set: cell.set,
20518         clear
20519       };
20520     };
20522     var ReflectingState = /*#__PURE__*/Object.freeze({
20523         __proto__: null,
20524         init: init$3
20525     });
20527     const Reflecting = create$4({
20528       fields: ReflectingSchema,
20529       name: 'reflecting',
20530       active: ActiveReflecting,
20531       apis: ReflectingApis,
20532       state: ReflectingState
20533     });
20535     const schema$7 = constant$1([
20536       required$1('toggleClass'),
20537       required$1('fetch'),
20538       onStrictHandler('onExecute'),
20539       defaulted('getHotspot', Optional.some),
20540       defaulted('getAnchorOverrides', constant$1({})),
20541       schema$y(),
20542       onStrictHandler('onItemExecute'),
20543       option$3('lazySink'),
20544       required$1('dom'),
20545       onHandler('onOpen'),
20546       field('splitDropdownBehaviours', [
20547         Coupling,
20548         Keying,
20549         Focusing
20550       ]),
20551       defaulted('matchWidth', false),
20552       defaulted('useMinWidth', false),
20553       defaulted('eventOrder', {}),
20554       option$3('role')
20555     ].concat(sandboxFields()));
20556     const arrowPart = required({
20557       factory: Button,
20558       schema: [required$1('dom')],
20559       name: 'arrow',
20560       defaults: () => {
20561         return { buttonBehaviours: derive$1([Focusing.revoke()]) };
20562       },
20563       overrides: detail => {
20564         return {
20565           dom: {
20566             tag: 'span',
20567             attributes: { role: 'presentation' }
20568           },
20569           action: arrow => {
20570             arrow.getSystem().getByUid(detail.uid).each(emitExecute);
20571           },
20572           buttonBehaviours: derive$1([Toggling.config({
20573               toggleOnExecute: false,
20574               toggleClass: detail.toggleClass
20575             })])
20576         };
20577       }
20578     });
20579     const buttonPart = required({
20580       factory: Button,
20581       schema: [required$1('dom')],
20582       name: 'button',
20583       defaults: () => {
20584         return { buttonBehaviours: derive$1([Focusing.revoke()]) };
20585       },
20586       overrides: detail => {
20587         return {
20588           dom: {
20589             tag: 'span',
20590             attributes: { role: 'presentation' }
20591           },
20592           action: btn => {
20593             btn.getSystem().getByUid(detail.uid).each(splitDropdown => {
20594               detail.onExecute(splitDropdown, btn);
20595             });
20596           }
20597         };
20598       }
20599     });
20600     const parts$3 = constant$1([
20601       arrowPart,
20602       buttonPart,
20603       optional({
20604         factory: {
20605           sketch: spec => {
20606             return {
20607               uid: spec.uid,
20608               dom: {
20609                 tag: 'span',
20610                 styles: { display: 'none' },
20611                 attributes: { 'aria-hidden': 'true' },
20612                 innerHtml: spec.text
20613               }
20614             };
20615           }
20616         },
20617         schema: [required$1('text')],
20618         name: 'aria-descriptor'
20619       }),
20620       external({
20621         schema: [tieredMenuMarkers()],
20622         name: 'menu',
20623         defaults: detail => {
20624           return {
20625             onExecute: (tmenu, item) => {
20626               tmenu.getSystem().getByUid(detail.uid).each(splitDropdown => {
20627                 detail.onItemExecute(splitDropdown, tmenu, item);
20628               });
20629             }
20630           };
20631         }
20632       }),
20633       partType$1()
20634     ]);
20636     const factory$5 = (detail, components, spec, externals) => {
20637       const switchToMenu = sandbox => {
20638         Composing.getCurrent(sandbox).each(current => {
20639           Highlighting.highlightFirst(current);
20640           Keying.focusIn(current);
20641         });
20642       };
20643       const action = component => {
20644         const onOpenSync = switchToMenu;
20645         togglePopup(detail, identity, component, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
20646       };
20647       const openMenu = comp => {
20648         action(comp);
20649         return Optional.some(true);
20650       };
20651       const executeOnButton = comp => {
20652         const button = getPartOrDie(comp, detail, 'button');
20653         emitExecute(button);
20654         return Optional.some(true);
20655       };
20656       const buttonEvents = {
20657         ...derive$2([runOnAttached((component, _simulatedEvent) => {
20658             const ariaDescriptor = getPart(component, detail, 'aria-descriptor');
20659             ariaDescriptor.each(descriptor => {
20660               const descriptorId = generate$6('aria');
20661               set$9(descriptor.element, 'id', descriptorId);
20662               set$9(component.element, 'aria-describedby', descriptorId);
20663             });
20664           })]),
20665         ...events$a(Optional.some(action))
20666       };
20667       const apis = {
20668         repositionMenus: comp => {
20669           if (Toggling.isOn(comp)) {
20670             repositionMenus(comp);
20671           }
20672         }
20673       };
20674       return {
20675         uid: detail.uid,
20676         dom: detail.dom,
20677         components,
20678         apis,
20679         eventOrder: {
20680           ...detail.eventOrder,
20681           [execute$5()]: [
20682             'disabling',
20683             'toggling',
20684             'alloy.base.behaviour'
20685           ]
20686         },
20687         events: buttonEvents,
20688         behaviours: augment(detail.splitDropdownBehaviours, [
20689           Coupling.config({
20690             others: {
20691               sandbox: hotspot => {
20692                 const arrow = getPartOrDie(hotspot, detail, 'arrow');
20693                 const extras = {
20694                   onOpen: () => {
20695                     Toggling.on(arrow);
20696                     Toggling.on(hotspot);
20697                   },
20698                   onClose: () => {
20699                     Toggling.off(arrow);
20700                     Toggling.off(hotspot);
20701                   }
20702                 };
20703                 return makeSandbox$1(detail, hotspot, extras);
20704               }
20705             }
20706           }),
20707           Keying.config({
20708             mode: 'special',
20709             onSpace: executeOnButton,
20710             onEnter: executeOnButton,
20711             onDown: openMenu
20712           }),
20713           Focusing.config({}),
20714           Toggling.config({
20715             toggleOnExecute: false,
20716             aria: { mode: 'expanded' }
20717           })
20718         ]),
20719         domModification: {
20720           attributes: {
20721             'role': detail.role.getOr('button'),
20722             'aria-haspopup': true
20723           }
20724         }
20725       };
20726     };
20727     const SplitDropdown = composite({
20728       name: 'SplitDropdown',
20729       configFields: schema$7(),
20730       partFields: parts$3(),
20731       factory: factory$5,
20732       apis: { repositionMenus: (apis, comp) => apis.repositionMenus(comp) }
20733     });
20735     const getButtonApi = component => ({
20736       isEnabled: () => !Disabling.isDisabled(component),
20737       setEnabled: state => Disabling.set(component, !state)
20738     });
20739     const getToggleApi = component => ({
20740       setActive: state => {
20741         Toggling.set(component, state);
20742       },
20743       isActive: () => Toggling.isOn(component),
20744       isEnabled: () => !Disabling.isDisabled(component),
20745       setEnabled: state => Disabling.set(component, !state)
20746     });
20747     const getTooltipAttributes = (tooltip, providersBackstage) => tooltip.map(tooltip => ({
20748       'aria-label': providersBackstage.translate(tooltip),
20749       'title': providersBackstage.translate(tooltip)
20750     })).getOr({});
20751     const focusButtonEvent = generate$6('focus-button');
20752     const renderCommonStructure = (icon, text, tooltip, receiver, behaviours, providersBackstage) => {
20753       return {
20754         dom: {
20755           tag: 'button',
20756           classes: ['tox-tbtn'].concat(text.isSome() ? ['tox-tbtn--select'] : []),
20757           attributes: getTooltipAttributes(tooltip, providersBackstage)
20758         },
20759         components: componentRenderPipeline([
20760           icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons)),
20761           text.map(text => renderLabel(text, 'tox-tbtn', providersBackstage))
20762         ]),
20763         eventOrder: {
20764           [mousedown()]: [
20765             'focusing',
20766             'alloy.base.behaviour',
20767             'common-button-display-events'
20768           ]
20769         },
20770         buttonBehaviours: derive$1([
20771           DisablingConfigs.toolbarButton(providersBackstage.isDisabled),
20772           receivingConfig(),
20773           config('common-button-display-events', [run$1(mousedown(), (button, se) => {
20774               se.event.prevent();
20775               emit(button, focusButtonEvent);
20776             })])
20777         ].concat(receiver.map(r => Reflecting.config({
20778           channel: r,
20779           initialData: {
20780             icon,
20781             text
20782           },
20783           renderComponents: (data, _state) => componentRenderPipeline([
20784             data.icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons)),
20785             data.text.map(text => renderLabel(text, 'tox-tbtn', providersBackstage))
20786           ])
20787         })).toArray()).concat(behaviours.getOr([])))
20788       };
20789     };
20790     const renderFloatingToolbarButton = (spec, backstage, identifyButtons, attributes) => {
20791       const sharedBackstage = backstage.shared;
20792       return FloatingToolbarButton.sketch({
20793         lazySink: sharedBackstage.getSink,
20794         fetch: () => Future.nu(resolve => {
20795           resolve(map$2(identifyButtons(spec.items), renderToolbarGroup));
20796         }),
20797         markers: { toggledClass: 'tox-tbtn--enabled' },
20798         parts: {
20799           button: renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.none(), Optional.none(), sharedBackstage.providers),
20800           toolbar: {
20801             dom: {
20802               tag: 'div',
20803               classes: ['tox-toolbar__overflow'],
20804               attributes
20805             }
20806           }
20807         }
20808       });
20809     };
20810     const renderCommonToolbarButton = (spec, specialisation, providersBackstage) => {
20811       const editorOffCell = Cell(noop);
20812       const structure = renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.none(), Optional.none(), providersBackstage);
20813       return Button.sketch({
20814         dom: structure.dom,
20815         components: structure.components,
20816         eventOrder: toolbarButtonEventOrder,
20817         buttonBehaviours: derive$1([
20818           config('toolbar-button-events', [
20819             onToolbarButtonExecute({
20820               onAction: spec.onAction,
20821               getApi: specialisation.getApi
20822             }),
20823             onControlAttached(specialisation, editorOffCell),
20824             onControlDetached(specialisation, editorOffCell)
20825           ]),
20826           DisablingConfigs.toolbarButton(() => !spec.enabled || providersBackstage.isDisabled()),
20827           receivingConfig()
20828         ].concat(specialisation.toolbarButtonBehaviours))
20829       });
20830     };
20831     const renderToolbarButton = (spec, providersBackstage) => renderToolbarButtonWith(spec, providersBackstage, []);
20832     const renderToolbarButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
20833       toolbarButtonBehaviours: bonusEvents.length > 0 ? [config('toolbarButtonWith', bonusEvents)] : [],
20834       getApi: getButtonApi,
20835       onSetup: spec.onSetup
20836     }, providersBackstage);
20837     const renderToolbarToggleButton = (spec, providersBackstage) => renderToolbarToggleButtonWith(spec, providersBackstage, []);
20838     const renderToolbarToggleButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
20839       toolbarButtonBehaviours: [
20840         Replacing.config({}),
20841         Toggling.config({
20842           toggleClass: 'tox-tbtn--enabled',
20843           aria: { mode: 'pressed' },
20844           toggleOnExecute: false
20845         })
20846       ].concat(bonusEvents.length > 0 ? [config('toolbarToggleButtonWith', bonusEvents)] : []),
20847       getApi: getToggleApi,
20848       onSetup: spec.onSetup
20849     }, providersBackstage);
20850     const fetchChoices = (getApi, spec, providersBackstage) => comp => Future.nu(callback => spec.fetch(callback)).map(items => Optional.from(createTieredDataFrom(deepMerge(createPartialChoiceMenu(generate$6('menu-value'), items, value => {
20851       spec.onItemAction(getApi(comp), value);
20852     }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, spec.select.getOr(never), providersBackstage), {
20853       movement: deriveMenuMovement(spec.columns, spec.presets),
20854       menuBehaviours: SimpleBehaviours.unnamedEvents(spec.columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
20855           detectSize(comp, 4, classForPreset(spec.presets)).each(({numRows, numColumns}) => {
20856             Keying.setGridSize(comp, numRows, numColumns);
20857           });
20858         })])
20859     }))));
20860     const renderSplitButton = (spec, sharedBackstage) => {
20861       const displayChannel = generate$6('channel-update-split-dropdown-display');
20862       const getApi = comp => ({
20863         isEnabled: () => !Disabling.isDisabled(comp),
20864         setEnabled: state => Disabling.set(comp, !state),
20865         setIconFill: (id, value) => {
20866           descendant(comp.element, 'svg path[id="' + id + '"], rect[id="' + id + '"]').each(underlinePath => {
20867             set$9(underlinePath, 'fill', value);
20868           });
20869         },
20870         setActive: state => {
20871           set$9(comp.element, 'aria-pressed', state);
20872           descendant(comp.element, 'span').each(button => {
20873             comp.getSystem().getByDom(button).each(buttonComp => Toggling.set(buttonComp, state));
20874           });
20875         },
20876         isActive: () => descendant(comp.element, 'span').exists(button => comp.getSystem().getByDom(button).exists(Toggling.isOn))
20877       });
20878       const editorOffCell = Cell(noop);
20879       const specialisation = {
20880         getApi,
20881         onSetup: spec.onSetup
20882       };
20883       return SplitDropdown.sketch({
20884         dom: {
20885           tag: 'div',
20886           classes: ['tox-split-button'],
20887           attributes: {
20888             'aria-pressed': false,
20889             ...getTooltipAttributes(spec.tooltip, sharedBackstage.providers)
20890           }
20891         },
20892         onExecute: button => {
20893           spec.onAction(getApi(button));
20894         },
20895         onItemExecute: (_a, _b, _c) => {
20896         },
20897         splitDropdownBehaviours: derive$1([
20898           DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
20899           receivingConfig(),
20900           config('split-dropdown-events', [
20901             run$1(focusButtonEvent, Focusing.focus),
20902             onControlAttached(specialisation, editorOffCell),
20903             onControlDetached(specialisation, editorOffCell)
20904           ]),
20905           Unselecting.config({})
20906         ]),
20907         eventOrder: {
20908           [attachedToDom()]: [
20909             'alloy.base.behaviour',
20910             'split-dropdown-events'
20911           ]
20912         },
20913         toggleClass: 'tox-tbtn--enabled',
20914         lazySink: sharedBackstage.getSink,
20915         fetch: fetchChoices(getApi, spec, sharedBackstage.providers),
20916         parts: { menu: part(false, spec.columns, spec.presets) },
20917         components: [
20918           SplitDropdown.parts.button(renderCommonStructure(spec.icon, spec.text, Optional.none(), Optional.some(displayChannel), Optional.some([Toggling.config({
20919               toggleClass: 'tox-tbtn--enabled',
20920               toggleOnExecute: false
20921             })]), sharedBackstage.providers)),
20922           SplitDropdown.parts.arrow({
20923             dom: {
20924               tag: 'button',
20925               classes: [
20926                 'tox-tbtn',
20927                 'tox-split-button__chevron'
20928               ],
20929               innerHtml: get$2('chevron-down', sharedBackstage.providers.icons)
20930             },
20931             buttonBehaviours: derive$1([
20932               DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
20933               receivingConfig(),
20934               addFocusableBehaviour()
20935             ])
20936           }),
20937           SplitDropdown.parts['aria-descriptor']({ text: sharedBackstage.providers.translate('To open the popup, press Shift+Enter') })
20938         ]
20939       });
20940     };
20942     const defaultToolbar = [
20943       {
20944         name: 'history',
20945         items: [
20946           'undo',
20947           'redo'
20948         ]
20949       },
20950       {
20951         name: 'styles',
20952         items: ['styles']
20953       },
20954       {
20955         name: 'formatting',
20956         items: [
20957           'bold',
20958           'italic'
20959         ]
20960       },
20961       {
20962         name: 'alignment',
20963         items: [
20964           'alignleft',
20965           'aligncenter',
20966           'alignright',
20967           'alignjustify'
20968         ]
20969       },
20970       {
20971         name: 'indentation',
20972         items: [
20973           'outdent',
20974           'indent'
20975         ]
20976       },
20977       {
20978         name: 'permanent pen',
20979         items: ['permanentpen']
20980       },
20981       {
20982         name: 'comments',
20983         items: ['addcomment']
20984       }
20985     ];
20986     const renderFromBridge = (bridgeBuilder, render) => (spec, backstage, editor) => {
20987       const internal = bridgeBuilder(spec).mapError(errInfo => formatError(errInfo)).getOrDie();
20988       return render(internal, backstage, editor);
20989     };
20990     const types = {
20991       button: renderFromBridge(createToolbarButton, (s, backstage) => renderToolbarButton(s, backstage.shared.providers)),
20992       togglebutton: renderFromBridge(createToggleButton, (s, backstage) => renderToolbarToggleButton(s, backstage.shared.providers)),
20993       menubutton: renderFromBridge(createMenuButton, (s, backstage) => renderMenuButton(s, 'tox-tbtn', backstage, Optional.none())),
20994       splitbutton: renderFromBridge(createSplitButton, (s, backstage) => renderSplitButton(s, backstage.shared)),
20995       grouptoolbarbutton: renderFromBridge(createGroupToolbarButton, (s, backstage, editor) => {
20996         const buttons = editor.ui.registry.getAll().buttons;
20997         const identify = toolbar => identifyButtons(editor, {
20998           buttons,
20999           toolbar,
21000           allowToolbarGroups: false
21001         }, backstage, Optional.none());
21002         const attributes = { [Attribute]: backstage.shared.header.isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop };
21003         switch (getToolbarMode(editor)) {
21004         case ToolbarMode$1.floating:
21005           return renderFloatingToolbarButton(s, backstage, identify, attributes);
21006         default:
21007           throw new Error('Toolbar groups are only supported when using floating toolbar mode');
21008         }
21009       })
21010     };
21011     const extractFrom = (spec, backstage, editor) => get$g(types, spec.type).fold(() => {
21012       console.error('skipping button defined by', spec);
21013       return Optional.none();
21014     }, render => Optional.some(render(spec, backstage, editor)));
21015     const bespokeButtons = {
21016       styles: createStylesButton,
21017       fontsize: createFontSizeButton,
21018       fontfamily: createFontFamilyButton,
21019       blocks: createBlocksButton,
21020       align: createAlignButton
21021     };
21022     const removeUnusedDefaults = buttons => {
21023       const filteredItemGroups = map$2(defaultToolbar, group => {
21024         const items = filter$2(group.items, subItem => has$2(buttons, subItem) || has$2(bespokeButtons, subItem));
21025         return {
21026           name: group.name,
21027           items
21028         };
21029       });
21030       return filter$2(filteredItemGroups, group => group.items.length > 0);
21031     };
21032     const convertStringToolbar = strToolbar => {
21033       const groupsStrings = strToolbar.split('|');
21034       return map$2(groupsStrings, g => ({ items: g.trim().split(' ') }));
21035     };
21036     const isToolbarGroupSettingArray = toolbar => isArrayOf(toolbar, t => has$2(t, 'name') && has$2(t, 'items'));
21037     const createToolbar = toolbarConfig => {
21038       const toolbar = toolbarConfig.toolbar;
21039       const buttons = toolbarConfig.buttons;
21040       if (toolbar === false) {
21041         return [];
21042       } else if (toolbar === undefined || toolbar === true) {
21043         return removeUnusedDefaults(buttons);
21044       } else if (isString(toolbar)) {
21045         return convertStringToolbar(toolbar);
21046       } else if (isToolbarGroupSettingArray(toolbar)) {
21047         return toolbar;
21048       } else {
21049         console.error('Toolbar type should be string, string[], boolean or ToolbarGroup[]');
21050         return [];
21051       }
21052     };
21053     const lookupButton = (editor, buttons, toolbarItem, allowToolbarGroups, backstage, prefixes) => get$g(buttons, toolbarItem.toLowerCase()).orThunk(() => prefixes.bind(ps => findMap(ps, prefix => get$g(buttons, prefix + toolbarItem.toLowerCase())))).fold(() => get$g(bespokeButtons, toolbarItem.toLowerCase()).map(r => r(editor, backstage)), spec => {
21054       if (spec.type === 'grouptoolbarbutton' && !allowToolbarGroups) {
21055         console.warn(`Ignoring the '${ toolbarItem }' toolbar button. Group toolbar buttons are only supported when using floating toolbar mode and cannot be nested.`);
21056         return Optional.none();
21057       } else {
21058         return extractFrom(spec, backstage, editor);
21059       }
21060     });
21061     const identifyButtons = (editor, toolbarConfig, backstage, prefixes) => {
21062       const toolbarGroups = createToolbar(toolbarConfig);
21063       const groups = map$2(toolbarGroups, group => {
21064         const items = bind$3(group.items, toolbarItem => {
21065           return toolbarItem.trim().length === 0 ? [] : lookupButton(editor, toolbarConfig.buttons, toolbarItem, toolbarConfig.allowToolbarGroups, backstage, prefixes).toArray();
21066         });
21067         return {
21068           title: Optional.from(editor.translate(group.name)),
21069           items
21070         };
21071       });
21072       return filter$2(groups, group => group.items.length > 0);
21073     };
21075     const setToolbar = (editor, uiComponents, rawUiConfig, backstage) => {
21076       const comp = uiComponents.outerContainer;
21077       const toolbarConfig = rawUiConfig.toolbar;
21078       const toolbarButtonsConfig = rawUiConfig.buttons;
21079       if (isArrayOf(toolbarConfig, isString)) {
21080         const toolbars = toolbarConfig.map(t => {
21081           const config = {
21082             toolbar: t,
21083             buttons: toolbarButtonsConfig,
21084             allowToolbarGroups: rawUiConfig.allowToolbarGroups
21085           };
21086           return identifyButtons(editor, config, backstage, Optional.none());
21087         });
21088         OuterContainer.setToolbars(comp, toolbars);
21089       } else {
21090         OuterContainer.setToolbar(comp, identifyButtons(editor, rawUiConfig, backstage, Optional.none()));
21091       }
21092     };
21094     const detection = detect$1();
21095     const isiOS12 = detection.os.isiOS() && detection.os.version.major <= 12;
21096     const setupEvents$1 = (editor, uiComponents) => {
21097       const dom = editor.dom;
21098       let contentWindow = editor.getWin();
21099       const initialDocEle = editor.getDoc().documentElement;
21100       const lastWindowDimensions = Cell(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
21101       const lastDocumentDimensions = Cell(SugarPosition(initialDocEle.offsetWidth, initialDocEle.offsetHeight));
21102       const resizeWindow = () => {
21103         const outer = lastWindowDimensions.get();
21104         if (outer.left !== contentWindow.innerWidth || outer.top !== contentWindow.innerHeight) {
21105           lastWindowDimensions.set(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
21106           fireResizeContent(editor);
21107         }
21108       };
21109       const resizeDocument = () => {
21110         const docEle = editor.getDoc().documentElement;
21111         const inner = lastDocumentDimensions.get();
21112         if (inner.left !== docEle.offsetWidth || inner.top !== docEle.offsetHeight) {
21113           lastDocumentDimensions.set(SugarPosition(docEle.offsetWidth, docEle.offsetHeight));
21114           fireResizeContent(editor);
21115         }
21116       };
21117       const scroll = e => {
21118         fireScrollContent(editor, e);
21119       };
21120       dom.bind(contentWindow, 'resize', resizeWindow);
21121       dom.bind(contentWindow, 'scroll', scroll);
21122       const elementLoad = capture(SugarElement.fromDom(editor.getBody()), 'load', resizeDocument);
21123       const mothership = uiComponents.uiMothership.element;
21124       editor.on('hide', () => {
21125         set$8(mothership, 'display', 'none');
21126       });
21127       editor.on('show', () => {
21128         remove$6(mothership, 'display');
21129       });
21130       editor.on('NodeChange', resizeDocument);
21131       editor.on('remove', () => {
21132         elementLoad.unbind();
21133         dom.unbind(contentWindow, 'resize', resizeWindow);
21134         dom.unbind(contentWindow, 'scroll', scroll);
21135         contentWindow = null;
21136       });
21137     };
21138     const render$1 = (editor, uiComponents, rawUiConfig, backstage, args) => {
21139       const lastToolbarWidth = Cell(0);
21140       const outerContainer = uiComponents.outerContainer;
21141       iframe(editor);
21142       const eTargetNode = SugarElement.fromDom(args.targetNode);
21143       const uiRoot = getContentContainer(getRootNode(eTargetNode));
21144       attachSystemAfter(eTargetNode, uiComponents.mothership);
21145       attachSystem(uiRoot, uiComponents.uiMothership);
21146       editor.on('PostRender', () => {
21147         OuterContainer.setSidebar(outerContainer, rawUiConfig.sidebar, getSidebarShow(editor));
21148         setToolbar(editor, uiComponents, rawUiConfig, backstage);
21149         lastToolbarWidth.set(editor.getWin().innerWidth);
21150         OuterContainer.setMenubar(outerContainer, identifyMenus(editor, rawUiConfig));
21151         setupEvents$1(editor, uiComponents);
21152       });
21153       const socket = OuterContainer.getSocket(outerContainer).getOrDie('Could not find expected socket element');
21154       if (isiOS12) {
21155         setAll(socket.element, {
21156           'overflow': 'scroll',
21157           '-webkit-overflow-scrolling': 'touch'
21158         });
21159         const limit = first(() => {
21160           editor.dispatch('ScrollContent');
21161         }, 20);
21162         const unbinder = bind(socket.element, 'scroll', limit.throttle);
21163         editor.on('remove', unbinder.unbind);
21164       }
21165       setupReadonlyModeSwitch(editor, uiComponents);
21166       editor.addCommand('ToggleSidebar', (_ui, value) => {
21167         OuterContainer.toggleSidebar(outerContainer, value);
21168         editor.dispatch('ToggleSidebar');
21169       });
21170       editor.addQueryValueHandler('ToggleSidebar', () => OuterContainer.whichSidebar(outerContainer) ?? '');
21171       const toolbarMode = getToolbarMode(editor);
21172       const refreshDrawer = () => {
21173         OuterContainer.refreshToolbar(uiComponents.outerContainer);
21174       };
21175       if (toolbarMode === ToolbarMode$1.sliding || toolbarMode === ToolbarMode$1.floating) {
21176         editor.on('ResizeWindow ResizeEditor ResizeContent', () => {
21177           const width = editor.getWin().innerWidth;
21178           if (width !== lastToolbarWidth.get()) {
21179             refreshDrawer();
21180             lastToolbarWidth.set(width);
21181           }
21182         });
21183       }
21184       const api = {
21185         setEnabled: state => {
21186           broadcastReadonly(uiComponents, !state);
21187         },
21188         isEnabled: () => !Disabling.isDisabled(outerContainer)
21189       };
21190       return {
21191         iframeContainer: socket.element.dom,
21192         editorContainer: outerContainer.element.dom,
21193         api
21194       };
21195     };
21197     var Iframe = /*#__PURE__*/Object.freeze({
21198         __proto__: null,
21199         render: render$1
21200     });
21202     const parseToInt = val => {
21203       const re = /^[0-9\.]+(|px)$/i;
21204       if (re.test('' + val)) {
21205         return Optional.some(parseInt('' + val, 10));
21206       }
21207       return Optional.none();
21208     };
21209     const numToPx = val => isNumber(val) ? val + 'px' : val;
21210     const calcCappedSize = (size, minSize, maxSize) => {
21211       const minOverride = minSize.filter(min => size < min);
21212       const maxOverride = maxSize.filter(max => size > max);
21213       return minOverride.or(maxOverride).getOr(size);
21214     };
21216     const getHeight = editor => {
21217       const baseHeight = getHeightOption(editor);
21218       const minHeight = getMinHeightOption(editor);
21219       const maxHeight = getMaxHeightOption(editor);
21220       return parseToInt(baseHeight).map(height => calcCappedSize(height, minHeight, maxHeight));
21221     };
21222     const getHeightWithFallback = editor => {
21223       const height = getHeight(editor);
21224       return height.getOr(getHeightOption(editor));
21225     };
21226     const getWidth = editor => {
21227       const baseWidth = getWidthOption(editor);
21228       const minWidth = getMinWidthOption(editor);
21229       const maxWidth = getMaxWidthOption(editor);
21230       return parseToInt(baseWidth).map(width => calcCappedSize(width, minWidth, maxWidth));
21231     };
21232     const getWidthWithFallback = editor => {
21233       const width = getWidth(editor);
21234       return width.getOr(getWidthOption(editor));
21235     };
21237     const {ToolbarLocation, ToolbarMode} = Options;
21238     const InlineHeader = (editor, targetElm, uiComponents, backstage, floatContainer) => {
21239       const {uiMothership, outerContainer} = uiComponents;
21240       const DOM = global$7.DOM;
21241       const useFixedToolbarContainer = useFixedContainer(editor);
21242       const isSticky = isStickyToolbar(editor);
21243       const editorMaxWidthOpt = getMaxWidthOption(editor).or(getWidth(editor));
21244       const headerBackstage = backstage.shared.header;
21245       const isPositionedAtTop = headerBackstage.isPositionedAtTop;
21246       const toolbarMode = getToolbarMode(editor);
21247       const isSplitToolbar = toolbarMode === ToolbarMode.sliding || toolbarMode === ToolbarMode.floating;
21248       const visible = Cell(false);
21249       const isVisible = () => visible.get() && !editor.removed;
21250       const calcToolbarOffset = toolbar => isSplitToolbar ? toolbar.fold(constant$1(0), tbar => tbar.components().length > 1 ? get$d(tbar.components()[1].element) : 0) : 0;
21251       const calcMode = container => {
21252         switch (getToolbarLocation(editor)) {
21253         case ToolbarLocation.auto:
21254           const toolbar = OuterContainer.getToolbar(outerContainer);
21255           const offset = calcToolbarOffset(toolbar);
21256           const toolbarHeight = get$d(container.element) - offset;
21257           const targetBounds = box$1(targetElm);
21258           const roomAtTop = targetBounds.y > toolbarHeight;
21259           if (roomAtTop) {
21260             return 'top';
21261           } else {
21262             const doc = documentElement(targetElm);
21263             const docHeight = Math.max(doc.dom.scrollHeight, get$d(doc));
21264             const roomAtBottom = targetBounds.bottom < docHeight - toolbarHeight;
21265             if (roomAtBottom) {
21266               return 'bottom';
21267             } else {
21268               const winBounds = win();
21269               const isRoomAtBottomViewport = winBounds.bottom < targetBounds.bottom - toolbarHeight;
21270               return isRoomAtBottomViewport ? 'bottom' : 'top';
21271             }
21272           }
21273         case ToolbarLocation.bottom:
21274           return 'bottom';
21275         case ToolbarLocation.top:
21276         default:
21277           return 'top';
21278         }
21279       };
21280       const setupMode = mode => {
21281         floatContainer.on(container => {
21282           Docking.setModes(container, [mode]);
21283           headerBackstage.setDockingMode(mode);
21284           const verticalDir = isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop;
21285           set$9(container.element, Attribute, verticalDir);
21286         });
21287       };
21288       const updateChromeWidth = () => {
21289         floatContainer.on(container => {
21290           const maxWidth = editorMaxWidthOpt.getOrThunk(() => {
21291             const bodyMargin = parseToInt(get$e(body(), 'margin-left')).getOr(0);
21292             return get$c(body()) - absolute$3(targetElm).left + bodyMargin;
21293           });
21294           set$8(container.element, 'max-width', maxWidth + 'px');
21295         });
21296       };
21297       const updateChromePosition = () => {
21298         floatContainer.on(container => {
21299           const toolbar = OuterContainer.getToolbar(outerContainer);
21300           const offset = calcToolbarOffset(toolbar);
21301           const targetBounds = box$1(targetElm);
21302           const top = isPositionedAtTop() ? Math.max(targetBounds.y - get$d(container.element) + offset, 0) : targetBounds.bottom;
21303           setAll(outerContainer.element, {
21304             position: 'absolute',
21305             top: Math.round(top) + 'px',
21306             left: Math.round(targetBounds.x) + 'px'
21307           });
21308         });
21309       };
21310       const repositionPopups$1 = () => {
21311         uiMothership.broadcastOn([repositionPopups()], {});
21312       };
21313       const updateChromeUi = (resetDocking = false) => {
21314         if (!isVisible()) {
21315           return;
21316         }
21317         if (!useFixedToolbarContainer) {
21318           updateChromeWidth();
21319         }
21320         if (isSplitToolbar) {
21321           OuterContainer.refreshToolbar(outerContainer);
21322         }
21323         if (!useFixedToolbarContainer) {
21324           updateChromePosition();
21325         }
21326         if (isSticky) {
21327           const action = resetDocking ? Docking.reset : Docking.refresh;
21328           floatContainer.on(action);
21329         }
21330         repositionPopups$1();
21331       };
21332       const updateMode = (updateUi = true) => {
21333         if (useFixedToolbarContainer || !isSticky || !isVisible()) {
21334           return;
21335         }
21336         floatContainer.on(container => {
21337           const currentMode = headerBackstage.getDockingMode();
21338           const newMode = calcMode(container);
21339           if (newMode !== currentMode) {
21340             setupMode(newMode);
21341             if (updateUi) {
21342               updateChromeUi(true);
21343             }
21344           }
21345         });
21346       };
21347       const show = () => {
21348         visible.set(true);
21349         set$8(outerContainer.element, 'display', 'flex');
21350         DOM.addClass(editor.getBody(), 'mce-edit-focus');
21351         remove$6(uiMothership.element, 'display');
21352         updateMode(false);
21353         updateChromeUi();
21354       };
21355       const hide = () => {
21356         visible.set(false);
21357         if (uiComponents.outerContainer) {
21358           set$8(outerContainer.element, 'display', 'none');
21359           DOM.removeClass(editor.getBody(), 'mce-edit-focus');
21360         }
21361         set$8(uiMothership.element, 'display', 'none');
21362       };
21363       return {
21364         isVisible,
21365         isPositionedAtTop,
21366         show,
21367         hide,
21368         update: updateChromeUi,
21369         updateMode,
21370         repositionPopups: repositionPopups$1
21371       };
21372     };
21374     const getTargetPosAndBounds = (targetElm, isToolbarTop) => {
21375       const bounds = box$1(targetElm);
21376       return {
21377         pos: isToolbarTop ? bounds.y : bounds.bottom,
21378         bounds
21379       };
21380     };
21381     const setupEvents = (editor, targetElm, ui, toolbarPersist) => {
21382       const prevPosAndBounds = Cell(getTargetPosAndBounds(targetElm, ui.isPositionedAtTop()));
21383       const resizeContent = e => {
21384         const {pos, bounds} = getTargetPosAndBounds(targetElm, ui.isPositionedAtTop());
21385         const {
21386           pos: prevPos,
21387           bounds: prevBounds
21388         } = prevPosAndBounds.get();
21389         const hasResized = bounds.height !== prevBounds.height || bounds.width !== prevBounds.width;
21390         prevPosAndBounds.set({
21391           pos,
21392           bounds
21393         });
21394         if (hasResized) {
21395           fireResizeContent(editor, e);
21396         }
21397         if (ui.isVisible()) {
21398           if (prevPos !== pos) {
21399             ui.update(true);
21400           } else if (hasResized) {
21401             ui.updateMode();
21402             ui.repositionPopups();
21403           }
21404         }
21405       };
21406       if (!toolbarPersist) {
21407         editor.on('activate', ui.show);
21408         editor.on('deactivate', ui.hide);
21409       }
21410       editor.on('SkinLoaded ResizeWindow', () => ui.update(true));
21411       editor.on('NodeChange keydown', e => {
21412         requestAnimationFrame(() => resizeContent(e));
21413       });
21414       editor.on('ScrollWindow', () => ui.updateMode());
21415       const elementLoad = unbindable();
21416       elementLoad.set(capture(SugarElement.fromDom(editor.getBody()), 'load', e => resizeContent(e.raw)));
21417       editor.on('remove', () => {
21418         elementLoad.clear();
21419       });
21420     };
21421     const render = (editor, uiComponents, rawUiConfig, backstage, args) => {
21422       const {mothership, uiMothership, outerContainer} = uiComponents;
21423       const floatContainer = value$2();
21424       const targetElm = SugarElement.fromDom(args.targetNode);
21425       const ui = InlineHeader(editor, targetElm, uiComponents, backstage, floatContainer);
21426       const toolbarPersist = isToolbarPersist(editor);
21427       inline(editor);
21428       const render = () => {
21429         if (floatContainer.isSet()) {
21430           ui.show();
21431           return;
21432         }
21433         floatContainer.set(OuterContainer.getHeader(outerContainer).getOrDie());
21434         const uiContainer = getUiContainer(editor);
21435         attachSystem(uiContainer, mothership);
21436         attachSystem(uiContainer, uiMothership);
21437         setToolbar(editor, uiComponents, rawUiConfig, backstage);
21438         OuterContainer.setMenubar(outerContainer, identifyMenus(editor, rawUiConfig));
21439         ui.show();
21440         setupEvents(editor, targetElm, ui, toolbarPersist);
21441         editor.nodeChanged();
21442       };
21443       editor.on('show', render);
21444       editor.on('hide', ui.hide);
21445       if (!toolbarPersist) {
21446         editor.on('focus', render);
21447         editor.on('blur', ui.hide);
21448       }
21449       editor.on('init', () => {
21450         if (editor.hasFocus() || toolbarPersist) {
21451           render();
21452         }
21453       });
21454       setupReadonlyModeSwitch(editor, uiComponents);
21455       const api = {
21456         show: render,
21457         hide: ui.hide,
21458         setEnabled: state => {
21459           broadcastReadonly(uiComponents, !state);
21460         },
21461         isEnabled: () => !Disabling.isDisabled(outerContainer)
21462       };
21463       return {
21464         editorContainer: outerContainer.element.dom,
21465         api
21466       };
21467     };
21469     var Inline = /*#__PURE__*/Object.freeze({
21470         __proto__: null,
21471         render: render
21472     });
21474     const showContextToolbarEvent = 'contexttoolbar-show';
21475     const hideContextToolbarEvent = 'contexttoolbar-hide';
21477     const getFormApi = input => ({
21478       hide: () => emit(input, sandboxClose()),
21479       getValue: () => Representing.getValue(input)
21480     });
21481     const runOnExecute = (memInput, original) => run$1(internalToolbarButtonExecute, (comp, se) => {
21482       const input = memInput.get(comp);
21483       const formApi = getFormApi(input);
21484       original.onAction(formApi, se.event.buttonApi);
21485     });
21486     const renderContextButton = (memInput, button, providers) => {
21487       const {primary, ...rest} = button.original;
21488       const bridged = getOrDie(createToolbarButton({
21489         ...rest,
21490         type: 'button',
21491         onAction: noop
21492       }));
21493       return renderToolbarButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
21494     };
21495     const renderContextToggleButton = (memInput, button, providers) => {
21496       const {primary, ...rest} = button.original;
21497       const bridged = getOrDie(createToggleButton({
21498         ...rest,
21499         type: 'togglebutton',
21500         onAction: noop
21501       }));
21502       return renderToolbarToggleButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
21503     };
21504     const isToggleButton = button => button.type === 'contextformtogglebutton';
21505     const generateOne = (memInput, button, providersBackstage) => {
21506       if (isToggleButton(button)) {
21507         return renderContextToggleButton(memInput, button, providersBackstage);
21508       } else {
21509         return renderContextButton(memInput, button, providersBackstage);
21510       }
21511     };
21512     const generate = (memInput, buttons, providersBackstage) => {
21513       const mementos = map$2(buttons, button => record(generateOne(memInput, button, providersBackstage)));
21514       const asSpecs = () => map$2(mementos, mem => mem.asSpec());
21515       const findPrimary = compInSystem => findMap(buttons, (button, i) => {
21516         if (button.primary) {
21517           return Optional.from(mementos[i]).bind(mem => mem.getOpt(compInSystem)).filter(not(Disabling.isDisabled));
21518         } else {
21519           return Optional.none();
21520         }
21521       });
21522       return {
21523         asSpecs,
21524         findPrimary
21525       };
21526     };
21528     const buildInitGroups = (ctx, providers) => {
21529       const inputAttributes = ctx.label.fold(() => ({}), label => ({ 'aria-label': label }));
21530       const memInput = record(Input.sketch({
21531         inputClasses: [
21532           'tox-toolbar-textfield',
21533           'tox-toolbar-nav-js'
21534         ],
21535         data: ctx.initValue(),
21536         inputAttributes,
21537         selectOnFocus: true,
21538         inputBehaviours: derive$1([Keying.config({
21539             mode: 'special',
21540             onEnter: input => commands.findPrimary(input).map(primary => {
21541               emitExecute(primary);
21542               return true;
21543             }),
21544             onLeft: (comp, se) => {
21545               se.cut();
21546               return Optional.none();
21547             },
21548             onRight: (comp, se) => {
21549               se.cut();
21550               return Optional.none();
21551             }
21552           })])
21553       }));
21554       const commands = generate(memInput, ctx.commands, providers);
21555       return [
21556         {
21557           title: Optional.none(),
21558           items: [memInput.asSpec()]
21559         },
21560         {
21561           title: Optional.none(),
21562           items: commands.asSpecs()
21563         }
21564       ];
21565     };
21566     const renderContextForm = (toolbarType, ctx, providers) => renderToolbar({
21567       type: toolbarType,
21568       uid: generate$6('context-toolbar'),
21569       initGroups: buildInitGroups(ctx, providers),
21570       onEscape: Optional.none,
21571       cyclicKeying: true,
21572       providers
21573     });
21574     const ContextForm = {
21575       renderContextForm,
21576       buildInitGroups
21577     };
21579     const isVerticalOverlap = (a, b, threshold = 0.01) => b.bottom - a.y >= threshold && a.bottom - b.y >= threshold;
21580     const getRangeRect = rng => {
21581       const rect = rng.getBoundingClientRect();
21582       if (rect.height <= 0 && rect.width <= 0) {
21583         const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset).element;
21584         const elm = isText(leaf$1) ? parent(leaf$1) : Optional.some(leaf$1);
21585         return elm.filter(isElement$1).map(e => e.dom.getBoundingClientRect()).getOr(rect);
21586       } else {
21587         return rect;
21588       }
21589     };
21590     const getSelectionBounds = editor => {
21591       const rng = editor.selection.getRng();
21592       const rect = getRangeRect(rng);
21593       if (editor.inline) {
21594         const scroll = get$b();
21595         return bounds(scroll.left + rect.left, scroll.top + rect.top, rect.width, rect.height);
21596       } else {
21597         const bodyPos = absolute$2(SugarElement.fromDom(editor.getBody()));
21598         return bounds(bodyPos.x + rect.left, bodyPos.y + rect.top, rect.width, rect.height);
21599       }
21600     };
21601     const getAnchorElementBounds = (editor, lastElement) => lastElement.filter(elem => inBody(elem) && isHTMLElement(elem)).map(absolute$2).getOrThunk(() => getSelectionBounds(editor));
21602     const getHorizontalBounds = (contentAreaBox, viewportBounds, margin) => {
21603       const x = Math.max(contentAreaBox.x + margin, viewportBounds.x);
21604       const right = Math.min(contentAreaBox.right - margin, viewportBounds.right);
21605       return {
21606         x,
21607         width: right - x
21608       };
21609     };
21610     const getVerticalBounds = (editor, contentAreaBox, viewportBounds, isToolbarLocationTop, toolbarType, margin) => {
21611       const container = SugarElement.fromDom(editor.getContainer());
21612       const header = descendant(container, '.tox-editor-header').getOr(container);
21613       const headerBox = box$1(header);
21614       const isToolbarBelowContentArea = headerBox.y >= contentAreaBox.bottom;
21615       const isToolbarAbove = isToolbarLocationTop && !isToolbarBelowContentArea;
21616       if (editor.inline && isToolbarAbove) {
21617         return {
21618           y: Math.max(headerBox.bottom + margin, viewportBounds.y),
21619           bottom: viewportBounds.bottom
21620         };
21621       }
21622       if (editor.inline && !isToolbarAbove) {
21623         return {
21624           y: viewportBounds.y,
21625           bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
21626         };
21627       }
21628       const containerBounds = toolbarType === 'line' ? box$1(container) : contentAreaBox;
21629       if (isToolbarAbove) {
21630         return {
21631           y: Math.max(headerBox.bottom + margin, viewportBounds.y),
21632           bottom: Math.min(containerBounds.bottom - margin, viewportBounds.bottom)
21633         };
21634       }
21635       return {
21636         y: Math.max(containerBounds.y + margin, viewportBounds.y),
21637         bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
21638       };
21639     };
21640     const getContextToolbarBounds = (editor, sharedBackstage, toolbarType, margin = 0) => {
21641       const viewportBounds = getBounds$3(window);
21642       const contentAreaBox = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
21643       const toolbarOrMenubarEnabled = isMenubarEnabled(editor) || isToolbarEnabled(editor) || isMultipleToolbars(editor);
21644       const {x, width} = getHorizontalBounds(contentAreaBox, viewportBounds, margin);
21645       if (editor.inline && !toolbarOrMenubarEnabled) {
21646         return bounds(x, viewportBounds.y, width, viewportBounds.height);
21647       } else {
21648         const isToolbarTop = sharedBackstage.header.isPositionedAtTop();
21649         const {y, bottom} = getVerticalBounds(editor, contentAreaBox, viewportBounds, isToolbarTop, toolbarType, margin);
21650         return bounds(x, y, width, bottom - y);
21651       }
21652     };
21654     const bubbleSize$1 = 12;
21655     const bubbleAlignments$1 = {
21656       valignCentre: [],
21657       alignCentre: [],
21658       alignLeft: ['tox-pop--align-left'],
21659       alignRight: ['tox-pop--align-right'],
21660       right: ['tox-pop--right'],
21661       left: ['tox-pop--left'],
21662       bottom: ['tox-pop--bottom'],
21663       top: ['tox-pop--top'],
21664       inset: ['tox-pop--inset']
21665     };
21666     const anchorOverrides = {
21667       maxHeightFunction: expandable$1(),
21668       maxWidthFunction: expandable()
21669     };
21670     const isEntireElementSelected = (editor, elem) => {
21671       const rng = editor.selection.getRng();
21672       const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset);
21673       return rng.startContainer === rng.endContainer && rng.startOffset === rng.endOffset - 1 && eq(leaf$1.element, elem);
21674     };
21675     const preservePosition = (elem, position, f) => {
21676       const currentPosition = getRaw(elem, 'position');
21677       set$8(elem, 'position', position);
21678       const result = f(elem);
21679       currentPosition.each(pos => set$8(elem, 'position', pos));
21680       return result;
21681     };
21682     const shouldUseInsetLayouts = position => position === 'node';
21683     const determineInsetLayout = (editor, contextbar, elem, data, bounds) => {
21684       const selectionBounds = getSelectionBounds(editor);
21685       const isSameAnchorElement = data.lastElement().exists(prev => eq(elem, prev));
21686       if (isEntireElementSelected(editor, elem)) {
21687         return isSameAnchorElement ? preserve : north;
21688       } else if (isSameAnchorElement) {
21689         return preservePosition(contextbar, data.getMode(), () => {
21690           const isOverlapping = isVerticalOverlap(selectionBounds, box$1(contextbar));
21691           return isOverlapping && !data.isReposition() ? flip : preserve;
21692         });
21693       } else {
21694         const yBounds = data.getMode() === 'fixed' ? bounds.y + get$b().top : bounds.y;
21695         const contextbarHeight = get$d(contextbar) + bubbleSize$1;
21696         return yBounds + contextbarHeight <= selectionBounds.y ? north : south;
21697       }
21698     };
21699     const getAnchorSpec$2 = (editor, mobile, data, position) => {
21700       const smartInsetLayout = elem => (anchor, element, bubbles, placee, bounds) => {
21701         const layout = determineInsetLayout(editor, placee, elem, data, bounds);
21702         const newAnchor = {
21703           ...anchor,
21704           y: bounds.y,
21705           height: bounds.height
21706         };
21707         return {
21708           ...layout(newAnchor, element, bubbles, placee, bounds),
21709           alwaysFit: true
21710         };
21711       };
21712       const getInsetLayouts = elem => shouldUseInsetLayouts(position) ? [smartInsetLayout(elem)] : [];
21713       const desktopAnchorSpecLayouts = {
21714         onLtr: elem => [
21715           north$2,
21716           south$2,
21717           northeast$2,
21718           southeast$2,
21719           northwest$2,
21720           southwest$2
21721         ].concat(getInsetLayouts(elem)),
21722         onRtl: elem => [
21723           north$2,
21724           south$2,
21725           northwest$2,
21726           southwest$2,
21727           northeast$2,
21728           southeast$2
21729         ].concat(getInsetLayouts(elem))
21730       };
21731       const mobileAnchorSpecLayouts = {
21732         onLtr: elem => [
21733           south$2,
21734           southeast$2,
21735           southwest$2,
21736           northeast$2,
21737           northwest$2,
21738           north$2
21739         ].concat(getInsetLayouts(elem)),
21740         onRtl: elem => [
21741           south$2,
21742           southwest$2,
21743           southeast$2,
21744           northwest$2,
21745           northeast$2,
21746           north$2
21747         ].concat(getInsetLayouts(elem))
21748       };
21749       return mobile ? mobileAnchorSpecLayouts : desktopAnchorSpecLayouts;
21750     };
21751     const getAnchorLayout = (editor, position, isTouch, data) => {
21752       if (position === 'line') {
21753         return {
21754           bubble: nu$5(bubbleSize$1, 0, bubbleAlignments$1),
21755           layouts: {
21756             onLtr: () => [east$2],
21757             onRtl: () => [west$2]
21758           },
21759           overrides: anchorOverrides
21760         };
21761       } else {
21762         return {
21763           bubble: nu$5(0, bubbleSize$1, bubbleAlignments$1, 1 / bubbleSize$1),
21764           layouts: getAnchorSpec$2(editor, isTouch, data, position),
21765           overrides: anchorOverrides
21766         };
21767       }
21768     };
21770     const matchTargetWith = (elem, candidates) => {
21771       const ctxs = filter$2(candidates, toolbarApi => toolbarApi.predicate(elem.dom));
21772       const {pass, fail} = partition$3(ctxs, t => t.type === 'contexttoolbar');
21773       return {
21774         contextToolbars: pass,
21775         contextForms: fail
21776       };
21777     };
21778     const filterByPositionForStartNode = toolbars => {
21779       if (toolbars.length <= 1) {
21780         return toolbars;
21781       } else {
21782         const doesPositionExist = value => exists(toolbars, t => t.position === value);
21783         const filterToolbarsByPosition = value => filter$2(toolbars, t => t.position === value);
21784         const hasSelectionToolbars = doesPositionExist('selection');
21785         const hasNodeToolbars = doesPositionExist('node');
21786         if (hasSelectionToolbars || hasNodeToolbars) {
21787           if (hasNodeToolbars && hasSelectionToolbars) {
21788             const nodeToolbars = filterToolbarsByPosition('node');
21789             const selectionToolbars = map$2(filterToolbarsByPosition('selection'), t => ({
21790               ...t,
21791               position: 'node'
21792             }));
21793             return nodeToolbars.concat(selectionToolbars);
21794           } else {
21795             return hasSelectionToolbars ? filterToolbarsByPosition('selection') : filterToolbarsByPosition('node');
21796           }
21797         } else {
21798           return filterToolbarsByPosition('line');
21799         }
21800       }
21801     };
21802     const filterByPositionForAncestorNode = toolbars => {
21803       if (toolbars.length <= 1) {
21804         return toolbars;
21805       } else {
21806         const findPosition = value => find$5(toolbars, t => t.position === value);
21807         const basePosition = findPosition('selection').orThunk(() => findPosition('node')).orThunk(() => findPosition('line')).map(t => t.position);
21808         return basePosition.fold(() => [], pos => filter$2(toolbars, t => t.position === pos));
21809       }
21810     };
21811     const matchStartNode = (elem, nodeCandidates, editorCandidates) => {
21812       const nodeMatches = matchTargetWith(elem, nodeCandidates);
21813       if (nodeMatches.contextForms.length > 0) {
21814         return Optional.some({
21815           elem,
21816           toolbars: [nodeMatches.contextForms[0]]
21817         });
21818       } else {
21819         const editorMatches = matchTargetWith(elem, editorCandidates);
21820         if (editorMatches.contextForms.length > 0) {
21821           return Optional.some({
21822             elem,
21823             toolbars: [editorMatches.contextForms[0]]
21824           });
21825         } else if (nodeMatches.contextToolbars.length > 0 || editorMatches.contextToolbars.length > 0) {
21826           const toolbars = filterByPositionForStartNode(nodeMatches.contextToolbars.concat(editorMatches.contextToolbars));
21827           return Optional.some({
21828             elem,
21829             toolbars
21830           });
21831         } else {
21832           return Optional.none();
21833         }
21834       }
21835     };
21836     const matchAncestor = (isRoot, startNode, scopes) => {
21837       if (isRoot(startNode)) {
21838         return Optional.none();
21839       } else {
21840         return ancestor$2(startNode, ancestorElem => {
21841           if (isElement$1(ancestorElem)) {
21842             const {contextToolbars, contextForms} = matchTargetWith(ancestorElem, scopes.inNodeScope);
21843             const toolbars = contextForms.length > 0 ? contextForms : filterByPositionForAncestorNode(contextToolbars);
21844             return toolbars.length > 0 ? Optional.some({
21845               elem: ancestorElem,
21846               toolbars
21847             }) : Optional.none();
21848           } else {
21849             return Optional.none();
21850           }
21851         }, isRoot);
21852       }
21853     };
21854     const lookup$1 = (scopes, editor) => {
21855       const rootElem = SugarElement.fromDom(editor.getBody());
21856       const isRoot = elem => eq(elem, rootElem);
21857       const isOutsideRoot = startNode => !isRoot(startNode) && !contains(rootElem, startNode);
21858       const startNode = SugarElement.fromDom(editor.selection.getNode());
21859       if (isOutsideRoot(startNode)) {
21860         return Optional.none();
21861       }
21862       return matchStartNode(startNode, scopes.inNodeScope, scopes.inEditorScope).orThunk(() => matchAncestor(isRoot, startNode, scopes));
21863     };
21865     const categorise = (contextToolbars, navigate) => {
21866       const forms = {};
21867       const inNodeScope = [];
21868       const inEditorScope = [];
21869       const formNavigators = {};
21870       const lookupTable = {};
21871       const registerForm = (key, toolbarSpec) => {
21872         const contextForm = getOrDie(createContextForm(toolbarSpec));
21873         forms[key] = contextForm;
21874         contextForm.launch.map(launch => {
21875           formNavigators['form:' + key + ''] = {
21876             ...toolbarSpec.launch,
21877             type: launch.type === 'contextformtogglebutton' ? 'togglebutton' : 'button',
21878             onAction: () => {
21879               navigate(contextForm);
21880             }
21881           };
21882         });
21883         if (contextForm.scope === 'editor') {
21884           inEditorScope.push(contextForm);
21885         } else {
21886           inNodeScope.push(contextForm);
21887         }
21888         lookupTable[key] = contextForm;
21889       };
21890       const registerToolbar = (key, toolbarSpec) => {
21891         createContextToolbar(toolbarSpec).each(contextToolbar => {
21892           if (toolbarSpec.scope === 'editor') {
21893             inEditorScope.push(contextToolbar);
21894           } else {
21895             inNodeScope.push(contextToolbar);
21896           }
21897           lookupTable[key] = contextToolbar;
21898         });
21899       };
21900       const keys$1 = keys(contextToolbars);
21901       each$1(keys$1, key => {
21902         const toolbarApi = contextToolbars[key];
21903         if (toolbarApi.type === 'contextform') {
21904           registerForm(key, toolbarApi);
21905         } else if (toolbarApi.type === 'contexttoolbar') {
21906           registerToolbar(key, toolbarApi);
21907         }
21908       });
21909       return {
21910         forms,
21911         inNodeScope,
21912         inEditorScope,
21913         lookupTable,
21914         formNavigators
21915       };
21916     };
21918     const forwardSlideEvent = generate$6('forward-slide');
21919     const backSlideEvent = generate$6('backward-slide');
21920     const changeSlideEvent = generate$6('change-slide-event');
21921     const resizingClass = 'tox-pop--resizing';
21922     const renderContextToolbar = spec => {
21923       const stack = Cell([]);
21924       return InlineView.sketch({
21925         dom: {
21926           tag: 'div',
21927           classes: ['tox-pop']
21928         },
21929         fireDismissalEventInstead: { event: 'doNotDismissYet' },
21930         onShow: comp => {
21931           stack.set([]);
21932           InlineView.getContent(comp).each(c => {
21933             remove$6(c.element, 'visibility');
21934           });
21935           remove$2(comp.element, resizingClass);
21936           remove$6(comp.element, 'width');
21937         },
21938         inlineBehaviours: derive$1([
21939           config('context-toolbar-events', [
21940             runOnSource(transitionend(), (comp, se) => {
21941               if (se.event.raw.propertyName === 'width') {
21942                 remove$2(comp.element, resizingClass);
21943                 remove$6(comp.element, 'width');
21944               }
21945             }),
21946             run$1(changeSlideEvent, (comp, se) => {
21947               const elem = comp.element;
21948               remove$6(elem, 'width');
21949               const currentWidth = get$c(elem);
21950               InlineView.setContent(comp, se.event.contents);
21951               add$2(elem, resizingClass);
21952               const newWidth = get$c(elem);
21953               set$8(elem, 'width', currentWidth + 'px');
21954               InlineView.getContent(comp).each(newContents => {
21955                 se.event.focus.bind(f => {
21956                   focus$3(f);
21957                   return search(elem);
21958                 }).orThunk(() => {
21959                   Keying.focusIn(newContents);
21960                   return active$1(getRootNode(elem));
21961                 });
21962               });
21963               setTimeout(() => {
21964                 set$8(comp.element, 'width', newWidth + 'px');
21965               }, 0);
21966             }),
21967             run$1(forwardSlideEvent, (comp, se) => {
21968               InlineView.getContent(comp).each(oldContents => {
21969                 stack.set(stack.get().concat([{
21970                     bar: oldContents,
21971                     focus: active$1(getRootNode(comp.element))
21972                   }]));
21973               });
21974               emitWith(comp, changeSlideEvent, {
21975                 contents: se.event.forwardContents,
21976                 focus: Optional.none()
21977               });
21978             }),
21979             run$1(backSlideEvent, (comp, _se) => {
21980               last$1(stack.get()).each(last => {
21981                 stack.set(stack.get().slice(0, stack.get().length - 1));
21982                 emitWith(comp, changeSlideEvent, {
21983                   contents: premade(last.bar),
21984                   focus: last.focus
21985                 });
21986               });
21987             })
21988           ]),
21989           Keying.config({
21990             mode: 'special',
21991             onEscape: comp => last$1(stack.get()).fold(() => spec.onEscape(), _ => {
21992               emit(comp, backSlideEvent);
21993               return Optional.some(true);
21994             })
21995           })
21996         ]),
21997         lazySink: () => Result.value(spec.sink)
21998       });
21999     };
22001     const transitionClass = 'tox-pop--transition';
22002     const register$9 = (editor, registryContextToolbars, sink, extras) => {
22003       const backstage = extras.backstage;
22004       const sharedBackstage = backstage.shared;
22005       const isTouch = detect$1().deviceType.isTouch;
22006       const lastElement = value$2();
22007       const lastTrigger = value$2();
22008       const lastContextPosition = value$2();
22009       const contextbar = build$1(renderContextToolbar({
22010         sink,
22011         onEscape: () => {
22012           editor.focus();
22013           return Optional.some(true);
22014         }
22015       }));
22016       const getBounds = () => {
22017         const position = lastContextPosition.get().getOr('node');
22018         const margin = shouldUseInsetLayouts(position) ? 1 : 0;
22019         return getContextToolbarBounds(editor, sharedBackstage, position, margin);
22020       };
22021       const canLaunchToolbar = () => {
22022         return !editor.removed && !(isTouch() && backstage.isContextMenuOpen());
22023       };
22024       const isSameLaunchElement = elem => is$1(lift2(elem, lastElement.get(), eq), true);
22025       const shouldContextToolbarHide = () => {
22026         if (!canLaunchToolbar()) {
22027           return true;
22028         } else {
22029           const contextToolbarBounds = getBounds();
22030           const anchorBounds = is$1(lastContextPosition.get(), 'node') ? getAnchorElementBounds(editor, lastElement.get()) : getSelectionBounds(editor);
22031           return contextToolbarBounds.height <= 0 || !isVerticalOverlap(anchorBounds, contextToolbarBounds);
22032         }
22033       };
22034       const close = () => {
22035         lastElement.clear();
22036         lastTrigger.clear();
22037         lastContextPosition.clear();
22038         InlineView.hide(contextbar);
22039       };
22040       const hideOrRepositionIfNecessary = () => {
22041         if (InlineView.isOpen(contextbar)) {
22042           const contextBarEle = contextbar.element;
22043           remove$6(contextBarEle, 'display');
22044           if (shouldContextToolbarHide()) {
22045             set$8(contextBarEle, 'display', 'none');
22046           } else {
22047             lastTrigger.set(0);
22048             InlineView.reposition(contextbar);
22049           }
22050         }
22051       };
22052       const wrapInPopDialog = toolbarSpec => ({
22053         dom: {
22054           tag: 'div',
22055           classes: ['tox-pop__dialog']
22056         },
22057         components: [toolbarSpec],
22058         behaviours: derive$1([
22059           Keying.config({ mode: 'acyclic' }),
22060           config('pop-dialog-wrap-events', [
22061             runOnAttached(comp => {
22062               editor.shortcuts.add('ctrl+F9', 'focus statusbar', () => Keying.focusIn(comp));
22063             }),
22064             runOnDetached(_comp => {
22065               editor.shortcuts.remove('ctrl+F9');
22066             })
22067           ])
22068         ])
22069       });
22070       const getScopes = cached(() => categorise(registryContextToolbars, toolbarApi => {
22071         const alloySpec = buildToolbar([toolbarApi]);
22072         emitWith(contextbar, forwardSlideEvent, { forwardContents: wrapInPopDialog(alloySpec) });
22073       }));
22074       const buildContextToolbarGroups = (allButtons, ctx) => identifyButtons(editor, {
22075         buttons: allButtons,
22076         toolbar: ctx.items,
22077         allowToolbarGroups: false
22078       }, extras.backstage, Optional.some(['form:']));
22079       const buildContextFormGroups = (ctx, providers) => ContextForm.buildInitGroups(ctx, providers);
22080       const buildToolbar = toolbars => {
22081         const {buttons} = editor.ui.registry.getAll();
22082         const scopes = getScopes();
22083         const allButtons = {
22084           ...buttons,
22085           ...scopes.formNavigators
22086         };
22087         const toolbarType = getToolbarMode(editor) === ToolbarMode$1.scrolling ? ToolbarMode$1.scrolling : ToolbarMode$1.default;
22088         const initGroups = flatten(map$2(toolbars, ctx => ctx.type === 'contexttoolbar' ? buildContextToolbarGroups(allButtons, ctx) : buildContextFormGroups(ctx, sharedBackstage.providers)));
22089         return renderToolbar({
22090           type: toolbarType,
22091           uid: generate$6('context-toolbar'),
22092           initGroups,
22093           onEscape: Optional.none,
22094           cyclicKeying: true,
22095           providers: sharedBackstage.providers
22096         });
22097       };
22098       const getAnchor = (position, element) => {
22099         const anchorage = position === 'node' ? sharedBackstage.anchors.node(element) : sharedBackstage.anchors.cursor();
22100         const anchorLayout = getAnchorLayout(editor, position, isTouch(), {
22101           lastElement: lastElement.get,
22102           isReposition: () => is$1(lastTrigger.get(), 0),
22103           getMode: () => Positioning.getMode(sink)
22104         });
22105         return deepMerge(anchorage, anchorLayout);
22106       };
22107       const launchContext = (toolbarApi, elem) => {
22108         launchContextToolbar.cancel();
22109         if (!canLaunchToolbar()) {
22110           return;
22111         }
22112         const toolbarSpec = buildToolbar(toolbarApi);
22113         const position = toolbarApi[0].position;
22114         const anchor = getAnchor(position, elem);
22115         lastContextPosition.set(position);
22116         lastTrigger.set(1);
22117         const contextBarEle = contextbar.element;
22118         remove$6(contextBarEle, 'display');
22119         if (!isSameLaunchElement(elem)) {
22120           remove$2(contextBarEle, transitionClass);
22121           Positioning.reset(sink, contextbar);
22122         }
22123         InlineView.showWithinBounds(contextbar, wrapInPopDialog(toolbarSpec), {
22124           anchor,
22125           transition: {
22126             classes: [transitionClass],
22127             mode: 'placement'
22128           }
22129         }, () => Optional.some(getBounds()));
22130         elem.fold(lastElement.clear, lastElement.set);
22131         if (shouldContextToolbarHide()) {
22132           set$8(contextBarEle, 'display', 'none');
22133         }
22134       };
22135       const launchContextToolbar = last(() => {
22136         if (!editor.hasFocus() || editor.removed) {
22137           return;
22138         }
22139         if (has(contextbar.element, transitionClass)) {
22140           launchContextToolbar.throttle();
22141         } else {
22142           const scopes = getScopes();
22143           lookup$1(scopes, editor).fold(close, info => {
22144             launchContext(info.toolbars, Optional.some(info.elem));
22145           });
22146         }
22147       }, 17);
22148       editor.on('init', () => {
22149         editor.on('remove', close);
22150         editor.on('ScrollContent ScrollWindow ObjectResized ResizeEditor longpress', hideOrRepositionIfNecessary);
22151         editor.on('click keyup focus SetContent', launchContextToolbar.throttle);
22152         editor.on(hideContextToolbarEvent, close);
22153         editor.on(showContextToolbarEvent, e => {
22154           const scopes = getScopes();
22155           get$g(scopes.lookupTable, e.toolbarKey).each(ctx => {
22156             launchContext([ctx], someIf(e.target !== editor, e.target));
22157             InlineView.getContent(contextbar).each(Keying.focusIn);
22158           });
22159         });
22160         editor.on('focusout', _e => {
22161           global$9.setEditorTimeout(editor, () => {
22162             if (search(sink.element).isNone() && search(contextbar.element).isNone()) {
22163               close();
22164             }
22165           }, 0);
22166         });
22167         editor.on('SwitchMode', () => {
22168           if (editor.mode.isReadOnly()) {
22169             close();
22170           }
22171         });
22172         editor.on('AfterProgressState', event => {
22173           if (event.state) {
22174             close();
22175           } else if (editor.hasFocus()) {
22176             launchContextToolbar.throttle();
22177           }
22178         });
22179         editor.on('NodeChange', _e => {
22180           search(contextbar.element).fold(launchContextToolbar.throttle, noop);
22181         });
22182       });
22183     };
22185     const register$8 = editor => {
22186       const alignToolbarButtons = [
22187         {
22188           name: 'alignleft',
22189           text: 'Align left',
22190           cmd: 'JustifyLeft',
22191           icon: 'align-left'
22192         },
22193         {
22194           name: 'aligncenter',
22195           text: 'Align center',
22196           cmd: 'JustifyCenter',
22197           icon: 'align-center'
22198         },
22199         {
22200           name: 'alignright',
22201           text: 'Align right',
22202           cmd: 'JustifyRight',
22203           icon: 'align-right'
22204         },
22205         {
22206           name: 'alignjustify',
22207           text: 'Justify',
22208           cmd: 'JustifyFull',
22209           icon: 'align-justify'
22210         }
22211       ];
22212       each$1(alignToolbarButtons, item => {
22213         editor.ui.registry.addToggleButton(item.name, {
22214           tooltip: item.text,
22215           icon: item.icon,
22216           onAction: onActionExecCommand(editor, item.cmd),
22217           onSetup: onSetupFormatToggle(editor, item.name)
22218         });
22219       });
22220       editor.ui.registry.addButton('alignnone', {
22221         tooltip: 'No alignment',
22222         icon: 'align-none',
22223         onAction: onActionExecCommand(editor, 'JustifyNone')
22224       });
22225     };
22227     const units = {
22228       unsupportedLength: [
22229         'em',
22230         'ex',
22231         'cap',
22232         'ch',
22233         'ic',
22234         'rem',
22235         'lh',
22236         'rlh',
22237         'vw',
22238         'vh',
22239         'vi',
22240         'vb',
22241         'vmin',
22242         'vmax',
22243         'cm',
22244         'mm',
22245         'Q',
22246         'in',
22247         'pc',
22248         'pt',
22249         'px'
22250       ],
22251       fixed: [
22252         'px',
22253         'pt'
22254       ],
22255       relative: ['%'],
22256       empty: ['']
22257     };
22258     const pattern = (() => {
22259       const decimalDigits = '[0-9]+';
22260       const signedInteger = '[+-]?' + decimalDigits;
22261       const exponentPart = '[eE]' + signedInteger;
22262       const dot = '\\.';
22263       const opt = input => `(?:${ input })?`;
22264       const unsignedDecimalLiteral = [
22265         'Infinity',
22266         decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
22267         dot + decimalDigits + opt(exponentPart),
22268         decimalDigits + opt(exponentPart)
22269       ].join('|');
22270       const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
22271       return new RegExp(`^(${ float })(.*)$`);
22272     })();
22273     const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
22274     const parse = (input, accepted) => {
22275       const match = Optional.from(pattern.exec(input));
22276       return match.bind(array => {
22277         const value = Number(array[1]);
22278         const unitRaw = array[2];
22279         if (isUnit(unitRaw, accepted)) {
22280           return Optional.some({
22281             value,
22282             unit: unitRaw
22283           });
22284         } else {
22285           return Optional.none();
22286         }
22287       });
22288     };
22289     const normalise = (input, accepted) => parse(input, accepted).map(({value, unit}) => value + unit);
22291     const registerController = (editor, spec) => {
22292       const getMenuItems = () => {
22293         const options = spec.getOptions(editor);
22294         const initial = spec.getCurrent(editor).map(spec.hash);
22295         const current = value$2();
22296         return map$2(options, value => ({
22297           type: 'togglemenuitem',
22298           text: spec.display(value),
22299           onSetup: api => {
22300             const setActive = active => {
22301               if (active) {
22302                 current.on(oldApi => oldApi.setActive(false));
22303                 current.set(api);
22304               }
22305               api.setActive(active);
22306             };
22307             setActive(is$1(initial, spec.hash(value)));
22308             const unbindWatcher = spec.watcher(editor, value, setActive);
22309             return () => {
22310               current.clear();
22311               unbindWatcher();
22312             };
22313           },
22314           onAction: () => spec.setCurrent(editor, value)
22315         }));
22316       };
22317       editor.ui.registry.addMenuButton(spec.name, {
22318         tooltip: spec.text,
22319         icon: spec.icon,
22320         fetch: callback => callback(getMenuItems()),
22321         onSetup: spec.onToolbarSetup
22322       });
22323       editor.ui.registry.addNestedMenuItem(spec.name, {
22324         type: 'nestedmenuitem',
22325         text: spec.text,
22326         getSubmenuItems: getMenuItems,
22327         onSetup: spec.onMenuSetup
22328       });
22329     };
22330     const lineHeightSpec = {
22331       name: 'lineheight',
22332       text: 'Line height',
22333       icon: 'line-height',
22334       getOptions: getLineHeightFormats,
22335       hash: input => normalise(input, [
22336         'fixed',
22337         'relative',
22338         'empty'
22339       ]).getOr(input),
22340       display: identity,
22341       watcher: (editor, value, callback) => editor.formatter.formatChanged('lineheight', callback, false, { value }).unbind,
22342       getCurrent: editor => Optional.from(editor.queryCommandValue('LineHeight')),
22343       setCurrent: (editor, value) => editor.execCommand('LineHeight', false, value)
22344     };
22345     const languageSpec = editor => {
22346       const settingsOpt = Optional.from(getContentLanguages(editor));
22347       return settingsOpt.map(settings => ({
22348         name: 'language',
22349         text: 'Language',
22350         icon: 'language',
22351         getOptions: constant$1(settings),
22352         hash: input => isUndefined(input.customCode) ? input.code : `${ input.code }/${ input.customCode }`,
22353         display: input => input.title,
22354         watcher: (editor, value, callback) => editor.formatter.formatChanged('lang', callback, false, {
22355           value: value.code,
22356           customValue: value.customCode ?? null
22357         }).unbind,
22358         getCurrent: editor => {
22359           const node = SugarElement.fromDom(editor.selection.getNode());
22360           return closest$4(node, n => Optional.some(n).filter(isElement$1).bind(ele => {
22361             const codeOpt = getOpt(ele, 'lang');
22362             return codeOpt.map(code => {
22363               const customCode = getOpt(ele, 'data-mce-lang').getOrUndefined();
22364               return {
22365                 code,
22366                 customCode,
22367                 title: ''
22368               };
22369             });
22370           }));
22371         },
22372         setCurrent: (editor, lang) => editor.execCommand('Lang', false, lang),
22373         onToolbarSetup: api => {
22374           const unbinder = unbindable();
22375           api.setActive(editor.formatter.match('lang', {}, undefined, true));
22376           unbinder.set(editor.formatter.formatChanged('lang', api.setActive, true));
22377           return unbinder.clear;
22378         }
22379       }));
22380     };
22381     const register$7 = editor => {
22382       registerController(editor, lineHeightSpec);
22383       languageSpec(editor).each(spec => registerController(editor, spec));
22384     };
22386     const register$6 = (editor, backstage) => {
22387       createAlignMenu(editor, backstage);
22388       createFontFamilyMenu(editor, backstage);
22389       createStylesMenu(editor, backstage);
22390       createBlocksMenu(editor, backstage);
22391       createFontSizeMenu(editor, backstage);
22392     };
22394     const onSetupOutdentState = editor => onSetupEvent(editor, 'NodeChange', api => {
22395       api.setEnabled(editor.queryCommandState('outdent'));
22396     });
22397     const registerButtons$2 = editor => {
22398       editor.ui.registry.addButton('outdent', {
22399         tooltip: 'Decrease indent',
22400         icon: 'outdent',
22401         onSetup: onSetupOutdentState(editor),
22402         onAction: onActionExecCommand(editor, 'outdent')
22403       });
22404       editor.ui.registry.addButton('indent', {
22405         tooltip: 'Increase indent',
22406         icon: 'indent',
22407         onAction: onActionExecCommand(editor, 'indent')
22408       });
22409     };
22410     const register$5 = editor => {
22411       registerButtons$2(editor);
22412     };
22414     const makeSetupHandler = (editor, pasteAsText) => api => {
22415       api.setActive(pasteAsText.get());
22416       const pastePlainTextToggleHandler = e => {
22417         pasteAsText.set(e.state);
22418         api.setActive(e.state);
22419       };
22420       editor.on('PastePlainTextToggle', pastePlainTextToggleHandler);
22421       return () => editor.off('PastePlainTextToggle', pastePlainTextToggleHandler);
22422     };
22423     const register$4 = editor => {
22424       const pasteAsText = Cell(getPasteAsText(editor));
22425       const onAction = () => editor.execCommand('mceTogglePlainTextPaste');
22426       editor.ui.registry.addToggleButton('pastetext', {
22427         active: false,
22428         icon: 'paste-text',
22429         tooltip: 'Paste as text',
22430         onAction,
22431         onSetup: makeSetupHandler(editor, pasteAsText)
22432       });
22433       editor.ui.registry.addToggleMenuItem('pastetext', {
22434         text: 'Paste as text',
22435         icon: 'paste-text',
22436         onAction,
22437         onSetup: makeSetupHandler(editor, pasteAsText)
22438       });
22439     };
22441     const onActionToggleFormat = (editor, fmt) => () => {
22442       editor.execCommand('mceToggleFormat', false, fmt);
22443     };
22444     const registerFormatButtons = editor => {
22445       global$1.each([
22446         {
22447           name: 'bold',
22448           text: 'Bold',
22449           icon: 'bold'
22450         },
22451         {
22452           name: 'italic',
22453           text: 'Italic',
22454           icon: 'italic'
22455         },
22456         {
22457           name: 'underline',
22458           text: 'Underline',
22459           icon: 'underline'
22460         },
22461         {
22462           name: 'strikethrough',
22463           text: 'Strikethrough',
22464           icon: 'strike-through'
22465         },
22466         {
22467           name: 'subscript',
22468           text: 'Subscript',
22469           icon: 'subscript'
22470         },
22471         {
22472           name: 'superscript',
22473           text: 'Superscript',
22474           icon: 'superscript'
22475         }
22476       ], (btn, _idx) => {
22477         editor.ui.registry.addToggleButton(btn.name, {
22478           tooltip: btn.text,
22479           icon: btn.icon,
22480           onSetup: onSetupFormatToggle(editor, btn.name),
22481           onAction: onActionToggleFormat(editor, btn.name)
22482         });
22483       });
22484       for (let i = 1; i <= 6; i++) {
22485         const name = 'h' + i;
22486         editor.ui.registry.addToggleButton(name, {
22487           text: name.toUpperCase(),
22488           tooltip: 'Heading ' + i,
22489           onSetup: onSetupFormatToggle(editor, name),
22490           onAction: onActionToggleFormat(editor, name)
22491         });
22492       }
22493     };
22494     const registerCommandButtons = editor => {
22495       global$1.each([
22496         {
22497           name: 'cut',
22498           text: 'Cut',
22499           action: 'Cut',
22500           icon: 'cut'
22501         },
22502         {
22503           name: 'copy',
22504           text: 'Copy',
22505           action: 'Copy',
22506           icon: 'copy'
22507         },
22508         {
22509           name: 'paste',
22510           text: 'Paste',
22511           action: 'Paste',
22512           icon: 'paste'
22513         },
22514         {
22515           name: 'help',
22516           text: 'Help',
22517           action: 'mceHelp',
22518           icon: 'help'
22519         },
22520         {
22521           name: 'selectall',
22522           text: 'Select all',
22523           action: 'SelectAll',
22524           icon: 'select-all'
22525         },
22526         {
22527           name: 'newdocument',
22528           text: 'New document',
22529           action: 'mceNewDocument',
22530           icon: 'new-document'
22531         },
22532         {
22533           name: 'removeformat',
22534           text: 'Clear formatting',
22535           action: 'RemoveFormat',
22536           icon: 'remove-formatting'
22537         },
22538         {
22539           name: 'remove',
22540           text: 'Remove',
22541           action: 'Delete',
22542           icon: 'remove'
22543         },
22544         {
22545           name: 'print',
22546           text: 'Print',
22547           action: 'mcePrint',
22548           icon: 'print'
22549         },
22550         {
22551           name: 'hr',
22552           text: 'Horizontal line',
22553           action: 'InsertHorizontalRule',
22554           icon: 'horizontal-rule'
22555         }
22556       ], btn => {
22557         editor.ui.registry.addButton(btn.name, {
22558           tooltip: btn.text,
22559           icon: btn.icon,
22560           onAction: onActionExecCommand(editor, btn.action)
22561         });
22562       });
22563     };
22564     const registerCommandToggleButtons = editor => {
22565       global$1.each([{
22566           name: 'blockquote',
22567           text: 'Blockquote',
22568           action: 'mceBlockQuote',
22569           icon: 'quote'
22570         }], btn => {
22571         editor.ui.registry.addToggleButton(btn.name, {
22572           tooltip: btn.text,
22573           icon: btn.icon,
22574           onAction: onActionExecCommand(editor, btn.action),
22575           onSetup: onSetupFormatToggle(editor, btn.name)
22576         });
22577       });
22578     };
22579     const registerButtons$1 = editor => {
22580       registerFormatButtons(editor);
22581       registerCommandButtons(editor);
22582       registerCommandToggleButtons(editor);
22583     };
22584     const registerMenuItems$2 = editor => {
22585       global$1.each([
22586         {
22587           name: 'bold',
22588           text: 'Bold',
22589           action: 'Bold',
22590           icon: 'bold',
22591           shortcut: 'Meta+B'
22592         },
22593         {
22594           name: 'italic',
22595           text: 'Italic',
22596           action: 'Italic',
22597           icon: 'italic',
22598           shortcut: 'Meta+I'
22599         },
22600         {
22601           name: 'underline',
22602           text: 'Underline',
22603           action: 'Underline',
22604           icon: 'underline',
22605           shortcut: 'Meta+U'
22606         },
22607         {
22608           name: 'strikethrough',
22609           text: 'Strikethrough',
22610           action: 'Strikethrough',
22611           icon: 'strike-through'
22612         },
22613         {
22614           name: 'subscript',
22615           text: 'Subscript',
22616           action: 'Subscript',
22617           icon: 'subscript'
22618         },
22619         {
22620           name: 'superscript',
22621           text: 'Superscript',
22622           action: 'Superscript',
22623           icon: 'superscript'
22624         },
22625         {
22626           name: 'removeformat',
22627           text: 'Clear formatting',
22628           action: 'RemoveFormat',
22629           icon: 'remove-formatting'
22630         },
22631         {
22632           name: 'newdocument',
22633           text: 'New document',
22634           action: 'mceNewDocument',
22635           icon: 'new-document'
22636         },
22637         {
22638           name: 'cut',
22639           text: 'Cut',
22640           action: 'Cut',
22641           icon: 'cut',
22642           shortcut: 'Meta+X'
22643         },
22644         {
22645           name: 'copy',
22646           text: 'Copy',
22647           action: 'Copy',
22648           icon: 'copy',
22649           shortcut: 'Meta+C'
22650         },
22651         {
22652           name: 'paste',
22653           text: 'Paste',
22654           action: 'Paste',
22655           icon: 'paste',
22656           shortcut: 'Meta+V'
22657         },
22658         {
22659           name: 'selectall',
22660           text: 'Select all',
22661           action: 'SelectAll',
22662           icon: 'select-all',
22663           shortcut: 'Meta+A'
22664         },
22665         {
22666           name: 'print',
22667           text: 'Print...',
22668           action: 'mcePrint',
22669           icon: 'print',
22670           shortcut: 'Meta+P'
22671         },
22672         {
22673           name: 'hr',
22674           text: 'Horizontal line',
22675           action: 'InsertHorizontalRule',
22676           icon: 'horizontal-rule'
22677         }
22678       ], menuitem => {
22679         editor.ui.registry.addMenuItem(menuitem.name, {
22680           text: menuitem.text,
22681           icon: menuitem.icon,
22682           shortcut: menuitem.shortcut,
22683           onAction: onActionExecCommand(editor, menuitem.action)
22684         });
22685       });
22686       editor.ui.registry.addMenuItem('codeformat', {
22687         text: 'Code',
22688         icon: 'sourcecode',
22689         onAction: onActionToggleFormat(editor, 'code')
22690       });
22691     };
22692     const register$3 = editor => {
22693       registerButtons$1(editor);
22694       registerMenuItems$2(editor);
22695     };
22697     const onSetupUndoRedoState = (editor, type) => onSetupEvent(editor, 'Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', api => {
22698       api.setEnabled(!editor.mode.isReadOnly() && editor.undoManager[type]());
22699     });
22700     const registerMenuItems$1 = editor => {
22701       editor.ui.registry.addMenuItem('undo', {
22702         text: 'Undo',
22703         icon: 'undo',
22704         shortcut: 'Meta+Z',
22705         onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
22706         onAction: onActionExecCommand(editor, 'undo')
22707       });
22708       editor.ui.registry.addMenuItem('redo', {
22709         text: 'Redo',
22710         icon: 'redo',
22711         shortcut: 'Meta+Y',
22712         onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
22713         onAction: onActionExecCommand(editor, 'redo')
22714       });
22715     };
22716     const registerButtons = editor => {
22717       editor.ui.registry.addButton('undo', {
22718         tooltip: 'Undo',
22719         icon: 'undo',
22720         enabled: false,
22721         onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
22722         onAction: onActionExecCommand(editor, 'undo')
22723       });
22724       editor.ui.registry.addButton('redo', {
22725         tooltip: 'Redo',
22726         icon: 'redo',
22727         enabled: false,
22728         onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
22729         onAction: onActionExecCommand(editor, 'redo')
22730       });
22731     };
22732     const register$2 = editor => {
22733       registerMenuItems$1(editor);
22734       registerButtons(editor);
22735     };
22737     const onSetupVisualAidState = editor => onSetupEvent(editor, 'VisualAid', api => {
22738       api.setActive(editor.hasVisual);
22739     });
22740     const registerMenuItems = editor => {
22741       editor.ui.registry.addToggleMenuItem('visualaid', {
22742         text: 'Visual aids',
22743         onSetup: onSetupVisualAidState(editor),
22744         onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
22745       });
22746     };
22747     const registerToolbarButton = editor => {
22748       editor.ui.registry.addButton('visualaid', {
22749         tooltip: 'Visual aids',
22750         text: 'Visual aids',
22751         onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
22752       });
22753     };
22754     const register$1 = editor => {
22755       registerToolbarButton(editor);
22756       registerMenuItems(editor);
22757     };
22759     const setup$6 = (editor, backstage) => {
22760       register$8(editor);
22761       register$3(editor);
22762       register$6(editor, backstage);
22763       register$2(editor);
22764       register$c(editor);
22765       register$1(editor);
22766       register$5(editor);
22767       register$7(editor);
22768       register$4(editor);
22769     };
22771     const patchPipeConfig = config => isString(config) ? config.split(/[ ,]/) : config;
22772     const option = name => editor => editor.options.get(name);
22773     const register = editor => {
22774       const registerOption = editor.options.register;
22775       registerOption('contextmenu_avoid_overlap', {
22776         processor: 'string',
22777         default: ''
22778       });
22779       registerOption('contextmenu_never_use_native', {
22780         processor: 'boolean',
22781         default: false
22782       });
22783       registerOption('contextmenu', {
22784         processor: value => {
22785           if (value === false) {
22786             return {
22787               value: [],
22788               valid: true
22789             };
22790           } else if (isString(value) || isArrayOf(value, isString)) {
22791             return {
22792               value: patchPipeConfig(value),
22793               valid: true
22794             };
22795           } else {
22796             return {
22797               valid: false,
22798               message: 'Must be false or a string.'
22799             };
22800           }
22801         },
22802         default: 'link linkchecker image editimage table spellchecker configurepermanentpen'
22803       });
22804     };
22805     const shouldNeverUseNative = option('contextmenu_never_use_native');
22806     const getAvoidOverlapSelector = option('contextmenu_avoid_overlap');
22807     const isContextMenuDisabled = editor => getContextMenu(editor).length === 0;
22808     const getContextMenu = editor => {
22809       const contextMenus = editor.ui.registry.getAll().contextMenus;
22810       const contextMenu = editor.options.get('contextmenu');
22811       if (editor.options.isSet('contextmenu')) {
22812         return contextMenu;
22813       } else {
22814         return filter$2(contextMenu, item => has$2(contextMenus, item));
22815       }
22816     };
22818     const nu = (x, y) => ({
22819       type: 'makeshift',
22820       x,
22821       y
22822     });
22823     const transpose = (pos, dx, dy) => {
22824       return nu(pos.x + dx, pos.y + dy);
22825     };
22826     const isTouchEvent$1 = e => e.type === 'longpress' || e.type.indexOf('touch') === 0;
22827     const fromPageXY = e => {
22828       if (isTouchEvent$1(e)) {
22829         const touch = e.touches[0];
22830         return nu(touch.pageX, touch.pageY);
22831       } else {
22832         return nu(e.pageX, e.pageY);
22833       }
22834     };
22835     const fromClientXY = e => {
22836       if (isTouchEvent$1(e)) {
22837         const touch = e.touches[0];
22838         return nu(touch.clientX, touch.clientY);
22839       } else {
22840         return nu(e.clientX, e.clientY);
22841       }
22842     };
22843     const transposeContentAreaContainer = (element, pos) => {
22844       const containerPos = global$7.DOM.getPos(element);
22845       return transpose(pos, containerPos.x, containerPos.y);
22846     };
22847     const getPointAnchor = (editor, e) => {
22848       if (e.type === 'contextmenu' || e.type === 'longpress') {
22849         if (editor.inline) {
22850           return fromPageXY(e);
22851         } else {
22852           return transposeContentAreaContainer(editor.getContentAreaContainer(), fromClientXY(e));
22853         }
22854       } else {
22855         return getSelectionAnchor(editor);
22856       }
22857     };
22858     const getSelectionAnchor = editor => {
22859       return {
22860         type: 'selection',
22861         root: SugarElement.fromDom(editor.selection.getNode())
22862       };
22863     };
22864     const getNodeAnchor = editor => ({
22865       type: 'node',
22866       node: Optional.some(SugarElement.fromDom(editor.selection.getNode())),
22867       root: SugarElement.fromDom(editor.getBody())
22868     });
22869     const getAnchorSpec$1 = (editor, e, anchorType) => {
22870       switch (anchorType) {
22871       case 'node':
22872         return getNodeAnchor(editor);
22873       case 'point':
22874         return getPointAnchor(editor, e);
22875       case 'selection':
22876         return getSelectionAnchor(editor);
22877       }
22878     };
22880     const initAndShow$1 = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
22881       const items = buildMenu();
22882       const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
22883       build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
22884         isHorizontalMenu: false,
22885         search: Optional.none()
22886       }).map(menuData => {
22887         e.preventDefault();
22888         InlineView.showMenuAt(contextmenu, { anchor: anchorSpec }, {
22889           menu: { markers: markers('normal') },
22890           data: menuData
22891         });
22892       });
22893     };
22895     const layouts = {
22896       onLtr: () => [
22897         south$2,
22898         southeast$2,
22899         southwest$2,
22900         northeast$2,
22901         northwest$2,
22902         north$2,
22903         north,
22904         south,
22905         northeast,
22906         southeast,
22907         northwest,
22908         southwest
22909       ],
22910       onRtl: () => [
22911         south$2,
22912         southwest$2,
22913         southeast$2,
22914         northwest$2,
22915         northeast$2,
22916         north$2,
22917         north,
22918         south,
22919         northwest,
22920         southwest,
22921         northeast,
22922         southeast
22923       ]
22924     };
22925     const bubbleSize = 12;
22926     const bubbleAlignments = {
22927       valignCentre: [],
22928       alignCentre: [],
22929       alignLeft: ['tox-pop--align-left'],
22930       alignRight: ['tox-pop--align-right'],
22931       right: ['tox-pop--right'],
22932       left: ['tox-pop--left'],
22933       bottom: ['tox-pop--bottom'],
22934       top: ['tox-pop--top']
22935     };
22936     const isTouchWithinSelection = (editor, e) => {
22937       const selection = editor.selection;
22938       if (selection.isCollapsed() || e.touches.length < 1) {
22939         return false;
22940       } else {
22941         const touch = e.touches[0];
22942         const rng = selection.getRng();
22943         const rngRectOpt = getFirstRect(editor.getWin(), SimSelection.domRange(rng));
22944         return rngRectOpt.exists(rngRect => rngRect.left <= touch.clientX && rngRect.right >= touch.clientX && rngRect.top <= touch.clientY && rngRect.bottom >= touch.clientY);
22945       }
22946     };
22947     const setupiOSOverrides = editor => {
22948       const originalSelection = editor.selection.getRng();
22949       const selectionReset = () => {
22950         global$9.setEditorTimeout(editor, () => {
22951           editor.selection.setRng(originalSelection);
22952         }, 10);
22953         unbindEventListeners();
22954       };
22955       editor.once('touchend', selectionReset);
22956       const preventMousedown = e => {
22957         e.preventDefault();
22958         e.stopImmediatePropagation();
22959       };
22960       editor.on('mousedown', preventMousedown, true);
22961       const clearSelectionReset = () => unbindEventListeners();
22962       editor.once('longpresscancel', clearSelectionReset);
22963       const unbindEventListeners = () => {
22964         editor.off('touchend', selectionReset);
22965         editor.off('longpresscancel', clearSelectionReset);
22966         editor.off('mousedown', preventMousedown);
22967       };
22968     };
22969     const getAnchorSpec = (editor, e, anchorType) => {
22970       const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
22971       const bubbleYOffset = anchorType === 'point' ? bubbleSize : 0;
22972       return {
22973         bubble: nu$5(0, bubbleYOffset, bubbleAlignments),
22974         layouts,
22975         overrides: {
22976           maxWidthFunction: expandable(),
22977           maxHeightFunction: expandable$1()
22978         },
22979         ...anchorSpec
22980       };
22981     };
22982     const show = (editor, e, items, backstage, contextmenu, anchorType, highlightImmediately) => {
22983       const anchorSpec = getAnchorSpec(editor, e, anchorType);
22984       build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
22985         isHorizontalMenu: true,
22986         search: Optional.none()
22987       }).map(menuData => {
22988         e.preventDefault();
22989         const highlightOnOpen = highlightImmediately ? HighlightOnOpen.HighlightMenuAndItem : HighlightOnOpen.HighlightNone;
22990         InlineView.showMenuWithinBounds(contextmenu, { anchor: anchorSpec }, {
22991           menu: {
22992             markers: markers('normal'),
22993             highlightOnOpen
22994           },
22995           data: menuData,
22996           type: 'horizontal'
22997         }, () => Optional.some(getContextToolbarBounds(editor, backstage.shared, anchorType === 'node' ? 'node' : 'selection')));
22998         editor.dispatch(hideContextToolbarEvent);
22999       });
23000     };
23001     const initAndShow = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
23002       const detection = detect$1();
23003       const isiOS = detection.os.isiOS();
23004       const isMacOS = detection.os.isMacOS();
23005       const isAndroid = detection.os.isAndroid();
23006       const isTouch = detection.deviceType.isTouch();
23007       const shouldHighlightImmediately = () => !(isAndroid || isiOS || isMacOS && isTouch);
23008       const open = () => {
23009         const items = buildMenu();
23010         show(editor, e, items, backstage, contextmenu, anchorType, shouldHighlightImmediately());
23011       };
23012       if ((isMacOS || isiOS) && anchorType !== 'node') {
23013         const openiOS = () => {
23014           setupiOSOverrides(editor);
23015           open();
23016         };
23017         if (isTouchWithinSelection(editor, e)) {
23018           openiOS();
23019         } else {
23020           editor.once('selectionchange', openiOS);
23021           editor.once('touchend', () => editor.off('selectionchange', openiOS));
23022         }
23023       } else {
23024         open();
23025       }
23026     };
23028     const isSeparator = item => isString(item) ? item === '|' : item.type === 'separator';
23029     const separator = { type: 'separator' };
23030     const makeContextItem = item => {
23031       const commonMenuItem = item => ({
23032         text: item.text,
23033         icon: item.icon,
23034         enabled: item.enabled,
23035         shortcut: item.shortcut
23036       });
23037       if (isString(item)) {
23038         return item;
23039       } else {
23040         switch (item.type) {
23041         case 'separator':
23042           return separator;
23043         case 'submenu':
23044           return {
23045             type: 'nestedmenuitem',
23046             ...commonMenuItem(item),
23047             getSubmenuItems: () => {
23048               const items = item.getSubmenuItems();
23049               if (isString(items)) {
23050                 return items;
23051               } else {
23052                 return map$2(items, makeContextItem);
23053               }
23054             }
23055           };
23056         default:
23057           const commonItem = item;
23058           return {
23059             type: 'menuitem',
23060             ...commonMenuItem(commonItem),
23061             onAction: noarg(commonItem.onAction)
23062           };
23063         }
23064       }
23065     };
23066     const addContextMenuGroup = (xs, groupItems) => {
23067       if (groupItems.length === 0) {
23068         return xs;
23069       }
23070       const lastMenuItem = last$1(xs).filter(item => !isSeparator(item));
23071       const before = lastMenuItem.fold(() => [], _ => [separator]);
23072       return xs.concat(before).concat(groupItems).concat([separator]);
23073     };
23074     const generateContextMenu = (contextMenus, menuConfig, selectedElement) => {
23075       const sections = foldl(menuConfig, (acc, name) => {
23076         return get$g(contextMenus, name.toLowerCase()).map(menu => {
23077           const items = menu.update(selectedElement);
23078           if (isString(items)) {
23079             return addContextMenuGroup(acc, items.split(' '));
23080           } else if (items.length > 0) {
23081             const allItems = map$2(items, makeContextItem);
23082             return addContextMenuGroup(acc, allItems);
23083           } else {
23084             return acc;
23085           }
23086         }).getOrThunk(() => acc.concat([name]));
23087       }, []);
23088       if (sections.length > 0 && isSeparator(sections[sections.length - 1])) {
23089         sections.pop();
23090       }
23091       return sections;
23092     };
23093     const isNativeOverrideKeyEvent = (editor, e) => e.ctrlKey && !shouldNeverUseNative(editor);
23094     const isTouchEvent = e => e.type === 'longpress' || has$2(e, 'touches');
23095     const isTriggeredByKeyboard = (editor, e) => !isTouchEvent(e) && (e.button !== 2 || e.target === editor.getBody() && e.pointerType === '');
23096     const getSelectedElement = (editor, e) => isTriggeredByKeyboard(editor, e) ? editor.selection.getStart(true) : e.target;
23097     const getAnchorType = (editor, e) => {
23098       const selector = getAvoidOverlapSelector(editor);
23099       const anchorType = isTriggeredByKeyboard(editor, e) ? 'selection' : 'point';
23100       if (isNotEmpty(selector)) {
23101         const target = getSelectedElement(editor, e);
23102         const selectorExists = closest(SugarElement.fromDom(target), selector);
23103         return selectorExists ? 'node' : anchorType;
23104       } else {
23105         return anchorType;
23106       }
23107     };
23108     const setup$5 = (editor, lazySink, backstage) => {
23109       const detection = detect$1();
23110       const isTouch = detection.deviceType.isTouch;
23111       const contextmenu = build$1(InlineView.sketch({
23112         dom: { tag: 'div' },
23113         lazySink,
23114         onEscape: () => editor.focus(),
23115         onShow: () => backstage.setContextMenuState(true),
23116         onHide: () => backstage.setContextMenuState(false),
23117         fireDismissalEventInstead: {},
23118         inlineBehaviours: derive$1([config('dismissContextMenu', [run$1(dismissRequested(), (comp, _se) => {
23119               Sandboxing.close(comp);
23120               editor.focus();
23121             })])])
23122       }));
23123       const hideContextMenu = () => InlineView.hide(contextmenu);
23124       const showContextMenu = e => {
23125         if (shouldNeverUseNative(editor)) {
23126           e.preventDefault();
23127         }
23128         if (isNativeOverrideKeyEvent(editor, e) || isContextMenuDisabled(editor)) {
23129           return;
23130         }
23131         const anchorType = getAnchorType(editor, e);
23132         const buildMenu = () => {
23133           const selectedElement = getSelectedElement(editor, e);
23134           const registry = editor.ui.registry.getAll();
23135           const menuConfig = getContextMenu(editor);
23136           return generateContextMenu(registry.contextMenus, menuConfig, selectedElement);
23137         };
23138         const initAndShow$2 = isTouch() ? initAndShow : initAndShow$1;
23139         initAndShow$2(editor, e, buildMenu, backstage, contextmenu, anchorType);
23140       };
23141       editor.on('init', () => {
23142         const hideEvents = 'ResizeEditor ScrollContent ScrollWindow longpresscancel' + (isTouch() ? '' : ' ResizeWindow');
23143         editor.on(hideEvents, hideContextMenu);
23144         editor.on('longpress contextmenu', showContextMenu);
23145       });
23146     };
23148     const adt = Adt.generate([
23149       {
23150         offset: [
23151           'x',
23152           'y'
23153         ]
23154       },
23155       {
23156         absolute: [
23157           'x',
23158           'y'
23159         ]
23160       },
23161       {
23162         fixed: [
23163           'x',
23164           'y'
23165         ]
23166       }
23167     ]);
23168     const subtract = change => point => point.translate(-change.left, -change.top);
23169     const add = change => point => point.translate(change.left, change.top);
23170     const transform = changes => (x, y) => foldl(changes, (rest, f) => f(rest), SugarPosition(x, y));
23171     const asFixed = (coord, scroll, origin) => coord.fold(transform([
23172       add(origin),
23173       subtract(scroll)
23174     ]), transform([subtract(scroll)]), transform([]));
23175     const asAbsolute = (coord, scroll, origin) => coord.fold(transform([add(origin)]), transform([]), transform([add(scroll)]));
23176     const asOffset = (coord, scroll, origin) => coord.fold(transform([]), transform([subtract(origin)]), transform([
23177       add(scroll),
23178       subtract(origin)
23179     ]));
23180     const withinRange = (coord1, coord2, xRange, yRange, scroll, origin) => {
23181       const a1 = asAbsolute(coord1, scroll, origin);
23182       const a2 = asAbsolute(coord2, scroll, origin);
23183       return Math.abs(a1.left - a2.left) <= xRange && Math.abs(a1.top - a2.top) <= yRange;
23184     };
23185     const getDeltas = (coord1, coord2, xRange, yRange, scroll, origin) => {
23186       const a1 = asAbsolute(coord1, scroll, origin);
23187       const a2 = asAbsolute(coord2, scroll, origin);
23188       const left = Math.abs(a1.left - a2.left);
23189       const top = Math.abs(a1.top - a2.top);
23190       return SugarPosition(left, top);
23191     };
23192     const toStyles = (coord, scroll, origin) => {
23193       const stylesOpt = coord.fold((x, y) => ({
23194         position: Optional.some('absolute'),
23195         left: Optional.some(x + 'px'),
23196         top: Optional.some(y + 'px')
23197       }), (x, y) => ({
23198         position: Optional.some('absolute'),
23199         left: Optional.some(x - origin.left + 'px'),
23200         top: Optional.some(y - origin.top + 'px')
23201       }), (x, y) => ({
23202         position: Optional.some('fixed'),
23203         left: Optional.some(x + 'px'),
23204         top: Optional.some(y + 'px')
23205       }));
23206       return {
23207         right: Optional.none(),
23208         bottom: Optional.none(),
23209         ...stylesOpt
23210       };
23211     };
23212     const translate = (coord, deltaX, deltaY) => coord.fold((x, y) => offset(x + deltaX, y + deltaY), (x, y) => absolute(x + deltaX, y + deltaY), (x, y) => fixed(x + deltaX, y + deltaY));
23213     const absorb = (partialCoord, originalCoord, scroll, origin) => {
23214       const absorbOne = (stencil, nu) => (optX, optY) => {
23215         const original = stencil(originalCoord, scroll, origin);
23216         return nu(optX.getOr(original.left), optY.getOr(original.top));
23217       };
23218       return partialCoord.fold(absorbOne(asOffset, offset), absorbOne(asAbsolute, absolute), absorbOne(asFixed, fixed));
23219     };
23220     const offset = adt.offset;
23221     const absolute = adt.absolute;
23222     const fixed = adt.fixed;
23224     const parseAttrToInt = (element, name) => {
23225       const value = get$f(element, name);
23226       return isUndefined(value) ? NaN : parseInt(value, 10);
23227     };
23228     const get = (component, snapsInfo) => {
23229       const element = component.element;
23230       const x = parseAttrToInt(element, snapsInfo.leftAttr);
23231       const y = parseAttrToInt(element, snapsInfo.topAttr);
23232       return isNaN(x) || isNaN(y) ? Optional.none() : Optional.some(SugarPosition(x, y));
23233     };
23234     const set = (component, snapsInfo, pt) => {
23235       const element = component.element;
23236       set$9(element, snapsInfo.leftAttr, pt.left + 'px');
23237       set$9(element, snapsInfo.topAttr, pt.top + 'px');
23238     };
23239     const clear = (component, snapsInfo) => {
23240       const element = component.element;
23241       remove$7(element, snapsInfo.leftAttr);
23242       remove$7(element, snapsInfo.topAttr);
23243     };
23245     const getCoords = (component, snapInfo, coord, delta) => get(component, snapInfo).fold(() => coord, fixed$1 => fixed(fixed$1.left + delta.left, fixed$1.top + delta.top));
23246     const moveOrSnap = (component, snapInfo, coord, delta, scroll, origin) => {
23247       const newCoord = getCoords(component, snapInfo, coord, delta);
23248       const snap = snapInfo.mustSnap ? findClosestSnap(component, snapInfo, newCoord, scroll, origin) : findSnap(component, snapInfo, newCoord, scroll, origin);
23249       const fixedCoord = asFixed(newCoord, scroll, origin);
23250       set(component, snapInfo, fixedCoord);
23251       return snap.fold(() => ({
23252         coord: fixed(fixedCoord.left, fixedCoord.top),
23253         extra: Optional.none()
23254       }), spanned => ({
23255         coord: spanned.output,
23256         extra: spanned.extra
23257       }));
23258     };
23259     const stopDrag = (component, snapInfo) => {
23260       clear(component, snapInfo);
23261     };
23262     const findMatchingSnap = (snaps, newCoord, scroll, origin) => findMap(snaps, snap => {
23263       const sensor = snap.sensor;
23264       const inRange = withinRange(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
23265       return inRange ? Optional.some({
23266         output: absorb(snap.output, newCoord, scroll, origin),
23267         extra: snap.extra
23268       }) : Optional.none();
23269     });
23270     const findClosestSnap = (component, snapInfo, newCoord, scroll, origin) => {
23271       const snaps = snapInfo.getSnapPoints(component);
23272       const matchSnap = findMatchingSnap(snaps, newCoord, scroll, origin);
23273       return matchSnap.orThunk(() => {
23274         const bestSnap = foldl(snaps, (acc, snap) => {
23275           const sensor = snap.sensor;
23276           const deltas = getDeltas(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
23277           return acc.deltas.fold(() => ({
23278             deltas: Optional.some(deltas),
23279             snap: Optional.some(snap)
23280           }), bestDeltas => {
23281             const currAvg = (deltas.left + deltas.top) / 2;
23282             const bestAvg = (bestDeltas.left + bestDeltas.top) / 2;
23283             if (currAvg <= bestAvg) {
23284               return {
23285                 deltas: Optional.some(deltas),
23286                 snap: Optional.some(snap)
23287               };
23288             } else {
23289               return acc;
23290             }
23291           });
23292         }, {
23293           deltas: Optional.none(),
23294           snap: Optional.none()
23295         });
23296         return bestSnap.snap.map(snap => ({
23297           output: absorb(snap.output, newCoord, scroll, origin),
23298           extra: snap.extra
23299         }));
23300       });
23301     };
23302     const findSnap = (component, snapInfo, newCoord, scroll, origin) => {
23303       const snaps = snapInfo.getSnapPoints(component);
23304       return findMatchingSnap(snaps, newCoord, scroll, origin);
23305     };
23306     const snapTo$1 = (snap, scroll, origin) => ({
23307       coord: absorb(snap.output, snap.output, scroll, origin),
23308       extra: snap.extra
23309     });
23311     const snapTo = (component, dragConfig, _state, snap) => {
23312       const target = dragConfig.getTarget(component.element);
23313       if (dragConfig.repositionTarget) {
23314         const doc = owner$4(component.element);
23315         const scroll = get$b(doc);
23316         const origin = getOrigin(target);
23317         const snapPin = snapTo$1(snap, scroll, origin);
23318         const styles = toStyles(snapPin.coord, scroll, origin);
23319         setOptions(target, styles);
23320       }
23321     };
23323     var DraggingApis = /*#__PURE__*/Object.freeze({
23324         __proto__: null,
23325         snapTo: snapTo
23326     });
23328     const initialAttribute = 'data-initial-z-index';
23329     const resetZIndex = blocker => {
23330       parent(blocker.element).filter(isElement$1).each(root => {
23331         getOpt(root, initialAttribute).fold(() => remove$6(root, 'z-index'), zIndex => set$8(root, 'z-index', zIndex));
23332         remove$7(root, initialAttribute);
23333       });
23334     };
23335     const changeZIndex = blocker => {
23336       parent(blocker.element).filter(isElement$1).each(root => {
23337         getRaw(root, 'z-index').each(zindex => {
23338           set$9(root, initialAttribute, zindex);
23339         });
23340         set$8(root, 'z-index', get$e(blocker.element, 'z-index'));
23341       });
23342     };
23343     const instigate = (anyComponent, blocker) => {
23344       anyComponent.getSystem().addToGui(blocker);
23345       changeZIndex(blocker);
23346     };
23347     const discard = blocker => {
23348       resetZIndex(blocker);
23349       blocker.getSystem().removeFromGui(blocker);
23350     };
23351     const createComponent = (component, blockerClass, blockerEvents) => component.getSystem().build(Container.sketch({
23352       dom: {
23353         styles: {
23354           'left': '0px',
23355           'top': '0px',
23356           'width': '100%',
23357           'height': '100%',
23358           'position': 'fixed',
23359           'z-index': '1000000000000000'
23360         },
23361         classes: [blockerClass]
23362       },
23363       events: blockerEvents
23364     }));
23366     var SnapSchema = optionObjOf('snaps', [
23367       required$1('getSnapPoints'),
23368       onHandler('onSensor'),
23369       required$1('leftAttr'),
23370       required$1('topAttr'),
23371       defaulted('lazyViewport', win),
23372       defaulted('mustSnap', false)
23373     ]);
23375     const schema$6 = [
23376       defaulted('useFixed', never),
23377       required$1('blockerClass'),
23378       defaulted('getTarget', identity),
23379       defaulted('onDrag', noop),
23380       defaulted('repositionTarget', true),
23381       defaulted('onDrop', noop),
23382       defaultedFunction('getBounds', win),
23383       SnapSchema
23384     ];
23386     const getCurrentCoord = target => lift3(getRaw(target, 'left'), getRaw(target, 'top'), getRaw(target, 'position'), (left, top, position) => {
23387       const nu = position === 'fixed' ? fixed : offset;
23388       return nu(parseInt(left, 10), parseInt(top, 10));
23389     }).getOrThunk(() => {
23390       const location = absolute$3(target);
23391       return absolute(location.left, location.top);
23392     });
23393     const clampCoords = (component, coords, scroll, origin, startData) => {
23394       const bounds = startData.bounds;
23395       const absoluteCoord = asAbsolute(coords, scroll, origin);
23396       const newX = clamp(absoluteCoord.left, bounds.x, bounds.x + bounds.width - startData.width);
23397       const newY = clamp(absoluteCoord.top, bounds.y, bounds.y + bounds.height - startData.height);
23398       const newCoords = absolute(newX, newY);
23399       return coords.fold(() => {
23400         const offset$1 = asOffset(newCoords, scroll, origin);
23401         return offset(offset$1.left, offset$1.top);
23402       }, constant$1(newCoords), () => {
23403         const fixed$1 = asFixed(newCoords, scroll, origin);
23404         return fixed(fixed$1.left, fixed$1.top);
23405       });
23406     };
23407     const calcNewCoord = (component, optSnaps, currentCoord, scroll, origin, delta, startData) => {
23408       const newCoord = optSnaps.fold(() => {
23409         const translated = translate(currentCoord, delta.left, delta.top);
23410         const fixedCoord = asFixed(translated, scroll, origin);
23411         return fixed(fixedCoord.left, fixedCoord.top);
23412       }, snapInfo => {
23413         const snapping = moveOrSnap(component, snapInfo, currentCoord, delta, scroll, origin);
23414         snapping.extra.each(extra => {
23415           snapInfo.onSensor(component, extra);
23416         });
23417         return snapping.coord;
23418       });
23419       return clampCoords(component, newCoord, scroll, origin, startData);
23420     };
23421     const dragBy = (component, dragConfig, startData, delta) => {
23422       const target = dragConfig.getTarget(component.element);
23423       if (dragConfig.repositionTarget) {
23424         const doc = owner$4(component.element);
23425         const scroll = get$b(doc);
23426         const origin = getOrigin(target);
23427         const currentCoord = getCurrentCoord(target);
23428         const newCoord = calcNewCoord(component, dragConfig.snaps, currentCoord, scroll, origin, delta, startData);
23429         const styles = toStyles(newCoord, scroll, origin);
23430         setOptions(target, styles);
23431       }
23432       dragConfig.onDrag(component, target, delta);
23433     };
23435     const calcStartData = (dragConfig, comp) => ({
23436       bounds: dragConfig.getBounds(),
23437       height: getOuter$2(comp.element),
23438       width: getOuter$1(comp.element)
23439     });
23440     const move = (component, dragConfig, dragState, dragMode, event) => {
23441       const delta = dragState.update(dragMode, event);
23442       const dragStartData = dragState.getStartData().getOrThunk(() => calcStartData(dragConfig, component));
23443       delta.each(dlt => {
23444         dragBy(component, dragConfig, dragStartData, dlt);
23445       });
23446     };
23447     const stop = (component, blocker, dragConfig, dragState) => {
23448       blocker.each(discard);
23449       dragConfig.snaps.each(snapInfo => {
23450         stopDrag(component, snapInfo);
23451       });
23452       const target = dragConfig.getTarget(component.element);
23453       dragState.reset();
23454       dragConfig.onDrop(component, target);
23455     };
23456     const handlers = events => (dragConfig, dragState) => {
23457       const updateStartState = comp => {
23458         dragState.setStartData(calcStartData(dragConfig, comp));
23459       };
23460       return derive$2([
23461         run$1(windowScroll(), comp => {
23462           dragState.getStartData().each(() => updateStartState(comp));
23463         }),
23464         ...events(dragConfig, dragState, updateStartState)
23465       ]);
23466     };
23468     const init$2 = dragApi => derive$2([
23469       run$1(mousedown(), dragApi.forceDrop),
23470       run$1(mouseup(), dragApi.drop),
23471       run$1(mousemove(), (comp, simulatedEvent) => {
23472         dragApi.move(simulatedEvent.event);
23473       }),
23474       run$1(mouseout(), dragApi.delayDrop)
23475     ]);
23477     const getData$1 = event => Optional.from(SugarPosition(event.x, event.y));
23478     const getDelta$1 = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
23480     var MouseData = /*#__PURE__*/Object.freeze({
23481         __proto__: null,
23482         getData: getData$1,
23483         getDelta: getDelta$1
23484     });
23486     const events$2 = (dragConfig, dragState, updateStartState) => [run$1(mousedown(), (component, simulatedEvent) => {
23487         const raw = simulatedEvent.event.raw;
23488         if (raw.button !== 0) {
23489           return;
23490         }
23491         simulatedEvent.stop();
23492         const stop$1 = () => stop(component, Optional.some(blocker), dragConfig, dragState);
23493         const delayDrop = DelayedFunction(stop$1, 200);
23494         const dragApi = {
23495           drop: stop$1,
23496           delayDrop: delayDrop.schedule,
23497           forceDrop: stop$1,
23498           move: event => {
23499             delayDrop.cancel();
23500             move(component, dragConfig, dragState, MouseData, event);
23501           }
23502         };
23503         const blocker = createComponent(component, dragConfig.blockerClass, init$2(dragApi));
23504         const start = () => {
23505           updateStartState(component);
23506           instigate(component, blocker);
23507         };
23508         start();
23509       })];
23510     const schema$5 = [
23511       ...schema$6,
23512       output$1('dragger', { handlers: handlers(events$2) })
23513     ];
23515     const init$1 = dragApi => derive$2([
23516       run$1(touchstart(), dragApi.forceDrop),
23517       run$1(touchend(), dragApi.drop),
23518       run$1(touchcancel(), dragApi.drop),
23519       run$1(touchmove(), (comp, simulatedEvent) => {
23520         dragApi.move(simulatedEvent.event);
23521       })
23522     ]);
23524     const getDataFrom = touches => {
23525       const touch = touches[0];
23526       return Optional.some(SugarPosition(touch.clientX, touch.clientY));
23527     };
23528     const getData = event => {
23529       const raw = event.raw;
23530       const touches = raw.touches;
23531       return touches.length === 1 ? getDataFrom(touches) : Optional.none();
23532     };
23533     const getDelta = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
23535     var TouchData = /*#__PURE__*/Object.freeze({
23536         __proto__: null,
23537         getData: getData,
23538         getDelta: getDelta
23539     });
23541     const events$1 = (dragConfig, dragState, updateStartState) => {
23542       const blockerSingleton = value$2();
23543       const stopBlocking = component => {
23544         stop(component, blockerSingleton.get(), dragConfig, dragState);
23545         blockerSingleton.clear();
23546       };
23547       return [
23548         run$1(touchstart(), (component, simulatedEvent) => {
23549           simulatedEvent.stop();
23550           const stop = () => stopBlocking(component);
23551           const dragApi = {
23552             drop: stop,
23553             delayDrop: noop,
23554             forceDrop: stop,
23555             move: event => {
23556               move(component, dragConfig, dragState, TouchData, event);
23557             }
23558           };
23559           const blocker = createComponent(component, dragConfig.blockerClass, init$1(dragApi));
23560           blockerSingleton.set(blocker);
23561           const start = () => {
23562             updateStartState(component);
23563             instigate(component, blocker);
23564           };
23565           start();
23566         }),
23567         run$1(touchmove(), (component, simulatedEvent) => {
23568           simulatedEvent.stop();
23569           move(component, dragConfig, dragState, TouchData, simulatedEvent.event);
23570         }),
23571         run$1(touchend(), (component, simulatedEvent) => {
23572           simulatedEvent.stop();
23573           stopBlocking(component);
23574         }),
23575         run$1(touchcancel(), stopBlocking)
23576       ];
23577     };
23578     const schema$4 = [
23579       ...schema$6,
23580       output$1('dragger', { handlers: handlers(events$1) })
23581     ];
23583     const events = (dragConfig, dragState, updateStartState) => [
23584       ...events$2(dragConfig, dragState, updateStartState),
23585       ...events$1(dragConfig, dragState, updateStartState)
23586     ];
23587     const schema$3 = [
23588       ...schema$6,
23589       output$1('dragger', { handlers: handlers(events) })
23590     ];
23592     const mouse = schema$5;
23593     const touch = schema$4;
23594     const mouseOrTouch = schema$3;
23596     var DraggingBranches = /*#__PURE__*/Object.freeze({
23597         __proto__: null,
23598         mouse: mouse,
23599         touch: touch,
23600         mouseOrTouch: mouseOrTouch
23601     });
23603     const init = () => {
23604       let previous = Optional.none();
23605       let startData = Optional.none();
23606       const reset = () => {
23607         previous = Optional.none();
23608         startData = Optional.none();
23609       };
23610       const calculateDelta = (mode, nu) => {
23611         const result = previous.map(old => mode.getDelta(old, nu));
23612         previous = Optional.some(nu);
23613         return result;
23614       };
23615       const update = (mode, dragEvent) => mode.getData(dragEvent).bind(nuData => calculateDelta(mode, nuData));
23616       const setStartData = data => {
23617         startData = Optional.some(data);
23618       };
23619       const getStartData = () => startData;
23620       const readState = constant$1({});
23621       return nu$8({
23622         readState,
23623         reset,
23624         update,
23625         getStartData,
23626         setStartData
23627       });
23628     };
23630     var DragState = /*#__PURE__*/Object.freeze({
23631         __proto__: null,
23632         init: init
23633     });
23635     const Dragging = createModes({
23636       branchKey: 'mode',
23637       branches: DraggingBranches,
23638       name: 'dragging',
23639       active: {
23640         events: (dragConfig, dragState) => {
23641           const dragger = dragConfig.dragger;
23642           return dragger.handlers(dragConfig, dragState);
23643         }
23644       },
23645       extra: {
23646         snap: sConfig => ({
23647           sensor: sConfig.sensor,
23648           range: sConfig.range,
23649           output: sConfig.output,
23650           extra: Optional.from(sConfig.extra)
23651         })
23652       },
23653       state: DragState,
23654       apis: DraggingApis
23655     });
23657     const snapWidth = 40;
23658     const snapOffset = snapWidth / 2;
23659     const calcSnap = (selectorOpt, td, x, y, width, height) => selectorOpt.fold(() => Dragging.snap({
23660       sensor: absolute(x - snapOffset, y - snapOffset),
23661       range: SugarPosition(width, height),
23662       output: absolute(Optional.some(x), Optional.some(y)),
23663       extra: { td }
23664     }), selectorHandle => {
23665       const sensorLeft = x - snapOffset;
23666       const sensorTop = y - snapOffset;
23667       const sensorWidth = snapWidth;
23668       const sensorHeight = snapWidth;
23669       const rect = selectorHandle.element.dom.getBoundingClientRect();
23670       return Dragging.snap({
23671         sensor: absolute(sensorLeft, sensorTop),
23672         range: SugarPosition(sensorWidth, sensorHeight),
23673         output: absolute(Optional.some(x - rect.width / 2), Optional.some(y - rect.height / 2)),
23674         extra: { td }
23675       });
23676     });
23677     const getSnapsConfig = (getSnapPoints, cell, onChange) => {
23678       const isSameCell = (cellOpt, td) => cellOpt.exists(currentTd => eq(currentTd, td));
23679       return {
23680         getSnapPoints,
23681         leftAttr: 'data-drag-left',
23682         topAttr: 'data-drag-top',
23683         onSensor: (component, extra) => {
23684           const td = extra.td;
23685           if (!isSameCell(cell.get(), td)) {
23686             cell.set(td);
23687             onChange(td);
23688           }
23689         },
23690         mustSnap: true
23691       };
23692     };
23693     const createSelector = snaps => record(Button.sketch({
23694       dom: {
23695         tag: 'div',
23696         classes: ['tox-selector']
23697       },
23698       buttonBehaviours: derive$1([
23699         Dragging.config({
23700           mode: 'mouseOrTouch',
23701           blockerClass: 'blocker',
23702           snaps
23703         }),
23704         Unselecting.config({})
23705       ]),
23706       eventOrder: {
23707         mousedown: [
23708           'dragging',
23709           'alloy.base.behaviour'
23710         ],
23711         touchstart: [
23712           'dragging',
23713           'alloy.base.behaviour'
23714         ]
23715       }
23716     }));
23717     const setup$4 = (editor, sink) => {
23718       const tlTds = Cell([]);
23719       const brTds = Cell([]);
23720       const isVisible = Cell(false);
23721       const startCell = value$2();
23722       const finishCell = value$2();
23723       const getTopLeftSnap = td => {
23724         const box = absolute$2(td);
23725         return calcSnap(memTopLeft.getOpt(sink), td, box.x, box.y, box.width, box.height);
23726       };
23727       const getTopLeftSnaps = () => map$2(tlTds.get(), td => getTopLeftSnap(td));
23728       const getBottomRightSnap = td => {
23729         const box = absolute$2(td);
23730         return calcSnap(memBottomRight.getOpt(sink), td, box.right, box.bottom, box.width, box.height);
23731       };
23732       const getBottomRightSnaps = () => map$2(brTds.get(), td => getBottomRightSnap(td));
23733       const topLeftSnaps = getSnapsConfig(getTopLeftSnaps, startCell, start => {
23734         finishCell.get().each(finish => {
23735           editor.dispatch('TableSelectorChange', {
23736             start,
23737             finish
23738           });
23739         });
23740       });
23741       const bottomRightSnaps = getSnapsConfig(getBottomRightSnaps, finishCell, finish => {
23742         startCell.get().each(start => {
23743           editor.dispatch('TableSelectorChange', {
23744             start,
23745             finish
23746           });
23747         });
23748       });
23749       const memTopLeft = createSelector(topLeftSnaps);
23750       const memBottomRight = createSelector(bottomRightSnaps);
23751       const topLeft = build$1(memTopLeft.asSpec());
23752       const bottomRight = build$1(memBottomRight.asSpec());
23753       const showOrHideHandle = (selector, cell, isAbove, isBelow) => {
23754         const cellRect = cell.dom.getBoundingClientRect();
23755         remove$6(selector.element, 'display');
23756         const viewportHeight = defaultView(SugarElement.fromDom(editor.getBody())).dom.innerHeight;
23757         const aboveViewport = isAbove(cellRect);
23758         const belowViewport = isBelow(cellRect, viewportHeight);
23759         if (aboveViewport || belowViewport) {
23760           set$8(selector.element, 'display', 'none');
23761         }
23762       };
23763       const snapTo = (selector, cell, getSnapConfig, pos) => {
23764         const snap = getSnapConfig(cell);
23765         Dragging.snapTo(selector, snap);
23766         const isAbove = rect => rect[pos] < 0;
23767         const isBelow = (rect, viewportHeight) => rect[pos] > viewportHeight;
23768         showOrHideHandle(selector, cell, isAbove, isBelow);
23769       };
23770       const snapTopLeft = cell => snapTo(topLeft, cell, getTopLeftSnap, 'top');
23771       const snapLastTopLeft = () => startCell.get().each(snapTopLeft);
23772       const snapBottomRight = cell => snapTo(bottomRight, cell, getBottomRightSnap, 'bottom');
23773       const snapLastBottomRight = () => finishCell.get().each(snapBottomRight);
23774       if (detect$1().deviceType.isTouch()) {
23775         editor.on('TableSelectionChange', e => {
23776           if (!isVisible.get()) {
23777             attach(sink, topLeft);
23778             attach(sink, bottomRight);
23779             isVisible.set(true);
23780           }
23781           startCell.set(e.start);
23782           finishCell.set(e.finish);
23783           e.otherCells.each(otherCells => {
23784             tlTds.set(otherCells.upOrLeftCells);
23785             brTds.set(otherCells.downOrRightCells);
23786             snapTopLeft(e.start);
23787             snapBottomRight(e.finish);
23788           });
23789         });
23790         editor.on('ResizeEditor ResizeWindow ScrollContent', () => {
23791           snapLastTopLeft();
23792           snapLastBottomRight();
23793         });
23794         editor.on('TableSelectionClear', () => {
23795           if (isVisible.get()) {
23796             detach(topLeft);
23797             detach(bottomRight);
23798             isVisible.set(false);
23799           }
23800           startCell.clear();
23801           finishCell.clear();
23802         });
23803       }
23804     };
23806     var Logo = "<svg width=\"50px\" height=\"16px\" viewBox=\"0 0 50 16\" xmlns=\"http://www.w3.org/2000/svg\">\n  <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M10.143 0c2.608.015 5.186 2.178 5.186 5.331 0 0 .077 3.812-.084 4.87-.361 2.41-2.164 4.074-4.65 4.496-1.453.284-2.523.49-3.212.623-.373.071-.634.122-.785.152-.184.038-.997.145-1.35.145-2.732 0-5.21-2.04-5.248-5.33 0 0 0-3.514.03-4.442.093-2.4 1.758-4.342 4.926-4.963 0 0 3.875-.752 4.036-.782.368-.07.775-.1 1.15-.1Zm1.826 2.8L5.83 3.989v2.393l-2.455.475v5.968l6.137-1.189V9.243l2.456-.476V2.8ZM5.83 6.382l3.682-.713v3.574l-3.682.713V6.382Zm27.173-1.64-.084-1.066h-2.226v9.132h2.456V7.743c-.008-1.151.998-2.064 2.149-2.072 1.15-.008 1.987.92 1.995 2.072v5.065h2.455V7.359c-.015-2.18-1.657-3.929-3.837-3.913a3.993 3.993 0 0 0-2.908 1.296Zm-6.3-4.266L29.16 0v2.387l-2.456.475V.476Zm0 3.2v9.132h2.456V3.676h-2.456Zm18.179 11.787L49.11 3.676H46.58l-1.612 4.527-.46 1.382-.384-1.382-1.611-4.527H39.98l3.3 9.132L42.15 16l2.732-.537ZM22.867 9.738c0 .752.568 1.075.921 1.075.353 0 .668-.047.998-.154l.537 1.765c-.23.154-.92.537-2.225.537-1.305 0-2.655-.997-2.686-2.686a136.877 136.877 0 0 1 0-4.374H18.8V3.676h1.612v-1.98l2.455-.476v2.456h2.302V5.9h-2.302v3.837Z\"/>\n</svg>\n";
23808     const isHidden = elm => elm.nodeName === 'BR' || !!elm.getAttribute('data-mce-bogus') || elm.getAttribute('data-mce-type') === 'bookmark';
23809     const renderElementPath = (editor, settings, providersBackstage) => {
23810       const delimiter = settings.delimiter ?? '\u203A';
23811       const renderElement = (name, element, index) => Button.sketch({
23812         dom: {
23813           tag: 'div',
23814           classes: ['tox-statusbar__path-item'],
23815           attributes: {
23816             'data-index': index,
23817             'aria-level': index + 1
23818           }
23819         },
23820         components: [text$2(name)],
23821         action: _btn => {
23822           editor.focus();
23823           editor.selection.select(element);
23824           editor.nodeChanged();
23825         },
23826         buttonBehaviours: derive$1([
23827           DisablingConfigs.button(providersBackstage.isDisabled),
23828           receivingConfig()
23829         ])
23830       });
23831       const renderDivider = () => ({
23832         dom: {
23833           tag: 'div',
23834           classes: ['tox-statusbar__path-divider'],
23835           attributes: { 'aria-hidden': true }
23836         },
23837         components: [text$2(` ${ delimiter } `)]
23838       });
23839       const renderPathData = data => foldl(data, (acc, path, index) => {
23840         const element = renderElement(path.name, path.element, index);
23841         if (index === 0) {
23842           return acc.concat([element]);
23843         } else {
23844           return acc.concat([
23845             renderDivider(),
23846             element
23847           ]);
23848         }
23849       }, []);
23850       const updatePath = parents => {
23851         const newPath = [];
23852         let i = parents.length;
23853         while (i-- > 0) {
23854           const parent = parents[i];
23855           if (parent.nodeType === 1 && !isHidden(parent)) {
23856             const args = fireResolveName(editor, parent);
23857             if (!args.isDefaultPrevented()) {
23858               newPath.push({
23859                 name: args.name,
23860                 element: parent
23861               });
23862             }
23863             if (args.isPropagationStopped()) {
23864               break;
23865             }
23866           }
23867         }
23868         return newPath;
23869       };
23870       return {
23871         dom: {
23872           tag: 'div',
23873           classes: ['tox-statusbar__path'],
23874           attributes: { role: 'navigation' }
23875         },
23876         behaviours: derive$1([
23877           Keying.config({
23878             mode: 'flow',
23879             selector: 'div[role=button]'
23880           }),
23881           Disabling.config({ disabled: providersBackstage.isDisabled }),
23882           receivingConfig(),
23883           Tabstopping.config({}),
23884           Replacing.config({}),
23885           config('elementPathEvents', [runOnAttached((comp, _e) => {
23886               editor.shortcuts.add('alt+F11', 'focus statusbar elementpath', () => Keying.focusIn(comp));
23887               editor.on('NodeChange', e => {
23888                 const newPath = updatePath(e.parents);
23889                 const newChildren = newPath.length > 0 ? renderPathData(newPath) : [];
23890                 Replacing.set(comp, newChildren);
23891               });
23892             })])
23893         ]),
23894         components: []
23895       };
23896     };
23898     var ResizeTypes;
23899     (function (ResizeTypes) {
23900       ResizeTypes[ResizeTypes['None'] = 0] = 'None';
23901       ResizeTypes[ResizeTypes['Both'] = 1] = 'Both';
23902       ResizeTypes[ResizeTypes['Vertical'] = 2] = 'Vertical';
23903     }(ResizeTypes || (ResizeTypes = {})));
23904     const getDimensions = (editor, deltas, resizeType, originalHeight, originalWidth) => {
23905       const dimensions = { height: calcCappedSize(originalHeight + deltas.top, getMinHeightOption(editor), getMaxHeightOption(editor)) };
23906       if (resizeType === ResizeTypes.Both) {
23907         dimensions.width = calcCappedSize(originalWidth + deltas.left, getMinWidthOption(editor), getMaxWidthOption(editor));
23908       }
23909       return dimensions;
23910     };
23911     const resize = (editor, deltas, resizeType) => {
23912       const container = SugarElement.fromDom(editor.getContainer());
23913       const dimensions = getDimensions(editor, deltas, resizeType, get$d(container), get$c(container));
23914       each(dimensions, (val, dim) => {
23915         if (isNumber(val)) {
23916           set$8(container, dim, numToPx(val));
23917         }
23918       });
23919       fireResizeEditor(editor);
23920     };
23922     const getResizeType = editor => {
23923       const resize = getResize(editor);
23924       if (resize === false) {
23925         return ResizeTypes.None;
23926       } else if (resize === 'both') {
23927         return ResizeTypes.Both;
23928       } else {
23929         return ResizeTypes.Vertical;
23930       }
23931     };
23932     const keyboardHandler = (editor, resizeType, x, y) => {
23933       const scale = 20;
23934       const delta = SugarPosition(x * scale, y * scale);
23935       resize(editor, delta, resizeType);
23936       return Optional.some(true);
23937     };
23938     const renderResizeHandler = (editor, providersBackstage) => {
23939       const resizeType = getResizeType(editor);
23940       if (resizeType === ResizeTypes.None) {
23941         return Optional.none();
23942       }
23943       return Optional.some(render$3('resize-handle', {
23944         tag: 'div',
23945         classes: ['tox-statusbar__resize-handle'],
23946         attributes: { title: providersBackstage.translate('Resize') },
23947         behaviours: [
23948           Dragging.config({
23949             mode: 'mouse',
23950             repositionTarget: false,
23951             onDrag: (_comp, _target, delta) => resize(editor, delta, resizeType),
23952             blockerClass: 'tox-blocker'
23953           }),
23954           Keying.config({
23955             mode: 'special',
23956             onLeft: () => keyboardHandler(editor, resizeType, -1, 0),
23957             onRight: () => keyboardHandler(editor, resizeType, 1, 0),
23958             onUp: () => keyboardHandler(editor, resizeType, 0, -1),
23959             onDown: () => keyboardHandler(editor, resizeType, 0, 1)
23960           }),
23961           Tabstopping.config({}),
23962           Focusing.config({})
23963         ]
23964       }, providersBackstage.icons));
23965     };
23967     const renderWordCount = (editor, providersBackstage) => {
23968       const replaceCountText = (comp, count, mode) => Replacing.set(comp, [text$2(providersBackstage.translate([
23969           '{0} ' + mode,
23970           count[mode]
23971         ]))]);
23972       return Button.sketch({
23973         dom: {
23974           tag: 'button',
23975           classes: ['tox-statusbar__wordcount']
23976         },
23977         components: [],
23978         buttonBehaviours: derive$1([
23979           DisablingConfigs.button(providersBackstage.isDisabled),
23980           receivingConfig(),
23981           Tabstopping.config({}),
23982           Replacing.config({}),
23983           Representing.config({
23984             store: {
23985               mode: 'memory',
23986               initialValue: {
23987                 mode: 'words',
23988                 count: {
23989                   words: 0,
23990                   characters: 0
23991                 }
23992               }
23993             }
23994           }),
23995           config('wordcount-events', [
23996             runOnExecute$1(comp => {
23997               const currentVal = Representing.getValue(comp);
23998               const newMode = currentVal.mode === 'words' ? 'characters' : 'words';
23999               Representing.setValue(comp, {
24000                 mode: newMode,
24001                 count: currentVal.count
24002               });
24003               replaceCountText(comp, currentVal.count, newMode);
24004             }),
24005             runOnAttached(comp => {
24006               editor.on('wordCountUpdate', e => {
24007                 const {mode} = Representing.getValue(comp);
24008                 Representing.setValue(comp, {
24009                   mode,
24010                   count: e.wordCount
24011                 });
24012                 replaceCountText(comp, e.wordCount, mode);
24013               });
24014             })
24015           ])
24016         ]),
24017         eventOrder: {
24018           [execute$5()]: [
24019             'disabling',
24020             'alloy.base.behaviour',
24021             'wordcount-events'
24022           ]
24023         }
24024       });
24025     };
24027     const renderStatusbar = (editor, providersBackstage) => {
24028       const renderBranding = () => {
24029         return {
24030           dom: {
24031             tag: 'span',
24032             classes: ['tox-statusbar__branding']
24033           },
24034           components: [{
24035               dom: {
24036                 tag: 'a',
24037                 attributes: {
24038                   'href': 'https://www.tiny.cloud/powered-by-tiny?utm_campaign=editor_referral&utm_medium=poweredby&utm_source=tinymce&utm_content=v6',
24039                   'rel': 'noopener',
24040                   'target': '_blank',
24041                   'aria-label': global$8.translate([
24042                     'Powered by {0}',
24043                     'Tiny'
24044                   ])
24045                 },
24046                 innerHtml: Logo.trim()
24047               },
24048               behaviours: derive$1([Focusing.config({})])
24049             }]
24050         };
24051       };
24052       const getTextComponents = () => {
24053         const components = [];
24054         if (useElementPath(editor)) {
24055           components.push(renderElementPath(editor, {}, providersBackstage));
24056         }
24057         if (editor.hasPlugin('wordcount')) {
24058           components.push(renderWordCount(editor, providersBackstage));
24059         }
24060         if (useBranding(editor)) {
24061           components.push(renderBranding());
24062         }
24063         if (components.length > 0) {
24064           return [{
24065               dom: {
24066                 tag: 'div',
24067                 classes: ['tox-statusbar__text-container']
24068               },
24069               components
24070             }];
24071         }
24072         return [];
24073       };
24074       const getComponents = () => {
24075         const components = getTextComponents();
24076         const resizeHandler = renderResizeHandler(editor, providersBackstage);
24077         return components.concat(resizeHandler.toArray());
24078       };
24079       return {
24080         dom: {
24081           tag: 'div',
24082           classes: ['tox-statusbar']
24083         },
24084         components: getComponents()
24085       };
24086     };
24088     const getLazyMothership = singleton => singleton.get().getOrDie('UI has not been rendered');
24089     const setup$3 = editor => {
24090       const isInline = editor.inline;
24091       const mode = isInline ? Inline : Iframe;
24092       const header = isStickyToolbar(editor) ? StickyHeader : StaticHeader;
24093       const lazySink = value$2();
24094       const lazyOuterContainer = value$2();
24095       const lazyMothership = value$2();
24096       const lazyUiMothership = value$2();
24097       const platform = detect$1();
24098       const isTouch = platform.deviceType.isTouch();
24099       const touchPlatformClass = 'tox-platform-touch';
24100       const deviceClasses = isTouch ? [touchPlatformClass] : [];
24101       const isToolbarBottom = isToolbarLocationBottom(editor);
24102       const toolbarMode = getToolbarMode(editor);
24103       const memAnchorBar = record({
24104         dom: {
24105           tag: 'div',
24106           classes: ['tox-anchorbar']
24107         }
24108       });
24109       const lazyHeader = () => lazyOuterContainer.get().bind(OuterContainer.getHeader);
24110       const lazySinkResult = () => Result.fromOption(lazySink.get(), 'UI has not been rendered');
24111       const lazyAnchorBar = () => lazyOuterContainer.get().bind(container => memAnchorBar.getOpt(container)).getOrDie('Could not find a anchor bar element');
24112       const lazyToolbar = () => lazyOuterContainer.get().bind(container => OuterContainer.getToolbar(container)).getOrDie('Could not find more toolbar element');
24113       const lazyThrobber = () => lazyOuterContainer.get().bind(container => OuterContainer.getThrobber(container)).getOrDie('Could not find throbber element');
24114       const backstage = init$7(lazySinkResult, editor, lazyAnchorBar);
24115       const makeHeaderPart = () => {
24116         const verticalDirAttributes = { attributes: { [Attribute]: isToolbarBottom ? AttributeValue.BottomToTop : AttributeValue.TopToBottom } };
24117         const partMenubar = OuterContainer.parts.menubar({
24118           dom: {
24119             tag: 'div',
24120             classes: ['tox-menubar']
24121           },
24122           backstage,
24123           onEscape: () => {
24124             editor.focus();
24125           }
24126         });
24127         const partToolbar = OuterContainer.parts.toolbar({
24128           dom: {
24129             tag: 'div',
24130             classes: ['tox-toolbar']
24131           },
24132           getSink: lazySinkResult,
24133           providers: backstage.shared.providers,
24134           onEscape: () => {
24135             editor.focus();
24136           },
24137           type: toolbarMode,
24138           lazyToolbar,
24139           lazyHeader: () => lazyHeader().getOrDie('Could not find header element'),
24140           ...verticalDirAttributes
24141         });
24142         const partMultipleToolbar = OuterContainer.parts['multiple-toolbar']({
24143           dom: {
24144             tag: 'div',
24145             classes: ['tox-toolbar-overlord']
24146           },
24147           providers: backstage.shared.providers,
24148           onEscape: () => {
24149             editor.focus();
24150           },
24151           type: toolbarMode
24152         });
24153         const hasMultipleToolbar = isMultipleToolbars(editor);
24154         const hasToolbar = isToolbarEnabled(editor);
24155         const hasMenubar = isMenubarEnabled(editor);
24156         const shouldHavePromotion = promotionEnabled(editor);
24157         const partPromotion = makePromotion();
24158         const getPartToolbar = () => {
24159           if (hasMultipleToolbar) {
24160             return [partMultipleToolbar];
24161           } else if (hasToolbar) {
24162             return [partToolbar];
24163           } else {
24164             return [];
24165           }
24166         };
24167         const menubarCollection = shouldHavePromotion ? [
24168           partPromotion,
24169           partMenubar
24170         ] : [partMenubar];
24171         return OuterContainer.parts.header({
24172           dom: {
24173             tag: 'div',
24174             classes: ['tox-editor-header'],
24175             ...verticalDirAttributes
24176           },
24177           components: flatten([
24178             hasMenubar ? menubarCollection : [],
24179             getPartToolbar(),
24180             useFixedContainer(editor) ? [] : [memAnchorBar.asSpec()]
24181           ]),
24182           sticky: isStickyToolbar(editor),
24183           editor,
24184           sharedBackstage: backstage.shared
24185         });
24186       };
24187       const makePromotion = () => {
24188         return OuterContainer.parts.promotion({
24189           dom: {
24190             tag: 'div',
24191             classes: ['tox-promotion']
24192           }
24193         });
24194       };
24195       const makeSidebarDefinition = () => {
24196         const partSocket = OuterContainer.parts.socket({
24197           dom: {
24198             tag: 'div',
24199             classes: ['tox-edit-area']
24200           }
24201         });
24202         const partSidebar = OuterContainer.parts.sidebar({
24203           dom: {
24204             tag: 'div',
24205             classes: ['tox-sidebar']
24206           }
24207         });
24208         return {
24209           dom: {
24210             tag: 'div',
24211             classes: ['tox-sidebar-wrap']
24212           },
24213           components: [
24214             partSocket,
24215             partSidebar
24216           ]
24217         };
24218       };
24219       const renderSink = () => {
24220         const uiContainer = getUiContainer(editor);
24221         const isGridUiContainer = eq(body(), uiContainer) && get$e(uiContainer, 'display') === 'grid';
24222         const sinkSpec = {
24223           dom: {
24224             tag: 'div',
24225             classes: [
24226               'tox',
24227               'tox-silver-sink',
24228               'tox-tinymce-aux'
24229             ].concat(deviceClasses),
24230             attributes: { ...global$8.isRtl() ? { dir: 'rtl' } : {} }
24231           },
24232           behaviours: derive$1([Positioning.config({ useFixed: () => header.isDocked(lazyHeader) })])
24233         };
24234         const reactiveWidthSpec = {
24235           dom: { styles: { width: document.body.clientWidth + 'px' } },
24236           events: derive$2([run$1(windowResize(), comp => {
24237               set$8(comp.element, 'width', document.body.clientWidth + 'px');
24238             })])
24239         };
24240         const sink = build$1(deepMerge(sinkSpec, isGridUiContainer ? reactiveWidthSpec : {}));
24241         const uiMothership = takeover(sink);
24242         lazySink.set(sink);
24243         lazyUiMothership.set(uiMothership);
24244         return {
24245           sink,
24246           uiMothership
24247         };
24248       };
24249       const renderContainer = () => {
24250         const partHeader = makeHeaderPart();
24251         const sidebarContainer = makeSidebarDefinition();
24252         const partThrobber = OuterContainer.parts.throbber({
24253           dom: {
24254             tag: 'div',
24255             classes: ['tox-throbber']
24256           },
24257           backstage
24258         });
24259         const statusbar = useStatusBar(editor) && !isInline ? Optional.some(renderStatusbar(editor, backstage.shared.providers)) : Optional.none();
24260         const editorComponents = flatten([
24261           isToolbarBottom ? [] : [partHeader],
24262           isInline ? [] : [sidebarContainer],
24263           isToolbarBottom ? [partHeader] : []
24264         ]);
24265         const editorContainer = {
24266           dom: {
24267             tag: 'div',
24268             classes: ['tox-editor-container']
24269           },
24270           components: editorComponents
24271         };
24272         const containerComponents = flatten([
24273           [editorContainer],
24274           isInline ? [] : statusbar.toArray(),
24275           [partThrobber]
24276         ]);
24277         const isHidden = isDistractionFree(editor);
24278         const attributes = {
24279           role: 'application',
24280           ...global$8.isRtl() ? { dir: 'rtl' } : {},
24281           ...isHidden ? { 'aria-hidden': 'true' } : {}
24282         };
24283         const outerContainer = build$1(OuterContainer.sketch({
24284           dom: {
24285             tag: 'div',
24286             classes: [
24287               'tox',
24288               'tox-tinymce'
24289             ].concat(isInline ? ['tox-tinymce-inline'] : []).concat(isToolbarBottom ? ['tox-tinymce--toolbar-bottom'] : []).concat(deviceClasses),
24290             styles: {
24291               visibility: 'hidden',
24292               ...isHidden ? {
24293                 opacity: '0',
24294                 border: '0'
24295               } : {}
24296             },
24297             attributes
24298           },
24299           components: containerComponents,
24300           behaviours: derive$1([
24301             receivingConfig(),
24302             Disabling.config({ disableClass: 'tox-tinymce--disabled' }),
24303             Keying.config({
24304               mode: 'cyclic',
24305               selector: '.tox-menubar, .tox-toolbar, .tox-toolbar__primary, .tox-toolbar__overflow--open, .tox-sidebar__overflow--open, .tox-statusbar__path, .tox-statusbar__wordcount, .tox-statusbar__branding a, .tox-statusbar__resize-handle'
24306             })
24307           ])
24308         }));
24309         const mothership = takeover(outerContainer);
24310         lazyOuterContainer.set(outerContainer);
24311         lazyMothership.set(mothership);
24312         return {
24313           mothership,
24314           outerContainer
24315         };
24316       };
24317       const setEditorSize = outerContainer => {
24318         const parsedHeight = numToPx(getHeightWithFallback(editor));
24319         const parsedWidth = numToPx(getWidthWithFallback(editor));
24320         if (!editor.inline) {
24321           if (isValidValue('div', 'width', parsedWidth)) {
24322             set$8(outerContainer.element, 'width', parsedWidth);
24323           }
24324           if (isValidValue('div', 'height', parsedHeight)) {
24325             set$8(outerContainer.element, 'height', parsedHeight);
24326           } else {
24327             set$8(outerContainer.element, 'height', '400px');
24328           }
24329         }
24330         return parsedHeight;
24331       };
24332       const setupShortcutsAndCommands = outerContainer => {
24333         editor.addShortcut('alt+F9', 'focus menubar', () => {
24334           OuterContainer.focusMenubar(outerContainer);
24335         });
24336         editor.addShortcut('alt+F10', 'focus toolbar', () => {
24337           OuterContainer.focusToolbar(outerContainer);
24338         });
24339         editor.addCommand('ToggleToolbarDrawer', () => {
24340           OuterContainer.toggleToolbarDrawer(outerContainer);
24341         });
24342         editor.addQueryStateHandler('ToggleToolbarDrawer', () => OuterContainer.isToolbarDrawerToggled(outerContainer));
24343       };
24344       const renderUI = () => {
24345         const {mothership, outerContainer} = renderContainer();
24346         const {uiMothership, sink} = renderSink();
24347         map$1(getToolbarGroups(editor), (toolbarGroupButtonConfig, name) => {
24348           editor.ui.registry.addGroupToolbarButton(name, toolbarGroupButtonConfig);
24349         });
24350         const {buttons, menuItems, contextToolbars, sidebars} = editor.ui.registry.getAll();
24351         const toolbarOpt = getMultipleToolbarsOption(editor);
24352         const rawUiConfig = {
24353           menuItems,
24354           menus: getMenus(editor),
24355           menubar: getMenubar(editor),
24356           toolbar: toolbarOpt.getOrThunk(() => getToolbar(editor)),
24357           allowToolbarGroups: toolbarMode === ToolbarMode$1.floating,
24358           buttons,
24359           sidebar: sidebars
24360         };
24361         setupShortcutsAndCommands(outerContainer);
24362         setup$b(editor, mothership, uiMothership);
24363         header.setup(editor, backstage.shared, lazyHeader);
24364         setup$6(editor, backstage);
24365         setup$5(editor, lazySinkResult, backstage);
24366         setup$8(editor);
24367         setup$7(editor, lazyThrobber, backstage.shared);
24368         register$9(editor, contextToolbars, sink, { backstage });
24369         setup$4(editor, sink);
24370         const elm = editor.getElement();
24371         const height = setEditorSize(outerContainer);
24372         const uiComponents = {
24373           mothership,
24374           uiMothership,
24375           outerContainer,
24376           sink
24377         };
24378         const args = {
24379           targetNode: elm,
24380           height
24381         };
24382         return mode.render(editor, uiComponents, rawUiConfig, backstage, args);
24383       };
24384       const getMothership = () => getLazyMothership(lazyMothership);
24385       const getUiMothership = () => getLazyMothership(lazyUiMothership);
24386       return {
24387         getMothership,
24388         getUiMothership,
24389         backstage,
24390         renderUI
24391       };
24392     };
24394     const describedBy = (describedElement, describeElement) => {
24395       const describeId = Optional.from(get$f(describedElement, 'id')).fold(() => {
24396         const id = generate$6('dialog-describe');
24397         set$9(describeElement, 'id', id);
24398         return id;
24399       }, identity);
24400       set$9(describedElement, 'aria-describedby', describeId);
24401     };
24403     const labelledBy = (labelledElement, labelElement) => {
24404       const labelId = getOpt(labelledElement, 'id').fold(() => {
24405         const id = generate$6('dialog-label');
24406         set$9(labelElement, 'id', id);
24407         return id;
24408       }, identity);
24409       set$9(labelledElement, 'aria-labelledby', labelId);
24410     };
24412     const schema$2 = constant$1([
24413       required$1('lazySink'),
24414       option$3('dragBlockClass'),
24415       defaultedFunction('getBounds', win),
24416       defaulted('useTabstopAt', always),
24417       defaulted('eventOrder', {}),
24418       field('modalBehaviours', [Keying]),
24419       onKeyboardHandler('onExecute'),
24420       onStrictKeyboardHandler('onEscape')
24421     ]);
24422     const basic = { sketch: identity };
24423     const parts$2 = constant$1([
24424       optional({
24425         name: 'draghandle',
24426         overrides: (detail, spec) => {
24427           return {
24428             behaviours: derive$1([Dragging.config({
24429                 mode: 'mouse',
24430                 getTarget: handle => {
24431                   return ancestor(handle, '[role="dialog"]').getOr(handle);
24432                 },
24433                 blockerClass: detail.dragBlockClass.getOrDie(new Error('The drag blocker class was not specified for a dialog with a drag handle: \n' + JSON.stringify(spec, null, 2)).message),
24434                 getBounds: detail.getDragBounds
24435               })])
24436           };
24437         }
24438       }),
24439       required({
24440         schema: [required$1('dom')],
24441         name: 'title'
24442       }),
24443       required({
24444         factory: basic,
24445         schema: [required$1('dom')],
24446         name: 'close'
24447       }),
24448       required({
24449         factory: basic,
24450         schema: [required$1('dom')],
24451         name: 'body'
24452       }),
24453       optional({
24454         factory: basic,
24455         schema: [required$1('dom')],
24456         name: 'footer'
24457       }),
24458       external({
24459         factory: {
24460           sketch: (spec, detail) => ({
24461             ...spec,
24462             dom: detail.dom,
24463             components: detail.components
24464           })
24465         },
24466         schema: [
24467           defaulted('dom', {
24468             tag: 'div',
24469             styles: {
24470               position: 'fixed',
24471               left: '0px',
24472               top: '0px',
24473               right: '0px',
24474               bottom: '0px'
24475             }
24476           }),
24477           defaulted('components', [])
24478         ],
24479         name: 'blocker'
24480       })
24481     ]);
24483     const factory$4 = (detail, components, spec, externals) => {
24484       const dialogComp = value$2();
24485       const showDialog = dialog => {
24486         dialogComp.set(dialog);
24487         const sink = detail.lazySink(dialog).getOrDie();
24488         const externalBlocker = externals.blocker();
24489         const blocker = sink.getSystem().build({
24490           ...externalBlocker,
24491           components: externalBlocker.components.concat([premade(dialog)]),
24492           behaviours: derive$1([
24493             Focusing.config({}),
24494             config('dialog-blocker-events', [runOnSource(focusin(), () => {
24495                 Keying.focusIn(dialog);
24496               })])
24497           ])
24498         });
24499         attach(sink, blocker);
24500         Keying.focusIn(dialog);
24501       };
24502       const hideDialog = dialog => {
24503         dialogComp.clear();
24504         parent(dialog.element).each(blockerDom => {
24505           dialog.getSystem().getByDom(blockerDom).each(blocker => {
24506             detach(blocker);
24507           });
24508         });
24509       };
24510       const getDialogBody = dialog => getPartOrDie(dialog, detail, 'body');
24511       const getDialogFooter = dialog => getPartOrDie(dialog, detail, 'footer');
24512       const setBusy = (dialog, getBusySpec) => {
24513         Blocking.block(dialog, getBusySpec);
24514       };
24515       const setIdle = dialog => {
24516         Blocking.unblock(dialog);
24517       };
24518       const modalEventsId = generate$6('modal-events');
24519       const eventOrder = {
24520         ...detail.eventOrder,
24521         [attachedToDom()]: [modalEventsId].concat(detail.eventOrder['alloy.system.attached'] || [])
24522       };
24523       return {
24524         uid: detail.uid,
24525         dom: detail.dom,
24526         components,
24527         apis: {
24528           show: showDialog,
24529           hide: hideDialog,
24530           getBody: getDialogBody,
24531           getFooter: getDialogFooter,
24532           setIdle,
24533           setBusy
24534         },
24535         eventOrder,
24536         domModification: {
24537           attributes: {
24538             'role': 'dialog',
24539             'aria-modal': 'true'
24540           }
24541         },
24542         behaviours: augment(detail.modalBehaviours, [
24543           Replacing.config({}),
24544           Keying.config({
24545             mode: 'cyclic',
24546             onEnter: detail.onExecute,
24547             onEscape: detail.onEscape,
24548             useTabstopAt: detail.useTabstopAt
24549           }),
24550           Blocking.config({ getRoot: dialogComp.get }),
24551           config(modalEventsId, [runOnAttached(c => {
24552               labelledBy(c.element, getPartOrDie(c, detail, 'title').element);
24553               describedBy(c.element, getPartOrDie(c, detail, 'body').element);
24554             })])
24555         ])
24556       };
24557     };
24558     const ModalDialog = composite({
24559       name: 'ModalDialog',
24560       configFields: schema$2(),
24561       partFields: parts$2(),
24562       factory: factory$4,
24563       apis: {
24564         show: (apis, dialog) => {
24565           apis.show(dialog);
24566         },
24567         hide: (apis, dialog) => {
24568           apis.hide(dialog);
24569         },
24570         getBody: (apis, dialog) => apis.getBody(dialog),
24571         getFooter: (apis, dialog) => apis.getFooter(dialog),
24572         setBusy: (apis, dialog, getBusySpec) => {
24573           apis.setBusy(dialog, getBusySpec);
24574         },
24575         setIdle: (apis, dialog) => {
24576           apis.setIdle(dialog);
24577         }
24578       }
24579     });
24581     const dialogToggleMenuItemSchema = objOf([
24582       type,
24583       name$1
24584     ].concat(commonMenuItemFields));
24585     const dialogToggleMenuItemDataProcessor = boolean;
24587     const baseFooterButtonFields = [
24588       generatedName('button'),
24589       optionalIcon,
24590       defaultedStringEnum('align', 'end', [
24591         'start',
24592         'end'
24593       ]),
24594       primary,
24595       enabled,
24596       optionStringEnum('buttonType', [
24597         'primary',
24598         'secondary'
24599       ])
24600     ];
24601     const dialogFooterButtonFields = [
24602       ...baseFooterButtonFields,
24603       text$1
24604     ];
24605     const normalFooterButtonFields = [
24606       requiredStringEnum('type', [
24607         'submit',
24608         'cancel',
24609         'custom'
24610       ]),
24611       ...dialogFooterButtonFields
24612     ];
24613     const menuFooterButtonFields = [
24614       requiredStringEnum('type', ['menu']),
24615       optionalText,
24616       optionalTooltip,
24617       optionalIcon,
24618       requiredArrayOf('items', dialogToggleMenuItemSchema),
24619       ...baseFooterButtonFields
24620     ];
24621     const dialogFooterButtonSchema = choose$1('type', {
24622       submit: normalFooterButtonFields,
24623       cancel: normalFooterButtonFields,
24624       custom: normalFooterButtonFields,
24625       menu: menuFooterButtonFields
24626     });
24628     const alertBannerFields = [
24629       type,
24630       text$1,
24631       requiredStringEnum('level', [
24632         'info',
24633         'warn',
24634         'error',
24635         'success'
24636       ]),
24637       icon,
24638       defaulted('url', '')
24639     ];
24640     const alertBannerSchema = objOf(alertBannerFields);
24642     const createBarFields = itemsField => [
24643       type,
24644       itemsField
24645     ];
24647     const buttonFields = [
24648       type,
24649       text$1,
24650       enabled,
24651       generatedName('button'),
24652       optionalIcon,
24653       borderless,
24654       optionStringEnum('buttonType', [
24655         'primary',
24656         'secondary',
24657         'toolbar'
24658       ]),
24659       primary
24660     ];
24661     const buttonSchema = objOf(buttonFields);
24663     const formComponentFields = [
24664       type,
24665       name$1
24666     ];
24667     const formComponentWithLabelFields = formComponentFields.concat([optionalLabel]);
24669     const checkboxFields = formComponentFields.concat([
24670       label,
24671       enabled
24672     ]);
24673     const checkboxSchema = objOf(checkboxFields);
24674     const checkboxDataProcessor = boolean;
24676     const collectionFields = formComponentWithLabelFields.concat([defaultedColumns('auto')]);
24677     const collectionSchema = objOf(collectionFields);
24678     const collectionDataProcessor = arrOfObj([
24679       value$1,
24680       text$1,
24681       icon
24682     ]);
24684     const colorInputFields = formComponentWithLabelFields;
24685     const colorInputSchema = objOf(colorInputFields);
24686     const colorInputDataProcessor = string;
24688     const colorPickerFields = formComponentWithLabelFields;
24689     const colorPickerSchema = objOf(colorPickerFields);
24690     const colorPickerDataProcessor = string;
24692     const customEditorFields = formComponentFields.concat([
24693       defaultedString('tag', 'textarea'),
24694       requiredString('scriptId'),
24695       requiredString('scriptUrl'),
24696       defaultedPostMsg('settings', undefined)
24697     ]);
24698     const customEditorFieldsOld = formComponentFields.concat([
24699       defaultedString('tag', 'textarea'),
24700       requiredFunction('init')
24701     ]);
24702     const customEditorSchema = valueOf(v => asRaw('customeditor.old', objOfOnly(customEditorFieldsOld), v).orThunk(() => asRaw('customeditor.new', objOfOnly(customEditorFields), v)));
24703     const customEditorDataProcessor = string;
24705     const dropZoneFields = formComponentWithLabelFields;
24706     const dropZoneSchema = objOf(dropZoneFields);
24707     const dropZoneDataProcessor = arrOfVal();
24709     const createGridFields = itemsField => [
24710       type,
24711       requiredNumber('columns'),
24712       itemsField
24713     ];
24715     const htmlPanelFields = [
24716       type,
24717       requiredString('html'),
24718       defaultedStringEnum('presets', 'presentation', [
24719         'presentation',
24720         'document'
24721       ])
24722     ];
24723     const htmlPanelSchema = objOf(htmlPanelFields);
24725     const iframeFields = formComponentWithLabelFields.concat([
24726       defaultedBoolean('sandboxed', true),
24727       defaultedBoolean('transparent', true)
24728     ]);
24729     const iframeSchema = objOf(iframeFields);
24730     const iframeDataProcessor = string;
24732     const imagePreviewSchema = objOf(formComponentFields.concat([optionString('height')]));
24733     const imagePreviewDataProcessor = objOf([
24734       requiredString('url'),
24735       optionNumber('zoom'),
24736       optionNumber('cachedWidth'),
24737       optionNumber('cachedHeight')
24738     ]);
24740     const inputFields = formComponentWithLabelFields.concat([
24741       optionString('inputMode'),
24742       optionString('placeholder'),
24743       defaultedBoolean('maximized', false),
24744       enabled
24745     ]);
24746     const inputSchema = objOf(inputFields);
24747     const inputDataProcessor = string;
24749     const createLabelFields = itemsField => [
24750       type,
24751       label,
24752       itemsField
24753     ];
24755     const listBoxSingleItemFields = [
24756       text$1,
24757       value$1
24758     ];
24759     const listBoxNestedItemFields = [
24760       text$1,
24761       requiredArrayOf('items', thunkOf('items', () => listBoxItemSchema))
24762     ];
24763     const listBoxItemSchema = oneOf([
24764       objOf(listBoxSingleItemFields),
24765       objOf(listBoxNestedItemFields)
24766     ]);
24767     const listBoxFields = formComponentWithLabelFields.concat([
24768       requiredArrayOf('items', listBoxItemSchema),
24769       enabled
24770     ]);
24771     const listBoxSchema = objOf(listBoxFields);
24772     const listBoxDataProcessor = string;
24774     const selectBoxFields = formComponentWithLabelFields.concat([
24775       requiredArrayOfObj('items', [
24776         text$1,
24777         value$1
24778       ]),
24779       defaultedNumber('size', 1),
24780       enabled
24781     ]);
24782     const selectBoxSchema = objOf(selectBoxFields);
24783     const selectBoxDataProcessor = string;
24785     const sizeInputFields = formComponentWithLabelFields.concat([
24786       defaultedBoolean('constrain', true),
24787       enabled
24788     ]);
24789     const sizeInputSchema = objOf(sizeInputFields);
24790     const sizeInputDataProcessor = objOf([
24791       requiredString('width'),
24792       requiredString('height')
24793     ]);
24795     const sliderFields = formComponentFields.concat([
24796       label,
24797       defaultedNumber('min', 0),
24798       defaultedNumber('max', 0)
24799     ]);
24800     const sliderSchema = objOf(sliderFields);
24801     const sliderInputDataProcessor = number;
24803     const tableFields = [
24804       type,
24805       requiredArrayOf('header', string),
24806       requiredArrayOf('cells', arrOf(string))
24807     ];
24808     const tableSchema = objOf(tableFields);
24810     const textAreaFields = formComponentWithLabelFields.concat([
24811       optionString('placeholder'),
24812       defaultedBoolean('maximized', false),
24813       enabled
24814     ]);
24815     const textAreaSchema = objOf(textAreaFields);
24816     const textAreaDataProcessor = string;
24818     const urlInputFields = formComponentWithLabelFields.concat([
24819       defaultedStringEnum('filetype', 'file', [
24820         'image',
24821         'media',
24822         'file'
24823       ]),
24824       enabled
24825     ]);
24826     const urlInputSchema = objOf(urlInputFields);
24827     const urlInputDataProcessor = objOf([
24828       value$1,
24829       defaultedMeta
24830     ]);
24832     const createItemsField = name => field$1('items', 'items', required$2(), arrOf(valueOf(v => asRaw(`Checking item of ${ name }`, itemSchema, v).fold(sErr => Result.error(formatError(sErr)), passValue => Result.value(passValue)))));
24833     const itemSchema = valueThunk(() => choose$2('type', {
24834       alertbanner: alertBannerSchema,
24835       bar: objOf(createBarFields(createItemsField('bar'))),
24836       button: buttonSchema,
24837       checkbox: checkboxSchema,
24838       colorinput: colorInputSchema,
24839       colorpicker: colorPickerSchema,
24840       dropzone: dropZoneSchema,
24841       grid: objOf(createGridFields(createItemsField('grid'))),
24842       iframe: iframeSchema,
24843       input: inputSchema,
24844       listbox: listBoxSchema,
24845       selectbox: selectBoxSchema,
24846       sizeinput: sizeInputSchema,
24847       slider: sliderSchema,
24848       textarea: textAreaSchema,
24849       urlinput: urlInputSchema,
24850       customeditor: customEditorSchema,
24851       htmlpanel: htmlPanelSchema,
24852       imagepreview: imagePreviewSchema,
24853       collection: collectionSchema,
24854       label: objOf(createLabelFields(createItemsField('label'))),
24855       table: tableSchema,
24856       panel: panelSchema
24857     }));
24858     const panelFields = [
24859       type,
24860       defaulted('classes', []),
24861       requiredArrayOf('items', itemSchema)
24862     ];
24863     const panelSchema = objOf(panelFields);
24865     const tabFields = [
24866       generatedName('tab'),
24867       title,
24868       requiredArrayOf('items', itemSchema)
24869     ];
24870     const tabPanelFields = [
24871       type,
24872       requiredArrayOfObj('tabs', tabFields)
24873     ];
24874     const tabPanelSchema = objOf(tabPanelFields);
24876     const dialogButtonFields = dialogFooterButtonFields;
24877     const dialogButtonSchema = dialogFooterButtonSchema;
24878     const dialogSchema = objOf([
24879       requiredString('title'),
24880       requiredOf('body', choose$2('type', {
24881         panel: panelSchema,
24882         tabpanel: tabPanelSchema
24883       })),
24884       defaultedString('size', 'normal'),
24885       requiredArrayOf('buttons', dialogButtonSchema),
24886       defaulted('initialData', {}),
24887       defaultedFunction('onAction', noop),
24888       defaultedFunction('onChange', noop),
24889       defaultedFunction('onSubmit', noop),
24890       defaultedFunction('onClose', noop),
24891       defaultedFunction('onCancel', noop),
24892       defaultedFunction('onTabChange', noop)
24893     ]);
24894     const createDialog = spec => asRaw('dialog', dialogSchema, spec);
24896     const urlDialogButtonSchema = objOf([
24897       requiredStringEnum('type', [
24898         'cancel',
24899         'custom'
24900       ]),
24901       ...dialogButtonFields
24902     ]);
24903     const urlDialogSchema = objOf([
24904       requiredString('title'),
24905       requiredString('url'),
24906       optionNumber('height'),
24907       optionNumber('width'),
24908       optionArrayOf('buttons', urlDialogButtonSchema),
24909       defaultedFunction('onAction', noop),
24910       defaultedFunction('onCancel', noop),
24911       defaultedFunction('onClose', noop),
24912       defaultedFunction('onMessage', noop)
24913     ]);
24914     const createUrlDialog = spec => asRaw('dialog', urlDialogSchema, spec);
24916     const getAllObjects = obj => {
24917       if (isObject(obj)) {
24918         return [obj].concat(bind$3(values(obj), getAllObjects));
24919       } else if (isArray(obj)) {
24920         return bind$3(obj, getAllObjects);
24921       } else {
24922         return [];
24923       }
24924     };
24926     const isNamedItem = obj => isString(obj.type) && isString(obj.name);
24927     const dataProcessors = {
24928       checkbox: checkboxDataProcessor,
24929       colorinput: colorInputDataProcessor,
24930       colorpicker: colorPickerDataProcessor,
24931       dropzone: dropZoneDataProcessor,
24932       input: inputDataProcessor,
24933       iframe: iframeDataProcessor,
24934       imagepreview: imagePreviewDataProcessor,
24935       selectbox: selectBoxDataProcessor,
24936       sizeinput: sizeInputDataProcessor,
24937       slider: sliderInputDataProcessor,
24938       listbox: listBoxDataProcessor,
24939       size: sizeInputDataProcessor,
24940       textarea: textAreaDataProcessor,
24941       urlinput: urlInputDataProcessor,
24942       customeditor: customEditorDataProcessor,
24943       collection: collectionDataProcessor,
24944       togglemenuitem: dialogToggleMenuItemDataProcessor
24945     };
24946     const getDataProcessor = item => Optional.from(dataProcessors[item.type]);
24947     const getNamedItems = structure => filter$2(getAllObjects(structure), isNamedItem);
24949     const createDataValidator = structure => {
24950       const namedItems = getNamedItems(structure);
24951       const fields = bind$3(namedItems, item => getDataProcessor(item).fold(() => [], schema => [requiredOf(item.name, schema)]));
24952       return objOf(fields);
24953     };
24955     const extract = structure => {
24956       const internalDialog = getOrDie(createDialog(structure));
24957       const dataValidator = createDataValidator(structure);
24958       const initialData = structure.initialData ?? {};
24959       return {
24960         internalDialog,
24961         dataValidator,
24962         initialData
24963       };
24964     };
24965     const DialogManager = {
24966       open: (factory, structure) => {
24967         const extraction = extract(structure);
24968         return factory(extraction.internalDialog, extraction.initialData, extraction.dataValidator);
24969       },
24970       openUrl: (factory, structure) => {
24971         const internalDialog = getOrDie(createUrlDialog(structure));
24972         return factory(internalDialog);
24973       },
24974       redial: structure => extract(structure)
24975     };
24977     const toValidValues = values => {
24978       const errors = [];
24979       const result = {};
24980       each(values, (value, name) => {
24981         value.fold(() => {
24982           errors.push(name);
24983         }, v => {
24984           result[name] = v;
24985         });
24986       });
24987       return errors.length > 0 ? Result.error(errors) : Result.value(result);
24988     };
24990     const renderBodyPanel = (spec, dialogData, backstage) => {
24991       const memForm = record(Form.sketch(parts => ({
24992         dom: {
24993           tag: 'div',
24994           classes: ['tox-form'].concat(spec.classes)
24995         },
24996         components: map$2(spec.items, item => interpretInForm(parts, item, dialogData, backstage))
24997       })));
24998       return {
24999         dom: {
25000           tag: 'div',
25001           classes: ['tox-dialog__body']
25002         },
25003         components: [{
25004             dom: {
25005               tag: 'div',
25006               classes: ['tox-dialog__body-content']
25007             },
25008             components: [memForm.asSpec()]
25009           }],
25010         behaviours: derive$1([
25011           Keying.config({
25012             mode: 'acyclic',
25013             useTabstopAt: not(isPseudoStop)
25014           }),
25015           ComposingConfigs.memento(memForm),
25016           RepresentingConfigs.memento(memForm, {
25017             postprocess: formValue => toValidValues(formValue).fold(err => {
25018               console.error(err);
25019               return {};
25020             }, identity)
25021           })
25022         ])
25023       };
25024     };
25026     const factory$3 = (detail, _spec) => ({
25027       uid: detail.uid,
25028       dom: detail.dom,
25029       components: detail.components,
25030       events: events$a(detail.action),
25031       behaviours: augment(detail.tabButtonBehaviours, [
25032         Focusing.config({}),
25033         Keying.config({
25034           mode: 'execution',
25035           useSpace: true,
25036           useEnter: true
25037         }),
25038         Representing.config({
25039           store: {
25040             mode: 'memory',
25041             initialValue: detail.value
25042           }
25043         })
25044       ]),
25045       domModification: detail.domModification
25046     });
25047     const TabButton = single({
25048       name: 'TabButton',
25049       configFields: [
25050         defaulted('uid', undefined),
25051         required$1('value'),
25052         field$1('dom', 'dom', mergeWithThunk(() => ({
25053           attributes: {
25054             'role': 'tab',
25055             'id': generate$6('aria'),
25056             'aria-selected': 'false'
25057           }
25058         })), anyValue()),
25059         option$3('action'),
25060         defaulted('domModification', {}),
25061         field('tabButtonBehaviours', [
25062           Focusing,
25063           Keying,
25064           Representing
25065         ]),
25066         required$1('view')
25067       ],
25068       factory: factory$3
25069     });
25071     const schema$1 = constant$1([
25072       required$1('tabs'),
25073       required$1('dom'),
25074       defaulted('clickToDismiss', false),
25075       field('tabbarBehaviours', [
25076         Highlighting,
25077         Keying
25078       ]),
25079       markers$1([
25080         'tabClass',
25081         'selectedClass'
25082       ])
25083     ]);
25084     const tabsPart = group({
25085       factory: TabButton,
25086       name: 'tabs',
25087       unit: 'tab',
25088       overrides: barDetail => {
25089         const dismissTab$1 = (tabbar, button) => {
25090           Highlighting.dehighlight(tabbar, button);
25091           emitWith(tabbar, dismissTab(), {
25092             tabbar,
25093             button
25094           });
25095         };
25096         const changeTab$1 = (tabbar, button) => {
25097           Highlighting.highlight(tabbar, button);
25098           emitWith(tabbar, changeTab(), {
25099             tabbar,
25100             button
25101           });
25102         };
25103         return {
25104           action: button => {
25105             const tabbar = button.getSystem().getByUid(barDetail.uid).getOrDie();
25106             const activeButton = Highlighting.isHighlighted(tabbar, button);
25107             const response = (() => {
25108               if (activeButton && barDetail.clickToDismiss) {
25109                 return dismissTab$1;
25110               } else if (!activeButton) {
25111                 return changeTab$1;
25112               } else {
25113                 return noop;
25114               }
25115             })();
25116             response(tabbar, button);
25117           },
25118           domModification: { classes: [barDetail.markers.tabClass] }
25119         };
25120       }
25121     });
25122     const parts$1 = constant$1([tabsPart]);
25124     const factory$2 = (detail, components, _spec, _externals) => ({
25125       'uid': detail.uid,
25126       'dom': detail.dom,
25127       components,
25128       'debug.sketcher': 'Tabbar',
25129       'domModification': { attributes: { role: 'tablist' } },
25130       'behaviours': augment(detail.tabbarBehaviours, [
25131         Highlighting.config({
25132           highlightClass: detail.markers.selectedClass,
25133           itemClass: detail.markers.tabClass,
25134           onHighlight: (tabbar, tab) => {
25135             set$9(tab.element, 'aria-selected', 'true');
25136           },
25137           onDehighlight: (tabbar, tab) => {
25138             set$9(tab.element, 'aria-selected', 'false');
25139           }
25140         }),
25141         Keying.config({
25142           mode: 'flow',
25143           getInitial: tabbar => {
25144             return Highlighting.getHighlighted(tabbar).map(tab => tab.element);
25145           },
25146           selector: '.' + detail.markers.tabClass,
25147           executeOnMove: true
25148         })
25149       ])
25150     });
25151     const Tabbar = composite({
25152       name: 'Tabbar',
25153       configFields: schema$1(),
25154       partFields: parts$1(),
25155       factory: factory$2
25156     });
25158     const factory$1 = (detail, _spec) => ({
25159       uid: detail.uid,
25160       dom: detail.dom,
25161       behaviours: augment(detail.tabviewBehaviours, [Replacing.config({})]),
25162       domModification: { attributes: { role: 'tabpanel' } }
25163     });
25164     const Tabview = single({
25165       name: 'Tabview',
25166       configFields: [field('tabviewBehaviours', [Replacing])],
25167       factory: factory$1
25168     });
25170     const schema = constant$1([
25171       defaulted('selectFirst', true),
25172       onHandler('onChangeTab'),
25173       onHandler('onDismissTab'),
25174       defaulted('tabs', []),
25175       field('tabSectionBehaviours', [])
25176     ]);
25177     const barPart = required({
25178       factory: Tabbar,
25179       schema: [
25180         required$1('dom'),
25181         requiredObjOf('markers', [
25182           required$1('tabClass'),
25183           required$1('selectedClass')
25184         ])
25185       ],
25186       name: 'tabbar',
25187       defaults: detail => {
25188         return { tabs: detail.tabs };
25189       }
25190     });
25191     const viewPart = required({
25192       factory: Tabview,
25193       name: 'tabview'
25194     });
25195     const parts = constant$1([
25196       barPart,
25197       viewPart
25198     ]);
25200     const factory = (detail, components, _spec, _externals) => {
25201       const changeTab$1 = button => {
25202         const tabValue = Representing.getValue(button);
25203         getPart(button, detail, 'tabview').each(tabview => {
25204           const tabWithValue = find$5(detail.tabs, t => t.value === tabValue);
25205           tabWithValue.each(tabData => {
25206             const panel = tabData.view();
25207             getOpt(button.element, 'id').each(id => {
25208               set$9(tabview.element, 'aria-labelledby', id);
25209             });
25210             Replacing.set(tabview, panel);
25211             detail.onChangeTab(tabview, button, panel);
25212           });
25213         });
25214       };
25215       const changeTabBy = (section, byPred) => {
25216         getPart(section, detail, 'tabbar').each(tabbar => {
25217           byPred(tabbar).each(emitExecute);
25218         });
25219       };
25220       return {
25221         uid: detail.uid,
25222         dom: detail.dom,
25223         components,
25224         behaviours: get$3(detail.tabSectionBehaviours),
25225         events: derive$2(flatten([
25226           detail.selectFirst ? [runOnAttached((section, _simulatedEvent) => {
25227               changeTabBy(section, Highlighting.getFirst);
25228             })] : [],
25229           [
25230             run$1(changeTab(), (section, simulatedEvent) => {
25231               const button = simulatedEvent.event.button;
25232               changeTab$1(button);
25233             }),
25234             run$1(dismissTab(), (section, simulatedEvent) => {
25235               const button = simulatedEvent.event.button;
25236               detail.onDismissTab(section, button);
25237             })
25238           ]
25239         ])),
25240         apis: {
25241           getViewItems: section => {
25242             return getPart(section, detail, 'tabview').map(tabview => Replacing.contents(tabview)).getOr([]);
25243           },
25244           showTab: (section, tabKey) => {
25245             const getTabIfNotActive = tabbar => {
25246               const candidates = Highlighting.getCandidates(tabbar);
25247               const optTab = find$5(candidates, c => Representing.getValue(c) === tabKey);
25248               return optTab.filter(tab => !Highlighting.isHighlighted(tabbar, tab));
25249             };
25250             changeTabBy(section, getTabIfNotActive);
25251           }
25252         }
25253       };
25254     };
25255     const TabSection = composite({
25256       name: 'TabSection',
25257       configFields: schema(),
25258       partFields: parts(),
25259       factory,
25260       apis: {
25261         getViewItems: (apis, component) => apis.getViewItems(component),
25262         showTab: (apis, component, tabKey) => {
25263           apis.showTab(component, tabKey);
25264         }
25265       }
25266     });
25268     const measureHeights = (allTabs, tabview, tabviewComp) => map$2(allTabs, (_tab, i) => {
25269       Replacing.set(tabviewComp, allTabs[i].view());
25270       const rect = tabview.dom.getBoundingClientRect();
25271       Replacing.set(tabviewComp, []);
25272       return rect.height;
25273     });
25274     const getMaxHeight = heights => head(sort(heights, (a, b) => {
25275       if (a > b) {
25276         return -1;
25277       } else if (a < b) {
25278         return +1;
25279       } else {
25280         return 0;
25281       }
25282     }));
25283     const getMaxTabviewHeight = (dialog, tabview, tablist) => {
25284       const documentElement$1 = documentElement(dialog).dom;
25285       const rootElm = ancestor(dialog, '.tox-dialog-wrap').getOr(dialog);
25286       const isFixed = get$e(rootElm, 'position') === 'fixed';
25287       let maxHeight;
25288       if (isFixed) {
25289         maxHeight = Math.max(documentElement$1.clientHeight, window.innerHeight);
25290       } else {
25291         maxHeight = Math.max(documentElement$1.offsetHeight, documentElement$1.scrollHeight);
25292       }
25293       const tabviewHeight = get$d(tabview);
25294       const isTabListBeside = tabview.dom.offsetLeft >= tablist.dom.offsetLeft + get$c(tablist);
25295       const currentTabHeight = isTabListBeside ? Math.max(get$d(tablist), tabviewHeight) : tabviewHeight;
25296       const dialogTopMargin = parseInt(get$e(dialog, 'margin-top'), 10) || 0;
25297       const dialogBottomMargin = parseInt(get$e(dialog, 'margin-bottom'), 10) || 0;
25298       const dialogHeight = get$d(dialog) + dialogTopMargin + dialogBottomMargin;
25299       const chromeHeight = dialogHeight - currentTabHeight;
25300       return maxHeight - chromeHeight;
25301     };
25302     const showTab = (allTabs, comp) => {
25303       head(allTabs).each(tab => TabSection.showTab(comp, tab.value));
25304     };
25305     const setTabviewHeight = (tabview, height) => {
25306       set$8(tabview, 'height', height + 'px');
25307       set$8(tabview, 'flex-basis', height + 'px');
25308     };
25309     const updateTabviewHeight = (dialogBody, tabview, maxTabHeight) => {
25310       ancestor(dialogBody, '[role="dialog"]').each(dialog => {
25311         descendant(dialog, '[role="tablist"]').each(tablist => {
25312           maxTabHeight.get().map(height => {
25313             set$8(tabview, 'height', '0');
25314             set$8(tabview, 'flex-basis', '0');
25315             return Math.min(height, getMaxTabviewHeight(dialog, tabview, tablist));
25316           }).each(height => {
25317             setTabviewHeight(tabview, height);
25318           });
25319         });
25320       });
25321     };
25322     const getTabview = dialog => descendant(dialog, '[role="tabpanel"]');
25323     const smartMode = allTabs => {
25324       const maxTabHeight = value$2();
25325       const extraEvents = [
25326         runOnAttached(comp => {
25327           const dialog = comp.element;
25328           getTabview(dialog).each(tabview => {
25329             set$8(tabview, 'visibility', 'hidden');
25330             comp.getSystem().getByDom(tabview).toOptional().each(tabviewComp => {
25331               const heights = measureHeights(allTabs, tabview, tabviewComp);
25332               const maxTabHeightOpt = getMaxHeight(heights);
25333               maxTabHeightOpt.fold(maxTabHeight.clear, maxTabHeight.set);
25334             });
25335             updateTabviewHeight(dialog, tabview, maxTabHeight);
25336             remove$6(tabview, 'visibility');
25337             showTab(allTabs, comp);
25338             requestAnimationFrame(() => {
25339               updateTabviewHeight(dialog, tabview, maxTabHeight);
25340             });
25341           });
25342         }),
25343         run$1(windowResize(), comp => {
25344           const dialog = comp.element;
25345           getTabview(dialog).each(tabview => {
25346             updateTabviewHeight(dialog, tabview, maxTabHeight);
25347           });
25348         }),
25349         run$1(formResizeEvent, (comp, _se) => {
25350           const dialog = comp.element;
25351           getTabview(dialog).each(tabview => {
25352             const oldFocus = active$1(getRootNode(tabview));
25353             set$8(tabview, 'visibility', 'hidden');
25354             const oldHeight = getRaw(tabview, 'height').map(h => parseInt(h, 10));
25355             remove$6(tabview, 'height');
25356             remove$6(tabview, 'flex-basis');
25357             const newHeight = tabview.dom.getBoundingClientRect().height;
25358             const hasGrown = oldHeight.forall(h => newHeight > h);
25359             if (hasGrown) {
25360               maxTabHeight.set(newHeight);
25361               updateTabviewHeight(dialog, tabview, maxTabHeight);
25362             } else {
25363               oldHeight.each(h => {
25364                 setTabviewHeight(tabview, h);
25365               });
25366             }
25367             remove$6(tabview, 'visibility');
25368             oldFocus.each(focus$3);
25369           });
25370         })
25371       ];
25372       const selectFirst = false;
25373       return {
25374         extraEvents,
25375         selectFirst
25376       };
25377     };
25379     const SendDataToSectionChannel = 'send-data-to-section';
25380     const SendDataToViewChannel = 'send-data-to-view';
25381     const renderTabPanel = (spec, dialogData, backstage) => {
25382       const storedValue = Cell({});
25383       const updateDataWithForm = form => {
25384         const formData = Representing.getValue(form);
25385         const validData = toValidValues(formData).getOr({});
25386         const currentData = storedValue.get();
25387         const newData = deepMerge(currentData, validData);
25388         storedValue.set(newData);
25389       };
25390       const setDataOnForm = form => {
25391         const tabData = storedValue.get();
25392         Representing.setValue(form, tabData);
25393       };
25394       const oldTab = Cell(null);
25395       const allTabs = map$2(spec.tabs, tab => {
25396         return {
25397           value: tab.name,
25398           dom: {
25399             tag: 'div',
25400             classes: ['tox-dialog__body-nav-item']
25401           },
25402           components: [text$2(backstage.shared.providers.translate(tab.title))],
25403           view: () => {
25404             return [Form.sketch(parts => ({
25405                 dom: {
25406                   tag: 'div',
25407                   classes: ['tox-form']
25408                 },
25409                 components: map$2(tab.items, item => interpretInForm(parts, item, dialogData, backstage)),
25410                 formBehaviours: derive$1([
25411                   Keying.config({
25412                     mode: 'acyclic',
25413                     useTabstopAt: not(isPseudoStop)
25414                   }),
25415                   config('TabView.form.events', [
25416                     runOnAttached(setDataOnForm),
25417                     runOnDetached(updateDataWithForm)
25418                   ]),
25419                   Receiving.config({
25420                     channels: wrapAll([
25421                       {
25422                         key: SendDataToSectionChannel,
25423                         value: { onReceive: updateDataWithForm }
25424                       },
25425                       {
25426                         key: SendDataToViewChannel,
25427                         value: { onReceive: setDataOnForm }
25428                       }
25429                     ])
25430                   })
25431                 ])
25432               }))];
25433           }
25434         };
25435       });
25436       const tabMode = smartMode(allTabs);
25437       return TabSection.sketch({
25438         dom: {
25439           tag: 'div',
25440           classes: ['tox-dialog__body']
25441         },
25442         onChangeTab: (section, button, _viewItems) => {
25443           const name = Representing.getValue(button);
25444           emitWith(section, formTabChangeEvent, {
25445             name,
25446             oldName: oldTab.get()
25447           });
25448           oldTab.set(name);
25449         },
25450         tabs: allTabs,
25451         components: [
25452           TabSection.parts.tabbar({
25453             dom: {
25454               tag: 'div',
25455               classes: ['tox-dialog__body-nav']
25456             },
25457             components: [Tabbar.parts.tabs({})],
25458             markers: {
25459               tabClass: 'tox-tab',
25460               selectedClass: 'tox-dialog__body-nav-item--active'
25461             },
25462             tabbarBehaviours: derive$1([Tabstopping.config({})])
25463           }),
25464           TabSection.parts.tabview({
25465             dom: {
25466               tag: 'div',
25467               classes: ['tox-dialog__body-content']
25468             }
25469           })
25470         ],
25471         selectFirst: tabMode.selectFirst,
25472         tabSectionBehaviours: derive$1([
25473           config('tabpanel', tabMode.extraEvents),
25474           Keying.config({ mode: 'acyclic' }),
25475           Composing.config({ find: comp => head(TabSection.getViewItems(comp)) }),
25476           RepresentingConfigs.withComp(Optional.none(), tsection => {
25477             tsection.getSystem().broadcastOn([SendDataToSectionChannel], {});
25478             return storedValue.get();
25479           }, (tsection, value) => {
25480             storedValue.set(value);
25481             tsection.getSystem().broadcastOn([SendDataToViewChannel], {});
25482           })
25483         ])
25484       });
25485     };
25487     const dialogChannel = generate$6('update-dialog');
25488     const titleChannel = generate$6('update-title');
25489     const bodyChannel = generate$6('update-body');
25490     const footerChannel = generate$6('update-footer');
25491     const bodySendMessageChannel = generate$6('body-send-message');
25493     const renderBody = (spec, dialogId, contentId, backstage, ariaAttrs) => {
25494       const renderComponents = incoming => {
25495         const body = incoming.body;
25496         switch (body.type) {
25497         case 'tabpanel': {
25498             return [renderTabPanel(body, incoming.initialData, backstage)];
25499           }
25500         default: {
25501             return [renderBodyPanel(body, incoming.initialData, backstage)];
25502           }
25503         }
25504       };
25505       const updateState = (_comp, incoming) => Optional.some({ isTabPanel: () => incoming.body.type === 'tabpanel' });
25506       const ariaAttributes = { 'aria-live': 'polite' };
25507       return {
25508         dom: {
25509           tag: 'div',
25510           classes: ['tox-dialog__content-js'],
25511           attributes: {
25512             ...contentId.map(x => ({ id: x })).getOr({}),
25513             ...ariaAttrs ? ariaAttributes : {}
25514           }
25515         },
25516         components: [],
25517         behaviours: derive$1([
25518           ComposingConfigs.childAt(0),
25519           Reflecting.config({
25520             channel: `${ bodyChannel }-${ dialogId }`,
25521             updateState,
25522             renderComponents,
25523             initialData: spec
25524           })
25525         ])
25526       };
25527     };
25528     const renderInlineBody = (spec, dialogId, contentId, backstage, ariaAttrs) => renderBody(spec, dialogId, Optional.some(contentId), backstage, ariaAttrs);
25529     const renderModalBody = (spec, dialogId, backstage) => {
25530       const bodySpec = renderBody(spec, dialogId, Optional.none(), backstage, false);
25531       return ModalDialog.parts.body(bodySpec);
25532     };
25533     const renderIframeBody = spec => {
25534       const bodySpec = {
25535         dom: {
25536           tag: 'div',
25537           classes: ['tox-dialog__content-js']
25538         },
25539         components: [{
25540             dom: {
25541               tag: 'div',
25542               classes: ['tox-dialog__body-iframe']
25543             },
25544             components: [craft({
25545                 dom: {
25546                   tag: 'iframe',
25547                   attributes: { src: spec.url }
25548                 },
25549                 behaviours: derive$1([
25550                   Tabstopping.config({}),
25551                   Focusing.config({})
25552                 ])
25553               })]
25554           }],
25555         behaviours: derive$1([Keying.config({
25556             mode: 'acyclic',
25557             useTabstopAt: not(isPseudoStop)
25558           })])
25559       };
25560       return ModalDialog.parts.body(bodySpec);
25561     };
25563     function _typeof(obj) {
25564       '@babel/helpers - typeof';
25565       return _typeof = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? function (obj) {
25566         return typeof obj;
25567       } : function (obj) {
25568         return obj && 'function' == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj;
25569       }, _typeof(obj);
25570     }
25571     function _setPrototypeOf(o, p) {
25572       _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
25573         o.__proto__ = p;
25574         return o;
25575       };
25576       return _setPrototypeOf(o, p);
25577     }
25578     function _isNativeReflectConstruct() {
25579       if (typeof Reflect === 'undefined' || !Reflect.construct)
25580         return false;
25581       if (Reflect.construct.sham)
25582         return false;
25583       if (typeof Proxy === 'function')
25584         return true;
25585       try {
25586         Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {
25587         }));
25588         return true;
25589       } catch (e) {
25590         return false;
25591       }
25592     }
25593     function _construct(Parent, args, Class) {
25594       if (_isNativeReflectConstruct()) {
25595         _construct = Reflect.construct;
25596       } else {
25597         _construct = function _construct(Parent, args, Class) {
25598           var a = [null];
25599           a.push.apply(a, args);
25600           var Constructor = Function.bind.apply(Parent, a);
25601           var instance = new Constructor();
25602           if (Class)
25603             _setPrototypeOf(instance, Class.prototype);
25604           return instance;
25605         };
25606       }
25607       return _construct.apply(null, arguments);
25608     }
25609     function _toConsumableArray(arr) {
25610       return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
25611     }
25612     function _arrayWithoutHoles(arr) {
25613       if (Array.isArray(arr))
25614         return _arrayLikeToArray(arr);
25615     }
25616     function _iterableToArray(iter) {
25617       if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null)
25618         return Array.from(iter);
25619     }
25620     function _unsupportedIterableToArray(o, minLen) {
25621       if (!o)
25622         return;
25623       if (typeof o === 'string')
25624         return _arrayLikeToArray(o, minLen);
25625       var n = Object.prototype.toString.call(o).slice(8, -1);
25626       if (n === 'Object' && o.constructor)
25627         n = o.constructor.name;
25628       if (n === 'Map' || n === 'Set')
25629         return Array.from(o);
25630       if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
25631         return _arrayLikeToArray(o, minLen);
25632     }
25633     function _arrayLikeToArray(arr, len) {
25634       if (len == null || len > arr.length)
25635         len = arr.length;
25636       for (var i = 0, arr2 = new Array(len); i < len; i++)
25637         arr2[i] = arr[i];
25638       return arr2;
25639     }
25640     function _nonIterableSpread() {
25641       throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.');
25642     }
25643     var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
25644     var freeze = Object.freeze, seal = Object.seal, create = Object.create;
25645     var _ref = typeof Reflect !== 'undefined' && Reflect, apply = _ref.apply, construct = _ref.construct;
25646     if (!apply) {
25647       apply = function apply(fun, thisValue, args) {
25648         return fun.apply(thisValue, args);
25649       };
25650     }
25651     if (!freeze) {
25652       freeze = function freeze(x) {
25653         return x;
25654       };
25655     }
25656     if (!seal) {
25657       seal = function seal(x) {
25658         return x;
25659       };
25660     }
25661     if (!construct) {
25662       construct = function construct(Func, args) {
25663         return _construct(Func, _toConsumableArray(args));
25664       };
25665     }
25666     var arrayForEach = unapply(Array.prototype.forEach);
25667     var arrayPop = unapply(Array.prototype.pop);
25668     var arrayPush = unapply(Array.prototype.push);
25669     var stringToLowerCase = unapply(String.prototype.toLowerCase);
25670     var stringMatch = unapply(String.prototype.match);
25671     var stringReplace = unapply(String.prototype.replace);
25672     var stringIndexOf = unapply(String.prototype.indexOf);
25673     var stringTrim = unapply(String.prototype.trim);
25674     var regExpTest = unapply(RegExp.prototype.test);
25675     var typeErrorCreate = unconstruct(TypeError);
25676     function unapply(func) {
25677       return function (thisArg) {
25678         for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
25679           args[_key - 1] = arguments[_key];
25680         }
25681         return apply(func, thisArg, args);
25682       };
25683     }
25684     function unconstruct(func) {
25685       return function () {
25686         for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
25687           args[_key2] = arguments[_key2];
25688         }
25689         return construct(func, args);
25690       };
25691     }
25692     function addToSet(set, array) {
25693       if (setPrototypeOf) {
25694         setPrototypeOf(set, null);
25695       }
25696       var l = array.length;
25697       while (l--) {
25698         var element = array[l];
25699         if (typeof element === 'string') {
25700           var lcElement = stringToLowerCase(element);
25701           if (lcElement !== element) {
25702             if (!isFrozen(array)) {
25703               array[l] = lcElement;
25704             }
25705             element = lcElement;
25706           }
25707         }
25708         set[element] = true;
25709       }
25710       return set;
25711     }
25712     function clone(object) {
25713       var newObject = create(null);
25714       var property;
25715       for (property in object) {
25716         if (apply(hasOwnProperty, object, [property])) {
25717           newObject[property] = object[property];
25718         }
25719       }
25720       return newObject;
25721     }
25722     function lookupGetter(object, prop) {
25723       while (object !== null) {
25724         var desc = getOwnPropertyDescriptor(object, prop);
25725         if (desc) {
25726           if (desc.get) {
25727             return unapply(desc.get);
25728           }
25729           if (typeof desc.value === 'function') {
25730             return unapply(desc.value);
25731           }
25732         }
25733         object = getPrototypeOf(object);
25734       }
25735       function fallbackValue(element) {
25736         console.warn('fallback value for', element);
25737         return null;
25738       }
25739       return fallbackValue;
25740     }
25741     var html$1 = freeze([
25742       'a',
25743       'abbr',
25744       'acronym',
25745       'address',
25746       'area',
25747       'article',
25748       'aside',
25749       'audio',
25750       'b',
25751       'bdi',
25752       'bdo',
25753       'big',
25754       'blink',
25755       'blockquote',
25756       'body',
25757       'br',
25758       'button',
25759       'canvas',
25760       'caption',
25761       'center',
25762       'cite',
25763       'code',
25764       'col',
25765       'colgroup',
25766       'content',
25767       'data',
25768       'datalist',
25769       'dd',
25770       'decorator',
25771       'del',
25772       'details',
25773       'dfn',
25774       'dialog',
25775       'dir',
25776       'div',
25777       'dl',
25778       'dt',
25779       'element',
25780       'em',
25781       'fieldset',
25782       'figcaption',
25783       'figure',
25784       'font',
25785       'footer',
25786       'form',
25787       'h1',
25788       'h2',
25789       'h3',
25790       'h4',
25791       'h5',
25792       'h6',
25793       'head',
25794       'header',
25795       'hgroup',
25796       'hr',
25797       'html',
25798       'i',
25799       'img',
25800       'input',
25801       'ins',
25802       'kbd',
25803       'label',
25804       'legend',
25805       'li',
25806       'main',
25807       'map',
25808       'mark',
25809       'marquee',
25810       'menu',
25811       'menuitem',
25812       'meter',
25813       'nav',
25814       'nobr',
25815       'ol',
25816       'optgroup',
25817       'option',
25818       'output',
25819       'p',
25820       'picture',
25821       'pre',
25822       'progress',
25823       'q',
25824       'rp',
25825       'rt',
25826       'ruby',
25827       's',
25828       'samp',
25829       'section',
25830       'select',
25831       'shadow',
25832       'small',
25833       'source',
25834       'spacer',
25835       'span',
25836       'strike',
25837       'strong',
25838       'style',
25839       'sub',
25840       'summary',
25841       'sup',
25842       'table',
25843       'tbody',
25844       'td',
25845       'template',
25846       'textarea',
25847       'tfoot',
25848       'th',
25849       'thead',
25850       'time',
25851       'tr',
25852       'track',
25853       'tt',
25854       'u',
25855       'ul',
25856       'var',
25857       'video',
25858       'wbr'
25859     ]);
25860     var svg$1 = freeze([
25861       'svg',
25862       'a',
25863       'altglyph',
25864       'altglyphdef',
25865       'altglyphitem',
25866       'animatecolor',
25867       'animatemotion',
25868       'animatetransform',
25869       'circle',
25870       'clippath',
25871       'defs',
25872       'desc',
25873       'ellipse',
25874       'filter',
25875       'font',
25876       'g',
25877       'glyph',
25878       'glyphref',
25879       'hkern',
25880       'image',
25881       'line',
25882       'lineargradient',
25883       'marker',
25884       'mask',
25885       'metadata',
25886       'mpath',
25887       'path',
25888       'pattern',
25889       'polygon',
25890       'polyline',
25891       'radialgradient',
25892       'rect',
25893       'stop',
25894       'style',
25895       'switch',
25896       'symbol',
25897       'text',
25898       'textpath',
25899       'title',
25900       'tref',
25901       'tspan',
25902       'view',
25903       'vkern'
25904     ]);
25905     var svgFilters = freeze([
25906       'feBlend',
25907       'feColorMatrix',
25908       'feComponentTransfer',
25909       'feComposite',
25910       'feConvolveMatrix',
25911       'feDiffuseLighting',
25912       'feDisplacementMap',
25913       'feDistantLight',
25914       'feFlood',
25915       'feFuncA',
25916       'feFuncB',
25917       'feFuncG',
25918       'feFuncR',
25919       'feGaussianBlur',
25920       'feImage',
25921       'feMerge',
25922       'feMergeNode',
25923       'feMorphology',
25924       'feOffset',
25925       'fePointLight',
25926       'feSpecularLighting',
25927       'feSpotLight',
25928       'feTile',
25929       'feTurbulence'
25930     ]);
25931     var svgDisallowed = freeze([
25932       'animate',
25933       'color-profile',
25934       'cursor',
25935       'discard',
25936       'fedropshadow',
25937       'font-face',
25938       'font-face-format',
25939       'font-face-name',
25940       'font-face-src',
25941       'font-face-uri',
25942       'foreignobject',
25943       'hatch',
25944       'hatchpath',
25945       'mesh',
25946       'meshgradient',
25947       'meshpatch',
25948       'meshrow',
25949       'missing-glyph',
25950       'script',
25951       'set',
25952       'solidcolor',
25953       'unknown',
25954       'use'
25955     ]);
25956     var mathMl$1 = freeze([
25957       'math',
25958       'menclose',
25959       'merror',
25960       'mfenced',
25961       'mfrac',
25962       'mglyph',
25963       'mi',
25964       'mlabeledtr',
25965       'mmultiscripts',
25966       'mn',
25967       'mo',
25968       'mover',
25969       'mpadded',
25970       'mphantom',
25971       'mroot',
25972       'mrow',
25973       'ms',
25974       'mspace',
25975       'msqrt',
25976       'mstyle',
25977       'msub',
25978       'msup',
25979       'msubsup',
25980       'mtable',
25981       'mtd',
25982       'mtext',
25983       'mtr',
25984       'munder',
25985       'munderover'
25986     ]);
25987     var mathMlDisallowed = freeze([
25988       'maction',
25989       'maligngroup',
25990       'malignmark',
25991       'mlongdiv',
25992       'mscarries',
25993       'mscarry',
25994       'msgroup',
25995       'mstack',
25996       'msline',
25997       'msrow',
25998       'semantics',
25999       'annotation',
26000       'annotation-xml',
26001       'mprescripts',
26002       'none'
26003     ]);
26004     var text = freeze(['#text']);
26005     var html = freeze([
26006       'accept',
26007       'action',
26008       'align',
26009       'alt',
26010       'autocapitalize',
26011       'autocomplete',
26012       'autopictureinpicture',
26013       'autoplay',
26014       'background',
26015       'bgcolor',
26016       'border',
26017       'capture',
26018       'cellpadding',
26019       'cellspacing',
26020       'checked',
26021       'cite',
26022       'class',
26023       'clear',
26024       'color',
26025       'cols',
26026       'colspan',
26027       'controls',
26028       'controlslist',
26029       'coords',
26030       'crossorigin',
26031       'datetime',
26032       'decoding',
26033       'default',
26034       'dir',
26035       'disabled',
26036       'disablepictureinpicture',
26037       'disableremoteplayback',
26038       'download',
26039       'draggable',
26040       'enctype',
26041       'enterkeyhint',
26042       'face',
26043       'for',
26044       'headers',
26045       'height',
26046       'hidden',
26047       'high',
26048       'href',
26049       'hreflang',
26050       'id',
26051       'inputmode',
26052       'integrity',
26053       'ismap',
26054       'kind',
26055       'label',
26056       'lang',
26057       'list',
26058       'loading',
26059       'loop',
26060       'low',
26061       'max',
26062       'maxlength',
26063       'media',
26064       'method',
26065       'min',
26066       'minlength',
26067       'multiple',
26068       'muted',
26069       'name',
26070       'nonce',
26071       'noshade',
26072       'novalidate',
26073       'nowrap',
26074       'open',
26075       'optimum',
26076       'pattern',
26077       'placeholder',
26078       'playsinline',
26079       'poster',
26080       'preload',
26081       'pubdate',
26082       'radiogroup',
26083       'readonly',
26084       'rel',
26085       'required',
26086       'rev',
26087       'reversed',
26088       'role',
26089       'rows',
26090       'rowspan',
26091       'spellcheck',
26092       'scope',
26093       'selected',
26094       'shape',
26095       'size',
26096       'sizes',
26097       'span',
26098       'srclang',
26099       'start',
26100       'src',
26101       'srcset',
26102       'step',
26103       'style',
26104       'summary',
26105       'tabindex',
26106       'title',
26107       'translate',
26108       'type',
26109       'usemap',
26110       'valign',
26111       'value',
26112       'width',
26113       'xmlns',
26114       'slot'
26115     ]);
26116     var svg = freeze([
26117       'accent-height',
26118       'accumulate',
26119       'additive',
26120       'alignment-baseline',
26121       'ascent',
26122       'attributename',
26123       'attributetype',
26124       'azimuth',
26125       'basefrequency',
26126       'baseline-shift',
26127       'begin',
26128       'bias',
26129       'by',
26130       'class',
26131       'clip',
26132       'clippathunits',
26133       'clip-path',
26134       'clip-rule',
26135       'color',
26136       'color-interpolation',
26137       'color-interpolation-filters',
26138       'color-profile',
26139       'color-rendering',
26140       'cx',
26141       'cy',
26142       'd',
26143       'dx',
26144       'dy',
26145       'diffuseconstant',
26146       'direction',
26147       'display',
26148       'divisor',
26149       'dur',
26150       'edgemode',
26151       'elevation',
26152       'end',
26153       'fill',
26154       'fill-opacity',
26155       'fill-rule',
26156       'filter',
26157       'filterunits',
26158       'flood-color',
26159       'flood-opacity',
26160       'font-family',
26161       'font-size',
26162       'font-size-adjust',
26163       'font-stretch',
26164       'font-style',
26165       'font-variant',
26166       'font-weight',
26167       'fx',
26168       'fy',
26169       'g1',
26170       'g2',
26171       'glyph-name',
26172       'glyphref',
26173       'gradientunits',
26174       'gradienttransform',
26175       'height',
26176       'href',
26177       'id',
26178       'image-rendering',
26179       'in',
26180       'in2',
26181       'k',
26182       'k1',
26183       'k2',
26184       'k3',
26185       'k4',
26186       'kerning',
26187       'keypoints',
26188       'keysplines',
26189       'keytimes',
26190       'lang',
26191       'lengthadjust',
26192       'letter-spacing',
26193       'kernelmatrix',
26194       'kernelunitlength',
26195       'lighting-color',
26196       'local',
26197       'marker-end',
26198       'marker-mid',
26199       'marker-start',
26200       'markerheight',
26201       'markerunits',
26202       'markerwidth',
26203       'maskcontentunits',
26204       'maskunits',
26205       'max',
26206       'mask',
26207       'media',
26208       'method',
26209       'mode',
26210       'min',
26211       'name',
26212       'numoctaves',
26213       'offset',
26214       'operator',
26215       'opacity',
26216       'order',
26217       'orient',
26218       'orientation',
26219       'origin',
26220       'overflow',
26221       'paint-order',
26222       'path',
26223       'pathlength',
26224       'patterncontentunits',
26225       'patterntransform',
26226       'patternunits',
26227       'points',
26228       'preservealpha',
26229       'preserveaspectratio',
26230       'primitiveunits',
26231       'r',
26232       'rx',
26233       'ry',
26234       'radius',
26235       'refx',
26236       'refy',
26237       'repeatcount',
26238       'repeatdur',
26239       'restart',
26240       'result',
26241       'rotate',
26242       'scale',
26243       'seed',
26244       'shape-rendering',
26245       'specularconstant',
26246       'specularexponent',
26247       'spreadmethod',
26248       'startoffset',
26249       'stddeviation',
26250       'stitchtiles',
26251       'stop-color',
26252       'stop-opacity',
26253       'stroke-dasharray',
26254       'stroke-dashoffset',
26255       'stroke-linecap',
26256       'stroke-linejoin',
26257       'stroke-miterlimit',
26258       'stroke-opacity',
26259       'stroke',
26260       'stroke-width',
26261       'style',
26262       'surfacescale',
26263       'systemlanguage',
26264       'tabindex',
26265       'targetx',
26266       'targety',
26267       'transform',
26268       'transform-origin',
26269       'text-anchor',
26270       'text-decoration',
26271       'text-rendering',
26272       'textlength',
26273       'type',
26274       'u1',
26275       'u2',
26276       'unicode',
26277       'values',
26278       'viewbox',
26279       'visibility',
26280       'version',
26281       'vert-adv-y',
26282       'vert-origin-x',
26283       'vert-origin-y',
26284       'width',
26285       'word-spacing',
26286       'wrap',
26287       'writing-mode',
26288       'xchannelselector',
26289       'ychannelselector',
26290       'x',
26291       'x1',
26292       'x2',
26293       'xmlns',
26294       'y',
26295       'y1',
26296       'y2',
26297       'z',
26298       'zoomandpan'
26299     ]);
26300     var mathMl = freeze([
26301       'accent',
26302       'accentunder',
26303       'align',
26304       'bevelled',
26305       'close',
26306       'columnsalign',
26307       'columnlines',
26308       'columnspan',
26309       'denomalign',
26310       'depth',
26311       'dir',
26312       'display',
26313       'displaystyle',
26314       'encoding',
26315       'fence',
26316       'frame',
26317       'height',
26318       'href',
26319       'id',
26320       'largeop',
26321       'length',
26322       'linethickness',
26323       'lspace',
26324       'lquote',
26325       'mathbackground',
26326       'mathcolor',
26327       'mathsize',
26328       'mathvariant',
26329       'maxsize',
26330       'minsize',
26331       'movablelimits',
26332       'notation',
26333       'numalign',
26334       'open',
26335       'rowalign',
26336       'rowlines',
26337       'rowspacing',
26338       'rowspan',
26339       'rspace',
26340       'rquote',
26341       'scriptlevel',
26342       'scriptminsize',
26343       'scriptsizemultiplier',
26344       'selection',
26345       'separator',
26346       'separators',
26347       'stretchy',
26348       'subscriptshift',
26349       'supscriptshift',
26350       'symmetric',
26351       'voffset',
26352       'width',
26353       'xmlns'
26354     ]);
26355     var xml = freeze([
26356       'xlink:href',
26357       'xml:id',
26358       'xlink:title',
26359       'xml:space',
26360       'xmlns:xlink'
26361     ]);
26362     var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
26363     var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
26364     var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
26365     var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
26366     var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
26367     var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
26368     var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
26369     var DOCTYPE_NAME = seal(/^html$/i);
26370     var getGlobal = function getGlobal() {
26371       return typeof window === 'undefined' ? null : window;
26372     };
26373     var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
26374       if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
26375         return null;
26376       }
26377       var suffix = null;
26378       var ATTR_NAME = 'data-tt-policy-suffix';
26379       if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
26380         suffix = document.currentScript.getAttribute(ATTR_NAME);
26381       }
26382       var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
26383       try {
26384         return trustedTypes.createPolicy(policyName, {
26385           createHTML: function createHTML(html) {
26386             return html;
26387           }
26388         });
26389       } catch (_) {
26390         console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
26391         return null;
26392       }
26393     };
26394     function createDOMPurify() {
26395       var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
26396       var DOMPurify = function DOMPurify(root) {
26397         return createDOMPurify(root);
26398       };
26399       DOMPurify.version = '2.3.8';
26400       DOMPurify.removed = [];
26401       if (!window || !window.document || window.document.nodeType !== 9) {
26402         DOMPurify.isSupported = false;
26403         return DOMPurify;
26404       }
26405       var originalDocument = window.document;
26406       var document = window.document;
26407       var DocumentFragment = window.DocumentFragment, HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter, _window$NamedNodeMap = window.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window.HTMLFormElement, DOMParser = window.DOMParser, trustedTypes = window.trustedTypes;
26408       var ElementPrototype = Element.prototype;
26409       var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
26410       var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
26411       var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
26412       var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
26413       if (typeof HTMLTemplateElement === 'function') {
26414         var template = document.createElement('template');
26415         if (template.content && template.content.ownerDocument) {
26416           document = template.content.ownerDocument;
26417         }
26418       }
26419       var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
26420       var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
26421       var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
26422       var importNode = originalDocument.importNode;
26423       var documentMode = {};
26424       try {
26425         documentMode = clone(document).documentMode ? document.documentMode : {};
26426       } catch (_) {
26427       }
26428       var hooks = {};
26429       DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
26430       var MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
26431       var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
26432       var ALLOWED_TAGS = null;
26433       var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
26434       var ALLOWED_ATTR = null;
26435       var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
26436       var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
26437         tagNameCheck: {
26438           writable: true,
26439           configurable: false,
26440           enumerable: true,
26441           value: null
26442         },
26443         attributeNameCheck: {
26444           writable: true,
26445           configurable: false,
26446           enumerable: true,
26447           value: null
26448         },
26449         allowCustomizedBuiltInElements: {
26450           writable: true,
26451           configurable: false,
26452           enumerable: true,
26453           value: false
26454         }
26455       }));
26456       var FORBID_TAGS = null;
26457       var FORBID_ATTR = null;
26458       var ALLOW_ARIA_ATTR = true;
26459       var ALLOW_DATA_ATTR = true;
26460       var ALLOW_UNKNOWN_PROTOCOLS = false;
26461       var SAFE_FOR_TEMPLATES = false;
26462       var WHOLE_DOCUMENT = false;
26463       var SET_CONFIG = false;
26464       var FORCE_BODY = false;
26465       var RETURN_DOM = false;
26466       var RETURN_DOM_FRAGMENT = false;
26467       var RETURN_TRUSTED_TYPE = false;
26468       var SANITIZE_DOM = true;
26469       var KEEP_CONTENT = true;
26470       var IN_PLACE = false;
26471       var USE_PROFILES = {};
26472       var FORBID_CONTENTS = null;
26473       var DEFAULT_FORBID_CONTENTS = addToSet({}, [
26474         'annotation-xml',
26475         'audio',
26476         'colgroup',
26477         'desc',
26478         'foreignobject',
26479         'head',
26480         'iframe',
26481         'math',
26482         'mi',
26483         'mn',
26484         'mo',
26485         'ms',
26486         'mtext',
26487         'noembed',
26488         'noframes',
26489         'noscript',
26490         'plaintext',
26491         'script',
26492         'style',
26493         'svg',
26494         'template',
26495         'thead',
26496         'title',
26497         'video',
26498         'xmp'
26499       ]);
26500       var DATA_URI_TAGS = null;
26501       var DEFAULT_DATA_URI_TAGS = addToSet({}, [
26502         'audio',
26503         'video',
26504         'img',
26505         'source',
26506         'image',
26507         'track'
26508       ]);
26509       var URI_SAFE_ATTRIBUTES = null;
26510       var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
26511         'alt',
26512         'class',
26513         'for',
26514         'id',
26515         'label',
26516         'name',
26517         'pattern',
26518         'placeholder',
26519         'role',
26520         'summary',
26521         'title',
26522         'value',
26523         'style',
26524         'xmlns'
26525       ]);
26526       var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
26527       var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
26528       var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
26529       var NAMESPACE = HTML_NAMESPACE;
26530       var IS_EMPTY_INPUT = false;
26531       var PARSER_MEDIA_TYPE;
26532       var SUPPORTED_PARSER_MEDIA_TYPES = [
26533         'application/xhtml+xml',
26534         'text/html'
26535       ];
26536       var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
26537       var transformCaseFunc;
26538       var CONFIG = null;
26539       var formElement = document.createElement('form');
26540       var isRegexOrFunction = function isRegexOrFunction(testValue) {
26541         return testValue instanceof RegExp || testValue instanceof Function;
26542       };
26543       var _parseConfig = function _parseConfig(cfg) {
26544         if (CONFIG && CONFIG === cfg) {
26545           return;
26546         }
26547         if (!cfg || _typeof(cfg) !== 'object') {
26548           cfg = {};
26549         }
26550         cfg = clone(cfg);
26551         ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
26552         ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
26553         URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
26554         DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
26555         FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
26556         FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
26557         FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
26558         USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
26559         ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
26560         ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
26561         ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
26562         SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
26563         WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
26564         RETURN_DOM = cfg.RETURN_DOM || false;
26565         RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
26566         RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
26567         FORCE_BODY = cfg.FORCE_BODY || false;
26568         SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
26569         KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
26570         IN_PLACE = cfg.IN_PLACE || false;
26571         IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
26572         NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
26573         if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
26574           CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
26575         }
26576         if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
26577           CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
26578         }
26579         if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
26580           CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
26581         }
26582         PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
26583         transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
26584           return x;
26585         } : stringToLowerCase;
26586         if (SAFE_FOR_TEMPLATES) {
26587           ALLOW_DATA_ATTR = false;
26588         }
26589         if (RETURN_DOM_FRAGMENT) {
26590           RETURN_DOM = true;
26591         }
26592         if (USE_PROFILES) {
26593           ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
26594           ALLOWED_ATTR = [];
26595           if (USE_PROFILES.html === true) {
26596             addToSet(ALLOWED_TAGS, html$1);
26597             addToSet(ALLOWED_ATTR, html);
26598           }
26599           if (USE_PROFILES.svg === true) {
26600             addToSet(ALLOWED_TAGS, svg$1);
26601             addToSet(ALLOWED_ATTR, svg);
26602             addToSet(ALLOWED_ATTR, xml);
26603           }
26604           if (USE_PROFILES.svgFilters === true) {
26605             addToSet(ALLOWED_TAGS, svgFilters);
26606             addToSet(ALLOWED_ATTR, svg);
26607             addToSet(ALLOWED_ATTR, xml);
26608           }
26609           if (USE_PROFILES.mathMl === true) {
26610             addToSet(ALLOWED_TAGS, mathMl$1);
26611             addToSet(ALLOWED_ATTR, mathMl);
26612             addToSet(ALLOWED_ATTR, xml);
26613           }
26614         }
26615         if (cfg.ADD_TAGS) {
26616           if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
26617             ALLOWED_TAGS = clone(ALLOWED_TAGS);
26618           }
26619           addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
26620         }
26621         if (cfg.ADD_ATTR) {
26622           if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
26623             ALLOWED_ATTR = clone(ALLOWED_ATTR);
26624           }
26625           addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
26626         }
26627         if (cfg.ADD_URI_SAFE_ATTR) {
26628           addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
26629         }
26630         if (cfg.FORBID_CONTENTS) {
26631           if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
26632             FORBID_CONTENTS = clone(FORBID_CONTENTS);
26633           }
26634           addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
26635         }
26636         if (KEEP_CONTENT) {
26637           ALLOWED_TAGS['#text'] = true;
26638         }
26639         if (WHOLE_DOCUMENT) {
26640           addToSet(ALLOWED_TAGS, [
26641             'html',
26642             'head',
26643             'body'
26644           ]);
26645         }
26646         if (ALLOWED_TAGS.table) {
26647           addToSet(ALLOWED_TAGS, ['tbody']);
26648           delete FORBID_TAGS.tbody;
26649         }
26650         if (freeze) {
26651           freeze(cfg);
26652         }
26653         CONFIG = cfg;
26654       };
26655       var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
26656         'mi',
26657         'mo',
26658         'mn',
26659         'ms',
26660         'mtext'
26661       ]);
26662       var HTML_INTEGRATION_POINTS = addToSet({}, [
26663         'foreignobject',
26664         'desc',
26665         'title',
26666         'annotation-xml'
26667       ]);
26668       var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
26669         'title',
26670         'style',
26671         'font',
26672         'a',
26673         'script'
26674       ]);
26675       var ALL_SVG_TAGS = addToSet({}, svg$1);
26676       addToSet(ALL_SVG_TAGS, svgFilters);
26677       addToSet(ALL_SVG_TAGS, svgDisallowed);
26678       var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
26679       addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
26680       var _checkValidNamespace = function _checkValidNamespace(element) {
26681         var parent = getParentNode(element);
26682         if (!parent || !parent.tagName) {
26683           parent = {
26684             namespaceURI: HTML_NAMESPACE,
26685             tagName: 'template'
26686           };
26687         }
26688         var tagName = stringToLowerCase(element.tagName);
26689         var parentTagName = stringToLowerCase(parent.tagName);
26690         if (element.namespaceURI === SVG_NAMESPACE) {
26691           if (parent.namespaceURI === HTML_NAMESPACE) {
26692             return tagName === 'svg';
26693           }
26694           if (parent.namespaceURI === MATHML_NAMESPACE) {
26695             return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
26696           }
26697           return Boolean(ALL_SVG_TAGS[tagName]);
26698         }
26699         if (element.namespaceURI === MATHML_NAMESPACE) {
26700           if (parent.namespaceURI === HTML_NAMESPACE) {
26701             return tagName === 'math';
26702           }
26703           if (parent.namespaceURI === SVG_NAMESPACE) {
26704             return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
26705           }
26706           return Boolean(ALL_MATHML_TAGS[tagName]);
26707         }
26708         if (element.namespaceURI === HTML_NAMESPACE) {
26709           if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
26710             return false;
26711           }
26712           if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
26713             return false;
26714           }
26715           return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
26716         }
26717         return false;
26718       };
26719       var _forceRemove = function _forceRemove(node) {
26720         arrayPush(DOMPurify.removed, { element: node });
26721         try {
26722           node.parentNode.removeChild(node);
26723         } catch (_) {
26724           try {
26725             node.outerHTML = emptyHTML;
26726           } catch (_) {
26727             node.remove();
26728           }
26729         }
26730       };
26731       var _removeAttribute = function _removeAttribute(name, node) {
26732         try {
26733           arrayPush(DOMPurify.removed, {
26734             attribute: node.getAttributeNode(name),
26735             from: node
26736           });
26737         } catch (_) {
26738           arrayPush(DOMPurify.removed, {
26739             attribute: null,
26740             from: node
26741           });
26742         }
26743         node.removeAttribute(name);
26744         if (name === 'is' && !ALLOWED_ATTR[name]) {
26745           if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
26746             try {
26747               _forceRemove(node);
26748             } catch (_) {
26749             }
26750           } else {
26751             try {
26752               node.setAttribute(name, '');
26753             } catch (_) {
26754             }
26755           }
26756         }
26757       };
26758       var _initDocument = function _initDocument(dirty) {
26759         var doc;
26760         var leadingWhitespace;
26761         if (FORCE_BODY) {
26762           dirty = '<remove></remove>' + dirty;
26763         } else {
26764           var matches = stringMatch(dirty, /^[\r\n\t ]+/);
26765           leadingWhitespace = matches && matches[0];
26766         }
26767         if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
26768           dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
26769         }
26770         var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
26771         if (NAMESPACE === HTML_NAMESPACE) {
26772           try {
26773             doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
26774           } catch (_) {
26775           }
26776         }
26777         if (!doc || !doc.documentElement) {
26778           doc = implementation.createDocument(NAMESPACE, 'template', null);
26779           try {
26780             doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
26781           } catch (_) {
26782           }
26783         }
26784         var body = doc.body || doc.documentElement;
26785         if (dirty && leadingWhitespace) {
26786           body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
26787         }
26788         if (NAMESPACE === HTML_NAMESPACE) {
26789           return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
26790         }
26791         return WHOLE_DOCUMENT ? doc.documentElement : body;
26792       };
26793       var _createIterator = function _createIterator(root) {
26794         return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
26795       };
26796       var _isClobbered = function _isClobbered(elm) {
26797         return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function');
26798       };
26799       var _isNode = function _isNode(object) {
26800         return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
26801       };
26802       var _executeHook = function _executeHook(entryPoint, currentNode, data) {
26803         if (!hooks[entryPoint]) {
26804           return;
26805         }
26806         arrayForEach(hooks[entryPoint], function (hook) {
26807           hook.call(DOMPurify, currentNode, data, CONFIG);
26808         });
26809       };
26810       var _sanitizeElements = function _sanitizeElements(currentNode) {
26811         var content;
26812         _executeHook('beforeSanitizeElements', currentNode, null);
26813         if (_isClobbered(currentNode)) {
26814           _forceRemove(currentNode);
26815           return true;
26816         }
26817         if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
26818           _forceRemove(currentNode);
26819           return true;
26820         }
26821         var tagName = transformCaseFunc(currentNode.nodeName);
26822         _executeHook('uponSanitizeElement', currentNode, {
26823           tagName: tagName,
26824           allowedTags: ALLOWED_TAGS
26825         });
26826         if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
26827           _forceRemove(currentNode);
26828           return true;
26829         }
26830         if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
26831           _forceRemove(currentNode);
26832           return true;
26833         }
26834         if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
26835           if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
26836             if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
26837               return false;
26838             if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))
26839               return false;
26840           }
26841           if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
26842             var parentNode = getParentNode(currentNode) || currentNode.parentNode;
26843             var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
26844             if (childNodes && parentNode) {
26845               var childCount = childNodes.length;
26846               for (var i = childCount - 1; i >= 0; --i) {
26847                 parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
26848               }
26849             }
26850           }
26851           _forceRemove(currentNode);
26852           return true;
26853         }
26854         if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
26855           _forceRemove(currentNode);
26856           return true;
26857         }
26858         if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
26859           _forceRemove(currentNode);
26860           return true;
26861         }
26862         if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
26863           content = currentNode.textContent;
26864           content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
26865           content = stringReplace(content, ERB_EXPR$1, ' ');
26866           if (currentNode.textContent !== content) {
26867             arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
26868             currentNode.textContent = content;
26869           }
26870         }
26871         _executeHook('afterSanitizeElements', currentNode, null);
26872         return false;
26873       };
26874       var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
26875         if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
26876           return false;
26877         }
26878         if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName));
26879         else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
26880         else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
26881           if (_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));
26882           else {
26883             return false;
26884           }
26885         } else if (URI_SAFE_ATTRIBUTES[lcName]);
26886         else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
26887         else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
26888         else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
26889         else if (!value);
26890         else {
26891           return false;
26892         }
26893         return true;
26894       };
26895       var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
26896         return tagName.indexOf('-') > 0;
26897       };
26898       var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
26899         var attr;
26900         var value;
26901         var lcName;
26902         var l;
26903         _executeHook('beforeSanitizeAttributes', currentNode, null);
26904         var attributes = currentNode.attributes;
26905         if (!attributes) {
26906           return;
26907         }
26908         var hookEvent = {
26909           attrName: '',
26910           attrValue: '',
26911           keepAttr: true,
26912           allowedAttributes: ALLOWED_ATTR
26913         };
26914         l = attributes.length;
26915         while (l--) {
26916           attr = attributes[l];
26917           var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI;
26918           value = name === 'value' ? attr.value : stringTrim(attr.value);
26919           lcName = transformCaseFunc(name);
26920           var initValue = value;
26921           hookEvent.attrName = lcName;
26922           hookEvent.attrValue = value;
26923           hookEvent.keepAttr = true;
26924           hookEvent.forceKeepAttr = undefined;
26925           _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
26926           value = hookEvent.attrValue;
26927           if (hookEvent.forceKeepAttr) {
26928             continue;
26929           }
26930           if (!hookEvent.keepAttr) {
26931             _removeAttribute(name, currentNode);
26932             continue;
26933           }
26934           if (regExpTest(/\/>/i, value)) {
26935             _removeAttribute(name, currentNode);
26936             continue;
26937           }
26938           if (SAFE_FOR_TEMPLATES) {
26939             value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
26940             value = stringReplace(value, ERB_EXPR$1, ' ');
26941           }
26942           var lcTag = transformCaseFunc(currentNode.nodeName);
26943           if (!_isValidAttribute(lcTag, lcName, value)) {
26944             _removeAttribute(name, currentNode);
26945             continue;
26946           }
26947           if (value !== initValue) {
26948             try {
26949               if (namespaceURI) {
26950                 currentNode.setAttributeNS(namespaceURI, name, value);
26951               } else {
26952                 currentNode.setAttribute(name, value);
26953               }
26954             } catch (_) {
26955               _removeAttribute(name, currentNode);
26956             }
26957           }
26958         }
26959         _executeHook('afterSanitizeAttributes', currentNode, null);
26960       };
26961       var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
26962         var shadowNode;
26963         var shadowIterator = _createIterator(fragment);
26964         _executeHook('beforeSanitizeShadowDOM', fragment, null);
26965         while (shadowNode = shadowIterator.nextNode()) {
26966           _executeHook('uponSanitizeShadowNode', shadowNode, null);
26967           if (_sanitizeElements(shadowNode)) {
26968             continue;
26969           }
26970           if (shadowNode.content instanceof DocumentFragment) {
26971             _sanitizeShadowDOM(shadowNode.content);
26972           }
26973           _sanitizeAttributes(shadowNode);
26974         }
26975         _executeHook('afterSanitizeShadowDOM', fragment, null);
26976       };
26977       DOMPurify.sanitize = function (dirty, cfg) {
26978         var body;
26979         var importedNode;
26980         var currentNode;
26981         var oldNode;
26982         var returnNode;
26983         IS_EMPTY_INPUT = !dirty;
26984         if (IS_EMPTY_INPUT) {
26985           dirty = '<!-->';
26986         }
26987         if (typeof dirty !== 'string' && !_isNode(dirty)) {
26988           if (typeof dirty.toString !== 'function') {
26989             throw typeErrorCreate('toString is not a function');
26990           } else {
26991             dirty = dirty.toString();
26992             if (typeof dirty !== 'string') {
26993               throw typeErrorCreate('dirty is not a string, aborting');
26994             }
26995           }
26996         }
26997         if (!DOMPurify.isSupported) {
26998           if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
26999             if (typeof dirty === 'string') {
27000               return window.toStaticHTML(dirty);
27001             }
27002             if (_isNode(dirty)) {
27003               return window.toStaticHTML(dirty.outerHTML);
27004             }
27005           }
27006           return dirty;
27007         }
27008         if (!SET_CONFIG) {
27009           _parseConfig(cfg);
27010         }
27011         DOMPurify.removed = [];
27012         if (typeof dirty === 'string') {
27013           IN_PLACE = false;
27014         }
27015         if (IN_PLACE) {
27016           if (dirty.nodeName) {
27017             var tagName = transformCaseFunc(dirty.nodeName);
27018             if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
27019               throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
27020             }
27021           }
27022         } else if (dirty instanceof Node) {
27023           body = _initDocument('<!---->');
27024           importedNode = body.ownerDocument.importNode(dirty, true);
27025           if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
27026             body = importedNode;
27027           } else if (importedNode.nodeName === 'HTML') {
27028             body = importedNode;
27029           } else {
27030             body.appendChild(importedNode);
27031           }
27032         } else {
27033           if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
27034             return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
27035           }
27036           body = _initDocument(dirty);
27037           if (!body) {
27038             return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
27039           }
27040         }
27041         if (body && FORCE_BODY) {
27042           _forceRemove(body.firstChild);
27043         }
27044         var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
27045         while (currentNode = nodeIterator.nextNode()) {
27046           if (currentNode.nodeType === 3 && currentNode === oldNode) {
27047             continue;
27048           }
27049           if (_sanitizeElements(currentNode)) {
27050             continue;
27051           }
27052           if (currentNode.content instanceof DocumentFragment) {
27053             _sanitizeShadowDOM(currentNode.content);
27054           }
27055           _sanitizeAttributes(currentNode);
27056           oldNode = currentNode;
27057         }
27058         oldNode = null;
27059         if (IN_PLACE) {
27060           return dirty;
27061         }
27062         if (RETURN_DOM) {
27063           if (RETURN_DOM_FRAGMENT) {
27064             returnNode = createDocumentFragment.call(body.ownerDocument);
27065             while (body.firstChild) {
27066               returnNode.appendChild(body.firstChild);
27067             }
27068           } else {
27069             returnNode = body;
27070           }
27071           if (ALLOWED_ATTR.shadowroot) {
27072             returnNode = importNode.call(originalDocument, returnNode, true);
27073           }
27074           return returnNode;
27075         }
27076         var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
27077         if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
27078           serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
27079         }
27080         if (SAFE_FOR_TEMPLATES) {
27081           serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
27082           serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
27083         }
27084         return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
27085       };
27086       DOMPurify.setConfig = function (cfg) {
27087         _parseConfig(cfg);
27088         SET_CONFIG = true;
27089       };
27090       DOMPurify.clearConfig = function () {
27091         CONFIG = null;
27092         SET_CONFIG = false;
27093       };
27094       DOMPurify.isValidAttribute = function (tag, attr, value) {
27095         if (!CONFIG) {
27096           _parseConfig({});
27097         }
27098         var lcTag = transformCaseFunc(tag);
27099         var lcName = transformCaseFunc(attr);
27100         return _isValidAttribute(lcTag, lcName, value);
27101       };
27102       DOMPurify.addHook = function (entryPoint, hookFunction) {
27103         if (typeof hookFunction !== 'function') {
27104           return;
27105         }
27106         hooks[entryPoint] = hooks[entryPoint] || [];
27107         arrayPush(hooks[entryPoint], hookFunction);
27108       };
27109       DOMPurify.removeHook = function (entryPoint) {
27110         if (hooks[entryPoint]) {
27111           return arrayPop(hooks[entryPoint]);
27112         }
27113       };
27114       DOMPurify.removeHooks = function (entryPoint) {
27115         if (hooks[entryPoint]) {
27116           hooks[entryPoint] = [];
27117         }
27118       };
27119       DOMPurify.removeAllHooks = function () {
27120         hooks = {};
27121       };
27122       return DOMPurify;
27123     }
27124     var purify = createDOMPurify();
27126     const sanitizeHtmlString = html => purify().sanitize(html);
27128     const isTouch = global$5.deviceType.isTouch();
27129     const hiddenHeader = (title, close) => ({
27130       dom: {
27131         tag: 'div',
27132         styles: { display: 'none' },
27133         classes: ['tox-dialog__header']
27134       },
27135       components: [
27136         title,
27137         close
27138       ]
27139     });
27140     const pClose = (onClose, providersBackstage) => ModalDialog.parts.close(Button.sketch({
27141       dom: {
27142         tag: 'button',
27143         classes: [
27144           'tox-button',
27145           'tox-button--icon',
27146           'tox-button--naked'
27147         ],
27148         attributes: {
27149           'type': 'button',
27150           'aria-label': providersBackstage.translate('Close')
27151         }
27152       },
27153       action: onClose,
27154       buttonBehaviours: derive$1([Tabstopping.config({})])
27155     }));
27156     const pUntitled = () => ModalDialog.parts.title({
27157       dom: {
27158         tag: 'div',
27159         classes: ['tox-dialog__title'],
27160         innerHtml: '',
27161         styles: { display: 'none' }
27162       }
27163     });
27164     const pBodyMessage = (message, providersBackstage) => ModalDialog.parts.body({
27165       dom: {
27166         tag: 'div',
27167         classes: ['tox-dialog__body']
27168       },
27169       components: [{
27170           dom: {
27171             tag: 'div',
27172             classes: ['tox-dialog__body-content']
27173           },
27174           components: [{ dom: fromHtml(`<p>${ sanitizeHtmlString(providersBackstage.translate(message)) }</p>`) }]
27175         }]
27176     });
27177     const pFooter = buttons => ModalDialog.parts.footer({
27178       dom: {
27179         tag: 'div',
27180         classes: ['tox-dialog__footer']
27181       },
27182       components: buttons
27183     });
27184     const pFooterGroup = (startButtons, endButtons) => [
27185       Container.sketch({
27186         dom: {
27187           tag: 'div',
27188           classes: ['tox-dialog__footer-start']
27189         },
27190         components: startButtons
27191       }),
27192       Container.sketch({
27193         dom: {
27194           tag: 'div',
27195           classes: ['tox-dialog__footer-end']
27196         },
27197         components: endButtons
27198       })
27199     ];
27200     const renderDialog$1 = spec => {
27201       const dialogClass = 'tox-dialog';
27202       const blockerClass = dialogClass + '-wrap';
27203       const blockerBackdropClass = blockerClass + '__backdrop';
27204       const scrollLockClass = dialogClass + '__disable-scroll';
27205       return ModalDialog.sketch({
27206         lazySink: spec.lazySink,
27207         onEscape: comp => {
27208           spec.onEscape(comp);
27209           return Optional.some(true);
27210         },
27211         useTabstopAt: elem => !isPseudoStop(elem),
27212         dom: {
27213           tag: 'div',
27214           classes: [dialogClass].concat(spec.extraClasses),
27215           styles: {
27216             position: 'relative',
27217             ...spec.extraStyles
27218           }
27219         },
27220         components: [
27221           spec.header,
27222           spec.body,
27223           ...spec.footer.toArray()
27224         ],
27225         parts: {
27226           blocker: {
27227             dom: fromHtml(`<div class="${ blockerClass }"></div>`),
27228             components: [{
27229                 dom: {
27230                   tag: 'div',
27231                   classes: isTouch ? [
27232                     blockerBackdropClass,
27233                     blockerBackdropClass + '--opaque'
27234                   ] : [blockerBackdropClass]
27235                 }
27236               }]
27237           }
27238         },
27239         dragBlockClass: blockerClass,
27240         modalBehaviours: derive$1([
27241           Focusing.config({}),
27242           config('dialog-events', spec.dialogEvents.concat([runOnSource(focusin(), (comp, _se) => {
27243               Keying.focusIn(comp);
27244             })])),
27245           config('scroll-lock', [
27246             runOnAttached(() => {
27247               add$2(body(), scrollLockClass);
27248             }),
27249             runOnDetached(() => {
27250               remove$2(body(), scrollLockClass);
27251             })
27252           ]),
27253           ...spec.extraBehaviours
27254         ]),
27255         eventOrder: {
27256           [execute$5()]: ['dialog-events'],
27257           [attachedToDom()]: [
27258             'scroll-lock',
27259             'dialog-events',
27260             'alloy.base.behaviour'
27261           ],
27262           [detachedFromDom()]: [
27263             'alloy.base.behaviour',
27264             'dialog-events',
27265             'scroll-lock'
27266           ],
27267           ...spec.eventOrder
27268         }
27269       });
27270     };
27272     const renderClose = providersBackstage => Button.sketch({
27273       dom: {
27274         tag: 'button',
27275         classes: [
27276           'tox-button',
27277           'tox-button--icon',
27278           'tox-button--naked'
27279         ],
27280         attributes: {
27281           'type': 'button',
27282           'aria-label': providersBackstage.translate('Close'),
27283           'title': providersBackstage.translate('Close')
27284         }
27285       },
27286       components: [render$3('close', {
27287           tag: 'div',
27288           classes: ['tox-icon']
27289         }, providersBackstage.icons)],
27290       action: comp => {
27291         emit(comp, formCancelEvent);
27292       }
27293     });
27294     const renderTitle = (spec, dialogId, titleId, providersBackstage) => {
27295       const renderComponents = data => [text$2(providersBackstage.translate(data.title))];
27296       return {
27297         dom: {
27298           tag: 'div',
27299           classes: ['tox-dialog__title'],
27300           attributes: { ...titleId.map(x => ({ id: x })).getOr({}) }
27301         },
27302         components: [],
27303         behaviours: derive$1([Reflecting.config({
27304             channel: `${ titleChannel }-${ dialogId }`,
27305             initialData: spec,
27306             renderComponents
27307           })])
27308       };
27309     };
27310     const renderDragHandle = () => ({ dom: fromHtml('<div class="tox-dialog__draghandle"></div>') });
27311     const renderInlineHeader = (spec, dialogId, titleId, providersBackstage) => Container.sketch({
27312       dom: fromHtml('<div class="tox-dialog__header"></div>'),
27313       components: [
27314         renderTitle(spec, dialogId, Optional.some(titleId), providersBackstage),
27315         renderDragHandle(),
27316         renderClose(providersBackstage)
27317       ],
27318       containerBehaviours: derive$1([Dragging.config({
27319           mode: 'mouse',
27320           blockerClass: 'blocker',
27321           getTarget: handle => {
27322             return closest$1(handle, '[role="dialog"]').getOrDie();
27323           },
27324           snaps: {
27325             getSnapPoints: () => [],
27326             leftAttr: 'data-drag-left',
27327             topAttr: 'data-drag-top'
27328           }
27329         })])
27330     });
27331     const renderModalHeader = (spec, dialogId, providersBackstage) => {
27332       const pTitle = ModalDialog.parts.title(renderTitle(spec, dialogId, Optional.none(), providersBackstage));
27333       const pHandle = ModalDialog.parts.draghandle(renderDragHandle());
27334       const pClose = ModalDialog.parts.close(renderClose(providersBackstage));
27335       const components = [pTitle].concat(spec.draggable ? [pHandle] : []).concat([pClose]);
27336       return Container.sketch({
27337         dom: fromHtml('<div class="tox-dialog__header"></div>'),
27338         components
27339       });
27340     };
27342     const getHeader = (title, dialogId, backstage) => renderModalHeader({
27343       title: backstage.shared.providers.translate(title),
27344       draggable: backstage.dialog.isDraggableModal()
27345     }, dialogId, backstage.shared.providers);
27346     const getBusySpec = (message, bs, providers) => ({
27347       dom: {
27348         tag: 'div',
27349         classes: ['tox-dialog__busy-spinner'],
27350         attributes: { 'aria-label': providers.translate(message) },
27351         styles: {
27352           left: '0px',
27353           right: '0px',
27354           bottom: '0px',
27355           top: '0px',
27356           position: 'absolute'
27357         }
27358       },
27359       behaviours: bs,
27360       components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
27361     });
27362     const getEventExtras = (lazyDialog, providers, extra) => ({
27363       onClose: () => extra.closeWindow(),
27364       onBlock: blockEvent => {
27365         ModalDialog.setBusy(lazyDialog(), (_comp, bs) => getBusySpec(blockEvent.message, bs, providers));
27366       },
27367       onUnblock: () => {
27368         ModalDialog.setIdle(lazyDialog());
27369       }
27370     });
27371     const renderModalDialog = (spec, initialData, dialogEvents, backstage) => {
27372       const updateState = (_comp, incoming) => Optional.some(incoming);
27373       return build$1(renderDialog$1({
27374         ...spec,
27375         lazySink: backstage.shared.getSink,
27376         extraBehaviours: [
27377           Reflecting.config({
27378             channel: `${ dialogChannel }-${ spec.id }`,
27379             updateState,
27380             initialData
27381           }),
27382           RepresentingConfigs.memory({}),
27383           ...spec.extraBehaviours
27384         ],
27385         onEscape: comp => {
27386           emit(comp, formCancelEvent);
27387         },
27388         dialogEvents,
27389         eventOrder: {
27390           [receive()]: [
27391             Reflecting.name(),
27392             Receiving.name()
27393           ],
27394           [attachedToDom()]: [
27395             'scroll-lock',
27396             Reflecting.name(),
27397             'messages',
27398             'dialog-events',
27399             'alloy.base.behaviour'
27400           ],
27401           [detachedFromDom()]: [
27402             'alloy.base.behaviour',
27403             'dialog-events',
27404             'messages',
27405             Reflecting.name(),
27406             'scroll-lock'
27407           ]
27408         }
27409       }));
27410     };
27411     const mapMenuButtons = buttons => {
27412       const mapItems = button => {
27413         const items = map$2(button.items, item => {
27414           const cell = Cell(false);
27415           return {
27416             ...item,
27417             storage: cell
27418           };
27419         });
27420         return {
27421           ...button,
27422           items
27423         };
27424       };
27425       return map$2(buttons, button => {
27426         return button.type === 'menu' ? mapItems(button) : button;
27427       });
27428     };
27429     const extractCellsToObject = buttons => foldl(buttons, (acc, button) => {
27430       if (button.type === 'menu') {
27431         const menuButton = button;
27432         return foldl(menuButton.items, (innerAcc, item) => {
27433           innerAcc[item.name] = item.storage;
27434           return innerAcc;
27435         }, acc);
27436       }
27437       return acc;
27438     }, {});
27440     const initCommonEvents = (fireApiEvent, extras) => [
27441       runWithTarget(focusin(), onFocus),
27442       fireApiEvent(formCloseEvent, (_api, spec) => {
27443         extras.onClose();
27444         spec.onClose();
27445       }),
27446       fireApiEvent(formCancelEvent, (api, spec, _event, self) => {
27447         spec.onCancel(api);
27448         emit(self, formCloseEvent);
27449       }),
27450       run$1(formUnblockEvent, (_c, _se) => extras.onUnblock()),
27451       run$1(formBlockEvent, (_c, se) => extras.onBlock(se.event))
27452     ];
27453     const initUrlDialog = (getInstanceApi, extras) => {
27454       const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
27455         withSpec(c, (spec, _c) => {
27456           f(getInstanceApi(), spec, se.event, c);
27457         });
27458       });
27459       const withSpec = (c, f) => {
27460         Reflecting.getState(c).get().each(currentDialog => {
27461           f(currentDialog, c);
27462         });
27463       };
27464       return [
27465         ...initCommonEvents(fireApiEvent, extras),
27466         fireApiEvent(formActionEvent, (api, spec, event) => {
27467           spec.onAction(api, { name: event.name });
27468         })
27469       ];
27470     };
27471     const initDialog = (getInstanceApi, extras, getSink) => {
27472       const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
27473         withSpec(c, (spec, _c) => {
27474           f(getInstanceApi(), spec, se.event, c);
27475         });
27476       });
27477       const withSpec = (c, f) => {
27478         Reflecting.getState(c).get().each(currentDialogInit => {
27479           f(currentDialogInit.internalDialog, c);
27480         });
27481       };
27482       return [
27483         ...initCommonEvents(fireApiEvent, extras),
27484         fireApiEvent(formSubmitEvent, (api, spec) => spec.onSubmit(api)),
27485         fireApiEvent(formChangeEvent, (api, spec, event) => {
27486           spec.onChange(api, { name: event.name });
27487         }),
27488         fireApiEvent(formActionEvent, (api, spec, event, component) => {
27489           const focusIn = () => Keying.focusIn(component);
27490           const isDisabled = focused => has$1(focused, 'disabled') || getOpt(focused, 'aria-disabled').exists(val => val === 'true');
27491           const rootNode = getRootNode(component.element);
27492           const current = active$1(rootNode);
27493           spec.onAction(api, {
27494             name: event.name,
27495             value: event.value
27496           });
27497           active$1(rootNode).fold(focusIn, focused => {
27498             if (isDisabled(focused)) {
27499               focusIn();
27500             } else if (current.exists(cur => contains(focused, cur) && isDisabled(cur))) {
27501               focusIn();
27502             } else {
27503               getSink().toOptional().filter(sink => !contains(sink.element, focused)).each(focusIn);
27504             }
27505           });
27506         }),
27507         fireApiEvent(formTabChangeEvent, (api, spec, event) => {
27508           spec.onTabChange(api, {
27509             newTabName: event.name,
27510             oldTabName: event.oldName
27511           });
27512         }),
27513         runOnDetached(component => {
27514           const api = getInstanceApi();
27515           Representing.setValue(component, api.getData());
27516         })
27517       ];
27518     };
27519     const SilverDialogEvents = {
27520       initUrlDialog,
27521       initDialog
27522     };
27524     const makeButton = (button, backstage) => renderFooterButton(button, button.type, backstage);
27525     const lookup = (compInSystem, footerButtons, buttonName) => find$5(footerButtons, button => button.name === buttonName).bind(memButton => memButton.memento.getOpt(compInSystem));
27526     const renderComponents = (_data, state) => {
27527       const footerButtons = state.map(s => s.footerButtons).getOr([]);
27528       const buttonGroups = partition$3(footerButtons, button => button.align === 'start');
27529       const makeGroup = (edge, buttons) => Container.sketch({
27530         dom: {
27531           tag: 'div',
27532           classes: [`tox-dialog__footer-${ edge }`]
27533         },
27534         components: map$2(buttons, button => button.memento.asSpec())
27535       });
27536       const startButtons = makeGroup('start', buttonGroups.pass);
27537       const endButtons = makeGroup('end', buttonGroups.fail);
27538       return [
27539         startButtons,
27540         endButtons
27541       ];
27542     };
27543     const renderFooter = (initSpec, dialogId, backstage) => {
27544       const updateState = (comp, data) => {
27545         const footerButtons = map$2(data.buttons, button => {
27546           const memButton = record(makeButton(button, backstage));
27547           return {
27548             name: button.name,
27549             align: button.align,
27550             memento: memButton
27551           };
27552         });
27553         const lookupByName = buttonName => lookup(comp, footerButtons, buttonName);
27554         return Optional.some({
27555           lookupByName,
27556           footerButtons
27557         });
27558       };
27559       return {
27560         dom: fromHtml('<div class="tox-dialog__footer"></div>'),
27561         components: [],
27562         behaviours: derive$1([Reflecting.config({
27563             channel: `${ footerChannel }-${ dialogId }`,
27564             initialData: initSpec,
27565             updateState,
27566             renderComponents
27567           })])
27568       };
27569     };
27570     const renderInlineFooter = (initSpec, dialogId, backstage) => renderFooter(initSpec, dialogId, backstage);
27571     const renderModalFooter = (initSpec, dialogId, backstage) => ModalDialog.parts.footer(renderFooter(initSpec, dialogId, backstage));
27573     const getCompByName = (access, name) => {
27574       const root = access.getRoot();
27575       if (root.getSystem().isConnected()) {
27576         const form = Composing.getCurrent(access.getFormWrapper()).getOr(access.getFormWrapper());
27577         return Form.getField(form, name).orThunk(() => {
27578           const footer = access.getFooter();
27579           const footerState = Reflecting.getState(footer).get();
27580           return footerState.bind(f => f.lookupByName(name));
27581         });
27582       } else {
27583         return Optional.none();
27584       }
27585     };
27586     const validateData$1 = (access, data) => {
27587       const root = access.getRoot();
27588       return Reflecting.getState(root).get().map(dialogState => getOrDie(asRaw('data', dialogState.dataValidator, data))).getOr(data);
27589     };
27590     const getDialogApi = (access, doRedial, menuItemStates) => {
27591       const withRoot = f => {
27592         const root = access.getRoot();
27593         if (root.getSystem().isConnected()) {
27594           f(root);
27595         }
27596       };
27597       const getData = () => {
27598         const root = access.getRoot();
27599         const valueComp = root.getSystem().isConnected() ? access.getFormWrapper() : root;
27600         const representedValues = Representing.getValue(valueComp);
27601         const menuItemCurrentState = map$1(menuItemStates, cell => cell.get());
27602         return {
27603           ...representedValues,
27604           ...menuItemCurrentState
27605         };
27606       };
27607       const setData = newData => {
27608         withRoot(_ => {
27609           const prevData = instanceApi.getData();
27610           const mergedData = deepMerge(prevData, newData);
27611           const newInternalData = validateData$1(access, mergedData);
27612           const form = access.getFormWrapper();
27613           Representing.setValue(form, newInternalData);
27614           each(menuItemStates, (v, k) => {
27615             if (has$2(mergedData, k)) {
27616               v.set(mergedData[k]);
27617             }
27618           });
27619         });
27620       };
27621       const setEnabled = (name, state) => {
27622         getCompByName(access, name).each(state ? Disabling.enable : Disabling.disable);
27623       };
27624       const focus = name => {
27625         getCompByName(access, name).each(Focusing.focus);
27626       };
27627       const block = message => {
27628         if (!isString(message)) {
27629           throw new Error('The dialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
27630         }
27631         withRoot(root => {
27632           emitWith(root, formBlockEvent, { message });
27633         });
27634       };
27635       const unblock = () => {
27636         withRoot(root => {
27637           emit(root, formUnblockEvent);
27638         });
27639       };
27640       const showTab = name => {
27641         withRoot(_ => {
27642           const body = access.getBody();
27643           const bodyState = Reflecting.getState(body);
27644           if (bodyState.get().exists(b => b.isTabPanel())) {
27645             Composing.getCurrent(body).each(tabSection => {
27646               TabSection.showTab(tabSection, name);
27647             });
27648           }
27649         });
27650       };
27651       const redial = d => {
27652         withRoot(root => {
27653           const id = access.getId();
27654           const dialogInit = doRedial(d);
27655           root.getSystem().broadcastOn([`${ dialogChannel }-${ id }`], dialogInit);
27656           root.getSystem().broadcastOn([`${ titleChannel }-${ id }`], dialogInit.internalDialog);
27657           root.getSystem().broadcastOn([`${ bodyChannel }-${ id }`], dialogInit.internalDialog);
27658           root.getSystem().broadcastOn([`${ footerChannel }-${ id }`], dialogInit.internalDialog);
27659           instanceApi.setData(dialogInit.initialData);
27660         });
27661       };
27662       const close = () => {
27663         withRoot(root => {
27664           emit(root, formCloseEvent);
27665         });
27666       };
27667       const instanceApi = {
27668         getData,
27669         setData,
27670         setEnabled,
27671         focus,
27672         block,
27673         unblock,
27674         showTab,
27675         redial,
27676         close
27677       };
27678       return instanceApi;
27679     };
27681     const getDialogSizeClasses = size => {
27682       switch (size) {
27683       case 'large':
27684         return ['tox-dialog--width-lg'];
27685       case 'medium':
27686         return ['tox-dialog--width-md'];
27687       default:
27688         return [];
27689       }
27690     };
27691     const renderDialog = (dialogInit, extra, backstage) => {
27692       const dialogId = generate$6('dialog');
27693       const internalDialog = dialogInit.internalDialog;
27694       const header = getHeader(internalDialog.title, dialogId, backstage);
27695       const body = renderModalBody({
27696         body: internalDialog.body,
27697         initialData: internalDialog.initialData
27698       }, dialogId, backstage);
27699       const storedMenuButtons = mapMenuButtons(internalDialog.buttons);
27700       const objOfCells = extractCellsToObject(storedMenuButtons);
27701       const footer = renderModalFooter({ buttons: storedMenuButtons }, dialogId, backstage);
27702       const dialogEvents = SilverDialogEvents.initDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra), backstage.shared.getSink);
27703       const dialogSize = getDialogSizeClasses(internalDialog.size);
27704       const spec = {
27705         id: dialogId,
27706         header,
27707         body,
27708         footer: Optional.some(footer),
27709         extraClasses: dialogSize,
27710         extraBehaviours: [],
27711         extraStyles: {}
27712       };
27713       const dialog = renderModalDialog(spec, dialogInit, dialogEvents, backstage);
27714       const modalAccess = (() => {
27715         const getForm = () => {
27716           const outerForm = ModalDialog.getBody(dialog);
27717           return Composing.getCurrent(outerForm).getOr(outerForm);
27718         };
27719         return {
27720           getId: constant$1(dialogId),
27721           getRoot: constant$1(dialog),
27722           getBody: () => ModalDialog.getBody(dialog),
27723           getFooter: () => ModalDialog.getFooter(dialog),
27724           getFormWrapper: getForm
27725         };
27726       })();
27727       const instanceApi = getDialogApi(modalAccess, extra.redial, objOfCells);
27728       return {
27729         dialog,
27730         instanceApi
27731       };
27732     };
27734     const renderInlineDialog = (dialogInit, extra, backstage, ariaAttrs) => {
27735       const dialogId = generate$6('dialog');
27736       const dialogLabelId = generate$6('dialog-label');
27737       const dialogContentId = generate$6('dialog-content');
27738       const internalDialog = dialogInit.internalDialog;
27739       const updateState = (_comp, incoming) => Optional.some(incoming);
27740       const memHeader = record(renderInlineHeader({
27741         title: internalDialog.title,
27742         draggable: true
27743       }, dialogId, dialogLabelId, backstage.shared.providers));
27744       const memBody = record(renderInlineBody({
27745         body: internalDialog.body,
27746         initialData: internalDialog.initialData
27747       }, dialogId, dialogContentId, backstage, ariaAttrs));
27748       const storagedMenuButtons = mapMenuButtons(internalDialog.buttons);
27749       const objOfCells = extractCellsToObject(storagedMenuButtons);
27750       const memFooter = record(renderInlineFooter({ buttons: storagedMenuButtons }, dialogId, backstage));
27751       const dialogEvents = SilverDialogEvents.initDialog(() => instanceApi, {
27752         onBlock: event => {
27753           Blocking.block(dialog, (_comp, bs) => getBusySpec(event.message, bs, backstage.shared.providers));
27754         },
27755         onUnblock: () => {
27756           Blocking.unblock(dialog);
27757         },
27758         onClose: () => extra.closeWindow()
27759       }, backstage.shared.getSink);
27760       const dialog = build$1({
27761         dom: {
27762           tag: 'div',
27763           classes: [
27764             'tox-dialog',
27765             'tox-dialog-inline'
27766           ],
27767           attributes: {
27768             role: 'dialog',
27769             ['aria-labelledby']: dialogLabelId,
27770             ['aria-describedby']: dialogContentId
27771           }
27772         },
27773         eventOrder: {
27774           [receive()]: [
27775             Reflecting.name(),
27776             Receiving.name()
27777           ],
27778           [execute$5()]: ['execute-on-form'],
27779           [attachedToDom()]: [
27780             'reflecting',
27781             'execute-on-form'
27782           ]
27783         },
27784         behaviours: derive$1([
27785           Keying.config({
27786             mode: 'cyclic',
27787             onEscape: c => {
27788               emit(c, formCloseEvent);
27789               return Optional.some(true);
27790             },
27791             useTabstopAt: elem => !isPseudoStop(elem) && (name$3(elem) !== 'button' || get$f(elem, 'disabled') !== 'disabled')
27792           }),
27793           Reflecting.config({
27794             channel: `${ dialogChannel }-${ dialogId }`,
27795             updateState,
27796             initialData: dialogInit
27797           }),
27798           Focusing.config({}),
27799           config('execute-on-form', dialogEvents.concat([runOnSource(focusin(), (comp, _se) => {
27800               Keying.focusIn(comp);
27801             })])),
27802           Blocking.config({ getRoot: () => Optional.some(dialog) }),
27803           Replacing.config({}),
27804           RepresentingConfigs.memory({})
27805         ]),
27806         components: [
27807           memHeader.asSpec(),
27808           memBody.asSpec(),
27809           memFooter.asSpec()
27810         ]
27811       });
27812       const instanceApi = getDialogApi({
27813         getId: constant$1(dialogId),
27814         getRoot: constant$1(dialog),
27815         getFooter: () => memFooter.get(dialog),
27816         getBody: () => memBody.get(dialog),
27817         getFormWrapper: () => {
27818           const body = memBody.get(dialog);
27819           return Composing.getCurrent(body).getOr(body);
27820         }
27821       }, extra.redial, objOfCells);
27822       return {
27823         dialog,
27824         instanceApi
27825       };
27826     };
27828     var global = tinymce.util.Tools.resolve('tinymce.util.URI');
27830     const getUrlDialogApi = root => {
27831       const withRoot = f => {
27832         if (root.getSystem().isConnected()) {
27833           f(root);
27834         }
27835       };
27836       const block = message => {
27837         if (!isString(message)) {
27838           throw new Error('The urlDialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
27839         }
27840         withRoot(root => {
27841           emitWith(root, formBlockEvent, { message });
27842         });
27843       };
27844       const unblock = () => {
27845         withRoot(root => {
27846           emit(root, formUnblockEvent);
27847         });
27848       };
27849       const close = () => {
27850         withRoot(root => {
27851           emit(root, formCloseEvent);
27852         });
27853       };
27854       const sendMessage = data => {
27855         withRoot(root => {
27856           root.getSystem().broadcastOn([bodySendMessageChannel], data);
27857         });
27858       };
27859       return {
27860         block,
27861         unblock,
27862         close,
27863         sendMessage
27864       };
27865     };
27867     const SUPPORTED_MESSAGE_ACTIONS = [
27868       'insertContent',
27869       'setContent',
27870       'execCommand',
27871       'close',
27872       'block',
27873       'unblock'
27874     ];
27875     const isSupportedMessage = data => isObject(data) && SUPPORTED_MESSAGE_ACTIONS.indexOf(data.mceAction) !== -1;
27876     const isCustomMessage = data => !isSupportedMessage(data) && isObject(data) && has$2(data, 'mceAction');
27877     const handleMessage = (editor, api, data) => {
27878       switch (data.mceAction) {
27879       case 'insertContent':
27880         editor.insertContent(data.content);
27881         break;
27882       case 'setContent':
27883         editor.setContent(data.content);
27884         break;
27885       case 'execCommand':
27886         const ui = isBoolean(data.ui) ? data.ui : false;
27887         editor.execCommand(data.cmd, ui, data.value);
27888         break;
27889       case 'close':
27890         api.close();
27891         break;
27892       case 'block':
27893         api.block(data.message);
27894         break;
27895       case 'unblock':
27896         api.unblock();
27897         break;
27898       }
27899     };
27900     const renderUrlDialog = (internalDialog, extra, editor, backstage) => {
27901       const dialogId = generate$6('dialog');
27902       const header = getHeader(internalDialog.title, dialogId, backstage);
27903       const body = renderIframeBody(internalDialog);
27904       const footer = internalDialog.buttons.bind(buttons => {
27905         if (buttons.length === 0) {
27906           return Optional.none();
27907         } else {
27908           return Optional.some(renderModalFooter({ buttons }, dialogId, backstage));
27909         }
27910       });
27911       const dialogEvents = SilverDialogEvents.initUrlDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra));
27912       const styles = {
27913         ...internalDialog.height.fold(() => ({}), height => ({
27914           'height': height + 'px',
27915           'max-height': height + 'px'
27916         })),
27917         ...internalDialog.width.fold(() => ({}), width => ({
27918           'width': width + 'px',
27919           'max-width': width + 'px'
27920         }))
27921       };
27922       const classes = internalDialog.width.isNone() && internalDialog.height.isNone() ? ['tox-dialog--width-lg'] : [];
27923       const iframeUri = new global(internalDialog.url, { base_uri: new global(window.location.href) });
27924       const iframeDomain = `${ iframeUri.protocol }://${ iframeUri.host }${ iframeUri.port ? ':' + iframeUri.port : '' }`;
27925       const messageHandlerUnbinder = unbindable();
27926       const extraBehaviours = [
27927         config('messages', [
27928           runOnAttached(() => {
27929             const unbind = bind(SugarElement.fromDom(window), 'message', e => {
27930               if (iframeUri.isSameOrigin(new global(e.raw.origin))) {
27931                 const data = e.raw.data;
27932                 if (isSupportedMessage(data)) {
27933                   handleMessage(editor, instanceApi, data);
27934                 } else if (isCustomMessage(data)) {
27935                   internalDialog.onMessage(instanceApi, data);
27936                 }
27937               }
27938             });
27939             messageHandlerUnbinder.set(unbind);
27940           }),
27941           runOnDetached(messageHandlerUnbinder.clear)
27942         ]),
27943         Receiving.config({
27944           channels: {
27945             [bodySendMessageChannel]: {
27946               onReceive: (comp, data) => {
27947                 descendant(comp.element, 'iframe').each(iframeEle => {
27948                   const iframeWin = iframeEle.dom.contentWindow;
27949                   if (isNonNullable(iframeWin)) {
27950                     iframeWin.postMessage(data, iframeDomain);
27951                   }
27952                 });
27953               }
27954             }
27955           }
27956         })
27957       ];
27958       const spec = {
27959         id: dialogId,
27960         header,
27961         body,
27962         footer,
27963         extraClasses: classes,
27964         extraBehaviours,
27965         extraStyles: styles
27966       };
27967       const dialog = renderModalDialog(spec, internalDialog, dialogEvents, backstage);
27968       const instanceApi = getUrlDialogApi(dialog);
27969       return {
27970         dialog,
27971         instanceApi
27972       };
27973     };
27975     const setup$2 = backstage => {
27976       const sharedBackstage = backstage.shared;
27977       const open = (message, callback) => {
27978         const closeDialog = () => {
27979           ModalDialog.hide(alertDialog);
27980           callback();
27981         };
27982         const memFooterClose = record(renderFooterButton({
27983           name: 'close-alert',
27984           text: 'OK',
27985           primary: true,
27986           buttonType: Optional.some('primary'),
27987           align: 'end',
27988           enabled: true,
27989           icon: Optional.none()
27990         }, 'cancel', backstage));
27991         const titleSpec = pUntitled();
27992         const closeSpec = pClose(closeDialog, sharedBackstage.providers);
27993         const alertDialog = build$1(renderDialog$1({
27994           lazySink: () => sharedBackstage.getSink(),
27995           header: hiddenHeader(titleSpec, closeSpec),
27996           body: pBodyMessage(message, sharedBackstage.providers),
27997           footer: Optional.some(pFooter(pFooterGroup([], [memFooterClose.asSpec()]))),
27998           onEscape: closeDialog,
27999           extraClasses: ['tox-alert-dialog'],
28000           extraBehaviours: [],
28001           extraStyles: {},
28002           dialogEvents: [run$1(formCancelEvent, closeDialog)],
28003           eventOrder: {}
28004         }));
28005         ModalDialog.show(alertDialog);
28006         const footerCloseButton = memFooterClose.get(alertDialog);
28007         Focusing.focus(footerCloseButton);
28008       };
28009       return { open };
28010     };
28012     const setup$1 = backstage => {
28013       const sharedBackstage = backstage.shared;
28014       const open = (message, callback) => {
28015         const closeDialog = state => {
28016           ModalDialog.hide(confirmDialog);
28017           callback(state);
28018         };
28019         const memFooterYes = record(renderFooterButton({
28020           name: 'yes',
28021           text: 'Yes',
28022           primary: true,
28023           buttonType: Optional.some('primary'),
28024           align: 'end',
28025           enabled: true,
28026           icon: Optional.none()
28027         }, 'submit', backstage));
28028         const footerNo = renderFooterButton({
28029           name: 'no',
28030           text: 'No',
28031           primary: false,
28032           buttonType: Optional.some('secondary'),
28033           align: 'end',
28034           enabled: true,
28035           icon: Optional.none()
28036         }, 'cancel', backstage);
28037         const titleSpec = pUntitled();
28038         const closeSpec = pClose(() => closeDialog(false), sharedBackstage.providers);
28039         const confirmDialog = build$1(renderDialog$1({
28040           lazySink: () => sharedBackstage.getSink(),
28041           header: hiddenHeader(titleSpec, closeSpec),
28042           body: pBodyMessage(message, sharedBackstage.providers),
28043           footer: Optional.some(pFooter(pFooterGroup([], [
28044             footerNo,
28045             memFooterYes.asSpec()
28046           ]))),
28047           onEscape: () => closeDialog(false),
28048           extraClasses: ['tox-confirm-dialog'],
28049           extraBehaviours: [],
28050           extraStyles: {},
28051           dialogEvents: [
28052             run$1(formCancelEvent, () => closeDialog(false)),
28053             run$1(formSubmitEvent, () => closeDialog(true))
28054           ],
28055           eventOrder: {}
28056         }));
28057         ModalDialog.show(confirmDialog);
28058         const footerYesButton = memFooterYes.get(confirmDialog);
28059         Focusing.focus(footerYesButton);
28060       };
28061       return { open };
28062     };
28064     const validateData = (data, validator) => getOrDie(asRaw('data', validator, data));
28065     const isAlertOrConfirmDialog = target => closest(target, '.tox-alert-dialog') || closest(target, '.tox-confirm-dialog');
28066     const inlineAdditionalBehaviours = (editor, isStickyToolbar, isToolbarLocationTop) => {
28067       if (isStickyToolbar && isToolbarLocationTop) {
28068         return [];
28069       } else {
28070         return [Docking.config({
28071             contextual: {
28072               lazyContext: () => Optional.some(box$1(SugarElement.fromDom(editor.getContentAreaContainer()))),
28073               fadeInClass: 'tox-dialog-dock-fadein',
28074               fadeOutClass: 'tox-dialog-dock-fadeout',
28075               transitionClass: 'tox-dialog-dock-transition'
28076             },
28077             modes: ['top']
28078           })];
28079       }
28080     };
28081     const setup = extras => {
28082       const backstage = extras.backstage;
28083       const editor = extras.editor;
28084       const isStickyToolbar$1 = isStickyToolbar(editor);
28085       const alertDialog = setup$2(backstage);
28086       const confirmDialog = setup$1(backstage);
28087       const open = (config, params, closeWindow) => {
28088         if (params !== undefined && params.inline === 'toolbar') {
28089           return openInlineDialog(config, backstage.shared.anchors.inlineDialog(), closeWindow, params.ariaAttrs);
28090         } else if (params !== undefined && params.inline === 'cursor') {
28091           return openInlineDialog(config, backstage.shared.anchors.cursor(), closeWindow, params.ariaAttrs);
28092         } else {
28093           return openModalDialog(config, closeWindow);
28094         }
28095       };
28096       const openUrl = (config, closeWindow) => openModalUrlDialog(config, closeWindow);
28097       const openModalUrlDialog = (config, closeWindow) => {
28098         const factory = contents => {
28099           const dialog = renderUrlDialog(contents, {
28100             closeWindow: () => {
28101               ModalDialog.hide(dialog.dialog);
28102               closeWindow(dialog.instanceApi);
28103             }
28104           }, editor, backstage);
28105           ModalDialog.show(dialog.dialog);
28106           return dialog.instanceApi;
28107         };
28108         return DialogManager.openUrl(factory, config);
28109       };
28110       const openModalDialog = (config, closeWindow) => {
28111         const factory = (contents, internalInitialData, dataValidator) => {
28112           const initialData = internalInitialData;
28113           const dialogInit = {
28114             dataValidator,
28115             initialData,
28116             internalDialog: contents
28117           };
28118           const dialog = renderDialog(dialogInit, {
28119             redial: DialogManager.redial,
28120             closeWindow: () => {
28121               ModalDialog.hide(dialog.dialog);
28122               closeWindow(dialog.instanceApi);
28123             }
28124           }, backstage);
28125           ModalDialog.show(dialog.dialog);
28126           dialog.instanceApi.setData(initialData);
28127           return dialog.instanceApi;
28128         };
28129         return DialogManager.open(factory, config);
28130       };
28131       const openInlineDialog = (config$1, anchor, closeWindow, ariaAttrs = false) => {
28132         const factory = (contents, internalInitialData, dataValidator) => {
28133           const initialData = validateData(internalInitialData, dataValidator);
28134           const inlineDialog = value$2();
28135           const isToolbarLocationTop = backstage.shared.header.isPositionedAtTop();
28136           const dialogInit = {
28137             dataValidator,
28138             initialData,
28139             internalDialog: contents
28140           };
28141           const refreshDocking = () => inlineDialog.on(dialog => {
28142             InlineView.reposition(dialog);
28143             Docking.refresh(dialog);
28144           });
28145           const dialogUi = renderInlineDialog(dialogInit, {
28146             redial: DialogManager.redial,
28147             closeWindow: () => {
28148               inlineDialog.on(InlineView.hide);
28149               editor.off('ResizeEditor', refreshDocking);
28150               inlineDialog.clear();
28151               closeWindow(dialogUi.instanceApi);
28152             }
28153           }, backstage, ariaAttrs);
28154           const inlineDialogComp = build$1(InlineView.sketch({
28155             lazySink: backstage.shared.getSink,
28156             dom: {
28157               tag: 'div',
28158               classes: []
28159             },
28160             fireDismissalEventInstead: {},
28161             ...isToolbarLocationTop ? {} : { fireRepositionEventInstead: {} },
28162             inlineBehaviours: derive$1([
28163               config('window-manager-inline-events', [run$1(dismissRequested(), (_comp, _se) => {
28164                   emit(dialogUi.dialog, formCancelEvent);
28165                 })]),
28166               ...inlineAdditionalBehaviours(editor, isStickyToolbar$1, isToolbarLocationTop)
28167             ]),
28168             isExtraPart: (_comp, target) => isAlertOrConfirmDialog(target)
28169           }));
28170           inlineDialog.set(inlineDialogComp);
28171           InlineView.showWithin(inlineDialogComp, premade(dialogUi.dialog), { anchor }, Optional.some(body()));
28172           if (!isStickyToolbar$1 || !isToolbarLocationTop) {
28173             Docking.refresh(inlineDialogComp);
28174             editor.on('ResizeEditor', refreshDocking);
28175           }
28176           dialogUi.instanceApi.setData(initialData);
28177           Keying.focusIn(dialogUi.dialog);
28178           return dialogUi.instanceApi;
28179         };
28180         return DialogManager.open(factory, config$1);
28181       };
28182       const confirm = (message, callback) => {
28183         confirmDialog.open(message, callback);
28184       };
28185       const alert = (message, callback) => {
28186         alertDialog.open(message, callback);
28187       };
28188       const close = instanceApi => {
28189         instanceApi.close();
28190       };
28191       return {
28192         open,
28193         openUrl,
28194         alert,
28195         close,
28196         confirm
28197       };
28198     };
28200     const registerOptions = editor => {
28201       register$e(editor);
28202       register$d(editor);
28203       register(editor);
28204     };
28205     var Theme = () => {
28206       global$a.add('silver', editor => {
28207         registerOptions(editor);
28208         const {getUiMothership, backstage, renderUI} = setup$3(editor);
28209         Autocompleter.register(editor, backstage.shared);
28210         const windowMgr = setup({
28211           editor,
28212           backstage
28213         });
28214         return {
28215           renderUI,
28216           getWindowManagerImpl: constant$1(windowMgr),
28217           getNotificationManagerImpl: () => NotificationManagerImpl(editor, { backstage }, getUiMothership())
28218         };
28219       });
28220     };
28222     Theme();
28224 })();