Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * TinyMCE version 6.8.3 (2024-02-08)
3
 */
4
 
5
(function () {
6
    'use strict';
7
 
8
    const getPrototypeOf$2 = Object.getPrototypeOf;
9
    const hasProto = (v, constructor, predicate) => {
10
      var _a;
11
      if (predicate(v, constructor.prototype)) {
12
        return true;
13
      } else {
14
        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
15
      }
16
    };
17
    const typeOf = x => {
18
      const t = typeof x;
19
      if (x === null) {
20
        return 'null';
21
      } else if (t === 'object' && Array.isArray(x)) {
22
        return 'array';
23
      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
24
        return 'string';
25
      } else {
26
        return t;
27
      }
28
    };
29
    const isType$1 = type => value => typeOf(value) === type;
30
    const isSimpleType = type => value => typeof value === type;
31
    const eq$1 = t => a => t === a;
32
    const is$2 = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
33
    const isString = isType$1('string');
34
    const isObject = isType$1('object');
35
    const isPlainObject = value => is$2(value, Object);
36
    const isArray = isType$1('array');
37
    const isNull = eq$1(null);
38
    const isBoolean = isSimpleType('boolean');
39
    const isUndefined = eq$1(undefined);
40
    const isNullable = a => a === null || a === undefined;
41
    const isNonNullable = a => !isNullable(a);
42
    const isFunction = isSimpleType('function');
43
    const isNumber = isSimpleType('number');
44
    const isArrayOf = (value, pred) => {
45
      if (isArray(value)) {
46
        for (let i = 0, len = value.length; i < len; ++i) {
47
          if (!pred(value[i])) {
48
            return false;
49
          }
50
        }
51
        return true;
52
      }
53
      return false;
54
    };
55
 
56
    const noop = () => {
57
    };
58
    const noarg = f => () => f();
59
    const compose = (fa, fb) => {
60
      return (...args) => {
61
        return fa(fb.apply(null, args));
62
      };
63
    };
64
    const compose1 = (fbc, fab) => a => fbc(fab(a));
65
    const constant$1 = value => {
66
      return () => {
67
        return value;
68
      };
69
    };
70
    const identity = x => {
71
      return x;
72
    };
73
    const tripleEquals = (a, b) => {
74
      return a === b;
75
    };
76
    function curry(fn, ...initialArgs) {
77
      return (...restArgs) => {
78
        const all = initialArgs.concat(restArgs);
79
        return fn.apply(null, all);
80
      };
81
    }
82
    const not = f => t => !f(t);
83
    const die = msg => {
84
      return () => {
85
        throw new Error(msg);
86
      };
87
    };
88
    const apply$1 = f => {
89
      return f();
90
    };
91
    const never = constant$1(false);
92
    const always = constant$1(true);
93
 
94
    class Optional {
95
      constructor(tag, value) {
96
        this.tag = tag;
97
        this.value = value;
98
      }
99
      static some(value) {
100
        return new Optional(true, value);
101
      }
102
      static none() {
103
        return Optional.singletonNone;
104
      }
105
      fold(onNone, onSome) {
106
        if (this.tag) {
107
          return onSome(this.value);
108
        } else {
109
          return onNone();
110
        }
111
      }
112
      isSome() {
113
        return this.tag;
114
      }
115
      isNone() {
116
        return !this.tag;
117
      }
118
      map(mapper) {
119
        if (this.tag) {
120
          return Optional.some(mapper(this.value));
121
        } else {
122
          return Optional.none();
123
        }
124
      }
125
      bind(binder) {
126
        if (this.tag) {
127
          return binder(this.value);
128
        } else {
129
          return Optional.none();
130
        }
131
      }
132
      exists(predicate) {
133
        return this.tag && predicate(this.value);
134
      }
135
      forall(predicate) {
136
        return !this.tag || predicate(this.value);
137
      }
138
      filter(predicate) {
139
        if (!this.tag || predicate(this.value)) {
140
          return this;
141
        } else {
142
          return Optional.none();
143
        }
144
      }
145
      getOr(replacement) {
146
        return this.tag ? this.value : replacement;
147
      }
148
      or(replacement) {
149
        return this.tag ? this : replacement;
150
      }
151
      getOrThunk(thunk) {
152
        return this.tag ? this.value : thunk();
153
      }
154
      orThunk(thunk) {
155
        return this.tag ? this : thunk();
156
      }
157
      getOrDie(message) {
158
        if (!this.tag) {
159
          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
160
        } else {
161
          return this.value;
162
        }
163
      }
164
      static from(value) {
165
        return isNonNullable(value) ? Optional.some(value) : Optional.none();
166
      }
167
      getOrNull() {
168
        return this.tag ? this.value : null;
169
      }
170
      getOrUndefined() {
171
        return this.value;
172
      }
173
      each(worker) {
174
        if (this.tag) {
175
          worker(this.value);
176
        }
177
      }
178
      toArray() {
179
        return this.tag ? [this.value] : [];
180
      }
181
      toString() {
182
        return this.tag ? `some(${ this.value })` : 'none()';
183
      }
184
    }
185
    Optional.singletonNone = new Optional(false);
186
 
187
    const nativeSlice = Array.prototype.slice;
188
    const nativeIndexOf = Array.prototype.indexOf;
189
    const nativePush = Array.prototype.push;
190
    const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
191
    const indexOf = (xs, x) => {
192
      const r = rawIndexOf(xs, x);
193
      return r === -1 ? Optional.none() : Optional.some(r);
194
    };
195
    const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
196
    const exists = (xs, pred) => {
197
      for (let i = 0, len = xs.length; i < len; i++) {
198
        const x = xs[i];
199
        if (pred(x, i)) {
200
          return true;
201
        }
202
      }
203
      return false;
204
    };
205
    const range$2 = (num, f) => {
206
      const r = [];
207
      for (let i = 0; i < num; i++) {
208
        r.push(f(i));
209
      }
210
      return r;
211
    };
212
    const chunk$1 = (array, size) => {
213
      const r = [];
214
      for (let i = 0; i < array.length; i += size) {
215
        const s = nativeSlice.call(array, i, i + size);
216
        r.push(s);
217
      }
218
      return r;
219
    };
220
    const map$2 = (xs, f) => {
221
      const len = xs.length;
222
      const r = new Array(len);
223
      for (let i = 0; i < len; i++) {
224
        const x = xs[i];
225
        r[i] = f(x, i);
226
      }
227
      return r;
228
    };
229
    const each$1 = (xs, f) => {
230
      for (let i = 0, len = xs.length; i < len; i++) {
231
        const x = xs[i];
232
        f(x, i);
233
      }
234
    };
235
    const eachr = (xs, f) => {
236
      for (let i = xs.length - 1; i >= 0; i--) {
237
        const x = xs[i];
238
        f(x, i);
239
      }
240
    };
241
    const partition$3 = (xs, pred) => {
242
      const pass = [];
243
      const fail = [];
244
      for (let i = 0, len = xs.length; i < len; i++) {
245
        const x = xs[i];
246
        const arr = pred(x, i) ? pass : fail;
247
        arr.push(x);
248
      }
249
      return {
250
        pass,
251
        fail
252
      };
253
    };
254
    const filter$2 = (xs, pred) => {
255
      const r = [];
256
      for (let i = 0, len = xs.length; i < len; i++) {
257
        const x = xs[i];
258
        if (pred(x, i)) {
259
          r.push(x);
260
        }
261
      }
262
      return r;
263
    };
264
    const foldr = (xs, f, acc) => {
265
      eachr(xs, (x, i) => {
266
        acc = f(acc, x, i);
267
      });
268
      return acc;
269
    };
270
    const foldl = (xs, f, acc) => {
271
      each$1(xs, (x, i) => {
272
        acc = f(acc, x, i);
273
      });
274
      return acc;
275
    };
276
    const findUntil = (xs, pred, until) => {
277
      for (let i = 0, len = xs.length; i < len; i++) {
278
        const x = xs[i];
279
        if (pred(x, i)) {
280
          return Optional.some(x);
281
        } else if (until(x, i)) {
282
          break;
283
        }
284
      }
285
      return Optional.none();
286
    };
287
    const find$5 = (xs, pred) => {
288
      return findUntil(xs, pred, never);
289
    };
290
    const findIndex$1 = (xs, pred) => {
291
      for (let i = 0, len = xs.length; i < len; i++) {
292
        const x = xs[i];
293
        if (pred(x, i)) {
294
          return Optional.some(i);
295
        }
296
      }
297
      return Optional.none();
298
    };
299
    const flatten = xs => {
300
      const r = [];
301
      for (let i = 0, len = xs.length; i < len; ++i) {
302
        if (!isArray(xs[i])) {
303
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
304
        }
305
        nativePush.apply(r, xs[i]);
306
      }
307
      return r;
308
    };
309
    const bind$3 = (xs, f) => flatten(map$2(xs, f));
310
    const forall = (xs, pred) => {
311
      for (let i = 0, len = xs.length; i < len; ++i) {
312
        const x = xs[i];
313
        if (pred(x, i) !== true) {
314
          return false;
315
        }
316
      }
317
      return true;
318
    };
319
    const reverse = xs => {
320
      const r = nativeSlice.call(xs, 0);
321
      r.reverse();
322
      return r;
323
    };
324
    const difference = (a1, a2) => filter$2(a1, x => !contains$2(a2, x));
325
    const mapToObject = (xs, f) => {
326
      const r = {};
327
      for (let i = 0, len = xs.length; i < len; i++) {
328
        const x = xs[i];
329
        r[String(x)] = f(x, i);
330
      }
331
      return r;
332
    };
333
    const pure$2 = x => [x];
334
    const sort = (xs, comparator) => {
335
      const copy = nativeSlice.call(xs, 0);
336
      copy.sort(comparator);
337
      return copy;
338
    };
339
    const get$h = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
340
    const head = xs => get$h(xs, 0);
341
    const last$1 = xs => get$h(xs, xs.length - 1);
342
    const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x);
343
    const findMap = (arr, f) => {
344
      for (let i = 0; i < arr.length; i++) {
345
        const r = f(arr[i], i);
346
        if (r.isSome()) {
347
          return r;
348
        }
349
      }
350
      return Optional.none();
351
    };
352
 
353
    const keys = Object.keys;
354
    const hasOwnProperty = Object.hasOwnProperty;
355
    const each = (obj, f) => {
356
      const props = keys(obj);
357
      for (let k = 0, len = props.length; k < len; k++) {
358
        const i = props[k];
359
        const x = obj[i];
360
        f(x, i);
361
      }
362
    };
363
    const map$1 = (obj, f) => {
364
      return tupleMap(obj, (x, i) => ({
365
        k: i,
366
        v: f(x, i)
367
      }));
368
    };
369
    const tupleMap = (obj, f) => {
370
      const r = {};
371
      each(obj, (x, i) => {
372
        const tuple = f(x, i);
373
        r[tuple.k] = tuple.v;
374
      });
375
      return r;
376
    };
377
    const objAcc = r => (x, i) => {
378
      r[i] = x;
379
    };
380
    const internalFilter = (obj, pred, onTrue, onFalse) => {
381
      each(obj, (x, i) => {
382
        (pred(x, i) ? onTrue : onFalse)(x, i);
383
      });
384
    };
385
    const bifilter = (obj, pred) => {
386
      const t = {};
387
      const f = {};
388
      internalFilter(obj, pred, objAcc(t), objAcc(f));
389
      return {
390
        t,
391
        f
392
      };
393
    };
394
    const filter$1 = (obj, pred) => {
395
      const t = {};
396
      internalFilter(obj, pred, objAcc(t), noop);
397
      return t;
398
    };
399
    const mapToArray = (obj, f) => {
400
      const r = [];
401
      each(obj, (value, name) => {
402
        r.push(f(value, name));
403
      });
404
      return r;
405
    };
406
    const find$4 = (obj, pred) => {
407
      const props = keys(obj);
408
      for (let k = 0, len = props.length; k < len; k++) {
409
        const i = props[k];
410
        const x = obj[i];
411
        if (pred(x, i, obj)) {
412
          return Optional.some(x);
413
        }
414
      }
415
      return Optional.none();
416
    };
417
    const values = obj => {
418
      return mapToArray(obj, identity);
419
    };
420
    const get$g = (obj, key) => {
421
      return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
422
    };
423
    const has$2 = (obj, key) => hasOwnProperty.call(obj, key);
424
    const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
425
 
426
    const is$1 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
427
    const equals = (lhs, rhs, comparator = tripleEquals) => lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
428
    const cat = arr => {
429
      const r = [];
430
      const push = x => {
431
        r.push(x);
432
      };
433
      for (let i = 0; i < arr.length; i++) {
434
        arr[i].each(push);
435
      }
436
      return r;
437
    };
438
    const sequence = arr => {
439
      const r = [];
440
      for (let i = 0; i < arr.length; i++) {
441
        const x = arr[i];
442
        if (x.isSome()) {
443
          r.push(x.getOrDie());
444
        } else {
445
          return Optional.none();
446
        }
447
      }
448
      return Optional.some(r);
449
    };
450
    const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
451
    const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
452
    const mapFrom = (a, f) => a !== undefined && a !== null ? Optional.some(f(a)) : Optional.none();
453
    const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
454
 
455
    const addToEnd = (str, suffix) => {
456
      return str + suffix;
457
    };
458
    const removeFromStart = (str, numChars) => {
459
      return str.substring(numChars);
460
    };
461
 
462
    const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
463
    const removeLeading = (str, prefix) => {
464
      return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
465
    };
466
    const ensureTrailing = (str, suffix) => {
467
      return endsWith(str, suffix) ? str : addToEnd(str, suffix);
468
    };
469
    const contains$1 = (str, substr, start = 0, end) => {
470
      const idx = str.indexOf(substr, start);
471
      if (idx !== -1) {
472
        return isUndefined(end) ? true : idx + substr.length <= end;
473
      } else {
474
        return false;
475
      }
476
    };
477
    const startsWith = (str, prefix) => {
478
      return checkRange(str, prefix, 0);
479
    };
480
    const endsWith = (str, suffix) => {
481
      return checkRange(str, suffix, str.length - suffix.length);
482
    };
483
    const blank = r => s => s.replace(r, '');
484
    const trim$1 = blank(/^\s+|\s+$/g);
485
    const isNotEmpty = s => s.length > 0;
486
    const isEmpty = s => !isNotEmpty(s);
487
 
488
    const isSupported$1 = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
489
 
490
    const fromHtml$2 = (html, scope) => {
491
      const doc = scope || document;
492
      const div = doc.createElement('div');
493
      div.innerHTML = html;
494
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
495
        const message = 'HTML does not have a single root node';
496
        console.error(message, html);
497
        throw new Error(message);
498
      }
499
      return fromDom(div.childNodes[0]);
500
    };
501
    const fromTag = (tag, scope) => {
502
      const doc = scope || document;
503
      const node = doc.createElement(tag);
504
      return fromDom(node);
505
    };
506
    const fromText = (text, scope) => {
507
      const doc = scope || document;
508
      const node = doc.createTextNode(text);
509
      return fromDom(node);
510
    };
511
    const fromDom = node => {
512
      if (node === null || node === undefined) {
513
        throw new Error('Node cannot be null or undefined');
514
      }
515
      return { dom: node };
516
    };
517
    const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
518
    const SugarElement = {
519
      fromHtml: fromHtml$2,
520
      fromTag,
521
      fromText,
522
      fromDom,
523
      fromPoint
524
    };
525
 
526
    const Global = typeof window !== 'undefined' ? window : Function('return this;')();
527
 
528
    const path$1 = (parts, scope) => {
529
      let o = scope !== undefined && scope !== null ? scope : Global;
530
      for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
531
        o = o[parts[i]];
532
      }
533
      return o;
534
    };
535
    const resolve = (p, scope) => {
536
      const parts = p.split('.');
537
      return path$1(parts, scope);
538
    };
539
 
540
    const unsafe = (name, scope) => {
541
      return resolve(name, scope);
542
    };
543
    const getOrDie$1 = (name, scope) => {
544
      const actual = unsafe(name, scope);
545
      if (actual === undefined || actual === null) {
546
        throw new Error(name + ' not available on this browser');
547
      }
548
      return actual;
549
    };
550
 
551
    const getPrototypeOf$1 = Object.getPrototypeOf;
552
    const sandHTMLElement = scope => {
553
      return getOrDie$1('HTMLElement', scope);
554
    };
555
    const isPrototypeOf = x => {
556
      const scope = resolve('ownerDocument.defaultView', x);
557
      return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name));
558
    };
559
 
560
    const DOCUMENT = 9;
561
    const DOCUMENT_FRAGMENT = 11;
562
    const ELEMENT = 1;
563
    const TEXT = 3;
564
 
565
    const name$3 = element => {
566
      const r = element.dom.nodeName;
567
      return r.toLowerCase();
568
    };
569
    const type$1 = element => element.dom.nodeType;
570
    const isType = t => element => type$1(element) === t;
571
    const isHTMLElement = element => isElement$1(element) && isPrototypeOf(element.dom);
572
    const isElement$1 = isType(ELEMENT);
573
    const isText = isType(TEXT);
574
    const isDocument = isType(DOCUMENT);
575
    const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
576
    const isTag = tag => e => isElement$1(e) && name$3(e) === tag;
577
 
578
    const is = (element, selector) => {
579
      const dom = element.dom;
580
      if (dom.nodeType !== ELEMENT) {
581
        return false;
582
      } else {
583
        const elem = dom;
584
        if (elem.matches !== undefined) {
585
          return elem.matches(selector);
586
        } else if (elem.msMatchesSelector !== undefined) {
587
          return elem.msMatchesSelector(selector);
588
        } else if (elem.webkitMatchesSelector !== undefined) {
589
          return elem.webkitMatchesSelector(selector);
590
        } else if (elem.mozMatchesSelector !== undefined) {
591
          return elem.mozMatchesSelector(selector);
592
        } else {
593
          throw new Error('Browser lacks native selectors');
594
        }
595
      }
596
    };
597
    const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
598
    const all$3 = (selector, scope) => {
599
      const base = scope === undefined ? document : scope.dom;
600
      return bypassSelector(base) ? [] : map$2(base.querySelectorAll(selector), SugarElement.fromDom);
601
    };
602
    const one = (selector, scope) => {
603
      const base = scope === undefined ? document : scope.dom;
604
      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
605
    };
606
 
607
    const eq = (e1, e2) => e1.dom === e2.dom;
608
    const contains = (e1, e2) => {
609
      const d1 = e1.dom;
610
      const d2 = e2.dom;
611
      return d1 === d2 ? false : d1.contains(d2);
612
    };
613
 
614
    const owner$4 = element => SugarElement.fromDom(element.dom.ownerDocument);
615
    const documentOrOwner = dos => isDocument(dos) ? dos : owner$4(dos);
616
    const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
617
    const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
618
    const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
619
    const parentNode = element => parent(element);
620
    const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
621
    const parents = (element, isRoot) => {
622
      const stop = isFunction(isRoot) ? isRoot : never;
623
      let dom = element.dom;
624
      const ret = [];
625
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
626
        const rawParent = dom.parentNode;
627
        const p = SugarElement.fromDom(rawParent);
628
        ret.push(p);
629
        if (stop(p) === true) {
630
          break;
631
        } else {
632
          dom = rawParent;
633
        }
634
      }
635
      return ret;
636
    };
637
    const offsetParent = element => Optional.from(element.dom.offsetParent).map(SugarElement.fromDom);
638
    const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
639
    const children = element => map$2(element.dom.childNodes, SugarElement.fromDom);
640
    const child$2 = (element, index) => {
641
      const cs = element.dom.childNodes;
642
      return Optional.from(cs[index]).map(SugarElement.fromDom);
643
    };
644
    const firstChild = element => child$2(element, 0);
645
    const spot = (element, offset) => ({
646
      element,
647
      offset
648
    });
649
    const leaf = (element, offset) => {
650
      const cs = children(element);
651
      return cs.length > 0 && offset < cs.length ? spot(cs[offset], 0) : spot(element, offset);
652
    };
653
 
654
    const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
655
    const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
656
    const isSupported = constant$1(supported);
657
    const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
658
    const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
659
    const isInShadowRoot = e => getShadowRoot(e).isSome();
660
    const getShadowRoot = e => {
661
      const r = getRootNode(e);
662
      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
663
    };
664
    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
665
    const getOriginalEventTarget = event => {
666
      if (isSupported() && isNonNullable(event.target)) {
667
        const el = SugarElement.fromDom(event.target);
668
        if (isElement$1(el) && isOpenShadowHost(el)) {
669
          if (event.composed && event.composedPath) {
670
            const composedPath = event.composedPath();
671
            if (composedPath) {
672
              return head(composedPath);
673
            }
674
          }
675
        }
676
      }
677
      return Optional.from(event.target);
678
    };
679
    const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
680
 
681
    const inBody = element => {
682
      const dom = isText(element) ? element.dom.parentNode : element.dom;
683
      if (dom === undefined || dom === null || dom.ownerDocument === null) {
684
        return false;
685
      }
686
      const doc = dom.ownerDocument;
687
      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
688
    };
689
    const body = () => getBody(SugarElement.fromDom(document));
690
    const getBody = doc => {
691
      const b = doc.dom.body;
692
      if (b === null || b === undefined) {
693
        throw new Error('Body is not available yet');
694
      }
695
      return SugarElement.fromDom(b);
696
    };
697
 
698
    const rawSet = (dom, key, value) => {
699
      if (isString(value) || isBoolean(value) || isNumber(value)) {
700
        dom.setAttribute(key, value + '');
701
      } else {
702
        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
703
        throw new Error('Attribute value was not simple');
704
      }
705
    };
706
    const set$9 = (element, key, value) => {
707
      rawSet(element.dom, key, value);
708
    };
709
    const setAll$1 = (element, attrs) => {
710
      const dom = element.dom;
711
      each(attrs, (v, k) => {
712
        rawSet(dom, k, v);
713
      });
714
    };
715
    const get$f = (element, key) => {
716
      const v = element.dom.getAttribute(key);
717
      return v === null ? undefined : v;
718
    };
719
    const getOpt = (element, key) => Optional.from(get$f(element, key));
720
    const has$1 = (element, key) => {
721
      const dom = element.dom;
722
      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
723
    };
724
    const remove$7 = (element, key) => {
725
      element.dom.removeAttribute(key);
726
    };
727
    const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
728
      acc[attr.name] = attr.value;
729
      return acc;
730
    }, {});
731
 
732
    const internalSet = (dom, property, value) => {
733
      if (!isString(value)) {
734
        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
735
        throw new Error('CSS value must be a string: ' + value);
736
      }
737
      if (isSupported$1(dom)) {
738
        dom.style.setProperty(property, value);
739
      }
740
    };
741
    const internalRemove = (dom, property) => {
742
      if (isSupported$1(dom)) {
743
        dom.style.removeProperty(property);
744
      }
745
    };
746
    const set$8 = (element, property, value) => {
747
      const dom = element.dom;
748
      internalSet(dom, property, value);
749
    };
750
    const setAll = (element, css) => {
751
      const dom = element.dom;
752
      each(css, (v, k) => {
753
        internalSet(dom, k, v);
754
      });
755
    };
756
    const setOptions = (element, css) => {
757
      const dom = element.dom;
758
      each(css, (v, k) => {
759
        v.fold(() => {
760
          internalRemove(dom, k);
761
        }, value => {
762
          internalSet(dom, k, value);
763
        });
764
      });
765
    };
766
    const get$e = (element, property) => {
767
      const dom = element.dom;
768
      const styles = window.getComputedStyle(dom);
769
      const r = styles.getPropertyValue(property);
770
      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
771
    };
772
    const getUnsafeProperty = (dom, property) => isSupported$1(dom) ? dom.style.getPropertyValue(property) : '';
773
    const getRaw = (element, property) => {
774
      const dom = element.dom;
775
      const raw = getUnsafeProperty(dom, property);
776
      return Optional.from(raw).filter(r => r.length > 0);
777
    };
778
    const getAllRaw = element => {
779
      const css = {};
780
      const dom = element.dom;
781
      if (isSupported$1(dom)) {
782
        for (let i = 0; i < dom.style.length; i++) {
783
          const ruleName = dom.style.item(i);
784
          css[ruleName] = dom.style[ruleName];
785
        }
786
      }
787
      return css;
788
    };
789
    const isValidValue$1 = (tag, property, value) => {
790
      const element = SugarElement.fromTag(tag);
791
      set$8(element, property, value);
792
      const style = getRaw(element, property);
793
      return style.isSome();
794
    };
795
    const remove$6 = (element, property) => {
796
      const dom = element.dom;
797
      internalRemove(dom, property);
798
      if (is$1(getOpt(element, 'style').map(trim$1), '')) {
799
        remove$7(element, 'style');
800
      }
801
    };
802
    const reflow = e => e.dom.offsetWidth;
803
 
804
    const Dimension = (name, getOffset) => {
805
      const set = (element, h) => {
806
        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
807
          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
808
        }
809
        const dom = element.dom;
810
        if (isSupported$1(dom)) {
811
          dom.style[name] = h + 'px';
812
        }
813
      };
814
      const get = element => {
815
        const r = getOffset(element);
816
        if (r <= 0 || r === null) {
817
          const css = get$e(element, name);
818
          return parseFloat(css) || 0;
819
        }
820
        return r;
821
      };
822
      const getOuter = get;
823
      const aggregate = (element, properties) => foldl(properties, (acc, property) => {
824
        const val = get$e(element, property);
825
        const value = val === undefined ? 0 : parseInt(val, 10);
826
        return isNaN(value) ? acc : acc + value;
827
      }, 0);
828
      const max = (element, value, properties) => {
829
        const cumulativeInclusions = aggregate(element, properties);
830
        const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
831
        return absoluteMax;
832
      };
833
      return {
834
        set,
835
        get,
836
        getOuter,
837
        aggregate,
838
        max
839
      };
840
    };
841
 
842
    const api$2 = Dimension('height', element => {
843
      const dom = element.dom;
844
      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
845
    });
846
    const get$d = element => api$2.get(element);
847
    const getOuter$2 = element => api$2.getOuter(element);
848
    const setMax$1 = (element, value) => {
849
      const inclusions = [
850
        'margin-top',
851
        'border-top-width',
852
        'padding-top',
853
        'padding-bottom',
854
        'border-bottom-width',
855
        'margin-bottom'
856
      ];
857
      const absMax = api$2.max(element, value, inclusions);
858
      set$8(element, 'max-height', absMax + 'px');
859
    };
860
 
861
    const r$1 = (left, top) => {
862
      const translate = (x, y) => r$1(left + x, top + y);
863
      return {
864
        left,
865
        top,
866
        translate
867
      };
868
    };
869
    const SugarPosition = r$1;
870
 
871
    const boxPosition = dom => {
872
      const box = dom.getBoundingClientRect();
873
      return SugarPosition(box.left, box.top);
874
    };
875
    const firstDefinedOrZero = (a, b) => {
876
      if (a !== undefined) {
877
        return a;
878
      } else {
879
        return b !== undefined ? b : 0;
880
      }
881
    };
882
    const absolute$3 = element => {
883
      const doc = element.dom.ownerDocument;
884
      const body = doc.body;
885
      const win = doc.defaultView;
886
      const html = doc.documentElement;
887
      if (body === element.dom) {
888
        return SugarPosition(body.offsetLeft, body.offsetTop);
889
      }
890
      const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
891
      const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
892
      const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
893
      const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
894
      return viewport$1(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
895
    };
896
    const viewport$1 = element => {
897
      const dom = element.dom;
898
      const doc = dom.ownerDocument;
899
      const body = doc.body;
900
      if (body === dom) {
901
        return SugarPosition(body.offsetLeft, body.offsetTop);
902
      }
903
      if (!inBody(element)) {
904
        return SugarPosition(0, 0);
905
      }
906
      return boxPosition(dom);
907
    };
908
 
909
    const api$1 = Dimension('width', element => element.dom.offsetWidth);
910
    const set$7 = (element, h) => api$1.set(element, h);
911
    const get$c = element => api$1.get(element);
912
    const getOuter$1 = element => api$1.getOuter(element);
913
    const setMax = (element, value) => {
914
      const inclusions = [
915
        'margin-left',
916
        'border-left-width',
917
        'padding-left',
918
        'padding-right',
919
        'border-right-width',
920
        'margin-right'
921
      ];
922
      const absMax = api$1.max(element, value, inclusions);
923
      set$8(element, 'max-width', absMax + 'px');
924
    };
925
 
926
    const cached = f => {
927
      let called = false;
928
      let r;
929
      return (...args) => {
930
        if (!called) {
931
          called = true;
932
          r = f.apply(null, args);
933
        }
934
        return r;
935
      };
936
    };
937
 
938
    const DeviceType = (os, browser, userAgent, mediaMatch) => {
939
      const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
940
      const isiPhone = os.isiOS() && !isiPad;
941
      const isMobile = os.isiOS() || os.isAndroid();
942
      const isTouch = isMobile || mediaMatch('(pointer:coarse)');
943
      const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
944
      const isPhone = isiPhone || isMobile && !isTablet;
945
      const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
946
      const isDesktop = !isPhone && !isTablet && !iOSwebview;
947
      return {
948
        isiPad: constant$1(isiPad),
949
        isiPhone: constant$1(isiPhone),
950
        isTablet: constant$1(isTablet),
951
        isPhone: constant$1(isPhone),
952
        isTouch: constant$1(isTouch),
953
        isAndroid: os.isAndroid,
954
        isiOS: os.isiOS,
955
        isWebView: constant$1(iOSwebview),
956
        isDesktop: constant$1(isDesktop)
957
      };
958
    };
959
 
960
    const firstMatch = (regexes, s) => {
961
      for (let i = 0; i < regexes.length; i++) {
962
        const x = regexes[i];
963
        if (x.test(s)) {
964
          return x;
965
        }
966
      }
967
      return undefined;
968
    };
969
    const find$3 = (regexes, agent) => {
970
      const r = firstMatch(regexes, agent);
971
      if (!r) {
972
        return {
973
          major: 0,
974
          minor: 0
975
        };
976
      }
977
      const group = i => {
978
        return Number(agent.replace(r, '$' + i));
979
      };
980
      return nu$d(group(1), group(2));
981
    };
982
    const detect$5 = (versionRegexes, agent) => {
983
      const cleanedAgent = String(agent).toLowerCase();
984
      if (versionRegexes.length === 0) {
985
        return unknown$3();
986
      }
987
      return find$3(versionRegexes, cleanedAgent);
988
    };
989
    const unknown$3 = () => {
990
      return nu$d(0, 0);
991
    };
992
    const nu$d = (major, minor) => {
993
      return {
994
        major,
995
        minor
996
      };
997
    };
998
    const Version = {
999
      nu: nu$d,
1000
      detect: detect$5,
1001
      unknown: unknown$3
1002
    };
1003
 
1004
    const detectBrowser$1 = (browsers, userAgentData) => {
1005
      return findMap(userAgentData.brands, uaBrand => {
1006
        const lcBrand = uaBrand.brand.toLowerCase();
1007
        return find$5(browsers, browser => {
1008
          var _a;
1009
          return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
1010
        }).map(info => ({
1011
          current: info.name,
1012
          version: Version.nu(parseInt(uaBrand.version, 10), 0)
1013
        }));
1014
      });
1015
    };
1016
 
1017
    const detect$4 = (candidates, userAgent) => {
1018
      const agent = String(userAgent).toLowerCase();
1019
      return find$5(candidates, candidate => {
1020
        return candidate.search(agent);
1021
      });
1022
    };
1023
    const detectBrowser = (browsers, userAgent) => {
1024
      return detect$4(browsers, userAgent).map(browser => {
1025
        const version = Version.detect(browser.versionRegexes, userAgent);
1026
        return {
1027
          current: browser.name,
1028
          version
1029
        };
1030
      });
1031
    };
1032
    const detectOs = (oses, userAgent) => {
1033
      return detect$4(oses, userAgent).map(os => {
1034
        const version = Version.detect(os.versionRegexes, userAgent);
1035
        return {
1036
          current: os.name,
1037
          version
1038
        };
1039
      });
1040
    };
1041
 
1042
    const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
1043
    const checkContains = target => {
1044
      return uastring => {
1045
        return contains$1(uastring, target);
1046
      };
1047
    };
1048
    const browsers = [
1049
      {
1050
        name: 'Edge',
1051
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
1052
        search: uastring => {
1053
          return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
1054
        }
1055
      },
1056
      {
1057
        name: 'Chromium',
1058
        brand: 'Chromium',
1059
        versionRegexes: [
1060
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
1061
          normalVersionRegex
1062
        ],
1063
        search: uastring => {
1064
          return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
1065
        }
1066
      },
1067
      {
1068
        name: 'IE',
1069
        versionRegexes: [
1070
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
1071
          /.*?rv:([0-9]+)\.([0-9]+).*/
1072
        ],
1073
        search: uastring => {
1074
          return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
1075
        }
1076
      },
1077
      {
1078
        name: 'Opera',
1079
        versionRegexes: [
1080
          normalVersionRegex,
1081
          /.*?opera\/([0-9]+)\.([0-9]+).*/
1082
        ],
1083
        search: checkContains('opera')
1084
      },
1085
      {
1086
        name: 'Firefox',
1087
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
1088
        search: checkContains('firefox')
1089
      },
1090
      {
1091
        name: 'Safari',
1092
        versionRegexes: [
1093
          normalVersionRegex,
1094
          /.*?cpu os ([0-9]+)_([0-9]+).*/
1095
        ],
1096
        search: uastring => {
1097
          return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
1098
        }
1099
      }
1100
    ];
1101
    const oses = [
1102
      {
1103
        name: 'Windows',
1104
        search: checkContains('win'),
1105
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
1106
      },
1107
      {
1108
        name: 'iOS',
1109
        search: uastring => {
1110
          return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
1111
        },
1112
        versionRegexes: [
1113
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
1114
          /.*cpu os ([0-9]+)_([0-9]+).*/,
1115
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
1116
        ]
1117
      },
1118
      {
1119
        name: 'Android',
1120
        search: checkContains('android'),
1121
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
1122
      },
1123
      {
1124
        name: 'macOS',
1125
        search: checkContains('mac os x'),
1126
        versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
1127
      },
1128
      {
1129
        name: 'Linux',
1130
        search: checkContains('linux'),
1131
        versionRegexes: []
1132
      },
1133
      {
1134
        name: 'Solaris',
1135
        search: checkContains('sunos'),
1136
        versionRegexes: []
1137
      },
1138
      {
1139
        name: 'FreeBSD',
1140
        search: checkContains('freebsd'),
1141
        versionRegexes: []
1142
      },
1143
      {
1144
        name: 'ChromeOS',
1145
        search: checkContains('cros'),
1146
        versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
1147
      }
1148
    ];
1149
    const PlatformInfo = {
1150
      browsers: constant$1(browsers),
1151
      oses: constant$1(oses)
1152
    };
1153
 
1154
    const edge = 'Edge';
1155
    const chromium = 'Chromium';
1156
    const ie = 'IE';
1157
    const opera = 'Opera';
1158
    const firefox = 'Firefox';
1159
    const safari = 'Safari';
1160
    const unknown$2 = () => {
1161
      return nu$c({
1162
        current: undefined,
1163
        version: Version.unknown()
1164
      });
1165
    };
1166
    const nu$c = info => {
1167
      const current = info.current;
1168
      const version = info.version;
1169
      const isBrowser = name => () => current === name;
1170
      return {
1171
        current,
1172
        version,
1173
        isEdge: isBrowser(edge),
1174
        isChromium: isBrowser(chromium),
1175
        isIE: isBrowser(ie),
1176
        isOpera: isBrowser(opera),
1177
        isFirefox: isBrowser(firefox),
1178
        isSafari: isBrowser(safari)
1179
      };
1180
    };
1181
    const Browser = {
1182
      unknown: unknown$2,
1183
      nu: nu$c,
1184
      edge: constant$1(edge),
1185
      chromium: constant$1(chromium),
1186
      ie: constant$1(ie),
1187
      opera: constant$1(opera),
1188
      firefox: constant$1(firefox),
1189
      safari: constant$1(safari)
1190
    };
1191
 
1192
    const windows = 'Windows';
1193
    const ios = 'iOS';
1194
    const android = 'Android';
1195
    const linux = 'Linux';
1196
    const macos = 'macOS';
1197
    const solaris = 'Solaris';
1198
    const freebsd = 'FreeBSD';
1199
    const chromeos = 'ChromeOS';
1200
    const unknown$1 = () => {
1201
      return nu$b({
1202
        current: undefined,
1203
        version: Version.unknown()
1204
      });
1205
    };
1206
    const nu$b = info => {
1207
      const current = info.current;
1208
      const version = info.version;
1209
      const isOS = name => () => current === name;
1210
      return {
1211
        current,
1212
        version,
1213
        isWindows: isOS(windows),
1214
        isiOS: isOS(ios),
1215
        isAndroid: isOS(android),
1216
        isMacOS: isOS(macos),
1217
        isLinux: isOS(linux),
1218
        isSolaris: isOS(solaris),
1219
        isFreeBSD: isOS(freebsd),
1220
        isChromeOS: isOS(chromeos)
1221
      };
1222
    };
1223
    const OperatingSystem = {
1224
      unknown: unknown$1,
1225
      nu: nu$b,
1226
      windows: constant$1(windows),
1227
      ios: constant$1(ios),
1228
      android: constant$1(android),
1229
      linux: constant$1(linux),
1230
      macos: constant$1(macos),
1231
      solaris: constant$1(solaris),
1232
      freebsd: constant$1(freebsd),
1233
      chromeos: constant$1(chromeos)
1234
    };
1235
 
1236
    const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
1237
      const browsers = PlatformInfo.browsers();
1238
      const oses = PlatformInfo.oses();
1239
      const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
1240
      const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
1241
      const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
1242
      return {
1243
        browser,
1244
        os,
1245
        deviceType
1246
      };
1247
    };
1248
    const PlatformDetection = { detect: detect$3 };
1249
 
1250
    const mediaMatch = query => window.matchMedia(query).matches;
1251
    let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
1252
    const detect$2 = () => platform();
1253
 
1254
    const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
1255
      target,
1256
      x,
1257
      y,
1258
      stop,
1259
      prevent,
1260
      kill,
1261
      raw
1262
    });
1263
    const fromRawEvent$1 = rawEvent => {
1264
      const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
1265
      const stop = () => rawEvent.stopPropagation();
1266
      const prevent = () => rawEvent.preventDefault();
1267
      const kill = compose(prevent, stop);
1268
      return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
1269
    };
1270
    const handle = (filter, handler) => rawEvent => {
1271
      if (filter(rawEvent)) {
1272
        handler(fromRawEvent$1(rawEvent));
1273
      }
1274
    };
1275
    const binder = (element, event, filter, handler, useCapture) => {
1276
      const wrapped = handle(filter, handler);
1277
      element.dom.addEventListener(event, wrapped, useCapture);
1278
      return { unbind: curry(unbind, element, event, wrapped, useCapture) };
1279
    };
1280
    const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
1281
    const capture$1 = (element, event, filter, handler) => binder(element, event, filter, handler, true);
1282
    const unbind = (element, event, handler, useCapture) => {
1283
      element.dom.removeEventListener(event, handler, useCapture);
1284
    };
1285
 
1286
    const before$1 = (marker, element) => {
1287
      const parent$1 = parent(marker);
1288
      parent$1.each(v => {
1289
        v.dom.insertBefore(element.dom, marker.dom);
1290
      });
1291
    };
1292
    const after$2 = (marker, element) => {
1293
      const sibling = nextSibling(marker);
1294
      sibling.fold(() => {
1295
        const parent$1 = parent(marker);
1296
        parent$1.each(v => {
1297
          append$2(v, element);
1298
        });
1299
      }, v => {
1300
        before$1(v, element);
1301
      });
1302
    };
1303
    const prepend$1 = (parent, element) => {
1304
      const firstChild$1 = firstChild(parent);
1305
      firstChild$1.fold(() => {
1306
        append$2(parent, element);
1307
      }, v => {
1308
        parent.dom.insertBefore(element.dom, v.dom);
1309
      });
1310
    };
1311
    const append$2 = (parent, element) => {
1312
      parent.dom.appendChild(element.dom);
1313
    };
1314
    const appendAt = (parent, element, index) => {
1315
      child$2(parent, index).fold(() => {
1316
        append$2(parent, element);
1317
      }, v => {
1318
        before$1(v, element);
1319
      });
1320
    };
1321
 
1322
    const append$1 = (parent, elements) => {
1323
      each$1(elements, x => {
1324
        append$2(parent, x);
1325
      });
1326
    };
1327
 
1328
    const empty = element => {
1329
      element.dom.textContent = '';
1330
      each$1(children(element), rogue => {
1331
        remove$5(rogue);
1332
      });
1333
    };
1334
    const remove$5 = element => {
1335
      const dom = element.dom;
1336
      if (dom.parentNode !== null) {
1337
        dom.parentNode.removeChild(dom);
1338
      }
1339
    };
1340
 
1341
    const get$b = _DOC => {
1342
      const doc = _DOC !== undefined ? _DOC.dom : document;
1343
      const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
1344
      const y = doc.body.scrollTop || doc.documentElement.scrollTop;
1345
      return SugarPosition(x, y);
1346
    };
1347
    const to = (x, y, _DOC) => {
1348
      const doc = _DOC !== undefined ? _DOC.dom : document;
1349
      const win = doc.defaultView;
1350
      if (win) {
1351
        win.scrollTo(x, y);
1352
      }
1353
    };
1354
 
1355
    const get$a = _win => {
1356
      const win = _win === undefined ? window : _win;
1357
      if (detect$2().browser.isFirefox()) {
1358
        return Optional.none();
1359
      } else {
1360
        return Optional.from(win.visualViewport);
1361
      }
1362
    };
1363
    const bounds$1 = (x, y, width, height) => ({
1364
      x,
1365
      y,
1366
      width,
1367
      height,
1368
      right: x + width,
1369
      bottom: y + height
1370
    });
1371
    const getBounds$3 = _win => {
1372
      const win = _win === undefined ? window : _win;
1373
      const doc = win.document;
1374
      const scroll = get$b(SugarElement.fromDom(doc));
1375
      return get$a(win).fold(() => {
1376
        const html = win.document.documentElement;
1377
        const width = html.clientWidth;
1378
        const height = html.clientHeight;
1379
        return bounds$1(scroll.left, scroll.top, width, height);
1380
      }, visualViewport => bounds$1(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height));
1381
    };
1382
 
1383
    const getDocument = () => SugarElement.fromDom(document);
1384
 
1385
    const walkUp = (navigation, doc) => {
1386
      const frame = navigation.view(doc);
1387
      return frame.fold(constant$1([]), f => {
1388
        const parent = navigation.owner(f);
1389
        const rest = walkUp(navigation, parent);
1390
        return [f].concat(rest);
1391
      });
1392
    };
1393
    const pathTo = (element, navigation) => {
1394
      const d = navigation.owner(element);
1395
      const paths = walkUp(navigation, d);
1396
      return Optional.some(paths);
1397
    };
1398
 
1399
    const view = doc => {
1400
      var _a;
1401
      const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
1402
      return element.map(SugarElement.fromDom);
1403
    };
1404
    const owner$3 = element => owner$4(element);
1405
 
1406
    var Navigation = /*#__PURE__*/Object.freeze({
1407
        __proto__: null,
1408
        view: view,
1409
        owner: owner$3
1410
    });
1411
 
1412
    const find$2 = element => {
1413
      const doc = getDocument();
1414
      const scroll = get$b(doc);
1415
      const path = pathTo(element, Navigation);
1416
      return path.fold(curry(absolute$3, element), frames => {
1417
        const offset = viewport$1(element);
1418
        const r = foldr(frames, (b, a) => {
1419
          const loc = viewport$1(a);
1420
          return {
1421
            left: b.left + loc.left,
1422
            top: b.top + loc.top
1423
          };
1424
        }, {
1425
          left: 0,
1426
          top: 0
1427
        });
1428
        return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
1429
      });
1430
    };
1431
 
1432
    const pointed = (point, width, height) => ({
1433
      point,
1434
      width,
1435
      height
1436
    });
1437
    const rect = (x, y, width, height) => ({
1438
      x,
1439
      y,
1440
      width,
1441
      height
1442
    });
1443
    const bounds = (x, y, width, height) => ({
1444
      x,
1445
      y,
1446
      width,
1447
      height,
1448
      right: x + width,
1449
      bottom: y + height
1450
    });
1451
    const box$1 = element => {
1452
      const xy = absolute$3(element);
1453
      const w = getOuter$1(element);
1454
      const h = getOuter$2(element);
1455
      return bounds(xy.left, xy.top, w, h);
1456
    };
1457
    const absolute$2 = element => {
1458
      const position = find$2(element);
1459
      const width = getOuter$1(element);
1460
      const height = getOuter$2(element);
1461
      return bounds(position.left, position.top, width, height);
1462
    };
1463
    const constrain = (original, constraint) => {
1464
      const left = Math.max(original.x, constraint.x);
1465
      const top = Math.max(original.y, constraint.y);
1466
      const right = Math.min(original.right, constraint.right);
1467
      const bottom = Math.min(original.bottom, constraint.bottom);
1468
      const width = right - left;
1469
      const height = bottom - top;
1470
      return bounds(left, top, width, height);
1471
    };
1472
    const constrainByMany = (original, constraints) => {
1473
      return foldl(constraints, (acc, c) => constrain(acc, c), original);
1474
    };
1475
    const win = () => getBounds$3(window);
1476
 
1477
    var global$a = tinymce.util.Tools.resolve('tinymce.ThemeManager');
1478
 
1479
    const value$4 = value => {
1480
      const applyHelper = fn => fn(value);
1481
      const constHelper = constant$1(value);
1482
      const outputHelper = () => output;
1483
      const output = {
1484
        tag: true,
1485
        inner: value,
1486
        fold: (_onError, onValue) => onValue(value),
1487
        isValue: always,
1488
        isError: never,
1489
        map: mapper => Result.value(mapper(value)),
1490
        mapError: outputHelper,
1491
        bind: applyHelper,
1492
        exists: applyHelper,
1493
        forall: applyHelper,
1494
        getOr: constHelper,
1495
        or: outputHelper,
1496
        getOrThunk: constHelper,
1497
        orThunk: outputHelper,
1498
        getOrDie: constHelper,
1499
        each: fn => {
1500
          fn(value);
1501
        },
1502
        toOptional: () => Optional.some(value)
1503
      };
1504
      return output;
1505
    };
1506
    const error$1 = error => {
1507
      const outputHelper = () => output;
1508
      const output = {
1509
        tag: false,
1510
        inner: error,
1511
        fold: (onError, _onValue) => onError(error),
1512
        isValue: never,
1513
        isError: always,
1514
        map: outputHelper,
1515
        mapError: mapper => Result.error(mapper(error)),
1516
        bind: outputHelper,
1517
        exists: never,
1518
        forall: always,
1519
        getOr: identity,
1520
        or: identity,
1521
        getOrThunk: apply$1,
1522
        orThunk: apply$1,
1523
        getOrDie: die(String(error)),
1524
        each: noop,
1525
        toOptional: Optional.none
1526
      };
1527
      return output;
1528
    };
1529
    const fromOption = (optional, err) => optional.fold(() => error$1(err), value$4);
1530
    const Result = {
1531
      value: value$4,
1532
      error: error$1,
1533
      fromOption
1534
    };
1535
 
1536
    var SimpleResultType;
1537
    (function (SimpleResultType) {
1538
      SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
1539
      SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
1540
    }(SimpleResultType || (SimpleResultType = {})));
1541
    const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
1542
    const partition$2 = results => {
1543
      const values = [];
1544
      const errors = [];
1545
      each$1(results, obj => {
1546
        fold$1(obj, err => errors.push(err), val => values.push(val));
1547
      });
1548
      return {
1549
        values,
1550
        errors
1551
      };
1552
    };
1553
    const mapError = (res, f) => {
1554
      if (res.stype === SimpleResultType.Error) {
1555
        return {
1556
          stype: SimpleResultType.Error,
1557
          serror: f(res.serror)
1558
        };
1559
      } else {
1560
        return res;
1561
      }
1562
    };
1563
    const map = (res, f) => {
1564
      if (res.stype === SimpleResultType.Value) {
1565
        return {
1566
          stype: SimpleResultType.Value,
1567
          svalue: f(res.svalue)
1568
        };
1569
      } else {
1570
        return res;
1571
      }
1572
    };
1573
    const bind$1 = (res, f) => {
1574
      if (res.stype === SimpleResultType.Value) {
1575
        return f(res.svalue);
1576
      } else {
1577
        return res;
1578
      }
1579
    };
1580
    const bindError = (res, f) => {
1581
      if (res.stype === SimpleResultType.Error) {
1582
        return f(res.serror);
1583
      } else {
1584
        return res;
1585
      }
1586
    };
1587
    const svalue = v => ({
1588
      stype: SimpleResultType.Value,
1589
      svalue: v
1590
    });
1591
    const serror = e => ({
1592
      stype: SimpleResultType.Error,
1593
      serror: e
1594
    });
1595
    const toResult$1 = res => fold$1(res, Result.error, Result.value);
1596
    const fromResult$1 = res => res.fold(serror, svalue);
1597
    const SimpleResult = {
1598
      fromResult: fromResult$1,
1599
      toResult: toResult$1,
1600
      svalue,
1601
      partition: partition$2,
1602
      serror,
1603
      bind: bind$1,
1604
      bindError,
1605
      map,
1606
      mapError,
1607
      fold: fold$1
1608
    };
1609
 
1610
    const field$2 = (key, newKey, presence, prop) => ({
1611
      tag: 'field',
1612
      key,
1613
      newKey,
1614
      presence,
1615
      prop
1616
    });
1617
    const customField$1 = (newKey, instantiator) => ({
1618
      tag: 'custom',
1619
      newKey,
1620
      instantiator
1621
    });
1622
    const fold = (value, ifField, ifCustom) => {
1623
      switch (value.tag) {
1624
      case 'field':
1625
        return ifField(value.key, value.newKey, value.presence, value.prop);
1626
      case 'custom':
1627
        return ifCustom(value.newKey, value.instantiator);
1628
      }
1629
    };
1630
 
1631
    const shallow$1 = (old, nu) => {
1632
      return nu;
1633
    };
1634
    const deep$1 = (old, nu) => {
1635
      const bothObjects = isPlainObject(old) && isPlainObject(nu);
1636
      return bothObjects ? deepMerge(old, nu) : nu;
1637
    };
1638
    const baseMerge = merger => {
1639
      return (...objects) => {
1640
        if (objects.length === 0) {
1641
          throw new Error(`Can't merge zero objects`);
1642
        }
1643
        const ret = {};
1644
        for (let j = 0; j < objects.length; j++) {
1645
          const curObject = objects[j];
1646
          for (const key in curObject) {
1647
            if (has$2(curObject, key)) {
1648
              ret[key] = merger(ret[key], curObject[key]);
1649
            }
1650
          }
1651
        }
1652
        return ret;
1653
      };
1654
    };
1655
    const deepMerge = baseMerge(deep$1);
1656
    const merge$1 = baseMerge(shallow$1);
1657
 
1658
    const required$2 = () => ({
1659
      tag: 'required',
1660
      process: {}
1661
    });
1662
    const defaultedThunk = fallbackThunk => ({
1663
      tag: 'defaultedThunk',
1664
      process: fallbackThunk
1665
    });
1666
    const defaulted$1 = fallback => defaultedThunk(constant$1(fallback));
1667
    const asOption = () => ({
1668
      tag: 'option',
1669
      process: {}
1670
    });
1671
    const mergeWithThunk = baseThunk => ({
1672
      tag: 'mergeWithThunk',
1673
      process: baseThunk
1674
    });
1675
    const mergeWith = base => mergeWithThunk(constant$1(base));
1676
 
1677
    const mergeValues$1 = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge$1.apply(undefined, values))) : SimpleResult.svalue(base);
1678
    const mergeErrors$1 = errors => compose(SimpleResult.serror, flatten)(errors);
1679
    const consolidateObj = (objects, base) => {
1680
      const partition = SimpleResult.partition(objects);
1681
      return partition.errors.length > 0 ? mergeErrors$1(partition.errors) : mergeValues$1(partition.values, base);
1682
    };
1683
    const consolidateArr = objects => {
1684
      const partitions = SimpleResult.partition(objects);
1685
      return partitions.errors.length > 0 ? mergeErrors$1(partitions.errors) : SimpleResult.svalue(partitions.values);
1686
    };
1687
    const ResultCombine = {
1688
      consolidateObj,
1689
      consolidateArr
1690
    };
1691
 
1692
    const formatObj = input => {
1693
      return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
1694
    };
1695
    const formatErrors = errors => {
1696
      const es = errors.length > 10 ? errors.slice(0, 10).concat([{
1697
          path: [],
1698
          getErrorInfo: constant$1('... (only showing first ten failures)')
1699
        }]) : errors;
1700
      return map$2(es, e => {
1701
        return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
1702
      });
1703
    };
1704
 
1705
    const nu$a = (path, getErrorInfo) => {
1706
      return SimpleResult.serror([{
1707
          path,
1708
          getErrorInfo
1709
        }]);
1710
    };
1711
    const missingRequired = (path, key, obj) => nu$a(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
1712
    const missingKey = (path, key) => nu$a(path, () => 'Choice schema did not contain choice key: "' + key + '"');
1713
    const missingBranch = (path, branches, branch) => nu$a(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
1714
    const unsupportedFields = (path, unsupported) => nu$a(path, () => 'There are unsupported fields: [' + unsupported.join(', ') + '] specified');
1715
    const custom = (path, err) => nu$a(path, constant$1(err));
1716
 
1717
    const value$3 = validator => {
1718
      const extract = (path, val) => {
1719
        return SimpleResult.bindError(validator(val), err => custom(path, err));
1720
      };
1721
      const toString = constant$1('val');
1722
      return {
1723
        extract,
1724
        toString
1725
      };
1726
    };
1727
    const anyValue$1 = value$3(SimpleResult.svalue);
1728
 
1729
    const requiredAccess = (path, obj, key, bundle) => get$g(obj, key).fold(() => missingRequired(path, key, obj), bundle);
1730
    const fallbackAccess = (obj, key, fallback, bundle) => {
1731
      const v = get$g(obj, key).getOrThunk(() => fallback(obj));
1732
      return bundle(v);
1733
    };
1734
    const optionAccess = (obj, key, bundle) => bundle(get$g(obj, key));
1735
    const optionDefaultedAccess = (obj, key, fallback, bundle) => {
1736
      const opt = get$g(obj, key).map(val => val === true ? fallback(obj) : val);
1737
      return bundle(opt);
1738
    };
1739
    const extractField = (field, path, obj, key, prop) => {
1740
      const bundle = av => prop.extract(path.concat([key]), av);
1741
      const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
1742
        const result = prop.extract(path.concat([key]), ov);
1743
        return SimpleResult.map(result, Optional.some);
1744
      });
1745
      switch (field.tag) {
1746
      case 'required':
1747
        return requiredAccess(path, obj, key, bundle);
1748
      case 'defaultedThunk':
1749
        return fallbackAccess(obj, key, field.process, bundle);
1750
      case 'option':
1751
        return optionAccess(obj, key, bundleAsOption);
1752
      case 'defaultedOptionThunk':
1753
        return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
1754
      case 'mergeWithThunk': {
1755
          return fallbackAccess(obj, key, constant$1({}), v => {
1756
            const result = deepMerge(field.process(obj), v);
1757
            return bundle(result);
1758
          });
1759
        }
1760
      }
1761
    };
1762
    const extractFields = (path, obj, fields) => {
1763
      const success = {};
1764
      const errors = [];
1765
      for (const field of fields) {
1766
        fold(field, (key, newKey, presence, prop) => {
1767
          const result = extractField(presence, path, obj, key, prop);
1768
          SimpleResult.fold(result, err => {
1769
            errors.push(...err);
1770
          }, res => {
1771
            success[newKey] = res;
1772
          });
1773
        }, (newKey, instantiator) => {
1774
          success[newKey] = instantiator(obj);
1775
        });
1776
      }
1777
      return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
1778
    };
1779
    const valueThunk = getDelegate => {
1780
      const extract = (path, val) => getDelegate().extract(path, val);
1781
      const toString = () => getDelegate().toString();
1782
      return {
1783
        extract,
1784
        toString
1785
      };
1786
    };
1787
    const getSetKeys = obj => keys(filter$1(obj, isNonNullable));
1788
    const objOfOnly = fields => {
1789
      const delegate = objOf(fields);
1790
      const fieldNames = foldr(fields, (acc, value) => {
1791
        return fold(value, key => deepMerge(acc, { [key]: true }), constant$1(acc));
1792
      }, {});
1793
      const extract = (path, o) => {
1794
        const keys = isBoolean(o) ? [] : getSetKeys(o);
1795
        const extra = filter$2(keys, k => !hasNonNullableKey(fieldNames, k));
1796
        return extra.length === 0 ? delegate.extract(path, o) : unsupportedFields(path, extra);
1797
      };
1798
      return {
1799
        extract,
1800
        toString: delegate.toString
1801
      };
1802
    };
1803
    const objOf = values => {
1804
      const extract = (path, o) => extractFields(path, o, values);
1805
      const toString = () => {
1806
        const fieldStrings = map$2(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
1807
        return 'obj{\n' + fieldStrings.join('\n') + '}';
1808
      };
1809
      return {
1810
        extract,
1811
        toString
1812
      };
1813
    };
1814
    const arrOf = prop => {
1815
      const extract = (path, array) => {
1816
        const results = map$2(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
1817
        return ResultCombine.consolidateArr(results);
1818
      };
1819
      const toString = () => 'array(' + prop.toString() + ')';
1820
      return {
1821
        extract,
1822
        toString
1823
      };
1824
    };
1825
    const oneOf = (props, rawF) => {
1826
      const f = rawF !== undefined ? rawF : identity;
1827
      const extract = (path, val) => {
1828
        const errors = [];
1829
        for (const prop of props) {
1830
          const res = prop.extract(path, val);
1831
          if (res.stype === SimpleResultType.Value) {
1832
            return {
1833
              stype: SimpleResultType.Value,
1834
              svalue: f(res.svalue)
1835
            };
1836
          }
1837
          errors.push(res);
1838
        }
1839
        return ResultCombine.consolidateArr(errors);
1840
      };
1841
      const toString = () => 'oneOf(' + map$2(props, prop => prop.toString()).join(', ') + ')';
1842
      return {
1843
        extract,
1844
        toString
1845
      };
1846
    };
1847
    const setOf$1 = (validator, prop) => {
1848
      const validateKeys = (path, keys) => arrOf(value$3(validator)).extract(path, keys);
1849
      const extract = (path, o) => {
1850
        const keys$1 = keys(o);
1851
        const validatedKeys = validateKeys(path, keys$1);
1852
        return SimpleResult.bind(validatedKeys, validKeys => {
1853
          const schema = map$2(validKeys, vk => {
1854
            return field$2(vk, vk, required$2(), prop);
1855
          });
1856
          return objOf(schema).extract(path, o);
1857
        });
1858
      };
1859
      const toString = () => 'setOf(' + prop.toString() + ')';
1860
      return {
1861
        extract,
1862
        toString
1863
      };
1864
    };
1865
    const thunk = (_desc, processor) => {
1866
      const getP = cached(processor);
1867
      const extract = (path, val) => getP().extract(path, val);
1868
      const toString = () => getP().toString();
1869
      return {
1870
        extract,
1871
        toString
1872
      };
1873
    };
1874
    const arrOfObj = compose(arrOf, objOf);
1875
 
1876
    const anyValue = constant$1(anyValue$1);
1877
    const typedValue = (validator, expectedType) => value$3(a => {
1878
      const actualType = typeof a;
1879
      return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
1880
    });
1881
    const number = typedValue(isNumber, 'number');
1882
    const string = typedValue(isString, 'string');
1883
    const boolean = typedValue(isBoolean, 'boolean');
1884
    const functionProcessor = typedValue(isFunction, 'function');
1885
    const isPostMessageable = val => {
1886
      if (Object(val) !== val) {
1887
        return true;
1888
      }
1889
      switch ({}.toString.call(val).slice(8, -1)) {
1890
      case 'Boolean':
1891
      case 'Number':
1892
      case 'String':
1893
      case 'Date':
1894
      case 'RegExp':
1895
      case 'Blob':
1896
      case 'FileList':
1897
      case 'ImageData':
1898
      case 'ImageBitmap':
1899
      case 'ArrayBuffer':
1900
        return true;
1901
      case 'Array':
1902
      case 'Object':
1903
        return Object.keys(val).every(prop => isPostMessageable(val[prop]));
1904
      default:
1905
        return false;
1906
      }
1907
    };
1908
    const postMessageable = value$3(a => {
1909
      if (isPostMessageable(a)) {
1910
        return SimpleResult.svalue(a);
1911
      } else {
1912
        return SimpleResult.serror('Expected value to be acceptable for sending via postMessage');
1913
      }
1914
    });
1915
 
1916
    const chooseFrom = (path, input, branches, ch) => {
1917
      const fields = get$g(branches, ch);
1918
      return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
1919
    };
1920
    const choose$2 = (key, branches) => {
1921
      const extract = (path, input) => {
1922
        const choice = get$g(input, key);
1923
        return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
1924
      };
1925
      const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
1926
      return {
1927
        extract,
1928
        toString
1929
      };
1930
    };
1931
 
1932
    const arrOfVal = () => arrOf(anyValue$1);
1933
    const valueOf = validator => value$3(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
1934
    const setOf = (validator, prop) => setOf$1(v => SimpleResult.fromResult(validator(v)), prop);
1935
    const extractValue = (label, prop, obj) => {
1936
      const res = prop.extract([label], obj);
1937
      return SimpleResult.mapError(res, errs => ({
1938
        input: obj,
1939
        errors: errs
1940
      }));
1941
    };
1942
    const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
1943
    const getOrDie = extraction => {
1944
      return extraction.fold(errInfo => {
1945
        throw new Error(formatError(errInfo));
1946
      }, identity);
1947
    };
1948
    const asRawOrDie$1 = (label, prop, obj) => getOrDie(asRaw(label, prop, obj));
1949
    const formatError = errInfo => {
1950
      return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
1951
    };
1952
    const choose$1 = (key, branches) => choose$2(key, map$1(branches, objOf));
1953
    const thunkOf = (desc, schema) => thunk(desc, schema);
1954
 
1955
    const field$1 = field$2;
1956
    const customField = customField$1;
1957
    const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
1958
    const required$1 = key => field$1(key, key, required$2(), anyValue());
1959
    const requiredOf = (key, schema) => field$1(key, key, required$2(), schema);
1960
    const requiredNumber = key => requiredOf(key, number);
1961
    const requiredString = key => requiredOf(key, string);
1962
    const requiredStringEnum = (key, values) => field$1(key, key, required$2(), validateEnum(values));
1963
    const requiredBoolean = key => requiredOf(key, boolean);
1964
    const requiredFunction = key => requiredOf(key, functionProcessor);
1965
    const forbid = (key, message) => field$1(key, key, asOption(), value$3(_v => SimpleResult.serror('The field: ' + key + ' is forbidden. ' + message)));
1966
    const requiredObjOf = (key, objSchema) => field$1(key, key, required$2(), objOf(objSchema));
1967
    const requiredArrayOfObj = (key, objFields) => field$1(key, key, required$2(), arrOfObj(objFields));
1968
    const requiredArrayOf = (key, schema) => field$1(key, key, required$2(), arrOf(schema));
1969
    const option$3 = key => field$1(key, key, asOption(), anyValue());
1970
    const optionOf = (key, schema) => field$1(key, key, asOption(), schema);
1971
    const optionNumber = key => optionOf(key, number);
1972
    const optionString = key => optionOf(key, string);
1973
    const optionStringEnum = (key, values) => optionOf(key, validateEnum(values));
1974
    const optionFunction = key => optionOf(key, functionProcessor);
1975
    const optionArrayOf = (key, schema) => optionOf(key, arrOf(schema));
1976
    const optionObjOf = (key, objSchema) => optionOf(key, objOf(objSchema));
1977
    const optionObjOfOnly = (key, objSchema) => optionOf(key, objOfOnly(objSchema));
1978
    const defaulted = (key, fallback) => field$1(key, key, defaulted$1(fallback), anyValue());
1979
    const defaultedOf = (key, fallback, schema) => field$1(key, key, defaulted$1(fallback), schema);
1980
    const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
1981
    const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
1982
    const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
1983
    const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
1984
    const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
1985
    const defaultedPostMsg = (key, fallback) => defaultedOf(key, fallback, postMessageable);
1986
    const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
1987
    const defaultedObjOf = (key, fallback, objSchema) => defaultedOf(key, fallback, objOf(objSchema));
1988
 
1989
    const Cell = initial => {
1990
      let value = initial;
1991
      const get = () => {
1992
        return value;
1993
      };
1994
      const set = v => {
1995
        value = v;
1996
      };
1997
      return {
1998
        get,
1999
        set
2000
      };
2001
    };
2002
 
2003
    const generate$7 = cases => {
2004
      if (!isArray(cases)) {
2005
        throw new Error('cases must be an array');
2006
      }
2007
      if (cases.length === 0) {
2008
        throw new Error('there must be at least one case');
2009
      }
2010
      const constructors = [];
2011
      const adt = {};
2012
      each$1(cases, (acase, count) => {
2013
        const keys$1 = keys(acase);
2014
        if (keys$1.length !== 1) {
2015
          throw new Error('one and only one name per case');
2016
        }
2017
        const key = keys$1[0];
2018
        const value = acase[key];
2019
        if (adt[key] !== undefined) {
2020
          throw new Error('duplicate key detected:' + key);
2021
        } else if (key === 'cata') {
2022
          throw new Error('cannot have a case named cata (sorry)');
2023
        } else if (!isArray(value)) {
2024
          throw new Error('case arguments must be an array');
2025
        }
2026
        constructors.push(key);
2027
        adt[key] = (...args) => {
2028
          const argLength = args.length;
2029
          if (argLength !== value.length) {
2030
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
2031
          }
2032
          const match = branches => {
2033
            const branchKeys = keys(branches);
2034
            if (constructors.length !== branchKeys.length) {
2035
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
2036
            }
2037
            const allReqd = forall(constructors, reqKey => {
2038
              return contains$2(branchKeys, reqKey);
2039
            });
2040
            if (!allReqd) {
2041
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
2042
            }
2043
            return branches[key].apply(null, args);
2044
          };
2045
          return {
2046
            fold: (...foldArgs) => {
2047
              if (foldArgs.length !== cases.length) {
2048
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
2049
              }
2050
              const target = foldArgs[count];
2051
              return target.apply(null, args);
2052
            },
2053
            match,
2054
            log: label => {
2055
              console.log(label, {
2056
                constructors,
2057
                constructor: key,
2058
                params: args
2059
              });
2060
            }
2061
          };
2062
        };
2063
      });
2064
      return adt;
2065
    };
2066
    const Adt = { generate: generate$7 };
2067
 
2068
    Adt.generate([
2069
      {
2070
        bothErrors: [
2071
          'error1',
2072
          'error2'
2073
        ]
2074
      },
2075
      {
2076
        firstError: [
2077
          'error1',
2078
          'value2'
2079
        ]
2080
      },
2081
      {
2082
        secondError: [
2083
          'value1',
2084
          'error2'
2085
        ]
2086
      },
2087
      {
2088
        bothValues: [
2089
          'value1',
2090
          'value2'
2091
        ]
2092
      }
2093
    ]);
2094
    const partition$1 = results => {
2095
      const errors = [];
2096
      const values = [];
2097
      each$1(results, result => {
2098
        result.fold(err => {
2099
          errors.push(err);
2100
        }, value => {
2101
          values.push(value);
2102
        });
2103
      });
2104
      return {
2105
        errors,
2106
        values
2107
      };
2108
    };
2109
 
2110
    const exclude$1 = (obj, fields) => {
2111
      const r = {};
2112
      each(obj, (v, k) => {
2113
        if (!contains$2(fields, k)) {
2114
          r[k] = v;
2115
        }
2116
      });
2117
      return r;
2118
    };
2119
 
2120
    const wrap$2 = (key, value) => ({ [key]: value });
2121
    const wrapAll$1 = keyvalues => {
2122
      const r = {};
2123
      each$1(keyvalues, kv => {
2124
        r[kv.key] = kv.value;
2125
      });
2126
      return r;
2127
    };
2128
 
2129
    const exclude = (obj, fields) => exclude$1(obj, fields);
2130
    const wrap$1 = (key, value) => wrap$2(key, value);
2131
    const wrapAll = keyvalues => wrapAll$1(keyvalues);
2132
    const mergeValues = (values, base) => {
2133
      return values.length === 0 ? Result.value(base) : Result.value(deepMerge(base, merge$1.apply(undefined, values)));
2134
    };
2135
    const mergeErrors = errors => Result.error(flatten(errors));
2136
    const consolidate = (objs, base) => {
2137
      const partitions = partition$1(objs);
2138
      return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : mergeValues(partitions.values, base);
2139
    };
2140
 
2141
    const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
2142
    const ancestor$2 = (scope, transform, isRoot) => {
2143
      let element = scope.dom;
2144
      const stop = ensureIsRoot(isRoot);
2145
      while (element.parentNode) {
2146
        element = element.parentNode;
2147
        const el = SugarElement.fromDom(element);
2148
        const transformed = transform(el);
2149
        if (transformed.isSome()) {
2150
          return transformed;
2151
        } else if (stop(el)) {
2152
          break;
2153
        }
2154
      }
2155
      return Optional.none();
2156
    };
2157
    const closest$4 = (scope, transform, isRoot) => {
2158
      const current = transform(scope);
2159
      const stop = ensureIsRoot(isRoot);
2160
      return current.orThunk(() => stop(scope) ? Optional.none() : ancestor$2(scope, transform, stop));
2161
    };
2162
 
2163
    const isSource = (component, simulatedEvent) => eq(component.element, simulatedEvent.event.target);
2164
 
2165
    const defaultEventHandler = {
2166
      can: always,
2167
      abort: never,
2168
      run: noop
2169
    };
2170
    const nu$9 = parts => {
2171
      if (!hasNonNullableKey(parts, 'can') && !hasNonNullableKey(parts, 'abort') && !hasNonNullableKey(parts, 'run')) {
2172
        throw new Error('EventHandler defined by: ' + JSON.stringify(parts, null, 2) + ' does not have can, abort, or run!');
2173
      }
2174
      return {
2175
        ...defaultEventHandler,
2176
        ...parts
2177
      };
2178
    };
2179
    const all$2 = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc && f(handler).apply(undefined, args), true);
2180
    const any = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc || f(handler).apply(undefined, args), false);
2181
    const read$2 = handler => isFunction(handler) ? {
2182
      can: always,
2183
      abort: never,
2184
      run: handler
2185
    } : handler;
2186
    const fuse$1 = handlers => {
2187
      const can = all$2(handlers, handler => handler.can);
2188
      const abort = any(handlers, handler => handler.abort);
2189
      const run = (...args) => {
2190
        each$1(handlers, handler => {
2191
          handler.run.apply(undefined, args);
2192
        });
2193
      };
2194
      return {
2195
        can,
2196
        abort,
2197
        run
2198
      };
2199
    };
2200
 
2201
    const constant = constant$1;
2202
    const touchstart = constant('touchstart');
2203
    const touchmove = constant('touchmove');
2204
    const touchend = constant('touchend');
2205
    const touchcancel = constant('touchcancel');
2206
    const mousedown = constant('mousedown');
2207
    const mousemove = constant('mousemove');
2208
    const mouseout = constant('mouseout');
2209
    const mouseup = constant('mouseup');
2210
    const mouseover = constant('mouseover');
2211
    const focusin = constant('focusin');
2212
    const focusout = constant('focusout');
2213
    const keydown = constant('keydown');
2214
    const keyup = constant('keyup');
2215
    const input = constant('input');
2216
    const change = constant('change');
2217
    const click = constant('click');
2218
    const transitioncancel = constant('transitioncancel');
2219
    const transitionend = constant('transitionend');
2220
    const transitionstart = constant('transitionstart');
2221
    const selectstart = constant('selectstart');
2222
 
2223
    const prefixName = name => constant$1('alloy.' + name);
2224
    const alloy = { tap: prefixName('tap') };
2225
    const focus$4 = prefixName('focus');
2226
    const postBlur = prefixName('blur.post');
2227
    const postPaste = prefixName('paste.post');
2228
    const receive = prefixName('receive');
2229
    const execute$5 = prefixName('execute');
2230
    const focusItem = prefixName('focus.item');
2231
    const tap = alloy.tap;
2232
    const longpress = prefixName('longpress');
2233
    const sandboxClose = prefixName('sandbox.close');
2234
    const typeaheadCancel = prefixName('typeahead.cancel');
2235
    const systemInit = prefixName('system.init');
2236
    const documentTouchmove = prefixName('system.touchmove');
2237
    const documentTouchend = prefixName('system.touchend');
2238
    const windowScroll = prefixName('system.scroll');
2239
    const windowResize = prefixName('system.resize');
2240
    const attachedToDom = prefixName('system.attached');
2241
    const detachedFromDom = prefixName('system.detached');
2242
    const dismissRequested = prefixName('system.dismissRequested');
2243
    const repositionRequested = prefixName('system.repositionRequested');
2244
    const focusShifted = prefixName('focusmanager.shifted');
2245
    const slotVisibility = prefixName('slotcontainer.visibility');
2246
    const externalElementScroll = prefixName('system.external.element.scroll');
2247
    const changeTab = prefixName('change.tab');
2248
    const dismissTab = prefixName('dismiss.tab');
2249
    const highlight$1 = prefixName('highlight');
2250
    const dehighlight$1 = prefixName('dehighlight');
2251
 
2252
    const emit = (component, event) => {
2253
      dispatchWith(component, component.element, event, {});
2254
    };
2255
    const emitWith = (component, event, properties) => {
2256
      dispatchWith(component, component.element, event, properties);
2257
    };
2258
    const emitExecute = component => {
2259
      emit(component, execute$5());
2260
    };
2261
    const dispatch = (component, target, event) => {
2262
      dispatchWith(component, target, event, {});
2263
    };
2264
    const dispatchWith = (component, target, event, properties) => {
2265
      const data = {
2266
        target,
2267
        ...properties
2268
      };
2269
      component.getSystem().triggerEvent(event, target, data);
2270
    };
2271
    const retargetAndDispatchWith = (component, target, eventName, properties) => {
2272
      const data = {
2273
        ...properties,
2274
        target
2275
      };
2276
      component.getSystem().triggerEvent(eventName, target, data);
2277
    };
2278
    const dispatchEvent = (component, target, event, simulatedEvent) => {
2279
      component.getSystem().triggerEvent(event, target, simulatedEvent.event);
2280
    };
2281
 
2282
    const derive$2 = configs => wrapAll(configs);
2283
    const abort = (name, predicate) => {
2284
      return {
2285
        key: name,
2286
        value: nu$9({ abort: predicate })
2287
      };
2288
    };
2289
    const can = (name, predicate) => {
2290
      return {
2291
        key: name,
2292
        value: nu$9({ can: predicate })
2293
      };
2294
    };
2295
    const preventDefault = name => {
2296
      return {
2297
        key: name,
2298
        value: nu$9({
2299
          run: (component, simulatedEvent) => {
2300
            simulatedEvent.event.prevent();
2301
          }
2302
        })
2303
      };
2304
    };
2305
    const run$1 = (name, handler) => {
2306
      return {
2307
        key: name,
2308
        value: nu$9({ run: handler })
2309
      };
2310
    };
2311
    const runActionExtra = (name, action, extra) => {
2312
      return {
2313
        key: name,
2314
        value: nu$9({
2315
          run: (component, simulatedEvent) => {
2316
            action.apply(undefined, [
2317
              component,
2318
              simulatedEvent
2319
            ].concat(extra));
2320
          }
2321
        })
2322
      };
2323
    };
2324
    const runOnName = name => {
2325
      return handler => run$1(name, handler);
2326
    };
2327
    const runOnSourceName = name => {
2328
      return handler => ({
2329
        key: name,
2330
        value: nu$9({
2331
          run: (component, simulatedEvent) => {
2332
            if (isSource(component, simulatedEvent)) {
2333
              handler(component, simulatedEvent);
2334
            }
2335
          }
2336
        })
2337
      });
2338
    };
2339
    const redirectToUid = (name, uid) => {
2340
      return run$1(name, (component, simulatedEvent) => {
2341
        component.getSystem().getByUid(uid).each(redirectee => {
2342
          dispatchEvent(redirectee, redirectee.element, name, simulatedEvent);
2343
        });
2344
      });
2345
    };
2346
    const redirectToPart = (name, detail, partName) => {
2347
      const uid = detail.partUids[partName];
2348
      return redirectToUid(name, uid);
2349
    };
2350
    const runWithTarget = (name, f) => {
2351
      return run$1(name, (component, simulatedEvent) => {
2352
        const ev = simulatedEvent.event;
2353
        const target = component.getSystem().getByDom(ev.target).getOrThunk(() => {
2354
          const closest = closest$4(ev.target, el => component.getSystem().getByDom(el).toOptional(), never);
2355
          return closest.getOr(component);
2356
        });
2357
        f(component, target, simulatedEvent);
2358
      });
2359
    };
2360
    const cutter = name => {
2361
      return run$1(name, (component, simulatedEvent) => {
2362
        simulatedEvent.cut();
2363
      });
2364
    };
2365
    const stopper = name => {
2366
      return run$1(name, (component, simulatedEvent) => {
2367
        simulatedEvent.stop();
2368
      });
2369
    };
2370
    const runOnSource = (name, f) => {
2371
      return runOnSourceName(name)(f);
2372
    };
2373
    const runOnAttached = runOnSourceName(attachedToDom());
2374
    const runOnDetached = runOnSourceName(detachedFromDom());
2375
    const runOnInit = runOnSourceName(systemInit());
2376
    const runOnExecute$1 = runOnName(execute$5());
2377
 
2378
    const fromHtml$1 = (html, scope) => {
2379
      const doc = scope || document;
2380
      const div = doc.createElement('div');
2381
      div.innerHTML = html;
2382
      return children(SugarElement.fromDom(div));
2383
    };
2384
 
2385
    const get$9 = element => element.dom.innerHTML;
2386
    const set$6 = (element, content) => {
2387
      const owner = owner$4(element);
2388
      const docDom = owner.dom;
2389
      const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
2390
      const contentElements = fromHtml$1(content, docDom);
2391
      append$1(fragment, contentElements);
2392
      empty(element);
2393
      append$2(element, fragment);
2394
    };
2395
    const getOuter = element => {
2396
      const container = SugarElement.fromTag('div');
2397
      const clone = SugarElement.fromDom(element.dom.cloneNode(true));
2398
      append$2(container, clone);
2399
      return get$9(container);
2400
    };
2401
 
2402
    const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
2403
    const shallow = original => clone$1(original, false);
2404
    const deep = original => clone$1(original, true);
2405
 
2406
    const getHtml = element => {
2407
      if (isShadowRoot(element)) {
2408
        return '#shadow-root';
2409
      } else {
2410
        const clone = shallow(element);
2411
        return getOuter(clone);
2412
      }
2413
    };
2414
 
2415
    const element = elem => getHtml(elem);
2416
 
2417
    const isRecursive = (component, originator, target) => eq(originator, component.element) && !eq(originator, target);
2418
    const events$i = derive$2([can(focus$4(), (component, simulatedEvent) => {
2419
        const event = simulatedEvent.event;
2420
        const originator = event.originator;
2421
        const target = event.target;
2422
        if (isRecursive(component, originator, target)) {
2423
          console.warn(focus$4() + ' did not get interpreted by the desired target. ' + '\nOriginator: ' + element(originator) + '\nTarget: ' + element(target) + '\nCheck the ' + focus$4() + ' event handlers');
2424
          return false;
2425
        } else {
2426
          return true;
2427
        }
2428
      })]);
2429
 
2430
    var DefaultEvents = /*#__PURE__*/Object.freeze({
2431
        __proto__: null,
2432
        events: events$i
2433
    });
2434
 
2435
    let unique = 0;
2436
    const generate$6 = prefix => {
2437
      const date = new Date();
2438
      const time = date.getTime();
2439
      const random = Math.floor(Math.random() * 1000000000);
2440
      unique++;
2441
      return prefix + '_' + random + unique + String(time);
2442
    };
2443
 
2444
    const prefix$1 = constant$1('alloy-id-');
2445
    const idAttr$1 = constant$1('data-alloy-id');
2446
 
2447
    const prefix = prefix$1();
2448
    const idAttr = idAttr$1();
2449
    const write = (label, elem) => {
2450
      const id = generate$6(prefix + label);
2451
      writeOnly(elem, id);
2452
      return id;
2453
    };
2454
    const writeOnly = (elem, uid) => {
2455
      Object.defineProperty(elem.dom, idAttr, {
2456
        value: uid,
2457
        writable: true
2458
      });
2459
    };
2460
    const read$1 = elem => {
2461
      const id = isElement$1(elem) ? elem.dom[idAttr] : null;
2462
      return Optional.from(id);
2463
    };
2464
    const generate$5 = prefix => generate$6(prefix);
2465
 
2466
    const make$8 = identity;
2467
 
2468
    const NoContextApi = getComp => {
2469
      const getMessage = event => `The component must be in a context to execute: ${ event }` + (getComp ? '\n' + element(getComp().element) + ' is not in context.' : '');
2470
      const fail = event => () => {
2471
        throw new Error(getMessage(event));
2472
      };
2473
      const warn = event => () => {
2474
        console.warn(getMessage(event));
2475
      };
2476
      return {
2477
        debugInfo: constant$1('fake'),
2478
        triggerEvent: warn('triggerEvent'),
2479
        triggerFocus: warn('triggerFocus'),
2480
        triggerEscape: warn('triggerEscape'),
2481
        broadcast: warn('broadcast'),
2482
        broadcastOn: warn('broadcastOn'),
2483
        broadcastEvent: warn('broadcastEvent'),
2484
        build: fail('build'),
2485
        buildOrPatch: fail('buildOrPatch'),
2486
        addToWorld: fail('addToWorld'),
2487
        removeFromWorld: fail('removeFromWorld'),
2488
        addToGui: fail('addToGui'),
2489
        removeFromGui: fail('removeFromGui'),
2490
        getByUid: fail('getByUid'),
2491
        getByDom: fail('getByDom'),
2492
        isConnected: never
2493
      };
2494
    };
2495
    const singleton$1 = NoContextApi();
2496
 
2497
    const markAsBehaviourApi = (f, apiName, apiFunction) => {
2498
      const delegate = apiFunction.toString();
2499
      const endIndex = delegate.indexOf(')') + 1;
2500
      const openBracketIndex = delegate.indexOf('(');
2501
      const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
2502
      f.toFunctionAnnotation = () => ({
2503
        name: apiName,
2504
        parameters: cleanParameters(parameters.slice(0, 1).concat(parameters.slice(3)))
2505
      });
2506
      return f;
2507
    };
2508
    const cleanParameters = parameters => map$2(parameters, p => endsWith(p, '/*') ? p.substring(0, p.length - '/*'.length) : p);
2509
    const markAsExtraApi = (f, extraName) => {
2510
      const delegate = f.toString();
2511
      const endIndex = delegate.indexOf(')') + 1;
2512
      const openBracketIndex = delegate.indexOf('(');
2513
      const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
2514
      f.toFunctionAnnotation = () => ({
2515
        name: extraName,
2516
        parameters: cleanParameters(parameters)
2517
      });
2518
      return f;
2519
    };
2520
    const markAsSketchApi = (f, apiFunction) => {
2521
      const delegate = apiFunction.toString();
2522
      const endIndex = delegate.indexOf(')') + 1;
2523
      const openBracketIndex = delegate.indexOf('(');
2524
      const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
2525
      f.toFunctionAnnotation = () => ({
2526
        name: 'OVERRIDE',
2527
        parameters: cleanParameters(parameters.slice(1))
2528
      });
2529
      return f;
2530
    };
2531
 
2532
    const premadeTag = generate$6('alloy-premade');
2533
    const premade$1 = comp => {
2534
      Object.defineProperty(comp.element.dom, premadeTag, {
2535
        value: comp.uid,
2536
        writable: true
2537
      });
2538
      return wrap$1(premadeTag, comp);
2539
    };
2540
    const isPremade = element => has$2(element.dom, premadeTag);
2541
    const getPremade = spec => get$g(spec, premadeTag);
2542
    const makeApi = f => markAsSketchApi((component, ...rest) => f(component.getApis(), component, ...rest), f);
2543
 
2544
    const NoState = { init: () => nu$8({ readState: constant$1('No State required') }) };
2545
    const nu$8 = spec => spec;
2546
 
2547
    const generateFrom$1 = (spec, all) => {
2548
      const schema = map$2(all, a => optionObjOf(a.name(), [
2549
        required$1('config'),
2550
        defaulted('state', NoState)
2551
      ]));
2552
      const validated = asRaw('component.behaviours', objOf(schema), spec.behaviours).fold(errInfo => {
2553
        throw new Error(formatError(errInfo) + '\nComplete spec:\n' + JSON.stringify(spec, null, 2));
2554
      }, identity);
2555
      return {
2556
        list: all,
2557
        data: map$1(validated, optBlobThunk => {
2558
          const output = optBlobThunk.map(blob => ({
2559
            config: blob.config,
2560
            state: blob.state.init(blob.config)
2561
          }));
2562
          return constant$1(output);
2563
        })
2564
      };
2565
    };
2566
    const getBehaviours$3 = bData => bData.list;
2567
    const getData$2 = bData => bData.data;
2568
 
2569
    const byInnerKey = (data, tuple) => {
2570
      const r = {};
2571
      each(data, (detail, key) => {
2572
        each(detail, (value, indexKey) => {
2573
          const chain = get$g(r, indexKey).getOr([]);
2574
          r[indexKey] = chain.concat([tuple(key, value)]);
2575
        });
2576
      });
2577
      return r;
2578
    };
2579
 
2580
    const nu$7 = s => ({
2581
      classes: isUndefined(s.classes) ? [] : s.classes,
2582
      attributes: isUndefined(s.attributes) ? {} : s.attributes,
2583
      styles: isUndefined(s.styles) ? {} : s.styles
2584
    });
2585
    const merge = (defnA, mod) => ({
2586
      ...defnA,
2587
      attributes: {
2588
        ...defnA.attributes,
2589
        ...mod.attributes
2590
      },
2591
      styles: {
2592
        ...defnA.styles,
2593
        ...mod.styles
2594
      },
2595
      classes: defnA.classes.concat(mod.classes)
2596
    });
2597
 
2598
    const combine$2 = (info, baseMod, behaviours, base) => {
2599
      const modsByBehaviour = { ...baseMod };
2600
      each$1(behaviours, behaviour => {
2601
        modsByBehaviour[behaviour.name()] = behaviour.exhibit(info, base);
2602
      });
2603
      const byAspect = byInnerKey(modsByBehaviour, (name, modification) => ({
2604
        name,
2605
        modification
2606
      }));
2607
      const combineObjects = objects => foldr(objects, (b, a) => ({
2608
        ...a.modification,
2609
        ...b
2610
      }), {});
2611
      const combinedClasses = foldr(byAspect.classes, (b, a) => a.modification.concat(b), []);
2612
      const combinedAttributes = combineObjects(byAspect.attributes);
2613
      const combinedStyles = combineObjects(byAspect.styles);
2614
      return nu$7({
2615
        classes: combinedClasses,
2616
        attributes: combinedAttributes,
2617
        styles: combinedStyles
2618
      });
2619
    };
2620
 
2621
    const sortKeys = (label, keyName, array, order) => {
2622
      try {
2623
        const sorted = sort(array, (a, b) => {
2624
          const aKey = a[keyName];
2625
          const bKey = b[keyName];
2626
          const aIndex = order.indexOf(aKey);
2627
          const bIndex = order.indexOf(bKey);
2628
          if (aIndex === -1) {
2629
            throw new Error('The ordering for ' + label + ' does not have an entry for ' + aKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
2630
          }
2631
          if (bIndex === -1) {
2632
            throw new Error('The ordering for ' + label + ' does not have an entry for ' + bKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
2633
          }
2634
          if (aIndex < bIndex) {
2635
            return -1;
2636
          } else if (bIndex < aIndex) {
2637
            return 1;
2638
          } else {
2639
            return 0;
2640
          }
2641
        });
2642
        return Result.value(sorted);
2643
      } catch (err) {
2644
        return Result.error([err]);
2645
      }
2646
    };
2647
 
2648
    const uncurried = (handler, purpose) => ({
2649
      handler,
2650
      purpose
2651
    });
2652
    const curried = (handler, purpose) => ({
2653
      cHandler: handler,
2654
      purpose
2655
    });
2656
    const curryArgs = (descHandler, extraArgs) => curried(curry.apply(undefined, [descHandler.handler].concat(extraArgs)), descHandler.purpose);
2657
    const getCurried = descHandler => descHandler.cHandler;
2658
 
2659
    const behaviourTuple = (name, handler) => ({
2660
      name,
2661
      handler
2662
    });
2663
    const nameToHandlers = (behaviours, info) => {
2664
      const r = {};
2665
      each$1(behaviours, behaviour => {
2666
        r[behaviour.name()] = behaviour.handlers(info);
2667
      });
2668
      return r;
2669
    };
2670
    const groupByEvents = (info, behaviours, base) => {
2671
      const behaviourEvents = {
2672
        ...base,
2673
        ...nameToHandlers(behaviours, info)
2674
      };
2675
      return byInnerKey(behaviourEvents, behaviourTuple);
2676
    };
2677
    const combine$1 = (info, eventOrder, behaviours, base) => {
2678
      const byEventName = groupByEvents(info, behaviours, base);
2679
      return combineGroups(byEventName, eventOrder);
2680
    };
2681
    const assemble = rawHandler => {
2682
      const handler = read$2(rawHandler);
2683
      return (component, simulatedEvent, ...rest) => {
2684
        const args = [
2685
          component,
2686
          simulatedEvent
2687
        ].concat(rest);
2688
        if (handler.abort.apply(undefined, args)) {
2689
          simulatedEvent.stop();
2690
        } else if (handler.can.apply(undefined, args)) {
2691
          handler.run.apply(undefined, args);
2692
        }
2693
      };
2694
    };
2695
    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)]);
2696
    const fuse = (tuples, eventOrder, eventName) => {
2697
      const order = eventOrder[eventName];
2698
      if (!order) {
2699
        return missingOrderError(eventName, tuples);
2700
      } else {
2701
        return sortKeys('Event: ' + eventName, 'name', tuples, order).map(sortedTuples => {
2702
          const handlers = map$2(sortedTuples, tuple => tuple.handler);
2703
          return fuse$1(handlers);
2704
        });
2705
      }
2706
    };
2707
    const combineGroups = (byEventName, eventOrder) => {
2708
      const r = mapToArray(byEventName, (tuples, eventName) => {
2709
        const combined = tuples.length === 1 ? Result.value(tuples[0].handler) : fuse(tuples, eventOrder, eventName);
2710
        return combined.map(handler => {
2711
          const assembled = assemble(handler);
2712
          const purpose = tuples.length > 1 ? filter$2(eventOrder[eventName], o => exists(tuples, t => t.name === o)).join(' > ') : tuples[0].name;
2713
          return wrap$1(eventName, uncurried(assembled, purpose));
2714
        });
2715
      });
2716
      return consolidate(r, {});
2717
    };
2718
 
2719
    const baseBehaviour = 'alloy.base.behaviour';
2720
    const schema$z = objOf([
2721
      field$1('dom', 'dom', required$2(), objOf([
2722
        required$1('tag'),
2723
        defaulted('styles', {}),
2724
        defaulted('classes', []),
2725
        defaulted('attributes', {}),
2726
        option$3('value'),
2727
        option$3('innerHtml')
2728
      ])),
2729
      required$1('components'),
2730
      required$1('uid'),
2731
      defaulted('events', {}),
2732
      defaulted('apis', {}),
2733
      field$1('eventOrder', 'eventOrder', mergeWith({
2734
        [execute$5()]: [
2735
          'disabling',
2736
          baseBehaviour,
2737
          'toggling',
2738
          'typeaheadevents'
2739
        ],
2740
        [focus$4()]: [
2741
          baseBehaviour,
2742
          'focusing',
2743
          'keying'
2744
        ],
2745
        [systemInit()]: [
2746
          baseBehaviour,
2747
          'disabling',
2748
          'toggling',
2749
          'representing'
2750
        ],
2751
        [input()]: [
2752
          baseBehaviour,
2753
          'representing',
2754
          'streaming',
2755
          'invalidating'
2756
        ],
2757
        [detachedFromDom()]: [
2758
          baseBehaviour,
2759
          'representing',
2760
          'item-events',
2761
          'tooltipping'
2762
        ],
2763
        [mousedown()]: [
2764
          'focusing',
2765
          baseBehaviour,
2766
          'item-type-events'
2767
        ],
2768
        [touchstart()]: [
2769
          'focusing',
2770
          baseBehaviour,
2771
          'item-type-events'
2772
        ],
2773
        [mouseover()]: [
2774
          'item-type-events',
2775
          'tooltipping'
2776
        ],
2777
        [receive()]: [
2778
          'receiving',
2779
          'reflecting',
2780
          'tooltipping'
2781
        ]
2782
      }), anyValue()),
2783
      option$3('domModification')
2784
    ]);
2785
    const toInfo = spec => asRaw('custom.definition', schema$z, spec);
2786
    const toDefinition = detail => ({
2787
      ...detail.dom,
2788
      uid: detail.uid,
2789
      domChildren: map$2(detail.components, comp => comp.element)
2790
    });
2791
    const toModification = detail => detail.domModification.fold(() => nu$7({}), nu$7);
2792
    const toEvents = info => info.events;
2793
 
2794
    const read = (element, attr) => {
2795
      const value = get$f(element, attr);
2796
      return value === undefined || value === '' ? [] : value.split(' ');
2797
    };
2798
    const add$4 = (element, attr, id) => {
2799
      const old = read(element, attr);
2800
      const nu = old.concat([id]);
2801
      set$9(element, attr, nu.join(' '));
2802
      return true;
2803
    };
2804
    const remove$4 = (element, attr, id) => {
2805
      const nu = filter$2(read(element, attr), v => v !== id);
2806
      if (nu.length > 0) {
2807
        set$9(element, attr, nu.join(' '));
2808
      } else {
2809
        remove$7(element, attr);
2810
      }
2811
      return false;
2812
    };
2813
 
2814
    const supports = element => element.dom.classList !== undefined;
2815
    const get$8 = element => read(element, 'class');
2816
    const add$3 = (element, clazz) => add$4(element, 'class', clazz);
2817
    const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
2818
    const toggle$5 = (element, clazz) => {
2819
      if (contains$2(get$8(element), clazz)) {
2820
        return remove$3(element, clazz);
2821
      } else {
2822
        return add$3(element, clazz);
2823
      }
2824
    };
2825
 
2826
    const add$2 = (element, clazz) => {
2827
      if (supports(element)) {
2828
        element.dom.classList.add(clazz);
2829
      } else {
2830
        add$3(element, clazz);
2831
      }
2832
    };
2833
    const cleanClass = element => {
2834
      const classList = supports(element) ? element.dom.classList : get$8(element);
2835
      if (classList.length === 0) {
2836
        remove$7(element, 'class');
2837
      }
2838
    };
2839
    const remove$2 = (element, clazz) => {
2840
      if (supports(element)) {
2841
        const classList = element.dom.classList;
2842
        classList.remove(clazz);
2843
      } else {
2844
        remove$3(element, clazz);
2845
      }
2846
      cleanClass(element);
2847
    };
2848
    const toggle$4 = (element, clazz) => {
2849
      const result = supports(element) ? element.dom.classList.toggle(clazz) : toggle$5(element, clazz);
2850
      cleanClass(element);
2851
      return result;
2852
    };
2853
    const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
2854
 
2855
    const add$1 = (element, classes) => {
2856
      each$1(classes, x => {
2857
        add$2(element, x);
2858
      });
2859
    };
2860
    const remove$1 = (element, classes) => {
2861
      each$1(classes, x => {
2862
        remove$2(element, x);
2863
      });
2864
    };
2865
    const toggle$3 = (element, classes) => {
2866
      each$1(classes, x => {
2867
        toggle$4(element, x);
2868
      });
2869
    };
2870
    const hasAll = (element, classes) => forall(classes, clazz => has(element, clazz));
2871
    const getNative = element => {
2872
      const classList = element.dom.classList;
2873
      const r = new Array(classList.length);
2874
      for (let i = 0; i < classList.length; i++) {
2875
        const item = classList.item(i);
2876
        if (item !== null) {
2877
          r[i] = item;
2878
        }
2879
      }
2880
      return r;
2881
    };
2882
    const get$7 = element => supports(element) ? getNative(element) : get$8(element);
2883
 
2884
    const get$6 = element => element.dom.value;
2885
    const set$5 = (element, value) => {
2886
      if (value === undefined) {
2887
        throw new Error('Value.set was undefined');
2888
      }
2889
      element.dom.value = value;
2890
    };
2891
 
2892
    const determineObsoleted = (parent, index, oldObsoleted) => {
2893
      const newObsoleted = child$2(parent, index);
2894
      return newObsoleted.map(newObs => {
2895
        const elemChanged = oldObsoleted.exists(o => !eq(o, newObs));
2896
        if (elemChanged) {
2897
          const oldTag = oldObsoleted.map(name$3).getOr('span');
2898
          const marker = SugarElement.fromTag(oldTag);
2899
          before$1(newObs, marker);
2900
          return marker;
2901
        } else {
2902
          return newObs;
2903
        }
2904
      });
2905
    };
2906
    const ensureInDom = (parent, child, obsoleted) => {
2907
      obsoleted.fold(() => append$2(parent, child), obs => {
2908
        if (!eq(obs, child)) {
2909
          before$1(obs, child);
2910
          remove$5(obs);
2911
        }
2912
      });
2913
    };
2914
    const patchChildrenWith = (parent, nu, f) => {
2915
      const builtChildren = map$2(nu, f);
2916
      const currentChildren = children(parent);
2917
      each$1(currentChildren.slice(builtChildren.length), remove$5);
2918
      return builtChildren;
2919
    };
2920
    const patchSpecChild = (parent, index, spec, build) => {
2921
      const oldObsoleted = child$2(parent, index);
2922
      const childComp = build(spec, oldObsoleted);
2923
      const obsoleted = determineObsoleted(parent, index, oldObsoleted);
2924
      ensureInDom(parent, childComp.element, obsoleted);
2925
      return childComp;
2926
    };
2927
    const patchSpecChildren = (parent, specs, build) => patchChildrenWith(parent, specs, (spec, index) => patchSpecChild(parent, index, spec, build));
2928
    const patchDomChildren = (parent, nodes) => patchChildrenWith(parent, nodes, (node, index) => {
2929
      const optObsoleted = child$2(parent, index);
2930
      ensureInDom(parent, node, optObsoleted);
2931
      return node;
2932
    });
2933
 
2934
    const diffKeyValueSet = (newObj, oldObj) => {
2935
      const newKeys = keys(newObj);
2936
      const oldKeys = keys(oldObj);
2937
      const toRemove = difference(oldKeys, newKeys);
2938
      const toSet = bifilter(newObj, (v, k) => {
2939
        return !has$2(oldObj, k) || v !== oldObj[k];
2940
      }).t;
2941
      return {
2942
        toRemove,
2943
        toSet
2944
      };
2945
    };
2946
    const reconcileToDom = (definition, obsoleted) => {
2947
      const {
2948
        class: clazz,
2949
        style,
2950
        ...existingAttributes
2951
      } = clone$2(obsoleted);
2952
      const {
2953
        toSet: attrsToSet,
2954
        toRemove: attrsToRemove
2955
      } = diffKeyValueSet(definition.attributes, existingAttributes);
2956
      const updateAttrs = () => {
2957
        each$1(attrsToRemove, a => remove$7(obsoleted, a));
2958
        setAll$1(obsoleted, attrsToSet);
2959
      };
2960
      const existingStyles = getAllRaw(obsoleted);
2961
      const {
2962
        toSet: stylesToSet,
2963
        toRemove: stylesToRemove
2964
      } = diffKeyValueSet(definition.styles, existingStyles);
2965
      const updateStyles = () => {
2966
        each$1(stylesToRemove, s => remove$6(obsoleted, s));
2967
        setAll(obsoleted, stylesToSet);
2968
      };
2969
      const existingClasses = get$7(obsoleted);
2970
      const classesToRemove = difference(existingClasses, definition.classes);
2971
      const classesToAdd = difference(definition.classes, existingClasses);
2972
      const updateClasses = () => {
2973
        add$1(obsoleted, classesToAdd);
2974
        remove$1(obsoleted, classesToRemove);
2975
      };
2976
      const updateHtml = html => {
2977
        set$6(obsoleted, html);
2978
      };
2979
      const updateChildren = () => {
2980
        const children = definition.domChildren;
2981
        patchDomChildren(obsoleted, children);
2982
      };
2983
      const updateValue = () => {
2984
        const valueElement = obsoleted;
2985
        const value = definition.value.getOrUndefined();
2986
        if (value !== get$6(valueElement)) {
2987
          set$5(valueElement, value !== null && value !== void 0 ? value : '');
2988
        }
2989
      };
2990
      updateAttrs();
2991
      updateClasses();
2992
      updateStyles();
2993
      definition.innerHtml.fold(updateChildren, updateHtml);
2994
      updateValue();
2995
      return obsoleted;
2996
    };
2997
 
2998
    const introduceToDom = definition => {
2999
      const subject = SugarElement.fromTag(definition.tag);
3000
      setAll$1(subject, definition.attributes);
3001
      add$1(subject, definition.classes);
3002
      setAll(subject, definition.styles);
3003
      definition.innerHtml.each(html => set$6(subject, html));
3004
      const children = definition.domChildren;
3005
      append$1(subject, children);
3006
      definition.value.each(value => {
3007
        set$5(subject, value);
3008
      });
3009
      return subject;
3010
    };
3011
    const attemptPatch = (definition, obsoleted) => {
3012
      try {
3013
        const e = reconcileToDom(definition, obsoleted);
3014
        return Optional.some(e);
3015
      } catch (err) {
3016
        return Optional.none();
3017
      }
3018
    };
3019
    const hasMixedChildren = definition => definition.innerHtml.isSome() && definition.domChildren.length > 0;
3020
    const renderToDom = (definition, optObsoleted) => {
3021
      const canBePatched = candidate => name$3(candidate) === definition.tag && !hasMixedChildren(definition) && !isPremade(candidate);
3022
      const elem = optObsoleted.filter(canBePatched).bind(obsoleted => attemptPatch(definition, obsoleted)).getOrThunk(() => introduceToDom(definition));
3023
      writeOnly(elem, definition.uid);
3024
      return elem;
3025
    };
3026
 
3027
    const getBehaviours$2 = spec => {
3028
      const behaviours = get$g(spec, 'behaviours').getOr({});
3029
      return bind$3(keys(behaviours), name => {
3030
        const behaviour = behaviours[name];
3031
        return isNonNullable(behaviour) ? [behaviour.me] : [];
3032
      });
3033
    };
3034
    const generateFrom = (spec, all) => generateFrom$1(spec, all);
3035
    const generate$4 = spec => {
3036
      const all = getBehaviours$2(spec);
3037
      return generateFrom(spec, all);
3038
    };
3039
 
3040
    const getDomDefinition = (info, bList, bData) => {
3041
      const definition = toDefinition(info);
3042
      const infoModification = toModification(info);
3043
      const baseModification = { 'alloy.base.modification': infoModification };
3044
      const modification = bList.length > 0 ? combine$2(bData, baseModification, bList, definition) : infoModification;
3045
      return merge(definition, modification);
3046
    };
3047
    const getEvents = (info, bList, bData) => {
3048
      const baseEvents = { 'alloy.base.behaviour': toEvents(info) };
3049
      return combine$1(bData, info.eventOrder, bList, baseEvents).getOrDie();
3050
    };
3051
    const build$2 = (spec, obsoleted) => {
3052
      const getMe = () => me;
3053
      const systemApi = Cell(singleton$1);
3054
      const info = getOrDie(toInfo(spec));
3055
      const bBlob = generate$4(spec);
3056
      const bList = getBehaviours$3(bBlob);
3057
      const bData = getData$2(bBlob);
3058
      const modDefinition = getDomDefinition(info, bList, bData);
3059
      const item = renderToDom(modDefinition, obsoleted);
3060
      const events = getEvents(info, bList, bData);
3061
      const subcomponents = Cell(info.components);
3062
      const connect = newApi => {
3063
        systemApi.set(newApi);
3064
      };
3065
      const disconnect = () => {
3066
        systemApi.set(NoContextApi(getMe));
3067
      };
3068
      const syncComponents = () => {
3069
        const children$1 = children(item);
3070
        const subs = bind$3(children$1, child => systemApi.get().getByDom(child).fold(() => [], pure$2));
3071
        subcomponents.set(subs);
3072
      };
3073
      const config = behaviour => {
3074
        const b = bData;
3075
        const f = isFunction(b[behaviour.name()]) ? b[behaviour.name()] : () => {
3076
          throw new Error('Could not find ' + behaviour.name() + ' in ' + JSON.stringify(spec, null, 2));
3077
        };
3078
        return f();
3079
      };
3080
      const hasConfigured = behaviour => isFunction(bData[behaviour.name()]);
3081
      const getApis = () => info.apis;
3082
      const readState = behaviourName => bData[behaviourName]().map(b => b.state.readState()).getOr('not enabled');
3083
      const me = {
3084
        uid: spec.uid,
3085
        getSystem: systemApi.get,
3086
        config,
3087
        hasConfigured,
3088
        spec,
3089
        readState,
3090
        getApis,
3091
        connect,
3092
        disconnect,
3093
        element: item,
3094
        syncComponents,
3095
        components: subcomponents.get,
3096
        events
3097
      };
3098
      return me;
3099
    };
3100
 
3101
    const buildSubcomponents = (spec, obsoleted) => {
3102
      const components = get$g(spec, 'components').getOr([]);
3103
      return obsoleted.fold(() => map$2(components, build$1), obs => map$2(components, (c, i) => {
3104
        return buildOrPatch(c, child$2(obs, i));
3105
      }));
3106
    };
3107
    const buildFromSpec = (userSpec, obsoleted) => {
3108
      const {
3109
        events: specEvents,
3110
        ...spec
3111
      } = make$8(userSpec);
3112
      const components = buildSubcomponents(spec, obsoleted);
3113
      const completeSpec = {
3114
        ...spec,
3115
        events: {
3116
          ...DefaultEvents,
3117
          ...specEvents
3118
        },
3119
        components
3120
      };
3121
      return Result.value(build$2(completeSpec, obsoleted));
3122
    };
3123
    const text$2 = textContent => {
3124
      const element = SugarElement.fromText(textContent);
3125
      return external$1({ element });
3126
    };
3127
    const external$1 = spec => {
3128
      const extSpec = asRawOrDie$1('external.component', objOfOnly([
3129
        required$1('element'),
3130
        option$3('uid')
3131
      ]), spec);
3132
      const systemApi = Cell(NoContextApi());
3133
      const connect = newApi => {
3134
        systemApi.set(newApi);
3135
      };
3136
      const disconnect = () => {
3137
        systemApi.set(NoContextApi(() => me));
3138
      };
3139
      const uid = extSpec.uid.getOrThunk(() => generate$5('external'));
3140
      writeOnly(extSpec.element, uid);
3141
      const me = {
3142
        uid,
3143
        getSystem: systemApi.get,
3144
        config: Optional.none,
3145
        hasConfigured: never,
3146
        connect,
3147
        disconnect,
3148
        getApis: () => ({}),
3149
        element: extSpec.element,
3150
        spec,
3151
        readState: constant$1('No state'),
3152
        syncComponents: noop,
3153
        components: constant$1([]),
3154
        events: {}
3155
      };
3156
      return premade$1(me);
3157
    };
3158
    const uids = generate$5;
3159
    const isSketchSpec$1 = spec => has$2(spec, 'uid');
3160
    const buildOrPatch = (spec, obsoleted) => getPremade(spec).getOrThunk(() => {
3161
      const userSpecWithUid = isSketchSpec$1(spec) ? spec : {
3162
        uid: uids(''),
3163
        ...spec
3164
      };
3165
      return buildFromSpec(userSpecWithUid, obsoleted).getOrDie();
3166
    });
3167
    const build$1 = spec => buildOrPatch(spec, Optional.none());
3168
    const premade = premade$1;
3169
 
3170
    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
3171
      if (is(scope, a)) {
3172
        return Optional.some(scope);
3173
      } else if (isFunction(isRoot) && isRoot(scope)) {
3174
        return Optional.none();
3175
      } else {
3176
        return ancestor(scope, a, isRoot);
3177
      }
3178
    };
3179
 
3180
    const ancestor$1 = (scope, predicate, isRoot) => {
3181
      let element = scope.dom;
3182
      const stop = isFunction(isRoot) ? isRoot : never;
3183
      while (element.parentNode) {
3184
        element = element.parentNode;
3185
        const el = SugarElement.fromDom(element);
3186
        if (predicate(el)) {
3187
          return Optional.some(el);
3188
        } else if (stop(el)) {
3189
          break;
3190
        }
3191
      }
3192
      return Optional.none();
3193
    };
3194
    const closest$3 = (scope, predicate, isRoot) => {
3195
      const is = (s, test) => test(s);
3196
      return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
3197
    };
3198
    const child$1 = (scope, predicate) => {
3199
      const pred = node => predicate(SugarElement.fromDom(node));
3200
      const result = find$5(scope.dom.childNodes, pred);
3201
      return result.map(SugarElement.fromDom);
3202
    };
3203
    const descendant$1 = (scope, predicate) => {
3204
      const descend = node => {
3205
        for (let i = 0; i < node.childNodes.length; i++) {
3206
          const child = SugarElement.fromDom(node.childNodes[i]);
3207
          if (predicate(child)) {
3208
            return Optional.some(child);
3209
          }
3210
          const res = descend(node.childNodes[i]);
3211
          if (res.isSome()) {
3212
            return res;
3213
          }
3214
        }
3215
        return Optional.none();
3216
      };
3217
      return descend(scope.dom);
3218
    };
3219
 
3220
    const closest$2 = (scope, predicate, isRoot) => closest$3(scope, predicate, isRoot).isSome();
3221
 
3222
    const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is(e, selector), isRoot);
3223
    const child = (scope, selector) => child$1(scope, e => is(e, selector));
3224
    const descendant = (scope, selector) => one(selector, scope);
3225
    const closest$1 = (scope, selector, isRoot) => {
3226
      const is$1 = (element, selector) => is(element, selector);
3227
      return ClosestOrAncestor(is$1, ancestor, scope, selector, isRoot);
3228
    };
3229
 
3230
    const attribute = 'aria-controls';
3231
    const find$1 = queryElem => {
3232
      const dependent = closest$3(queryElem, elem => {
3233
        if (!isElement$1(elem)) {
3234
          return false;
3235
        }
3236
        const id = get$f(elem, 'id');
3237
        return id !== undefined && id.indexOf(attribute) > -1;
3238
      });
3239
      return dependent.bind(dep => {
3240
        const id = get$f(dep, 'id');
3241
        const dos = getRootNode(dep);
3242
        return descendant(dos, `[${ attribute }="${ id }"]`);
3243
      });
3244
    };
3245
    const manager = () => {
3246
      const ariaId = generate$6(attribute);
3247
      const link = elem => {
3248
        set$9(elem, attribute, ariaId);
3249
      };
3250
      const unlink = elem => {
3251
        remove$7(elem, attribute);
3252
      };
3253
      return {
3254
        id: ariaId,
3255
        link,
3256
        unlink
3257
      };
3258
    };
3259
 
3260
    const isAriaPartOf = (component, queryElem) => find$1(queryElem).exists(owner => isPartOf$1(component, owner));
3261
    const isPartOf$1 = (component, queryElem) => closest$2(queryElem, el => eq(el, component.element), never) || isAriaPartOf(component, queryElem);
3262
 
3263
    const unknown = 'unknown';
3264
    var EventConfiguration;
3265
    (function (EventConfiguration) {
3266
      EventConfiguration[EventConfiguration['STOP'] = 0] = 'STOP';
3267
      EventConfiguration[EventConfiguration['NORMAL'] = 1] = 'NORMAL';
3268
      EventConfiguration[EventConfiguration['LOGGING'] = 2] = 'LOGGING';
3269
    }(EventConfiguration || (EventConfiguration = {})));
3270
    const eventConfig = Cell({});
3271
    const makeEventLogger = (eventName, initialTarget) => {
3272
      const sequence = [];
3273
      const startTime = new Date().getTime();
3274
      return {
3275
        logEventCut: (_name, target, purpose) => {
3276
          sequence.push({
3277
            outcome: 'cut',
3278
            target,
3279
            purpose
3280
          });
3281
        },
3282
        logEventStopped: (_name, target, purpose) => {
3283
          sequence.push({
3284
            outcome: 'stopped',
3285
            target,
3286
            purpose
3287
          });
3288
        },
3289
        logNoParent: (_name, target, purpose) => {
3290
          sequence.push({
3291
            outcome: 'no-parent',
3292
            target,
3293
            purpose
3294
          });
3295
        },
3296
        logEventNoHandlers: (_name, target) => {
3297
          sequence.push({
3298
            outcome: 'no-handlers-left',
3299
            target
3300
          });
3301
        },
3302
        logEventResponse: (_name, target, purpose) => {
3303
          sequence.push({
3304
            outcome: 'response',
3305
            purpose,
3306
            target
3307
          });
3308
        },
3309
        write: () => {
3310
          const finishTime = new Date().getTime();
3311
          if (contains$2([
3312
              'mousemove',
3313
              'mouseover',
3314
              'mouseout',
3315
              systemInit()
3316
            ], eventName)) {
3317
            return;
3318
          }
3319
          console.log(eventName, {
3320
            event: eventName,
3321
            time: finishTime - startTime,
3322
            target: initialTarget.dom,
3323
            sequence: map$2(sequence, s => {
3324
              if (!contains$2([
3325
                  'cut',
3326
                  'stopped',
3327
                  'response'
3328
                ], s.outcome)) {
3329
                return s.outcome;
3330
              } else {
3331
                return '{' + s.purpose + '} ' + s.outcome + ' at (' + element(s.target) + ')';
3332
              }
3333
            })
3334
          });
3335
        }
3336
      };
3337
    };
3338
    const processEvent = (eventName, initialTarget, f) => {
3339
      const status = get$g(eventConfig.get(), eventName).orThunk(() => {
3340
        const patterns = keys(eventConfig.get());
3341
        return findMap(patterns, p => eventName.indexOf(p) > -1 ? Optional.some(eventConfig.get()[p]) : Optional.none());
3342
      }).getOr(EventConfiguration.NORMAL);
3343
      switch (status) {
3344
      case EventConfiguration.NORMAL:
3345
        return f(noLogger());
3346
      case EventConfiguration.LOGGING: {
3347
          const logger = makeEventLogger(eventName, initialTarget);
3348
          const output = f(logger);
3349
          logger.write();
3350
          return output;
3351
        }
3352
      case EventConfiguration.STOP:
3353
        return true;
3354
      }
3355
    };
3356
    const path = [
3357
      'alloy/data/Fields',
3358
      'alloy/debugging/Debugging'
3359
    ];
3360
    const getTrace = () => {
3361
      const err = new Error();
3362
      if (err.stack !== undefined) {
3363
        const lines = err.stack.split('\n');
3364
        return find$5(lines, line => line.indexOf('alloy') > 0 && !exists(path, p => line.indexOf(p) > -1)).getOr(unknown);
3365
      } else {
3366
        return unknown;
3367
      }
3368
    };
3369
    const ignoreEvent = {
3370
      logEventCut: noop,
3371
      logEventStopped: noop,
3372
      logNoParent: noop,
3373
      logEventNoHandlers: noop,
3374
      logEventResponse: noop,
3375
      write: noop
3376
    };
3377
    const monitorEvent = (eventName, initialTarget, f) => processEvent(eventName, initialTarget, f);
3378
    const noLogger = constant$1(ignoreEvent);
3379
 
3380
    const menuFields = constant$1([
3381
      required$1('menu'),
3382
      required$1('selectedMenu')
3383
    ]);
3384
    const itemFields = constant$1([
3385
      required$1('item'),
3386
      required$1('selectedItem')
3387
    ]);
3388
    constant$1(objOf(itemFields().concat(menuFields())));
3389
    const itemSchema$3 = constant$1(objOf(itemFields()));
3390
 
3391
    const _initSize = requiredObjOf('initSize', [
3392
      required$1('numColumns'),
3393
      required$1('numRows')
3394
    ]);
3395
    const itemMarkers = () => requiredOf('markers', itemSchema$3());
3396
    const tieredMenuMarkers = () => requiredObjOf('markers', [required$1('backgroundMenu')].concat(menuFields()).concat(itemFields()));
3397
    const markers$1 = required => requiredObjOf('markers', map$2(required, required$1));
3398
    const onPresenceHandler = (label, fieldName, presence) => {
3399
      getTrace();
3400
      return field$1(fieldName, fieldName, presence, valueOf(f => Result.value((...args) => {
3401
        return f.apply(undefined, args);
3402
      })));
3403
    };
3404
    const onHandler = fieldName => onPresenceHandler('onHandler', fieldName, defaulted$1(noop));
3405
    const onKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, defaulted$1(Optional.none));
3406
    const onStrictHandler = fieldName => onPresenceHandler('onHandler', fieldName, required$2());
3407
    const onStrictKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, required$2());
3408
    const output$1 = (name, value) => customField(name, constant$1(value));
3409
    const snapshot = name => customField(name, identity);
3410
    const initSize = constant$1(_initSize);
3411
 
3412
    const nu$6 = (x, y, bubble, direction, placement, boundsRestriction, labelPrefix, alwaysFit = false) => ({
3413
      x,
3414
      y,
3415
      bubble,
3416
      direction,
3417
      placement,
3418
      restriction: boundsRestriction,
3419
      label: `${ labelPrefix }-${ placement }`,
3420
      alwaysFit
3421
    });
3422
 
3423
    const adt$a = Adt.generate([
3424
      { southeast: [] },
3425
      { southwest: [] },
3426
      { northeast: [] },
3427
      { northwest: [] },
3428
      { south: [] },
3429
      { north: [] },
3430
      { east: [] },
3431
      { west: [] }
3432
    ]);
3433
    const cata$2 = (subject, southeast, southwest, northeast, northwest, south, north, east, west) => subject.fold(southeast, southwest, northeast, northwest, south, north, east, west);
3434
    const cataVertical = (subject, south, middle, north) => subject.fold(south, south, north, north, south, north, middle, middle);
3435
    const cataHorizontal = (subject, east, middle, west) => subject.fold(east, west, east, west, middle, middle, east, west);
3436
    const southeast$3 = adt$a.southeast;
3437
    const southwest$3 = adt$a.southwest;
3438
    const northeast$3 = adt$a.northeast;
3439
    const northwest$3 = adt$a.northwest;
3440
    const south$3 = adt$a.south;
3441
    const north$3 = adt$a.north;
3442
    const east$3 = adt$a.east;
3443
    const west$3 = adt$a.west;
3444
 
3445
    const cycleBy = (value, delta, min, max) => {
3446
      const r = value + delta;
3447
      if (r > max) {
3448
        return min;
3449
      } else if (r < min) {
3450
        return max;
3451
      } else {
3452
        return r;
3453
      }
3454
    };
3455
    const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
3456
 
3457
    const getRestriction = (anchor, restriction) => {
3458
      switch (restriction) {
3459
      case 1:
3460
        return anchor.x;
3461
      case 0:
3462
        return anchor.x + anchor.width;
3463
      case 2:
3464
        return anchor.y;
3465
      case 3:
3466
        return anchor.y + anchor.height;
3467
      }
3468
    };
3469
    const boundsRestriction = (anchor, restrictions) => mapToObject([
3470
      'left',
3471
      'right',
3472
      'top',
3473
      'bottom'
3474
    ], dir => get$g(restrictions, dir).map(restriction => getRestriction(anchor, restriction)));
3475
    const adjustBounds = (bounds$1, restriction, bubbleOffset) => {
3476
      const applyRestriction = (dir, current) => restriction[dir].map(pos => {
3477
        const isVerticalAxis = dir === 'top' || dir === 'bottom';
3478
        const offset = isVerticalAxis ? bubbleOffset.top : bubbleOffset.left;
3479
        const comparator = dir === 'left' || dir === 'top' ? Math.max : Math.min;
3480
        const newPos = comparator(pos, current) + offset;
3481
        return isVerticalAxis ? clamp(newPos, bounds$1.y, bounds$1.bottom) : clamp(newPos, bounds$1.x, bounds$1.right);
3482
      }).getOr(current);
3483
      const adjustedLeft = applyRestriction('left', bounds$1.x);
3484
      const adjustedTop = applyRestriction('top', bounds$1.y);
3485
      const adjustedRight = applyRestriction('right', bounds$1.right);
3486
      const adjustedBottom = applyRestriction('bottom', bounds$1.bottom);
3487
      return bounds(adjustedLeft, adjustedTop, adjustedRight - adjustedLeft, adjustedBottom - adjustedTop);
3488
    };
3489
 
3490
    const labelPrefix$2 = 'layout';
3491
    const eastX$1 = anchor => anchor.x;
3492
    const middleX$1 = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
3493
    const westX$1 = (anchor, element) => anchor.x + anchor.width - element.width;
3494
    const northY$2 = (anchor, element) => anchor.y - element.height;
3495
    const southY$2 = anchor => anchor.y + anchor.height;
3496
    const centreY$1 = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
3497
    const eastEdgeX$1 = anchor => anchor.x + anchor.width;
3498
    const westEdgeX$1 = (anchor, element) => anchor.x - element.width;
3499
    const southeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), southY$2(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
3500
      left: 1,
3501
      top: 3
3502
    }), labelPrefix$2);
3503
    const southwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), southY$2(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
3504
      right: 0,
3505
      top: 3
3506
    }), labelPrefix$2);
3507
    const northeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), northY$2(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
3508
      left: 1,
3509
      bottom: 2
3510
    }), labelPrefix$2);
3511
    const northwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), northY$2(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
3512
      right: 0,
3513
      bottom: 2
3514
    }), labelPrefix$2);
3515
    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);
3516
    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);
3517
    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);
3518
    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);
3519
    const all$1 = () => [
3520
      southeast$2,
3521
      southwest$2,
3522
      northeast$2,
3523
      northwest$2,
3524
      south$2,
3525
      north$2,
3526
      east$2,
3527
      west$2
3528
    ];
3529
    const allRtl$1 = () => [
3530
      southwest$2,
3531
      southeast$2,
3532
      northwest$2,
3533
      northeast$2,
3534
      south$2,
3535
      north$2,
3536
      east$2,
3537
      west$2
3538
    ];
3539
    const aboveOrBelow = () => [
3540
      northeast$2,
3541
      northwest$2,
3542
      southeast$2,
3543
      southwest$2,
3544
      north$2,
3545
      south$2
3546
    ];
3547
    const aboveOrBelowRtl = () => [
3548
      northwest$2,
3549
      northeast$2,
3550
      southwest$2,
3551
      southeast$2,
3552
      north$2,
3553
      south$2
3554
    ];
3555
    const belowOrAbove = () => [
3556
      southeast$2,
3557
      southwest$2,
3558
      northeast$2,
3559
      northwest$2,
3560
      south$2,
3561
      north$2
3562
    ];
3563
    const belowOrAboveRtl = () => [
3564
      southwest$2,
3565
      southeast$2,
3566
      northwest$2,
3567
      northeast$2,
3568
      south$2,
3569
      north$2
3570
    ];
3571
 
3572
    const chooseChannels = (channels, message) => message.universal ? channels : filter$2(channels, ch => contains$2(message.channels, ch));
3573
    const events$h = receiveConfig => derive$2([run$1(receive(), (component, message) => {
3574
        const channelMap = receiveConfig.channels;
3575
        const channels = keys(channelMap);
3576
        const receivingData = message;
3577
        const targetChannels = chooseChannels(channels, receivingData);
3578
        each$1(targetChannels, ch => {
3579
          const channelInfo = channelMap[ch];
3580
          const channelSchema = channelInfo.schema;
3581
          const data = asRawOrDie$1('channel[' + ch + '] data\nReceiver: ' + element(component.element), channelSchema, receivingData.data);
3582
          channelInfo.onReceive(component, data);
3583
        });
3584
      })]);
3585
 
3586
    var ActiveReceiving = /*#__PURE__*/Object.freeze({
3587
        __proto__: null,
3588
        events: events$h
3589
    });
3590
 
3591
    var ReceivingSchema = [requiredOf('channels', setOf(Result.value, objOfOnly([
3592
        onStrictHandler('onReceive'),
3593
        defaulted('schema', anyValue())
3594
      ])))];
3595
 
3596
    const executeEvent = (bConfig, bState, executor) => runOnExecute$1(component => {
3597
      executor(component, bConfig, bState);
3598
    });
3599
    const loadEvent = (bConfig, bState, f) => runOnInit((component, _simulatedEvent) => {
3600
      f(component, bConfig, bState);
3601
    });
3602
    const create$5 = (schema, name, active, apis, extra, state) => {
3603
      const configSchema = objOfOnly(schema);
3604
      const schemaSchema = optionObjOf(name, [optionObjOfOnly('config', schema)]);
3605
      return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
3606
    };
3607
    const createModes$1 = (modes, name, active, apis, extra, state) => {
3608
      const configSchema = modes;
3609
      const schemaSchema = optionObjOf(name, [optionOf('config', modes)]);
3610
      return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
3611
    };
3612
    const wrapApi = (bName, apiFunction, apiName) => {
3613
      const f = (component, ...rest) => {
3614
        const args = [component].concat(rest);
3615
        return component.config({ name: constant$1(bName) }).fold(() => {
3616
          throw new Error('We could not find any behaviour configuration for: ' + bName + '. Using API: ' + apiName);
3617
        }, info => {
3618
          const rest = Array.prototype.slice.call(args, 1);
3619
          return apiFunction.apply(undefined, [
3620
            component,
3621
            info.config,
3622
            info.state
3623
          ].concat(rest));
3624
        });
3625
      };
3626
      return markAsBehaviourApi(f, apiName, apiFunction);
3627
    };
3628
    const revokeBehaviour = name => ({
3629
      key: name,
3630
      value: undefined
3631
    });
3632
    const doCreate = (configSchema, schemaSchema, name, active, apis, extra, state) => {
3633
      const getConfig = info => hasNonNullableKey(info, name) ? info[name]() : Optional.none();
3634
      const wrappedApis = map$1(apis, (apiF, apiName) => wrapApi(name, apiF, apiName));
3635
      const wrappedExtra = map$1(extra, (extraF, extraName) => markAsExtraApi(extraF, extraName));
3636
      const me = {
3637
        ...wrappedExtra,
3638
        ...wrappedApis,
3639
        revoke: curry(revokeBehaviour, name),
3640
        config: spec => {
3641
          const prepared = asRawOrDie$1(name + '-config', configSchema, spec);
3642
          return {
3643
            key: name,
3644
            value: {
3645
              config: prepared,
3646
              me,
3647
              configAsRaw: cached(() => asRawOrDie$1(name + '-config', configSchema, spec)),
3648
              initialConfig: spec,
3649
              state
3650
            }
3651
          };
3652
        },
3653
        schema: constant$1(schemaSchema),
3654
        exhibit: (info, base) => {
3655
          return lift2(getConfig(info), get$g(active, 'exhibit'), (behaviourInfo, exhibitor) => {
3656
            return exhibitor(base, behaviourInfo.config, behaviourInfo.state);
3657
          }).getOrThunk(() => nu$7({}));
3658
        },
3659
        name: constant$1(name),
3660
        handlers: info => {
3661
          return getConfig(info).map(behaviourInfo => {
3662
            const getEvents = get$g(active, 'events').getOr(() => ({}));
3663
            return getEvents(behaviourInfo.config, behaviourInfo.state);
3664
          }).getOr({});
3665
        }
3666
      };
3667
      return me;
3668
    };
3669
 
3670
    const derive$1 = capabilities => wrapAll(capabilities);
3671
    const simpleSchema = objOfOnly([
3672
      required$1('fields'),
3673
      required$1('name'),
3674
      defaulted('active', {}),
3675
      defaulted('apis', {}),
3676
      defaulted('state', NoState),
3677
      defaulted('extra', {})
3678
    ]);
3679
    const create$4 = data => {
3680
      const value = asRawOrDie$1('Creating behaviour: ' + data.name, simpleSchema, data);
3681
      return create$5(value.fields, value.name, value.active, value.apis, value.extra, value.state);
3682
    };
3683
    const modeSchema = objOfOnly([
3684
      required$1('branchKey'),
3685
      required$1('branches'),
3686
      required$1('name'),
3687
      defaulted('active', {}),
3688
      defaulted('apis', {}),
3689
      defaulted('state', NoState),
3690
      defaulted('extra', {})
3691
    ]);
3692
    const createModes = data => {
3693
      const value = asRawOrDie$1('Creating behaviour: ' + data.name, modeSchema, data);
3694
      return createModes$1(choose$1(value.branchKey, value.branches), value.name, value.active, value.apis, value.extra, value.state);
3695
    };
3696
    const revoke = constant$1(undefined);
3697
 
3698
    const Receiving = create$4({
3699
      fields: ReceivingSchema,
3700
      name: 'receiving',
3701
      active: ActiveReceiving
3702
    });
3703
 
3704
    const exhibit$6 = (base, posConfig) => nu$7({
3705
      classes: [],
3706
      styles: posConfig.useFixed() ? {} : { position: 'relative' }
3707
    });
3708
 
3709
    var ActivePosition = /*#__PURE__*/Object.freeze({
3710
        __proto__: null,
3711
        exhibit: exhibit$6
3712
    });
3713
 
3714
    const focus$3 = (element, preventScroll = false) => element.dom.focus({ preventScroll });
3715
    const blur$1 = element => element.dom.blur();
3716
    const hasFocus = element => {
3717
      const root = getRootNode(element).dom;
3718
      return element.dom === root.activeElement;
3719
    };
3720
    const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
3721
    const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
3722
 
3723
    const preserve$1 = (f, container) => {
3724
      const dos = getRootNode(container);
3725
      const refocus = active$1(dos).bind(focused => {
3726
        const hasFocus = elem => eq(focused, elem);
3727
        return hasFocus(container) ? Optional.some(container) : descendant$1(container, hasFocus);
3728
      });
3729
      const result = f(container);
3730
      refocus.each(oldFocus => {
3731
        active$1(dos).filter(newFocus => eq(newFocus, oldFocus)).fold(() => {
3732
          focus$3(oldFocus);
3733
        }, noop);
3734
      });
3735
      return result;
3736
    };
3737
 
3738
    const NuPositionCss = (position, left, top, right, bottom) => {
3739
      const toPx = num => num + 'px';
3740
      return {
3741
        position,
3742
        left: left.map(toPx),
3743
        top: top.map(toPx),
3744
        right: right.map(toPx),
3745
        bottom: bottom.map(toPx)
3746
      };
3747
    };
3748
    const toOptions = position => ({
3749
      ...position,
3750
      position: Optional.some(position.position)
3751
    });
3752
    const applyPositionCss = (element, position) => {
3753
      setOptions(element, toOptions(position));
3754
    };
3755
 
3756
    const adt$9 = Adt.generate([
3757
      { none: [] },
3758
      {
3759
        relative: [
3760
          'x',
3761
          'y',
3762
          'width',
3763
          'height'
3764
        ]
3765
      },
3766
      {
3767
        fixed: [
3768
          'x',
3769
          'y',
3770
          'width',
3771
          'height'
3772
        ]
3773
      }
3774
    ]);
3775
    const positionWithDirection = (posName, decision, x, y, width, height) => {
3776
      const decisionRect = decision.rect;
3777
      const decisionX = decisionRect.x - x;
3778
      const decisionY = decisionRect.y - y;
3779
      const decisionWidth = decisionRect.width;
3780
      const decisionHeight = decisionRect.height;
3781
      const decisionRight = width - (decisionX + decisionWidth);
3782
      const decisionBottom = height - (decisionY + decisionHeight);
3783
      const left = Optional.some(decisionX);
3784
      const top = Optional.some(decisionY);
3785
      const right = Optional.some(decisionRight);
3786
      const bottom = Optional.some(decisionBottom);
3787
      const none = Optional.none();
3788
      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));
3789
    };
3790
    const reposition = (origin, decision) => origin.fold(() => {
3791
      const decisionRect = decision.rect;
3792
      return NuPositionCss('absolute', Optional.some(decisionRect.x), Optional.some(decisionRect.y), Optional.none(), Optional.none());
3793
    }, (x, y, width, height) => {
3794
      return positionWithDirection('absolute', decision, x, y, width, height);
3795
    }, (x, y, width, height) => {
3796
      return positionWithDirection('fixed', decision, x, y, width, height);
3797
    });
3798
    const toBox = (origin, element) => {
3799
      const rel = curry(find$2, element);
3800
      const position = origin.fold(rel, rel, () => {
3801
        const scroll = get$b();
3802
        return find$2(element).translate(-scroll.left, -scroll.top);
3803
      });
3804
      const width = getOuter$1(element);
3805
      const height = getOuter$2(element);
3806
      return bounds(position.left, position.top, width, height);
3807
    };
3808
    const viewport = (origin, optBounds) => optBounds.fold(() => origin.fold(win, win, bounds), bounds$1 => origin.fold(constant$1(bounds$1), constant$1(bounds$1), () => {
3809
      const pos = translate$2(origin, bounds$1.x, bounds$1.y);
3810
      return bounds(pos.left, pos.top, bounds$1.width, bounds$1.height);
3811
    }));
3812
    const translate$2 = (origin, x, y) => {
3813
      const pos = SugarPosition(x, y);
3814
      const removeScroll = () => {
3815
        const outerScroll = get$b();
3816
        return pos.translate(-outerScroll.left, -outerScroll.top);
3817
      };
3818
      return origin.fold(constant$1(pos), constant$1(pos), removeScroll);
3819
    };
3820
    const cata$1 = (subject, onNone, onRelative, onFixed) => subject.fold(onNone, onRelative, onFixed);
3821
    adt$9.none;
3822
    const relative$1 = adt$9.relative;
3823
    const fixed$1 = adt$9.fixed;
3824
 
3825
    const anchor = (anchorBox, origin) => ({
3826
      anchorBox,
3827
      origin
3828
    });
3829
    const box = (anchorBox, origin) => anchor(anchorBox, origin);
3830
 
3831
    const placementAttribute = 'data-alloy-placement';
3832
    const setPlacement$1 = (element, placement) => {
3833
      set$9(element, placementAttribute, placement);
3834
    };
3835
    const getPlacement = element => getOpt(element, placementAttribute);
3836
    const reset$2 = element => remove$7(element, placementAttribute);
3837
 
3838
    const adt$8 = Adt.generate([
3839
      { fit: ['reposition'] },
3840
      {
3841
        nofit: [
3842
          'reposition',
3843
          'visibleW',
3844
          'visibleH',
3845
          'isVisible'
3846
        ]
3847
      }
3848
    ]);
3849
    const determinePosition = (box, bounds) => {
3850
      const {
3851
        x: boundsX,
3852
        y: boundsY,
3853
        right: boundsRight,
3854
        bottom: boundsBottom
3855
      } = bounds;
3856
      const {x, y, right, bottom, width, height} = box;
3857
      const xInBounds = x >= boundsX && x <= boundsRight;
3858
      const yInBounds = y >= boundsY && y <= boundsBottom;
3859
      const originInBounds = xInBounds && yInBounds;
3860
      const rightInBounds = right <= boundsRight && right >= boundsX;
3861
      const bottomInBounds = bottom <= boundsBottom && bottom >= boundsY;
3862
      const sizeInBounds = rightInBounds && bottomInBounds;
3863
      const visibleW = Math.min(width, x >= boundsX ? boundsRight - x : right - boundsX);
3864
      const visibleH = Math.min(height, y >= boundsY ? boundsBottom - y : bottom - boundsY);
3865
      return {
3866
        originInBounds,
3867
        sizeInBounds,
3868
        visibleW,
3869
        visibleH
3870
      };
3871
    };
3872
    const calcReposition = (box, bounds$1) => {
3873
      const {
3874
        x: boundsX,
3875
        y: boundsY,
3876
        right: boundsRight,
3877
        bottom: boundsBottom
3878
      } = bounds$1;
3879
      const {x, y, width, height} = box;
3880
      const maxX = Math.max(boundsX, boundsRight - width);
3881
      const maxY = Math.max(boundsY, boundsBottom - height);
3882
      const restrictedX = clamp(x, boundsX, maxX);
3883
      const restrictedY = clamp(y, boundsY, maxY);
3884
      const restrictedWidth = Math.min(restrictedX + width, boundsRight) - restrictedX;
3885
      const restrictedHeight = Math.min(restrictedY + height, boundsBottom) - restrictedY;
3886
      return bounds(restrictedX, restrictedY, restrictedWidth, restrictedHeight);
3887
    };
3888
    const calcMaxSizes = (direction, box, bounds) => {
3889
      const upAvailable = constant$1(box.bottom - bounds.y);
3890
      const downAvailable = constant$1(bounds.bottom - box.y);
3891
      const maxHeight = cataVertical(direction, downAvailable, downAvailable, upAvailable);
3892
      const westAvailable = constant$1(box.right - bounds.x);
3893
      const eastAvailable = constant$1(bounds.right - box.x);
3894
      const maxWidth = cataHorizontal(direction, eastAvailable, eastAvailable, westAvailable);
3895
      return {
3896
        maxWidth,
3897
        maxHeight
3898
      };
3899
    };
3900
    const attempt = (candidate, width, height, bounds$1) => {
3901
      const bubble = candidate.bubble;
3902
      const bubbleOffset = bubble.offset;
3903
      const adjustedBounds = adjustBounds(bounds$1, candidate.restriction, bubbleOffset);
3904
      const newX = candidate.x + bubbleOffset.left;
3905
      const newY = candidate.y + bubbleOffset.top;
3906
      const box = bounds(newX, newY, width, height);
3907
      const {originInBounds, sizeInBounds, visibleW, visibleH} = determinePosition(box, adjustedBounds);
3908
      const fits = originInBounds && sizeInBounds;
3909
      const fittedBox = fits ? box : calcReposition(box, adjustedBounds);
3910
      const isPartlyVisible = fittedBox.width > 0 && fittedBox.height > 0;
3911
      const {maxWidth, maxHeight} = calcMaxSizes(candidate.direction, fittedBox, bounds$1);
3912
      const reposition = {
3913
        rect: fittedBox,
3914
        maxHeight,
3915
        maxWidth,
3916
        direction: candidate.direction,
3917
        placement: candidate.placement,
3918
        classes: {
3919
          on: bubble.classesOn,
3920
          off: bubble.classesOff
3921
        },
3922
        layout: candidate.label,
3923
        testY: newY
3924
      };
3925
      return fits || candidate.alwaysFit ? adt$8.fit(reposition) : adt$8.nofit(reposition, visibleW, visibleH, isPartlyVisible);
3926
    };
3927
    const attempts = (element, candidates, anchorBox, elementBox, bubbles, bounds) => {
3928
      const panelWidth = elementBox.width;
3929
      const panelHeight = elementBox.height;
3930
      const attemptBestFit = (layout, reposition, visibleW, visibleH, isVisible) => {
3931
        const next = layout(anchorBox, elementBox, bubbles, element, bounds);
3932
        const attemptLayout = attempt(next, panelWidth, panelHeight, bounds);
3933
        return attemptLayout.fold(constant$1(attemptLayout), (newReposition, newVisibleW, newVisibleH, newIsVisible) => {
3934
          const improved = isVisible === newIsVisible ? newVisibleH > visibleH || newVisibleW > visibleW : !isVisible && newIsVisible;
3935
          return improved ? attemptLayout : adt$8.nofit(reposition, visibleW, visibleH, isVisible);
3936
        });
3937
      };
3938
      const abc = foldl(candidates, (b, a) => {
3939
        const bestNext = curry(attemptBestFit, a);
3940
        return b.fold(constant$1(b), bestNext);
3941
      }, adt$8.nofit({
3942
        rect: anchorBox,
3943
        maxHeight: elementBox.height,
3944
        maxWidth: elementBox.width,
3945
        direction: southeast$3(),
3946
        placement: 'southeast',
3947
        classes: {
3948
          on: [],
3949
          off: []
3950
        },
3951
        layout: 'none',
3952
        testY: anchorBox.y
3953
      }, -1, -1, false));
3954
      return abc.fold(identity, identity);
3955
    };
3956
 
3957
    const singleton = doRevoke => {
3958
      const subject = Cell(Optional.none());
3959
      const revoke = () => subject.get().each(doRevoke);
3960
      const clear = () => {
3961
        revoke();
3962
        subject.set(Optional.none());
3963
      };
3964
      const isSet = () => subject.get().isSome();
3965
      const get = () => subject.get();
3966
      const set = s => {
3967
        revoke();
3968
        subject.set(Optional.some(s));
3969
      };
3970
      return {
3971
        clear,
3972
        isSet,
3973
        get,
3974
        set
3975
      };
3976
    };
3977
    const destroyable = () => singleton(s => s.destroy());
3978
    const unbindable = () => singleton(s => s.unbind());
3979
    const value$2 = () => {
3980
      const subject = singleton(noop);
3981
      const on = f => subject.get().each(f);
3982
      return {
3983
        ...subject,
3984
        on
3985
      };
3986
    };
3987
 
3988
    const filter = always;
3989
    const bind = (element, event, handler) => bind$2(element, event, filter, handler);
3990
    const capture = (element, event, handler) => capture$1(element, event, filter, handler);
3991
    const fromRawEvent = fromRawEvent$1;
3992
 
3993
    const properties = [
3994
      'top',
3995
      'bottom',
3996
      'right',
3997
      'left'
3998
    ];
3999
    const timerAttr = 'data-alloy-transition-timer';
4000
    const isTransitioning$1 = (element, transition) => hasAll(element, transition.classes);
4001
    const shouldApplyTransitionCss = (transition, decision, lastPlacement) => {
4002
      return lastPlacement.exists(placer => {
4003
        const mode = transition.mode;
4004
        return mode === 'all' ? true : placer[mode] !== decision[mode];
4005
      });
4006
    };
4007
    const hasChanges = (position, intermediate) => {
4008
      const round = value => parseFloat(value).toFixed(3);
4009
      return find$4(intermediate, (value, key) => {
4010
        const newValue = position[key].map(round);
4011
        const val = value.map(round);
4012
        return !equals(newValue, val);
4013
      }).isSome();
4014
    };
4015
    const getTransitionDuration = element => {
4016
      const get = name => {
4017
        const style = get$e(element, name);
4018
        const times = style.split(/\s*,\s*/);
4019
        return filter$2(times, isNotEmpty);
4020
      };
4021
      const parse = value => {
4022
        if (isString(value) && /^[\d.]+/.test(value)) {
4023
          const num = parseFloat(value);
4024
          return endsWith(value, 'ms') ? num : num * 1000;
4025
        } else {
4026
          return 0;
4027
        }
4028
      };
4029
      const delay = get('transition-delay');
4030
      const duration = get('transition-duration');
4031
      return foldl(duration, (acc, dur, i) => {
4032
        const time = parse(delay[i]) + parse(dur);
4033
        return Math.max(acc, time);
4034
      }, 0);
4035
    };
4036
    const setupTransitionListeners = (element, transition) => {
4037
      const transitionEnd = unbindable();
4038
      const transitionCancel = unbindable();
4039
      let timer;
4040
      const isSourceTransition = e => {
4041
        var _a;
4042
        const pseudoElement = (_a = e.raw.pseudoElement) !== null && _a !== void 0 ? _a : '';
4043
        return eq(e.target, element) && isEmpty(pseudoElement) && contains$2(properties, e.raw.propertyName);
4044
      };
4045
      const transitionDone = e => {
4046
        if (isNullable(e) || isSourceTransition(e)) {
4047
          transitionEnd.clear();
4048
          transitionCancel.clear();
4049
          const type = e === null || e === void 0 ? void 0 : e.raw.type;
4050
          if (isNullable(type) || type === transitionend()) {
4051
            clearTimeout(timer);
4052
            remove$7(element, timerAttr);
4053
            remove$1(element, transition.classes);
4054
          }
4055
        }
4056
      };
4057
      const transitionStart = bind(element, transitionstart(), e => {
4058
        if (isSourceTransition(e)) {
4059
          transitionStart.unbind();
4060
          transitionEnd.set(bind(element, transitionend(), transitionDone));
4061
          transitionCancel.set(bind(element, transitioncancel(), transitionDone));
4062
        }
4063
      });
4064
      const duration = getTransitionDuration(element);
4065
      requestAnimationFrame(() => {
4066
        timer = setTimeout(transitionDone, duration + 17);
4067
        set$9(element, timerAttr, timer);
4068
      });
4069
    };
4070
    const startTransitioning = (element, transition) => {
4071
      add$1(element, transition.classes);
4072
      getOpt(element, timerAttr).each(timerId => {
4073
        clearTimeout(parseInt(timerId, 10));
4074
        remove$7(element, timerAttr);
4075
      });
4076
      setupTransitionListeners(element, transition);
4077
    };
4078
    const applyTransitionCss = (element, origin, position, transition, decision, lastPlacement) => {
4079
      const shouldTransition = shouldApplyTransitionCss(transition, decision, lastPlacement);
4080
      if (shouldTransition || isTransitioning$1(element, transition)) {
4081
        set$8(element, 'position', position.position);
4082
        const rect = toBox(origin, element);
4083
        const intermediatePosition = reposition(origin, {
4084
          ...decision,
4085
          rect
4086
        });
4087
        const intermediateCssOptions = mapToObject(properties, prop => intermediatePosition[prop]);
4088
        if (hasChanges(position, intermediateCssOptions)) {
4089
          setOptions(element, intermediateCssOptions);
4090
          if (shouldTransition) {
4091
            startTransitioning(element, transition);
4092
          }
4093
          reflow(element);
4094
        }
4095
      } else {
4096
        remove$1(element, transition.classes);
4097
      }
4098
    };
4099
 
4100
    const elementSize = p => ({
4101
      width: getOuter$1(p),
4102
      height: getOuter$2(p)
4103
    });
4104
    const layout = (anchorBox, element, bubbles, options) => {
4105
      remove$6(element, 'max-height');
4106
      remove$6(element, 'max-width');
4107
      const elementBox = elementSize(element);
4108
      return attempts(element, options.preference, anchorBox, elementBox, bubbles, options.bounds);
4109
    };
4110
    const setClasses = (element, decision) => {
4111
      const classInfo = decision.classes;
4112
      remove$1(element, classInfo.off);
4113
      add$1(element, classInfo.on);
4114
    };
4115
    const setHeight = (element, decision, options) => {
4116
      const maxHeightFunction = options.maxHeightFunction;
4117
      maxHeightFunction(element, decision.maxHeight);
4118
    };
4119
    const setWidth = (element, decision, options) => {
4120
      const maxWidthFunction = options.maxWidthFunction;
4121
      maxWidthFunction(element, decision.maxWidth);
4122
    };
4123
    const position$2 = (element, decision, options) => {
4124
      const positionCss = reposition(options.origin, decision);
4125
      options.transition.each(transition => {
4126
        applyTransitionCss(element, options.origin, positionCss, transition, decision, options.lastPlacement);
4127
      });
4128
      applyPositionCss(element, positionCss);
4129
    };
4130
    const setPlacement = (element, decision) => {
4131
      setPlacement$1(element, decision.placement);
4132
    };
4133
 
4134
    const setMaxHeight = (element, maxHeight) => {
4135
      setMax$1(element, Math.floor(maxHeight));
4136
    };
4137
    const anchored = constant$1((element, available) => {
4138
      setMaxHeight(element, available);
4139
      setAll(element, {
4140
        'overflow-x': 'hidden',
4141
        'overflow-y': 'auto'
4142
      });
4143
    });
4144
    const expandable$1 = constant$1((element, available) => {
4145
      setMaxHeight(element, available);
4146
    });
4147
 
4148
    const defaultOr = (options, key, dephault) => options[key] === undefined ? dephault : options[key];
4149
    const simple = (anchor, element, bubble, layouts, lastPlacement, optBounds, overrideOptions, transition) => {
4150
      const maxHeightFunction = defaultOr(overrideOptions, 'maxHeightFunction', anchored());
4151
      const maxWidthFunction = defaultOr(overrideOptions, 'maxWidthFunction', noop);
4152
      const anchorBox = anchor.anchorBox;
4153
      const origin = anchor.origin;
4154
      const options = {
4155
        bounds: viewport(origin, optBounds),
4156
        origin,
4157
        preference: layouts,
4158
        maxHeightFunction,
4159
        maxWidthFunction,
4160
        lastPlacement,
4161
        transition
4162
      };
4163
      return go(anchorBox, element, bubble, options);
4164
    };
4165
    const go = (anchorBox, element, bubble, options) => {
4166
      const decision = layout(anchorBox, element, bubble, options);
4167
      position$2(element, decision, options);
4168
      setPlacement(element, decision);
4169
      setClasses(element, decision);
4170
      setHeight(element, decision, options);
4171
      setWidth(element, decision, options);
4172
      return {
4173
        layout: decision.layout,
4174
        placement: decision.placement
4175
      };
4176
    };
4177
 
4178
    const allAlignments = [
4179
      'valignCentre',
4180
      'alignLeft',
4181
      'alignRight',
4182
      'alignCentre',
4183
      'top',
4184
      'bottom',
4185
      'left',
4186
      'right',
4187
      'inset'
4188
    ];
4189
    const nu$5 = (xOffset, yOffset, classes, insetModifier = 1) => {
4190
      const insetXOffset = xOffset * insetModifier;
4191
      const insetYOffset = yOffset * insetModifier;
4192
      const getClasses = prop => get$g(classes, prop).getOr([]);
4193
      const make = (xDelta, yDelta, alignmentsOn) => {
4194
        const alignmentsOff = difference(allAlignments, alignmentsOn);
4195
        return {
4196
          offset: SugarPosition(xDelta, yDelta),
4197
          classesOn: bind$3(alignmentsOn, getClasses),
4198
          classesOff: bind$3(alignmentsOff, getClasses)
4199
        };
4200
      };
4201
      return {
4202
        southeast: () => make(-xOffset, yOffset, [
4203
          'top',
4204
          'alignLeft'
4205
        ]),
4206
        southwest: () => make(xOffset, yOffset, [
4207
          'top',
4208
          'alignRight'
4209
        ]),
4210
        south: () => make(-xOffset / 2, yOffset, [
4211
          'top',
4212
          'alignCentre'
4213
        ]),
4214
        northeast: () => make(-xOffset, -yOffset, [
4215
          'bottom',
4216
          'alignLeft'
4217
        ]),
4218
        northwest: () => make(xOffset, -yOffset, [
4219
          'bottom',
4220
          'alignRight'
4221
        ]),
4222
        north: () => make(-xOffset / 2, -yOffset, [
4223
          'bottom',
4224
          'alignCentre'
4225
        ]),
4226
        east: () => make(xOffset, -yOffset / 2, [
4227
          'valignCentre',
4228
          'left'
4229
        ]),
4230
        west: () => make(-xOffset, -yOffset / 2, [
4231
          'valignCentre',
4232
          'right'
4233
        ]),
4234
        insetNortheast: () => make(insetXOffset, insetYOffset, [
4235
          'top',
4236
          'alignLeft',
4237
          'inset'
4238
        ]),
4239
        insetNorthwest: () => make(-insetXOffset, insetYOffset, [
4240
          'top',
4241
          'alignRight',
4242
          'inset'
4243
        ]),
4244
        insetNorth: () => make(-insetXOffset / 2, insetYOffset, [
4245
          'top',
4246
          'alignCentre',
4247
          'inset'
4248
        ]),
4249
        insetSoutheast: () => make(insetXOffset, -insetYOffset, [
4250
          'bottom',
4251
          'alignLeft',
4252
          'inset'
4253
        ]),
4254
        insetSouthwest: () => make(-insetXOffset, -insetYOffset, [
4255
          'bottom',
4256
          'alignRight',
4257
          'inset'
4258
        ]),
4259
        insetSouth: () => make(-insetXOffset / 2, -insetYOffset, [
4260
          'bottom',
4261
          'alignCentre',
4262
          'inset'
4263
        ]),
4264
        insetEast: () => make(-insetXOffset, -insetYOffset / 2, [
4265
          'valignCentre',
4266
          'right',
4267
          'inset'
4268
        ]),
4269
        insetWest: () => make(insetXOffset, -insetYOffset / 2, [
4270
          'valignCentre',
4271
          'left',
4272
          'inset'
4273
        ])
4274
      };
4275
    };
4276
    const fallback = () => nu$5(0, 0, {});
4277
 
4278
    const nu$4 = identity;
4279
 
4280
    const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
4281
    const getDirection = element => get$e(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
4282
 
4283
    var AttributeValue;
4284
    (function (AttributeValue) {
4285
      AttributeValue['TopToBottom'] = 'toptobottom';
4286
      AttributeValue['BottomToTop'] = 'bottomtotop';
4287
    }(AttributeValue || (AttributeValue = {})));
4288
    const Attribute = 'data-alloy-vertical-dir';
4289
    const isBottomToTopDir = el => closest$2(el, current => isElement$1(current) && get$f(current, 'data-alloy-vertical-dir') === AttributeValue.BottomToTop);
4290
 
4291
    const schema$y = () => optionObjOf('layouts', [
4292
      required$1('onLtr'),
4293
      required$1('onRtl'),
4294
      option$3('onBottomLtr'),
4295
      option$3('onBottomRtl')
4296
    ]);
4297
    const get$5 = (elem, info, defaultLtr, defaultRtl, defaultBottomLtr, defaultBottomRtl, dirElement) => {
4298
      const isBottomToTop = dirElement.map(isBottomToTopDir).getOr(false);
4299
      const customLtr = info.layouts.map(ls => ls.onLtr(elem));
4300
      const customRtl = info.layouts.map(ls => ls.onRtl(elem));
4301
      const ltr = isBottomToTop ? info.layouts.bind(ls => ls.onBottomLtr.map(f => f(elem))).or(customLtr).getOr(defaultBottomLtr) : customLtr.getOr(defaultLtr);
4302
      const rtl = isBottomToTop ? info.layouts.bind(ls => ls.onBottomRtl.map(f => f(elem))).or(customRtl).getOr(defaultBottomRtl) : customRtl.getOr(defaultRtl);
4303
      const f = onDirection(ltr, rtl);
4304
      return f(elem);
4305
    };
4306
 
4307
    const placement$4 = (component, anchorInfo, origin) => {
4308
      const hotspot = anchorInfo.hotspot;
4309
      const anchorBox = toBox(origin, hotspot.element);
4310
      const layouts = get$5(component.element, anchorInfo, belowOrAbove(), belowOrAboveRtl(), aboveOrBelow(), aboveOrBelowRtl(), Optional.some(anchorInfo.hotspot.element));
4311
      return Optional.some(nu$4({
4312
        anchorBox,
4313
        bubble: anchorInfo.bubble.getOr(fallback()),
4314
        overrides: anchorInfo.overrides,
4315
        layouts
4316
      }));
4317
    };
4318
    var HotspotAnchor = [
4319
      required$1('hotspot'),
4320
      option$3('bubble'),
4321
      defaulted('overrides', {}),
4322
      schema$y(),
4323
      output$1('placement', placement$4)
4324
    ];
4325
 
4326
    const placement$3 = (component, anchorInfo, origin) => {
4327
      const pos = translate$2(origin, anchorInfo.x, anchorInfo.y);
4328
      const anchorBox = bounds(pos.left, pos.top, anchorInfo.width, anchorInfo.height);
4329
      const layouts = get$5(component.element, anchorInfo, all$1(), allRtl$1(), all$1(), allRtl$1(), Optional.none());
4330
      return Optional.some(nu$4({
4331
        anchorBox,
4332
        bubble: anchorInfo.bubble,
4333
        overrides: anchorInfo.overrides,
4334
        layouts
4335
      }));
4336
    };
4337
    var MakeshiftAnchor = [
4338
      required$1('x'),
4339
      required$1('y'),
4340
      defaulted('height', 0),
4341
      defaulted('width', 0),
4342
      defaulted('bubble', fallback()),
4343
      defaulted('overrides', {}),
4344
      schema$y(),
4345
      output$1('placement', placement$3)
4346
    ];
4347
 
4348
    const adt$7 = Adt.generate([
4349
      { screen: ['point'] },
4350
      {
4351
        absolute: [
4352
          'point',
4353
          'scrollLeft',
4354
          'scrollTop'
4355
        ]
4356
      }
4357
    ]);
4358
    const toFixed = pos => pos.fold(identity, (point, scrollLeft, scrollTop) => point.translate(-scrollLeft, -scrollTop));
4359
    const toAbsolute = pos => pos.fold(identity, identity);
4360
    const sum = points => foldl(points, (b, a) => b.translate(a.left, a.top), SugarPosition(0, 0));
4361
    const sumAsFixed = positions => {
4362
      const points = map$2(positions, toFixed);
4363
      return sum(points);
4364
    };
4365
    const sumAsAbsolute = positions => {
4366
      const points = map$2(positions, toAbsolute);
4367
      return sum(points);
4368
    };
4369
    const screen = adt$7.screen;
4370
    const absolute$1 = adt$7.absolute;
4371
 
4372
    const getOffset = (component, origin, anchorInfo) => {
4373
      const win = defaultView(anchorInfo.root).dom;
4374
      const hasSameOwner = frame => {
4375
        const frameOwner = owner$4(frame);
4376
        const compOwner = owner$4(component.element);
4377
        return eq(frameOwner, compOwner);
4378
      };
4379
      return Optional.from(win.frameElement).map(SugarElement.fromDom).filter(hasSameOwner).map(absolute$3);
4380
    };
4381
    const getRootPoint = (component, origin, anchorInfo) => {
4382
      const doc = owner$4(component.element);
4383
      const outerScroll = get$b(doc);
4384
      const offset = getOffset(component, origin, anchorInfo).getOr(outerScroll);
4385
      return absolute$1(offset, outerScroll.left, outerScroll.top);
4386
    };
4387
 
4388
    const getBox = (left, top, width, height) => {
4389
      const point = screen(SugarPosition(left, top));
4390
      return Optional.some(pointed(point, width, height));
4391
    };
4392
    const calcNewAnchor = (optBox, rootPoint, anchorInfo, origin, elem) => optBox.map(box => {
4393
      const points = [
4394
        rootPoint,
4395
        box.point
4396
      ];
4397
      const topLeft = cata$1(origin, () => sumAsAbsolute(points), () => sumAsAbsolute(points), () => sumAsFixed(points));
4398
      const anchorBox = rect(topLeft.left, topLeft.top, box.width, box.height);
4399
      const layoutsLtr = anchorInfo.showAbove ? aboveOrBelow() : belowOrAbove();
4400
      const layoutsRtl = anchorInfo.showAbove ? aboveOrBelowRtl() : belowOrAboveRtl();
4401
      const layouts = get$5(elem, anchorInfo, layoutsLtr, layoutsRtl, layoutsLtr, layoutsRtl, Optional.none());
4402
      return nu$4({
4403
        anchorBox,
4404
        bubble: anchorInfo.bubble.getOr(fallback()),
4405
        overrides: anchorInfo.overrides,
4406
        layouts
4407
      });
4408
    });
4409
 
4410
    const placement$2 = (component, anchorInfo, origin) => {
4411
      const rootPoint = getRootPoint(component, origin, anchorInfo);
4412
      return anchorInfo.node.filter(inBody).bind(target => {
4413
        const rect = target.dom.getBoundingClientRect();
4414
        const nodeBox = getBox(rect.left, rect.top, rect.width, rect.height);
4415
        const elem = anchorInfo.node.getOr(component.element);
4416
        return calcNewAnchor(nodeBox, rootPoint, anchorInfo, origin, elem);
4417
      });
4418
    };
4419
    var NodeAnchor = [
4420
      required$1('node'),
4421
      required$1('root'),
4422
      option$3('bubble'),
4423
      schema$y(),
4424
      defaulted('overrides', {}),
4425
      defaulted('showAbove', false),
4426
      output$1('placement', placement$2)
4427
    ];
4428
 
4429
    const zeroWidth = '\uFEFF';
4430
    const nbsp = '\xA0';
4431
 
4432
    const create$3 = (start, soffset, finish, foffset) => ({
4433
      start,
4434
      soffset,
4435
      finish,
4436
      foffset
4437
    });
4438
    const SimRange = { create: create$3 };
4439
 
4440
    const adt$6 = Adt.generate([
4441
      { before: ['element'] },
4442
      {
4443
        on: [
4444
          'element',
4445
          'offset'
4446
        ]
4447
      },
4448
      { after: ['element'] }
4449
    ]);
4450
    const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
4451
    const getStart$1 = situ => situ.fold(identity, identity, identity);
4452
    const before = adt$6.before;
4453
    const on$1 = adt$6.on;
4454
    const after$1 = adt$6.after;
4455
    const Situ = {
4456
      before,
4457
      on: on$1,
4458
      after: after$1,
4459
      cata,
4460
      getStart: getStart$1
4461
    };
4462
 
4463
    const adt$5 = Adt.generate([
4464
      { domRange: ['rng'] },
4465
      {
4466
        relative: [
4467
          'startSitu',
4468
          'finishSitu'
4469
        ]
4470
      },
4471
      {
4472
        exact: [
4473
          'start',
4474
          'soffset',
4475
          'finish',
4476
          'foffset'
4477
        ]
4478
      }
4479
    ]);
4480
    const exactFromRange = simRange => adt$5.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
4481
    const getStart = selection => selection.match({
4482
      domRange: rng => SugarElement.fromDom(rng.startContainer),
4483
      relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
4484
      exact: (start, _soffset, _finish, _foffset) => start
4485
    });
4486
    const domRange = adt$5.domRange;
4487
    const relative = adt$5.relative;
4488
    const exact = adt$5.exact;
4489
    const getWin = selection => {
4490
      const start = getStart(selection);
4491
      return defaultView(start);
4492
    };
4493
    const range$1 = SimRange.create;
4494
    const SimSelection = {
4495
      domRange,
4496
      relative,
4497
      exact,
4498
      exactFromRange,
4499
      getWin,
4500
      range: range$1
4501
    };
4502
 
4503
    const setStart = (rng, situ) => {
4504
      situ.fold(e => {
4505
        rng.setStartBefore(e.dom);
4506
      }, (e, o) => {
4507
        rng.setStart(e.dom, o);
4508
      }, e => {
4509
        rng.setStartAfter(e.dom);
4510
      });
4511
    };
4512
    const setFinish = (rng, situ) => {
4513
      situ.fold(e => {
4514
        rng.setEndBefore(e.dom);
4515
      }, (e, o) => {
4516
        rng.setEnd(e.dom, o);
4517
      }, e => {
4518
        rng.setEndAfter(e.dom);
4519
      });
4520
    };
4521
    const relativeToNative = (win, startSitu, finishSitu) => {
4522
      const range = win.document.createRange();
4523
      setStart(range, startSitu);
4524
      setFinish(range, finishSitu);
4525
      return range;
4526
    };
4527
    const exactToNative = (win, start, soffset, finish, foffset) => {
4528
      const rng = win.document.createRange();
4529
      rng.setStart(start.dom, soffset);
4530
      rng.setEnd(finish.dom, foffset);
4531
      return rng;
4532
    };
4533
    const toRect = rect => ({
4534
      left: rect.left,
4535
      top: rect.top,
4536
      right: rect.right,
4537
      bottom: rect.bottom,
4538
      width: rect.width,
4539
      height: rect.height
4540
    });
4541
    const getFirstRect$1 = rng => {
4542
      const rects = rng.getClientRects();
4543
      const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
4544
      return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
4545
    };
4546
    const getBounds$2 = rng => {
4547
      const rect = rng.getBoundingClientRect();
4548
      return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
4549
    };
4550
 
4551
    const adt$4 = Adt.generate([
4552
      {
4553
        ltr: [
4554
          'start',
4555
          'soffset',
4556
          'finish',
4557
          'foffset'
4558
        ]
4559
      },
4560
      {
4561
        rtl: [
4562
          'start',
4563
          'soffset',
4564
          'finish',
4565
          'foffset'
4566
        ]
4567
      }
4568
    ]);
4569
    const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
4570
    const getRanges = (win, selection) => selection.match({
4571
      domRange: rng => {
4572
        return {
4573
          ltr: constant$1(rng),
4574
          rtl: Optional.none
4575
        };
4576
      },
4577
      relative: (startSitu, finishSitu) => {
4578
        return {
4579
          ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
4580
          rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
4581
        };
4582
      },
4583
      exact: (start, soffset, finish, foffset) => {
4584
        return {
4585
          ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
4586
          rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
4587
        };
4588
      }
4589
    });
4590
    const doDiagnose = (win, ranges) => {
4591
      const rng = ranges.ltr();
4592
      if (rng.collapsed) {
4593
        const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
4594
        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));
4595
      } else {
4596
        return fromRange(win, adt$4.ltr, rng);
4597
      }
4598
    };
4599
    const diagnose = (win, selection) => {
4600
      const ranges = getRanges(win, selection);
4601
      return doDiagnose(win, ranges);
4602
    };
4603
    const asLtrRange = (win, selection) => {
4604
      const diagnosis = diagnose(win, selection);
4605
      return diagnosis.match({
4606
        ltr: (start, soffset, finish, foffset) => {
4607
          const rng = win.document.createRange();
4608
          rng.setStart(start.dom, soffset);
4609
          rng.setEnd(finish.dom, foffset);
4610
          return rng;
4611
        },
4612
        rtl: (start, soffset, finish, foffset) => {
4613
          const rng = win.document.createRange();
4614
          rng.setStart(finish.dom, foffset);
4615
          rng.setEnd(start.dom, soffset);
4616
          return rng;
4617
        }
4618
      });
4619
    };
4620
    adt$4.ltr;
4621
    adt$4.rtl;
4622
 
4623
    const ancestors = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate);
4624
 
4625
    const descendants = (scope, selector) => all$3(selector, scope);
4626
 
4627
    const makeRange = (start, soffset, finish, foffset) => {
4628
      const doc = owner$4(start);
4629
      const rng = doc.dom.createRange();
4630
      rng.setStart(start.dom, soffset);
4631
      rng.setEnd(finish.dom, foffset);
4632
      return rng;
4633
    };
4634
    const after = (start, soffset, finish, foffset) => {
4635
      const r = makeRange(start, soffset, finish, foffset);
4636
      const same = eq(start, finish) && soffset === foffset;
4637
      return r.collapsed && !same;
4638
    };
4639
 
4640
    const getNativeSelection = win => Optional.from(win.getSelection());
4641
    const readRange = selection => {
4642
      if (selection.rangeCount > 0) {
4643
        const firstRng = selection.getRangeAt(0);
4644
        const lastRng = selection.getRangeAt(selection.rangeCount - 1);
4645
        return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
4646
      } else {
4647
        return Optional.none();
4648
      }
4649
    };
4650
    const doGetExact = selection => {
4651
      if (selection.anchorNode === null || selection.focusNode === null) {
4652
        return readRange(selection);
4653
      } else {
4654
        const anchor = SugarElement.fromDom(selection.anchorNode);
4655
        const focus = SugarElement.fromDom(selection.focusNode);
4656
        return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
4657
      }
4658
    };
4659
    const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
4660
    const getFirstRect = (win, selection) => {
4661
      const rng = asLtrRange(win, selection);
4662
      return getFirstRect$1(rng);
4663
    };
4664
    const getBounds$1 = (win, selection) => {
4665
      const rng = asLtrRange(win, selection);
4666
      return getBounds$2(rng);
4667
    };
4668
 
4669
    const NodeValue = (is, name) => {
4670
      const get = element => {
4671
        if (!is(element)) {
4672
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
4673
        }
4674
        return getOption(element).getOr('');
4675
      };
4676
      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
4677
      const set = (element, value) => {
4678
        if (!is(element)) {
4679
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
4680
        }
4681
        element.dom.nodeValue = value;
4682
      };
4683
      return {
4684
        get,
4685
        getOption,
4686
        set
4687
      };
4688
    };
4689
 
4690
    const api = NodeValue(isText, 'text');
4691
    const get$4 = element => api.get(element);
4692
 
4693
    const point = (element, offset) => ({
4694
      element,
4695
      offset
4696
    });
4697
    const descendOnce$1 = (element, offset) => {
4698
      const children$1 = children(element);
4699
      if (children$1.length === 0) {
4700
        return point(element, offset);
4701
      } else if (offset < children$1.length) {
4702
        return point(children$1[offset], 0);
4703
      } else {
4704
        const last = children$1[children$1.length - 1];
4705
        const len = isText(last) ? get$4(last).length : children(last).length;
4706
        return point(last, len);
4707
      }
4708
    };
4709
 
4710
    const descendOnce = (element, offset) => isText(element) ? point(element, offset) : descendOnce$1(element, offset);
4711
    const isSimRange = detail => detail.foffset !== undefined;
4712
    const getAnchorSelection = (win, anchorInfo) => {
4713
      const getSelection = anchorInfo.getSelection.getOrThunk(() => () => getExact(win));
4714
      return getSelection().map(sel => {
4715
        if (isSimRange(sel)) {
4716
          const modStart = descendOnce(sel.start, sel.soffset);
4717
          const modFinish = descendOnce(sel.finish, sel.foffset);
4718
          return SimSelection.range(modStart.element, modStart.offset, modFinish.element, modFinish.offset);
4719
        } else {
4720
          return sel;
4721
        }
4722
      });
4723
    };
4724
    const placement$1 = (component, anchorInfo, origin) => {
4725
      const win = defaultView(anchorInfo.root).dom;
4726
      const rootPoint = getRootPoint(component, origin, anchorInfo);
4727
      const selectionBox = getAnchorSelection(win, anchorInfo).bind(sel => {
4728
        if (isSimRange(sel)) {
4729
          const optRect = getBounds$1(win, SimSelection.exactFromRange(sel)).orThunk(() => {
4730
            const zeroWidth$1 = SugarElement.fromText(zeroWidth);
4731
            before$1(sel.start, zeroWidth$1);
4732
            const rect = getFirstRect(win, SimSelection.exact(zeroWidth$1, 0, zeroWidth$1, 1));
4733
            remove$5(zeroWidth$1);
4734
            return rect;
4735
          });
4736
          return optRect.bind(rawRect => {
4737
            return getBox(rawRect.left, rawRect.top, rawRect.width, rawRect.height);
4738
          });
4739
        } else {
4740
          const selectionRect = map$1(sel, cell => cell.dom.getBoundingClientRect());
4741
          const bounds = {
4742
            left: Math.min(selectionRect.firstCell.left, selectionRect.lastCell.left),
4743
            right: Math.max(selectionRect.firstCell.right, selectionRect.lastCell.right),
4744
            top: Math.min(selectionRect.firstCell.top, selectionRect.lastCell.top),
4745
            bottom: Math.max(selectionRect.firstCell.bottom, selectionRect.lastCell.bottom)
4746
          };
4747
          return getBox(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
4748
        }
4749
      });
4750
      const targetElement = getAnchorSelection(win, anchorInfo).bind(sel => {
4751
        if (isSimRange(sel)) {
4752
          return isElement$1(sel.start) ? Optional.some(sel.start) : parentElement(sel.start);
4753
        } else {
4754
          return Optional.some(sel.firstCell);
4755
        }
4756
      });
4757
      const elem = targetElement.getOr(component.element);
4758
      return calcNewAnchor(selectionBox, rootPoint, anchorInfo, origin, elem);
4759
    };
4760
    var SelectionAnchor = [
4761
      option$3('getSelection'),
4762
      required$1('root'),
4763
      option$3('bubble'),
4764
      schema$y(),
4765
      defaulted('overrides', {}),
4766
      defaulted('showAbove', false),
4767
      output$1('placement', placement$1)
4768
    ];
4769
 
4770
    const labelPrefix$1 = 'link-layout';
4771
    const eastX = anchor => anchor.x + anchor.width;
4772
    const westX = (anchor, element) => anchor.x - element.width;
4773
    const northY$1 = (anchor, element) => anchor.y - element.height + anchor.height;
4774
    const southY$1 = anchor => anchor.y;
4775
    const southeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), southY$1(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
4776
      left: 0,
4777
      top: 2
4778
    }), labelPrefix$1);
4779
    const southwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), southY$1(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
4780
      right: 1,
4781
      top: 2
4782
    }), labelPrefix$1);
4783
    const northeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), northY$1(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
4784
      left: 0,
4785
      bottom: 3
4786
    }), labelPrefix$1);
4787
    const northwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), northY$1(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
4788
      right: 1,
4789
      bottom: 3
4790
    }), labelPrefix$1);
4791
    const all = () => [
4792
      southeast$1,
4793
      southwest$1,
4794
      northeast$1,
4795
      northwest$1
4796
    ];
4797
    const allRtl = () => [
4798
      southwest$1,
4799
      southeast$1,
4800
      northwest$1,
4801
      northeast$1
4802
    ];
4803
 
4804
    const placement = (component, submenuInfo, origin) => {
4805
      const anchorBox = toBox(origin, submenuInfo.item.element);
4806
      const layouts = get$5(component.element, submenuInfo, all(), allRtl(), all(), allRtl(), Optional.none());
4807
      return Optional.some(nu$4({
4808
        anchorBox,
4809
        bubble: fallback(),
4810
        overrides: submenuInfo.overrides,
4811
        layouts
4812
      }));
4813
    };
4814
    var SubmenuAnchor = [
4815
      required$1('item'),
4816
      schema$y(),
4817
      defaulted('overrides', {}),
4818
      output$1('placement', placement)
4819
    ];
4820
 
4821
    var AnchorSchema = choose$1('type', {
4822
      selection: SelectionAnchor,
4823
      node: NodeAnchor,
4824
      hotspot: HotspotAnchor,
4825
      submenu: SubmenuAnchor,
4826
      makeshift: MakeshiftAnchor
4827
    });
4828
 
4829
    const TransitionSchema = [
4830
      requiredArrayOf('classes', string),
4831
      defaultedStringEnum('mode', 'all', [
4832
        'all',
4833
        'layout',
4834
        'placement'
4835
      ])
4836
    ];
4837
    const PositionSchema = [
4838
      defaulted('useFixed', never),
4839
      option$3('getBounds')
4840
    ];
4841
    const PlacementSchema = [
4842
      requiredOf('anchor', AnchorSchema),
4843
      optionObjOf('transition', TransitionSchema)
4844
    ];
4845
 
4846
    const getFixedOrigin = () => {
4847
      const html = document.documentElement;
4848
      return fixed$1(0, 0, html.clientWidth, html.clientHeight);
4849
    };
4850
    const getRelativeOrigin = component => {
4851
      const position = absolute$3(component.element);
4852
      const bounds = component.element.dom.getBoundingClientRect();
4853
      return relative$1(position.left, position.top, bounds.width, bounds.height);
4854
    };
4855
    const place = (origin, anchoring, optBounds, placee, lastPlace, transition) => {
4856
      const anchor = box(anchoring.anchorBox, origin);
4857
      return simple(anchor, placee.element, anchoring.bubble, anchoring.layouts, lastPlace, optBounds, anchoring.overrides, transition);
4858
    };
4859
    const position$1 = (component, posConfig, posState, placee, placementSpec) => {
4860
      const optWithinBounds = Optional.none();
4861
      positionWithinBounds(component, posConfig, posState, placee, placementSpec, optWithinBounds);
4862
    };
4863
    const positionWithinBounds = (component, posConfig, posState, placee, placementSpec, optWithinBounds) => {
4864
      const placeeDetail = asRawOrDie$1('placement.info', objOf(PlacementSchema), placementSpec);
4865
      const anchorage = placeeDetail.anchor;
4866
      const element = placee.element;
4867
      const placeeState = posState.get(placee.uid);
4868
      preserve$1(() => {
4869
        set$8(element, 'position', 'fixed');
4870
        const oldVisibility = getRaw(element, 'visibility');
4871
        set$8(element, 'visibility', 'hidden');
4872
        const origin = posConfig.useFixed() ? getFixedOrigin() : getRelativeOrigin(component);
4873
        anchorage.placement(component, anchorage, origin).each(anchoring => {
4874
          const optBounds = optWithinBounds.orThunk(() => posConfig.getBounds.map(apply$1));
4875
          const newState = place(origin, anchoring, optBounds, placee, placeeState, placeeDetail.transition);
4876
          posState.set(placee.uid, newState);
4877
        });
4878
        oldVisibility.fold(() => {
4879
          remove$6(element, 'visibility');
4880
        }, vis => {
4881
          set$8(element, 'visibility', vis);
4882
        });
4883
        if (getRaw(element, 'left').isNone() && getRaw(element, 'top').isNone() && getRaw(element, 'right').isNone() && getRaw(element, 'bottom').isNone() && is$1(getRaw(element, 'position'), 'fixed')) {
4884
          remove$6(element, 'position');
4885
        }
4886
      }, element);
4887
    };
4888
    const getMode = (component, pConfig, _pState) => pConfig.useFixed() ? 'fixed' : 'absolute';
4889
    const reset$1 = (component, pConfig, posState, placee) => {
4890
      const element = placee.element;
4891
      each$1([
4892
        'position',
4893
        'left',
4894
        'right',
4895
        'top',
4896
        'bottom'
4897
      ], prop => remove$6(element, prop));
4898
      reset$2(element);
4899
      posState.clear(placee.uid);
4900
    };
4901
 
4902
    var PositionApis = /*#__PURE__*/Object.freeze({
4903
        __proto__: null,
4904
        position: position$1,
4905
        positionWithinBounds: positionWithinBounds,
4906
        getMode: getMode,
4907
        reset: reset$1
4908
    });
4909
 
4910
    const init$g = () => {
4911
      let state = {};
4912
      const set = (id, data) => {
4913
        state[id] = data;
4914
      };
4915
      const get = id => get$g(state, id);
4916
      const clear = id => {
4917
        if (isNonNullable(id)) {
4918
          delete state[id];
4919
        } else {
4920
          state = {};
4921
        }
4922
      };
4923
      return nu$8({
4924
        readState: () => state,
4925
        clear,
4926
        set,
4927
        get
4928
      });
4929
    };
4930
 
4931
    var PositioningState = /*#__PURE__*/Object.freeze({
4932
        __proto__: null,
4933
        init: init$g
4934
    });
4935
 
4936
    const Positioning = create$4({
4937
      fields: PositionSchema,
4938
      name: 'positioning',
4939
      active: ActivePosition,
4940
      apis: PositionApis,
4941
      state: PositioningState
4942
    });
4943
 
4944
    const isConnected = comp => comp.getSystem().isConnected();
4945
    const fireDetaching = component => {
4946
      emit(component, detachedFromDom());
4947
      const children = component.components();
4948
      each$1(children, fireDetaching);
4949
    };
4950
    const fireAttaching = component => {
4951
      const children = component.components();
4952
      each$1(children, fireAttaching);
4953
      emit(component, attachedToDom());
4954
    };
4955
    const virtualAttach = (parent, child) => {
4956
      parent.getSystem().addToWorld(child);
4957
      if (inBody(parent.element)) {
4958
        fireAttaching(child);
4959
      }
4960
    };
4961
    const virtualDetach = comp => {
4962
      fireDetaching(comp);
4963
      comp.getSystem().removeFromWorld(comp);
4964
    };
4965
    const attach$1 = (parent, child) => {
4966
      append$2(parent.element, child.element);
4967
    };
4968
    const detachChildren$1 = component => {
4969
      each$1(component.components(), childComp => remove$5(childComp.element));
4970
      empty(component.element);
4971
      component.syncComponents();
4972
    };
4973
    const replaceChildren = (component, newSpecs, buildNewChildren) => {
4974
      const subs = component.components();
4975
      detachChildren$1(component);
4976
      const newChildren = buildNewChildren(newSpecs);
4977
      const deleted = difference(subs, newChildren);
4978
      each$1(deleted, comp => {
4979
        fireDetaching(comp);
4980
        component.getSystem().removeFromWorld(comp);
4981
      });
4982
      each$1(newChildren, childComp => {
4983
        if (!isConnected(childComp)) {
4984
          component.getSystem().addToWorld(childComp);
4985
          attach$1(component, childComp);
4986
          if (inBody(component.element)) {
4987
            fireAttaching(childComp);
4988
          }
4989
        } else {
4990
          attach$1(component, childComp);
4991
        }
4992
      });
4993
      component.syncComponents();
4994
    };
4995
    const virtualReplaceChildren = (component, newSpecs, buildNewChildren) => {
4996
      const subs = component.components();
4997
      const existingComps = bind$3(newSpecs, spec => getPremade(spec).toArray());
4998
      each$1(subs, childComp => {
4999
        if (!contains$2(existingComps, childComp)) {
5000
          virtualDetach(childComp);
5001
        }
5002
      });
5003
      const newChildren = buildNewChildren(newSpecs);
5004
      const deleted = difference(subs, newChildren);
5005
      each$1(deleted, deletedComp => {
5006
        if (isConnected(deletedComp)) {
5007
          virtualDetach(deletedComp);
5008
        }
5009
      });
5010
      each$1(newChildren, childComp => {
5011
        if (!isConnected(childComp)) {
5012
          virtualAttach(component, childComp);
5013
        }
5014
      });
5015
      component.syncComponents();
5016
    };
5017
 
5018
    const attach = (parent, child) => {
5019
      attachWith(parent, child, append$2);
5020
    };
5021
    const attachWith = (parent, child, insertion) => {
5022
      parent.getSystem().addToWorld(child);
5023
      insertion(parent.element, child.element);
5024
      if (inBody(parent.element)) {
5025
        fireAttaching(child);
5026
      }
5027
      parent.syncComponents();
5028
    };
5029
    const doDetach = component => {
5030
      fireDetaching(component);
5031
      remove$5(component.element);
5032
      component.getSystem().removeFromWorld(component);
5033
    };
5034
    const detach = component => {
5035
      const parent$1 = parent(component.element).bind(p => component.getSystem().getByDom(p).toOptional());
5036
      doDetach(component);
5037
      parent$1.each(p => {
5038
        p.syncComponents();
5039
      });
5040
    };
5041
    const detachChildren = component => {
5042
      const subs = component.components();
5043
      each$1(subs, doDetach);
5044
      empty(component.element);
5045
      component.syncComponents();
5046
    };
5047
    const attachSystem = (element, guiSystem) => {
5048
      attachSystemWith(element, guiSystem, append$2);
5049
    };
5050
    const attachSystemAfter = (element, guiSystem) => {
5051
      attachSystemWith(element, guiSystem, after$2);
5052
    };
5053
    const attachSystemWith = (element, guiSystem, inserter) => {
5054
      inserter(element, guiSystem.element);
5055
      const children$1 = children(guiSystem.element);
5056
      each$1(children$1, child => {
5057
        guiSystem.getByDom(child).each(fireAttaching);
5058
      });
5059
    };
5060
    const detachSystem = guiSystem => {
5061
      const children$1 = children(guiSystem.element);
5062
      each$1(children$1, child => {
5063
        guiSystem.getByDom(child).each(fireDetaching);
5064
      });
5065
      remove$5(guiSystem.element);
5066
    };
5067
 
5068
    const rebuild = (sandbox, sConfig, sState, data) => {
5069
      sState.get().each(_data => {
5070
        detachChildren(sandbox);
5071
      });
5072
      const point = sConfig.getAttachPoint(sandbox);
5073
      attach(point, sandbox);
5074
      const built = sandbox.getSystem().build(data);
5075
      attach(sandbox, built);
5076
      sState.set(built);
5077
      return built;
5078
    };
5079
    const open$1 = (sandbox, sConfig, sState, data) => {
5080
      const newState = rebuild(sandbox, sConfig, sState, data);
5081
      sConfig.onOpen(sandbox, newState);
5082
      return newState;
5083
    };
5084
    const setContent = (sandbox, sConfig, sState, data) => sState.get().map(() => rebuild(sandbox, sConfig, sState, data));
5085
    const openWhileCloaked = (sandbox, sConfig, sState, data, transaction) => {
5086
      cloak(sandbox, sConfig);
5087
      open$1(sandbox, sConfig, sState, data);
5088
      transaction();
5089
      decloak(sandbox, sConfig);
5090
    };
5091
    const close$1 = (sandbox, sConfig, sState) => {
5092
      sState.get().each(data => {
5093
        detachChildren(sandbox);
5094
        detach(sandbox);
5095
        sConfig.onClose(sandbox, data);
5096
        sState.clear();
5097
      });
5098
    };
5099
    const isOpen$1 = (_sandbox, _sConfig, sState) => sState.isOpen();
5100
    const isPartOf = (sandbox, sConfig, sState, queryElem) => isOpen$1(sandbox, sConfig, sState) && sState.get().exists(data => sConfig.isPartOf(sandbox, data, queryElem));
5101
    const getState$2 = (_sandbox, _sConfig, sState) => sState.get();
5102
    const store = (sandbox, cssKey, attr, newValue) => {
5103
      getRaw(sandbox.element, cssKey).fold(() => {
5104
        remove$7(sandbox.element, attr);
5105
      }, v => {
5106
        set$9(sandbox.element, attr, v);
5107
      });
5108
      set$8(sandbox.element, cssKey, newValue);
5109
    };
5110
    const restore = (sandbox, cssKey, attr) => {
5111
      getOpt(sandbox.element, attr).fold(() => remove$6(sandbox.element, cssKey), oldValue => set$8(sandbox.element, cssKey, oldValue));
5112
    };
5113
    const cloak = (sandbox, sConfig, _sState) => {
5114
      const sink = sConfig.getAttachPoint(sandbox);
5115
      set$8(sandbox.element, 'position', Positioning.getMode(sink));
5116
      store(sandbox, 'visibility', sConfig.cloakVisibilityAttr, 'hidden');
5117
    };
5118
    const hasPosition = element => exists([
5119
      'top',
5120
      'left',
5121
      'right',
5122
      'bottom'
5123
    ], pos => getRaw(element, pos).isSome());
5124
    const decloak = (sandbox, sConfig, _sState) => {
5125
      if (!hasPosition(sandbox.element)) {
5126
        remove$6(sandbox.element, 'position');
5127
      }
5128
      restore(sandbox, 'visibility', sConfig.cloakVisibilityAttr);
5129
    };
5130
 
5131
    var SandboxApis = /*#__PURE__*/Object.freeze({
5132
        __proto__: null,
5133
        cloak: cloak,
5134
        decloak: decloak,
5135
        open: open$1,
5136
        openWhileCloaked: openWhileCloaked,
5137
        close: close$1,
5138
        isOpen: isOpen$1,
5139
        isPartOf: isPartOf,
5140
        getState: getState$2,
5141
        setContent: setContent
5142
    });
5143
 
5144
    const events$g = (sandboxConfig, sandboxState) => derive$2([run$1(sandboxClose(), (sandbox, _simulatedEvent) => {
5145
        close$1(sandbox, sandboxConfig, sandboxState);
5146
      })]);
5147
 
5148
    var ActiveSandbox = /*#__PURE__*/Object.freeze({
5149
        __proto__: null,
5150
        events: events$g
5151
    });
5152
 
5153
    var SandboxSchema = [
5154
      onHandler('onOpen'),
5155
      onHandler('onClose'),
5156
      required$1('isPartOf'),
5157
      required$1('getAttachPoint'),
5158
      defaulted('cloakVisibilityAttr', 'data-precloak-visibility')
5159
    ];
5160
 
5161
    const init$f = () => {
5162
      const contents = value$2();
5163
      const readState = constant$1('not-implemented');
5164
      return nu$8({
5165
        readState,
5166
        isOpen: contents.isSet,
5167
        clear: contents.clear,
5168
        set: contents.set,
5169
        get: contents.get
5170
      });
5171
    };
5172
 
5173
    var SandboxState = /*#__PURE__*/Object.freeze({
5174
        __proto__: null,
5175
        init: init$f
5176
    });
5177
 
5178
    const Sandboxing = create$4({
5179
      fields: SandboxSchema,
5180
      name: 'sandboxing',
5181
      active: ActiveSandbox,
5182
      apis: SandboxApis,
5183
      state: SandboxState
5184
    });
5185
 
5186
    const dismissPopups = constant$1('dismiss.popups');
5187
    const repositionPopups = constant$1('reposition.popups');
5188
    const mouseReleased = constant$1('mouse.released');
5189
 
5190
    const schema$x = objOfOnly([
5191
      defaulted('isExtraPart', never),
5192
      optionObjOf('fireEventInstead', [defaulted('event', dismissRequested())])
5193
    ]);
5194
    const receivingChannel$1 = rawSpec => {
5195
      const detail = asRawOrDie$1('Dismissal', schema$x, rawSpec);
5196
      return {
5197
        [dismissPopups()]: {
5198
          schema: objOfOnly([required$1('target')]),
5199
          onReceive: (sandbox, data) => {
5200
            if (Sandboxing.isOpen(sandbox)) {
5201
              const isPart = Sandboxing.isPartOf(sandbox, data.target) || detail.isExtraPart(sandbox, data.target);
5202
              if (!isPart) {
5203
                detail.fireEventInstead.fold(() => Sandboxing.close(sandbox), fe => emit(sandbox, fe.event));
5204
              }
5205
            }
5206
          }
5207
        }
5208
      };
5209
    };
5210
 
5211
    const schema$w = objOfOnly([
5212
      optionObjOf('fireEventInstead', [defaulted('event', repositionRequested())]),
5213
      requiredFunction('doReposition')
5214
    ]);
5215
    const receivingChannel = rawSpec => {
5216
      const detail = asRawOrDie$1('Reposition', schema$w, rawSpec);
5217
      return {
5218
        [repositionPopups()]: {
5219
          onReceive: sandbox => {
5220
            if (Sandboxing.isOpen(sandbox)) {
5221
              detail.fireEventInstead.fold(() => detail.doReposition(sandbox), fe => emit(sandbox, fe.event));
5222
            }
5223
          }
5224
        }
5225
      };
5226
    };
5227
 
5228
    const onLoad$5 = (component, repConfig, repState) => {
5229
      repConfig.store.manager.onLoad(component, repConfig, repState);
5230
    };
5231
    const onUnload$2 = (component, repConfig, repState) => {
5232
      repConfig.store.manager.onUnload(component, repConfig, repState);
5233
    };
5234
    const setValue$3 = (component, repConfig, repState, data) => {
5235
      repConfig.store.manager.setValue(component, repConfig, repState, data);
5236
    };
5237
    const getValue$3 = (component, repConfig, repState) => repConfig.store.manager.getValue(component, repConfig, repState);
5238
    const getState$1 = (component, repConfig, repState) => repState;
5239
 
5240
    var RepresentApis = /*#__PURE__*/Object.freeze({
5241
        __proto__: null,
5242
        onLoad: onLoad$5,
5243
        onUnload: onUnload$2,
5244
        setValue: setValue$3,
5245
        getValue: getValue$3,
5246
        getState: getState$1
5247
    });
5248
 
5249
    const events$f = (repConfig, repState) => {
5250
      const es = repConfig.resetOnDom ? [
5251
        runOnAttached((comp, _se) => {
5252
          onLoad$5(comp, repConfig, repState);
5253
        }),
5254
        runOnDetached((comp, _se) => {
5255
          onUnload$2(comp, repConfig, repState);
5256
        })
5257
      ] : [loadEvent(repConfig, repState, onLoad$5)];
5258
      return derive$2(es);
5259
    };
5260
 
5261
    var ActiveRepresenting = /*#__PURE__*/Object.freeze({
5262
        __proto__: null,
5263
        events: events$f
5264
    });
5265
 
5266
    const memory$1 = () => {
5267
      const data = Cell(null);
5268
      const readState = () => ({
5269
        mode: 'memory',
5270
        value: data.get()
5271
      });
5272
      const isNotSet = () => data.get() === null;
5273
      const clear = () => {
5274
        data.set(null);
5275
      };
5276
      return nu$8({
5277
        set: data.set,
5278
        get: data.get,
5279
        isNotSet,
5280
        clear,
5281
        readState
5282
      });
5283
    };
5284
    const manual = () => {
5285
      const readState = noop;
5286
      return nu$8({ readState });
5287
    };
5288
    const dataset = () => {
5289
      const dataByValue = Cell({});
5290
      const dataByText = Cell({});
5291
      const readState = () => ({
5292
        mode: 'dataset',
5293
        dataByValue: dataByValue.get(),
5294
        dataByText: dataByText.get()
5295
      });
5296
      const clear = () => {
5297
        dataByValue.set({});
5298
        dataByText.set({});
5299
      };
5300
      const lookup = itemString => get$g(dataByValue.get(), itemString).orThunk(() => get$g(dataByText.get(), itemString));
5301
      const update = items => {
5302
        const currentDataByValue = dataByValue.get();
5303
        const currentDataByText = dataByText.get();
5304
        const newDataByValue = {};
5305
        const newDataByText = {};
5306
        each$1(items, item => {
5307
          newDataByValue[item.value] = item;
5308
          get$g(item, 'meta').each(meta => {
5309
            get$g(meta, 'text').each(text => {
5310
              newDataByText[text] = item;
5311
            });
5312
          });
5313
        });
5314
        dataByValue.set({
5315
          ...currentDataByValue,
5316
          ...newDataByValue
5317
        });
5318
        dataByText.set({
5319
          ...currentDataByText,
5320
          ...newDataByText
5321
        });
5322
      };
5323
      return nu$8({
5324
        readState,
5325
        lookup,
5326
        update,
5327
        clear
5328
      });
5329
    };
5330
    const init$e = spec => spec.store.manager.state(spec);
5331
 
5332
    var RepresentState = /*#__PURE__*/Object.freeze({
5333
        __proto__: null,
5334
        memory: memory$1,
5335
        dataset: dataset,
5336
        manual: manual,
5337
        init: init$e
5338
    });
5339
 
5340
    const setValue$2 = (component, repConfig, repState, data) => {
5341
      const store = repConfig.store;
5342
      repState.update([data]);
5343
      store.setValue(component, data);
5344
      repConfig.onSetValue(component, data);
5345
    };
5346
    const getValue$2 = (component, repConfig, repState) => {
5347
      const store = repConfig.store;
5348
      const key = store.getDataKey(component);
5349
      return repState.lookup(key).getOrThunk(() => store.getFallbackEntry(key));
5350
    };
5351
    const onLoad$4 = (component, repConfig, repState) => {
5352
      const store = repConfig.store;
5353
      store.initialValue.each(data => {
5354
        setValue$2(component, repConfig, repState, data);
5355
      });
5356
    };
5357
    const onUnload$1 = (component, repConfig, repState) => {
5358
      repState.clear();
5359
    };
5360
    var DatasetStore = [
5361
      option$3('initialValue'),
5362
      required$1('getFallbackEntry'),
5363
      required$1('getDataKey'),
5364
      required$1('setValue'),
5365
      output$1('manager', {
5366
        setValue: setValue$2,
5367
        getValue: getValue$2,
5368
        onLoad: onLoad$4,
5369
        onUnload: onUnload$1,
5370
        state: dataset
5371
      })
5372
    ];
5373
 
5374
    const getValue$1 = (component, repConfig, _repState) => repConfig.store.getValue(component);
5375
    const setValue$1 = (component, repConfig, _repState, data) => {
5376
      repConfig.store.setValue(component, data);
5377
      repConfig.onSetValue(component, data);
5378
    };
5379
    const onLoad$3 = (component, repConfig, _repState) => {
5380
      repConfig.store.initialValue.each(data => {
5381
        repConfig.store.setValue(component, data);
5382
      });
5383
    };
5384
    var ManualStore = [
5385
      required$1('getValue'),
5386
      defaulted('setValue', noop),
5387
      option$3('initialValue'),
5388
      output$1('manager', {
5389
        setValue: setValue$1,
5390
        getValue: getValue$1,
5391
        onLoad: onLoad$3,
5392
        onUnload: noop,
5393
        state: NoState.init
5394
      })
5395
    ];
5396
 
5397
    const setValue = (component, repConfig, repState, data) => {
5398
      repState.set(data);
5399
      repConfig.onSetValue(component, data);
5400
    };
5401
    const getValue = (component, repConfig, repState) => repState.get();
5402
    const onLoad$2 = (component, repConfig, repState) => {
5403
      repConfig.store.initialValue.each(initVal => {
5404
        if (repState.isNotSet()) {
5405
          repState.set(initVal);
5406
        }
5407
      });
5408
    };
5409
    const onUnload = (component, repConfig, repState) => {
5410
      repState.clear();
5411
    };
5412
    var MemoryStore = [
5413
      option$3('initialValue'),
5414
      output$1('manager', {
5415
        setValue,
5416
        getValue,
5417
        onLoad: onLoad$2,
5418
        onUnload,
5419
        state: memory$1
5420
      })
5421
    ];
5422
 
5423
    var RepresentSchema = [
5424
      defaultedOf('store', { mode: 'memory' }, choose$1('mode', {
5425
        memory: MemoryStore,
5426
        manual: ManualStore,
5427
        dataset: DatasetStore
5428
      })),
5429
      onHandler('onSetValue'),
5430
      defaulted('resetOnDom', false)
5431
    ];
5432
 
5433
    const Representing = create$4({
5434
      fields: RepresentSchema,
5435
      name: 'representing',
5436
      active: ActiveRepresenting,
5437
      apis: RepresentApis,
5438
      extra: {
5439
        setValueFrom: (component, source) => {
5440
          const value = Representing.getValue(source);
5441
          Representing.setValue(component, value);
5442
        }
5443
      },
5444
      state: RepresentState
5445
    });
5446
 
5447
    const field = (name, forbidden) => defaultedObjOf(name, {}, map$2(forbidden, f => forbid(f.name(), 'Cannot configure ' + f.name() + ' for ' + name)).concat([customField('dump', identity)]));
5448
    const get$3 = data => data.dump;
5449
    const augment = (data, original) => ({
5450
      ...derive$1(original),
5451
      ...data.dump
5452
    });
5453
    const SketchBehaviours = {
5454
      field,
5455
      augment,
5456
      get: get$3
5457
    };
5458
 
5459
    const _placeholder = 'placeholder';
5460
    const adt$3 = Adt.generate([
5461
      {
5462
        single: [
5463
          'required',
5464
          'valueThunk'
5465
        ]
5466
      },
5467
      {
5468
        multiple: [
5469
          'required',
5470
          'valueThunks'
5471
        ]
5472
      }
5473
    ]);
5474
    const isSubstituted = spec => has$2(spec, 'uiType');
5475
    const subPlaceholder = (owner, detail, compSpec, placeholders) => {
5476
      if (owner.exists(o => o !== compSpec.owner)) {
5477
        return adt$3.single(true, constant$1(compSpec));
5478
      }
5479
      return get$g(placeholders, compSpec.name).fold(() => {
5480
        throw new Error('Unknown placeholder component: ' + compSpec.name + '\nKnown: [' + keys(placeholders) + ']\nNamespace: ' + owner.getOr('none') + '\nSpec: ' + JSON.stringify(compSpec, null, 2));
5481
      }, newSpec => newSpec.replace());
5482
    };
5483
    const scan = (owner, detail, compSpec, placeholders) => {
5484
      if (isSubstituted(compSpec) && compSpec.uiType === _placeholder) {
5485
        return subPlaceholder(owner, detail, compSpec, placeholders);
5486
      } else {
5487
        return adt$3.single(false, constant$1(compSpec));
5488
      }
5489
    };
5490
    const substitute = (owner, detail, compSpec, placeholders) => {
5491
      const base = scan(owner, detail, compSpec, placeholders);
5492
      return base.fold((req, valueThunk) => {
5493
        const value = isSubstituted(compSpec) ? valueThunk(detail, compSpec.config, compSpec.validated) : valueThunk(detail);
5494
        const childSpecs = get$g(value, 'components').getOr([]);
5495
        const substituted = bind$3(childSpecs, c => substitute(owner, detail, c, placeholders));
5496
        return [{
5497
            ...value,
5498
            components: substituted
5499
          }];
5500
      }, (req, valuesThunk) => {
5501
        if (isSubstituted(compSpec)) {
5502
          const values = valuesThunk(detail, compSpec.config, compSpec.validated);
5503
          const preprocessor = compSpec.validated.preprocess.getOr(identity);
5504
          return preprocessor(values);
5505
        } else {
5506
          return valuesThunk(detail);
5507
        }
5508
      });
5509
    };
5510
    const substituteAll = (owner, detail, components, placeholders) => bind$3(components, c => substitute(owner, detail, c, placeholders));
5511
    const oneReplace = (label, replacements) => {
5512
      let called = false;
5513
      const used = () => called;
5514
      const replace = () => {
5515
        if (called) {
5516
          throw new Error('Trying to use the same placeholder more than once: ' + label);
5517
        }
5518
        called = true;
5519
        return replacements;
5520
      };
5521
      const required = () => replacements.fold((req, _) => req, (req, _) => req);
5522
      return {
5523
        name: constant$1(label),
5524
        required,
5525
        used,
5526
        replace
5527
      };
5528
    };
5529
    const substitutePlaces = (owner, detail, components, placeholders) => {
5530
      const ps = map$1(placeholders, (ph, name) => oneReplace(name, ph));
5531
      const outcome = substituteAll(owner, detail, components, ps);
5532
      each(ps, p => {
5533
        if (p.used() === false && p.required()) {
5534
          throw new Error('Placeholder: ' + p.name() + ' was not found in components list\nNamespace: ' + owner.getOr('none') + '\nComponents: ' + JSON.stringify(detail.components, null, 2));
5535
        }
5536
      });
5537
      return outcome;
5538
    };
5539
    const single$2 = adt$3.single;
5540
    const multiple = adt$3.multiple;
5541
    const placeholder = constant$1(_placeholder);
5542
 
5543
    const adt$2 = Adt.generate([
5544
      { required: ['data'] },
5545
      { external: ['data'] },
5546
      { optional: ['data'] },
5547
      { group: ['data'] }
5548
    ]);
5549
    const fFactory = defaulted('factory', { sketch: identity });
5550
    const fSchema = defaulted('schema', []);
5551
    const fName = required$1('name');
5552
    const fPname = field$1('pname', 'pname', defaultedThunk(typeSpec => '<alloy.' + generate$6(typeSpec.name) + '>'), anyValue());
5553
    const fGroupSchema = customField('schema', () => [option$3('preprocess')]);
5554
    const fDefaults = defaulted('defaults', constant$1({}));
5555
    const fOverrides = defaulted('overrides', constant$1({}));
5556
    const requiredSpec = objOf([
5557
      fFactory,
5558
      fSchema,
5559
      fName,
5560
      fPname,
5561
      fDefaults,
5562
      fOverrides
5563
    ]);
5564
    const externalSpec = objOf([
5565
      fFactory,
5566
      fSchema,
5567
      fName,
5568
      fDefaults,
5569
      fOverrides
5570
    ]);
5571
    const optionalSpec = objOf([
5572
      fFactory,
5573
      fSchema,
5574
      fName,
5575
      fPname,
5576
      fDefaults,
5577
      fOverrides
5578
    ]);
5579
    const groupSpec = objOf([
5580
      fFactory,
5581
      fGroupSchema,
5582
      fName,
5583
      required$1('unit'),
5584
      fPname,
5585
      fDefaults,
5586
      fOverrides
5587
    ]);
5588
    const asNamedPart = part => {
5589
      return part.fold(Optional.some, Optional.none, Optional.some, Optional.some);
5590
    };
5591
    const name$2 = part => {
5592
      const get = data => data.name;
5593
      return part.fold(get, get, get, get);
5594
    };
5595
    const asCommon = part => {
5596
      return part.fold(identity, identity, identity, identity);
5597
    };
5598
    const convert = (adtConstructor, partSchema) => spec => {
5599
      const data = asRawOrDie$1('Converting part type', partSchema, spec);
5600
      return adtConstructor(data);
5601
    };
5602
    const required = convert(adt$2.required, requiredSpec);
5603
    const external = convert(adt$2.external, externalSpec);
5604
    const optional = convert(adt$2.optional, optionalSpec);
5605
    const group = convert(adt$2.group, groupSpec);
5606
    const original = constant$1('entirety');
5607
 
5608
    var PartType = /*#__PURE__*/Object.freeze({
5609
        __proto__: null,
5610
        required: required,
5611
        external: external,
5612
        optional: optional,
5613
        group: group,
5614
        asNamedPart: asNamedPart,
5615
        name: name$2,
5616
        asCommon: asCommon,
5617
        original: original
5618
    });
5619
 
5620
    const combine = (detail, data, partSpec, partValidated) => deepMerge(data.defaults(detail, partSpec, partValidated), partSpec, { uid: detail.partUids[data.name] }, data.overrides(detail, partSpec, partValidated));
5621
    const subs = (owner, detail, parts) => {
5622
      const internals = {};
5623
      const externals = {};
5624
      each$1(parts, part => {
5625
        part.fold(data => {
5626
          internals[data.pname] = single$2(true, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
5627
        }, data => {
5628
          const partSpec = detail.parts[data.name];
5629
          externals[data.name] = constant$1(data.factory.sketch(combine(detail, data, partSpec[original()]), partSpec));
5630
        }, data => {
5631
          internals[data.pname] = single$2(false, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
5632
        }, data => {
5633
          internals[data.pname] = multiple(true, (detail, _partSpec, _partValidated) => {
5634
            const units = detail[data.name];
5635
            return map$2(units, u => data.factory.sketch(deepMerge(data.defaults(detail, u, _partValidated), u, data.overrides(detail, u))));
5636
          });
5637
        });
5638
      });
5639
      return {
5640
        internals: constant$1(internals),
5641
        externals: constant$1(externals)
5642
      };
5643
    };
5644
 
5645
    const generate$3 = (owner, parts) => {
5646
      const r = {};
5647
      each$1(parts, part => {
5648
        asNamedPart(part).each(np => {
5649
          const g = doGenerateOne(owner, np.pname);
5650
          r[np.name] = config => {
5651
            const validated = asRawOrDie$1('Part: ' + np.name + ' in ' + owner, objOf(np.schema), config);
5652
            return {
5653
              ...g,
5654
              config,
5655
              validated
5656
            };
5657
          };
5658
        });
5659
      });
5660
      return r;
5661
    };
5662
    const doGenerateOne = (owner, pname) => ({
5663
      uiType: placeholder(),
5664
      owner,
5665
      name: pname
5666
    });
5667
    const generateOne$1 = (owner, pname, config) => ({
5668
      uiType: placeholder(),
5669
      owner,
5670
      name: pname,
5671
      config,
5672
      validated: {}
5673
    });
5674
    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());
5675
    const names = parts => map$2(parts, name$2);
5676
    const substitutes = (owner, detail, parts) => subs(owner, detail, parts);
5677
    const components$1 = (owner, detail, internals) => substitutePlaces(Optional.some(owner), detail, detail.components, internals);
5678
    const getPart = (component, detail, partKey) => {
5679
      const uid = detail.partUids[partKey];
5680
      return component.getSystem().getByUid(uid).toOptional();
5681
    };
5682
    const getPartOrDie = (component, detail, partKey) => getPart(component, detail, partKey).getOrDie('Could not find part: ' + partKey);
5683
    const getParts = (component, detail, partKeys) => {
5684
      const r = {};
5685
      const uids = detail.partUids;
5686
      const system = component.getSystem();
5687
      each$1(partKeys, pk => {
5688
        r[pk] = constant$1(system.getByUid(uids[pk]));
5689
      });
5690
      return r;
5691
    };
5692
    const getAllParts = (component, detail) => {
5693
      const system = component.getSystem();
5694
      return map$1(detail.partUids, (pUid, _k) => constant$1(system.getByUid(pUid)));
5695
    };
5696
    const getAllPartNames = detail => keys(detail.partUids);
5697
    const getPartsOrDie = (component, detail, partKeys) => {
5698
      const r = {};
5699
      const uids = detail.partUids;
5700
      const system = component.getSystem();
5701
      each$1(partKeys, pk => {
5702
        r[pk] = constant$1(system.getByUid(uids[pk]).getOrDie());
5703
      });
5704
      return r;
5705
    };
5706
    const defaultUids = (baseUid, partTypes) => {
5707
      const partNames = names(partTypes);
5708
      return wrapAll(map$2(partNames, pn => ({
5709
        key: pn,
5710
        value: baseUid + '-' + pn
5711
      })));
5712
    };
5713
    const defaultUidsSchema = partTypes => field$1('partUids', 'partUids', mergeWithThunk(spec => defaultUids(spec.uid, partTypes)), anyValue());
5714
 
5715
    var AlloyParts = /*#__PURE__*/Object.freeze({
5716
        __proto__: null,
5717
        generate: generate$3,
5718
        generateOne: generateOne$1,
5719
        schemas: schemas,
5720
        names: names,
5721
        substitutes: substitutes,
5722
        components: components$1,
5723
        defaultUids: defaultUids,
5724
        defaultUidsSchema: defaultUidsSchema,
5725
        getAllParts: getAllParts,
5726
        getAllPartNames: getAllPartNames,
5727
        getPart: getPart,
5728
        getPartOrDie: getPartOrDie,
5729
        getParts: getParts,
5730
        getPartsOrDie: getPartsOrDie
5731
    });
5732
 
5733
    const base = (partSchemas, partUidsSchemas) => {
5734
      const ps = partSchemas.length > 0 ? [requiredObjOf('parts', partSchemas)] : [];
5735
      return ps.concat([
5736
        required$1('uid'),
5737
        defaulted('dom', {}),
5738
        defaulted('components', []),
5739
        snapshot('originalSpec'),
5740
        defaulted('debug.sketcher', {})
5741
      ]).concat(partUidsSchemas);
5742
    };
5743
    const asRawOrDie = (label, schema, spec, partSchemas, partUidsSchemas) => {
5744
      const baseS = base(partSchemas, partUidsSchemas);
5745
      return asRawOrDie$1(label + ' [SpecSchema]', objOfOnly(baseS.concat(schema)), spec);
5746
    };
5747
 
5748
    const single$1 = (owner, schema, factory, spec) => {
5749
      const specWithUid = supplyUid(spec);
5750
      const detail = asRawOrDie(owner, schema, specWithUid, [], []);
5751
      return factory(detail, specWithUid);
5752
    };
5753
    const composite$1 = (owner, schema, partTypes, factory, spec) => {
5754
      const specWithUid = supplyUid(spec);
5755
      const partSchemas = schemas(partTypes);
5756
      const partUidsSchema = defaultUidsSchema(partTypes);
5757
      const detail = asRawOrDie(owner, schema, specWithUid, partSchemas, [partUidsSchema]);
5758
      const subs = substitutes(owner, detail, partTypes);
5759
      const components = components$1(owner, detail, subs.internals());
5760
      return factory(detail, components, specWithUid, subs.externals());
5761
    };
5762
    const hasUid = spec => has$2(spec, 'uid');
5763
    const supplyUid = spec => {
5764
      return hasUid(spec) ? spec : {
5765
        ...spec,
5766
        uid: generate$5('uid')
5767
      };
5768
    };
5769
 
5770
    const isSketchSpec = spec => {
5771
      return spec.uid !== undefined;
5772
    };
5773
    const singleSchema = objOfOnly([
5774
      required$1('name'),
5775
      required$1('factory'),
5776
      required$1('configFields'),
5777
      defaulted('apis', {}),
5778
      defaulted('extraApis', {})
5779
    ]);
5780
    const compositeSchema = objOfOnly([
5781
      required$1('name'),
5782
      required$1('factory'),
5783
      required$1('configFields'),
5784
      required$1('partFields'),
5785
      defaulted('apis', {}),
5786
      defaulted('extraApis', {})
5787
    ]);
5788
    const single = rawConfig => {
5789
      const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, singleSchema, rawConfig);
5790
      const sketch = spec => single$1(config.name, config.configFields, config.factory, spec);
5791
      const apis = map$1(config.apis, makeApi);
5792
      const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
5793
      return {
5794
        name: config.name,
5795
        configFields: config.configFields,
5796
        sketch,
5797
        ...apis,
5798
        ...extraApis
5799
      };
5800
    };
5801
    const composite = rawConfig => {
5802
      const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, compositeSchema, rawConfig);
5803
      const sketch = spec => composite$1(config.name, config.configFields, config.partFields, config.factory, spec);
5804
      const parts = generate$3(config.name, config.partFields);
5805
      const apis = map$1(config.apis, makeApi);
5806
      const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
5807
      return {
5808
        name: config.name,
5809
        partFields: config.partFields,
5810
        configFields: config.configFields,
5811
        sketch,
5812
        parts,
5813
        ...apis,
5814
        ...extraApis
5815
      };
5816
    };
5817
 
5818
    const inside = target => isTag('input')(target) && get$f(target, 'type') !== 'radio' || isTag('textarea')(target);
5819
 
5820
    const getCurrent = (component, composeConfig, _composeState) => composeConfig.find(component);
5821
 
5822
    var ComposeApis = /*#__PURE__*/Object.freeze({
5823
        __proto__: null,
5824
        getCurrent: getCurrent
5825
    });
5826
 
5827
    const ComposeSchema = [required$1('find')];
5828
 
5829
    const Composing = create$4({
5830
      fields: ComposeSchema,
5831
      name: 'composing',
5832
      apis: ComposeApis
5833
    });
5834
 
5835
    const nativeDisabled = [
5836
      'input',
5837
      'button',
5838
      'textarea',
5839
      'select'
5840
    ];
5841
    const onLoad$1 = (component, disableConfig, disableState) => {
5842
      const f = disableConfig.disabled() ? disable : enable;
5843
      f(component, disableConfig);
5844
    };
5845
    const hasNative = (component, config) => config.useNative === true && contains$2(nativeDisabled, name$3(component.element));
5846
    const nativeIsDisabled = component => has$1(component.element, 'disabled');
5847
    const nativeDisable = component => {
5848
      set$9(component.element, 'disabled', 'disabled');
5849
    };
5850
    const nativeEnable = component => {
5851
      remove$7(component.element, 'disabled');
5852
    };
5853
    const ariaIsDisabled = component => get$f(component.element, 'aria-disabled') === 'true';
5854
    const ariaDisable = component => {
5855
      set$9(component.element, 'aria-disabled', 'true');
5856
    };
5857
    const ariaEnable = component => {
5858
      set$9(component.element, 'aria-disabled', 'false');
5859
    };
5860
    const disable = (component, disableConfig, _disableState) => {
5861
      disableConfig.disableClass.each(disableClass => {
5862
        add$2(component.element, disableClass);
5863
      });
5864
      const f = hasNative(component, disableConfig) ? nativeDisable : ariaDisable;
5865
      f(component);
5866
      disableConfig.onDisabled(component);
5867
    };
5868
    const enable = (component, disableConfig, _disableState) => {
5869
      disableConfig.disableClass.each(disableClass => {
5870
        remove$2(component.element, disableClass);
5871
      });
5872
      const f = hasNative(component, disableConfig) ? nativeEnable : ariaEnable;
5873
      f(component);
5874
      disableConfig.onEnabled(component);
5875
    };
5876
    const isDisabled = (component, disableConfig) => hasNative(component, disableConfig) ? nativeIsDisabled(component) : ariaIsDisabled(component);
5877
    const set$4 = (component, disableConfig, disableState, disabled) => {
5878
      const f = disabled ? disable : enable;
5879
      f(component, disableConfig);
5880
    };
5881
 
5882
    var DisableApis = /*#__PURE__*/Object.freeze({
5883
        __proto__: null,
5884
        enable: enable,
5885
        disable: disable,
5886
        isDisabled: isDisabled,
5887
        onLoad: onLoad$1,
5888
        set: set$4
5889
    });
5890
 
5891
    const exhibit$5 = (base, disableConfig) => nu$7({ classes: disableConfig.disabled() ? disableConfig.disableClass.toArray() : [] });
5892
    const events$e = (disableConfig, disableState) => derive$2([
5893
      abort(execute$5(), (component, _simulatedEvent) => isDisabled(component, disableConfig)),
5894
      loadEvent(disableConfig, disableState, onLoad$1)
5895
    ]);
5896
 
5897
    var ActiveDisable = /*#__PURE__*/Object.freeze({
5898
        __proto__: null,
5899
        exhibit: exhibit$5,
5900
        events: events$e
5901
    });
5902
 
5903
    var DisableSchema = [
5904
      defaultedFunction('disabled', never),
5905
      defaulted('useNative', true),
5906
      option$3('disableClass'),
5907
      onHandler('onDisabled'),
5908
      onHandler('onEnabled')
5909
    ];
5910
 
5911
    const Disabling = create$4({
5912
      fields: DisableSchema,
5913
      name: 'disabling',
5914
      active: ActiveDisable,
5915
      apis: DisableApis
5916
    });
5917
 
5918
    const dehighlightAllExcept = (component, hConfig, hState, skip) => {
5919
      const highlighted = descendants(component.element, '.' + hConfig.highlightClass);
5920
      each$1(highlighted, h => {
5921
        const shouldSkip = exists(skip, skipComp => eq(skipComp.element, h));
5922
        if (!shouldSkip) {
5923
          remove$2(h, hConfig.highlightClass);
5924
          component.getSystem().getByDom(h).each(target => {
5925
            hConfig.onDehighlight(component, target);
5926
            emit(target, dehighlight$1());
5927
          });
5928
        }
5929
      });
5930
    };
5931
    const dehighlightAll = (component, hConfig, hState) => dehighlightAllExcept(component, hConfig, hState, []);
5932
    const dehighlight = (component, hConfig, hState, target) => {
5933
      if (isHighlighted(component, hConfig, hState, target)) {
5934
        remove$2(target.element, hConfig.highlightClass);
5935
        hConfig.onDehighlight(component, target);
5936
        emit(target, dehighlight$1());
5937
      }
5938
    };
5939
    const highlight = (component, hConfig, hState, target) => {
5940
      dehighlightAllExcept(component, hConfig, hState, [target]);
5941
      if (!isHighlighted(component, hConfig, hState, target)) {
5942
        add$2(target.element, hConfig.highlightClass);
5943
        hConfig.onHighlight(component, target);
5944
        emit(target, highlight$1());
5945
      }
5946
    };
5947
    const highlightFirst = (component, hConfig, hState) => {
5948
      getFirst(component, hConfig).each(firstComp => {
5949
        highlight(component, hConfig, hState, firstComp);
5950
      });
5951
    };
5952
    const highlightLast = (component, hConfig, hState) => {
5953
      getLast(component, hConfig).each(lastComp => {
5954
        highlight(component, hConfig, hState, lastComp);
5955
      });
5956
    };
5957
    const highlightAt = (component, hConfig, hState, index) => {
5958
      getByIndex(component, hConfig, hState, index).fold(err => {
5959
        throw err;
5960
      }, firstComp => {
5961
        highlight(component, hConfig, hState, firstComp);
5962
      });
5963
    };
5964
    const highlightBy = (component, hConfig, hState, predicate) => {
5965
      const candidates = getCandidates(component, hConfig);
5966
      const targetComp = find$5(candidates, predicate);
5967
      targetComp.each(c => {
5968
        highlight(component, hConfig, hState, c);
5969
      });
5970
    };
5971
    const isHighlighted = (component, hConfig, hState, queryTarget) => has(queryTarget.element, hConfig.highlightClass);
5972
    const getHighlighted = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.highlightClass).bind(e => component.getSystem().getByDom(e).toOptional());
5973
    const getByIndex = (component, hConfig, hState, index) => {
5974
      const items = descendants(component.element, '.' + hConfig.itemClass);
5975
      return Optional.from(items[index]).fold(() => Result.error(new Error('No element found with index ' + index)), component.getSystem().getByDom);
5976
    };
5977
    const getFirst = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.itemClass).bind(e => component.getSystem().getByDom(e).toOptional());
5978
    const getLast = (component, hConfig, _hState) => {
5979
      const items = descendants(component.element, '.' + hConfig.itemClass);
5980
      const last = items.length > 0 ? Optional.some(items[items.length - 1]) : Optional.none();
5981
      return last.bind(c => component.getSystem().getByDom(c).toOptional());
5982
    };
5983
    const getDelta$2 = (component, hConfig, hState, delta) => {
5984
      const items = descendants(component.element, '.' + hConfig.itemClass);
5985
      const current = findIndex$1(items, item => has(item, hConfig.highlightClass));
5986
      return current.bind(selected => {
5987
        const dest = cycleBy(selected, delta, 0, items.length - 1);
5988
        return component.getSystem().getByDom(items[dest]).toOptional();
5989
      });
5990
    };
5991
    const getPrevious = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, -1);
5992
    const getNext = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, +1);
5993
    const getCandidates = (component, hConfig, _hState) => {
5994
      const items = descendants(component.element, '.' + hConfig.itemClass);
5995
      return cat(map$2(items, i => component.getSystem().getByDom(i).toOptional()));
5996
    };
5997
 
5998
    var HighlightApis = /*#__PURE__*/Object.freeze({
5999
        __proto__: null,
6000
        dehighlightAll: dehighlightAll,
6001
        dehighlight: dehighlight,
6002
        highlight: highlight,
6003
        highlightFirst: highlightFirst,
6004
        highlightLast: highlightLast,
6005
        highlightAt: highlightAt,
6006
        highlightBy: highlightBy,
6007
        isHighlighted: isHighlighted,
6008
        getHighlighted: getHighlighted,
6009
        getFirst: getFirst,
6010
        getLast: getLast,
6011
        getPrevious: getPrevious,
6012
        getNext: getNext,
6013
        getCandidates: getCandidates
6014
    });
6015
 
6016
    var HighlightSchema = [
6017
      required$1('highlightClass'),
6018
      required$1('itemClass'),
6019
      onHandler('onHighlight'),
6020
      onHandler('onDehighlight')
6021
    ];
6022
 
6023
    const Highlighting = create$4({
6024
      fields: HighlightSchema,
6025
      name: 'highlighting',
6026
      apis: HighlightApis
6027
    });
6028
 
6029
    const BACKSPACE = [8];
6030
    const TAB = [9];
6031
    const ENTER = [13];
6032
    const ESCAPE = [27];
6033
    const SPACE = [32];
6034
    const LEFT = [37];
6035
    const UP = [38];
6036
    const RIGHT = [39];
6037
    const DOWN = [40];
6038
 
6039
    const cyclePrev = (values, index, predicate) => {
6040
      const before = reverse(values.slice(0, index));
6041
      const after = reverse(values.slice(index + 1));
6042
      return find$5(before.concat(after), predicate);
6043
    };
6044
    const tryPrev = (values, index, predicate) => {
6045
      const before = reverse(values.slice(0, index));
6046
      return find$5(before, predicate);
6047
    };
6048
    const cycleNext = (values, index, predicate) => {
6049
      const before = values.slice(0, index);
6050
      const after = values.slice(index + 1);
6051
      return find$5(after.concat(before), predicate);
6052
    };
6053
    const tryNext = (values, index, predicate) => {
6054
      const after = values.slice(index + 1);
6055
      return find$5(after, predicate);
6056
    };
6057
 
6058
    const inSet = keys => event => {
6059
      const raw = event.raw;
6060
      return contains$2(keys, raw.which);
6061
    };
6062
    const and = preds => event => forall(preds, pred => pred(event));
6063
    const isShift$1 = event => {
6064
      const raw = event.raw;
6065
      return raw.shiftKey === true;
6066
    };
6067
    const isControl = event => {
6068
      const raw = event.raw;
6069
      return raw.ctrlKey === true;
6070
    };
6071
    const isNotShift = not(isShift$1);
6072
 
6073
    const rule = (matches, action) => ({
6074
      matches,
6075
      classification: action
6076
    });
6077
    const choose = (transitions, event) => {
6078
      const transition = find$5(transitions, t => t.matches(event));
6079
      return transition.map(t => t.classification);
6080
    };
6081
 
6082
    const reportFocusShifting = (component, prevFocus, newFocus) => {
6083
      const noChange = prevFocus.exists(p => newFocus.exists(n => eq(n, p)));
6084
      if (!noChange) {
6085
        emitWith(component, focusShifted(), {
6086
          prevFocus,
6087
          newFocus
6088
        });
6089
      }
6090
    };
6091
    const dom$2 = () => {
6092
      const get = component => search(component.element);
6093
      const set = (component, focusee) => {
6094
        const prevFocus = get(component);
6095
        component.getSystem().triggerFocus(focusee, component.element);
6096
        const newFocus = get(component);
6097
        reportFocusShifting(component, prevFocus, newFocus);
6098
      };
6099
      return {
6100
        get,
6101
        set
6102
      };
6103
    };
6104
    const highlights = () => {
6105
      const get = component => Highlighting.getHighlighted(component).map(item => item.element);
6106
      const set = (component, element) => {
6107
        const prevFocus = get(component);
6108
        component.getSystem().getByDom(element).fold(noop, item => {
6109
          Highlighting.highlight(component, item);
6110
        });
6111
        const newFocus = get(component);
6112
        reportFocusShifting(component, prevFocus, newFocus);
6113
      };
6114
      return {
6115
        get,
6116
        set
6117
      };
6118
    };
6119
 
6120
    var FocusInsideModes;
6121
    (function (FocusInsideModes) {
6122
      FocusInsideModes['OnFocusMode'] = 'onFocus';
6123
      FocusInsideModes['OnEnterOrSpaceMode'] = 'onEnterOrSpace';
6124
      FocusInsideModes['OnApiMode'] = 'onApi';
6125
    }(FocusInsideModes || (FocusInsideModes = {})));
6126
 
6127
    const typical = (infoSchema, stateInit, getKeydownRules, getKeyupRules, optFocusIn) => {
6128
      const schema = () => infoSchema.concat([
6129
        defaulted('focusManager', dom$2()),
6130
        defaultedOf('focusInside', 'onFocus', valueOf(val => contains$2([
6131
          'onFocus',
6132
          'onEnterOrSpace',
6133
          'onApi'
6134
        ], val) ? Result.value(val) : Result.error('Invalid value for focusInside'))),
6135
        output$1('handler', me),
6136
        output$1('state', stateInit),
6137
        output$1('sendFocusIn', optFocusIn)
6138
      ]);
6139
      const processKey = (component, simulatedEvent, getRules, keyingConfig, keyingState) => {
6140
        const rules = getRules(component, simulatedEvent, keyingConfig, keyingState);
6141
        return choose(rules, simulatedEvent.event).bind(rule => rule(component, simulatedEvent, keyingConfig, keyingState));
6142
      };
6143
      const toEvents = (keyingConfig, keyingState) => {
6144
        const onFocusHandler = keyingConfig.focusInside !== FocusInsideModes.OnFocusMode ? Optional.none() : optFocusIn(keyingConfig).map(focusIn => run$1(focus$4(), (component, simulatedEvent) => {
6145
          focusIn(component, keyingConfig, keyingState);
6146
          simulatedEvent.stop();
6147
        }));
6148
        const tryGoInsideComponent = (component, simulatedEvent) => {
6149
          const isEnterOrSpace = inSet(SPACE.concat(ENTER))(simulatedEvent.event);
6150
          if (keyingConfig.focusInside === FocusInsideModes.OnEnterOrSpaceMode && isEnterOrSpace && isSource(component, simulatedEvent)) {
6151
            optFocusIn(keyingConfig).each(focusIn => {
6152
              focusIn(component, keyingConfig, keyingState);
6153
              simulatedEvent.stop();
6154
            });
6155
          }
6156
        };
6157
        const keyboardEvents = [
6158
          run$1(keydown(), (component, simulatedEvent) => {
6159
            processKey(component, simulatedEvent, getKeydownRules, keyingConfig, keyingState).fold(() => {
6160
              tryGoInsideComponent(component, simulatedEvent);
6161
            }, _ => {
6162
              simulatedEvent.stop();
6163
            });
6164
          }),
6165
          run$1(keyup(), (component, simulatedEvent) => {
6166
            processKey(component, simulatedEvent, getKeyupRules, keyingConfig, keyingState).each(_ => {
6167
              simulatedEvent.stop();
6168
            });
6169
          })
6170
        ];
6171
        return derive$2(onFocusHandler.toArray().concat(keyboardEvents));
6172
      };
6173
      const me = {
6174
        schema,
6175
        processKey,
6176
        toEvents
6177
      };
6178
      return me;
6179
    };
6180
 
6181
    const create$2 = cyclicField => {
6182
      const schema = [
6183
        option$3('onEscape'),
6184
        option$3('onEnter'),
6185
        defaulted('selector', '[data-alloy-tabstop="true"]:not(:disabled)'),
6186
        defaulted('firstTabstop', 0),
6187
        defaulted('useTabstopAt', always),
6188
        option$3('visibilitySelector')
6189
      ].concat([cyclicField]);
6190
      const isVisible = (tabbingConfig, element) => {
6191
        const target = tabbingConfig.visibilitySelector.bind(sel => closest$1(element, sel)).getOr(element);
6192
        return get$d(target) > 0;
6193
      };
6194
      const findInitial = (component, tabbingConfig) => {
6195
        const tabstops = descendants(component.element, tabbingConfig.selector);
6196
        const visibles = filter$2(tabstops, elem => isVisible(tabbingConfig, elem));
6197
        return Optional.from(visibles[tabbingConfig.firstTabstop]);
6198
      };
6199
      const findCurrent = (component, tabbingConfig) => tabbingConfig.focusManager.get(component).bind(elem => closest$1(elem, tabbingConfig.selector));
6200
      const isTabstop = (tabbingConfig, element) => isVisible(tabbingConfig, element) && tabbingConfig.useTabstopAt(element);
6201
      const focusIn = (component, tabbingConfig, _tabbingState) => {
6202
        findInitial(component, tabbingConfig).each(target => {
6203
          tabbingConfig.focusManager.set(component, target);
6204
        });
6205
      };
6206
      const goFromTabstop = (component, tabstops, stopIndex, tabbingConfig, cycle) => cycle(tabstops, stopIndex, elem => isTabstop(tabbingConfig, elem)).fold(() => tabbingConfig.cyclic ? Optional.some(true) : Optional.none(), target => {
6207
        tabbingConfig.focusManager.set(component, target);
6208
        return Optional.some(true);
6209
      });
6210
      const go = (component, _simulatedEvent, tabbingConfig, cycle) => {
6211
        const tabstops = descendants(component.element, tabbingConfig.selector);
6212
        return findCurrent(component, tabbingConfig).bind(tabstop => {
6213
          const optStopIndex = findIndex$1(tabstops, curry(eq, tabstop));
6214
          return optStopIndex.bind(stopIndex => goFromTabstop(component, tabstops, stopIndex, tabbingConfig, cycle));
6215
        });
6216
      };
6217
      const goBackwards = (component, simulatedEvent, tabbingConfig) => {
6218
        const navigate = tabbingConfig.cyclic ? cyclePrev : tryPrev;
6219
        return go(component, simulatedEvent, tabbingConfig, navigate);
6220
      };
6221
      const goForwards = (component, simulatedEvent, tabbingConfig) => {
6222
        const navigate = tabbingConfig.cyclic ? cycleNext : tryNext;
6223
        return go(component, simulatedEvent, tabbingConfig, navigate);
6224
      };
6225
      const isFirstChild = elem => parentNode(elem).bind(firstChild).exists(child => eq(child, elem));
6226
      const goFromPseudoTabstop = (component, simulatedEvent, tabbingConfig) => findCurrent(component, tabbingConfig).filter(elem => !tabbingConfig.useTabstopAt(elem)).bind(elem => (isFirstChild(elem) ? goBackwards : goForwards)(component, simulatedEvent, tabbingConfig));
6227
      const execute = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEnter.bind(f => f(component, simulatedEvent));
6228
      const exit = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEscape.bind(f => f(component, simulatedEvent));
6229
      const getKeydownRules = constant$1([
6230
        rule(and([
6231
          isShift$1,
6232
          inSet(TAB)
6233
        ]), goBackwards),
6234
        rule(inSet(TAB), goForwards),
6235
        rule(and([
6236
          isNotShift,
6237
          inSet(ENTER)
6238
        ]), execute)
6239
      ]);
6240
      const getKeyupRules = constant$1([
6241
        rule(inSet(ESCAPE), exit),
6242
        rule(inSet(TAB), goFromPseudoTabstop)
6243
      ]);
6244
      return typical(schema, NoState.init, getKeydownRules, getKeyupRules, () => Optional.some(focusIn));
6245
    };
6246
 
6247
    var AcyclicType = create$2(customField('cyclic', never));
6248
 
6249
    var CyclicType = create$2(customField('cyclic', always));
6250
 
6251
    const doDefaultExecute = (component, _simulatedEvent, focused) => {
6252
      dispatch(component, focused, execute$5());
6253
      return Optional.some(true);
6254
    };
6255
    const defaultExecute = (component, simulatedEvent, focused) => {
6256
      const isComplex = inside(focused) && inSet(SPACE)(simulatedEvent.event);
6257
      return isComplex ? Optional.none() : doDefaultExecute(component, simulatedEvent, focused);
6258
    };
6259
    const stopEventForFirefox = (_component, _simulatedEvent) => Optional.some(true);
6260
 
6261
    const schema$v = [
6262
      defaulted('execute', defaultExecute),
6263
      defaulted('useSpace', false),
6264
      defaulted('useEnter', true),
6265
      defaulted('useControlEnter', false),
6266
      defaulted('useDown', false)
6267
    ];
6268
    const execute$4 = (component, simulatedEvent, executeConfig) => executeConfig.execute(component, simulatedEvent, component.element);
6269
    const getKeydownRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => {
6270
      const spaceExec = executeConfig.useSpace && !inside(component.element) ? SPACE : [];
6271
      const enterExec = executeConfig.useEnter ? ENTER : [];
6272
      const downExec = executeConfig.useDown ? DOWN : [];
6273
      const execKeys = spaceExec.concat(enterExec).concat(downExec);
6274
      return [rule(inSet(execKeys), execute$4)].concat(executeConfig.useControlEnter ? [rule(and([
6275
          isControl,
6276
          inSet(ENTER)
6277
        ]), execute$4)] : []);
6278
    };
6279
    const getKeyupRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => executeConfig.useSpace && !inside(component.element) ? [rule(inSet(SPACE), stopEventForFirefox)] : [];
6280
    var ExecutionType = typical(schema$v, NoState.init, getKeydownRules$5, getKeyupRules$5, () => Optional.none());
6281
 
6282
    const flatgrid$1 = () => {
6283
      const dimensions = value$2();
6284
      const setGridSize = (numRows, numColumns) => {
6285
        dimensions.set({
6286
          numRows,
6287
          numColumns
6288
        });
6289
      };
6290
      const getNumRows = () => dimensions.get().map(d => d.numRows);
6291
      const getNumColumns = () => dimensions.get().map(d => d.numColumns);
6292
      return nu$8({
6293
        readState: () => dimensions.get().map(d => ({
6294
          numRows: String(d.numRows),
6295
          numColumns: String(d.numColumns)
6296
        })).getOr({
6297
          numRows: '?',
6298
          numColumns: '?'
6299
        }),
6300
        setGridSize,
6301
        getNumRows,
6302
        getNumColumns
6303
      });
6304
    };
6305
    const init$d = spec => spec.state(spec);
6306
 
6307
    var KeyingState = /*#__PURE__*/Object.freeze({
6308
        __proto__: null,
6309
        flatgrid: flatgrid$1,
6310
        init: init$d
6311
    });
6312
 
6313
    const useH = movement => (component, simulatedEvent, config, state) => {
6314
      const move = movement(component.element);
6315
      return use(move, component, simulatedEvent, config, state);
6316
    };
6317
    const west$1 = (moveLeft, moveRight) => {
6318
      const movement = onDirection(moveLeft, moveRight);
6319
      return useH(movement);
6320
    };
6321
    const east$1 = (moveLeft, moveRight) => {
6322
      const movement = onDirection(moveRight, moveLeft);
6323
      return useH(movement);
6324
    };
6325
    const useV = move => (component, simulatedEvent, config, state) => use(move, component, simulatedEvent, config, state);
6326
    const use = (move, component, simulatedEvent, config, state) => {
6327
      const outcome = config.focusManager.get(component).bind(focused => move(component.element, focused, config, state));
6328
      return outcome.map(newFocus => {
6329
        config.focusManager.set(component, newFocus);
6330
        return true;
6331
      });
6332
    };
6333
    const north$1 = useV;
6334
    const south$1 = useV;
6335
    const move$1 = useV;
6336
 
6337
    const isHidden$1 = dom => dom.offsetWidth <= 0 && dom.offsetHeight <= 0;
6338
    const isVisible = element => !isHidden$1(element.dom);
6339
 
6340
    const locate = (candidates, predicate) => findIndex$1(candidates, predicate).map(index => ({
6341
      index,
6342
      candidates
6343
    }));
6344
 
6345
    const locateVisible = (container, current, selector) => {
6346
      const predicate = x => eq(x, current);
6347
      const candidates = descendants(container, selector);
6348
      const visible = filter$2(candidates, isVisible);
6349
      return locate(visible, predicate);
6350
    };
6351
    const findIndex = (elements, target) => findIndex$1(elements, elem => eq(target, elem));
6352
 
6353
    const withGrid = (values, index, numCols, f) => {
6354
      const oldRow = Math.floor(index / numCols);
6355
      const oldColumn = index % numCols;
6356
      return f(oldRow, oldColumn).bind(address => {
6357
        const newIndex = address.row * numCols + address.column;
6358
        return newIndex >= 0 && newIndex < values.length ? Optional.some(values[newIndex]) : Optional.none();
6359
      });
6360
    };
6361
    const cycleHorizontal$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
6362
      const onLastRow = oldRow === numRows - 1;
6363
      const colsInRow = onLastRow ? values.length - oldRow * numCols : numCols;
6364
      const newColumn = cycleBy(oldColumn, delta, 0, colsInRow - 1);
6365
      return Optional.some({
6366
        row: oldRow,
6367
        column: newColumn
6368
      });
6369
    });
6370
    const cycleVertical$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
6371
      const newRow = cycleBy(oldRow, delta, 0, numRows - 1);
6372
      const onLastRow = newRow === numRows - 1;
6373
      const colsInRow = onLastRow ? values.length - newRow * numCols : numCols;
6374
      const newCol = clamp(oldColumn, 0, colsInRow - 1);
6375
      return Optional.some({
6376
        row: newRow,
6377
        column: newCol
6378
      });
6379
    });
6380
    const cycleRight$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, +1);
6381
    const cycleLeft$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, -1);
6382
    const cycleUp$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, -1);
6383
    const cycleDown$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, +1);
6384
 
6385
    const schema$u = [
6386
      required$1('selector'),
6387
      defaulted('execute', defaultExecute),
6388
      onKeyboardHandler('onEscape'),
6389
      defaulted('captureTab', false),
6390
      initSize()
6391
    ];
6392
    const focusIn$3 = (component, gridConfig, _gridState) => {
6393
      descendant(component.element, gridConfig.selector).each(first => {
6394
        gridConfig.focusManager.set(component, first);
6395
      });
6396
    };
6397
    const findCurrent$1 = (component, gridConfig) => gridConfig.focusManager.get(component).bind(elem => closest$1(elem, gridConfig.selector));
6398
    const execute$3 = (component, simulatedEvent, gridConfig, _gridState) => findCurrent$1(component, gridConfig).bind(focused => gridConfig.execute(component, simulatedEvent, focused));
6399
    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)));
6400
    const handleTab = (_component, _simulatedEvent, gridConfig) => gridConfig.captureTab ? Optional.some(true) : Optional.none();
6401
    const doEscape$1 = (component, simulatedEvent, gridConfig) => gridConfig.onEscape(component, simulatedEvent);
6402
    const moveLeft$3 = doMove$2(cycleLeft$1);
6403
    const moveRight$3 = doMove$2(cycleRight$1);
6404
    const moveNorth$1 = doMove$2(cycleUp$1);
6405
    const moveSouth$1 = doMove$2(cycleDown$1);
6406
    const getKeydownRules$4 = constant$1([
6407
      rule(inSet(LEFT), west$1(moveLeft$3, moveRight$3)),
6408
      rule(inSet(RIGHT), east$1(moveLeft$3, moveRight$3)),
6409
      rule(inSet(UP), north$1(moveNorth$1)),
6410
      rule(inSet(DOWN), south$1(moveSouth$1)),
6411
      rule(and([
6412
        isShift$1,
6413
        inSet(TAB)
6414
      ]), handleTab),
6415
      rule(and([
6416
        isNotShift,
6417
        inSet(TAB)
6418
      ]), handleTab),
6419
      rule(inSet(SPACE.concat(ENTER)), execute$3)
6420
    ]);
6421
    const getKeyupRules$4 = constant$1([
6422
      rule(inSet(ESCAPE), doEscape$1),
6423
      rule(inSet(SPACE), stopEventForFirefox)
6424
    ]);
6425
    var FlatgridType = typical(schema$u, flatgrid$1, getKeydownRules$4, getKeyupRules$4, () => Optional.some(focusIn$3));
6426
 
6427
    const f = (container, selector, current, delta, getNewIndex) => {
6428
      const isDisabledButton = candidate => name$3(candidate) === 'button' && get$f(candidate, 'disabled') === 'disabled';
6429
      const tryNewIndex = (initial, index, candidates) => getNewIndex(initial, index, delta, 0, candidates.length - 1, candidates[index], newIndex => isDisabledButton(candidates[newIndex]) ? tryNewIndex(initial, newIndex, candidates) : Optional.from(candidates[newIndex]));
6430
      return locateVisible(container, current, selector).bind(identified => {
6431
        const index = identified.index;
6432
        const candidates = identified.candidates;
6433
        return tryNewIndex(index, index, candidates);
6434
      });
6435
    };
6436
    const horizontalWithoutCycles = (container, selector, current, delta) => f(container, selector, current, delta, (prevIndex, v, d, min, max, oldCandidate, onNewIndex) => {
6437
      const newIndex = clamp(v + d, min, max);
6438
      return newIndex === prevIndex ? Optional.from(oldCandidate) : onNewIndex(newIndex);
6439
    });
6440
    const horizontal = (container, selector, current, delta) => f(container, selector, current, delta, (prevIndex, v, d, min, max, _oldCandidate, onNewIndex) => {
6441
      const newIndex = cycleBy(v, d, min, max);
6442
      return newIndex === prevIndex ? Optional.none() : onNewIndex(newIndex);
6443
    });
6444
 
6445
    const schema$t = [
6446
      required$1('selector'),
6447
      defaulted('getInitial', Optional.none),
6448
      defaulted('execute', defaultExecute),
6449
      onKeyboardHandler('onEscape'),
6450
      defaulted('executeOnMove', false),
6451
      defaulted('allowVertical', true),
6452
      defaulted('allowHorizontal', true),
6453
      defaulted('cycles', true)
6454
    ];
6455
    const findCurrent = (component, flowConfig) => flowConfig.focusManager.get(component).bind(elem => closest$1(elem, flowConfig.selector));
6456
    const execute$2 = (component, simulatedEvent, flowConfig) => findCurrent(component, flowConfig).bind(focused => flowConfig.execute(component, simulatedEvent, focused));
6457
    const focusIn$2 = (component, flowConfig, _state) => {
6458
      flowConfig.getInitial(component).orThunk(() => descendant(component.element, flowConfig.selector)).each(first => {
6459
        flowConfig.focusManager.set(component, first);
6460
      });
6461
    };
6462
    const moveLeft$2 = (element, focused, info) => (info.cycles ? horizontal : horizontalWithoutCycles)(element, info.selector, focused, -1);
6463
    const moveRight$2 = (element, focused, info) => (info.cycles ? horizontal : horizontalWithoutCycles)(element, info.selector, focused, +1);
6464
    const doMove$1 = movement => (component, simulatedEvent, flowConfig, flowState) => movement(component, simulatedEvent, flowConfig, flowState).bind(() => flowConfig.executeOnMove ? execute$2(component, simulatedEvent, flowConfig) : Optional.some(true));
6465
    const doEscape = (component, simulatedEvent, flowConfig) => flowConfig.onEscape(component, simulatedEvent);
6466
    const getKeydownRules$3 = (_component, _se, flowConfig, _flowState) => {
6467
      const westMovers = [...flowConfig.allowHorizontal ? LEFT : []].concat(flowConfig.allowVertical ? UP : []);
6468
      const eastMovers = [...flowConfig.allowHorizontal ? RIGHT : []].concat(flowConfig.allowVertical ? DOWN : []);
6469
      return [
6470
        rule(inSet(westMovers), doMove$1(west$1(moveLeft$2, moveRight$2))),
6471
        rule(inSet(eastMovers), doMove$1(east$1(moveLeft$2, moveRight$2))),
6472
        rule(inSet(ENTER), execute$2),
6473
        rule(inSet(SPACE), execute$2)
6474
      ];
6475
    };
6476
    const getKeyupRules$3 = constant$1([
6477
      rule(inSet(SPACE), stopEventForFirefox),
6478
      rule(inSet(ESCAPE), doEscape)
6479
    ]);
6480
    var FlowType = typical(schema$t, NoState.init, getKeydownRules$3, getKeyupRules$3, () => Optional.some(focusIn$2));
6481
 
6482
    const toCell = (matrix, rowIndex, columnIndex) => Optional.from(matrix[rowIndex]).bind(row => Optional.from(row[columnIndex]).map(cell => ({
6483
      rowIndex,
6484
      columnIndex,
6485
      cell
6486
    })));
6487
    const cycleHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
6488
      const row = matrix[rowIndex];
6489
      const colsInRow = row.length;
6490
      const newColIndex = cycleBy(startCol, deltaCol, 0, colsInRow - 1);
6491
      return toCell(matrix, rowIndex, newColIndex);
6492
    };
6493
    const cycleVertical = (matrix, colIndex, startRow, deltaRow) => {
6494
      const nextRowIndex = cycleBy(startRow, deltaRow, 0, matrix.length - 1);
6495
      const colsInNextRow = matrix[nextRowIndex].length;
6496
      const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
6497
      return toCell(matrix, nextRowIndex, nextColIndex);
6498
    };
6499
    const moveHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
6500
      const row = matrix[rowIndex];
6501
      const colsInRow = row.length;
6502
      const newColIndex = clamp(startCol + deltaCol, 0, colsInRow - 1);
6503
      return toCell(matrix, rowIndex, newColIndex);
6504
    };
6505
    const moveVertical = (matrix, colIndex, startRow, deltaRow) => {
6506
      const nextRowIndex = clamp(startRow + deltaRow, 0, matrix.length - 1);
6507
      const colsInNextRow = matrix[nextRowIndex].length;
6508
      const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
6509
      return toCell(matrix, nextRowIndex, nextColIndex);
6510
    };
6511
    const cycleRight = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, +1);
6512
    const cycleLeft = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, -1);
6513
    const cycleUp = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, -1);
6514
    const cycleDown = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, +1);
6515
    const moveLeft$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, -1);
6516
    const moveRight$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, +1);
6517
    const moveUp$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, -1);
6518
    const moveDown$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, +1);
6519
 
6520
    const schema$s = [
6521
      requiredObjOf('selectors', [
6522
        required$1('row'),
6523
        required$1('cell')
6524
      ]),
6525
      defaulted('cycles', true),
6526
      defaulted('previousSelector', Optional.none),
6527
      defaulted('execute', defaultExecute)
6528
    ];
6529
    const focusIn$1 = (component, matrixConfig, _state) => {
6530
      const focused = matrixConfig.previousSelector(component).orThunk(() => {
6531
        const selectors = matrixConfig.selectors;
6532
        return descendant(component.element, selectors.cell);
6533
      });
6534
      focused.each(cell => {
6535
        matrixConfig.focusManager.set(component, cell);
6536
      });
6537
    };
6538
    const execute$1 = (component, simulatedEvent, matrixConfig) => search(component.element).bind(focused => matrixConfig.execute(component, simulatedEvent, focused));
6539
    const toMatrix = (rows, matrixConfig) => map$2(rows, row => descendants(row, matrixConfig.selectors.cell));
6540
    const doMove = (ifCycle, ifMove) => (element, focused, matrixConfig) => {
6541
      const move = matrixConfig.cycles ? ifCycle : ifMove;
6542
      return closest$1(focused, matrixConfig.selectors.row).bind(inRow => {
6543
        const cellsInRow = descendants(inRow, matrixConfig.selectors.cell);
6544
        return findIndex(cellsInRow, focused).bind(colIndex => {
6545
          const allRows = descendants(element, matrixConfig.selectors.row);
6546
          return findIndex(allRows, inRow).bind(rowIndex => {
6547
            const matrix = toMatrix(allRows, matrixConfig);
6548
            return move(matrix, rowIndex, colIndex).map(next => next.cell);
6549
          });
6550
        });
6551
      });
6552
    };
6553
    const moveLeft = doMove(cycleLeft, moveLeft$1);
6554
    const moveRight = doMove(cycleRight, moveRight$1);
6555
    const moveNorth = doMove(cycleUp, moveUp$1);
6556
    const moveSouth = doMove(cycleDown, moveDown$1);
6557
    const getKeydownRules$2 = constant$1([
6558
      rule(inSet(LEFT), west$1(moveLeft, moveRight)),
6559
      rule(inSet(RIGHT), east$1(moveLeft, moveRight)),
6560
      rule(inSet(UP), north$1(moveNorth)),
6561
      rule(inSet(DOWN), south$1(moveSouth)),
6562
      rule(inSet(SPACE.concat(ENTER)), execute$1)
6563
    ]);
6564
    const getKeyupRules$2 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
6565
    var MatrixType = typical(schema$s, NoState.init, getKeydownRules$2, getKeyupRules$2, () => Optional.some(focusIn$1));
6566
 
6567
    const schema$r = [
6568
      required$1('selector'),
6569
      defaulted('execute', defaultExecute),
6570
      defaulted('moveOnTab', false)
6571
    ];
6572
    const execute = (component, simulatedEvent, menuConfig) => menuConfig.focusManager.get(component).bind(focused => menuConfig.execute(component, simulatedEvent, focused));
6573
    const focusIn = (component, menuConfig, _state) => {
6574
      descendant(component.element, menuConfig.selector).each(first => {
6575
        menuConfig.focusManager.set(component, first);
6576
      });
6577
    };
6578
    const moveUp = (element, focused, info) => horizontal(element, info.selector, focused, -1);
6579
    const moveDown = (element, focused, info) => horizontal(element, info.selector, focused, +1);
6580
    const fireShiftTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveUp)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
6581
    const fireTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveDown)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
6582
    const getKeydownRules$1 = constant$1([
6583
      rule(inSet(UP), move$1(moveUp)),
6584
      rule(inSet(DOWN), move$1(moveDown)),
6585
      rule(and([
6586
        isShift$1,
6587
        inSet(TAB)
6588
      ]), fireShiftTab),
6589
      rule(and([
6590
        isNotShift,
6591
        inSet(TAB)
6592
      ]), fireTab),
6593
      rule(inSet(ENTER), execute),
6594
      rule(inSet(SPACE), execute)
6595
    ]);
6596
    const getKeyupRules$1 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
6597
    var MenuType = typical(schema$r, NoState.init, getKeydownRules$1, getKeyupRules$1, () => Optional.some(focusIn));
6598
 
6599
    const schema$q = [
6600
      onKeyboardHandler('onSpace'),
6601
      onKeyboardHandler('onEnter'),
6602
      onKeyboardHandler('onShiftEnter'),
6603
      onKeyboardHandler('onLeft'),
6604
      onKeyboardHandler('onRight'),
6605
      onKeyboardHandler('onTab'),
6606
      onKeyboardHandler('onShiftTab'),
6607
      onKeyboardHandler('onUp'),
6608
      onKeyboardHandler('onDown'),
6609
      onKeyboardHandler('onEscape'),
6610
      defaulted('stopSpaceKeyup', false),
6611
      option$3('focusIn')
6612
    ];
6613
    const getKeydownRules = (component, simulatedEvent, specialInfo) => [
6614
      rule(inSet(SPACE), specialInfo.onSpace),
6615
      rule(and([
6616
        isNotShift,
6617
        inSet(ENTER)
6618
      ]), specialInfo.onEnter),
6619
      rule(and([
6620
        isShift$1,
6621
        inSet(ENTER)
6622
      ]), specialInfo.onShiftEnter),
6623
      rule(and([
6624
        isShift$1,
6625
        inSet(TAB)
6626
      ]), specialInfo.onShiftTab),
6627
      rule(and([
6628
        isNotShift,
6629
        inSet(TAB)
6630
      ]), specialInfo.onTab),
6631
      rule(inSet(UP), specialInfo.onUp),
6632
      rule(inSet(DOWN), specialInfo.onDown),
6633
      rule(inSet(LEFT), specialInfo.onLeft),
6634
      rule(inSet(RIGHT), specialInfo.onRight),
6635
      rule(inSet(SPACE), specialInfo.onSpace)
6636
    ];
6637
    const getKeyupRules = (component, simulatedEvent, specialInfo) => [
6638
      ...specialInfo.stopSpaceKeyup ? [rule(inSet(SPACE), stopEventForFirefox)] : [],
6639
      rule(inSet(ESCAPE), specialInfo.onEscape)
6640
    ];
6641
    var SpecialType = typical(schema$q, NoState.init, getKeydownRules, getKeyupRules, specialInfo => specialInfo.focusIn);
6642
 
6643
    const acyclic = AcyclicType.schema();
6644
    const cyclic = CyclicType.schema();
6645
    const flow = FlowType.schema();
6646
    const flatgrid = FlatgridType.schema();
6647
    const matrix = MatrixType.schema();
6648
    const execution = ExecutionType.schema();
6649
    const menu = MenuType.schema();
6650
    const special = SpecialType.schema();
6651
 
6652
    var KeyboardBranches = /*#__PURE__*/Object.freeze({
6653
        __proto__: null,
6654
        acyclic: acyclic,
6655
        cyclic: cyclic,
6656
        flow: flow,
6657
        flatgrid: flatgrid,
6658
        matrix: matrix,
6659
        execution: execution,
6660
        menu: menu,
6661
        special: special
6662
    });
6663
 
6664
    const isFlatgridState = keyState => hasNonNullableKey(keyState, 'setGridSize');
6665
    const Keying = createModes({
6666
      branchKey: 'mode',
6667
      branches: KeyboardBranches,
6668
      name: 'keying',
6669
      active: {
6670
        events: (keyingConfig, keyingState) => {
6671
          const handler = keyingConfig.handler;
6672
          return handler.toEvents(keyingConfig, keyingState);
6673
        }
6674
      },
6675
      apis: {
6676
        focusIn: (component, keyConfig, keyState) => {
6677
          keyConfig.sendFocusIn(keyConfig).fold(() => {
6678
            component.getSystem().triggerFocus(component.element, component.element);
6679
          }, sendFocusIn => {
6680
            sendFocusIn(component, keyConfig, keyState);
6681
          });
6682
        },
6683
        setGridSize: (component, keyConfig, keyState, numRows, numColumns) => {
6684
          if (!isFlatgridState(keyState)) {
6685
            console.error('Layout does not support setGridSize');
6686
          } else {
6687
            keyState.setGridSize(numRows, numColumns);
6688
          }
6689
        }
6690
      },
6691
      state: KeyingState
6692
    });
6693
 
6694
    const withoutReuse = (parent, data) => {
6695
      preserve$1(() => {
6696
        replaceChildren(parent, data, () => map$2(data, parent.getSystem().build));
6697
      }, parent.element);
6698
    };
6699
    const withReuse = (parent, data) => {
6700
      preserve$1(() => {
6701
        virtualReplaceChildren(parent, data, () => {
6702
          return patchSpecChildren(parent.element, data, parent.getSystem().buildOrPatch);
6703
        });
6704
      }, parent.element);
6705
    };
6706
 
6707
    const virtualReplace = (component, replacee, replaceeIndex, childSpec) => {
6708
      virtualDetach(replacee);
6709
      const child = patchSpecChild(component.element, replaceeIndex, childSpec, component.getSystem().buildOrPatch);
6710
      virtualAttach(component, child);
6711
      component.syncComponents();
6712
    };
6713
    const insert = (component, insertion, childSpec) => {
6714
      const child = component.getSystem().build(childSpec);
6715
      attachWith(component, child, insertion);
6716
    };
6717
    const replace = (component, replacee, replaceeIndex, childSpec) => {
6718
      detach(replacee);
6719
      insert(component, (p, c) => appendAt(p, c, replaceeIndex), childSpec);
6720
    };
6721
    const set$3 = (component, replaceConfig, replaceState, data) => {
6722
      const replacer = replaceConfig.reuseDom ? withReuse : withoutReuse;
6723
      return replacer(component, data);
6724
    };
6725
    const append = (component, replaceConfig, replaceState, appendee) => {
6726
      insert(component, append$2, appendee);
6727
    };
6728
    const prepend = (component, replaceConfig, replaceState, prependee) => {
6729
      insert(component, prepend$1, prependee);
6730
    };
6731
    const remove = (component, replaceConfig, replaceState, removee) => {
6732
      const children = contents(component);
6733
      const foundChild = find$5(children, child => eq(removee.element, child.element));
6734
      foundChild.each(detach);
6735
    };
6736
    const contents = (component, _replaceConfig) => component.components();
6737
    const replaceAt = (component, replaceConfig, replaceState, replaceeIndex, replacer) => {
6738
      const children = contents(component);
6739
      return Optional.from(children[replaceeIndex]).map(replacee => {
6740
        replacer.fold(() => detach(replacee), r => {
6741
          const replacer = replaceConfig.reuseDom ? virtualReplace : replace;
6742
          replacer(component, replacee, replaceeIndex, r);
6743
        });
6744
        return replacee;
6745
      });
6746
    };
6747
    const replaceBy = (component, replaceConfig, replaceState, replaceePred, replacer) => {
6748
      const children = contents(component);
6749
      return findIndex$1(children, replaceePred).bind(replaceeIndex => replaceAt(component, replaceConfig, replaceState, replaceeIndex, replacer));
6750
    };
6751
 
6752
    var ReplaceApis = /*#__PURE__*/Object.freeze({
6753
        __proto__: null,
6754
        append: append,
6755
        prepend: prepend,
6756
        remove: remove,
6757
        replaceAt: replaceAt,
6758
        replaceBy: replaceBy,
6759
        set: set$3,
6760
        contents: contents
6761
    });
6762
 
6763
    const Replacing = create$4({
6764
      fields: [defaultedBoolean('reuseDom', true)],
6765
      name: 'replacing',
6766
      apis: ReplaceApis
6767
    });
6768
 
6769
    const events$d = (name, eventHandlers) => {
6770
      const events = derive$2(eventHandlers);
6771
      return create$4({
6772
        fields: [required$1('enabled')],
6773
        name,
6774
        active: { events: constant$1(events) }
6775
      });
6776
    };
6777
    const config = (name, eventHandlers) => {
6778
      const me = events$d(name, eventHandlers);
6779
      return {
6780
        key: name,
6781
        value: {
6782
          config: {},
6783
          me,
6784
          configAsRaw: constant$1({}),
6785
          initialConfig: {},
6786
          state: NoState
6787
        }
6788
      };
6789
    };
6790
 
6791
    const focus$2 = (component, focusConfig) => {
6792
      if (!focusConfig.ignore) {
6793
        focus$3(component.element);
6794
        focusConfig.onFocus(component);
6795
      }
6796
    };
6797
    const blur = (component, focusConfig) => {
6798
      if (!focusConfig.ignore) {
6799
        blur$1(component.element);
6800
      }
6801
    };
6802
    const isFocused = component => hasFocus(component.element);
6803
 
6804
    var FocusApis = /*#__PURE__*/Object.freeze({
6805
        __proto__: null,
6806
        focus: focus$2,
6807
        blur: blur,
6808
        isFocused: isFocused
6809
    });
6810
 
6811
    const exhibit$4 = (base, focusConfig) => {
6812
      const mod = focusConfig.ignore ? {} : { attributes: { tabindex: '-1' } };
6813
      return nu$7(mod);
6814
    };
6815
    const events$c = focusConfig => derive$2([run$1(focus$4(), (component, simulatedEvent) => {
6816
        focus$2(component, focusConfig);
6817
        simulatedEvent.stop();
6818
      })].concat(focusConfig.stopMousedown ? [run$1(mousedown(), (_, simulatedEvent) => {
6819
        simulatedEvent.event.prevent();
6820
      })] : []));
6821
 
6822
    var ActiveFocus = /*#__PURE__*/Object.freeze({
6823
        __proto__: null,
6824
        exhibit: exhibit$4,
6825
        events: events$c
6826
    });
6827
 
6828
    var FocusSchema = [
6829
      onHandler('onFocus'),
6830
      defaulted('stopMousedown', false),
6831
      defaulted('ignore', false)
6832
    ];
6833
 
6834
    const Focusing = create$4({
6835
      fields: FocusSchema,
6836
      name: 'focusing',
6837
      active: ActiveFocus,
6838
      apis: FocusApis
6839
    });
6840
 
6841
    const SetupBehaviourCellState = initialState => {
6842
      const init = () => {
6843
        const cell = Cell(initialState);
6844
        const get = () => cell.get();
6845
        const set = newState => cell.set(newState);
6846
        const clear = () => cell.set(initialState);
6847
        const readState = () => cell.get();
6848
        return {
6849
          get,
6850
          set,
6851
          clear,
6852
          readState
6853
        };
6854
      };
6855
      return { init };
6856
    };
6857
 
6858
    const updateAriaState = (component, toggleConfig, toggleState) => {
6859
      const ariaInfo = toggleConfig.aria;
6860
      ariaInfo.update(component, ariaInfo, toggleState.get());
6861
    };
6862
    const updateClass = (component, toggleConfig, toggleState) => {
6863
      toggleConfig.toggleClass.each(toggleClass => {
6864
        if (toggleState.get()) {
6865
          add$2(component.element, toggleClass);
6866
        } else {
6867
          remove$2(component.element, toggleClass);
6868
        }
6869
      });
6870
    };
6871
    const set$2 = (component, toggleConfig, toggleState, state) => {
6872
      const initialState = toggleState.get();
6873
      toggleState.set(state);
6874
      updateClass(component, toggleConfig, toggleState);
6875
      updateAriaState(component, toggleConfig, toggleState);
6876
      if (initialState !== state) {
6877
        toggleConfig.onToggled(component, state);
6878
      }
6879
    };
6880
    const toggle$2 = (component, toggleConfig, toggleState) => {
6881
      set$2(component, toggleConfig, toggleState, !toggleState.get());
6882
    };
6883
    const on = (component, toggleConfig, toggleState) => {
6884
      set$2(component, toggleConfig, toggleState, true);
6885
    };
6886
    const off = (component, toggleConfig, toggleState) => {
6887
      set$2(component, toggleConfig, toggleState, false);
6888
    };
6889
    const isOn = (component, toggleConfig, toggleState) => toggleState.get();
6890
    const onLoad = (component, toggleConfig, toggleState) => {
6891
      set$2(component, toggleConfig, toggleState, toggleConfig.selected);
6892
    };
6893
 
6894
    var ToggleApis = /*#__PURE__*/Object.freeze({
6895
        __proto__: null,
6896
        onLoad: onLoad,
6897
        toggle: toggle$2,
6898
        isOn: isOn,
6899
        on: on,
6900
        off: off,
6901
        set: set$2
6902
    });
6903
 
6904
    const exhibit$3 = () => nu$7({});
6905
    const events$b = (toggleConfig, toggleState) => {
6906
      const execute = executeEvent(toggleConfig, toggleState, toggle$2);
6907
      const load = loadEvent(toggleConfig, toggleState, onLoad);
6908
      return derive$2(flatten([
6909
        toggleConfig.toggleOnExecute ? [execute] : [],
6910
        [load]
6911
      ]));
6912
    };
6913
 
6914
    var ActiveToggle = /*#__PURE__*/Object.freeze({
6915
        __proto__: null,
6916
        exhibit: exhibit$3,
6917
        events: events$b
6918
    });
6919
 
6920
    const updatePressed = (component, ariaInfo, status) => {
6921
      set$9(component.element, 'aria-pressed', status);
6922
      if (ariaInfo.syncWithExpanded) {
6923
        updateExpanded(component, ariaInfo, status);
6924
      }
6925
    };
6926
    const updateSelected = (component, ariaInfo, status) => {
6927
      set$9(component.element, 'aria-selected', status);
6928
    };
6929
    const updateChecked = (component, ariaInfo, status) => {
6930
      set$9(component.element, 'aria-checked', status);
6931
    };
6932
    const updateExpanded = (component, ariaInfo, status) => {
6933
      set$9(component.element, 'aria-expanded', status);
6934
    };
6935
 
6936
    var ToggleSchema = [
6937
      defaulted('selected', false),
6938
      option$3('toggleClass'),
6939
      defaulted('toggleOnExecute', true),
6940
      onHandler('onToggled'),
6941
      defaultedOf('aria', { mode: 'none' }, choose$1('mode', {
6942
        pressed: [
6943
          defaulted('syncWithExpanded', false),
6944
          output$1('update', updatePressed)
6945
        ],
6946
        checked: [output$1('update', updateChecked)],
6947
        expanded: [output$1('update', updateExpanded)],
6948
        selected: [output$1('update', updateSelected)],
6949
        none: [output$1('update', noop)]
6950
      }))
6951
    ];
6952
 
6953
    const Toggling = create$4({
6954
      fields: ToggleSchema,
6955
      name: 'toggling',
6956
      active: ActiveToggle,
6957
      apis: ToggleApis,
6958
      state: SetupBehaviourCellState(false)
6959
    });
6960
 
6961
    const pointerEvents = () => {
6962
      const onClick = (component, simulatedEvent) => {
6963
        simulatedEvent.stop();
6964
        emitExecute(component);
6965
      };
6966
      return [
6967
        run$1(click(), onClick),
6968
        run$1(tap(), onClick),
6969
        cutter(touchstart()),
6970
        cutter(mousedown())
6971
      ];
6972
    };
6973
    const events$a = optAction => {
6974
      const executeHandler = action => runOnExecute$1((component, simulatedEvent) => {
6975
        action(component);
6976
        simulatedEvent.stop();
6977
      });
6978
      return derive$2(flatten([
6979
        optAction.map(executeHandler).toArray(),
6980
        pointerEvents()
6981
      ]));
6982
    };
6983
 
6984
    const hoverEvent = 'alloy.item-hover';
6985
    const focusEvent = 'alloy.item-focus';
6986
    const toggledEvent = 'alloy.item-toggled';
6987
    const onHover = item => {
6988
      if (search(item.element).isNone() || Focusing.isFocused(item)) {
6989
        if (!Focusing.isFocused(item)) {
6990
          Focusing.focus(item);
6991
        }
6992
        emitWith(item, hoverEvent, { item });
6993
      }
6994
    };
6995
    const onFocus$1 = item => {
6996
      emitWith(item, focusEvent, { item });
6997
    };
6998
    const onToggled = (item, state) => {
6999
      emitWith(item, toggledEvent, {
7000
        item,
7001
        state
7002
      });
7003
    };
7004
    const hover = constant$1(hoverEvent);
7005
    const focus$1 = constant$1(focusEvent);
7006
    const toggled = constant$1(toggledEvent);
7007
 
7008
    const getItemRole = detail => detail.toggling.map(toggling => toggling.exclusive ? 'menuitemradio' : 'menuitemcheckbox').getOr('menuitem');
7009
    const getTogglingSpec = tConfig => ({
7010
      aria: { mode: 'checked' },
7011
      ...filter$1(tConfig, (_value, name) => name !== 'exclusive'),
7012
      onToggled: (component, state) => {
7013
        if (isFunction(tConfig.onToggled)) {
7014
          tConfig.onToggled(component, state);
7015
        }
7016
        onToggled(component, state);
7017
      }
7018
    });
7019
    const builder$2 = detail => ({
7020
      dom: detail.dom,
7021
      domModification: {
7022
        ...detail.domModification,
7023
        attributes: {
7024
          'role': getItemRole(detail),
7025
          ...detail.domModification.attributes,
7026
          'aria-haspopup': detail.hasSubmenu,
7027
          ...detail.hasSubmenu ? { 'aria-expanded': false } : {}
7028
        }
7029
      },
7030
      behaviours: SketchBehaviours.augment(detail.itemBehaviours, [
7031
        detail.toggling.fold(Toggling.revoke, tConfig => Toggling.config(getTogglingSpec(tConfig))),
7032
        Focusing.config({
7033
          ignore: detail.ignoreFocus,
7034
          stopMousedown: detail.ignoreFocus,
7035
          onFocus: component => {
7036
            onFocus$1(component);
7037
          }
7038
        }),
7039
        Keying.config({ mode: 'execution' }),
7040
        Representing.config({
7041
          store: {
7042
            mode: 'memory',
7043
            initialValue: detail.data
7044
          }
7045
        }),
7046
        config('item-type-events', [
7047
          ...pointerEvents(),
7048
          run$1(mouseover(), onHover),
7049
          run$1(focusItem(), Focusing.focus)
7050
        ])
7051
      ]),
7052
      components: detail.components,
7053
      eventOrder: detail.eventOrder
7054
    });
7055
    const schema$p = [
7056
      required$1('data'),
7057
      required$1('components'),
7058
      required$1('dom'),
7059
      defaulted('hasSubmenu', false),
7060
      option$3('toggling'),
7061
      SketchBehaviours.field('itemBehaviours', [
7062
        Toggling,
7063
        Focusing,
7064
        Keying,
7065
        Representing
7066
      ]),
7067
      defaulted('ignoreFocus', false),
7068
      defaulted('domModification', {}),
7069
      output$1('builder', builder$2),
7070
      defaulted('eventOrder', {})
7071
    ];
7072
 
7073
    const builder$1 = detail => ({
7074
      dom: detail.dom,
7075
      components: detail.components,
7076
      events: derive$2([stopper(focusItem())])
7077
    });
7078
    const schema$o = [
7079
      required$1('dom'),
7080
      required$1('components'),
7081
      output$1('builder', builder$1)
7082
    ];
7083
 
7084
    const owner$2 = constant$1('item-widget');
7085
    const parts$h = constant$1([required({
7086
        name: 'widget',
7087
        overrides: detail => {
7088
          return {
7089
            behaviours: derive$1([Representing.config({
7090
                store: {
7091
                  mode: 'manual',
7092
                  getValue: _component => {
7093
                    return detail.data;
7094
                  },
7095
                  setValue: noop
7096
                }
7097
              })])
7098
          };
7099
        }
7100
      })]);
7101
 
7102
    const builder = detail => {
7103
      const subs = substitutes(owner$2(), detail, parts$h());
7104
      const components = components$1(owner$2(), detail, subs.internals());
7105
      const focusWidget = component => getPart(component, detail, 'widget').map(widget => {
7106
        Keying.focusIn(widget);
7107
        return widget;
7108
      });
7109
      const onHorizontalArrow = (component, simulatedEvent) => inside(simulatedEvent.event.target) ? Optional.none() : (() => {
7110
        if (detail.autofocus) {
7111
          simulatedEvent.setSource(component.element);
7112
          return Optional.none();
7113
        } else {
7114
          return Optional.none();
7115
        }
7116
      })();
7117
      return {
7118
        dom: detail.dom,
7119
        components,
7120
        domModification: detail.domModification,
7121
        events: derive$2([
7122
          runOnExecute$1((component, simulatedEvent) => {
7123
            focusWidget(component).each(_widget => {
7124
              simulatedEvent.stop();
7125
            });
7126
          }),
7127
          run$1(mouseover(), onHover),
7128
          run$1(focusItem(), (component, _simulatedEvent) => {
7129
            if (detail.autofocus) {
7130
              focusWidget(component);
7131
            } else {
7132
              Focusing.focus(component);
7133
            }
7134
          })
7135
        ]),
7136
        behaviours: SketchBehaviours.augment(detail.widgetBehaviours, [
7137
          Representing.config({
7138
            store: {
7139
              mode: 'memory',
7140
              initialValue: detail.data
7141
            }
7142
          }),
7143
          Focusing.config({
7144
            ignore: detail.ignoreFocus,
7145
            onFocus: component => {
7146
              onFocus$1(component);
7147
            }
7148
          }),
7149
          Keying.config({
7150
            mode: 'special',
7151
            focusIn: detail.autofocus ? component => {
7152
              focusWidget(component);
7153
            } : revoke(),
7154
            onLeft: onHorizontalArrow,
7155
            onRight: onHorizontalArrow,
7156
            onEscape: (component, simulatedEvent) => {
7157
              if (!Focusing.isFocused(component) && !detail.autofocus) {
7158
                Focusing.focus(component);
7159
                return Optional.some(true);
7160
              } else if (detail.autofocus) {
7161
                simulatedEvent.setSource(component.element);
7162
                return Optional.none();
7163
              } else {
7164
                return Optional.none();
7165
              }
7166
            }
7167
          })
7168
        ])
7169
      };
7170
    };
7171
    const schema$n = [
7172
      required$1('uid'),
7173
      required$1('data'),
7174
      required$1('components'),
7175
      required$1('dom'),
7176
      defaulted('autofocus', false),
7177
      defaulted('ignoreFocus', false),
7178
      SketchBehaviours.field('widgetBehaviours', [
7179
        Representing,
7180
        Focusing,
7181
        Keying
7182
      ]),
7183
      defaulted('domModification', {}),
7184
      defaultUidsSchema(parts$h()),
7185
      output$1('builder', builder)
7186
    ];
7187
 
7188
    const itemSchema$2 = choose$1('type', {
7189
      widget: schema$n,
7190
      item: schema$p,
7191
      separator: schema$o
7192
    });
7193
    const configureGrid = (detail, movementInfo) => ({
7194
      mode: 'flatgrid',
7195
      selector: '.' + detail.markers.item,
7196
      initSize: {
7197
        numColumns: movementInfo.initSize.numColumns,
7198
        numRows: movementInfo.initSize.numRows
7199
      },
7200
      focusManager: detail.focusManager
7201
    });
7202
    const configureMatrix = (detail, movementInfo) => ({
7203
      mode: 'matrix',
7204
      selectors: {
7205
        row: movementInfo.rowSelector,
7206
        cell: '.' + detail.markers.item
7207
      },
7208
      previousSelector: movementInfo.previousSelector,
7209
      focusManager: detail.focusManager
7210
    });
7211
    const configureMenu = (detail, movementInfo) => ({
7212
      mode: 'menu',
7213
      selector: '.' + detail.markers.item,
7214
      moveOnTab: movementInfo.moveOnTab,
7215
      focusManager: detail.focusManager
7216
    });
7217
    const parts$g = constant$1([group({
7218
        factory: {
7219
          sketch: spec => {
7220
            const itemInfo = asRawOrDie$1('menu.spec item', itemSchema$2, spec);
7221
            return itemInfo.builder(itemInfo);
7222
          }
7223
        },
7224
        name: 'items',
7225
        unit: 'item',
7226
        defaults: (detail, u) => {
7227
          return has$2(u, 'uid') ? u : {
7228
            ...u,
7229
            uid: generate$5('item')
7230
          };
7231
        },
7232
        overrides: (detail, u) => {
7233
          return {
7234
            type: u.type,
7235
            ignoreFocus: detail.fakeFocus,
7236
            domModification: { classes: [detail.markers.item] }
7237
          };
7238
        }
7239
      })]);
7240
    const schema$m = constant$1([
7241
      required$1('value'),
7242
      required$1('items'),
7243
      required$1('dom'),
7244
      required$1('components'),
7245
      defaulted('eventOrder', {}),
7246
      field('menuBehaviours', [
7247
        Highlighting,
7248
        Representing,
7249
        Composing,
7250
        Keying
7251
      ]),
7252
      defaultedOf('movement', {
7253
        mode: 'menu',
7254
        moveOnTab: true
7255
      }, choose$1('mode', {
7256
        grid: [
7257
          initSize(),
7258
          output$1('config', configureGrid)
7259
        ],
7260
        matrix: [
7261
          output$1('config', configureMatrix),
7262
          required$1('rowSelector'),
7263
          defaulted('previousSelector', Optional.none)
7264
        ],
7265
        menu: [
7266
          defaulted('moveOnTab', true),
7267
          output$1('config', configureMenu)
7268
        ]
7269
      })),
7270
      itemMarkers(),
7271
      defaulted('fakeFocus', false),
7272
      defaulted('focusManager', dom$2()),
7273
      onHandler('onHighlight'),
7274
      onHandler('onDehighlight')
7275
    ]);
7276
 
7277
    const focus = constant$1('alloy.menu-focus');
7278
 
7279
    const deselectOtherRadioItems = (menu, item) => {
7280
      const checkedRadioItems = descendants(menu.element, '[role="menuitemradio"][aria-checked="true"]');
7281
      each$1(checkedRadioItems, ele => {
7282
        if (!eq(ele, item.element)) {
7283
          menu.getSystem().getByDom(ele).each(c => {
7284
            Toggling.off(c);
7285
          });
7286
        }
7287
      });
7288
    };
7289
    const make$7 = (detail, components, _spec, _externals) => ({
7290
      uid: detail.uid,
7291
      dom: detail.dom,
7292
      markers: detail.markers,
7293
      behaviours: augment(detail.menuBehaviours, [
7294
        Highlighting.config({
7295
          highlightClass: detail.markers.selectedItem,
7296
          itemClass: detail.markers.item,
7297
          onHighlight: detail.onHighlight,
7298
          onDehighlight: detail.onDehighlight
7299
        }),
7300
        Representing.config({
7301
          store: {
7302
            mode: 'memory',
7303
            initialValue: detail.value
7304
          }
7305
        }),
7306
        Composing.config({ find: Optional.some }),
7307
        Keying.config(detail.movement.config(detail, detail.movement))
7308
      ]),
7309
      events: derive$2([
7310
        run$1(focus$1(), (menu, simulatedEvent) => {
7311
          const event = simulatedEvent.event;
7312
          menu.getSystem().getByDom(event.target).each(item => {
7313
            Highlighting.highlight(menu, item);
7314
            simulatedEvent.stop();
7315
            emitWith(menu, focus(), {
7316
              menu,
7317
              item
7318
            });
7319
          });
7320
        }),
7321
        run$1(hover(), (menu, simulatedEvent) => {
7322
          const item = simulatedEvent.event.item;
7323
          Highlighting.highlight(menu, item);
7324
        }),
7325
        run$1(toggled(), (menu, simulatedEvent) => {
7326
          const {item, state} = simulatedEvent.event;
7327
          if (state && get$f(item.element, 'role') === 'menuitemradio') {
7328
            deselectOtherRadioItems(menu, item);
7329
          }
7330
        })
7331
      ]),
7332
      components,
7333
      eventOrder: detail.eventOrder,
7334
      domModification: { attributes: { role: 'menu' } }
7335
    });
7336
 
7337
    const Menu = composite({
7338
      name: 'Menu',
7339
      configFields: schema$m(),
7340
      partFields: parts$g(),
7341
      factory: make$7
7342
    });
7343
 
7344
    const transpose$1 = obj => tupleMap(obj, (v, k) => ({
7345
      k: v,
7346
      v: k
7347
    }));
7348
    const trace = (items, byItem, byMenu, finish) => get$g(byMenu, finish).bind(triggerItem => get$g(items, triggerItem).bind(triggerMenu => {
7349
      const rest = trace(items, byItem, byMenu, triggerMenu);
7350
      return Optional.some([triggerMenu].concat(rest));
7351
    })).getOr([]);
7352
    const generate$2 = (menus, expansions) => {
7353
      const items = {};
7354
      each(menus, (menuItems, menu) => {
7355
        each$1(menuItems, item => {
7356
          items[item] = menu;
7357
        });
7358
      });
7359
      const byItem = expansions;
7360
      const byMenu = transpose$1(expansions);
7361
      const menuPaths = map$1(byMenu, (_triggerItem, submenu) => [submenu].concat(trace(items, byItem, byMenu, submenu)));
7362
      return map$1(items, menu => get$g(menuPaths, menu).getOr([menu]));
7363
    };
7364
 
7365
    const init$c = () => {
7366
      const expansions = Cell({});
7367
      const menus = Cell({});
7368
      const paths = Cell({});
7369
      const primary = value$2();
7370
      const directory = Cell({});
7371
      const clear = () => {
7372
        expansions.set({});
7373
        menus.set({});
7374
        paths.set({});
7375
        primary.clear();
7376
      };
7377
      const isClear = () => primary.get().isNone();
7378
      const setMenuBuilt = (menuName, built) => {
7379
        menus.set({
7380
          ...menus.get(),
7381
          [menuName]: {
7382
            type: 'prepared',
7383
            menu: built
7384
          }
7385
        });
7386
      };
7387
      const setContents = (sPrimary, sMenus, sExpansions, dir) => {
7388
        primary.set(sPrimary);
7389
        expansions.set(sExpansions);
7390
        menus.set(sMenus);
7391
        directory.set(dir);
7392
        const sPaths = generate$2(dir, sExpansions);
7393
        paths.set(sPaths);
7394
      };
7395
      const getTriggeringItem = menuValue => find$4(expansions.get(), (v, _k) => v === menuValue);
7396
      const getTriggerData = (menuValue, getItemByValue, path) => getPreparedMenu(menuValue).bind(menu => getTriggeringItem(menuValue).bind(triggeringItemValue => getItemByValue(triggeringItemValue).map(triggeredItem => ({
7397
        triggeredMenu: menu,
7398
        triggeringItem: triggeredItem,
7399
        triggeringPath: path
7400
      }))));
7401
      const getTriggeringPath = (itemValue, getItemByValue) => {
7402
        const extraPath = filter$2(lookupItem(itemValue).toArray(), menuValue => getPreparedMenu(menuValue).isSome());
7403
        return get$g(paths.get(), itemValue).bind(path => {
7404
          const revPath = reverse(extraPath.concat(path));
7405
          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)]));
7406
          return sequence(triggers);
7407
        });
7408
      };
7409
      const expand = itemValue => get$g(expansions.get(), itemValue).map(menu => {
7410
        const current = get$g(paths.get(), itemValue).getOr([]);
7411
        return [menu].concat(current);
7412
      });
7413
      const collapse = itemValue => get$g(paths.get(), itemValue).bind(path => path.length > 1 ? Optional.some(path.slice(1)) : Optional.none());
7414
      const refresh = itemValue => get$g(paths.get(), itemValue);
7415
      const getPreparedMenu = menuValue => lookupMenu(menuValue).bind(extractPreparedMenu);
7416
      const lookupMenu = menuValue => get$g(menus.get(), menuValue);
7417
      const lookupItem = itemValue => get$g(expansions.get(), itemValue);
7418
      const otherMenus = path => {
7419
        const menuValues = directory.get();
7420
        return difference(keys(menuValues), path);
7421
      };
7422
      const getPrimary = () => primary.get().bind(getPreparedMenu);
7423
      const getMenus = () => menus.get();
7424
      return {
7425
        setMenuBuilt,
7426
        setContents,
7427
        expand,
7428
        refresh,
7429
        collapse,
7430
        lookupMenu,
7431
        lookupItem,
7432
        otherMenus,
7433
        getPrimary,
7434
        getMenus,
7435
        clear,
7436
        isClear,
7437
        getTriggeringPath
7438
      };
7439
    };
7440
    const extractPreparedMenu = prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none();
7441
    const LayeredState = {
7442
      init: init$c,
7443
      extractPreparedMenu
7444
    };
7445
 
7446
    const onMenuItemHighlightedEvent = generate$6('tiered-menu-item-highlight');
7447
    const onMenuItemDehighlightedEvent = generate$6('tiered-menu-item-dehighlight');
7448
 
7449
    var HighlightOnOpen;
7450
    (function (HighlightOnOpen) {
7451
      HighlightOnOpen[HighlightOnOpen['HighlightMenuAndItem'] = 0] = 'HighlightMenuAndItem';
7452
      HighlightOnOpen[HighlightOnOpen['HighlightJustMenu'] = 1] = 'HighlightJustMenu';
7453
      HighlightOnOpen[HighlightOnOpen['HighlightNone'] = 2] = 'HighlightNone';
7454
    }(HighlightOnOpen || (HighlightOnOpen = {})));
7455
 
7456
    const make$6 = (detail, _rawUiSpec) => {
7457
      const submenuParentItems = value$2();
7458
      const buildMenus = (container, primaryName, menus) => map$1(menus, (spec, name) => {
7459
        const makeSketch = () => Menu.sketch({
7460
          ...spec,
7461
          value: name,
7462
          markers: detail.markers,
7463
          fakeFocus: detail.fakeFocus,
7464
          onHighlight: (menuComp, itemComp) => {
7465
            const highlightData = {
7466
              menuComp,
7467
              itemComp
7468
            };
7469
            emitWith(menuComp, onMenuItemHighlightedEvent, highlightData);
7470
          },
7471
          onDehighlight: (menuComp, itemComp) => {
7472
            const dehighlightData = {
7473
              menuComp,
7474
              itemComp
7475
            };
7476
            emitWith(menuComp, onMenuItemDehighlightedEvent, dehighlightData);
7477
          },
7478
          focusManager: detail.fakeFocus ? highlights() : dom$2()
7479
        });
7480
        return name === primaryName ? {
7481
          type: 'prepared',
7482
          menu: container.getSystem().build(makeSketch())
7483
        } : {
7484
          type: 'notbuilt',
7485
          nbMenu: makeSketch
7486
        };
7487
      });
7488
      const layeredState = LayeredState.init();
7489
      const setup = container => {
7490
        const componentMap = buildMenus(container, detail.data.primary, detail.data.menus);
7491
        const directory = toDirectory();
7492
        layeredState.setContents(detail.data.primary, componentMap, detail.data.expansions, directory);
7493
        return layeredState.getPrimary();
7494
      };
7495
      const getItemValue = item => Representing.getValue(item).value;
7496
      const getItemByValue = (_container, menus, itemValue) => findMap(menus, menu => {
7497
        if (!menu.getSystem().isConnected()) {
7498
          return Optional.none();
7499
        }
7500
        const candidates = Highlighting.getCandidates(menu);
7501
        return find$5(candidates, c => getItemValue(c) === itemValue);
7502
      });
7503
      const toDirectory = _container => map$1(detail.data.menus, (data, _menuName) => bind$3(data.items, item => item.type === 'separator' ? [] : [item.data.value]));
7504
      const setActiveMenu = Highlighting.highlight;
7505
      const setActiveMenuAndItem = (container, menu) => {
7506
        setActiveMenu(container, menu);
7507
        Highlighting.getHighlighted(menu).orThunk(() => Highlighting.getFirst(menu)).each(item => {
7508
          if (detail.fakeFocus) {
7509
            Highlighting.highlight(menu, item);
7510
          } else {
7511
            dispatch(container, item.element, focusItem());
7512
          }
7513
        });
7514
      };
7515
      const getMenus = (state, menuValues) => cat(map$2(menuValues, mv => state.lookupMenu(mv).bind(prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none())));
7516
      const closeOthers = (container, state, path) => {
7517
        const others = getMenus(state, state.otherMenus(path));
7518
        each$1(others, o => {
7519
          remove$1(o.element, [detail.markers.backgroundMenu]);
7520
          if (!detail.stayInDom) {
7521
            Replacing.remove(container, o);
7522
          }
7523
        });
7524
      };
7525
      const getSubmenuParents = container => submenuParentItems.get().getOrThunk(() => {
7526
        const r = {};
7527
        const items = descendants(container.element, `.${ detail.markers.item }`);
7528
        const parentItems = filter$2(items, i => get$f(i, 'aria-haspopup') === 'true');
7529
        each$1(parentItems, i => {
7530
          container.getSystem().getByDom(i).each(itemComp => {
7531
            const key = getItemValue(itemComp);
7532
            r[key] = itemComp;
7533
          });
7534
        });
7535
        submenuParentItems.set(r);
7536
        return r;
7537
      });
7538
      const updateAriaExpansions = (container, path) => {
7539
        const parentItems = getSubmenuParents(container);
7540
        each(parentItems, (v, k) => {
7541
          const expanded = contains$2(path, k);
7542
          set$9(v.element, 'aria-expanded', expanded);
7543
        });
7544
      };
7545
      const updateMenuPath = (container, state, path) => Optional.from(path[0]).bind(latestMenuName => state.lookupMenu(latestMenuName).bind(menuPrep => {
7546
        if (menuPrep.type === 'notbuilt') {
7547
          return Optional.none();
7548
        } else {
7549
          const activeMenu = menuPrep.menu;
7550
          const rest = getMenus(state, path.slice(1));
7551
          each$1(rest, r => {
7552
            add$2(r.element, detail.markers.backgroundMenu);
7553
          });
7554
          if (!inBody(activeMenu.element)) {
7555
            Replacing.append(container, premade(activeMenu));
7556
          }
7557
          remove$1(activeMenu.element, [detail.markers.backgroundMenu]);
7558
          setActiveMenuAndItem(container, activeMenu);
7559
          closeOthers(container, state, path);
7560
          return Optional.some(activeMenu);
7561
        }
7562
      }));
7563
      let ExpandHighlightDecision;
7564
      (function (ExpandHighlightDecision) {
7565
        ExpandHighlightDecision[ExpandHighlightDecision['HighlightSubmenu'] = 0] = 'HighlightSubmenu';
7566
        ExpandHighlightDecision[ExpandHighlightDecision['HighlightParent'] = 1] = 'HighlightParent';
7567
      }(ExpandHighlightDecision || (ExpandHighlightDecision = {})));
7568
      const buildIfRequired = (container, menuName, menuPrep) => {
7569
        if (menuPrep.type === 'notbuilt') {
7570
          const menu = container.getSystem().build(menuPrep.nbMenu());
7571
          layeredState.setMenuBuilt(menuName, menu);
7572
          return menu;
7573
        } else {
7574
          return menuPrep.menu;
7575
        }
7576
      };
7577
      const expandRight = (container, item, decision = ExpandHighlightDecision.HighlightSubmenu) => {
7578
        if (item.hasConfigured(Disabling) && Disabling.isDisabled(item)) {
7579
          return Optional.some(item);
7580
        } else {
7581
          const value = getItemValue(item);
7582
          return layeredState.expand(value).bind(path => {
7583
            updateAriaExpansions(container, path);
7584
            return Optional.from(path[0]).bind(menuName => layeredState.lookupMenu(menuName).bind(activeMenuPrep => {
7585
              const activeMenu = buildIfRequired(container, menuName, activeMenuPrep);
7586
              if (!inBody(activeMenu.element)) {
7587
                Replacing.append(container, premade(activeMenu));
7588
              }
7589
              detail.onOpenSubmenu(container, item, activeMenu, reverse(path));
7590
              if (decision === ExpandHighlightDecision.HighlightSubmenu) {
7591
                Highlighting.highlightFirst(activeMenu);
7592
                return updateMenuPath(container, layeredState, path);
7593
              } else {
7594
                Highlighting.dehighlightAll(activeMenu);
7595
                return Optional.some(item);
7596
              }
7597
            }));
7598
          });
7599
        }
7600
      };
7601
      const collapseLeft = (container, item) => {
7602
        const value = getItemValue(item);
7603
        return layeredState.collapse(value).bind(path => {
7604
          updateAriaExpansions(container, path);
7605
          return updateMenuPath(container, layeredState, path).map(activeMenu => {
7606
            detail.onCollapseMenu(container, item, activeMenu);
7607
            return activeMenu;
7608
          });
7609
        });
7610
      };
7611
      const updateView = (container, item) => {
7612
        const value = getItemValue(item);
7613
        return layeredState.refresh(value).bind(path => {
7614
          updateAriaExpansions(container, path);
7615
          return updateMenuPath(container, layeredState, path);
7616
        });
7617
      };
7618
      const onRight = (container, item) => inside(item.element) ? Optional.none() : expandRight(container, item, ExpandHighlightDecision.HighlightSubmenu);
7619
      const onLeft = (container, item) => inside(item.element) ? Optional.none() : collapseLeft(container, item);
7620
      const onEscape = (container, item) => collapseLeft(container, item).orThunk(() => detail.onEscape(container, item).map(() => container));
7621
      const keyOnItem = f => (container, simulatedEvent) => {
7622
        return closest$1(simulatedEvent.getSource(), `.${ detail.markers.item }`).bind(target => container.getSystem().getByDom(target).toOptional().bind(item => f(container, item).map(always)));
7623
      };
7624
      const events = derive$2([
7625
        run$1(focus(), (tmenu, simulatedEvent) => {
7626
          const item = simulatedEvent.event.item;
7627
          layeredState.lookupItem(getItemValue(item)).each(() => {
7628
            const menu = simulatedEvent.event.menu;
7629
            Highlighting.highlight(tmenu, menu);
7630
            const value = getItemValue(simulatedEvent.event.item);
7631
            layeredState.refresh(value).each(path => closeOthers(tmenu, layeredState, path));
7632
          });
7633
        }),
7634
        runOnExecute$1((component, simulatedEvent) => {
7635
          const target = simulatedEvent.event.target;
7636
          component.getSystem().getByDom(target).each(item => {
7637
            const itemValue = getItemValue(item);
7638
            if (itemValue.indexOf('collapse-item') === 0) {
7639
              collapseLeft(component, item);
7640
            }
7641
            expandRight(component, item, ExpandHighlightDecision.HighlightSubmenu).fold(() => {
7642
              detail.onExecute(component, item);
7643
            }, noop);
7644
          });
7645
        }),
7646
        runOnAttached((container, _simulatedEvent) => {
7647
          setup(container).each(primary => {
7648
            Replacing.append(container, premade(primary));
7649
            detail.onOpenMenu(container, primary);
7650
            if (detail.highlightOnOpen === HighlightOnOpen.HighlightMenuAndItem) {
7651
              setActiveMenuAndItem(container, primary);
7652
            } else if (detail.highlightOnOpen === HighlightOnOpen.HighlightJustMenu) {
7653
              setActiveMenu(container, primary);
7654
            }
7655
          });
7656
        }),
7657
        run$1(onMenuItemHighlightedEvent, (tmenuComp, se) => {
7658
          detail.onHighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
7659
        }),
7660
        run$1(onMenuItemDehighlightedEvent, (tmenuComp, se) => {
7661
          detail.onDehighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
7662
        }),
7663
        ...detail.navigateOnHover ? [run$1(hover(), (tmenu, simulatedEvent) => {
7664
            const item = simulatedEvent.event.item;
7665
            updateView(tmenu, item);
7666
            expandRight(tmenu, item, ExpandHighlightDecision.HighlightParent);
7667
            detail.onHover(tmenu, item);
7668
          })] : []
7669
      ]);
7670
      const getActiveItem = container => Highlighting.getHighlighted(container).bind(Highlighting.getHighlighted);
7671
      const collapseMenuApi = container => {
7672
        getActiveItem(container).each(currentItem => {
7673
          collapseLeft(container, currentItem);
7674
        });
7675
      };
7676
      const highlightPrimary = container => {
7677
        layeredState.getPrimary().each(primary => {
7678
          setActiveMenuAndItem(container, primary);
7679
        });
7680
      };
7681
      const extractMenuFromContainer = container => Optional.from(container.components()[0]).filter(comp => get$f(comp.element, 'role') === 'menu');
7682
      const repositionMenus = container => {
7683
        const maybeActivePrimary = layeredState.getPrimary().bind(primary => getActiveItem(container).bind(currentItem => {
7684
          const itemValue = getItemValue(currentItem);
7685
          const allMenus = values(layeredState.getMenus());
7686
          const preparedMenus = cat(map$2(allMenus, LayeredState.extractPreparedMenu));
7687
          return layeredState.getTriggeringPath(itemValue, v => getItemByValue(container, preparedMenus, v));
7688
        }).map(triggeringPath => ({
7689
          primary,
7690
          triggeringPath
7691
        })));
7692
        maybeActivePrimary.fold(() => {
7693
          extractMenuFromContainer(container).each(primaryMenu => {
7694
            detail.onRepositionMenu(container, primaryMenu, []);
7695
          });
7696
        }, ({primary, triggeringPath}) => {
7697
          detail.onRepositionMenu(container, primary, triggeringPath);
7698
        });
7699
      };
7700
      const apis = {
7701
        collapseMenu: collapseMenuApi,
7702
        highlightPrimary,
7703
        repositionMenus
7704
      };
7705
      return {
7706
        uid: detail.uid,
7707
        dom: detail.dom,
7708
        markers: detail.markers,
7709
        behaviours: augment(detail.tmenuBehaviours, [
7710
          Keying.config({
7711
            mode: 'special',
7712
            onRight: keyOnItem(onRight),
7713
            onLeft: keyOnItem(onLeft),
7714
            onEscape: keyOnItem(onEscape),
7715
            focusIn: (container, _keyInfo) => {
7716
              layeredState.getPrimary().each(primary => {
7717
                dispatch(container, primary.element, focusItem());
7718
              });
7719
            }
7720
          }),
7721
          Highlighting.config({
7722
            highlightClass: detail.markers.selectedMenu,
7723
            itemClass: detail.markers.menu
7724
          }),
7725
          Composing.config({
7726
            find: container => {
7727
              return Highlighting.getHighlighted(container);
7728
            }
7729
          }),
7730
          Replacing.config({})
7731
        ]),
7732
        eventOrder: detail.eventOrder,
7733
        apis,
7734
        events
7735
      };
7736
    };
7737
    const collapseItem$1 = constant$1('collapse-item');
7738
 
7739
    const tieredData = (primary, menus, expansions) => ({
7740
      primary,
7741
      menus,
7742
      expansions
7743
    });
7744
    const singleData = (name, menu) => ({
7745
      primary: name,
7746
      menus: wrap$1(name, menu),
7747
      expansions: {}
7748
    });
7749
    const collapseItem = text => ({
7750
      value: generate$6(collapseItem$1()),
7751
      meta: { text }
7752
    });
7753
    const tieredMenu = single({
7754
      name: 'TieredMenu',
7755
      configFields: [
7756
        onStrictKeyboardHandler('onExecute'),
7757
        onStrictKeyboardHandler('onEscape'),
7758
        onStrictHandler('onOpenMenu'),
7759
        onStrictHandler('onOpenSubmenu'),
7760
        onHandler('onRepositionMenu'),
7761
        onHandler('onCollapseMenu'),
7762
        defaulted('highlightOnOpen', HighlightOnOpen.HighlightMenuAndItem),
7763
        requiredObjOf('data', [
7764
          required$1('primary'),
7765
          required$1('menus'),
7766
          required$1('expansions')
7767
        ]),
7768
        defaulted('fakeFocus', false),
7769
        onHandler('onHighlightItem'),
7770
        onHandler('onDehighlightItem'),
7771
        onHandler('onHover'),
7772
        tieredMenuMarkers(),
7773
        required$1('dom'),
7774
        defaulted('navigateOnHover', true),
7775
        defaulted('stayInDom', false),
7776
        field('tmenuBehaviours', [
7777
          Keying,
7778
          Highlighting,
7779
          Composing,
7780
          Replacing
7781
        ]),
7782
        defaulted('eventOrder', {})
7783
      ],
7784
      apis: {
7785
        collapseMenu: (apis, tmenu) => {
7786
          apis.collapseMenu(tmenu);
7787
        },
7788
        highlightPrimary: (apis, tmenu) => {
7789
          apis.highlightPrimary(tmenu);
7790
        },
7791
        repositionMenus: (apis, tmenu) => {
7792
          apis.repositionMenus(tmenu);
7793
        }
7794
      },
7795
      factory: make$6,
7796
      extraApis: {
7797
        tieredData,
7798
        singleData,
7799
        collapseItem
7800
      }
7801
    });
7802
 
7803
    const makeMenu = (detail, menuSandbox, placementSpec, menuSpec, getBounds) => {
7804
      const lazySink = () => detail.lazySink(menuSandbox);
7805
      const layouts = menuSpec.type === 'horizontal' ? {
7806
        layouts: {
7807
          onLtr: () => belowOrAbove(),
7808
          onRtl: () => belowOrAboveRtl()
7809
        }
7810
      } : {};
7811
      const isFirstTierSubmenu = triggeringPaths => triggeringPaths.length === 2;
7812
      const getSubmenuLayouts = triggeringPaths => isFirstTierSubmenu(triggeringPaths) ? layouts : {};
7813
      return tieredMenu.sketch({
7814
        dom: { tag: 'div' },
7815
        data: menuSpec.data,
7816
        markers: menuSpec.menu.markers,
7817
        highlightOnOpen: menuSpec.menu.highlightOnOpen,
7818
        fakeFocus: menuSpec.menu.fakeFocus,
7819
        onEscape: () => {
7820
          Sandboxing.close(menuSandbox);
7821
          detail.onEscape.map(handler => handler(menuSandbox));
7822
          return Optional.some(true);
7823
        },
7824
        onExecute: () => {
7825
          return Optional.some(true);
7826
        },
7827
        onOpenMenu: (tmenu, menu) => {
7828
          Positioning.positionWithinBounds(lazySink().getOrDie(), menu, placementSpec, getBounds());
7829
        },
7830
        onOpenSubmenu: (tmenu, item, submenu, triggeringPaths) => {
7831
          const sink = lazySink().getOrDie();
7832
          Positioning.position(sink, submenu, {
7833
            anchor: {
7834
              type: 'submenu',
7835
              item,
7836
              ...getSubmenuLayouts(triggeringPaths)
7837
            }
7838
          });
7839
        },
7840
        onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
7841
          const sink = lazySink().getOrDie();
7842
          Positioning.positionWithinBounds(sink, primaryMenu, placementSpec, getBounds());
7843
          each$1(submenuTriggers, st => {
7844
            const submenuLayouts = getSubmenuLayouts(st.triggeringPath);
7845
            Positioning.position(sink, st.triggeredMenu, {
7846
              anchor: {
7847
                type: 'submenu',
7848
                item: st.triggeringItem,
7849
                ...submenuLayouts
7850
              }
7851
            });
7852
          });
7853
        }
7854
      });
7855
    };
7856
    const factory$o = (detail, spec) => {
7857
      const isPartOfRelated = (sandbox, queryElem) => {
7858
        const related = detail.getRelated(sandbox);
7859
        return related.exists(rel => isPartOf$1(rel, queryElem));
7860
      };
7861
      const setContent = (sandbox, thing) => {
7862
        Sandboxing.setContent(sandbox, thing);
7863
      };
7864
      const showAt = (sandbox, thing, placementSpec) => {
7865
        const getBounds = Optional.none;
7866
        showWithinBounds(sandbox, thing, placementSpec, getBounds);
7867
      };
7868
      const showWithinBounds = (sandbox, thing, placementSpec, getBounds) => {
7869
        const sink = detail.lazySink(sandbox).getOrDie();
7870
        Sandboxing.openWhileCloaked(sandbox, thing, () => Positioning.positionWithinBounds(sink, sandbox, placementSpec, getBounds()));
7871
        Representing.setValue(sandbox, Optional.some({
7872
          mode: 'position',
7873
          config: placementSpec,
7874
          getBounds
7875
        }));
7876
      };
7877
      const showMenuAt = (sandbox, placementSpec, menuSpec) => {
7878
        showMenuWithinBounds(sandbox, placementSpec, menuSpec, Optional.none);
7879
      };
7880
      const showMenuWithinBounds = (sandbox, placementSpec, menuSpec, getBounds) => {
7881
        const menu = makeMenu(detail, sandbox, placementSpec, menuSpec, getBounds);
7882
        Sandboxing.open(sandbox, menu);
7883
        Representing.setValue(sandbox, Optional.some({
7884
          mode: 'menu',
7885
          menu
7886
        }));
7887
      };
7888
      const hide = sandbox => {
7889
        if (Sandboxing.isOpen(sandbox)) {
7890
          Representing.setValue(sandbox, Optional.none());
7891
          Sandboxing.close(sandbox);
7892
        }
7893
      };
7894
      const getContent = sandbox => Sandboxing.getState(sandbox);
7895
      const reposition = sandbox => {
7896
        if (Sandboxing.isOpen(sandbox)) {
7897
          Representing.getValue(sandbox).each(state => {
7898
            switch (state.mode) {
7899
            case 'menu':
7900
              Sandboxing.getState(sandbox).each(tieredMenu.repositionMenus);
7901
              break;
7902
            case 'position':
7903
              const sink = detail.lazySink(sandbox).getOrDie();
7904
              Positioning.positionWithinBounds(sink, sandbox, state.config, state.getBounds());
7905
              break;
7906
            }
7907
          });
7908
        }
7909
      };
7910
      const apis = {
7911
        setContent,
7912
        showAt,
7913
        showWithinBounds,
7914
        showMenuAt,
7915
        showMenuWithinBounds,
7916
        hide,
7917
        getContent,
7918
        reposition,
7919
        isOpen: Sandboxing.isOpen
7920
      };
7921
      return {
7922
        uid: detail.uid,
7923
        dom: detail.dom,
7924
        behaviours: augment(detail.inlineBehaviours, [
7925
          Sandboxing.config({
7926
            isPartOf: (sandbox, data, queryElem) => {
7927
              return isPartOf$1(data, queryElem) || isPartOfRelated(sandbox, queryElem);
7928
            },
7929
            getAttachPoint: sandbox => {
7930
              return detail.lazySink(sandbox).getOrDie();
7931
            },
7932
            onOpen: sandbox => {
7933
              detail.onShow(sandbox);
7934
            },
7935
            onClose: sandbox => {
7936
              detail.onHide(sandbox);
7937
            }
7938
          }),
7939
          Representing.config({
7940
            store: {
7941
              mode: 'memory',
7942
              initialValue: Optional.none()
7943
            }
7944
          }),
7945
          Receiving.config({
7946
            channels: {
7947
              ...receivingChannel$1({
7948
                isExtraPart: spec.isExtraPart,
7949
                ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
7950
              }),
7951
              ...receivingChannel({
7952
                ...detail.fireRepositionEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({}),
7953
                doReposition: reposition
7954
              })
7955
            }
7956
          })
7957
        ]),
7958
        eventOrder: detail.eventOrder,
7959
        apis
7960
      };
7961
    };
7962
    const InlineView = single({
7963
      name: 'InlineView',
7964
      configFields: [
7965
        required$1('lazySink'),
7966
        onHandler('onShow'),
7967
        onHandler('onHide'),
7968
        optionFunction('onEscape'),
7969
        field('inlineBehaviours', [
7970
          Sandboxing,
7971
          Representing,
7972
          Receiving
7973
        ]),
7974
        optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
7975
        optionObjOf('fireRepositionEventInstead', [defaulted('event', repositionRequested())]),
7976
        defaulted('getRelated', Optional.none),
7977
        defaulted('isExtraPart', never),
7978
        defaulted('eventOrder', Optional.none)
7979
      ],
7980
      factory: factory$o,
7981
      apis: {
7982
        showAt: (apis, component, anchor, thing) => {
7983
          apis.showAt(component, anchor, thing);
7984
        },
7985
        showWithinBounds: (apis, component, anchor, thing, bounds) => {
7986
          apis.showWithinBounds(component, anchor, thing, bounds);
7987
        },
7988
        showMenuAt: (apis, component, anchor, menuSpec) => {
7989
          apis.showMenuAt(component, anchor, menuSpec);
7990
        },
7991
        showMenuWithinBounds: (apis, component, anchor, menuSpec, bounds) => {
7992
          apis.showMenuWithinBounds(component, anchor, menuSpec, bounds);
7993
        },
7994
        hide: (apis, component) => {
7995
          apis.hide(component);
7996
        },
7997
        isOpen: (apis, component) => apis.isOpen(component),
7998
        getContent: (apis, component) => apis.getContent(component),
7999
        setContent: (apis, component, thing) => {
8000
          apis.setContent(component, thing);
8001
        },
8002
        reposition: (apis, component) => {
8003
          apis.reposition(component);
8004
        }
8005
      }
8006
    });
8007
 
8008
    var global$9 = tinymce.util.Tools.resolve('tinymce.util.Delay');
8009
 
8010
    const factory$n = detail => {
8011
      const events = events$a(detail.action);
8012
      const tag = detail.dom.tag;
8013
      const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
8014
      const getModAttributes = () => {
8015
        if (tag === 'button') {
8016
          const type = lookupAttr('type').getOr('button');
8017
          const roleAttrs = lookupAttr('role').map(role => ({ role })).getOr({});
8018
          return {
8019
            type,
8020
            ...roleAttrs
8021
          };
8022
        } else {
8023
          const role = detail.role.getOr(lookupAttr('role').getOr('button'));
8024
          return { role };
8025
        }
8026
      };
8027
      return {
8028
        uid: detail.uid,
8029
        dom: detail.dom,
8030
        components: detail.components,
8031
        events,
8032
        behaviours: SketchBehaviours.augment(detail.buttonBehaviours, [
8033
          Focusing.config({}),
8034
          Keying.config({
8035
            mode: 'execution',
8036
            useSpace: true,
8037
            useEnter: true
8038
          })
8039
        ]),
8040
        domModification: { attributes: getModAttributes() },
8041
        eventOrder: detail.eventOrder
8042
      };
8043
    };
8044
    const Button = single({
8045
      name: 'Button',
8046
      factory: factory$n,
8047
      configFields: [
8048
        defaulted('uid', undefined),
8049
        required$1('dom'),
8050
        defaulted('components', []),
8051
        SketchBehaviours.field('buttonBehaviours', [
8052
          Focusing,
8053
          Keying
8054
        ]),
8055
        option$3('action'),
8056
        option$3('role'),
8057
        defaulted('eventOrder', {})
8058
      ]
8059
    });
8060
 
8061
    const getAttrs = elem => {
8062
      const attributes = elem.dom.attributes !== undefined ? elem.dom.attributes : [];
8063
      return foldl(attributes, (b, attr) => {
8064
        if (attr.name === 'class') {
8065
          return b;
8066
        } else {
8067
          return {
8068
            ...b,
8069
            [attr.name]: attr.value
8070
          };
8071
        }
8072
      }, {});
8073
    };
8074
    const getClasses = elem => Array.prototype.slice.call(elem.dom.classList, 0);
8075
    const fromHtml = html => {
8076
      const elem = SugarElement.fromHtml(html);
8077
      const children$1 = children(elem);
8078
      const attrs = getAttrs(elem);
8079
      const classes = getClasses(elem);
8080
      const contents = children$1.length === 0 ? {} : { innerHtml: get$9(elem) };
8081
      return {
8082
        tag: name$3(elem),
8083
        classes,
8084
        attributes: attrs,
8085
        ...contents
8086
      };
8087
    };
8088
 
8089
    const record = spec => {
8090
      const uid = isSketchSpec(spec) && hasNonNullableKey(spec, 'uid') ? spec.uid : generate$5('memento');
8091
      const get = anyInSystem => anyInSystem.getSystem().getByUid(uid).getOrDie();
8092
      const getOpt = anyInSystem => anyInSystem.getSystem().getByUid(uid).toOptional();
8093
      const asSpec = () => ({
8094
        ...spec,
8095
        uid
8096
      });
8097
      return {
8098
        get,
8099
        getOpt,
8100
        asSpec
8101
      };
8102
    };
8103
 
8104
    const {entries, setPrototypeOf, isFrozen, getPrototypeOf, getOwnPropertyDescriptor} = Object;
8105
    let {freeze, seal, create: create$1} = Object;
8106
    let {apply, construct} = typeof Reflect !== 'undefined' && Reflect;
8107
    if (!apply) {
8108
      apply = function apply(fun, thisValue, args) {
8109
        return fun.apply(thisValue, args);
8110
      };
8111
    }
8112
    if (!freeze) {
8113
      freeze = function freeze(x) {
8114
        return x;
8115
      };
8116
    }
8117
    if (!seal) {
8118
      seal = function seal(x) {
8119
        return x;
8120
      };
8121
    }
8122
    if (!construct) {
8123
      construct = function construct(Func, args) {
8124
        return new Func(...args);
8125
      };
8126
    }
8127
    const arrayForEach = unapply(Array.prototype.forEach);
8128
    const arrayPop = unapply(Array.prototype.pop);
8129
    const arrayPush = unapply(Array.prototype.push);
8130
    const stringToLowerCase = unapply(String.prototype.toLowerCase);
8131
    const stringToString = unapply(String.prototype.toString);
8132
    const stringMatch = unapply(String.prototype.match);
8133
    const stringReplace = unapply(String.prototype.replace);
8134
    const stringIndexOf = unapply(String.prototype.indexOf);
8135
    const stringTrim = unapply(String.prototype.trim);
8136
    const regExpTest = unapply(RegExp.prototype.test);
8137
    const typeErrorCreate = unconstruct(TypeError);
8138
    function unapply(func) {
8139
      return function (thisArg) {
8140
        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
8141
          args[_key - 1] = arguments[_key];
8142
        }
8143
        return apply(func, thisArg, args);
8144
      };
8145
    }
8146
    function unconstruct(func) {
8147
      return function () {
8148
        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
8149
          args[_key2] = arguments[_key2];
8150
        }
8151
        return construct(func, args);
8152
      };
8153
    }
8154
    function addToSet(set, array, transformCaseFunc) {
8155
      var _transformCaseFunc;
8156
      transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase;
8157
      if (setPrototypeOf) {
8158
        setPrototypeOf(set, null);
8159
      }
8160
      let l = array.length;
8161
      while (l--) {
8162
        let element = array[l];
8163
        if (typeof element === 'string') {
8164
          const lcElement = transformCaseFunc(element);
8165
          if (lcElement !== element) {
8166
            if (!isFrozen(array)) {
8167
              array[l] = lcElement;
8168
            }
8169
            element = lcElement;
8170
          }
8171
        }
8172
        set[element] = true;
8173
      }
8174
      return set;
8175
    }
8176
    function clone(object) {
8177
      const newObject = create$1(null);
8178
      for (const [property, value] of entries(object)) {
8179
        newObject[property] = value;
8180
      }
8181
      return newObject;
8182
    }
8183
    function lookupGetter(object, prop) {
8184
      while (object !== null) {
8185
        const desc = getOwnPropertyDescriptor(object, prop);
8186
        if (desc) {
8187
          if (desc.get) {
8188
            return unapply(desc.get);
8189
          }
8190
          if (typeof desc.value === 'function') {
8191
            return unapply(desc.value);
8192
          }
8193
        }
8194
        object = getPrototypeOf(object);
8195
      }
8196
      function fallbackValue(element) {
8197
        console.warn('fallback value for', element);
8198
        return null;
8199
      }
8200
      return fallbackValue;
8201
    }
8202
    const html$1 = freeze([
8203
      'a',
8204
      'abbr',
8205
      'acronym',
8206
      'address',
8207
      'area',
8208
      'article',
8209
      'aside',
8210
      'audio',
8211
      'b',
8212
      'bdi',
8213
      'bdo',
8214
      'big',
8215
      'blink',
8216
      'blockquote',
8217
      'body',
8218
      'br',
8219
      'button',
8220
      'canvas',
8221
      'caption',
8222
      'center',
8223
      'cite',
8224
      'code',
8225
      'col',
8226
      'colgroup',
8227
      'content',
8228
      'data',
8229
      'datalist',
8230
      'dd',
8231
      'decorator',
8232
      'del',
8233
      'details',
8234
      'dfn',
8235
      'dialog',
8236
      'dir',
8237
      'div',
8238
      'dl',
8239
      'dt',
8240
      'element',
8241
      'em',
8242
      'fieldset',
8243
      'figcaption',
8244
      'figure',
8245
      'font',
8246
      'footer',
8247
      'form',
8248
      'h1',
8249
      'h2',
8250
      'h3',
8251
      'h4',
8252
      'h5',
8253
      'h6',
8254
      'head',
8255
      'header',
8256
      'hgroup',
8257
      'hr',
8258
      'html',
8259
      'i',
8260
      'img',
8261
      'input',
8262
      'ins',
8263
      'kbd',
8264
      'label',
8265
      'legend',
8266
      'li',
8267
      'main',
8268
      'map',
8269
      'mark',
8270
      'marquee',
8271
      'menu',
8272
      'menuitem',
8273
      'meter',
8274
      'nav',
8275
      'nobr',
8276
      'ol',
8277
      'optgroup',
8278
      'option',
8279
      'output',
8280
      'p',
8281
      'picture',
8282
      'pre',
8283
      'progress',
8284
      'q',
8285
      'rp',
8286
      'rt',
8287
      'ruby',
8288
      's',
8289
      'samp',
8290
      'section',
8291
      'select',
8292
      'shadow',
8293
      'small',
8294
      'source',
8295
      'spacer',
8296
      'span',
8297
      'strike',
8298
      'strong',
8299
      'style',
8300
      'sub',
8301
      'summary',
8302
      'sup',
8303
      'table',
8304
      'tbody',
8305
      'td',
8306
      'template',
8307
      'textarea',
8308
      'tfoot',
8309
      'th',
8310
      'thead',
8311
      'time',
8312
      'tr',
8313
      'track',
8314
      'tt',
8315
      'u',
8316
      'ul',
8317
      'var',
8318
      'video',
8319
      'wbr'
8320
    ]);
8321
    const svg$1 = freeze([
8322
      'svg',
8323
      'a',
8324
      'altglyph',
8325
      'altglyphdef',
8326
      'altglyphitem',
8327
      'animatecolor',
8328
      'animatemotion',
8329
      'animatetransform',
8330
      'circle',
8331
      'clippath',
8332
      'defs',
8333
      'desc',
8334
      'ellipse',
8335
      'filter',
8336
      'font',
8337
      'g',
8338
      'glyph',
8339
      'glyphref',
8340
      'hkern',
8341
      'image',
8342
      'line',
8343
      'lineargradient',
8344
      'marker',
8345
      'mask',
8346
      'metadata',
8347
      'mpath',
8348
      'path',
8349
      'pattern',
8350
      'polygon',
8351
      'polyline',
8352
      'radialgradient',
8353
      'rect',
8354
      'stop',
8355
      'style',
8356
      'switch',
8357
      'symbol',
8358
      'text',
8359
      'textpath',
8360
      'title',
8361
      'tref',
8362
      'tspan',
8363
      'view',
8364
      'vkern'
8365
    ]);
8366
    const svgFilters = freeze([
8367
      'feBlend',
8368
      'feColorMatrix',
8369
      'feComponentTransfer',
8370
      'feComposite',
8371
      'feConvolveMatrix',
8372
      'feDiffuseLighting',
8373
      'feDisplacementMap',
8374
      'feDistantLight',
8375
      'feDropShadow',
8376
      'feFlood',
8377
      'feFuncA',
8378
      'feFuncB',
8379
      'feFuncG',
8380
      'feFuncR',
8381
      'feGaussianBlur',
8382
      'feImage',
8383
      'feMerge',
8384
      'feMergeNode',
8385
      'feMorphology',
8386
      'feOffset',
8387
      'fePointLight',
8388
      'feSpecularLighting',
8389
      'feSpotLight',
8390
      'feTile',
8391
      'feTurbulence'
8392
    ]);
8393
    const svgDisallowed = freeze([
8394
      'animate',
8395
      'color-profile',
8396
      'cursor',
8397
      'discard',
8398
      'font-face',
8399
      'font-face-format',
8400
      'font-face-name',
8401
      'font-face-src',
8402
      'font-face-uri',
8403
      'foreignobject',
8404
      'hatch',
8405
      'hatchpath',
8406
      'mesh',
8407
      'meshgradient',
8408
      'meshpatch',
8409
      'meshrow',
8410
      'missing-glyph',
8411
      'script',
8412
      'set',
8413
      'solidcolor',
8414
      'unknown',
8415
      'use'
8416
    ]);
8417
    const mathMl$1 = freeze([
8418
      'math',
8419
      'menclose',
8420
      'merror',
8421
      'mfenced',
8422
      'mfrac',
8423
      'mglyph',
8424
      'mi',
8425
      'mlabeledtr',
8426
      'mmultiscripts',
8427
      'mn',
8428
      'mo',
8429
      'mover',
8430
      'mpadded',
8431
      'mphantom',
8432
      'mroot',
8433
      'mrow',
8434
      'ms',
8435
      'mspace',
8436
      'msqrt',
8437
      'mstyle',
8438
      'msub',
8439
      'msup',
8440
      'msubsup',
8441
      'mtable',
8442
      'mtd',
8443
      'mtext',
8444
      'mtr',
8445
      'munder',
8446
      'munderover',
8447
      'mprescripts'
8448
    ]);
8449
    const mathMlDisallowed = freeze([
8450
      'maction',
8451
      'maligngroup',
8452
      'malignmark',
8453
      'mlongdiv',
8454
      'mscarries',
8455
      'mscarry',
8456
      'msgroup',
8457
      'mstack',
8458
      'msline',
8459
      'msrow',
8460
      'semantics',
8461
      'annotation',
8462
      'annotation-xml',
8463
      'mprescripts',
8464
      'none'
8465
    ]);
8466
    const text$1 = freeze(['#text']);
8467
    const html = freeze([
8468
      'accept',
8469
      'action',
8470
      'align',
8471
      'alt',
8472
      'autocapitalize',
8473
      'autocomplete',
8474
      'autopictureinpicture',
8475
      'autoplay',
8476
      'background',
8477
      'bgcolor',
8478
      'border',
8479
      'capture',
8480
      'cellpadding',
8481
      'cellspacing',
8482
      'checked',
8483
      'cite',
8484
      'class',
8485
      'clear',
8486
      'color',
8487
      'cols',
8488
      'colspan',
8489
      'controls',
8490
      'controlslist',
8491
      'coords',
8492
      'crossorigin',
8493
      'datetime',
8494
      'decoding',
8495
      'default',
8496
      'dir',
8497
      'disabled',
8498
      'disablepictureinpicture',
8499
      'disableremoteplayback',
8500
      'download',
8501
      'draggable',
8502
      'enctype',
8503
      'enterkeyhint',
8504
      'face',
8505
      'for',
8506
      'headers',
8507
      'height',
8508
      'hidden',
8509
      'high',
8510
      'href',
8511
      'hreflang',
8512
      'id',
8513
      'inputmode',
8514
      'integrity',
8515
      'ismap',
8516
      'kind',
8517
      'label',
8518
      'lang',
8519
      'list',
8520
      'loading',
8521
      'loop',
8522
      'low',
8523
      'max',
8524
      'maxlength',
8525
      'media',
8526
      'method',
8527
      'min',
8528
      'minlength',
8529
      'multiple',
8530
      'muted',
8531
      'name',
8532
      'nonce',
8533
      'noshade',
8534
      'novalidate',
8535
      'nowrap',
8536
      'open',
8537
      'optimum',
8538
      'pattern',
8539
      'placeholder',
8540
      'playsinline',
8541
      'poster',
8542
      'preload',
8543
      'pubdate',
8544
      'radiogroup',
8545
      'readonly',
8546
      'rel',
8547
      'required',
8548
      'rev',
8549
      'reversed',
8550
      'role',
8551
      'rows',
8552
      'rowspan',
8553
      'spellcheck',
8554
      'scope',
8555
      'selected',
8556
      'shape',
8557
      'size',
8558
      'sizes',
8559
      'span',
8560
      'srclang',
8561
      'start',
8562
      'src',
8563
      'srcset',
8564
      'step',
8565
      'style',
8566
      'summary',
8567
      'tabindex',
8568
      'title',
8569
      'translate',
8570
      'type',
8571
      'usemap',
8572
      'valign',
8573
      'value',
8574
      'width',
8575
      'xmlns',
8576
      'slot'
8577
    ]);
8578
    const svg = freeze([
8579
      'accent-height',
8580
      'accumulate',
8581
      'additive',
8582
      'alignment-baseline',
8583
      'ascent',
8584
      'attributename',
8585
      'attributetype',
8586
      'azimuth',
8587
      'basefrequency',
8588
      'baseline-shift',
8589
      'begin',
8590
      'bias',
8591
      'by',
8592
      'class',
8593
      'clip',
8594
      'clippathunits',
8595
      'clip-path',
8596
      'clip-rule',
8597
      'color',
8598
      'color-interpolation',
8599
      'color-interpolation-filters',
8600
      'color-profile',
8601
      'color-rendering',
8602
      'cx',
8603
      'cy',
8604
      'd',
8605
      'dx',
8606
      'dy',
8607
      'diffuseconstant',
8608
      'direction',
8609
      'display',
8610
      'divisor',
8611
      'dur',
8612
      'edgemode',
8613
      'elevation',
8614
      'end',
8615
      'fill',
8616
      'fill-opacity',
8617
      'fill-rule',
8618
      'filter',
8619
      'filterunits',
8620
      'flood-color',
8621
      'flood-opacity',
8622
      'font-family',
8623
      'font-size',
8624
      'font-size-adjust',
8625
      'font-stretch',
8626
      'font-style',
8627
      'font-variant',
8628
      'font-weight',
8629
      'fx',
8630
      'fy',
8631
      'g1',
8632
      'g2',
8633
      'glyph-name',
8634
      'glyphref',
8635
      'gradientunits',
8636
      'gradienttransform',
8637
      'height',
8638
      'href',
8639
      'id',
8640
      'image-rendering',
8641
      'in',
8642
      'in2',
8643
      'k',
8644
      'k1',
8645
      'k2',
8646
      'k3',
8647
      'k4',
8648
      'kerning',
8649
      'keypoints',
8650
      'keysplines',
8651
      'keytimes',
8652
      'lang',
8653
      'lengthadjust',
8654
      'letter-spacing',
8655
      'kernelmatrix',
8656
      'kernelunitlength',
8657
      'lighting-color',
8658
      'local',
8659
      'marker-end',
8660
      'marker-mid',
8661
      'marker-start',
8662
      'markerheight',
8663
      'markerunits',
8664
      'markerwidth',
8665
      'maskcontentunits',
8666
      'maskunits',
8667
      'max',
8668
      'mask',
8669
      'media',
8670
      'method',
8671
      'mode',
8672
      'min',
8673
      'name',
8674
      'numoctaves',
8675
      'offset',
8676
      'operator',
8677
      'opacity',
8678
      'order',
8679
      'orient',
8680
      'orientation',
8681
      'origin',
8682
      'overflow',
8683
      'paint-order',
8684
      'path',
8685
      'pathlength',
8686
      'patterncontentunits',
8687
      'patterntransform',
8688
      'patternunits',
8689
      'points',
8690
      'preservealpha',
8691
      'preserveaspectratio',
8692
      'primitiveunits',
8693
      'r',
8694
      'rx',
8695
      'ry',
8696
      'radius',
8697
      'refx',
8698
      'refy',
8699
      'repeatcount',
8700
      'repeatdur',
8701
      'restart',
8702
      'result',
8703
      'rotate',
8704
      'scale',
8705
      'seed',
8706
      'shape-rendering',
8707
      'specularconstant',
8708
      'specularexponent',
8709
      'spreadmethod',
8710
      'startoffset',
8711
      'stddeviation',
8712
      'stitchtiles',
8713
      'stop-color',
8714
      'stop-opacity',
8715
      'stroke-dasharray',
8716
      'stroke-dashoffset',
8717
      'stroke-linecap',
8718
      'stroke-linejoin',
8719
      'stroke-miterlimit',
8720
      'stroke-opacity',
8721
      'stroke',
8722
      'stroke-width',
8723
      'style',
8724
      'surfacescale',
8725
      'systemlanguage',
8726
      'tabindex',
8727
      'targetx',
8728
      'targety',
8729
      'transform',
8730
      'transform-origin',
8731
      'text-anchor',
8732
      'text-decoration',
8733
      'text-rendering',
8734
      'textlength',
8735
      'type',
8736
      'u1',
8737
      'u2',
8738
      'unicode',
8739
      'values',
8740
      'viewbox',
8741
      'visibility',
8742
      'version',
8743
      'vert-adv-y',
8744
      'vert-origin-x',
8745
      'vert-origin-y',
8746
      'width',
8747
      'word-spacing',
8748
      'wrap',
8749
      'writing-mode',
8750
      'xchannelselector',
8751
      'ychannelselector',
8752
      'x',
8753
      'x1',
8754
      'x2',
8755
      'xmlns',
8756
      'y',
8757
      'y1',
8758
      'y2',
8759
      'z',
8760
      'zoomandpan'
8761
    ]);
8762
    const mathMl = freeze([
8763
      'accent',
8764
      'accentunder',
8765
      'align',
8766
      'bevelled',
8767
      'close',
8768
      'columnsalign',
8769
      'columnlines',
8770
      'columnspan',
8771
      'denomalign',
8772
      'depth',
8773
      'dir',
8774
      'display',
8775
      'displaystyle',
8776
      'encoding',
8777
      'fence',
8778
      'frame',
8779
      'height',
8780
      'href',
8781
      'id',
8782
      'largeop',
8783
      'length',
8784
      'linethickness',
8785
      'lspace',
8786
      'lquote',
8787
      'mathbackground',
8788
      'mathcolor',
8789
      'mathsize',
8790
      'mathvariant',
8791
      'maxsize',
8792
      'minsize',
8793
      'movablelimits',
8794
      'notation',
8795
      'numalign',
8796
      'open',
8797
      'rowalign',
8798
      'rowlines',
8799
      'rowspacing',
8800
      'rowspan',
8801
      'rspace',
8802
      'rquote',
8803
      'scriptlevel',
8804
      'scriptminsize',
8805
      'scriptsizemultiplier',
8806
      'selection',
8807
      'separator',
8808
      'separators',
8809
      'stretchy',
8810
      'subscriptshift',
8811
      'supscriptshift',
8812
      'symmetric',
8813
      'voffset',
8814
      'width',
8815
      'xmlns'
8816
    ]);
8817
    const xml = freeze([
8818
      'xlink:href',
8819
      'xml:id',
8820
      'xlink:title',
8821
      'xml:space',
8822
      'xmlns:xlink'
8823
    ]);
8824
    const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
8825
    const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
8826
    const TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
8827
    const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
8828
    const ARIA_ATTR = seal(/^aria-[\-\w]+$/);
8829
    const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
8830
    const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
8831
    const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
8832
    const DOCTYPE_NAME = seal(/^html$/i);
8833
    var EXPRESSIONS = Object.freeze({
8834
      __proto__: null,
8835
      MUSTACHE_EXPR: MUSTACHE_EXPR,
8836
      ERB_EXPR: ERB_EXPR,
8837
      TMPLIT_EXPR: TMPLIT_EXPR,
8838
      DATA_ATTR: DATA_ATTR,
8839
      ARIA_ATTR: ARIA_ATTR,
8840
      IS_ALLOWED_URI: IS_ALLOWED_URI,
8841
      IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
8842
      ATTR_WHITESPACE: ATTR_WHITESPACE,
8843
      DOCTYPE_NAME: DOCTYPE_NAME
8844
    });
8845
    const getGlobal = () => typeof window === 'undefined' ? null : window;
8846
    const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
8847
      if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
8848
        return null;
8849
      }
8850
      let suffix = null;
8851
      const ATTR_NAME = 'data-tt-policy-suffix';
8852
      if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
8853
        suffix = purifyHostElement.getAttribute(ATTR_NAME);
8854
      }
8855
      const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
8856
      try {
8857
        return trustedTypes.createPolicy(policyName, {
8858
          createHTML(html) {
8859
            return html;
8860
          },
8861
          createScriptURL(scriptUrl) {
8862
            return scriptUrl;
8863
          }
8864
        });
8865
      } catch (_) {
8866
        console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
8867
        return null;
8868
      }
8869
    };
8870
    function createDOMPurify() {
8871
      let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
8872
      const DOMPurify = root => createDOMPurify(root);
8873
      DOMPurify.version = '3.0.5';
8874
      DOMPurify.removed = [];
8875
      if (!window || !window.document || window.document.nodeType !== 9) {
8876
        DOMPurify.isSupported = false;
8877
        return DOMPurify;
8878
      }
8879
      const originalDocument = window.document;
8880
      const currentScript = originalDocument.currentScript;
8881
      let {document} = window;
8882
      const {DocumentFragment, HTMLTemplateElement, Node, Element, NodeFilter, NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap, HTMLFormElement, DOMParser, trustedTypes} = window;
8883
      const ElementPrototype = Element.prototype;
8884
      const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
8885
      const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
8886
      const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
8887
      const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
8888
      if (typeof HTMLTemplateElement === 'function') {
8889
        const template = document.createElement('template');
8890
        if (template.content && template.content.ownerDocument) {
8891
          document = template.content.ownerDocument;
8892
        }
8893
      }
8894
      let trustedTypesPolicy;
8895
      let emptyHTML = '';
8896
      const {implementation, createNodeIterator, createDocumentFragment, getElementsByTagName} = document;
8897
      const {importNode} = originalDocument;
8898
      let hooks = {};
8899
      DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
8900
      const {MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR, DATA_ATTR, ARIA_ATTR, IS_SCRIPT_OR_DATA, ATTR_WHITESPACE} = EXPRESSIONS;
8901
      let {IS_ALLOWED_URI: IS_ALLOWED_URI$1} = EXPRESSIONS;
8902
      let ALLOWED_TAGS = null;
8903
      const DEFAULT_ALLOWED_TAGS = addToSet({}, [
8904
        ...html$1,
8905
        ...svg$1,
8906
        ...svgFilters,
8907
        ...mathMl$1,
8908
        ...text$1
8909
      ]);
8910
      let ALLOWED_ATTR = null;
8911
      const DEFAULT_ALLOWED_ATTR = addToSet({}, [
8912
        ...html,
8913
        ...svg,
8914
        ...mathMl,
8915
        ...xml
8916
      ]);
8917
      let CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
8918
        tagNameCheck: {
8919
          writable: true,
8920
          configurable: false,
8921
          enumerable: true,
8922
          value: null
8923
        },
8924
        attributeNameCheck: {
8925
          writable: true,
8926
          configurable: false,
8927
          enumerable: true,
8928
          value: null
8929
        },
8930
        allowCustomizedBuiltInElements: {
8931
          writable: true,
8932
          configurable: false,
8933
          enumerable: true,
8934
          value: false
8935
        }
8936
      }));
8937
      let FORBID_TAGS = null;
8938
      let FORBID_ATTR = null;
8939
      let ALLOW_ARIA_ATTR = true;
8940
      let ALLOW_DATA_ATTR = true;
8941
      let ALLOW_UNKNOWN_PROTOCOLS = false;
8942
      let ALLOW_SELF_CLOSE_IN_ATTR = true;
8943
      let SAFE_FOR_TEMPLATES = false;
8944
      let WHOLE_DOCUMENT = false;
8945
      let SET_CONFIG = false;
8946
      let FORCE_BODY = false;
8947
      let RETURN_DOM = false;
8948
      let RETURN_DOM_FRAGMENT = false;
8949
      let RETURN_TRUSTED_TYPE = false;
8950
      let SANITIZE_DOM = true;
8951
      let SANITIZE_NAMED_PROPS = false;
8952
      const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
8953
      let KEEP_CONTENT = true;
8954
      let IN_PLACE = false;
8955
      let USE_PROFILES = {};
8956
      let FORBID_CONTENTS = null;
8957
      const DEFAULT_FORBID_CONTENTS = addToSet({}, [
8958
        'annotation-xml',
8959
        'audio',
8960
        'colgroup',
8961
        'desc',
8962
        'foreignobject',
8963
        'head',
8964
        'iframe',
8965
        'math',
8966
        'mi',
8967
        'mn',
8968
        'mo',
8969
        'ms',
8970
        'mtext',
8971
        'noembed',
8972
        'noframes',
8973
        'noscript',
8974
        'plaintext',
8975
        'script',
8976
        'style',
8977
        'svg',
8978
        'template',
8979
        'thead',
8980
        'title',
8981
        'video',
8982
        'xmp'
8983
      ]);
8984
      let DATA_URI_TAGS = null;
8985
      const DEFAULT_DATA_URI_TAGS = addToSet({}, [
8986
        'audio',
8987
        'video',
8988
        'img',
8989
        'source',
8990
        'image',
8991
        'track'
8992
      ]);
8993
      let URI_SAFE_ATTRIBUTES = null;
8994
      const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
8995
        'alt',
8996
        'class',
8997
        'for',
8998
        'id',
8999
        'label',
9000
        'name',
9001
        'pattern',
9002
        'placeholder',
9003
        'role',
9004
        'summary',
9005
        'title',
9006
        'value',
9007
        'style',
9008
        'xmlns'
9009
      ]);
9010
      const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
9011
      const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
9012
      const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
9013
      let NAMESPACE = HTML_NAMESPACE;
9014
      let IS_EMPTY_INPUT = false;
9015
      let ALLOWED_NAMESPACES = null;
9016
      const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [
9017
        MATHML_NAMESPACE,
9018
        SVG_NAMESPACE,
9019
        HTML_NAMESPACE
9020
      ], stringToString);
9021
      let PARSER_MEDIA_TYPE;
9022
      const SUPPORTED_PARSER_MEDIA_TYPES = [
9023
        'application/xhtml+xml',
9024
        'text/html'
9025
      ];
9026
      const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
9027
      let transformCaseFunc;
9028
      let CONFIG = null;
9029
      const formElement = document.createElement('form');
9030
      const isRegexOrFunction = function isRegexOrFunction(testValue) {
9031
        return testValue instanceof RegExp || testValue instanceof Function;
9032
      };
9033
      const _parseConfig = function _parseConfig(cfg) {
9034
        if (CONFIG && CONFIG === cfg) {
9035
          return;
9036
        }
9037
        if (!cfg || typeof cfg !== 'object') {
9038
          cfg = {};
9039
        }
9040
        cfg = clone(cfg);
9041
        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;
9042
        transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
9043
        ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
9044
        ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
9045
        ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
9046
        URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
9047
        DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
9048
        FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
9049
        FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
9050
        FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
9051
        USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
9052
        ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
9053
        ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
9054
        ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
9055
        ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
9056
        SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
9057
        WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
9058
        RETURN_DOM = cfg.RETURN_DOM || false;
9059
        RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
9060
        RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
9061
        FORCE_BODY = cfg.FORCE_BODY || false;
9062
        SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
9063
        SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
9064
        KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
9065
        IN_PLACE = cfg.IN_PLACE || false;
9066
        IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
9067
        NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
9068
        CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
9069
        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
9070
          CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
9071
        }
9072
        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
9073
          CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
9074
        }
9075
        if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
9076
          CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
9077
        }
9078
        if (SAFE_FOR_TEMPLATES) {
9079
          ALLOW_DATA_ATTR = false;
9080
        }
9081
        if (RETURN_DOM_FRAGMENT) {
9082
          RETURN_DOM = true;
9083
        }
9084
        if (USE_PROFILES) {
9085
          ALLOWED_TAGS = addToSet({}, [...text$1]);
9086
          ALLOWED_ATTR = [];
9087
          if (USE_PROFILES.html === true) {
9088
            addToSet(ALLOWED_TAGS, html$1);
9089
            addToSet(ALLOWED_ATTR, html);
9090
          }
9091
          if (USE_PROFILES.svg === true) {
9092
            addToSet(ALLOWED_TAGS, svg$1);
9093
            addToSet(ALLOWED_ATTR, svg);
9094
            addToSet(ALLOWED_ATTR, xml);
9095
          }
9096
          if (USE_PROFILES.svgFilters === true) {
9097
            addToSet(ALLOWED_TAGS, svgFilters);
9098
            addToSet(ALLOWED_ATTR, svg);
9099
            addToSet(ALLOWED_ATTR, xml);
9100
          }
9101
          if (USE_PROFILES.mathMl === true) {
9102
            addToSet(ALLOWED_TAGS, mathMl$1);
9103
            addToSet(ALLOWED_ATTR, mathMl);
9104
            addToSet(ALLOWED_ATTR, xml);
9105
          }
9106
        }
9107
        if (cfg.ADD_TAGS) {
9108
          if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
9109
            ALLOWED_TAGS = clone(ALLOWED_TAGS);
9110
          }
9111
          addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
9112
        }
9113
        if (cfg.ADD_ATTR) {
9114
          if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
9115
            ALLOWED_ATTR = clone(ALLOWED_ATTR);
9116
          }
9117
          addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
9118
        }
9119
        if (cfg.ADD_URI_SAFE_ATTR) {
9120
          addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
9121
        }
9122
        if (cfg.FORBID_CONTENTS) {
9123
          if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
9124
            FORBID_CONTENTS = clone(FORBID_CONTENTS);
9125
          }
9126
          addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
9127
        }
9128
        if (KEEP_CONTENT) {
9129
          ALLOWED_TAGS['#text'] = true;
9130
        }
9131
        if (WHOLE_DOCUMENT) {
9132
          addToSet(ALLOWED_TAGS, [
9133
            'html',
9134
            'head',
9135
            'body'
9136
          ]);
9137
        }
9138
        if (ALLOWED_TAGS.table) {
9139
          addToSet(ALLOWED_TAGS, ['tbody']);
9140
          delete FORBID_TAGS.tbody;
9141
        }
9142
        if (cfg.TRUSTED_TYPES_POLICY) {
9143
          if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
9144
            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
9145
          }
9146
          if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
9147
            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
9148
          }
9149
          trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
9150
          emptyHTML = trustedTypesPolicy.createHTML('');
9151
        } else {
9152
          if (trustedTypesPolicy === undefined) {
9153
            trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
9154
          }
9155
          if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
9156
            emptyHTML = trustedTypesPolicy.createHTML('');
9157
          }
9158
        }
9159
        if (freeze) {
9160
          freeze(cfg);
9161
        }
9162
        CONFIG = cfg;
9163
      };
9164
      const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
9165
        'mi',
9166
        'mo',
9167
        'mn',
9168
        'ms',
9169
        'mtext'
9170
      ]);
9171
      const HTML_INTEGRATION_POINTS = addToSet({}, [
9172
        'foreignobject',
9173
        'desc',
9174
        'title',
9175
        'annotation-xml'
9176
      ]);
9177
      const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
9178
        'title',
9179
        'style',
9180
        'font',
9181
        'a',
9182
        'script'
9183
      ]);
9184
      const ALL_SVG_TAGS = addToSet({}, svg$1);
9185
      addToSet(ALL_SVG_TAGS, svgFilters);
9186
      addToSet(ALL_SVG_TAGS, svgDisallowed);
9187
      const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
9188
      addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
9189
      const _checkValidNamespace = function _checkValidNamespace(element) {
9190
        let parent = getParentNode(element);
9191
        if (!parent || !parent.tagName) {
9192
          parent = {
9193
            namespaceURI: NAMESPACE,
9194
            tagName: 'template'
9195
          };
9196
        }
9197
        const tagName = stringToLowerCase(element.tagName);
9198
        const parentTagName = stringToLowerCase(parent.tagName);
9199
        if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
9200
          return false;
9201
        }
9202
        if (element.namespaceURI === SVG_NAMESPACE) {
9203
          if (parent.namespaceURI === HTML_NAMESPACE) {
9204
            return tagName === 'svg';
9205
          }
9206
          if (parent.namespaceURI === MATHML_NAMESPACE) {
9207
            return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
9208
          }
9209
          return Boolean(ALL_SVG_TAGS[tagName]);
9210
        }
9211
        if (element.namespaceURI === MATHML_NAMESPACE) {
9212
          if (parent.namespaceURI === HTML_NAMESPACE) {
9213
            return tagName === 'math';
9214
          }
9215
          if (parent.namespaceURI === SVG_NAMESPACE) {
9216
            return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
9217
          }
9218
          return Boolean(ALL_MATHML_TAGS[tagName]);
9219
        }
9220
        if (element.namespaceURI === HTML_NAMESPACE) {
9221
          if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
9222
            return false;
9223
          }
9224
          if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
9225
            return false;
9226
          }
9227
          return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
9228
        }
9229
        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
9230
          return true;
9231
        }
9232
        return false;
9233
      };
9234
      const _forceRemove = function _forceRemove(node) {
9235
        arrayPush(DOMPurify.removed, { element: node });
9236
        try {
9237
          node.parentNode.removeChild(node);
9238
        } catch (_) {
9239
          node.remove();
9240
        }
9241
      };
9242
      const _removeAttribute = function _removeAttribute(name, node) {
9243
        try {
9244
          arrayPush(DOMPurify.removed, {
9245
            attribute: node.getAttributeNode(name),
9246
            from: node
9247
          });
9248
        } catch (_) {
9249
          arrayPush(DOMPurify.removed, {
9250
            attribute: null,
9251
            from: node
9252
          });
9253
        }
9254
        node.removeAttribute(name);
9255
        if (name === 'is' && !ALLOWED_ATTR[name]) {
9256
          if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
9257
            try {
9258
              _forceRemove(node);
9259
            } catch (_) {
9260
            }
9261
          } else {
9262
            try {
9263
              node.setAttribute(name, '');
9264
            } catch (_) {
9265
            }
9266
          }
9267
        }
9268
      };
9269
      const _initDocument = function _initDocument(dirty) {
9270
        let doc;
9271
        let leadingWhitespace;
9272
        if (FORCE_BODY) {
9273
          dirty = '<remove></remove>' + dirty;
9274
        } else {
9275
          const matches = stringMatch(dirty, /^[\r\n\t ]+/);
9276
          leadingWhitespace = matches && matches[0];
9277
        }
9278
        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
9279
          dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
9280
        }
9281
        const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
9282
        if (NAMESPACE === HTML_NAMESPACE) {
9283
          try {
9284
            doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
9285
          } catch (_) {
9286
          }
9287
        }
9288
        if (!doc || !doc.documentElement) {
9289
          doc = implementation.createDocument(NAMESPACE, 'template', null);
9290
          try {
9291
            doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
9292
          } catch (_) {
9293
          }
9294
        }
9295
        const body = doc.body || doc.documentElement;
9296
        if (dirty && leadingWhitespace) {
9297
          body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
9298
        }
9299
        if (NAMESPACE === HTML_NAMESPACE) {
9300
          return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
9301
        }
9302
        return WHOLE_DOCUMENT ? doc.documentElement : body;
9303
      };
9304
      const _createIterator = function _createIterator(root) {
9305
        return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
9306
      };
9307
      const _isClobbered = function _isClobbered(elm) {
9308
        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' || typeof elm.hasChildNodes !== 'function');
9309
      };
9310
      const _isNode = function _isNode(object) {
9311
        return typeof Node === 'object' ? object instanceof Node : object && typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
9312
      };
9313
      const _executeHook = function _executeHook(entryPoint, currentNode, data) {
9314
        if (!hooks[entryPoint]) {
9315
          return;
9316
        }
9317
        arrayForEach(hooks[entryPoint], hook => {
9318
          hook.call(DOMPurify, currentNode, data, CONFIG);
9319
        });
9320
      };
9321
      const _sanitizeElements = function _sanitizeElements(currentNode) {
9322
        let content;
9323
        _executeHook('beforeSanitizeElements', currentNode, null);
9324
        if (_isClobbered(currentNode)) {
9325
          _forceRemove(currentNode);
9326
          return true;
9327
        }
9328
        const tagName = transformCaseFunc(currentNode.nodeName);
9329
        _executeHook('uponSanitizeElement', currentNode, {
9330
          tagName,
9331
          allowedTags: ALLOWED_TAGS
9332
        });
9333
        if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
9334
          _forceRemove(currentNode);
9335
          return true;
9336
        }
9337
        if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
9338
          if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
9339
            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
9340
              return false;
9341
            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))
9342
              return false;
9343
          }
9344
          if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
9345
            const parentNode = getParentNode(currentNode) || currentNode.parentNode;
9346
            const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
9347
            if (childNodes && parentNode) {
9348
              const childCount = childNodes.length;
9349
              for (let i = childCount - 1; i >= 0; --i) {
9350
                parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
9351
              }
9352
            }
9353
          }
9354
          _forceRemove(currentNode);
9355
          return true;
9356
        }
9357
        if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
9358
          _forceRemove(currentNode);
9359
          return true;
9360
        }
9361
        if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
9362
          _forceRemove(currentNode);
9363
          return true;
9364
        }
9365
        if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
9366
          content = currentNode.textContent;
9367
          content = stringReplace(content, MUSTACHE_EXPR, ' ');
9368
          content = stringReplace(content, ERB_EXPR, ' ');
9369
          content = stringReplace(content, TMPLIT_EXPR, ' ');
9370
          if (currentNode.textContent !== content) {
9371
            arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
9372
            currentNode.textContent = content;
9373
          }
9374
        }
9375
        _executeHook('afterSanitizeElements', currentNode, null);
9376
        return false;
9377
      };
9378
      const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
9379
        if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
9380
          return false;
9381
        }
9382
        if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName));
9383
        else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName));
9384
        else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
9385
          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)));
9386
          else {
9387
            return false;
9388
          }
9389
        } else if (URI_SAFE_ATTRIBUTES[lcName]);
9390
        else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, '')));
9391
        else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
9392
        else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, '')));
9393
        else if (value) {
9394
          return false;
9395
        } else ;
9396
        return true;
9397
      };
9398
      const _basicCustomElementTest = function _basicCustomElementTest(tagName) {
9399
        return tagName.indexOf('-') > 0;
9400
      };
9401
      const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
9402
        let attr;
9403
        let value;
9404
        let lcName;
9405
        let l;
9406
        _executeHook('beforeSanitizeAttributes', currentNode, null);
9407
        const {attributes} = currentNode;
9408
        if (!attributes) {
9409
          return;
9410
        }
9411
        const hookEvent = {
9412
          attrName: '',
9413
          attrValue: '',
9414
          keepAttr: true,
9415
          allowedAttributes: ALLOWED_ATTR
9416
        };
9417
        l = attributes.length;
9418
        while (l--) {
9419
          attr = attributes[l];
9420
          const {name, namespaceURI} = attr;
9421
          value = name === 'value' ? attr.value : stringTrim(attr.value);
9422
          const initValue = value;
9423
          lcName = transformCaseFunc(name);
9424
          hookEvent.attrName = lcName;
9425
          hookEvent.attrValue = value;
9426
          hookEvent.keepAttr = true;
9427
          hookEvent.forceKeepAttr = undefined;
9428
          _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
9429
          value = hookEvent.attrValue;
9430
          if (hookEvent.forceKeepAttr) {
9431
            continue;
9432
          }
9433
          if (!hookEvent.keepAttr) {
9434
            _removeAttribute(name, currentNode);
9435
            continue;
9436
          }
9437
          if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
9438
            _removeAttribute(name, currentNode);
9439
            continue;
9440
          }
9441
          if (SAFE_FOR_TEMPLATES) {
9442
            value = stringReplace(value, MUSTACHE_EXPR, ' ');
9443
            value = stringReplace(value, ERB_EXPR, ' ');
9444
            value = stringReplace(value, TMPLIT_EXPR, ' ');
9445
          }
9446
          const lcTag = transformCaseFunc(currentNode.nodeName);
9447
          if (!_isValidAttribute(lcTag, lcName, value)) {
9448
            _removeAttribute(name, currentNode);
9449
            continue;
9450
          }
9451
          if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
9452
            _removeAttribute(name, currentNode);
9453
            value = SANITIZE_NAMED_PROPS_PREFIX + value;
9454
          }
9455
          if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
9456
            if (namespaceURI);
9457
            else {
9458
              switch (trustedTypes.getAttributeType(lcTag, lcName)) {
9459
              case 'TrustedHTML': {
9460
                  value = trustedTypesPolicy.createHTML(value);
9461
                  break;
9462
                }
9463
              case 'TrustedScriptURL': {
9464
                  value = trustedTypesPolicy.createScriptURL(value);
9465
                  break;
9466
                }
9467
              }
9468
            }
9469
          }
9470
          if (value !== initValue) {
9471
            try {
9472
              if (namespaceURI) {
9473
                currentNode.setAttributeNS(namespaceURI, name, value);
9474
              } else {
9475
                currentNode.setAttribute(name, value);
9476
              }
9477
            } catch (_) {
9478
              _removeAttribute(name, currentNode);
9479
            }
9480
          }
9481
        }
9482
        _executeHook('afterSanitizeAttributes', currentNode, null);
9483
      };
9484
      const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
9485
        let shadowNode;
9486
        const shadowIterator = _createIterator(fragment);
9487
        _executeHook('beforeSanitizeShadowDOM', fragment, null);
9488
        while (shadowNode = shadowIterator.nextNode()) {
9489
          _executeHook('uponSanitizeShadowNode', shadowNode, null);
9490
          if (_sanitizeElements(shadowNode)) {
9491
            continue;
9492
          }
9493
          if (shadowNode.content instanceof DocumentFragment) {
9494
            _sanitizeShadowDOM(shadowNode.content);
9495
          }
9496
          _sanitizeAttributes(shadowNode);
9497
        }
9498
        _executeHook('afterSanitizeShadowDOM', fragment, null);
9499
      };
9500
      DOMPurify.sanitize = function (dirty) {
9501
        let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9502
        let body;
9503
        let importedNode;
9504
        let currentNode;
9505
        let returnNode;
9506
        IS_EMPTY_INPUT = !dirty;
9507
        if (IS_EMPTY_INPUT) {
9508
          dirty = '<!-->';
9509
        }
9510
        if (typeof dirty !== 'string' && !_isNode(dirty)) {
9511
          if (typeof dirty.toString === 'function') {
9512
            dirty = dirty.toString();
9513
            if (typeof dirty !== 'string') {
9514
              throw typeErrorCreate('dirty is not a string, aborting');
9515
            }
9516
          } else {
9517
            throw typeErrorCreate('toString is not a function');
9518
          }
9519
        }
9520
        if (!DOMPurify.isSupported) {
9521
          return dirty;
9522
        }
9523
        if (!SET_CONFIG) {
9524
          _parseConfig(cfg);
9525
        }
9526
        DOMPurify.removed = [];
9527
        if (typeof dirty === 'string') {
9528
          IN_PLACE = false;
9529
        }
9530
        if (IN_PLACE) {
9531
          if (dirty.nodeName) {
9532
            const tagName = transformCaseFunc(dirty.nodeName);
9533
            if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
9534
              throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
9535
            }
9536
          }
9537
        } else if (dirty instanceof Node) {
9538
          body = _initDocument('<!---->');
9539
          importedNode = body.ownerDocument.importNode(dirty, true);
9540
          if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
9541
            body = importedNode;
9542
          } else if (importedNode.nodeName === 'HTML') {
9543
            body = importedNode;
9544
          } else {
9545
            body.appendChild(importedNode);
9546
          }
9547
        } else {
9548
          if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
9549
            return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
9550
          }
9551
          body = _initDocument(dirty);
9552
          if (!body) {
9553
            return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
9554
          }
9555
        }
9556
        if (body && FORCE_BODY) {
9557
          _forceRemove(body.firstChild);
9558
        }
9559
        const nodeIterator = _createIterator(IN_PLACE ? dirty : body);
9560
        while (currentNode = nodeIterator.nextNode()) {
9561
          if (_sanitizeElements(currentNode)) {
9562
            continue;
9563
          }
9564
          if (currentNode.content instanceof DocumentFragment) {
9565
            _sanitizeShadowDOM(currentNode.content);
9566
          }
9567
          _sanitizeAttributes(currentNode);
9568
        }
9569
        if (IN_PLACE) {
9570
          return dirty;
9571
        }
9572
        if (RETURN_DOM) {
9573
          if (RETURN_DOM_FRAGMENT) {
9574
            returnNode = createDocumentFragment.call(body.ownerDocument);
9575
            while (body.firstChild) {
9576
              returnNode.appendChild(body.firstChild);
9577
            }
9578
          } else {
9579
            returnNode = body;
9580
          }
9581
          if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
9582
            returnNode = importNode.call(originalDocument, returnNode, true);
9583
          }
9584
          return returnNode;
9585
        }
9586
        let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
9587
        if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
9588
          serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
9589
        }
9590
        if (SAFE_FOR_TEMPLATES) {
9591
          serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR, ' ');
9592
          serializedHTML = stringReplace(serializedHTML, ERB_EXPR, ' ');
9593
          serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR, ' ');
9594
        }
9595
        return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
9596
      };
9597
      DOMPurify.setConfig = function (cfg) {
9598
        _parseConfig(cfg);
9599
        SET_CONFIG = true;
9600
      };
9601
      DOMPurify.clearConfig = function () {
9602
        CONFIG = null;
9603
        SET_CONFIG = false;
9604
      };
9605
      DOMPurify.isValidAttribute = function (tag, attr, value) {
9606
        if (!CONFIG) {
9607
          _parseConfig({});
9608
        }
9609
        const lcTag = transformCaseFunc(tag);
9610
        const lcName = transformCaseFunc(attr);
9611
        return _isValidAttribute(lcTag, lcName, value);
9612
      };
9613
      DOMPurify.addHook = function (entryPoint, hookFunction) {
9614
        if (typeof hookFunction !== 'function') {
9615
          return;
9616
        }
9617
        hooks[entryPoint] = hooks[entryPoint] || [];
9618
        arrayPush(hooks[entryPoint], hookFunction);
9619
      };
9620
      DOMPurify.removeHook = function (entryPoint) {
9621
        if (hooks[entryPoint]) {
9622
          return arrayPop(hooks[entryPoint]);
9623
        }
9624
      };
9625
      DOMPurify.removeHooks = function (entryPoint) {
9626
        if (hooks[entryPoint]) {
9627
          hooks[entryPoint] = [];
9628
        }
9629
      };
9630
      DOMPurify.removeAllHooks = function () {
9631
        hooks = {};
9632
      };
9633
      return DOMPurify;
9634
    }
9635
    var purify = createDOMPurify();
9636
 
9637
    const sanitizeHtmlString = html => purify().sanitize(html);
9638
 
9639
    var global$8 = tinymce.util.Tools.resolve('tinymce.util.I18n');
9640
 
9641
    const rtlTransform = {
9642
      'indent': true,
9643
      'outdent': true,
9644
      'table-insert-column-after': true,
9645
      'table-insert-column-before': true,
9646
      'paste-column-after': true,
9647
      'paste-column-before': true,
9648
      'unordered-list': true,
9649
      'list-bull-circle': true,
9650
      'list-bull-default': true,
9651
      'list-bull-square': true
9652
    };
9653
    const defaultIconName = 'temporary-placeholder';
9654
    const defaultIcon = icons => () => get$g(icons, defaultIconName).getOr('!not found!');
9655
    const getIconName = (name, icons) => {
9656
      const lcName = name.toLowerCase();
9657
      if (global$8.isRtl()) {
9658
        const rtlName = ensureTrailing(lcName, '-rtl');
9659
        return has$2(icons, rtlName) ? rtlName : lcName;
9660
      } else {
9661
        return lcName;
9662
      }
9663
    };
9664
    const lookupIcon = (name, icons) => get$g(icons, getIconName(name, icons));
9665
    const get$2 = (name, iconProvider) => {
9666
      const icons = iconProvider();
9667
      return lookupIcon(name, icons).getOrThunk(defaultIcon(icons));
9668
    };
9669
    const getOr = (name, iconProvider, fallbackIcon) => {
9670
      const icons = iconProvider();
9671
      return lookupIcon(name, icons).or(fallbackIcon).getOrThunk(defaultIcon(icons));
9672
    };
9673
    const needsRtlTransform = iconName => global$8.isRtl() ? has$2(rtlTransform, iconName) : false;
9674
    const addFocusableBehaviour = () => config('add-focusable', [runOnAttached(comp => {
9675
        child(comp.element, 'svg').each(svg => set$9(svg, 'focusable', 'false'));
9676
      })]);
9677
    const renderIcon$3 = (spec, iconName, icons, fallbackIcon) => {
9678
      var _a, _b;
9679
      const rtlIconClasses = needsRtlTransform(iconName) ? ['tox-icon--flip'] : [];
9680
      const iconHtml = get$g(icons, getIconName(iconName, icons)).or(fallbackIcon).getOrThunk(defaultIcon(icons));
9681
      return {
9682
        dom: {
9683
          tag: spec.tag,
9684
          attributes: (_a = spec.attributes) !== null && _a !== void 0 ? _a : {},
9685
          classes: spec.classes.concat(rtlIconClasses),
9686
          innerHtml: iconHtml
9687
        },
9688
        behaviours: derive$1([
9689
          ...(_b = spec.behaviours) !== null && _b !== void 0 ? _b : [],
9690
          addFocusableBehaviour()
9691
        ])
9692
      };
9693
    };
9694
    const render$3 = (iconName, spec, iconProvider, fallbackIcon = Optional.none()) => renderIcon$3(spec, iconName, iconProvider(), fallbackIcon);
9695
    const renderFirst = (iconNames, spec, iconProvider) => {
9696
      const icons = iconProvider();
9697
      const iconName = find$5(iconNames, name => has$2(icons, getIconName(name, icons)));
9698
      return renderIcon$3(spec, iconName.getOr(defaultIconName), icons, Optional.none());
9699
    };
9700
 
9701
    const notificationIconMap = {
9702
      success: 'checkmark',
9703
      error: 'warning',
9704
      err: 'error',
9705
      warning: 'warning',
9706
      warn: 'warning',
9707
      info: 'info'
9708
    };
9709
    const factory$m = detail => {
9710
      const memBannerText = record({
9711
        dom: fromHtml(`<p>${ sanitizeHtmlString(detail.translationProvider(detail.text)) }</p>`),
9712
        behaviours: derive$1([Replacing.config({})])
9713
      });
9714
      const renderPercentBar = percent => ({
9715
        dom: {
9716
          tag: 'div',
9717
          classes: ['tox-bar'],
9718
          styles: { width: `${ percent }%` }
9719
        }
9720
      });
9721
      const renderPercentText = percent => ({
9722
        dom: {
9723
          tag: 'div',
9724
          classes: ['tox-text'],
9725
          innerHtml: `${ percent }%`
9726
        }
9727
      });
9728
      const memBannerProgress = record({
9729
        dom: {
9730
          tag: 'div',
9731
          classes: detail.progress ? [
9732
            'tox-progress-bar',
9733
            'tox-progress-indicator'
9734
          ] : ['tox-progress-bar']
9735
        },
9736
        components: [
9737
          {
9738
            dom: {
9739
              tag: 'div',
9740
              classes: ['tox-bar-container']
9741
            },
9742
            components: [renderPercentBar(0)]
9743
          },
9744
          renderPercentText(0)
9745
        ],
9746
        behaviours: derive$1([Replacing.config({})])
9747
      });
9748
      const updateProgress = (comp, percent) => {
9749
        if (comp.getSystem().isConnected()) {
9750
          memBannerProgress.getOpt(comp).each(progress => {
9751
            Replacing.set(progress, [
9752
              {
9753
                dom: {
9754
                  tag: 'div',
9755
                  classes: ['tox-bar-container']
9756
                },
9757
                components: [renderPercentBar(percent)]
9758
              },
9759
              renderPercentText(percent)
9760
            ]);
9761
          });
9762
        }
9763
      };
9764
      const updateText = (comp, text) => {
9765
        if (comp.getSystem().isConnected()) {
9766
          const banner = memBannerText.get(comp);
9767
          Replacing.set(banner, [text$2(text)]);
9768
        }
9769
      };
9770
      const apis = {
9771
        updateProgress,
9772
        updateText
9773
      };
9774
      const iconChoices = flatten([
9775
        detail.icon.toArray(),
9776
        detail.level.toArray(),
9777
        detail.level.bind(level => Optional.from(notificationIconMap[level])).toArray()
9778
      ]);
9779
      const memButton = record(Button.sketch({
9780
        dom: {
9781
          tag: 'button',
9782
          classes: [
9783
            'tox-notification__dismiss',
9784
            'tox-button',
9785
            'tox-button--naked',
9786
            'tox-button--icon'
9787
          ]
9788
        },
9789
        components: [render$3('close', {
9790
            tag: 'span',
9791
            classes: ['tox-icon'],
9792
            attributes: { 'aria-label': detail.translationProvider('Close') }
9793
          }, detail.iconProvider)],
9794
        action: comp => {
9795
          detail.onAction(comp);
9796
        }
9797
      }));
9798
      const notificationIconSpec = renderFirst(iconChoices, {
9799
        tag: 'div',
9800
        classes: ['tox-notification__icon']
9801
      }, detail.iconProvider);
9802
      const notificationBodySpec = {
9803
        dom: {
9804
          tag: 'div',
9805
          classes: ['tox-notification__body']
9806
        },
9807
        components: [memBannerText.asSpec()],
9808
        behaviours: derive$1([Replacing.config({})])
9809
      };
9810
      const components = [
9811
        notificationIconSpec,
9812
        notificationBodySpec
9813
      ];
9814
      return {
9815
        uid: detail.uid,
9816
        dom: {
9817
          tag: 'div',
9818
          attributes: { role: 'alert' },
9819
          classes: detail.level.map(level => [
9820
            'tox-notification',
9821
            'tox-notification--in',
9822
            `tox-notification--${ level }`
9823
          ]).getOr([
9824
            'tox-notification',
9825
            'tox-notification--in'
9826
          ])
9827
        },
9828
        behaviours: derive$1([
9829
          Focusing.config({}),
9830
          config('notification-events', [run$1(focusin(), comp => {
9831
              memButton.getOpt(comp).each(Focusing.focus);
9832
            })])
9833
        ]),
9834
        components: components.concat(detail.progress ? [memBannerProgress.asSpec()] : []).concat(!detail.closeButton ? [] : [memButton.asSpec()]),
9835
        apis
9836
      };
9837
    };
9838
    const Notification = single({
9839
      name: 'Notification',
9840
      factory: factory$m,
9841
      configFields: [
9842
        option$3('level'),
9843
        required$1('progress'),
9844
        option$3('icon'),
9845
        required$1('onAction'),
9846
        required$1('text'),
9847
        required$1('iconProvider'),
9848
        required$1('translationProvider'),
9849
        defaultedBoolean('closeButton', true)
9850
      ],
9851
      apis: {
9852
        updateProgress: (apis, comp, percent) => {
9853
          apis.updateProgress(comp, percent);
9854
        },
9855
        updateText: (apis, comp, text) => {
9856
          apis.updateText(comp, text);
9857
        }
9858
      }
9859
    });
9860
 
9861
    var NotificationManagerImpl = (editor, extras, uiMothership) => {
9862
      const sharedBackstage = extras.backstage.shared;
9863
      const getBounds = () => {
9864
        const contentArea = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
9865
        const win$1 = win();
9866
        const x = clamp(win$1.x, contentArea.x, contentArea.right);
9867
        const y = clamp(win$1.y, contentArea.y, contentArea.bottom);
9868
        const right = Math.max(contentArea.right, win$1.right);
9869
        const bottom = Math.max(contentArea.bottom, win$1.bottom);
9870
        return Optional.some(bounds(x, y, right - x, bottom - y));
9871
      };
9872
      const open = (settings, closeCallback) => {
9873
        const close = () => {
9874
          closeCallback();
9875
          InlineView.hide(notificationWrapper);
9876
        };
9877
        const notification = build$1(Notification.sketch({
9878
          text: settings.text,
9879
          level: contains$2([
9880
            'success',
9881
            'error',
9882
            'warning',
9883
            'warn',
9884
            'info'
9885
          ], settings.type) ? settings.type : undefined,
9886
          progress: settings.progressBar === true,
9887
          icon: settings.icon,
9888
          closeButton: settings.closeButton,
9889
          onAction: close,
9890
          iconProvider: sharedBackstage.providers.icons,
9891
          translationProvider: sharedBackstage.providers.translate
9892
        }));
9893
        const notificationWrapper = build$1(InlineView.sketch({
9894
          dom: {
9895
            tag: 'div',
9896
            classes: ['tox-notifications-container']
9897
          },
9898
          lazySink: sharedBackstage.getSink,
9899
          fireDismissalEventInstead: {},
9900
          ...sharedBackstage.header.isPositionedAtTop() ? {} : { fireRepositionEventInstead: {} }
9901
        }));
9902
        uiMothership.add(notificationWrapper);
9903
        if (isNumber(settings.timeout) && settings.timeout > 0) {
9904
          global$9.setEditorTimeout(editor, () => {
9905
            close();
9906
          }, settings.timeout);
9907
        }
9908
        const reposition = () => {
9909
          const notificationSpec = premade(notification);
9910
          const anchorOverrides = { maxHeightFunction: expandable$1() };
9911
          const allNotifications = editor.notificationManager.getNotifications();
9912
          if (allNotifications[0] === thisNotification) {
9913
            const anchor = {
9914
              ...sharedBackstage.anchors.banner(),
9915
              overrides: anchorOverrides
9916
            };
9917
            InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor }, getBounds);
9918
          } else {
9919
            indexOf(allNotifications, thisNotification).each(idx => {
9920
              const previousNotification = allNotifications[idx - 1].getEl();
9921
              const nodeAnchor = {
9922
                type: 'node',
9923
                root: body(),
9924
                node: Optional.some(SugarElement.fromDom(previousNotification)),
9925
                overrides: anchorOverrides,
9926
                layouts: {
9927
                  onRtl: () => [south$2],
9928
                  onLtr: () => [south$2]
9929
                }
9930
              };
9931
              InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor: nodeAnchor }, getBounds);
9932
            });
9933
          }
9934
        };
9935
        const thisNotification = {
9936
          close,
9937
          reposition,
9938
          text: nuText => {
9939
            Notification.updateText(notification, nuText);
9940
          },
9941
          settings,
9942
          getEl: () => notification.element.dom,
9943
          progressBar: {
9944
            value: percent => {
9945
              Notification.updateProgress(notification, percent);
9946
            }
9947
          }
9948
        };
9949
        return thisNotification;
9950
      };
9951
      const close = notification => {
9952
        notification.close();
9953
      };
9954
      const getArgs = notification => {
9955
        return notification.settings;
9956
      };
9957
      return {
9958
        open,
9959
        close,
9960
        getArgs
9961
      };
9962
    };
9963
 
9964
    var global$7 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
9965
 
9966
    var global$6 = tinymce.util.Tools.resolve('tinymce.EditorManager');
9967
 
9968
    var global$5 = tinymce.util.Tools.resolve('tinymce.Env');
9969
 
9970
    var ToolbarMode$1;
9971
    (function (ToolbarMode) {
9972
      ToolbarMode['default'] = 'wrap';
9973
      ToolbarMode['floating'] = 'floating';
9974
      ToolbarMode['sliding'] = 'sliding';
9975
      ToolbarMode['scrolling'] = 'scrolling';
9976
    }(ToolbarMode$1 || (ToolbarMode$1 = {})));
9977
    var ToolbarLocation$1;
9978
    (function (ToolbarLocation) {
9979
      ToolbarLocation['auto'] = 'auto';
9980
      ToolbarLocation['top'] = 'top';
9981
      ToolbarLocation['bottom'] = 'bottom';
9982
    }(ToolbarLocation$1 || (ToolbarLocation$1 = {})));
9983
    const option$2 = name => editor => editor.options.get(name);
9984
    const wrapOptional = fn => editor => Optional.from(fn(editor));
9985
    const register$e = editor => {
9986
      const isPhone = global$5.deviceType.isPhone();
9987
      const isMobile = global$5.deviceType.isTablet() || isPhone;
9988
      const registerOption = editor.options.register;
9989
      const stringOrFalseProcessor = value => isString(value) || value === false;
9990
      const stringOrNumberProcessor = value => isString(value) || isNumber(value);
9991
      registerOption('skin', {
9992
        processor: value => isString(value) || value === false,
9993
        default: 'oxide'
9994
      });
9995
      registerOption('skin_url', { processor: 'string' });
9996
      registerOption('height', {
9997
        processor: stringOrNumberProcessor,
9998
        default: Math.max(editor.getElement().offsetHeight, 400)
9999
      });
10000
      registerOption('width', {
10001
        processor: stringOrNumberProcessor,
10002
        default: global$7.DOM.getStyle(editor.getElement(), 'width')
10003
      });
10004
      registerOption('min_height', {
10005
        processor: 'number',
10006
        default: 100
10007
      });
10008
      registerOption('min_width', { processor: 'number' });
10009
      registerOption('max_height', { processor: 'number' });
10010
      registerOption('max_width', { processor: 'number' });
10011
      registerOption('style_formats', { processor: 'object[]' });
10012
      registerOption('style_formats_merge', {
10013
        processor: 'boolean',
10014
        default: false
10015
      });
10016
      registerOption('style_formats_autohide', {
10017
        processor: 'boolean',
10018
        default: false
10019
      });
10020
      registerOption('line_height_formats', {
10021
        processor: 'string',
10022
        default: '1 1.1 1.2 1.3 1.4 1.5 2'
10023
      });
10024
      registerOption('font_family_formats', {
10025
        processor: 'string',
10026
        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'
10027
      });
10028
      registerOption('font_size_formats', {
10029
        processor: 'string',
10030
        default: '8pt 10pt 12pt 14pt 18pt 24pt 36pt'
10031
      });
10032
      registerOption('font_size_input_default_unit', {
10033
        processor: 'string',
10034
        default: 'pt'
10035
      });
10036
      registerOption('block_formats', {
10037
        processor: 'string',
10038
        default: 'Paragraph=p;' + 'Heading 1=h1;' + 'Heading 2=h2;' + 'Heading 3=h3;' + 'Heading 4=h4;' + 'Heading 5=h5;' + 'Heading 6=h6;' + 'Preformatted=pre'
10039
      });
10040
      registerOption('content_langs', { processor: 'object[]' });
10041
      registerOption('removed_menuitems', {
10042
        processor: 'string',
10043
        default: ''
10044
      });
10045
      registerOption('menubar', {
10046
        processor: value => isString(value) || isBoolean(value),
10047
        default: !isPhone
10048
      });
10049
      registerOption('menu', {
10050
        processor: 'object',
10051
        default: {}
10052
      });
10053
      registerOption('toolbar', {
10054
        processor: value => {
10055
          if (isBoolean(value) || isString(value) || isArray(value)) {
10056
            return {
10057
              value,
10058
              valid: true
10059
            };
10060
          } else {
10061
            return {
10062
              valid: false,
10063
              message: 'Must be a boolean, string or array.'
10064
            };
10065
          }
10066
        },
10067
        default: true
10068
      });
10069
      range$2(9, num => {
10070
        registerOption('toolbar' + (num + 1), { processor: 'string' });
10071
      });
10072
      registerOption('toolbar_mode', {
10073
        processor: 'string',
10074
        default: isMobile ? 'scrolling' : 'floating'
10075
      });
10076
      registerOption('toolbar_groups', {
10077
        processor: 'object',
10078
        default: {}
10079
      });
10080
      registerOption('toolbar_location', {
10081
        processor: 'string',
10082
        default: ToolbarLocation$1.auto
10083
      });
10084
      registerOption('toolbar_persist', {
10085
        processor: 'boolean',
10086
        default: false
10087
      });
10088
      registerOption('toolbar_sticky', {
10089
        processor: 'boolean',
10090
        default: editor.inline
10091
      });
10092
      registerOption('toolbar_sticky_offset', {
10093
        processor: 'number',
10094
        default: 0
10095
      });
10096
      registerOption('fixed_toolbar_container', {
10097
        processor: 'string',
10098
        default: ''
10099
      });
10100
      registerOption('fixed_toolbar_container_target', { processor: 'object' });
10101
      registerOption('ui_mode', {
10102
        processor: 'string',
10103
        default: 'combined'
10104
      });
10105
      registerOption('file_picker_callback', { processor: 'function' });
10106
      registerOption('file_picker_validator_handler', { processor: 'function' });
10107
      registerOption('file_picker_types', { processor: 'string' });
10108
      registerOption('typeahead_urls', {
10109
        processor: 'boolean',
10110
        default: true
10111
      });
10112
      registerOption('anchor_top', {
10113
        processor: stringOrFalseProcessor,
10114
        default: '#top'
10115
      });
10116
      registerOption('anchor_bottom', {
10117
        processor: stringOrFalseProcessor,
10118
        default: '#bottom'
10119
      });
10120
      registerOption('draggable_modal', {
10121
        processor: 'boolean',
10122
        default: false
10123
      });
10124
      registerOption('statusbar', {
10125
        processor: 'boolean',
10126
        default: true
10127
      });
10128
      registerOption('elementpath', {
10129
        processor: 'boolean',
10130
        default: true
10131
      });
10132
      registerOption('branding', {
10133
        processor: 'boolean',
10134
        default: true
10135
      });
10136
      registerOption('promotion', {
10137
        processor: 'boolean',
10138
        default: true
10139
      });
10140
      registerOption('resize', {
10141
        processor: value => value === 'both' || isBoolean(value),
10142
        default: !global$5.deviceType.isTouch()
10143
      });
10144
      registerOption('sidebar_show', { processor: 'string' });
10145
      registerOption('help_accessibility', {
10146
        processor: 'boolean',
10147
        default: editor.hasPlugin('help')
10148
      });
10149
      registerOption('default_font_stack', {
10150
        processor: 'string[]',
10151
        default: []
10152
      });
10153
    };
10154
    const isReadOnly = option$2('readonly');
10155
    const getHeightOption = option$2('height');
10156
    const getWidthOption = option$2('width');
10157
    const getMinWidthOption = wrapOptional(option$2('min_width'));
10158
    const getMinHeightOption = wrapOptional(option$2('min_height'));
10159
    const getMaxWidthOption = wrapOptional(option$2('max_width'));
10160
    const getMaxHeightOption = wrapOptional(option$2('max_height'));
10161
    const getUserStyleFormats = wrapOptional(option$2('style_formats'));
10162
    const shouldMergeStyleFormats = option$2('style_formats_merge');
10163
    const shouldAutoHideStyleFormats = option$2('style_formats_autohide');
10164
    const getContentLanguages = option$2('content_langs');
10165
    const getRemovedMenuItems = option$2('removed_menuitems');
10166
    const getToolbarMode = option$2('toolbar_mode');
10167
    const getToolbarGroups = option$2('toolbar_groups');
10168
    const getToolbarLocation = option$2('toolbar_location');
10169
    const fixedContainerSelector = option$2('fixed_toolbar_container');
10170
    const fixedToolbarContainerTarget = option$2('fixed_toolbar_container_target');
10171
    const isToolbarPersist = option$2('toolbar_persist');
10172
    const getStickyToolbarOffset = option$2('toolbar_sticky_offset');
10173
    const getMenubar = option$2('menubar');
10174
    const getToolbar = option$2('toolbar');
10175
    const getFilePickerCallback = option$2('file_picker_callback');
10176
    const getFilePickerValidatorHandler = option$2('file_picker_validator_handler');
10177
    const getFontSizeInputDefaultUnit = option$2('font_size_input_default_unit');
10178
    const getFilePickerTypes = option$2('file_picker_types');
10179
    const useTypeaheadUrls = option$2('typeahead_urls');
10180
    const getAnchorTop = option$2('anchor_top');
10181
    const getAnchorBottom = option$2('anchor_bottom');
10182
    const isDraggableModal$1 = option$2('draggable_modal');
10183
    const useStatusBar = option$2('statusbar');
10184
    const useElementPath = option$2('elementpath');
10185
    const useBranding = option$2('branding');
10186
    const getResize = option$2('resize');
10187
    const getPasteAsText = option$2('paste_as_text');
10188
    const getSidebarShow = option$2('sidebar_show');
10189
    const promotionEnabled = option$2('promotion');
10190
    const useHelpAccessibility = option$2('help_accessibility');
10191
    const getDefaultFontStack = option$2('default_font_stack');
10192
    const isSkinDisabled = editor => editor.options.get('skin') === false;
10193
    const isMenubarEnabled = editor => editor.options.get('menubar') !== false;
10194
    const getSkinUrl = editor => {
10195
      const skinUrl = editor.options.get('skin_url');
10196
      if (isSkinDisabled(editor)) {
10197
        return skinUrl;
10198
      } else {
10199
        if (skinUrl) {
10200
          return editor.documentBaseURI.toAbsolute(skinUrl);
10201
        } else {
10202
          const skin = editor.options.get('skin');
10203
          return global$6.baseURL + '/skins/ui/' + skin;
10204
        }
10205
      }
10206
    };
10207
    const getSkinUrlOption = editor => Optional.from(editor.options.get('skin_url'));
10208
    const getLineHeightFormats = editor => editor.options.get('line_height_formats').split(' ');
10209
    const isToolbarEnabled = editor => {
10210
      const toolbar = getToolbar(editor);
10211
      const isToolbarString = isString(toolbar);
10212
      const isToolbarObjectArray = isArray(toolbar) && toolbar.length > 0;
10213
      return !isMultipleToolbars(editor) && (isToolbarObjectArray || isToolbarString || toolbar === true);
10214
    };
10215
    const getMultipleToolbarsOption = editor => {
10216
      const toolbars = range$2(9, num => editor.options.get('toolbar' + (num + 1)));
10217
      const toolbarArray = filter$2(toolbars, isString);
10218
      return someIf(toolbarArray.length > 0, toolbarArray);
10219
    };
10220
    const isMultipleToolbars = editor => getMultipleToolbarsOption(editor).fold(() => {
10221
      const toolbar = getToolbar(editor);
10222
      return isArrayOf(toolbar, isString) && toolbar.length > 0;
10223
    }, always);
10224
    const isToolbarLocationBottom = editor => getToolbarLocation(editor) === ToolbarLocation$1.bottom;
10225
    const fixedContainerTarget = editor => {
10226
      var _a;
10227
      if (!editor.inline) {
10228
        return Optional.none();
10229
      }
10230
      const selector = (_a = fixedContainerSelector(editor)) !== null && _a !== void 0 ? _a : '';
10231
      if (selector.length > 0) {
10232
        return descendant(body(), selector);
10233
      }
10234
      const element = fixedToolbarContainerTarget(editor);
10235
      if (isNonNullable(element)) {
10236
        return Optional.some(SugarElement.fromDom(element));
10237
      }
10238
      return Optional.none();
10239
    };
10240
    const useFixedContainer = editor => editor.inline && fixedContainerTarget(editor).isSome();
10241
    const getUiContainer = editor => {
10242
      const fixedContainer = fixedContainerTarget(editor);
10243
      return fixedContainer.getOrThunk(() => getContentContainer(getRootNode(SugarElement.fromDom(editor.getElement()))));
10244
    };
10245
    const isDistractionFree = editor => editor.inline && !isMenubarEnabled(editor) && !isToolbarEnabled(editor) && !isMultipleToolbars(editor);
10246
    const isStickyToolbar = editor => {
10247
      const isStickyToolbar = editor.options.get('toolbar_sticky');
10248
      return (isStickyToolbar || editor.inline) && !useFixedContainer(editor) && !isDistractionFree(editor);
10249
    };
10250
    const isSplitUiMode = editor => !useFixedContainer(editor) && editor.options.get('ui_mode') === 'split';
10251
    const getMenus = editor => {
10252
      const menu = editor.options.get('menu');
10253
      return map$1(menu, menu => ({
10254
        ...menu,
10255
        items: menu.items
10256
      }));
10257
    };
10258
 
10259
    var Options = /*#__PURE__*/Object.freeze({
10260
        __proto__: null,
10261
        get ToolbarMode () { return ToolbarMode$1; },
10262
        get ToolbarLocation () { return ToolbarLocation$1; },
10263
        register: register$e,
10264
        getSkinUrl: getSkinUrl,
10265
        getSkinUrlOption: getSkinUrlOption,
10266
        isReadOnly: isReadOnly,
10267
        isSkinDisabled: isSkinDisabled,
10268
        getHeightOption: getHeightOption,
10269
        getWidthOption: getWidthOption,
10270
        getMinWidthOption: getMinWidthOption,
10271
        getMinHeightOption: getMinHeightOption,
10272
        getMaxWidthOption: getMaxWidthOption,
10273
        getMaxHeightOption: getMaxHeightOption,
10274
        getUserStyleFormats: getUserStyleFormats,
10275
        shouldMergeStyleFormats: shouldMergeStyleFormats,
10276
        shouldAutoHideStyleFormats: shouldAutoHideStyleFormats,
10277
        getLineHeightFormats: getLineHeightFormats,
10278
        getContentLanguages: getContentLanguages,
10279
        getRemovedMenuItems: getRemovedMenuItems,
10280
        isMenubarEnabled: isMenubarEnabled,
10281
        isMultipleToolbars: isMultipleToolbars,
10282
        isToolbarEnabled: isToolbarEnabled,
10283
        isToolbarPersist: isToolbarPersist,
10284
        getMultipleToolbarsOption: getMultipleToolbarsOption,
10285
        getUiContainer: getUiContainer,
10286
        useFixedContainer: useFixedContainer,
10287
        isSplitUiMode: isSplitUiMode,
10288
        getToolbarMode: getToolbarMode,
10289
        isDraggableModal: isDraggableModal$1,
10290
        isDistractionFree: isDistractionFree,
10291
        isStickyToolbar: isStickyToolbar,
10292
        getStickyToolbarOffset: getStickyToolbarOffset,
10293
        getToolbarLocation: getToolbarLocation,
10294
        isToolbarLocationBottom: isToolbarLocationBottom,
10295
        getToolbarGroups: getToolbarGroups,
10296
        getMenus: getMenus,
10297
        getMenubar: getMenubar,
10298
        getToolbar: getToolbar,
10299
        getFilePickerCallback: getFilePickerCallback,
10300
        getFilePickerTypes: getFilePickerTypes,
10301
        useTypeaheadUrls: useTypeaheadUrls,
10302
        getAnchorTop: getAnchorTop,
10303
        getAnchorBottom: getAnchorBottom,
10304
        getFilePickerValidatorHandler: getFilePickerValidatorHandler,
10305
        getFontSizeInputDefaultUnit: getFontSizeInputDefaultUnit,
10306
        useStatusBar: useStatusBar,
10307
        useElementPath: useElementPath,
10308
        promotionEnabled: promotionEnabled,
10309
        useBranding: useBranding,
10310
        getResize: getResize,
10311
        getPasteAsText: getPasteAsText,
10312
        getSidebarShow: getSidebarShow,
10313
        useHelpAccessibility: useHelpAccessibility,
10314
        getDefaultFontStack: getDefaultFontStack
10315
    });
10316
 
10317
    const autocompleteSelector = '[data-mce-autocompleter]';
10318
    const detect$1 = elm => closest$1(elm, autocompleteSelector);
10319
    const findIn = elm => descendant(elm, autocompleteSelector);
10320
 
10321
    const setup$e = (api, editor) => {
10322
      const redirectKeyToItem = (item, e) => {
10323
        emitWith(item, keydown(), { raw: e });
10324
      };
10325
      const getItem = () => api.getMenu().bind(Highlighting.getHighlighted);
10326
      editor.on('keydown', e => {
10327
        const keyCode = e.which;
10328
        if (!api.isActive()) {
10329
          return;
10330
        }
10331
        if (api.isMenuOpen()) {
10332
          if (keyCode === 13) {
10333
            getItem().each(emitExecute);
10334
            e.preventDefault();
10335
          } else if (keyCode === 40) {
10336
            getItem().fold(() => {
10337
              api.getMenu().each(Highlighting.highlightFirst);
10338
            }, item => {
10339
              redirectKeyToItem(item, e);
10340
            });
10341
            e.preventDefault();
10342
            e.stopImmediatePropagation();
10343
          } else if (keyCode === 37 || keyCode === 38 || keyCode === 39) {
10344
            getItem().each(item => {
10345
              redirectKeyToItem(item, e);
10346
              e.preventDefault();
10347
              e.stopImmediatePropagation();
10348
            });
10349
          }
10350
        } else {
10351
          if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
10352
            api.cancelIfNecessary();
10353
          }
10354
        }
10355
      });
10356
      editor.on('NodeChange', e => {
10357
        if (api.isActive() && !api.isProcessingAction() && detect$1(SugarElement.fromDom(e.element)).isNone()) {
10358
          api.cancelIfNecessary();
10359
        }
10360
      });
10361
    };
10362
    const AutocompleterEditorEvents = { setup: setup$e };
10363
 
10364
    var ItemResponse;
10365
    (function (ItemResponse) {
10366
      ItemResponse[ItemResponse['CLOSE_ON_EXECUTE'] = 0] = 'CLOSE_ON_EXECUTE';
10367
      ItemResponse[ItemResponse['BUBBLE_TO_SANDBOX'] = 1] = 'BUBBLE_TO_SANDBOX';
10368
    }(ItemResponse || (ItemResponse = {})));
10369
    var ItemResponse$1 = ItemResponse;
10370
 
10371
    const navClass = 'tox-menu-nav__js';
10372
    const selectableClass = 'tox-collection__item';
10373
    const colorClass = 'tox-swatch';
10374
    const presetClasses = {
10375
      normal: navClass,
10376
      color: colorClass
10377
    };
10378
    const tickedClass = 'tox-collection__item--enabled';
10379
    const groupHeadingClass = 'tox-collection__group-heading';
10380
    const iconClass = 'tox-collection__item-icon';
10381
    const textClass = 'tox-collection__item-label';
10382
    const accessoryClass = 'tox-collection__item-accessory';
10383
    const caretClass = 'tox-collection__item-caret';
10384
    const checkmarkClass = 'tox-collection__item-checkmark';
10385
    const activeClass = 'tox-collection__item--active';
10386
    const containerClass = 'tox-collection__item-container';
10387
    const containerColumnClass = 'tox-collection__item-container--column';
10388
    const containerRowClass = 'tox-collection__item-container--row';
10389
    const containerAlignRightClass = 'tox-collection__item-container--align-right';
10390
    const containerAlignLeftClass = 'tox-collection__item-container--align-left';
10391
    const containerValignTopClass = 'tox-collection__item-container--valign-top';
10392
    const containerValignMiddleClass = 'tox-collection__item-container--valign-middle';
10393
    const containerValignBottomClass = 'tox-collection__item-container--valign-bottom';
10394
    const classForPreset = presets => get$g(presetClasses, presets).getOr(navClass);
10395
 
10396
    const forMenu = presets => {
10397
      if (presets === 'color') {
10398
        return 'tox-swatches';
10399
      } else {
10400
        return 'tox-menu';
10401
      }
10402
    };
10403
    const classes = presets => ({
10404
      backgroundMenu: 'tox-background-menu',
10405
      selectedMenu: 'tox-selected-menu',
10406
      selectedItem: 'tox-collection__item--active',
10407
      hasIcons: 'tox-menu--has-icons',
10408
      menu: forMenu(presets),
10409
      tieredMenu: 'tox-tiered-menu'
10410
    });
10411
 
10412
    const markers = presets => {
10413
      const menuClasses = classes(presets);
10414
      return {
10415
        backgroundMenu: menuClasses.backgroundMenu,
10416
        selectedMenu: menuClasses.selectedMenu,
10417
        menu: menuClasses.menu,
10418
        selectedItem: menuClasses.selectedItem,
10419
        item: classForPreset(presets)
10420
      };
10421
    };
10422
    const dom$1 = (hasIcons, columns, presets) => {
10423
      const menuClasses = classes(presets);
10424
      return {
10425
        tag: 'div',
10426
        classes: flatten([
10427
          [
10428
            menuClasses.menu,
10429
            `tox-menu-${ columns }-column`
10430
          ],
10431
          hasIcons ? [menuClasses.hasIcons] : []
10432
        ])
10433
      };
10434
    };
10435
    const components = [Menu.parts.items({})];
10436
    const part = (hasIcons, columns, presets) => {
10437
      const menuClasses = classes(presets);
10438
      const d = {
10439
        tag: 'div',
10440
        classes: flatten([[menuClasses.tieredMenu]])
10441
      };
10442
      return {
10443
        dom: d,
10444
        markers: markers(presets)
10445
      };
10446
    };
10447
 
10448
    const schema$l = constant$1([
10449
      option$3('data'),
10450
      defaulted('inputAttributes', {}),
10451
      defaulted('inputStyles', {}),
10452
      defaulted('tag', 'input'),
10453
      defaulted('inputClasses', []),
10454
      onHandler('onSetValue'),
10455
      defaulted('styles', {}),
10456
      defaulted('eventOrder', {}),
10457
      field('inputBehaviours', [
10458
        Representing,
10459
        Focusing
10460
      ]),
10461
      defaulted('selectOnFocus', true)
10462
    ]);
10463
    const focusBehaviours = detail => derive$1([Focusing.config({
10464
        onFocus: !detail.selectOnFocus ? noop : component => {
10465
          const input = component.element;
10466
          const value = get$6(input);
10467
          input.dom.setSelectionRange(0, value.length);
10468
        }
10469
      })]);
10470
    const behaviours = detail => ({
10471
      ...focusBehaviours(detail),
10472
      ...augment(detail.inputBehaviours, [Representing.config({
10473
          store: {
10474
            mode: 'manual',
10475
            ...detail.data.map(data => ({ initialValue: data })).getOr({}),
10476
            getValue: input => {
10477
              return get$6(input.element);
10478
            },
10479
            setValue: (input, data) => {
10480
              const current = get$6(input.element);
10481
              if (current !== data) {
10482
                set$5(input.element, data);
10483
              }
10484
            }
10485
          },
10486
          onSetValue: detail.onSetValue
10487
        })])
10488
    });
10489
    const dom = detail => ({
10490
      tag: detail.tag,
10491
      attributes: {
10492
        type: 'text',
10493
        ...detail.inputAttributes
10494
      },
10495
      styles: detail.inputStyles,
10496
      classes: detail.inputClasses
10497
    });
10498
 
10499
    const factory$l = (detail, _spec) => ({
10500
      uid: detail.uid,
10501
      dom: dom(detail),
10502
      components: [],
10503
      behaviours: behaviours(detail),
10504
      eventOrder: detail.eventOrder
10505
    });
10506
    const Input = single({
10507
      name: 'Input',
10508
      configFields: schema$l(),
10509
      factory: factory$l
10510
    });
10511
 
10512
    const refetchTriggerEvent = generate$6('refetch-trigger-event');
10513
    const redirectMenuItemInteractionEvent = generate$6('redirect-menu-item-interaction');
10514
 
10515
    const menuSearcherClass = 'tox-menu__searcher';
10516
    const findWithinSandbox = sandboxComp => {
10517
      return descendant(sandboxComp.element, `.${ menuSearcherClass }`).bind(inputElem => sandboxComp.getSystem().getByDom(inputElem).toOptional());
10518
    };
10519
    const findWithinMenu = findWithinSandbox;
10520
    const restoreState = (inputComp, searcherState) => {
10521
      Representing.setValue(inputComp, searcherState.fetchPattern);
10522
      inputComp.element.dom.selectionStart = searcherState.selectionStart;
10523
      inputComp.element.dom.selectionEnd = searcherState.selectionEnd;
10524
    };
10525
    const saveState = inputComp => {
10526
      const fetchPattern = Representing.getValue(inputComp);
10527
      const selectionStart = inputComp.element.dom.selectionStart;
10528
      const selectionEnd = inputComp.element.dom.selectionEnd;
10529
      return {
10530
        fetchPattern,
10531
        selectionStart,
10532
        selectionEnd
10533
      };
10534
    };
10535
    const setActiveDescendant = (inputComp, active) => {
10536
      getOpt(active.element, 'id').each(id => set$9(inputComp.element, 'aria-activedescendant', id));
10537
    };
10538
    const renderMenuSearcher = spec => {
10539
      const handleByBrowser = (comp, se) => {
10540
        se.cut();
10541
        return Optional.none();
10542
      };
10543
      const handleByHighlightedItem = (comp, se) => {
10544
        const eventData = {
10545
          interactionEvent: se.event,
10546
          eventType: se.event.raw.type
10547
        };
10548
        emitWith(comp, redirectMenuItemInteractionEvent, eventData);
10549
        return Optional.some(true);
10550
      };
10551
      const customSearcherEventsName = 'searcher-events';
10552
      return {
10553
        dom: {
10554
          tag: 'div',
10555
          classes: [selectableClass]
10556
        },
10557
        components: [Input.sketch({
10558
            inputClasses: [
10559
              menuSearcherClass,
10560
              'tox-textfield'
10561
            ],
10562
            inputAttributes: {
10563
              ...spec.placeholder.map(placeholder => ({ placeholder: spec.i18n(placeholder) })).getOr({}),
10564
              'type': 'search',
10565
              'aria-autocomplete': 'list'
10566
            },
10567
            inputBehaviours: derive$1([
10568
              config(customSearcherEventsName, [
10569
                run$1(input(), inputComp => {
10570
                  emit(inputComp, refetchTriggerEvent);
10571
                }),
10572
                run$1(keydown(), (inputComp, se) => {
10573
                  if (se.event.raw.key === 'Escape') {
10574
                    se.stop();
10575
                  }
10576
                })
10577
              ]),
10578
              Keying.config({
10579
                mode: 'special',
10580
                onLeft: handleByBrowser,
10581
                onRight: handleByBrowser,
10582
                onSpace: handleByBrowser,
10583
                onEnter: handleByHighlightedItem,
10584
                onEscape: handleByHighlightedItem,
10585
                onUp: handleByHighlightedItem,
10586
                onDown: handleByHighlightedItem
10587
              })
10588
            ]),
10589
            eventOrder: {
10590
              keydown: [
10591
                customSearcherEventsName,
10592
                Keying.name()
10593
              ]
10594
            }
10595
          })]
10596
      };
10597
    };
10598
 
10599
    const searchResultsClass = 'tox-collection--results__js';
10600
    const augmentWithAria = item => {
10601
      var _a;
10602
      if (item.dom) {
10603
        return {
10604
          ...item,
10605
          dom: {
10606
            ...item.dom,
10607
            attributes: {
10608
              ...(_a = item.dom.attributes) !== null && _a !== void 0 ? _a : {},
10609
              'id': generate$6('aria-item-search-result-id'),
10610
              'aria-selected': 'false'
10611
            }
10612
          }
10613
        };
10614
      } else {
10615
        return item;
10616
      }
10617
    };
10618
 
10619
    const chunk = (rowDom, numColumns) => items => {
10620
      const chunks = chunk$1(items, numColumns);
10621
      return map$2(chunks, c => ({
10622
        dom: rowDom,
10623
        components: c
10624
      }));
10625
    };
10626
    const forSwatch = columns => ({
10627
      dom: {
10628
        tag: 'div',
10629
        classes: [
10630
          'tox-menu',
10631
          'tox-swatches-menu'
10632
        ]
10633
      },
10634
      components: [{
10635
          dom: {
10636
            tag: 'div',
10637
            classes: ['tox-swatches']
10638
          },
10639
          components: [Menu.parts.items({
10640
              preprocess: columns !== 'auto' ? chunk({
10641
                tag: 'div',
10642
                classes: ['tox-swatches__row']
10643
              }, columns) : identity
10644
            })]
10645
        }]
10646
    });
10647
    const forToolbar = columns => ({
10648
      dom: {
10649
        tag: 'div',
10650
        classes: [
10651
          'tox-menu',
10652
          'tox-collection',
10653
          'tox-collection--toolbar',
10654
          'tox-collection--toolbar-lg'
10655
        ]
10656
      },
10657
      components: [Menu.parts.items({
10658
          preprocess: chunk({
10659
            tag: 'div',
10660
            classes: ['tox-collection__group']
10661
          }, columns)
10662
        })]
10663
    });
10664
    const preprocessCollection = (items, isSeparator) => {
10665
      const allSplits = [];
10666
      let currentSplit = [];
10667
      each$1(items, (item, i) => {
10668
        if (isSeparator(item, i)) {
10669
          if (currentSplit.length > 0) {
10670
            allSplits.push(currentSplit);
10671
          }
10672
          currentSplit = [];
10673
          if (has$2(item.dom, 'innerHtml') || item.components && item.components.length > 0) {
10674
            currentSplit.push(item);
10675
          }
10676
        } else {
10677
          currentSplit.push(item);
10678
        }
10679
      });
10680
      if (currentSplit.length > 0) {
10681
        allSplits.push(currentSplit);
10682
      }
10683
      return map$2(allSplits, s => ({
10684
        dom: {
10685
          tag: 'div',
10686
          classes: ['tox-collection__group']
10687
        },
10688
        components: s
10689
      }));
10690
    };
10691
    const insertItemsPlaceholder = (columns, initItems, onItem) => {
10692
      return Menu.parts.items({
10693
        preprocess: rawItems => {
10694
          const enrichedItems = map$2(rawItems, onItem);
10695
          if (columns !== 'auto' && columns > 1) {
10696
            return chunk({
10697
              tag: 'div',
10698
              classes: ['tox-collection__group']
10699
            }, columns)(enrichedItems);
10700
          } else {
10701
            return preprocessCollection(enrichedItems, (_item, i) => initItems[i].type === 'separator');
10702
          }
10703
        }
10704
      });
10705
    };
10706
    const forCollection = (columns, initItems, _hasIcons = true) => ({
10707
      dom: {
10708
        tag: 'div',
10709
        classes: [
10710
          'tox-menu',
10711
          'tox-collection'
10712
        ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
10713
      },
10714
      components: [insertItemsPlaceholder(columns, initItems, identity)]
10715
    });
10716
    const forCollectionWithSearchResults = (columns, initItems, _hasIcons = true) => {
10717
      const ariaControlsSearchResults = generate$6('aria-controls-search-results');
10718
      return {
10719
        dom: {
10720
          tag: 'div',
10721
          classes: [
10722
            'tox-menu',
10723
            'tox-collection',
10724
            searchResultsClass
10725
          ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid']),
10726
          attributes: { id: ariaControlsSearchResults }
10727
        },
10728
        components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
10729
      };
10730
    };
10731
    const forCollectionWithSearchField = (columns, initItems, searchField) => {
10732
      const ariaControlsSearchResults = generate$6('aria-controls-search-results');
10733
      return {
10734
        dom: {
10735
          tag: 'div',
10736
          classes: [
10737
            'tox-menu',
10738
            'tox-collection'
10739
          ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
10740
        },
10741
        components: [
10742
          renderMenuSearcher({
10743
            i18n: global$8.translate,
10744
            placeholder: searchField.placeholder
10745
          }),
10746
          {
10747
            dom: {
10748
              tag: 'div',
10749
              classes: [
10750
                ...columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'],
10751
                searchResultsClass
10752
              ],
10753
              attributes: { id: ariaControlsSearchResults }
10754
            },
10755
            components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
10756
          }
10757
        ]
10758
      };
10759
    };
10760
    const forHorizontalCollection = (initItems, _hasIcons = true) => ({
10761
      dom: {
10762
        tag: 'div',
10763
        classes: [
10764
          'tox-collection',
10765
          'tox-collection--horizontal'
10766
        ]
10767
      },
10768
      components: [Menu.parts.items({ preprocess: items => preprocessCollection(items, (_item, i) => initItems[i].type === 'separator') })]
10769
    });
10770
 
10771
    const menuHasIcons = xs => exists(xs, item => 'icon' in item && item.icon !== undefined);
10772
    const handleError = error => {
10773
      console.error(formatError(error));
10774
      console.log(error);
10775
      return Optional.none();
10776
    };
10777
    const createHorizontalPartialMenuWithAlloyItems = (value, _hasIcons, items, _columns, _menuLayout) => {
10778
      const structure = forHorizontalCollection(items);
10779
      return {
10780
        value,
10781
        dom: structure.dom,
10782
        components: structure.components,
10783
        items
10784
      };
10785
    };
10786
    const createPartialMenuWithAlloyItems = (value, hasIcons, items, columns, menuLayout) => {
10787
      const getNormalStructure = () => {
10788
        if (menuLayout.menuType !== 'searchable') {
10789
          return forCollection(columns, items);
10790
        } else {
10791
          return menuLayout.searchMode.searchMode === 'search-with-field' ? forCollectionWithSearchField(columns, items, menuLayout.searchMode) : forCollectionWithSearchResults(columns, items);
10792
        }
10793
      };
10794
      if (menuLayout.menuType === 'color') {
10795
        const structure = forSwatch(columns);
10796
        return {
10797
          value,
10798
          dom: structure.dom,
10799
          components: structure.components,
10800
          items
10801
        };
10802
      } else if (menuLayout.menuType === 'normal' && columns === 'auto') {
10803
        const structure = forCollection(columns, items);
10804
        return {
10805
          value,
10806
          dom: structure.dom,
10807
          components: structure.components,
10808
          items
10809
        };
10810
      } else if (menuLayout.menuType === 'normal' || menuLayout.menuType === 'searchable') {
10811
        const structure = getNormalStructure();
10812
        return {
10813
          value,
10814
          dom: structure.dom,
10815
          components: structure.components,
10816
          items
10817
        };
10818
      } else if (menuLayout.menuType === 'listpreview' && columns !== 'auto') {
10819
        const structure = forToolbar(columns);
10820
        return {
10821
          value,
10822
          dom: structure.dom,
10823
          components: structure.components,
10824
          items
10825
        };
10826
      } else {
10827
        return {
10828
          value,
10829
          dom: dom$1(hasIcons, columns, menuLayout.menuType),
10830
          components: components,
10831
          items
10832
        };
10833
      }
10834
    };
10835
 
10836
    const type = requiredString('type');
10837
    const name$1 = requiredString('name');
10838
    const label = requiredString('label');
10839
    const text = requiredString('text');
10840
    const title = requiredString('title');
10841
    const icon = requiredString('icon');
10842
    const value$1 = requiredString('value');
10843
    const fetch$1 = requiredFunction('fetch');
10844
    const getSubmenuItems = requiredFunction('getSubmenuItems');
10845
    const onAction = requiredFunction('onAction');
10846
    const onItemAction = requiredFunction('onItemAction');
10847
    const onSetup = defaultedFunction('onSetup', () => noop);
10848
    const optionalName = optionString('name');
10849
    const optionalText = optionString('text');
10850
    const optionalIcon = optionString('icon');
10851
    const optionalTooltip = optionString('tooltip');
10852
    const optionalLabel = optionString('label');
10853
    const optionalShortcut = optionString('shortcut');
10854
    const optionalSelect = optionFunction('select');
10855
    const active = defaultedBoolean('active', false);
10856
    const borderless = defaultedBoolean('borderless', false);
10857
    const enabled = defaultedBoolean('enabled', true);
10858
    const primary = defaultedBoolean('primary', false);
10859
    const defaultedColumns = num => defaulted('columns', num);
10860
    const defaultedMeta = defaulted('meta', {});
10861
    const defaultedOnAction = defaultedFunction('onAction', noop);
10862
    const defaultedType = type => defaultedString('type', type);
10863
    const generatedName = namePrefix => field$1('name', 'name', defaultedThunk(() => generate$6(`${ namePrefix }-name`)), string);
10864
    const generatedValue = valuePrefix => field$1('value', 'value', defaultedThunk(() => generate$6(`${ valuePrefix }-value`)), anyValue());
10865
 
10866
    const separatorMenuItemSchema = objOf([
10867
      type,
10868
      optionalText
10869
    ]);
10870
    const createSeparatorMenuItem = spec => asRaw('separatormenuitem', separatorMenuItemSchema, spec);
10871
 
10872
    const autocompleterItemSchema = objOf([
10873
      defaultedType('autocompleteitem'),
10874
      active,
10875
      enabled,
10876
      defaultedMeta,
10877
      value$1,
10878
      optionalText,
10879
      optionalIcon
10880
    ]);
10881
    const createSeparatorItem = spec => asRaw('Autocompleter.Separator', separatorMenuItemSchema, spec);
10882
    const createAutocompleterItem = spec => asRaw('Autocompleter.Item', autocompleterItemSchema, spec);
10883
 
10884
    const baseToolbarButtonFields = [
10885
      enabled,
10886
      optionalTooltip,
10887
      optionalIcon,
10888
      optionalText,
10889
      onSetup
10890
    ];
10891
    const toolbarButtonSchema = objOf([
10892
      type,
10893
      onAction
10894
    ].concat(baseToolbarButtonFields));
10895
    const createToolbarButton = spec => asRaw('toolbarbutton', toolbarButtonSchema, spec);
10896
 
10897
    const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
10898
    const toggleButtonSchema = objOf(baseToolbarToggleButtonFields.concat([
10899
      type,
10900
      onAction
10901
    ]));
10902
    const createToggleButton = spec => asRaw('ToggleButton', toggleButtonSchema, spec);
10903
 
10904
    const contextBarFields = [
10905
      defaultedFunction('predicate', never),
10906
      defaultedStringEnum('scope', 'node', [
10907
        'node',
10908
        'editor'
10909
      ]),
10910
      defaultedStringEnum('position', 'selection', [
10911
        'node',
10912
        'selection',
10913
        'line'
10914
      ])
10915
    ];
10916
 
10917
    const contextButtonFields = baseToolbarButtonFields.concat([
10918
      defaultedType('contextformbutton'),
10919
      primary,
10920
      onAction,
10921
      customField('original', identity)
10922
    ]);
10923
    const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
10924
      defaultedType('contextformbutton'),
10925
      primary,
10926
      onAction,
10927
      customField('original', identity)
10928
    ]);
10929
    const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
10930
    const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
10931
    const toggleOrNormal = choose$1('type', {
10932
      contextformbutton: contextButtonFields,
10933
      contextformtogglebutton: contextToggleButtonFields
10934
    });
10935
    const contextFormSchema = objOf([
10936
      defaultedType('contextform'),
10937
      defaultedFunction('initValue', constant$1('')),
10938
      optionalLabel,
10939
      requiredArrayOf('commands', toggleOrNormal),
10940
      optionOf('launch', choose$1('type', {
10941
        contextformbutton: launchButtonFields,
10942
        contextformtogglebutton: launchToggleButtonFields
10943
      }))
10944
    ].concat(contextBarFields));
10945
    const createContextForm = spec => asRaw('ContextForm', contextFormSchema, spec);
10946
 
10947
    const contextToolbarSchema = objOf([
10948
      defaultedType('contexttoolbar'),
10949
      requiredString('items')
10950
    ].concat(contextBarFields));
10951
    const createContextToolbar = spec => asRaw('ContextToolbar', contextToolbarSchema, spec);
10952
 
10953
    const cardImageFields = [
10954
      type,
10955
      requiredString('src'),
10956
      optionString('alt'),
10957
      defaultedArrayOf('classes', [], string)
10958
    ];
10959
    const cardImageSchema = objOf(cardImageFields);
10960
 
10961
    const cardTextFields = [
10962
      type,
10963
      text,
10964
      optionalName,
10965
      defaultedArrayOf('classes', ['tox-collection__item-label'], string)
10966
    ];
10967
    const cardTextSchema = objOf(cardTextFields);
10968
 
10969
    const itemSchema$1 = valueThunk(() => choose$2('type', {
10970
      cardimage: cardImageSchema,
10971
      cardtext: cardTextSchema,
10972
      cardcontainer: cardContainerSchema
10973
    }));
10974
    const cardContainerSchema = objOf([
10975
      type,
10976
      defaultedString('direction', 'horizontal'),
10977
      defaultedString('align', 'left'),
10978
      defaultedString('valign', 'middle'),
10979
      requiredArrayOf('items', itemSchema$1)
10980
    ]);
10981
 
10982
    const commonMenuItemFields = [
10983
      enabled,
10984
      optionalText,
10985
      optionalShortcut,
10986
      generatedValue('menuitem'),
10987
      defaultedMeta
10988
    ];
10989
 
10990
    const cardMenuItemSchema = objOf([
10991
      type,
10992
      optionalLabel,
10993
      requiredArrayOf('items', itemSchema$1),
10994
      onSetup,
10995
      defaultedOnAction
10996
    ].concat(commonMenuItemFields));
10997
    const createCardMenuItem = spec => asRaw('cardmenuitem', cardMenuItemSchema, spec);
10998
 
10999
    const choiceMenuItemSchema = objOf([
11000
      type,
11001
      active,
11002
      optionalIcon
11003
    ].concat(commonMenuItemFields));
11004
    const createChoiceMenuItem = spec => asRaw('choicemenuitem', choiceMenuItemSchema, spec);
11005
 
11006
    const baseFields = [
11007
      type,
11008
      requiredString('fancytype'),
11009
      defaultedOnAction
11010
    ];
11011
    const insertTableFields = [defaulted('initData', {})].concat(baseFields);
11012
    const colorSwatchFields = [
11013
      optionFunction('select'),
11014
      defaultedObjOf('initData', {}, [
11015
        defaultedBoolean('allowCustomColors', true),
11016
        defaultedString('storageKey', 'default'),
11017
        optionArrayOf('colors', anyValue())
11018
      ])
11019
    ].concat(baseFields);
11020
    const fancyMenuItemSchema = choose$1('fancytype', {
11021
      inserttable: insertTableFields,
11022
      colorswatch: colorSwatchFields
11023
    });
11024
    const createFancyMenuItem = spec => asRaw('fancymenuitem', fancyMenuItemSchema, spec);
11025
 
11026
    const menuItemSchema = objOf([
11027
      type,
11028
      onSetup,
11029
      defaultedOnAction,
11030
      optionalIcon
11031
    ].concat(commonMenuItemFields));
11032
    const createMenuItem = spec => asRaw('menuitem', menuItemSchema, spec);
11033
 
11034
    const nestedMenuItemSchema = objOf([
11035
      type,
11036
      getSubmenuItems,
11037
      onSetup,
11038
      optionalIcon
11039
    ].concat(commonMenuItemFields));
11040
    const createNestedMenuItem = spec => asRaw('nestedmenuitem', nestedMenuItemSchema, spec);
11041
 
11042
    const toggleMenuItemSchema = objOf([
11043
      type,
11044
      optionalIcon,
11045
      active,
11046
      onSetup,
11047
      onAction
11048
    ].concat(commonMenuItemFields));
11049
    const createToggleMenuItem = spec => asRaw('togglemenuitem', toggleMenuItemSchema, spec);
11050
 
11051
    const detectSize = (comp, margin, selectorClass) => {
11052
      const descendants$1 = descendants(comp.element, '.' + selectorClass);
11053
      if (descendants$1.length > 0) {
11054
        const columnLength = findIndex$1(descendants$1, c => {
11055
          const thisTop = c.dom.getBoundingClientRect().top;
11056
          const cTop = descendants$1[0].dom.getBoundingClientRect().top;
11057
          return Math.abs(thisTop - cTop) > margin;
11058
        }).getOr(descendants$1.length);
11059
        return Optional.some({
11060
          numColumns: columnLength,
11061
          numRows: Math.ceil(descendants$1.length / columnLength)
11062
        });
11063
      } else {
11064
        return Optional.none();
11065
      }
11066
    };
11067
 
11068
    const namedEvents = (name, handlers) => derive$1([config(name, handlers)]);
11069
    const unnamedEvents = handlers => namedEvents(generate$6('unnamed-events'), handlers);
11070
    const SimpleBehaviours = {
11071
      namedEvents,
11072
      unnamedEvents
11073
    };
11074
 
11075
    const ExclusivityChannel = generate$6('tooltip.exclusive');
11076
    const ShowTooltipEvent = generate$6('tooltip.show');
11077
    const HideTooltipEvent = generate$6('tooltip.hide');
11078
 
11079
    const hideAllExclusive = (component, _tConfig, _tState) => {
11080
      component.getSystem().broadcastOn([ExclusivityChannel], {});
11081
    };
11082
    const setComponents = (component, tConfig, tState, specs) => {
11083
      tState.getTooltip().each(tooltip => {
11084
        if (tooltip.getSystem().isConnected()) {
11085
          Replacing.set(tooltip, specs);
11086
        }
11087
      });
11088
    };
11089
 
11090
    var TooltippingApis = /*#__PURE__*/Object.freeze({
11091
        __proto__: null,
11092
        hideAllExclusive: hideAllExclusive,
11093
        setComponents: setComponents
11094
    });
11095
 
11096
    const events$9 = (tooltipConfig, state) => {
11097
      const hide = comp => {
11098
        state.getTooltip().each(p => {
11099
          detach(p);
11100
          tooltipConfig.onHide(comp, p);
11101
          state.clearTooltip();
11102
        });
11103
        state.clearTimer();
11104
      };
11105
      const show = comp => {
11106
        if (!state.isShowing()) {
11107
          hideAllExclusive(comp);
11108
          const sink = tooltipConfig.lazySink(comp).getOrDie();
11109
          const popup = comp.getSystem().build({
11110
            dom: tooltipConfig.tooltipDom,
11111
            components: tooltipConfig.tooltipComponents,
11112
            events: derive$2(tooltipConfig.mode === 'normal' ? [
11113
              run$1(mouseover(), _ => {
11114
                emit(comp, ShowTooltipEvent);
11115
              }),
11116
              run$1(mouseout(), _ => {
11117
                emit(comp, HideTooltipEvent);
11118
              })
11119
            ] : []),
11120
            behaviours: derive$1([Replacing.config({})])
11121
          });
11122
          state.setTooltip(popup);
11123
          attach(sink, popup);
11124
          tooltipConfig.onShow(comp, popup);
11125
          Positioning.position(sink, popup, { anchor: tooltipConfig.anchor(comp) });
11126
        }
11127
      };
11128
      return derive$2(flatten([
11129
        [
11130
          run$1(ShowTooltipEvent, comp => {
11131
            state.resetTimer(() => {
11132
              show(comp);
11133
            }, tooltipConfig.delay);
11134
          }),
11135
          run$1(HideTooltipEvent, comp => {
11136
            state.resetTimer(() => {
11137
              hide(comp);
11138
            }, tooltipConfig.delay);
11139
          }),
11140
          run$1(receive(), (comp, message) => {
11141
            const receivingData = message;
11142
            if (!receivingData.universal) {
11143
              if (contains$2(receivingData.channels, ExclusivityChannel)) {
11144
                hide(comp);
11145
              }
11146
            }
11147
          }),
11148
          runOnDetached(comp => {
11149
            hide(comp);
11150
          })
11151
        ],
11152
        tooltipConfig.mode === 'normal' ? [
11153
          run$1(focusin(), comp => {
11154
            emit(comp, ShowTooltipEvent);
11155
          }),
11156
          run$1(postBlur(), comp => {
11157
            emit(comp, HideTooltipEvent);
11158
          }),
11159
          run$1(mouseover(), comp => {
11160
            emit(comp, ShowTooltipEvent);
11161
          }),
11162
          run$1(mouseout(), comp => {
11163
            emit(comp, HideTooltipEvent);
11164
          })
11165
        ] : [
11166
          run$1(highlight$1(), (comp, _se) => {
11167
            emit(comp, ShowTooltipEvent);
11168
          }),
11169
          run$1(dehighlight$1(), comp => {
11170
            emit(comp, HideTooltipEvent);
11171
          })
11172
        ]
11173
      ]));
11174
    };
11175
 
11176
    var ActiveTooltipping = /*#__PURE__*/Object.freeze({
11177
        __proto__: null,
11178
        events: events$9
11179
    });
11180
 
11181
    var TooltippingSchema = [
11182
      required$1('lazySink'),
11183
      required$1('tooltipDom'),
11184
      defaulted('exclusive', true),
11185
      defaulted('tooltipComponents', []),
11186
      defaulted('delay', 300),
11187
      defaultedStringEnum('mode', 'normal', [
11188
        'normal',
11189
        'follow-highlight'
11190
      ]),
11191
      defaulted('anchor', comp => ({
11192
        type: 'hotspot',
11193
        hotspot: comp,
11194
        layouts: {
11195
          onLtr: constant$1([
11196
            south$2,
11197
            north$2,
11198
            southeast$2,
11199
            northeast$2,
11200
            southwest$2,
11201
            northwest$2
11202
          ]),
11203
          onRtl: constant$1([
11204
            south$2,
11205
            north$2,
11206
            southeast$2,
11207
            northeast$2,
11208
            southwest$2,
11209
            northwest$2
11210
          ])
11211
        }
11212
      })),
11213
      onHandler('onHide'),
11214
      onHandler('onShow')
11215
    ];
11216
 
11217
    const init$b = () => {
11218
      const timer = value$2();
11219
      const popup = value$2();
11220
      const clearTimer = () => {
11221
        timer.on(clearTimeout);
11222
      };
11223
      const resetTimer = (f, delay) => {
11224
        clearTimer();
11225
        timer.set(setTimeout(f, delay));
11226
      };
11227
      const readState = constant$1('not-implemented');
11228
      return nu$8({
11229
        getTooltip: popup.get,
11230
        isShowing: popup.isSet,
11231
        setTooltip: popup.set,
11232
        clearTooltip: popup.clear,
11233
        clearTimer,
11234
        resetTimer,
11235
        readState
11236
      });
11237
    };
11238
 
11239
    var TooltippingState = /*#__PURE__*/Object.freeze({
11240
        __proto__: null,
11241
        init: init$b
11242
    });
11243
 
11244
    const Tooltipping = create$4({
11245
      fields: TooltippingSchema,
11246
      name: 'tooltipping',
11247
      active: ActiveTooltipping,
11248
      state: TooltippingState,
11249
      apis: TooltippingApis
11250
    });
11251
 
11252
    const escape = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
11253
 
11254
    const ReadOnlyChannel = 'silver.readonly';
11255
    const ReadOnlyDataSchema = objOf([requiredBoolean('readonly')]);
11256
    const broadcastReadonly = (uiRefs, readonly) => {
11257
      const outerContainer = uiRefs.mainUi.outerContainer;
11258
      const target = outerContainer.element;
11259
      const motherships = [
11260
        uiRefs.mainUi.mothership,
11261
        ...uiRefs.uiMotherships
11262
      ];
11263
      if (readonly) {
11264
        each$1(motherships, m => {
11265
          m.broadcastOn([dismissPopups()], { target });
11266
        });
11267
      }
11268
      each$1(motherships, m => {
11269
        m.broadcastOn([ReadOnlyChannel], { readonly });
11270
      });
11271
    };
11272
    const setupReadonlyModeSwitch = (editor, uiRefs) => {
11273
      editor.on('init', () => {
11274
        if (editor.mode.isReadOnly()) {
11275
          broadcastReadonly(uiRefs, true);
11276
        }
11277
      });
11278
      editor.on('SwitchMode', () => broadcastReadonly(uiRefs, editor.mode.isReadOnly()));
11279
      if (isReadOnly(editor)) {
11280
        editor.mode.set('readonly');
11281
      }
11282
    };
11283
    const receivingConfig = () => Receiving.config({
11284
      channels: {
11285
        [ReadOnlyChannel]: {
11286
          schema: ReadOnlyDataSchema,
11287
          onReceive: (comp, data) => {
11288
            Disabling.set(comp, data.readonly);
11289
          }
11290
        }
11291
      }
11292
    });
11293
 
11294
    const item = disabled => Disabling.config({
11295
      disabled,
11296
      disableClass: 'tox-collection__item--state-disabled'
11297
    });
11298
    const button = disabled => Disabling.config({ disabled });
11299
    const splitButton = disabled => Disabling.config({
11300
      disabled,
11301
      disableClass: 'tox-tbtn--disabled'
11302
    });
11303
    const toolbarButton = disabled => Disabling.config({
11304
      disabled,
11305
      disableClass: 'tox-tbtn--disabled',
11306
      useNative: false
11307
    });
11308
    const DisablingConfigs = {
11309
      item,
11310
      button,
11311
      splitButton,
11312
      toolbarButton
11313
    };
11314
 
11315
    const runWithApi = (info, comp) => {
11316
      const api = info.getApi(comp);
11317
      return f => {
11318
        f(api);
11319
      };
11320
    };
11321
    const onControlAttached = (info, editorOffCell) => runOnAttached(comp => {
11322
      const run = runWithApi(info, comp);
11323
      run(api => {
11324
        const onDestroy = info.onSetup(api);
11325
        if (isFunction(onDestroy)) {
11326
          editorOffCell.set(onDestroy);
11327
        }
11328
      });
11329
    });
11330
    const onControlDetached = (getApi, editorOffCell) => runOnDetached(comp => runWithApi(getApi, comp)(editorOffCell.get()));
11331
 
11332
    const onMenuItemExecute = (info, itemResponse) => runOnExecute$1((comp, simulatedEvent) => {
11333
      runWithApi(info, comp)(info.onAction);
11334
      if (!info.triggersSubmenu && itemResponse === ItemResponse$1.CLOSE_ON_EXECUTE) {
11335
        if (comp.getSystem().isConnected()) {
11336
          emit(comp, sandboxClose());
11337
        }
11338
        simulatedEvent.stop();
11339
      }
11340
    });
11341
    const menuItemEventOrder = {
11342
      [execute$5()]: [
11343
        'disabling',
11344
        'alloy.base.behaviour',
11345
        'toggling',
11346
        'item-events'
11347
      ]
11348
    };
11349
 
11350
    const componentRenderPipeline = cat;
11351
    const renderCommonItem = (spec, structure, itemResponse, providersBackstage) => {
11352
      const editorOffCell = Cell(noop);
11353
      return {
11354
        type: 'item',
11355
        dom: structure.dom,
11356
        components: componentRenderPipeline(structure.optComponents),
11357
        data: spec.data,
11358
        eventOrder: menuItemEventOrder,
11359
        hasSubmenu: spec.triggersSubmenu,
11360
        itemBehaviours: derive$1([
11361
          config('item-events', [
11362
            onMenuItemExecute(spec, itemResponse),
11363
            onControlAttached(spec, editorOffCell),
11364
            onControlDetached(spec, editorOffCell)
11365
          ]),
11366
          DisablingConfigs.item(() => !spec.enabled || providersBackstage.isDisabled()),
11367
          receivingConfig(),
11368
          Replacing.config({})
11369
        ].concat(spec.itemBehaviours))
11370
      };
11371
    };
11372
    const buildData = source => ({
11373
      value: source.value,
11374
      meta: {
11375
        text: source.text.getOr(''),
11376
        ...source.meta
11377
      }
11378
    });
11379
 
11380
    const convertText = source => {
11381
      const isMac = global$5.os.isMacOS() || global$5.os.isiOS();
11382
      const mac = {
11383
        alt: '\u2325',
11384
        ctrl: '\u2303',
11385
        shift: '\u21E7',
11386
        meta: '\u2318',
11387
        access: '\u2303\u2325'
11388
      };
11389
      const other = {
11390
        meta: 'Ctrl',
11391
        access: 'Shift+Alt'
11392
      };
11393
      const replace = isMac ? mac : other;
11394
      const shortcut = source.split('+');
11395
      const updated = map$2(shortcut, segment => {
11396
        const search = segment.toLowerCase().trim();
11397
        return has$2(replace, search) ? replace[search] : segment;
11398
      });
11399
      return isMac ? updated.join('') : updated.join('+');
11400
    };
11401
 
11402
    const renderIcon$2 = (name, icons, classes = [iconClass]) => render$3(name, {
11403
      tag: 'div',
11404
      classes
11405
    }, icons);
11406
    const renderText = text => ({
11407
      dom: {
11408
        tag: 'div',
11409
        classes: [textClass]
11410
      },
11411
      components: [text$2(global$8.translate(text))]
11412
    });
11413
    const renderHtml = (html, classes) => ({
11414
      dom: {
11415
        tag: 'div',
11416
        classes,
11417
        innerHtml: html
11418
      }
11419
    });
11420
    const renderStyledText = (style, text) => ({
11421
      dom: {
11422
        tag: 'div',
11423
        classes: [textClass]
11424
      },
11425
      components: [{
11426
          dom: {
11427
            tag: style.tag,
11428
            styles: style.styles
11429
          },
11430
          components: [text$2(global$8.translate(text))]
11431
        }]
11432
    });
11433
    const renderShortcut = shortcut => ({
11434
      dom: {
11435
        tag: 'div',
11436
        classes: [accessoryClass]
11437
      },
11438
      components: [text$2(convertText(shortcut))]
11439
    });
11440
    const renderCheckmark = icons => renderIcon$2('checkmark', icons, [checkmarkClass]);
11441
    const renderSubmenuCaret = icons => renderIcon$2('chevron-right', icons, [caretClass]);
11442
    const renderDownwardsCaret = icons => renderIcon$2('chevron-down', icons, [caretClass]);
11443
    const renderContainer = (container, components) => {
11444
      const directionClass = container.direction === 'vertical' ? containerColumnClass : containerRowClass;
11445
      const alignClass = container.align === 'left' ? containerAlignLeftClass : containerAlignRightClass;
11446
      const getValignClass = () => {
11447
        switch (container.valign) {
11448
        case 'top':
11449
          return containerValignTopClass;
11450
        case 'middle':
11451
          return containerValignMiddleClass;
11452
        case 'bottom':
11453
          return containerValignBottomClass;
11454
        }
11455
      };
11456
      return {
11457
        dom: {
11458
          tag: 'div',
11459
          classes: [
11460
            containerClass,
11461
            directionClass,
11462
            alignClass,
11463
            getValignClass()
11464
          ]
11465
        },
11466
        components
11467
      };
11468
    };
11469
    const renderImage = (src, classes, alt) => ({
11470
      dom: {
11471
        tag: 'img',
11472
        classes,
11473
        attributes: {
11474
          src,
11475
          alt: alt.getOr('')
11476
        }
11477
      }
11478
    });
11479
 
11480
    const renderColorStructure = (item, providerBackstage, fallbackIcon) => {
11481
      const colorPickerCommand = 'custom';
11482
      const removeColorCommand = 'remove';
11483
      const itemText = item.ariaLabel;
11484
      const itemValue = item.value;
11485
      const iconSvg = item.iconContent.map(name => getOr(name, providerBackstage.icons, fallbackIcon));
11486
      const getDom = () => {
11487
        const common = colorClass;
11488
        const icon = iconSvg.getOr('');
11489
        const attributes = itemText.map(text => ({ title: providerBackstage.translate(text) })).getOr({});
11490
        const baseDom = {
11491
          tag: 'div',
11492
          attributes,
11493
          classes: [common]
11494
        };
11495
        if (itemValue === colorPickerCommand) {
11496
          return {
11497
            ...baseDom,
11498
            tag: 'button',
11499
            classes: [
11500
              ...baseDom.classes,
11501
              'tox-swatches__picker-btn'
11502
            ],
11503
            innerHtml: icon
11504
          };
11505
        } else if (itemValue === removeColorCommand) {
11506
          return {
11507
            ...baseDom,
11508
            classes: [
11509
              ...baseDom.classes,
11510
              'tox-swatch--remove'
11511
            ],
11512
            innerHtml: icon
11513
          };
11514
        } else if (isNonNullable(itemValue)) {
11515
          return {
11516
            ...baseDom,
11517
            attributes: {
11518
              ...baseDom.attributes,
11519
              'data-mce-color': itemValue
11520
            },
11521
            styles: { 'background-color': itemValue },
11522
            innerHtml: icon
11523
          };
11524
        } else {
11525
          return baseDom;
11526
        }
11527
      };
11528
      return {
11529
        dom: getDom(),
11530
        optComponents: []
11531
      };
11532
    };
11533
    const renderItemDomStructure = ariaLabel => {
11534
      const domTitle = ariaLabel.map(label => ({
11535
        attributes: {
11536
          title: global$8.translate(label),
11537
          id: generate$6('menu-item')
11538
        }
11539
      })).getOr({});
11540
      return {
11541
        tag: 'div',
11542
        classes: [
11543
          navClass,
11544
          selectableClass
11545
        ],
11546
        ...domTitle
11547
      };
11548
    };
11549
    const renderNormalItemStructure = (info, providersBackstage, renderIcons, fallbackIcon) => {
11550
      const iconSpec = {
11551
        tag: 'div',
11552
        classes: [iconClass]
11553
      };
11554
      const renderIcon = iconName => render$3(iconName, iconSpec, providersBackstage.icons, fallbackIcon);
11555
      const renderEmptyIcon = () => Optional.some({ dom: iconSpec });
11556
      const leftIcon = renderIcons ? info.iconContent.map(renderIcon).orThunk(renderEmptyIcon) : Optional.none();
11557
      const checkmark = info.checkMark;
11558
      const textRender = Optional.from(info.meta).fold(() => renderText, meta => has$2(meta, 'style') ? curry(renderStyledText, meta.style) : renderText);
11559
      const content = info.htmlContent.fold(() => info.textContent.map(textRender), html => Optional.some(renderHtml(html, [textClass])));
11560
      const menuItem = {
11561
        dom: renderItemDomStructure(info.ariaLabel),
11562
        optComponents: [
11563
          leftIcon,
11564
          content,
11565
          info.shortcutContent.map(renderShortcut),
11566
          checkmark,
11567
          info.caret
11568
        ]
11569
      };
11570
      return menuItem;
11571
    };
11572
    const renderItemStructure = (info, providersBackstage, renderIcons, fallbackIcon = Optional.none()) => {
11573
      if (info.presets === 'color') {
11574
        return renderColorStructure(info, providersBackstage, fallbackIcon);
11575
      } else {
11576
        return renderNormalItemStructure(info, providersBackstage, renderIcons, fallbackIcon);
11577
      }
11578
    };
11579
 
11580
    const tooltipBehaviour = (meta, sharedBackstage) => get$g(meta, 'tooltipWorker').map(tooltipWorker => [Tooltipping.config({
11581
        lazySink: sharedBackstage.getSink,
11582
        tooltipDom: {
11583
          tag: 'div',
11584
          classes: ['tox-tooltip-worker-container']
11585
        },
11586
        tooltipComponents: [],
11587
        anchor: comp => ({
11588
          type: 'submenu',
11589
          item: comp,
11590
          overrides: { maxHeightFunction: expandable$1 }
11591
        }),
11592
        mode: 'follow-highlight',
11593
        onShow: (component, _tooltip) => {
11594
          tooltipWorker(elm => {
11595
            Tooltipping.setComponents(component, [external$1({ element: SugarElement.fromDom(elm) })]);
11596
          });
11597
        }
11598
      })]).getOr([]);
11599
    const encodeText = text => global$7.DOM.encode(text);
11600
    const replaceText = (text, matchText) => {
11601
      const translated = global$8.translate(text);
11602
      const encoded = encodeText(translated);
11603
      if (matchText.length > 0) {
11604
        const escapedMatchRegex = new RegExp(escape(matchText), 'gi');
11605
        return encoded.replace(escapedMatchRegex, match => `<span class="tox-autocompleter-highlight">${ match }</span>`);
11606
      } else {
11607
        return encoded;
11608
      }
11609
    };
11610
    const renderAutocompleteItem = (spec, matchText, useText, presets, onItemValueHandler, itemResponse, sharedBackstage, renderIcons = true) => {
11611
      const structure = renderItemStructure({
11612
        presets,
11613
        textContent: Optional.none(),
11614
        htmlContent: useText ? spec.text.map(text => replaceText(text, matchText)) : Optional.none(),
11615
        ariaLabel: spec.text,
11616
        iconContent: spec.icon,
11617
        shortcutContent: Optional.none(),
11618
        checkMark: Optional.none(),
11619
        caret: Optional.none(),
11620
        value: spec.value
11621
      }, sharedBackstage.providers, renderIcons, spec.icon);
11622
      return renderCommonItem({
11623
        data: buildData(spec),
11624
        enabled: spec.enabled,
11625
        getApi: constant$1({}),
11626
        onAction: _api => onItemValueHandler(spec.value, spec.meta),
11627
        onSetup: constant$1(noop),
11628
        triggersSubmenu: false,
11629
        itemBehaviours: tooltipBehaviour(spec.meta, sharedBackstage)
11630
      }, structure, itemResponse, sharedBackstage.providers);
11631
    };
11632
 
11633
    const render$2 = (items, extras) => map$2(items, item => {
11634
      switch (item.type) {
11635
      case 'cardcontainer':
11636
        return renderContainer(item, render$2(item.items, extras));
11637
      case 'cardimage':
11638
        return renderImage(item.src, item.classes, item.alt);
11639
      case 'cardtext':
11640
        const shouldHighlight = item.name.exists(name => contains$2(extras.cardText.highlightOn, name));
11641
        const matchText = shouldHighlight ? Optional.from(extras.cardText.matchText).getOr('') : '';
11642
        return renderHtml(replaceText(item.text, matchText), item.classes);
11643
      }
11644
    });
11645
    const renderCardMenuItem = (spec, itemResponse, sharedBackstage, extras) => {
11646
      const getApi = component => ({
11647
        isEnabled: () => !Disabling.isDisabled(component),
11648
        setEnabled: state => {
11649
          Disabling.set(component, !state);
11650
          each$1(descendants(component.element, '*'), elm => {
11651
            component.getSystem().getByDom(elm).each(comp => {
11652
              if (comp.hasConfigured(Disabling)) {
11653
                Disabling.set(comp, !state);
11654
              }
11655
            });
11656
          });
11657
        }
11658
      });
11659
      const structure = {
11660
        dom: renderItemDomStructure(spec.label),
11661
        optComponents: [Optional.some({
11662
            dom: {
11663
              tag: 'div',
11664
              classes: [
11665
                containerClass,
11666
                containerRowClass
11667
              ]
11668
            },
11669
            components: render$2(spec.items, extras)
11670
          })]
11671
      };
11672
      return renderCommonItem({
11673
        data: buildData({
11674
          text: Optional.none(),
11675
          ...spec
11676
        }),
11677
        enabled: spec.enabled,
11678
        getApi,
11679
        onAction: spec.onAction,
11680
        onSetup: spec.onSetup,
11681
        triggersSubmenu: false,
11682
        itemBehaviours: Optional.from(extras.itemBehaviours).getOr([])
11683
      }, structure, itemResponse, sharedBackstage.providers);
11684
    };
11685
 
11686
    const renderChoiceItem = (spec, useText, presets, onItemValueHandler, isSelected, itemResponse, providersBackstage, renderIcons = true) => {
11687
      const getApi = component => ({
11688
        setActive: state => {
11689
          Toggling.set(component, state);
11690
        },
11691
        isActive: () => Toggling.isOn(component),
11692
        isEnabled: () => !Disabling.isDisabled(component),
11693
        setEnabled: state => Disabling.set(component, !state)
11694
      });
11695
      const structure = renderItemStructure({
11696
        presets,
11697
        textContent: useText ? spec.text : Optional.none(),
11698
        htmlContent: Optional.none(),
11699
        ariaLabel: spec.text,
11700
        iconContent: spec.icon,
11701
        shortcutContent: useText ? spec.shortcut : Optional.none(),
11702
        checkMark: useText ? Optional.some(renderCheckmark(providersBackstage.icons)) : Optional.none(),
11703
        caret: Optional.none(),
11704
        value: spec.value
11705
      }, providersBackstage, renderIcons);
11706
      return deepMerge(renderCommonItem({
11707
        data: buildData(spec),
11708
        enabled: spec.enabled,
11709
        getApi,
11710
        onAction: _api => onItemValueHandler(spec.value),
11711
        onSetup: api => {
11712
          api.setActive(isSelected);
11713
          return noop;
11714
        },
11715
        triggersSubmenu: false,
11716
        itemBehaviours: []
11717
      }, structure, itemResponse, providersBackstage), {
11718
        toggling: {
11719
          toggleClass: tickedClass,
11720
          toggleOnExecute: false,
11721
          selected: spec.active,
11722
          exclusive: true
11723
        }
11724
      });
11725
    };
11726
 
11727
    const parts$f = generate$3(owner$2(), parts$h());
11728
 
11729
    const hexColour = value => ({ value: normalizeHex(value) });
11730
    const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
11731
    const longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
11732
    const isHexString = hex => shorthandRegex.test(hex) || longformRegex.test(hex);
11733
    const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
11734
    const fromString$1 = hex => isHexString(hex) ? Optional.some({ value: normalizeHex(hex) }) : Optional.none();
11735
    const getLongForm = hex => {
11736
      const hexString = hex.value.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
11737
      return { value: hexString };
11738
    };
11739
    const extractValues = hex => {
11740
      const longForm = getLongForm(hex);
11741
      const splitForm = longformRegex.exec(longForm.value);
11742
      return splitForm === null ? [
11743
        'FFFFFF',
11744
        'FF',
11745
        'FF',
11746
        'FF'
11747
      ] : splitForm;
11748
    };
11749
    const toHex = component => {
11750
      const hex = component.toString(16);
11751
      return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
11752
    };
11753
    const fromRgba = rgbaColour => {
11754
      const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
11755
      return hexColour(value);
11756
    };
11757
 
11758
    const min = Math.min;
11759
    const max = Math.max;
11760
    const round$1 = Math.round;
11761
    const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
11762
    const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
11763
    const rgbaColour = (red, green, blue, alpha) => ({
11764
      red,
11765
      green,
11766
      blue,
11767
      alpha
11768
    });
11769
    const isRgbaComponent = value => {
11770
      const num = parseInt(value, 10);
11771
      return num.toString() === value && num >= 0 && num <= 255;
11772
    };
11773
    const fromHsv = hsv => {
11774
      let r;
11775
      let g;
11776
      let b;
11777
      const hue = (hsv.hue || 0) % 360;
11778
      let saturation = hsv.saturation / 100;
11779
      let brightness = hsv.value / 100;
11780
      saturation = max(0, min(saturation, 1));
11781
      brightness = max(0, min(brightness, 1));
11782
      if (saturation === 0) {
11783
        r = g = b = round$1(255 * brightness);
11784
        return rgbaColour(r, g, b, 1);
11785
      }
11786
      const side = hue / 60;
11787
      const chroma = brightness * saturation;
11788
      const x = chroma * (1 - Math.abs(side % 2 - 1));
11789
      const match = brightness - chroma;
11790
      switch (Math.floor(side)) {
11791
      case 0:
11792
        r = chroma;
11793
        g = x;
11794
        b = 0;
11795
        break;
11796
      case 1:
11797
        r = x;
11798
        g = chroma;
11799
        b = 0;
11800
        break;
11801
      case 2:
11802
        r = 0;
11803
        g = chroma;
11804
        b = x;
11805
        break;
11806
      case 3:
11807
        r = 0;
11808
        g = x;
11809
        b = chroma;
11810
        break;
11811
      case 4:
11812
        r = x;
11813
        g = 0;
11814
        b = chroma;
11815
        break;
11816
      case 5:
11817
        r = chroma;
11818
        g = 0;
11819
        b = x;
11820
        break;
11821
      default:
11822
        r = g = b = 0;
11823
      }
11824
      r = round$1(255 * (r + match));
11825
      g = round$1(255 * (g + match));
11826
      b = round$1(255 * (b + match));
11827
      return rgbaColour(r, g, b, 1);
11828
    };
11829
    const fromHex = hexColour => {
11830
      const result = extractValues(hexColour);
11831
      const red = parseInt(result[1], 16);
11832
      const green = parseInt(result[2], 16);
11833
      const blue = parseInt(result[3], 16);
11834
      return rgbaColour(red, green, blue, 1);
11835
    };
11836
    const fromStringValues = (red, green, blue, alpha) => {
11837
      const r = parseInt(red, 10);
11838
      const g = parseInt(green, 10);
11839
      const b = parseInt(blue, 10);
11840
      const a = parseFloat(alpha);
11841
      return rgbaColour(r, g, b, a);
11842
    };
11843
    const fromString = rgbaString => {
11844
      if (rgbaString === 'transparent') {
11845
        return Optional.some(rgbaColour(0, 0, 0, 0));
11846
      }
11847
      const rgbMatch = rgbRegex.exec(rgbaString);
11848
      if (rgbMatch !== null) {
11849
        return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
11850
      }
11851
      const rgbaMatch = rgbaRegex.exec(rgbaString);
11852
      if (rgbaMatch !== null) {
11853
        return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
11854
      }
11855
      return Optional.none();
11856
    };
11857
    const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
11858
    const red = rgbaColour(255, 0, 0, 1);
11859
 
11860
    const fireSkinLoaded$1 = editor => {
11861
      editor.dispatch('SkinLoaded');
11862
    };
11863
    const fireSkinLoadError$1 = (editor, error) => {
11864
      editor.dispatch('SkinLoadError', error);
11865
    };
11866
    const fireResizeEditor = editor => {
11867
      editor.dispatch('ResizeEditor');
11868
    };
11869
    const fireResizeContent = (editor, e) => {
11870
      editor.dispatch('ResizeContent', e);
11871
    };
11872
    const fireScrollContent = (editor, e) => {
11873
      editor.dispatch('ScrollContent', e);
11874
    };
11875
    const fireTextColorChange = (editor, data) => {
11876
      editor.dispatch('TextColorChange', data);
11877
    };
11878
    const fireAfterProgressState = (editor, state) => {
11879
      editor.dispatch('AfterProgressState', { state });
11880
    };
11881
    const fireResolveName = (editor, node) => editor.dispatch('ResolveName', {
11882
      name: node.nodeName.toLowerCase(),
11883
      target: node
11884
    });
11885
    const fireToggleToolbarDrawer = (editor, state) => {
11886
      editor.dispatch('ToggleToolbarDrawer', { state });
11887
    };
11888
    const fireStylesTextUpdate = (editor, data) => {
11889
      editor.dispatch('StylesTextUpdate', data);
11890
    };
11891
    const fireAlignTextUpdate = (editor, data) => {
11892
      editor.dispatch('AlignTextUpdate', data);
11893
    };
11894
    const fireFontSizeTextUpdate = (editor, data) => {
11895
      editor.dispatch('FontSizeTextUpdate', data);
11896
    };
11897
    const fireFontSizeInputTextUpdate = (editor, data) => {
11898
      editor.dispatch('FontSizeInputTextUpdate', data);
11899
    };
11900
    const fireBlocksTextUpdate = (editor, data) => {
11901
      editor.dispatch('BlocksTextUpdate', data);
11902
    };
11903
    const fireFontFamilyTextUpdate = (editor, data) => {
11904
      editor.dispatch('FontFamilyTextUpdate', data);
11905
    };
11906
 
11907
    const composeUnbinders = (f, g) => () => {
11908
      f();
11909
      g();
11910
    };
11911
    const onSetupEditableToggle = editor => onSetupEvent(editor, 'NodeChange', api => {
11912
      api.setEnabled(editor.selection.isEditable());
11913
    });
11914
    const onSetupFormatToggle = (editor, name) => api => {
11915
      const boundFormatChangeCallback = unbindable();
11916
      const init = () => {
11917
        api.setActive(editor.formatter.match(name));
11918
        const binding = editor.formatter.formatChanged(name, api.setActive);
11919
        boundFormatChangeCallback.set(binding);
11920
      };
11921
      editor.initialized ? init() : editor.once('init', init);
11922
      return () => {
11923
        editor.off('init', init);
11924
        boundFormatChangeCallback.clear();
11925
      };
11926
    };
11927
    const onSetupStateToggle = (editor, name) => api => {
11928
      const unbindEditableToogle = onSetupEditableToggle(editor)(api);
11929
      const unbindFormatToggle = onSetupFormatToggle(editor, name)(api);
11930
      return () => {
11931
        unbindEditableToogle();
11932
        unbindFormatToggle();
11933
      };
11934
    };
11935
    const onSetupEvent = (editor, event, f) => api => {
11936
      const handleEvent = () => f(api);
11937
      const init = () => {
11938
        f(api);
11939
        editor.on(event, handleEvent);
11940
      };
11941
      editor.initialized ? init() : editor.once('init', init);
11942
      return () => {
11943
        editor.off('init', init);
11944
        editor.off(event, handleEvent);
11945
      };
11946
    };
11947
    const onActionToggleFormat$1 = editor => rawItem => () => {
11948
      editor.undoManager.transact(() => {
11949
        editor.focus();
11950
        editor.execCommand('mceToggleFormat', false, rawItem.format);
11951
      });
11952
    };
11953
    const onActionExecCommand = (editor, command) => () => editor.execCommand(command);
11954
 
11955
    var global$4 = tinymce.util.Tools.resolve('tinymce.util.LocalStorage');
11956
 
11957
    const cacheStorage = {};
11958
    const ColorCache = (storageId, max = 10) => {
11959
      const storageString = global$4.getItem(storageId);
11960
      const localstorage = isString(storageString) ? JSON.parse(storageString) : [];
11961
      const prune = list => {
11962
        const diff = max - list.length;
11963
        return diff < 0 ? list.slice(0, max) : list;
11964
      };
11965
      const cache = prune(localstorage);
11966
      const add = key => {
11967
        indexOf(cache, key).each(remove);
11968
        cache.unshift(key);
11969
        if (cache.length > max) {
11970
          cache.pop();
11971
        }
11972
        global$4.setItem(storageId, JSON.stringify(cache));
11973
      };
11974
      const remove = idx => {
11975
        cache.splice(idx, 1);
11976
      };
11977
      const state = () => cache.slice(0);
11978
      return {
11979
        add,
11980
        state
11981
      };
11982
    };
11983
    const getCacheForId = id => get$g(cacheStorage, id).getOrThunk(() => {
11984
      const storageId = `tinymce-custom-colors-${ id }`;
11985
      const currentData = global$4.getItem(storageId);
11986
      if (isNullable(currentData)) {
11987
        const legacyDefault = global$4.getItem('tinymce-custom-colors');
11988
        global$4.setItem(storageId, isNonNullable(legacyDefault) ? legacyDefault : '[]');
11989
      }
11990
      const storage = ColorCache(storageId, 10);
11991
      cacheStorage[id] = storage;
11992
      return storage;
11993
    });
11994
    const getCurrentColors = id => map$2(getCacheForId(id).state(), color => ({
11995
      type: 'choiceitem',
11996
      text: color,
11997
      icon: 'checkmark',
11998
      value: color
11999
    }));
12000
    const addColor = (id, color) => {
12001
      getCacheForId(id).add(color);
12002
    };
12003
 
12004
    const hsvColour = (hue, saturation, value) => ({
12005
      hue,
12006
      saturation,
12007
      value
12008
    });
12009
    const fromRgb = rgbaColour => {
12010
      let h = 0;
12011
      let s = 0;
12012
      let v = 0;
12013
      const r = rgbaColour.red / 255;
12014
      const g = rgbaColour.green / 255;
12015
      const b = rgbaColour.blue / 255;
12016
      const minRGB = Math.min(r, Math.min(g, b));
12017
      const maxRGB = Math.max(r, Math.max(g, b));
12018
      if (minRGB === maxRGB) {
12019
        v = minRGB;
12020
        return hsvColour(0, 0, v * 100);
12021
      }
12022
      const d = r === minRGB ? g - b : b === minRGB ? r - g : b - r;
12023
      h = r === minRGB ? 3 : b === minRGB ? 1 : 5;
12024
      h = 60 * (h - d / (maxRGB - minRGB));
12025
      s = (maxRGB - minRGB) / maxRGB;
12026
      v = maxRGB;
12027
      return hsvColour(Math.round(h), Math.round(s * 100), Math.round(v * 100));
12028
    };
12029
 
12030
    const hexToHsv = hex => fromRgb(fromHex(hex));
12031
    const hsvToHex = hsv => fromRgba(fromHsv(hsv));
12032
    const anyToHex = color => fromString$1(color).orThunk(() => fromString(color).map(fromRgba)).getOrThunk(() => {
12033
      const canvas = document.createElement('canvas');
12034
      canvas.height = 1;
12035
      canvas.width = 1;
12036
      const canvasContext = canvas.getContext('2d');
12037
      canvasContext.clearRect(0, 0, canvas.width, canvas.height);
12038
      canvasContext.fillStyle = '#FFFFFF';
12039
      canvasContext.fillStyle = color;
12040
      canvasContext.fillRect(0, 0, 1, 1);
12041
      const rgba = canvasContext.getImageData(0, 0, 1, 1).data;
12042
      const r = rgba[0];
12043
      const g = rgba[1];
12044
      const b = rgba[2];
12045
      const a = rgba[3];
12046
      return fromRgba(rgbaColour(r, g, b, a));
12047
    });
12048
 
12049
    const foregroundId = 'forecolor';
12050
    const backgroundId = 'hilitecolor';
12051
    const fallbackCols = 5;
12052
    const mapColors = colorMap => {
12053
      const colors = [];
12054
      for (let i = 0; i < colorMap.length; i += 2) {
12055
        colors.push({
12056
          text: colorMap[i + 1],
12057
          value: '#' + anyToHex(colorMap[i]).value,
12058
          icon: 'checkmark',
12059
          type: 'choiceitem'
12060
        });
12061
      }
12062
      return colors;
12063
    };
12064
    const option$1 = name => editor => editor.options.get(name);
12065
    const fallbackColor = '#000000';
12066
    const register$d = editor => {
12067
      const registerOption = editor.options.register;
12068
      const colorProcessor = value => {
12069
        if (isArrayOf(value, isString)) {
12070
          return {
12071
            value: mapColors(value),
12072
            valid: true
12073
          };
12074
        } else {
12075
          return {
12076
            valid: false,
12077
            message: 'Must be an array of strings.'
12078
          };
12079
        }
12080
      };
12081
      const colorColsProcessor = value => {
12082
        if (isNumber(value) && value > 0) {
12083
          return {
12084
            value,
12085
            valid: true
12086
          };
12087
        } else {
12088
          return {
12089
            valid: false,
12090
            message: 'Must be a positive number.'
12091
          };
12092
        }
12093
      };
12094
      registerOption('color_map', {
12095
        processor: colorProcessor,
12096
        default: [
12097
          '#BFEDD2',
12098
          'Light Green',
12099
          '#FBEEB8',
12100
          'Light Yellow',
12101
          '#F8CAC6',
12102
          'Light Red',
12103
          '#ECCAFA',
12104
          'Light Purple',
12105
          '#C2E0F4',
12106
          'Light Blue',
12107
          '#2DC26B',
12108
          'Green',
12109
          '#F1C40F',
12110
          'Yellow',
12111
          '#E03E2D',
12112
          'Red',
12113
          '#B96AD9',
12114
          'Purple',
12115
          '#3598DB',
12116
          'Blue',
12117
          '#169179',
12118
          'Dark Turquoise',
12119
          '#E67E23',
12120
          'Orange',
12121
          '#BA372A',
12122
          'Dark Red',
12123
          '#843FA1',
12124
          'Dark Purple',
12125
          '#236FA1',
12126
          'Dark Blue',
12127
          '#ECF0F1',
12128
          'Light Gray',
12129
          '#CED4D9',
12130
          'Medium Gray',
12131
          '#95A5A6',
12132
          'Gray',
12133
          '#7E8C8D',
12134
          'Dark Gray',
12135
          '#34495E',
12136
          'Navy Blue',
12137
          '#000000',
12138
          'Black',
12139
          '#ffffff',
12140
          'White'
12141
        ]
12142
      });
12143
      registerOption('color_map_background', { processor: colorProcessor });
12144
      registerOption('color_map_foreground', { processor: colorProcessor });
12145
      registerOption('color_cols', {
12146
        processor: colorColsProcessor,
12147
        default: calcCols(editor)
12148
      });
12149
      registerOption('color_cols_foreground', {
12150
        processor: colorColsProcessor,
12151
        default: defaultCols(editor, foregroundId)
12152
      });
12153
      registerOption('color_cols_background', {
12154
        processor: colorColsProcessor,
12155
        default: defaultCols(editor, backgroundId)
12156
      });
12157
      registerOption('custom_colors', {
12158
        processor: 'boolean',
12159
        default: true
12160
      });
12161
      registerOption('color_default_foreground', {
12162
        processor: 'string',
12163
        default: fallbackColor
12164
      });
12165
      registerOption('color_default_background', {
12166
        processor: 'string',
12167
        default: fallbackColor
12168
      });
12169
    };
12170
    const getColors$2 = (editor, id) => {
12171
      if (id === foregroundId && editor.options.isSet('color_map_foreground')) {
12172
        return option$1('color_map_foreground')(editor);
12173
      } else if (id === backgroundId && editor.options.isSet('color_map_background')) {
12174
        return option$1('color_map_background')(editor);
12175
      } else {
12176
        return option$1('color_map')(editor);
12177
      }
12178
    };
12179
    const calcCols = (editor, id = 'default') => Math.max(fallbackCols, Math.ceil(Math.sqrt(getColors$2(editor, id).length)));
12180
    const defaultCols = (editor, id) => {
12181
      const defaultCols = option$1('color_cols')(editor);
12182
      const calculatedCols = calcCols(editor, id);
12183
      if (defaultCols === calcCols(editor)) {
12184
        return calculatedCols;
12185
      } else {
12186
        return defaultCols;
12187
      }
12188
    };
12189
    const getColorCols$1 = (editor, id = 'default') => {
12190
      const getCols = () => {
12191
        if (id === foregroundId) {
12192
          return option$1('color_cols_foreground')(editor);
12193
        } else if (id === backgroundId) {
12194
          return option$1('color_cols_background')(editor);
12195
        } else {
12196
          return option$1('color_cols')(editor);
12197
        }
12198
      };
12199
      return Math.round(getCols());
12200
    };
12201
    const hasCustomColors$1 = option$1('custom_colors');
12202
    const getDefaultForegroundColor = option$1('color_default_foreground');
12203
    const getDefaultBackgroundColor = option$1('color_default_background');
12204
 
12205
    const defaultBackgroundColor = 'rgba(0, 0, 0, 0)';
12206
    const isValidBackgroundColor = value => fromString(value).exists(c => c.alpha !== 0);
12207
    const getClosestCssBackgroundColorValue = scope => {
12208
      return closest$4(scope, node => {
12209
        if (isElement$1(node)) {
12210
          const color = get$e(node, 'background-color');
12211
          return someIf(isValidBackgroundColor(color), color);
12212
        } else {
12213
          return Optional.none();
12214
        }
12215
      }).getOr(defaultBackgroundColor);
12216
    };
12217
    const getCurrentColor = (editor, format) => {
12218
      const node = SugarElement.fromDom(editor.selection.getStart());
12219
      const cssRgbValue = format === 'hilitecolor' ? getClosestCssBackgroundColorValue(node) : get$e(node, 'color');
12220
      return fromString(cssRgbValue).map(rgba => '#' + fromRgba(rgba).value);
12221
    };
12222
    const applyFormat = (editor, format, value) => {
12223
      editor.undoManager.transact(() => {
12224
        editor.focus();
12225
        editor.formatter.apply(format, { value });
12226
        editor.nodeChanged();
12227
      });
12228
    };
12229
    const removeFormat = (editor, format) => {
12230
      editor.undoManager.transact(() => {
12231
        editor.focus();
12232
        editor.formatter.remove(format, { value: null }, undefined, true);
12233
        editor.nodeChanged();
12234
      });
12235
    };
12236
    const registerCommands = editor => {
12237
      editor.addCommand('mceApplyTextcolor', (format, value) => {
12238
        applyFormat(editor, format, value);
12239
      });
12240
      editor.addCommand('mceRemoveTextcolor', format => {
12241
        removeFormat(editor, format);
12242
      });
12243
    };
12244
    const getAdditionalColors = hasCustom => {
12245
      const type = 'choiceitem';
12246
      const remove = {
12247
        type,
12248
        text: 'Remove color',
12249
        icon: 'color-swatch-remove-color',
12250
        value: 'remove'
12251
      };
12252
      const custom = {
12253
        type,
12254
        text: 'Custom color',
12255
        icon: 'color-picker',
12256
        value: 'custom'
12257
      };
12258
      return hasCustom ? [
12259
        remove,
12260
        custom
12261
      ] : [remove];
12262
    };
12263
    const applyColor = (editor, format, value, onChoice) => {
12264
      if (value === 'custom') {
12265
        const dialog = colorPickerDialog(editor);
12266
        dialog(colorOpt => {
12267
          colorOpt.each(color => {
12268
            addColor(format, color);
12269
            editor.execCommand('mceApplyTextcolor', format, color);
12270
            onChoice(color);
12271
          });
12272
        }, getCurrentColor(editor, format).getOr(fallbackColor));
12273
      } else if (value === 'remove') {
12274
        onChoice('');
12275
        editor.execCommand('mceRemoveTextcolor', format);
12276
      } else {
12277
        onChoice(value);
12278
        editor.execCommand('mceApplyTextcolor', format, value);
12279
      }
12280
    };
12281
    const getColors$1 = (colors, id, hasCustom) => colors.concat(getCurrentColors(id).concat(getAdditionalColors(hasCustom)));
12282
    const getFetch$1 = (colors, id, hasCustom) => callback => {
12283
      callback(getColors$1(colors, id, hasCustom));
12284
    };
12285
    const setIconColor = (splitButtonApi, name, newColor) => {
12286
      const id = name === 'forecolor' ? 'tox-icon-text-color__color' : 'tox-icon-highlight-bg-color__color';
12287
      splitButtonApi.setIconFill(id, newColor);
12288
    };
12289
    const setTooltip = (buttonApi, tooltip) => {
12290
      buttonApi.setTooltip(tooltip);
12291
    };
12292
    const select$1 = (editor, format) => value => {
12293
      const optCurrentHex = getCurrentColor(editor, format);
12294
      return is$1(optCurrentHex, value.toUpperCase());
12295
    };
12296
    const getToolTipText = (editor, format, lastColor) => {
12297
      if (isEmpty(lastColor)) {
12298
        return format === 'forecolor' ? 'Text color' : 'Background color';
12299
      }
12300
      const tooltipPrefix = format === 'forecolor' ? 'Text color {0}' : 'Background color {0}';
12301
      const colors = getColors$1(getColors$2(editor, format), format, false);
12302
      const colorText = find$5(colors, c => c.value === lastColor).getOr({ text: '' }).text;
12303
      return editor.translate([
12304
        tooltipPrefix,
12305
        editor.translate(colorText)
12306
      ]);
12307
    };
12308
    const registerTextColorButton = (editor, name, format, lastColor) => {
12309
      editor.ui.registry.addSplitButton(name, {
12310
        tooltip: getToolTipText(editor, format, lastColor.get()),
12311
        presets: 'color',
12312
        icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
12313
        select: select$1(editor, format),
12314
        columns: getColorCols$1(editor, format),
12315
        fetch: getFetch$1(getColors$2(editor, format), format, hasCustomColors$1(editor)),
12316
        onAction: _splitButtonApi => {
12317
          applyColor(editor, format, lastColor.get(), noop);
12318
        },
12319
        onItemAction: (_splitButtonApi, value) => {
12320
          applyColor(editor, format, value, newColor => {
12321
            lastColor.set(newColor);
12322
            fireTextColorChange(editor, {
12323
              name,
12324
              color: newColor
12325
            });
12326
          });
12327
        },
12328
        onSetup: splitButtonApi => {
12329
          setIconColor(splitButtonApi, name, lastColor.get());
12330
          const handler = e => {
12331
            if (e.name === name) {
12332
              setIconColor(splitButtonApi, e.name, e.color);
12333
              setTooltip(splitButtonApi, getToolTipText(editor, format, e.color));
12334
            }
12335
          };
12336
          editor.on('TextColorChange', handler);
12337
          return composeUnbinders(onSetupEditableToggle(editor)(splitButtonApi), () => {
12338
            editor.off('TextColorChange', handler);
12339
          });
12340
        }
12341
      });
12342
    };
12343
    const registerTextColorMenuItem = (editor, name, format, text, lastColor) => {
12344
      editor.ui.registry.addNestedMenuItem(name, {
12345
        text,
12346
        icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
12347
        onSetup: api => {
12348
          setTooltip(api, getToolTipText(editor, format, lastColor.get()));
12349
          setIconColor(api, name, lastColor.get());
12350
          return onSetupEditableToggle(editor)(api);
12351
        },
12352
        getSubmenuItems: () => [{
12353
            type: 'fancymenuitem',
12354
            fancytype: 'colorswatch',
12355
            select: select$1(editor, format),
12356
            initData: { storageKey: format },
12357
            onAction: data => {
12358
              applyColor(editor, format, data.value, newColor => {
12359
                lastColor.set(newColor);
12360
                fireTextColorChange(editor, {
12361
                  name,
12362
                  color: newColor
12363
                });
12364
              });
12365
            }
12366
          }]
12367
      });
12368
    };
12369
    const colorPickerDialog = editor => (callback, value) => {
12370
      let isValid = false;
12371
      const onSubmit = api => {
12372
        const data = api.getData();
12373
        const hex = data.colorpicker;
12374
        if (isValid) {
12375
          callback(Optional.from(hex));
12376
          api.close();
12377
        } else {
12378
          editor.windowManager.alert(editor.translate([
12379
            'Invalid hex color code: {0}',
12380
            hex
12381
          ]));
12382
        }
12383
      };
12384
      const onAction = (_api, details) => {
12385
        if (details.name === 'hex-valid') {
12386
          isValid = details.value;
12387
        }
12388
      };
12389
      const initialData = { colorpicker: value };
12390
      editor.windowManager.open({
12391
        title: 'Color Picker',
12392
        size: 'normal',
12393
        body: {
12394
          type: 'panel',
12395
          items: [{
12396
              type: 'colorpicker',
12397
              name: 'colorpicker',
12398
              label: 'Color'
12399
            }]
12400
        },
12401
        buttons: [
12402
          {
12403
            type: 'cancel',
12404
            name: 'cancel',
12405
            text: 'Cancel'
12406
          },
12407
          {
12408
            type: 'submit',
12409
            name: 'save',
12410
            text: 'Save',
12411
            primary: true
12412
          }
12413
        ],
12414
        initialData,
12415
        onAction,
12416
        onSubmit,
12417
        onClose: noop,
12418
        onCancel: () => {
12419
          callback(Optional.none());
12420
        }
12421
      });
12422
    };
12423
    const register$c = editor => {
12424
      registerCommands(editor);
12425
      const fallbackColorForeground = getDefaultForegroundColor(editor);
12426
      const fallbackColorBackground = getDefaultBackgroundColor(editor);
12427
      const lastForeColor = Cell(fallbackColorForeground);
12428
      const lastBackColor = Cell(fallbackColorBackground);
12429
      registerTextColorButton(editor, 'forecolor', 'forecolor', lastForeColor);
12430
      registerTextColorButton(editor, 'backcolor', 'hilitecolor', lastBackColor);
12431
      registerTextColorMenuItem(editor, 'forecolor', 'forecolor', 'Text color', lastForeColor);
12432
      registerTextColorMenuItem(editor, 'backcolor', 'hilitecolor', 'Background color', lastBackColor);
12433
    };
12434
 
12435
    const createPartialChoiceMenu = (value, items, onItemValueHandler, columns, presets, itemResponse, select, providersBackstage) => {
12436
      const hasIcons = menuHasIcons(items);
12437
      const presetItemTypes = presets !== 'color' ? 'normal' : 'color';
12438
      const alloyItems = createChoiceItems(items, onItemValueHandler, columns, presetItemTypes, itemResponse, select, providersBackstage);
12439
      const menuLayout = { menuType: presets };
12440
      return createPartialMenuWithAlloyItems(value, hasIcons, alloyItems, columns, menuLayout);
12441
    };
12442
    const createChoiceItems = (items, onItemValueHandler, columns, itemPresets, itemResponse, select, providersBackstage) => cat(map$2(items, item => {
12443
      if (item.type === 'choiceitem') {
12444
        return createChoiceMenuItem(item).fold(handleError, d => Optional.some(renderChoiceItem(d, columns === 1, itemPresets, onItemValueHandler, select(d.value), itemResponse, providersBackstage, menuHasIcons(items))));
12445
      } else {
12446
        return Optional.none();
12447
      }
12448
    }));
12449
 
12450
    const deriveMenuMovement = (columns, presets) => {
12451
      const menuMarkers = markers(presets);
12452
      if (columns === 1) {
12453
        return {
12454
          mode: 'menu',
12455
          moveOnTab: true
12456
        };
12457
      } else if (columns === 'auto') {
12458
        return {
12459
          mode: 'grid',
12460
          selector: '.' + menuMarkers.item,
12461
          initSize: {
12462
            numColumns: 1,
12463
            numRows: 1
12464
          }
12465
        };
12466
      } else {
12467
        const rowClass = presets === 'color' ? 'tox-swatches__row' : 'tox-collection__group';
12468
        return {
12469
          mode: 'matrix',
12470
          rowSelector: '.' + rowClass,
12471
          previousSelector: menu => {
12472
            return presets === 'color' ? descendant(menu.element, '[aria-checked=true]') : Optional.none();
12473
          }
12474
        };
12475
      }
12476
    };
12477
    const deriveCollectionMovement = (columns, presets) => {
12478
      if (columns === 1) {
12479
        return {
12480
          mode: 'menu',
12481
          moveOnTab: false,
12482
          selector: '.tox-collection__item'
12483
        };
12484
      } else if (columns === 'auto') {
12485
        return {
12486
          mode: 'flatgrid',
12487
          selector: '.' + 'tox-collection__item',
12488
          initSize: {
12489
            numColumns: 1,
12490
            numRows: 1
12491
          }
12492
        };
12493
      } else {
12494
        return {
12495
          mode: 'matrix',
12496
          selectors: {
12497
            row: presets === 'color' ? '.tox-swatches__row' : '.tox-collection__group',
12498
            cell: presets === 'color' ? `.${ colorClass }` : `.${ selectableClass }`
12499
          }
12500
        };
12501
      }
12502
    };
12503
 
12504
    const renderColorSwatchItem = (spec, backstage) => {
12505
      const items = getColorItems(spec, backstage);
12506
      const columns = backstage.colorinput.getColorCols(spec.initData.storageKey);
12507
      const presets = 'color';
12508
      const menuSpec = createPartialChoiceMenu(generate$6('menu-value'), items, value => {
12509
        spec.onAction({ value });
12510
      }, columns, presets, ItemResponse$1.CLOSE_ON_EXECUTE, spec.select.getOr(never), backstage.shared.providers);
12511
      const widgetSpec = {
12512
        ...menuSpec,
12513
        markers: markers(presets),
12514
        movement: deriveMenuMovement(columns, presets)
12515
      };
12516
      return {
12517
        type: 'widget',
12518
        data: { value: generate$6('widget-id') },
12519
        dom: {
12520
          tag: 'div',
12521
          classes: ['tox-fancymenuitem']
12522
        },
12523
        autofocus: true,
12524
        components: [parts$f.widget(Menu.sketch(widgetSpec))]
12525
      };
12526
    };
12527
    const getColorItems = (spec, backstage) => {
12528
      const useCustomColors = spec.initData.allowCustomColors && backstage.colorinput.hasCustomColors();
12529
      return spec.initData.colors.fold(() => getColors$1(backstage.colorinput.getColors(spec.initData.storageKey), spec.initData.storageKey, useCustomColors), colors => colors.concat(getAdditionalColors(useCustomColors)));
12530
    };
12531
 
12532
    const cellOverEvent = generate$6('cell-over');
12533
    const cellExecuteEvent = generate$6('cell-execute');
12534
    const makeAnnouncementText = backstage => (row, col) => backstage.shared.providers.translate([
12535
      '{0} columns, {1} rows',
12536
      col,
12537
      row
12538
    ]);
12539
    const makeCell = (row, col, label) => {
12540
      const emitCellOver = c => emitWith(c, cellOverEvent, {
12541
        row,
12542
        col
12543
      });
12544
      const emitExecute = c => emitWith(c, cellExecuteEvent, {
12545
        row,
12546
        col
12547
      });
12548
      const onClick = (c, se) => {
12549
        se.stop();
12550
        emitExecute(c);
12551
      };
12552
      return build$1({
12553
        dom: {
12554
          tag: 'div',
12555
          attributes: {
12556
            role: 'button',
12557
            ['aria-label']: label
12558
          }
12559
        },
12560
        behaviours: derive$1([
12561
          config('insert-table-picker-cell', [
12562
            run$1(mouseover(), Focusing.focus),
12563
            run$1(execute$5(), emitExecute),
12564
            run$1(click(), onClick),
12565
            run$1(tap(), onClick)
12566
          ]),
12567
          Toggling.config({
12568
            toggleClass: 'tox-insert-table-picker__selected',
12569
            toggleOnExecute: false
12570
          }),
12571
          Focusing.config({ onFocus: emitCellOver })
12572
        ])
12573
      });
12574
    };
12575
    const makeCells = (getCellLabel, numRows, numCols) => {
12576
      const cells = [];
12577
      for (let i = 0; i < numRows; i++) {
12578
        const row = [];
12579
        for (let j = 0; j < numCols; j++) {
12580
          const label = getCellLabel(i + 1, j + 1);
12581
          row.push(makeCell(i, j, label));
12582
        }
12583
        cells.push(row);
12584
      }
12585
      return cells;
12586
    };
12587
    const selectCells = (cells, selectedRow, selectedColumn, numRows, numColumns) => {
12588
      for (let i = 0; i < numRows; i++) {
12589
        for (let j = 0; j < numColumns; j++) {
12590
          Toggling.set(cells[i][j], i <= selectedRow && j <= selectedColumn);
12591
        }
12592
      }
12593
    };
12594
    const makeComponents = cells => bind$3(cells, cellRow => map$2(cellRow, premade));
12595
    const makeLabelText = (row, col) => text$2(`${ col }x${ row }`);
12596
    const renderInsertTableMenuItem = (spec, backstage) => {
12597
      const numRows = 10;
12598
      const numColumns = 10;
12599
      const getCellLabel = makeAnnouncementText(backstage);
12600
      const cells = makeCells(getCellLabel, numRows, numColumns);
12601
      const emptyLabelText = makeLabelText(0, 0);
12602
      const memLabel = record({
12603
        dom: {
12604
          tag: 'span',
12605
          classes: ['tox-insert-table-picker__label']
12606
        },
12607
        components: [emptyLabelText],
12608
        behaviours: derive$1([Replacing.config({})])
12609
      });
12610
      return {
12611
        type: 'widget',
12612
        data: { value: generate$6('widget-id') },
12613
        dom: {
12614
          tag: 'div',
12615
          classes: ['tox-fancymenuitem']
12616
        },
12617
        autofocus: true,
12618
        components: [parts$f.widget({
12619
            dom: {
12620
              tag: 'div',
12621
              classes: ['tox-insert-table-picker']
12622
            },
12623
            components: makeComponents(cells).concat(memLabel.asSpec()),
12624
            behaviours: derive$1([
12625
              config('insert-table-picker', [
12626
                runOnAttached(c => {
12627
                  Replacing.set(memLabel.get(c), [emptyLabelText]);
12628
                }),
12629
                runWithTarget(cellOverEvent, (c, t, e) => {
12630
                  const {row, col} = e.event;
12631
                  selectCells(cells, row, col, numRows, numColumns);
12632
                  Replacing.set(memLabel.get(c), [makeLabelText(row + 1, col + 1)]);
12633
                }),
12634
                runWithTarget(cellExecuteEvent, (c, _, e) => {
12635
                  const {row, col} = e.event;
12636
                  spec.onAction({
12637
                    numRows: row + 1,
12638
                    numColumns: col + 1
12639
                  });
12640
                  emit(c, sandboxClose());
12641
                })
12642
              ]),
12643
              Keying.config({
12644
                initSize: {
12645
                  numRows,
12646
                  numColumns
12647
                },
12648
                mode: 'flatgrid',
12649
                selector: '[role="button"]'
12650
              })
12651
            ])
12652
          })]
12653
      };
12654
    };
12655
 
12656
    const fancyMenuItems = {
12657
      inserttable: renderInsertTableMenuItem,
12658
      colorswatch: renderColorSwatchItem
12659
    };
12660
    const renderFancyMenuItem = (spec, backstage) => get$g(fancyMenuItems, spec.fancytype).map(render => render(spec, backstage));
12661
 
12662
    const renderNestedItem = (spec, itemResponse, providersBackstage, renderIcons = true, downwardsCaret = false) => {
12663
      const caret = downwardsCaret ? renderDownwardsCaret(providersBackstage.icons) : renderSubmenuCaret(providersBackstage.icons);
12664
      const getApi = component => ({
12665
        isEnabled: () => !Disabling.isDisabled(component),
12666
        setEnabled: state => Disabling.set(component, !state),
12667
        setIconFill: (id, value) => {
12668
          descendant(component.element, `svg path[class="${ id }"], rect[class="${ id }"]`).each(underlinePath => {
12669
            set$9(underlinePath, 'fill', value);
12670
          });
12671
        },
12672
        setTooltip: tooltip => {
12673
          const translatedTooltip = providersBackstage.translate(tooltip);
12674
          setAll$1(component.element, {
12675
            'aria-label': translatedTooltip,
12676
            'title': translatedTooltip
12677
          });
12678
        }
12679
      });
12680
      const structure = renderItemStructure({
12681
        presets: 'normal',
12682
        iconContent: spec.icon,
12683
        textContent: spec.text,
12684
        htmlContent: Optional.none(),
12685
        ariaLabel: spec.text,
12686
        caret: Optional.some(caret),
12687
        checkMark: Optional.none(),
12688
        shortcutContent: spec.shortcut
12689
      }, providersBackstage, renderIcons);
12690
      return renderCommonItem({
12691
        data: buildData(spec),
12692
        getApi,
12693
        enabled: spec.enabled,
12694
        onAction: noop,
12695
        onSetup: spec.onSetup,
12696
        triggersSubmenu: true,
12697
        itemBehaviours: []
12698
      }, structure, itemResponse, providersBackstage);
12699
    };
12700
 
12701
    const renderNormalItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
12702
      const getApi = component => ({
12703
        isEnabled: () => !Disabling.isDisabled(component),
12704
        setEnabled: state => Disabling.set(component, !state)
12705
      });
12706
      const structure = renderItemStructure({
12707
        presets: 'normal',
12708
        iconContent: spec.icon,
12709
        textContent: spec.text,
12710
        htmlContent: Optional.none(),
12711
        ariaLabel: spec.text,
12712
        caret: Optional.none(),
12713
        checkMark: Optional.none(),
12714
        shortcutContent: spec.shortcut
12715
      }, providersBackstage, renderIcons);
12716
      return renderCommonItem({
12717
        data: buildData(spec),
12718
        getApi,
12719
        enabled: spec.enabled,
12720
        onAction: spec.onAction,
12721
        onSetup: spec.onSetup,
12722
        triggersSubmenu: false,
12723
        itemBehaviours: []
12724
      }, structure, itemResponse, providersBackstage);
12725
    };
12726
 
12727
    const renderSeparatorItem = spec => ({
12728
      type: 'separator',
12729
      dom: {
12730
        tag: 'div',
12731
        classes: [
12732
          selectableClass,
12733
          groupHeadingClass
12734
        ]
12735
      },
12736
      components: spec.text.map(text$2).toArray()
12737
    });
12738
 
12739
    const renderToggleMenuItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
12740
      const getApi = component => ({
12741
        setActive: state => {
12742
          Toggling.set(component, state);
12743
        },
12744
        isActive: () => Toggling.isOn(component),
12745
        isEnabled: () => !Disabling.isDisabled(component),
12746
        setEnabled: state => Disabling.set(component, !state)
12747
      });
12748
      const structure = renderItemStructure({
12749
        iconContent: spec.icon,
12750
        textContent: spec.text,
12751
        htmlContent: Optional.none(),
12752
        ariaLabel: spec.text,
12753
        checkMark: Optional.some(renderCheckmark(providersBackstage.icons)),
12754
        caret: Optional.none(),
12755
        shortcutContent: spec.shortcut,
12756
        presets: 'normal',
12757
        meta: spec.meta
12758
      }, providersBackstage, renderIcons);
12759
      return deepMerge(renderCommonItem({
12760
        data: buildData(spec),
12761
        enabled: spec.enabled,
12762
        getApi,
12763
        onAction: spec.onAction,
12764
        onSetup: spec.onSetup,
12765
        triggersSubmenu: false,
12766
        itemBehaviours: []
12767
      }, structure, itemResponse, providersBackstage), {
12768
        toggling: {
12769
          toggleClass: tickedClass,
12770
          toggleOnExecute: false,
12771
          selected: spec.active
12772
        }
12773
      });
12774
    };
12775
 
12776
    const autocomplete = renderAutocompleteItem;
12777
    const separator$3 = renderSeparatorItem;
12778
    const normal = renderNormalItem;
12779
    const nested = renderNestedItem;
12780
    const toggle$1 = renderToggleMenuItem;
12781
    const fancy = renderFancyMenuItem;
12782
    const card = renderCardMenuItem;
12783
 
12784
    const getCoupled = (component, coupleConfig, coupleState, name) => coupleState.getOrCreate(component, coupleConfig, name);
12785
    const getExistingCoupled = (component, coupleConfig, coupleState, name) => coupleState.getExisting(component, coupleConfig, name);
12786
 
12787
    var CouplingApis = /*#__PURE__*/Object.freeze({
12788
        __proto__: null,
12789
        getCoupled: getCoupled,
12790
        getExistingCoupled: getExistingCoupled
12791
    });
12792
 
12793
    var CouplingSchema = [requiredOf('others', setOf(Result.value, anyValue()))];
12794
 
12795
    const init$a = () => {
12796
      const coupled = {};
12797
      const lookupCoupled = (coupleConfig, coupledName) => {
12798
        const available = keys(coupleConfig.others);
12799
        if (available.length === 0) {
12800
          throw new Error('Cannot find any known coupled components');
12801
        } else {
12802
          return get$g(coupled, coupledName);
12803
        }
12804
      };
12805
      const getOrCreate = (component, coupleConfig, name) => {
12806
        return lookupCoupled(coupleConfig, name).getOrThunk(() => {
12807
          const builder = get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
12808
          const spec = builder(component);
12809
          const built = component.getSystem().build(spec);
12810
          coupled[name] = built;
12811
          return built;
12812
        });
12813
      };
12814
      const getExisting = (component, coupleConfig, name) => {
12815
        return lookupCoupled(coupleConfig, name).orThunk(() => {
12816
          get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
12817
          return Optional.none();
12818
        });
12819
      };
12820
      const readState = constant$1({});
12821
      return nu$8({
12822
        readState,
12823
        getExisting,
12824
        getOrCreate
12825
      });
12826
    };
12827
 
12828
    var CouplingState = /*#__PURE__*/Object.freeze({
12829
        __proto__: null,
12830
        init: init$a
12831
    });
12832
 
12833
    const Coupling = create$4({
12834
      fields: CouplingSchema,
12835
      name: 'coupling',
12836
      apis: CouplingApis,
12837
      state: CouplingState
12838
    });
12839
 
12840
    const nu$3 = baseFn => {
12841
      let data = Optional.none();
12842
      let callbacks = [];
12843
      const map = f => nu$3(nCallback => {
12844
        get(data => {
12845
          nCallback(f(data));
12846
        });
12847
      });
12848
      const get = nCallback => {
12849
        if (isReady()) {
12850
          call(nCallback);
12851
        } else {
12852
          callbacks.push(nCallback);
12853
        }
12854
      };
12855
      const set = x => {
12856
        if (!isReady()) {
12857
          data = Optional.some(x);
12858
          run(callbacks);
12859
          callbacks = [];
12860
        }
12861
      };
12862
      const isReady = () => data.isSome();
12863
      const run = cbs => {
12864
        each$1(cbs, call);
12865
      };
12866
      const call = cb => {
12867
        data.each(x => {
12868
          setTimeout(() => {
12869
            cb(x);
12870
          }, 0);
12871
        });
12872
      };
12873
      baseFn(set);
12874
      return {
12875
        get,
12876
        map,
12877
        isReady
12878
      };
12879
    };
12880
    const pure$1 = a => nu$3(callback => {
12881
      callback(a);
12882
    });
12883
    const LazyValue = {
12884
      nu: nu$3,
12885
      pure: pure$1
12886
    };
12887
 
12888
    const errorReporter = err => {
12889
      setTimeout(() => {
12890
        throw err;
12891
      }, 0);
12892
    };
12893
    const make$5 = run => {
12894
      const get = callback => {
12895
        run().then(callback, errorReporter);
12896
      };
12897
      const map = fab => {
12898
        return make$5(() => run().then(fab));
12899
      };
12900
      const bind = aFutureB => {
12901
        return make$5(() => run().then(v => aFutureB(v).toPromise()));
12902
      };
12903
      const anonBind = futureB => {
12904
        return make$5(() => run().then(() => futureB.toPromise()));
12905
      };
12906
      const toLazy = () => {
12907
        return LazyValue.nu(get);
12908
      };
12909
      const toCached = () => {
12910
        let cache = null;
12911
        return make$5(() => {
12912
          if (cache === null) {
12913
            cache = run();
12914
          }
12915
          return cache;
12916
        });
12917
      };
12918
      const toPromise = run;
12919
      return {
12920
        map,
12921
        bind,
12922
        anonBind,
12923
        toLazy,
12924
        toCached,
12925
        toPromise,
12926
        get
12927
      };
12928
    };
12929
    const nu$2 = baseFn => {
12930
      return make$5(() => new Promise(baseFn));
12931
    };
12932
    const pure = a => {
12933
      return make$5(() => Promise.resolve(a));
12934
    };
12935
    const Future = {
12936
      nu: nu$2,
12937
      pure
12938
    };
12939
 
12940
    const suffix = constant$1('sink');
12941
    const partType$1 = constant$1(optional({
12942
      name: suffix(),
12943
      overrides: constant$1({
12944
        dom: { tag: 'div' },
12945
        behaviours: derive$1([Positioning.config({ useFixed: always })]),
12946
        events: derive$2([
12947
          cutter(keydown()),
12948
          cutter(mousedown()),
12949
          cutter(click())
12950
        ])
12951
      })
12952
    }));
12953
 
12954
    const getAnchor = (detail, component) => {
12955
      const hotspot = detail.getHotspot(component).getOr(component);
12956
      const type = 'hotspot';
12957
      const overrides = detail.getAnchorOverrides();
12958
      return detail.layouts.fold(() => ({
12959
        type,
12960
        hotspot,
12961
        overrides
12962
      }), layouts => ({
12963
        type,
12964
        hotspot,
12965
        overrides,
12966
        layouts
12967
      }));
12968
    };
12969
    const fetch = (detail, mapFetch, component) => {
12970
      const fetcher = detail.fetch;
12971
      return fetcher(component).map(mapFetch);
12972
    };
12973
    const openF = (detail, mapFetch, anchor, component, sandbox, externals, highlightOnOpen) => {
12974
      const futureData = fetch(detail, mapFetch, component);
12975
      const getLazySink = getSink(component, detail);
12976
      return futureData.map(tdata => tdata.bind(data => Optional.from(tieredMenu.sketch({
12977
        ...externals.menu(),
12978
        uid: generate$5(''),
12979
        data,
12980
        highlightOnOpen,
12981
        onOpenMenu: (tmenu, menu) => {
12982
          const sink = getLazySink().getOrDie();
12983
          Positioning.position(sink, menu, { anchor });
12984
          Sandboxing.decloak(sandbox);
12985
        },
12986
        onOpenSubmenu: (tmenu, item, submenu) => {
12987
          const sink = getLazySink().getOrDie();
12988
          Positioning.position(sink, submenu, {
12989
            anchor: {
12990
              type: 'submenu',
12991
              item
12992
            }
12993
          });
12994
          Sandboxing.decloak(sandbox);
12995
        },
12996
        onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
12997
          const sink = getLazySink().getOrDie();
12998
          Positioning.position(sink, primaryMenu, { anchor });
12999
          each$1(submenuTriggers, st => {
13000
            Positioning.position(sink, st.triggeredMenu, {
13001
              anchor: {
13002
                type: 'submenu',
13003
                item: st.triggeringItem
13004
              }
13005
            });
13006
          });
13007
        },
13008
        onEscape: () => {
13009
          Focusing.focus(component);
13010
          Sandboxing.close(sandbox);
13011
          return Optional.some(true);
13012
        }
13013
      }))));
13014
    };
13015
    const open = (detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen) => {
13016
      const anchor = getAnchor(detail, hotspot);
13017
      const processed = openF(detail, mapFetch, anchor, hotspot, sandbox, externals, highlightOnOpen);
13018
      return processed.map(tdata => {
13019
        tdata.fold(() => {
13020
          if (Sandboxing.isOpen(sandbox)) {
13021
            Sandboxing.close(sandbox);
13022
          }
13023
        }, data => {
13024
          Sandboxing.cloak(sandbox);
13025
          Sandboxing.open(sandbox, data);
13026
          onOpenSync(sandbox);
13027
        });
13028
        return sandbox;
13029
      });
13030
    };
13031
    const close = (detail, mapFetch, component, sandbox, _externals, _onOpenSync, _highlightOnOpen) => {
13032
      Sandboxing.close(sandbox);
13033
      return Future.pure(sandbox);
13034
    };
13035
    const togglePopup = (detail, mapFetch, hotspot, externals, onOpenSync, highlightOnOpen) => {
13036
      const sandbox = Coupling.getCoupled(hotspot, 'sandbox');
13037
      const showing = Sandboxing.isOpen(sandbox);
13038
      const action = showing ? close : open;
13039
      return action(detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen);
13040
    };
13041
    const matchWidth = (hotspot, container, useMinWidth) => {
13042
      const menu = Composing.getCurrent(container).getOr(container);
13043
      const buttonWidth = get$c(hotspot.element);
13044
      if (useMinWidth) {
13045
        set$8(menu.element, 'min-width', buttonWidth + 'px');
13046
      } else {
13047
        set$7(menu.element, buttonWidth);
13048
      }
13049
    };
13050
    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)));
13051
    const doRepositionMenus = sandbox => {
13052
      Sandboxing.getState(sandbox).each(tmenu => {
13053
        tieredMenu.repositionMenus(tmenu);
13054
      });
13055
    };
13056
    const makeSandbox$1 = (detail, hotspot, extras) => {
13057
      const ariaControls = manager();
13058
      const onOpen = (component, menu) => {
13059
        const anchor = getAnchor(detail, hotspot);
13060
        ariaControls.link(hotspot.element);
13061
        if (detail.matchWidth) {
13062
          matchWidth(anchor.hotspot, menu, detail.useMinWidth);
13063
        }
13064
        detail.onOpen(anchor, component, menu);
13065
        if (extras !== undefined && extras.onOpen !== undefined) {
13066
          extras.onOpen(component, menu);
13067
        }
13068
      };
13069
      const onClose = (component, menu) => {
13070
        ariaControls.unlink(hotspot.element);
13071
        if (extras !== undefined && extras.onClose !== undefined) {
13072
          extras.onClose(component, menu);
13073
        }
13074
      };
13075
      const lazySink = getSink(hotspot, detail);
13076
      return {
13077
        dom: {
13078
          tag: 'div',
13079
          classes: detail.sandboxClasses,
13080
          attributes: {
13081
            id: ariaControls.id,
13082
            role: 'listbox'
13083
          }
13084
        },
13085
        behaviours: SketchBehaviours.augment(detail.sandboxBehaviours, [
13086
          Representing.config({
13087
            store: {
13088
              mode: 'memory',
13089
              initialValue: hotspot
13090
            }
13091
          }),
13092
          Sandboxing.config({
13093
            onOpen,
13094
            onClose,
13095
            isPartOf: (container, data, queryElem) => {
13096
              return isPartOf$1(data, queryElem) || isPartOf$1(hotspot, queryElem);
13097
            },
13098
            getAttachPoint: () => {
13099
              return lazySink().getOrDie();
13100
            }
13101
          }),
13102
          Composing.config({
13103
            find: sandbox => {
13104
              return Sandboxing.getState(sandbox).bind(menu => Composing.getCurrent(menu));
13105
            }
13106
          }),
13107
          Receiving.config({
13108
            channels: {
13109
              ...receivingChannel$1({ isExtraPart: never }),
13110
              ...receivingChannel({ doReposition: doRepositionMenus })
13111
            }
13112
          })
13113
        ])
13114
      };
13115
    };
13116
    const repositionMenus = comp => {
13117
      const sandbox = Coupling.getCoupled(comp, 'sandbox');
13118
      doRepositionMenus(sandbox);
13119
    };
13120
 
13121
    const sandboxFields = () => [
13122
      defaulted('sandboxClasses', []),
13123
      SketchBehaviours.field('sandboxBehaviours', [
13124
        Composing,
13125
        Receiving,
13126
        Sandboxing,
13127
        Representing
13128
      ])
13129
    ];
13130
 
13131
    const schema$k = constant$1([
13132
      required$1('dom'),
13133
      required$1('fetch'),
13134
      onHandler('onOpen'),
13135
      onKeyboardHandler('onExecute'),
13136
      defaulted('getHotspot', Optional.some),
13137
      defaulted('getAnchorOverrides', constant$1({})),
13138
      schema$y(),
13139
      field('dropdownBehaviours', [
13140
        Toggling,
13141
        Coupling,
13142
        Keying,
13143
        Focusing
13144
      ]),
13145
      required$1('toggleClass'),
13146
      defaulted('eventOrder', {}),
13147
      option$3('lazySink'),
13148
      defaulted('matchWidth', false),
13149
      defaulted('useMinWidth', false),
13150
      option$3('role')
13151
    ].concat(sandboxFields()));
13152
    const parts$e = constant$1([
13153
      external({
13154
        schema: [
13155
          tieredMenuMarkers(),
13156
          defaulted('fakeFocus', false)
13157
        ],
13158
        name: 'menu',
13159
        defaults: detail => {
13160
          return { onExecute: detail.onExecute };
13161
        }
13162
      }),
13163
      partType$1()
13164
    ]);
13165
 
13166
    const factory$k = (detail, components, _spec, externals) => {
13167
      const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
13168
      const switchToMenu = sandbox => {
13169
        Sandboxing.getState(sandbox).each(tmenu => {
13170
          tieredMenu.highlightPrimary(tmenu);
13171
        });
13172
      };
13173
      const togglePopup$1 = (dropdownComp, onOpenSync, highlightOnOpen) => {
13174
        return togglePopup(detail, identity, dropdownComp, externals, onOpenSync, highlightOnOpen);
13175
      };
13176
      const action = component => {
13177
        const onOpenSync = switchToMenu;
13178
        togglePopup$1(component, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
13179
      };
13180
      const apis = {
13181
        expand: comp => {
13182
          if (!Toggling.isOn(comp)) {
13183
            togglePopup$1(comp, noop, HighlightOnOpen.HighlightNone).get(noop);
13184
          }
13185
        },
13186
        open: comp => {
13187
          if (!Toggling.isOn(comp)) {
13188
            togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
13189
          }
13190
        },
13191
        refetch: comp => {
13192
          const optSandbox = Coupling.getExistingCoupled(comp, 'sandbox');
13193
          return optSandbox.fold(() => {
13194
            return togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
13195
          }, sandboxComp => {
13196
            return open(detail, identity, comp, sandboxComp, externals, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
13197
          });
13198
        },
13199
        isOpen: Toggling.isOn,
13200
        close: comp => {
13201
          if (Toggling.isOn(comp)) {
13202
            togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
13203
          }
13204
        },
13205
        repositionMenus: comp => {
13206
          if (Toggling.isOn(comp)) {
13207
            repositionMenus(comp);
13208
          }
13209
        }
13210
      };
13211
      const triggerExecute = (comp, _se) => {
13212
        emitExecute(comp);
13213
        return Optional.some(true);
13214
      };
13215
      return {
13216
        uid: detail.uid,
13217
        dom: detail.dom,
13218
        components,
13219
        behaviours: augment(detail.dropdownBehaviours, [
13220
          Toggling.config({
13221
            toggleClass: detail.toggleClass,
13222
            aria: { mode: 'expanded' }
13223
          }),
13224
          Coupling.config({
13225
            others: {
13226
              sandbox: hotspot => {
13227
                return makeSandbox$1(detail, hotspot, {
13228
                  onOpen: () => Toggling.on(hotspot),
13229
                  onClose: () => Toggling.off(hotspot)
13230
                });
13231
              }
13232
            }
13233
          }),
13234
          Keying.config({
13235
            mode: 'special',
13236
            onSpace: triggerExecute,
13237
            onEnter: triggerExecute,
13238
            onDown: (comp, _se) => {
13239
              if (Dropdown.isOpen(comp)) {
13240
                const sandbox = Coupling.getCoupled(comp, 'sandbox');
13241
                switchToMenu(sandbox);
13242
              } else {
13243
                Dropdown.open(comp);
13244
              }
13245
              return Optional.some(true);
13246
            },
13247
            onEscape: (comp, _se) => {
13248
              if (Dropdown.isOpen(comp)) {
13249
                Dropdown.close(comp);
13250
                return Optional.some(true);
13251
              } else {
13252
                return Optional.none();
13253
              }
13254
            }
13255
          }),
13256
          Focusing.config({})
13257
        ]),
13258
        events: events$a(Optional.some(action)),
13259
        eventOrder: {
13260
          ...detail.eventOrder,
13261
          [execute$5()]: [
13262
            'disabling',
13263
            'toggling',
13264
            'alloy.base.behaviour'
13265
          ]
13266
        },
13267
        apis,
13268
        domModification: {
13269
          attributes: {
13270
            'aria-haspopup': 'true',
13271
            ...detail.role.fold(() => ({}), role => ({ role })),
13272
            ...detail.dom.tag === 'button' ? { type: lookupAttr('type').getOr('button') } : {}
13273
          }
13274
        }
13275
      };
13276
    };
13277
    const Dropdown = composite({
13278
      name: 'Dropdown',
13279
      configFields: schema$k(),
13280
      partFields: parts$e(),
13281
      factory: factory$k,
13282
      apis: {
13283
        open: (apis, comp) => apis.open(comp),
13284
        refetch: (apis, comp) => apis.refetch(comp),
13285
        expand: (apis, comp) => apis.expand(comp),
13286
        close: (apis, comp) => apis.close(comp),
13287
        isOpen: (apis, comp) => apis.isOpen(comp),
13288
        repositionMenus: (apis, comp) => apis.repositionMenus(comp)
13289
      }
13290
    });
13291
 
13292
    const identifyMenuLayout = searchMode => {
13293
      switch (searchMode.searchMode) {
13294
      case 'no-search': {
13295
          return { menuType: 'normal' };
13296
        }
13297
      default: {
13298
          return {
13299
            menuType: 'searchable',
13300
            searchMode
13301
          };
13302
        }
13303
      }
13304
    };
13305
    const handleRefetchTrigger = originalSandboxComp => {
13306
      const dropdown = Representing.getValue(originalSandboxComp);
13307
      const optSearcherState = findWithinSandbox(originalSandboxComp).map(saveState);
13308
      Dropdown.refetch(dropdown).get(() => {
13309
        const newSandboxComp = Coupling.getCoupled(dropdown, 'sandbox');
13310
        optSearcherState.each(searcherState => findWithinSandbox(newSandboxComp).each(inputComp => restoreState(inputComp, searcherState)));
13311
      });
13312
    };
13313
    const handleRedirectToMenuItem = (sandboxComp, se) => {
13314
      getActiveMenuItemFrom(sandboxComp).each(activeItem => {
13315
        retargetAndDispatchWith(sandboxComp, activeItem.element, se.event.eventType, se.event.interactionEvent);
13316
      });
13317
    };
13318
    const getActiveMenuItemFrom = sandboxComp => {
13319
      return Sandboxing.getState(sandboxComp).bind(Highlighting.getHighlighted).bind(Highlighting.getHighlighted);
13320
    };
13321
    const getSearchResults = activeMenuComp => {
13322
      return has(activeMenuComp.element, searchResultsClass) ? Optional.some(activeMenuComp.element) : descendant(activeMenuComp.element, '.' + searchResultsClass);
13323
    };
13324
    const updateAriaOnHighlight = (tmenuComp, menuComp, itemComp) => {
13325
      findWithinMenu(tmenuComp).each(inputComp => {
13326
        setActiveDescendant(inputComp, itemComp);
13327
        const optActiveResults = getSearchResults(menuComp);
13328
        optActiveResults.each(resultsElem => {
13329
          getOpt(resultsElem, 'id').each(controlledId => set$9(inputComp.element, 'aria-controls', controlledId));
13330
        });
13331
      });
13332
      set$9(itemComp.element, 'aria-selected', 'true');
13333
    };
13334
    const updateAriaOnDehighlight = (tmenuComp, menuComp, itemComp) => {
13335
      set$9(itemComp.element, 'aria-selected', 'false');
13336
    };
13337
    const focusSearchField = tmenuComp => {
13338
      findWithinMenu(tmenuComp).each(searcherComp => Focusing.focus(searcherComp));
13339
    };
13340
    const getSearchPattern = dropdownComp => {
13341
      const optSandboxComp = Coupling.getExistingCoupled(dropdownComp, 'sandbox');
13342
      return optSandboxComp.bind(findWithinSandbox).map(saveState).map(state => state.fetchPattern).getOr('');
13343
    };
13344
 
13345
    var FocusMode;
13346
    (function (FocusMode) {
13347
      FocusMode[FocusMode['ContentFocus'] = 0] = 'ContentFocus';
13348
      FocusMode[FocusMode['UiFocus'] = 1] = 'UiFocus';
13349
    }(FocusMode || (FocusMode = {})));
13350
    const createMenuItemFromBridge = (item, itemResponse, backstage, menuHasIcons, isHorizontalMenu) => {
13351
      const providersBackstage = backstage.shared.providers;
13352
      const parseForHorizontalMenu = menuitem => !isHorizontalMenu ? menuitem : {
13353
        ...menuitem,
13354
        shortcut: Optional.none(),
13355
        icon: menuitem.text.isSome() ? Optional.none() : menuitem.icon
13356
      };
13357
      switch (item.type) {
13358
      case 'menuitem':
13359
        return createMenuItem(item).fold(handleError, d => Optional.some(normal(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
13360
      case 'nestedmenuitem':
13361
        return createNestedMenuItem(item).fold(handleError, d => Optional.some(nested(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons, isHorizontalMenu)));
13362
      case 'togglemenuitem':
13363
        return createToggleMenuItem(item).fold(handleError, d => Optional.some(toggle$1(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
13364
      case 'separator':
13365
        return createSeparatorMenuItem(item).fold(handleError, d => Optional.some(separator$3(d)));
13366
      case 'fancymenuitem':
13367
        return createFancyMenuItem(item).fold(handleError, d => fancy(d, backstage));
13368
      default: {
13369
          console.error('Unknown item in general menu', item);
13370
          return Optional.none();
13371
        }
13372
      }
13373
    };
13374
    const createAutocompleteItems = (items, matchText, onItemValueHandler, columns, itemResponse, sharedBackstage, highlightOn) => {
13375
      const renderText = columns === 1;
13376
      const renderIcons = !renderText || menuHasIcons(items);
13377
      return cat(map$2(items, item => {
13378
        switch (item.type) {
13379
        case 'separator':
13380
          return createSeparatorItem(item).fold(handleError, d => Optional.some(separator$3(d)));
13381
        case 'cardmenuitem':
13382
          return createCardMenuItem(item).fold(handleError, d => Optional.some(card({
13383
            ...d,
13384
            onAction: api => {
13385
              d.onAction(api);
13386
              onItemValueHandler(d.value, d.meta);
13387
            }
13388
          }, itemResponse, sharedBackstage, {
13389
            itemBehaviours: tooltipBehaviour(d.meta, sharedBackstage),
13390
            cardText: {
13391
              matchText,
13392
              highlightOn
13393
            }
13394
          })));
13395
        case 'autocompleteitem':
13396
        default:
13397
          return createAutocompleterItem(item).fold(handleError, d => Optional.some(autocomplete(d, matchText, renderText, 'normal', onItemValueHandler, itemResponse, sharedBackstage, renderIcons)));
13398
        }
13399
      }));
13400
    };
13401
    const createPartialMenu = (value, items, itemResponse, backstage, isHorizontalMenu, searchMode) => {
13402
      const hasIcons = menuHasIcons(items);
13403
      const alloyItems = cat(map$2(items, item => {
13404
        const itemHasIcon = i => isHorizontalMenu ? !has$2(i, 'text') : hasIcons;
13405
        const createItem = i => createMenuItemFromBridge(i, itemResponse, backstage, itemHasIcon(i), isHorizontalMenu);
13406
        if (item.type === 'nestedmenuitem' && item.getSubmenuItems().length <= 0) {
13407
          return createItem({
13408
            ...item,
13409
            enabled: false
13410
          });
13411
        } else {
13412
          return createItem(item);
13413
        }
13414
      }));
13415
      const menuLayout = identifyMenuLayout(searchMode);
13416
      const createPartial = isHorizontalMenu ? createHorizontalPartialMenuWithAlloyItems : createPartialMenuWithAlloyItems;
13417
      return createPartial(value, hasIcons, alloyItems, 1, menuLayout);
13418
    };
13419
    const createTieredDataFrom = partialMenu => tieredMenu.singleData(partialMenu.value, partialMenu);
13420
    const createInlineMenuFrom = (partialMenu, columns, focusMode, presets) => {
13421
      const movement = deriveMenuMovement(columns, presets);
13422
      const menuMarkers = markers(presets);
13423
      return {
13424
        data: createTieredDataFrom({
13425
          ...partialMenu,
13426
          movement,
13427
          menuBehaviours: SimpleBehaviours.unnamedEvents(columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
13428
              detectSize(comp, 4, menuMarkers.item).each(({numColumns, numRows}) => {
13429
                Keying.setGridSize(comp, numRows, numColumns);
13430
              });
13431
            })])
13432
        }),
13433
        menu: {
13434
          markers: markers(presets),
13435
          fakeFocus: focusMode === FocusMode.ContentFocus
13436
        }
13437
      };
13438
    };
13439
 
13440
    const getAutocompleterRange = (dom, initRange) => {
13441
      return detect$1(SugarElement.fromDom(initRange.startContainer)).map(elm => {
13442
        const range = dom.createRng();
13443
        range.selectNode(elm.dom);
13444
        return range;
13445
      });
13446
    };
13447
    const register$b = (editor, sharedBackstage) => {
13448
      const autocompleterId = generate$6('autocompleter');
13449
      const processingAction = Cell(false);
13450
      const activeState = Cell(false);
13451
      const autocompleter = build$1(InlineView.sketch({
13452
        dom: {
13453
          tag: 'div',
13454
          classes: ['tox-autocompleter'],
13455
          attributes: { id: autocompleterId }
13456
        },
13457
        components: [],
13458
        fireDismissalEventInstead: {},
13459
        inlineBehaviours: derive$1([config('dismissAutocompleter', [
13460
            run$1(dismissRequested(), () => cancelIfNecessary()),
13461
            run$1(highlight$1(), (_, se) => {
13462
              getOpt(se.event.target, 'id').each(id => set$9(SugarElement.fromDom(editor.getBody()), 'aria-activedescendant', id));
13463
            })
13464
          ])]),
13465
        lazySink: sharedBackstage.getSink
13466
      }));
13467
      const isMenuOpen = () => InlineView.isOpen(autocompleter);
13468
      const isActive = activeState.get;
13469
      const hideIfNecessary = () => {
13470
        if (isMenuOpen()) {
13471
          InlineView.hide(autocompleter);
13472
          editor.dom.remove(autocompleterId, false);
13473
          const editorBody = SugarElement.fromDom(editor.getBody());
13474
          getOpt(editorBody, 'aria-owns').filter(ariaOwnsAttr => ariaOwnsAttr === autocompleterId).each(() => {
13475
            remove$7(editorBody, 'aria-owns');
13476
            remove$7(editorBody, 'aria-activedescendant');
13477
          });
13478
        }
13479
      };
13480
      const getMenu = () => InlineView.getContent(autocompleter).bind(tmenu => {
13481
        return get$h(tmenu.components(), 0);
13482
      });
13483
      const cancelIfNecessary = () => editor.execCommand('mceAutocompleterClose');
13484
      const getCombinedItems = matches => {
13485
        const columns = findMap(matches, m => Optional.from(m.columns)).getOr(1);
13486
        return bind$3(matches, match => {
13487
          const choices = match.items;
13488
          return createAutocompleteItems(choices, match.matchText, (itemValue, itemMeta) => {
13489
            const nr = editor.selection.getRng();
13490
            getAutocompleterRange(editor.dom, nr).each(range => {
13491
              const autocompleterApi = {
13492
                hide: () => cancelIfNecessary(),
13493
                reload: fetchOptions => {
13494
                  hideIfNecessary();
13495
                  editor.execCommand('mceAutocompleterReload', false, { fetchOptions });
13496
                }
13497
              };
13498
              processingAction.set(true);
13499
              match.onAction(autocompleterApi, range, itemValue, itemMeta);
13500
              processingAction.set(false);
13501
            });
13502
          }, columns, ItemResponse$1.BUBBLE_TO_SANDBOX, sharedBackstage, match.highlightOn);
13503
        });
13504
      };
13505
      const display = (lookupData, items) => {
13506
        findIn(SugarElement.fromDom(editor.getBody())).each(element => {
13507
          const columns = findMap(lookupData, ld => Optional.from(ld.columns)).getOr(1);
13508
          InlineView.showMenuAt(autocompleter, {
13509
            anchor: {
13510
              type: 'node',
13511
              root: SugarElement.fromDom(editor.getBody()),
13512
              node: Optional.from(element)
13513
            }
13514
          }, createInlineMenuFrom(createPartialMenuWithAlloyItems('autocompleter-value', true, items, columns, { menuType: 'normal' }), columns, FocusMode.ContentFocus, 'normal'));
13515
        });
13516
        getMenu().each(Highlighting.highlightFirst);
13517
      };
13518
      const updateDisplay = lookupData => {
13519
        const combinedItems = getCombinedItems(lookupData);
13520
        if (combinedItems.length > 0) {
13521
          display(lookupData, combinedItems);
13522
          set$9(SugarElement.fromDom(editor.getBody()), 'aria-owns', autocompleterId);
13523
          if (!editor.inline) {
13524
            cloneAutocompleterToEditorDoc();
13525
          }
13526
        } else {
13527
          hideIfNecessary();
13528
        }
13529
      };
13530
      const cloneAutocompleterToEditorDoc = () => {
13531
        if (editor.dom.get(autocompleterId)) {
13532
          editor.dom.remove(autocompleterId, false);
13533
        }
13534
        const docElm = editor.getDoc().documentElement;
13535
        const selection = editor.selection.getNode();
13536
        const newElm = deep(autocompleter.element);
13537
        setAll(newElm, {
13538
          border: '0',
13539
          clip: 'rect(0 0 0 0)',
13540
          height: '1px',
13541
          margin: '-1px',
13542
          overflow: 'hidden',
13543
          padding: '0',
13544
          position: 'absolute',
13545
          width: '1px',
13546
          top: `${ selection.offsetTop }px`,
13547
          left: `${ selection.offsetLeft }px`
13548
        });
13549
        editor.dom.add(docElm, newElm.dom);
13550
        descendant(newElm, '[role="menu"]').each(child => {
13551
          remove$6(child, 'position');
13552
          remove$6(child, 'max-height');
13553
        });
13554
      };
13555
      editor.on('AutocompleterStart', ({lookupData}) => {
13556
        activeState.set(true);
13557
        processingAction.set(false);
13558
        updateDisplay(lookupData);
13559
      });
13560
      editor.on('AutocompleterUpdate', ({lookupData}) => updateDisplay(lookupData));
13561
      editor.on('AutocompleterEnd', () => {
13562
        hideIfNecessary();
13563
        activeState.set(false);
13564
        processingAction.set(false);
13565
      });
13566
      const autocompleterUiApi = {
13567
        cancelIfNecessary,
13568
        isMenuOpen,
13569
        isActive,
13570
        isProcessingAction: processingAction.get,
13571
        getMenu
13572
      };
13573
      AutocompleterEditorEvents.setup(autocompleterUiApi, editor);
13574
    };
13575
    const Autocompleter = { register: register$b };
13576
 
13577
    const nonScrollingOverflows = [
13578
      'visible',
13579
      'hidden',
13580
      'clip'
13581
    ];
13582
    const isScrollingOverflowValue = value => trim$1(value).length > 0 && !contains$2(nonScrollingOverflows, value);
13583
    const isScroller = elem => {
13584
      if (isHTMLElement(elem)) {
13585
        const overflowX = get$e(elem, 'overflow-x');
13586
        const overflowY = get$e(elem, 'overflow-y');
13587
        return isScrollingOverflowValue(overflowX) || isScrollingOverflowValue(overflowY);
13588
      } else {
13589
        return false;
13590
      }
13591
    };
13592
    const detect = popupSinkElem => {
13593
      const ancestorsScrollers = ancestors(popupSinkElem, isScroller);
13594
      const scrollers = ancestorsScrollers.length === 0 ? getShadowRoot(popupSinkElem).map(getShadowHost).map(x => ancestors(x, isScroller)).getOr([]) : ancestorsScrollers;
13595
      return head(scrollers).map(element => ({
13596
        element,
13597
        others: scrollers.slice(1)
13598
      }));
13599
    };
13600
    const detectWhenSplitUiMode = (editor, popupSinkElem) => isSplitUiMode(editor) ? detect(popupSinkElem) : Optional.none();
13601
    const getBoundsFrom = sc => {
13602
      const scrollableBoxes = [
13603
        ...map$2(sc.others, box$1),
13604
        win()
13605
      ];
13606
      return constrainByMany(box$1(sc.element), scrollableBoxes);
13607
    };
13608
 
13609
    const closest = (scope, selector, isRoot) => closest$1(scope, selector, isRoot).isSome();
13610
 
13611
    const DelayedFunction = (fun, delay) => {
13612
      let ref = null;
13613
      const schedule = (...args) => {
13614
        ref = setTimeout(() => {
13615
          fun.apply(null, args);
13616
          ref = null;
13617
        }, delay);
13618
      };
13619
      const cancel = () => {
13620
        if (ref !== null) {
13621
          clearTimeout(ref);
13622
          ref = null;
13623
        }
13624
      };
13625
      return {
13626
        cancel,
13627
        schedule
13628
      };
13629
    };
13630
 
13631
    const SIGNIFICANT_MOVE = 5;
13632
    const LONGPRESS_DELAY = 400;
13633
    const getTouch = event => {
13634
      const raw = event.raw;
13635
      if (raw.touches === undefined || raw.touches.length !== 1) {
13636
        return Optional.none();
13637
      }
13638
      return Optional.some(raw.touches[0]);
13639
    };
13640
    const isFarEnough = (touch, data) => {
13641
      const distX = Math.abs(touch.clientX - data.x);
13642
      const distY = Math.abs(touch.clientY - data.y);
13643
      return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
13644
    };
13645
    const monitor = settings => {
13646
      const startData = value$2();
13647
      const longpressFired = Cell(false);
13648
      const longpress$1 = DelayedFunction(event => {
13649
        settings.triggerEvent(longpress(), event);
13650
        longpressFired.set(true);
13651
      }, LONGPRESS_DELAY);
13652
      const handleTouchstart = event => {
13653
        getTouch(event).each(touch => {
13654
          longpress$1.cancel();
13655
          const data = {
13656
            x: touch.clientX,
13657
            y: touch.clientY,
13658
            target: event.target
13659
          };
13660
          longpress$1.schedule(event);
13661
          longpressFired.set(false);
13662
          startData.set(data);
13663
        });
13664
        return Optional.none();
13665
      };
13666
      const handleTouchmove = event => {
13667
        longpress$1.cancel();
13668
        getTouch(event).each(touch => {
13669
          startData.on(data => {
13670
            if (isFarEnough(touch, data)) {
13671
              startData.clear();
13672
            }
13673
          });
13674
        });
13675
        return Optional.none();
13676
      };
13677
      const handleTouchend = event => {
13678
        longpress$1.cancel();
13679
        const isSame = data => eq(data.target, event.target);
13680
        return startData.get().filter(isSame).map(_data => {
13681
          if (longpressFired.get()) {
13682
            event.prevent();
13683
            return false;
13684
          } else {
13685
            return settings.triggerEvent(tap(), event);
13686
          }
13687
        });
13688
      };
13689
      const handlers = wrapAll([
13690
        {
13691
          key: touchstart(),
13692
          value: handleTouchstart
13693
        },
13694
        {
13695
          key: touchmove(),
13696
          value: handleTouchmove
13697
        },
13698
        {
13699
          key: touchend(),
13700
          value: handleTouchend
13701
        }
13702
      ]);
13703
      const fireIfReady = (event, type) => get$g(handlers, type).bind(handler => handler(event));
13704
      return { fireIfReady };
13705
    };
13706
 
13707
    const isDangerous = event => {
13708
      const keyEv = event.raw;
13709
      return keyEv.which === BACKSPACE[0] && !contains$2([
13710
        'input',
13711
        'textarea'
13712
      ], name$3(event.target)) && !closest(event.target, '[contenteditable="true"]');
13713
    };
13714
    const setup$d = (container, rawSettings) => {
13715
      const settings = {
13716
        stopBackspace: true,
13717
        ...rawSettings
13718
      };
13719
      const pointerEvents = [
13720
        'touchstart',
13721
        'touchmove',
13722
        'touchend',
13723
        'touchcancel',
13724
        'gesturestart',
13725
        'mousedown',
13726
        'mouseup',
13727
        'mouseover',
13728
        'mousemove',
13729
        'mouseout',
13730
        'click'
13731
      ];
13732
      const tapEvent = monitor(settings);
13733
      const simpleEvents = map$2(pointerEvents.concat([
13734
        'selectstart',
13735
        'input',
13736
        'contextmenu',
13737
        'change',
13738
        'transitionend',
13739
        'transitioncancel',
13740
        'drag',
13741
        'dragstart',
13742
        'dragend',
13743
        'dragenter',
13744
        'dragleave',
13745
        'dragover',
13746
        'drop',
13747
        'keyup'
13748
      ]), type => bind(container, type, event => {
13749
        tapEvent.fireIfReady(event, type).each(tapStopped => {
13750
          if (tapStopped) {
13751
            event.kill();
13752
          }
13753
        });
13754
        const stopped = settings.triggerEvent(type, event);
13755
        if (stopped) {
13756
          event.kill();
13757
        }
13758
      }));
13759
      const pasteTimeout = value$2();
13760
      const onPaste = bind(container, 'paste', event => {
13761
        tapEvent.fireIfReady(event, 'paste').each(tapStopped => {
13762
          if (tapStopped) {
13763
            event.kill();
13764
          }
13765
        });
13766
        const stopped = settings.triggerEvent('paste', event);
13767
        if (stopped) {
13768
          event.kill();
13769
        }
13770
        pasteTimeout.set(setTimeout(() => {
13771
          settings.triggerEvent(postPaste(), event);
13772
        }, 0));
13773
      });
13774
      const onKeydown = bind(container, 'keydown', event => {
13775
        const stopped = settings.triggerEvent('keydown', event);
13776
        if (stopped) {
13777
          event.kill();
13778
        } else if (settings.stopBackspace && isDangerous(event)) {
13779
          event.prevent();
13780
        }
13781
      });
13782
      const onFocusIn = bind(container, 'focusin', event => {
13783
        const stopped = settings.triggerEvent('focusin', event);
13784
        if (stopped) {
13785
          event.kill();
13786
        }
13787
      });
13788
      const focusoutTimeout = value$2();
13789
      const onFocusOut = bind(container, 'focusout', event => {
13790
        const stopped = settings.triggerEvent('focusout', event);
13791
        if (stopped) {
13792
          event.kill();
13793
        }
13794
        focusoutTimeout.set(setTimeout(() => {
13795
          settings.triggerEvent(postBlur(), event);
13796
        }, 0));
13797
      });
13798
      const unbind = () => {
13799
        each$1(simpleEvents, e => {
13800
          e.unbind();
13801
        });
13802
        onKeydown.unbind();
13803
        onFocusIn.unbind();
13804
        onFocusOut.unbind();
13805
        onPaste.unbind();
13806
        pasteTimeout.on(clearTimeout);
13807
        focusoutTimeout.on(clearTimeout);
13808
      };
13809
      return { unbind };
13810
    };
13811
 
13812
    const derive = (rawEvent, rawTarget) => {
13813
      const source = get$g(rawEvent, 'target').getOr(rawTarget);
13814
      return Cell(source);
13815
    };
13816
 
13817
    const fromSource = (event, source) => {
13818
      const stopper = Cell(false);
13819
      const cutter = Cell(false);
13820
      const stop = () => {
13821
        stopper.set(true);
13822
      };
13823
      const cut = () => {
13824
        cutter.set(true);
13825
      };
13826
      return {
13827
        stop,
13828
        cut,
13829
        isStopped: stopper.get,
13830
        isCut: cutter.get,
13831
        event,
13832
        setSource: source.set,
13833
        getSource: source.get
13834
      };
13835
    };
13836
    const fromExternal = event => {
13837
      const stopper = Cell(false);
13838
      const stop = () => {
13839
        stopper.set(true);
13840
      };
13841
      return {
13842
        stop,
13843
        cut: noop,
13844
        isStopped: stopper.get,
13845
        isCut: never,
13846
        event,
13847
        setSource: die('Cannot set source of a broadcasted event'),
13848
        getSource: die('Cannot get source of a broadcasted event')
13849
      };
13850
    };
13851
 
13852
    const adt$1 = Adt.generate([
13853
      { stopped: [] },
13854
      { resume: ['element'] },
13855
      { complete: [] }
13856
    ]);
13857
    const doTriggerHandler = (lookup, eventType, rawEvent, target, source, logger) => {
13858
      const handler = lookup(eventType, target);
13859
      const simulatedEvent = fromSource(rawEvent, source);
13860
      return handler.fold(() => {
13861
        logger.logEventNoHandlers(eventType, target);
13862
        return adt$1.complete();
13863
      }, handlerInfo => {
13864
        const descHandler = handlerInfo.descHandler;
13865
        const eventHandler = getCurried(descHandler);
13866
        eventHandler(simulatedEvent);
13867
        if (simulatedEvent.isStopped()) {
13868
          logger.logEventStopped(eventType, handlerInfo.element, descHandler.purpose);
13869
          return adt$1.stopped();
13870
        } else if (simulatedEvent.isCut()) {
13871
          logger.logEventCut(eventType, handlerInfo.element, descHandler.purpose);
13872
          return adt$1.complete();
13873
        } else {
13874
          return parent(handlerInfo.element).fold(() => {
13875
            logger.logNoParent(eventType, handlerInfo.element, descHandler.purpose);
13876
            return adt$1.complete();
13877
          }, parent => {
13878
            logger.logEventResponse(eventType, handlerInfo.element, descHandler.purpose);
13879
            return adt$1.resume(parent);
13880
          });
13881
        }
13882
      });
13883
    };
13884
    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);
13885
    const triggerHandler = (lookup, eventType, rawEvent, target, logger) => {
13886
      const source = derive(rawEvent, target);
13887
      return doTriggerHandler(lookup, eventType, rawEvent, target, source, logger);
13888
    };
13889
    const broadcast = (listeners, rawEvent, _logger) => {
13890
      const simulatedEvent = fromExternal(rawEvent);
13891
      each$1(listeners, listener => {
13892
        const descHandler = listener.descHandler;
13893
        const handler = getCurried(descHandler);
13894
        handler(simulatedEvent);
13895
      });
13896
      return simulatedEvent.isStopped();
13897
    };
13898
    const triggerUntilStopped = (lookup, eventType, rawEvent, logger) => triggerOnUntilStopped(lookup, eventType, rawEvent, rawEvent.target, logger);
13899
    const triggerOnUntilStopped = (lookup, eventType, rawEvent, rawTarget, logger) => {
13900
      const source = derive(rawEvent, rawTarget);
13901
      return doTriggerOnUntilStopped(lookup, eventType, rawEvent, rawTarget, source, logger);
13902
    };
13903
 
13904
    const eventHandler = (element, descHandler) => ({
13905
      element,
13906
      descHandler
13907
    });
13908
    const broadcastHandler = (id, handler) => ({
13909
      id,
13910
      descHandler: handler
13911
    });
13912
    const EventRegistry = () => {
13913
      const registry = {};
13914
      const registerId = (extraArgs, id, events) => {
13915
        each(events, (v, k) => {
13916
          const handlers = registry[k] !== undefined ? registry[k] : {};
13917
          handlers[id] = curryArgs(v, extraArgs);
13918
          registry[k] = handlers;
13919
        });
13920
      };
13921
      const findHandler = (handlers, elem) => read$1(elem).bind(id => get$g(handlers, id)).map(descHandler => eventHandler(elem, descHandler));
13922
      const filterByType = type => get$g(registry, type).map(handlers => mapToArray(handlers, (f, id) => broadcastHandler(id, f))).getOr([]);
13923
      const find = (isAboveRoot, type, target) => get$g(registry, type).bind(handlers => closest$4(target, elem => findHandler(handlers, elem), isAboveRoot));
13924
      const unregisterId = id => {
13925
        each(registry, (handlersById, _eventName) => {
13926
          if (has$2(handlersById, id)) {
13927
            delete handlersById[id];
13928
          }
13929
        });
13930
      };
13931
      return {
13932
        registerId,
13933
        unregisterId,
13934
        filterByType,
13935
        find
13936
      };
13937
    };
13938
 
13939
    const Registry = () => {
13940
      const events = EventRegistry();
13941
      const components = {};
13942
      const readOrTag = component => {
13943
        const elem = component.element;
13944
        return read$1(elem).getOrThunk(() => write('uid-', component.element));
13945
      };
13946
      const failOnDuplicate = (component, tagId) => {
13947
        const conflict = components[tagId];
13948
        if (conflict === component) {
13949
          unregister(component);
13950
        } else {
13951
          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');
13952
        }
13953
      };
13954
      const register = component => {
13955
        const tagId = readOrTag(component);
13956
        if (hasNonNullableKey(components, tagId)) {
13957
          failOnDuplicate(component, tagId);
13958
        }
13959
        const extraArgs = [component];
13960
        events.registerId(extraArgs, tagId, component.events);
13961
        components[tagId] = component;
13962
      };
13963
      const unregister = component => {
13964
        read$1(component.element).each(tagId => {
13965
          delete components[tagId];
13966
          events.unregisterId(tagId);
13967
        });
13968
      };
13969
      const filter = type => events.filterByType(type);
13970
      const find = (isAboveRoot, type, target) => events.find(isAboveRoot, type, target);
13971
      const getById = id => get$g(components, id);
13972
      return {
13973
        find,
13974
        filter,
13975
        register,
13976
        unregister,
13977
        getById
13978
      };
13979
    };
13980
 
13981
    const factory$j = detail => {
13982
      const {attributes, ...domWithoutAttributes} = detail.dom;
13983
      return {
13984
        uid: detail.uid,
13985
        dom: {
13986
          tag: 'div',
13987
          attributes: {
13988
            role: 'presentation',
13989
            ...attributes
13990
          },
13991
          ...domWithoutAttributes
13992
        },
13993
        components: detail.components,
13994
        behaviours: get$3(detail.containerBehaviours),
13995
        events: detail.events,
13996
        domModification: detail.domModification,
13997
        eventOrder: detail.eventOrder
13998
      };
13999
    };
14000
    const Container = single({
14001
      name: 'Container',
14002
      factory: factory$j,
14003
      configFields: [
14004
        defaulted('components', []),
14005
        field('containerBehaviours', []),
14006
        defaulted('events', {}),
14007
        defaulted('domModification', {}),
14008
        defaulted('eventOrder', {})
14009
      ]
14010
    });
14011
 
14012
    const takeover = root => {
14013
      const isAboveRoot = el => parent(root.element).fold(always, parent => eq(el, parent));
14014
      const registry = Registry();
14015
      const lookup = (eventName, target) => registry.find(isAboveRoot, eventName, target);
14016
      const domEvents = setup$d(root.element, {
14017
        triggerEvent: (eventName, event) => {
14018
          return monitorEvent(eventName, event.target, logger => triggerUntilStopped(lookup, eventName, event, logger));
14019
        }
14020
      });
14021
      const systemApi = {
14022
        debugInfo: constant$1('real'),
14023
        triggerEvent: (eventName, target, data) => {
14024
          monitorEvent(eventName, target, logger => triggerOnUntilStopped(lookup, eventName, data, target, logger));
14025
        },
14026
        triggerFocus: (target, originator) => {
14027
          read$1(target).fold(() => {
14028
            focus$3(target);
14029
          }, _alloyId => {
14030
            monitorEvent(focus$4(), target, logger => {
14031
              triggerHandler(lookup, focus$4(), {
14032
                originator,
14033
                kill: noop,
14034
                prevent: noop,
14035
                target
14036
              }, target, logger);
14037
              return false;
14038
            });
14039
          });
14040
        },
14041
        triggerEscape: (comp, simulatedEvent) => {
14042
          systemApi.triggerEvent('keydown', comp.element, simulatedEvent.event);
14043
        },
14044
        getByUid: uid => {
14045
          return getByUid(uid);
14046
        },
14047
        getByDom: elem => {
14048
          return getByDom(elem);
14049
        },
14050
        build: build$1,
14051
        buildOrPatch: buildOrPatch,
14052
        addToGui: c => {
14053
          add(c);
14054
        },
14055
        removeFromGui: c => {
14056
          remove(c);
14057
        },
14058
        addToWorld: c => {
14059
          addToWorld(c);
14060
        },
14061
        removeFromWorld: c => {
14062
          removeFromWorld(c);
14063
        },
14064
        broadcast: message => {
14065
          broadcast$1(message);
14066
        },
14067
        broadcastOn: (channels, message) => {
14068
          broadcastOn(channels, message);
14069
        },
14070
        broadcastEvent: (eventName, event) => {
14071
          broadcastEvent(eventName, event);
14072
        },
14073
        isConnected: always
14074
      };
14075
      const addToWorld = component => {
14076
        component.connect(systemApi);
14077
        if (!isText(component.element)) {
14078
          registry.register(component);
14079
          each$1(component.components(), addToWorld);
14080
          systemApi.triggerEvent(systemInit(), component.element, { target: component.element });
14081
        }
14082
      };
14083
      const removeFromWorld = component => {
14084
        if (!isText(component.element)) {
14085
          each$1(component.components(), removeFromWorld);
14086
          registry.unregister(component);
14087
        }
14088
        component.disconnect();
14089
      };
14090
      const add = component => {
14091
        attach(root, component);
14092
      };
14093
      const remove = component => {
14094
        detach(component);
14095
      };
14096
      const destroy = () => {
14097
        domEvents.unbind();
14098
        remove$5(root.element);
14099
      };
14100
      const broadcastData = data => {
14101
        const receivers = registry.filter(receive());
14102
        each$1(receivers, receiver => {
14103
          const descHandler = receiver.descHandler;
14104
          const handler = getCurried(descHandler);
14105
          handler(data);
14106
        });
14107
      };
14108
      const broadcast$1 = message => {
14109
        broadcastData({
14110
          universal: true,
14111
          data: message
14112
        });
14113
      };
14114
      const broadcastOn = (channels, message) => {
14115
        broadcastData({
14116
          universal: false,
14117
          channels,
14118
          data: message
14119
        });
14120
      };
14121
      const broadcastEvent = (eventName, event) => {
14122
        const listeners = registry.filter(eventName);
14123
        return broadcast(listeners, event);
14124
      };
14125
      const getByUid = uid => registry.getById(uid).fold(() => Result.error(new Error('Could not find component with uid: "' + uid + '" in system.')), Result.value);
14126
      const getByDom = elem => {
14127
        const uid = read$1(elem).getOr('not found');
14128
        return getByUid(uid);
14129
      };
14130
      addToWorld(root);
14131
      return {
14132
        root,
14133
        element: root.element,
14134
        destroy,
14135
        add,
14136
        remove,
14137
        getByUid,
14138
        getByDom,
14139
        addToWorld,
14140
        removeFromWorld,
14141
        broadcast: broadcast$1,
14142
        broadcastOn,
14143
        broadcastEvent
14144
      };
14145
    };
14146
 
14147
    const renderBar = (spec, backstage) => ({
14148
      dom: {
14149
        tag: 'div',
14150
        classes: [
14151
          'tox-bar',
14152
          'tox-form__controls-h-stack'
14153
        ]
14154
      },
14155
      components: map$2(spec.items, backstage.interpreter)
14156
    });
14157
 
14158
    const schema$j = constant$1([
14159
      defaulted('prefix', 'form-field'),
14160
      field('fieldBehaviours', [
14161
        Composing,
14162
        Representing
14163
      ])
14164
    ]);
14165
    const parts$d = constant$1([
14166
      optional({
14167
        schema: [required$1('dom')],
14168
        name: 'label'
14169
      }),
14170
      optional({
14171
        factory: {
14172
          sketch: spec => {
14173
            return {
14174
              uid: spec.uid,
14175
              dom: {
14176
                tag: 'span',
14177
                styles: { display: 'none' },
14178
                attributes: { 'aria-hidden': 'true' },
14179
                innerHtml: spec.text
14180
              }
14181
            };
14182
          }
14183
        },
14184
        schema: [required$1('text')],
14185
        name: 'aria-descriptor'
14186
      }),
14187
      required({
14188
        factory: {
14189
          sketch: spec => {
14190
            const excludeFactory = exclude(spec, ['factory']);
14191
            return spec.factory.sketch(excludeFactory);
14192
          }
14193
        },
14194
        schema: [required$1('factory')],
14195
        name: 'field'
14196
      })
14197
    ]);
14198
 
14199
    const factory$i = (detail, components, _spec, _externals) => {
14200
      const behaviours = augment(detail.fieldBehaviours, [
14201
        Composing.config({
14202
          find: container => {
14203
            return getPart(container, detail, 'field');
14204
          }
14205
        }),
14206
        Representing.config({
14207
          store: {
14208
            mode: 'manual',
14209
            getValue: field => {
14210
              return Composing.getCurrent(field).bind(Representing.getValue);
14211
            },
14212
            setValue: (field, value) => {
14213
              Composing.getCurrent(field).each(current => {
14214
                Representing.setValue(current, value);
14215
              });
14216
            }
14217
          }
14218
        })
14219
      ]);
14220
      const events = derive$2([runOnAttached((component, _simulatedEvent) => {
14221
          const ps = getParts(component, detail, [
14222
            'label',
14223
            'field',
14224
            'aria-descriptor'
14225
          ]);
14226
          ps.field().each(field => {
14227
            const id = generate$6(detail.prefix);
14228
            ps.label().each(label => {
14229
              set$9(label.element, 'for', id);
14230
              set$9(field.element, 'id', id);
14231
            });
14232
            ps['aria-descriptor']().each(descriptor => {
14233
              const descriptorId = generate$6(detail.prefix);
14234
              set$9(descriptor.element, 'id', descriptorId);
14235
              set$9(field.element, 'aria-describedby', descriptorId);
14236
            });
14237
          });
14238
        })]);
14239
      const apis = {
14240
        getField: container => getPart(container, detail, 'field'),
14241
        getLabel: container => getPart(container, detail, 'label')
14242
      };
14243
      return {
14244
        uid: detail.uid,
14245
        dom: detail.dom,
14246
        components,
14247
        behaviours,
14248
        events,
14249
        apis
14250
      };
14251
    };
14252
    const FormField = composite({
14253
      name: 'FormField',
14254
      configFields: schema$j(),
14255
      partFields: parts$d(),
14256
      factory: factory$i,
14257
      apis: {
14258
        getField: (apis, comp) => apis.getField(comp),
14259
        getLabel: (apis, comp) => apis.getLabel(comp)
14260
      }
14261
    });
14262
 
14263
    const exhibit$2 = (base, tabConfig) => nu$7({
14264
      attributes: wrapAll([{
14265
          key: tabConfig.tabAttr,
14266
          value: 'true'
14267
        }])
14268
    });
14269
 
14270
    var ActiveTabstopping = /*#__PURE__*/Object.freeze({
14271
        __proto__: null,
14272
        exhibit: exhibit$2
14273
    });
14274
 
14275
    var TabstopSchema = [defaulted('tabAttr', 'data-alloy-tabstop')];
14276
 
14277
    const Tabstopping = create$4({
14278
      fields: TabstopSchema,
14279
      name: 'tabstopping',
14280
      active: ActiveTabstopping
14281
    });
14282
 
14283
    var global$3 = tinymce.util.Tools.resolve('tinymce.html.Entities');
14284
 
14285
    const renderFormFieldWith = (pLabel, pField, extraClasses, extraBehaviours) => {
14286
      const spec = renderFormFieldSpecWith(pLabel, pField, extraClasses, extraBehaviours);
14287
      return FormField.sketch(spec);
14288
    };
14289
    const renderFormField = (pLabel, pField) => renderFormFieldWith(pLabel, pField, [], []);
14290
    const renderFormFieldSpecWith = (pLabel, pField, extraClasses, extraBehaviours) => ({
14291
      dom: renderFormFieldDomWith(extraClasses),
14292
      components: pLabel.toArray().concat([pField]),
14293
      fieldBehaviours: derive$1(extraBehaviours)
14294
    });
14295
    const renderFormFieldDom = () => renderFormFieldDomWith([]);
14296
    const renderFormFieldDomWith = extraClasses => ({
14297
      tag: 'div',
14298
      classes: ['tox-form__group'].concat(extraClasses)
14299
    });
14300
    const renderLabel$3 = (label, providersBackstage) => FormField.parts.label({
14301
      dom: {
14302
        tag: 'label',
14303
        classes: ['tox-label']
14304
      },
14305
      components: [text$2(providersBackstage.translate(label))]
14306
    });
14307
 
14308
    const formChangeEvent = generate$6('form-component-change');
14309
    const formCloseEvent = generate$6('form-close');
14310
    const formCancelEvent = generate$6('form-cancel');
14311
    const formActionEvent = generate$6('form-action');
14312
    const formSubmitEvent = generate$6('form-submit');
14313
    const formBlockEvent = generate$6('form-block');
14314
    const formUnblockEvent = generate$6('form-unblock');
14315
    const formTabChangeEvent = generate$6('form-tabchange');
14316
    const formResizeEvent = generate$6('form-resize');
14317
 
14318
    const renderCollection = (spec, providersBackstage, initialData) => {
14319
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
14320
      const icons = providersBackstage.icons();
14321
      const getIcon = icon => {
14322
        var _a;
14323
        return (_a = icons[icon]) !== null && _a !== void 0 ? _a : icon;
14324
      };
14325
      const runOnItem = f => (comp, se) => {
14326
        closest$1(se.event.target, '[data-collection-item-value]').each(target => {
14327
          f(comp, se, target, get$f(target, 'data-collection-item-value'));
14328
        });
14329
      };
14330
      const setContents = (comp, items) => {
14331
        const htmlLines = map$2(items, item => {
14332
          const itemText = global$8.translate(item.text);
14333
          const textContent = spec.columns === 1 ? `<div class="tox-collection__item-label">${ itemText }</div>` : '';
14334
          const iconContent = `<div class="tox-collection__item-icon">${ getIcon(item.icon) }</div>`;
14335
          const mapItemName = {
14336
            '_': ' ',
14337
            ' - ': ' ',
14338
            '-': ' '
14339
          };
14340
          const ariaLabel = itemText.replace(/\_| \- |\-/g, match => mapItemName[match]);
14341
          const disabledClass = providersBackstage.isDisabled() ? ' tox-collection__item--state-disabled' : '';
14342
          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>`;
14343
        });
14344
        const chunks = spec.columns !== 'auto' && spec.columns > 1 ? chunk$1(htmlLines, spec.columns) : [htmlLines];
14345
        const html = map$2(chunks, ch => `<div class="tox-collection__group">${ ch.join('') }</div>`);
14346
        set$6(comp.element, html.join(''));
14347
      };
14348
      const onClick = runOnItem((comp, se, tgt, itemValue) => {
14349
        se.stop();
14350
        if (!providersBackstage.isDisabled()) {
14351
          emitWith(comp, formActionEvent, {
14352
            name: spec.name,
14353
            value: itemValue
14354
          });
14355
        }
14356
      });
14357
      const collectionEvents = [
14358
        run$1(mouseover(), runOnItem((comp, se, tgt) => {
14359
          focus$3(tgt);
14360
        })),
14361
        run$1(click(), onClick),
14362
        run$1(tap(), onClick),
14363
        run$1(focusin(), runOnItem((comp, se, tgt) => {
14364
          descendant(comp.element, '.' + activeClass).each(currentActive => {
14365
            remove$2(currentActive, activeClass);
14366
          });
14367
          add$2(tgt, activeClass);
14368
        })),
14369
        run$1(focusout(), runOnItem(comp => {
14370
          descendant(comp.element, '.' + activeClass).each(currentActive => {
14371
            remove$2(currentActive, activeClass);
14372
          });
14373
        })),
14374
        runOnExecute$1(runOnItem((comp, se, tgt, itemValue) => {
14375
          emitWith(comp, formActionEvent, {
14376
            name: spec.name,
14377
            value: itemValue
14378
          });
14379
        }))
14380
      ];
14381
      const iterCollectionItems = (comp, applyAttributes) => map$2(descendants(comp.element, '.tox-collection__item'), applyAttributes);
14382
      const pField = FormField.parts.field({
14383
        dom: {
14384
          tag: 'div',
14385
          classes: ['tox-collection'].concat(spec.columns !== 1 ? ['tox-collection--grid'] : ['tox-collection--list'])
14386
        },
14387
        components: [],
14388
        factory: { sketch: identity },
14389
        behaviours: derive$1([
14390
          Disabling.config({
14391
            disabled: providersBackstage.isDisabled,
14392
            onDisabled: comp => {
14393
              iterCollectionItems(comp, childElm => {
14394
                add$2(childElm, 'tox-collection__item--state-disabled');
14395
                set$9(childElm, 'aria-disabled', true);
14396
              });
14397
            },
14398
            onEnabled: comp => {
14399
              iterCollectionItems(comp, childElm => {
14400
                remove$2(childElm, 'tox-collection__item--state-disabled');
14401
                remove$7(childElm, 'aria-disabled');
14402
              });
14403
            }
14404
          }),
14405
          receivingConfig(),
14406
          Replacing.config({}),
14407
          Representing.config({
14408
            store: {
14409
              mode: 'memory',
14410
              initialValue: initialData.getOr([])
14411
            },
14412
            onSetValue: (comp, items) => {
14413
              setContents(comp, items);
14414
              if (spec.columns === 'auto') {
14415
                detectSize(comp, 5, 'tox-collection__item').each(({numRows, numColumns}) => {
14416
                  Keying.setGridSize(comp, numRows, numColumns);
14417
                });
14418
              }
14419
              emit(comp, formResizeEvent);
14420
            }
14421
          }),
14422
          Tabstopping.config({}),
14423
          Keying.config(deriveCollectionMovement(spec.columns, 'normal')),
14424
          config('collection-events', collectionEvents)
14425
        ]),
14426
        eventOrder: {
14427
          [execute$5()]: [
14428
            'disabling',
14429
            'alloy.base.behaviour',
14430
            'collection-events'
14431
          ]
14432
        }
14433
      });
14434
      const extraClasses = ['tox-form__group--collection'];
14435
      return renderFormFieldWith(pLabel, pField, extraClasses, []);
14436
    };
14437
 
14438
    const ariaElements = [
14439
      'input',
14440
      'textarea'
14441
    ];
14442
    const isAriaElement = elem => {
14443
      const name = name$3(elem);
14444
      return contains$2(ariaElements, name);
14445
    };
14446
    const markValid = (component, invalidConfig) => {
14447
      const elem = invalidConfig.getRoot(component).getOr(component.element);
14448
      remove$2(elem, invalidConfig.invalidClass);
14449
      invalidConfig.notify.each(notifyInfo => {
14450
        if (isAriaElement(component.element)) {
14451
          set$9(component.element, 'aria-invalid', false);
14452
        }
14453
        notifyInfo.getContainer(component).each(container => {
14454
          set$6(container, notifyInfo.validHtml);
14455
        });
14456
        notifyInfo.onValid(component);
14457
      });
14458
    };
14459
    const markInvalid = (component, invalidConfig, invalidState, text) => {
14460
      const elem = invalidConfig.getRoot(component).getOr(component.element);
14461
      add$2(elem, invalidConfig.invalidClass);
14462
      invalidConfig.notify.each(notifyInfo => {
14463
        if (isAriaElement(component.element)) {
14464
          set$9(component.element, 'aria-invalid', true);
14465
        }
14466
        notifyInfo.getContainer(component).each(container => {
14467
          set$6(container, text);
14468
        });
14469
        notifyInfo.onInvalid(component, text);
14470
      });
14471
    };
14472
    const query = (component, invalidConfig, _invalidState) => invalidConfig.validator.fold(() => Future.pure(Result.value(true)), validatorInfo => validatorInfo.validate(component));
14473
    const run = (component, invalidConfig, invalidState) => {
14474
      invalidConfig.notify.each(notifyInfo => {
14475
        notifyInfo.onValidate(component);
14476
      });
14477
      return query(component, invalidConfig).map(valid => {
14478
        if (component.getSystem().isConnected()) {
14479
          return valid.fold(err => {
14480
            markInvalid(component, invalidConfig, invalidState, err);
14481
            return Result.error(err);
14482
          }, v => {
14483
            markValid(component, invalidConfig);
14484
            return Result.value(v);
14485
          });
14486
        } else {
14487
          return Result.error('No longer in system');
14488
        }
14489
      });
14490
    };
14491
    const isInvalid = (component, invalidConfig) => {
14492
      const elem = invalidConfig.getRoot(component).getOr(component.element);
14493
      return has(elem, invalidConfig.invalidClass);
14494
    };
14495
 
14496
    var InvalidateApis = /*#__PURE__*/Object.freeze({
14497
        __proto__: null,
14498
        markValid: markValid,
14499
        markInvalid: markInvalid,
14500
        query: query,
14501
        run: run,
14502
        isInvalid: isInvalid
14503
    });
14504
 
14505
    const events$8 = (invalidConfig, invalidState) => invalidConfig.validator.map(validatorInfo => derive$2([run$1(validatorInfo.onEvent, component => {
14506
        run(component, invalidConfig, invalidState).get(identity);
14507
      })].concat(validatorInfo.validateOnLoad ? [runOnAttached(component => {
14508
        run(component, invalidConfig, invalidState).get(noop);
14509
      })] : []))).getOr({});
14510
 
14511
    var ActiveInvalidate = /*#__PURE__*/Object.freeze({
14512
        __proto__: null,
14513
        events: events$8
14514
    });
14515
 
14516
    var InvalidateSchema = [
14517
      required$1('invalidClass'),
14518
      defaulted('getRoot', Optional.none),
14519
      optionObjOf('notify', [
14520
        defaulted('aria', 'alert'),
14521
        defaulted('getContainer', Optional.none),
14522
        defaulted('validHtml', ''),
14523
        onHandler('onValid'),
14524
        onHandler('onInvalid'),
14525
        onHandler('onValidate')
14526
      ]),
14527
      optionObjOf('validator', [
14528
        required$1('validate'),
14529
        defaulted('onEvent', 'input'),
14530
        defaulted('validateOnLoad', true)
14531
      ])
14532
    ];
14533
 
14534
    const Invalidating = create$4({
14535
      fields: InvalidateSchema,
14536
      name: 'invalidating',
14537
      active: ActiveInvalidate,
14538
      apis: InvalidateApis,
14539
      extra: {
14540
        validation: validator => {
14541
          return component => {
14542
            const v = Representing.getValue(component);
14543
            return Future.pure(validator(v));
14544
          };
14545
        }
14546
      }
14547
    });
14548
 
14549
    const exhibit$1 = () => nu$7({
14550
      styles: {
14551
        '-webkit-user-select': 'none',
14552
        'user-select': 'none',
14553
        '-ms-user-select': 'none',
14554
        '-moz-user-select': '-moz-none'
14555
      },
14556
      attributes: { unselectable: 'on' }
14557
    });
14558
    const events$7 = () => derive$2([abort(selectstart(), always)]);
14559
 
14560
    var ActiveUnselecting = /*#__PURE__*/Object.freeze({
14561
        __proto__: null,
14562
        events: events$7,
14563
        exhibit: exhibit$1
14564
    });
14565
 
14566
    const Unselecting = create$4({
14567
      fields: [],
14568
      name: 'unselecting',
14569
      active: ActiveUnselecting
14570
    });
14571
 
14572
    const renderPanelButton = (spec, sharedBackstage) => Dropdown.sketch({
14573
      dom: spec.dom,
14574
      components: spec.components,
14575
      toggleClass: 'mce-active',
14576
      dropdownBehaviours: derive$1([
14577
        DisablingConfigs.button(sharedBackstage.providers.isDisabled),
14578
        receivingConfig(),
14579
        Unselecting.config({}),
14580
        Tabstopping.config({})
14581
      ]),
14582
      layouts: spec.layouts,
14583
      sandboxClasses: ['tox-dialog__popups'],
14584
      lazySink: sharedBackstage.getSink,
14585
      fetch: comp => Future.nu(callback => spec.fetch(callback)).map(items => Optional.from(createTieredDataFrom(deepMerge(createPartialChoiceMenu(generate$6('menu-value'), items, value => {
14586
        spec.onItemAction(comp, value);
14587
      }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, never, sharedBackstage.providers), { movement: deriveMenuMovement(spec.columns, spec.presets) })))),
14588
      parts: { menu: part(false, 1, spec.presets) }
14589
    });
14590
 
14591
    const colorInputChangeEvent = generate$6('color-input-change');
14592
    const colorSwatchChangeEvent = generate$6('color-swatch-change');
14593
    const colorPickerCancelEvent = generate$6('color-picker-cancel');
14594
    const renderColorInput = (spec, sharedBackstage, colorInputBackstage, initialData) => {
14595
      const pField = FormField.parts.field({
14596
        factory: Input,
14597
        inputClasses: ['tox-textfield'],
14598
        data: initialData,
14599
        onSetValue: c => Invalidating.run(c).get(noop),
14600
        inputBehaviours: derive$1([
14601
          Disabling.config({ disabled: sharedBackstage.providers.isDisabled }),
14602
          receivingConfig(),
14603
          Tabstopping.config({}),
14604
          Invalidating.config({
14605
            invalidClass: 'tox-textbox-field-invalid',
14606
            getRoot: comp => parentElement(comp.element),
14607
            notify: {
14608
              onValid: comp => {
14609
                const val = Representing.getValue(comp);
14610
                emitWith(comp, colorInputChangeEvent, { color: val });
14611
              }
14612
            },
14613
            validator: {
14614
              validateOnLoad: false,
14615
              validate: input => {
14616
                const inputValue = Representing.getValue(input);
14617
                if (inputValue.length === 0) {
14618
                  return Future.pure(Result.value(true));
14619
                } else {
14620
                  const span = SugarElement.fromTag('span');
14621
                  set$8(span, 'background-color', inputValue);
14622
                  const res = getRaw(span, 'background-color').fold(() => Result.error('blah'), _ => Result.value(inputValue));
14623
                  return Future.pure(res);
14624
                }
14625
              }
14626
            }
14627
          })
14628
        ]),
14629
        selectOnFocus: false
14630
      });
14631
      const pLabel = spec.label.map(label => renderLabel$3(label, sharedBackstage.providers));
14632
      const emitSwatchChange = (colorBit, value) => {
14633
        emitWith(colorBit, colorSwatchChangeEvent, { value });
14634
      };
14635
      const onItemAction = (comp, value) => {
14636
        memColorButton.getOpt(comp).each(colorBit => {
14637
          if (value === 'custom') {
14638
            colorInputBackstage.colorPicker(valueOpt => {
14639
              valueOpt.fold(() => emit(colorBit, colorPickerCancelEvent), value => {
14640
                emitSwatchChange(colorBit, value);
14641
                addColor(spec.storageKey, value);
14642
              });
14643
            }, '#ffffff');
14644
          } else if (value === 'remove') {
14645
            emitSwatchChange(colorBit, '');
14646
          } else {
14647
            emitSwatchChange(colorBit, value);
14648
          }
14649
        });
14650
      };
14651
      const memColorButton = record(renderPanelButton({
14652
        dom: {
14653
          tag: 'span',
14654
          attributes: { 'aria-label': sharedBackstage.providers.translate('Color swatch') }
14655
        },
14656
        layouts: {
14657
          onRtl: () => [
14658
            southwest$2,
14659
            southeast$2,
14660
            south$2
14661
          ],
14662
          onLtr: () => [
14663
            southeast$2,
14664
            southwest$2,
14665
            south$2
14666
          ]
14667
        },
14668
        components: [],
14669
        fetch: getFetch$1(colorInputBackstage.getColors(spec.storageKey), spec.storageKey, colorInputBackstage.hasCustomColors()),
14670
        columns: colorInputBackstage.getColorCols(spec.storageKey),
14671
        presets: 'color',
14672
        onItemAction
14673
      }, sharedBackstage));
14674
      return FormField.sketch({
14675
        dom: {
14676
          tag: 'div',
14677
          classes: ['tox-form__group']
14678
        },
14679
        components: pLabel.toArray().concat([{
14680
            dom: {
14681
              tag: 'div',
14682
              classes: ['tox-color-input']
14683
            },
14684
            components: [
14685
              pField,
14686
              memColorButton.asSpec()
14687
            ]
14688
          }]),
14689
        fieldBehaviours: derive$1([config('form-field-events', [
14690
            run$1(colorInputChangeEvent, (comp, se) => {
14691
              memColorButton.getOpt(comp).each(colorButton => {
14692
                set$8(colorButton.element, 'background-color', se.event.color);
14693
              });
14694
              emitWith(comp, formChangeEvent, { name: spec.name });
14695
            }),
14696
            run$1(colorSwatchChangeEvent, (comp, se) => {
14697
              FormField.getField(comp).each(field => {
14698
                Representing.setValue(field, se.event.value);
14699
                Composing.getCurrent(comp).each(Focusing.focus);
14700
              });
14701
            }),
14702
            run$1(colorPickerCancelEvent, (comp, _se) => {
14703
              FormField.getField(comp).each(_field => {
14704
                Composing.getCurrent(comp).each(Focusing.focus);
14705
              });
14706
            })
14707
          ])])
14708
      });
14709
    };
14710
 
14711
    const labelPart = optional({
14712
      schema: [required$1('dom')],
14713
      name: 'label'
14714
    });
14715
    const edgePart = name => optional({
14716
      name: '' + name + '-edge',
14717
      overrides: detail => {
14718
        const action = detail.model.manager.edgeActions[name];
14719
        return action.fold(() => ({}), a => ({
14720
          events: derive$2([
14721
            runActionExtra(touchstart(), (comp, se, d) => a(comp, d), [detail]),
14722
            runActionExtra(mousedown(), (comp, se, d) => a(comp, d), [detail]),
14723
            runActionExtra(mousemove(), (comp, se, det) => {
14724
              if (det.mouseIsDown.get()) {
14725
                a(comp, det);
14726
              }
14727
            }, [detail])
14728
          ])
14729
        }));
14730
      }
14731
    });
14732
    const tlEdgePart = edgePart('top-left');
14733
    const tedgePart = edgePart('top');
14734
    const trEdgePart = edgePart('top-right');
14735
    const redgePart = edgePart('right');
14736
    const brEdgePart = edgePart('bottom-right');
14737
    const bedgePart = edgePart('bottom');
14738
    const blEdgePart = edgePart('bottom-left');
14739
    const ledgePart = edgePart('left');
14740
    const thumbPart = required({
14741
      name: 'thumb',
14742
      defaults: constant$1({ dom: { styles: { position: 'absolute' } } }),
14743
      overrides: detail => {
14744
        return {
14745
          events: derive$2([
14746
            redirectToPart(touchstart(), detail, 'spectrum'),
14747
            redirectToPart(touchmove(), detail, 'spectrum'),
14748
            redirectToPart(touchend(), detail, 'spectrum'),
14749
            redirectToPart(mousedown(), detail, 'spectrum'),
14750
            redirectToPart(mousemove(), detail, 'spectrum'),
14751
            redirectToPart(mouseup(), detail, 'spectrum')
14752
          ])
14753
        };
14754
      }
14755
    });
14756
    const isShift = event => isShift$1(event.event);
14757
    const spectrumPart = required({
14758
      schema: [customField('mouseIsDown', () => Cell(false))],
14759
      name: 'spectrum',
14760
      overrides: detail => {
14761
        const modelDetail = detail.model;
14762
        const model = modelDetail.manager;
14763
        const setValueFrom = (component, simulatedEvent) => model.getValueFromEvent(simulatedEvent).map(value => model.setValueFrom(component, detail, value));
14764
        return {
14765
          behaviours: derive$1([
14766
            Keying.config({
14767
              mode: 'special',
14768
              onLeft: (spectrum, event) => model.onLeft(spectrum, detail, isShift(event)),
14769
              onRight: (spectrum, event) => model.onRight(spectrum, detail, isShift(event)),
14770
              onUp: (spectrum, event) => model.onUp(spectrum, detail, isShift(event)),
14771
              onDown: (spectrum, event) => model.onDown(spectrum, detail, isShift(event))
14772
            }),
14773
            Tabstopping.config({}),
14774
            Focusing.config({})
14775
          ]),
14776
          events: derive$2([
14777
            run$1(touchstart(), setValueFrom),
14778
            run$1(touchmove(), setValueFrom),
14779
            run$1(mousedown(), setValueFrom),
14780
            run$1(mousemove(), (spectrum, se) => {
14781
              if (detail.mouseIsDown.get()) {
14782
                setValueFrom(spectrum, se);
14783
              }
14784
            })
14785
          ])
14786
        };
14787
      }
14788
    });
14789
    var SliderParts = [
14790
      labelPart,
14791
      ledgePart,
14792
      redgePart,
14793
      tedgePart,
14794
      bedgePart,
14795
      tlEdgePart,
14796
      trEdgePart,
14797
      blEdgePart,
14798
      brEdgePart,
14799
      thumbPart,
14800
      spectrumPart
14801
    ];
14802
 
14803
    const _sliderChangeEvent = 'slider.change.value';
14804
    const sliderChangeEvent = constant$1(_sliderChangeEvent);
14805
    const isTouchEvent$2 = evt => evt.type.indexOf('touch') !== -1;
14806
    const getEventSource = simulatedEvent => {
14807
      const evt = simulatedEvent.event.raw;
14808
      if (isTouchEvent$2(evt)) {
14809
        const touchEvent = evt;
14810
        return touchEvent.touches !== undefined && touchEvent.touches.length === 1 ? Optional.some(touchEvent.touches[0]).map(t => SugarPosition(t.clientX, t.clientY)) : Optional.none();
14811
      } else {
14812
        const mouseEvent = evt;
14813
        return mouseEvent.clientX !== undefined ? Optional.some(mouseEvent).map(me => SugarPosition(me.clientX, me.clientY)) : Optional.none();
14814
      }
14815
    };
14816
 
14817
    const t = 'top', r = 'right', b = 'bottom', l = 'left';
14818
    const minX = detail => detail.model.minX;
14819
    const minY = detail => detail.model.minY;
14820
    const min1X = detail => detail.model.minX - 1;
14821
    const min1Y = detail => detail.model.minY - 1;
14822
    const maxX = detail => detail.model.maxX;
14823
    const maxY = detail => detail.model.maxY;
14824
    const max1X = detail => detail.model.maxX + 1;
14825
    const max1Y = detail => detail.model.maxY + 1;
14826
    const range = (detail, max, min) => max(detail) - min(detail);
14827
    const xRange = detail => range(detail, maxX, minX);
14828
    const yRange = detail => range(detail, maxY, minY);
14829
    const halfX = detail => xRange(detail) / 2;
14830
    const halfY = detail => yRange(detail) / 2;
14831
    const step = (detail, useMultiplier) => useMultiplier ? detail.stepSize * detail.speedMultiplier : detail.stepSize;
14832
    const snap = detail => detail.snapToGrid;
14833
    const snapStart = detail => detail.snapStart;
14834
    const rounded = detail => detail.rounded;
14835
    const hasEdge = (detail, edgeName) => detail[edgeName + '-edge'] !== undefined;
14836
    const hasLEdge = detail => hasEdge(detail, l);
14837
    const hasREdge = detail => hasEdge(detail, r);
14838
    const hasTEdge = detail => hasEdge(detail, t);
14839
    const hasBEdge = detail => hasEdge(detail, b);
14840
    const currentValue = detail => detail.model.value.get();
14841
 
14842
    const xyValue = (x, y) => ({
14843
      x,
14844
      y
14845
    });
14846
    const fireSliderChange$3 = (component, value) => {
14847
      emitWith(component, sliderChangeEvent(), { value });
14848
    };
14849
    const setToTLEdgeXY = (edge, detail) => {
14850
      fireSliderChange$3(edge, xyValue(min1X(detail), min1Y(detail)));
14851
    };
14852
    const setToTEdge = (edge, detail) => {
14853
      fireSliderChange$3(edge, min1Y(detail));
14854
    };
14855
    const setToTEdgeXY = (edge, detail) => {
14856
      fireSliderChange$3(edge, xyValue(halfX(detail), min1Y(detail)));
14857
    };
14858
    const setToTREdgeXY = (edge, detail) => {
14859
      fireSliderChange$3(edge, xyValue(max1X(detail), min1Y(detail)));
14860
    };
14861
    const setToREdge = (edge, detail) => {
14862
      fireSliderChange$3(edge, max1X(detail));
14863
    };
14864
    const setToREdgeXY = (edge, detail) => {
14865
      fireSliderChange$3(edge, xyValue(max1X(detail), halfY(detail)));
14866
    };
14867
    const setToBREdgeXY = (edge, detail) => {
14868
      fireSliderChange$3(edge, xyValue(max1X(detail), max1Y(detail)));
14869
    };
14870
    const setToBEdge = (edge, detail) => {
14871
      fireSliderChange$3(edge, max1Y(detail));
14872
    };
14873
    const setToBEdgeXY = (edge, detail) => {
14874
      fireSliderChange$3(edge, xyValue(halfX(detail), max1Y(detail)));
14875
    };
14876
    const setToBLEdgeXY = (edge, detail) => {
14877
      fireSliderChange$3(edge, xyValue(min1X(detail), max1Y(detail)));
14878
    };
14879
    const setToLEdge = (edge, detail) => {
14880
      fireSliderChange$3(edge, min1X(detail));
14881
    };
14882
    const setToLEdgeXY = (edge, detail) => {
14883
      fireSliderChange$3(edge, xyValue(min1X(detail), halfY(detail)));
14884
    };
14885
 
14886
    const reduceBy = (value, min, max, step) => {
14887
      if (value < min) {
14888
        return value;
14889
      } else if (value > max) {
14890
        return max;
14891
      } else if (value === min) {
14892
        return min - 1;
14893
      } else {
14894
        return Math.max(min, value - step);
14895
      }
14896
    };
14897
    const increaseBy = (value, min, max, step) => {
14898
      if (value > max) {
14899
        return value;
14900
      } else if (value < min) {
14901
        return min;
14902
      } else if (value === max) {
14903
        return max + 1;
14904
      } else {
14905
        return Math.min(max, value + step);
14906
      }
14907
    };
14908
    const capValue = (value, min, max) => Math.max(min, Math.min(max, value));
14909
    const snapValueOf = (value, min, max, step, snapStart) => snapStart.fold(() => {
14910
      const initValue = value - min;
14911
      const extraValue = Math.round(initValue / step) * step;
14912
      return capValue(min + extraValue, min - 1, max + 1);
14913
    }, start => {
14914
      const remainder = (value - start) % step;
14915
      const adjustment = Math.round(remainder / step);
14916
      const rawSteps = Math.floor((value - start) / step);
14917
      const maxSteps = Math.floor((max - start) / step);
14918
      const numSteps = Math.min(maxSteps, rawSteps + adjustment);
14919
      const r = start + numSteps * step;
14920
      return Math.max(start, r);
14921
    });
14922
    const findOffsetOf = (value, min, max) => Math.min(max, Math.max(value, min)) - min;
14923
    const findValueOf = args => {
14924
      const {min, max, range, value, step, snap, snapStart, rounded, hasMinEdge, hasMaxEdge, minBound, maxBound, screenRange} = args;
14925
      const capMin = hasMinEdge ? min - 1 : min;
14926
      const capMax = hasMaxEdge ? max + 1 : max;
14927
      if (value < minBound) {
14928
        return capMin;
14929
      } else if (value > maxBound) {
14930
        return capMax;
14931
      } else {
14932
        const offset = findOffsetOf(value, minBound, maxBound);
14933
        const newValue = capValue(offset / screenRange * range + min, capMin, capMax);
14934
        if (snap && newValue >= min && newValue <= max) {
14935
          return snapValueOf(newValue, min, max, step, snapStart);
14936
        } else if (rounded) {
14937
          return Math.round(newValue);
14938
        } else {
14939
          return newValue;
14940
        }
14941
      }
14942
    };
14943
    const findOffsetOfValue$2 = args => {
14944
      const {min, max, range, value, hasMinEdge, hasMaxEdge, maxBound, maxOffset, centerMinEdge, centerMaxEdge} = args;
14945
      if (value < min) {
14946
        return hasMinEdge ? 0 : centerMinEdge;
14947
      } else if (value > max) {
14948
        return hasMaxEdge ? maxBound : centerMaxEdge;
14949
      } else {
14950
        return (value - min) / range * maxOffset;
14951
      }
14952
    };
14953
 
14954
    const top = 'top', right = 'right', bottom = 'bottom', left = 'left', width = 'width', height = 'height';
14955
    const getBounds = component => component.element.dom.getBoundingClientRect();
14956
    const getBoundsProperty = (bounds, property) => bounds[property];
14957
    const getMinXBounds = component => {
14958
      const bounds = getBounds(component);
14959
      return getBoundsProperty(bounds, left);
14960
    };
14961
    const getMaxXBounds = component => {
14962
      const bounds = getBounds(component);
14963
      return getBoundsProperty(bounds, right);
14964
    };
14965
    const getMinYBounds = component => {
14966
      const bounds = getBounds(component);
14967
      return getBoundsProperty(bounds, top);
14968
    };
14969
    const getMaxYBounds = component => {
14970
      const bounds = getBounds(component);
14971
      return getBoundsProperty(bounds, bottom);
14972
    };
14973
    const getXScreenRange = component => {
14974
      const bounds = getBounds(component);
14975
      return getBoundsProperty(bounds, width);
14976
    };
14977
    const getYScreenRange = component => {
14978
      const bounds = getBounds(component);
14979
      return getBoundsProperty(bounds, height);
14980
    };
14981
    const getCenterOffsetOf = (componentMinEdge, componentMaxEdge, spectrumMinEdge) => (componentMinEdge + componentMaxEdge) / 2 - spectrumMinEdge;
14982
    const getXCenterOffSetOf = (component, spectrum) => {
14983
      const componentBounds = getBounds(component);
14984
      const spectrumBounds = getBounds(spectrum);
14985
      const componentMinEdge = getBoundsProperty(componentBounds, left);
14986
      const componentMaxEdge = getBoundsProperty(componentBounds, right);
14987
      const spectrumMinEdge = getBoundsProperty(spectrumBounds, left);
14988
      return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
14989
    };
14990
    const getYCenterOffSetOf = (component, spectrum) => {
14991
      const componentBounds = getBounds(component);
14992
      const spectrumBounds = getBounds(spectrum);
14993
      const componentMinEdge = getBoundsProperty(componentBounds, top);
14994
      const componentMaxEdge = getBoundsProperty(componentBounds, bottom);
14995
      const spectrumMinEdge = getBoundsProperty(spectrumBounds, top);
14996
      return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
14997
    };
14998
 
14999
    const fireSliderChange$2 = (spectrum, value) => {
15000
      emitWith(spectrum, sliderChangeEvent(), { value });
15001
    };
15002
    const findValueOfOffset$1 = (spectrum, detail, left) => {
15003
      const args = {
15004
        min: minX(detail),
15005
        max: maxX(detail),
15006
        range: xRange(detail),
15007
        value: left,
15008
        step: step(detail),
15009
        snap: snap(detail),
15010
        snapStart: snapStart(detail),
15011
        rounded: rounded(detail),
15012
        hasMinEdge: hasLEdge(detail),
15013
        hasMaxEdge: hasREdge(detail),
15014
        minBound: getMinXBounds(spectrum),
15015
        maxBound: getMaxXBounds(spectrum),
15016
        screenRange: getXScreenRange(spectrum)
15017
      };
15018
      return findValueOf(args);
15019
    };
15020
    const setValueFrom$2 = (spectrum, detail, value) => {
15021
      const xValue = findValueOfOffset$1(spectrum, detail, value);
15022
      const sliderVal = xValue;
15023
      fireSliderChange$2(spectrum, sliderVal);
15024
      return xValue;
15025
    };
15026
    const setToMin$2 = (spectrum, detail) => {
15027
      const min = minX(detail);
15028
      fireSliderChange$2(spectrum, min);
15029
    };
15030
    const setToMax$2 = (spectrum, detail) => {
15031
      const max = maxX(detail);
15032
      fireSliderChange$2(spectrum, max);
15033
    };
15034
    const moveBy$2 = (direction, spectrum, detail, useMultiplier) => {
15035
      const f = direction > 0 ? increaseBy : reduceBy;
15036
      const xValue = f(currentValue(detail), minX(detail), maxX(detail), step(detail, useMultiplier));
15037
      fireSliderChange$2(spectrum, xValue);
15038
      return Optional.some(xValue);
15039
    };
15040
    const handleMovement$2 = direction => (spectrum, detail, useMultiplier) => moveBy$2(direction, spectrum, detail, useMultiplier).map(always);
15041
    const getValueFromEvent$2 = simulatedEvent => {
15042
      const pos = getEventSource(simulatedEvent);
15043
      return pos.map(p => p.left);
15044
    };
15045
    const findOffsetOfValue$1 = (spectrum, detail, value, minEdge, maxEdge) => {
15046
      const minOffset = 0;
15047
      const maxOffset = getXScreenRange(spectrum);
15048
      const centerMinEdge = minEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(minOffset);
15049
      const centerMaxEdge = maxEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
15050
      const args = {
15051
        min: minX(detail),
15052
        max: maxX(detail),
15053
        range: xRange(detail),
15054
        value,
15055
        hasMinEdge: hasLEdge(detail),
15056
        hasMaxEdge: hasREdge(detail),
15057
        minBound: getMinXBounds(spectrum),
15058
        minOffset,
15059
        maxBound: getMaxXBounds(spectrum),
15060
        maxOffset,
15061
        centerMinEdge,
15062
        centerMaxEdge
15063
      };
15064
      return findOffsetOfValue$2(args);
15065
    };
15066
    const findPositionOfValue$1 = (slider, spectrum, value, minEdge, maxEdge, detail) => {
15067
      const offset = findOffsetOfValue$1(spectrum, detail, value, minEdge, maxEdge);
15068
      return getMinXBounds(spectrum) - getMinXBounds(slider) + offset;
15069
    };
15070
    const setPositionFromValue$2 = (slider, thumb, detail, edges) => {
15071
      const value = currentValue(detail);
15072
      const pos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
15073
      const thumbRadius = get$c(thumb.element) / 2;
15074
      set$8(thumb.element, 'left', pos - thumbRadius + 'px');
15075
    };
15076
    const onLeft$2 = handleMovement$2(-1);
15077
    const onRight$2 = handleMovement$2(1);
15078
    const onUp$2 = Optional.none;
15079
    const onDown$2 = Optional.none;
15080
    const edgeActions$2 = {
15081
      'top-left': Optional.none(),
15082
      'top': Optional.none(),
15083
      'top-right': Optional.none(),
15084
      'right': Optional.some(setToREdge),
15085
      'bottom-right': Optional.none(),
15086
      'bottom': Optional.none(),
15087
      'bottom-left': Optional.none(),
15088
      'left': Optional.some(setToLEdge)
15089
    };
15090
 
15091
    var HorizontalModel = /*#__PURE__*/Object.freeze({
15092
        __proto__: null,
15093
        setValueFrom: setValueFrom$2,
15094
        setToMin: setToMin$2,
15095
        setToMax: setToMax$2,
15096
        findValueOfOffset: findValueOfOffset$1,
15097
        getValueFromEvent: getValueFromEvent$2,
15098
        findPositionOfValue: findPositionOfValue$1,
15099
        setPositionFromValue: setPositionFromValue$2,
15100
        onLeft: onLeft$2,
15101
        onRight: onRight$2,
15102
        onUp: onUp$2,
15103
        onDown: onDown$2,
15104
        edgeActions: edgeActions$2
15105
    });
15106
 
15107
    const fireSliderChange$1 = (spectrum, value) => {
15108
      emitWith(spectrum, sliderChangeEvent(), { value });
15109
    };
15110
    const findValueOfOffset = (spectrum, detail, top) => {
15111
      const args = {
15112
        min: minY(detail),
15113
        max: maxY(detail),
15114
        range: yRange(detail),
15115
        value: top,
15116
        step: step(detail),
15117
        snap: snap(detail),
15118
        snapStart: snapStart(detail),
15119
        rounded: rounded(detail),
15120
        hasMinEdge: hasTEdge(detail),
15121
        hasMaxEdge: hasBEdge(detail),
15122
        minBound: getMinYBounds(spectrum),
15123
        maxBound: getMaxYBounds(spectrum),
15124
        screenRange: getYScreenRange(spectrum)
15125
      };
15126
      return findValueOf(args);
15127
    };
15128
    const setValueFrom$1 = (spectrum, detail, value) => {
15129
      const yValue = findValueOfOffset(spectrum, detail, value);
15130
      const sliderVal = yValue;
15131
      fireSliderChange$1(spectrum, sliderVal);
15132
      return yValue;
15133
    };
15134
    const setToMin$1 = (spectrum, detail) => {
15135
      const min = minY(detail);
15136
      fireSliderChange$1(spectrum, min);
15137
    };
15138
    const setToMax$1 = (spectrum, detail) => {
15139
      const max = maxY(detail);
15140
      fireSliderChange$1(spectrum, max);
15141
    };
15142
    const moveBy$1 = (direction, spectrum, detail, useMultiplier) => {
15143
      const f = direction > 0 ? increaseBy : reduceBy;
15144
      const yValue = f(currentValue(detail), minY(detail), maxY(detail), step(detail, useMultiplier));
15145
      fireSliderChange$1(spectrum, yValue);
15146
      return Optional.some(yValue);
15147
    };
15148
    const handleMovement$1 = direction => (spectrum, detail, useMultiplier) => moveBy$1(direction, spectrum, detail, useMultiplier).map(always);
15149
    const getValueFromEvent$1 = simulatedEvent => {
15150
      const pos = getEventSource(simulatedEvent);
15151
      return pos.map(p => {
15152
        return p.top;
15153
      });
15154
    };
15155
    const findOffsetOfValue = (spectrum, detail, value, minEdge, maxEdge) => {
15156
      const minOffset = 0;
15157
      const maxOffset = getYScreenRange(spectrum);
15158
      const centerMinEdge = minEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(minOffset);
15159
      const centerMaxEdge = maxEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
15160
      const args = {
15161
        min: minY(detail),
15162
        max: maxY(detail),
15163
        range: yRange(detail),
15164
        value,
15165
        hasMinEdge: hasTEdge(detail),
15166
        hasMaxEdge: hasBEdge(detail),
15167
        minBound: getMinYBounds(spectrum),
15168
        minOffset,
15169
        maxBound: getMaxYBounds(spectrum),
15170
        maxOffset,
15171
        centerMinEdge,
15172
        centerMaxEdge
15173
      };
15174
      return findOffsetOfValue$2(args);
15175
    };
15176
    const findPositionOfValue = (slider, spectrum, value, minEdge, maxEdge, detail) => {
15177
      const offset = findOffsetOfValue(spectrum, detail, value, minEdge, maxEdge);
15178
      return getMinYBounds(spectrum) - getMinYBounds(slider) + offset;
15179
    };
15180
    const setPositionFromValue$1 = (slider, thumb, detail, edges) => {
15181
      const value = currentValue(detail);
15182
      const pos = findPositionOfValue(slider, edges.getSpectrum(slider), value, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
15183
      const thumbRadius = get$d(thumb.element) / 2;
15184
      set$8(thumb.element, 'top', pos - thumbRadius + 'px');
15185
    };
15186
    const onLeft$1 = Optional.none;
15187
    const onRight$1 = Optional.none;
15188
    const onUp$1 = handleMovement$1(-1);
15189
    const onDown$1 = handleMovement$1(1);
15190
    const edgeActions$1 = {
15191
      'top-left': Optional.none(),
15192
      'top': Optional.some(setToTEdge),
15193
      'top-right': Optional.none(),
15194
      'right': Optional.none(),
15195
      'bottom-right': Optional.none(),
15196
      'bottom': Optional.some(setToBEdge),
15197
      'bottom-left': Optional.none(),
15198
      'left': Optional.none()
15199
    };
15200
 
15201
    var VerticalModel = /*#__PURE__*/Object.freeze({
15202
        __proto__: null,
15203
        setValueFrom: setValueFrom$1,
15204
        setToMin: setToMin$1,
15205
        setToMax: setToMax$1,
15206
        findValueOfOffset: findValueOfOffset,
15207
        getValueFromEvent: getValueFromEvent$1,
15208
        findPositionOfValue: findPositionOfValue,
15209
        setPositionFromValue: setPositionFromValue$1,
15210
        onLeft: onLeft$1,
15211
        onRight: onRight$1,
15212
        onUp: onUp$1,
15213
        onDown: onDown$1,
15214
        edgeActions: edgeActions$1
15215
    });
15216
 
15217
    const fireSliderChange = (spectrum, value) => {
15218
      emitWith(spectrum, sliderChangeEvent(), { value });
15219
    };
15220
    const sliderValue = (x, y) => ({
15221
      x,
15222
      y
15223
    });
15224
    const setValueFrom = (spectrum, detail, value) => {
15225
      const xValue = findValueOfOffset$1(spectrum, detail, value.left);
15226
      const yValue = findValueOfOffset(spectrum, detail, value.top);
15227
      const val = sliderValue(xValue, yValue);
15228
      fireSliderChange(spectrum, val);
15229
      return val;
15230
    };
15231
    const moveBy = (direction, isVerticalMovement, spectrum, detail, useMultiplier) => {
15232
      const f = direction > 0 ? increaseBy : reduceBy;
15233
      const xValue = isVerticalMovement ? currentValue(detail).x : f(currentValue(detail).x, minX(detail), maxX(detail), step(detail, useMultiplier));
15234
      const yValue = !isVerticalMovement ? currentValue(detail).y : f(currentValue(detail).y, minY(detail), maxY(detail), step(detail, useMultiplier));
15235
      fireSliderChange(spectrum, sliderValue(xValue, yValue));
15236
      return Optional.some(xValue);
15237
    };
15238
    const handleMovement = (direction, isVerticalMovement) => (spectrum, detail, useMultiplier) => moveBy(direction, isVerticalMovement, spectrum, detail, useMultiplier).map(always);
15239
    const setToMin = (spectrum, detail) => {
15240
      const mX = minX(detail);
15241
      const mY = minY(detail);
15242
      fireSliderChange(spectrum, sliderValue(mX, mY));
15243
    };
15244
    const setToMax = (spectrum, detail) => {
15245
      const mX = maxX(detail);
15246
      const mY = maxY(detail);
15247
      fireSliderChange(spectrum, sliderValue(mX, mY));
15248
    };
15249
    const getValueFromEvent = simulatedEvent => getEventSource(simulatedEvent);
15250
    const setPositionFromValue = (slider, thumb, detail, edges) => {
15251
      const value = currentValue(detail);
15252
      const xPos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value.x, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
15253
      const yPos = findPositionOfValue(slider, edges.getSpectrum(slider), value.y, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
15254
      const thumbXRadius = get$c(thumb.element) / 2;
15255
      const thumbYRadius = get$d(thumb.element) / 2;
15256
      set$8(thumb.element, 'left', xPos - thumbXRadius + 'px');
15257
      set$8(thumb.element, 'top', yPos - thumbYRadius + 'px');
15258
    };
15259
    const onLeft = handleMovement(-1, false);
15260
    const onRight = handleMovement(1, false);
15261
    const onUp = handleMovement(-1, true);
15262
    const onDown = handleMovement(1, true);
15263
    const edgeActions = {
15264
      'top-left': Optional.some(setToTLEdgeXY),
15265
      'top': Optional.some(setToTEdgeXY),
15266
      'top-right': Optional.some(setToTREdgeXY),
15267
      'right': Optional.some(setToREdgeXY),
15268
      'bottom-right': Optional.some(setToBREdgeXY),
15269
      'bottom': Optional.some(setToBEdgeXY),
15270
      'bottom-left': Optional.some(setToBLEdgeXY),
15271
      'left': Optional.some(setToLEdgeXY)
15272
    };
15273
 
15274
    var TwoDModel = /*#__PURE__*/Object.freeze({
15275
        __proto__: null,
15276
        setValueFrom: setValueFrom,
15277
        setToMin: setToMin,
15278
        setToMax: setToMax,
15279
        getValueFromEvent: getValueFromEvent,
15280
        setPositionFromValue: setPositionFromValue,
15281
        onLeft: onLeft,
15282
        onRight: onRight,
15283
        onUp: onUp,
15284
        onDown: onDown,
15285
        edgeActions: edgeActions
15286
    });
15287
 
15288
    const SliderSchema = [
15289
      defaulted('stepSize', 1),
15290
      defaulted('speedMultiplier', 10),
15291
      defaulted('onChange', noop),
15292
      defaulted('onChoose', noop),
15293
      defaulted('onInit', noop),
15294
      defaulted('onDragStart', noop),
15295
      defaulted('onDragEnd', noop),
15296
      defaulted('snapToGrid', false),
15297
      defaulted('rounded', true),
15298
      option$3('snapStart'),
15299
      requiredOf('model', choose$1('mode', {
15300
        x: [
15301
          defaulted('minX', 0),
15302
          defaulted('maxX', 100),
15303
          customField('value', spec => Cell(spec.mode.minX)),
15304
          required$1('getInitialValue'),
15305
          output$1('manager', HorizontalModel)
15306
        ],
15307
        y: [
15308
          defaulted('minY', 0),
15309
          defaulted('maxY', 100),
15310
          customField('value', spec => Cell(spec.mode.minY)),
15311
          required$1('getInitialValue'),
15312
          output$1('manager', VerticalModel)
15313
        ],
15314
        xy: [
15315
          defaulted('minX', 0),
15316
          defaulted('maxX', 100),
15317
          defaulted('minY', 0),
15318
          defaulted('maxY', 100),
15319
          customField('value', spec => Cell({
15320
            x: spec.mode.minX,
15321
            y: spec.mode.minY
15322
          })),
15323
          required$1('getInitialValue'),
15324
          output$1('manager', TwoDModel)
15325
        ]
15326
      })),
15327
      field('sliderBehaviours', [
15328
        Keying,
15329
        Representing
15330
      ]),
15331
      customField('mouseIsDown', () => Cell(false))
15332
    ];
15333
 
15334
    const sketch$2 = (detail, components, _spec, _externals) => {
15335
      const getThumb = component => getPartOrDie(component, detail, 'thumb');
15336
      const getSpectrum = component => getPartOrDie(component, detail, 'spectrum');
15337
      const getLeftEdge = component => getPart(component, detail, 'left-edge');
15338
      const getRightEdge = component => getPart(component, detail, 'right-edge');
15339
      const getTopEdge = component => getPart(component, detail, 'top-edge');
15340
      const getBottomEdge = component => getPart(component, detail, 'bottom-edge');
15341
      const modelDetail = detail.model;
15342
      const model = modelDetail.manager;
15343
      const refresh = (slider, thumb) => {
15344
        model.setPositionFromValue(slider, thumb, detail, {
15345
          getLeftEdge,
15346
          getRightEdge,
15347
          getTopEdge,
15348
          getBottomEdge,
15349
          getSpectrum
15350
        });
15351
      };
15352
      const setValue = (slider, newValue) => {
15353
        modelDetail.value.set(newValue);
15354
        const thumb = getThumb(slider);
15355
        refresh(slider, thumb);
15356
      };
15357
      const changeValue = (slider, newValue) => {
15358
        setValue(slider, newValue);
15359
        const thumb = getThumb(slider);
15360
        detail.onChange(slider, thumb, newValue);
15361
        return Optional.some(true);
15362
      };
15363
      const resetToMin = slider => {
15364
        model.setToMin(slider, detail);
15365
      };
15366
      const resetToMax = slider => {
15367
        model.setToMax(slider, detail);
15368
      };
15369
      const choose = slider => {
15370
        const fireOnChoose = () => {
15371
          getPart(slider, detail, 'thumb').each(thumb => {
15372
            const value = modelDetail.value.get();
15373
            detail.onChoose(slider, thumb, value);
15374
          });
15375
        };
15376
        const wasDown = detail.mouseIsDown.get();
15377
        detail.mouseIsDown.set(false);
15378
        if (wasDown) {
15379
          fireOnChoose();
15380
        }
15381
      };
15382
      const onDragStart = (slider, simulatedEvent) => {
15383
        simulatedEvent.stop();
15384
        detail.mouseIsDown.set(true);
15385
        detail.onDragStart(slider, getThumb(slider));
15386
      };
15387
      const onDragEnd = (slider, simulatedEvent) => {
15388
        simulatedEvent.stop();
15389
        detail.onDragEnd(slider, getThumb(slider));
15390
        choose(slider);
15391
      };
15392
      const focusWidget = component => {
15393
        getPart(component, detail, 'spectrum').map(Keying.focusIn);
15394
      };
15395
      return {
15396
        uid: detail.uid,
15397
        dom: detail.dom,
15398
        components,
15399
        behaviours: augment(detail.sliderBehaviours, [
15400
          Keying.config({
15401
            mode: 'special',
15402
            focusIn: focusWidget
15403
          }),
15404
          Representing.config({
15405
            store: {
15406
              mode: 'manual',
15407
              getValue: _ => {
15408
                return modelDetail.value.get();
15409
              },
15410
              setValue
15411
            }
15412
          }),
15413
          Receiving.config({ channels: { [mouseReleased()]: { onReceive: choose } } })
15414
        ]),
15415
        events: derive$2([
15416
          run$1(sliderChangeEvent(), (slider, simulatedEvent) => {
15417
            changeValue(slider, simulatedEvent.event.value);
15418
          }),
15419
          runOnAttached((slider, _simulatedEvent) => {
15420
            const getInitial = modelDetail.getInitialValue();
15421
            modelDetail.value.set(getInitial);
15422
            const thumb = getThumb(slider);
15423
            refresh(slider, thumb);
15424
            const spectrum = getSpectrum(slider);
15425
            detail.onInit(slider, thumb, spectrum, modelDetail.value.get());
15426
          }),
15427
          run$1(touchstart(), onDragStart),
15428
          run$1(touchend(), onDragEnd),
15429
          run$1(mousedown(), (component, event) => {
15430
            focusWidget(component);
15431
            onDragStart(component, event);
15432
          }),
15433
          run$1(mouseup(), onDragEnd)
15434
        ]),
15435
        apis: {
15436
          resetToMin,
15437
          resetToMax,
15438
          setValue,
15439
          refresh
15440
        },
15441
        domModification: { styles: { position: 'relative' } }
15442
      };
15443
    };
15444
 
15445
    const Slider = composite({
15446
      name: 'Slider',
15447
      configFields: SliderSchema,
15448
      partFields: SliderParts,
15449
      factory: sketch$2,
15450
      apis: {
15451
        setValue: (apis, slider, value) => {
15452
          apis.setValue(slider, value);
15453
        },
15454
        resetToMin: (apis, slider) => {
15455
          apis.resetToMin(slider);
15456
        },
15457
        resetToMax: (apis, slider) => {
15458
          apis.resetToMax(slider);
15459
        },
15460
        refresh: (apis, slider) => {
15461
          apis.refresh(slider);
15462
        }
15463
      }
15464
    });
15465
 
15466
    const fieldsUpdate = generate$6('rgb-hex-update');
15467
    const sliderUpdate = generate$6('slider-update');
15468
    const paletteUpdate = generate$6('palette-update');
15469
 
15470
    const sliderFactory = (translate, getClass) => {
15471
      const spectrum = Slider.parts.spectrum({
15472
        dom: {
15473
          tag: 'div',
15474
          classes: [getClass('hue-slider-spectrum')],
15475
          attributes: { role: 'presentation' }
15476
        }
15477
      });
15478
      const thumb = Slider.parts.thumb({
15479
        dom: {
15480
          tag: 'div',
15481
          classes: [getClass('hue-slider-thumb')],
15482
          attributes: { role: 'presentation' }
15483
        }
15484
      });
15485
      return Slider.sketch({
15486
        dom: {
15487
          tag: 'div',
15488
          classes: [getClass('hue-slider')],
15489
          attributes: {
15490
            'role': 'slider',
15491
            'aria-valuemin': 0,
15492
            'aria-valuemax': 360,
15493
            'aria-valuenow': 120
15494
          }
15495
        },
15496
        rounded: false,
15497
        model: {
15498
          mode: 'y',
15499
          getInitialValue: constant$1(0)
15500
        },
15501
        components: [
15502
          spectrum,
15503
          thumb
15504
        ],
15505
        sliderBehaviours: derive$1([Focusing.config({})]),
15506
        onChange: (slider, _thumb, value) => {
15507
          set$9(slider.element, 'aria-valuenow', Math.floor(360 - value * 3.6));
15508
          emitWith(slider, sliderUpdate, { value });
15509
        }
15510
      });
15511
    };
15512
 
15513
    const owner$1 = 'form';
15514
    const schema$i = [field('formBehaviours', [Representing])];
15515
    const getPartName$1 = name => '<alloy.field.' + name + '>';
15516
    const sketch$1 = fSpec => {
15517
      const parts = (() => {
15518
        const record = [];
15519
        const field = (name, config) => {
15520
          record.push(name);
15521
          return generateOne$1(owner$1, getPartName$1(name), config);
15522
        };
15523
        return {
15524
          field,
15525
          record: constant$1(record)
15526
        };
15527
      })();
15528
      const spec = fSpec(parts);
15529
      const partNames = parts.record();
15530
      const fieldParts = map$2(partNames, n => required({
15531
        name: n,
15532
        pname: getPartName$1(n)
15533
      }));
15534
      return composite$1(owner$1, schema$i, fieldParts, make$4, spec);
15535
    };
15536
    const toResult = (o, e) => o.fold(() => Result.error(e), Result.value);
15537
    const make$4 = (detail, components) => ({
15538
      uid: detail.uid,
15539
      dom: detail.dom,
15540
      components,
15541
      behaviours: augment(detail.formBehaviours, [Representing.config({
15542
          store: {
15543
            mode: 'manual',
15544
            getValue: form => {
15545
              const resPs = getAllParts(form, detail);
15546
              return map$1(resPs, (resPThunk, pName) => resPThunk().bind(v => {
15547
                const opt = Composing.getCurrent(v);
15548
                return toResult(opt, new Error(`Cannot find a current component to extract the value from for form part '${ pName }': ` + element(v.element)));
15549
              }).map(Representing.getValue));
15550
            },
15551
            setValue: (form, values) => {
15552
              each(values, (newValue, key) => {
15553
                getPart(form, detail, key).each(wrapper => {
15554
                  Composing.getCurrent(wrapper).each(field => {
15555
                    Representing.setValue(field, newValue);
15556
                  });
15557
                });
15558
              });
15559
            }
15560
          }
15561
        })]),
15562
      apis: {
15563
        getField: (form, key) => {
15564
          return getPart(form, detail, key).bind(Composing.getCurrent);
15565
        }
15566
      }
15567
    });
15568
    const Form = {
15569
      getField: makeApi((apis, component, key) => apis.getField(component, key)),
15570
      sketch: sketch$1
15571
    };
15572
 
15573
    const validInput = generate$6('valid-input');
15574
    const invalidInput = generate$6('invalid-input');
15575
    const validatingInput = generate$6('validating-input');
15576
    const translatePrefix = 'colorcustom.rgb.';
15577
    const rgbFormFactory = (translate, getClass, onValidHexx, onInvalidHexx) => {
15578
      const invalidation = (label, isValid) => Invalidating.config({
15579
        invalidClass: getClass('invalid'),
15580
        notify: {
15581
          onValidate: comp => {
15582
            emitWith(comp, validatingInput, { type: label });
15583
          },
15584
          onValid: comp => {
15585
            emitWith(comp, validInput, {
15586
              type: label,
15587
              value: Representing.getValue(comp)
15588
            });
15589
          },
15590
          onInvalid: comp => {
15591
            emitWith(comp, invalidInput, {
15592
              type: label,
15593
              value: Representing.getValue(comp)
15594
            });
15595
          }
15596
        },
15597
        validator: {
15598
          validate: comp => {
15599
            const value = Representing.getValue(comp);
15600
            const res = isValid(value) ? Result.value(true) : Result.error(translate('aria.input.invalid'));
15601
            return Future.pure(res);
15602
          },
15603
          validateOnLoad: false
15604
        }
15605
      });
15606
      const renderTextField = (isValid, name, label, description, data) => {
15607
        const helptext = translate(translatePrefix + 'range');
15608
        const pLabel = FormField.parts.label({
15609
          dom: {
15610
            tag: 'label',
15611
            attributes: { 'aria-label': description }
15612
          },
15613
          components: [text$2(label)]
15614
        });
15615
        const pField = FormField.parts.field({
15616
          data,
15617
          factory: Input,
15618
          inputAttributes: {
15619
            type: 'text',
15620
            ...name === 'hex' ? { 'aria-live': 'polite' } : {}
15621
          },
15622
          inputClasses: [getClass('textfield')],
15623
          inputBehaviours: derive$1([
15624
            invalidation(name, isValid),
15625
            Tabstopping.config({})
15626
          ]),
15627
          onSetValue: input => {
15628
            if (Invalidating.isInvalid(input)) {
15629
              const run = Invalidating.run(input);
15630
              run.get(noop);
15631
            }
15632
          }
15633
        });
15634
        const comps = [
15635
          pLabel,
15636
          pField
15637
        ];
15638
        const concats = name !== 'hex' ? [FormField.parts['aria-descriptor']({ text: helptext })] : [];
15639
        const components = comps.concat(concats);
15640
        return {
15641
          dom: {
15642
            tag: 'div',
15643
            attributes: { role: 'presentation' }
15644
          },
15645
          components
15646
        };
15647
      };
15648
      const copyRgbToHex = (form, rgba) => {
15649
        const hex = fromRgba(rgba);
15650
        Form.getField(form, 'hex').each(hexField => {
15651
          if (!Focusing.isFocused(hexField)) {
15652
            Representing.setValue(form, { hex: hex.value });
15653
          }
15654
        });
15655
        return hex;
15656
      };
15657
      const copyRgbToForm = (form, rgb) => {
15658
        const red = rgb.red;
15659
        const green = rgb.green;
15660
        const blue = rgb.blue;
15661
        Representing.setValue(form, {
15662
          red,
15663
          green,
15664
          blue
15665
        });
15666
      };
15667
      const memPreview = record({
15668
        dom: {
15669
          tag: 'div',
15670
          classes: [getClass('rgba-preview')],
15671
          styles: { 'background-color': 'white' },
15672
          attributes: { role: 'presentation' }
15673
        }
15674
      });
15675
      const updatePreview = (anyInSystem, hex) => {
15676
        memPreview.getOpt(anyInSystem).each(preview => {
15677
          set$8(preview.element, 'background-color', '#' + hex.value);
15678
        });
15679
      };
15680
      const factory = () => {
15681
        const state = {
15682
          red: Cell(Optional.some(255)),
15683
          green: Cell(Optional.some(255)),
15684
          blue: Cell(Optional.some(255)),
15685
          hex: Cell(Optional.some('ffffff'))
15686
        };
15687
        const copyHexToRgb = (form, hex) => {
15688
          const rgb = fromHex(hex);
15689
          copyRgbToForm(form, rgb);
15690
          setValueRgb(rgb);
15691
        };
15692
        const get = prop => state[prop].get();
15693
        const set = (prop, value) => {
15694
          state[prop].set(value);
15695
        };
15696
        const getValueRgb = () => get('red').bind(red => get('green').bind(green => get('blue').map(blue => rgbaColour(red, green, blue, 1))));
15697
        const setValueRgb = rgb => {
15698
          const red = rgb.red;
15699
          const green = rgb.green;
15700
          const blue = rgb.blue;
15701
          set('red', Optional.some(red));
15702
          set('green', Optional.some(green));
15703
          set('blue', Optional.some(blue));
15704
        };
15705
        const onInvalidInput = (form, simulatedEvent) => {
15706
          const data = simulatedEvent.event;
15707
          if (data.type !== 'hex') {
15708
            set(data.type, Optional.none());
15709
          } else {
15710
            onInvalidHexx(form);
15711
          }
15712
        };
15713
        const onValidHex = (form, value) => {
15714
          onValidHexx(form);
15715
          const hex = hexColour(value);
15716
          set('hex', Optional.some(hex.value));
15717
          const rgb = fromHex(hex);
15718
          copyRgbToForm(form, rgb);
15719
          setValueRgb(rgb);
15720
          emitWith(form, fieldsUpdate, { hex });
15721
          updatePreview(form, hex);
15722
        };
15723
        const onValidRgb = (form, prop, value) => {
15724
          const val = parseInt(value, 10);
15725
          set(prop, Optional.some(val));
15726
          getValueRgb().each(rgb => {
15727
            const hex = copyRgbToHex(form, rgb);
15728
            emitWith(form, fieldsUpdate, { hex });
15729
            updatePreview(form, hex);
15730
          });
15731
        };
15732
        const isHexInputEvent = data => data.type === 'hex';
15733
        const onValidInput = (form, simulatedEvent) => {
15734
          const data = simulatedEvent.event;
15735
          if (isHexInputEvent(data)) {
15736
            onValidHex(form, data.value);
15737
          } else {
15738
            onValidRgb(form, data.type, data.value);
15739
          }
15740
        };
15741
        const formPartStrings = key => ({
15742
          label: translate(translatePrefix + key + '.label'),
15743
          description: translate(translatePrefix + key + '.description')
15744
        });
15745
        const redStrings = formPartStrings('red');
15746
        const greenStrings = formPartStrings('green');
15747
        const blueStrings = formPartStrings('blue');
15748
        const hexStrings = formPartStrings('hex');
15749
        return deepMerge(Form.sketch(parts => ({
15750
          dom: {
15751
            tag: 'form',
15752
            classes: [getClass('rgb-form')],
15753
            attributes: { 'aria-label': translate('aria.color.picker') }
15754
          },
15755
          components: [
15756
            parts.field('red', FormField.sketch(renderTextField(isRgbaComponent, 'red', redStrings.label, redStrings.description, 255))),
15757
            parts.field('green', FormField.sketch(renderTextField(isRgbaComponent, 'green', greenStrings.label, greenStrings.description, 255))),
15758
            parts.field('blue', FormField.sketch(renderTextField(isRgbaComponent, 'blue', blueStrings.label, blueStrings.description, 255))),
15759
            parts.field('hex', FormField.sketch(renderTextField(isHexString, 'hex', hexStrings.label, hexStrings.description, 'ffffff'))),
15760
            memPreview.asSpec()
15761
          ],
15762
          formBehaviours: derive$1([
15763
            Invalidating.config({ invalidClass: getClass('form-invalid') }),
15764
            config('rgb-form-events', [
15765
              run$1(validInput, onValidInput),
15766
              run$1(invalidInput, onInvalidInput),
15767
              run$1(validatingInput, onInvalidInput)
15768
            ])
15769
          ])
15770
        })), {
15771
          apis: {
15772
            updateHex: (form, hex) => {
15773
              Representing.setValue(form, { hex: hex.value });
15774
              copyHexToRgb(form, hex);
15775
              updatePreview(form, hex);
15776
            }
15777
          }
15778
        });
15779
      };
15780
      const rgbFormSketcher = single({
15781
        factory,
15782
        name: 'RgbForm',
15783
        configFields: [],
15784
        apis: {
15785
          updateHex: (apis, form, hex) => {
15786
            apis.updateHex(form, hex);
15787
          }
15788
        },
15789
        extraApis: {}
15790
      });
15791
      return rgbFormSketcher;
15792
    };
15793
 
15794
    const paletteFactory = (translate, getClass) => {
15795
      const spectrumPart = Slider.parts.spectrum({
15796
        dom: {
15797
          tag: 'canvas',
15798
          attributes: { role: 'presentation' },
15799
          classes: [getClass('sv-palette-spectrum')]
15800
        }
15801
      });
15802
      const thumbPart = Slider.parts.thumb({
15803
        dom: {
15804
          tag: 'div',
15805
          attributes: { role: 'presentation' },
15806
          classes: [getClass('sv-palette-thumb')],
15807
          innerHtml: `<div class=${ getClass('sv-palette-inner-thumb') } role="presentation"></div>`
15808
        }
15809
      });
15810
      const setColour = (canvas, rgba) => {
15811
        const {width, height} = canvas;
15812
        const ctx = canvas.getContext('2d');
15813
        if (ctx === null) {
15814
          return;
15815
        }
15816
        ctx.fillStyle = rgba;
15817
        ctx.fillRect(0, 0, width, height);
15818
        const grdWhite = ctx.createLinearGradient(0, 0, width, 0);
15819
        grdWhite.addColorStop(0, 'rgba(255,255,255,1)');
15820
        grdWhite.addColorStop(1, 'rgba(255,255,255,0)');
15821
        ctx.fillStyle = grdWhite;
15822
        ctx.fillRect(0, 0, width, height);
15823
        const grdBlack = ctx.createLinearGradient(0, 0, 0, height);
15824
        grdBlack.addColorStop(0, 'rgba(0,0,0,0)');
15825
        grdBlack.addColorStop(1, 'rgba(0,0,0,1)');
15826
        ctx.fillStyle = grdBlack;
15827
        ctx.fillRect(0, 0, width, height);
15828
      };
15829
      const setPaletteHue = (slider, hue) => {
15830
        const canvas = slider.components()[0].element.dom;
15831
        const hsv = hsvColour(hue, 100, 100);
15832
        const rgba = fromHsv(hsv);
15833
        setColour(canvas, toString(rgba));
15834
      };
15835
      const setPaletteThumb = (slider, hex) => {
15836
        const hsv = fromRgb(fromHex(hex));
15837
        Slider.setValue(slider, {
15838
          x: hsv.saturation,
15839
          y: 100 - hsv.value
15840
        });
15841
        set$9(slider.element, 'aria-valuetext', translate([
15842
          'Saturation {0}%, Brightness {1}%',
15843
          hsv.saturation,
15844
          hsv.value
15845
        ]));
15846
      };
15847
      const factory = _detail => {
15848
        const getInitialValue = constant$1({
15849
          x: 0,
15850
          y: 0
15851
        });
15852
        const onChange = (slider, _thumb, value) => {
15853
          if (!isNumber(value)) {
15854
            set$9(slider.element, 'aria-valuetext', translate([
15855
              'Saturation {0}%, Brightness {1}%',
15856
              Math.floor(value.x),
15857
              Math.floor(100 - value.y)
15858
            ]));
15859
          }
15860
          emitWith(slider, paletteUpdate, { value });
15861
        };
15862
        const onInit = (_slider, _thumb, spectrum, _value) => {
15863
          setColour(spectrum.element.dom, toString(red));
15864
        };
15865
        const sliderBehaviours = derive$1([
15866
          Composing.config({ find: Optional.some }),
15867
          Focusing.config({})
15868
        ]);
15869
        return Slider.sketch({
15870
          dom: {
15871
            tag: 'div',
15872
            attributes: {
15873
              'role': 'slider',
15874
              'aria-valuetext': translate([
15875
                'Saturation {0}%, Brightness {1}%',
15876
                0,
15877
 
15878
              ])
15879
            },
15880
            classes: [getClass('sv-palette')]
15881
          },
15882
          model: {
15883
            mode: 'xy',
15884
            getInitialValue
15885
          },
15886
          rounded: false,
15887
          components: [
15888
            spectrumPart,
15889
            thumbPart
15890
          ],
15891
          onChange,
15892
          onInit,
15893
          sliderBehaviours
15894
        });
15895
      };
15896
      const saturationBrightnessPaletteSketcher = single({
15897
        factory,
15898
        name: 'SaturationBrightnessPalette',
15899
        configFields: [],
15900
        apis: {
15901
          setHue: (_apis, slider, hue) => {
15902
            setPaletteHue(slider, hue);
15903
          },
15904
          setThumb: (_apis, slider, hex) => {
15905
            setPaletteThumb(slider, hex);
15906
          }
15907
        },
15908
        extraApis: {}
15909
      });
15910
      return saturationBrightnessPaletteSketcher;
15911
    };
15912
 
15913
    const makeFactory = (translate, getClass) => {
15914
      const factory = detail => {
15915
        const rgbForm = rgbFormFactory(translate, getClass, detail.onValidHex, detail.onInvalidHex);
15916
        const sbPalette = paletteFactory(translate, getClass);
15917
        const hueSliderToDegrees = hue => (100 - hue) / 100 * 360;
15918
        const hueDegreesToSlider = hue => 100 - hue / 360 * 100;
15919
        const state = {
15920
          paletteRgba: Cell(red),
15921
          paletteHue: Cell(0)
15922
        };
15923
        const memSlider = record(sliderFactory(translate, getClass));
15924
        const memPalette = record(sbPalette.sketch({}));
15925
        const memRgb = record(rgbForm.sketch({}));
15926
        const updatePalette = (anyInSystem, _hex, hue) => {
15927
          memPalette.getOpt(anyInSystem).each(palette => {
15928
            sbPalette.setHue(palette, hue);
15929
          });
15930
        };
15931
        const updateFields = (anyInSystem, hex) => {
15932
          memRgb.getOpt(anyInSystem).each(form => {
15933
            rgbForm.updateHex(form, hex);
15934
          });
15935
        };
15936
        const updateSlider = (anyInSystem, _hex, hue) => {
15937
          memSlider.getOpt(anyInSystem).each(slider => {
15938
            Slider.setValue(slider, hueDegreesToSlider(hue));
15939
          });
15940
        };
15941
        const updatePaletteThumb = (anyInSystem, hex) => {
15942
          memPalette.getOpt(anyInSystem).each(palette => {
15943
            sbPalette.setThumb(palette, hex);
15944
          });
15945
        };
15946
        const updateState = (hex, hue) => {
15947
          const rgba = fromHex(hex);
15948
          state.paletteRgba.set(rgba);
15949
          state.paletteHue.set(hue);
15950
        };
15951
        const runUpdates = (anyInSystem, hex, hue, updates) => {
15952
          updateState(hex, hue);
15953
          each$1(updates, update => {
15954
            update(anyInSystem, hex, hue);
15955
          });
15956
        };
15957
        const onPaletteUpdate = () => {
15958
          const updates = [updateFields];
15959
          return (form, simulatedEvent) => {
15960
            const value = simulatedEvent.event.value;
15961
            const oldHue = state.paletteHue.get();
15962
            const newHsv = hsvColour(oldHue, value.x, 100 - value.y);
15963
            const newHex = hsvToHex(newHsv);
15964
            runUpdates(form, newHex, oldHue, updates);
15965
          };
15966
        };
15967
        const onSliderUpdate = () => {
15968
          const updates = [
15969
            updatePalette,
15970
            updateFields
15971
          ];
15972
          return (form, simulatedEvent) => {
15973
            const hue = hueSliderToDegrees(simulatedEvent.event.value);
15974
            const oldRgb = state.paletteRgba.get();
15975
            const oldHsv = fromRgb(oldRgb);
15976
            const newHsv = hsvColour(hue, oldHsv.saturation, oldHsv.value);
15977
            const newHex = hsvToHex(newHsv);
15978
            runUpdates(form, newHex, hue, updates);
15979
          };
15980
        };
15981
        const onFieldsUpdate = () => {
15982
          const updates = [
15983
            updatePalette,
15984
            updateSlider,
15985
            updatePaletteThumb
15986
          ];
15987
          return (form, simulatedEvent) => {
15988
            const hex = simulatedEvent.event.hex;
15989
            const hsv = hexToHsv(hex);
15990
            runUpdates(form, hex, hsv.hue, updates);
15991
          };
15992
        };
15993
        return {
15994
          uid: detail.uid,
15995
          dom: detail.dom,
15996
          components: [
15997
            memPalette.asSpec(),
15998
            memSlider.asSpec(),
15999
            memRgb.asSpec()
16000
          ],
16001
          behaviours: derive$1([
16002
            config('colour-picker-events', [
16003
              run$1(fieldsUpdate, onFieldsUpdate()),
16004
              run$1(paletteUpdate, onPaletteUpdate()),
16005
              run$1(sliderUpdate, onSliderUpdate())
16006
            ]),
16007
            Composing.config({ find: comp => memRgb.getOpt(comp) }),
16008
            Keying.config({ mode: 'acyclic' })
16009
          ])
16010
        };
16011
      };
16012
      const colourPickerSketcher = single({
16013
        name: 'ColourPicker',
16014
        configFields: [
16015
          required$1('dom'),
16016
          defaulted('onValidHex', noop),
16017
          defaulted('onInvalidHex', noop)
16018
        ],
16019
        factory
16020
      });
16021
      return colourPickerSketcher;
16022
    };
16023
 
16024
    const self = () => Composing.config({ find: Optional.some });
16025
    const memento$1 = mem => Composing.config({ find: mem.getOpt });
16026
    const childAt = index => Composing.config({ find: comp => child$2(comp.element, index).bind(element => comp.getSystem().getByDom(element).toOptional()) });
16027
    const ComposingConfigs = {
16028
      self,
16029
      memento: memento$1,
16030
      childAt
16031
    };
16032
 
16033
    const processors = objOf([
16034
      defaulted('preprocess', identity),
16035
      defaulted('postprocess', identity)
16036
    ]);
16037
    const memento = (mem, rawProcessors) => {
16038
      const ps = asRawOrDie$1('RepresentingConfigs.memento processors', processors, rawProcessors);
16039
      return Representing.config({
16040
        store: {
16041
          mode: 'manual',
16042
          getValue: comp => {
16043
            const other = mem.get(comp);
16044
            const rawValue = Representing.getValue(other);
16045
            return ps.postprocess(rawValue);
16046
          },
16047
          setValue: (comp, rawValue) => {
16048
            const newValue = ps.preprocess(rawValue);
16049
            const other = mem.get(comp);
16050
            Representing.setValue(other, newValue);
16051
          }
16052
        }
16053
      });
16054
    };
16055
    const withComp = (optInitialValue, getter, setter) => Representing.config({
16056
      store: {
16057
        mode: 'manual',
16058
        ...optInitialValue.map(initialValue => ({ initialValue })).getOr({}),
16059
        getValue: getter,
16060
        setValue: setter
16061
      }
16062
    });
16063
    const withElement = (initialValue, getter, setter) => withComp(initialValue, c => getter(c.element), (c, v) => setter(c.element, v));
16064
    const domHtml = optInitialValue => withElement(optInitialValue, get$9, set$6);
16065
    const memory = initialValue => Representing.config({
16066
      store: {
16067
        mode: 'memory',
16068
        initialValue
16069
      }
16070
    });
16071
 
16072
    const english = {
16073
      'colorcustom.rgb.red.label': 'R',
16074
      'colorcustom.rgb.red.description': 'Red component',
16075
      'colorcustom.rgb.green.label': 'G',
16076
      'colorcustom.rgb.green.description': 'Green component',
16077
      'colorcustom.rgb.blue.label': 'B',
16078
      'colorcustom.rgb.blue.description': 'Blue component',
16079
      'colorcustom.rgb.hex.label': '#',
16080
      'colorcustom.rgb.hex.description': 'Hex color code',
16081
      'colorcustom.rgb.range': 'Range 0 to 255',
16082
      'aria.color.picker': 'Color Picker',
16083
      'aria.input.invalid': 'Invalid input'
16084
    };
16085
    const translate$1 = providerBackstage => key => {
16086
      if (isString(key)) {
16087
        return providerBackstage.translate(english[key]);
16088
      } else {
16089
        return providerBackstage.translate(key);
16090
      }
16091
    };
16092
    const renderColorPicker = (_spec, providerBackstage, initialData) => {
16093
      const getClass = key => 'tox-' + key;
16094
      const colourPickerFactory = makeFactory(translate$1(providerBackstage), getClass);
16095
      const onValidHex = form => {
16096
        emitWith(form, formActionEvent, {
16097
          name: 'hex-valid',
16098
          value: true
16099
        });
16100
      };
16101
      const onInvalidHex = form => {
16102
        emitWith(form, formActionEvent, {
16103
          name: 'hex-valid',
16104
          value: false
16105
        });
16106
      };
16107
      const memPicker = record(colourPickerFactory.sketch({
16108
        dom: {
16109
          tag: 'div',
16110
          classes: [getClass('color-picker-container')],
16111
          attributes: { role: 'presentation' }
16112
        },
16113
        onValidHex,
16114
        onInvalidHex
16115
      }));
16116
      return {
16117
        dom: { tag: 'div' },
16118
        components: [memPicker.asSpec()],
16119
        behaviours: derive$1([
16120
          withComp(initialData, comp => {
16121
            const picker = memPicker.get(comp);
16122
            const optRgbForm = Composing.getCurrent(picker);
16123
            const optHex = optRgbForm.bind(rgbForm => {
16124
              const formValues = Representing.getValue(rgbForm);
16125
              return formValues.hex;
16126
            });
16127
            return optHex.map(hex => '#' + removeLeading(hex, '#')).getOr('');
16128
          }, (comp, newValue) => {
16129
            const pattern = /^#([a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?)/;
16130
            const valOpt = Optional.from(pattern.exec(newValue)).bind(matches => get$h(matches, 1));
16131
            const picker = memPicker.get(comp);
16132
            const optRgbForm = Composing.getCurrent(picker);
16133
            optRgbForm.fold(() => {
16134
              console.log('Can not find form');
16135
            }, rgbForm => {
16136
              Representing.setValue(rgbForm, { hex: valOpt.getOr('') });
16137
              Form.getField(rgbForm, 'hex').each(hexField => {
16138
                emit(hexField, input());
16139
              });
16140
            });
16141
          }),
16142
          ComposingConfigs.self()
16143
        ])
16144
      };
16145
    };
16146
 
16147
    var global$2 = tinymce.util.Tools.resolve('tinymce.Resource');
16148
 
16149
    const isOldCustomEditor = spec => has$2(spec, 'init');
16150
    const renderCustomEditor = spec => {
16151
      const editorApi = value$2();
16152
      const memReplaced = record({ dom: { tag: spec.tag } });
16153
      const initialValue = value$2();
16154
      return {
16155
        dom: {
16156
          tag: 'div',
16157
          classes: ['tox-custom-editor']
16158
        },
16159
        behaviours: derive$1([
16160
          config('custom-editor-events', [runOnAttached(component => {
16161
              memReplaced.getOpt(component).each(ta => {
16162
                (isOldCustomEditor(spec) ? spec.init(ta.element.dom) : global$2.load(spec.scriptId, spec.scriptUrl).then(init => init(ta.element.dom, spec.settings))).then(ea => {
16163
                  initialValue.on(cvalue => {
16164
                    ea.setValue(cvalue);
16165
                  });
16166
                  initialValue.clear();
16167
                  editorApi.set(ea);
16168
                });
16169
              });
16170
            })]),
16171
          withComp(Optional.none(), () => editorApi.get().fold(() => initialValue.get().getOr(''), ed => ed.getValue()), (component, value) => {
16172
            editorApi.get().fold(() => initialValue.set(value), ed => ed.setValue(value));
16173
          }),
16174
          ComposingConfigs.self()
16175
        ]),
16176
        components: [memReplaced.asSpec()]
16177
      };
16178
    };
16179
 
16180
    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
16181
 
16182
    const filterByExtension = (files, providersBackstage) => {
16183
      const allowedImageFileTypes = global$1.explode(providersBackstage.getOption('images_file_types'));
16184
      const isFileInAllowedTypes = file => exists(allowedImageFileTypes, type => endsWith(file.name.toLowerCase(), `.${ type.toLowerCase() }`));
16185
      return filter$2(from(files), isFileInAllowedTypes);
16186
    };
16187
    const renderDropZone = (spec, providersBackstage, initialData) => {
16188
      const stopper = (_, se) => {
16189
        se.stop();
16190
      };
16191
      const sequence = actions => (comp, se) => {
16192
        each$1(actions, a => {
16193
          a(comp, se);
16194
        });
16195
      };
16196
      const onDrop = (comp, se) => {
16197
        var _a;
16198
        if (!Disabling.isDisabled(comp)) {
16199
          const transferEvent = se.event.raw;
16200
          handleFiles(comp, (_a = transferEvent.dataTransfer) === null || _a === void 0 ? void 0 : _a.files);
16201
        }
16202
      };
16203
      const onSelect = (component, simulatedEvent) => {
16204
        const input = simulatedEvent.event.raw.target;
16205
        handleFiles(component, input.files);
16206
      };
16207
      const handleFiles = (component, files) => {
16208
        if (files) {
16209
          Representing.setValue(component, filterByExtension(files, providersBackstage));
16210
          emitWith(component, formChangeEvent, { name: spec.name });
16211
        }
16212
      };
16213
      const memInput = record({
16214
        dom: {
16215
          tag: 'input',
16216
          attributes: {
16217
            type: 'file',
16218
            accept: 'image/*'
16219
          },
16220
          styles: { display: 'none' }
16221
        },
16222
        behaviours: derive$1([config('input-file-events', [
16223
            cutter(click()),
16224
            cutter(tap())
16225
          ])])
16226
      });
16227
      const renderField = s => ({
16228
        uid: s.uid,
16229
        dom: {
16230
          tag: 'div',
16231
          classes: ['tox-dropzone-container']
16232
        },
16233
        behaviours: derive$1([
16234
          memory(initialData.getOr([])),
16235
          ComposingConfigs.self(),
16236
          Disabling.config({}),
16237
          Toggling.config({
16238
            toggleClass: 'dragenter',
16239
            toggleOnExecute: false
16240
          }),
16241
          config('dropzone-events', [
16242
            run$1('dragenter', sequence([
16243
              stopper,
16244
              Toggling.toggle
16245
            ])),
16246
            run$1('dragleave', sequence([
16247
              stopper,
16248
              Toggling.toggle
16249
            ])),
16250
            run$1('dragover', stopper),
16251
            run$1('drop', sequence([
16252
              stopper,
16253
              onDrop
16254
            ])),
16255
            run$1(change(), onSelect)
16256
          ])
16257
        ]),
16258
        components: [{
16259
            dom: {
16260
              tag: 'div',
16261
              classes: ['tox-dropzone'],
16262
              styles: {}
16263
            },
16264
            components: [
16265
              {
16266
                dom: { tag: 'p' },
16267
                components: [text$2(providersBackstage.translate('Drop an image here'))]
16268
              },
16269
              Button.sketch({
16270
                dom: {
16271
                  tag: 'button',
16272
                  styles: { position: 'relative' },
16273
                  classes: [
16274
                    'tox-button',
16275
                    'tox-button--secondary'
16276
                  ]
16277
                },
16278
                components: [
16279
                  text$2(providersBackstage.translate('Browse for an image')),
16280
                  memInput.asSpec()
16281
                ],
16282
                action: comp => {
16283
                  const inputComp = memInput.get(comp);
16284
                  inputComp.element.dom.click();
16285
                },
16286
                buttonBehaviours: derive$1([
16287
                  Tabstopping.config({}),
16288
                  DisablingConfigs.button(providersBackstage.isDisabled),
16289
                  receivingConfig()
16290
                ])
16291
              })
16292
            ]
16293
          }]
16294
      });
16295
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
16296
      const pField = FormField.parts.field({ factory: { sketch: renderField } });
16297
      return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
16298
    };
16299
 
16300
    const renderGrid = (spec, backstage) => ({
16301
      dom: {
16302
        tag: 'div',
16303
        classes: [
16304
          'tox-form__grid',
16305
          `tox-form__grid--${ spec.columns }col`
16306
        ]
16307
      },
16308
      components: map$2(spec.items, backstage.interpreter)
16309
    });
16310
 
16311
    const adaptable = (fn, rate) => {
16312
      let timer = null;
16313
      let args = null;
16314
      const cancel = () => {
16315
        if (!isNull(timer)) {
16316
          clearTimeout(timer);
16317
          timer = null;
16318
          args = null;
16319
        }
16320
      };
16321
      const throttle = (...newArgs) => {
16322
        args = newArgs;
16323
        if (isNull(timer)) {
16324
          timer = setTimeout(() => {
16325
            const tempArgs = args;
16326
            timer = null;
16327
            args = null;
16328
            fn.apply(null, tempArgs);
16329
          }, rate);
16330
        }
16331
      };
16332
      return {
16333
        cancel,
16334
        throttle
16335
      };
16336
    };
16337
    const first = (fn, rate) => {
16338
      let timer = null;
16339
      const cancel = () => {
16340
        if (!isNull(timer)) {
16341
          clearTimeout(timer);
16342
          timer = null;
16343
        }
16344
      };
16345
      const throttle = (...args) => {
16346
        if (isNull(timer)) {
16347
          timer = setTimeout(() => {
16348
            timer = null;
16349
            fn.apply(null, args);
16350
          }, rate);
16351
        }
16352
      };
16353
      return {
16354
        cancel,
16355
        throttle
16356
      };
16357
    };
16358
    const last = (fn, rate) => {
16359
      let timer = null;
16360
      const cancel = () => {
16361
        if (!isNull(timer)) {
16362
          clearTimeout(timer);
16363
          timer = null;
16364
        }
16365
      };
16366
      const throttle = (...args) => {
16367
        cancel();
16368
        timer = setTimeout(() => {
16369
          timer = null;
16370
          fn.apply(null, args);
16371
        }, rate);
16372
      };
16373
      return {
16374
        cancel,
16375
        throttle
16376
      };
16377
    };
16378
 
16379
    const beforeObject = generate$6('alloy-fake-before-tabstop');
16380
    const afterObject = generate$6('alloy-fake-after-tabstop');
16381
    const craftWithClasses = classes => {
16382
      return {
16383
        dom: {
16384
          tag: 'div',
16385
          styles: {
16386
            width: '1px',
16387
            height: '1px',
16388
            outline: 'none'
16389
          },
16390
          attributes: { tabindex: '0' },
16391
          classes
16392
        },
16393
        behaviours: derive$1([
16394
          Focusing.config({ ignore: true }),
16395
          Tabstopping.config({})
16396
        ])
16397
      };
16398
    };
16399
    const craft = (containerClasses, spec) => {
16400
      return {
16401
        dom: {
16402
          tag: 'div',
16403
          classes: [
16404
            'tox-navobj',
16405
            ...containerClasses.getOr([])
16406
          ]
16407
        },
16408
        components: [
16409
          craftWithClasses([beforeObject]),
16410
          spec,
16411
          craftWithClasses([afterObject])
16412
        ],
16413
        behaviours: derive$1([ComposingConfigs.childAt(1)])
16414
      };
16415
    };
16416
    const triggerTab = (placeholder, shiftKey) => {
16417
      emitWith(placeholder, keydown(), {
16418
        raw: {
16419
          which: 9,
16420
          shiftKey
16421
        }
16422
      });
16423
    };
16424
    const onFocus = (container, targetComp) => {
16425
      const target = targetComp.element;
16426
      if (has(target, beforeObject)) {
16427
        triggerTab(container, true);
16428
      } else if (has(target, afterObject)) {
16429
        triggerTab(container, false);
16430
      }
16431
    };
16432
    const isPseudoStop = element => {
16433
      return closest(element, [
16434
        '.' + beforeObject,
16435
        '.' + afterObject
16436
      ].join(','), never);
16437
    };
16438
 
16439
    const dialogChannel = generate$6('update-dialog');
16440
    const titleChannel = generate$6('update-title');
16441
    const bodyChannel = generate$6('update-body');
16442
    const footerChannel = generate$6('update-footer');
16443
    const bodySendMessageChannel = generate$6('body-send-message');
16444
    const dialogFocusShiftedChannel = generate$6('dialog-focus-shifted');
16445
 
16446
    const browser = detect$2().browser;
16447
    const isSafari = browser.isSafari();
16448
    const isFirefox = browser.isFirefox();
16449
    const isSafariOrFirefox = isSafari || isFirefox;
16450
    const isChromium = browser.isChromium();
16451
    const isElementScrollAtBottom = ({scrollTop, scrollHeight, clientHeight}) => Math.ceil(scrollTop) + clientHeight >= scrollHeight;
16452
    const scrollToY = (win, y) => win.scrollTo(0, y === 'bottom' ? 99999999 : y);
16453
    const getScrollingElement = (doc, html) => {
16454
      const body = doc.body;
16455
      return Optional.from(!/^<!DOCTYPE (html|HTML)/.test(html) && (!isChromium && !isSafari || isNonNullable(body) && (body.scrollTop !== 0 || Math.abs(body.scrollHeight - body.clientHeight) > 1)) ? body : doc.documentElement);
16456
    };
16457
    const writeValue = (iframeElement, html, fallbackFn) => {
16458
      const iframe = iframeElement.dom;
16459
      Optional.from(iframe.contentDocument).fold(fallbackFn, doc => {
16460
        let lastScrollTop = 0;
16461
        const isScrollAtBottom = getScrollingElement(doc, html).map(el => {
16462
          lastScrollTop = el.scrollTop;
16463
          return el;
16464
        }).forall(isElementScrollAtBottom);
16465
        const scrollAfterWrite = () => {
16466
          const win = iframe.contentWindow;
16467
          if (isNonNullable(win)) {
16468
            if (isScrollAtBottom) {
16469
              scrollToY(win, 'bottom');
16470
            } else if (!isScrollAtBottom && isSafariOrFirefox && lastScrollTop !== 0) {
16471
              scrollToY(win, lastScrollTop);
16472
            }
16473
          }
16474
        };
16475
        if (isSafari) {
16476
          iframe.addEventListener('load', scrollAfterWrite, { once: true });
16477
        }
16478
        doc.open();
16479
        doc.write(html);
16480
        doc.close();
16481
        if (!isSafari) {
16482
          scrollAfterWrite();
16483
        }
16484
      });
16485
    };
16486
    const throttleInterval = someIf(isSafariOrFirefox, isSafari ? 500 : 200);
16487
    const writeValueThrottler = throttleInterval.map(interval => adaptable(writeValue, interval));
16488
    const getDynamicSource = (initialData, stream) => {
16489
      const cachedValue = Cell(initialData.getOr(''));
16490
      return {
16491
        getValue: _frameComponent => cachedValue.get(),
16492
        setValue: (frameComponent, html) => {
16493
          if (cachedValue.get() !== html) {
16494
            const iframeElement = frameComponent.element;
16495
            const setSrcdocValue = () => set$9(iframeElement, 'srcdoc', html);
16496
            if (stream) {
16497
              writeValueThrottler.fold(constant$1(writeValue), throttler => throttler.throttle)(iframeElement, html, setSrcdocValue);
16498
            } else {
16499
              setSrcdocValue();
16500
            }
16501
          }
16502
          cachedValue.set(html);
16503
        }
16504
      };
16505
    };
16506
    const renderIFrame = (spec, providersBackstage, initialData) => {
16507
      const baseClass = 'tox-dialog__iframe';
16508
      const opaqueClass = spec.transparent ? [] : [`${ baseClass }--opaque`];
16509
      const containerBorderedClass = spec.border ? [`tox-navobj-bordered`] : [];
16510
      const attributes = {
16511
        ...spec.label.map(title => ({ title })).getOr({}),
16512
        ...initialData.map(html => ({ srcdoc: html })).getOr({}),
16513
        ...spec.sandboxed ? { sandbox: 'allow-scripts allow-same-origin' } : {}
16514
      };
16515
      const sourcing = getDynamicSource(initialData, spec.streamContent);
16516
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
16517
      const factory = newSpec => craft(Optional.from(containerBorderedClass), {
16518
        uid: newSpec.uid,
16519
        dom: {
16520
          tag: 'iframe',
16521
          attributes,
16522
          classes: [
16523
            baseClass,
16524
            ...opaqueClass
16525
          ]
16526
        },
16527
        behaviours: derive$1([
16528
          Tabstopping.config({}),
16529
          Focusing.config({}),
16530
          withComp(initialData, sourcing.getValue, sourcing.setValue),
16531
          Receiving.config({
16532
            channels: {
16533
              [dialogFocusShiftedChannel]: {
16534
                onReceive: (comp, message) => {
16535
                  message.newFocus.each(newFocus => {
16536
                    parentElement(comp.element).each(parent => {
16537
                      const f = eq(comp.element, newFocus) ? add$2 : remove$2;
16538
                      f(parent, 'tox-navobj-bordered-focus');
16539
                    });
16540
                  });
16541
                }
16542
              }
16543
            }
16544
          })
16545
        ])
16546
      });
16547
      const pField = FormField.parts.field({ factory: { sketch: factory } });
16548
      return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
16549
    };
16550
 
16551
    const image = image => new Promise((resolve, reject) => {
16552
      const loaded = () => {
16553
        destroy();
16554
        resolve(image);
16555
      };
16556
      const listeners = [
16557
        bind(image, 'load', loaded),
16558
        bind(image, 'error', () => {
16559
          destroy();
16560
          reject('Unable to load data from image: ' + image.dom.src);
16561
        })
16562
      ];
16563
      const destroy = () => each$1(listeners, l => l.unbind());
16564
      if (image.dom.complete) {
16565
        loaded();
16566
      }
16567
    });
16568
 
16569
    const calculateImagePosition = (panelWidth, panelHeight, imageWidth, imageHeight, zoom) => {
16570
      const width = imageWidth * zoom;
16571
      const height = imageHeight * zoom;
16572
      const left = Math.max(0, panelWidth / 2 - width / 2);
16573
      const top = Math.max(0, panelHeight / 2 - height / 2);
16574
      return {
16575
        left: left.toString() + 'px',
16576
        top: top.toString() + 'px',
16577
        width: width.toString() + 'px',
16578
        height: height.toString() + 'px'
16579
      };
16580
    };
16581
    const zoomToFit = (panel, width, height) => {
16582
      const panelW = get$c(panel);
16583
      const panelH = get$d(panel);
16584
      return Math.min(panelW / width, panelH / height, 1);
16585
    };
16586
    const renderImagePreview = (spec, initialData) => {
16587
      const cachedData = Cell(initialData.getOr({ url: '' }));
16588
      const memImage = record({
16589
        dom: {
16590
          tag: 'img',
16591
          classes: ['tox-imagepreview__image'],
16592
          attributes: initialData.map(data => ({ src: data.url })).getOr({})
16593
        }
16594
      });
16595
      const memContainer = record({
16596
        dom: {
16597
          tag: 'div',
16598
          classes: ['tox-imagepreview__container'],
16599
          attributes: { role: 'presentation' }
16600
        },
16601
        components: [memImage.asSpec()]
16602
      });
16603
      const setValue = (frameComponent, data) => {
16604
        const translatedData = { url: data.url };
16605
        data.zoom.each(z => translatedData.zoom = z);
16606
        data.cachedWidth.each(z => translatedData.cachedWidth = z);
16607
        data.cachedHeight.each(z => translatedData.cachedHeight = z);
16608
        cachedData.set(translatedData);
16609
        const applyFramePositioning = () => {
16610
          const {cachedWidth, cachedHeight, zoom} = translatedData;
16611
          if (!isUndefined(cachedWidth) && !isUndefined(cachedHeight)) {
16612
            if (isUndefined(zoom)) {
16613
              const z = zoomToFit(frameComponent.element, cachedWidth, cachedHeight);
16614
              translatedData.zoom = z;
16615
            }
16616
            const position = calculateImagePosition(get$c(frameComponent.element), get$d(frameComponent.element), cachedWidth, cachedHeight, translatedData.zoom);
16617
            memContainer.getOpt(frameComponent).each(container => {
16618
              setAll(container.element, position);
16619
            });
16620
          }
16621
        };
16622
        memImage.getOpt(frameComponent).each(imageComponent => {
16623
          const img = imageComponent.element;
16624
          if (data.url !== get$f(img, 'src')) {
16625
            set$9(img, 'src', data.url);
16626
            remove$2(frameComponent.element, 'tox-imagepreview__loaded');
16627
          }
16628
          applyFramePositioning();
16629
          image(img).then(img => {
16630
            if (frameComponent.getSystem().isConnected()) {
16631
              add$2(frameComponent.element, 'tox-imagepreview__loaded');
16632
              translatedData.cachedWidth = img.dom.naturalWidth;
16633
              translatedData.cachedHeight = img.dom.naturalHeight;
16634
              applyFramePositioning();
16635
            }
16636
          });
16637
        });
16638
      };
16639
      const styles = {};
16640
      spec.height.each(h => styles.height = h);
16641
      const fakeValidatedData = initialData.map(d => ({
16642
        url: d.url,
16643
        zoom: Optional.from(d.zoom),
16644
        cachedWidth: Optional.from(d.cachedWidth),
16645
        cachedHeight: Optional.from(d.cachedHeight)
16646
      }));
16647
      return {
16648
        dom: {
16649
          tag: 'div',
16650
          classes: ['tox-imagepreview'],
16651
          styles,
16652
          attributes: { role: 'presentation' }
16653
        },
16654
        components: [memContainer.asSpec()],
16655
        behaviours: derive$1([
16656
          ComposingConfigs.self(),
16657
          withComp(fakeValidatedData, () => cachedData.get(), setValue)
16658
        ])
16659
      };
16660
    };
16661
 
16662
    const renderLabel$2 = (spec, backstageShared) => {
16663
      const baseClass = 'tox-label';
16664
      const centerClass = spec.align === 'center' ? [`${ baseClass }--center`] : [];
16665
      const endClass = spec.align === 'end' ? [`${ baseClass }--end`] : [];
16666
      const label = {
16667
        dom: {
16668
          tag: 'label',
16669
          classes: [
16670
            baseClass,
16671
            ...centerClass,
16672
            ...endClass
16673
          ]
16674
        },
16675
        components: [text$2(backstageShared.providers.translate(spec.label))]
16676
      };
16677
      const comps = map$2(spec.items, backstageShared.interpreter);
16678
      return {
16679
        dom: {
16680
          tag: 'div',
16681
          classes: ['tox-form__group']
16682
        },
16683
        components: [
16684
          label,
16685
          ...comps
16686
        ],
16687
        behaviours: derive$1([
16688
          ComposingConfigs.self(),
16689
          Replacing.config({}),
16690
          domHtml(Optional.none()),
16691
          Keying.config({ mode: 'acyclic' })
16692
        ])
16693
      };
16694
    };
16695
 
16696
    const internalToolbarButtonExecute = generate$6('toolbar.button.execute');
16697
    const onToolbarButtonExecute = info => runOnExecute$1((comp, _simulatedEvent) => {
16698
      runWithApi(info, comp)(itemApi => {
16699
        emitWith(comp, internalToolbarButtonExecute, { buttonApi: itemApi });
16700
        info.onAction(itemApi);
16701
      });
16702
    });
16703
    const commonButtonDisplayEvent = generate$6('common-button-display-events');
16704
    const toolbarButtonEventOrder = {
16705
      [execute$5()]: [
16706
        'disabling',
16707
        'alloy.base.behaviour',
16708
        'toggling',
16709
        'toolbar-button-events'
16710
      ],
16711
      [attachedToDom()]: [
16712
        'toolbar-button-events',
16713
        commonButtonDisplayEvent
16714
      ],
16715
      [mousedown()]: [
16716
        'focusing',
16717
        'alloy.base.behaviour',
16718
        commonButtonDisplayEvent
16719
      ]
16720
    };
16721
 
16722
    const forceInitialSize = comp => set$8(comp.element, 'width', get$e(comp.element, 'width'));
16723
 
16724
    const renderIcon$1 = (iconName, iconsProvider, behaviours) => render$3(iconName, {
16725
      tag: 'span',
16726
      classes: [
16727
        'tox-icon',
16728
        'tox-tbtn__icon-wrap'
16729
      ],
16730
      behaviours
16731
    }, iconsProvider);
16732
    const renderIconFromPack$1 = (iconName, iconsProvider) => renderIcon$1(iconName, iconsProvider, []);
16733
    const renderReplaceableIconFromPack = (iconName, iconsProvider) => renderIcon$1(iconName, iconsProvider, [Replacing.config({})]);
16734
    const renderLabel$1 = (text, prefix, providersBackstage) => ({
16735
      dom: {
16736
        tag: 'span',
16737
        classes: [`${ prefix }__select-label`]
16738
      },
16739
      components: [text$2(providersBackstage.translate(text))],
16740
      behaviours: derive$1([Replacing.config({})])
16741
    });
16742
 
16743
    const updateMenuText = generate$6('update-menu-text');
16744
    const updateMenuIcon = generate$6('update-menu-icon');
16745
    const renderCommonDropdown = (spec, prefix, sharedBackstage) => {
16746
      const editorOffCell = Cell(noop);
16747
      const optMemDisplayText = spec.text.map(text => record(renderLabel$1(text, prefix, sharedBackstage.providers)));
16748
      const optMemDisplayIcon = spec.icon.map(iconName => record(renderReplaceableIconFromPack(iconName, sharedBackstage.providers.icons)));
16749
      const onLeftOrRightInMenu = (comp, se) => {
16750
        const dropdown = Representing.getValue(comp);
16751
        Focusing.focus(dropdown);
16752
        emitWith(dropdown, 'keydown', { raw: se.event.raw });
16753
        Dropdown.close(dropdown);
16754
        return Optional.some(true);
16755
      };
16756
      const role = spec.role.fold(() => ({}), role => ({ role }));
16757
      const tooltipAttributes = spec.tooltip.fold(() => ({}), tooltip => {
16758
        const translatedTooltip = sharedBackstage.providers.translate(tooltip);
16759
        return {
16760
          'title': translatedTooltip,
16761
          'aria-label': translatedTooltip
16762
        };
16763
      });
16764
      const iconSpec = render$3('chevron-down', {
16765
        tag: 'div',
16766
        classes: [`${ prefix }__select-chevron`]
16767
      }, sharedBackstage.providers.icons);
16768
      const fixWidthBehaviourName = generate$6('common-button-display-events');
16769
      const memDropdown = record(Dropdown.sketch({
16770
        ...spec.uid ? { uid: spec.uid } : {},
16771
        ...role,
16772
        dom: {
16773
          tag: 'button',
16774
          classes: [
16775
            prefix,
16776
            `${ prefix }--select`
16777
          ].concat(map$2(spec.classes, c => `${ prefix }--${ c }`)),
16778
          attributes: { ...tooltipAttributes }
16779
        },
16780
        components: componentRenderPipeline([
16781
          optMemDisplayIcon.map(mem => mem.asSpec()),
16782
          optMemDisplayText.map(mem => mem.asSpec()),
16783
          Optional.some(iconSpec)
16784
        ]),
16785
        matchWidth: true,
16786
        useMinWidth: true,
16787
        onOpen: (anchor, dropdownComp, tmenuComp) => {
16788
          if (spec.searchable) {
16789
            focusSearchField(tmenuComp);
16790
          }
16791
        },
16792
        dropdownBehaviours: derive$1([
16793
          ...spec.dropdownBehaviours,
16794
          DisablingConfigs.button(() => spec.disabled || sharedBackstage.providers.isDisabled()),
16795
          receivingConfig(),
16796
          Unselecting.config({}),
16797
          Replacing.config({}),
16798
          config('dropdown-events', [
16799
            onControlAttached(spec, editorOffCell),
16800
            onControlDetached(spec, editorOffCell)
16801
          ]),
16802
          config(fixWidthBehaviourName, [runOnAttached((comp, _se) => forceInitialSize(comp))]),
16803
          config('menubutton-update-display-text', [
16804
            run$1(updateMenuText, (comp, se) => {
16805
              optMemDisplayText.bind(mem => mem.getOpt(comp)).each(displayText => {
16806
                Replacing.set(displayText, [text$2(sharedBackstage.providers.translate(se.event.text))]);
16807
              });
16808
            }),
16809
            run$1(updateMenuIcon, (comp, se) => {
16810
              optMemDisplayIcon.bind(mem => mem.getOpt(comp)).each(displayIcon => {
16811
                Replacing.set(displayIcon, [renderReplaceableIconFromPack(se.event.icon, sharedBackstage.providers.icons)]);
16812
              });
16813
            })
16814
          ])
16815
        ]),
16816
        eventOrder: deepMerge(toolbarButtonEventOrder, {
16817
          mousedown: [
16818
            'focusing',
16819
            'alloy.base.behaviour',
16820
            'item-type-events',
16821
            'normal-dropdown-events'
16822
          ],
16823
          [attachedToDom()]: [
16824
            'toolbar-button-events',
16825
            'dropdown-events',
16826
            fixWidthBehaviourName
16827
          ]
16828
        }),
16829
        sandboxBehaviours: derive$1([
16830
          Keying.config({
16831
            mode: 'special',
16832
            onLeft: onLeftOrRightInMenu,
16833
            onRight: onLeftOrRightInMenu
16834
          }),
16835
          config('dropdown-sandbox-events', [
16836
            run$1(refetchTriggerEvent, (originalSandboxComp, se) => {
16837
              handleRefetchTrigger(originalSandboxComp);
16838
              se.stop();
16839
            }),
16840
            run$1(redirectMenuItemInteractionEvent, (sandboxComp, se) => {
16841
              handleRedirectToMenuItem(sandboxComp, se);
16842
              se.stop();
16843
            })
16844
          ])
16845
        ]),
16846
        lazySink: sharedBackstage.getSink,
16847
        toggleClass: `${ prefix }--active`,
16848
        parts: {
16849
          menu: {
16850
            ...part(false, spec.columns, spec.presets),
16851
            fakeFocus: spec.searchable,
16852
            onHighlightItem: updateAriaOnHighlight,
16853
            onCollapseMenu: (tmenuComp, itemCompCausingCollapse, nowActiveMenuComp) => {
16854
              Highlighting.getHighlighted(nowActiveMenuComp).each(itemComp => {
16855
                updateAriaOnHighlight(tmenuComp, nowActiveMenuComp, itemComp);
16856
              });
16857
            },
16858
            onDehighlightItem: updateAriaOnDehighlight
16859
          }
16860
        },
16861
        getAnchorOverrides: () => {
16862
          return {
16863
            maxHeightFunction: (element, available) => {
16864
              anchored()(element, available - 10);
16865
            }
16866
          };
16867
        },
16868
        fetch: comp => Future.nu(curry(spec.fetch, comp))
16869
      }));
16870
      return memDropdown.asSpec();
16871
    };
16872
 
16873
    const isMenuItemReference = item => isString(item);
16874
    const isSeparator$2 = item => item.type === 'separator';
16875
    const isExpandingMenuItem = item => has$2(item, 'getSubmenuItems');
16876
    const separator$2 = { type: 'separator' };
16877
    const unwrapReferences = (items, menuItems) => {
16878
      const realItems = foldl(items, (acc, item) => {
16879
        if (isMenuItemReference(item)) {
16880
          if (item === '') {
16881
            return acc;
16882
          } else if (item === '|') {
16883
            return acc.length > 0 && !isSeparator$2(acc[acc.length - 1]) ? acc.concat([separator$2]) : acc;
16884
          } else if (has$2(menuItems, item.toLowerCase())) {
16885
            return acc.concat([menuItems[item.toLowerCase()]]);
16886
          } else {
16887
            return acc;
16888
          }
16889
        } else {
16890
          return acc.concat([item]);
16891
        }
16892
      }, []);
16893
      if (realItems.length > 0 && isSeparator$2(realItems[realItems.length - 1])) {
16894
        realItems.pop();
16895
      }
16896
      return realItems;
16897
    };
16898
    const getFromExpandingItem = (item, menuItems) => {
16899
      const submenuItems = item.getSubmenuItems();
16900
      const rest = expand(submenuItems, menuItems);
16901
      const newMenus = deepMerge(rest.menus, { [item.value]: rest.items });
16902
      const newExpansions = deepMerge(rest.expansions, { [item.value]: item.value });
16903
      return {
16904
        item,
16905
        menus: newMenus,
16906
        expansions: newExpansions
16907
      };
16908
    };
16909
    const generateValueIfRequired = item => {
16910
      const itemValue = get$g(item, 'value').getOrThunk(() => generate$6('generated-menu-item'));
16911
      return deepMerge({ value: itemValue }, item);
16912
    };
16913
    const expand = (items, menuItems) => {
16914
      const realItems = unwrapReferences(isString(items) ? items.split(' ') : items, menuItems);
16915
      return foldr(realItems, (acc, item) => {
16916
        if (isExpandingMenuItem(item)) {
16917
          const itemWithValue = generateValueIfRequired(item);
16918
          const newData = getFromExpandingItem(itemWithValue, menuItems);
16919
          return {
16920
            menus: deepMerge(acc.menus, newData.menus),
16921
            items: [
16922
              newData.item,
16923
              ...acc.items
16924
            ],
16925
            expansions: deepMerge(acc.expansions, newData.expansions)
16926
          };
16927
        } else {
16928
          return {
16929
            ...acc,
16930
            items: [
16931
              item,
16932
              ...acc.items
16933
            ]
16934
          };
16935
        }
16936
      }, {
16937
        menus: {},
16938
        expansions: {},
16939
        items: []
16940
      });
16941
    };
16942
 
16943
    const getSearchModeForField = settings => {
16944
      return settings.search.fold(() => ({ searchMode: 'no-search' }), searchSettings => ({
16945
        searchMode: 'search-with-field',
16946
        placeholder: searchSettings.placeholder
16947
      }));
16948
    };
16949
    const getSearchModeForResults = settings => {
16950
      return settings.search.fold(() => ({ searchMode: 'no-search' }), _ => ({ searchMode: 'search-with-results' }));
16951
    };
16952
    const build = (items, itemResponse, backstage, settings) => {
16953
      const primary = generate$6('primary-menu');
16954
      const data = expand(items, backstage.shared.providers.menuItems());
16955
      if (data.items.length === 0) {
16956
        return Optional.none();
16957
      }
16958
      const mainMenuSearchMode = getSearchModeForField(settings);
16959
      const mainMenu = createPartialMenu(primary, data.items, itemResponse, backstage, settings.isHorizontalMenu, mainMenuSearchMode);
16960
      const submenuSearchMode = getSearchModeForResults(settings);
16961
      const submenus = map$1(data.menus, (menuItems, menuName) => createPartialMenu(menuName, menuItems, itemResponse, backstage, false, submenuSearchMode));
16962
      const menus = deepMerge(submenus, wrap$1(primary, mainMenu));
16963
      return Optional.from(tieredMenu.tieredData(primary, menus, data.expansions));
16964
    };
16965
 
16966
    const isSingleListItem = item => !has$2(item, 'items');
16967
    const dataAttribute = 'data-value';
16968
    const fetchItems = (dropdownComp, name, items, selectedValue) => map$2(items, item => {
16969
      if (!isSingleListItem(item)) {
16970
        return {
16971
          type: 'nestedmenuitem',
16972
          text: item.text,
16973
          getSubmenuItems: () => fetchItems(dropdownComp, name, item.items, selectedValue)
16974
        };
16975
      } else {
16976
        return {
16977
          type: 'togglemenuitem',
16978
          text: item.text,
16979
          value: item.value,
16980
          active: item.value === selectedValue,
16981
          onAction: () => {
16982
            Representing.setValue(dropdownComp, item.value);
16983
            emitWith(dropdownComp, formChangeEvent, { name });
16984
            Focusing.focus(dropdownComp);
16985
          }
16986
        };
16987
      }
16988
    });
16989
    const findItemByValue = (items, value) => findMap(items, item => {
16990
      if (!isSingleListItem(item)) {
16991
        return findItemByValue(item.items, value);
16992
      } else {
16993
        return someIf(item.value === value, item);
16994
      }
16995
    });
16996
    const renderListBox = (spec, backstage, initialData) => {
16997
      const providersBackstage = backstage.shared.providers;
16998
      const initialItem = initialData.bind(value => findItemByValue(spec.items, value)).orThunk(() => head(spec.items).filter(isSingleListItem));
16999
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
17000
      const pField = FormField.parts.field({
17001
        dom: {},
17002
        factory: {
17003
          sketch: sketchSpec => renderCommonDropdown({
17004
            uid: sketchSpec.uid,
17005
            text: initialItem.map(item => item.text),
17006
            icon: Optional.none(),
17007
            tooltip: spec.label,
17008
            role: Optional.none(),
17009
            fetch: (comp, callback) => {
17010
              const items = fetchItems(comp, spec.name, spec.items, Representing.getValue(comp));
17011
              callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
17012
                isHorizontalMenu: false,
17013
                search: Optional.none()
17014
              }));
17015
            },
17016
            onSetup: constant$1(noop),
17017
            getApi: constant$1({}),
17018
            columns: 1,
17019
            presets: 'normal',
17020
            classes: [],
17021
            dropdownBehaviours: [
17022
              Tabstopping.config({}),
17023
              withComp(initialItem.map(item => item.value), comp => get$f(comp.element, dataAttribute), (comp, data) => {
17024
                findItemByValue(spec.items, data).each(item => {
17025
                  set$9(comp.element, dataAttribute, item.value);
17026
                  emitWith(comp, updateMenuText, { text: item.text });
17027
                });
17028
              })
17029
            ]
17030
          }, 'tox-listbox', backstage.shared)
17031
        }
17032
      });
17033
      const listBoxWrap = {
17034
        dom: {
17035
          tag: 'div',
17036
          classes: ['tox-listboxfield']
17037
        },
17038
        components: [pField]
17039
      };
17040
      return FormField.sketch({
17041
        dom: {
17042
          tag: 'div',
17043
          classes: ['tox-form__group']
17044
        },
17045
        components: flatten([
17046
          pLabel.toArray(),
17047
          [listBoxWrap]
17048
        ]),
17049
        fieldBehaviours: derive$1([Disabling.config({
17050
            disabled: constant$1(!spec.enabled),
17051
            onDisabled: comp => {
17052
              FormField.getField(comp).each(Disabling.disable);
17053
            },
17054
            onEnabled: comp => {
17055
              FormField.getField(comp).each(Disabling.enable);
17056
            }
17057
          })])
17058
      });
17059
    };
17060
 
17061
    const renderPanel = (spec, backstage) => ({
17062
      dom: {
17063
        tag: 'div',
17064
        classes: spec.classes
17065
      },
17066
      components: map$2(spec.items, backstage.shared.interpreter)
17067
    });
17068
 
17069
    const factory$h = (detail, _spec) => {
17070
      const options = map$2(detail.options, option => ({
17071
        dom: {
17072
          tag: 'option',
17073
          value: option.value,
17074
          innerHtml: option.text
17075
        }
17076
      }));
17077
      const initialValues = detail.data.map(v => wrap$1('initialValue', v)).getOr({});
17078
      return {
17079
        uid: detail.uid,
17080
        dom: {
17081
          tag: 'select',
17082
          classes: detail.selectClasses,
17083
          attributes: detail.selectAttributes
17084
        },
17085
        components: options,
17086
        behaviours: augment(detail.selectBehaviours, [
17087
          Focusing.config({}),
17088
          Representing.config({
17089
            store: {
17090
              mode: 'manual',
17091
              getValue: select => {
17092
                return get$6(select.element);
17093
              },
17094
              setValue: (select, newValue) => {
17095
                const firstOption = head(detail.options);
17096
                const found = find$5(detail.options, opt => opt.value === newValue);
17097
                if (found.isSome()) {
17098
                  set$5(select.element, newValue);
17099
                } else if (select.element.dom.selectedIndex === -1 && newValue === '') {
17100
                  firstOption.each(value => set$5(select.element, value.value));
17101
                }
17102
              },
17103
              ...initialValues
17104
            }
17105
          })
17106
        ])
17107
      };
17108
    };
17109
    const HtmlSelect = single({
17110
      name: 'HtmlSelect',
17111
      configFields: [
17112
        required$1('options'),
17113
        field('selectBehaviours', [
17114
          Focusing,
17115
          Representing
17116
        ]),
17117
        defaulted('selectClasses', []),
17118
        defaulted('selectAttributes', {}),
17119
        option$3('data')
17120
      ],
17121
      factory: factory$h
17122
    });
17123
 
17124
    const renderSelectBox = (spec, providersBackstage, initialData) => {
17125
      const translatedOptions = map$2(spec.items, item => ({
17126
        text: providersBackstage.translate(item.text),
17127
        value: item.value
17128
      }));
17129
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
17130
      const pField = FormField.parts.field({
17131
        dom: {},
17132
        ...initialData.map(data => ({ data })).getOr({}),
17133
        selectAttributes: { size: spec.size },
17134
        options: translatedOptions,
17135
        factory: HtmlSelect,
17136
        selectBehaviours: derive$1([
17137
          Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
17138
          Tabstopping.config({}),
17139
          config('selectbox-change', [run$1(change(), (component, _) => {
17140
              emitWith(component, formChangeEvent, { name: spec.name });
17141
            })])
17142
        ])
17143
      });
17144
      const chevron = spec.size > 1 ? Optional.none() : Optional.some(render$3('chevron-down', {
17145
        tag: 'div',
17146
        classes: ['tox-selectfield__icon-js']
17147
      }, providersBackstage.icons));
17148
      const selectWrap = {
17149
        dom: {
17150
          tag: 'div',
17151
          classes: ['tox-selectfield']
17152
        },
17153
        components: flatten([
17154
          [pField],
17155
          chevron.toArray()
17156
        ])
17157
      };
17158
      return FormField.sketch({
17159
        dom: {
17160
          tag: 'div',
17161
          classes: ['tox-form__group']
17162
        },
17163
        components: flatten([
17164
          pLabel.toArray(),
17165
          [selectWrap]
17166
        ]),
17167
        fieldBehaviours: derive$1([
17168
          Disabling.config({
17169
            disabled: () => !spec.enabled || providersBackstage.isDisabled(),
17170
            onDisabled: comp => {
17171
              FormField.getField(comp).each(Disabling.disable);
17172
            },
17173
            onEnabled: comp => {
17174
              FormField.getField(comp).each(Disabling.enable);
17175
            }
17176
          }),
17177
          receivingConfig()
17178
        ])
17179
      });
17180
    };
17181
 
17182
    const schema$h = constant$1([
17183
      defaulted('field1Name', 'field1'),
17184
      defaulted('field2Name', 'field2'),
17185
      onStrictHandler('onLockedChange'),
17186
      markers$1(['lockClass']),
17187
      defaulted('locked', false),
17188
      SketchBehaviours.field('coupledFieldBehaviours', [
17189
        Composing,
17190
        Representing
17191
      ])
17192
    ]);
17193
    const getField = (comp, detail, partName) => getPart(comp, detail, partName).bind(Composing.getCurrent);
17194
    const coupledPart = (selfName, otherName) => required({
17195
      factory: FormField,
17196
      name: selfName,
17197
      overrides: detail => {
17198
        return {
17199
          fieldBehaviours: derive$1([config('coupled-input-behaviour', [run$1(input(), me => {
17200
                getField(me, detail, otherName).each(other => {
17201
                  getPart(me, detail, 'lock').each(lock => {
17202
                    if (Toggling.isOn(lock)) {
17203
                      detail.onLockedChange(me, other, lock);
17204
                    }
17205
                  });
17206
                });
17207
              })])])
17208
        };
17209
      }
17210
    });
17211
    const parts$c = constant$1([
17212
      coupledPart('field1', 'field2'),
17213
      coupledPart('field2', 'field1'),
17214
      required({
17215
        factory: Button,
17216
        schema: [required$1('dom')],
17217
        name: 'lock',
17218
        overrides: detail => {
17219
          return {
17220
            buttonBehaviours: derive$1([Toggling.config({
17221
                selected: detail.locked,
17222
                toggleClass: detail.markers.lockClass,
17223
                aria: { mode: 'pressed' }
17224
              })])
17225
          };
17226
        }
17227
      })
17228
    ]);
17229
 
17230
    const factory$g = (detail, components, _spec, _externals) => ({
17231
      uid: detail.uid,
17232
      dom: detail.dom,
17233
      components,
17234
      behaviours: SketchBehaviours.augment(detail.coupledFieldBehaviours, [
17235
        Composing.config({ find: Optional.some }),
17236
        Representing.config({
17237
          store: {
17238
            mode: 'manual',
17239
            getValue: comp => {
17240
              const parts = getPartsOrDie(comp, detail, [
17241
                'field1',
17242
                'field2'
17243
              ]);
17244
              return {
17245
                [detail.field1Name]: Representing.getValue(parts.field1()),
17246
                [detail.field2Name]: Representing.getValue(parts.field2())
17247
              };
17248
            },
17249
            setValue: (comp, value) => {
17250
              const parts = getPartsOrDie(comp, detail, [
17251
                'field1',
17252
                'field2'
17253
              ]);
17254
              if (hasNonNullableKey(value, detail.field1Name)) {
17255
                Representing.setValue(parts.field1(), value[detail.field1Name]);
17256
              }
17257
              if (hasNonNullableKey(value, detail.field2Name)) {
17258
                Representing.setValue(parts.field2(), value[detail.field2Name]);
17259
              }
17260
            }
17261
          }
17262
        })
17263
      ]),
17264
      apis: {
17265
        getField1: component => getPart(component, detail, 'field1'),
17266
        getField2: component => getPart(component, detail, 'field2'),
17267
        getLock: component => getPart(component, detail, 'lock')
17268
      }
17269
    });
17270
    const FormCoupledInputs = composite({
17271
      name: 'FormCoupledInputs',
17272
      configFields: schema$h(),
17273
      partFields: parts$c(),
17274
      factory: factory$g,
17275
      apis: {
17276
        getField1: (apis, component) => apis.getField1(component),
17277
        getField2: (apis, component) => apis.getField2(component),
17278
        getLock: (apis, component) => apis.getLock(component)
17279
      }
17280
    });
17281
 
17282
    const formatSize = size => {
17283
      const unitDec = {
17284
        '': 0,
17285
        'px': 0,
17286
        'pt': 1,
17287
        'mm': 1,
17288
        'pc': 2,
17289
        'ex': 2,
17290
        'em': 2,
17291
        'ch': 2,
17292
        'rem': 2,
17293
        'cm': 3,
17294
        'in': 4,
17295
        '%': 4
17296
      };
17297
      const maxDecimal = unit => unit in unitDec ? unitDec[unit] : 1;
17298
      let numText = size.value.toFixed(maxDecimal(size.unit));
17299
      if (numText.indexOf('.') !== -1) {
17300
        numText = numText.replace(/\.?0*$/, '');
17301
      }
17302
      return numText + size.unit;
17303
    };
17304
    const parseSize = sizeText => {
17305
      const numPattern = /^\s*(\d+(?:\.\d+)?)\s*(|cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|%)\s*$/;
17306
      const match = numPattern.exec(sizeText);
17307
      if (match !== null) {
17308
        const value = parseFloat(match[1]);
17309
        const unit = match[2];
17310
        return Result.value({
17311
          value,
17312
          unit
17313
        });
17314
      } else {
17315
        return Result.error(sizeText);
17316
      }
17317
    };
17318
    const convertUnit = (size, unit) => {
17319
      const inInch = {
17320
        '': 96,
17321
        'px': 96,
17322
        'pt': 72,
17323
        'cm': 2.54,
17324
        'pc': 12,
17325
        'mm': 25.4,
17326
        'in': 1
17327
      };
17328
      const supported = u => has$2(inInch, u);
17329
      if (size.unit === unit) {
17330
        return Optional.some(size.value);
17331
      } else if (supported(size.unit) && supported(unit)) {
17332
        if (inInch[size.unit] === inInch[unit]) {
17333
          return Optional.some(size.value);
17334
        } else {
17335
          return Optional.some(size.value / inInch[size.unit] * inInch[unit]);
17336
        }
17337
      } else {
17338
        return Optional.none();
17339
      }
17340
    };
17341
    const noSizeConversion = _input => Optional.none();
17342
    const ratioSizeConversion = (scale, unit) => size => convertUnit(size, unit).map(value => ({
17343
      value: value * scale,
17344
      unit
17345
    }));
17346
    const makeRatioConverter = (currentFieldText, otherFieldText) => {
17347
      const cValue = parseSize(currentFieldText).toOptional();
17348
      const oValue = parseSize(otherFieldText).toOptional();
17349
      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);
17350
    };
17351
 
17352
    const renderSizeInput = (spec, providersBackstage) => {
17353
      let converter = noSizeConversion;
17354
      const ratioEvent = generate$6('ratio-event');
17355
      const makeIcon = iconName => render$3(iconName, {
17356
        tag: 'span',
17357
        classes: [
17358
          'tox-icon',
17359
          'tox-lock-icon__' + iconName
17360
        ]
17361
      }, providersBackstage.icons);
17362
      const pLock = FormCoupledInputs.parts.lock({
17363
        dom: {
17364
          tag: 'button',
17365
          classes: [
17366
            'tox-lock',
17367
            'tox-button',
17368
            'tox-button--naked',
17369
            'tox-button--icon'
17370
          ],
17371
          attributes: { title: providersBackstage.translate(spec.label.getOr('Constrain proportions')) }
17372
        },
17373
        components: [
17374
          makeIcon('lock'),
17375
          makeIcon('unlock')
17376
        ],
17377
        buttonBehaviours: derive$1([
17378
          Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
17379
          receivingConfig(),
17380
          Tabstopping.config({})
17381
        ])
17382
      });
17383
      const formGroup = components => ({
17384
        dom: {
17385
          tag: 'div',
17386
          classes: ['tox-form__group']
17387
        },
17388
        components
17389
      });
17390
      const getFieldPart = isField1 => FormField.parts.field({
17391
        factory: Input,
17392
        inputClasses: ['tox-textfield'],
17393
        inputBehaviours: derive$1([
17394
          Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
17395
          receivingConfig(),
17396
          Tabstopping.config({}),
17397
          config('size-input-events', [
17398
            run$1(focusin(), (component, _simulatedEvent) => {
17399
              emitWith(component, ratioEvent, { isField1 });
17400
            }),
17401
            run$1(change(), (component, _simulatedEvent) => {
17402
              emitWith(component, formChangeEvent, { name: spec.name });
17403
            })
17404
          ])
17405
        ]),
17406
        selectOnFocus: false
17407
      });
17408
      const getLabel = label => ({
17409
        dom: {
17410
          tag: 'label',
17411
          classes: ['tox-label']
17412
        },
17413
        components: [text$2(providersBackstage.translate(label))]
17414
      });
17415
      const widthField = FormCoupledInputs.parts.field1(formGroup([
17416
        FormField.parts.label(getLabel('Width')),
17417
        getFieldPart(true)
17418
      ]));
17419
      const heightField = FormCoupledInputs.parts.field2(formGroup([
17420
        FormField.parts.label(getLabel('Height')),
17421
        getFieldPart(false)
17422
      ]));
17423
      return FormCoupledInputs.sketch({
17424
        dom: {
17425
          tag: 'div',
17426
          classes: ['tox-form__group']
17427
        },
17428
        components: [{
17429
            dom: {
17430
              tag: 'div',
17431
              classes: ['tox-form__controls-h-stack']
17432
            },
17433
            components: [
17434
              widthField,
17435
              heightField,
17436
              formGroup([
17437
                getLabel(nbsp),
17438
                pLock
17439
              ])
17440
            ]
17441
          }],
17442
        field1Name: 'width',
17443
        field2Name: 'height',
17444
        locked: true,
17445
        markers: { lockClass: 'tox-locked' },
17446
        onLockedChange: (current, other, _lock) => {
17447
          parseSize(Representing.getValue(current)).each(size => {
17448
            converter(size).each(newSize => {
17449
              Representing.setValue(other, formatSize(newSize));
17450
            });
17451
          });
17452
        },
17453
        coupledFieldBehaviours: derive$1([
17454
          Disabling.config({
17455
            disabled: () => !spec.enabled || providersBackstage.isDisabled(),
17456
            onDisabled: comp => {
17457
              FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.disable);
17458
              FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.disable);
17459
              FormCoupledInputs.getLock(comp).each(Disabling.disable);
17460
            },
17461
            onEnabled: comp => {
17462
              FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.enable);
17463
              FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.enable);
17464
              FormCoupledInputs.getLock(comp).each(Disabling.enable);
17465
            }
17466
          }),
17467
          receivingConfig(),
17468
          config('size-input-events2', [run$1(ratioEvent, (component, simulatedEvent) => {
17469
              const isField1 = simulatedEvent.event.isField1;
17470
              const optCurrent = isField1 ? FormCoupledInputs.getField1(component) : FormCoupledInputs.getField2(component);
17471
              const optOther = isField1 ? FormCoupledInputs.getField2(component) : FormCoupledInputs.getField1(component);
17472
              const value1 = optCurrent.map(Representing.getValue).getOr('');
17473
              const value2 = optOther.map(Representing.getValue).getOr('');
17474
              converter = makeRatioConverter(value1, value2);
17475
            })])
17476
        ])
17477
      });
17478
    };
17479
 
17480
    const renderSlider = (spec, providerBackstage, initialData) => {
17481
      const labelPart = Slider.parts.label({
17482
        dom: {
17483
          tag: 'label',
17484
          classes: ['tox-label']
17485
        },
17486
        components: [text$2(providerBackstage.translate(spec.label))]
17487
      });
17488
      const spectrum = Slider.parts.spectrum({
17489
        dom: {
17490
          tag: 'div',
17491
          classes: ['tox-slider__rail'],
17492
          attributes: { role: 'presentation' }
17493
        }
17494
      });
17495
      const thumb = Slider.parts.thumb({
17496
        dom: {
17497
          tag: 'div',
17498
          classes: ['tox-slider__handle'],
17499
          attributes: { role: 'presentation' }
17500
        }
17501
      });
17502
      return Slider.sketch({
17503
        dom: {
17504
          tag: 'div',
17505
          classes: ['tox-slider'],
17506
          attributes: { role: 'presentation' }
17507
        },
17508
        model: {
17509
          mode: 'x',
17510
          minX: spec.min,
17511
          maxX: spec.max,
17512
          getInitialValue: constant$1(initialData.getOrThunk(() => (Math.abs(spec.max) - Math.abs(spec.min)) / 2))
17513
        },
17514
        components: [
17515
          labelPart,
17516
          spectrum,
17517
          thumb
17518
        ],
17519
        sliderBehaviours: derive$1([
17520
          ComposingConfigs.self(),
17521
          Focusing.config({})
17522
        ]),
17523
        onChoose: (component, thumb, value) => {
17524
          emitWith(component, formChangeEvent, {
17525
            name: spec.name,
17526
            value
17527
          });
17528
        }
17529
      });
17530
    };
17531
 
17532
    const renderTable = (spec, providersBackstage) => {
17533
      const renderTh = text => ({
17534
        dom: {
17535
          tag: 'th',
17536
          innerHtml: providersBackstage.translate(text)
17537
        }
17538
      });
17539
      const renderHeader = header => ({
17540
        dom: { tag: 'thead' },
17541
        components: [{
17542
            dom: { tag: 'tr' },
17543
            components: map$2(header, renderTh)
17544
          }]
17545
      });
17546
      const renderTd = text => ({
17547
        dom: {
17548
          tag: 'td',
17549
          innerHtml: providersBackstage.translate(text)
17550
        }
17551
      });
17552
      const renderTr = row => ({
17553
        dom: { tag: 'tr' },
17554
        components: map$2(row, renderTd)
17555
      });
17556
      const renderRows = rows => ({
17557
        dom: { tag: 'tbody' },
17558
        components: map$2(rows, renderTr)
17559
      });
17560
      return {
17561
        dom: {
17562
          tag: 'table',
17563
          classes: ['tox-dialog__table']
17564
        },
17565
        components: [
17566
          renderHeader(spec.header),
17567
          renderRows(spec.cells)
17568
        ],
17569
        behaviours: derive$1([
17570
          Tabstopping.config({}),
17571
          Focusing.config({})
17572
        ])
17573
      };
17574
    };
17575
 
17576
    const renderTextField = (spec, providersBackstage) => {
17577
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
17578
      const baseInputBehaviours = [
17579
        Disabling.config({ disabled: () => spec.disabled || providersBackstage.isDisabled() }),
17580
        receivingConfig(),
17581
        Keying.config({
17582
          mode: 'execution',
17583
          useEnter: spec.multiline !== true,
17584
          useControlEnter: spec.multiline === true,
17585
          execute: comp => {
17586
            emit(comp, formSubmitEvent);
17587
            return Optional.some(true);
17588
          }
17589
        }),
17590
        config('textfield-change', [
17591
          run$1(input(), (component, _) => {
17592
            emitWith(component, formChangeEvent, { name: spec.name });
17593
          }),
17594
          run$1(postPaste(), (component, _) => {
17595
            emitWith(component, formChangeEvent, { name: spec.name });
17596
          })
17597
        ]),
17598
        Tabstopping.config({})
17599
      ];
17600
      const validatingBehaviours = spec.validation.map(vl => Invalidating.config({
17601
        getRoot: input => {
17602
          return parentElement(input.element);
17603
        },
17604
        invalidClass: 'tox-invalid',
17605
        validator: {
17606
          validate: input => {
17607
            const v = Representing.getValue(input);
17608
            const result = vl.validator(v);
17609
            return Future.pure(result === true ? Result.value(v) : Result.error(result));
17610
          },
17611
          validateOnLoad: vl.validateOnLoad
17612
        }
17613
      })).toArray();
17614
      const placeholder = spec.placeholder.fold(constant$1({}), p => ({ placeholder: providersBackstage.translate(p) }));
17615
      const inputMode = spec.inputMode.fold(constant$1({}), mode => ({ inputmode: mode }));
17616
      const inputAttributes = {
17617
        ...placeholder,
17618
        ...inputMode
17619
      };
17620
      const pField = FormField.parts.field({
17621
        tag: spec.multiline === true ? 'textarea' : 'input',
17622
        ...spec.data.map(data => ({ data })).getOr({}),
17623
        inputAttributes,
17624
        inputClasses: [spec.classname],
17625
        inputBehaviours: derive$1(flatten([
17626
          baseInputBehaviours,
17627
          validatingBehaviours
17628
        ])),
17629
        selectOnFocus: false,
17630
        factory: Input
17631
      });
17632
      const pTextField = spec.multiline ? {
17633
        dom: {
17634
          tag: 'div',
17635
          classes: ['tox-textarea-wrap']
17636
        },
17637
        components: [pField]
17638
      } : pField;
17639
      const extraClasses = spec.flex ? ['tox-form__group--stretched'] : [];
17640
      const extraClasses2 = extraClasses.concat(spec.maximized ? ['tox-form-group--maximize'] : []);
17641
      const extraBehaviours = [
17642
        Disabling.config({
17643
          disabled: () => spec.disabled || providersBackstage.isDisabled(),
17644
          onDisabled: comp => {
17645
            FormField.getField(comp).each(Disabling.disable);
17646
          },
17647
          onEnabled: comp => {
17648
            FormField.getField(comp).each(Disabling.enable);
17649
          }
17650
        }),
17651
        receivingConfig()
17652
      ];
17653
      return renderFormFieldWith(pLabel, pTextField, extraClasses2, extraBehaviours);
17654
    };
17655
    const renderInput = (spec, providersBackstage, initialData) => renderTextField({
17656
      name: spec.name,
17657
      multiline: false,
17658
      label: spec.label,
17659
      inputMode: spec.inputMode,
17660
      placeholder: spec.placeholder,
17661
      flex: false,
17662
      disabled: !spec.enabled,
17663
      classname: 'tox-textfield',
17664
      validation: Optional.none(),
17665
      maximized: spec.maximized,
17666
      data: initialData
17667
    }, providersBackstage);
17668
    const renderTextarea = (spec, providersBackstage, initialData) => renderTextField({
17669
      name: spec.name,
17670
      multiline: true,
17671
      label: spec.label,
17672
      inputMode: Optional.none(),
17673
      placeholder: spec.placeholder,
17674
      flex: true,
17675
      disabled: !spec.enabled,
17676
      classname: 'tox-textarea',
17677
      validation: Optional.none(),
17678
      maximized: spec.maximized,
17679
      data: initialData
17680
    }, providersBackstage);
17681
 
17682
    const getAnimationRoot = (component, slideConfig) => slideConfig.getAnimationRoot.fold(() => component.element, get => get(component));
17683
 
17684
    const getDimensionProperty = slideConfig => slideConfig.dimension.property;
17685
    const getDimension = (slideConfig, elem) => slideConfig.dimension.getDimension(elem);
17686
    const disableTransitions = (component, slideConfig) => {
17687
      const root = getAnimationRoot(component, slideConfig);
17688
      remove$1(root, [
17689
        slideConfig.shrinkingClass,
17690
        slideConfig.growingClass
17691
      ]);
17692
    };
17693
    const setShrunk = (component, slideConfig) => {
17694
      remove$2(component.element, slideConfig.openClass);
17695
      add$2(component.element, slideConfig.closedClass);
17696
      set$8(component.element, getDimensionProperty(slideConfig), '0px');
17697
      reflow(component.element);
17698
    };
17699
    const setGrown = (component, slideConfig) => {
17700
      remove$2(component.element, slideConfig.closedClass);
17701
      add$2(component.element, slideConfig.openClass);
17702
      remove$6(component.element, getDimensionProperty(slideConfig));
17703
    };
17704
    const doImmediateShrink = (component, slideConfig, slideState, _calculatedSize) => {
17705
      slideState.setCollapsed();
17706
      set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
17707
      disableTransitions(component, slideConfig);
17708
      setShrunk(component, slideConfig);
17709
      slideConfig.onStartShrink(component);
17710
      slideConfig.onShrunk(component);
17711
    };
17712
    const doStartShrink = (component, slideConfig, slideState, calculatedSize) => {
17713
      const size = calculatedSize.getOrThunk(() => getDimension(slideConfig, component.element));
17714
      slideState.setCollapsed();
17715
      set$8(component.element, getDimensionProperty(slideConfig), size);
17716
      reflow(component.element);
17717
      const root = getAnimationRoot(component, slideConfig);
17718
      remove$2(root, slideConfig.growingClass);
17719
      add$2(root, slideConfig.shrinkingClass);
17720
      setShrunk(component, slideConfig);
17721
      slideConfig.onStartShrink(component);
17722
    };
17723
    const doStartSmartShrink = (component, slideConfig, slideState) => {
17724
      const size = getDimension(slideConfig, component.element);
17725
      const shrinker = size === '0px' ? doImmediateShrink : doStartShrink;
17726
      shrinker(component, slideConfig, slideState, Optional.some(size));
17727
    };
17728
    const doStartGrow = (component, slideConfig, slideState) => {
17729
      const root = getAnimationRoot(component, slideConfig);
17730
      const wasShrinking = has(root, slideConfig.shrinkingClass);
17731
      const beforeSize = getDimension(slideConfig, component.element);
17732
      setGrown(component, slideConfig);
17733
      const fullSize = getDimension(slideConfig, component.element);
17734
      const startPartialGrow = () => {
17735
        set$8(component.element, getDimensionProperty(slideConfig), beforeSize);
17736
        reflow(component.element);
17737
      };
17738
      const startCompleteGrow = () => {
17739
        setShrunk(component, slideConfig);
17740
      };
17741
      const setStartSize = wasShrinking ? startPartialGrow : startCompleteGrow;
17742
      setStartSize();
17743
      remove$2(root, slideConfig.shrinkingClass);
17744
      add$2(root, slideConfig.growingClass);
17745
      setGrown(component, slideConfig);
17746
      set$8(component.element, getDimensionProperty(slideConfig), fullSize);
17747
      slideState.setExpanded();
17748
      slideConfig.onStartGrow(component);
17749
    };
17750
    const refresh$4 = (component, slideConfig, slideState) => {
17751
      if (slideState.isExpanded()) {
17752
        remove$6(component.element, getDimensionProperty(slideConfig));
17753
        const fullSize = getDimension(slideConfig, component.element);
17754
        set$8(component.element, getDimensionProperty(slideConfig), fullSize);
17755
      }
17756
    };
17757
    const grow = (component, slideConfig, slideState) => {
17758
      if (!slideState.isExpanded()) {
17759
        doStartGrow(component, slideConfig, slideState);
17760
      }
17761
    };
17762
    const shrink = (component, slideConfig, slideState) => {
17763
      if (slideState.isExpanded()) {
17764
        doStartSmartShrink(component, slideConfig, slideState);
17765
      }
17766
    };
17767
    const immediateShrink = (component, slideConfig, slideState) => {
17768
      if (slideState.isExpanded()) {
17769
        doImmediateShrink(component, slideConfig, slideState);
17770
      }
17771
    };
17772
    const hasGrown = (component, slideConfig, slideState) => slideState.isExpanded();
17773
    const hasShrunk = (component, slideConfig, slideState) => slideState.isCollapsed();
17774
    const isGrowing = (component, slideConfig, _slideState) => {
17775
      const root = getAnimationRoot(component, slideConfig);
17776
      return has(root, slideConfig.growingClass) === true;
17777
    };
17778
    const isShrinking = (component, slideConfig, _slideState) => {
17779
      const root = getAnimationRoot(component, slideConfig);
17780
      return has(root, slideConfig.shrinkingClass) === true;
17781
    };
17782
    const isTransitioning = (component, slideConfig, slideState) => isGrowing(component, slideConfig) || isShrinking(component, slideConfig);
17783
    const toggleGrow = (component, slideConfig, slideState) => {
17784
      const f = slideState.isExpanded() ? doStartSmartShrink : doStartGrow;
17785
      f(component, slideConfig, slideState);
17786
    };
17787
    const immediateGrow = (component, slideConfig, slideState) => {
17788
      if (!slideState.isExpanded()) {
17789
        setGrown(component, slideConfig);
17790
        set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
17791
        disableTransitions(component, slideConfig);
17792
        slideState.setExpanded();
17793
        slideConfig.onStartGrow(component);
17794
        slideConfig.onGrown(component);
17795
      }
17796
    };
17797
 
17798
    var SlidingApis = /*#__PURE__*/Object.freeze({
17799
        __proto__: null,
17800
        refresh: refresh$4,
17801
        grow: grow,
17802
        shrink: shrink,
17803
        immediateShrink: immediateShrink,
17804
        hasGrown: hasGrown,
17805
        hasShrunk: hasShrunk,
17806
        isGrowing: isGrowing,
17807
        isShrinking: isShrinking,
17808
        isTransitioning: isTransitioning,
17809
        toggleGrow: toggleGrow,
17810
        disableTransitions: disableTransitions,
17811
        immediateGrow: immediateGrow
17812
    });
17813
 
17814
    const exhibit = (base, slideConfig, _slideState) => {
17815
      const expanded = slideConfig.expanded;
17816
      return expanded ? nu$7({
17817
        classes: [slideConfig.openClass],
17818
        styles: {}
17819
      }) : nu$7({
17820
        classes: [slideConfig.closedClass],
17821
        styles: wrap$1(slideConfig.dimension.property, '0px')
17822
      });
17823
    };
17824
    const events$6 = (slideConfig, slideState) => derive$2([runOnSource(transitionend(), (component, simulatedEvent) => {
17825
        const raw = simulatedEvent.event.raw;
17826
        if (raw.propertyName === slideConfig.dimension.property) {
17827
          disableTransitions(component, slideConfig);
17828
          if (slideState.isExpanded()) {
17829
            remove$6(component.element, slideConfig.dimension.property);
17830
          }
17831
          const notify = slideState.isExpanded() ? slideConfig.onGrown : slideConfig.onShrunk;
17832
          notify(component);
17833
        }
17834
      })]);
17835
 
17836
    var ActiveSliding = /*#__PURE__*/Object.freeze({
17837
        __proto__: null,
17838
        exhibit: exhibit,
17839
        events: events$6
17840
    });
17841
 
17842
    var SlidingSchema = [
17843
      required$1('closedClass'),
17844
      required$1('openClass'),
17845
      required$1('shrinkingClass'),
17846
      required$1('growingClass'),
17847
      option$3('getAnimationRoot'),
17848
      onHandler('onShrunk'),
17849
      onHandler('onStartShrink'),
17850
      onHandler('onGrown'),
17851
      onHandler('onStartGrow'),
17852
      defaulted('expanded', false),
17853
      requiredOf('dimension', choose$1('property', {
17854
        width: [
17855
          output$1('property', 'width'),
17856
          output$1('getDimension', elem => get$c(elem) + 'px')
17857
        ],
17858
        height: [
17859
          output$1('property', 'height'),
17860
          output$1('getDimension', elem => get$d(elem) + 'px')
17861
        ]
17862
      }))
17863
    ];
17864
 
17865
    const init$9 = spec => {
17866
      const state = Cell(spec.expanded);
17867
      const readState = () => 'expanded: ' + state.get();
17868
      return nu$8({
17869
        isExpanded: () => state.get() === true,
17870
        isCollapsed: () => state.get() === false,
17871
        setCollapsed: curry(state.set, false),
17872
        setExpanded: curry(state.set, true),
17873
        readState
17874
      });
17875
    };
17876
 
17877
    var SlidingState = /*#__PURE__*/Object.freeze({
17878
        __proto__: null,
17879
        init: init$9
17880
    });
17881
 
17882
    const Sliding = create$4({
17883
      fields: SlidingSchema,
17884
      name: 'sliding',
17885
      active: ActiveSliding,
17886
      apis: SlidingApis,
17887
      state: SlidingState
17888
    });
17889
 
17890
    const getMenuButtonApi = component => ({
17891
      isEnabled: () => !Disabling.isDisabled(component),
17892
      setEnabled: state => Disabling.set(component, !state),
17893
      setActive: state => {
17894
        const elm = component.element;
17895
        if (state) {
17896
          add$2(elm, 'tox-tbtn--enabled');
17897
          set$9(elm, 'aria-pressed', true);
17898
        } else {
17899
          remove$2(elm, 'tox-tbtn--enabled');
17900
          remove$7(elm, 'aria-pressed');
17901
        }
17902
      },
17903
      isActive: () => has(component.element, 'tox-tbtn--enabled'),
17904
      setText: text => {
17905
        emitWith(component, updateMenuText, { text });
17906
      },
17907
      setIcon: icon => emitWith(component, updateMenuIcon, { icon })
17908
    });
17909
    const renderMenuButton = (spec, prefix, backstage, role, tabstopping = true) => {
17910
      return renderCommonDropdown({
17911
        text: spec.text,
17912
        icon: spec.icon,
17913
        tooltip: spec.tooltip,
17914
        searchable: spec.search.isSome(),
17915
        role,
17916
        fetch: (dropdownComp, callback) => {
17917
          const fetchContext = { pattern: spec.search.isSome() ? getSearchPattern(dropdownComp) : '' };
17918
          spec.fetch(items => {
17919
            callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
17920
              isHorizontalMenu: false,
17921
              search: spec.search
17922
            }));
17923
          }, fetchContext, getMenuButtonApi(dropdownComp));
17924
        },
17925
        onSetup: spec.onSetup,
17926
        getApi: getMenuButtonApi,
17927
        columns: 1,
17928
        presets: 'normal',
17929
        classes: [],
17930
        dropdownBehaviours: [...tabstopping ? [Tabstopping.config({})] : []]
17931
      }, prefix, backstage.shared);
17932
    };
17933
    const getFetch = (items, getButton, backstage) => {
17934
      const getMenuItemAction = item => api => {
17935
        const newValue = !api.isActive();
17936
        api.setActive(newValue);
17937
        item.storage.set(newValue);
17938
        backstage.shared.getSink().each(sink => {
17939
          getButton().getOpt(sink).each(orig => {
17940
            focus$3(orig.element);
17941
            emitWith(orig, formActionEvent, {
17942
              name: item.name,
17943
              value: item.storage.get()
17944
            });
17945
          });
17946
        });
17947
      };
17948
      const getMenuItemSetup = item => api => {
17949
        api.setActive(item.storage.get());
17950
      };
17951
      return success => {
17952
        success(map$2(items, item => {
17953
          const text = item.text.fold(() => ({}), text => ({ text }));
17954
          return {
17955
            type: item.type,
17956
            active: false,
17957
            ...text,
17958
            onAction: getMenuItemAction(item),
17959
            onSetup: getMenuItemSetup(item)
17960
          };
17961
        }));
17962
      };
17963
    };
17964
 
17965
    const renderLabel = text => ({
17966
      dom: {
17967
        tag: 'span',
17968
        classes: ['tox-tree__label'],
17969
        attributes: {
17970
          'title': text,
17971
          'aria-label': text
17972
        }
17973
      },
17974
      components: [text$2(text)]
17975
    });
17976
    const leafLabelEventsId = generate$6('leaf-label-event-id');
17977
    const renderLeafLabel = ({leaf, onLeafAction, visible, treeId, selectedId, backstage}) => {
17978
      const internalMenuButton = leaf.menu.map(btn => renderMenuButton(btn, 'tox-mbtn', backstage, Optional.none(), visible));
17979
      const components = [renderLabel(leaf.title)];
17980
      internalMenuButton.each(btn => components.push(btn));
17981
      return Button.sketch({
17982
        dom: {
17983
          tag: 'div',
17984
          classes: [
17985
            'tox-tree--leaf__label',
17986
            'tox-trbtn'
17987
          ].concat(visible ? ['tox-tree--leaf__label--visible'] : [])
17988
        },
17989
        components,
17990
        role: 'treeitem',
17991
        action: button => {
17992
          onLeafAction(leaf.id);
17993
          button.getSystem().broadcastOn([`update-active-item-${ treeId }`], { value: leaf.id });
17994
        },
17995
        eventOrder: {
17996
          [keydown()]: [
17997
            leafLabelEventsId,
17998
            'keying'
17999
          ]
18000
        },
18001
        buttonBehaviours: derive$1([
18002
          ...visible ? [Tabstopping.config({})] : [],
18003
          Toggling.config({
18004
            toggleClass: 'tox-trbtn--enabled',
18005
            toggleOnExecute: false,
18006
            aria: { mode: 'selected' }
18007
          }),
18008
          Receiving.config({
18009
            channels: {
18010
              [`update-active-item-${ treeId }`]: {
18011
                onReceive: (comp, message) => {
18012
                  (message.value === leaf.id ? Toggling.on : Toggling.off)(comp);
18013
                }
18014
              }
18015
            }
18016
          }),
18017
          config(leafLabelEventsId, [
18018
            runOnAttached((comp, _se) => {
18019
              selectedId.each(id => {
18020
                const toggle = id === leaf.id ? Toggling.on : Toggling.off;
18021
                toggle(comp);
18022
              });
18023
            }),
18024
            run$1(keydown(), (comp, se) => {
18025
              const isLeftArrowKey = se.event.raw.code === 'ArrowLeft';
18026
              const isRightArrowKey = se.event.raw.code === 'ArrowRight';
18027
              if (isLeftArrowKey) {
18028
                ancestor(comp.element, '.tox-tree--directory').each(dirElement => {
18029
                  comp.getSystem().getByDom(dirElement).each(dirComp => {
18030
                    child(dirElement, '.tox-tree--directory__label').each(dirLabelElement => {
18031
                      dirComp.getSystem().getByDom(dirLabelElement).each(Focusing.focus);
18032
                    });
18033
                  });
18034
                });
18035
                se.stop();
18036
              } else if (isRightArrowKey) {
18037
                se.stop();
18038
              }
18039
            })
18040
          ])
18041
        ])
18042
      });
18043
    };
18044
    const renderIcon = (iconName, iconsProvider, behaviours) => render$3(iconName, {
18045
      tag: 'span',
18046
      classes: [
18047
        'tox-tree__icon-wrap',
18048
        'tox-icon'
18049
      ],
18050
      behaviours
18051
    }, iconsProvider);
18052
    const renderIconFromPack = (iconName, iconsProvider) => renderIcon(iconName, iconsProvider, []);
18053
    const directoryLabelEventsId = generate$6('directory-label-event-id');
18054
    const renderDirectoryLabel = ({directory, visible, noChildren, backstage}) => {
18055
      const internalMenuButton = directory.menu.map(btn => renderMenuButton(btn, 'tox-mbtn', backstage, Optional.none()));
18056
      const components = [
18057
        {
18058
          dom: {
18059
            tag: 'div',
18060
            classes: ['tox-chevron']
18061
          },
18062
          components: [renderIconFromPack('chevron-right', backstage.shared.providers.icons)]
18063
        },
18064
        renderLabel(directory.title)
18065
      ];
18066
      internalMenuButton.each(btn => {
18067
        components.push(btn);
18068
      });
18069
      const toggleExpandChildren = button => {
18070
        ancestor(button.element, '.tox-tree--directory').each(directoryEle => {
18071
          button.getSystem().getByDom(directoryEle).each(directoryComp => {
18072
            const willExpand = !Toggling.isOn(directoryComp);
18073
            Toggling.toggle(directoryComp);
18074
            emitWith(button, 'expand-tree-node', {
18075
              expanded: willExpand,
18076
              node: directory.id
18077
            });
18078
          });
18079
        });
18080
      };
18081
      return Button.sketch({
18082
        dom: {
18083
          tag: 'div',
18084
          classes: [
18085
            'tox-tree--directory__label',
18086
            'tox-trbtn'
18087
          ].concat(visible ? ['tox-tree--directory__label--visible'] : [])
18088
        },
18089
        components,
18090
        action: toggleExpandChildren,
18091
        eventOrder: {
18092
          [keydown()]: [
18093
            directoryLabelEventsId,
18094
            'keying'
18095
          ]
18096
        },
18097
        buttonBehaviours: derive$1([
18098
          ...visible ? [Tabstopping.config({})] : [],
18099
          config(directoryLabelEventsId, [run$1(keydown(), (comp, se) => {
18100
              const isRightArrowKey = se.event.raw.code === 'ArrowRight';
18101
              const isLeftArrowKey = se.event.raw.code === 'ArrowLeft';
18102
              if (isRightArrowKey && noChildren) {
18103
                se.stop();
18104
              }
18105
              if (isRightArrowKey || isLeftArrowKey) {
18106
                ancestor(comp.element, '.tox-tree--directory').each(directoryEle => {
18107
                  comp.getSystem().getByDom(directoryEle).each(directoryComp => {
18108
                    if (!Toggling.isOn(directoryComp) && isRightArrowKey || Toggling.isOn(directoryComp) && isLeftArrowKey) {
18109
                      toggleExpandChildren(comp);
18110
                      se.stop();
18111
                    } else if (isLeftArrowKey && !Toggling.isOn(directoryComp)) {
18112
                      ancestor(directoryComp.element, '.tox-tree--directory').each(parentDirElement => {
18113
                        child(parentDirElement, '.tox-tree--directory__label').each(parentDirLabelElement => {
18114
                          directoryComp.getSystem().getByDom(parentDirLabelElement).each(Focusing.focus);
18115
                        });
18116
                      });
18117
                      se.stop();
18118
                    }
18119
                  });
18120
                });
18121
              }
18122
            })])
18123
        ])
18124
      });
18125
    };
18126
    const renderDirectoryChildren = ({children, onLeafAction, visible, treeId, expandedIds, selectedId, backstage}) => {
18127
      return {
18128
        dom: {
18129
          tag: 'div',
18130
          classes: ['tox-tree--directory__children']
18131
        },
18132
        components: children.map(item => {
18133
          return item.type === 'leaf' ? renderLeafLabel({
18134
            leaf: item,
18135
            selectedId,
18136
            onLeafAction,
18137
            visible,
18138
            treeId,
18139
            backstage
18140
          }) : renderDirectory({
18141
            directory: item,
18142
            expandedIds,
18143
            selectedId,
18144
            onLeafAction,
18145
            labelTabstopping: visible,
18146
            treeId,
18147
            backstage
18148
          });
18149
        }),
18150
        behaviours: derive$1([
18151
          Sliding.config({
18152
            dimension: { property: 'height' },
18153
            closedClass: 'tox-tree--directory__children--closed',
18154
            openClass: 'tox-tree--directory__children--open',
18155
            growingClass: 'tox-tree--directory__children--growing',
18156
            shrinkingClass: 'tox-tree--directory__children--shrinking',
18157
            expanded: visible
18158
          }),
18159
          Replacing.config({})
18160
        ])
18161
      };
18162
    };
18163
    const directoryEventsId = generate$6('directory-event-id');
18164
    const renderDirectory = ({directory, onLeafAction, labelTabstopping, treeId, backstage, expandedIds, selectedId}) => {
18165
      const {children} = directory;
18166
      const expandedIdsCell = Cell(expandedIds);
18167
      const computedChildrenComponents = visible => children.map(item => {
18168
        return item.type === 'leaf' ? renderLeafLabel({
18169
          leaf: item,
18170
          selectedId,
18171
          onLeafAction,
18172
          visible,
18173
          treeId,
18174
          backstage
18175
        }) : renderDirectory({
18176
          directory: item,
18177
          expandedIds: expandedIdsCell.get(),
18178
          selectedId,
18179
          onLeafAction,
18180
          labelTabstopping: visible,
18181
          treeId,
18182
          backstage
18183
        });
18184
      });
18185
      const childrenVisible = expandedIds.includes(directory.id);
18186
      return {
18187
        dom: {
18188
          tag: 'div',
18189
          classes: ['tox-tree--directory'],
18190
          attributes: { role: 'treeitem' }
18191
        },
18192
        components: [
18193
          renderDirectoryLabel({
18194
            directory,
18195
            visible: labelTabstopping,
18196
            noChildren: directory.children.length === 0,
18197
            backstage
18198
          }),
18199
          renderDirectoryChildren({
18200
            children,
18201
            expandedIds,
18202
            selectedId,
18203
            onLeafAction,
18204
            visible: childrenVisible,
18205
            treeId,
18206
            backstage
18207
          })
18208
        ],
18209
        behaviours: derive$1([
18210
          config(directoryEventsId, [
18211
            runOnAttached((comp, _se) => {
18212
              Toggling.set(comp, childrenVisible);
18213
            }),
18214
            run$1('expand-tree-node', (_cmp, se) => {
18215
              const {expanded, node} = se.event;
18216
              expandedIdsCell.set(expanded ? [
18217
                ...expandedIdsCell.get(),
18218
                node
18219
              ] : expandedIdsCell.get().filter(id => id !== node));
18220
            })
18221
          ]),
18222
          Toggling.config({
18223
            ...directory.children.length > 0 ? { aria: { mode: 'expanded' } } : {},
18224
            toggleClass: 'tox-tree--directory--expanded',
18225
            onToggled: (comp, childrenVisible) => {
18226
              const childrenComp = comp.components()[1];
18227
              const newChildren = computedChildrenComponents(childrenVisible);
18228
              if (childrenVisible) {
18229
                Sliding.grow(childrenComp);
18230
              } else {
18231
                Sliding.shrink(childrenComp);
18232
              }
18233
              Replacing.set(childrenComp, newChildren);
18234
            }
18235
          })
18236
        ])
18237
      };
18238
    };
18239
    const treeEventsId = generate$6('tree-event-id');
18240
    const renderTree = (spec, backstage) => {
18241
      const onLeafAction = spec.onLeafAction.getOr(noop);
18242
      const onToggleExpand = spec.onToggleExpand.getOr(noop);
18243
      const defaultExpandedIds = spec.defaultExpandedIds;
18244
      const expandedIds = Cell(defaultExpandedIds);
18245
      const selectedIdCell = Cell(spec.defaultSelectedId);
18246
      const treeId = generate$6('tree-id');
18247
      const children = (selectedId, expandedIds) => spec.items.map(item => {
18248
        return item.type === 'leaf' ? renderLeafLabel({
18249
          leaf: item,
18250
          selectedId,
18251
          onLeafAction,
18252
          visible: true,
18253
          treeId,
18254
          backstage
18255
        }) : renderDirectory({
18256
          directory: item,
18257
          selectedId,
18258
          onLeafAction,
18259
          expandedIds,
18260
          labelTabstopping: true,
18261
          treeId,
18262
          backstage
18263
        });
18264
      });
18265
      return {
18266
        dom: {
18267
          tag: 'div',
18268
          classes: ['tox-tree'],
18269
          attributes: { role: 'tree' }
18270
        },
18271
        components: children(selectedIdCell.get(), expandedIds.get()),
18272
        behaviours: derive$1([
18273
          Keying.config({
18274
            mode: 'flow',
18275
            selector: '.tox-tree--leaf__label--visible, .tox-tree--directory__label--visible',
18276
            cycles: false
18277
          }),
18278
          config(treeEventsId, [run$1('expand-tree-node', (_cmp, se) => {
18279
              const {expanded, node} = se.event;
18280
              expandedIds.set(expanded ? [
18281
                ...expandedIds.get(),
18282
                node
18283
              ] : expandedIds.get().filter(id => id !== node));
18284
              onToggleExpand(expandedIds.get(), {
18285
                expanded,
18286
                node
18287
              });
18288
            })]),
18289
          Receiving.config({
18290
            channels: {
18291
              [`update-active-item-${ treeId }`]: {
18292
                onReceive: (comp, message) => {
18293
                  selectedIdCell.set(Optional.some(message.value));
18294
                  Replacing.set(comp, children(Optional.some(message.value), expandedIds.get()));
18295
                }
18296
              }
18297
            }
18298
          }),
18299
          Replacing.config({})
18300
        ])
18301
      };
18302
    };
18303
 
18304
    const events$5 = (streamConfig, streamState) => {
18305
      const streams = streamConfig.stream.streams;
18306
      const processor = streams.setup(streamConfig, streamState);
18307
      return derive$2([
18308
        run$1(streamConfig.event, processor),
18309
        runOnDetached(() => streamState.cancel())
18310
      ].concat(streamConfig.cancelEvent.map(e => [run$1(e, () => streamState.cancel())]).getOr([])));
18311
    };
18312
 
18313
    var ActiveStreaming = /*#__PURE__*/Object.freeze({
18314
        __proto__: null,
18315
        events: events$5
18316
    });
18317
 
18318
    const throttle = _config => {
18319
      const state = Cell(null);
18320
      const readState = () => ({ timer: state.get() !== null ? 'set' : 'unset' });
18321
      const setTimer = t => {
18322
        state.set(t);
18323
      };
18324
      const cancel = () => {
18325
        const t = state.get();
18326
        if (t !== null) {
18327
          t.cancel();
18328
        }
18329
      };
18330
      return nu$8({
18331
        readState,
18332
        setTimer,
18333
        cancel
18334
      });
18335
    };
18336
    const init$8 = spec => spec.stream.streams.state(spec);
18337
 
18338
    var StreamingState = /*#__PURE__*/Object.freeze({
18339
        __proto__: null,
18340
        throttle: throttle,
18341
        init: init$8
18342
    });
18343
 
18344
    const setup$c = (streamInfo, streamState) => {
18345
      const sInfo = streamInfo.stream;
18346
      const throttler = last(streamInfo.onStream, sInfo.delay);
18347
      streamState.setTimer(throttler);
18348
      return (component, simulatedEvent) => {
18349
        throttler.throttle(component, simulatedEvent);
18350
        if (sInfo.stopEvent) {
18351
          simulatedEvent.stop();
18352
        }
18353
      };
18354
    };
18355
    var StreamingSchema = [
18356
      requiredOf('stream', choose$1('mode', {
18357
        throttle: [
18358
          required$1('delay'),
18359
          defaulted('stopEvent', true),
18360
          output$1('streams', {
18361
            setup: setup$c,
18362
            state: throttle
18363
          })
18364
        ]
18365
      })),
18366
      defaulted('event', 'input'),
18367
      option$3('cancelEvent'),
18368
      onStrictHandler('onStream')
18369
    ];
18370
 
18371
    const Streaming = create$4({
18372
      fields: StreamingSchema,
18373
      name: 'streaming',
18374
      active: ActiveStreaming,
18375
      state: StreamingState
18376
    });
18377
 
18378
    const setValueFromItem = (model, input, item) => {
18379
      const itemData = Representing.getValue(item);
18380
      Representing.setValue(input, itemData);
18381
      setCursorAtEnd(input);
18382
    };
18383
    const setSelectionOn = (input, f) => {
18384
      const el = input.element;
18385
      const value = get$6(el);
18386
      const node = el.dom;
18387
      if (get$f(el, 'type') !== 'number') {
18388
        f(node, value);
18389
      }
18390
    };
18391
    const setCursorAtEnd = input => {
18392
      setSelectionOn(input, (node, value) => node.setSelectionRange(value.length, value.length));
18393
    };
18394
    const setSelectionToEnd = (input, startOffset) => {
18395
      setSelectionOn(input, (node, value) => node.setSelectionRange(startOffset, value.length));
18396
    };
18397
    const attemptSelectOver = (model, input, item) => {
18398
      if (!model.selectsOver) {
18399
        return Optional.none();
18400
      } else {
18401
        const currentValue = Representing.getValue(input);
18402
        const inputDisplay = model.getDisplayText(currentValue);
18403
        const itemValue = Representing.getValue(item);
18404
        const itemDisplay = model.getDisplayText(itemValue);
18405
        return itemDisplay.indexOf(inputDisplay) === 0 ? Optional.some(() => {
18406
          setValueFromItem(model, input, item);
18407
          setSelectionToEnd(input, inputDisplay.length);
18408
        }) : Optional.none();
18409
      }
18410
    };
18411
 
18412
    const itemExecute = constant$1('alloy.typeahead.itemexecute');
18413
 
18414
    const make$3 = (detail, components, spec, externals) => {
18415
      const navigateList = (comp, simulatedEvent, highlighter) => {
18416
        detail.previewing.set(false);
18417
        const sandbox = Coupling.getCoupled(comp, 'sandbox');
18418
        if (Sandboxing.isOpen(sandbox)) {
18419
          Composing.getCurrent(sandbox).each(menu => {
18420
            Highlighting.getHighlighted(menu).fold(() => {
18421
              highlighter(menu);
18422
            }, () => {
18423
              dispatchEvent(sandbox, menu.element, 'keydown', simulatedEvent);
18424
            });
18425
          });
18426
        } else {
18427
          const onOpenSync = sandbox => {
18428
            Composing.getCurrent(sandbox).each(highlighter);
18429
          };
18430
          open(detail, mapFetch(comp), comp, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
18431
        }
18432
      };
18433
      const focusBehaviours$1 = focusBehaviours(detail);
18434
      const mapFetch = comp => tdata => tdata.map(data => {
18435
        const menus = values(data.menus);
18436
        const items = bind$3(menus, menu => filter$2(menu.items, item => item.type === 'item'));
18437
        const repState = Representing.getState(comp);
18438
        repState.update(map$2(items, item => item.data));
18439
        return data;
18440
      });
18441
      const getActiveMenu = sandboxComp => Composing.getCurrent(sandboxComp);
18442
      const typeaheadCustomEvents = 'typeaheadevents';
18443
      const behaviours = [
18444
        Focusing.config({}),
18445
        Representing.config({
18446
          onSetValue: detail.onSetValue,
18447
          store: {
18448
            mode: 'dataset',
18449
            getDataKey: comp => get$6(comp.element),
18450
            getFallbackEntry: itemString => ({
18451
              value: itemString,
18452
              meta: {}
18453
            }),
18454
            setValue: (comp, data) => {
18455
              set$5(comp.element, detail.model.getDisplayText(data));
18456
            },
18457
            ...detail.initialData.map(d => wrap$1('initialValue', d)).getOr({})
18458
          }
18459
        }),
18460
        Streaming.config({
18461
          stream: {
18462
            mode: 'throttle',
18463
            delay: detail.responseTime,
18464
            stopEvent: false
18465
          },
18466
          onStream: (component, _simulatedEvent) => {
18467
            const sandbox = Coupling.getCoupled(component, 'sandbox');
18468
            const focusInInput = Focusing.isFocused(component);
18469
            if (focusInInput) {
18470
              if (get$6(component.element).length >= detail.minChars) {
18471
                const previousValue = getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu).map(Representing.getValue));
18472
                detail.previewing.set(true);
18473
                const onOpenSync = _sandbox => {
18474
                  getActiveMenu(sandbox).each(activeMenu => {
18475
                    previousValue.fold(() => {
18476
                      if (detail.model.selectsOver) {
18477
                        Highlighting.highlightFirst(activeMenu);
18478
                      }
18479
                    }, pv => {
18480
                      Highlighting.highlightBy(activeMenu, item => {
18481
                        const itemData = Representing.getValue(item);
18482
                        return itemData.value === pv.value;
18483
                      });
18484
                      Highlighting.getHighlighted(activeMenu).orThunk(() => {
18485
                        Highlighting.highlightFirst(activeMenu);
18486
                        return Optional.none();
18487
                      });
18488
                    });
18489
                  });
18490
                };
18491
                open(detail, mapFetch(component), component, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightJustMenu).get(noop);
18492
              }
18493
            }
18494
          },
18495
          cancelEvent: typeaheadCancel()
18496
        }),
18497
        Keying.config({
18498
          mode: 'special',
18499
          onDown: (comp, simulatedEvent) => {
18500
            navigateList(comp, simulatedEvent, Highlighting.highlightFirst);
18501
            return Optional.some(true);
18502
          },
18503
          onEscape: comp => {
18504
            const sandbox = Coupling.getCoupled(comp, 'sandbox');
18505
            if (Sandboxing.isOpen(sandbox)) {
18506
              Sandboxing.close(sandbox);
18507
              return Optional.some(true);
18508
            }
18509
            return Optional.none();
18510
          },
18511
          onUp: (comp, simulatedEvent) => {
18512
            navigateList(comp, simulatedEvent, Highlighting.highlightLast);
18513
            return Optional.some(true);
18514
          },
18515
          onEnter: comp => {
18516
            const sandbox = Coupling.getCoupled(comp, 'sandbox');
18517
            const sandboxIsOpen = Sandboxing.isOpen(sandbox);
18518
            if (sandboxIsOpen && !detail.previewing.get()) {
18519
              return getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu)).map(item => {
18520
                emitWith(comp, itemExecute(), { item });
18521
                return true;
18522
              });
18523
            } else {
18524
              const currentValue = Representing.getValue(comp);
18525
              emit(comp, typeaheadCancel());
18526
              detail.onExecute(sandbox, comp, currentValue);
18527
              if (sandboxIsOpen) {
18528
                Sandboxing.close(sandbox);
18529
              }
18530
              return Optional.some(true);
18531
            }
18532
          }
18533
        }),
18534
        Toggling.config({
18535
          toggleClass: detail.markers.openClass,
18536
          aria: { mode: 'expanded' }
18537
        }),
18538
        Coupling.config({
18539
          others: {
18540
            sandbox: hotspot => {
18541
              return makeSandbox$1(detail, hotspot, {
18542
                onOpen: () => Toggling.on(hotspot),
18543
                onClose: () => {
18544
                  detail.lazyTypeaheadComp.get().each(input => remove$7(input.element, 'aria-activedescendant'));
18545
                  Toggling.off(hotspot);
18546
                }
18547
              });
18548
            }
18549
          }
18550
        }),
18551
        config(typeaheadCustomEvents, [
18552
          runOnAttached(typeaheadComp => {
18553
            detail.lazyTypeaheadComp.set(Optional.some(typeaheadComp));
18554
          }),
18555
          runOnDetached(_typeaheadComp => {
18556
            detail.lazyTypeaheadComp.set(Optional.none());
18557
          }),
18558
          runOnExecute$1(comp => {
18559
            const onOpenSync = noop;
18560
            togglePopup(detail, mapFetch(comp), comp, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
18561
          }),
18562
          run$1(itemExecute(), (comp, se) => {
18563
            const sandbox = Coupling.getCoupled(comp, 'sandbox');
18564
            setValueFromItem(detail.model, comp, se.event.item);
18565
            emit(comp, typeaheadCancel());
18566
            detail.onItemExecute(comp, sandbox, se.event.item, Representing.getValue(comp));
18567
            Sandboxing.close(sandbox);
18568
            setCursorAtEnd(comp);
18569
          })
18570
        ].concat(detail.dismissOnBlur ? [run$1(postBlur(), typeahead => {
18571
            const sandbox = Coupling.getCoupled(typeahead, 'sandbox');
18572
            if (search(sandbox.element).isNone()) {
18573
              Sandboxing.close(sandbox);
18574
            }
18575
          })] : []))
18576
      ];
18577
      const eventOrder = {
18578
        [detachedFromDom()]: [
18579
          Representing.name(),
18580
          Streaming.name(),
18581
          typeaheadCustomEvents
18582
        ],
18583
        ...detail.eventOrder
18584
      };
18585
      return {
18586
        uid: detail.uid,
18587
        dom: dom(deepMerge(detail, {
18588
          inputAttributes: {
18589
            'role': 'combobox',
18590
            'aria-autocomplete': 'list',
18591
            'aria-haspopup': 'true'
18592
          }
18593
        })),
18594
        behaviours: {
18595
          ...focusBehaviours$1,
18596
          ...augment(detail.typeaheadBehaviours, behaviours)
18597
        },
18598
        eventOrder
18599
      };
18600
    };
18601
 
18602
    const schema$g = constant$1([
18603
      option$3('lazySink'),
18604
      required$1('fetch'),
18605
      defaulted('minChars', 5),
18606
      defaulted('responseTime', 1000),
18607
      onHandler('onOpen'),
18608
      defaulted('getHotspot', Optional.some),
18609
      defaulted('getAnchorOverrides', constant$1({})),
18610
      defaulted('layouts', Optional.none()),
18611
      defaulted('eventOrder', {}),
18612
      defaultedObjOf('model', {}, [
18613
        defaulted('getDisplayText', itemData => itemData.meta !== undefined && itemData.meta.text !== undefined ? itemData.meta.text : itemData.value),
18614
        defaulted('selectsOver', true),
18615
        defaulted('populateFromBrowse', true)
18616
      ]),
18617
      onHandler('onSetValue'),
18618
      onKeyboardHandler('onExecute'),
18619
      onHandler('onItemExecute'),
18620
      defaulted('inputClasses', []),
18621
      defaulted('inputAttributes', {}),
18622
      defaulted('inputStyles', {}),
18623
      defaulted('matchWidth', true),
18624
      defaulted('useMinWidth', false),
18625
      defaulted('dismissOnBlur', true),
18626
      markers$1(['openClass']),
18627
      option$3('initialData'),
18628
      field('typeaheadBehaviours', [
18629
        Focusing,
18630
        Representing,
18631
        Streaming,
18632
        Keying,
18633
        Toggling,
18634
        Coupling
18635
      ]),
18636
      customField('lazyTypeaheadComp', () => Cell(Optional.none)),
18637
      customField('previewing', () => Cell(true))
18638
    ].concat(schema$l()).concat(sandboxFields()));
18639
    const parts$b = constant$1([external({
18640
        schema: [tieredMenuMarkers()],
18641
        name: 'menu',
18642
        overrides: detail => {
18643
          return {
18644
            fakeFocus: true,
18645
            onHighlightItem: (_tmenu, menu, item) => {
18646
              if (!detail.previewing.get()) {
18647
                detail.lazyTypeaheadComp.get().each(input => {
18648
                  if (detail.model.populateFromBrowse) {
18649
                    setValueFromItem(detail.model, input, item);
18650
                  }
18651
                  getOpt(item.element, 'id').each(id => set$9(input.element, 'aria-activedescendant', id));
18652
                });
18653
              } else {
18654
                detail.lazyTypeaheadComp.get().each(input => {
18655
                  attemptSelectOver(detail.model, input, item).fold(() => {
18656
                    if (detail.model.selectsOver) {
18657
                      Highlighting.dehighlight(menu, item);
18658
                      detail.previewing.set(true);
18659
                    } else {
18660
                      detail.previewing.set(false);
18661
                    }
18662
                  }, selectOverTextInInput => {
18663
                    selectOverTextInInput();
18664
                    detail.previewing.set(false);
18665
                  });
18666
                });
18667
              }
18668
            },
18669
            onExecute: (_menu, item) => {
18670
              return detail.lazyTypeaheadComp.get().map(typeahead => {
18671
                emitWith(typeahead, itemExecute(), { item });
18672
                return true;
18673
              });
18674
            },
18675
            onHover: (menu, item) => {
18676
              detail.previewing.set(false);
18677
              detail.lazyTypeaheadComp.get().each(input => {
18678
                if (detail.model.populateFromBrowse) {
18679
                  setValueFromItem(detail.model, input, item);
18680
                }
18681
              });
18682
            }
18683
          };
18684
        }
18685
      })]);
18686
 
18687
    const Typeahead = composite({
18688
      name: 'Typeahead',
18689
      configFields: schema$g(),
18690
      partFields: parts$b(),
18691
      factory: make$3
18692
    });
18693
 
18694
    const wrap = delegate => {
18695
      const toCached = () => {
18696
        return wrap(delegate.toCached());
18697
      };
18698
      const bindFuture = f => {
18699
        return wrap(delegate.bind(resA => resA.fold(err => Future.pure(Result.error(err)), a => f(a))));
18700
      };
18701
      const bindResult = f => {
18702
        return wrap(delegate.map(resA => resA.bind(f)));
18703
      };
18704
      const mapResult = f => {
18705
        return wrap(delegate.map(resA => resA.map(f)));
18706
      };
18707
      const mapError = f => {
18708
        return wrap(delegate.map(resA => resA.mapError(f)));
18709
      };
18710
      const foldResult = (whenError, whenValue) => {
18711
        return delegate.map(res => res.fold(whenError, whenValue));
18712
      };
18713
      const withTimeout = (timeout, errorThunk) => {
18714
        return wrap(Future.nu(callback => {
18715
          let timedOut = false;
18716
          const timer = setTimeout(() => {
18717
            timedOut = true;
18718
            callback(Result.error(errorThunk()));
18719
          }, timeout);
18720
          delegate.get(result => {
18721
            if (!timedOut) {
18722
              clearTimeout(timer);
18723
              callback(result);
18724
            }
18725
          });
18726
        }));
18727
      };
18728
      return {
18729
        ...delegate,
18730
        toCached,
18731
        bindFuture,
18732
        bindResult,
18733
        mapResult,
18734
        mapError,
18735
        foldResult,
18736
        withTimeout
18737
      };
18738
    };
18739
    const nu$1 = worker => {
18740
      return wrap(Future.nu(worker));
18741
    };
18742
    const value = value => {
18743
      return wrap(Future.pure(Result.value(value)));
18744
    };
18745
    const error = error => {
18746
      return wrap(Future.pure(Result.error(error)));
18747
    };
18748
    const fromResult = result => {
18749
      return wrap(Future.pure(result));
18750
    };
18751
    const fromFuture = future => {
18752
      return wrap(future.map(Result.value));
18753
    };
18754
    const fromPromise = promise => {
18755
      return nu$1(completer => {
18756
        promise.then(value => {
18757
          completer(Result.value(value));
18758
        }, error => {
18759
          completer(Result.error(error));
18760
        });
18761
      });
18762
    };
18763
    const FutureResult = {
18764
      nu: nu$1,
18765
      wrap,
18766
      pure: value,
18767
      value,
18768
      error,
18769
      fromResult,
18770
      fromFuture,
18771
      fromPromise
18772
    };
18773
 
18774
    const renderCommonSpec = (spec, actionOpt, extraBehaviours = [], dom, components, providersBackstage) => {
18775
      const action = actionOpt.fold(() => ({}), action => ({ action }));
18776
      const common = {
18777
        buttonBehaviours: derive$1([
18778
          DisablingConfigs.button(() => !spec.enabled || providersBackstage.isDisabled()),
18779
          receivingConfig(),
18780
          Tabstopping.config({}),
18781
          config('button press', [
18782
            preventDefault('click'),
18783
            preventDefault('mousedown')
18784
          ])
18785
        ].concat(extraBehaviours)),
18786
        eventOrder: {
18787
          click: [
18788
            'button press',
18789
            'alloy.base.behaviour'
18790
          ],
18791
          mousedown: [
18792
            'button press',
18793
            'alloy.base.behaviour'
18794
          ]
18795
        },
18796
        ...action
18797
      };
18798
      const domFinal = deepMerge(common, { dom });
18799
      return deepMerge(domFinal, { components });
18800
    };
18801
    const renderIconButtonSpec = (spec, action, providersBackstage, extraBehaviours = []) => {
18802
      const tooltipAttributes = spec.tooltip.map(tooltip => ({
18803
        'aria-label': providersBackstage.translate(tooltip),
18804
        'title': providersBackstage.translate(tooltip)
18805
      })).getOr({});
18806
      const dom = {
18807
        tag: 'button',
18808
        classes: ['tox-tbtn'],
18809
        attributes: tooltipAttributes
18810
      };
18811
      const icon = spec.icon.map(iconName => renderIconFromPack$1(iconName, providersBackstage.icons));
18812
      const components = componentRenderPipeline([icon]);
18813
      return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
18814
    };
18815
    const calculateClassesFromButtonType = buttonType => {
18816
      switch (buttonType) {
18817
      case 'primary':
18818
        return ['tox-button'];
18819
      case 'toolbar':
18820
        return ['tox-tbtn'];
18821
      case 'secondary':
18822
      default:
18823
        return [
18824
          'tox-button',
18825
          'tox-button--secondary'
18826
        ];
18827
      }
18828
    };
18829
    const renderButtonSpec = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
18830
      const translatedText = providersBackstage.translate(spec.text);
18831
      const icon = spec.icon.map(iconName => renderIconFromPack$1(iconName, providersBackstage.icons));
18832
      const components = [icon.getOrThunk(() => text$2(translatedText))];
18833
      const buttonType = spec.buttonType.getOr(!spec.primary && !spec.borderless ? 'secondary' : 'primary');
18834
      const baseClasses = calculateClassesFromButtonType(buttonType);
18835
      const classes = [
18836
        ...baseClasses,
18837
        ...icon.isSome() ? ['tox-button--icon'] : [],
18838
        ...spec.borderless ? ['tox-button--naked'] : [],
18839
        ...extraClasses
18840
      ];
18841
      const dom = {
18842
        tag: 'button',
18843
        classes,
18844
        attributes: { title: translatedText }
18845
      };
18846
      return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
18847
    };
18848
    const renderButton$1 = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
18849
      const buttonSpec = renderButtonSpec(spec, Optional.some(action), providersBackstage, extraBehaviours, extraClasses);
18850
      return Button.sketch(buttonSpec);
18851
    };
18852
    const getAction = (name, buttonType) => comp => {
18853
      if (buttonType === 'custom') {
18854
        emitWith(comp, formActionEvent, {
18855
          name,
18856
          value: {}
18857
        });
18858
      } else if (buttonType === 'submit') {
18859
        emit(comp, formSubmitEvent);
18860
      } else if (buttonType === 'cancel') {
18861
        emit(comp, formCancelEvent);
18862
      } else {
18863
        console.error('Unknown button type: ', buttonType);
18864
      }
18865
    };
18866
    const isMenuFooterButtonSpec = (spec, buttonType) => buttonType === 'menu';
18867
    const isNormalFooterButtonSpec = (spec, buttonType) => buttonType === 'custom' || buttonType === 'cancel' || buttonType === 'submit';
18868
    const isToggleButtonSpec = (spec, buttonType) => buttonType === 'togglebutton';
18869
    const renderToggleButton = (spec, providers) => {
18870
      var _a, _b;
18871
      const optMemIcon = spec.icon.map(memIcon => renderReplaceableIconFromPack(memIcon, providers.icons)).map(record);
18872
      const action = comp => {
18873
        emitWith(comp, formActionEvent, {
18874
          name: spec.name,
18875
          value: {
18876
            setIcon: newIcon => {
18877
              optMemIcon.map(memIcon => memIcon.getOpt(comp).each(displayIcon => {
18878
                Replacing.set(displayIcon, [renderReplaceableIconFromPack(newIcon, providers.icons)]);
18879
              }));
18880
            }
18881
          }
18882
        });
18883
      };
18884
      const buttonType = spec.buttonType.getOr(!spec.primary ? 'secondary' : 'primary');
18885
      const buttonSpec = {
18886
        ...spec,
18887
        name: (_a = spec.name) !== null && _a !== void 0 ? _a : '',
18888
        primary: buttonType === 'primary',
18889
        tooltip: Optional.from(spec.tooltip),
18890
        enabled: (_b = spec.enabled) !== null && _b !== void 0 ? _b : false,
18891
        borderless: false
18892
      };
18893
      const tooltipAttributes = buttonSpec.tooltip.map(tooltip => ({
18894
        'aria-label': providers.translate(tooltip),
18895
        'title': providers.translate(tooltip)
18896
      })).getOr({});
18897
      const buttonTypeClasses = calculateClassesFromButtonType(buttonType !== null && buttonType !== void 0 ? buttonType : 'secondary');
18898
      const showIconAndText = spec.icon.isSome() && spec.text.isSome();
18899
      const dom = {
18900
        tag: 'button',
18901
        classes: [
18902
          ...buttonTypeClasses.concat(spec.icon.isSome() ? ['tox-button--icon'] : []),
18903
          ...spec.active ? ['tox-button--enabled'] : [],
18904
          ...showIconAndText ? ['tox-button--icon-and-text'] : []
18905
        ],
18906
        attributes: tooltipAttributes
18907
      };
18908
      const extraBehaviours = [];
18909
      const translatedText = providers.translate(spec.text.getOr(''));
18910
      const translatedTextComponed = text$2(translatedText);
18911
      const iconComp = componentRenderPipeline([optMemIcon.map(memIcon => memIcon.asSpec())]);
18912
      const components = [
18913
        ...iconComp,
18914
        ...spec.text.isSome() ? [translatedTextComponed] : []
18915
      ];
18916
      const iconButtonSpec = renderCommonSpec(buttonSpec, Optional.some(action), extraBehaviours, dom, components, providers);
18917
      return Button.sketch(iconButtonSpec);
18918
    };
18919
    const renderFooterButton = (spec, buttonType, backstage) => {
18920
      if (isMenuFooterButtonSpec(spec, buttonType)) {
18921
        const getButton = () => memButton;
18922
        const menuButtonSpec = spec;
18923
        const fixedSpec = {
18924
          ...spec,
18925
          type: 'menubutton',
18926
          search: Optional.none(),
18927
          onSetup: api => {
18928
            api.setEnabled(spec.enabled);
18929
            return noop;
18930
          },
18931
          fetch: getFetch(menuButtonSpec.items, getButton, backstage)
18932
        };
18933
        const memButton = record(renderMenuButton(fixedSpec, 'tox-tbtn', backstage, Optional.none()));
18934
        return memButton.asSpec();
18935
      } else if (isNormalFooterButtonSpec(spec, buttonType)) {
18936
        const action = getAction(spec.name, buttonType);
18937
        const buttonSpec = {
18938
          ...spec,
18939
          borderless: false
18940
        };
18941
        return renderButton$1(buttonSpec, action, backstage.shared.providers, []);
18942
      } else if (isToggleButtonSpec(spec, buttonType)) {
18943
        return renderToggleButton(spec, backstage.shared.providers);
18944
      } else {
18945
        console.error('Unknown footer button type: ', buttonType);
18946
        throw new Error('Unknown footer button type');
18947
      }
18948
    };
18949
    const renderDialogButton = (spec, providersBackstage) => {
18950
      const action = getAction(spec.name, 'custom');
18951
      return renderFormField(Optional.none(), FormField.parts.field({
18952
        factory: Button,
18953
        ...renderButtonSpec(spec, Optional.some(action), providersBackstage, [
18954
          memory(''),
18955
          ComposingConfigs.self()
18956
        ])
18957
      }));
18958
    };
18959
 
18960
    const separator$1 = { type: 'separator' };
18961
    const toMenuItem = target => ({
18962
      type: 'menuitem',
18963
      value: target.url,
18964
      text: target.title,
18965
      meta: { attach: target.attach },
18966
      onAction: noop
18967
    });
18968
    const staticMenuItem = (title, url) => ({
18969
      type: 'menuitem',
18970
      value: url,
18971
      text: title,
18972
      meta: { attach: undefined },
18973
      onAction: noop
18974
    });
18975
    const toMenuItems = targets => map$2(targets, toMenuItem);
18976
    const filterLinkTargets = (type, targets) => filter$2(targets, target => target.type === type);
18977
    const filteredTargets = (type, targets) => toMenuItems(filterLinkTargets(type, targets));
18978
    const headerTargets = linkInfo => filteredTargets('header', linkInfo.targets);
18979
    const anchorTargets = linkInfo => filteredTargets('anchor', linkInfo.targets);
18980
    const anchorTargetTop = linkInfo => Optional.from(linkInfo.anchorTop).map(url => staticMenuItem('<top>', url)).toArray();
18981
    const anchorTargetBottom = linkInfo => Optional.from(linkInfo.anchorBottom).map(url => staticMenuItem('<bottom>', url)).toArray();
18982
    const historyTargets = history => map$2(history, url => staticMenuItem(url, url));
18983
    const joinMenuLists = items => {
18984
      return foldl(items, (a, b) => {
18985
        const bothEmpty = a.length === 0 || b.length === 0;
18986
        return bothEmpty ? a.concat(b) : a.concat(separator$1, b);
18987
      }, []);
18988
    };
18989
    const filterByQuery = (term, menuItems) => {
18990
      const lowerCaseTerm = term.toLowerCase();
18991
      return filter$2(menuItems, item => {
18992
        var _a;
18993
        const text = item.meta !== undefined && item.meta.text !== undefined ? item.meta.text : item.text;
18994
        const value = (_a = item.value) !== null && _a !== void 0 ? _a : '';
18995
        return contains$1(text.toLowerCase(), lowerCaseTerm) || contains$1(value.toLowerCase(), lowerCaseTerm);
18996
      });
18997
    };
18998
 
18999
    const getItems = (fileType, input, urlBackstage) => {
19000
      var _a, _b;
19001
      const urlInputValue = Representing.getValue(input);
19002
      const term = (_b = (_a = urlInputValue === null || urlInputValue === void 0 ? void 0 : urlInputValue.meta) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : urlInputValue.value;
19003
      const info = urlBackstage.getLinkInformation();
19004
      return info.fold(() => [], linkInfo => {
19005
        const history = filterByQuery(term, historyTargets(urlBackstage.getHistory(fileType)));
19006
        return fileType === 'file' ? joinMenuLists([
19007
          history,
19008
          filterByQuery(term, headerTargets(linkInfo)),
19009
          filterByQuery(term, flatten([
19010
            anchorTargetTop(linkInfo),
19011
            anchorTargets(linkInfo),
19012
            anchorTargetBottom(linkInfo)
19013
          ]))
19014
        ]) : history;
19015
      });
19016
    };
19017
    const errorId = generate$6('aria-invalid');
19018
    const renderUrlInput = (spec, backstage, urlBackstage, initialData) => {
19019
      const providersBackstage = backstage.shared.providers;
19020
      const updateHistory = component => {
19021
        const urlEntry = Representing.getValue(component);
19022
        urlBackstage.addToHistory(urlEntry.value, spec.filetype);
19023
      };
19024
      const typeaheadSpec = {
19025
        ...initialData.map(initialData => ({ initialData })).getOr({}),
19026
        dismissOnBlur: true,
19027
        inputClasses: ['tox-textfield'],
19028
        sandboxClasses: ['tox-dialog__popups'],
19029
        inputAttributes: {
19030
          'aria-errormessage': errorId,
19031
          'type': 'url'
19032
        },
19033
        minChars: 0,
19034
        responseTime: 0,
19035
        fetch: input => {
19036
          const items = getItems(spec.filetype, input, urlBackstage);
19037
          const tdata = build(items, ItemResponse$1.BUBBLE_TO_SANDBOX, backstage, {
19038
            isHorizontalMenu: false,
19039
            search: Optional.none()
19040
          });
19041
          return Future.pure(tdata);
19042
        },
19043
        getHotspot: comp => memUrlBox.getOpt(comp),
19044
        onSetValue: (comp, _newValue) => {
19045
          if (comp.hasConfigured(Invalidating)) {
19046
            Invalidating.run(comp).get(noop);
19047
          }
19048
        },
19049
        typeaheadBehaviours: derive$1([
19050
          ...urlBackstage.getValidationHandler().map(handler => Invalidating.config({
19051
            getRoot: comp => parentElement(comp.element),
19052
            invalidClass: 'tox-control-wrap--status-invalid',
19053
            notify: {
19054
              onInvalid: (comp, err) => {
19055
                memInvalidIcon.getOpt(comp).each(invalidComp => {
19056
                  set$9(invalidComp.element, 'title', providersBackstage.translate(err));
19057
                });
19058
              }
19059
            },
19060
            validator: {
19061
              validate: input => {
19062
                const urlEntry = Representing.getValue(input);
19063
                return FutureResult.nu(completer => {
19064
                  handler({
19065
                    type: spec.filetype,
19066
                    url: urlEntry.value
19067
                  }, validation => {
19068
                    if (validation.status === 'invalid') {
19069
                      const err = Result.error(validation.message);
19070
                      completer(err);
19071
                    } else {
19072
                      const val = Result.value(validation.message);
19073
                      completer(val);
19074
                    }
19075
                  });
19076
                });
19077
              },
19078
              validateOnLoad: false
19079
            }
19080
          })).toArray(),
19081
          Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
19082
          Tabstopping.config({}),
19083
          config('urlinput-events', [
19084
            run$1(input(), comp => {
19085
              const currentValue = get$6(comp.element);
19086
              const trimmedValue = currentValue.trim();
19087
              if (trimmedValue !== currentValue) {
19088
                set$5(comp.element, trimmedValue);
19089
              }
19090
              if (spec.filetype === 'file') {
19091
                emitWith(comp, formChangeEvent, { name: spec.name });
19092
              }
19093
            }),
19094
            run$1(change(), comp => {
19095
              emitWith(comp, formChangeEvent, { name: spec.name });
19096
              updateHistory(comp);
19097
            }),
19098
            run$1(postPaste(), comp => {
19099
              emitWith(comp, formChangeEvent, { name: spec.name });
19100
              updateHistory(comp);
19101
            })
19102
          ])
19103
        ]),
19104
        eventOrder: {
19105
          [input()]: [
19106
            'streaming',
19107
            'urlinput-events',
19108
            'invalidating'
19109
          ]
19110
        },
19111
        model: {
19112
          getDisplayText: itemData => itemData.value,
19113
          selectsOver: false,
19114
          populateFromBrowse: false
19115
        },
19116
        markers: { openClass: 'tox-textfield--popup-open' },
19117
        lazySink: backstage.shared.getSink,
19118
        parts: { menu: part(false, 1, 'normal') },
19119
        onExecute: (_menu, component, _entry) => {
19120
          emitWith(component, formSubmitEvent, {});
19121
        },
19122
        onItemExecute: (typeahead, _sandbox, _item, _value) => {
19123
          updateHistory(typeahead);
19124
          emitWith(typeahead, formChangeEvent, { name: spec.name });
19125
        }
19126
      };
19127
      const pField = FormField.parts.field({
19128
        ...typeaheadSpec,
19129
        factory: Typeahead
19130
      });
19131
      const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
19132
      const makeIcon = (name, errId, icon = name, label = name) => render$3(icon, {
19133
        tag: 'div',
19134
        classes: [
19135
          'tox-icon',
19136
          'tox-control-wrap__status-icon-' + name
19137
        ],
19138
        attributes: {
19139
          'title': providersBackstage.translate(label),
19140
          'aria-live': 'polite',
19141
          ...errId.fold(() => ({}), id => ({ id }))
19142
        }
19143
      }, providersBackstage.icons);
19144
      const memInvalidIcon = record(makeIcon('invalid', Optional.some(errorId), 'warning'));
19145
      const memStatus = record({
19146
        dom: {
19147
          tag: 'div',
19148
          classes: ['tox-control-wrap__status-icon-wrap']
19149
        },
19150
        components: [memInvalidIcon.asSpec()]
19151
      });
19152
      const optUrlPicker = urlBackstage.getUrlPicker(spec.filetype);
19153
      const browseUrlEvent = generate$6('browser.url.event');
19154
      const memUrlBox = record({
19155
        dom: {
19156
          tag: 'div',
19157
          classes: ['tox-control-wrap']
19158
        },
19159
        components: [
19160
          pField,
19161
          memStatus.asSpec()
19162
        ],
19163
        behaviours: derive$1([Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() })])
19164
      });
19165
      const memUrlPickerButton = record(renderButton$1({
19166
        name: spec.name,
19167
        icon: Optional.some('browse'),
19168
        text: spec.picker_text.or(spec.label).getOr(''),
19169
        enabled: spec.enabled,
19170
        primary: false,
19171
        buttonType: Optional.none(),
19172
        borderless: true
19173
      }, component => emit(component, browseUrlEvent), providersBackstage, [], ['tox-browse-url']));
19174
      const controlHWrapper = () => ({
19175
        dom: {
19176
          tag: 'div',
19177
          classes: ['tox-form__controls-h-stack']
19178
        },
19179
        components: flatten([
19180
          [memUrlBox.asSpec()],
19181
          optUrlPicker.map(() => memUrlPickerButton.asSpec()).toArray()
19182
        ])
19183
      });
19184
      const openUrlPicker = comp => {
19185
        Composing.getCurrent(comp).each(field => {
19186
          const componentData = Representing.getValue(field);
19187
          const urlData = {
19188
            fieldname: spec.name,
19189
            ...componentData
19190
          };
19191
          optUrlPicker.each(picker => {
19192
            picker(urlData).get(chosenData => {
19193
              Representing.setValue(field, chosenData);
19194
              emitWith(comp, formChangeEvent, { name: spec.name });
19195
            });
19196
          });
19197
        });
19198
      };
19199
      return FormField.sketch({
19200
        dom: renderFormFieldDom(),
19201
        components: pLabel.toArray().concat([controlHWrapper()]),
19202
        fieldBehaviours: derive$1([
19203
          Disabling.config({
19204
            disabled: () => !spec.enabled || providersBackstage.isDisabled(),
19205
            onDisabled: comp => {
19206
              FormField.getField(comp).each(Disabling.disable);
19207
              memUrlPickerButton.getOpt(comp).each(Disabling.disable);
19208
            },
19209
            onEnabled: comp => {
19210
              FormField.getField(comp).each(Disabling.enable);
19211
              memUrlPickerButton.getOpt(comp).each(Disabling.enable);
19212
            }
19213
          }),
19214
          receivingConfig(),
19215
          config('url-input-events', [run$1(browseUrlEvent, openUrlPicker)])
19216
        ])
19217
      });
19218
    };
19219
 
19220
    const renderAlertBanner = (spec, providersBackstage) => {
19221
      const icon = get$2(spec.icon, providersBackstage.icons);
19222
      return Container.sketch({
19223
        dom: {
19224
          tag: 'div',
19225
          attributes: { role: 'alert' },
19226
          classes: [
19227
            'tox-notification',
19228
            'tox-notification--in',
19229
            `tox-notification--${ spec.level }`
19230
          ]
19231
        },
19232
        components: [
19233
          {
19234
            dom: {
19235
              tag: 'div',
19236
              classes: ['tox-notification__icon'],
19237
              innerHtml: !spec.url ? icon : undefined
19238
            },
19239
            components: spec.url ? [Button.sketch({
19240
                dom: {
19241
                  tag: 'button',
19242
                  classes: [
19243
                    'tox-button',
19244
                    'tox-button--naked',
19245
                    'tox-button--icon'
19246
                  ],
19247
                  innerHtml: icon,
19248
                  attributes: { title: providersBackstage.translate(spec.iconTooltip) }
19249
                },
19250
                action: comp => emitWith(comp, formActionEvent, {
19251
                  name: 'alert-banner',
19252
                  value: spec.url
19253
                }),
19254
                buttonBehaviours: derive$1([addFocusableBehaviour()])
19255
              })] : undefined
19256
          },
19257
          {
19258
            dom: {
19259
              tag: 'div',
19260
              classes: ['tox-notification__body'],
19261
              innerHtml: providersBackstage.translate(spec.text)
19262
            }
19263
          }
19264
        ]
19265
      });
19266
    };
19267
 
19268
    const set$1 = (element, status) => {
19269
      element.dom.checked = status;
19270
    };
19271
    const get$1 = element => element.dom.checked;
19272
 
19273
    const renderCheckbox = (spec, providerBackstage, initialData) => {
19274
      const toggleCheckboxHandler = comp => {
19275
        comp.element.dom.click();
19276
        return Optional.some(true);
19277
      };
19278
      const pField = FormField.parts.field({
19279
        factory: { sketch: identity },
19280
        dom: {
19281
          tag: 'input',
19282
          classes: ['tox-checkbox__input'],
19283
          attributes: { type: 'checkbox' }
19284
        },
19285
        behaviours: derive$1([
19286
          ComposingConfigs.self(),
19287
          Disabling.config({
19288
            disabled: () => !spec.enabled || providerBackstage.isDisabled(),
19289
            onDisabled: component => {
19290
              parentElement(component.element).each(element => add$2(element, 'tox-checkbox--disabled'));
19291
            },
19292
            onEnabled: component => {
19293
              parentElement(component.element).each(element => remove$2(element, 'tox-checkbox--disabled'));
19294
            }
19295
          }),
19296
          Tabstopping.config({}),
19297
          Focusing.config({}),
19298
          withElement(initialData, get$1, set$1),
19299
          Keying.config({
19300
            mode: 'special',
19301
            onEnter: toggleCheckboxHandler,
19302
            onSpace: toggleCheckboxHandler,
19303
            stopSpaceKeyup: true
19304
          }),
19305
          config('checkbox-events', [run$1(change(), (component, _) => {
19306
              emitWith(component, formChangeEvent, { name: spec.name });
19307
            })])
19308
        ])
19309
      });
19310
      const pLabel = FormField.parts.label({
19311
        dom: {
19312
          tag: 'span',
19313
          classes: ['tox-checkbox__label']
19314
        },
19315
        components: [text$2(providerBackstage.translate(spec.label))],
19316
        behaviours: derive$1([Unselecting.config({})])
19317
      });
19318
      const makeIcon = className => {
19319
        const iconName = className === 'checked' ? 'selected' : 'unselected';
19320
        return render$3(iconName, {
19321
          tag: 'span',
19322
          classes: [
19323
            'tox-icon',
19324
            'tox-checkbox-icon__' + className
19325
          ]
19326
        }, providerBackstage.icons);
19327
      };
19328
      const memIcons = record({
19329
        dom: {
19330
          tag: 'div',
19331
          classes: ['tox-checkbox__icons']
19332
        },
19333
        components: [
19334
          makeIcon('checked'),
19335
          makeIcon('unchecked')
19336
        ]
19337
      });
19338
      return FormField.sketch({
19339
        dom: {
19340
          tag: 'label',
19341
          classes: ['tox-checkbox']
19342
        },
19343
        components: [
19344
          pField,
19345
          memIcons.asSpec(),
19346
          pLabel
19347
        ],
19348
        fieldBehaviours: derive$1([
19349
          Disabling.config({ disabled: () => !spec.enabled || providerBackstage.isDisabled() }),
19350
          receivingConfig()
19351
        ])
19352
      });
19353
    };
19354
 
19355
    const renderHtmlPanel = spec => {
19356
      if (spec.presets === 'presentation') {
19357
        return Container.sketch({
19358
          dom: {
19359
            tag: 'div',
19360
            classes: ['tox-form__group'],
19361
            innerHtml: spec.html
19362
          }
19363
        });
19364
      } else {
19365
        return Container.sketch({
19366
          dom: {
19367
            tag: 'div',
19368
            classes: ['tox-form__group'],
19369
            innerHtml: spec.html,
19370
            attributes: { role: 'document' }
19371
          },
19372
          containerBehaviours: derive$1([
19373
            Tabstopping.config({}),
19374
            Focusing.config({})
19375
          ])
19376
        });
19377
      }
19378
    };
19379
 
19380
    const make$2 = render => {
19381
      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))));
19382
    };
19383
    const makeIframe = render => (parts, spec, dialogData, backstage) => {
19384
      const iframeSpec = deepMerge(spec, { source: 'dynamic' });
19385
      return make$2(render)(parts, iframeSpec, dialogData, backstage);
19386
    };
19387
    const factories = {
19388
      bar: make$2((spec, backstage) => renderBar(spec, backstage.shared)),
19389
      collection: make$2((spec, backstage, data) => renderCollection(spec, backstage.shared.providers, data)),
19390
      alertbanner: make$2((spec, backstage) => renderAlertBanner(spec, backstage.shared.providers)),
19391
      input: make$2((spec, backstage, data) => renderInput(spec, backstage.shared.providers, data)),
19392
      textarea: make$2((spec, backstage, data) => renderTextarea(spec, backstage.shared.providers, data)),
19393
      label: make$2((spec, backstage) => renderLabel$2(spec, backstage.shared)),
19394
      iframe: makeIframe((spec, backstage, data) => renderIFrame(spec, backstage.shared.providers, data)),
19395
      button: make$2((spec, backstage) => renderDialogButton(spec, backstage.shared.providers)),
19396
      checkbox: make$2((spec, backstage, data) => renderCheckbox(spec, backstage.shared.providers, data)),
19397
      colorinput: make$2((spec, backstage, data) => renderColorInput(spec, backstage.shared, backstage.colorinput, data)),
19398
      colorpicker: make$2((spec, backstage, data) => renderColorPicker(spec, backstage.shared.providers, data)),
19399
      dropzone: make$2((spec, backstage, data) => renderDropZone(spec, backstage.shared.providers, data)),
19400
      grid: make$2((spec, backstage) => renderGrid(spec, backstage.shared)),
19401
      listbox: make$2((spec, backstage, data) => renderListBox(spec, backstage, data)),
19402
      selectbox: make$2((spec, backstage, data) => renderSelectBox(spec, backstage.shared.providers, data)),
19403
      sizeinput: make$2((spec, backstage) => renderSizeInput(spec, backstage.shared.providers)),
19404
      slider: make$2((spec, backstage, data) => renderSlider(spec, backstage.shared.providers, data)),
19405
      urlinput: make$2((spec, backstage, data) => renderUrlInput(spec, backstage, backstage.urlinput, data)),
19406
      customeditor: make$2(renderCustomEditor),
19407
      htmlpanel: make$2(renderHtmlPanel),
19408
      imagepreview: make$2((spec, _, data) => renderImagePreview(spec, data)),
19409
      table: make$2((spec, backstage) => renderTable(spec, backstage.shared.providers)),
19410
      tree: make$2((spec, backstage) => renderTree(spec, backstage)),
19411
      panel: make$2((spec, backstage) => renderPanel(spec, backstage))
19412
    };
19413
    const noFormParts = {
19414
      field: (_name, spec) => spec,
19415
      record: constant$1([])
19416
    };
19417
    const interpretInForm = (parts, spec, dialogData, oldBackstage) => {
19418
      const newBackstage = deepMerge(oldBackstage, { shared: { interpreter: childSpec => interpretParts(parts, childSpec, dialogData, newBackstage) } });
19419
      return interpretParts(parts, spec, dialogData, newBackstage);
19420
    };
19421
    const interpretParts = (parts, spec, dialogData, backstage) => get$g(factories, spec.type).fold(() => {
19422
      console.error(`Unknown factory type "${ spec.type }", defaulting to container: `, spec);
19423
      return spec;
19424
    }, factory => factory(parts, spec, dialogData, backstage));
19425
    const interpretWithoutForm = (spec, dialogData, backstage) => interpretParts(noFormParts, spec, dialogData, backstage);
19426
 
19427
    const labelPrefix = 'layout-inset';
19428
    const westEdgeX = anchor => anchor.x;
19429
    const middleX = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
19430
    const eastEdgeX = (anchor, element) => anchor.x + anchor.width - element.width;
19431
    const northY = anchor => anchor.y;
19432
    const southY = (anchor, element) => anchor.y + anchor.height - element.height;
19433
    const centreY = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
19434
    const southwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), southY(anchor, element), bubbles.insetSouthwest(), northwest$3(), 'southwest', boundsRestriction(anchor, {
19435
      right: 0,
19436
      bottom: 3
19437
    }), labelPrefix);
19438
    const southeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), southY(anchor, element), bubbles.insetSoutheast(), northeast$3(), 'southeast', boundsRestriction(anchor, {
19439
      left: 1,
19440
      bottom: 3
19441
    }), labelPrefix);
19442
    const northwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), northY(anchor), bubbles.insetNorthwest(), southwest$3(), 'northwest', boundsRestriction(anchor, {
19443
      right: 0,
19444
      top: 2
19445
    }), labelPrefix);
19446
    const northeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), northY(anchor), bubbles.insetNortheast(), southeast$3(), 'northeast', boundsRestriction(anchor, {
19447
      left: 1,
19448
      top: 2
19449
    }), labelPrefix);
19450
    const north = (anchor, element, bubbles) => nu$6(middleX(anchor, element), northY(anchor), bubbles.insetNorth(), south$3(), 'north', boundsRestriction(anchor, { top: 2 }), labelPrefix);
19451
    const south = (anchor, element, bubbles) => nu$6(middleX(anchor, element), southY(anchor, element), bubbles.insetSouth(), north$3(), 'south', boundsRestriction(anchor, { bottom: 3 }), labelPrefix);
19452
    const east = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), centreY(anchor, element), bubbles.insetEast(), west$3(), 'east', boundsRestriction(anchor, { right: 0 }), labelPrefix);
19453
    const west = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), centreY(anchor, element), bubbles.insetWest(), east$3(), 'west', boundsRestriction(anchor, { left: 1 }), labelPrefix);
19454
    const lookupPreserveLayout = lastPlacement => {
19455
      switch (lastPlacement) {
19456
      case 'north':
19457
        return north;
19458
      case 'northeast':
19459
        return northeast;
19460
      case 'northwest':
19461
        return northwest;
19462
      case 'south':
19463
        return south;
19464
      case 'southeast':
19465
        return southeast;
19466
      case 'southwest':
19467
        return southwest;
19468
      case 'east':
19469
        return east;
19470
      case 'west':
19471
        return west;
19472
      }
19473
    };
19474
    const preserve = (anchor, element, bubbles, placee, bounds) => {
19475
      const layout = getPlacement(placee).map(lookupPreserveLayout).getOr(north);
19476
      return layout(anchor, element, bubbles, placee, bounds);
19477
    };
19478
    const lookupFlippedLayout = lastPlacement => {
19479
      switch (lastPlacement) {
19480
      case 'north':
19481
        return south;
19482
      case 'northeast':
19483
        return southeast;
19484
      case 'northwest':
19485
        return southwest;
19486
      case 'south':
19487
        return north;
19488
      case 'southeast':
19489
        return northeast;
19490
      case 'southwest':
19491
        return northwest;
19492
      case 'east':
19493
        return west;
19494
      case 'west':
19495
        return east;
19496
      }
19497
    };
19498
    const flip = (anchor, element, bubbles, placee, bounds) => {
19499
      const layout = getPlacement(placee).map(lookupFlippedLayout).getOr(north);
19500
      return layout(anchor, element, bubbles, placee, bounds);
19501
    };
19502
 
19503
    const bubbleAlignments$2 = {
19504
      valignCentre: [],
19505
      alignCentre: [],
19506
      alignLeft: [],
19507
      alignRight: [],
19508
      right: [],
19509
      left: [],
19510
      bottom: [],
19511
      top: []
19512
    };
19513
    const getInlineDialogAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
19514
      const bubbleSize = 12;
19515
      const overrides = { maxHeightFunction: expandable$1() };
19516
      const editableAreaAnchor = () => ({
19517
        type: 'node',
19518
        root: getContentContainer(getRootNode(contentAreaElement())),
19519
        node: Optional.from(contentAreaElement()),
19520
        bubble: nu$5(bubbleSize, bubbleSize, bubbleAlignments$2),
19521
        layouts: {
19522
          onRtl: () => [northeast],
19523
          onLtr: () => [northwest]
19524
        },
19525
        overrides
19526
      });
19527
      const standardAnchor = () => ({
19528
        type: 'hotspot',
19529
        hotspot: lazyAnchorbar(),
19530
        bubble: nu$5(-bubbleSize, bubbleSize, bubbleAlignments$2),
19531
        layouts: {
19532
          onRtl: () => [
19533
            southeast$2,
19534
            southwest$2,
19535
            south$2
19536
          ],
19537
          onLtr: () => [
19538
            southwest$2,
19539
            southeast$2,
19540
            south$2
19541
          ]
19542
        },
19543
        overrides
19544
      });
19545
      return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
19546
    };
19547
    const getInlineBottomDialogAnchor = (inline, contentAreaElement, lazyBottomAnchorBar, lazyUseEditableAreaAnchor) => {
19548
      const bubbleSize = 12;
19549
      const overrides = { maxHeightFunction: expandable$1() };
19550
      const editableAreaAnchor = () => ({
19551
        type: 'node',
19552
        root: getContentContainer(getRootNode(contentAreaElement())),
19553
        node: Optional.from(contentAreaElement()),
19554
        bubble: nu$5(bubbleSize, bubbleSize, bubbleAlignments$2),
19555
        layouts: {
19556
          onRtl: () => [north],
19557
          onLtr: () => [north]
19558
        },
19559
        overrides
19560
      });
19561
      const standardAnchor = () => inline ? {
19562
        type: 'node',
19563
        root: getContentContainer(getRootNode(contentAreaElement())),
19564
        node: Optional.from(contentAreaElement()),
19565
        bubble: nu$5(0, -getOuter$2(contentAreaElement()), bubbleAlignments$2),
19566
        layouts: {
19567
          onRtl: () => [north$2],
19568
          onLtr: () => [north$2]
19569
        },
19570
        overrides
19571
      } : {
19572
        type: 'hotspot',
19573
        hotspot: lazyBottomAnchorBar(),
19574
        bubble: nu$5(0, 0, bubbleAlignments$2),
19575
        layouts: {
19576
          onRtl: () => [north$2],
19577
          onLtr: () => [north$2]
19578
        },
19579
        overrides
19580
      };
19581
      return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
19582
    };
19583
    const getBannerAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
19584
      const editableAreaAnchor = () => ({
19585
        type: 'node',
19586
        root: getContentContainer(getRootNode(contentAreaElement())),
19587
        node: Optional.from(contentAreaElement()),
19588
        layouts: {
19589
          onRtl: () => [north],
19590
          onLtr: () => [north]
19591
        }
19592
      });
19593
      const standardAnchor = () => ({
19594
        type: 'hotspot',
19595
        hotspot: lazyAnchorbar(),
19596
        layouts: {
19597
          onRtl: () => [south$2],
19598
          onLtr: () => [south$2]
19599
        }
19600
      });
19601
      return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
19602
    };
19603
    const getCursorAnchor = (editor, bodyElement) => () => ({
19604
      type: 'selection',
19605
      root: bodyElement(),
19606
      getSelection: () => {
19607
        const rng = editor.selection.getRng();
19608
        const selectedCells = editor.model.table.getSelectedCells();
19609
        if (selectedCells.length > 1) {
19610
          const firstCell = selectedCells[0];
19611
          const lastCell = selectedCells[selectedCells.length - 1];
19612
          const selectionTableCellRange = {
19613
            firstCell: SugarElement.fromDom(firstCell),
19614
            lastCell: SugarElement.fromDom(lastCell)
19615
          };
19616
          return Optional.some(selectionTableCellRange);
19617
        }
19618
        return Optional.some(SimSelection.range(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
19619
      }
19620
    });
19621
    const getNodeAnchor$1 = bodyElement => element => ({
19622
      type: 'node',
19623
      root: bodyElement(),
19624
      node: element
19625
    });
19626
    const getAnchors = (editor, lazyAnchorbar, lazyBottomAnchorBar, isToolbarTop) => {
19627
      const useFixedToolbarContainer = useFixedContainer(editor);
19628
      const bodyElement = () => SugarElement.fromDom(editor.getBody());
19629
      const contentAreaElement = () => SugarElement.fromDom(editor.getContentAreaContainer());
19630
      const lazyUseEditableAreaAnchor = () => useFixedToolbarContainer || !isToolbarTop();
19631
      return {
19632
        inlineDialog: getInlineDialogAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
19633
        inlineBottomDialog: getInlineBottomDialogAnchor(editor.inline, contentAreaElement, lazyBottomAnchorBar, lazyUseEditableAreaAnchor),
19634
        banner: getBannerAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
19635
        cursor: getCursorAnchor(editor, bodyElement),
19636
        node: getNodeAnchor$1(bodyElement)
19637
      };
19638
    };
19639
 
19640
    const colorPicker = editor => (callback, value) => {
19641
      const dialog = colorPickerDialog(editor);
19642
      dialog(callback, value);
19643
    };
19644
    const hasCustomColors = editor => () => hasCustomColors$1(editor);
19645
    const getColors = editor => id => getColors$2(editor, id);
19646
    const getColorCols = editor => id => getColorCols$1(editor, id);
19647
    const ColorInputBackstage = editor => ({
19648
      colorPicker: colorPicker(editor),
19649
      hasCustomColors: hasCustomColors(editor),
19650
      getColors: getColors(editor),
19651
      getColorCols: getColorCols(editor)
19652
    });
19653
 
19654
    const isDraggableModal = editor => () => isDraggableModal$1(editor);
19655
    const DialogBackstage = editor => ({ isDraggableModal: isDraggableModal(editor) });
19656
 
19657
    const HeaderBackstage = editor => {
19658
      const mode = Cell(isToolbarLocationBottom(editor) ? 'bottom' : 'top');
19659
      return {
19660
        isPositionedAtTop: () => mode.get() === 'top',
19661
        getDockingMode: mode.get,
19662
        setDockingMode: mode.set
19663
      };
19664
    };
19665
 
19666
    const isNestedFormat = format => hasNonNullableKey(format, 'items');
19667
    const isFormatReference = format => hasNonNullableKey(format, 'format');
19668
    const defaultStyleFormats = [
19669
      {
19670
        title: 'Headings',
19671
        items: [
19672
          {
19673
            title: 'Heading 1',
19674
            format: 'h1'
19675
          },
19676
          {
19677
            title: 'Heading 2',
19678
            format: 'h2'
19679
          },
19680
          {
19681
            title: 'Heading 3',
19682
            format: 'h3'
19683
          },
19684
          {
19685
            title: 'Heading 4',
19686
            format: 'h4'
19687
          },
19688
          {
19689
            title: 'Heading 5',
19690
            format: 'h5'
19691
          },
19692
          {
19693
            title: 'Heading 6',
19694
            format: 'h6'
19695
          }
19696
        ]
19697
      },
19698
      {
19699
        title: 'Inline',
19700
        items: [
19701
          {
19702
            title: 'Bold',
19703
            format: 'bold'
19704
          },
19705
          {
19706
            title: 'Italic',
19707
            format: 'italic'
19708
          },
19709
          {
19710
            title: 'Underline',
19711
            format: 'underline'
19712
          },
19713
          {
19714
            title: 'Strikethrough',
19715
            format: 'strikethrough'
19716
          },
19717
          {
19718
            title: 'Superscript',
19719
            format: 'superscript'
19720
          },
19721
          {
19722
            title: 'Subscript',
19723
            format: 'subscript'
19724
          },
19725
          {
19726
            title: 'Code',
19727
            format: 'code'
19728
          }
19729
        ]
19730
      },
19731
      {
19732
        title: 'Blocks',
19733
        items: [
19734
          {
19735
            title: 'Paragraph',
19736
            format: 'p'
19737
          },
19738
          {
19739
            title: 'Blockquote',
19740
            format: 'blockquote'
19741
          },
19742
          {
19743
            title: 'Div',
19744
            format: 'div'
19745
          },
19746
          {
19747
            title: 'Pre',
19748
            format: 'pre'
19749
          }
19750
        ]
19751
      },
19752
      {
19753
        title: 'Align',
19754
        items: [
19755
          {
19756
            title: 'Left',
19757
            format: 'alignleft'
19758
          },
19759
          {
19760
            title: 'Center',
19761
            format: 'aligncenter'
19762
          },
19763
          {
19764
            title: 'Right',
19765
            format: 'alignright'
19766
          },
19767
          {
19768
            title: 'Justify',
19769
            format: 'alignjustify'
19770
          }
19771
        ]
19772
      }
19773
    ];
19774
    const isNestedFormats = format => has$2(format, 'items');
19775
    const isBlockFormat = format => has$2(format, 'block');
19776
    const isInlineFormat = format => has$2(format, 'inline');
19777
    const isSelectorFormat = format => has$2(format, 'selector');
19778
    const mapFormats = userFormats => foldl(userFormats, (acc, fmt) => {
19779
      if (isNestedFormats(fmt)) {
19780
        const result = mapFormats(fmt.items);
19781
        return {
19782
          customFormats: acc.customFormats.concat(result.customFormats),
19783
          formats: acc.formats.concat([{
19784
              title: fmt.title,
19785
              items: result.formats
19786
            }])
19787
        };
19788
      } else if (isInlineFormat(fmt) || isBlockFormat(fmt) || isSelectorFormat(fmt)) {
19789
        const formatName = isString(fmt.name) ? fmt.name : fmt.title.toLowerCase();
19790
        const formatNameWithPrefix = `custom-${ formatName }`;
19791
        return {
19792
          customFormats: acc.customFormats.concat([{
19793
              name: formatNameWithPrefix,
19794
              format: fmt
19795
            }]),
19796
          formats: acc.formats.concat([{
19797
              title: fmt.title,
19798
              format: formatNameWithPrefix,
19799
              icon: fmt.icon
19800
            }])
19801
        };
19802
      } else {
19803
        return {
19804
          ...acc,
19805
          formats: acc.formats.concat(fmt)
19806
        };
19807
      }
19808
    }, {
19809
      customFormats: [],
19810
      formats: []
19811
    });
19812
    const registerCustomFormats = (editor, userFormats) => {
19813
      const result = mapFormats(userFormats);
19814
      const registerFormats = customFormats => {
19815
        each$1(customFormats, fmt => {
19816
          if (!editor.formatter.has(fmt.name)) {
19817
            editor.formatter.register(fmt.name, fmt.format);
19818
          }
19819
        });
19820
      };
19821
      if (editor.formatter) {
19822
        registerFormats(result.customFormats);
19823
      } else {
19824
        editor.on('init', () => {
19825
          registerFormats(result.customFormats);
19826
        });
19827
      }
19828
      return result.formats;
19829
    };
19830
    const getStyleFormats = editor => getUserStyleFormats(editor).map(userFormats => {
19831
      const registeredUserFormats = registerCustomFormats(editor, userFormats);
19832
      return shouldMergeStyleFormats(editor) ? defaultStyleFormats.concat(registeredUserFormats) : registeredUserFormats;
19833
    }).getOr(defaultStyleFormats);
19834
 
19835
    const isSeparator$1 = format => {
19836
      const keys$1 = keys(format);
19837
      return keys$1.length === 1 && contains$2(keys$1, 'title');
19838
    };
19839
    const processBasic = (item, isSelectedFor, getPreviewFor) => ({
19840
      ...item,
19841
      type: 'formatter',
19842
      isSelected: isSelectedFor(item.format),
19843
      getStylePreview: getPreviewFor(item.format)
19844
    });
19845
    const register$a = (editor, formats, isSelectedFor, getPreviewFor) => {
19846
      const enrichSupported = item => processBasic(item, isSelectedFor, getPreviewFor);
19847
      const enrichMenu = item => {
19848
        const newItems = doEnrich(item.items);
19849
        return {
19850
          ...item,
19851
          type: 'submenu',
19852
          getStyleItems: constant$1(newItems)
19853
        };
19854
      };
19855
      const enrichCustom = item => {
19856
        const formatName = isString(item.name) ? item.name : generate$6(item.title);
19857
        const formatNameWithPrefix = `custom-${ formatName }`;
19858
        const newItem = {
19859
          ...item,
19860
          type: 'formatter',
19861
          format: formatNameWithPrefix,
19862
          isSelected: isSelectedFor(formatNameWithPrefix),
19863
          getStylePreview: getPreviewFor(formatNameWithPrefix)
19864
        };
19865
        editor.formatter.register(formatName, newItem);
19866
        return newItem;
19867
      };
19868
      const doEnrich = items => map$2(items, item => {
19869
        if (isNestedFormat(item)) {
19870
          return enrichMenu(item);
19871
        } else if (isFormatReference(item)) {
19872
          return enrichSupported(item);
19873
        } else if (isSeparator$1(item)) {
19874
          return {
19875
            ...item,
19876
            type: 'separator'
19877
          };
19878
        } else {
19879
          return enrichCustom(item);
19880
        }
19881
      });
19882
      return doEnrich(formats);
19883
    };
19884
 
19885
    const init$7 = editor => {
19886
      const isSelectedFor = format => () => editor.formatter.match(format);
19887
      const getPreviewFor = format => () => {
19888
        const fmt = editor.formatter.get(format);
19889
        return fmt !== undefined ? Optional.some({
19890
          tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
19891
          styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
19892
        }) : Optional.none();
19893
      };
19894
      const settingsFormats = Cell([]);
19895
      const eventsFormats = Cell([]);
19896
      const replaceSettings = Cell(false);
19897
      editor.on('PreInit', _e => {
19898
        const formats = getStyleFormats(editor);
19899
        const enriched = register$a(editor, formats, isSelectedFor, getPreviewFor);
19900
        settingsFormats.set(enriched);
19901
      });
19902
      editor.on('addStyleModifications', e => {
19903
        const modifications = register$a(editor, e.items, isSelectedFor, getPreviewFor);
19904
        eventsFormats.set(modifications);
19905
        replaceSettings.set(e.replace);
19906
      });
19907
      const getData = () => {
19908
        const fromSettings = replaceSettings.get() ? [] : settingsFormats.get();
19909
        const fromEvents = eventsFormats.get();
19910
        return fromSettings.concat(fromEvents);
19911
      };
19912
      return { getData };
19913
    };
19914
 
19915
    const isElement = node => isNonNullable(node) && node.nodeType === 1;
19916
    const trim = global$1.trim;
19917
    const hasContentEditableState = value => {
19918
      return node => {
19919
        if (isElement(node)) {
19920
          if (node.contentEditable === value) {
19921
            return true;
19922
          }
19923
          if (node.getAttribute('data-mce-contenteditable') === value) {
19924
            return true;
19925
          }
19926
        }
19927
        return false;
19928
      };
19929
    };
19930
    const isContentEditableTrue = hasContentEditableState('true');
19931
    const isContentEditableFalse = hasContentEditableState('false');
19932
    const create = (type, title, url, level, attach) => ({
19933
      type,
19934
      title,
19935
      url,
19936
      level,
19937
      attach
19938
    });
19939
    const isChildOfContentEditableTrue = node => {
19940
      let tempNode = node;
19941
      while (tempNode = tempNode.parentNode) {
19942
        const value = tempNode.contentEditable;
19943
        if (value && value !== 'inherit') {
19944
          return isContentEditableTrue(tempNode);
19945
        }
19946
      }
19947
      return false;
19948
    };
19949
    const select = (selector, root) => {
19950
      return map$2(descendants(SugarElement.fromDom(root), selector), element => {
19951
        return element.dom;
19952
      });
19953
    };
19954
    const getElementText = elm => {
19955
      return elm.innerText || elm.textContent;
19956
    };
19957
    const getOrGenerateId = elm => {
19958
      return elm.id ? elm.id : generate$6('h');
19959
    };
19960
    const isAnchor = elm => {
19961
      return elm && elm.nodeName === 'A' && (elm.id || elm.name) !== undefined;
19962
    };
19963
    const isValidAnchor = elm => {
19964
      return isAnchor(elm) && isEditable(elm);
19965
    };
19966
    const isHeader = elm => {
19967
      return elm && /^(H[1-6])$/.test(elm.nodeName);
19968
    };
19969
    const isEditable = elm => {
19970
      return isChildOfContentEditableTrue(elm) && !isContentEditableFalse(elm);
19971
    };
19972
    const isValidHeader = elm => {
19973
      return isHeader(elm) && isEditable(elm);
19974
    };
19975
    const getLevel = elm => {
19976
      return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
19977
    };
19978
    const headerTarget = elm => {
19979
      var _a;
19980
      const headerId = getOrGenerateId(elm);
19981
      const attach = () => {
19982
        elm.id = headerId;
19983
      };
19984
      return create('header', (_a = getElementText(elm)) !== null && _a !== void 0 ? _a : '', '#' + headerId, getLevel(elm), attach);
19985
    };
19986
    const anchorTarget = elm => {
19987
      const anchorId = elm.id || elm.name;
19988
      const anchorText = getElementText(elm);
19989
      return create('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, noop);
19990
    };
19991
    const getHeaderTargets = elms => {
19992
      return map$2(filter$2(elms, isValidHeader), headerTarget);
19993
    };
19994
    const getAnchorTargets = elms => {
19995
      return map$2(filter$2(elms, isValidAnchor), anchorTarget);
19996
    };
19997
    const getTargetElements = elm => {
19998
      const elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
19999
      return elms;
20000
    };
20001
    const hasTitle = target => {
20002
      return trim(target.title).length > 0;
20003
    };
20004
    const find = elm => {
20005
      const elms = getTargetElements(elm);
20006
      return filter$2(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
20007
    };
20008
    const LinkTargets = { find };
20009
 
20010
    const STORAGE_KEY = 'tinymce-url-history';
20011
    const HISTORY_LENGTH = 5;
20012
    const isHttpUrl = url => isString(url) && /^https?/.test(url);
20013
    const isArrayOfUrl = a => isArray(a) && a.length <= HISTORY_LENGTH && forall(a, isHttpUrl);
20014
    const isRecordOfUrlArray = r => isObject(r) && find$4(r, value => !isArrayOfUrl(value)).isNone();
20015
    const getAllHistory = () => {
20016
      const unparsedHistory = global$4.getItem(STORAGE_KEY);
20017
      if (unparsedHistory === null) {
20018
        return {};
20019
      }
20020
      let history;
20021
      try {
20022
        history = JSON.parse(unparsedHistory);
20023
      } catch (e) {
20024
        if (e instanceof SyntaxError) {
20025
          console.log('Local storage ' + STORAGE_KEY + ' was not valid JSON', e);
20026
          return {};
20027
        }
20028
        throw e;
20029
      }
20030
      if (!isRecordOfUrlArray(history)) {
20031
        console.log('Local storage ' + STORAGE_KEY + ' was not valid format', history);
20032
        return {};
20033
      }
20034
      return history;
20035
    };
20036
    const setAllHistory = history => {
20037
      if (!isRecordOfUrlArray(history)) {
20038
        throw new Error('Bad format for history:\n' + JSON.stringify(history));
20039
      }
20040
      global$4.setItem(STORAGE_KEY, JSON.stringify(history));
20041
    };
20042
    const getHistory = fileType => {
20043
      const history = getAllHistory();
20044
      return get$g(history, fileType).getOr([]);
20045
    };
20046
    const addToHistory = (url, fileType) => {
20047
      if (!isHttpUrl(url)) {
20048
        return;
20049
      }
20050
      const history = getAllHistory();
20051
      const items = get$g(history, fileType).getOr([]);
20052
      const itemsWithoutUrl = filter$2(items, item => item !== url);
20053
      history[fileType] = [url].concat(itemsWithoutUrl).slice(0, HISTORY_LENGTH);
20054
      setAllHistory(history);
20055
    };
20056
 
20057
    const isTruthy = value => !!value;
20058
    const makeMap = value => map$1(global$1.makeMap(value, /[, ]/), isTruthy);
20059
    const getPicker = editor => Optional.from(getFilePickerCallback(editor));
20060
    const getPickerTypes = editor => {
20061
      const optFileTypes = Optional.from(getFilePickerTypes(editor)).filter(isTruthy).map(makeMap);
20062
      return getPicker(editor).fold(never, _picker => optFileTypes.fold(always, types => keys(types).length > 0 ? types : false));
20063
    };
20064
    const getPickerSetting = (editor, filetype) => {
20065
      const pickerTypes = getPickerTypes(editor);
20066
      if (isBoolean(pickerTypes)) {
20067
        return pickerTypes ? getPicker(editor) : Optional.none();
20068
      } else {
20069
        return pickerTypes[filetype] ? getPicker(editor) : Optional.none();
20070
      }
20071
    };
20072
    const getUrlPicker = (editor, filetype) => getPickerSetting(editor, filetype).map(picker => entry => Future.nu(completer => {
20073
      const handler = (value, meta) => {
20074
        if (!isString(value)) {
20075
          throw new Error('Expected value to be string');
20076
        }
20077
        if (meta !== undefined && !isObject(meta)) {
20078
          throw new Error('Expected meta to be a object');
20079
        }
20080
        const r = {
20081
          value,
20082
          meta
20083
        };
20084
        completer(r);
20085
      };
20086
      const meta = {
20087
        filetype,
20088
        fieldname: entry.fieldname,
20089
        ...Optional.from(entry.meta).getOr({})
20090
      };
20091
      picker.call(editor, handler, entry.value, meta);
20092
    }));
20093
    const getTextSetting = value => Optional.from(value).filter(isString).getOrUndefined();
20094
    const getLinkInformation = editor => {
20095
      if (!useTypeaheadUrls(editor)) {
20096
        return Optional.none();
20097
      }
20098
      return Optional.some({
20099
        targets: LinkTargets.find(editor.getBody()),
20100
        anchorTop: getTextSetting(getAnchorTop(editor)),
20101
        anchorBottom: getTextSetting(getAnchorBottom(editor))
20102
      });
20103
    };
20104
    const getValidationHandler = editor => Optional.from(getFilePickerValidatorHandler(editor));
20105
    const UrlInputBackstage = editor => ({
20106
      getHistory,
20107
      addToHistory,
20108
      getLinkInformation: () => getLinkInformation(editor),
20109
      getValidationHandler: () => getValidationHandler(editor),
20110
      getUrlPicker: filetype => getUrlPicker(editor, filetype)
20111
    });
20112
 
20113
    const init$6 = (lazySinks, editor, lazyAnchorbar, lazyBottomAnchorBar) => {
20114
      const contextMenuState = Cell(false);
20115
      const toolbar = HeaderBackstage(editor);
20116
      const providers = {
20117
        icons: () => editor.ui.registry.getAll().icons,
20118
        menuItems: () => editor.ui.registry.getAll().menuItems,
20119
        translate: global$8.translate,
20120
        isDisabled: () => editor.mode.isReadOnly() || !editor.ui.isEnabled(),
20121
        getOption: editor.options.get
20122
      };
20123
      const urlinput = UrlInputBackstage(editor);
20124
      const styles = init$7(editor);
20125
      const colorinput = ColorInputBackstage(editor);
20126
      const dialogSettings = DialogBackstage(editor);
20127
      const isContextMenuOpen = () => contextMenuState.get();
20128
      const setContextMenuState = state => contextMenuState.set(state);
20129
      const commonBackstage = {
20130
        shared: {
20131
          providers,
20132
          anchors: getAnchors(editor, lazyAnchorbar, lazyBottomAnchorBar, toolbar.isPositionedAtTop),
20133
          header: toolbar
20134
        },
20135
        urlinput,
20136
        styles,
20137
        colorinput,
20138
        dialog: dialogSettings,
20139
        isContextMenuOpen,
20140
        setContextMenuState
20141
      };
20142
      const popupBackstage = {
20143
        ...commonBackstage,
20144
        shared: {
20145
          ...commonBackstage.shared,
20146
          interpreter: s => interpretWithoutForm(s, {}, popupBackstage),
20147
          getSink: lazySinks.popup
20148
        }
20149
      };
20150
      const dialogBackstage = {
20151
        ...commonBackstage,
20152
        shared: {
20153
          ...commonBackstage.shared,
20154
          interpreter: s => interpretWithoutForm(s, {}, dialogBackstage),
20155
          getSink: lazySinks.dialog
20156
        }
20157
      };
20158
      return {
20159
        popup: popupBackstage,
20160
        dialog: dialogBackstage
20161
      };
20162
    };
20163
 
20164
    const setup$b = (editor, mothership, uiMotherships) => {
20165
      const broadcastEvent = (name, evt) => {
20166
        each$1([
20167
          mothership,
20168
          ...uiMotherships
20169
        ], m => {
20170
          m.broadcastEvent(name, evt);
20171
        });
20172
      };
20173
      const broadcastOn = (channel, message) => {
20174
        each$1([
20175
          mothership,
20176
          ...uiMotherships
20177
        ], m => {
20178
          m.broadcastOn([channel], message);
20179
        });
20180
      };
20181
      const fireDismissPopups = evt => broadcastOn(dismissPopups(), { target: evt.target });
20182
      const doc = getDocument();
20183
      const onTouchstart = bind(doc, 'touchstart', fireDismissPopups);
20184
      const onTouchmove = bind(doc, 'touchmove', evt => broadcastEvent(documentTouchmove(), evt));
20185
      const onTouchend = bind(doc, 'touchend', evt => broadcastEvent(documentTouchend(), evt));
20186
      const onMousedown = bind(doc, 'mousedown', fireDismissPopups);
20187
      const onMouseup = bind(doc, 'mouseup', evt => {
20188
        if (evt.raw.button === 0) {
20189
          broadcastOn(mouseReleased(), { target: evt.target });
20190
        }
20191
      });
20192
      const onContentClick = raw => broadcastOn(dismissPopups(), { target: SugarElement.fromDom(raw.target) });
20193
      const onContentMouseup = raw => {
20194
        if (raw.button === 0) {
20195
          broadcastOn(mouseReleased(), { target: SugarElement.fromDom(raw.target) });
20196
        }
20197
      };
20198
      const onContentMousedown = () => {
20199
        each$1(editor.editorManager.get(), loopEditor => {
20200
          if (editor !== loopEditor) {
20201
            loopEditor.dispatch('DismissPopups', { relatedTarget: editor });
20202
          }
20203
        });
20204
      };
20205
      const onWindowScroll = evt => broadcastEvent(windowScroll(), fromRawEvent(evt));
20206
      const onWindowResize = evt => {
20207
        broadcastOn(repositionPopups(), {});
20208
        broadcastEvent(windowResize(), fromRawEvent(evt));
20209
      };
20210
      const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
20211
      const onElementScroll = capture(dos, 'scroll', evt => {
20212
        requestAnimationFrame(() => {
20213
          const c = editor.getContainer();
20214
          if (c !== undefined && c !== null) {
20215
            const optScrollingContext = detectWhenSplitUiMode(editor, mothership.element);
20216
            const scrollers = optScrollingContext.map(sc => [
20217
              sc.element,
20218
              ...sc.others
20219
            ]).getOr([]);
20220
            if (exists(scrollers, s => eq(s, evt.target))) {
20221
              editor.dispatch('ElementScroll', { target: evt.target.dom });
20222
              broadcastEvent(externalElementScroll(), evt);
20223
            }
20224
          }
20225
        });
20226
      });
20227
      const onEditorResize = () => broadcastOn(repositionPopups(), {});
20228
      const onEditorProgress = evt => {
20229
        if (evt.state) {
20230
          broadcastOn(dismissPopups(), { target: SugarElement.fromDom(editor.getContainer()) });
20231
        }
20232
      };
20233
      const onDismissPopups = event => {
20234
        broadcastOn(dismissPopups(), { target: SugarElement.fromDom(event.relatedTarget.getContainer()) });
20235
      };
20236
      editor.on('PostRender', () => {
20237
        editor.on('click', onContentClick);
20238
        editor.on('tap', onContentClick);
20239
        editor.on('mouseup', onContentMouseup);
20240
        editor.on('mousedown', onContentMousedown);
20241
        editor.on('ScrollWindow', onWindowScroll);
20242
        editor.on('ResizeWindow', onWindowResize);
20243
        editor.on('ResizeEditor', onEditorResize);
20244
        editor.on('AfterProgressState', onEditorProgress);
20245
        editor.on('DismissPopups', onDismissPopups);
20246
      });
20247
      editor.on('remove', () => {
20248
        editor.off('click', onContentClick);
20249
        editor.off('tap', onContentClick);
20250
        editor.off('mouseup', onContentMouseup);
20251
        editor.off('mousedown', onContentMousedown);
20252
        editor.off('ScrollWindow', onWindowScroll);
20253
        editor.off('ResizeWindow', onWindowResize);
20254
        editor.off('ResizeEditor', onEditorResize);
20255
        editor.off('AfterProgressState', onEditorProgress);
20256
        editor.off('DismissPopups', onDismissPopups);
20257
        onMousedown.unbind();
20258
        onTouchstart.unbind();
20259
        onTouchmove.unbind();
20260
        onTouchend.unbind();
20261
        onMouseup.unbind();
20262
        onElementScroll.unbind();
20263
      });
20264
      editor.on('detach', () => {
20265
        each$1([
20266
          mothership,
20267
          ...uiMotherships
20268
        ], detachSystem);
20269
        each$1([
20270
          mothership,
20271
          ...uiMotherships
20272
        ], m => m.destroy());
20273
      });
20274
    };
20275
 
20276
    const parts$a = AlloyParts;
20277
    const partType = PartType;
20278
 
20279
    const schema$f = constant$1([
20280
      defaulted('shell', false),
20281
      required$1('makeItem'),
20282
      defaulted('setupItem', noop),
20283
      SketchBehaviours.field('listBehaviours', [Replacing])
20284
    ]);
20285
    const customListDetail = () => ({ behaviours: derive$1([Replacing.config({})]) });
20286
    const itemsPart = optional({
20287
      name: 'items',
20288
      overrides: customListDetail
20289
    });
20290
    const parts$9 = constant$1([itemsPart]);
20291
    const name = constant$1('CustomList');
20292
 
20293
    const factory$f = (detail, components, _spec, _external) => {
20294
      const setItems = (list, items) => {
20295
        getListContainer(list).fold(() => {
20296
          console.error('Custom List was defined to not be a shell, but no item container was specified in components');
20297
          throw new Error('Custom List was defined to not be a shell, but no item container was specified in components');
20298
        }, container => {
20299
          const itemComps = Replacing.contents(container);
20300
          const numListsRequired = items.length;
20301
          const numListsToAdd = numListsRequired - itemComps.length;
20302
          const itemsToAdd = numListsToAdd > 0 ? range$2(numListsToAdd, () => detail.makeItem()) : [];
20303
          const itemsToRemove = itemComps.slice(numListsRequired);
20304
          each$1(itemsToRemove, item => Replacing.remove(container, item));
20305
          each$1(itemsToAdd, item => Replacing.append(container, item));
20306
          const builtLists = Replacing.contents(container);
20307
          each$1(builtLists, (item, i) => {
20308
            detail.setupItem(list, item, items[i], i);
20309
          });
20310
        });
20311
      };
20312
      const extra = detail.shell ? {
20313
        behaviours: [Replacing.config({})],
20314
        components: []
20315
      } : {
20316
        behaviours: [],
20317
        components
20318
      };
20319
      const getListContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'items');
20320
      return {
20321
        uid: detail.uid,
20322
        dom: detail.dom,
20323
        components: extra.components,
20324
        behaviours: augment(detail.listBehaviours, extra.behaviours),
20325
        apis: { setItems }
20326
      };
20327
    };
20328
    const CustomList = composite({
20329
      name: name(),
20330
      configFields: schema$f(),
20331
      partFields: parts$9(),
20332
      factory: factory$f,
20333
      apis: {
20334
        setItems: (apis, list, items) => {
20335
          apis.setItems(list, items);
20336
        }
20337
      }
20338
    });
20339
 
20340
    const schema$e = constant$1([
20341
      required$1('dom'),
20342
      defaulted('shell', true),
20343
      field('toolbarBehaviours', [Replacing])
20344
    ]);
20345
    const enhanceGroups = () => ({ behaviours: derive$1([Replacing.config({})]) });
20346
    const parts$8 = constant$1([optional({
20347
        name: 'groups',
20348
        overrides: enhanceGroups
20349
      })]);
20350
 
20351
    const factory$e = (detail, components, _spec, _externals) => {
20352
      const setGroups = (toolbar, groups) => {
20353
        getGroupContainer(toolbar).fold(() => {
20354
          console.error('Toolbar was defined to not be a shell, but no groups container was specified in components');
20355
          throw new Error('Toolbar was defined to not be a shell, but no groups container was specified in components');
20356
        }, container => {
20357
          Replacing.set(container, groups);
20358
        });
20359
      };
20360
      const getGroupContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'groups');
20361
      const extra = detail.shell ? {
20362
        behaviours: [Replacing.config({})],
20363
        components: []
20364
      } : {
20365
        behaviours: [],
20366
        components
20367
      };
20368
      return {
20369
        uid: detail.uid,
20370
        dom: detail.dom,
20371
        components: extra.components,
20372
        behaviours: augment(detail.toolbarBehaviours, extra.behaviours),
20373
        apis: {
20374
          setGroups,
20375
          refresh: noop
20376
        },
20377
        domModification: { attributes: { role: 'group' } }
20378
      };
20379
    };
20380
    const Toolbar = composite({
20381
      name: 'Toolbar',
20382
      configFields: schema$e(),
20383
      partFields: parts$8(),
20384
      factory: factory$e,
20385
      apis: {
20386
        setGroups: (apis, toolbar, groups) => {
20387
          apis.setGroups(toolbar, groups);
20388
        }
20389
      }
20390
    });
20391
 
20392
    const setup$a = noop;
20393
    const isDocked$2 = never;
20394
    const getBehaviours$1 = constant$1([]);
20395
 
20396
    var StaticHeader = /*#__PURE__*/Object.freeze({
20397
        __proto__: null,
20398
        setup: setup$a,
20399
        isDocked: isDocked$2,
20400
        getBehaviours: getBehaviours$1
20401
    });
20402
 
20403
    const getOffsetParent = element => {
20404
      const isFixed = is$1(getRaw(element, 'position'), 'fixed');
20405
      const offsetParent$1 = isFixed ? Optional.none() : offsetParent(element);
20406
      return offsetParent$1.orThunk(() => {
20407
        const marker = SugarElement.fromTag('span');
20408
        return parent(element).bind(parent => {
20409
          append$2(parent, marker);
20410
          const offsetParent$1 = offsetParent(marker);
20411
          remove$5(marker);
20412
          return offsetParent$1;
20413
        });
20414
      });
20415
    };
20416
    const getOrigin = element => getOffsetParent(element).map(absolute$3).getOrThunk(() => SugarPosition(0, 0));
20417
 
20418
    const appear = (component, contextualInfo) => {
20419
      const elem = component.element;
20420
      add$2(elem, contextualInfo.transitionClass);
20421
      remove$2(elem, contextualInfo.fadeOutClass);
20422
      add$2(elem, contextualInfo.fadeInClass);
20423
      contextualInfo.onShow(component);
20424
    };
20425
    const disappear = (component, contextualInfo) => {
20426
      const elem = component.element;
20427
      add$2(elem, contextualInfo.transitionClass);
20428
      remove$2(elem, contextualInfo.fadeInClass);
20429
      add$2(elem, contextualInfo.fadeOutClass);
20430
      contextualInfo.onHide(component);
20431
    };
20432
    const isPartiallyVisible = (box, bounds) => box.y < bounds.bottom && box.bottom > bounds.y;
20433
    const isTopCompletelyVisible = (box, bounds) => box.y >= bounds.y;
20434
    const isBottomCompletelyVisible = (box, bounds) => box.bottom <= bounds.bottom;
20435
    const forceTopPosition = (winBox, leftX, viewport) => ({
20436
      location: 'top',
20437
      leftX,
20438
      topY: viewport.bounds.y - winBox.y
20439
    });
20440
    const forceBottomPosition = (winBox, leftX, viewport) => ({
20441
      location: 'bottom',
20442
      leftX,
20443
      bottomY: winBox.bottom - viewport.bounds.bottom
20444
    });
20445
    const getDockedLeftPosition = bounds => {
20446
      return bounds.box.x - bounds.win.x;
20447
    };
20448
    const tryDockingPosition = (modes, bounds, viewport) => {
20449
      const winBox = bounds.win;
20450
      const box = bounds.box;
20451
      const leftX = getDockedLeftPosition(bounds);
20452
      return findMap(modes, mode => {
20453
        switch (mode) {
20454
        case 'bottom':
20455
          return !isBottomCompletelyVisible(box, viewport.bounds) ? Optional.some(forceBottomPosition(winBox, leftX, viewport)) : Optional.none();
20456
        case 'top':
20457
          return !isTopCompletelyVisible(box, viewport.bounds) ? Optional.some(forceTopPosition(winBox, leftX, viewport)) : Optional.none();
20458
        default:
20459
          return Optional.none();
20460
        }
20461
      }).getOr({ location: 'no-dock' });
20462
    };
20463
    const isVisibleForModes = (modes, box, viewport) => forall(modes, mode => {
20464
      switch (mode) {
20465
      case 'bottom':
20466
        return isBottomCompletelyVisible(box, viewport.bounds);
20467
      case 'top':
20468
        return isTopCompletelyVisible(box, viewport.bounds);
20469
      }
20470
    });
20471
    const getXYForRestoring = (pos, viewport) => {
20472
      const priorY = viewport.optScrollEnv.fold(constant$1(pos.bounds.y), scrollEnv => scrollEnv.scrollElmTop + (pos.bounds.y - scrollEnv.currentScrollTop));
20473
      return SugarPosition(pos.bounds.x, priorY);
20474
    };
20475
    const getXYForSaving = (box, viewport) => {
20476
      const priorY = viewport.optScrollEnv.fold(constant$1(box.y), scrollEnv => box.y + scrollEnv.currentScrollTop - scrollEnv.scrollElmTop);
20477
      return SugarPosition(box.x, priorY);
20478
    };
20479
    const getPrior = (elem, viewport, state) => state.getInitialPos().map(pos => {
20480
      const xy = getXYForRestoring(pos, viewport);
20481
      return {
20482
        box: bounds(xy.left, xy.top, get$c(elem), get$d(elem)),
20483
        location: pos.location
20484
      };
20485
    });
20486
    const storePrior = (elem, box, viewport, state, decision) => {
20487
      const xy = getXYForSaving(box, viewport);
20488
      const bounds$1 = bounds(xy.left, xy.top, box.width, box.height);
20489
      state.setInitialPos({
20490
        style: getAllRaw(elem),
20491
        position: get$e(elem, 'position') || 'static',
20492
        bounds: bounds$1,
20493
        location: decision.location
20494
      });
20495
    };
20496
    const storePriorIfNone = (elem, box, viewport, state, decision) => {
20497
      state.getInitialPos().fold(() => storePrior(elem, box, viewport, state, decision), () => noop);
20498
    };
20499
    const revertToOriginal = (elem, box, state) => state.getInitialPos().bind(position => {
20500
      var _a;
20501
      state.clearInitialPos();
20502
      switch (position.position) {
20503
      case 'static':
20504
        return Optional.some({ morph: 'static' });
20505
      case 'absolute':
20506
        const offsetParent = getOffsetParent(elem).getOr(body());
20507
        const offsetBox = box$1(offsetParent);
20508
        const scrollDelta = (_a = offsetParent.dom.scrollTop) !== null && _a !== void 0 ? _a : 0;
20509
        return Optional.some({
20510
          morph: 'absolute',
20511
          positionCss: NuPositionCss('absolute', get$g(position.style, 'left').map(_left => box.x - offsetBox.x), get$g(position.style, 'top').map(_top => box.y - offsetBox.y + scrollDelta), get$g(position.style, 'right').map(_right => offsetBox.right - box.right), get$g(position.style, 'bottom').map(_bottom => offsetBox.bottom - box.bottom))
20512
        });
20513
      default:
20514
        return Optional.none();
20515
      }
20516
    });
20517
    const tryMorphToOriginal = (elem, viewport, state) => getPrior(elem, viewport, state).filter(({box}) => isVisibleForModes(state.getModes(), box, viewport)).bind(({box}) => revertToOriginal(elem, box, state));
20518
    const tryDecisionToFixedMorph = decision => {
20519
      switch (decision.location) {
20520
      case 'top': {
20521
          return Optional.some({
20522
            morph: 'fixed',
20523
            positionCss: NuPositionCss('fixed', Optional.some(decision.leftX), Optional.some(decision.topY), Optional.none(), Optional.none())
20524
          });
20525
        }
20526
      case 'bottom': {
20527
          return Optional.some({
20528
            morph: 'fixed',
20529
            positionCss: NuPositionCss('fixed', Optional.some(decision.leftX), Optional.none(), Optional.none(), Optional.some(decision.bottomY))
20530
          });
20531
        }
20532
      default:
20533
        return Optional.none();
20534
      }
20535
    };
20536
    const tryMorphToFixed = (elem, viewport, state) => {
20537
      const box = box$1(elem);
20538
      const winBox = win();
20539
      const decision = tryDockingPosition(state.getModes(), {
20540
        win: winBox,
20541
        box
20542
      }, viewport);
20543
      if (decision.location === 'top' || decision.location === 'bottom') {
20544
        storePrior(elem, box, viewport, state, decision);
20545
        return tryDecisionToFixedMorph(decision);
20546
      } else {
20547
        return Optional.none();
20548
      }
20549
    };
20550
    const tryMorphToOriginalOrUpdateFixed = (elem, viewport, state) => {
20551
      return tryMorphToOriginal(elem, viewport, state).orThunk(() => {
20552
        return viewport.optScrollEnv.bind(_ => getPrior(elem, viewport, state)).bind(({box, location}) => {
20553
          const winBox = win();
20554
          const leftX = getDockedLeftPosition({
20555
            win: winBox,
20556
            box
20557
          });
20558
          const decision = location === 'top' ? forceTopPosition(winBox, leftX, viewport) : forceBottomPosition(winBox, leftX, viewport);
20559
          return tryDecisionToFixedMorph(decision);
20560
        });
20561
      });
20562
    };
20563
    const tryMorph = (component, viewport, state) => {
20564
      const elem = component.element;
20565
      const isDocked = is$1(getRaw(elem, 'position'), 'fixed');
20566
      return isDocked ? tryMorphToOriginalOrUpdateFixed(elem, viewport, state) : tryMorphToFixed(elem, viewport, state);
20567
    };
20568
    const calculateMorphToOriginal = (component, viewport, state) => {
20569
      const elem = component.element;
20570
      return getPrior(elem, viewport, state).bind(({box}) => revertToOriginal(elem, box, state));
20571
    };
20572
    const forceDockWith = (elem, viewport, state, getDecision) => {
20573
      const box = box$1(elem);
20574
      const winBox = win();
20575
      const leftX = getDockedLeftPosition({
20576
        win: winBox,
20577
        box
20578
      });
20579
      const decision = getDecision(winBox, leftX, viewport);
20580
      if (decision.location === 'bottom' || decision.location === 'top') {
20581
        storePriorIfNone(elem, box, viewport, state, decision);
20582
        return tryDecisionToFixedMorph(decision);
20583
      } else {
20584
        return Optional.none();
20585
      }
20586
    };
20587
 
20588
    const morphToStatic = (component, config, state) => {
20589
      state.setDocked(false);
20590
      each$1([
20591
        'left',
20592
        'right',
20593
        'top',
20594
        'bottom',
20595
        'position'
20596
      ], prop => remove$6(component.element, prop));
20597
      config.onUndocked(component);
20598
    };
20599
    const morphToCoord = (component, config, state, position) => {
20600
      const isDocked = position.position === 'fixed';
20601
      state.setDocked(isDocked);
20602
      applyPositionCss(component.element, position);
20603
      const method = isDocked ? config.onDocked : config.onUndocked;
20604
      method(component);
20605
    };
20606
    const updateVisibility = (component, config, state, viewport, morphToDocked = false) => {
20607
      config.contextual.each(contextInfo => {
20608
        contextInfo.lazyContext(component).each(box => {
20609
          const isVisible = isPartiallyVisible(box, viewport.bounds);
20610
          if (isVisible !== state.isVisible()) {
20611
            state.setVisible(isVisible);
20612
            if (morphToDocked && !isVisible) {
20613
              add$1(component.element, [contextInfo.fadeOutClass]);
20614
              contextInfo.onHide(component);
20615
            } else {
20616
              const method = isVisible ? appear : disappear;
20617
              method(component, contextInfo);
20618
            }
20619
          }
20620
        });
20621
      });
20622
    };
20623
    const applyFixedMorph = (component, config, state, viewport, morph) => {
20624
      updateVisibility(component, config, state, viewport, true);
20625
      morphToCoord(component, config, state, morph.positionCss);
20626
    };
20627
    const applyMorph = (component, config, state, viewport, morph) => {
20628
      switch (morph.morph) {
20629
      case 'static': {
20630
          return morphToStatic(component, config, state);
20631
        }
20632
      case 'absolute': {
20633
          return morphToCoord(component, config, state, morph.positionCss);
20634
        }
20635
      case 'fixed': {
20636
          return applyFixedMorph(component, config, state, viewport, morph);
20637
        }
20638
      }
20639
    };
20640
    const refreshInternal = (component, config, state) => {
20641
      const viewport = config.lazyViewport(component);
20642
      updateVisibility(component, config, state, viewport);
20643
      tryMorph(component, viewport, state).each(morph => {
20644
        applyMorph(component, config, state, viewport, morph);
20645
      });
20646
    };
20647
    const resetInternal = (component, config, state) => {
20648
      const elem = component.element;
20649
      state.setDocked(false);
20650
      const viewport = config.lazyViewport(component);
20651
      calculateMorphToOriginal(component, viewport, state).each(staticOrAbsoluteMorph => {
20652
        switch (staticOrAbsoluteMorph.morph) {
20653
        case 'static': {
20654
            morphToStatic(component, config, state);
20655
            break;
20656
          }
20657
        case 'absolute': {
20658
            morphToCoord(component, config, state, staticOrAbsoluteMorph.positionCss);
20659
            break;
20660
          }
20661
        }
20662
      });
20663
      state.setVisible(true);
20664
      config.contextual.each(contextInfo => {
20665
        remove$1(elem, [
20666
          contextInfo.fadeInClass,
20667
          contextInfo.fadeOutClass,
20668
          contextInfo.transitionClass
20669
        ]);
20670
        contextInfo.onShow(component);
20671
      });
20672
      refresh$3(component, config, state);
20673
    };
20674
    const refresh$3 = (component, config, state) => {
20675
      if (component.getSystem().isConnected()) {
20676
        refreshInternal(component, config, state);
20677
      }
20678
    };
20679
    const reset = (component, config, state) => {
20680
      if (state.isDocked()) {
20681
        resetInternal(component, config, state);
20682
      }
20683
    };
20684
    const forceDockWithDecision = getDecision => (component, config, state) => {
20685
      const viewport = config.lazyViewport(component);
20686
      const optMorph = forceDockWith(component.element, viewport, state, getDecision);
20687
      optMorph.each(morph => {
20688
        applyFixedMorph(component, config, state, viewport, morph);
20689
      });
20690
    };
20691
    const forceDockToTop = forceDockWithDecision(forceTopPosition);
20692
    const forceDockToBottom = forceDockWithDecision(forceBottomPosition);
20693
    const isDocked$1 = (component, config, state) => state.isDocked();
20694
    const setModes = (component, config, state, modes) => state.setModes(modes);
20695
    const getModes = (component, config, state) => state.getModes();
20696
 
20697
    var DockingApis = /*#__PURE__*/Object.freeze({
20698
        __proto__: null,
20699
        refresh: refresh$3,
20700
        reset: reset,
20701
        isDocked: isDocked$1,
20702
        getModes: getModes,
20703
        setModes: setModes,
20704
        forceDockToTop: forceDockToTop,
20705
        forceDockToBottom: forceDockToBottom
20706
    });
20707
 
20708
    const events$4 = (dockInfo, dockState) => derive$2([
20709
      runOnSource(transitionend(), (component, simulatedEvent) => {
20710
        dockInfo.contextual.each(contextInfo => {
20711
          if (has(component.element, contextInfo.transitionClass)) {
20712
            remove$1(component.element, [
20713
              contextInfo.transitionClass,
20714
              contextInfo.fadeInClass
20715
            ]);
20716
            const notify = dockState.isVisible() ? contextInfo.onShown : contextInfo.onHidden;
20717
            notify(component);
20718
          }
20719
          simulatedEvent.stop();
20720
        });
20721
      }),
20722
      run$1(windowScroll(), (component, _) => {
20723
        refresh$3(component, dockInfo, dockState);
20724
      }),
20725
      run$1(externalElementScroll(), (component, _) => {
20726
        refresh$3(component, dockInfo, dockState);
20727
      }),
20728
      run$1(windowResize(), (component, _) => {
20729
        reset(component, dockInfo, dockState);
20730
      })
20731
    ]);
20732
 
20733
    var ActiveDocking = /*#__PURE__*/Object.freeze({
20734
        __proto__: null,
20735
        events: events$4
20736
    });
20737
 
20738
    var DockingSchema = [
20739
      optionObjOf('contextual', [
20740
        requiredString('fadeInClass'),
20741
        requiredString('fadeOutClass'),
20742
        requiredString('transitionClass'),
20743
        requiredFunction('lazyContext'),
20744
        onHandler('onShow'),
20745
        onHandler('onShown'),
20746
        onHandler('onHide'),
20747
        onHandler('onHidden')
20748
      ]),
20749
      defaultedFunction('lazyViewport', () => ({
20750
        bounds: win(),
20751
        optScrollEnv: Optional.none()
20752
      })),
20753
      defaultedArrayOf('modes', [
20754
        'top',
20755
        'bottom'
20756
      ], string),
20757
      onHandler('onDocked'),
20758
      onHandler('onUndocked')
20759
    ];
20760
 
20761
    const init$5 = spec => {
20762
      const docked = Cell(false);
20763
      const visible = Cell(true);
20764
      const initialBounds = value$2();
20765
      const modes = Cell(spec.modes);
20766
      const readState = () => `docked:  ${ docked.get() }, visible: ${ visible.get() }, modes: ${ modes.get().join(',') }`;
20767
      return nu$8({
20768
        isDocked: docked.get,
20769
        setDocked: docked.set,
20770
        getInitialPos: initialBounds.get,
20771
        setInitialPos: initialBounds.set,
20772
        clearInitialPos: initialBounds.clear,
20773
        isVisible: visible.get,
20774
        setVisible: visible.set,
20775
        getModes: modes.get,
20776
        setModes: modes.set,
20777
        readState
20778
      });
20779
    };
20780
 
20781
    var DockingState = /*#__PURE__*/Object.freeze({
20782
        __proto__: null,
20783
        init: init$5
20784
    });
20785
 
20786
    const Docking = create$4({
20787
      fields: DockingSchema,
20788
      name: 'docking',
20789
      active: ActiveDocking,
20790
      apis: DockingApis,
20791
      state: DockingState
20792
    });
20793
 
20794
    const toolbarHeightChange = constant$1(generate$6('toolbar-height-change'));
20795
 
20796
    const visibility = {
20797
      fadeInClass: 'tox-editor-dock-fadein',
20798
      fadeOutClass: 'tox-editor-dock-fadeout',
20799
      transitionClass: 'tox-editor-dock-transition'
20800
    };
20801
    const editorStickyOnClass = 'tox-tinymce--toolbar-sticky-on';
20802
    const editorStickyOffClass = 'tox-tinymce--toolbar-sticky-off';
20803
    const scrollFromBehindHeader = (e, containerHeader) => {
20804
      const doc = owner$4(containerHeader);
20805
      const win = defaultView(containerHeader);
20806
      const viewHeight = win.dom.innerHeight;
20807
      const scrollPos = get$b(doc);
20808
      const markerElement = SugarElement.fromDom(e.elm);
20809
      const markerPos = absolute$2(markerElement);
20810
      const markerHeight = get$d(markerElement);
20811
      const markerTop = markerPos.y;
20812
      const markerBottom = markerTop + markerHeight;
20813
      const editorHeaderPos = absolute$3(containerHeader);
20814
      const editorHeaderHeight = get$d(containerHeader);
20815
      const editorHeaderTop = editorHeaderPos.top;
20816
      const editorHeaderBottom = editorHeaderTop + editorHeaderHeight;
20817
      const editorHeaderDockedAtTop = Math.abs(editorHeaderTop - scrollPos.top) < 2;
20818
      const editorHeaderDockedAtBottom = Math.abs(editorHeaderBottom - (scrollPos.top + viewHeight)) < 2;
20819
      if (editorHeaderDockedAtTop && markerTop < editorHeaderBottom) {
20820
        to(scrollPos.left, markerTop - editorHeaderHeight, doc);
20821
      } else if (editorHeaderDockedAtBottom && markerBottom > editorHeaderTop) {
20822
        const y = markerTop - viewHeight + markerHeight + editorHeaderHeight;
20823
        to(scrollPos.left, y, doc);
20824
      }
20825
    };
20826
    const isDockedMode = (header, mode) => contains$2(Docking.getModes(header), mode);
20827
    const updateIframeContentFlow = header => {
20828
      const getOccupiedHeight = elm => getOuter$2(elm) + (parseInt(get$e(elm, 'margin-top'), 10) || 0) + (parseInt(get$e(elm, 'margin-bottom'), 10) || 0);
20829
      const elm = header.element;
20830
      parentElement(elm).each(parentElem => {
20831
        const padding = 'padding-' + Docking.getModes(header)[0];
20832
        if (Docking.isDocked(header)) {
20833
          const parentWidth = get$c(parentElem);
20834
          set$8(elm, 'width', parentWidth + 'px');
20835
          set$8(parentElem, padding, getOccupiedHeight(elm) + 'px');
20836
        } else {
20837
          remove$6(elm, 'width');
20838
          remove$6(parentElem, padding);
20839
        }
20840
      });
20841
    };
20842
    const updateSinkVisibility = (sinkElem, visible) => {
20843
      if (visible) {
20844
        remove$2(sinkElem, visibility.fadeOutClass);
20845
        add$1(sinkElem, [
20846
          visibility.transitionClass,
20847
          visibility.fadeInClass
20848
        ]);
20849
      } else {
20850
        remove$2(sinkElem, visibility.fadeInClass);
20851
        add$1(sinkElem, [
20852
          visibility.fadeOutClass,
20853
          visibility.transitionClass
20854
        ]);
20855
      }
20856
    };
20857
    const updateEditorClasses = (editor, docked) => {
20858
      const editorContainer = SugarElement.fromDom(editor.getContainer());
20859
      if (docked) {
20860
        add$2(editorContainer, editorStickyOnClass);
20861
        remove$2(editorContainer, editorStickyOffClass);
20862
      } else {
20863
        add$2(editorContainer, editorStickyOffClass);
20864
        remove$2(editorContainer, editorStickyOnClass);
20865
      }
20866
    };
20867
    const restoreFocus = (headerElem, focusedElem) => {
20868
      const ownerDoc = owner$4(focusedElem);
20869
      active$1(ownerDoc).filter(activeElm => !eq(focusedElem, activeElm)).filter(activeElm => eq(activeElm, SugarElement.fromDom(ownerDoc.dom.body)) || contains(headerElem, activeElm)).each(() => focus$3(focusedElem));
20870
    };
20871
    const findFocusedElem = (rootElm, lazySink) => search(rootElm).orThunk(() => lazySink().toOptional().bind(sink => search(sink.element)));
20872
    const setup$9 = (editor, sharedBackstage, lazyHeader) => {
20873
      if (!editor.inline) {
20874
        if (!sharedBackstage.header.isPositionedAtTop()) {
20875
          editor.on('ResizeEditor', () => {
20876
            lazyHeader().each(Docking.reset);
20877
          });
20878
        }
20879
        editor.on('ResizeWindow ResizeEditor', () => {
20880
          lazyHeader().each(updateIframeContentFlow);
20881
        });
20882
        editor.on('SkinLoaded', () => {
20883
          lazyHeader().each(comp => {
20884
            Docking.isDocked(comp) ? Docking.reset(comp) : Docking.refresh(comp);
20885
          });
20886
        });
20887
        editor.on('FullscreenStateChanged', () => {
20888
          lazyHeader().each(Docking.reset);
20889
        });
20890
      }
20891
      editor.on('AfterScrollIntoView', e => {
20892
        lazyHeader().each(header => {
20893
          Docking.refresh(header);
20894
          const headerElem = header.element;
20895
          if (isVisible(headerElem)) {
20896
            scrollFromBehindHeader(e, headerElem);
20897
          }
20898
        });
20899
      });
20900
      editor.on('PostRender', () => {
20901
        updateEditorClasses(editor, false);
20902
      });
20903
    };
20904
    const isDocked = lazyHeader => lazyHeader().map(Docking.isDocked).getOr(false);
20905
    const getIframeBehaviours = () => [Receiving.config({ channels: { [toolbarHeightChange()]: { onReceive: updateIframeContentFlow } } })];
20906
    const getBehaviours = (editor, sharedBackstage) => {
20907
      const focusedElm = value$2();
20908
      const lazySink = sharedBackstage.getSink;
20909
      const runOnSinkElement = f => {
20910
        lazySink().each(sink => f(sink.element));
20911
      };
20912
      const onDockingSwitch = comp => {
20913
        if (!editor.inline) {
20914
          updateIframeContentFlow(comp);
20915
        }
20916
        updateEditorClasses(editor, Docking.isDocked(comp));
20917
        comp.getSystem().broadcastOn([repositionPopups()], {});
20918
        lazySink().each(sink => sink.getSystem().broadcastOn([repositionPopups()], {}));
20919
      };
20920
      const additionalBehaviours = editor.inline ? [] : getIframeBehaviours();
20921
      return [
20922
        Focusing.config({}),
20923
        Docking.config({
20924
          contextual: {
20925
            lazyContext: comp => {
20926
              const headerHeight = getOuter$2(comp.element);
20927
              const container = editor.inline ? editor.getContentAreaContainer() : editor.getContainer();
20928
              return Optional.from(container).map(c => {
20929
                const box = box$1(SugarElement.fromDom(c));
20930
                const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
20931
                return optScrollingContext.fold(() => {
20932
                  const boxHeight = box.height - headerHeight;
20933
                  const topBound = box.y + (isDockedMode(comp, 'top') ? 0 : headerHeight);
20934
                  return bounds(box.x, topBound, box.width, boxHeight);
20935
                }, scrollEnv => {
20936
                  const constrainedBounds = constrain(box, getBoundsFrom(scrollEnv));
20937
                  const constrainedBoundsY = isDockedMode(comp, 'top') ? constrainedBounds.y : constrainedBounds.y + headerHeight;
20938
                  return bounds(constrainedBounds.x, constrainedBoundsY, constrainedBounds.width, constrainedBounds.height - headerHeight);
20939
                });
20940
              });
20941
            },
20942
            onShow: () => {
20943
              runOnSinkElement(elem => updateSinkVisibility(elem, true));
20944
            },
20945
            onShown: comp => {
20946
              runOnSinkElement(elem => remove$1(elem, [
20947
                visibility.transitionClass,
20948
                visibility.fadeInClass
20949
              ]));
20950
              focusedElm.get().each(elem => {
20951
                restoreFocus(comp.element, elem);
20952
                focusedElm.clear();
20953
              });
20954
            },
20955
            onHide: comp => {
20956
              findFocusedElem(comp.element, lazySink).fold(focusedElm.clear, focusedElm.set);
20957
              runOnSinkElement(elem => updateSinkVisibility(elem, false));
20958
            },
20959
            onHidden: () => {
20960
              runOnSinkElement(elem => remove$1(elem, [visibility.transitionClass]));
20961
            },
20962
            ...visibility
20963
          },
20964
          lazyViewport: comp => {
20965
            const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
20966
            return optScrollingContext.fold(() => {
20967
              const boundsWithoutOffset = win();
20968
              const offset = getStickyToolbarOffset(editor);
20969
              const top = boundsWithoutOffset.y + (isDockedMode(comp, 'top') ? offset : 0);
20970
              const height = boundsWithoutOffset.height - (isDockedMode(comp, 'bottom') ? offset : 0);
20971
              return {
20972
                bounds: bounds(boundsWithoutOffset.x, top, boundsWithoutOffset.width, height),
20973
                optScrollEnv: Optional.none()
20974
              };
20975
            }, sc => {
20976
              const combinedBounds = getBoundsFrom(sc);
20977
              return {
20978
                bounds: combinedBounds,
20979
                optScrollEnv: Optional.some({
20980
                  currentScrollTop: sc.element.dom.scrollTop,
20981
                  scrollElmTop: absolute$3(sc.element).top
20982
                })
20983
              };
20984
            });
20985
          },
20986
          modes: [sharedBackstage.header.getDockingMode()],
20987
          onDocked: onDockingSwitch,
20988
          onUndocked: onDockingSwitch
20989
        }),
20990
        ...additionalBehaviours
20991
      ];
20992
    };
20993
 
20994
    var StickyHeader = /*#__PURE__*/Object.freeze({
20995
        __proto__: null,
20996
        setup: setup$9,
20997
        isDocked: isDocked,
20998
        getBehaviours: getBehaviours
20999
    });
21000
 
21001
    const renderHeader = spec => {
21002
      const editor = spec.editor;
21003
      const getBehaviours$2 = spec.sticky ? getBehaviours : getBehaviours$1;
21004
      return {
21005
        uid: spec.uid,
21006
        dom: spec.dom,
21007
        components: spec.components,
21008
        behaviours: derive$1(getBehaviours$2(editor, spec.sharedBackstage))
21009
      };
21010
    };
21011
 
21012
    const groupToolbarButtonSchema = objOf([
21013
      type,
21014
      requiredOf('items', oneOf([
21015
        arrOfObj([
21016
          name$1,
21017
          requiredArrayOf('items', string)
21018
        ]),
21019
        string
21020
      ]))
21021
    ].concat(baseToolbarButtonFields));
21022
    const createGroupToolbarButton = spec => asRaw('GroupToolbarButton', groupToolbarButtonSchema, spec);
21023
 
21024
    const baseMenuButtonFields = [
21025
      optionString('text'),
21026
      optionString('tooltip'),
21027
      optionString('icon'),
21028
      defaultedOf('search', false, oneOf([
21029
        boolean,
21030
        objOf([optionString('placeholder')])
21031
      ], x => {
21032
        if (isBoolean(x)) {
21033
          return x ? Optional.some({ placeholder: Optional.none() }) : Optional.none();
21034
        } else {
21035
          return Optional.some(x);
21036
        }
21037
      })),
21038
      requiredFunction('fetch'),
21039
      defaultedFunction('onSetup', () => noop)
21040
    ];
21041
 
21042
    const MenuButtonSchema = objOf([
21043
      type,
21044
      ...baseMenuButtonFields
21045
    ]);
21046
    const createMenuButton = spec => asRaw('menubutton', MenuButtonSchema, spec);
21047
 
21048
    const splitButtonSchema = objOf([
21049
      type,
21050
      optionalTooltip,
21051
      optionalIcon,
21052
      optionalText,
21053
      optionalSelect,
21054
      fetch$1,
21055
      onSetup,
21056
      defaultedStringEnum('presets', 'normal', [
21057
        'normal',
21058
        'color',
21059
        'listpreview'
21060
      ]),
21061
      defaultedColumns(1),
21062
      onAction,
21063
      onItemAction
21064
    ]);
21065
    const createSplitButton = spec => asRaw('SplitButton', splitButtonSchema, spec);
21066
 
21067
    const factory$d = (detail, spec) => {
21068
      const setMenus = (comp, menus) => {
21069
        const newMenus = map$2(menus, m => {
21070
          const buttonSpec = {
21071
            type: 'menubutton',
21072
            text: m.text,
21073
            fetch: callback => {
21074
              callback(m.getItems());
21075
            }
21076
          };
21077
          const internal = createMenuButton(buttonSpec).mapError(errInfo => formatError(errInfo)).getOrDie();
21078
          return renderMenuButton(internal, 'tox-mbtn', spec.backstage, Optional.some('menuitem'));
21079
        });
21080
        Replacing.set(comp, newMenus);
21081
      };
21082
      const apis = {
21083
        focus: Keying.focusIn,
21084
        setMenus
21085
      };
21086
      return {
21087
        uid: detail.uid,
21088
        dom: detail.dom,
21089
        components: [],
21090
        behaviours: derive$1([
21091
          Replacing.config({}),
21092
          config('menubar-events', [
21093
            runOnAttached(component => {
21094
              detail.onSetup(component);
21095
            }),
21096
            run$1(mouseover(), (comp, se) => {
21097
              descendant(comp.element, '.' + 'tox-mbtn--active').each(activeButton => {
21098
                closest$1(se.event.target, '.' + 'tox-mbtn').each(hoveredButton => {
21099
                  if (!eq(activeButton, hoveredButton)) {
21100
                    comp.getSystem().getByDom(activeButton).each(activeComp => {
21101
                      comp.getSystem().getByDom(hoveredButton).each(hoveredComp => {
21102
                        Dropdown.expand(hoveredComp);
21103
                        Dropdown.close(activeComp);
21104
                        Focusing.focus(hoveredComp);
21105
                      });
21106
                    });
21107
                  }
21108
                });
21109
              });
21110
            }),
21111
            run$1(focusShifted(), (comp, se) => {
21112
              se.event.prevFocus.bind(prev => comp.getSystem().getByDom(prev).toOptional()).each(prev => {
21113
                se.event.newFocus.bind(nu => comp.getSystem().getByDom(nu).toOptional()).each(nu => {
21114
                  if (Dropdown.isOpen(prev)) {
21115
                    Dropdown.expand(nu);
21116
                    Dropdown.close(prev);
21117
                  }
21118
                });
21119
              });
21120
            })
21121
          ]),
21122
          Keying.config({
21123
            mode: 'flow',
21124
            selector: '.' + 'tox-mbtn',
21125
            onEscape: comp => {
21126
              detail.onEscape(comp);
21127
              return Optional.some(true);
21128
            }
21129
          }),
21130
          Tabstopping.config({})
21131
        ]),
21132
        apis,
21133
        domModification: { attributes: { role: 'menubar' } }
21134
      };
21135
    };
21136
    var SilverMenubar = single({
21137
      factory: factory$d,
21138
      name: 'silver.Menubar',
21139
      configFields: [
21140
        required$1('dom'),
21141
        required$1('uid'),
21142
        required$1('onEscape'),
21143
        required$1('backstage'),
21144
        defaulted('onSetup', noop)
21145
      ],
21146
      apis: {
21147
        focus: (apis, comp) => {
21148
          apis.focus(comp);
21149
        },
21150
        setMenus: (apis, comp, menus) => {
21151
          apis.setMenus(comp, menus);
21152
        }
21153
      }
21154
    });
21155
 
21156
    const promotionMessage = '\u26A1\ufe0fUpgrade';
21157
    const promotionLink = 'https://www.tiny.cloud/tinymce-self-hosted-premium-features/?utm_campaign=self_hosted_upgrade_promo&utm_source=tiny&utm_medium=referral';
21158
    const renderPromotion = spec => {
21159
      return {
21160
        uid: spec.uid,
21161
        dom: spec.dom,
21162
        components: [{
21163
            dom: {
21164
              tag: 'a',
21165
              attributes: {
21166
                'href': promotionLink,
21167
                'rel': 'noopener',
21168
                'target': '_blank',
21169
                'aria-hidden': 'true'
21170
              },
21171
              classes: ['tox-promotion-link'],
21172
              innerHtml: promotionMessage
21173
            }
21174
          }]
21175
      };
21176
    };
21177
 
21178
    const owner = 'container';
21179
    const schema$d = [field('slotBehaviours', [])];
21180
    const getPartName = name => '<alloy.field.' + name + '>';
21181
    const sketch = sSpec => {
21182
      const parts = (() => {
21183
        const record = [];
21184
        const slot = (name, config) => {
21185
          record.push(name);
21186
          return generateOne$1(owner, getPartName(name), config);
21187
        };
21188
        return {
21189
          slot,
21190
          record: constant$1(record)
21191
        };
21192
      })();
21193
      const spec = sSpec(parts);
21194
      const partNames = parts.record();
21195
      const fieldParts = map$2(partNames, n => required({
21196
        name: n,
21197
        pname: getPartName(n)
21198
      }));
21199
      return composite$1(owner, schema$d, fieldParts, make$1, spec);
21200
    };
21201
    const make$1 = (detail, components) => {
21202
      const getSlotNames = _ => getAllPartNames(detail);
21203
      const getSlot = (container, key) => getPart(container, detail, key);
21204
      const onSlot = (f, def) => (container, key) => getPart(container, detail, key).map(slot => f(slot, key)).getOr(def);
21205
      const onSlots = f => (container, keys) => {
21206
        each$1(keys, key => f(container, key));
21207
      };
21208
      const doShowing = (comp, _key) => get$f(comp.element, 'aria-hidden') !== 'true';
21209
      const doShow = (comp, key) => {
21210
        if (!doShowing(comp)) {
21211
          const element = comp.element;
21212
          remove$6(element, 'display');
21213
          remove$7(element, 'aria-hidden');
21214
          emitWith(comp, slotVisibility(), {
21215
            name: key,
21216
            visible: true
21217
          });
21218
        }
21219
      };
21220
      const doHide = (comp, key) => {
21221
        if (doShowing(comp)) {
21222
          const element = comp.element;
21223
          set$8(element, 'display', 'none');
21224
          set$9(element, 'aria-hidden', 'true');
21225
          emitWith(comp, slotVisibility(), {
21226
            name: key,
21227
            visible: false
21228
          });
21229
        }
21230
      };
21231
      const isShowing = onSlot(doShowing, false);
21232
      const hideSlot = onSlot(doHide);
21233
      const hideSlots = onSlots(hideSlot);
21234
      const hideAllSlots = container => hideSlots(container, getSlotNames());
21235
      const showSlot = onSlot(doShow);
21236
      const apis = {
21237
        getSlotNames,
21238
        getSlot,
21239
        isShowing,
21240
        hideSlot,
21241
        hideAllSlots,
21242
        showSlot
21243
      };
21244
      return {
21245
        uid: detail.uid,
21246
        dom: detail.dom,
21247
        components,
21248
        behaviours: get$3(detail.slotBehaviours),
21249
        apis
21250
      };
21251
    };
21252
    const slotApis = map$1({
21253
      getSlotNames: (apis, c) => apis.getSlotNames(c),
21254
      getSlot: (apis, c, key) => apis.getSlot(c, key),
21255
      isShowing: (apis, c, key) => apis.isShowing(c, key),
21256
      hideSlot: (apis, c, key) => apis.hideSlot(c, key),
21257
      hideAllSlots: (apis, c) => apis.hideAllSlots(c),
21258
      showSlot: (apis, c, key) => apis.showSlot(c, key)
21259
    }, value => makeApi(value));
21260
    const SlotContainer = {
21261
      ...slotApis,
21262
      ...{ sketch }
21263
    };
21264
 
21265
    const sidebarSchema = objOf([
21266
      optionalIcon,
21267
      optionalTooltip,
21268
      defaultedFunction('onShow', noop),
21269
      defaultedFunction('onHide', noop),
21270
      onSetup
21271
    ]);
21272
    const createSidebar = spec => asRaw('sidebar', sidebarSchema, spec);
21273
 
21274
    const setup$8 = editor => {
21275
      const {sidebars} = editor.ui.registry.getAll();
21276
      each$1(keys(sidebars), name => {
21277
        const spec = sidebars[name];
21278
        const isActive = () => is$1(Optional.from(editor.queryCommandValue('ToggleSidebar')), name);
21279
        editor.ui.registry.addToggleButton(name, {
21280
          icon: spec.icon,
21281
          tooltip: spec.tooltip,
21282
          onAction: buttonApi => {
21283
            editor.execCommand('ToggleSidebar', false, name);
21284
            buttonApi.setActive(isActive());
21285
          },
21286
          onSetup: buttonApi => {
21287
            buttonApi.setActive(isActive());
21288
            const handleToggle = () => buttonApi.setActive(isActive());
21289
            editor.on('ToggleSidebar', handleToggle);
21290
            return () => {
21291
              editor.off('ToggleSidebar', handleToggle);
21292
            };
21293
          }
21294
        });
21295
      });
21296
    };
21297
    const getApi = comp => ({ element: () => comp.element.dom });
21298
    const makePanels = (parts, panelConfigs) => {
21299
      const specs = map$2(keys(panelConfigs), name => {
21300
        const spec = panelConfigs[name];
21301
        const bridged = getOrDie(createSidebar(spec));
21302
        return {
21303
          name,
21304
          getApi,
21305
          onSetup: bridged.onSetup,
21306
          onShow: bridged.onShow,
21307
          onHide: bridged.onHide
21308
        };
21309
      });
21310
      return map$2(specs, spec => {
21311
        const editorOffCell = Cell(noop);
21312
        return parts.slot(spec.name, {
21313
          dom: {
21314
            tag: 'div',
21315
            classes: ['tox-sidebar__pane']
21316
          },
21317
          behaviours: SimpleBehaviours.unnamedEvents([
21318
            onControlAttached(spec, editorOffCell),
21319
            onControlDetached(spec, editorOffCell),
21320
            run$1(slotVisibility(), (sidepanel, se) => {
21321
              const data = se.event;
21322
              const optSidePanelSpec = find$5(specs, config => config.name === data.name);
21323
              optSidePanelSpec.each(sidePanelSpec => {
21324
                const handler = data.visible ? sidePanelSpec.onShow : sidePanelSpec.onHide;
21325
                handler(sidePanelSpec.getApi(sidepanel));
21326
              });
21327
            })
21328
          ])
21329
        });
21330
      });
21331
    };
21332
    const makeSidebar = panelConfigs => SlotContainer.sketch(parts => ({
21333
      dom: {
21334
        tag: 'div',
21335
        classes: ['tox-sidebar__pane-container']
21336
      },
21337
      components: makePanels(parts, panelConfigs),
21338
      slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
21339
    }));
21340
    const setSidebar = (sidebar, panelConfigs, showSidebar) => {
21341
      const optSlider = Composing.getCurrent(sidebar);
21342
      optSlider.each(slider => {
21343
        Replacing.set(slider, [makeSidebar(panelConfigs)]);
21344
        const configKey = showSidebar === null || showSidebar === void 0 ? void 0 : showSidebar.toLowerCase();
21345
        if (isString(configKey) && has$2(panelConfigs, configKey)) {
21346
          Composing.getCurrent(slider).each(slotContainer => {
21347
            SlotContainer.showSlot(slotContainer, configKey);
21348
            Sliding.immediateGrow(slider);
21349
            remove$6(slider.element, 'width');
21350
            updateSidebarRoleOnToggle(sidebar.element, 'region');
21351
          });
21352
        }
21353
      });
21354
    };
21355
    const updateSidebarRoleOnToggle = (sidebar, sidebarState) => {
21356
      set$9(sidebar, 'role', sidebarState);
21357
    };
21358
    const toggleSidebar = (sidebar, name) => {
21359
      const optSlider = Composing.getCurrent(sidebar);
21360
      optSlider.each(slider => {
21361
        const optSlotContainer = Composing.getCurrent(slider);
21362
        optSlotContainer.each(slotContainer => {
21363
          if (Sliding.hasGrown(slider)) {
21364
            if (SlotContainer.isShowing(slotContainer, name)) {
21365
              Sliding.shrink(slider);
21366
              updateSidebarRoleOnToggle(sidebar.element, 'presentation');
21367
            } else {
21368
              SlotContainer.hideAllSlots(slotContainer);
21369
              SlotContainer.showSlot(slotContainer, name);
21370
              updateSidebarRoleOnToggle(sidebar.element, 'region');
21371
            }
21372
          } else {
21373
            SlotContainer.hideAllSlots(slotContainer);
21374
            SlotContainer.showSlot(slotContainer, name);
21375
            Sliding.grow(slider);
21376
            updateSidebarRoleOnToggle(sidebar.element, 'region');
21377
          }
21378
        });
21379
      });
21380
    };
21381
    const whichSidebar = sidebar => {
21382
      const optSlider = Composing.getCurrent(sidebar);
21383
      return optSlider.bind(slider => {
21384
        const sidebarOpen = Sliding.isGrowing(slider) || Sliding.hasGrown(slider);
21385
        if (sidebarOpen) {
21386
          const optSlotContainer = Composing.getCurrent(slider);
21387
          return optSlotContainer.bind(slotContainer => find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name)));
21388
        } else {
21389
          return Optional.none();
21390
        }
21391
      });
21392
    };
21393
    const fixSize = generate$6('FixSizeEvent');
21394
    const autoSize = generate$6('AutoSizeEvent');
21395
    const renderSidebar = spec => ({
21396
      uid: spec.uid,
21397
      dom: {
21398
        tag: 'div',
21399
        classes: ['tox-sidebar'],
21400
        attributes: { role: 'presentation' }
21401
      },
21402
      components: [{
21403
          dom: {
21404
            tag: 'div',
21405
            classes: ['tox-sidebar__slider']
21406
          },
21407
          components: [],
21408
          behaviours: derive$1([
21409
            Tabstopping.config({}),
21410
            Focusing.config({}),
21411
            Sliding.config({
21412
              dimension: { property: 'width' },
21413
              closedClass: 'tox-sidebar--sliding-closed',
21414
              openClass: 'tox-sidebar--sliding-open',
21415
              shrinkingClass: 'tox-sidebar--sliding-shrinking',
21416
              growingClass: 'tox-sidebar--sliding-growing',
21417
              onShrunk: slider => {
21418
                const optSlotContainer = Composing.getCurrent(slider);
21419
                optSlotContainer.each(SlotContainer.hideAllSlots);
21420
                emit(slider, autoSize);
21421
              },
21422
              onGrown: slider => {
21423
                emit(slider, autoSize);
21424
              },
21425
              onStartGrow: slider => {
21426
                emitWith(slider, fixSize, { width: getRaw(slider.element, 'width').getOr('') });
21427
              },
21428
              onStartShrink: slider => {
21429
                emitWith(slider, fixSize, { width: get$c(slider.element) + 'px' });
21430
              }
21431
            }),
21432
            Replacing.config({}),
21433
            Composing.config({
21434
              find: comp => {
21435
                const children = Replacing.contents(comp);
21436
                return head(children);
21437
              }
21438
            })
21439
          ])
21440
        }],
21441
      behaviours: derive$1([
21442
        ComposingConfigs.childAt(0),
21443
        config('sidebar-sliding-events', [
21444
          run$1(fixSize, (comp, se) => {
21445
            set$8(comp.element, 'width', se.event.width);
21446
          }),
21447
          run$1(autoSize, (comp, _se) => {
21448
            remove$6(comp.element, 'width');
21449
          })
21450
        ])
21451
      ])
21452
    });
21453
 
21454
    const block = (component, config, state, getBusySpec) => {
21455
      set$9(component.element, 'aria-busy', true);
21456
      const root = config.getRoot(component).getOr(component);
21457
      const blockerBehaviours = derive$1([
21458
        Keying.config({
21459
          mode: 'special',
21460
          onTab: () => Optional.some(true),
21461
          onShiftTab: () => Optional.some(true)
21462
        }),
21463
        Focusing.config({})
21464
      ]);
21465
      const blockSpec = getBusySpec(root, blockerBehaviours);
21466
      const blocker = root.getSystem().build(blockSpec);
21467
      Replacing.append(root, premade(blocker));
21468
      if (blocker.hasConfigured(Keying) && config.focus) {
21469
        Keying.focusIn(blocker);
21470
      }
21471
      if (!state.isBlocked()) {
21472
        config.onBlock(component);
21473
      }
21474
      state.blockWith(() => Replacing.remove(root, blocker));
21475
    };
21476
    const unblock = (component, config, state) => {
21477
      remove$7(component.element, 'aria-busy');
21478
      if (state.isBlocked()) {
21479
        config.onUnblock(component);
21480
      }
21481
      state.clear();
21482
    };
21483
    const isBlocked = (component, blockingConfig, blockingState) => blockingState.isBlocked();
21484
 
21485
    var BlockingApis = /*#__PURE__*/Object.freeze({
21486
        __proto__: null,
21487
        block: block,
21488
        unblock: unblock,
21489
        isBlocked: isBlocked
21490
    });
21491
 
21492
    var BlockingSchema = [
21493
      defaultedFunction('getRoot', Optional.none),
21494
      defaultedBoolean('focus', true),
21495
      onHandler('onBlock'),
21496
      onHandler('onUnblock')
21497
    ];
21498
 
21499
    const init$4 = () => {
21500
      const blocker = destroyable();
21501
      const blockWith = destroy => {
21502
        blocker.set({ destroy });
21503
      };
21504
      return nu$8({
21505
        readState: blocker.isSet,
21506
        blockWith,
21507
        clear: blocker.clear,
21508
        isBlocked: blocker.isSet
21509
      });
21510
    };
21511
 
21512
    var BlockingState = /*#__PURE__*/Object.freeze({
21513
        __proto__: null,
21514
        init: init$4
21515
    });
21516
 
21517
    const Blocking = create$4({
21518
      fields: BlockingSchema,
21519
      name: 'blocking',
21520
      apis: BlockingApis,
21521
      state: BlockingState
21522
    });
21523
 
21524
    const getBusySpec$1 = providerBackstage => (_root, _behaviours) => ({
21525
      dom: {
21526
        tag: 'div',
21527
        attributes: {
21528
          'aria-label': providerBackstage.translate('Loading...'),
21529
          'tabindex': '0'
21530
        },
21531
        classes: ['tox-throbber__busy-spinner']
21532
      },
21533
      components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
21534
    });
21535
    const focusBusyComponent = throbber => Composing.getCurrent(throbber).each(comp => focus$3(comp.element, true));
21536
    const toggleEditorTabIndex = (editor, state) => {
21537
      const tabIndexAttr = 'tabindex';
21538
      const dataTabIndexAttr = `data-mce-${ tabIndexAttr }`;
21539
      Optional.from(editor.iframeElement).map(SugarElement.fromDom).each(iframe => {
21540
        if (state) {
21541
          getOpt(iframe, tabIndexAttr).each(tabIndex => set$9(iframe, dataTabIndexAttr, tabIndex));
21542
          set$9(iframe, tabIndexAttr, -1);
21543
        } else {
21544
          remove$7(iframe, tabIndexAttr);
21545
          getOpt(iframe, dataTabIndexAttr).each(tabIndex => {
21546
            set$9(iframe, tabIndexAttr, tabIndex);
21547
            remove$7(iframe, dataTabIndexAttr);
21548
          });
21549
        }
21550
      });
21551
    };
21552
    const toggleThrobber = (editor, comp, state, providerBackstage) => {
21553
      const element = comp.element;
21554
      toggleEditorTabIndex(editor, state);
21555
      if (state) {
21556
        Blocking.block(comp, getBusySpec$1(providerBackstage));
21557
        remove$6(element, 'display');
21558
        remove$7(element, 'aria-hidden');
21559
        if (editor.hasFocus()) {
21560
          focusBusyComponent(comp);
21561
        }
21562
      } else {
21563
        const throbberFocus = Composing.getCurrent(comp).exists(busyComp => hasFocus(busyComp.element));
21564
        Blocking.unblock(comp);
21565
        set$8(element, 'display', 'none');
21566
        set$9(element, 'aria-hidden', 'true');
21567
        if (throbberFocus) {
21568
          editor.focus();
21569
        }
21570
      }
21571
    };
21572
    const renderThrobber = spec => ({
21573
      uid: spec.uid,
21574
      dom: {
21575
        tag: 'div',
21576
        attributes: { 'aria-hidden': 'true' },
21577
        classes: ['tox-throbber'],
21578
        styles: { display: 'none' }
21579
      },
21580
      behaviours: derive$1([
21581
        Replacing.config({}),
21582
        Blocking.config({ focus: false }),
21583
        Composing.config({ find: comp => head(comp.components()) })
21584
      ]),
21585
      components: []
21586
    });
21587
    const isFocusEvent = event => event.type === 'focusin';
21588
    const isPasteBinTarget = event => {
21589
      if (isFocusEvent(event)) {
21590
        const node = event.composed ? head(event.composedPath()) : Optional.from(event.target);
21591
        return node.map(SugarElement.fromDom).filter(isElement$1).exists(targetElm => has(targetElm, 'mce-pastebin'));
21592
      } else {
21593
        return false;
21594
      }
21595
    };
21596
    const setup$7 = (editor, lazyThrobber, sharedBackstage) => {
21597
      const throbberState = Cell(false);
21598
      const timer = value$2();
21599
      const stealFocus = e => {
21600
        if (throbberState.get() && !isPasteBinTarget(e)) {
21601
          e.preventDefault();
21602
          focusBusyComponent(lazyThrobber());
21603
          editor.editorManager.setActive(editor);
21604
        }
21605
      };
21606
      if (!editor.inline) {
21607
        editor.on('PreInit', () => {
21608
          editor.dom.bind(editor.getWin(), 'focusin', stealFocus);
21609
          editor.on('BeforeExecCommand', e => {
21610
            if (e.command.toLowerCase() === 'mcefocus' && e.value !== true) {
21611
              stealFocus(e);
21612
            }
21613
          });
21614
        });
21615
      }
21616
      const toggle = state => {
21617
        if (state !== throbberState.get()) {
21618
          throbberState.set(state);
21619
          toggleThrobber(editor, lazyThrobber(), state, sharedBackstage.providers);
21620
          fireAfterProgressState(editor, state);
21621
        }
21622
      };
21623
      editor.on('ProgressState', e => {
21624
        timer.on(clearTimeout);
21625
        if (isNumber(e.time)) {
21626
          const timerId = global$9.setEditorTimeout(editor, () => toggle(e.state), e.time);
21627
          timer.set(timerId);
21628
        } else {
21629
          toggle(e.state);
21630
          timer.clear();
21631
        }
21632
      });
21633
    };
21634
 
21635
    const generate$1 = (xs, f) => {
21636
      const init = {
21637
        len: 0,
21638
        list: []
21639
      };
21640
      const r = foldl(xs, (b, a) => {
21641
        const value = f(a, b.len);
21642
        return value.fold(constant$1(b), v => ({
21643
          len: v.finish,
21644
          list: b.list.concat([v])
21645
        }));
21646
      }, init);
21647
      return r.list;
21648
    };
21649
 
21650
    const output = (within, extra, withinWidth) => ({
21651
      within,
21652
      extra,
21653
      withinWidth
21654
    });
21655
    const apportion = (units, total, len) => {
21656
      const parray = generate$1(units, (unit, current) => {
21657
        const width = len(unit);
21658
        return Optional.some({
21659
          element: unit,
21660
          start: current,
21661
          finish: current + width,
21662
          width
21663
        });
21664
      });
21665
      const within = filter$2(parray, unit => unit.finish <= total);
21666
      const withinWidth = foldr(within, (acc, el) => acc + el.width, 0);
21667
      const extra = parray.slice(within.length);
21668
      return {
21669
        within,
21670
        extra,
21671
        withinWidth
21672
      };
21673
    };
21674
    const toUnit = parray => map$2(parray, unit => unit.element);
21675
    const fitLast = (within, extra, withinWidth) => {
21676
      const fits = toUnit(within.concat(extra));
21677
      return output(fits, [], withinWidth);
21678
    };
21679
    const overflow = (within, extra, overflower, withinWidth) => {
21680
      const fits = toUnit(within).concat([overflower]);
21681
      return output(fits, toUnit(extra), withinWidth);
21682
    };
21683
    const fitAll = (within, extra, withinWidth) => output(toUnit(within), [], withinWidth);
21684
    const tryFit = (total, units, len) => {
21685
      const divide = apportion(units, total, len);
21686
      return divide.extra.length === 0 ? Optional.some(divide) : Optional.none();
21687
    };
21688
    const partition = (total, units, len, overflower) => {
21689
      const divide = tryFit(total, units, len).getOrThunk(() => apportion(units, total - len(overflower), len));
21690
      const within = divide.within;
21691
      const extra = divide.extra;
21692
      const withinWidth = divide.withinWidth;
21693
      if (extra.length === 1 && extra[0].width <= len(overflower)) {
21694
        return fitLast(within, extra, withinWidth);
21695
      } else if (extra.length >= 1) {
21696
        return overflow(within, extra, overflower, withinWidth);
21697
      } else {
21698
        return fitAll(within, extra, withinWidth);
21699
      }
21700
    };
21701
 
21702
    const setGroups$1 = (toolbar, storedGroups) => {
21703
      const bGroups = map$2(storedGroups, g => premade(g));
21704
      Toolbar.setGroups(toolbar, bGroups);
21705
    };
21706
    const findFocusedComp = comps => findMap(comps, comp => search(comp.element).bind(focusedElm => comp.getSystem().getByDom(focusedElm).toOptional()));
21707
    const refresh$2 = (toolbar, detail, setOverflow) => {
21708
      const builtGroups = detail.builtGroups.get();
21709
      if (builtGroups.length === 0) {
21710
        return;
21711
      }
21712
      const primary = getPartOrDie(toolbar, detail, 'primary');
21713
      const overflowGroup = Coupling.getCoupled(toolbar, 'overflowGroup');
21714
      set$8(primary.element, 'visibility', 'hidden');
21715
      const groups = builtGroups.concat([overflowGroup]);
21716
      const focusedComp = findFocusedComp(groups);
21717
      setOverflow([]);
21718
      setGroups$1(primary, groups);
21719
      const availableWidth = get$c(primary.element);
21720
      const overflows = partition(availableWidth, detail.builtGroups.get(), comp => get$c(comp.element), overflowGroup);
21721
      if (overflows.extra.length === 0) {
21722
        Replacing.remove(primary, overflowGroup);
21723
        setOverflow([]);
21724
      } else {
21725
        setGroups$1(primary, overflows.within);
21726
        setOverflow(overflows.extra);
21727
      }
21728
      remove$6(primary.element, 'visibility');
21729
      reflow(primary.element);
21730
      focusedComp.each(Focusing.focus);
21731
    };
21732
 
21733
    const schema$c = constant$1([
21734
      field('splitToolbarBehaviours', [Coupling]),
21735
      customField('builtGroups', () => Cell([]))
21736
    ]);
21737
 
21738
    const schema$b = constant$1([
21739
      markers$1(['overflowToggledClass']),
21740
      optionFunction('getOverflowBounds'),
21741
      required$1('lazySink'),
21742
      customField('overflowGroups', () => Cell([])),
21743
      onHandler('onOpened'),
21744
      onHandler('onClosed')
21745
    ].concat(schema$c()));
21746
    const parts$7 = constant$1([
21747
      required({
21748
        factory: Toolbar,
21749
        schema: schema$e(),
21750
        name: 'primary'
21751
      }),
21752
      external({
21753
        schema: schema$e(),
21754
        name: 'overflow'
21755
      }),
21756
      external({ name: 'overflow-button' }),
21757
      external({ name: 'overflow-group' })
21758
    ]);
21759
 
21760
    const expandable = constant$1((element, available) => {
21761
      setMax(element, Math.floor(available));
21762
    });
21763
 
21764
    const schema$a = constant$1([
21765
      markers$1(['toggledClass']),
21766
      required$1('lazySink'),
21767
      requiredFunction('fetch'),
21768
      optionFunction('getBounds'),
21769
      optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
21770
      schema$y(),
21771
      onHandler('onToggled')
21772
    ]);
21773
    const parts$6 = constant$1([
21774
      external({
21775
        name: 'button',
21776
        overrides: detail => ({
21777
          dom: { attributes: { 'aria-haspopup': 'true' } },
21778
          buttonBehaviours: derive$1([Toggling.config({
21779
              toggleClass: detail.markers.toggledClass,
21780
              aria: { mode: 'expanded' },
21781
              toggleOnExecute: false,
21782
              onToggled: detail.onToggled
21783
            })])
21784
        })
21785
      }),
21786
      external({
21787
        factory: Toolbar,
21788
        schema: schema$e(),
21789
        name: 'toolbar',
21790
        overrides: detail => {
21791
          return {
21792
            toolbarBehaviours: derive$1([Keying.config({
21793
                mode: 'cyclic',
21794
                onEscape: comp => {
21795
                  getPart(comp, detail, 'button').each(Focusing.focus);
21796
                  return Optional.none();
21797
                }
21798
              })])
21799
          };
21800
        }
21801
      })
21802
    ]);
21803
 
21804
    const shouldSkipFocus = value$2();
21805
    const toggleWithoutFocusing = (button, externals) => {
21806
      shouldSkipFocus.set(true);
21807
      toggle(button, externals);
21808
      shouldSkipFocus.clear();
21809
    };
21810
    const toggle = (button, externals) => {
21811
      const toolbarSandbox = Coupling.getCoupled(button, 'toolbarSandbox');
21812
      if (Sandboxing.isOpen(toolbarSandbox)) {
21813
        Sandboxing.close(toolbarSandbox);
21814
      } else {
21815
        Sandboxing.open(toolbarSandbox, externals.toolbar());
21816
      }
21817
    };
21818
    const position = (button, toolbar, detail, layouts) => {
21819
      const bounds = detail.getBounds.map(bounder => bounder());
21820
      const sink = detail.lazySink(button).getOrDie();
21821
      Positioning.positionWithinBounds(sink, toolbar, {
21822
        anchor: {
21823
          type: 'hotspot',
21824
          hotspot: button,
21825
          layouts,
21826
          overrides: { maxWidthFunction: expandable() }
21827
        }
21828
      }, bounds);
21829
    };
21830
    const setGroups = (button, toolbar, detail, layouts, groups) => {
21831
      Toolbar.setGroups(toolbar, groups);
21832
      position(button, toolbar, detail, layouts);
21833
      Toggling.on(button);
21834
    };
21835
    const makeSandbox = (button, spec, detail) => {
21836
      const ariaControls = manager();
21837
      const onOpen = (sandbox, toolbar) => {
21838
        const skipFocus = shouldSkipFocus.get().getOr(false);
21839
        detail.fetch().get(groups => {
21840
          setGroups(button, toolbar, detail, spec.layouts, groups);
21841
          ariaControls.link(button.element);
21842
          if (!skipFocus) {
21843
            Keying.focusIn(toolbar);
21844
          }
21845
        });
21846
      };
21847
      const onClose = () => {
21848
        Toggling.off(button);
21849
        if (!shouldSkipFocus.get().getOr(false)) {
21850
          Focusing.focus(button);
21851
        }
21852
        ariaControls.unlink(button.element);
21853
      };
21854
      return {
21855
        dom: {
21856
          tag: 'div',
21857
          attributes: { id: ariaControls.id }
21858
        },
21859
        behaviours: derive$1([
21860
          Keying.config({
21861
            mode: 'special',
21862
            onEscape: comp => {
21863
              Sandboxing.close(comp);
21864
              return Optional.some(true);
21865
            }
21866
          }),
21867
          Sandboxing.config({
21868
            onOpen,
21869
            onClose,
21870
            isPartOf: (container, data, queryElem) => {
21871
              return isPartOf$1(data, queryElem) || isPartOf$1(button, queryElem);
21872
            },
21873
            getAttachPoint: () => {
21874
              return detail.lazySink(button).getOrDie();
21875
            }
21876
          }),
21877
          Receiving.config({
21878
            channels: {
21879
              ...receivingChannel$1({
21880
                isExtraPart: never,
21881
                ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
21882
              }),
21883
              ...receivingChannel({
21884
                doReposition: () => {
21885
                  Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
21886
                    position(button, toolbar, detail, spec.layouts);
21887
                  });
21888
                }
21889
              })
21890
            }
21891
          })
21892
        ])
21893
      };
21894
    };
21895
    const factory$c = (detail, components, spec, externals) => ({
21896
      ...Button.sketch({
21897
        ...externals.button(),
21898
        action: button => {
21899
          toggle(button, externals);
21900
        },
21901
        buttonBehaviours: SketchBehaviours.augment({ dump: externals.button().buttonBehaviours }, [Coupling.config({
21902
            others: {
21903
              toolbarSandbox: button => {
21904
                return makeSandbox(button, spec, detail);
21905
              }
21906
            }
21907
          })])
21908
      }),
21909
      apis: {
21910
        setGroups: (button, groups) => {
21911
          Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
21912
            setGroups(button, toolbar, detail, spec.layouts, groups);
21913
          });
21914
        },
21915
        reposition: button => {
21916
          Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
21917
            position(button, toolbar, detail, spec.layouts);
21918
          });
21919
        },
21920
        toggle: button => {
21921
          toggle(button, externals);
21922
        },
21923
        toggleWithoutFocusing: button => {
21924
          toggleWithoutFocusing(button, externals);
21925
        },
21926
        getToolbar: button => {
21927
          return Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox'));
21928
        },
21929
        isOpen: button => {
21930
          return Sandboxing.isOpen(Coupling.getCoupled(button, 'toolbarSandbox'));
21931
        }
21932
      }
21933
    });
21934
    const FloatingToolbarButton = composite({
21935
      name: 'FloatingToolbarButton',
21936
      factory: factory$c,
21937
      configFields: schema$a(),
21938
      partFields: parts$6(),
21939
      apis: {
21940
        setGroups: (apis, button, groups) => {
21941
          apis.setGroups(button, groups);
21942
        },
21943
        reposition: (apis, button) => {
21944
          apis.reposition(button);
21945
        },
21946
        toggle: (apis, button) => {
21947
          apis.toggle(button);
21948
        },
21949
        toggleWithoutFocusing: (apis, button) => {
21950
          apis.toggleWithoutFocusing(button);
21951
        },
21952
        getToolbar: (apis, button) => apis.getToolbar(button),
21953
        isOpen: (apis, button) => apis.isOpen(button)
21954
      }
21955
    });
21956
 
21957
    const schema$9 = constant$1([
21958
      required$1('items'),
21959
      markers$1(['itemSelector']),
21960
      field('tgroupBehaviours', [Keying])
21961
    ]);
21962
    const parts$5 = constant$1([group({
21963
        name: 'items',
21964
        unit: 'item'
21965
      })]);
21966
 
21967
    const factory$b = (detail, components, _spec, _externals) => ({
21968
      uid: detail.uid,
21969
      dom: detail.dom,
21970
      components,
21971
      behaviours: augment(detail.tgroupBehaviours, [Keying.config({
21972
          mode: 'flow',
21973
          selector: detail.markers.itemSelector
21974
        })]),
21975
      domModification: { attributes: { role: 'toolbar' } }
21976
    });
21977
    const ToolbarGroup = composite({
21978
      name: 'ToolbarGroup',
21979
      configFields: schema$9(),
21980
      partFields: parts$5(),
21981
      factory: factory$b
21982
    });
21983
 
21984
    const buildGroups = comps => map$2(comps, g => premade(g));
21985
    const refresh$1 = (toolbar, memFloatingToolbarButton, detail) => {
21986
      refresh$2(toolbar, detail, overflowGroups => {
21987
        detail.overflowGroups.set(overflowGroups);
21988
        memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
21989
          FloatingToolbarButton.setGroups(floatingToolbarButton, buildGroups(overflowGroups));
21990
        });
21991
      });
21992
    };
21993
    const factory$a = (detail, components, spec, externals) => {
21994
      const memFloatingToolbarButton = record(FloatingToolbarButton.sketch({
21995
        fetch: () => Future.nu(resolve => {
21996
          resolve(buildGroups(detail.overflowGroups.get()));
21997
        }),
21998
        layouts: {
21999
          onLtr: () => [
22000
            southwest$2,
22001
            southeast$2
22002
          ],
22003
          onRtl: () => [
22004
            southeast$2,
22005
            southwest$2
22006
          ],
22007
          onBottomLtr: () => [
22008
            northwest$2,
22009
            northeast$2
22010
          ],
22011
          onBottomRtl: () => [
22012
            northeast$2,
22013
            northwest$2
22014
          ]
22015
        },
22016
        getBounds: spec.getOverflowBounds,
22017
        lazySink: detail.lazySink,
22018
        fireDismissalEventInstead: {},
22019
        markers: { toggledClass: detail.markers.overflowToggledClass },
22020
        parts: {
22021
          button: externals['overflow-button'](),
22022
          toolbar: externals.overflow()
22023
        },
22024
        onToggled: (comp, state) => detail[state ? 'onOpened' : 'onClosed'](comp)
22025
      }));
22026
      return {
22027
        uid: detail.uid,
22028
        dom: detail.dom,
22029
        components,
22030
        behaviours: augment(detail.splitToolbarBehaviours, [Coupling.config({
22031
            others: {
22032
              overflowGroup: () => {
22033
                return ToolbarGroup.sketch({
22034
                  ...externals['overflow-group'](),
22035
                  items: [memFloatingToolbarButton.asSpec()]
22036
                });
22037
              }
22038
            }
22039
          })]),
22040
        apis: {
22041
          setGroups: (toolbar, groups) => {
22042
            detail.builtGroups.set(map$2(groups, toolbar.getSystem().build));
22043
            refresh$1(toolbar, memFloatingToolbarButton, detail);
22044
          },
22045
          refresh: toolbar => refresh$1(toolbar, memFloatingToolbarButton, detail),
22046
          toggle: toolbar => {
22047
            memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
22048
              FloatingToolbarButton.toggle(floatingToolbarButton);
22049
            });
22050
          },
22051
          toggleWithoutFocusing: toolbar => {
22052
            memFloatingToolbarButton.getOpt(toolbar).each(FloatingToolbarButton.toggleWithoutFocusing);
22053
          },
22054
          isOpen: toolbar => memFloatingToolbarButton.getOpt(toolbar).map(FloatingToolbarButton.isOpen).getOr(false),
22055
          reposition: toolbar => {
22056
            memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
22057
              FloatingToolbarButton.reposition(floatingToolbarButton);
22058
            });
22059
          },
22060
          getOverflow: toolbar => memFloatingToolbarButton.getOpt(toolbar).bind(FloatingToolbarButton.getToolbar)
22061
        },
22062
        domModification: { attributes: { role: 'group' } }
22063
      };
22064
    };
22065
    const SplitFloatingToolbar = composite({
22066
      name: 'SplitFloatingToolbar',
22067
      configFields: schema$b(),
22068
      partFields: parts$7(),
22069
      factory: factory$a,
22070
      apis: {
22071
        setGroups: (apis, toolbar, groups) => {
22072
          apis.setGroups(toolbar, groups);
22073
        },
22074
        refresh: (apis, toolbar) => {
22075
          apis.refresh(toolbar);
22076
        },
22077
        reposition: (apis, toolbar) => {
22078
          apis.reposition(toolbar);
22079
        },
22080
        toggle: (apis, toolbar) => {
22081
          apis.toggle(toolbar);
22082
        },
22083
        toggleWithoutFocusing: (apis, toolbar) => {
22084
          apis.toggle(toolbar);
22085
        },
22086
        isOpen: (apis, toolbar) => apis.isOpen(toolbar),
22087
        getOverflow: (apis, toolbar) => apis.getOverflow(toolbar)
22088
      }
22089
    });
22090
 
22091
    const schema$8 = constant$1([
22092
      markers$1([
22093
        'closedClass',
22094
        'openClass',
22095
        'shrinkingClass',
22096
        'growingClass',
22097
        'overflowToggledClass'
22098
      ]),
22099
      onHandler('onOpened'),
22100
      onHandler('onClosed')
22101
    ].concat(schema$c()));
22102
    const parts$4 = constant$1([
22103
      required({
22104
        factory: Toolbar,
22105
        schema: schema$e(),
22106
        name: 'primary'
22107
      }),
22108
      required({
22109
        factory: Toolbar,
22110
        schema: schema$e(),
22111
        name: 'overflow',
22112
        overrides: detail => {
22113
          return {
22114
            toolbarBehaviours: derive$1([
22115
              Sliding.config({
22116
                dimension: { property: 'height' },
22117
                closedClass: detail.markers.closedClass,
22118
                openClass: detail.markers.openClass,
22119
                shrinkingClass: detail.markers.shrinkingClass,
22120
                growingClass: detail.markers.growingClass,
22121
                onShrunk: comp => {
22122
                  getPart(comp, detail, 'overflow-button').each(button => {
22123
                    Toggling.off(button);
22124
                    Focusing.focus(button);
22125
                  });
22126
                  detail.onClosed(comp);
22127
                },
22128
                onGrown: comp => {
22129
                  Keying.focusIn(comp);
22130
                  detail.onOpened(comp);
22131
                },
22132
                onStartGrow: comp => {
22133
                  getPart(comp, detail, 'overflow-button').each(Toggling.on);
22134
                }
22135
              }),
22136
              Keying.config({
22137
                mode: 'acyclic',
22138
                onEscape: comp => {
22139
                  getPart(comp, detail, 'overflow-button').each(Focusing.focus);
22140
                  return Optional.some(true);
22141
                }
22142
              })
22143
            ])
22144
          };
22145
        }
22146
      }),
22147
      external({
22148
        name: 'overflow-button',
22149
        overrides: detail => ({
22150
          buttonBehaviours: derive$1([Toggling.config({
22151
              toggleClass: detail.markers.overflowToggledClass,
22152
              aria: { mode: 'pressed' },
22153
              toggleOnExecute: false
22154
            })])
22155
        })
22156
      }),
22157
      external({ name: 'overflow-group' })
22158
    ]);
22159
 
22160
    const isOpen = (toolbar, detail) => getPart(toolbar, detail, 'overflow').map(Sliding.hasGrown).getOr(false);
22161
    const toggleToolbar = (toolbar, detail) => {
22162
      getPart(toolbar, detail, 'overflow-button').bind(() => getPart(toolbar, detail, 'overflow')).each(overf => {
22163
        refresh(toolbar, detail);
22164
        Sliding.toggleGrow(overf);
22165
      });
22166
    };
22167
    const refresh = (toolbar, detail) => {
22168
      getPart(toolbar, detail, 'overflow').each(overflow => {
22169
        refresh$2(toolbar, detail, groups => {
22170
          const builtGroups = map$2(groups, g => premade(g));
22171
          Toolbar.setGroups(overflow, builtGroups);
22172
        });
22173
        getPart(toolbar, detail, 'overflow-button').each(button => {
22174
          if (Sliding.hasGrown(overflow)) {
22175
            Toggling.on(button);
22176
          }
22177
        });
22178
        Sliding.refresh(overflow);
22179
      });
22180
    };
22181
    const factory$9 = (detail, components, spec, externals) => {
22182
      const toolbarToggleEvent = 'alloy.toolbar.toggle';
22183
      const doSetGroups = (toolbar, groups) => {
22184
        const built = map$2(groups, toolbar.getSystem().build);
22185
        detail.builtGroups.set(built);
22186
      };
22187
      return {
22188
        uid: detail.uid,
22189
        dom: detail.dom,
22190
        components,
22191
        behaviours: augment(detail.splitToolbarBehaviours, [
22192
          Coupling.config({
22193
            others: {
22194
              overflowGroup: toolbar => {
22195
                return ToolbarGroup.sketch({
22196
                  ...externals['overflow-group'](),
22197
                  items: [Button.sketch({
22198
                      ...externals['overflow-button'](),
22199
                      action: _button => {
22200
                        emit(toolbar, toolbarToggleEvent);
22201
                      }
22202
                    })]
22203
                });
22204
              }
22205
            }
22206
          }),
22207
          config('toolbar-toggle-events', [run$1(toolbarToggleEvent, toolbar => {
22208
              toggleToolbar(toolbar, detail);
22209
            })])
22210
        ]),
22211
        apis: {
22212
          setGroups: (toolbar, groups) => {
22213
            doSetGroups(toolbar, groups);
22214
            refresh(toolbar, detail);
22215
          },
22216
          refresh: toolbar => refresh(toolbar, detail),
22217
          toggle: toolbar => toggleToolbar(toolbar, detail),
22218
          isOpen: toolbar => isOpen(toolbar, detail)
22219
        },
22220
        domModification: { attributes: { role: 'group' } }
22221
      };
22222
    };
22223
    const SplitSlidingToolbar = composite({
22224
      name: 'SplitSlidingToolbar',
22225
      configFields: schema$8(),
22226
      partFields: parts$4(),
22227
      factory: factory$9,
22228
      apis: {
22229
        setGroups: (apis, toolbar, groups) => {
22230
          apis.setGroups(toolbar, groups);
22231
        },
22232
        refresh: (apis, toolbar) => {
22233
          apis.refresh(toolbar);
22234
        },
22235
        toggle: (apis, toolbar) => {
22236
          apis.toggle(toolbar);
22237
        },
22238
        isOpen: (apis, toolbar) => apis.isOpen(toolbar)
22239
      }
22240
    });
22241
 
22242
    const renderToolbarGroupCommon = toolbarGroup => {
22243
      const attributes = toolbarGroup.title.fold(() => ({}), title => ({ attributes: { title } }));
22244
      return {
22245
        dom: {
22246
          tag: 'div',
22247
          classes: ['tox-toolbar__group'],
22248
          ...attributes
22249
        },
22250
        components: [ToolbarGroup.parts.items({})],
22251
        items: toolbarGroup.items,
22252
        markers: { itemSelector: '*:not(.tox-split-button) > .tox-tbtn:not([disabled]), ' + '.tox-split-button:not([disabled]), ' + '.tox-toolbar-nav-js:not([disabled]), ' + '.tox-number-input:not([disabled])' },
22253
        tgroupBehaviours: derive$1([
22254
          Tabstopping.config({}),
22255
          Focusing.config({})
22256
        ])
22257
      };
22258
    };
22259
    const renderToolbarGroup = toolbarGroup => ToolbarGroup.sketch(renderToolbarGroupCommon(toolbarGroup));
22260
    const getToolbarBehaviours = (toolbarSpec, modeName) => {
22261
      const onAttached = runOnAttached(component => {
22262
        const groups = map$2(toolbarSpec.initGroups, renderToolbarGroup);
22263
        Toolbar.setGroups(component, groups);
22264
      });
22265
      return derive$1([
22266
        DisablingConfigs.toolbarButton(toolbarSpec.providers.isDisabled),
22267
        receivingConfig(),
22268
        Keying.config({
22269
          mode: modeName,
22270
          onEscape: toolbarSpec.onEscape,
22271
          selector: '.tox-toolbar__group'
22272
        }),
22273
        config('toolbar-events', [onAttached])
22274
      ]);
22275
    };
22276
    const renderMoreToolbarCommon = toolbarSpec => {
22277
      const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
22278
      return {
22279
        uid: toolbarSpec.uid,
22280
        dom: {
22281
          tag: 'div',
22282
          classes: ['tox-toolbar-overlord']
22283
        },
22284
        parts: {
22285
          'overflow-group': renderToolbarGroupCommon({
22286
            title: Optional.none(),
22287
            items: []
22288
          }),
22289
          'overflow-button': renderIconButtonSpec({
22290
            name: 'more',
22291
            icon: Optional.some('more-drawer'),
22292
            enabled: true,
22293
            tooltip: Optional.some('Reveal or hide additional toolbar items'),
22294
            primary: false,
22295
            buttonType: Optional.none(),
22296
            borderless: false
22297
          }, Optional.none(), toolbarSpec.providers)
22298
        },
22299
        splitToolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
22300
      };
22301
    };
22302
    const renderFloatingMoreToolbar = toolbarSpec => {
22303
      const baseSpec = renderMoreToolbarCommon(toolbarSpec);
22304
      const overflowXOffset = 4;
22305
      const primary = SplitFloatingToolbar.parts.primary({
22306
        dom: {
22307
          tag: 'div',
22308
          classes: ['tox-toolbar__primary']
22309
        }
22310
      });
22311
      return SplitFloatingToolbar.sketch({
22312
        ...baseSpec,
22313
        lazySink: toolbarSpec.getSink,
22314
        getOverflowBounds: () => {
22315
          const headerElem = toolbarSpec.moreDrawerData.lazyHeader().element;
22316
          const headerBounds = absolute$2(headerElem);
22317
          const docElem = documentElement(headerElem);
22318
          const docBounds = absolute$2(docElem);
22319
          const height = Math.max(docElem.dom.scrollHeight, docBounds.height);
22320
          return bounds(headerBounds.x + overflowXOffset, docBounds.y, headerBounds.width - overflowXOffset * 2, height);
22321
        },
22322
        parts: {
22323
          ...baseSpec.parts,
22324
          overflow: {
22325
            dom: {
22326
              tag: 'div',
22327
              classes: ['tox-toolbar__overflow'],
22328
              attributes: toolbarSpec.attributes
22329
            }
22330
          }
22331
        },
22332
        components: [primary],
22333
        markers: { overflowToggledClass: 'tox-tbtn--enabled' },
22334
        onOpened: comp => toolbarSpec.onToggled(comp, true),
22335
        onClosed: comp => toolbarSpec.onToggled(comp, false)
22336
      });
22337
    };
22338
    const renderSlidingMoreToolbar = toolbarSpec => {
22339
      const primary = SplitSlidingToolbar.parts.primary({
22340
        dom: {
22341
          tag: 'div',
22342
          classes: ['tox-toolbar__primary']
22343
        }
22344
      });
22345
      const overflow = SplitSlidingToolbar.parts.overflow({
22346
        dom: {
22347
          tag: 'div',
22348
          classes: ['tox-toolbar__overflow']
22349
        }
22350
      });
22351
      const baseSpec = renderMoreToolbarCommon(toolbarSpec);
22352
      return SplitSlidingToolbar.sketch({
22353
        ...baseSpec,
22354
        components: [
22355
          primary,
22356
          overflow
22357
        ],
22358
        markers: {
22359
          openClass: 'tox-toolbar__overflow--open',
22360
          closedClass: 'tox-toolbar__overflow--closed',
22361
          growingClass: 'tox-toolbar__overflow--growing',
22362
          shrinkingClass: 'tox-toolbar__overflow--shrinking',
22363
          overflowToggledClass: 'tox-tbtn--enabled'
22364
        },
22365
        onOpened: comp => {
22366
          comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'opened' });
22367
          toolbarSpec.onToggled(comp, true);
22368
        },
22369
        onClosed: comp => {
22370
          comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'closed' });
22371
          toolbarSpec.onToggled(comp, false);
22372
        }
22373
      });
22374
    };
22375
    const renderToolbar = toolbarSpec => {
22376
      const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
22377
      return Toolbar.sketch({
22378
        uid: toolbarSpec.uid,
22379
        dom: {
22380
          tag: 'div',
22381
          classes: ['tox-toolbar'].concat(toolbarSpec.type === ToolbarMode$1.scrolling ? ['tox-toolbar--scrolling'] : [])
22382
        },
22383
        components: [Toolbar.parts.groups({})],
22384
        toolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
22385
      });
22386
    };
22387
 
22388
    const baseButtonFields = [
22389
      optionalText,
22390
      optionalIcon,
22391
      optionString('tooltip'),
22392
      defaultedStringEnum('buttonType', 'secondary', [
22393
        'primary',
22394
        'secondary'
22395
      ]),
22396
      defaultedBoolean('borderless', false),
22397
      requiredFunction('onAction')
22398
    ];
22399
    const normalButtonFields = [
22400
      ...baseButtonFields,
22401
      text,
22402
      requiredStringEnum('type', ['button'])
22403
    ];
22404
    const toggleButtonFields = [
22405
      ...baseButtonFields,
22406
      defaultedBoolean('active', false),
22407
      requiredStringEnum('type', ['togglebutton'])
22408
    ];
22409
    const schemaWithoutGroupButton = {
22410
      button: normalButtonFields,
22411
      togglebutton: toggleButtonFields
22412
    };
22413
    const groupFields = [
22414
      requiredStringEnum('type', ['group']),
22415
      defaultedArrayOf('buttons', [], choose$1('type', schemaWithoutGroupButton))
22416
    ];
22417
    const viewButtonSchema = choose$1('type', {
22418
      ...schemaWithoutGroupButton,
22419
      group: groupFields
22420
    });
22421
 
22422
    const viewSchema = objOf([
22423
      defaultedArrayOf('buttons', [], viewButtonSchema),
22424
      requiredFunction('onShow'),
22425
      requiredFunction('onHide')
22426
    ]);
22427
    const createView = spec => asRaw('view', viewSchema, spec);
22428
 
22429
    const renderButton = (spec, providers) => {
22430
      var _a, _b;
22431
      const isToggleButton = spec.type === 'togglebutton';
22432
      const optMemIcon = spec.icon.map(memIcon => renderReplaceableIconFromPack(memIcon, providers.icons)).map(record);
22433
      const getAction = () => comp => {
22434
        const setIcon = newIcon => {
22435
          optMemIcon.map(memIcon => memIcon.getOpt(comp).each(displayIcon => {
22436
            Replacing.set(displayIcon, [renderReplaceableIconFromPack(newIcon, providers.icons)]);
22437
          }));
22438
        };
22439
        const setActive = state => {
22440
          const elm = comp.element;
22441
          if (state) {
22442
            add$2(elm, 'tox-button--enabled');
22443
            set$9(elm, 'aria-pressed', true);
22444
          } else {
22445
            remove$2(elm, 'tox-button--enabled');
22446
            remove$7(elm, 'aria-pressed');
22447
          }
22448
        };
22449
        const isActive = () => has(comp.element, 'tox-button--enabled');
22450
        if (isToggleButton) {
22451
          return spec.onAction({
22452
            setIcon,
22453
            setActive,
22454
            isActive
22455
          });
22456
        }
22457
        if (spec.type === 'button') {
22458
          return spec.onAction({ setIcon });
22459
        }
22460
      };
22461
      const action = getAction();
22462
      const buttonSpec = {
22463
        ...spec,
22464
        name: isToggleButton ? spec.text.getOr(spec.icon.getOr('')) : (_a = spec.text) !== null && _a !== void 0 ? _a : spec.icon.getOr(''),
22465
        primary: spec.buttonType === 'primary',
22466
        buttonType: Optional.from(spec.buttonType),
22467
        tooltip: spec.tooltip,
22468
        icon: spec.icon,
22469
        enabled: true,
22470
        borderless: spec.borderless
22471
      };
22472
      const buttonTypeClasses = calculateClassesFromButtonType((_b = spec.buttonType) !== null && _b !== void 0 ? _b : 'secondary');
22473
      const optTranslatedText = isToggleButton ? spec.text.map(providers.translate) : Optional.some(providers.translate(spec.text));
22474
      const optTranslatedTextComponed = optTranslatedText.map(text$2);
22475
      const tooltipAttributes = buttonSpec.tooltip.or(optTranslatedText).map(tooltip => ({
22476
        'aria-label': providers.translate(tooltip),
22477
        'title': providers.translate(tooltip)
22478
      })).getOr({});
22479
      const optIconSpec = optMemIcon.map(memIcon => memIcon.asSpec());
22480
      const components = componentRenderPipeline([
22481
        optIconSpec,
22482
        optTranslatedTextComponed
22483
      ]);
22484
      const hasIconAndText = spec.icon.isSome() && optTranslatedTextComponed.isSome();
22485
      const dom = {
22486
        tag: 'button',
22487
        classes: buttonTypeClasses.concat(...spec.icon.isSome() && !hasIconAndText ? ['tox-button--icon'] : []).concat(...hasIconAndText ? ['tox-button--icon-and-text'] : []).concat(...spec.borderless ? ['tox-button--naked'] : []).concat(...spec.type === 'togglebutton' && spec.active ? ['tox-button--enabled'] : []),
22488
        attributes: tooltipAttributes
22489
      };
22490
      const extraBehaviours = [];
22491
      const iconButtonSpec = renderCommonSpec(buttonSpec, Optional.some(action), extraBehaviours, dom, components, providers);
22492
      return Button.sketch(iconButtonSpec);
22493
    };
22494
 
22495
    const renderViewButton = (spec, providers) => renderButton(spec, providers);
22496
    const renderButtonsGroup = (spec, providers) => {
22497
      return {
22498
        dom: {
22499
          tag: 'div',
22500
          classes: ['tox-view__toolbar__group']
22501
        },
22502
        components: map$2(spec.buttons, button => renderViewButton(button, providers))
22503
      };
22504
    };
22505
    const deviceDetection = detect$2().deviceType;
22506
    const isPhone = deviceDetection.isPhone();
22507
    const isTablet = deviceDetection.isTablet();
22508
    const renderViewHeader = spec => {
22509
      let hasGroups = false;
22510
      const endButtons = map$2(spec.buttons, btnspec => {
22511
        if (btnspec.type === 'group') {
22512
          hasGroups = true;
22513
          return renderButtonsGroup(btnspec, spec.providers);
22514
        } else {
22515
          return renderViewButton(btnspec, spec.providers);
22516
        }
22517
      });
22518
      return {
22519
        uid: spec.uid,
22520
        dom: {
22521
          tag: 'div',
22522
          classes: [
22523
            !hasGroups ? 'tox-view__header' : 'tox-view__toolbar',
22524
            ...isPhone || isTablet ? [
22525
              'tox-view--mobile',
22526
              'tox-view--scrolling'
22527
            ] : []
22528
          ]
22529
        },
22530
        behaviours: derive$1([
22531
          Focusing.config({}),
22532
          Keying.config({
22533
            mode: 'flow',
22534
            selector: 'button, .tox-button',
22535
            focusInside: FocusInsideModes.OnEnterOrSpaceMode
22536
          })
22537
        ]),
22538
        components: hasGroups ? endButtons : [
22539
          Container.sketch({
22540
            dom: {
22541
              tag: 'div',
22542
              classes: ['tox-view__header-start']
22543
            },
22544
            components: []
22545
          }),
22546
          Container.sketch({
22547
            dom: {
22548
              tag: 'div',
22549
              classes: ['tox-view__header-end']
22550
            },
22551
            components: endButtons
22552
          })
22553
        ]
22554
      };
22555
    };
22556
    const renderViewPane = spec => {
22557
      return {
22558
        uid: spec.uid,
22559
        dom: {
22560
          tag: 'div',
22561
          classes: ['tox-view__pane']
22562
        }
22563
      };
22564
    };
22565
    const factory$8 = (detail, components, _spec, _externals) => {
22566
      const apis = {
22567
        getPane: comp => parts$a.getPart(comp, detail, 'pane'),
22568
        getOnShow: _comp => detail.viewConfig.onShow,
22569
        getOnHide: _comp => detail.viewConfig.onHide
22570
      };
22571
      return {
22572
        uid: detail.uid,
22573
        dom: detail.dom,
22574
        components,
22575
        apis
22576
      };
22577
    };
22578
    var View = composite({
22579
      name: 'silver.View',
22580
      configFields: [required$1('viewConfig')],
22581
      partFields: [
22582
        optional({
22583
          factory: { sketch: renderViewHeader },
22584
          schema: [
22585
            required$1('buttons'),
22586
            required$1('providers')
22587
          ],
22588
          name: 'header'
22589
        }),
22590
        optional({
22591
          factory: { sketch: renderViewPane },
22592
          schema: [],
22593
          name: 'pane'
22594
        })
22595
      ],
22596
      factory: factory$8,
22597
      apis: {
22598
        getPane: (apis, comp) => apis.getPane(comp),
22599
        getOnShow: (apis, comp) => apis.getOnShow(comp),
22600
        getOnHide: (apis, comp) => apis.getOnHide(comp)
22601
      }
22602
    });
22603
 
22604
    const makeViews = (parts, viewConfigs, providers) => {
22605
      return mapToArray(viewConfigs, (config, name) => {
22606
        const internalViewConfig = getOrDie(createView(config));
22607
        return parts.slot(name, View.sketch({
22608
          dom: {
22609
            tag: 'div',
22610
            classes: ['tox-view']
22611
          },
22612
          viewConfig: internalViewConfig,
22613
          components: [
22614
            ...internalViewConfig.buttons.length > 0 ? [View.parts.header({
22615
                buttons: internalViewConfig.buttons,
22616
                providers
22617
              })] : [],
22618
            View.parts.pane({})
22619
          ]
22620
        }));
22621
      });
22622
    };
22623
    const makeSlotContainer = (viewConfigs, providers) => SlotContainer.sketch(parts => ({
22624
      dom: {
22625
        tag: 'div',
22626
        classes: ['tox-view-wrap__slot-container']
22627
      },
22628
      components: makeViews(parts, viewConfigs, providers),
22629
      slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
22630
    }));
22631
    const getCurrentName = slotContainer => {
22632
      return find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name));
22633
    };
22634
    const hideContainer = comp => {
22635
      const element = comp.element;
22636
      set$8(element, 'display', 'none');
22637
      set$9(element, 'aria-hidden', 'true');
22638
    };
22639
    const showContainer = comp => {
22640
      const element = comp.element;
22641
      remove$6(element, 'display');
22642
      remove$7(element, 'aria-hidden');
22643
    };
22644
    const makeViewInstanceApi = slot => ({ getContainer: constant$1(slot) });
22645
    const runOnPaneWithInstanceApi = (slotContainer, name, get) => {
22646
      SlotContainer.getSlot(slotContainer, name).each(view => {
22647
        View.getPane(view).each(pane => {
22648
          const onCallback = get(view);
22649
          onCallback(makeViewInstanceApi(pane.element.dom));
22650
        });
22651
      });
22652
    };
22653
    const runOnShow = (slotContainer, name) => runOnPaneWithInstanceApi(slotContainer, name, View.getOnShow);
22654
    const runOnHide = (slotContainer, name) => runOnPaneWithInstanceApi(slotContainer, name, View.getOnHide);
22655
    const factory$7 = (detail, spec) => {
22656
      const setViews = (comp, viewConfigs) => {
22657
        Replacing.set(comp, [makeSlotContainer(viewConfigs, spec.backstage.shared.providers)]);
22658
      };
22659
      const whichView = comp => {
22660
        return Composing.getCurrent(comp).bind(getCurrentName);
22661
      };
22662
      const toggleView = (comp, showMainView, hideMainView, name) => {
22663
        return Composing.getCurrent(comp).exists(slotContainer => {
22664
          const optCurrentSlotName = getCurrentName(slotContainer);
22665
          const isTogglingCurrentView = optCurrentSlotName.exists(current => name === current);
22666
          const exists = SlotContainer.getSlot(slotContainer, name).isSome();
22667
          if (exists) {
22668
            SlotContainer.hideAllSlots(slotContainer);
22669
            if (!isTogglingCurrentView) {
22670
              hideMainView();
22671
              showContainer(comp);
22672
              SlotContainer.showSlot(slotContainer, name);
22673
              runOnShow(slotContainer, name);
22674
            } else {
22675
              hideContainer(comp);
22676
              showMainView();
22677
            }
22678
            optCurrentSlotName.each(prevName => runOnHide(slotContainer, prevName));
22679
          }
22680
          return exists;
22681
        });
22682
      };
22683
      const apis = {
22684
        setViews,
22685
        whichView,
22686
        toggleView
22687
      };
22688
      return {
22689
        uid: detail.uid,
22690
        dom: {
22691
          tag: 'div',
22692
          classes: ['tox-view-wrap'],
22693
          attributes: { 'aria-hidden': 'true' },
22694
          styles: { display: 'none' }
22695
        },
22696
        components: [],
22697
        behaviours: derive$1([
22698
          Replacing.config({}),
22699
          Composing.config({
22700
            find: comp => {
22701
              const children = Replacing.contents(comp);
22702
              return head(children);
22703
            }
22704
          })
22705
        ]),
22706
        apis
22707
      };
22708
    };
22709
    var ViewWrapper = single({
22710
      factory: factory$7,
22711
      name: 'silver.ViewWrapper',
22712
      configFields: [required$1('backstage')],
22713
      apis: {
22714
        setViews: (apis, comp, views) => apis.setViews(comp, views),
22715
        toggleView: (apis, comp, outerContainer, editorCont, name) => apis.toggleView(comp, outerContainer, editorCont, name),
22716
        whichView: (apis, comp) => apis.whichView(comp)
22717
      }
22718
    });
22719
 
22720
    const factory$6 = (detail, components, _spec) => {
22721
      let toolbarDrawerOpenState = false;
22722
      const apis = {
22723
        getSocket: comp => {
22724
          return parts$a.getPart(comp, detail, 'socket');
22725
        },
22726
        setSidebar: (comp, panelConfigs, showSidebar) => {
22727
          parts$a.getPart(comp, detail, 'sidebar').each(sidebar => setSidebar(sidebar, panelConfigs, showSidebar));
22728
        },
22729
        toggleSidebar: (comp, name) => {
22730
          parts$a.getPart(comp, detail, 'sidebar').each(sidebar => toggleSidebar(sidebar, name));
22731
        },
22732
        whichSidebar: comp => {
22733
          return parts$a.getPart(comp, detail, 'sidebar').bind(whichSidebar).getOrNull();
22734
        },
22735
        getHeader: comp => {
22736
          return parts$a.getPart(comp, detail, 'header');
22737
        },
22738
        getToolbar: comp => {
22739
          return parts$a.getPart(comp, detail, 'toolbar');
22740
        },
22741
        setToolbar: (comp, groups) => {
22742
          parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
22743
            const renderedGroups = map$2(groups, renderToolbarGroup);
22744
            toolbar.getApis().setGroups(toolbar, renderedGroups);
22745
          });
22746
        },
22747
        setToolbars: (comp, toolbars) => {
22748
          parts$a.getPart(comp, detail, 'multiple-toolbar').each(mToolbar => {
22749
            const renderedToolbars = map$2(toolbars, g => map$2(g, renderToolbarGroup));
22750
            CustomList.setItems(mToolbar, renderedToolbars);
22751
          });
22752
        },
22753
        refreshToolbar: comp => {
22754
          const toolbar = parts$a.getPart(comp, detail, 'toolbar');
22755
          toolbar.each(toolbar => toolbar.getApis().refresh(toolbar));
22756
        },
22757
        toggleToolbarDrawer: comp => {
22758
          parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
22759
            mapFrom(toolbar.getApis().toggle, toggle => toggle(toolbar));
22760
          });
22761
        },
22762
        toggleToolbarDrawerWithoutFocusing: comp => {
22763
          parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
22764
            mapFrom(toolbar.getApis().toggleWithoutFocusing, toggleWithoutFocusing => toggleWithoutFocusing(toolbar));
22765
          });
22766
        },
22767
        isToolbarDrawerToggled: comp => {
22768
          return parts$a.getPart(comp, detail, 'toolbar').bind(toolbar => Optional.from(toolbar.getApis().isOpen).map(isOpen => isOpen(toolbar))).getOr(false);
22769
        },
22770
        getThrobber: comp => {
22771
          return parts$a.getPart(comp, detail, 'throbber');
22772
        },
22773
        focusToolbar: comp => {
22774
          const optToolbar = parts$a.getPart(comp, detail, 'toolbar').orThunk(() => parts$a.getPart(comp, detail, 'multiple-toolbar'));
22775
          optToolbar.each(toolbar => {
22776
            Keying.focusIn(toolbar);
22777
          });
22778
        },
22779
        setMenubar: (comp, menus) => {
22780
          parts$a.getPart(comp, detail, 'menubar').each(menubar => {
22781
            SilverMenubar.setMenus(menubar, menus);
22782
          });
22783
        },
22784
        focusMenubar: comp => {
22785
          parts$a.getPart(comp, detail, 'menubar').each(menubar => {
22786
            SilverMenubar.focus(menubar);
22787
          });
22788
        },
22789
        setViews: (comp, viewConfigs) => {
22790
          parts$a.getPart(comp, detail, 'viewWrapper').each(wrapper => {
22791
            ViewWrapper.setViews(wrapper, viewConfigs);
22792
          });
22793
        },
22794
        toggleView: (comp, name) => {
22795
          return parts$a.getPart(comp, detail, 'viewWrapper').exists(wrapper => ViewWrapper.toggleView(wrapper, () => apis.showMainView(comp), () => apis.hideMainView(comp), name));
22796
        },
22797
        whichView: comp => {
22798
          return parts$a.getPart(comp, detail, 'viewWrapper').bind(ViewWrapper.whichView).getOrNull();
22799
        },
22800
        hideMainView: comp => {
22801
          toolbarDrawerOpenState = apis.isToolbarDrawerToggled(comp);
22802
          if (toolbarDrawerOpenState) {
22803
            apis.toggleToolbarDrawer(comp);
22804
          }
22805
          parts$a.getPart(comp, detail, 'editorContainer').each(editorContainer => {
22806
            const element = editorContainer.element;
22807
            set$8(element, 'display', 'none');
22808
            set$9(element, 'aria-hidden', 'true');
22809
          });
22810
        },
22811
        showMainView: comp => {
22812
          if (toolbarDrawerOpenState) {
22813
            apis.toggleToolbarDrawer(comp);
22814
          }
22815
          parts$a.getPart(comp, detail, 'editorContainer').each(editorContainer => {
22816
            const element = editorContainer.element;
22817
            remove$6(element, 'display');
22818
            remove$7(element, 'aria-hidden');
22819
          });
22820
        }
22821
      };
22822
      return {
22823
        uid: detail.uid,
22824
        dom: detail.dom,
22825
        components,
22826
        apis,
22827
        behaviours: detail.behaviours
22828
      };
22829
    };
22830
    const partMenubar = partType.optional({
22831
      factory: SilverMenubar,
22832
      name: 'menubar',
22833
      schema: [required$1('backstage')]
22834
    });
22835
    const toolbarFactory = spec => {
22836
      if (spec.type === ToolbarMode$1.sliding) {
22837
        return renderSlidingMoreToolbar;
22838
      } else if (spec.type === ToolbarMode$1.floating) {
22839
        return renderFloatingMoreToolbar;
22840
      } else {
22841
        return renderToolbar;
22842
      }
22843
    };
22844
    const partMultipleToolbar = partType.optional({
22845
      factory: {
22846
        sketch: spec => CustomList.sketch({
22847
          uid: spec.uid,
22848
          dom: spec.dom,
22849
          listBehaviours: derive$1([Keying.config({
22850
              mode: 'acyclic',
22851
              selector: '.tox-toolbar'
22852
            })]),
22853
          makeItem: () => renderToolbar({
22854
            type: spec.type,
22855
            uid: generate$6('multiple-toolbar-item'),
22856
            cyclicKeying: false,
22857
            initGroups: [],
22858
            providers: spec.providers,
22859
            onEscape: () => {
22860
              spec.onEscape();
22861
              return Optional.some(true);
22862
            }
22863
          }),
22864
          setupItem: (_mToolbar, tc, data, _index) => {
22865
            Toolbar.setGroups(tc, data);
22866
          },
22867
          shell: true
22868
        })
22869
      },
22870
      name: 'multiple-toolbar',
22871
      schema: [
22872
        required$1('dom'),
22873
        required$1('onEscape')
22874
      ]
22875
    });
22876
    const partToolbar = partType.optional({
22877
      factory: {
22878
        sketch: spec => {
22879
          const renderer = toolbarFactory(spec);
22880
          const toolbarSpec = {
22881
            type: spec.type,
22882
            uid: spec.uid,
22883
            onEscape: () => {
22884
              spec.onEscape();
22885
              return Optional.some(true);
22886
            },
22887
            onToggled: (_comp, state) => spec.onToolbarToggled(state),
22888
            cyclicKeying: false,
22889
            initGroups: [],
22890
            getSink: spec.getSink,
22891
            providers: spec.providers,
22892
            moreDrawerData: {
22893
              lazyToolbar: spec.lazyToolbar,
22894
              lazyMoreButton: spec.lazyMoreButton,
22895
              lazyHeader: spec.lazyHeader
22896
            },
22897
            attributes: spec.attributes
22898
          };
22899
          return renderer(toolbarSpec);
22900
        }
22901
      },
22902
      name: 'toolbar',
22903
      schema: [
22904
        required$1('dom'),
22905
        required$1('onEscape'),
22906
        required$1('getSink')
22907
      ]
22908
    });
22909
    const partHeader = partType.optional({
22910
      factory: { sketch: renderHeader },
22911
      name: 'header',
22912
      schema: [required$1('dom')]
22913
    });
22914
    const partPromotion = partType.optional({
22915
      factory: { sketch: renderPromotion },
22916
      name: 'promotion',
22917
      schema: [required$1('dom')]
22918
    });
22919
    const partSocket = partType.optional({
22920
      name: 'socket',
22921
      schema: [required$1('dom')]
22922
    });
22923
    const partSidebar = partType.optional({
22924
      factory: { sketch: renderSidebar },
22925
      name: 'sidebar',
22926
      schema: [required$1('dom')]
22927
    });
22928
    const partThrobber = partType.optional({
22929
      factory: { sketch: renderThrobber },
22930
      name: 'throbber',
22931
      schema: [required$1('dom')]
22932
    });
22933
    const partViewWrapper = partType.optional({
22934
      factory: ViewWrapper,
22935
      name: 'viewWrapper',
22936
      schema: [required$1('backstage')]
22937
    });
22938
    const renderEditorContainer = spec => ({
22939
      uid: spec.uid,
22940
      dom: {
22941
        tag: 'div',
22942
        classes: ['tox-editor-container']
22943
      },
22944
      components: spec.components
22945
    });
22946
    const partEditorContainer = partType.optional({
22947
      factory: { sketch: renderEditorContainer },
22948
      name: 'editorContainer',
22949
      schema: []
22950
    });
22951
    var OuterContainer = composite({
22952
      name: 'OuterContainer',
22953
      factory: factory$6,
22954
      configFields: [
22955
        required$1('dom'),
22956
        required$1('behaviours')
22957
      ],
22958
      partFields: [
22959
        partHeader,
22960
        partMenubar,
22961
        partToolbar,
22962
        partMultipleToolbar,
22963
        partSocket,
22964
        partSidebar,
22965
        partPromotion,
22966
        partThrobber,
22967
        partViewWrapper,
22968
        partEditorContainer
22969
      ],
22970
      apis: {
22971
        getSocket: (apis, comp) => {
22972
          return apis.getSocket(comp);
22973
        },
22974
        setSidebar: (apis, comp, panelConfigs, showSidebar) => {
22975
          apis.setSidebar(comp, panelConfigs, showSidebar);
22976
        },
22977
        toggleSidebar: (apis, comp, name) => {
22978
          apis.toggleSidebar(comp, name);
22979
        },
22980
        whichSidebar: (apis, comp) => {
22981
          return apis.whichSidebar(comp);
22982
        },
22983
        getHeader: (apis, comp) => {
22984
          return apis.getHeader(comp);
22985
        },
22986
        getToolbar: (apis, comp) => {
22987
          return apis.getToolbar(comp);
22988
        },
22989
        setToolbar: (apis, comp, groups) => {
22990
          apis.setToolbar(comp, groups);
22991
        },
22992
        setToolbars: (apis, comp, toolbars) => {
22993
          apis.setToolbars(comp, toolbars);
22994
        },
22995
        refreshToolbar: (apis, comp) => {
22996
          return apis.refreshToolbar(comp);
22997
        },
22998
        toggleToolbarDrawer: (apis, comp) => {
22999
          apis.toggleToolbarDrawer(comp);
23000
        },
23001
        toggleToolbarDrawerWithoutFocusing: (apis, comp) => {
23002
          apis.toggleToolbarDrawerWithoutFocusing(comp);
23003
        },
23004
        isToolbarDrawerToggled: (apis, comp) => {
23005
          return apis.isToolbarDrawerToggled(comp);
23006
        },
23007
        getThrobber: (apis, comp) => {
23008
          return apis.getThrobber(comp);
23009
        },
23010
        setMenubar: (apis, comp, menus) => {
23011
          apis.setMenubar(comp, menus);
23012
        },
23013
        focusMenubar: (apis, comp) => {
23014
          apis.focusMenubar(comp);
23015
        },
23016
        focusToolbar: (apis, comp) => {
23017
          apis.focusToolbar(comp);
23018
        },
23019
        setViews: (apis, comp, views) => {
23020
          apis.setViews(comp, views);
23021
        },
23022
        toggleView: (apis, comp, name) => {
23023
          return apis.toggleView(comp, name);
23024
        },
23025
        whichView: (apis, comp) => {
23026
          return apis.whichView(comp);
23027
        }
23028
      }
23029
    });
23030
 
23031
    const defaultMenubar = 'file edit view insert format tools table help';
23032
    const defaultMenus = {
23033
      file: {
23034
        title: 'File',
23035
        items: 'newdocument restoredraft | preview | export print | deleteallconversations'
23036
      },
23037
      edit: {
23038
        title: 'Edit',
23039
        items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'
23040
      },
23041
      view: {
23042
        title: 'View',
23043
        items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'
23044
      },
23045
      insert: {
23046
        title: 'Insert',
23047
        items: 'image link media addcomment pageembed template inserttemplate codesample inserttable accordion | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents footnotes | mergetags | insertdatetime'
23048
      },
23049
      format: {
23050
        title: 'Format',
23051
        items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'
23052
      },
23053
      tools: {
23054
        title: 'Tools',
23055
        items: 'aidialog aishortcuts | spellchecker spellcheckerlanguage | autocorrect capitalization | a11ycheck code typography wordcount addtemplate'
23056
      },
23057
      table: {
23058
        title: 'Table',
23059
        items: 'inserttable | cell row column | advtablesort | tableprops deletetable'
23060
      },
23061
      help: {
23062
        title: 'Help',
23063
        items: 'help'
23064
      }
23065
    };
23066
    const make = (menu, registry, editor) => {
23067
      const removedMenuItems = getRemovedMenuItems(editor).split(/[ ,]/);
23068
      return {
23069
        text: menu.title,
23070
        getItems: () => bind$3(menu.items, i => {
23071
          const itemName = i.toLowerCase();
23072
          if (itemName.trim().length === 0) {
23073
            return [];
23074
          } else if (exists(removedMenuItems, removedMenuItem => removedMenuItem === itemName)) {
23075
            return [];
23076
          } else if (itemName === 'separator' || itemName === '|') {
23077
            return [{ type: 'separator' }];
23078
          } else if (registry.menuItems[itemName]) {
23079
            return [registry.menuItems[itemName]];
23080
          } else {
23081
            return [];
23082
          }
23083
        })
23084
      };
23085
    };
23086
    const parseItemsString = items => {
23087
      return items.split(' ');
23088
    };
23089
    const identifyMenus = (editor, registry) => {
23090
      const rawMenuData = {
23091
        ...defaultMenus,
23092
        ...registry.menus
23093
      };
23094
      const userDefinedMenus = keys(registry.menus).length > 0;
23095
      const menubar = registry.menubar === undefined || registry.menubar === true ? parseItemsString(defaultMenubar) : parseItemsString(registry.menubar === false ? '' : registry.menubar);
23096
      const validMenus = filter$2(menubar, menuName => {
23097
        const isDefaultMenu = has$2(defaultMenus, menuName);
23098
        if (userDefinedMenus) {
23099
          return isDefaultMenu || get$g(registry.menus, menuName).exists(menu => has$2(menu, 'items'));
23100
        } else {
23101
          return isDefaultMenu;
23102
        }
23103
      });
23104
      const menus = map$2(validMenus, menuName => {
23105
        const menuData = rawMenuData[menuName];
23106
        return make({
23107
          title: menuData.title,
23108
          items: parseItemsString(menuData.items)
23109
        }, registry, editor);
23110
      });
23111
      return filter$2(menus, menu => {
23112
        const isNotSeparator = item => isString(item) || item.type !== 'separator';
23113
        return menu.getItems().length > 0 && exists(menu.getItems(), isNotSeparator);
23114
      });
23115
    };
23116
 
23117
    const fireSkinLoaded = editor => {
23118
      const done = () => {
23119
        editor._skinLoaded = true;
23120
        fireSkinLoaded$1(editor);
23121
      };
23122
      return () => {
23123
        if (editor.initialized) {
23124
          done();
23125
        } else {
23126
          editor.on('init', done);
23127
        }
23128
      };
23129
    };
23130
    const fireSkinLoadError = (editor, err) => () => fireSkinLoadError$1(editor, { message: err });
23131
 
23132
    const loadStylesheet = (editor, stylesheetUrl, styleSheetLoader) => {
23133
      editor.on('remove', () => styleSheetLoader.unload(stylesheetUrl));
23134
      return styleSheetLoader.load(stylesheetUrl);
23135
    };
23136
    const loadRawCss = (editor, key, css, styleSheetLoader) => {
23137
      editor.on('remove', () => styleSheetLoader.unloadRawCss(key));
23138
      return styleSheetLoader.loadRawCss(key, css);
23139
    };
23140
    const loadUiSkins = async (editor, skinUrl) => {
23141
      const skinResourceIdentifier = getSkinUrlOption(editor).getOr('default');
23142
      const skinUiCss = 'ui/' + skinResourceIdentifier + '/skin.css';
23143
      const css = tinymce.Resource.get(skinUiCss);
23144
      if (isString(css)) {
23145
        return Promise.resolve(loadRawCss(editor, skinUiCss, css, editor.ui.styleSheetLoader));
23146
      } else {
23147
        const skinUiCss = skinUrl + '/skin.min.css';
23148
        return loadStylesheet(editor, skinUiCss, editor.ui.styleSheetLoader);
23149
      }
23150
    };
23151
    const loadShadowDomUiSkins = async (editor, skinUrl) => {
23152
      const isInShadowRoot$1 = isInShadowRoot(SugarElement.fromDom(editor.getElement()));
23153
      if (isInShadowRoot$1) {
23154
        const skinResourceIdentifier = getSkinUrlOption(editor).getOr('default');
23155
        const shadowDomSkinCss = 'ui/' + skinResourceIdentifier + '/skin.shadowdom.css';
23156
        const css = tinymce.Resource.get(shadowDomSkinCss);
23157
        if (isString(css)) {
23158
          loadRawCss(editor, shadowDomSkinCss, css, global$7.DOM.styleSheetLoader);
23159
          return Promise.resolve();
23160
        } else {
23161
          const shadowDomSkinCss = skinUrl + '/skin.shadowdom.min.css';
23162
          return loadStylesheet(editor, shadowDomSkinCss, global$7.DOM.styleSheetLoader);
23163
        }
23164
      }
23165
    };
23166
    const loadUrlSkin = async (isInline, editor) => {
23167
      getSkinUrlOption(editor).fold(() => {
23168
        const skinResourceIdentifier = getSkinUrl(editor);
23169
        if (skinResourceIdentifier) {
23170
          editor.contentCSS.push(skinResourceIdentifier + (isInline ? '/content.inline' : '/content') + '.min.css');
23171
        }
23172
      }, skinUrl => {
23173
        const skinContentCss = 'ui/' + skinUrl + (isInline ? '/content.inline' : '/content') + '.css';
23174
        const css = tinymce.Resource.get(skinContentCss);
23175
        if (isString(css)) {
23176
          loadRawCss(editor, skinContentCss, css, editor.ui.styleSheetLoader);
23177
        } else {
23178
          const skinResourceIdentifier = getSkinUrl(editor);
23179
          if (skinResourceIdentifier) {
23180
            editor.contentCSS.push(skinResourceIdentifier + (isInline ? '/content.inline' : '/content') + '.min.css');
23181
          }
23182
        }
23183
      });
23184
      const skinUrl = getSkinUrl(editor);
23185
      if (!isSkinDisabled(editor) && isString(skinUrl)) {
23186
        return Promise.all([
23187
          loadUiSkins(editor, skinUrl),
23188
          loadShadowDomUiSkins(editor, skinUrl)
23189
        ]).then();
23190
      }
23191
    };
23192
    const loadSkin = (isInline, editor) => {
23193
      return loadUrlSkin(isInline, editor).then(fireSkinLoaded(editor), fireSkinLoadError(editor, 'Skin could not be loaded'));
23194
    };
23195
    const iframe = curry(loadSkin, false);
23196
    const inline = curry(loadSkin, true);
23197
 
23198
    const makeTooltipText = (editor, labelWithPlaceholder, value) => editor.translate([
23199
      labelWithPlaceholder,
23200
      editor.translate(value)
23201
    ]);
23202
 
23203
    const generateSelectItems = (backstage, spec) => {
23204
      const generateItem = (rawItem, response, invalid, value) => {
23205
        const translatedText = backstage.shared.providers.translate(rawItem.title);
23206
        if (rawItem.type === 'separator') {
23207
          return Optional.some({
23208
            type: 'separator',
23209
            text: translatedText
23210
          });
23211
        } else if (rawItem.type === 'submenu') {
23212
          const items = bind$3(rawItem.getStyleItems(), si => validate(si, response, value));
23213
          if (response === 0 && items.length <= 0) {
23214
            return Optional.none();
23215
          } else {
23216
            return Optional.some({
23217
              type: 'nestedmenuitem',
23218
              text: translatedText,
23219
              enabled: items.length > 0,
23220
              getSubmenuItems: () => bind$3(rawItem.getStyleItems(), si => validate(si, response, value))
23221
            });
23222
          }
23223
        } else {
23224
          return Optional.some({
23225
            type: 'togglemenuitem',
23226
            text: translatedText,
23227
            icon: rawItem.icon,
23228
            active: rawItem.isSelected(value),
23229
            enabled: !invalid,
23230
            onAction: spec.onAction(rawItem),
23231
            ...rawItem.getStylePreview().fold(() => ({}), preview => ({ meta: { style: preview } }))
23232
          });
23233
        }
23234
      };
23235
      const validate = (item, response, value) => {
23236
        const invalid = item.type === 'formatter' && spec.isInvalid(item);
23237
        if (response === 0) {
23238
          return invalid ? [] : generateItem(item, response, false, value).toArray();
23239
        } else {
23240
          return generateItem(item, response, invalid, value).toArray();
23241
        }
23242
      };
23243
      const validateItems = preItems => {
23244
        const value = spec.getCurrentValue();
23245
        const response = spec.shouldHide ? 0 : 1;
23246
        return bind$3(preItems, item => validate(item, response, value));
23247
      };
23248
      const getFetch = (backstage, getStyleItems) => (comp, callback) => {
23249
        const preItems = getStyleItems();
23250
        const items = validateItems(preItems);
23251
        const menu = build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
23252
          isHorizontalMenu: false,
23253
          search: Optional.none()
23254
        });
23255
        callback(menu);
23256
      };
23257
      return {
23258
        validateItems,
23259
        getFetch
23260
      };
23261
    };
23262
    const createMenuItems = (editor, backstage, spec) => {
23263
      const dataset = spec.dataset;
23264
      const getStyleItems = dataset.type === 'basic' ? () => map$2(dataset.data, d => processBasic(d, spec.isSelectedFor, spec.getPreviewFor)) : dataset.getData;
23265
      return {
23266
        items: generateSelectItems(backstage, spec),
23267
        getStyleItems
23268
      };
23269
    };
23270
    const createSelectButton = (editor, backstage, spec, tooltipWithPlaceholder, textUpdateEventName) => {
23271
      const {items, getStyleItems} = createMenuItems(editor, backstage, spec);
23272
      const getApi = comp => ({
23273
        getComponent: constant$1(comp),
23274
        setTooltip: tooltip => {
23275
          const translatedTooltip = backstage.shared.providers.translate(tooltip);
23276
          setAll$1(comp.element, {
23277
            'aria-label': translatedTooltip,
23278
            'title': translatedTooltip
23279
          });
23280
        }
23281
      });
23282
      const onSetup = api => {
23283
        const handler = e => api.setTooltip(makeTooltipText(editor, tooltipWithPlaceholder, e.value));
23284
        editor.on(textUpdateEventName, handler);
23285
        return composeUnbinders(onSetupEvent(editor, 'NodeChange', api => {
23286
          const comp = api.getComponent();
23287
          spec.updateText(comp);
23288
          Disabling.set(api.getComponent(), !editor.selection.isEditable());
23289
        })(api), () => editor.off(textUpdateEventName, handler));
23290
      };
23291
      return renderCommonDropdown({
23292
        text: spec.icon.isSome() ? Optional.none() : spec.text,
23293
        icon: spec.icon,
23294
        tooltip: Optional.from(spec.tooltip),
23295
        role: Optional.none(),
23296
        fetch: items.getFetch(backstage, getStyleItems),
23297
        onSetup,
23298
        getApi,
23299
        columns: 1,
23300
        presets: 'normal',
23301
        classes: spec.icon.isSome() ? [] : ['bespoke'],
23302
        dropdownBehaviours: []
23303
      }, 'tox-tbtn', backstage.shared);
23304
    };
23305
 
23306
    const process = rawFormats => map$2(rawFormats, item => {
23307
      let title = item, format = item;
23308
      const values = item.split('=');
23309
      if (values.length > 1) {
23310
        title = values[0];
23311
        format = values[1];
23312
      }
23313
      return {
23314
        title,
23315
        format
23316
      };
23317
    });
23318
    const buildBasicStaticDataset = data => ({
23319
      type: 'basic',
23320
      data
23321
    });
23322
    var Delimiter;
23323
    (function (Delimiter) {
23324
      Delimiter[Delimiter['SemiColon'] = 0] = 'SemiColon';
23325
      Delimiter[Delimiter['Space'] = 1] = 'Space';
23326
    }(Delimiter || (Delimiter = {})));
23327
    const split = (rawFormats, delimiter) => {
23328
      if (delimiter === Delimiter.SemiColon) {
23329
        return rawFormats.replace(/;$/, '').split(';');
23330
      } else {
23331
        return rawFormats.split(' ');
23332
      }
23333
    };
23334
    const buildBasicSettingsDataset = (editor, settingName, delimiter) => {
23335
      const rawFormats = editor.options.get(settingName);
23336
      const data = process(split(rawFormats, delimiter));
23337
      return {
23338
        type: 'basic',
23339
        data
23340
      };
23341
    };
23342
 
23343
    const menuTitle$4 = 'Align';
23344
    const btnTooltip$4 = 'Alignment {0}';
23345
    const fallbackAlignment = 'left';
23346
    const alignMenuItems = [
23347
      {
23348
        title: 'Left',
23349
        icon: 'align-left',
23350
        format: 'alignleft',
23351
        command: 'JustifyLeft'
23352
      },
23353
      {
23354
        title: 'Center',
23355
        icon: 'align-center',
23356
        format: 'aligncenter',
23357
        command: 'JustifyCenter'
23358
      },
23359
      {
23360
        title: 'Right',
23361
        icon: 'align-right',
23362
        format: 'alignright',
23363
        command: 'JustifyRight'
23364
      },
23365
      {
23366
        title: 'Justify',
23367
        icon: 'align-justify',
23368
        format: 'alignjustify',
23369
        command: 'JustifyFull'
23370
      }
23371
    ];
23372
    const getSpec$4 = editor => {
23373
      const getMatchingValue = () => find$5(alignMenuItems, item => editor.formatter.match(item.format));
23374
      const isSelectedFor = format => () => editor.formatter.match(format);
23375
      const getPreviewFor = _format => Optional.none;
23376
      const updateSelectMenuIcon = comp => {
23377
        const match = getMatchingValue();
23378
        const alignment = match.fold(constant$1(fallbackAlignment), item => item.title.toLowerCase());
23379
        emitWith(comp, updateMenuIcon, { icon: `align-${ alignment }` });
23380
        fireAlignTextUpdate(editor, { value: alignment });
23381
      };
23382
      const dataset = buildBasicStaticDataset(alignMenuItems);
23383
      const onAction = rawItem => () => find$5(alignMenuItems, item => item.format === rawItem.format).each(item => editor.execCommand(item.command));
23384
      return {
23385
        tooltip: makeTooltipText(editor, btnTooltip$4, fallbackAlignment),
23386
        text: Optional.none(),
23387
        icon: Optional.some('align-left'),
23388
        isSelectedFor,
23389
        getCurrentValue: Optional.none,
23390
        getPreviewFor,
23391
        onAction,
23392
        updateText: updateSelectMenuIcon,
23393
        dataset,
23394
        shouldHide: false,
23395
        isInvalid: item => !editor.formatter.canApply(item.format)
23396
      };
23397
    };
23398
    const createAlignButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$4(editor), btnTooltip$4, 'AlignTextUpdate');
23399
    const createAlignMenu = (editor, backstage) => {
23400
      const menuItems = createMenuItems(editor, backstage, getSpec$4(editor));
23401
      editor.ui.registry.addNestedMenuItem('align', {
23402
        text: backstage.shared.providers.translate(menuTitle$4),
23403
        onSetup: onSetupEditableToggle(editor),
23404
        getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
23405
      });
23406
    };
23407
 
23408
    const findNearest = (editor, getStyles) => {
23409
      const styles = getStyles();
23410
      const formats = map$2(styles, style => style.format);
23411
      return Optional.from(editor.formatter.closest(formats)).bind(fmt => find$5(styles, data => data.format === fmt)).orThunk(() => someIf(editor.formatter.match('p'), {
23412
        title: 'Paragraph',
23413
        format: 'p'
23414
      }));
23415
    };
23416
 
23417
    const menuTitle$3 = 'Blocks';
23418
    const btnTooltip$3 = 'Block {0}';
23419
    const fallbackFormat = 'Paragraph';
23420
    const getSpec$3 = editor => {
23421
      const isSelectedFor = format => () => editor.formatter.match(format);
23422
      const getPreviewFor = format => () => {
23423
        const fmt = editor.formatter.get(format);
23424
        if (fmt) {
23425
          return Optional.some({
23426
            tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
23427
            styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
23428
          });
23429
        } else {
23430
          return Optional.none();
23431
        }
23432
      };
23433
      const updateSelectMenuText = comp => {
23434
        const detectedFormat = findNearest(editor, () => dataset.data);
23435
        const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
23436
        emitWith(comp, updateMenuText, { text });
23437
        fireBlocksTextUpdate(editor, { value: text });
23438
      };
23439
      const dataset = buildBasicSettingsDataset(editor, 'block_formats', Delimiter.SemiColon);
23440
      return {
23441
        tooltip: makeTooltipText(editor, btnTooltip$3, fallbackFormat),
23442
        text: Optional.some(fallbackFormat),
23443
        icon: Optional.none(),
23444
        isSelectedFor,
23445
        getCurrentValue: Optional.none,
23446
        getPreviewFor,
23447
        onAction: onActionToggleFormat$1(editor),
23448
        updateText: updateSelectMenuText,
23449
        dataset,
23450
        shouldHide: false,
23451
        isInvalid: item => !editor.formatter.canApply(item.format)
23452
      };
23453
    };
23454
    const createBlocksButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$3(editor), btnTooltip$3, 'BlocksTextUpdate');
23455
    const createBlocksMenu = (editor, backstage) => {
23456
      const menuItems = createMenuItems(editor, backstage, getSpec$3(editor));
23457
      editor.ui.registry.addNestedMenuItem('blocks', {
23458
        text: menuTitle$3,
23459
        onSetup: onSetupEditableToggle(editor),
23460
        getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
23461
      });
23462
    };
23463
 
23464
    const menuTitle$2 = 'Fonts';
23465
    const btnTooltip$2 = 'Font {0}';
23466
    const systemFont = 'System Font';
23467
    const systemStackFonts = [
23468
      '-apple-system',
23469
      'Segoe UI',
23470
      'Roboto',
23471
      'Helvetica Neue',
23472
      'sans-serif'
23473
    ];
23474
    const splitFonts = fontFamily => {
23475
      const fonts = fontFamily.split(/\s*,\s*/);
23476
      return map$2(fonts, font => font.replace(/^['"]+|['"]+$/g, ''));
23477
    };
23478
    const matchesStack = (fonts, stack) => stack.length > 0 && forall(stack, font => fonts.indexOf(font.toLowerCase()) > -1);
23479
    const isSystemFontStack = (fontFamily, userStack) => {
23480
      if (fontFamily.indexOf('-apple-system') === 0 || userStack.length > 0) {
23481
        const fonts = splitFonts(fontFamily.toLowerCase());
23482
        return matchesStack(fonts, systemStackFonts) || matchesStack(fonts, userStack);
23483
      } else {
23484
        return false;
23485
      }
23486
    };
23487
    const getSpec$2 = editor => {
23488
      const getMatchingValue = () => {
23489
        const getFirstFont = fontFamily => fontFamily ? splitFonts(fontFamily)[0] : '';
23490
        const fontFamily = editor.queryCommandValue('FontName');
23491
        const items = dataset.data;
23492
        const font = fontFamily ? fontFamily.toLowerCase() : '';
23493
        const userStack = getDefaultFontStack(editor);
23494
        const matchOpt = find$5(items, item => {
23495
          const format = item.format;
23496
          return format.toLowerCase() === font || getFirstFont(format).toLowerCase() === getFirstFont(font).toLowerCase();
23497
        }).orThunk(() => {
23498
          return someIf(isSystemFontStack(font, userStack), {
23499
            title: systemFont,
23500
            format: font
23501
          });
23502
        });
23503
        return {
23504
          matchOpt,
23505
          font: fontFamily
23506
        };
23507
      };
23508
      const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
23509
      const getCurrentValue = () => {
23510
        const {matchOpt} = getMatchingValue();
23511
        return matchOpt;
23512
      };
23513
      const getPreviewFor = item => () => Optional.some({
23514
        tag: 'div',
23515
        styles: item.indexOf('dings') === -1 ? { 'font-family': item } : {}
23516
      });
23517
      const onAction = rawItem => () => {
23518
        editor.undoManager.transact(() => {
23519
          editor.focus();
23520
          editor.execCommand('FontName', false, rawItem.format);
23521
        });
23522
      };
23523
      const updateSelectMenuText = comp => {
23524
        const {matchOpt, font} = getMatchingValue();
23525
        const text = matchOpt.fold(constant$1(font), item => item.title);
23526
        emitWith(comp, updateMenuText, { text });
23527
        fireFontFamilyTextUpdate(editor, { value: text });
23528
      };
23529
      const dataset = buildBasicSettingsDataset(editor, 'font_family_formats', Delimiter.SemiColon);
23530
      return {
23531
        tooltip: makeTooltipText(editor, btnTooltip$2, systemFont),
23532
        text: Optional.some(systemFont),
23533
        icon: Optional.none(),
23534
        isSelectedFor,
23535
        getCurrentValue,
23536
        getPreviewFor,
23537
        onAction,
23538
        updateText: updateSelectMenuText,
23539
        dataset,
23540
        shouldHide: false,
23541
        isInvalid: never
23542
      };
23543
    };
23544
    const createFontFamilyButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$2(editor), btnTooltip$2, 'FontFamilyTextUpdate');
23545
    const createFontFamilyMenu = (editor, backstage) => {
23546
      const menuItems = createMenuItems(editor, backstage, getSpec$2(editor));
23547
      editor.ui.registry.addNestedMenuItem('fontfamily', {
23548
        text: backstage.shared.providers.translate(menuTitle$2),
23549
        onSetup: onSetupEditableToggle(editor),
23550
        getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
23551
      });
23552
    };
23553
 
23554
    const units = {
23555
      unsupportedLength: [
23556
        'em',
23557
        'ex',
23558
        'cap',
23559
        'ch',
23560
        'ic',
23561
        'rem',
23562
        'lh',
23563
        'rlh',
23564
        'vw',
23565
        'vh',
23566
        'vi',
23567
        'vb',
23568
        'vmin',
23569
        'vmax',
23570
        'cm',
23571
        'mm',
23572
        'Q',
23573
        'in',
23574
        'pc',
23575
        'pt',
23576
        'px'
23577
      ],
23578
      fixed: [
23579
        'px',
23580
        'pt'
23581
      ],
23582
      relative: ['%'],
23583
      empty: ['']
23584
    };
23585
    const pattern = (() => {
23586
      const decimalDigits = '[0-9]+';
23587
      const signedInteger = '[+-]?' + decimalDigits;
23588
      const exponentPart = '[eE]' + signedInteger;
23589
      const dot = '\\.';
23590
      const opt = input => `(?:${ input })?`;
23591
      const unsignedDecimalLiteral = [
23592
        'Infinity',
23593
        decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
23594
        dot + decimalDigits + opt(exponentPart),
23595
        decimalDigits + opt(exponentPart)
23596
      ].join('|');
23597
      const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
23598
      return new RegExp(`^(${ float })(.*)$`);
23599
    })();
23600
    const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
23601
    const parse = (input, accepted) => {
23602
      const match = Optional.from(pattern.exec(input));
23603
      return match.bind(array => {
23604
        const value = Number(array[1]);
23605
        const unitRaw = array[2];
23606
        if (isUnit(unitRaw, accepted)) {
23607
          return Optional.some({
23608
            value,
23609
            unit: unitRaw
23610
          });
23611
        } else {
23612
          return Optional.none();
23613
        }
23614
      });
23615
    };
23616
    const normalise = (input, accepted) => parse(input, accepted).map(({value, unit}) => value + unit);
23617
 
23618
    const Keys = {
23619
      tab: constant$1(9),
23620
      escape: constant$1(27),
23621
      enter: constant$1(13),
23622
      backspace: constant$1(8),
23623
      delete: constant$1(46),
23624
      left: constant$1(37),
23625
      up: constant$1(38),
23626
      right: constant$1(39),
23627
      down: constant$1(40),
23628
      space: constant$1(32),
23629
      home: constant$1(36),
23630
      end: constant$1(35),
23631
      pageUp: constant$1(33),
23632
      pageDown: constant$1(34)
23633
    };
23634
 
23635
    const createBespokeNumberInput = (editor, backstage, spec) => {
23636
      let currentComp = Optional.none();
23637
      const getValueFromCurrentComp = comp => comp.map(alloyComp => Representing.getValue(alloyComp)).getOr('');
23638
      const onSetup = onSetupEvent(editor, 'NodeChange SwitchMode', api => {
23639
        const comp = api.getComponent();
23640
        currentComp = Optional.some(comp);
23641
        spec.updateInputValue(comp);
23642
        Disabling.set(comp, !editor.selection.isEditable());
23643
      });
23644
      const getApi = comp => ({ getComponent: constant$1(comp) });
23645
      const editorOffCell = Cell(noop);
23646
      const customEvents = generate$6('custom-number-input-events');
23647
      const changeValue = (f, fromInput, focusBack) => {
23648
        const text = getValueFromCurrentComp(currentComp);
23649
        const newValue = spec.getNewValue(text, f);
23650
        const lenghtDelta = text.length - `${ newValue }`.length;
23651
        const oldStart = currentComp.map(comp => comp.element.dom.selectionStart - lenghtDelta);
23652
        const oldEnd = currentComp.map(comp => comp.element.dom.selectionEnd - lenghtDelta);
23653
        spec.onAction(newValue, focusBack);
23654
        currentComp.each(comp => {
23655
          Representing.setValue(comp, newValue);
23656
          if (fromInput) {
23657
            oldStart.each(oldStart => comp.element.dom.selectionStart = oldStart);
23658
            oldEnd.each(oldEnd => comp.element.dom.selectionEnd = oldEnd);
23659
          }
23660
        });
23661
      };
23662
      const decrease = (fromInput, focusBack) => changeValue((n, s) => n - s, fromInput, focusBack);
23663
      const increase = (fromInput, focusBack) => changeValue((n, s) => n + s, fromInput, focusBack);
23664
      const goToParent = comp => parentElement(comp.element).fold(Optional.none, parent => {
23665
        focus$3(parent);
23666
        return Optional.some(true);
23667
      });
23668
      const focusInput = comp => {
23669
        if (hasFocus(comp.element)) {
23670
          firstChild(comp.element).each(input => focus$3(input));
23671
          return Optional.some(true);
23672
        } else {
23673
          return Optional.none();
23674
        }
23675
      };
23676
      const makeStepperButton = (action, title, tooltip, classes) => {
23677
        const editorOffCellStepButton = Cell(noop);
23678
        const translatedTooltip = backstage.shared.providers.translate(tooltip);
23679
        const altExecuting = generate$6('altExecuting');
23680
        const onSetup = onSetupEvent(editor, 'NodeChange SwitchMode', api => {
23681
          Disabling.set(api.getComponent(), !editor.selection.isEditable());
23682
        });
23683
        const onClick = comp => {
23684
          if (!Disabling.isDisabled(comp)) {
23685
            action(true);
23686
          }
23687
        };
23688
        return Button.sketch({
23689
          dom: {
23690
            tag: 'button',
23691
            attributes: {
23692
              'title': translatedTooltip,
23693
              'aria-label': translatedTooltip
23694
            },
23695
            classes: classes.concat(title)
23696
          },
23697
          components: [renderIconFromPack$1(title, backstage.shared.providers.icons)],
23698
          buttonBehaviours: derive$1([
23699
            Disabling.config({}),
23700
            config(altExecuting, [
23701
              onControlAttached({
23702
                onSetup,
23703
                getApi
23704
              }, editorOffCellStepButton),
23705
              onControlDetached({ getApi }, editorOffCellStepButton),
23706
              run$1(keydown(), (comp, se) => {
23707
                if (se.event.raw.keyCode === Keys.space() || se.event.raw.keyCode === Keys.enter()) {
23708
                  if (!Disabling.isDisabled(comp)) {
23709
                    action(false);
23710
                  }
23711
                }
23712
              }),
23713
              run$1(click(), onClick),
23714
              run$1(touchend(), onClick)
23715
            ])
23716
          ]),
23717
          eventOrder: {
23718
            [keydown()]: [
23719
              altExecuting,
23720
              'keying'
23721
            ],
23722
            [click()]: [
23723
              altExecuting,
23724
              'alloy.base.behaviour'
23725
            ],
23726
            [touchend()]: [
23727
              altExecuting,
23728
              'alloy.base.behaviour'
23729
            ]
23730
          }
23731
        });
23732
      };
23733
      const memMinus = record(makeStepperButton(focusBack => decrease(false, focusBack), 'minus', 'Decrease font size', []));
23734
      const memPlus = record(makeStepperButton(focusBack => increase(false, focusBack), 'plus', 'Increase font size', []));
23735
      const memInput = record({
23736
        dom: {
23737
          tag: 'div',
23738
          classes: ['tox-input-wrapper']
23739
        },
23740
        components: [Input.sketch({
23741
            inputBehaviours: derive$1([
23742
              Disabling.config({}),
23743
              config(customEvents, [
23744
                onControlAttached({
23745
                  onSetup,
23746
                  getApi
23747
                }, editorOffCell),
23748
                onControlDetached({ getApi }, editorOffCell)
23749
              ]),
23750
              config('input-update-display-text', [
23751
                run$1(updateMenuText, (comp, se) => {
23752
                  Representing.setValue(comp, se.event.text);
23753
                }),
23754
                run$1(focusout(), comp => {
23755
                  spec.onAction(Representing.getValue(comp));
23756
                }),
23757
                run$1(change(), comp => {
23758
                  spec.onAction(Representing.getValue(comp));
23759
                })
23760
              ]),
23761
              Keying.config({
23762
                mode: 'special',
23763
                onEnter: _comp => {
23764
                  changeValue(identity, true, true);
23765
                  return Optional.some(true);
23766
                },
23767
                onEscape: goToParent,
23768
                onUp: _comp => {
23769
                  increase(true, false);
23770
                  return Optional.some(true);
23771
                },
23772
                onDown: _comp => {
23773
                  decrease(true, false);
23774
                  return Optional.some(true);
23775
                },
23776
                onLeft: (_comp, se) => {
23777
                  se.cut();
23778
                  return Optional.none();
23779
                },
23780
                onRight: (_comp, se) => {
23781
                  se.cut();
23782
                  return Optional.none();
23783
                }
23784
              })
23785
            ])
23786
          })],
23787
        behaviours: derive$1([
23788
          Focusing.config({}),
23789
          Keying.config({
23790
            mode: 'special',
23791
            onEnter: focusInput,
23792
            onSpace: focusInput,
23793
            onEscape: goToParent
23794
          }),
23795
          config('input-wrapper-events', [run$1(mouseover(), comp => {
23796
              each$1([
23797
                memMinus,
23798
                memPlus
23799
              ], button => {
23800
                const buttonNode = SugarElement.fromDom(button.get(comp).element.dom);
23801
                if (hasFocus(buttonNode)) {
23802
                  blur$1(buttonNode);
23803
                }
23804
              });
23805
            })])
23806
        ])
23807
      });
23808
      return {
23809
        dom: {
23810
          tag: 'div',
23811
          classes: ['tox-number-input']
23812
        },
23813
        components: [
23814
          memMinus.asSpec(),
23815
          memInput.asSpec(),
23816
          memPlus.asSpec()
23817
        ],
23818
        behaviours: derive$1([
23819
          Focusing.config({}),
23820
          Keying.config({
23821
            mode: 'flow',
23822
            focusInside: FocusInsideModes.OnEnterOrSpaceMode,
23823
            cycles: false,
23824
            selector: 'button, .tox-input-wrapper',
23825
            onEscape: wrapperComp => {
23826
              if (hasFocus(wrapperComp.element)) {
23827
                return Optional.none();
23828
              } else {
23829
                focus$3(wrapperComp.element);
23830
                return Optional.some(true);
23831
              }
23832
            }
23833
          })
23834
        ])
23835
      };
23836
    };
23837
 
23838
    const menuTitle$1 = 'Font sizes';
23839
    const btnTooltip$1 = 'Font size {0}';
23840
    const fallbackFontSize = '12pt';
23841
    const legacyFontSizes = {
23842
      '8pt': '1',
23843
      '10pt': '2',
23844
      '12pt': '3',
23845
      '14pt': '4',
23846
      '18pt': '5',
23847
      '24pt': '6',
23848
      '36pt': '7'
23849
    };
23850
    const keywordFontSizes = {
23851
      'xx-small': '7pt',
23852
      'x-small': '8pt',
23853
      'small': '10pt',
23854
      'medium': '12pt',
23855
      'large': '14pt',
23856
      'x-large': '18pt',
23857
      'xx-large': '24pt'
23858
    };
23859
    const round = (number, precision) => {
23860
      const factor = Math.pow(10, precision);
23861
      return Math.round(number * factor) / factor;
23862
    };
23863
    const toPt = (fontSize, precision) => {
23864
      if (/[0-9.]+px$/.test(fontSize)) {
23865
        return round(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
23866
      } else {
23867
        return get$g(keywordFontSizes, fontSize).getOr(fontSize);
23868
      }
23869
    };
23870
    const toLegacy = fontSize => get$g(legacyFontSizes, fontSize).getOr('');
23871
    const getSpec$1 = editor => {
23872
      const getMatchingValue = () => {
23873
        let matchOpt = Optional.none();
23874
        const items = dataset.data;
23875
        const fontSize = editor.queryCommandValue('FontSize');
23876
        if (fontSize) {
23877
          for (let precision = 3; matchOpt.isNone() && precision >= 0; precision--) {
23878
            const pt = toPt(fontSize, precision);
23879
            const legacy = toLegacy(pt);
23880
            matchOpt = find$5(items, item => item.format === fontSize || item.format === pt || item.format === legacy);
23881
          }
23882
        }
23883
        return {
23884
          matchOpt,
23885
          size: fontSize
23886
        };
23887
      };
23888
      const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
23889
      const getCurrentValue = () => {
23890
        const {matchOpt} = getMatchingValue();
23891
        return matchOpt;
23892
      };
23893
      const getPreviewFor = constant$1(Optional.none);
23894
      const onAction = rawItem => () => {
23895
        editor.undoManager.transact(() => {
23896
          editor.focus();
23897
          editor.execCommand('FontSize', false, rawItem.format);
23898
        });
23899
      };
23900
      const updateSelectMenuText = comp => {
23901
        const {matchOpt, size} = getMatchingValue();
23902
        const text = matchOpt.fold(constant$1(size), match => match.title);
23903
        emitWith(comp, updateMenuText, { text });
23904
        fireFontSizeTextUpdate(editor, { value: text });
23905
      };
23906
      const dataset = buildBasicSettingsDataset(editor, 'font_size_formats', Delimiter.Space);
23907
      return {
23908
        tooltip: makeTooltipText(editor, btnTooltip$1, fallbackFontSize),
23909
        text: Optional.some(fallbackFontSize),
23910
        icon: Optional.none(),
23911
        isSelectedFor,
23912
        getPreviewFor,
23913
        getCurrentValue,
23914
        onAction,
23915
        updateText: updateSelectMenuText,
23916
        dataset,
23917
        shouldHide: false,
23918
        isInvalid: never
23919
      };
23920
    };
23921
    const createFontSizeButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$1(editor), btnTooltip$1, 'FontSizeTextUpdate');
23922
    const getConfigFromUnit = unit => {
23923
      var _a;
23924
      const baseConfig = { step: 1 };
23925
      const configs = {
23926
        em: { step: 0.1 },
23927
        cm: { step: 0.1 },
23928
        in: { step: 0.1 },
23929
        pc: { step: 0.1 },
23930
        ch: { step: 0.1 },
23931
        rem: { step: 0.1 }
23932
      };
23933
      return (_a = configs[unit]) !== null && _a !== void 0 ? _a : baseConfig;
23934
    };
23935
    const defaultValue = 16;
23936
    const isValidValue = value => value >= 0;
23937
    const getNumberInputSpec = editor => {
23938
      const getCurrentValue = () => editor.queryCommandValue('FontSize');
23939
      const updateInputValue = comp => emitWith(comp, updateMenuText, { text: getCurrentValue() });
23940
      return {
23941
        updateInputValue,
23942
        onAction: (format, focusBack) => editor.execCommand('FontSize', false, format, { skip_focus: !focusBack }),
23943
        getNewValue: (text, updateFunction) => {
23944
          parse(text, [
23945
            'unsupportedLength',
23946
            'empty'
23947
          ]);
23948
          const currentValue = getCurrentValue();
23949
          const parsedText = parse(text, [
23950
            'unsupportedLength',
23951
            'empty'
23952
          ]).or(parse(currentValue, [
23953
            'unsupportedLength',
23954
            'empty'
23955
          ]));
23956
          const value = parsedText.map(res => res.value).getOr(defaultValue);
23957
          const defaultUnit = getFontSizeInputDefaultUnit(editor);
23958
          const unit = parsedText.map(res => res.unit).filter(u => u !== '').getOr(defaultUnit);
23959
          const newValue = updateFunction(value, getConfigFromUnit(unit).step);
23960
          const res = `${ isValidValue(newValue) ? newValue : value }${ unit }`;
23961
          if (res !== currentValue) {
23962
            fireFontSizeInputTextUpdate(editor, { value: res });
23963
          }
23964
          return res;
23965
        }
23966
      };
23967
    };
23968
    const createFontSizeInputButton = (editor, backstage) => createBespokeNumberInput(editor, backstage, getNumberInputSpec(editor));
23969
    const createFontSizeMenu = (editor, backstage) => {
23970
      const menuItems = createMenuItems(editor, backstage, getSpec$1(editor));
23971
      editor.ui.registry.addNestedMenuItem('fontsize', {
23972
        text: menuTitle$1,
23973
        onSetup: onSetupEditableToggle(editor),
23974
        getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
23975
      });
23976
    };
23977
 
23978
    const menuTitle = 'Formats';
23979
    const btnTooltip = 'Format {0}';
23980
    const getSpec = (editor, dataset) => {
23981
      const fallbackFormat = 'Paragraph';
23982
      const isSelectedFor = format => () => editor.formatter.match(format);
23983
      const getPreviewFor = format => () => {
23984
        const fmt = editor.formatter.get(format);
23985
        return fmt !== undefined ? Optional.some({
23986
          tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
23987
          styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
23988
        }) : Optional.none();
23989
      };
23990
      const updateSelectMenuText = comp => {
23991
        const getFormatItems = fmt => {
23992
          if (isNestedFormat(fmt)) {
23993
            return bind$3(fmt.items, getFormatItems);
23994
          } else if (isFormatReference(fmt)) {
23995
            return [{
23996
                title: fmt.title,
23997
                format: fmt.format
23998
              }];
23999
          } else {
24000
            return [];
24001
          }
24002
        };
24003
        const flattenedItems = bind$3(getStyleFormats(editor), getFormatItems);
24004
        const detectedFormat = findNearest(editor, constant$1(flattenedItems));
24005
        const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
24006
        emitWith(comp, updateMenuText, { text });
24007
        fireStylesTextUpdate(editor, { value: text });
24008
      };
24009
      return {
24010
        tooltip: makeTooltipText(editor, btnTooltip, fallbackFormat),
24011
        text: Optional.some(fallbackFormat),
24012
        icon: Optional.none(),
24013
        isSelectedFor,
24014
        getCurrentValue: Optional.none,
24015
        getPreviewFor,
24016
        onAction: onActionToggleFormat$1(editor),
24017
        updateText: updateSelectMenuText,
24018
        shouldHide: shouldAutoHideStyleFormats(editor),
24019
        isInvalid: item => !editor.formatter.canApply(item.format),
24020
        dataset
24021
      };
24022
    };
24023
    const createStylesButton = (editor, backstage) => {
24024
      const dataset = {
24025
        type: 'advanced',
24026
        ...backstage.styles
24027
      };
24028
      return createSelectButton(editor, backstage, getSpec(editor, dataset), btnTooltip, 'StylesTextUpdate');
24029
    };
24030
    const createStylesMenu = (editor, backstage) => {
24031
      const dataset = {
24032
        type: 'advanced',
24033
        ...backstage.styles
24034
      };
24035
      const menuItems = createMenuItems(editor, backstage, getSpec(editor, dataset));
24036
      editor.ui.registry.addNestedMenuItem('styles', {
24037
        text: menuTitle,
24038
        onSetup: onSetupEditableToggle(editor),
24039
        getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
24040
      });
24041
    };
24042
 
24043
    const schema$7 = constant$1([
24044
      required$1('toggleClass'),
24045
      required$1('fetch'),
24046
      onStrictHandler('onExecute'),
24047
      defaulted('getHotspot', Optional.some),
24048
      defaulted('getAnchorOverrides', constant$1({})),
24049
      schema$y(),
24050
      onStrictHandler('onItemExecute'),
24051
      option$3('lazySink'),
24052
      required$1('dom'),
24053
      onHandler('onOpen'),
24054
      field('splitDropdownBehaviours', [
24055
        Coupling,
24056
        Keying,
24057
        Focusing
24058
      ]),
24059
      defaulted('matchWidth', false),
24060
      defaulted('useMinWidth', false),
24061
      defaulted('eventOrder', {}),
24062
      option$3('role')
24063
    ].concat(sandboxFields()));
24064
    const arrowPart = required({
24065
      factory: Button,
24066
      schema: [required$1('dom')],
24067
      name: 'arrow',
24068
      defaults: () => {
24069
        return { buttonBehaviours: derive$1([Focusing.revoke()]) };
24070
      },
24071
      overrides: detail => {
24072
        return {
24073
          dom: {
24074
            tag: 'span',
24075
            attributes: { role: 'presentation' }
24076
          },
24077
          action: arrow => {
24078
            arrow.getSystem().getByUid(detail.uid).each(emitExecute);
24079
          },
24080
          buttonBehaviours: derive$1([Toggling.config({
24081
              toggleOnExecute: false,
24082
              toggleClass: detail.toggleClass
24083
            })])
24084
        };
24085
      }
24086
    });
24087
    const buttonPart = required({
24088
      factory: Button,
24089
      schema: [required$1('dom')],
24090
      name: 'button',
24091
      defaults: () => {
24092
        return { buttonBehaviours: derive$1([Focusing.revoke()]) };
24093
      },
24094
      overrides: detail => {
24095
        return {
24096
          dom: {
24097
            tag: 'span',
24098
            attributes: { role: 'presentation' }
24099
          },
24100
          action: btn => {
24101
            btn.getSystem().getByUid(detail.uid).each(splitDropdown => {
24102
              detail.onExecute(splitDropdown, btn);
24103
            });
24104
          }
24105
        };
24106
      }
24107
    });
24108
    const parts$3 = constant$1([
24109
      arrowPart,
24110
      buttonPart,
24111
      optional({
24112
        factory: {
24113
          sketch: spec => {
24114
            return {
24115
              uid: spec.uid,
24116
              dom: {
24117
                tag: 'span',
24118
                styles: { display: 'none' },
24119
                attributes: { 'aria-hidden': 'true' },
24120
                innerHtml: spec.text
24121
              }
24122
            };
24123
          }
24124
        },
24125
        schema: [required$1('text')],
24126
        name: 'aria-descriptor'
24127
      }),
24128
      external({
24129
        schema: [tieredMenuMarkers()],
24130
        name: 'menu',
24131
        defaults: detail => {
24132
          return {
24133
            onExecute: (tmenu, item) => {
24134
              tmenu.getSystem().getByUid(detail.uid).each(splitDropdown => {
24135
                detail.onItemExecute(splitDropdown, tmenu, item);
24136
              });
24137
            }
24138
          };
24139
        }
24140
      }),
24141
      partType$1()
24142
    ]);
24143
 
24144
    const factory$5 = (detail, components, spec, externals) => {
24145
      const switchToMenu = sandbox => {
24146
        Composing.getCurrent(sandbox).each(current => {
24147
          Highlighting.highlightFirst(current);
24148
          Keying.focusIn(current);
24149
        });
24150
      };
24151
      const action = component => {
24152
        const onOpenSync = switchToMenu;
24153
        togglePopup(detail, identity, component, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
24154
      };
24155
      const openMenu = comp => {
24156
        action(comp);
24157
        return Optional.some(true);
24158
      };
24159
      const executeOnButton = comp => {
24160
        const button = getPartOrDie(comp, detail, 'button');
24161
        emitExecute(button);
24162
        return Optional.some(true);
24163
      };
24164
      const buttonEvents = {
24165
        ...derive$2([runOnAttached((component, _simulatedEvent) => {
24166
            const ariaDescriptor = getPart(component, detail, 'aria-descriptor');
24167
            ariaDescriptor.each(descriptor => {
24168
              const descriptorId = generate$6('aria');
24169
              set$9(descriptor.element, 'id', descriptorId);
24170
              set$9(component.element, 'aria-describedby', descriptorId);
24171
            });
24172
          })]),
24173
        ...events$a(Optional.some(action))
24174
      };
24175
      const apis = {
24176
        repositionMenus: comp => {
24177
          if (Toggling.isOn(comp)) {
24178
            repositionMenus(comp);
24179
          }
24180
        }
24181
      };
24182
      return {
24183
        uid: detail.uid,
24184
        dom: detail.dom,
24185
        components,
24186
        apis,
24187
        eventOrder: {
24188
          ...detail.eventOrder,
24189
          [execute$5()]: [
24190
            'disabling',
24191
            'toggling',
24192
            'alloy.base.behaviour'
24193
          ]
24194
        },
24195
        events: buttonEvents,
24196
        behaviours: augment(detail.splitDropdownBehaviours, [
24197
          Coupling.config({
24198
            others: {
24199
              sandbox: hotspot => {
24200
                const arrow = getPartOrDie(hotspot, detail, 'arrow');
24201
                const extras = {
24202
                  onOpen: () => {
24203
                    Toggling.on(arrow);
24204
                    Toggling.on(hotspot);
24205
                  },
24206
                  onClose: () => {
24207
                    Toggling.off(arrow);
24208
                    Toggling.off(hotspot);
24209
                  }
24210
                };
24211
                return makeSandbox$1(detail, hotspot, extras);
24212
              }
24213
            }
24214
          }),
24215
          Keying.config({
24216
            mode: 'special',
24217
            onSpace: executeOnButton,
24218
            onEnter: executeOnButton,
24219
            onDown: openMenu
24220
          }),
24221
          Focusing.config({}),
24222
          Toggling.config({
24223
            toggleOnExecute: false,
24224
            aria: { mode: 'expanded' }
24225
          })
24226
        ]),
24227
        domModification: {
24228
          attributes: {
24229
            'role': detail.role.getOr('button'),
24230
            'aria-haspopup': true
24231
          }
24232
        }
24233
      };
24234
    };
24235
    const SplitDropdown = composite({
24236
      name: 'SplitDropdown',
24237
      configFields: schema$7(),
24238
      partFields: parts$3(),
24239
      factory: factory$5,
24240
      apis: { repositionMenus: (apis, comp) => apis.repositionMenus(comp) }
24241
    });
24242
 
24243
    const getButtonApi = component => ({
24244
      isEnabled: () => !Disabling.isDisabled(component),
24245
      setEnabled: state => Disabling.set(component, !state),
24246
      setText: text => emitWith(component, updateMenuText, { text }),
24247
      setIcon: icon => emitWith(component, updateMenuIcon, { icon })
24248
    });
24249
    const getToggleApi = component => ({
24250
      setActive: state => {
24251
        Toggling.set(component, state);
24252
      },
24253
      isActive: () => Toggling.isOn(component),
24254
      isEnabled: () => !Disabling.isDisabled(component),
24255
      setEnabled: state => Disabling.set(component, !state),
24256
      setText: text => emitWith(component, updateMenuText, { text }),
24257
      setIcon: icon => emitWith(component, updateMenuIcon, { icon })
24258
    });
24259
    const getTooltipAttributes = (tooltip, providersBackstage) => tooltip.map(tooltip => ({
24260
      'aria-label': providersBackstage.translate(tooltip),
24261
      'title': providersBackstage.translate(tooltip)
24262
    })).getOr({});
24263
    const focusButtonEvent = generate$6('focus-button');
24264
    const renderCommonStructure = (optIcon, optText, tooltip, behaviours, providersBackstage) => {
24265
      const optMemDisplayText = optText.map(text => record(renderLabel$1(text, 'tox-tbtn', providersBackstage)));
24266
      const optMemDisplayIcon = optIcon.map(icon => record(renderReplaceableIconFromPack(icon, providersBackstage.icons)));
24267
      return {
24268
        dom: {
24269
          tag: 'button',
24270
          classes: ['tox-tbtn'].concat(optText.isSome() ? ['tox-tbtn--select'] : []),
24271
          attributes: getTooltipAttributes(tooltip, providersBackstage)
24272
        },
24273
        components: componentRenderPipeline([
24274
          optMemDisplayIcon.map(mem => mem.asSpec()),
24275
          optMemDisplayText.map(mem => mem.asSpec())
24276
        ]),
24277
        eventOrder: {
24278
          [mousedown()]: [
24279
            'focusing',
24280
            'alloy.base.behaviour',
24281
            commonButtonDisplayEvent
24282
          ],
24283
          [attachedToDom()]: [
24284
            commonButtonDisplayEvent,
24285
            'toolbar-group-button-events'
24286
          ]
24287
        },
24288
        buttonBehaviours: derive$1([
24289
          DisablingConfigs.toolbarButton(providersBackstage.isDisabled),
24290
          receivingConfig(),
24291
          config(commonButtonDisplayEvent, [
24292
            runOnAttached((comp, _se) => forceInitialSize(comp)),
24293
            run$1(updateMenuText, (comp, se) => {
24294
              optMemDisplayText.bind(mem => mem.getOpt(comp)).each(displayText => {
24295
                Replacing.set(displayText, [text$2(providersBackstage.translate(se.event.text))]);
24296
              });
24297
            }),
24298
            run$1(updateMenuIcon, (comp, se) => {
24299
              optMemDisplayIcon.bind(mem => mem.getOpt(comp)).each(displayIcon => {
24300
                Replacing.set(displayIcon, [renderReplaceableIconFromPack(se.event.icon, providersBackstage.icons)]);
24301
              });
24302
            }),
24303
            run$1(mousedown(), (button, se) => {
24304
              se.event.prevent();
24305
              emit(button, focusButtonEvent);
24306
            })
24307
          ])
24308
        ].concat(behaviours.getOr([])))
24309
      };
24310
    };
24311
    const renderFloatingToolbarButton = (spec, backstage, identifyButtons, attributes) => {
24312
      const sharedBackstage = backstage.shared;
24313
      const editorOffCell = Cell(noop);
24314
      const specialisation = {
24315
        toolbarButtonBehaviours: [],
24316
        getApi: getButtonApi,
24317
        onSetup: spec.onSetup
24318
      };
24319
      const behaviours = [config('toolbar-group-button-events', [
24320
          onControlAttached(specialisation, editorOffCell),
24321
          onControlDetached(specialisation, editorOffCell)
24322
        ])];
24323
      return FloatingToolbarButton.sketch({
24324
        lazySink: sharedBackstage.getSink,
24325
        fetch: () => Future.nu(resolve => {
24326
          resolve(map$2(identifyButtons(spec.items), renderToolbarGroup));
24327
        }),
24328
        markers: { toggledClass: 'tox-tbtn--enabled' },
24329
        parts: {
24330
          button: renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.some(behaviours), sharedBackstage.providers),
24331
          toolbar: {
24332
            dom: {
24333
              tag: 'div',
24334
              classes: ['tox-toolbar__overflow'],
24335
              attributes
24336
            }
24337
          }
24338
        }
24339
      });
24340
    };
24341
    const renderCommonToolbarButton = (spec, specialisation, providersBackstage) => {
24342
      var _d;
24343
      const editorOffCell = Cell(noop);
24344
      const structure = renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.none(), providersBackstage);
24345
      return Button.sketch({
24346
        dom: structure.dom,
24347
        components: structure.components,
24348
        eventOrder: toolbarButtonEventOrder,
24349
        buttonBehaviours: {
24350
          ...derive$1([
24351
            config('toolbar-button-events', [
24352
              onToolbarButtonExecute({
24353
                onAction: spec.onAction,
24354
                getApi: specialisation.getApi
24355
              }),
24356
              onControlAttached(specialisation, editorOffCell),
24357
              onControlDetached(specialisation, editorOffCell)
24358
            ]),
24359
            DisablingConfigs.toolbarButton(() => !spec.enabled || providersBackstage.isDisabled()),
24360
            receivingConfig()
24361
          ].concat(specialisation.toolbarButtonBehaviours)),
24362
          [commonButtonDisplayEvent]: (_d = structure.buttonBehaviours) === null || _d === void 0 ? void 0 : _d[commonButtonDisplayEvent]
24363
        }
24364
      });
24365
    };
24366
    const renderToolbarButton = (spec, providersBackstage) => renderToolbarButtonWith(spec, providersBackstage, []);
24367
    const renderToolbarButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
24368
      toolbarButtonBehaviours: bonusEvents.length > 0 ? [config('toolbarButtonWith', bonusEvents)] : [],
24369
      getApi: getButtonApi,
24370
      onSetup: spec.onSetup
24371
    }, providersBackstage);
24372
    const renderToolbarToggleButton = (spec, providersBackstage) => renderToolbarToggleButtonWith(spec, providersBackstage, []);
24373
    const renderToolbarToggleButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
24374
      toolbarButtonBehaviours: [
24375
        Replacing.config({}),
24376
        Toggling.config({
24377
          toggleClass: 'tox-tbtn--enabled',
24378
          aria: { mode: 'pressed' },
24379
          toggleOnExecute: false
24380
        })
24381
      ].concat(bonusEvents.length > 0 ? [config('toolbarToggleButtonWith', bonusEvents)] : []),
24382
      getApi: getToggleApi,
24383
      onSetup: spec.onSetup
24384
    }, providersBackstage);
24385
    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 => {
24386
      spec.onItemAction(getApi(comp), value);
24387
    }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, spec.select.getOr(never), providersBackstage), {
24388
      movement: deriveMenuMovement(spec.columns, spec.presets),
24389
      menuBehaviours: SimpleBehaviours.unnamedEvents(spec.columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
24390
          detectSize(comp, 4, classForPreset(spec.presets)).each(({numRows, numColumns}) => {
24391
            Keying.setGridSize(comp, numRows, numColumns);
24392
          });
24393
        })])
24394
    }))));
24395
    const renderSplitButton = (spec, sharedBackstage) => {
24396
      const getApi = comp => ({
24397
        isEnabled: () => !Disabling.isDisabled(comp),
24398
        setEnabled: state => Disabling.set(comp, !state),
24399
        setIconFill: (id, value) => {
24400
          descendant(comp.element, `svg path[class="${ id }"], rect[class="${ id }"]`).each(underlinePath => {
24401
            set$9(underlinePath, 'fill', value);
24402
          });
24403
        },
24404
        setActive: state => {
24405
          set$9(comp.element, 'aria-pressed', state);
24406
          descendant(comp.element, 'span').each(button => {
24407
            comp.getSystem().getByDom(button).each(buttonComp => Toggling.set(buttonComp, state));
24408
          });
24409
        },
24410
        isActive: () => descendant(comp.element, 'span').exists(button => comp.getSystem().getByDom(button).exists(Toggling.isOn)),
24411
        setText: text => descendant(comp.element, 'span').each(button => comp.getSystem().getByDom(button).each(buttonComp => emitWith(buttonComp, updateMenuText, { text }))),
24412
        setIcon: icon => descendant(comp.element, 'span').each(button => comp.getSystem().getByDom(button).each(buttonComp => emitWith(buttonComp, updateMenuIcon, { icon }))),
24413
        setTooltip: tooltip => {
24414
          const translatedTooltip = sharedBackstage.providers.translate(tooltip);
24415
          setAll$1(comp.element, {
24416
            'aria-label': translatedTooltip,
24417
            'title': translatedTooltip
24418
          });
24419
        }
24420
      });
24421
      const editorOffCell = Cell(noop);
24422
      const specialisation = {
24423
        getApi,
24424
        onSetup: spec.onSetup
24425
      };
24426
      return SplitDropdown.sketch({
24427
        dom: {
24428
          tag: 'div',
24429
          classes: ['tox-split-button'],
24430
          attributes: {
24431
            'aria-pressed': false,
24432
            ...getTooltipAttributes(spec.tooltip, sharedBackstage.providers)
24433
          }
24434
        },
24435
        onExecute: button => {
24436
          const api = getApi(button);
24437
          if (api.isEnabled()) {
24438
            spec.onAction(api);
24439
          }
24440
        },
24441
        onItemExecute: (_a, _b, _c) => {
24442
        },
24443
        splitDropdownBehaviours: derive$1([
24444
          DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
24445
          receivingConfig(),
24446
          config('split-dropdown-events', [
24447
            runOnAttached((comp, _se) => forceInitialSize(comp)),
24448
            run$1(focusButtonEvent, Focusing.focus),
24449
            onControlAttached(specialisation, editorOffCell),
24450
            onControlDetached(specialisation, editorOffCell)
24451
          ]),
24452
          Unselecting.config({})
24453
        ]),
24454
        eventOrder: {
24455
          [attachedToDom()]: [
24456
            'alloy.base.behaviour',
24457
            'split-dropdown-events'
24458
          ]
24459
        },
24460
        toggleClass: 'tox-tbtn--enabled',
24461
        lazySink: sharedBackstage.getSink,
24462
        fetch: fetchChoices(getApi, spec, sharedBackstage.providers),
24463
        parts: { menu: part(false, spec.columns, spec.presets) },
24464
        components: [
24465
          SplitDropdown.parts.button(renderCommonStructure(spec.icon, spec.text, Optional.none(), Optional.some([Toggling.config({
24466
              toggleClass: 'tox-tbtn--enabled',
24467
              toggleOnExecute: false
24468
            })]), sharedBackstage.providers)),
24469
          SplitDropdown.parts.arrow({
24470
            dom: {
24471
              tag: 'button',
24472
              classes: [
24473
                'tox-tbtn',
24474
                'tox-split-button__chevron'
24475
              ],
24476
              innerHtml: get$2('chevron-down', sharedBackstage.providers.icons)
24477
            },
24478
            buttonBehaviours: derive$1([
24479
              DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
24480
              receivingConfig(),
24481
              addFocusableBehaviour()
24482
            ])
24483
          }),
24484
          SplitDropdown.parts['aria-descriptor']({ text: sharedBackstage.providers.translate('To open the popup, press Shift+Enter') })
24485
        ]
24486
      });
24487
    };
24488
 
24489
    const defaultToolbar = [
24490
      {
24491
        name: 'history',
24492
        items: [
24493
          'undo',
24494
          'redo'
24495
        ]
24496
      },
24497
      {
24498
        name: 'ai',
24499
        items: [
24500
          'aidialog',
24501
          'aishortcuts'
24502
        ]
24503
      },
24504
      {
24505
        name: 'styles',
24506
        items: ['styles']
24507
      },
24508
      {
24509
        name: 'formatting',
24510
        items: [
24511
          'bold',
24512
          'italic'
24513
        ]
24514
      },
24515
      {
24516
        name: 'alignment',
24517
        items: [
24518
          'alignleft',
24519
          'aligncenter',
24520
          'alignright',
24521
          'alignjustify'
24522
        ]
24523
      },
24524
      {
24525
        name: 'indentation',
24526
        items: [
24527
          'outdent',
24528
          'indent'
24529
        ]
24530
      },
24531
      {
24532
        name: 'permanent pen',
24533
        items: ['permanentpen']
24534
      },
24535
      {
24536
        name: 'comments',
24537
        items: ['addcomment']
24538
      }
24539
    ];
24540
    const renderFromBridge = (bridgeBuilder, render) => (spec, backstage, editor) => {
24541
      const internal = bridgeBuilder(spec).mapError(errInfo => formatError(errInfo)).getOrDie();
24542
      return render(internal, backstage, editor);
24543
    };
24544
    const types = {
24545
      button: renderFromBridge(createToolbarButton, (s, backstage) => renderToolbarButton(s, backstage.shared.providers)),
24546
      togglebutton: renderFromBridge(createToggleButton, (s, backstage) => renderToolbarToggleButton(s, backstage.shared.providers)),
24547
      menubutton: renderFromBridge(createMenuButton, (s, backstage) => renderMenuButton(s, 'tox-tbtn', backstage, Optional.none(), false)),
24548
      splitbutton: renderFromBridge(createSplitButton, (s, backstage) => renderSplitButton(s, backstage.shared)),
24549
      grouptoolbarbutton: renderFromBridge(createGroupToolbarButton, (s, backstage, editor) => {
24550
        const buttons = editor.ui.registry.getAll().buttons;
24551
        const identify = toolbar => identifyButtons(editor, {
24552
          buttons,
24553
          toolbar,
24554
          allowToolbarGroups: false
24555
        }, backstage, Optional.none());
24556
        const attributes = { [Attribute]: backstage.shared.header.isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop };
24557
        switch (getToolbarMode(editor)) {
24558
        case ToolbarMode$1.floating:
24559
          return renderFloatingToolbarButton(s, backstage, identify, attributes);
24560
        default:
24561
          throw new Error('Toolbar groups are only supported when using floating toolbar mode');
24562
        }
24563
      })
24564
    };
24565
    const extractFrom = (spec, backstage, editor) => get$g(types, spec.type).fold(() => {
24566
      console.error('skipping button defined by', spec);
24567
      return Optional.none();
24568
    }, render => Optional.some(render(spec, backstage, editor)));
24569
    const bespokeButtons = {
24570
      styles: createStylesButton,
24571
      fontsize: createFontSizeButton,
24572
      fontsizeinput: createFontSizeInputButton,
24573
      fontfamily: createFontFamilyButton,
24574
      blocks: createBlocksButton,
24575
      align: createAlignButton
24576
    };
24577
    const removeUnusedDefaults = buttons => {
24578
      const filteredItemGroups = map$2(defaultToolbar, group => {
24579
        const items = filter$2(group.items, subItem => has$2(buttons, subItem) || has$2(bespokeButtons, subItem));
24580
        return {
24581
          name: group.name,
24582
          items
24583
        };
24584
      });
24585
      return filter$2(filteredItemGroups, group => group.items.length > 0);
24586
    };
24587
    const convertStringToolbar = strToolbar => {
24588
      const groupsStrings = strToolbar.split('|');
24589
      return map$2(groupsStrings, g => ({ items: g.trim().split(' ') }));
24590
    };
24591
    const isToolbarGroupSettingArray = toolbar => isArrayOf(toolbar, t => has$2(t, 'name') && has$2(t, 'items'));
24592
    const createToolbar = toolbarConfig => {
24593
      const toolbar = toolbarConfig.toolbar;
24594
      const buttons = toolbarConfig.buttons;
24595
      if (toolbar === false) {
24596
        return [];
24597
      } else if (toolbar === undefined || toolbar === true) {
24598
        return removeUnusedDefaults(buttons);
24599
      } else if (isString(toolbar)) {
24600
        return convertStringToolbar(toolbar);
24601
      } else if (isToolbarGroupSettingArray(toolbar)) {
24602
        return toolbar;
24603
      } else {
24604
        console.error('Toolbar type should be string, string[], boolean or ToolbarGroup[]');
24605
        return [];
24606
      }
24607
    };
24608
    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 => {
24609
      if (spec.type === 'grouptoolbarbutton' && !allowToolbarGroups) {
24610
        console.warn(`Ignoring the '${ toolbarItem }' toolbar button. Group toolbar buttons are only supported when using floating toolbar mode and cannot be nested.`);
24611
        return Optional.none();
24612
      } else {
24613
        return extractFrom(spec, backstage, editor);
24614
      }
24615
    });
24616
    const identifyButtons = (editor, toolbarConfig, backstage, prefixes) => {
24617
      const toolbarGroups = createToolbar(toolbarConfig);
24618
      const groups = map$2(toolbarGroups, group => {
24619
        const items = bind$3(group.items, toolbarItem => {
24620
          return toolbarItem.trim().length === 0 ? [] : lookupButton(editor, toolbarConfig.buttons, toolbarItem, toolbarConfig.allowToolbarGroups, backstage, prefixes).toArray();
24621
        });
24622
        return {
24623
          title: Optional.from(editor.translate(group.name)),
24624
          items
24625
        };
24626
      });
24627
      return filter$2(groups, group => group.items.length > 0);
24628
    };
24629
 
24630
    const setToolbar = (editor, uiRefs, rawUiConfig, backstage) => {
24631
      const outerContainer = uiRefs.mainUi.outerContainer;
24632
      const toolbarConfig = rawUiConfig.toolbar;
24633
      const toolbarButtonsConfig = rawUiConfig.buttons;
24634
      if (isArrayOf(toolbarConfig, isString)) {
24635
        const toolbars = toolbarConfig.map(t => {
24636
          const config = {
24637
            toolbar: t,
24638
            buttons: toolbarButtonsConfig,
24639
            allowToolbarGroups: rawUiConfig.allowToolbarGroups
24640
          };
24641
          return identifyButtons(editor, config, backstage, Optional.none());
24642
        });
24643
        OuterContainer.setToolbars(outerContainer, toolbars);
24644
      } else {
24645
        OuterContainer.setToolbar(outerContainer, identifyButtons(editor, rawUiConfig, backstage, Optional.none()));
24646
      }
24647
    };
24648
 
24649
    const detection = detect$2();
24650
    const isiOS12 = detection.os.isiOS() && detection.os.version.major <= 12;
24651
    const setupEvents$1 = (editor, uiRefs) => {
24652
      const {uiMotherships} = uiRefs;
24653
      const dom = editor.dom;
24654
      let contentWindow = editor.getWin();
24655
      const initialDocEle = editor.getDoc().documentElement;
24656
      const lastWindowDimensions = Cell(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
24657
      const lastDocumentDimensions = Cell(SugarPosition(initialDocEle.offsetWidth, initialDocEle.offsetHeight));
24658
      const resizeWindow = () => {
24659
        const outer = lastWindowDimensions.get();
24660
        if (outer.left !== contentWindow.innerWidth || outer.top !== contentWindow.innerHeight) {
24661
          lastWindowDimensions.set(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
24662
          fireResizeContent(editor);
24663
        }
24664
      };
24665
      const resizeDocument = () => {
24666
        const docEle = editor.getDoc().documentElement;
24667
        const inner = lastDocumentDimensions.get();
24668
        if (inner.left !== docEle.offsetWidth || inner.top !== docEle.offsetHeight) {
24669
          lastDocumentDimensions.set(SugarPosition(docEle.offsetWidth, docEle.offsetHeight));
24670
          fireResizeContent(editor);
24671
        }
24672
      };
24673
      const scroll = e => {
24674
        fireScrollContent(editor, e);
24675
      };
24676
      dom.bind(contentWindow, 'resize', resizeWindow);
24677
      dom.bind(contentWindow, 'scroll', scroll);
24678
      const elementLoad = capture(SugarElement.fromDom(editor.getBody()), 'load', resizeDocument);
24679
      editor.on('hide', () => {
24680
        each$1(uiMotherships, m => {
24681
          set$8(m.element, 'display', 'none');
24682
        });
24683
      });
24684
      editor.on('show', () => {
24685
        each$1(uiMotherships, m => {
24686
          remove$6(m.element, 'display');
24687
        });
24688
      });
24689
      editor.on('NodeChange', resizeDocument);
24690
      editor.on('remove', () => {
24691
        elementLoad.unbind();
24692
        dom.unbind(contentWindow, 'resize', resizeWindow);
24693
        dom.unbind(contentWindow, 'scroll', scroll);
24694
        contentWindow = null;
24695
      });
24696
    };
24697
    const attachUiMotherships = (editor, uiRoot, uiRefs) => {
24698
      if (isSplitUiMode(editor)) {
24699
        attachSystemAfter(uiRefs.mainUi.mothership.element, uiRefs.popupUi.mothership);
24700
      }
24701
      attachSystem(uiRoot, uiRefs.dialogUi.mothership);
24702
    };
24703
    const render$1 = (editor, uiRefs, rawUiConfig, backstage, args) => {
24704
      const {mainUi, uiMotherships} = uiRefs;
24705
      const lastToolbarWidth = Cell(0);
24706
      const outerContainer = mainUi.outerContainer;
24707
      iframe(editor);
24708
      const eTargetNode = SugarElement.fromDom(args.targetNode);
24709
      const uiRoot = getContentContainer(getRootNode(eTargetNode));
24710
      attachSystemAfter(eTargetNode, mainUi.mothership);
24711
      attachUiMotherships(editor, uiRoot, uiRefs);
24712
      editor.on('SkinLoaded', () => {
24713
        OuterContainer.setSidebar(outerContainer, rawUiConfig.sidebar, getSidebarShow(editor));
24714
        setToolbar(editor, uiRefs, rawUiConfig, backstage);
24715
        lastToolbarWidth.set(editor.getWin().innerWidth);
24716
        OuterContainer.setMenubar(outerContainer, identifyMenus(editor, rawUiConfig));
24717
        OuterContainer.setViews(outerContainer, rawUiConfig.views);
24718
        setupEvents$1(editor, uiRefs);
24719
      });
24720
      const socket = OuterContainer.getSocket(outerContainer).getOrDie('Could not find expected socket element');
24721
      if (isiOS12) {
24722
        setAll(socket.element, {
24723
          'overflow': 'scroll',
24724
          '-webkit-overflow-scrolling': 'touch'
24725
        });
24726
        const limit = first(() => {
24727
          editor.dispatch('ScrollContent');
24728
        }, 20);
24729
        const unbinder = bind(socket.element, 'scroll', limit.throttle);
24730
        editor.on('remove', unbinder.unbind);
24731
      }
24732
      setupReadonlyModeSwitch(editor, uiRefs);
24733
      editor.addCommand('ToggleSidebar', (_ui, value) => {
24734
        OuterContainer.toggleSidebar(outerContainer, value);
24735
        editor.dispatch('ToggleSidebar');
24736
      });
24737
      editor.addQueryValueHandler('ToggleSidebar', () => {
24738
        var _a;
24739
        return (_a = OuterContainer.whichSidebar(outerContainer)) !== null && _a !== void 0 ? _a : '';
24740
      });
24741
      editor.addCommand('ToggleView', (_ui, value) => {
24742
        if (OuterContainer.toggleView(outerContainer, value)) {
24743
          const target = outerContainer.element;
24744
          mainUi.mothership.broadcastOn([dismissPopups()], { target });
24745
          each$1(uiMotherships, m => {
24746
            m.broadcastOn([dismissPopups()], { target });
24747
          });
24748
          if (isNull(OuterContainer.whichView(outerContainer))) {
24749
            editor.focus();
24750
            editor.nodeChanged();
24751
            OuterContainer.refreshToolbar(outerContainer);
24752
          }
24753
        }
24754
      });
24755
      editor.addQueryValueHandler('ToggleView', () => {
24756
        var _a;
24757
        return (_a = OuterContainer.whichView(outerContainer)) !== null && _a !== void 0 ? _a : '';
24758
      });
24759
      const toolbarMode = getToolbarMode(editor);
24760
      const refreshDrawer = () => {
24761
        OuterContainer.refreshToolbar(uiRefs.mainUi.outerContainer);
24762
      };
24763
      if (toolbarMode === ToolbarMode$1.sliding || toolbarMode === ToolbarMode$1.floating) {
24764
        editor.on('ResizeWindow ResizeEditor ResizeContent', () => {
24765
          const width = editor.getWin().innerWidth;
24766
          if (width !== lastToolbarWidth.get()) {
24767
            refreshDrawer();
24768
            lastToolbarWidth.set(width);
24769
          }
24770
        });
24771
      }
24772
      const api = {
24773
        setEnabled: state => {
24774
          broadcastReadonly(uiRefs, !state);
24775
        },
24776
        isEnabled: () => !Disabling.isDisabled(outerContainer)
24777
      };
24778
      return {
24779
        iframeContainer: socket.element.dom,
24780
        editorContainer: outerContainer.element.dom,
24781
        api
24782
      };
24783
    };
24784
 
24785
    var Iframe = /*#__PURE__*/Object.freeze({
24786
        __proto__: null,
24787
        render: render$1
24788
    });
24789
 
24790
    const parseToInt = val => {
24791
      const re = /^[0-9\.]+(|px)$/i;
24792
      if (re.test('' + val)) {
24793
        return Optional.some(parseInt('' + val, 10));
24794
      }
24795
      return Optional.none();
24796
    };
24797
    const numToPx = val => isNumber(val) ? val + 'px' : val;
24798
    const calcCappedSize = (size, minSize, maxSize) => {
24799
      const minOverride = minSize.filter(min => size < min);
24800
      const maxOverride = maxSize.filter(max => size > max);
24801
      return minOverride.or(maxOverride).getOr(size);
24802
    };
24803
 
24804
    const getHeight = editor => {
24805
      const baseHeight = getHeightOption(editor);
24806
      const minHeight = getMinHeightOption(editor);
24807
      const maxHeight = getMaxHeightOption(editor);
24808
      return parseToInt(baseHeight).map(height => calcCappedSize(height, minHeight, maxHeight));
24809
    };
24810
    const getHeightWithFallback = editor => {
24811
      const height = getHeight(editor);
24812
      return height.getOr(getHeightOption(editor));
24813
    };
24814
    const getWidth = editor => {
24815
      const baseWidth = getWidthOption(editor);
24816
      const minWidth = getMinWidthOption(editor);
24817
      const maxWidth = getMaxWidthOption(editor);
24818
      return parseToInt(baseWidth).map(width => calcCappedSize(width, minWidth, maxWidth));
24819
    };
24820
    const getWidthWithFallback = editor => {
24821
      const width = getWidth(editor);
24822
      return width.getOr(getWidthOption(editor));
24823
    };
24824
 
24825
    const {ToolbarLocation, ToolbarMode} = Options;
24826
    const maximumDistanceToEdge = 40;
24827
    const InlineHeader = (editor, targetElm, uiRefs, backstage, floatContainer) => {
24828
      const {mainUi, uiMotherships} = uiRefs;
24829
      const DOM = global$7.DOM;
24830
      const useFixedToolbarContainer = useFixedContainer(editor);
24831
      const isSticky = isStickyToolbar(editor);
24832
      const editorMaxWidthOpt = getMaxWidthOption(editor).or(getWidth(editor));
24833
      const headerBackstage = backstage.shared.header;
24834
      const isPositionedAtTop = headerBackstage.isPositionedAtTop;
24835
      const toolbarMode = getToolbarMode(editor);
24836
      const isSplitToolbar = toolbarMode === ToolbarMode.sliding || toolbarMode === ToolbarMode.floating;
24837
      const visible = Cell(false);
24838
      const isVisible = () => visible.get() && !editor.removed;
24839
      const calcToolbarOffset = toolbar => isSplitToolbar ? toolbar.fold(constant$1(0), tbar => tbar.components().length > 1 ? get$d(tbar.components()[1].element) : 0) : 0;
24840
      const calcMode = container => {
24841
        switch (getToolbarLocation(editor)) {
24842
        case ToolbarLocation.auto:
24843
          const toolbar = OuterContainer.getToolbar(mainUi.outerContainer);
24844
          const offset = calcToolbarOffset(toolbar);
24845
          const toolbarHeight = get$d(container.element) - offset;
24846
          const targetBounds = box$1(targetElm);
24847
          const roomAtTop = targetBounds.y > toolbarHeight;
24848
          if (roomAtTop) {
24849
            return 'top';
24850
          } else {
24851
            const doc = documentElement(targetElm);
24852
            const docHeight = Math.max(doc.dom.scrollHeight, get$d(doc));
24853
            const roomAtBottom = targetBounds.bottom < docHeight - toolbarHeight;
24854
            if (roomAtBottom) {
24855
              return 'bottom';
24856
            } else {
24857
              const winBounds = win();
24858
              const isRoomAtBottomViewport = winBounds.bottom < targetBounds.bottom - toolbarHeight;
24859
              return isRoomAtBottomViewport ? 'bottom' : 'top';
24860
            }
24861
          }
24862
        case ToolbarLocation.bottom:
24863
          return 'bottom';
24864
        case ToolbarLocation.top:
24865
        default:
24866
          return 'top';
24867
        }
24868
      };
24869
      const setupMode = mode => {
24870
        floatContainer.on(container => {
24871
          Docking.setModes(container, [mode]);
24872
          headerBackstage.setDockingMode(mode);
24873
          const verticalDir = isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop;
24874
          set$9(container.element, Attribute, verticalDir);
24875
        });
24876
      };
24877
      const updateChromeWidth = () => {
24878
        floatContainer.on(container => {
24879
          const maxWidth = editorMaxWidthOpt.getOrThunk(() => {
24880
            const bodyMargin = parseToInt(get$e(body(), 'margin-left')).getOr(0);
24881
            return get$c(body()) - absolute$3(targetElm).left + bodyMargin;
24882
          });
24883
          set$8(container.element, 'max-width', maxWidth + 'px');
24884
        });
24885
      };
24886
      const updateChromePosition = optToolbarWidth => {
24887
        floatContainer.on(container => {
24888
          const toolbar = OuterContainer.getToolbar(mainUi.outerContainer);
24889
          const offset = calcToolbarOffset(toolbar);
24890
          const targetBounds = box$1(targetElm);
24891
          const {top, left} = getOffsetParent$1(editor, mainUi.outerContainer.element).fold(() => {
24892
            return {
24893
              top: isPositionedAtTop() ? Math.max(targetBounds.y - get$d(container.element) + offset, 0) : targetBounds.bottom,
24894
              left: targetBounds.x
24895
            };
24896
          }, offsetParent => {
24897
            var _a;
24898
            const offsetBox = box$1(offsetParent);
24899
            const scrollDelta = (_a = offsetParent.dom.scrollTop) !== null && _a !== void 0 ? _a : 0;
24900
            const isOffsetParentBody = eq(offsetParent, body());
24901
            const topValue = isOffsetParentBody ? Math.max(targetBounds.y - get$d(container.element) + offset, 0) : targetBounds.y - offsetBox.y + scrollDelta - get$d(container.element) + offset;
24902
            return {
24903
              top: isPositionedAtTop() ? topValue : targetBounds.bottom,
24904
              left: isOffsetParentBody ? targetBounds.x : targetBounds.x - offsetBox.x
24905
            };
24906
          });
24907
          const baseProperties = {
24908
            position: 'absolute',
24909
            left: Math.round(left) + 'px',
24910
            top: Math.round(top) + 'px'
24911
          };
24912
          const widthProperties = optToolbarWidth.map(toolbarWidth => {
24913
            const scroll = get$b();
24914
            const minimumToolbarWidth = 150;
24915
            const availableWidth = window.innerWidth - (left - scroll.left);
24916
            const width = Math.max(Math.min(toolbarWidth, availableWidth), minimumToolbarWidth);
24917
            return { width: width + 'px' };
24918
          }).getOr({});
24919
          setAll(mainUi.outerContainer.element, {
24920
            ...baseProperties,
24921
            ...widthProperties
24922
          });
24923
        });
24924
      };
24925
      const getOffsetParent$1 = (editor, element) => isSplitUiMode(editor) ? getOffsetParent(element) : Optional.none();
24926
      const repositionPopups$1 = () => {
24927
        each$1(uiMotherships, m => {
24928
          m.broadcastOn([repositionPopups()], {});
24929
        });
24930
      };
24931
      const restoreAndGetCompleteOuterContainerWidth = () => {
24932
        if (!useFixedToolbarContainer) {
24933
          const toolbarCurrentRightsidePosition = absolute$3(mainUi.outerContainer.element).left + getOuter$1(mainUi.outerContainer.element);
24934
          if (toolbarCurrentRightsidePosition >= window.innerWidth - maximumDistanceToEdge || getRaw(mainUi.outerContainer.element, 'width').isSome()) {
24935
            set$8(mainUi.outerContainer.element, 'position', 'absolute');
24936
            set$8(mainUi.outerContainer.element, 'left', '0px');
24937
            remove$6(mainUi.outerContainer.element, 'width');
24938
            const w = getOuter$1(mainUi.outerContainer.element);
24939
            return Optional.some(w);
24940
          } else {
24941
            return Optional.none();
24942
          }
24943
        } else {
24944
          return Optional.none();
24945
        }
24946
      };
24947
      const update = stickyAction => {
24948
        if (!isVisible()) {
24949
          return;
24950
        }
24951
        if (!useFixedToolbarContainer) {
24952
          updateChromeWidth();
24953
        }
24954
        const optToolbarWidth = useFixedToolbarContainer ? Optional.none() : restoreAndGetCompleteOuterContainerWidth();
24955
        if (isSplitToolbar) {
24956
          OuterContainer.refreshToolbar(mainUi.outerContainer);
24957
        }
24958
        if (!useFixedToolbarContainer) {
24959
          updateChromePosition(optToolbarWidth);
24960
        }
24961
        if (isSticky) {
24962
          floatContainer.on(stickyAction);
24963
        }
24964
        repositionPopups$1();
24965
      };
24966
      const doUpdateMode = () => {
24967
        if (useFixedToolbarContainer || !isSticky || !isVisible()) {
24968
          return false;
24969
        }
24970
        return floatContainer.get().exists(fc => {
24971
          const currentMode = headerBackstage.getDockingMode();
24972
          const newMode = calcMode(fc);
24973
          if (newMode !== currentMode) {
24974
            setupMode(newMode);
24975
            return true;
24976
          } else {
24977
            return false;
24978
          }
24979
        });
24980
      };
24981
      const show = () => {
24982
        visible.set(true);
24983
        set$8(mainUi.outerContainer.element, 'display', 'flex');
24984
        DOM.addClass(editor.getBody(), 'mce-edit-focus');
24985
        each$1(uiMotherships, m => {
24986
          remove$6(m.element, 'display');
24987
        });
24988
        doUpdateMode();
24989
        if (isSplitUiMode(editor)) {
24990
          update(elem => Docking.isDocked(elem) ? Docking.reset(elem) : Docking.refresh(elem));
24991
        } else {
24992
          update(Docking.refresh);
24993
        }
24994
      };
24995
      const hide = () => {
24996
        visible.set(false);
24997
        set$8(mainUi.outerContainer.element, 'display', 'none');
24998
        DOM.removeClass(editor.getBody(), 'mce-edit-focus');
24999
        each$1(uiMotherships, m => {
25000
          set$8(m.element, 'display', 'none');
25001
        });
25002
      };
25003
      const updateMode = () => {
25004
        const changedMode = doUpdateMode();
25005
        if (changedMode) {
25006
          update(Docking.reset);
25007
        }
25008
      };
25009
      return {
25010
        isVisible,
25011
        isPositionedAtTop,
25012
        show,
25013
        hide,
25014
        update,
25015
        updateMode,
25016
        repositionPopups: repositionPopups$1
25017
      };
25018
    };
25019
 
25020
    const getTargetPosAndBounds = (targetElm, isToolbarTop) => {
25021
      const bounds = box$1(targetElm);
25022
      return {
25023
        pos: isToolbarTop ? bounds.y : bounds.bottom,
25024
        bounds
25025
      };
25026
    };
25027
    const setupEvents = (editor, targetElm, ui, toolbarPersist) => {
25028
      const prevPosAndBounds = Cell(getTargetPosAndBounds(targetElm, ui.isPositionedAtTop()));
25029
      const resizeContent = e => {
25030
        const {pos, bounds} = getTargetPosAndBounds(targetElm, ui.isPositionedAtTop());
25031
        const {
25032
          pos: prevPos,
25033
          bounds: prevBounds
25034
        } = prevPosAndBounds.get();
25035
        const hasResized = bounds.height !== prevBounds.height || bounds.width !== prevBounds.width;
25036
        prevPosAndBounds.set({
25037
          pos,
25038
          bounds
25039
        });
25040
        if (hasResized) {
25041
          fireResizeContent(editor, e);
25042
        }
25043
        if (ui.isVisible()) {
25044
          if (prevPos !== pos) {
25045
            ui.update(Docking.reset);
25046
          } else if (hasResized) {
25047
            ui.updateMode();
25048
            ui.repositionPopups();
25049
          }
25050
        }
25051
      };
25052
      if (!toolbarPersist) {
25053
        editor.on('activate', ui.show);
25054
        editor.on('deactivate', ui.hide);
25055
      }
25056
      editor.on('SkinLoaded ResizeWindow', () => ui.update(Docking.reset));
25057
      editor.on('NodeChange keydown', e => {
25058
        requestAnimationFrame(() => resizeContent(e));
25059
      });
25060
      let lastScrollX = 0;
25061
      const updateUi = last(() => ui.update(Docking.refresh), 33);
25062
      editor.on('ScrollWindow', () => {
25063
        const newScrollX = get$b().left;
25064
        if (newScrollX !== lastScrollX) {
25065
          lastScrollX = newScrollX;
25066
          updateUi.throttle();
25067
        }
25068
        ui.updateMode();
25069
      });
25070
      if (isSplitUiMode(editor)) {
25071
        editor.on('ElementScroll', _args => {
25072
          ui.update(Docking.refresh);
25073
        });
25074
      }
25075
      const elementLoad = unbindable();
25076
      elementLoad.set(capture(SugarElement.fromDom(editor.getBody()), 'load', e => resizeContent(e.raw)));
25077
      editor.on('remove', () => {
25078
        elementLoad.clear();
25079
      });
25080
    };
25081
    const render = (editor, uiRefs, rawUiConfig, backstage, args) => {
25082
      const {mainUi} = uiRefs;
25083
      const floatContainer = value$2();
25084
      const targetElm = SugarElement.fromDom(args.targetNode);
25085
      const ui = InlineHeader(editor, targetElm, uiRefs, backstage, floatContainer);
25086
      const toolbarPersist = isToolbarPersist(editor);
25087
      inline(editor);
25088
      const render = () => {
25089
        if (floatContainer.isSet()) {
25090
          ui.show();
25091
          return;
25092
        }
25093
        floatContainer.set(OuterContainer.getHeader(mainUi.outerContainer).getOrDie());
25094
        const uiContainer = getUiContainer(editor);
25095
        if (isSplitUiMode(editor)) {
25096
          attachSystemAfter(targetElm, mainUi.mothership);
25097
          attachSystemAfter(targetElm, uiRefs.popupUi.mothership);
25098
        } else {
25099
          attachSystem(uiContainer, mainUi.mothership);
25100
        }
25101
        attachSystem(uiContainer, uiRefs.dialogUi.mothership);
25102
        setToolbar(editor, uiRefs, rawUiConfig, backstage);
25103
        OuterContainer.setMenubar(mainUi.outerContainer, identifyMenus(editor, rawUiConfig));
25104
        ui.show();
25105
        setupEvents(editor, targetElm, ui, toolbarPersist);
25106
        editor.nodeChanged();
25107
      };
25108
      editor.on('show', render);
25109
      editor.on('hide', ui.hide);
25110
      if (!toolbarPersist) {
25111
        editor.on('focus', render);
25112
        editor.on('blur', ui.hide);
25113
      }
25114
      editor.on('init', () => {
25115
        if (editor.hasFocus() || toolbarPersist) {
25116
          render();
25117
        }
25118
      });
25119
      setupReadonlyModeSwitch(editor, uiRefs);
25120
      const api = {
25121
        show: render,
25122
        hide: ui.hide,
25123
        setEnabled: state => {
25124
          broadcastReadonly(uiRefs, !state);
25125
        },
25126
        isEnabled: () => !Disabling.isDisabled(mainUi.outerContainer)
25127
      };
25128
      return {
25129
        editorContainer: mainUi.outerContainer.element.dom,
25130
        api
25131
      };
25132
    };
25133
 
25134
    var Inline = /*#__PURE__*/Object.freeze({
25135
        __proto__: null,
25136
        render: render
25137
    });
25138
 
25139
    const LazyUiReferences = () => {
25140
      const dialogUi = value$2();
25141
      const popupUi = value$2();
25142
      const mainUi = value$2();
25143
      const lazyGetInOuterOrDie = (label, f) => () => mainUi.get().bind(oc => f(oc.outerContainer)).getOrDie(`Could not find ${ label } element in OuterContainer`);
25144
      const getUiMotherships = () => {
25145
        const optDialogMothership = dialogUi.get().map(ui => ui.mothership);
25146
        const optPopupMothership = popupUi.get().map(ui => ui.mothership);
25147
        return optDialogMothership.fold(() => optPopupMothership.toArray(), dm => optPopupMothership.fold(() => [dm], pm => eq(dm.element, pm.element) ? [dm] : [
25148
          dm,
25149
          pm
25150
        ]));
25151
      };
25152
      return {
25153
        dialogUi,
25154
        popupUi,
25155
        mainUi,
25156
        getUiMotherships,
25157
        lazyGetInOuterOrDie
25158
      };
25159
    };
25160
 
25161
    const showContextToolbarEvent = 'contexttoolbar-show';
25162
    const hideContextToolbarEvent = 'contexttoolbar-hide';
25163
 
25164
    const getFormApi = input => ({
25165
      hide: () => emit(input, sandboxClose()),
25166
      getValue: () => Representing.getValue(input)
25167
    });
25168
    const runOnExecute = (memInput, original) => run$1(internalToolbarButtonExecute, (comp, se) => {
25169
      const input = memInput.get(comp);
25170
      const formApi = getFormApi(input);
25171
      original.onAction(formApi, se.event.buttonApi);
25172
    });
25173
    const renderContextButton = (memInput, button, providers) => {
25174
      const {primary, ...rest} = button.original;
25175
      const bridged = getOrDie(createToolbarButton({
25176
        ...rest,
25177
        type: 'button',
25178
        onAction: noop
25179
      }));
25180
      return renderToolbarButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
25181
    };
25182
    const renderContextToggleButton = (memInput, button, providers) => {
25183
      const {primary, ...rest} = button.original;
25184
      const bridged = getOrDie(createToggleButton({
25185
        ...rest,
25186
        type: 'togglebutton',
25187
        onAction: noop
25188
      }));
25189
      return renderToolbarToggleButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
25190
    };
25191
    const isToggleButton = button => button.type === 'contextformtogglebutton';
25192
    const generateOne = (memInput, button, providersBackstage) => {
25193
      if (isToggleButton(button)) {
25194
        return renderContextToggleButton(memInput, button, providersBackstage);
25195
      } else {
25196
        return renderContextButton(memInput, button, providersBackstage);
25197
      }
25198
    };
25199
    const generate = (memInput, buttons, providersBackstage) => {
25200
      const mementos = map$2(buttons, button => record(generateOne(memInput, button, providersBackstage)));
25201
      const asSpecs = () => map$2(mementos, mem => mem.asSpec());
25202
      const findPrimary = compInSystem => findMap(buttons, (button, i) => {
25203
        if (button.primary) {
25204
          return Optional.from(mementos[i]).bind(mem => mem.getOpt(compInSystem)).filter(not(Disabling.isDisabled));
25205
        } else {
25206
          return Optional.none();
25207
        }
25208
      });
25209
      return {
25210
        asSpecs,
25211
        findPrimary
25212
      };
25213
    };
25214
 
25215
    const buildInitGroups = (ctx, providers) => {
25216
      const inputAttributes = ctx.label.fold(() => ({}), label => ({ 'aria-label': label }));
25217
      const memInput = record(Input.sketch({
25218
        inputClasses: [
25219
          'tox-toolbar-textfield',
25220
          'tox-toolbar-nav-js'
25221
        ],
25222
        data: ctx.initValue(),
25223
        inputAttributes,
25224
        selectOnFocus: true,
25225
        inputBehaviours: derive$1([Keying.config({
25226
            mode: 'special',
25227
            onEnter: input => commands.findPrimary(input).map(primary => {
25228
              emitExecute(primary);
25229
              return true;
25230
            }),
25231
            onLeft: (comp, se) => {
25232
              se.cut();
25233
              return Optional.none();
25234
            },
25235
            onRight: (comp, se) => {
25236
              se.cut();
25237
              return Optional.none();
25238
            }
25239
          })])
25240
      }));
25241
      const commands = generate(memInput, ctx.commands, providers);
25242
      return [
25243
        {
25244
          title: Optional.none(),
25245
          items: [memInput.asSpec()]
25246
        },
25247
        {
25248
          title: Optional.none(),
25249
          items: commands.asSpecs()
25250
        }
25251
      ];
25252
    };
25253
    const renderContextForm = (toolbarType, ctx, providers) => renderToolbar({
25254
      type: toolbarType,
25255
      uid: generate$6('context-toolbar'),
25256
      initGroups: buildInitGroups(ctx, providers),
25257
      onEscape: Optional.none,
25258
      cyclicKeying: true,
25259
      providers
25260
    });
25261
    const ContextForm = {
25262
      renderContextForm,
25263
      buildInitGroups
25264
    };
25265
 
25266
    const isVerticalOverlap = (a, b, threshold) => b.bottom - a.y >= threshold && a.bottom - b.y >= threshold;
25267
    const getRangeRect = rng => {
25268
      const rect = rng.getBoundingClientRect();
25269
      if (rect.height <= 0 && rect.width <= 0) {
25270
        const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset).element;
25271
        const elm = isText(leaf$1) ? parent(leaf$1) : Optional.some(leaf$1);
25272
        return elm.filter(isElement$1).map(e => e.dom.getBoundingClientRect()).getOr(rect);
25273
      } else {
25274
        return rect;
25275
      }
25276
    };
25277
    const getSelectionBounds = editor => {
25278
      const rng = editor.selection.getRng();
25279
      const rect = getRangeRect(rng);
25280
      if (editor.inline) {
25281
        const scroll = get$b();
25282
        return bounds(scroll.left + rect.left, scroll.top + rect.top, rect.width, rect.height);
25283
      } else {
25284
        const bodyPos = absolute$2(SugarElement.fromDom(editor.getBody()));
25285
        return bounds(bodyPos.x + rect.left, bodyPos.y + rect.top, rect.width, rect.height);
25286
      }
25287
    };
25288
    const getAnchorElementBounds = (editor, lastElement) => lastElement.filter(elem => inBody(elem) && isHTMLElement(elem)).map(absolute$2).getOrThunk(() => getSelectionBounds(editor));
25289
    const getHorizontalBounds = (contentAreaBox, viewportBounds, margin) => {
25290
      const x = Math.max(contentAreaBox.x + margin, viewportBounds.x);
25291
      const right = Math.min(contentAreaBox.right - margin, viewportBounds.right);
25292
      return {
25293
        x,
25294
        width: right - x
25295
      };
25296
    };
25297
    const getVerticalBounds = (editor, contentAreaBox, viewportBounds, isToolbarLocationTop, toolbarType, margin) => {
25298
      const container = SugarElement.fromDom(editor.getContainer());
25299
      const header = descendant(container, '.tox-editor-header').getOr(container);
25300
      const headerBox = box$1(header);
25301
      const isToolbarBelowContentArea = headerBox.y >= contentAreaBox.bottom;
25302
      const isToolbarAbove = isToolbarLocationTop && !isToolbarBelowContentArea;
25303
      if (editor.inline && isToolbarAbove) {
25304
        return {
25305
          y: Math.max(headerBox.bottom + margin, viewportBounds.y),
25306
          bottom: viewportBounds.bottom
25307
        };
25308
      }
25309
      if (editor.inline && !isToolbarAbove) {
25310
        return {
25311
          y: viewportBounds.y,
25312
          bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
25313
        };
25314
      }
25315
      const containerBounds = toolbarType === 'line' ? box$1(container) : contentAreaBox;
25316
      if (isToolbarAbove) {
25317
        return {
25318
          y: Math.max(headerBox.bottom + margin, viewportBounds.y),
25319
          bottom: Math.min(containerBounds.bottom - margin, viewportBounds.bottom)
25320
        };
25321
      }
25322
      return {
25323
        y: Math.max(containerBounds.y + margin, viewportBounds.y),
25324
        bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
25325
      };
25326
    };
25327
    const getContextToolbarBounds = (editor, sharedBackstage, toolbarType, margin = 0) => {
25328
      const viewportBounds = getBounds$3(window);
25329
      const contentAreaBox = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
25330
      const toolbarOrMenubarEnabled = isMenubarEnabled(editor) || isToolbarEnabled(editor) || isMultipleToolbars(editor);
25331
      const {x, width} = getHorizontalBounds(contentAreaBox, viewportBounds, margin);
25332
      if (editor.inline && !toolbarOrMenubarEnabled) {
25333
        return bounds(x, viewportBounds.y, width, viewportBounds.height);
25334
      } else {
25335
        const isToolbarTop = sharedBackstage.header.isPositionedAtTop();
25336
        const {y, bottom} = getVerticalBounds(editor, contentAreaBox, viewportBounds, isToolbarTop, toolbarType, margin);
25337
        return bounds(x, y, width, bottom - y);
25338
      }
25339
    };
25340
 
25341
    const bubbleSize$1 = 12;
25342
    const bubbleAlignments$1 = {
25343
      valignCentre: [],
25344
      alignCentre: [],
25345
      alignLeft: ['tox-pop--align-left'],
25346
      alignRight: ['tox-pop--align-right'],
25347
      right: ['tox-pop--right'],
25348
      left: ['tox-pop--left'],
25349
      bottom: ['tox-pop--bottom'],
25350
      top: ['tox-pop--top'],
25351
      inset: ['tox-pop--inset']
25352
    };
25353
    const anchorOverrides = {
25354
      maxHeightFunction: expandable$1(),
25355
      maxWidthFunction: expandable()
25356
    };
25357
    const isEntireElementSelected = (editor, elem) => {
25358
      const rng = editor.selection.getRng();
25359
      const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset);
25360
      return rng.startContainer === rng.endContainer && rng.startOffset === rng.endOffset - 1 && eq(leaf$1.element, elem);
25361
    };
25362
    const preservePosition = (elem, position, f) => {
25363
      const currentPosition = getRaw(elem, 'position');
25364
      set$8(elem, 'position', position);
25365
      const result = f(elem);
25366
      currentPosition.each(pos => set$8(elem, 'position', pos));
25367
      return result;
25368
    };
25369
    const shouldUseInsetLayouts = position => position === 'node';
25370
    const determineInsetLayout = (editor, contextbar, elem, data, bounds) => {
25371
      const selectionBounds = getSelectionBounds(editor);
25372
      const isSameAnchorElement = data.lastElement().exists(prev => eq(elem, prev));
25373
      if (isEntireElementSelected(editor, elem)) {
25374
        return isSameAnchorElement ? preserve : north;
25375
      } else if (isSameAnchorElement) {
25376
        return preservePosition(contextbar, data.getMode(), () => {
25377
          const isOverlapping = isVerticalOverlap(selectionBounds, box$1(contextbar), -20);
25378
          return isOverlapping && !data.isReposition() ? flip : preserve;
25379
        });
25380
      } else {
25381
        const yBounds = data.getMode() === 'fixed' ? bounds.y + get$b().top : bounds.y;
25382
        const contextbarHeight = get$d(contextbar) + bubbleSize$1;
25383
        return yBounds + contextbarHeight <= selectionBounds.y ? north : south;
25384
      }
25385
    };
25386
    const getAnchorSpec$2 = (editor, mobile, data, position) => {
25387
      const smartInsetLayout = elem => (anchor, element, bubbles, placee, bounds) => {
25388
        const layout = determineInsetLayout(editor, placee, elem, data, bounds);
25389
        const newAnchor = {
25390
          ...anchor,
25391
          y: bounds.y,
25392
          height: bounds.height
25393
        };
25394
        return {
25395
          ...layout(newAnchor, element, bubbles, placee, bounds),
25396
          alwaysFit: true
25397
        };
25398
      };
25399
      const getInsetLayouts = elem => shouldUseInsetLayouts(position) ? [smartInsetLayout(elem)] : [];
25400
      const desktopAnchorSpecLayouts = {
25401
        onLtr: elem => [
25402
          north$2,
25403
          south$2,
25404
          northeast$2,
25405
          southeast$2,
25406
          northwest$2,
25407
          southwest$2
25408
        ].concat(getInsetLayouts(elem)),
25409
        onRtl: elem => [
25410
          north$2,
25411
          south$2,
25412
          northwest$2,
25413
          southwest$2,
25414
          northeast$2,
25415
          southeast$2
25416
        ].concat(getInsetLayouts(elem))
25417
      };
25418
      const mobileAnchorSpecLayouts = {
25419
        onLtr: elem => [
25420
          south$2,
25421
          southeast$2,
25422
          southwest$2,
25423
          northeast$2,
25424
          northwest$2,
25425
          north$2
25426
        ].concat(getInsetLayouts(elem)),
25427
        onRtl: elem => [
25428
          south$2,
25429
          southwest$2,
25430
          southeast$2,
25431
          northwest$2,
25432
          northeast$2,
25433
          north$2
25434
        ].concat(getInsetLayouts(elem))
25435
      };
25436
      return mobile ? mobileAnchorSpecLayouts : desktopAnchorSpecLayouts;
25437
    };
25438
    const getAnchorLayout = (editor, position, isTouch, data) => {
25439
      if (position === 'line') {
25440
        return {
25441
          bubble: nu$5(bubbleSize$1, 0, bubbleAlignments$1),
25442
          layouts: {
25443
            onLtr: () => [east$2],
25444
            onRtl: () => [west$2]
25445
          },
25446
          overrides: anchorOverrides
25447
        };
25448
      } else {
25449
        return {
25450
          bubble: nu$5(0, bubbleSize$1, bubbleAlignments$1, 1 / bubbleSize$1),
25451
          layouts: getAnchorSpec$2(editor, isTouch, data, position),
25452
          overrides: anchorOverrides
25453
        };
25454
      }
25455
    };
25456
 
25457
    const matchTargetWith = (elem, candidates) => {
25458
      const ctxs = filter$2(candidates, toolbarApi => toolbarApi.predicate(elem.dom));
25459
      const {pass, fail} = partition$3(ctxs, t => t.type === 'contexttoolbar');
25460
      return {
25461
        contextToolbars: pass,
25462
        contextForms: fail
25463
      };
25464
    };
25465
    const filterByPositionForStartNode = toolbars => {
25466
      if (toolbars.length <= 1) {
25467
        return toolbars;
25468
      } else {
25469
        const doesPositionExist = value => exists(toolbars, t => t.position === value);
25470
        const filterToolbarsByPosition = value => filter$2(toolbars, t => t.position === value);
25471
        const hasSelectionToolbars = doesPositionExist('selection');
25472
        const hasNodeToolbars = doesPositionExist('node');
25473
        if (hasSelectionToolbars || hasNodeToolbars) {
25474
          if (hasNodeToolbars && hasSelectionToolbars) {
25475
            const nodeToolbars = filterToolbarsByPosition('node');
25476
            const selectionToolbars = map$2(filterToolbarsByPosition('selection'), t => ({
25477
              ...t,
25478
              position: 'node'
25479
            }));
25480
            return nodeToolbars.concat(selectionToolbars);
25481
          } else {
25482
            return hasSelectionToolbars ? filterToolbarsByPosition('selection') : filterToolbarsByPosition('node');
25483
          }
25484
        } else {
25485
          return filterToolbarsByPosition('line');
25486
        }
25487
      }
25488
    };
25489
    const filterByPositionForAncestorNode = toolbars => {
25490
      if (toolbars.length <= 1) {
25491
        return toolbars;
25492
      } else {
25493
        const findPosition = value => find$5(toolbars, t => t.position === value);
25494
        const basePosition = findPosition('selection').orThunk(() => findPosition('node')).orThunk(() => findPosition('line')).map(t => t.position);
25495
        return basePosition.fold(() => [], pos => filter$2(toolbars, t => t.position === pos));
25496
      }
25497
    };
25498
    const matchStartNode = (elem, nodeCandidates, editorCandidates) => {
25499
      const nodeMatches = matchTargetWith(elem, nodeCandidates);
25500
      if (nodeMatches.contextForms.length > 0) {
25501
        return Optional.some({
25502
          elem,
25503
          toolbars: [nodeMatches.contextForms[0]]
25504
        });
25505
      } else {
25506
        const editorMatches = matchTargetWith(elem, editorCandidates);
25507
        if (editorMatches.contextForms.length > 0) {
25508
          return Optional.some({
25509
            elem,
25510
            toolbars: [editorMatches.contextForms[0]]
25511
          });
25512
        } else if (nodeMatches.contextToolbars.length > 0 || editorMatches.contextToolbars.length > 0) {
25513
          const toolbars = filterByPositionForStartNode(nodeMatches.contextToolbars.concat(editorMatches.contextToolbars));
25514
          return Optional.some({
25515
            elem,
25516
            toolbars
25517
          });
25518
        } else {
25519
          return Optional.none();
25520
        }
25521
      }
25522
    };
25523
    const matchAncestor = (isRoot, startNode, scopes) => {
25524
      if (isRoot(startNode)) {
25525
        return Optional.none();
25526
      } else {
25527
        return ancestor$2(startNode, ancestorElem => {
25528
          if (isElement$1(ancestorElem)) {
25529
            const {contextToolbars, contextForms} = matchTargetWith(ancestorElem, scopes.inNodeScope);
25530
            const toolbars = contextForms.length > 0 ? contextForms : filterByPositionForAncestorNode(contextToolbars);
25531
            return toolbars.length > 0 ? Optional.some({
25532
              elem: ancestorElem,
25533
              toolbars
25534
            }) : Optional.none();
25535
          } else {
25536
            return Optional.none();
25537
          }
25538
        }, isRoot);
25539
      }
25540
    };
25541
    const lookup$1 = (scopes, editor) => {
25542
      const rootElem = SugarElement.fromDom(editor.getBody());
25543
      const isRoot = elem => eq(elem, rootElem);
25544
      const isOutsideRoot = startNode => !isRoot(startNode) && !contains(rootElem, startNode);
25545
      const startNode = SugarElement.fromDom(editor.selection.getNode());
25546
      if (isOutsideRoot(startNode)) {
25547
        return Optional.none();
25548
      }
25549
      return matchStartNode(startNode, scopes.inNodeScope, scopes.inEditorScope).orThunk(() => matchAncestor(isRoot, startNode, scopes));
25550
    };
25551
 
25552
    const categorise = (contextToolbars, navigate) => {
25553
      const forms = {};
25554
      const inNodeScope = [];
25555
      const inEditorScope = [];
25556
      const formNavigators = {};
25557
      const lookupTable = {};
25558
      const registerForm = (key, toolbarSpec) => {
25559
        const contextForm = getOrDie(createContextForm(toolbarSpec));
25560
        forms[key] = contextForm;
25561
        contextForm.launch.map(launch => {
25562
          formNavigators['form:' + key + ''] = {
25563
            ...toolbarSpec.launch,
25564
            type: launch.type === 'contextformtogglebutton' ? 'togglebutton' : 'button',
25565
            onAction: () => {
25566
              navigate(contextForm);
25567
            }
25568
          };
25569
        });
25570
        if (contextForm.scope === 'editor') {
25571
          inEditorScope.push(contextForm);
25572
        } else {
25573
          inNodeScope.push(contextForm);
25574
        }
25575
        lookupTable[key] = contextForm;
25576
      };
25577
      const registerToolbar = (key, toolbarSpec) => {
25578
        createContextToolbar(toolbarSpec).each(contextToolbar => {
25579
          if (toolbarSpec.scope === 'editor') {
25580
            inEditorScope.push(contextToolbar);
25581
          } else {
25582
            inNodeScope.push(contextToolbar);
25583
          }
25584
          lookupTable[key] = contextToolbar;
25585
        });
25586
      };
25587
      const keys$1 = keys(contextToolbars);
25588
      each$1(keys$1, key => {
25589
        const toolbarApi = contextToolbars[key];
25590
        if (toolbarApi.type === 'contextform') {
25591
          registerForm(key, toolbarApi);
25592
        } else if (toolbarApi.type === 'contexttoolbar') {
25593
          registerToolbar(key, toolbarApi);
25594
        }
25595
      });
25596
      return {
25597
        forms,
25598
        inNodeScope,
25599
        inEditorScope,
25600
        lookupTable,
25601
        formNavigators
25602
      };
25603
    };
25604
 
25605
    const forwardSlideEvent = generate$6('forward-slide');
25606
    const backSlideEvent = generate$6('backward-slide');
25607
    const changeSlideEvent = generate$6('change-slide-event');
25608
    const resizingClass = 'tox-pop--resizing';
25609
    const renderContextToolbar = spec => {
25610
      const stack = Cell([]);
25611
      return InlineView.sketch({
25612
        dom: {
25613
          tag: 'div',
25614
          classes: ['tox-pop']
25615
        },
25616
        fireDismissalEventInstead: { event: 'doNotDismissYet' },
25617
        onShow: comp => {
25618
          stack.set([]);
25619
          InlineView.getContent(comp).each(c => {
25620
            remove$6(c.element, 'visibility');
25621
          });
25622
          remove$2(comp.element, resizingClass);
25623
          remove$6(comp.element, 'width');
25624
        },
25625
        inlineBehaviours: derive$1([
25626
          config('context-toolbar-events', [
25627
            runOnSource(transitionend(), (comp, se) => {
25628
              if (se.event.raw.propertyName === 'width') {
25629
                remove$2(comp.element, resizingClass);
25630
                remove$6(comp.element, 'width');
25631
              }
25632
            }),
25633
            run$1(changeSlideEvent, (comp, se) => {
25634
              const elem = comp.element;
25635
              remove$6(elem, 'width');
25636
              const currentWidth = get$c(elem);
25637
              InlineView.setContent(comp, se.event.contents);
25638
              add$2(elem, resizingClass);
25639
              const newWidth = get$c(elem);
25640
              set$8(elem, 'width', currentWidth + 'px');
25641
              InlineView.getContent(comp).each(newContents => {
25642
                se.event.focus.bind(f => {
25643
                  focus$3(f);
25644
                  return search(elem);
25645
                }).orThunk(() => {
25646
                  Keying.focusIn(newContents);
25647
                  return active$1(getRootNode(elem));
25648
                });
25649
              });
25650
              setTimeout(() => {
25651
                set$8(comp.element, 'width', newWidth + 'px');
25652
              }, 0);
25653
            }),
25654
            run$1(forwardSlideEvent, (comp, se) => {
25655
              InlineView.getContent(comp).each(oldContents => {
25656
                stack.set(stack.get().concat([{
25657
                    bar: oldContents,
25658
                    focus: active$1(getRootNode(comp.element))
25659
                  }]));
25660
              });
25661
              emitWith(comp, changeSlideEvent, {
25662
                contents: se.event.forwardContents,
25663
                focus: Optional.none()
25664
              });
25665
            }),
25666
            run$1(backSlideEvent, (comp, _se) => {
25667
              last$1(stack.get()).each(last => {
25668
                stack.set(stack.get().slice(0, stack.get().length - 1));
25669
                emitWith(comp, changeSlideEvent, {
25670
                  contents: premade(last.bar),
25671
                  focus: last.focus
25672
                });
25673
              });
25674
            })
25675
          ]),
25676
          Keying.config({
25677
            mode: 'special',
25678
            onEscape: comp => last$1(stack.get()).fold(() => spec.onEscape(), _ => {
25679
              emit(comp, backSlideEvent);
25680
              return Optional.some(true);
25681
            })
25682
          })
25683
        ]),
25684
        lazySink: () => Result.value(spec.sink)
25685
      });
25686
    };
25687
 
25688
    const transitionClass = 'tox-pop--transition';
25689
    const register$9 = (editor, registryContextToolbars, sink, extras) => {
25690
      const backstage = extras.backstage;
25691
      const sharedBackstage = backstage.shared;
25692
      const isTouch = detect$2().deviceType.isTouch;
25693
      const lastElement = value$2();
25694
      const lastTrigger = value$2();
25695
      const lastContextPosition = value$2();
25696
      const contextbar = build$1(renderContextToolbar({
25697
        sink,
25698
        onEscape: () => {
25699
          editor.focus();
25700
          return Optional.some(true);
25701
        }
25702
      }));
25703
      const getBounds = () => {
25704
        const position = lastContextPosition.get().getOr('node');
25705
        const margin = shouldUseInsetLayouts(position) ? 1 : 0;
25706
        return getContextToolbarBounds(editor, sharedBackstage, position, margin);
25707
      };
25708
      const canLaunchToolbar = () => {
25709
        return !editor.removed && !(isTouch() && backstage.isContextMenuOpen());
25710
      };
25711
      const isSameLaunchElement = elem => is$1(lift2(elem, lastElement.get(), eq), true);
25712
      const shouldContextToolbarHide = () => {
25713
        if (!canLaunchToolbar()) {
25714
          return true;
25715
        } else {
25716
          const contextToolbarBounds = getBounds();
25717
          const anchorBounds = is$1(lastContextPosition.get(), 'node') ? getAnchorElementBounds(editor, lastElement.get()) : getSelectionBounds(editor);
25718
          return contextToolbarBounds.height <= 0 || !isVerticalOverlap(anchorBounds, contextToolbarBounds, 0.01);
25719
        }
25720
      };
25721
      const close = () => {
25722
        lastElement.clear();
25723
        lastTrigger.clear();
25724
        lastContextPosition.clear();
25725
        InlineView.hide(contextbar);
25726
      };
25727
      const hideOrRepositionIfNecessary = () => {
25728
        if (InlineView.isOpen(contextbar)) {
25729
          const contextBarEle = contextbar.element;
25730
          remove$6(contextBarEle, 'display');
25731
          if (shouldContextToolbarHide()) {
25732
            set$8(contextBarEle, 'display', 'none');
25733
          } else {
25734
            lastTrigger.set(0);
25735
            InlineView.reposition(contextbar);
25736
          }
25737
        }
25738
      };
25739
      const wrapInPopDialog = toolbarSpec => ({
25740
        dom: {
25741
          tag: 'div',
25742
          classes: ['tox-pop__dialog']
25743
        },
25744
        components: [toolbarSpec],
25745
        behaviours: derive$1([
25746
          Keying.config({ mode: 'acyclic' }),
25747
          config('pop-dialog-wrap-events', [
25748
            runOnAttached(comp => {
25749
              editor.shortcuts.add('ctrl+F9', 'focus statusbar', () => Keying.focusIn(comp));
25750
            }),
25751
            runOnDetached(_comp => {
25752
              editor.shortcuts.remove('ctrl+F9');
25753
            })
25754
          ])
25755
        ])
25756
      });
25757
      const getScopes = cached(() => categorise(registryContextToolbars, toolbarApi => {
25758
        const alloySpec = buildToolbar([toolbarApi]);
25759
        emitWith(contextbar, forwardSlideEvent, { forwardContents: wrapInPopDialog(alloySpec) });
25760
      }));
25761
      const buildContextToolbarGroups = (allButtons, ctx) => identifyButtons(editor, {
25762
        buttons: allButtons,
25763
        toolbar: ctx.items,
25764
        allowToolbarGroups: false
25765
      }, extras.backstage, Optional.some(['form:']));
25766
      const buildContextFormGroups = (ctx, providers) => ContextForm.buildInitGroups(ctx, providers);
25767
      const buildToolbar = toolbars => {
25768
        const {buttons} = editor.ui.registry.getAll();
25769
        const scopes = getScopes();
25770
        const allButtons = {
25771
          ...buttons,
25772
          ...scopes.formNavigators
25773
        };
25774
        const toolbarType = getToolbarMode(editor) === ToolbarMode$1.scrolling ? ToolbarMode$1.scrolling : ToolbarMode$1.default;
25775
        const initGroups = flatten(map$2(toolbars, ctx => ctx.type === 'contexttoolbar' ? buildContextToolbarGroups(allButtons, ctx) : buildContextFormGroups(ctx, sharedBackstage.providers)));
25776
        return renderToolbar({
25777
          type: toolbarType,
25778
          uid: generate$6('context-toolbar'),
25779
          initGroups,
25780
          onEscape: Optional.none,
25781
          cyclicKeying: true,
25782
          providers: sharedBackstage.providers
25783
        });
25784
      };
25785
      const getAnchor = (position, element) => {
25786
        const anchorage = position === 'node' ? sharedBackstage.anchors.node(element) : sharedBackstage.anchors.cursor();
25787
        const anchorLayout = getAnchorLayout(editor, position, isTouch(), {
25788
          lastElement: lastElement.get,
25789
          isReposition: () => is$1(lastTrigger.get(), 0),
25790
          getMode: () => Positioning.getMode(sink)
25791
        });
25792
        return deepMerge(anchorage, anchorLayout);
25793
      };
25794
      const launchContext = (toolbarApi, elem) => {
25795
        launchContextToolbar.cancel();
25796
        if (!canLaunchToolbar()) {
25797
          return;
25798
        }
25799
        const toolbarSpec = buildToolbar(toolbarApi);
25800
        const position = toolbarApi[0].position;
25801
        const anchor = getAnchor(position, elem);
25802
        lastContextPosition.set(position);
25803
        lastTrigger.set(1);
25804
        const contextBarEle = contextbar.element;
25805
        remove$6(contextBarEle, 'display');
25806
        if (!isSameLaunchElement(elem)) {
25807
          remove$2(contextBarEle, transitionClass);
25808
          Positioning.reset(sink, contextbar);
25809
        }
25810
        InlineView.showWithinBounds(contextbar, wrapInPopDialog(toolbarSpec), {
25811
          anchor,
25812
          transition: {
25813
            classes: [transitionClass],
25814
            mode: 'placement'
25815
          }
25816
        }, () => Optional.some(getBounds()));
25817
        elem.fold(lastElement.clear, lastElement.set);
25818
        if (shouldContextToolbarHide()) {
25819
          set$8(contextBarEle, 'display', 'none');
25820
        }
25821
      };
25822
      let isDragging = false;
25823
      const launchContextToolbar = last(() => {
25824
        if (!editor.hasFocus() || editor.removed || isDragging) {
25825
          return;
25826
        }
25827
        if (has(contextbar.element, transitionClass)) {
25828
          launchContextToolbar.throttle();
25829
        } else {
25830
          const scopes = getScopes();
25831
          lookup$1(scopes, editor).fold(close, info => {
25832
            launchContext(info.toolbars, Optional.some(info.elem));
25833
          });
25834
        }
25835
      }, 17);
25836
      editor.on('init', () => {
25837
        editor.on('remove', close);
25838
        editor.on('ScrollContent ScrollWindow ObjectResized ResizeEditor longpress', hideOrRepositionIfNecessary);
25839
        editor.on('click keyup focus SetContent', launchContextToolbar.throttle);
25840
        editor.on(hideContextToolbarEvent, close);
25841
        editor.on(showContextToolbarEvent, e => {
25842
          const scopes = getScopes();
25843
          get$g(scopes.lookupTable, e.toolbarKey).each(ctx => {
25844
            launchContext([ctx], someIf(e.target !== editor, e.target));
25845
            InlineView.getContent(contextbar).each(Keying.focusIn);
25846
          });
25847
        });
25848
        editor.on('focusout', _e => {
25849
          global$9.setEditorTimeout(editor, () => {
25850
            if (search(sink.element).isNone() && search(contextbar.element).isNone()) {
25851
              close();
25852
            }
25853
          }, 0);
25854
        });
25855
        editor.on('SwitchMode', () => {
25856
          if (editor.mode.isReadOnly()) {
25857
            close();
25858
          }
25859
        });
25860
        editor.on('AfterProgressState', event => {
25861
          if (event.state) {
25862
            close();
25863
          } else if (editor.hasFocus()) {
25864
            launchContextToolbar.throttle();
25865
          }
25866
        });
25867
        editor.on('dragstart', () => {
25868
          isDragging = true;
25869
        });
25870
        editor.on('dragend drop', () => {
25871
          isDragging = false;
25872
        });
25873
        editor.on('NodeChange', _e => {
25874
          search(contextbar.element).fold(launchContextToolbar.throttle, noop);
25875
        });
25876
      });
25877
    };
25878
 
25879
    const register$8 = editor => {
25880
      const alignToolbarButtons = [
25881
        {
25882
          name: 'alignleft',
25883
          text: 'Align left',
25884
          cmd: 'JustifyLeft',
25885
          icon: 'align-left'
25886
        },
25887
        {
25888
          name: 'aligncenter',
25889
          text: 'Align center',
25890
          cmd: 'JustifyCenter',
25891
          icon: 'align-center'
25892
        },
25893
        {
25894
          name: 'alignright',
25895
          text: 'Align right',
25896
          cmd: 'JustifyRight',
25897
          icon: 'align-right'
25898
        },
25899
        {
25900
          name: 'alignjustify',
25901
          text: 'Justify',
25902
          cmd: 'JustifyFull',
25903
          icon: 'align-justify'
25904
        }
25905
      ];
25906
      each$1(alignToolbarButtons, item => {
25907
        editor.ui.registry.addToggleButton(item.name, {
25908
          tooltip: item.text,
25909
          icon: item.icon,
25910
          onAction: onActionExecCommand(editor, item.cmd),
25911
          onSetup: onSetupStateToggle(editor, item.name)
25912
        });
25913
      });
25914
      editor.ui.registry.addButton('alignnone', {
25915
        tooltip: 'No alignment',
25916
        icon: 'align-none',
25917
        onSetup: onSetupEditableToggle(editor),
25918
        onAction: onActionExecCommand(editor, 'JustifyNone')
25919
      });
25920
    };
25921
 
25922
    const registerController = (editor, spec) => {
25923
      const getMenuItems = () => {
25924
        const options = spec.getOptions(editor);
25925
        const initial = spec.getCurrent(editor).map(spec.hash);
25926
        const current = value$2();
25927
        return map$2(options, value => ({
25928
          type: 'togglemenuitem',
25929
          text: spec.display(value),
25930
          onSetup: api => {
25931
            const setActive = active => {
25932
              if (active) {
25933
                current.on(oldApi => oldApi.setActive(false));
25934
                current.set(api);
25935
              }
25936
              api.setActive(active);
25937
            };
25938
            setActive(is$1(initial, spec.hash(value)));
25939
            const unbindWatcher = spec.watcher(editor, value, setActive);
25940
            return () => {
25941
              current.clear();
25942
              unbindWatcher();
25943
            };
25944
          },
25945
          onAction: () => spec.setCurrent(editor, value)
25946
        }));
25947
      };
25948
      editor.ui.registry.addMenuButton(spec.name, {
25949
        tooltip: spec.text,
25950
        icon: spec.icon,
25951
        fetch: callback => callback(getMenuItems()),
25952
        onSetup: spec.onToolbarSetup
25953
      });
25954
      editor.ui.registry.addNestedMenuItem(spec.name, {
25955
        type: 'nestedmenuitem',
25956
        text: spec.text,
25957
        getSubmenuItems: getMenuItems,
25958
        onSetup: spec.onMenuSetup
25959
      });
25960
    };
25961
    const lineHeightSpec = editor => ({
25962
      name: 'lineheight',
25963
      text: 'Line height',
25964
      icon: 'line-height',
25965
      getOptions: getLineHeightFormats,
25966
      hash: input => normalise(input, [
25967
        'fixed',
25968
        'relative',
25969
        'empty'
25970
      ]).getOr(input),
25971
      display: identity,
25972
      watcher: (editor, value, callback) => editor.formatter.formatChanged('lineheight', callback, false, { value }).unbind,
25973
      getCurrent: editor => Optional.from(editor.queryCommandValue('LineHeight')),
25974
      setCurrent: (editor, value) => editor.execCommand('LineHeight', false, value),
25975
      onToolbarSetup: onSetupEditableToggle(editor),
25976
      onMenuSetup: onSetupEditableToggle(editor)
25977
    });
25978
    const languageSpec = editor => {
25979
      const settingsOpt = Optional.from(getContentLanguages(editor));
25980
      return settingsOpt.map(settings => ({
25981
        name: 'language',
25982
        text: 'Language',
25983
        icon: 'language',
25984
        getOptions: constant$1(settings),
25985
        hash: input => isUndefined(input.customCode) ? input.code : `${ input.code }/${ input.customCode }`,
25986
        display: input => input.title,
25987
        watcher: (editor, value, callback) => {
25988
          var _a;
25989
          return editor.formatter.formatChanged('lang', callback, false, {
25990
            value: value.code,
25991
            customValue: (_a = value.customCode) !== null && _a !== void 0 ? _a : null
25992
          }).unbind;
25993
        },
25994
        getCurrent: editor => {
25995
          const node = SugarElement.fromDom(editor.selection.getNode());
25996
          return closest$4(node, n => Optional.some(n).filter(isElement$1).bind(ele => {
25997
            const codeOpt = getOpt(ele, 'lang');
25998
            return codeOpt.map(code => {
25999
              const customCode = getOpt(ele, 'data-mce-lang').getOrUndefined();
26000
              return {
26001
                code,
26002
                customCode,
26003
                title: ''
26004
              };
26005
            });
26006
          }));
26007
        },
26008
        setCurrent: (editor, lang) => editor.execCommand('Lang', false, lang),
26009
        onToolbarSetup: api => {
26010
          const unbinder = unbindable();
26011
          api.setActive(editor.formatter.match('lang', {}, undefined, true));
26012
          unbinder.set(editor.formatter.formatChanged('lang', api.setActive, true));
26013
          return composeUnbinders(unbinder.clear, onSetupEditableToggle(editor)(api));
26014
        },
26015
        onMenuSetup: onSetupEditableToggle(editor)
26016
      }));
26017
    };
26018
    const register$7 = editor => {
26019
      registerController(editor, lineHeightSpec(editor));
26020
      languageSpec(editor).each(spec => registerController(editor, spec));
26021
    };
26022
 
26023
    const register$6 = (editor, backstage) => {
26024
      createAlignMenu(editor, backstage);
26025
      createFontFamilyMenu(editor, backstage);
26026
      createStylesMenu(editor, backstage);
26027
      createBlocksMenu(editor, backstage);
26028
      createFontSizeMenu(editor, backstage);
26029
    };
26030
 
26031
    const onSetupOutdentState = editor => onSetupEvent(editor, 'NodeChange', api => {
26032
      api.setEnabled(editor.queryCommandState('outdent') && editor.selection.isEditable());
26033
    });
26034
    const registerButtons$2 = editor => {
26035
      editor.ui.registry.addButton('outdent', {
26036
        tooltip: 'Decrease indent',
26037
        icon: 'outdent',
26038
        onSetup: onSetupOutdentState(editor),
26039
        onAction: onActionExecCommand(editor, 'outdent')
26040
      });
26041
      editor.ui.registry.addButton('indent', {
26042
        tooltip: 'Increase indent',
26043
        icon: 'indent',
26044
        onSetup: onSetupEditableToggle(editor),
26045
        onAction: onActionExecCommand(editor, 'indent')
26046
      });
26047
    };
26048
    const register$5 = editor => {
26049
      registerButtons$2(editor);
26050
    };
26051
 
26052
    const makeSetupHandler = (editor, pasteAsText) => api => {
26053
      api.setActive(pasteAsText.get());
26054
      const pastePlainTextToggleHandler = e => {
26055
        pasteAsText.set(e.state);
26056
        api.setActive(e.state);
26057
      };
26058
      editor.on('PastePlainTextToggle', pastePlainTextToggleHandler);
26059
      return composeUnbinders(() => editor.off('PastePlainTextToggle', pastePlainTextToggleHandler), onSetupEditableToggle(editor)(api));
26060
    };
26061
    const register$4 = editor => {
26062
      const pasteAsText = Cell(getPasteAsText(editor));
26063
      const onAction = () => editor.execCommand('mceTogglePlainTextPaste');
26064
      editor.ui.registry.addToggleButton('pastetext', {
26065
        active: false,
26066
        icon: 'paste-text',
26067
        tooltip: 'Paste as text',
26068
        onAction,
26069
        onSetup: makeSetupHandler(editor, pasteAsText)
26070
      });
26071
      editor.ui.registry.addToggleMenuItem('pastetext', {
26072
        text: 'Paste as text',
26073
        icon: 'paste-text',
26074
        onAction,
26075
        onSetup: makeSetupHandler(editor, pasteAsText)
26076
      });
26077
    };
26078
 
26079
    const onActionToggleFormat = (editor, fmt) => () => {
26080
      editor.execCommand('mceToggleFormat', false, fmt);
26081
    };
26082
    const registerFormatButtons = editor => {
26083
      global$1.each([
26084
        {
26085
          name: 'bold',
26086
          text: 'Bold',
26087
          icon: 'bold'
26088
        },
26089
        {
26090
          name: 'italic',
26091
          text: 'Italic',
26092
          icon: 'italic'
26093
        },
26094
        {
26095
          name: 'underline',
26096
          text: 'Underline',
26097
          icon: 'underline'
26098
        },
26099
        {
26100
          name: 'strikethrough',
26101
          text: 'Strikethrough',
26102
          icon: 'strike-through'
26103
        },
26104
        {
26105
          name: 'subscript',
26106
          text: 'Subscript',
26107
          icon: 'subscript'
26108
        },
26109
        {
26110
          name: 'superscript',
26111
          text: 'Superscript',
26112
          icon: 'superscript'
26113
        }
26114
      ], (btn, _idx) => {
26115
        editor.ui.registry.addToggleButton(btn.name, {
26116
          tooltip: btn.text,
26117
          icon: btn.icon,
26118
          onSetup: onSetupStateToggle(editor, btn.name),
26119
          onAction: onActionToggleFormat(editor, btn.name)
26120
        });
26121
      });
26122
      for (let i = 1; i <= 6; i++) {
26123
        const name = 'h' + i;
26124
        editor.ui.registry.addToggleButton(name, {
26125
          text: name.toUpperCase(),
26126
          tooltip: 'Heading ' + i,
26127
          onSetup: onSetupStateToggle(editor, name),
26128
          onAction: onActionToggleFormat(editor, name)
26129
        });
26130
      }
26131
    };
26132
    const registerCommandButtons = editor => {
26133
      global$1.each([
26134
        {
26135
          name: 'copy',
26136
          text: 'Copy',
26137
          action: 'Copy',
26138
          icon: 'copy'
26139
        },
26140
        {
26141
          name: 'help',
26142
          text: 'Help',
26143
          action: 'mceHelp',
26144
          icon: 'help'
26145
        },
26146
        {
26147
          name: 'selectall',
26148
          text: 'Select all',
26149
          action: 'SelectAll',
26150
          icon: 'select-all'
26151
        },
26152
        {
26153
          name: 'newdocument',
26154
          text: 'New document',
26155
          action: 'mceNewDocument',
26156
          icon: 'new-document'
26157
        },
26158
        {
26159
          name: 'print',
26160
          text: 'Print',
26161
          action: 'mcePrint',
26162
          icon: 'print'
26163
        }
26164
      ], btn => {
26165
        editor.ui.registry.addButton(btn.name, {
26166
          tooltip: btn.text,
26167
          icon: btn.icon,
26168
          onAction: onActionExecCommand(editor, btn.action)
26169
        });
26170
      });
26171
      global$1.each([
26172
        {
26173
          name: 'cut',
26174
          text: 'Cut',
26175
          action: 'Cut',
26176
          icon: 'cut'
26177
        },
26178
        {
26179
          name: 'paste',
26180
          text: 'Paste',
26181
          action: 'Paste',
26182
          icon: 'paste'
26183
        },
26184
        {
26185
          name: 'removeformat',
26186
          text: 'Clear formatting',
26187
          action: 'RemoveFormat',
26188
          icon: 'remove-formatting'
26189
        },
26190
        {
26191
          name: 'remove',
26192
          text: 'Remove',
26193
          action: 'Delete',
26194
          icon: 'remove'
26195
        },
26196
        {
26197
          name: 'hr',
26198
          text: 'Horizontal line',
26199
          action: 'InsertHorizontalRule',
26200
          icon: 'horizontal-rule'
26201
        }
26202
      ], btn => {
26203
        editor.ui.registry.addButton(btn.name, {
26204
          tooltip: btn.text,
26205
          icon: btn.icon,
26206
          onSetup: onSetupEditableToggle(editor),
26207
          onAction: onActionExecCommand(editor, btn.action)
26208
        });
26209
      });
26210
    };
26211
    const registerCommandToggleButtons = editor => {
26212
      global$1.each([{
26213
          name: 'blockquote',
26214
          text: 'Blockquote',
26215
          action: 'mceBlockQuote',
26216
          icon: 'quote'
26217
        }], btn => {
26218
        editor.ui.registry.addToggleButton(btn.name, {
26219
          tooltip: btn.text,
26220
          icon: btn.icon,
26221
          onAction: onActionExecCommand(editor, btn.action),
26222
          onSetup: onSetupStateToggle(editor, btn.name)
26223
        });
26224
      });
26225
    };
26226
    const registerButtons$1 = editor => {
26227
      registerFormatButtons(editor);
26228
      registerCommandButtons(editor);
26229
      registerCommandToggleButtons(editor);
26230
    };
26231
    const registerMenuItems$2 = editor => {
26232
      global$1.each([
26233
        {
26234
          name: 'newdocument',
26235
          text: 'New document',
26236
          action: 'mceNewDocument',
26237
          icon: 'new-document'
26238
        },
26239
        {
26240
          name: 'copy',
26241
          text: 'Copy',
26242
          action: 'Copy',
26243
          icon: 'copy',
26244
          shortcut: 'Meta+C'
26245
        },
26246
        {
26247
          name: 'selectall',
26248
          text: 'Select all',
26249
          action: 'SelectAll',
26250
          icon: 'select-all',
26251
          shortcut: 'Meta+A'
26252
        },
26253
        {
26254
          name: 'print',
26255
          text: 'Print...',
26256
          action: 'mcePrint',
26257
          icon: 'print',
26258
          shortcut: 'Meta+P'
26259
        }
26260
      ], menuitem => {
26261
        editor.ui.registry.addMenuItem(menuitem.name, {
26262
          text: menuitem.text,
26263
          icon: menuitem.icon,
26264
          shortcut: menuitem.shortcut,
26265
          onAction: onActionExecCommand(editor, menuitem.action)
26266
        });
26267
      });
26268
      global$1.each([
26269
        {
26270
          name: 'bold',
26271
          text: 'Bold',
26272
          action: 'Bold',
26273
          icon: 'bold',
26274
          shortcut: 'Meta+B'
26275
        },
26276
        {
26277
          name: 'italic',
26278
          text: 'Italic',
26279
          action: 'Italic',
26280
          icon: 'italic',
26281
          shortcut: 'Meta+I'
26282
        },
26283
        {
26284
          name: 'underline',
26285
          text: 'Underline',
26286
          action: 'Underline',
26287
          icon: 'underline',
26288
          shortcut: 'Meta+U'
26289
        },
26290
        {
26291
          name: 'strikethrough',
26292
          text: 'Strikethrough',
26293
          action: 'Strikethrough',
26294
          icon: 'strike-through'
26295
        },
26296
        {
26297
          name: 'subscript',
26298
          text: 'Subscript',
26299
          action: 'Subscript',
26300
          icon: 'subscript'
26301
        },
26302
        {
26303
          name: 'superscript',
26304
          text: 'Superscript',
26305
          action: 'Superscript',
26306
          icon: 'superscript'
26307
        },
26308
        {
26309
          name: 'removeformat',
26310
          text: 'Clear formatting',
26311
          action: 'RemoveFormat',
26312
          icon: 'remove-formatting'
26313
        },
26314
        {
26315
          name: 'cut',
26316
          text: 'Cut',
26317
          action: 'Cut',
26318
          icon: 'cut',
26319
          shortcut: 'Meta+X'
26320
        },
26321
        {
26322
          name: 'paste',
26323
          text: 'Paste',
26324
          action: 'Paste',
26325
          icon: 'paste',
26326
          shortcut: 'Meta+V'
26327
        },
26328
        {
26329
          name: 'hr',
26330
          text: 'Horizontal line',
26331
          action: 'InsertHorizontalRule',
26332
          icon: 'horizontal-rule'
26333
        }
26334
      ], menuitem => {
26335
        editor.ui.registry.addMenuItem(menuitem.name, {
26336
          text: menuitem.text,
26337
          icon: menuitem.icon,
26338
          shortcut: menuitem.shortcut,
26339
          onSetup: onSetupEditableToggle(editor),
26340
          onAction: onActionExecCommand(editor, menuitem.action)
26341
        });
26342
      });
26343
      editor.ui.registry.addMenuItem('codeformat', {
26344
        text: 'Code',
26345
        icon: 'sourcecode',
26346
        onSetup: onSetupEditableToggle(editor),
26347
        onAction: onActionToggleFormat(editor, 'code')
26348
      });
26349
    };
26350
    const register$3 = editor => {
26351
      registerButtons$1(editor);
26352
      registerMenuItems$2(editor);
26353
    };
26354
 
26355
    const onSetupUndoRedoState = (editor, type) => onSetupEvent(editor, 'Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', api => {
26356
      api.setEnabled(!editor.mode.isReadOnly() && editor.undoManager[type]());
26357
    });
26358
    const registerMenuItems$1 = editor => {
26359
      editor.ui.registry.addMenuItem('undo', {
26360
        text: 'Undo',
26361
        icon: 'undo',
26362
        shortcut: 'Meta+Z',
26363
        onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
26364
        onAction: onActionExecCommand(editor, 'undo')
26365
      });
26366
      editor.ui.registry.addMenuItem('redo', {
26367
        text: 'Redo',
26368
        icon: 'redo',
26369
        shortcut: 'Meta+Y',
26370
        onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
26371
        onAction: onActionExecCommand(editor, 'redo')
26372
      });
26373
    };
26374
    const registerButtons = editor => {
26375
      editor.ui.registry.addButton('undo', {
26376
        tooltip: 'Undo',
26377
        icon: 'undo',
26378
        enabled: false,
26379
        onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
26380
        onAction: onActionExecCommand(editor, 'undo')
26381
      });
26382
      editor.ui.registry.addButton('redo', {
26383
        tooltip: 'Redo',
26384
        icon: 'redo',
26385
        enabled: false,
26386
        onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
26387
        onAction: onActionExecCommand(editor, 'redo')
26388
      });
26389
    };
26390
    const register$2 = editor => {
26391
      registerMenuItems$1(editor);
26392
      registerButtons(editor);
26393
    };
26394
 
26395
    const onSetupVisualAidState = editor => onSetupEvent(editor, 'VisualAid', api => {
26396
      api.setActive(editor.hasVisual);
26397
    });
26398
    const registerMenuItems = editor => {
26399
      editor.ui.registry.addToggleMenuItem('visualaid', {
26400
        text: 'Visual aids',
26401
        onSetup: onSetupVisualAidState(editor),
26402
        onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
26403
      });
26404
    };
26405
    const registerToolbarButton = editor => {
26406
      editor.ui.registry.addButton('visualaid', {
26407
        tooltip: 'Visual aids',
26408
        text: 'Visual aids',
26409
        onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
26410
      });
26411
    };
26412
    const register$1 = editor => {
26413
      registerToolbarButton(editor);
26414
      registerMenuItems(editor);
26415
    };
26416
 
26417
    const setup$6 = (editor, backstage) => {
26418
      register$8(editor);
26419
      register$3(editor);
26420
      register$6(editor, backstage);
26421
      register$2(editor);
26422
      register$c(editor);
26423
      register$1(editor);
26424
      register$5(editor);
26425
      register$7(editor);
26426
      register$4(editor);
26427
    };
26428
 
26429
    const patchPipeConfig = config => isString(config) ? config.split(/[ ,]/) : config;
26430
    const option = name => editor => editor.options.get(name);
26431
    const register = editor => {
26432
      const registerOption = editor.options.register;
26433
      registerOption('contextmenu_avoid_overlap', {
26434
        processor: 'string',
26435
        default: ''
26436
      });
26437
      registerOption('contextmenu_never_use_native', {
26438
        processor: 'boolean',
26439
        default: false
26440
      });
26441
      registerOption('contextmenu', {
26442
        processor: value => {
26443
          if (value === false) {
26444
            return {
26445
              value: [],
26446
              valid: true
26447
            };
26448
          } else if (isString(value) || isArrayOf(value, isString)) {
26449
            return {
26450
              value: patchPipeConfig(value),
26451
              valid: true
26452
            };
26453
          } else {
26454
            return {
26455
              valid: false,
26456
              message: 'Must be false or a string.'
26457
            };
26458
          }
26459
        },
26460
        default: 'link linkchecker image editimage table spellchecker configurepermanentpen'
26461
      });
26462
    };
26463
    const shouldNeverUseNative = option('contextmenu_never_use_native');
26464
    const getAvoidOverlapSelector = option('contextmenu_avoid_overlap');
26465
    const isContextMenuDisabled = editor => getContextMenu(editor).length === 0;
26466
    const getContextMenu = editor => {
26467
      const contextMenus = editor.ui.registry.getAll().contextMenus;
26468
      const contextMenu = editor.options.get('contextmenu');
26469
      if (editor.options.isSet('contextmenu')) {
26470
        return contextMenu;
26471
      } else {
26472
        return filter$2(contextMenu, item => has$2(contextMenus, item));
26473
      }
26474
    };
26475
 
26476
    const nu = (x, y) => ({
26477
      type: 'makeshift',
26478
      x,
26479
      y
26480
    });
26481
    const transpose = (pos, dx, dy) => {
26482
      return nu(pos.x + dx, pos.y + dy);
26483
    };
26484
    const isTouchEvent$1 = e => e.type === 'longpress' || e.type.indexOf('touch') === 0;
26485
    const fromPageXY = e => {
26486
      if (isTouchEvent$1(e)) {
26487
        const touch = e.touches[0];
26488
        return nu(touch.pageX, touch.pageY);
26489
      } else {
26490
        return nu(e.pageX, e.pageY);
26491
      }
26492
    };
26493
    const fromClientXY = e => {
26494
      if (isTouchEvent$1(e)) {
26495
        const touch = e.touches[0];
26496
        return nu(touch.clientX, touch.clientY);
26497
      } else {
26498
        return nu(e.clientX, e.clientY);
26499
      }
26500
    };
26501
    const transposeContentAreaContainer = (element, pos) => {
26502
      const containerPos = global$7.DOM.getPos(element);
26503
      return transpose(pos, containerPos.x, containerPos.y);
26504
    };
26505
    const getPointAnchor = (editor, e) => {
26506
      if (e.type === 'contextmenu' || e.type === 'longpress') {
26507
        if (editor.inline) {
26508
          return fromPageXY(e);
26509
        } else {
26510
          return transposeContentAreaContainer(editor.getContentAreaContainer(), fromClientXY(e));
26511
        }
26512
      } else {
26513
        return getSelectionAnchor(editor);
26514
      }
26515
    };
26516
    const getSelectionAnchor = editor => {
26517
      return {
26518
        type: 'selection',
26519
        root: SugarElement.fromDom(editor.selection.getNode())
26520
      };
26521
    };
26522
    const getNodeAnchor = editor => ({
26523
      type: 'node',
26524
      node: Optional.some(SugarElement.fromDom(editor.selection.getNode())),
26525
      root: SugarElement.fromDom(editor.getBody())
26526
    });
26527
    const getAnchorSpec$1 = (editor, e, anchorType) => {
26528
      switch (anchorType) {
26529
      case 'node':
26530
        return getNodeAnchor(editor);
26531
      case 'point':
26532
        return getPointAnchor(editor, e);
26533
      case 'selection':
26534
        return getSelectionAnchor(editor);
26535
      }
26536
    };
26537
 
26538
    const initAndShow$1 = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
26539
      const items = buildMenu();
26540
      const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
26541
      build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
26542
        isHorizontalMenu: false,
26543
        search: Optional.none()
26544
      }).map(menuData => {
26545
        e.preventDefault();
26546
        InlineView.showMenuAt(contextmenu, { anchor: anchorSpec }, {
26547
          menu: { markers: markers('normal') },
26548
          data: menuData
26549
        });
26550
      });
26551
    };
26552
 
26553
    const layouts = {
26554
      onLtr: () => [
26555
        south$2,
26556
        southeast$2,
26557
        southwest$2,
26558
        northeast$2,
26559
        northwest$2,
26560
        north$2,
26561
        north,
26562
        south,
26563
        northeast,
26564
        southeast,
26565
        northwest,
26566
        southwest
26567
      ],
26568
      onRtl: () => [
26569
        south$2,
26570
        southwest$2,
26571
        southeast$2,
26572
        northwest$2,
26573
        northeast$2,
26574
        north$2,
26575
        north,
26576
        south,
26577
        northwest,
26578
        southwest,
26579
        northeast,
26580
        southeast
26581
      ]
26582
    };
26583
    const bubbleSize = 12;
26584
    const bubbleAlignments = {
26585
      valignCentre: [],
26586
      alignCentre: [],
26587
      alignLeft: ['tox-pop--align-left'],
26588
      alignRight: ['tox-pop--align-right'],
26589
      right: ['tox-pop--right'],
26590
      left: ['tox-pop--left'],
26591
      bottom: ['tox-pop--bottom'],
26592
      top: ['tox-pop--top']
26593
    };
26594
    const isTouchWithinSelection = (editor, e) => {
26595
      const selection = editor.selection;
26596
      if (selection.isCollapsed() || e.touches.length < 1) {
26597
        return false;
26598
      } else {
26599
        const touch = e.touches[0];
26600
        const rng = selection.getRng();
26601
        const rngRectOpt = getFirstRect(editor.getWin(), SimSelection.domRange(rng));
26602
        return rngRectOpt.exists(rngRect => rngRect.left <= touch.clientX && rngRect.right >= touch.clientX && rngRect.top <= touch.clientY && rngRect.bottom >= touch.clientY);
26603
      }
26604
    };
26605
    const setupiOSOverrides = editor => {
26606
      const originalSelection = editor.selection.getRng();
26607
      const selectionReset = () => {
26608
        global$9.setEditorTimeout(editor, () => {
26609
          editor.selection.setRng(originalSelection);
26610
        }, 10);
26611
        unbindEventListeners();
26612
      };
26613
      editor.once('touchend', selectionReset);
26614
      const preventMousedown = e => {
26615
        e.preventDefault();
26616
        e.stopImmediatePropagation();
26617
      };
26618
      editor.on('mousedown', preventMousedown, true);
26619
      const clearSelectionReset = () => unbindEventListeners();
26620
      editor.once('longpresscancel', clearSelectionReset);
26621
      const unbindEventListeners = () => {
26622
        editor.off('touchend', selectionReset);
26623
        editor.off('longpresscancel', clearSelectionReset);
26624
        editor.off('mousedown', preventMousedown);
26625
      };
26626
    };
26627
    const getAnchorSpec = (editor, e, anchorType) => {
26628
      const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
26629
      const bubbleYOffset = anchorType === 'point' ? bubbleSize : 0;
26630
      return {
26631
        bubble: nu$5(0, bubbleYOffset, bubbleAlignments),
26632
        layouts,
26633
        overrides: {
26634
          maxWidthFunction: expandable(),
26635
          maxHeightFunction: expandable$1()
26636
        },
26637
        ...anchorSpec
26638
      };
26639
    };
26640
    const show = (editor, e, items, backstage, contextmenu, anchorType, highlightImmediately) => {
26641
      const anchorSpec = getAnchorSpec(editor, e, anchorType);
26642
      build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
26643
        isHorizontalMenu: true,
26644
        search: Optional.none()
26645
      }).map(menuData => {
26646
        e.preventDefault();
26647
        const highlightOnOpen = highlightImmediately ? HighlightOnOpen.HighlightMenuAndItem : HighlightOnOpen.HighlightNone;
26648
        InlineView.showMenuWithinBounds(contextmenu, { anchor: anchorSpec }, {
26649
          menu: {
26650
            markers: markers('normal'),
26651
            highlightOnOpen
26652
          },
26653
          data: menuData,
26654
          type: 'horizontal'
26655
        }, () => Optional.some(getContextToolbarBounds(editor, backstage.shared, anchorType === 'node' ? 'node' : 'selection')));
26656
        editor.dispatch(hideContextToolbarEvent);
26657
      });
26658
    };
26659
    const initAndShow = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
26660
      const detection = detect$2();
26661
      const isiOS = detection.os.isiOS();
26662
      const isMacOS = detection.os.isMacOS();
26663
      const isAndroid = detection.os.isAndroid();
26664
      const isTouch = detection.deviceType.isTouch();
26665
      const shouldHighlightImmediately = () => !(isAndroid || isiOS || isMacOS && isTouch);
26666
      const open = () => {
26667
        const items = buildMenu();
26668
        show(editor, e, items, backstage, contextmenu, anchorType, shouldHighlightImmediately());
26669
      };
26670
      if ((isMacOS || isiOS) && anchorType !== 'node') {
26671
        const openiOS = () => {
26672
          setupiOSOverrides(editor);
26673
          open();
26674
        };
26675
        if (isTouchWithinSelection(editor, e)) {
26676
          openiOS();
26677
        } else {
26678
          editor.once('selectionchange', openiOS);
26679
          editor.once('touchend', () => editor.off('selectionchange', openiOS));
26680
        }
26681
      } else {
26682
        open();
26683
      }
26684
    };
26685
 
26686
    const isSeparator = item => isString(item) ? item === '|' : item.type === 'separator';
26687
    const separator = { type: 'separator' };
26688
    const makeContextItem = item => {
26689
      const commonMenuItem = item => ({
26690
        text: item.text,
26691
        icon: item.icon,
26692
        enabled: item.enabled,
26693
        shortcut: item.shortcut
26694
      });
26695
      if (isString(item)) {
26696
        return item;
26697
      } else {
26698
        switch (item.type) {
26699
        case 'separator':
26700
          return separator;
26701
        case 'submenu':
26702
          return {
26703
            type: 'nestedmenuitem',
26704
            ...commonMenuItem(item),
26705
            getSubmenuItems: () => {
26706
              const items = item.getSubmenuItems();
26707
              if (isString(items)) {
26708
                return items;
26709
              } else {
26710
                return map$2(items, makeContextItem);
26711
              }
26712
            }
26713
          };
26714
        default:
26715
          const commonItem = item;
26716
          return {
26717
            type: 'menuitem',
26718
            ...commonMenuItem(commonItem),
26719
            onAction: noarg(commonItem.onAction)
26720
          };
26721
        }
26722
      }
26723
    };
26724
    const addContextMenuGroup = (xs, groupItems) => {
26725
      if (groupItems.length === 0) {
26726
        return xs;
26727
      }
26728
      const lastMenuItem = last$1(xs).filter(item => !isSeparator(item));
26729
      const before = lastMenuItem.fold(() => [], _ => [separator]);
26730
      return xs.concat(before).concat(groupItems).concat([separator]);
26731
    };
26732
    const generateContextMenu = (contextMenus, menuConfig, selectedElement) => {
26733
      const sections = foldl(menuConfig, (acc, name) => {
26734
        return get$g(contextMenus, name.toLowerCase()).map(menu => {
26735
          const items = menu.update(selectedElement);
26736
          if (isString(items) && isNotEmpty(trim$1(items))) {
26737
            return addContextMenuGroup(acc, items.split(' '));
26738
          } else if (isArray(items) && items.length > 0) {
26739
            const allItems = map$2(items, makeContextItem);
26740
            return addContextMenuGroup(acc, allItems);
26741
          } else {
26742
            return acc;
26743
          }
26744
        }).getOrThunk(() => acc.concat([name]));
26745
      }, []);
26746
      if (sections.length > 0 && isSeparator(sections[sections.length - 1])) {
26747
        sections.pop();
26748
      }
26749
      return sections;
26750
    };
26751
    const isNativeOverrideKeyEvent = (editor, e) => e.ctrlKey && !shouldNeverUseNative(editor);
26752
    const isTouchEvent = e => e.type === 'longpress' || has$2(e, 'touches');
26753
    const isTriggeredByKeyboard = (editor, e) => !isTouchEvent(e) && (e.button !== 2 || e.target === editor.getBody() && e.pointerType === '');
26754
    const getSelectedElement = (editor, e) => isTriggeredByKeyboard(editor, e) ? editor.selection.getStart(true) : e.target;
26755
    const getAnchorType = (editor, e) => {
26756
      const selector = getAvoidOverlapSelector(editor);
26757
      const anchorType = isTriggeredByKeyboard(editor, e) ? 'selection' : 'point';
26758
      if (isNotEmpty(selector)) {
26759
        const target = getSelectedElement(editor, e);
26760
        const selectorExists = closest(SugarElement.fromDom(target), selector);
26761
        return selectorExists ? 'node' : anchorType;
26762
      } else {
26763
        return anchorType;
26764
      }
26765
    };
26766
    const setup$5 = (editor, lazySink, backstage) => {
26767
      const detection = detect$2();
26768
      const isTouch = detection.deviceType.isTouch;
26769
      const contextmenu = build$1(InlineView.sketch({
26770
        dom: { tag: 'div' },
26771
        lazySink,
26772
        onEscape: () => editor.focus(),
26773
        onShow: () => backstage.setContextMenuState(true),
26774
        onHide: () => backstage.setContextMenuState(false),
26775
        fireDismissalEventInstead: {},
26776
        inlineBehaviours: derive$1([config('dismissContextMenu', [run$1(dismissRequested(), (comp, _se) => {
26777
              Sandboxing.close(comp);
26778
              editor.focus();
26779
            })])])
26780
      }));
26781
      const hideContextMenu = () => InlineView.hide(contextmenu);
26782
      const showContextMenu = e => {
26783
        if (shouldNeverUseNative(editor)) {
26784
          e.preventDefault();
26785
        }
26786
        if (isNativeOverrideKeyEvent(editor, e) || isContextMenuDisabled(editor)) {
26787
          return;
26788
        }
26789
        const anchorType = getAnchorType(editor, e);
26790
        const buildMenu = () => {
26791
          const selectedElement = getSelectedElement(editor, e);
26792
          const registry = editor.ui.registry.getAll();
26793
          const menuConfig = getContextMenu(editor);
26794
          return generateContextMenu(registry.contextMenus, menuConfig, selectedElement);
26795
        };
26796
        const initAndShow$2 = isTouch() ? initAndShow : initAndShow$1;
26797
        initAndShow$2(editor, e, buildMenu, backstage, contextmenu, anchorType);
26798
      };
26799
      editor.on('init', () => {
26800
        const hideEvents = 'ResizeEditor ScrollContent ScrollWindow longpresscancel' + (isTouch() ? '' : ' ResizeWindow');
26801
        editor.on(hideEvents, hideContextMenu);
26802
        editor.on('longpress contextmenu', showContextMenu);
26803
      });
26804
    };
26805
 
26806
    const adt = Adt.generate([
26807
      {
26808
        offset: [
26809
          'x',
26810
          'y'
26811
        ]
26812
      },
26813
      {
26814
        absolute: [
26815
          'x',
26816
          'y'
26817
        ]
26818
      },
26819
      {
26820
        fixed: [
26821
          'x',
26822
          'y'
26823
        ]
26824
      }
26825
    ]);
26826
    const subtract = change => point => point.translate(-change.left, -change.top);
26827
    const add = change => point => point.translate(change.left, change.top);
26828
    const transform = changes => (x, y) => foldl(changes, (rest, f) => f(rest), SugarPosition(x, y));
26829
    const asFixed = (coord, scroll, origin) => coord.fold(transform([
26830
      add(origin),
26831
      subtract(scroll)
26832
    ]), transform([subtract(scroll)]), transform([]));
26833
    const asAbsolute = (coord, scroll, origin) => coord.fold(transform([add(origin)]), transform([]), transform([add(scroll)]));
26834
    const asOffset = (coord, scroll, origin) => coord.fold(transform([]), transform([subtract(origin)]), transform([
26835
      add(scroll),
26836
      subtract(origin)
26837
    ]));
26838
    const withinRange = (coord1, coord2, xRange, yRange, scroll, origin) => {
26839
      const a1 = asAbsolute(coord1, scroll, origin);
26840
      const a2 = asAbsolute(coord2, scroll, origin);
26841
      return Math.abs(a1.left - a2.left) <= xRange && Math.abs(a1.top - a2.top) <= yRange;
26842
    };
26843
    const getDeltas = (coord1, coord2, xRange, yRange, scroll, origin) => {
26844
      const a1 = asAbsolute(coord1, scroll, origin);
26845
      const a2 = asAbsolute(coord2, scroll, origin);
26846
      const left = Math.abs(a1.left - a2.left);
26847
      const top = Math.abs(a1.top - a2.top);
26848
      return SugarPosition(left, top);
26849
    };
26850
    const toStyles = (coord, scroll, origin) => {
26851
      const stylesOpt = coord.fold((x, y) => ({
26852
        position: Optional.some('absolute'),
26853
        left: Optional.some(x + 'px'),
26854
        top: Optional.some(y + 'px')
26855
      }), (x, y) => ({
26856
        position: Optional.some('absolute'),
26857
        left: Optional.some(x - origin.left + 'px'),
26858
        top: Optional.some(y - origin.top + 'px')
26859
      }), (x, y) => ({
26860
        position: Optional.some('fixed'),
26861
        left: Optional.some(x + 'px'),
26862
        top: Optional.some(y + 'px')
26863
      }));
26864
      return {
26865
        right: Optional.none(),
26866
        bottom: Optional.none(),
26867
        ...stylesOpt
26868
      };
26869
    };
26870
    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));
26871
    const absorb = (partialCoord, originalCoord, scroll, origin) => {
26872
      const absorbOne = (stencil, nu) => (optX, optY) => {
26873
        const original = stencil(originalCoord, scroll, origin);
26874
        return nu(optX.getOr(original.left), optY.getOr(original.top));
26875
      };
26876
      return partialCoord.fold(absorbOne(asOffset, offset), absorbOne(asAbsolute, absolute), absorbOne(asFixed, fixed));
26877
    };
26878
    const offset = adt.offset;
26879
    const absolute = adt.absolute;
26880
    const fixed = adt.fixed;
26881
 
26882
    const parseAttrToInt = (element, name) => {
26883
      const value = get$f(element, name);
26884
      return isUndefined(value) ? NaN : parseInt(value, 10);
26885
    };
26886
    const get = (component, snapsInfo) => {
26887
      const element = component.element;
26888
      const x = parseAttrToInt(element, snapsInfo.leftAttr);
26889
      const y = parseAttrToInt(element, snapsInfo.topAttr);
26890
      return isNaN(x) || isNaN(y) ? Optional.none() : Optional.some(SugarPosition(x, y));
26891
    };
26892
    const set = (component, snapsInfo, pt) => {
26893
      const element = component.element;
26894
      set$9(element, snapsInfo.leftAttr, pt.left + 'px');
26895
      set$9(element, snapsInfo.topAttr, pt.top + 'px');
26896
    };
26897
    const clear = (component, snapsInfo) => {
26898
      const element = component.element;
26899
      remove$7(element, snapsInfo.leftAttr);
26900
      remove$7(element, snapsInfo.topAttr);
26901
    };
26902
 
26903
    const getCoords = (component, snapInfo, coord, delta) => get(component, snapInfo).fold(() => coord, fixed$1 => fixed(fixed$1.left + delta.left, fixed$1.top + delta.top));
26904
    const moveOrSnap = (component, snapInfo, coord, delta, scroll, origin) => {
26905
      const newCoord = getCoords(component, snapInfo, coord, delta);
26906
      const snap = snapInfo.mustSnap ? findClosestSnap(component, snapInfo, newCoord, scroll, origin) : findSnap(component, snapInfo, newCoord, scroll, origin);
26907
      const fixedCoord = asFixed(newCoord, scroll, origin);
26908
      set(component, snapInfo, fixedCoord);
26909
      return snap.fold(() => ({
26910
        coord: fixed(fixedCoord.left, fixedCoord.top),
26911
        extra: Optional.none()
26912
      }), spanned => ({
26913
        coord: spanned.output,
26914
        extra: spanned.extra
26915
      }));
26916
    };
26917
    const stopDrag = (component, snapInfo) => {
26918
      clear(component, snapInfo);
26919
    };
26920
    const findMatchingSnap = (snaps, newCoord, scroll, origin) => findMap(snaps, snap => {
26921
      const sensor = snap.sensor;
26922
      const inRange = withinRange(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
26923
      return inRange ? Optional.some({
26924
        output: absorb(snap.output, newCoord, scroll, origin),
26925
        extra: snap.extra
26926
      }) : Optional.none();
26927
    });
26928
    const findClosestSnap = (component, snapInfo, newCoord, scroll, origin) => {
26929
      const snaps = snapInfo.getSnapPoints(component);
26930
      const matchSnap = findMatchingSnap(snaps, newCoord, scroll, origin);
26931
      return matchSnap.orThunk(() => {
26932
        const bestSnap = foldl(snaps, (acc, snap) => {
26933
          const sensor = snap.sensor;
26934
          const deltas = getDeltas(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
26935
          return acc.deltas.fold(() => ({
26936
            deltas: Optional.some(deltas),
26937
            snap: Optional.some(snap)
26938
          }), bestDeltas => {
26939
            const currAvg = (deltas.left + deltas.top) / 2;
26940
            const bestAvg = (bestDeltas.left + bestDeltas.top) / 2;
26941
            if (currAvg <= bestAvg) {
26942
              return {
26943
                deltas: Optional.some(deltas),
26944
                snap: Optional.some(snap)
26945
              };
26946
            } else {
26947
              return acc;
26948
            }
26949
          });
26950
        }, {
26951
          deltas: Optional.none(),
26952
          snap: Optional.none()
26953
        });
26954
        return bestSnap.snap.map(snap => ({
26955
          output: absorb(snap.output, newCoord, scroll, origin),
26956
          extra: snap.extra
26957
        }));
26958
      });
26959
    };
26960
    const findSnap = (component, snapInfo, newCoord, scroll, origin) => {
26961
      const snaps = snapInfo.getSnapPoints(component);
26962
      return findMatchingSnap(snaps, newCoord, scroll, origin);
26963
    };
26964
    const snapTo$1 = (snap, scroll, origin) => ({
26965
      coord: absorb(snap.output, snap.output, scroll, origin),
26966
      extra: snap.extra
26967
    });
26968
 
26969
    const snapTo = (component, dragConfig, _state, snap) => {
26970
      const target = dragConfig.getTarget(component.element);
26971
      if (dragConfig.repositionTarget) {
26972
        const doc = owner$4(component.element);
26973
        const scroll = get$b(doc);
26974
        const origin = getOrigin(target);
26975
        const snapPin = snapTo$1(snap, scroll, origin);
26976
        const styles = toStyles(snapPin.coord, scroll, origin);
26977
        setOptions(target, styles);
26978
      }
26979
    };
26980
 
26981
    var DraggingApis = /*#__PURE__*/Object.freeze({
26982
        __proto__: null,
26983
        snapTo: snapTo
26984
    });
26985
 
26986
    const initialAttribute = 'data-initial-z-index';
26987
    const resetZIndex = blocker => {
26988
      parent(blocker.element).filter(isElement$1).each(root => {
26989
        getOpt(root, initialAttribute).fold(() => remove$6(root, 'z-index'), zIndex => set$8(root, 'z-index', zIndex));
26990
        remove$7(root, initialAttribute);
26991
      });
26992
    };
26993
    const changeZIndex = blocker => {
26994
      parent(blocker.element).filter(isElement$1).each(root => {
26995
        getRaw(root, 'z-index').each(zindex => {
26996
          set$9(root, initialAttribute, zindex);
26997
        });
26998
        set$8(root, 'z-index', get$e(blocker.element, 'z-index'));
26999
      });
27000
    };
27001
    const instigate = (anyComponent, blocker) => {
27002
      anyComponent.getSystem().addToGui(blocker);
27003
      changeZIndex(blocker);
27004
    };
27005
    const discard = blocker => {
27006
      resetZIndex(blocker);
27007
      blocker.getSystem().removeFromGui(blocker);
27008
    };
27009
    const createComponent = (component, blockerClass, blockerEvents) => component.getSystem().build(Container.sketch({
27010
      dom: {
27011
        styles: {
27012
          'left': '0px',
27013
          'top': '0px',
27014
          'width': '100%',
27015
          'height': '100%',
27016
          'position': 'fixed',
27017
          'z-index': '1000000000000000'
27018
        },
27019
        classes: [blockerClass]
27020
      },
27021
      events: blockerEvents
27022
    }));
27023
 
27024
    var SnapSchema = optionObjOf('snaps', [
27025
      required$1('getSnapPoints'),
27026
      onHandler('onSensor'),
27027
      required$1('leftAttr'),
27028
      required$1('topAttr'),
27029
      defaulted('lazyViewport', win),
27030
      defaulted('mustSnap', false)
27031
    ]);
27032
 
27033
    const schema$6 = [
27034
      defaulted('useFixed', never),
27035
      required$1('blockerClass'),
27036
      defaulted('getTarget', identity),
27037
      defaulted('onDrag', noop),
27038
      defaulted('repositionTarget', true),
27039
      defaulted('onDrop', noop),
27040
      defaultedFunction('getBounds', win),
27041
      SnapSchema
27042
    ];
27043
 
27044
    const getCurrentCoord = target => lift3(getRaw(target, 'left'), getRaw(target, 'top'), getRaw(target, 'position'), (left, top, position) => {
27045
      const nu = position === 'fixed' ? fixed : offset;
27046
      return nu(parseInt(left, 10), parseInt(top, 10));
27047
    }).getOrThunk(() => {
27048
      const location = absolute$3(target);
27049
      return absolute(location.left, location.top);
27050
    });
27051
    const clampCoords = (component, coords, scroll, origin, startData) => {
27052
      const bounds = startData.bounds;
27053
      const absoluteCoord = asAbsolute(coords, scroll, origin);
27054
      const newX = clamp(absoluteCoord.left, bounds.x, bounds.x + bounds.width - startData.width);
27055
      const newY = clamp(absoluteCoord.top, bounds.y, bounds.y + bounds.height - startData.height);
27056
      const newCoords = absolute(newX, newY);
27057
      return coords.fold(() => {
27058
        const offset$1 = asOffset(newCoords, scroll, origin);
27059
        return offset(offset$1.left, offset$1.top);
27060
      }, constant$1(newCoords), () => {
27061
        const fixed$1 = asFixed(newCoords, scroll, origin);
27062
        return fixed(fixed$1.left, fixed$1.top);
27063
      });
27064
    };
27065
    const calcNewCoord = (component, optSnaps, currentCoord, scroll, origin, delta, startData) => {
27066
      const newCoord = optSnaps.fold(() => {
27067
        const translated = translate(currentCoord, delta.left, delta.top);
27068
        const fixedCoord = asFixed(translated, scroll, origin);
27069
        return fixed(fixedCoord.left, fixedCoord.top);
27070
      }, snapInfo => {
27071
        const snapping = moveOrSnap(component, snapInfo, currentCoord, delta, scroll, origin);
27072
        snapping.extra.each(extra => {
27073
          snapInfo.onSensor(component, extra);
27074
        });
27075
        return snapping.coord;
27076
      });
27077
      return clampCoords(component, newCoord, scroll, origin, startData);
27078
    };
27079
    const dragBy = (component, dragConfig, startData, delta) => {
27080
      const target = dragConfig.getTarget(component.element);
27081
      if (dragConfig.repositionTarget) {
27082
        const doc = owner$4(component.element);
27083
        const scroll = get$b(doc);
27084
        const origin = getOrigin(target);
27085
        const currentCoord = getCurrentCoord(target);
27086
        const newCoord = calcNewCoord(component, dragConfig.snaps, currentCoord, scroll, origin, delta, startData);
27087
        const styles = toStyles(newCoord, scroll, origin);
27088
        setOptions(target, styles);
27089
      }
27090
      dragConfig.onDrag(component, target, delta);
27091
    };
27092
 
27093
    const calcStartData = (dragConfig, comp) => ({
27094
      bounds: dragConfig.getBounds(),
27095
      height: getOuter$2(comp.element),
27096
      width: getOuter$1(comp.element)
27097
    });
27098
    const move = (component, dragConfig, dragState, dragMode, event) => {
27099
      const delta = dragState.update(dragMode, event);
27100
      const dragStartData = dragState.getStartData().getOrThunk(() => calcStartData(dragConfig, component));
27101
      delta.each(dlt => {
27102
        dragBy(component, dragConfig, dragStartData, dlt);
27103
      });
27104
    };
27105
    const stop = (component, blocker, dragConfig, dragState) => {
27106
      blocker.each(discard);
27107
      dragConfig.snaps.each(snapInfo => {
27108
        stopDrag(component, snapInfo);
27109
      });
27110
      const target = dragConfig.getTarget(component.element);
27111
      dragState.reset();
27112
      dragConfig.onDrop(component, target);
27113
    };
27114
    const handlers = events => (dragConfig, dragState) => {
27115
      const updateStartState = comp => {
27116
        dragState.setStartData(calcStartData(dragConfig, comp));
27117
      };
27118
      return derive$2([
27119
        run$1(windowScroll(), comp => {
27120
          dragState.getStartData().each(() => updateStartState(comp));
27121
        }),
27122
        ...events(dragConfig, dragState, updateStartState)
27123
      ]);
27124
    };
27125
 
27126
    const init$3 = dragApi => derive$2([
27127
      run$1(mousedown(), dragApi.forceDrop),
27128
      run$1(mouseup(), dragApi.drop),
27129
      run$1(mousemove(), (comp, simulatedEvent) => {
27130
        dragApi.move(simulatedEvent.event);
27131
      }),
27132
      run$1(mouseout(), dragApi.delayDrop)
27133
    ]);
27134
 
27135
    const getData$1 = event => Optional.from(SugarPosition(event.x, event.y));
27136
    const getDelta$1 = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
27137
 
27138
    var MouseData = /*#__PURE__*/Object.freeze({
27139
        __proto__: null,
27140
        getData: getData$1,
27141
        getDelta: getDelta$1
27142
    });
27143
 
27144
    const events$3 = (dragConfig, dragState, updateStartState) => [run$1(mousedown(), (component, simulatedEvent) => {
27145
        const raw = simulatedEvent.event.raw;
27146
        if (raw.button !== 0) {
27147
          return;
27148
        }
27149
        simulatedEvent.stop();
27150
        const stop$1 = () => stop(component, Optional.some(blocker), dragConfig, dragState);
27151
        const delayDrop = DelayedFunction(stop$1, 200);
27152
        const dragApi = {
27153
          drop: stop$1,
27154
          delayDrop: delayDrop.schedule,
27155
          forceDrop: stop$1,
27156
          move: event => {
27157
            delayDrop.cancel();
27158
            move(component, dragConfig, dragState, MouseData, event);
27159
          }
27160
        };
27161
        const blocker = createComponent(component, dragConfig.blockerClass, init$3(dragApi));
27162
        const start = () => {
27163
          updateStartState(component);
27164
          instigate(component, blocker);
27165
        };
27166
        start();
27167
      })];
27168
    const schema$5 = [
27169
      ...schema$6,
27170
      output$1('dragger', { handlers: handlers(events$3) })
27171
    ];
27172
 
27173
    const init$2 = dragApi => derive$2([
27174
      run$1(touchstart(), dragApi.forceDrop),
27175
      run$1(touchend(), dragApi.drop),
27176
      run$1(touchcancel(), dragApi.drop),
27177
      run$1(touchmove(), (comp, simulatedEvent) => {
27178
        dragApi.move(simulatedEvent.event);
27179
      })
27180
    ]);
27181
 
27182
    const getDataFrom = touches => {
27183
      const touch = touches[0];
27184
      return Optional.some(SugarPosition(touch.clientX, touch.clientY));
27185
    };
27186
    const getData = event => {
27187
      const raw = event.raw;
27188
      const touches = raw.touches;
27189
      return touches.length === 1 ? getDataFrom(touches) : Optional.none();
27190
    };
27191
    const getDelta = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
27192
 
27193
    var TouchData = /*#__PURE__*/Object.freeze({
27194
        __proto__: null,
27195
        getData: getData,
27196
        getDelta: getDelta
27197
    });
27198
 
27199
    const events$2 = (dragConfig, dragState, updateStartState) => {
27200
      const blockerSingleton = value$2();
27201
      const stopBlocking = component => {
27202
        stop(component, blockerSingleton.get(), dragConfig, dragState);
27203
        blockerSingleton.clear();
27204
      };
27205
      return [
27206
        run$1(touchstart(), (component, simulatedEvent) => {
27207
          simulatedEvent.stop();
27208
          const stop = () => stopBlocking(component);
27209
          const dragApi = {
27210
            drop: stop,
27211
            delayDrop: noop,
27212
            forceDrop: stop,
27213
            move: event => {
27214
              move(component, dragConfig, dragState, TouchData, event);
27215
            }
27216
          };
27217
          const blocker = createComponent(component, dragConfig.blockerClass, init$2(dragApi));
27218
          blockerSingleton.set(blocker);
27219
          const start = () => {
27220
            updateStartState(component);
27221
            instigate(component, blocker);
27222
          };
27223
          start();
27224
        }),
27225
        run$1(touchmove(), (component, simulatedEvent) => {
27226
          simulatedEvent.stop();
27227
          move(component, dragConfig, dragState, TouchData, simulatedEvent.event);
27228
        }),
27229
        run$1(touchend(), (component, simulatedEvent) => {
27230
          simulatedEvent.stop();
27231
          stopBlocking(component);
27232
        }),
27233
        run$1(touchcancel(), stopBlocking)
27234
      ];
27235
    };
27236
    const schema$4 = [
27237
      ...schema$6,
27238
      output$1('dragger', { handlers: handlers(events$2) })
27239
    ];
27240
 
27241
    const events$1 = (dragConfig, dragState, updateStartState) => [
27242
      ...events$3(dragConfig, dragState, updateStartState),
27243
      ...events$2(dragConfig, dragState, updateStartState)
27244
    ];
27245
    const schema$3 = [
27246
      ...schema$6,
27247
      output$1('dragger', { handlers: handlers(events$1) })
27248
    ];
27249
 
27250
    const mouse = schema$5;
27251
    const touch = schema$4;
27252
    const mouseOrTouch = schema$3;
27253
 
27254
    var DraggingBranches = /*#__PURE__*/Object.freeze({
27255
        __proto__: null,
27256
        mouse: mouse,
27257
        touch: touch,
27258
        mouseOrTouch: mouseOrTouch
27259
    });
27260
 
27261
    const init$1 = () => {
27262
      let previous = Optional.none();
27263
      let startData = Optional.none();
27264
      const reset = () => {
27265
        previous = Optional.none();
27266
        startData = Optional.none();
27267
      };
27268
      const calculateDelta = (mode, nu) => {
27269
        const result = previous.map(old => mode.getDelta(old, nu));
27270
        previous = Optional.some(nu);
27271
        return result;
27272
      };
27273
      const update = (mode, dragEvent) => mode.getData(dragEvent).bind(nuData => calculateDelta(mode, nuData));
27274
      const setStartData = data => {
27275
        startData = Optional.some(data);
27276
      };
27277
      const getStartData = () => startData;
27278
      const readState = constant$1({});
27279
      return nu$8({
27280
        readState,
27281
        reset,
27282
        update,
27283
        getStartData,
27284
        setStartData
27285
      });
27286
    };
27287
 
27288
    var DragState = /*#__PURE__*/Object.freeze({
27289
        __proto__: null,
27290
        init: init$1
27291
    });
27292
 
27293
    const Dragging = createModes({
27294
      branchKey: 'mode',
27295
      branches: DraggingBranches,
27296
      name: 'dragging',
27297
      active: {
27298
        events: (dragConfig, dragState) => {
27299
          const dragger = dragConfig.dragger;
27300
          return dragger.handlers(dragConfig, dragState);
27301
        }
27302
      },
27303
      extra: {
27304
        snap: sConfig => ({
27305
          sensor: sConfig.sensor,
27306
          range: sConfig.range,
27307
          output: sConfig.output,
27308
          extra: Optional.from(sConfig.extra)
27309
        })
27310
      },
27311
      state: DragState,
27312
      apis: DraggingApis
27313
    });
27314
 
27315
    const snapWidth = 40;
27316
    const snapOffset = snapWidth / 2;
27317
    const calcSnap = (selectorOpt, td, x, y, width, height) => selectorOpt.fold(() => Dragging.snap({
27318
      sensor: absolute(x - snapOffset, y - snapOffset),
27319
      range: SugarPosition(width, height),
27320
      output: absolute(Optional.some(x), Optional.some(y)),
27321
      extra: { td }
27322
    }), selectorHandle => {
27323
      const sensorLeft = x - snapOffset;
27324
      const sensorTop = y - snapOffset;
27325
      const sensorWidth = snapWidth;
27326
      const sensorHeight = snapWidth;
27327
      const rect = selectorHandle.element.dom.getBoundingClientRect();
27328
      return Dragging.snap({
27329
        sensor: absolute(sensorLeft, sensorTop),
27330
        range: SugarPosition(sensorWidth, sensorHeight),
27331
        output: absolute(Optional.some(x - rect.width / 2), Optional.some(y - rect.height / 2)),
27332
        extra: { td }
27333
      });
27334
    });
27335
    const getSnapsConfig = (getSnapPoints, cell, onChange) => {
27336
      const isSameCell = (cellOpt, td) => cellOpt.exists(currentTd => eq(currentTd, td));
27337
      return {
27338
        getSnapPoints,
27339
        leftAttr: 'data-drag-left',
27340
        topAttr: 'data-drag-top',
27341
        onSensor: (component, extra) => {
27342
          const td = extra.td;
27343
          if (!isSameCell(cell.get(), td)) {
27344
            cell.set(td);
27345
            onChange(td);
27346
          }
27347
        },
27348
        mustSnap: true
27349
      };
27350
    };
27351
    const createSelector = snaps => record(Button.sketch({
27352
      dom: {
27353
        tag: 'div',
27354
        classes: ['tox-selector']
27355
      },
27356
      buttonBehaviours: derive$1([
27357
        Dragging.config({
27358
          mode: 'mouseOrTouch',
27359
          blockerClass: 'blocker',
27360
          snaps
27361
        }),
27362
        Unselecting.config({})
27363
      ]),
27364
      eventOrder: {
27365
        mousedown: [
27366
          'dragging',
27367
          'alloy.base.behaviour'
27368
        ],
27369
        touchstart: [
27370
          'dragging',
27371
          'alloy.base.behaviour'
27372
        ]
27373
      }
27374
    }));
27375
    const setup$4 = (editor, sink) => {
27376
      const tlTds = Cell([]);
27377
      const brTds = Cell([]);
27378
      const isVisible = Cell(false);
27379
      const startCell = value$2();
27380
      const finishCell = value$2();
27381
      const getTopLeftSnap = td => {
27382
        const box = absolute$2(td);
27383
        return calcSnap(memTopLeft.getOpt(sink), td, box.x, box.y, box.width, box.height);
27384
      };
27385
      const getTopLeftSnaps = () => map$2(tlTds.get(), td => getTopLeftSnap(td));
27386
      const getBottomRightSnap = td => {
27387
        const box = absolute$2(td);
27388
        return calcSnap(memBottomRight.getOpt(sink), td, box.right, box.bottom, box.width, box.height);
27389
      };
27390
      const getBottomRightSnaps = () => map$2(brTds.get(), td => getBottomRightSnap(td));
27391
      const topLeftSnaps = getSnapsConfig(getTopLeftSnaps, startCell, start => {
27392
        finishCell.get().each(finish => {
27393
          editor.dispatch('TableSelectorChange', {
27394
            start,
27395
            finish
27396
          });
27397
        });
27398
      });
27399
      const bottomRightSnaps = getSnapsConfig(getBottomRightSnaps, finishCell, finish => {
27400
        startCell.get().each(start => {
27401
          editor.dispatch('TableSelectorChange', {
27402
            start,
27403
            finish
27404
          });
27405
        });
27406
      });
27407
      const memTopLeft = createSelector(topLeftSnaps);
27408
      const memBottomRight = createSelector(bottomRightSnaps);
27409
      const topLeft = build$1(memTopLeft.asSpec());
27410
      const bottomRight = build$1(memBottomRight.asSpec());
27411
      const showOrHideHandle = (selector, cell, isAbove, isBelow) => {
27412
        const cellRect = cell.dom.getBoundingClientRect();
27413
        remove$6(selector.element, 'display');
27414
        const viewportHeight = defaultView(SugarElement.fromDom(editor.getBody())).dom.innerHeight;
27415
        const aboveViewport = isAbove(cellRect);
27416
        const belowViewport = isBelow(cellRect, viewportHeight);
27417
        if (aboveViewport || belowViewport) {
27418
          set$8(selector.element, 'display', 'none');
27419
        }
27420
      };
27421
      const snapTo = (selector, cell, getSnapConfig, pos) => {
27422
        const snap = getSnapConfig(cell);
27423
        Dragging.snapTo(selector, snap);
27424
        const isAbove = rect => rect[pos] < 0;
27425
        const isBelow = (rect, viewportHeight) => rect[pos] > viewportHeight;
27426
        showOrHideHandle(selector, cell, isAbove, isBelow);
27427
      };
27428
      const snapTopLeft = cell => snapTo(topLeft, cell, getTopLeftSnap, 'top');
27429
      const snapLastTopLeft = () => startCell.get().each(snapTopLeft);
27430
      const snapBottomRight = cell => snapTo(bottomRight, cell, getBottomRightSnap, 'bottom');
27431
      const snapLastBottomRight = () => finishCell.get().each(snapBottomRight);
27432
      if (detect$2().deviceType.isTouch()) {
27433
        editor.on('TableSelectionChange', e => {
27434
          if (!isVisible.get()) {
27435
            attach(sink, topLeft);
27436
            attach(sink, bottomRight);
27437
            isVisible.set(true);
27438
          }
27439
          startCell.set(e.start);
27440
          finishCell.set(e.finish);
27441
          e.otherCells.each(otherCells => {
27442
            tlTds.set(otherCells.upOrLeftCells);
27443
            brTds.set(otherCells.downOrRightCells);
27444
            snapTopLeft(e.start);
27445
            snapBottomRight(e.finish);
27446
          });
27447
        });
27448
        editor.on('ResizeEditor ResizeWindow ScrollContent', () => {
27449
          snapLastTopLeft();
27450
          snapLastBottomRight();
27451
        });
27452
        editor.on('TableSelectionClear', () => {
27453
          if (isVisible.get()) {
27454
            detach(topLeft);
27455
            detach(bottomRight);
27456
            isVisible.set(false);
27457
          }
27458
          startCell.clear();
27459
          finishCell.clear();
27460
        });
27461
      }
27462
    };
27463
 
27464
    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";
27465
 
27466
    const isHidden = elm => elm.nodeName === 'BR' || !!elm.getAttribute('data-mce-bogus') || elm.getAttribute('data-mce-type') === 'bookmark';
27467
    const renderElementPath = (editor, settings, providersBackstage) => {
27468
      var _a;
27469
      const delimiter = (_a = settings.delimiter) !== null && _a !== void 0 ? _a : '\u203A';
27470
      const renderElement = (name, element, index) => Button.sketch({
27471
        dom: {
27472
          tag: 'div',
27473
          classes: ['tox-statusbar__path-item'],
27474
          attributes: {
27475
            'data-index': index,
27476
            'aria-level': index + 1
27477
          }
27478
        },
27479
        components: [text$2(name)],
27480
        action: _btn => {
27481
          editor.focus();
27482
          editor.selection.select(element);
27483
          editor.nodeChanged();
27484
        },
27485
        buttonBehaviours: derive$1([
27486
          DisablingConfigs.button(providersBackstage.isDisabled),
27487
          receivingConfig()
27488
        ])
27489
      });
27490
      const renderDivider = () => ({
27491
        dom: {
27492
          tag: 'div',
27493
          classes: ['tox-statusbar__path-divider'],
27494
          attributes: { 'aria-hidden': true }
27495
        },
27496
        components: [text$2(` ${ delimiter } `)]
27497
      });
27498
      const renderPathData = data => foldl(data, (acc, path, index) => {
27499
        const element = renderElement(path.name, path.element, index);
27500
        if (index === 0) {
27501
          return acc.concat([element]);
27502
        } else {
27503
          return acc.concat([
27504
            renderDivider(),
27505
            element
27506
          ]);
27507
        }
27508
      }, []);
27509
      const updatePath = parents => {
27510
        const newPath = [];
27511
        let i = parents.length;
27512
        while (i-- > 0) {
27513
          const parent = parents[i];
27514
          if (parent.nodeType === 1 && !isHidden(parent)) {
27515
            const args = fireResolveName(editor, parent);
27516
            if (!args.isDefaultPrevented()) {
27517
              newPath.push({
27518
                name: args.name,
27519
                element: parent
27520
              });
27521
            }
27522
            if (args.isPropagationStopped()) {
27523
              break;
27524
            }
27525
          }
27526
        }
27527
        return newPath;
27528
      };
27529
      return {
27530
        dom: {
27531
          tag: 'div',
27532
          classes: ['tox-statusbar__path'],
27533
          attributes: { role: 'navigation' }
27534
        },
27535
        behaviours: derive$1([
27536
          Keying.config({
27537
            mode: 'flow',
27538
            selector: 'div[role=button]'
27539
          }),
27540
          Disabling.config({ disabled: providersBackstage.isDisabled }),
27541
          receivingConfig(),
27542
          Tabstopping.config({}),
27543
          Replacing.config({}),
27544
          config('elementPathEvents', [runOnAttached((comp, _e) => {
27545
              editor.shortcuts.add('alt+F11', 'focus statusbar elementpath', () => Keying.focusIn(comp));
27546
              editor.on('NodeChange', e => {
27547
                const newPath = updatePath(e.parents);
27548
                const newChildren = newPath.length > 0 ? renderPathData(newPath) : [];
27549
                Replacing.set(comp, newChildren);
27550
              });
27551
            })])
27552
        ]),
27553
        components: []
27554
      };
27555
    };
27556
 
27557
    var ResizeTypes;
27558
    (function (ResizeTypes) {
27559
      ResizeTypes[ResizeTypes['None'] = 0] = 'None';
27560
      ResizeTypes[ResizeTypes['Both'] = 1] = 'Both';
27561
      ResizeTypes[ResizeTypes['Vertical'] = 2] = 'Vertical';
27562
    }(ResizeTypes || (ResizeTypes = {})));
27563
    const getDimensions = (editor, deltas, resizeType, originalHeight, originalWidth) => {
27564
      const dimensions = { height: calcCappedSize(originalHeight + deltas.top, getMinHeightOption(editor), getMaxHeightOption(editor)) };
27565
      if (resizeType === ResizeTypes.Both) {
27566
        dimensions.width = calcCappedSize(originalWidth + deltas.left, getMinWidthOption(editor), getMaxWidthOption(editor));
27567
      }
27568
      return dimensions;
27569
    };
27570
    const resize = (editor, deltas, resizeType) => {
27571
      const container = SugarElement.fromDom(editor.getContainer());
27572
      const dimensions = getDimensions(editor, deltas, resizeType, get$d(container), get$c(container));
27573
      each(dimensions, (val, dim) => {
27574
        if (isNumber(val)) {
27575
          set$8(container, dim, numToPx(val));
27576
        }
27577
      });
27578
      fireResizeEditor(editor);
27579
    };
27580
 
27581
    const getResizeType = editor => {
27582
      const resize = getResize(editor);
27583
      if (resize === false) {
27584
        return ResizeTypes.None;
27585
      } else if (resize === 'both') {
27586
        return ResizeTypes.Both;
27587
      } else {
27588
        return ResizeTypes.Vertical;
27589
      }
27590
    };
27591
    const keyboardHandler = (editor, resizeType, x, y) => {
27592
      const scale = 20;
27593
      const delta = SugarPosition(x * scale, y * scale);
27594
      resize(editor, delta, resizeType);
27595
      return Optional.some(true);
27596
    };
27597
    const renderResizeHandler = (editor, providersBackstage) => {
27598
      const resizeType = getResizeType(editor);
27599
      if (resizeType === ResizeTypes.None) {
27600
        return Optional.none();
27601
      }
27602
      const resizeLabel = resizeType === ResizeTypes.Both ? 'Press the arrow keys to resize the editor.' : 'Press the Up and Down arrow keys to resize the editor.';
27603
      return Optional.some(render$3('resize-handle', {
27604
        tag: 'div',
27605
        classes: ['tox-statusbar__resize-handle'],
27606
        attributes: {
27607
          'title': providersBackstage.translate('Resize'),
27608
          'aria-label': providersBackstage.translate(resizeLabel)
27609
        },
27610
        behaviours: [
27611
          Dragging.config({
27612
            mode: 'mouse',
27613
            repositionTarget: false,
27614
            onDrag: (_comp, _target, delta) => resize(editor, delta, resizeType),
27615
            blockerClass: 'tox-blocker'
27616
          }),
27617
          Keying.config({
27618
            mode: 'special',
27619
            onLeft: () => keyboardHandler(editor, resizeType, -1, 0),
27620
            onRight: () => keyboardHandler(editor, resizeType, 1, 0),
27621
            onUp: () => keyboardHandler(editor, resizeType, 0, -1),
27622
            onDown: () => keyboardHandler(editor, resizeType, 0, 1)
27623
          }),
27624
          Tabstopping.config({}),
27625
          Focusing.config({})
27626
        ]
27627
      }, providersBackstage.icons));
27628
    };
27629
 
27630
    const renderWordCount = (editor, providersBackstage) => {
27631
      const replaceCountText = (comp, count, mode) => Replacing.set(comp, [text$2(providersBackstage.translate([
27632
          '{0} ' + mode,
27633
          count[mode]
27634
        ]))]);
27635
      return Button.sketch({
27636
        dom: {
27637
          tag: 'button',
27638
          classes: ['tox-statusbar__wordcount']
27639
        },
27640
        components: [],
27641
        buttonBehaviours: derive$1([
27642
          DisablingConfigs.button(providersBackstage.isDisabled),
27643
          receivingConfig(),
27644
          Tabstopping.config({}),
27645
          Replacing.config({}),
27646
          Representing.config({
27647
            store: {
27648
              mode: 'memory',
27649
              initialValue: {
27650
                mode: 'words',
27651
                count: {
27652
                  words: 0,
27653
                  characters: 0
27654
                }
27655
              }
27656
            }
27657
          }),
27658
          config('wordcount-events', [
27659
            runOnExecute$1(comp => {
27660
              const currentVal = Representing.getValue(comp);
27661
              const newMode = currentVal.mode === 'words' ? 'characters' : 'words';
27662
              Representing.setValue(comp, {
27663
                mode: newMode,
27664
                count: currentVal.count
27665
              });
27666
              replaceCountText(comp, currentVal.count, newMode);
27667
            }),
27668
            runOnAttached(comp => {
27669
              editor.on('wordCountUpdate', e => {
27670
                const {mode} = Representing.getValue(comp);
27671
                Representing.setValue(comp, {
27672
                  mode,
27673
                  count: e.wordCount
27674
                });
27675
                replaceCountText(comp, e.wordCount, mode);
27676
              });
27677
            })
27678
          ])
27679
        ]),
27680
        eventOrder: {
27681
          [execute$5()]: [
27682
            'disabling',
27683
            'alloy.base.behaviour',
27684
            'wordcount-events'
27685
          ]
27686
        }
27687
      });
27688
    };
27689
 
27690
    const renderStatusbar = (editor, providersBackstage) => {
27691
      const renderBranding = () => {
27692
        return {
27693
          dom: {
27694
            tag: 'span',
27695
            classes: ['tox-statusbar__branding']
27696
          },
27697
          components: [{
27698
              dom: {
27699
                tag: 'a',
27700
                attributes: {
27701
                  'href': 'https://www.tiny.cloud/powered-by-tiny?utm_campaign=poweredby&utm_source=tiny&utm_medium=referral&utm_content=v6',
27702
                  'rel': 'noopener',
27703
                  'target': '_blank',
27704
                  'aria-label': global$8.translate([
27705
                    'Powered by {0}',
27706
                    'Tiny'
27707
                  ])
27708
                },
27709
                innerHtml: Logo.trim()
27710
              },
27711
              behaviours: derive$1([Focusing.config({})])
27712
            }]
27713
        };
27714
      };
27715
      const renderHelpAccessibility = () => {
27716
        const shortcutText = convertText('Alt+0');
27717
        const text = `Press {0} for help`;
27718
        return {
27719
          dom: {
27720
            tag: 'div',
27721
            classes: ['tox-statusbar__help-text']
27722
          },
27723
          components: [text$2(global$8.translate([
27724
              text,
27725
              shortcutText
27726
            ]))]
27727
        };
27728
      };
27729
      const renderRightContainer = () => {
27730
        const components = [];
27731
        if (editor.hasPlugin('wordcount')) {
27732
          components.push(renderWordCount(editor, providersBackstage));
27733
        }
27734
        if (useBranding(editor)) {
27735
          components.push(renderBranding());
27736
        }
27737
        return {
27738
          dom: {
27739
            tag: 'div',
27740
            classes: ['tox-statusbar__right-container']
27741
          },
27742
          components
27743
        };
27744
      };
27745
      const getTextComponents = () => {
27746
        const components = [];
27747
        const shouldRenderHelp = useHelpAccessibility(editor);
27748
        const shouldRenderElementPath = useElementPath(editor);
27749
        const shouldRenderRightContainer = useBranding(editor) || editor.hasPlugin('wordcount');
27750
        const getTextComponentClasses = () => {
27751
          const flexStart = 'tox-statusbar__text-container--flex-start';
27752
          const flexEnd = 'tox-statusbar__text-container--flex-end';
27753
          const spaceAround = 'tox-statusbar__text-container--space-around';
27754
          if (shouldRenderHelp) {
27755
            const container3Columns = 'tox-statusbar__text-container-3-cols';
27756
            if (!shouldRenderRightContainer && !shouldRenderElementPath) {
27757
              return [
27758
                container3Columns,
27759
                spaceAround
27760
              ];
27761
            }
27762
            if (shouldRenderRightContainer && !shouldRenderElementPath) {
27763
              return [
27764
                container3Columns,
27765
                flexEnd
27766
              ];
27767
            }
27768
            return [
27769
              container3Columns,
27770
              flexStart
27771
            ];
27772
          }
27773
          return [shouldRenderRightContainer && !shouldRenderElementPath ? flexEnd : flexStart];
27774
        };
27775
        if (shouldRenderElementPath) {
27776
          components.push(renderElementPath(editor, {}, providersBackstage));
27777
        }
27778
        if (shouldRenderHelp) {
27779
          components.push(renderHelpAccessibility());
27780
        }
27781
        if (shouldRenderRightContainer) {
27782
          components.push(renderRightContainer());
27783
        }
27784
        if (components.length > 0) {
27785
          return [{
27786
              dom: {
27787
                tag: 'div',
27788
                classes: [
27789
                  'tox-statusbar__text-container',
27790
                  ...getTextComponentClasses()
27791
                ]
27792
              },
27793
              components
27794
            }];
27795
        }
27796
        return [];
27797
      };
27798
      const getComponents = () => {
27799
        const components = getTextComponents();
27800
        const resizeHandler = renderResizeHandler(editor, providersBackstage);
27801
        return components.concat(resizeHandler.toArray());
27802
      };
27803
      return {
27804
        dom: {
27805
          tag: 'div',
27806
          classes: ['tox-statusbar']
27807
        },
27808
        components: getComponents()
27809
      };
27810
    };
27811
 
27812
    const getLazyMothership = (label, singleton) => singleton.get().getOrDie(`UI for ${ label } has not been rendered`);
27813
    const setup$3 = (editor, setupForTheme) => {
27814
      const isInline = editor.inline;
27815
      const mode = isInline ? Inline : Iframe;
27816
      const header = isStickyToolbar(editor) ? StickyHeader : StaticHeader;
27817
      const lazyUiRefs = LazyUiReferences();
27818
      const lazyMothership = value$2();
27819
      const lazyDialogMothership = value$2();
27820
      const lazyPopupMothership = value$2();
27821
      const platform = detect$2();
27822
      const isTouch = platform.deviceType.isTouch();
27823
      const touchPlatformClass = 'tox-platform-touch';
27824
      const deviceClasses = isTouch ? [touchPlatformClass] : [];
27825
      const isToolbarBottom = isToolbarLocationBottom(editor);
27826
      const toolbarMode = getToolbarMode(editor);
27827
      const memAnchorBar = record({
27828
        dom: {
27829
          tag: 'div',
27830
          classes: ['tox-anchorbar']
27831
        }
27832
      });
27833
      const memBottomAnchorBar = record({
27834
        dom: {
27835
          tag: 'div',
27836
          classes: ['tox-bottom-anchorbar']
27837
        }
27838
      });
27839
      const lazyHeader = () => lazyUiRefs.mainUi.get().map(ui => ui.outerContainer).bind(OuterContainer.getHeader);
27840
      const lazyDialogSinkResult = () => Result.fromOption(lazyUiRefs.dialogUi.get().map(ui => ui.sink), 'UI has not been rendered');
27841
      const lazyPopupSinkResult = () => Result.fromOption(lazyUiRefs.popupUi.get().map(ui => ui.sink), '(popup) UI has not been rendered');
27842
      const lazyAnchorBar = lazyUiRefs.lazyGetInOuterOrDie('anchor bar', memAnchorBar.getOpt);
27843
      const lazyBottomAnchorBar = lazyUiRefs.lazyGetInOuterOrDie('bottom anchor bar', memBottomAnchorBar.getOpt);
27844
      const lazyToolbar = lazyUiRefs.lazyGetInOuterOrDie('toolbar', OuterContainer.getToolbar);
27845
      const lazyThrobber = lazyUiRefs.lazyGetInOuterOrDie('throbber', OuterContainer.getThrobber);
27846
      const backstages = init$6({
27847
        popup: lazyPopupSinkResult,
27848
        dialog: lazyDialogSinkResult
27849
      }, editor, lazyAnchorBar, lazyBottomAnchorBar);
27850
      const makeHeaderPart = () => {
27851
        const verticalDirAttributes = { attributes: { [Attribute]: isToolbarBottom ? AttributeValue.BottomToTop : AttributeValue.TopToBottom } };
27852
        const partMenubar = OuterContainer.parts.menubar({
27853
          dom: {
27854
            tag: 'div',
27855
            classes: ['tox-menubar']
27856
          },
27857
          backstage: backstages.popup,
27858
          onEscape: () => {
27859
            editor.focus();
27860
          }
27861
        });
27862
        const partToolbar = OuterContainer.parts.toolbar({
27863
          dom: {
27864
            tag: 'div',
27865
            classes: ['tox-toolbar']
27866
          },
27867
          getSink: backstages.popup.shared.getSink,
27868
          providers: backstages.popup.shared.providers,
27869
          onEscape: () => {
27870
            editor.focus();
27871
          },
27872
          onToolbarToggled: state => {
27873
            fireToggleToolbarDrawer(editor, state);
27874
          },
27875
          type: toolbarMode,
27876
          lazyToolbar,
27877
          lazyHeader: () => lazyHeader().getOrDie('Could not find header element'),
27878
          ...verticalDirAttributes
27879
        });
27880
        const partMultipleToolbar = OuterContainer.parts['multiple-toolbar']({
27881
          dom: {
27882
            tag: 'div',
27883
            classes: ['tox-toolbar-overlord']
27884
          },
27885
          providers: backstages.popup.shared.providers,
27886
          onEscape: () => {
27887
            editor.focus();
27888
          },
27889
          type: toolbarMode
27890
        });
27891
        const hasMultipleToolbar = isMultipleToolbars(editor);
27892
        const hasToolbar = isToolbarEnabled(editor);
27893
        const hasMenubar = isMenubarEnabled(editor);
27894
        const shouldHavePromotion = promotionEnabled(editor);
27895
        const partPromotion = makePromotion();
27896
        const hasAnyContents = hasMultipleToolbar || hasToolbar || hasMenubar;
27897
        const getPartToolbar = () => {
27898
          if (hasMultipleToolbar) {
27899
            return [partMultipleToolbar];
27900
          } else if (hasToolbar) {
27901
            return [partToolbar];
27902
          } else {
27903
            return [];
27904
          }
27905
        };
27906
        const menubarCollection = shouldHavePromotion ? [
27907
          partPromotion,
27908
          partMenubar
27909
        ] : [partMenubar];
27910
        return OuterContainer.parts.header({
27911
          dom: {
27912
            tag: 'div',
27913
            classes: ['tox-editor-header'].concat(hasAnyContents ? [] : ['tox-editor-header--empty']),
27914
            ...verticalDirAttributes
27915
          },
27916
          components: flatten([
27917
            hasMenubar ? menubarCollection : [],
27918
            getPartToolbar(),
27919
            useFixedContainer(editor) ? [] : [memAnchorBar.asSpec()]
27920
          ]),
27921
          sticky: isStickyToolbar(editor),
27922
          editor,
27923
          sharedBackstage: backstages.popup.shared
27924
        });
27925
      };
27926
      const makePromotion = () => {
27927
        return OuterContainer.parts.promotion({
27928
          dom: {
27929
            tag: 'div',
27930
            classes: ['tox-promotion']
27931
          }
27932
        });
27933
      };
27934
      const makeSidebarDefinition = () => {
27935
        const partSocket = OuterContainer.parts.socket({
27936
          dom: {
27937
            tag: 'div',
27938
            classes: ['tox-edit-area']
27939
          }
27940
        });
27941
        const partSidebar = OuterContainer.parts.sidebar({
27942
          dom: {
27943
            tag: 'div',
27944
            classes: ['tox-sidebar']
27945
          }
27946
        });
27947
        return {
27948
          dom: {
27949
            tag: 'div',
27950
            classes: ['tox-sidebar-wrap']
27951
          },
27952
          components: [
27953
            partSocket,
27954
            partSidebar
27955
          ]
27956
        };
27957
      };
27958
      const renderDialogUi = () => {
27959
        const uiContainer = getUiContainer(editor);
27960
        const isGridUiContainer = eq(body(), uiContainer) && get$e(uiContainer, 'display') === 'grid';
27961
        const sinkSpec = {
27962
          dom: {
27963
            tag: 'div',
27964
            classes: [
27965
              'tox',
27966
              'tox-silver-sink',
27967
              'tox-tinymce-aux'
27968
            ].concat(deviceClasses),
27969
            attributes: { ...global$8.isRtl() ? { dir: 'rtl' } : {} }
27970
          },
27971
          behaviours: derive$1([Positioning.config({ useFixed: () => header.isDocked(lazyHeader) })])
27972
        };
27973
        const reactiveWidthSpec = {
27974
          dom: { styles: { width: document.body.clientWidth + 'px' } },
27975
          events: derive$2([run$1(windowResize(), comp => {
27976
              set$8(comp.element, 'width', document.body.clientWidth + 'px');
27977
            })])
27978
        };
27979
        const sink = build$1(deepMerge(sinkSpec, isGridUiContainer ? reactiveWidthSpec : {}));
27980
        const uiMothership = takeover(sink);
27981
        lazyDialogMothership.set(uiMothership);
27982
        return {
27983
          sink,
27984
          mothership: uiMothership
27985
        };
27986
      };
27987
      const renderPopupUi = () => {
27988
        const sinkSpec = {
27989
          dom: {
27990
            tag: 'div',
27991
            classes: [
27992
              'tox',
27993
              'tox-silver-sink',
27994
              'tox-silver-popup-sink',
27995
              'tox-tinymce-aux'
27996
            ].concat(deviceClasses),
27997
            attributes: { ...global$8.isRtl() ? { dir: 'rtl' } : {} }
27998
          },
27999
          behaviours: derive$1([Positioning.config({
28000
              useFixed: () => header.isDocked(lazyHeader),
28001
              getBounds: () => setupForTheme.getPopupSinkBounds()
28002
            })])
28003
        };
28004
        const sink = build$1(sinkSpec);
28005
        const uiMothership = takeover(sink);
28006
        lazyPopupMothership.set(uiMothership);
28007
        return {
28008
          sink,
28009
          mothership: uiMothership
28010
        };
28011
      };
28012
      const renderMainUi = () => {
28013
        const partHeader = makeHeaderPart();
28014
        const sidebarContainer = makeSidebarDefinition();
28015
        const partThrobber = OuterContainer.parts.throbber({
28016
          dom: {
28017
            tag: 'div',
28018
            classes: ['tox-throbber']
28019
          },
28020
          backstage: backstages.popup
28021
        });
28022
        const partViewWrapper = OuterContainer.parts.viewWrapper({ backstage: backstages.popup });
28023
        const statusbar = useStatusBar(editor) && !isInline ? Optional.some(renderStatusbar(editor, backstages.popup.shared.providers)) : Optional.none();
28024
        const editorComponents = flatten([
28025
          isToolbarBottom ? [] : [partHeader],
28026
          isInline ? [] : [sidebarContainer],
28027
          isToolbarBottom ? [partHeader] : []
28028
        ]);
28029
        const editorContainer = OuterContainer.parts.editorContainer({
28030
          components: flatten([
28031
            editorComponents,
28032
            isInline ? [] : [
28033
              memBottomAnchorBar.asSpec(),
28034
              ...statusbar.toArray()
28035
            ]
28036
          ])
28037
        });
28038
        const isHidden = isDistractionFree(editor);
28039
        const attributes = {
28040
          role: 'application',
28041
          ...global$8.isRtl() ? { dir: 'rtl' } : {},
28042
          ...isHidden ? { 'aria-hidden': 'true' } : {}
28043
        };
28044
        const outerContainer = build$1(OuterContainer.sketch({
28045
          dom: {
28046
            tag: 'div',
28047
            classes: [
28048
              'tox',
28049
              'tox-tinymce'
28050
            ].concat(isInline ? ['tox-tinymce-inline'] : []).concat(isToolbarBottom ? ['tox-tinymce--toolbar-bottom'] : []).concat(deviceClasses),
28051
            styles: {
28052
              visibility: 'hidden',
28053
              ...isHidden ? {
28054
                opacity: '0',
28055
                border: '0'
28056
              } : {}
28057
            },
28058
            attributes
28059
          },
28060
          components: [
28061
            editorContainer,
28062
            ...isInline ? [] : [partViewWrapper],
28063
            partThrobber
28064
          ],
28065
          behaviours: derive$1([
28066
            receivingConfig(),
28067
            Disabling.config({ disableClass: 'tox-tinymce--disabled' }),
28068
            Keying.config({
28069
              mode: 'cyclic',
28070
              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'
28071
            })
28072
          ])
28073
        }));
28074
        const mothership = takeover(outerContainer);
28075
        lazyMothership.set(mothership);
28076
        return {
28077
          mothership,
28078
          outerContainer
28079
        };
28080
      };
28081
      const setEditorSize = outerContainer => {
28082
        const parsedHeight = numToPx(getHeightWithFallback(editor));
28083
        const parsedWidth = numToPx(getWidthWithFallback(editor));
28084
        if (!editor.inline) {
28085
          if (isValidValue$1('div', 'width', parsedWidth)) {
28086
            set$8(outerContainer.element, 'width', parsedWidth);
28087
          }
28088
          if (isValidValue$1('div', 'height', parsedHeight)) {
28089
            set$8(outerContainer.element, 'height', parsedHeight);
28090
          } else {
28091
            set$8(outerContainer.element, 'height', '400px');
28092
          }
28093
        }
28094
        return parsedHeight;
28095
      };
28096
      const setupShortcutsAndCommands = outerContainer => {
28097
        editor.addShortcut('alt+F9', 'focus menubar', () => {
28098
          OuterContainer.focusMenubar(outerContainer);
28099
        });
28100
        editor.addShortcut('alt+F10', 'focus toolbar', () => {
28101
          OuterContainer.focusToolbar(outerContainer);
28102
        });
28103
        editor.addCommand('ToggleToolbarDrawer', (_ui, options) => {
28104
          if (options === null || options === void 0 ? void 0 : options.skipFocus) {
28105
            OuterContainer.toggleToolbarDrawerWithoutFocusing(outerContainer);
28106
          } else {
28107
            OuterContainer.toggleToolbarDrawer(outerContainer);
28108
          }
28109
        });
28110
        editor.addQueryStateHandler('ToggleToolbarDrawer', () => OuterContainer.isToolbarDrawerToggled(outerContainer));
28111
      };
28112
      const renderUIWithRefs = uiRefs => {
28113
        const {mainUi, popupUi, uiMotherships} = uiRefs;
28114
        map$1(getToolbarGroups(editor), (toolbarGroupButtonConfig, name) => {
28115
          editor.ui.registry.addGroupToolbarButton(name, toolbarGroupButtonConfig);
28116
        });
28117
        const {buttons, menuItems, contextToolbars, sidebars, views} = editor.ui.registry.getAll();
28118
        const toolbarOpt = getMultipleToolbarsOption(editor);
28119
        const rawUiConfig = {
28120
          menuItems,
28121
          menus: getMenus(editor),
28122
          menubar: getMenubar(editor),
28123
          toolbar: toolbarOpt.getOrThunk(() => getToolbar(editor)),
28124
          allowToolbarGroups: toolbarMode === ToolbarMode$1.floating,
28125
          buttons,
28126
          sidebar: sidebars,
28127
          views
28128
        };
28129
        setupShortcutsAndCommands(mainUi.outerContainer);
28130
        setup$b(editor, mainUi.mothership, uiMotherships);
28131
        header.setup(editor, backstages.popup.shared, lazyHeader);
28132
        setup$6(editor, backstages.popup);
28133
        setup$5(editor, backstages.popup.shared.getSink, backstages.popup);
28134
        setup$8(editor);
28135
        setup$7(editor, lazyThrobber, backstages.popup.shared);
28136
        register$9(editor, contextToolbars, popupUi.sink, { backstage: backstages.popup });
28137
        setup$4(editor, popupUi.sink);
28138
        const elm = editor.getElement();
28139
        const height = setEditorSize(mainUi.outerContainer);
28140
        const args = {
28141
          targetNode: elm,
28142
          height
28143
        };
28144
        return mode.render(editor, uiRefs, rawUiConfig, backstages.popup, args);
28145
      };
28146
      const reuseDialogUiForPopuUi = dialogUi => {
28147
        lazyPopupMothership.set(dialogUi.mothership);
28148
        return dialogUi;
28149
      };
28150
      const renderUI = () => {
28151
        const mainUi = renderMainUi();
28152
        const dialogUi = renderDialogUi();
28153
        const popupUi = isSplitUiMode(editor) ? renderPopupUi() : reuseDialogUiForPopuUi(dialogUi);
28154
        lazyUiRefs.dialogUi.set(dialogUi);
28155
        lazyUiRefs.popupUi.set(popupUi);
28156
        lazyUiRefs.mainUi.set(mainUi);
28157
        const uiRefs = {
28158
          popupUi,
28159
          dialogUi,
28160
          mainUi,
28161
          uiMotherships: lazyUiRefs.getUiMotherships()
28162
        };
28163
        return renderUIWithRefs(uiRefs);
28164
      };
28165
      return {
28166
        popups: {
28167
          backstage: backstages.popup,
28168
          getMothership: () => getLazyMothership('popups', lazyPopupMothership)
28169
        },
28170
        dialogs: {
28171
          backstage: backstages.dialog,
28172
          getMothership: () => getLazyMothership('dialogs', lazyDialogMothership)
28173
        },
28174
        renderUI
28175
      };
28176
    };
28177
 
28178
    const labelledBy = (labelledElement, labelElement) => {
28179
      const labelId = getOpt(labelledElement, 'id').fold(() => {
28180
        const id = generate$6('dialog-label');
28181
        set$9(labelElement, 'id', id);
28182
        return id;
28183
      }, identity);
28184
      set$9(labelledElement, 'aria-labelledby', labelId);
28185
    };
28186
 
28187
    const schema$2 = constant$1([
28188
      required$1('lazySink'),
28189
      option$3('dragBlockClass'),
28190
      defaultedFunction('getBounds', win),
28191
      defaulted('useTabstopAt', always),
28192
      defaulted('firstTabstop', 0),
28193
      defaulted('eventOrder', {}),
28194
      field('modalBehaviours', [Keying]),
28195
      onKeyboardHandler('onExecute'),
28196
      onStrictKeyboardHandler('onEscape')
28197
    ]);
28198
    const basic = { sketch: identity };
28199
    const parts$2 = constant$1([
28200
      optional({
28201
        name: 'draghandle',
28202
        overrides: (detail, spec) => {
28203
          return {
28204
            behaviours: derive$1([Dragging.config({
28205
                mode: 'mouse',
28206
                getTarget: handle => {
28207
                  return ancestor(handle, '[role="dialog"]').getOr(handle);
28208
                },
28209
                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),
28210
                getBounds: detail.getDragBounds
28211
              })])
28212
          };
28213
        }
28214
      }),
28215
      required({
28216
        schema: [required$1('dom')],
28217
        name: 'title'
28218
      }),
28219
      required({
28220
        factory: basic,
28221
        schema: [required$1('dom')],
28222
        name: 'close'
28223
      }),
28224
      required({
28225
        factory: basic,
28226
        schema: [required$1('dom')],
28227
        name: 'body'
28228
      }),
28229
      optional({
28230
        factory: basic,
28231
        schema: [required$1('dom')],
28232
        name: 'footer'
28233
      }),
28234
      external({
28235
        factory: {
28236
          sketch: (spec, detail) => ({
28237
            ...spec,
28238
            dom: detail.dom,
28239
            components: detail.components
28240
          })
28241
        },
28242
        schema: [
28243
          defaulted('dom', {
28244
            tag: 'div',
28245
            styles: {
28246
              position: 'fixed',
28247
              left: '0px',
28248
              top: '0px',
28249
              right: '0px',
28250
              bottom: '0px'
28251
            }
28252
          }),
28253
          defaulted('components', [])
28254
        ],
28255
        name: 'blocker'
28256
      })
28257
    ]);
28258
 
28259
    const factory$4 = (detail, components, spec, externals) => {
28260
      const dialogComp = value$2();
28261
      const showDialog = dialog => {
28262
        dialogComp.set(dialog);
28263
        const sink = detail.lazySink(dialog).getOrDie();
28264
        const externalBlocker = externals.blocker();
28265
        const blocker = sink.getSystem().build({
28266
          ...externalBlocker,
28267
          components: externalBlocker.components.concat([premade(dialog)]),
28268
          behaviours: derive$1([
28269
            Focusing.config({}),
28270
            config('dialog-blocker-events', [runOnSource(focusin(), () => {
28271
                Blocking.isBlocked(dialog) ? noop() : Keying.focusIn(dialog);
28272
              })])
28273
          ])
28274
        });
28275
        attach(sink, blocker);
28276
        Keying.focusIn(dialog);
28277
      };
28278
      const hideDialog = dialog => {
28279
        dialogComp.clear();
28280
        parent(dialog.element).each(blockerDom => {
28281
          dialog.getSystem().getByDom(blockerDom).each(blocker => {
28282
            detach(blocker);
28283
          });
28284
        });
28285
      };
28286
      const getDialogBody = dialog => getPartOrDie(dialog, detail, 'body');
28287
      const getDialogFooter = dialog => getPart(dialog, detail, 'footer');
28288
      const setBusy = (dialog, getBusySpec) => {
28289
        Blocking.block(dialog, getBusySpec);
28290
      };
28291
      const setIdle = dialog => {
28292
        Blocking.unblock(dialog);
28293
      };
28294
      const modalEventsId = generate$6('modal-events');
28295
      const eventOrder = {
28296
        ...detail.eventOrder,
28297
        [attachedToDom()]: [modalEventsId].concat(detail.eventOrder['alloy.system.attached'] || [])
28298
      };
28299
      return {
28300
        uid: detail.uid,
28301
        dom: detail.dom,
28302
        components,
28303
        apis: {
28304
          show: showDialog,
28305
          hide: hideDialog,
28306
          getBody: getDialogBody,
28307
          getFooter: getDialogFooter,
28308
          setIdle,
28309
          setBusy
28310
        },
28311
        eventOrder,
28312
        domModification: {
28313
          attributes: {
28314
            'role': 'dialog',
28315
            'aria-modal': 'true'
28316
          }
28317
        },
28318
        behaviours: augment(detail.modalBehaviours, [
28319
          Replacing.config({}),
28320
          Keying.config({
28321
            mode: 'cyclic',
28322
            onEnter: detail.onExecute,
28323
            onEscape: detail.onEscape,
28324
            useTabstopAt: detail.useTabstopAt,
28325
            firstTabstop: detail.firstTabstop
28326
          }),
28327
          Blocking.config({ getRoot: dialogComp.get }),
28328
          config(modalEventsId, [runOnAttached(c => {
28329
              labelledBy(c.element, getPartOrDie(c, detail, 'title').element);
28330
            })])
28331
        ])
28332
      };
28333
    };
28334
    const ModalDialog = composite({
28335
      name: 'ModalDialog',
28336
      configFields: schema$2(),
28337
      partFields: parts$2(),
28338
      factory: factory$4,
28339
      apis: {
28340
        show: (apis, dialog) => {
28341
          apis.show(dialog);
28342
        },
28343
        hide: (apis, dialog) => {
28344
          apis.hide(dialog);
28345
        },
28346
        getBody: (apis, dialog) => apis.getBody(dialog),
28347
        getFooter: (apis, dialog) => apis.getFooter(dialog),
28348
        setBusy: (apis, dialog, getBusySpec) => {
28349
          apis.setBusy(dialog, getBusySpec);
28350
        },
28351
        setIdle: (apis, dialog) => {
28352
          apis.setIdle(dialog);
28353
        }
28354
      }
28355
    });
28356
 
28357
    const dialogToggleMenuItemSchema = objOf([
28358
      type,
28359
      name$1
28360
    ].concat(commonMenuItemFields));
28361
    const dialogToggleMenuItemDataProcessor = boolean;
28362
 
28363
    const baseFooterButtonFields = [
28364
      generatedName('button'),
28365
      optionalIcon,
28366
      defaultedStringEnum('align', 'end', [
28367
        'start',
28368
        'end'
28369
      ]),
28370
      primary,
28371
      enabled,
28372
      optionStringEnum('buttonType', [
28373
        'primary',
28374
        'secondary'
28375
      ])
28376
    ];
28377
    const dialogFooterButtonFields = [
28378
      ...baseFooterButtonFields,
28379
      text
28380
    ];
28381
    const normalFooterButtonFields = [
28382
      requiredStringEnum('type', [
28383
        'submit',
28384
        'cancel',
28385
        'custom'
28386
      ]),
28387
      ...dialogFooterButtonFields
28388
    ];
28389
    const menuFooterButtonFields = [
28390
      requiredStringEnum('type', ['menu']),
28391
      optionalText,
28392
      optionalTooltip,
28393
      optionalIcon,
28394
      requiredArrayOf('items', dialogToggleMenuItemSchema),
28395
      ...baseFooterButtonFields
28396
    ];
28397
    const toggleButtonSpecFields = [
28398
      ...baseFooterButtonFields,
28399
      requiredStringEnum('type', ['togglebutton']),
28400
      requiredString('tooltip'),
28401
      optionalIcon,
28402
      optionalText,
28403
      defaultedBoolean('active', false)
28404
    ];
28405
    const dialogFooterButtonSchema = choose$1('type', {
28406
      submit: normalFooterButtonFields,
28407
      cancel: normalFooterButtonFields,
28408
      custom: normalFooterButtonFields,
28409
      menu: menuFooterButtonFields,
28410
      togglebutton: toggleButtonSpecFields
28411
    });
28412
 
28413
    const alertBannerFields = [
28414
      type,
28415
      text,
28416
      requiredStringEnum('level', [
28417
        'info',
28418
        'warn',
28419
        'error',
28420
        'success'
28421
      ]),
28422
      icon,
28423
      defaulted('url', '')
28424
    ];
28425
    const alertBannerSchema = objOf(alertBannerFields);
28426
 
28427
    const createBarFields = itemsField => [
28428
      type,
28429
      itemsField
28430
    ];
28431
 
28432
    const buttonFields = [
28433
      type,
28434
      text,
28435
      enabled,
28436
      generatedName('button'),
28437
      optionalIcon,
28438
      borderless,
28439
      optionStringEnum('buttonType', [
28440
        'primary',
28441
        'secondary',
28442
        'toolbar'
28443
      ]),
28444
      primary
28445
    ];
28446
    const buttonSchema = objOf(buttonFields);
28447
 
28448
    const formComponentFields = [
28449
      type,
28450
      name$1
28451
    ];
28452
    const formComponentWithLabelFields = formComponentFields.concat([optionalLabel]);
28453
 
28454
    const checkboxFields = formComponentFields.concat([
28455
      label,
28456
      enabled
28457
    ]);
28458
    const checkboxSchema = objOf(checkboxFields);
28459
    const checkboxDataProcessor = boolean;
28460
 
28461
    const collectionFields = formComponentWithLabelFields.concat([defaultedColumns('auto')]);
28462
    const collectionSchema = objOf(collectionFields);
28463
    const collectionDataProcessor = arrOfObj([
28464
      value$1,
28465
      text,
28466
      icon
28467
    ]);
28468
 
28469
    const colorInputFields = formComponentWithLabelFields.concat([defaultedString('storageKey', 'default')]);
28470
    const colorInputSchema = objOf(colorInputFields);
28471
    const colorInputDataProcessor = string;
28472
 
28473
    const colorPickerFields = formComponentWithLabelFields;
28474
    const colorPickerSchema = objOf(colorPickerFields);
28475
    const colorPickerDataProcessor = string;
28476
 
28477
    const customEditorFields = formComponentFields.concat([
28478
      defaultedString('tag', 'textarea'),
28479
      requiredString('scriptId'),
28480
      requiredString('scriptUrl'),
28481
      defaultedPostMsg('settings', undefined)
28482
    ]);
28483
    const customEditorFieldsOld = formComponentFields.concat([
28484
      defaultedString('tag', 'textarea'),
28485
      requiredFunction('init')
28486
    ]);
28487
    const customEditorSchema = valueOf(v => asRaw('customeditor.old', objOfOnly(customEditorFieldsOld), v).orThunk(() => asRaw('customeditor.new', objOfOnly(customEditorFields), v)));
28488
    const customEditorDataProcessor = string;
28489
 
28490
    const dropZoneFields = formComponentWithLabelFields;
28491
    const dropZoneSchema = objOf(dropZoneFields);
28492
    const dropZoneDataProcessor = arrOfVal();
28493
 
28494
    const createGridFields = itemsField => [
28495
      type,
28496
      requiredNumber('columns'),
28497
      itemsField
28498
    ];
28499
 
28500
    const htmlPanelFields = [
28501
      type,
28502
      requiredString('html'),
28503
      defaultedStringEnum('presets', 'presentation', [
28504
        'presentation',
28505
        'document'
28506
      ])
28507
    ];
28508
    const htmlPanelSchema = objOf(htmlPanelFields);
28509
 
28510
    const iframeFields = formComponentWithLabelFields.concat([
28511
      defaultedBoolean('border', false),
28512
      defaultedBoolean('sandboxed', true),
28513
      defaultedBoolean('streamContent', false),
28514
      defaultedBoolean('transparent', true)
28515
    ]);
28516
    const iframeSchema = objOf(iframeFields);
28517
    const iframeDataProcessor = string;
28518
 
28519
    const imagePreviewSchema = objOf(formComponentFields.concat([optionString('height')]));
28520
    const imagePreviewDataProcessor = objOf([
28521
      requiredString('url'),
28522
      optionNumber('zoom'),
28523
      optionNumber('cachedWidth'),
28524
      optionNumber('cachedHeight')
28525
    ]);
28526
 
28527
    const inputFields = formComponentWithLabelFields.concat([
28528
      optionString('inputMode'),
28529
      optionString('placeholder'),
28530
      defaultedBoolean('maximized', false),
28531
      enabled
28532
    ]);
28533
    const inputSchema = objOf(inputFields);
28534
    const inputDataProcessor = string;
28535
 
28536
    const createLabelFields = itemsField => [
28537
      type,
28538
      label,
28539
      itemsField,
28540
      defaultedStringEnum('align', 'start', [
28541
        'start',
28542
        'center',
28543
        'end'
28544
      ])
28545
    ];
28546
 
28547
    const listBoxSingleItemFields = [
28548
      text,
28549
      value$1
28550
    ];
28551
    const listBoxNestedItemFields = [
28552
      text,
28553
      requiredArrayOf('items', thunkOf('items', () => listBoxItemSchema))
28554
    ];
28555
    const listBoxItemSchema = oneOf([
28556
      objOf(listBoxSingleItemFields),
28557
      objOf(listBoxNestedItemFields)
28558
    ]);
28559
    const listBoxFields = formComponentWithLabelFields.concat([
28560
      requiredArrayOf('items', listBoxItemSchema),
28561
      enabled
28562
    ]);
28563
    const listBoxSchema = objOf(listBoxFields);
28564
    const listBoxDataProcessor = string;
28565
 
28566
    const selectBoxFields = formComponentWithLabelFields.concat([
28567
      requiredArrayOfObj('items', [
28568
        text,
28569
        value$1
28570
      ]),
28571
      defaultedNumber('size', 1),
28572
      enabled
28573
    ]);
28574
    const selectBoxSchema = objOf(selectBoxFields);
28575
    const selectBoxDataProcessor = string;
28576
 
28577
    const sizeInputFields = formComponentWithLabelFields.concat([
28578
      defaultedBoolean('constrain', true),
28579
      enabled
28580
    ]);
28581
    const sizeInputSchema = objOf(sizeInputFields);
28582
    const sizeInputDataProcessor = objOf([
28583
      requiredString('width'),
28584
      requiredString('height')
28585
    ]);
28586
 
28587
    const sliderFields = formComponentFields.concat([
28588
      label,
28589
      defaultedNumber('min', 0),
28590
      defaultedNumber('max', 0)
28591
    ]);
28592
    const sliderSchema = objOf(sliderFields);
28593
    const sliderInputDataProcessor = number;
28594
 
28595
    const tableFields = [
28596
      type,
28597
      requiredArrayOf('header', string),
28598
      requiredArrayOf('cells', arrOf(string))
28599
    ];
28600
    const tableSchema = objOf(tableFields);
28601
 
28602
    const textAreaFields = formComponentWithLabelFields.concat([
28603
      optionString('placeholder'),
28604
      defaultedBoolean('maximized', false),
28605
      enabled
28606
    ]);
28607
    const textAreaSchema = objOf(textAreaFields);
28608
    const textAreaDataProcessor = string;
28609
 
28610
    const baseTreeItemFields = [
28611
      requiredStringEnum('type', [
28612
        'directory',
28613
        'leaf'
28614
      ]),
28615
      title,
28616
      requiredString('id'),
28617
      optionOf('menu', MenuButtonSchema)
28618
    ];
28619
    const treeItemLeafFields = baseTreeItemFields;
28620
    const treeItemLeafSchema = objOf(treeItemLeafFields);
28621
    const treeItemDirectoryFields = baseTreeItemFields.concat([requiredArrayOf('children', thunkOf('children', () => {
28622
        return choose$2('type', {
28623
          directory: treeItemDirectorySchema,
28624
          leaf: treeItemLeafSchema
28625
        });
28626
      }))]);
28627
    const treeItemDirectorySchema = objOf(treeItemDirectoryFields);
28628
    const treeItemSchema = choose$2('type', {
28629
      directory: treeItemDirectorySchema,
28630
      leaf: treeItemLeafSchema
28631
    });
28632
    const treeFields = [
28633
      type,
28634
      requiredArrayOf('items', treeItemSchema),
28635
      optionFunction('onLeafAction'),
28636
      optionFunction('onToggleExpand'),
28637
      defaultedArrayOf('defaultExpandedIds', [], string),
28638
      optionString('defaultSelectedId')
28639
    ];
28640
    const treeSchema = objOf(treeFields);
28641
 
28642
    const urlInputFields = formComponentWithLabelFields.concat([
28643
      defaultedStringEnum('filetype', 'file', [
28644
        'image',
28645
        'media',
28646
        'file'
28647
      ]),
28648
      enabled,
28649
      optionString('picker_text')
28650
    ]);
28651
    const urlInputSchema = objOf(urlInputFields);
28652
    const urlInputDataProcessor = objOf([
28653
      value$1,
28654
      defaultedMeta
28655
    ]);
28656
 
28657
    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)))));
28658
    const itemSchema = valueThunk(() => choose$2('type', {
28659
      alertbanner: alertBannerSchema,
28660
      bar: objOf(createBarFields(createItemsField('bar'))),
28661
      button: buttonSchema,
28662
      checkbox: checkboxSchema,
28663
      colorinput: colorInputSchema,
28664
      colorpicker: colorPickerSchema,
28665
      dropzone: dropZoneSchema,
28666
      grid: objOf(createGridFields(createItemsField('grid'))),
28667
      iframe: iframeSchema,
28668
      input: inputSchema,
28669
      listbox: listBoxSchema,
28670
      selectbox: selectBoxSchema,
28671
      sizeinput: sizeInputSchema,
28672
      slider: sliderSchema,
28673
      textarea: textAreaSchema,
28674
      urlinput: urlInputSchema,
28675
      customeditor: customEditorSchema,
28676
      htmlpanel: htmlPanelSchema,
28677
      imagepreview: imagePreviewSchema,
28678
      collection: collectionSchema,
28679
      label: objOf(createLabelFields(createItemsField('label'))),
28680
      table: tableSchema,
28681
      tree: treeSchema,
28682
      panel: panelSchema
28683
    }));
28684
    const panelFields = [
28685
      type,
28686
      defaulted('classes', []),
28687
      requiredArrayOf('items', itemSchema)
28688
    ];
28689
    const panelSchema = objOf(panelFields);
28690
 
28691
    const tabFields = [
28692
      generatedName('tab'),
28693
      title,
28694
      requiredArrayOf('items', itemSchema)
28695
    ];
28696
    const tabPanelFields = [
28697
      type,
28698
      requiredArrayOfObj('tabs', tabFields)
28699
    ];
28700
    const tabPanelSchema = objOf(tabPanelFields);
28701
 
28702
    const dialogButtonFields = dialogFooterButtonFields;
28703
    const dialogButtonSchema = dialogFooterButtonSchema;
28704
    const dialogSchema = objOf([
28705
      requiredString('title'),
28706
      requiredOf('body', choose$2('type', {
28707
        panel: panelSchema,
28708
        tabpanel: tabPanelSchema
28709
      })),
28710
      defaultedString('size', 'normal'),
28711
      defaultedArrayOf('buttons', [], dialogButtonSchema),
28712
      defaulted('initialData', {}),
28713
      defaultedFunction('onAction', noop),
28714
      defaultedFunction('onChange', noop),
28715
      defaultedFunction('onSubmit', noop),
28716
      defaultedFunction('onClose', noop),
28717
      defaultedFunction('onCancel', noop),
28718
      defaultedFunction('onTabChange', noop)
28719
    ]);
28720
    const createDialog = spec => asRaw('dialog', dialogSchema, spec);
28721
 
28722
    const urlDialogButtonSchema = objOf([
28723
      requiredStringEnum('type', [
28724
        'cancel',
28725
        'custom'
28726
      ]),
28727
      ...dialogButtonFields
28728
    ]);
28729
    const urlDialogSchema = objOf([
28730
      requiredString('title'),
28731
      requiredString('url'),
28732
      optionNumber('height'),
28733
      optionNumber('width'),
28734
      optionArrayOf('buttons', urlDialogButtonSchema),
28735
      defaultedFunction('onAction', noop),
28736
      defaultedFunction('onCancel', noop),
28737
      defaultedFunction('onClose', noop),
28738
      defaultedFunction('onMessage', noop)
28739
    ]);
28740
    const createUrlDialog = spec => asRaw('dialog', urlDialogSchema, spec);
28741
 
28742
    const getAllObjects = obj => {
28743
      if (isObject(obj)) {
28744
        return [obj].concat(bind$3(values(obj), getAllObjects));
28745
      } else if (isArray(obj)) {
28746
        return bind$3(obj, getAllObjects);
28747
      } else {
28748
        return [];
28749
      }
28750
    };
28751
 
28752
    const isNamedItem = obj => isString(obj.type) && isString(obj.name);
28753
    const dataProcessors = {
28754
      checkbox: checkboxDataProcessor,
28755
      colorinput: colorInputDataProcessor,
28756
      colorpicker: colorPickerDataProcessor,
28757
      dropzone: dropZoneDataProcessor,
28758
      input: inputDataProcessor,
28759
      iframe: iframeDataProcessor,
28760
      imagepreview: imagePreviewDataProcessor,
28761
      selectbox: selectBoxDataProcessor,
28762
      sizeinput: sizeInputDataProcessor,
28763
      slider: sliderInputDataProcessor,
28764
      listbox: listBoxDataProcessor,
28765
      size: sizeInputDataProcessor,
28766
      textarea: textAreaDataProcessor,
28767
      urlinput: urlInputDataProcessor,
28768
      customeditor: customEditorDataProcessor,
28769
      collection: collectionDataProcessor,
28770
      togglemenuitem: dialogToggleMenuItemDataProcessor
28771
    };
28772
    const getDataProcessor = item => Optional.from(dataProcessors[item.type]);
28773
    const getNamedItems = structure => filter$2(getAllObjects(structure), isNamedItem);
28774
 
28775
    const createDataValidator = structure => {
28776
      const namedItems = getNamedItems(structure);
28777
      const fields = bind$3(namedItems, item => getDataProcessor(item).fold(() => [], schema => [requiredOf(item.name, schema)]));
28778
      return objOf(fields);
28779
    };
28780
 
28781
    const extract = structure => {
28782
      var _a;
28783
      const internalDialog = getOrDie(createDialog(structure));
28784
      const dataValidator = createDataValidator(structure);
28785
      const initialData = (_a = structure.initialData) !== null && _a !== void 0 ? _a : {};
28786
      return {
28787
        internalDialog,
28788
        dataValidator,
28789
        initialData
28790
      };
28791
    };
28792
    const DialogManager = {
28793
      open: (factory, structure) => {
28794
        const extraction = extract(structure);
28795
        return factory(extraction.internalDialog, extraction.initialData, extraction.dataValidator);
28796
      },
28797
      openUrl: (factory, structure) => {
28798
        const internalDialog = getOrDie(createUrlDialog(structure));
28799
        return factory(internalDialog);
28800
      },
28801
      redial: structure => extract(structure)
28802
    };
28803
 
28804
    const events = (reflectingConfig, reflectingState) => {
28805
      const update = (component, data) => {
28806
        reflectingConfig.updateState.each(updateState => {
28807
          const newState = updateState(component, data);
28808
          reflectingState.set(newState);
28809
        });
28810
        reflectingConfig.renderComponents.each(renderComponents => {
28811
          const newComponents = renderComponents(data, reflectingState.get());
28812
          const replacer = reflectingConfig.reuseDom ? withReuse : withoutReuse;
28813
          replacer(component, newComponents);
28814
        });
28815
      };
28816
      return derive$2([
28817
        run$1(receive(), (component, message) => {
28818
          const receivingData = message;
28819
          if (!receivingData.universal) {
28820
            const channel = reflectingConfig.channel;
28821
            if (contains$2(receivingData.channels, channel)) {
28822
              update(component, receivingData.data);
28823
            }
28824
          }
28825
        }),
28826
        runOnAttached((comp, _se) => {
28827
          reflectingConfig.initialData.each(rawData => {
28828
            update(comp, rawData);
28829
          });
28830
        })
28831
      ]);
28832
    };
28833
 
28834
    var ActiveReflecting = /*#__PURE__*/Object.freeze({
28835
        __proto__: null,
28836
        events: events
28837
    });
28838
 
28839
    const getState = (component, replaceConfig, reflectState) => reflectState;
28840
 
28841
    var ReflectingApis = /*#__PURE__*/Object.freeze({
28842
        __proto__: null,
28843
        getState: getState
28844
    });
28845
 
28846
    var ReflectingSchema = [
28847
      required$1('channel'),
28848
      option$3('renderComponents'),
28849
      option$3('updateState'),
28850
      option$3('initialData'),
28851
      defaultedBoolean('reuseDom', true)
28852
    ];
28853
 
28854
    const init = () => {
28855
      const cell = Cell(Optional.none());
28856
      const clear = () => cell.set(Optional.none());
28857
      const readState = () => cell.get().getOr('none');
28858
      return {
28859
        readState,
28860
        get: cell.get,
28861
        set: cell.set,
28862
        clear
28863
      };
28864
    };
28865
 
28866
    var ReflectingState = /*#__PURE__*/Object.freeze({
28867
        __proto__: null,
28868
        init: init
28869
    });
28870
 
28871
    const Reflecting = create$4({
28872
      fields: ReflectingSchema,
28873
      name: 'reflecting',
28874
      active: ActiveReflecting,
28875
      apis: ReflectingApis,
28876
      state: ReflectingState
28877
    });
28878
 
28879
    const toValidValues = values => {
28880
      const errors = [];
28881
      const result = {};
28882
      each(values, (value, name) => {
28883
        value.fold(() => {
28884
          errors.push(name);
28885
        }, v => {
28886
          result[name] = v;
28887
        });
28888
      });
28889
      return errors.length > 0 ? Result.error(errors) : Result.value(result);
28890
    };
28891
 
28892
    const renderBodyPanel = (spec, dialogData, backstage) => {
28893
      const memForm = record(Form.sketch(parts => ({
28894
        dom: {
28895
          tag: 'div',
28896
          classes: ['tox-form'].concat(spec.classes)
28897
        },
28898
        components: map$2(spec.items, item => interpretInForm(parts, item, dialogData, backstage))
28899
      })));
28900
      return {
28901
        dom: {
28902
          tag: 'div',
28903
          classes: ['tox-dialog__body']
28904
        },
28905
        components: [{
28906
            dom: {
28907
              tag: 'div',
28908
              classes: ['tox-dialog__body-content']
28909
            },
28910
            components: [memForm.asSpec()]
28911
          }],
28912
        behaviours: derive$1([
28913
          Keying.config({
28914
            mode: 'acyclic',
28915
            useTabstopAt: not(isPseudoStop)
28916
          }),
28917
          ComposingConfigs.memento(memForm),
28918
          memento(memForm, {
28919
            postprocess: formValue => toValidValues(formValue).fold(err => {
28920
              console.error(err);
28921
              return {};
28922
            }, identity)
28923
          }),
28924
          config('dialog-body-panel', [run$1(focusin(), (comp, se) => {
28925
              comp.getSystem().broadcastOn([dialogFocusShiftedChannel], { newFocus: Optional.some(se.event.target) });
28926
            })])
28927
        ])
28928
      };
28929
    };
28930
 
28931
    const factory$3 = (detail, _spec) => ({
28932
      uid: detail.uid,
28933
      dom: detail.dom,
28934
      components: detail.components,
28935
      events: events$a(detail.action),
28936
      behaviours: augment(detail.tabButtonBehaviours, [
28937
        Focusing.config({}),
28938
        Keying.config({
28939
          mode: 'execution',
28940
          useSpace: true,
28941
          useEnter: true
28942
        }),
28943
        Representing.config({
28944
          store: {
28945
            mode: 'memory',
28946
            initialValue: detail.value
28947
          }
28948
        })
28949
      ]),
28950
      domModification: detail.domModification
28951
    });
28952
    const TabButton = single({
28953
      name: 'TabButton',
28954
      configFields: [
28955
        defaulted('uid', undefined),
28956
        required$1('value'),
28957
        field$1('dom', 'dom', mergeWithThunk(() => ({
28958
          attributes: {
28959
            'role': 'tab',
28960
            'id': generate$6('aria'),
28961
            'aria-selected': 'false'
28962
          }
28963
        })), anyValue()),
28964
        option$3('action'),
28965
        defaulted('domModification', {}),
28966
        field('tabButtonBehaviours', [
28967
          Focusing,
28968
          Keying,
28969
          Representing
28970
        ]),
28971
        required$1('view')
28972
      ],
28973
      factory: factory$3
28974
    });
28975
 
28976
    const schema$1 = constant$1([
28977
      required$1('tabs'),
28978
      required$1('dom'),
28979
      defaulted('clickToDismiss', false),
28980
      field('tabbarBehaviours', [
28981
        Highlighting,
28982
        Keying
28983
      ]),
28984
      markers$1([
28985
        'tabClass',
28986
        'selectedClass'
28987
      ])
28988
    ]);
28989
    const tabsPart = group({
28990
      factory: TabButton,
28991
      name: 'tabs',
28992
      unit: 'tab',
28993
      overrides: barDetail => {
28994
        const dismissTab$1 = (tabbar, button) => {
28995
          Highlighting.dehighlight(tabbar, button);
28996
          emitWith(tabbar, dismissTab(), {
28997
            tabbar,
28998
            button
28999
          });
29000
        };
29001
        const changeTab$1 = (tabbar, button) => {
29002
          Highlighting.highlight(tabbar, button);
29003
          emitWith(tabbar, changeTab(), {
29004
            tabbar,
29005
            button
29006
          });
29007
        };
29008
        return {
29009
          action: button => {
29010
            const tabbar = button.getSystem().getByUid(barDetail.uid).getOrDie();
29011
            const activeButton = Highlighting.isHighlighted(tabbar, button);
29012
            const response = (() => {
29013
              if (activeButton && barDetail.clickToDismiss) {
29014
                return dismissTab$1;
29015
              } else if (!activeButton) {
29016
                return changeTab$1;
29017
              } else {
29018
                return noop;
29019
              }
29020
            })();
29021
            response(tabbar, button);
29022
          },
29023
          domModification: { classes: [barDetail.markers.tabClass] }
29024
        };
29025
      }
29026
    });
29027
    const parts$1 = constant$1([tabsPart]);
29028
 
29029
    const factory$2 = (detail, components, _spec, _externals) => ({
29030
      'uid': detail.uid,
29031
      'dom': detail.dom,
29032
      components,
29033
      'debug.sketcher': 'Tabbar',
29034
      'domModification': { attributes: { role: 'tablist' } },
29035
      'behaviours': augment(detail.tabbarBehaviours, [
29036
        Highlighting.config({
29037
          highlightClass: detail.markers.selectedClass,
29038
          itemClass: detail.markers.tabClass,
29039
          onHighlight: (tabbar, tab) => {
29040
            set$9(tab.element, 'aria-selected', 'true');
29041
          },
29042
          onDehighlight: (tabbar, tab) => {
29043
            set$9(tab.element, 'aria-selected', 'false');
29044
          }
29045
        }),
29046
        Keying.config({
29047
          mode: 'flow',
29048
          getInitial: tabbar => {
29049
            return Highlighting.getHighlighted(tabbar).map(tab => tab.element);
29050
          },
29051
          selector: '.' + detail.markers.tabClass,
29052
          executeOnMove: true
29053
        })
29054
      ])
29055
    });
29056
    const Tabbar = composite({
29057
      name: 'Tabbar',
29058
      configFields: schema$1(),
29059
      partFields: parts$1(),
29060
      factory: factory$2
29061
    });
29062
 
29063
    const factory$1 = (detail, _spec) => ({
29064
      uid: detail.uid,
29065
      dom: detail.dom,
29066
      behaviours: augment(detail.tabviewBehaviours, [Replacing.config({})]),
29067
      domModification: { attributes: { role: 'tabpanel' } }
29068
    });
29069
    const Tabview = single({
29070
      name: 'Tabview',
29071
      configFields: [field('tabviewBehaviours', [Replacing])],
29072
      factory: factory$1
29073
    });
29074
 
29075
    const schema = constant$1([
29076
      defaulted('selectFirst', true),
29077
      onHandler('onChangeTab'),
29078
      onHandler('onDismissTab'),
29079
      defaulted('tabs', []),
29080
      field('tabSectionBehaviours', [])
29081
    ]);
29082
    const barPart = required({
29083
      factory: Tabbar,
29084
      schema: [
29085
        required$1('dom'),
29086
        requiredObjOf('markers', [
29087
          required$1('tabClass'),
29088
          required$1('selectedClass')
29089
        ])
29090
      ],
29091
      name: 'tabbar',
29092
      defaults: detail => {
29093
        return { tabs: detail.tabs };
29094
      }
29095
    });
29096
    const viewPart = required({
29097
      factory: Tabview,
29098
      name: 'tabview'
29099
    });
29100
    const parts = constant$1([
29101
      barPart,
29102
      viewPart
29103
    ]);
29104
 
29105
    const factory = (detail, components, _spec, _externals) => {
29106
      const changeTab$1 = button => {
29107
        const tabValue = Representing.getValue(button);
29108
        getPart(button, detail, 'tabview').each(tabview => {
29109
          const tabWithValue = find$5(detail.tabs, t => t.value === tabValue);
29110
          tabWithValue.each(tabData => {
29111
            const panel = tabData.view();
29112
            getOpt(button.element, 'id').each(id => {
29113
              set$9(tabview.element, 'aria-labelledby', id);
29114
            });
29115
            Replacing.set(tabview, panel);
29116
            detail.onChangeTab(tabview, button, panel);
29117
          });
29118
        });
29119
      };
29120
      const changeTabBy = (section, byPred) => {
29121
        getPart(section, detail, 'tabbar').each(tabbar => {
29122
          byPred(tabbar).each(emitExecute);
29123
        });
29124
      };
29125
      return {
29126
        uid: detail.uid,
29127
        dom: detail.dom,
29128
        components,
29129
        behaviours: get$3(detail.tabSectionBehaviours),
29130
        events: derive$2(flatten([
29131
          detail.selectFirst ? [runOnAttached((section, _simulatedEvent) => {
29132
              changeTabBy(section, Highlighting.getFirst);
29133
            })] : [],
29134
          [
29135
            run$1(changeTab(), (section, simulatedEvent) => {
29136
              const button = simulatedEvent.event.button;
29137
              changeTab$1(button);
29138
            }),
29139
            run$1(dismissTab(), (section, simulatedEvent) => {
29140
              const button = simulatedEvent.event.button;
29141
              detail.onDismissTab(section, button);
29142
            })
29143
          ]
29144
        ])),
29145
        apis: {
29146
          getViewItems: section => {
29147
            return getPart(section, detail, 'tabview').map(tabview => Replacing.contents(tabview)).getOr([]);
29148
          },
29149
          showTab: (section, tabKey) => {
29150
            const getTabIfNotActive = tabbar => {
29151
              const candidates = Highlighting.getCandidates(tabbar);
29152
              const optTab = find$5(candidates, c => Representing.getValue(c) === tabKey);
29153
              return optTab.filter(tab => !Highlighting.isHighlighted(tabbar, tab));
29154
            };
29155
            changeTabBy(section, getTabIfNotActive);
29156
          }
29157
        }
29158
      };
29159
    };
29160
    const TabSection = composite({
29161
      name: 'TabSection',
29162
      configFields: schema(),
29163
      partFields: parts(),
29164
      factory,
29165
      apis: {
29166
        getViewItems: (apis, component) => apis.getViewItems(component),
29167
        showTab: (apis, component, tabKey) => {
29168
          apis.showTab(component, tabKey);
29169
        }
29170
      }
29171
    });
29172
 
29173
    const measureHeights = (allTabs, tabview, tabviewComp) => map$2(allTabs, (_tab, i) => {
29174
      Replacing.set(tabviewComp, allTabs[i].view());
29175
      const rect = tabview.dom.getBoundingClientRect();
29176
      Replacing.set(tabviewComp, []);
29177
      return rect.height;
29178
    });
29179
    const getMaxHeight = heights => head(sort(heights, (a, b) => {
29180
      if (a > b) {
29181
        return -1;
29182
      } else if (a < b) {
29183
        return +1;
29184
      } else {
29185
        return 0;
29186
      }
29187
    }));
29188
    const getMaxTabviewHeight = (dialog, tabview, tablist) => {
29189
      const documentElement$1 = documentElement(dialog).dom;
29190
      const rootElm = ancestor(dialog, '.tox-dialog-wrap').getOr(dialog);
29191
      const isFixed = get$e(rootElm, 'position') === 'fixed';
29192
      let maxHeight;
29193
      if (isFixed) {
29194
        maxHeight = Math.max(documentElement$1.clientHeight, window.innerHeight);
29195
      } else {
29196
        maxHeight = Math.max(documentElement$1.offsetHeight, documentElement$1.scrollHeight);
29197
      }
29198
      const tabviewHeight = get$d(tabview);
29199
      const isTabListBeside = tabview.dom.offsetLeft >= tablist.dom.offsetLeft + get$c(tablist);
29200
      const currentTabHeight = isTabListBeside ? Math.max(get$d(tablist), tabviewHeight) : tabviewHeight;
29201
      const dialogTopMargin = parseInt(get$e(dialog, 'margin-top'), 10) || 0;
29202
      const dialogBottomMargin = parseInt(get$e(dialog, 'margin-bottom'), 10) || 0;
29203
      const dialogHeight = get$d(dialog) + dialogTopMargin + dialogBottomMargin;
29204
      const chromeHeight = dialogHeight - currentTabHeight;
29205
      return maxHeight - chromeHeight;
29206
    };
29207
    const showTab = (allTabs, comp) => {
29208
      head(allTabs).each(tab => TabSection.showTab(comp, tab.value));
29209
    };
29210
    const setTabviewHeight = (tabview, height) => {
29211
      set$8(tabview, 'height', height + 'px');
29212
      set$8(tabview, 'flex-basis', height + 'px');
29213
    };
29214
    const updateTabviewHeight = (dialogBody, tabview, maxTabHeight) => {
29215
      ancestor(dialogBody, '[role="dialog"]').each(dialog => {
29216
        descendant(dialog, '[role="tablist"]').each(tablist => {
29217
          maxTabHeight.get().map(height => {
29218
            set$8(tabview, 'height', '0');
29219
            set$8(tabview, 'flex-basis', '0');
29220
            return Math.min(height, getMaxTabviewHeight(dialog, tabview, tablist));
29221
          }).each(height => {
29222
            setTabviewHeight(tabview, height);
29223
          });
29224
        });
29225
      });
29226
    };
29227
    const getTabview = dialog => descendant(dialog, '[role="tabpanel"]');
29228
    const smartMode = allTabs => {
29229
      const maxTabHeight = value$2();
29230
      const extraEvents = [
29231
        runOnAttached(comp => {
29232
          const dialog = comp.element;
29233
          getTabview(dialog).each(tabview => {
29234
            set$8(tabview, 'visibility', 'hidden');
29235
            comp.getSystem().getByDom(tabview).toOptional().each(tabviewComp => {
29236
              const heights = measureHeights(allTabs, tabview, tabviewComp);
29237
              const maxTabHeightOpt = getMaxHeight(heights);
29238
              maxTabHeightOpt.fold(maxTabHeight.clear, maxTabHeight.set);
29239
            });
29240
            updateTabviewHeight(dialog, tabview, maxTabHeight);
29241
            remove$6(tabview, 'visibility');
29242
            showTab(allTabs, comp);
29243
            requestAnimationFrame(() => {
29244
              updateTabviewHeight(dialog, tabview, maxTabHeight);
29245
            });
29246
          });
29247
        }),
29248
        run$1(windowResize(), comp => {
29249
          const dialog = comp.element;
29250
          getTabview(dialog).each(tabview => {
29251
            updateTabviewHeight(dialog, tabview, maxTabHeight);
29252
          });
29253
        }),
29254
        run$1(formResizeEvent, (comp, _se) => {
29255
          const dialog = comp.element;
29256
          getTabview(dialog).each(tabview => {
29257
            const oldFocus = active$1(getRootNode(tabview));
29258
            set$8(tabview, 'visibility', 'hidden');
29259
            const oldHeight = getRaw(tabview, 'height').map(h => parseInt(h, 10));
29260
            remove$6(tabview, 'height');
29261
            remove$6(tabview, 'flex-basis');
29262
            const newHeight = tabview.dom.getBoundingClientRect().height;
29263
            const hasGrown = oldHeight.forall(h => newHeight > h);
29264
            if (hasGrown) {
29265
              maxTabHeight.set(newHeight);
29266
              updateTabviewHeight(dialog, tabview, maxTabHeight);
29267
            } else {
29268
              oldHeight.each(h => {
29269
                setTabviewHeight(tabview, h);
29270
              });
29271
            }
29272
            remove$6(tabview, 'visibility');
29273
            oldFocus.each(focus$3);
29274
          });
29275
        })
29276
      ];
29277
      const selectFirst = false;
29278
      return {
29279
        extraEvents,
29280
        selectFirst
29281
      };
29282
    };
29283
 
29284
    const SendDataToSectionChannel = 'send-data-to-section';
29285
    const SendDataToViewChannel = 'send-data-to-view';
29286
    const renderTabPanel = (spec, dialogData, backstage) => {
29287
      const storedValue = Cell({});
29288
      const updateDataWithForm = form => {
29289
        const formData = Representing.getValue(form);
29290
        const validData = toValidValues(formData).getOr({});
29291
        const currentData = storedValue.get();
29292
        const newData = deepMerge(currentData, validData);
29293
        storedValue.set(newData);
29294
      };
29295
      const setDataOnForm = form => {
29296
        const tabData = storedValue.get();
29297
        Representing.setValue(form, tabData);
29298
      };
29299
      const oldTab = Cell(null);
29300
      const allTabs = map$2(spec.tabs, tab => {
29301
        return {
29302
          value: tab.name,
29303
          dom: {
29304
            tag: 'div',
29305
            classes: ['tox-dialog__body-nav-item']
29306
          },
29307
          components: [text$2(backstage.shared.providers.translate(tab.title))],
29308
          view: () => {
29309
            return [Form.sketch(parts => ({
29310
                dom: {
29311
                  tag: 'div',
29312
                  classes: ['tox-form']
29313
                },
29314
                components: map$2(tab.items, item => interpretInForm(parts, item, dialogData, backstage)),
29315
                formBehaviours: derive$1([
29316
                  Keying.config({
29317
                    mode: 'acyclic',
29318
                    useTabstopAt: not(isPseudoStop)
29319
                  }),
29320
                  config('TabView.form.events', [
29321
                    runOnAttached(setDataOnForm),
29322
                    runOnDetached(updateDataWithForm)
29323
                  ]),
29324
                  Receiving.config({
29325
                    channels: wrapAll([
29326
                      {
29327
                        key: SendDataToSectionChannel,
29328
                        value: { onReceive: updateDataWithForm }
29329
                      },
29330
                      {
29331
                        key: SendDataToViewChannel,
29332
                        value: { onReceive: setDataOnForm }
29333
                      }
29334
                    ])
29335
                  })
29336
                ])
29337
              }))];
29338
          }
29339
        };
29340
      });
29341
      const tabMode = smartMode(allTabs);
29342
      return TabSection.sketch({
29343
        dom: {
29344
          tag: 'div',
29345
          classes: ['tox-dialog__body']
29346
        },
29347
        onChangeTab: (section, button, _viewItems) => {
29348
          const name = Representing.getValue(button);
29349
          emitWith(section, formTabChangeEvent, {
29350
            name,
29351
            oldName: oldTab.get()
29352
          });
29353
          oldTab.set(name);
29354
        },
29355
        tabs: allTabs,
29356
        components: [
29357
          TabSection.parts.tabbar({
29358
            dom: {
29359
              tag: 'div',
29360
              classes: ['tox-dialog__body-nav']
29361
            },
29362
            components: [Tabbar.parts.tabs({})],
29363
            markers: {
29364
              tabClass: 'tox-tab',
29365
              selectedClass: 'tox-dialog__body-nav-item--active'
29366
            },
29367
            tabbarBehaviours: derive$1([Tabstopping.config({})])
29368
          }),
29369
          TabSection.parts.tabview({
29370
            dom: {
29371
              tag: 'div',
29372
              classes: ['tox-dialog__body-content']
29373
            }
29374
          })
29375
        ],
29376
        selectFirst: tabMode.selectFirst,
29377
        tabSectionBehaviours: derive$1([
29378
          config('tabpanel', tabMode.extraEvents),
29379
          Keying.config({ mode: 'acyclic' }),
29380
          Composing.config({ find: comp => head(TabSection.getViewItems(comp)) }),
29381
          withComp(Optional.none(), tsection => {
29382
            tsection.getSystem().broadcastOn([SendDataToSectionChannel], {});
29383
            return storedValue.get();
29384
          }, (tsection, value) => {
29385
            storedValue.set(value);
29386
            tsection.getSystem().broadcastOn([SendDataToViewChannel], {});
29387
          })
29388
        ])
29389
      });
29390
    };
29391
 
29392
    const renderBody = (spec, dialogId, contentId, backstage, ariaAttrs) => {
29393
      const renderComponents = incoming => {
29394
        const body = incoming.body;
29395
        switch (body.type) {
29396
        case 'tabpanel': {
29397
            return [renderTabPanel(body, incoming.initialData, backstage)];
29398
          }
29399
        default: {
29400
            return [renderBodyPanel(body, incoming.initialData, backstage)];
29401
          }
29402
        }
29403
      };
29404
      const updateState = (_comp, incoming) => Optional.some({ isTabPanel: () => incoming.body.type === 'tabpanel' });
29405
      const ariaAttributes = { 'aria-live': 'polite' };
29406
      return {
29407
        dom: {
29408
          tag: 'div',
29409
          classes: ['tox-dialog__content-js'],
29410
          attributes: {
29411
            ...contentId.map(x => ({ id: x })).getOr({}),
29412
            ...ariaAttrs ? ariaAttributes : {}
29413
          }
29414
        },
29415
        components: [],
29416
        behaviours: derive$1([
29417
          ComposingConfigs.childAt(0),
29418
          Reflecting.config({
29419
            channel: `${ bodyChannel }-${ dialogId }`,
29420
            updateState,
29421
            renderComponents,
29422
            initialData: spec
29423
          })
29424
        ])
29425
      };
29426
    };
29427
    const renderInlineBody = (spec, dialogId, contentId, backstage, ariaAttrs) => renderBody(spec, dialogId, Optional.some(contentId), backstage, ariaAttrs);
29428
    const renderModalBody = (spec, dialogId, backstage) => {
29429
      const bodySpec = renderBody(spec, dialogId, Optional.none(), backstage, false);
29430
      return ModalDialog.parts.body(bodySpec);
29431
    };
29432
    const renderIframeBody = spec => {
29433
      const bodySpec = {
29434
        dom: {
29435
          tag: 'div',
29436
          classes: ['tox-dialog__content-js']
29437
        },
29438
        components: [{
29439
            dom: {
29440
              tag: 'div',
29441
              classes: ['tox-dialog__body-iframe']
29442
            },
29443
            components: [craft(Optional.none(), {
29444
                dom: {
29445
                  tag: 'iframe',
29446
                  attributes: { src: spec.url }
29447
                },
29448
                behaviours: derive$1([
29449
                  Tabstopping.config({}),
29450
                  Focusing.config({})
29451
                ])
29452
              })]
29453
          }],
29454
        behaviours: derive$1([Keying.config({
29455
            mode: 'acyclic',
29456
            useTabstopAt: not(isPseudoStop)
29457
          })])
29458
      };
29459
      return ModalDialog.parts.body(bodySpec);
29460
    };
29461
 
29462
    const isTouch = global$5.deviceType.isTouch();
29463
    const hiddenHeader = (title, close) => ({
29464
      dom: {
29465
        tag: 'div',
29466
        styles: { display: 'none' },
29467
        classes: ['tox-dialog__header']
29468
      },
29469
      components: [
29470
        title,
29471
        close
29472
      ]
29473
    });
29474
    const pClose = (onClose, providersBackstage) => ModalDialog.parts.close(Button.sketch({
29475
      dom: {
29476
        tag: 'button',
29477
        classes: [
29478
          'tox-button',
29479
          'tox-button--icon',
29480
          'tox-button--naked'
29481
        ],
29482
        attributes: {
29483
          'type': 'button',
29484
          'aria-label': providersBackstage.translate('Close')
29485
        }
29486
      },
29487
      action: onClose,
29488
      buttonBehaviours: derive$1([Tabstopping.config({})])
29489
    }));
29490
    const pUntitled = () => ModalDialog.parts.title({
29491
      dom: {
29492
        tag: 'div',
29493
        classes: ['tox-dialog__title'],
29494
        innerHtml: '',
29495
        styles: { display: 'none' }
29496
      }
29497
    });
29498
    const pBodyMessage = (message, providersBackstage) => ModalDialog.parts.body({
29499
      dom: {
29500
        tag: 'div',
29501
        classes: ['tox-dialog__body']
29502
      },
29503
      components: [{
29504
          dom: {
29505
            tag: 'div',
29506
            classes: ['tox-dialog__body-content']
29507
          },
29508
          components: [{ dom: fromHtml(`<p>${ sanitizeHtmlString(providersBackstage.translate(message)) }</p>`) }]
29509
        }]
29510
    });
29511
    const pFooter = buttons => ModalDialog.parts.footer({
29512
      dom: {
29513
        tag: 'div',
29514
        classes: ['tox-dialog__footer']
29515
      },
29516
      components: buttons
29517
    });
29518
    const pFooterGroup = (startButtons, endButtons) => [
29519
      Container.sketch({
29520
        dom: {
29521
          tag: 'div',
29522
          classes: ['tox-dialog__footer-start']
29523
        },
29524
        components: startButtons
29525
      }),
29526
      Container.sketch({
29527
        dom: {
29528
          tag: 'div',
29529
          classes: ['tox-dialog__footer-end']
29530
        },
29531
        components: endButtons
29532
      })
29533
    ];
29534
    const renderDialog$1 = spec => {
29535
      const dialogClass = 'tox-dialog';
29536
      const blockerClass = dialogClass + '-wrap';
29537
      const blockerBackdropClass = blockerClass + '__backdrop';
29538
      const scrollLockClass = dialogClass + '__disable-scroll';
29539
      return ModalDialog.sketch({
29540
        lazySink: spec.lazySink,
29541
        onEscape: comp => {
29542
          spec.onEscape(comp);
29543
          return Optional.some(true);
29544
        },
29545
        useTabstopAt: elem => !isPseudoStop(elem),
29546
        firstTabstop: spec.firstTabstop,
29547
        dom: {
29548
          tag: 'div',
29549
          classes: [dialogClass].concat(spec.extraClasses),
29550
          styles: {
29551
            position: 'relative',
29552
            ...spec.extraStyles
29553
          }
29554
        },
29555
        components: [
29556
          spec.header,
29557
          spec.body,
29558
          ...spec.footer.toArray()
29559
        ],
29560
        parts: {
29561
          blocker: {
29562
            dom: fromHtml(`<div class="${ blockerClass }"></div>`),
29563
            components: [{
29564
                dom: {
29565
                  tag: 'div',
29566
                  classes: isTouch ? [
29567
                    blockerBackdropClass,
29568
                    blockerBackdropClass + '--opaque'
29569
                  ] : [blockerBackdropClass]
29570
                }
29571
              }]
29572
          }
29573
        },
29574
        dragBlockClass: blockerClass,
29575
        modalBehaviours: derive$1([
29576
          Focusing.config({}),
29577
          config('dialog-events', spec.dialogEvents.concat([
29578
            runOnSource(focusin(), (comp, _se) => {
29579
              Blocking.isBlocked(comp) ? noop() : Keying.focusIn(comp);
29580
            }),
29581
            run$1(focusShifted(), (comp, se) => {
29582
              comp.getSystem().broadcastOn([dialogFocusShiftedChannel], { newFocus: se.event.newFocus });
29583
            })
29584
          ])),
29585
          config('scroll-lock', [
29586
            runOnAttached(() => {
29587
              add$2(body(), scrollLockClass);
29588
            }),
29589
            runOnDetached(() => {
29590
              remove$2(body(), scrollLockClass);
29591
            })
29592
          ]),
29593
          ...spec.extraBehaviours
29594
        ]),
29595
        eventOrder: {
29596
          [execute$5()]: ['dialog-events'],
29597
          [attachedToDom()]: [
29598
            'scroll-lock',
29599
            'dialog-events',
29600
            'alloy.base.behaviour'
29601
          ],
29602
          [detachedFromDom()]: [
29603
            'alloy.base.behaviour',
29604
            'dialog-events',
29605
            'scroll-lock'
29606
          ],
29607
          ...spec.eventOrder
29608
        }
29609
      });
29610
    };
29611
 
29612
    const renderClose = providersBackstage => Button.sketch({
29613
      dom: {
29614
        tag: 'button',
29615
        classes: [
29616
          'tox-button',
29617
          'tox-button--icon',
29618
          'tox-button--naked'
29619
        ],
29620
        attributes: {
29621
          'type': 'button',
29622
          'aria-label': providersBackstage.translate('Close'),
29623
          'title': providersBackstage.translate('Close')
29624
        }
29625
      },
29626
      buttonBehaviours: derive$1([Tabstopping.config({})]),
29627
      components: [render$3('close', {
29628
          tag: 'span',
29629
          classes: ['tox-icon']
29630
        }, providersBackstage.icons)],
29631
      action: comp => {
29632
        emit(comp, formCancelEvent);
29633
      }
29634
    });
29635
    const renderTitle = (spec, dialogId, titleId, providersBackstage) => {
29636
      const renderComponents = data => [text$2(providersBackstage.translate(data.title))];
29637
      return {
29638
        dom: {
29639
          tag: 'div',
29640
          classes: ['tox-dialog__title'],
29641
          attributes: { ...titleId.map(x => ({ id: x })).getOr({}) }
29642
        },
29643
        components: [],
29644
        behaviours: derive$1([Reflecting.config({
29645
            channel: `${ titleChannel }-${ dialogId }`,
29646
            initialData: spec,
29647
            renderComponents
29648
          })])
29649
      };
29650
    };
29651
    const renderDragHandle = () => ({ dom: fromHtml('<div class="tox-dialog__draghandle"></div>') });
29652
    const renderInlineHeader = (spec, dialogId, titleId, providersBackstage) => Container.sketch({
29653
      dom: fromHtml('<div class="tox-dialog__header"></div>'),
29654
      components: [
29655
        renderTitle(spec, dialogId, Optional.some(titleId), providersBackstage),
29656
        renderDragHandle(),
29657
        renderClose(providersBackstage)
29658
      ],
29659
      containerBehaviours: derive$1([Dragging.config({
29660
          mode: 'mouse',
29661
          blockerClass: 'blocker',
29662
          getTarget: handle => {
29663
            return closest$1(handle, '[role="dialog"]').getOrDie();
29664
          },
29665
          snaps: {
29666
            getSnapPoints: () => [],
29667
            leftAttr: 'data-drag-left',
29668
            topAttr: 'data-drag-top'
29669
          }
29670
        })])
29671
    });
29672
    const renderModalHeader = (spec, dialogId, providersBackstage) => {
29673
      const pTitle = ModalDialog.parts.title(renderTitle(spec, dialogId, Optional.none(), providersBackstage));
29674
      const pHandle = ModalDialog.parts.draghandle(renderDragHandle());
29675
      const pClose = ModalDialog.parts.close(renderClose(providersBackstage));
29676
      const components = [pTitle].concat(spec.draggable ? [pHandle] : []).concat([pClose]);
29677
      return Container.sketch({
29678
        dom: fromHtml('<div class="tox-dialog__header"></div>'),
29679
        components
29680
      });
29681
    };
29682
 
29683
    const getHeader = (title, dialogId, backstage) => renderModalHeader({
29684
      title: backstage.shared.providers.translate(title),
29685
      draggable: backstage.dialog.isDraggableModal()
29686
    }, dialogId, backstage.shared.providers);
29687
    const getBusySpec = (message, bs, providers, headerHeight) => ({
29688
      dom: {
29689
        tag: 'div',
29690
        classes: ['tox-dialog__busy-spinner'],
29691
        attributes: { 'aria-label': providers.translate(message) },
29692
        styles: {
29693
          left: '0px',
29694
          right: '0px',
29695
          bottom: '0px',
29696
          top: `${ headerHeight.getOr(0) }px`,
29697
          position: 'absolute'
29698
        }
29699
      },
29700
      behaviours: bs,
29701
      components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
29702
    });
29703
    const getEventExtras = (lazyDialog, providers, extra) => ({
29704
      onClose: () => extra.closeWindow(),
29705
      onBlock: blockEvent => {
29706
        const headerHeight = descendant(lazyDialog().element, '.tox-dialog__header').map(header => get$d(header));
29707
        ModalDialog.setBusy(lazyDialog(), (_comp, bs) => getBusySpec(blockEvent.message, bs, providers, headerHeight));
29708
      },
29709
      onUnblock: () => {
29710
        ModalDialog.setIdle(lazyDialog());
29711
      }
29712
    });
29713
    const fullscreenClass = 'tox-dialog--fullscreen';
29714
    const largeDialogClass = 'tox-dialog--width-lg';
29715
    const mediumDialogClass = 'tox-dialog--width-md';
29716
    const getDialogSizeClass = size => {
29717
      switch (size) {
29718
      case 'large':
29719
        return Optional.some(largeDialogClass);
29720
      case 'medium':
29721
        return Optional.some(mediumDialogClass);
29722
      default:
29723
        return Optional.none();
29724
      }
29725
    };
29726
    const updateDialogSizeClass = (size, component) => {
29727
      const dialogBody = SugarElement.fromDom(component.element.dom);
29728
      if (!has(dialogBody, fullscreenClass)) {
29729
        remove$1(dialogBody, [
29730
          largeDialogClass,
29731
          mediumDialogClass
29732
        ]);
29733
        getDialogSizeClass(size).each(dialogSizeClass => add$2(dialogBody, dialogSizeClass));
29734
      }
29735
    };
29736
    const toggleFullscreen = (comp, currentSize) => {
29737
      const dialogBody = SugarElement.fromDom(comp.element.dom);
29738
      const classes = get$7(dialogBody);
29739
      const currentSizeClass = find$5(classes, c => c === largeDialogClass || c === mediumDialogClass).or(getDialogSizeClass(currentSize));
29740
      toggle$3(dialogBody, [
29741
        fullscreenClass,
29742
        ...currentSizeClass.toArray()
29743
      ]);
29744
    };
29745
    const renderModalDialog = (spec, dialogEvents, backstage) => build$1(renderDialog$1({
29746
      ...spec,
29747
      firstTabstop: 1,
29748
      lazySink: backstage.shared.getSink,
29749
      extraBehaviours: [
29750
        memory({}),
29751
        ...spec.extraBehaviours
29752
      ],
29753
      onEscape: comp => {
29754
        emit(comp, formCancelEvent);
29755
      },
29756
      dialogEvents,
29757
      eventOrder: {
29758
        [receive()]: [
29759
          Reflecting.name(),
29760
          Receiving.name()
29761
        ],
29762
        [attachedToDom()]: [
29763
          'scroll-lock',
29764
          Reflecting.name(),
29765
          'messages',
29766
          'dialog-events',
29767
          'alloy.base.behaviour'
29768
        ],
29769
        [detachedFromDom()]: [
29770
          'alloy.base.behaviour',
29771
          'dialog-events',
29772
          'messages',
29773
          Reflecting.name(),
29774
          'scroll-lock'
29775
        ]
29776
      }
29777
    }));
29778
    const mapMenuButtons = (buttons, menuItemStates = {}) => {
29779
      const mapItems = button => {
29780
        const items = map$2(button.items, item => {
29781
          const cell = get$g(menuItemStates, item.name).getOr(Cell(false));
29782
          return {
29783
            ...item,
29784
            storage: cell
29785
          };
29786
        });
29787
        return {
29788
          ...button,
29789
          items
29790
        };
29791
      };
29792
      return map$2(buttons, button => {
29793
        return button.type === 'menu' ? mapItems(button) : button;
29794
      });
29795
    };
29796
    const extractCellsToObject = buttons => foldl(buttons, (acc, button) => {
29797
      if (button.type === 'menu') {
29798
        const menuButton = button;
29799
        return foldl(menuButton.items, (innerAcc, item) => {
29800
          innerAcc[item.name] = item.storage;
29801
          return innerAcc;
29802
        }, acc);
29803
      }
29804
      return acc;
29805
    }, {});
29806
 
29807
    const initCommonEvents = (fireApiEvent, extras) => [
29808
      runWithTarget(focusin(), onFocus),
29809
      fireApiEvent(formCloseEvent, (_api, spec, _event, self) => {
29810
        active$1(getRootNode(self.element)).fold(noop, blur$1);
29811
        extras.onClose();
29812
        spec.onClose();
29813
      }),
29814
      fireApiEvent(formCancelEvent, (api, spec, _event, self) => {
29815
        spec.onCancel(api);
29816
        emit(self, formCloseEvent);
29817
      }),
29818
      run$1(formUnblockEvent, (_c, _se) => extras.onUnblock()),
29819
      run$1(formBlockEvent, (_c, se) => extras.onBlock(se.event))
29820
    ];
29821
    const initUrlDialog = (getInstanceApi, extras) => {
29822
      const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
29823
        withSpec(c, (spec, _c) => {
29824
          f(getInstanceApi(), spec, se.event, c);
29825
        });
29826
      });
29827
      const withSpec = (c, f) => {
29828
        Reflecting.getState(c).get().each(currentDialog => {
29829
          f(currentDialog, c);
29830
        });
29831
      };
29832
      return [
29833
        ...initCommonEvents(fireApiEvent, extras),
29834
        fireApiEvent(formActionEvent, (api, spec, event) => {
29835
          spec.onAction(api, { name: event.name });
29836
        })
29837
      ];
29838
    };
29839
    const initDialog = (getInstanceApi, extras, getSink) => {
29840
      const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
29841
        withSpec(c, (spec, _c) => {
29842
          f(getInstanceApi(), spec, se.event, c);
29843
        });
29844
      });
29845
      const withSpec = (c, f) => {
29846
        Reflecting.getState(c).get().each(currentDialogInit => {
29847
          f(currentDialogInit.internalDialog, c);
29848
        });
29849
      };
29850
      return [
29851
        ...initCommonEvents(fireApiEvent, extras),
29852
        fireApiEvent(formSubmitEvent, (api, spec) => spec.onSubmit(api)),
29853
        fireApiEvent(formChangeEvent, (api, spec, event) => {
29854
          spec.onChange(api, { name: event.name });
29855
        }),
29856
        fireApiEvent(formActionEvent, (api, spec, event, component) => {
29857
          const focusIn = () => component.getSystem().isConnected() ? Keying.focusIn(component) : undefined;
29858
          const isDisabled = focused => has$1(focused, 'disabled') || getOpt(focused, 'aria-disabled').exists(val => val === 'true');
29859
          const rootNode = getRootNode(component.element);
29860
          const current = active$1(rootNode);
29861
          spec.onAction(api, {
29862
            name: event.name,
29863
            value: event.value
29864
          });
29865
          active$1(rootNode).fold(focusIn, focused => {
29866
            if (isDisabled(focused)) {
29867
              focusIn();
29868
            } else if (current.exists(cur => contains(focused, cur) && isDisabled(cur))) {
29869
              focusIn();
29870
            } else {
29871
              getSink().toOptional().filter(sink => !contains(sink.element, focused)).each(focusIn);
29872
            }
29873
          });
29874
        }),
29875
        fireApiEvent(formTabChangeEvent, (api, spec, event) => {
29876
          spec.onTabChange(api, {
29877
            newTabName: event.name,
29878
            oldTabName: event.oldName
29879
          });
29880
        }),
29881
        runOnDetached(component => {
29882
          const api = getInstanceApi();
29883
          Representing.setValue(component, api.getData());
29884
        })
29885
      ];
29886
    };
29887
 
29888
    const makeButton = (button, backstage) => renderFooterButton(button, button.type, backstage);
29889
    const lookup = (compInSystem, footerButtons, buttonName) => find$5(footerButtons, button => button.name === buttonName).bind(memButton => memButton.memento.getOpt(compInSystem));
29890
    const renderComponents = (_data, state) => {
29891
      const footerButtons = state.map(s => s.footerButtons).getOr([]);
29892
      const buttonGroups = partition$3(footerButtons, button => button.align === 'start');
29893
      const makeGroup = (edge, buttons) => Container.sketch({
29894
        dom: {
29895
          tag: 'div',
29896
          classes: [`tox-dialog__footer-${ edge }`]
29897
        },
29898
        components: map$2(buttons, button => button.memento.asSpec())
29899
      });
29900
      const startButtons = makeGroup('start', buttonGroups.pass);
29901
      const endButtons = makeGroup('end', buttonGroups.fail);
29902
      return [
29903
        startButtons,
29904
        endButtons
29905
      ];
29906
    };
29907
    const renderFooter = (initSpec, dialogId, backstage) => {
29908
      const updateState = (comp, data) => {
29909
        const footerButtons = map$2(data.buttons, button => {
29910
          const memButton = record(makeButton(button, backstage));
29911
          return {
29912
            name: button.name,
29913
            align: button.align,
29914
            memento: memButton
29915
          };
29916
        });
29917
        const lookupByName = buttonName => lookup(comp, footerButtons, buttonName);
29918
        return Optional.some({
29919
          lookupByName,
29920
          footerButtons
29921
        });
29922
      };
29923
      return {
29924
        dom: fromHtml('<div class="tox-dialog__footer"></div>'),
29925
        components: [],
29926
        behaviours: derive$1([Reflecting.config({
29927
            channel: `${ footerChannel }-${ dialogId }`,
29928
            initialData: initSpec,
29929
            updateState,
29930
            renderComponents
29931
          })])
29932
      };
29933
    };
29934
    const renderInlineFooter = (initSpec, dialogId, backstage) => renderFooter(initSpec, dialogId, backstage);
29935
    const renderModalFooter = (initSpec, dialogId, backstage) => ModalDialog.parts.footer(renderFooter(initSpec, dialogId, backstage));
29936
 
29937
    const getCompByName = (access, name) => {
29938
      const root = access.getRoot();
29939
      if (root.getSystem().isConnected()) {
29940
        const form = Composing.getCurrent(access.getFormWrapper()).getOr(access.getFormWrapper());
29941
        return Form.getField(form, name).orThunk(() => {
29942
          const footer = access.getFooter();
29943
          const footerState = footer.bind(f => Reflecting.getState(f).get());
29944
          return footerState.bind(f => f.lookupByName(name));
29945
        });
29946
      } else {
29947
        return Optional.none();
29948
      }
29949
    };
29950
    const validateData$1 = (access, data) => {
29951
      const root = access.getRoot();
29952
      return Reflecting.getState(root).get().map(dialogState => getOrDie(asRaw('data', dialogState.dataValidator, data))).getOr(data);
29953
    };
29954
    const getDialogApi = (access, doRedial, menuItemStates) => {
29955
      const withRoot = f => {
29956
        const root = access.getRoot();
29957
        if (root.getSystem().isConnected()) {
29958
          f(root);
29959
        }
29960
      };
29961
      const getData = () => {
29962
        const root = access.getRoot();
29963
        const valueComp = root.getSystem().isConnected() ? access.getFormWrapper() : root;
29964
        const representedValues = Representing.getValue(valueComp);
29965
        const menuItemCurrentState = map$1(menuItemStates, cell => cell.get());
29966
        return {
29967
          ...representedValues,
29968
          ...menuItemCurrentState
29969
        };
29970
      };
29971
      const setData = newData => {
29972
        withRoot(_ => {
29973
          const prevData = instanceApi.getData();
29974
          const mergedData = deepMerge(prevData, newData);
29975
          const newInternalData = validateData$1(access, mergedData);
29976
          const form = access.getFormWrapper();
29977
          Representing.setValue(form, newInternalData);
29978
          each(menuItemStates, (v, k) => {
29979
            if (has$2(mergedData, k)) {
29980
              v.set(mergedData[k]);
29981
            }
29982
          });
29983
        });
29984
      };
29985
      const setEnabled = (name, state) => {
29986
        getCompByName(access, name).each(state ? Disabling.enable : Disabling.disable);
29987
      };
29988
      const focus = name => {
29989
        getCompByName(access, name).each(Focusing.focus);
29990
      };
29991
      const block = message => {
29992
        if (!isString(message)) {
29993
          throw new Error('The dialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
29994
        }
29995
        withRoot(root => {
29996
          emitWith(root, formBlockEvent, { message });
29997
        });
29998
      };
29999
      const unblock = () => {
30000
        withRoot(root => {
30001
          emit(root, formUnblockEvent);
30002
        });
30003
      };
30004
      const showTab = name => {
30005
        withRoot(_ => {
30006
          const body = access.getBody();
30007
          const bodyState = Reflecting.getState(body);
30008
          if (bodyState.get().exists(b => b.isTabPanel())) {
30009
            Composing.getCurrent(body).each(tabSection => {
30010
              TabSection.showTab(tabSection, name);
30011
            });
30012
          }
30013
        });
30014
      };
30015
      const redial = d => {
30016
        withRoot(root => {
30017
          const id = access.getId();
30018
          const dialogInit = doRedial(d);
30019
          const storedMenuButtons = mapMenuButtons(dialogInit.internalDialog.buttons, menuItemStates);
30020
          root.getSystem().broadcastOn([`${ dialogChannel }-${ id }`], dialogInit);
30021
          root.getSystem().broadcastOn([`${ titleChannel }-${ id }`], dialogInit.internalDialog);
30022
          root.getSystem().broadcastOn([`${ bodyChannel }-${ id }`], dialogInit.internalDialog);
30023
          root.getSystem().broadcastOn([`${ footerChannel }-${ id }`], {
30024
            ...dialogInit.internalDialog,
30025
            buttons: storedMenuButtons
30026
          });
30027
          instanceApi.setData(dialogInit.initialData);
30028
        });
30029
      };
30030
      const close = () => {
30031
        withRoot(root => {
30032
          emit(root, formCloseEvent);
30033
        });
30034
      };
30035
      const instanceApi = {
30036
        getData,
30037
        setData,
30038
        setEnabled,
30039
        focus,
30040
        block,
30041
        unblock,
30042
        showTab,
30043
        redial,
30044
        close,
30045
        toggleFullscreen: access.toggleFullscreen
30046
      };
30047
      return instanceApi;
30048
    };
30049
 
30050
    const renderDialog = (dialogInit, extra, backstage) => {
30051
      const dialogId = generate$6('dialog');
30052
      const internalDialog = dialogInit.internalDialog;
30053
      const header = getHeader(internalDialog.title, dialogId, backstage);
30054
      const dialogSize = Cell(internalDialog.size);
30055
      const dialogSizeClasses = getDialogSizeClass(dialogSize.get()).toArray();
30056
      const updateState = (comp, incoming) => {
30057
        dialogSize.set(incoming.internalDialog.size);
30058
        updateDialogSizeClass(incoming.internalDialog.size, comp);
30059
        return Optional.some(incoming);
30060
      };
30061
      const body = renderModalBody({
30062
        body: internalDialog.body,
30063
        initialData: internalDialog.initialData
30064
      }, dialogId, backstage);
30065
      const storedMenuButtons = mapMenuButtons(internalDialog.buttons);
30066
      const objOfCells = extractCellsToObject(storedMenuButtons);
30067
      const footer = someIf(storedMenuButtons.length !== 0, renderModalFooter({ buttons: storedMenuButtons }, dialogId, backstage));
30068
      const dialogEvents = initDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra), backstage.shared.getSink);
30069
      const spec = {
30070
        id: dialogId,
30071
        header,
30072
        body,
30073
        footer,
30074
        extraClasses: dialogSizeClasses,
30075
        extraBehaviours: [Reflecting.config({
30076
            channel: `${ dialogChannel }-${ dialogId }`,
30077
            updateState,
30078
            initialData: dialogInit
30079
          })],
30080
        extraStyles: {}
30081
      };
30082
      const dialog = renderModalDialog(spec, dialogEvents, backstage);
30083
      const modalAccess = (() => {
30084
        const getForm = () => {
30085
          const outerForm = ModalDialog.getBody(dialog);
30086
          return Composing.getCurrent(outerForm).getOr(outerForm);
30087
        };
30088
        const toggleFullscreen$1 = () => {
30089
          toggleFullscreen(dialog, dialogSize.get());
30090
        };
30091
        return {
30092
          getId: constant$1(dialogId),
30093
          getRoot: constant$1(dialog),
30094
          getBody: () => ModalDialog.getBody(dialog),
30095
          getFooter: () => ModalDialog.getFooter(dialog),
30096
          getFormWrapper: getForm,
30097
          toggleFullscreen: toggleFullscreen$1
30098
        };
30099
      })();
30100
      const instanceApi = getDialogApi(modalAccess, extra.redial, objOfCells);
30101
      return {
30102
        dialog,
30103
        instanceApi
30104
      };
30105
    };
30106
 
30107
    const renderInlineDialog = (dialogInit, extra, backstage, ariaAttrs = false, refreshDocking) => {
30108
      const dialogId = generate$6('dialog');
30109
      const dialogLabelId = generate$6('dialog-label');
30110
      const dialogContentId = generate$6('dialog-content');
30111
      const internalDialog = dialogInit.internalDialog;
30112
      const dialogSize = Cell(internalDialog.size);
30113
      const dialogSizeClass = getDialogSizeClass(dialogSize.get()).toArray();
30114
      const updateState = (comp, incoming) => {
30115
        dialogSize.set(incoming.internalDialog.size);
30116
        updateDialogSizeClass(incoming.internalDialog.size, comp);
30117
        refreshDocking();
30118
        return Optional.some(incoming);
30119
      };
30120
      const memHeader = record(renderInlineHeader({
30121
        title: internalDialog.title,
30122
        draggable: true
30123
      }, dialogId, dialogLabelId, backstage.shared.providers));
30124
      const memBody = record(renderInlineBody({
30125
        body: internalDialog.body,
30126
        initialData: internalDialog.initialData
30127
      }, dialogId, dialogContentId, backstage, ariaAttrs));
30128
      const storagedMenuButtons = mapMenuButtons(internalDialog.buttons);
30129
      const objOfCells = extractCellsToObject(storagedMenuButtons);
30130
      const optMemFooter = someIf(storagedMenuButtons.length !== 0, record(renderInlineFooter({ buttons: storagedMenuButtons }, dialogId, backstage)));
30131
      const dialogEvents = initDialog(() => instanceApi, {
30132
        onBlock: event => {
30133
          Blocking.block(dialog, (_comp, bs) => {
30134
            const headerHeight = memHeader.getOpt(dialog).map(dialog => get$d(dialog.element));
30135
            return getBusySpec(event.message, bs, backstage.shared.providers, headerHeight);
30136
          });
30137
        },
30138
        onUnblock: () => {
30139
          Blocking.unblock(dialog);
30140
        },
30141
        onClose: () => extra.closeWindow()
30142
      }, backstage.shared.getSink);
30143
      const inlineClass = 'tox-dialog-inline';
30144
      const dialog = build$1({
30145
        dom: {
30146
          tag: 'div',
30147
          classes: [
30148
            'tox-dialog',
30149
            inlineClass,
30150
            ...dialogSizeClass
30151
          ],
30152
          attributes: {
30153
            role: 'dialog',
30154
            ['aria-labelledby']: dialogLabelId
30155
          }
30156
        },
30157
        eventOrder: {
30158
          [receive()]: [
30159
            Reflecting.name(),
30160
            Receiving.name()
30161
          ],
30162
          [execute$5()]: ['execute-on-form'],
30163
          [attachedToDom()]: [
30164
            'reflecting',
30165
            'execute-on-form'
30166
          ]
30167
        },
30168
        behaviours: derive$1([
30169
          Keying.config({
30170
            mode: 'cyclic',
30171
            onEscape: c => {
30172
              emit(c, formCloseEvent);
30173
              return Optional.some(true);
30174
            },
30175
            useTabstopAt: elem => !isPseudoStop(elem) && (name$3(elem) !== 'button' || get$f(elem, 'disabled') !== 'disabled'),
30176
            firstTabstop: 1
30177
          }),
30178
          Reflecting.config({
30179
            channel: `${ dialogChannel }-${ dialogId }`,
30180
            updateState,
30181
            initialData: dialogInit
30182
          }),
30183
          Focusing.config({}),
30184
          config('execute-on-form', dialogEvents.concat([
30185
            runOnSource(focusin(), (comp, _se) => {
30186
              Keying.focusIn(comp);
30187
            }),
30188
            run$1(focusShifted(), (comp, se) => {
30189
              comp.getSystem().broadcastOn([dialogFocusShiftedChannel], { newFocus: se.event.newFocus });
30190
            })
30191
          ])),
30192
          Blocking.config({ getRoot: () => Optional.some(dialog) }),
30193
          Replacing.config({}),
30194
          memory({})
30195
        ]),
30196
        components: [
30197
          memHeader.asSpec(),
30198
          memBody.asSpec(),
30199
          ...optMemFooter.map(memFooter => memFooter.asSpec()).toArray()
30200
        ]
30201
      });
30202
      const toggleFullscreen$1 = () => {
30203
        toggleFullscreen(dialog, dialogSize.get());
30204
      };
30205
      const instanceApi = getDialogApi({
30206
        getId: constant$1(dialogId),
30207
        getRoot: constant$1(dialog),
30208
        getFooter: () => optMemFooter.map(memFooter => memFooter.get(dialog)),
30209
        getBody: () => memBody.get(dialog),
30210
        getFormWrapper: () => {
30211
          const body = memBody.get(dialog);
30212
          return Composing.getCurrent(body).getOr(body);
30213
        },
30214
        toggleFullscreen: toggleFullscreen$1
30215
      }, extra.redial, objOfCells);
30216
      return {
30217
        dialog,
30218
        instanceApi
30219
      };
30220
    };
30221
 
30222
    var global = tinymce.util.Tools.resolve('tinymce.util.URI');
30223
 
30224
    const getUrlDialogApi = root => {
30225
      const withRoot = f => {
30226
        if (root.getSystem().isConnected()) {
30227
          f(root);
30228
        }
30229
      };
30230
      const block = message => {
30231
        if (!isString(message)) {
30232
          throw new Error('The urlDialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
30233
        }
30234
        withRoot(root => {
30235
          emitWith(root, formBlockEvent, { message });
30236
        });
30237
      };
30238
      const unblock = () => {
30239
        withRoot(root => {
30240
          emit(root, formUnblockEvent);
30241
        });
30242
      };
30243
      const close = () => {
30244
        withRoot(root => {
30245
          emit(root, formCloseEvent);
30246
        });
30247
      };
30248
      const sendMessage = data => {
30249
        withRoot(root => {
30250
          root.getSystem().broadcastOn([bodySendMessageChannel], data);
30251
        });
30252
      };
30253
      return {
30254
        block,
30255
        unblock,
30256
        close,
30257
        sendMessage
30258
      };
30259
    };
30260
 
30261
    const SUPPORTED_MESSAGE_ACTIONS = [
30262
      'insertContent',
30263
      'setContent',
30264
      'execCommand',
30265
      'close',
30266
      'block',
30267
      'unblock'
30268
    ];
30269
    const isSupportedMessage = data => isObject(data) && SUPPORTED_MESSAGE_ACTIONS.indexOf(data.mceAction) !== -1;
30270
    const isCustomMessage = data => !isSupportedMessage(data) && isObject(data) && has$2(data, 'mceAction');
30271
    const handleMessage = (editor, api, data) => {
30272
      switch (data.mceAction) {
30273
      case 'insertContent':
30274
        editor.insertContent(data.content);
30275
        break;
30276
      case 'setContent':
30277
        editor.setContent(data.content);
30278
        break;
30279
      case 'execCommand':
30280
        const ui = isBoolean(data.ui) ? data.ui : false;
30281
        editor.execCommand(data.cmd, ui, data.value);
30282
        break;
30283
      case 'close':
30284
        api.close();
30285
        break;
30286
      case 'block':
30287
        api.block(data.message);
30288
        break;
30289
      case 'unblock':
30290
        api.unblock();
30291
        break;
30292
      }
30293
    };
30294
    const renderUrlDialog = (internalDialog, extra, editor, backstage) => {
30295
      const dialogId = generate$6('dialog');
30296
      const header = getHeader(internalDialog.title, dialogId, backstage);
30297
      const body = renderIframeBody(internalDialog);
30298
      const footer = internalDialog.buttons.bind(buttons => {
30299
        if (buttons.length === 0) {
30300
          return Optional.none();
30301
        } else {
30302
          return Optional.some(renderModalFooter({ buttons }, dialogId, backstage));
30303
        }
30304
      });
30305
      const dialogEvents = initUrlDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra));
30306
      const styles = {
30307
        ...internalDialog.height.fold(() => ({}), height => ({
30308
          'height': height + 'px',
30309
          'max-height': height + 'px'
30310
        })),
30311
        ...internalDialog.width.fold(() => ({}), width => ({
30312
          'width': width + 'px',
30313
          'max-width': width + 'px'
30314
        }))
30315
      };
30316
      const classes = internalDialog.width.isNone() && internalDialog.height.isNone() ? ['tox-dialog--width-lg'] : [];
30317
      const iframeUri = new global(internalDialog.url, { base_uri: new global(window.location.href) });
30318
      const iframeDomain = `${ iframeUri.protocol }://${ iframeUri.host }${ iframeUri.port ? ':' + iframeUri.port : '' }`;
30319
      const messageHandlerUnbinder = unbindable();
30320
      const updateState = (_comp, incoming) => Optional.some(incoming);
30321
      const extraBehaviours = [
30322
        Reflecting.config({
30323
          channel: `${ dialogChannel }-${ dialogId }`,
30324
          updateState,
30325
          initialData: internalDialog
30326
        }),
30327
        config('messages', [
30328
          runOnAttached(() => {
30329
            const unbind = bind(SugarElement.fromDom(window), 'message', e => {
30330
              if (iframeUri.isSameOrigin(new global(e.raw.origin))) {
30331
                const data = e.raw.data;
30332
                if (isSupportedMessage(data)) {
30333
                  handleMessage(editor, instanceApi, data);
30334
                } else if (isCustomMessage(data)) {
30335
                  internalDialog.onMessage(instanceApi, data);
30336
                }
30337
              }
30338
            });
30339
            messageHandlerUnbinder.set(unbind);
30340
          }),
30341
          runOnDetached(messageHandlerUnbinder.clear)
30342
        ]),
30343
        Receiving.config({
30344
          channels: {
30345
            [bodySendMessageChannel]: {
30346
              onReceive: (comp, data) => {
30347
                descendant(comp.element, 'iframe').each(iframeEle => {
30348
                  const iframeWin = iframeEle.dom.contentWindow;
30349
                  if (isNonNullable(iframeWin)) {
30350
                    iframeWin.postMessage(data, iframeDomain);
30351
                  }
30352
                });
30353
              }
30354
            }
30355
          }
30356
        })
30357
      ];
30358
      const spec = {
30359
        id: dialogId,
30360
        header,
30361
        body,
30362
        footer,
30363
        extraClasses: classes,
30364
        extraBehaviours,
30365
        extraStyles: styles
30366
      };
30367
      const dialog = renderModalDialog(spec, dialogEvents, backstage);
30368
      const instanceApi = getUrlDialogApi(dialog);
30369
      return {
30370
        dialog,
30371
        instanceApi
30372
      };
30373
    };
30374
 
30375
    const setup$2 = backstage => {
30376
      const sharedBackstage = backstage.shared;
30377
      const open = (message, callback) => {
30378
        const closeDialog = () => {
30379
          ModalDialog.hide(alertDialog);
30380
          callback();
30381
        };
30382
        const memFooterClose = record(renderFooterButton({
30383
          name: 'close-alert',
30384
          text: 'OK',
30385
          primary: true,
30386
          buttonType: Optional.some('primary'),
30387
          align: 'end',
30388
          enabled: true,
30389
          icon: Optional.none()
30390
        }, 'cancel', backstage));
30391
        const titleSpec = pUntitled();
30392
        const closeSpec = pClose(closeDialog, sharedBackstage.providers);
30393
        const alertDialog = build$1(renderDialog$1({
30394
          lazySink: () => sharedBackstage.getSink(),
30395
          header: hiddenHeader(titleSpec, closeSpec),
30396
          body: pBodyMessage(message, sharedBackstage.providers),
30397
          footer: Optional.some(pFooter(pFooterGroup([], [memFooterClose.asSpec()]))),
30398
          onEscape: closeDialog,
30399
          extraClasses: ['tox-alert-dialog'],
30400
          extraBehaviours: [],
30401
          extraStyles: {},
30402
          dialogEvents: [run$1(formCancelEvent, closeDialog)],
30403
          eventOrder: {}
30404
        }));
30405
        ModalDialog.show(alertDialog);
30406
        const footerCloseButton = memFooterClose.get(alertDialog);
30407
        Focusing.focus(footerCloseButton);
30408
      };
30409
      return { open };
30410
    };
30411
 
30412
    const setup$1 = backstage => {
30413
      const sharedBackstage = backstage.shared;
30414
      const open = (message, callback) => {
30415
        const closeDialog = state => {
30416
          ModalDialog.hide(confirmDialog);
30417
          callback(state);
30418
        };
30419
        const memFooterYes = record(renderFooterButton({
30420
          name: 'yes',
30421
          text: 'Yes',
30422
          primary: true,
30423
          buttonType: Optional.some('primary'),
30424
          align: 'end',
30425
          enabled: true,
30426
          icon: Optional.none()
30427
        }, 'submit', backstage));
30428
        const footerNo = renderFooterButton({
30429
          name: 'no',
30430
          text: 'No',
30431
          primary: false,
30432
          buttonType: Optional.some('secondary'),
30433
          align: 'end',
30434
          enabled: true,
30435
          icon: Optional.none()
30436
        }, 'cancel', backstage);
30437
        const titleSpec = pUntitled();
30438
        const closeSpec = pClose(() => closeDialog(false), sharedBackstage.providers);
30439
        const confirmDialog = build$1(renderDialog$1({
30440
          lazySink: () => sharedBackstage.getSink(),
30441
          header: hiddenHeader(titleSpec, closeSpec),
30442
          body: pBodyMessage(message, sharedBackstage.providers),
30443
          footer: Optional.some(pFooter(pFooterGroup([], [
30444
            footerNo,
30445
            memFooterYes.asSpec()
30446
          ]))),
30447
          onEscape: () => closeDialog(false),
30448
          extraClasses: ['tox-confirm-dialog'],
30449
          extraBehaviours: [],
30450
          extraStyles: {},
30451
          dialogEvents: [
30452
            run$1(formCancelEvent, () => closeDialog(false)),
30453
            run$1(formSubmitEvent, () => closeDialog(true))
30454
          ],
30455
          eventOrder: {}
30456
        }));
30457
        ModalDialog.show(confirmDialog);
30458
        const footerYesButton = memFooterYes.get(confirmDialog);
30459
        Focusing.focus(footerYesButton);
30460
      };
30461
      return { open };
30462
    };
30463
 
30464
    const validateData = (data, validator) => getOrDie(asRaw('data', validator, data));
30465
    const isAlertOrConfirmDialog = target => closest(target, '.tox-alert-dialog') || closest(target, '.tox-confirm-dialog');
30466
    const inlineAdditionalBehaviours = (editor, isStickyToolbar, isToolbarLocationTop) => {
30467
      if (isStickyToolbar && isToolbarLocationTop) {
30468
        return [];
30469
      } else {
30470
        return [Docking.config({
30471
            contextual: {
30472
              lazyContext: () => Optional.some(box$1(SugarElement.fromDom(editor.getContentAreaContainer()))),
30473
              fadeInClass: 'tox-dialog-dock-fadein',
30474
              fadeOutClass: 'tox-dialog-dock-fadeout',
30475
              transitionClass: 'tox-dialog-dock-transition'
30476
            },
30477
            modes: ['top'],
30478
            lazyViewport: comp => {
30479
              const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
30480
              return optScrollingContext.map(sc => {
30481
                const combinedBounds = getBoundsFrom(sc);
30482
                return {
30483
                  bounds: combinedBounds,
30484
                  optScrollEnv: Optional.some({
30485
                    currentScrollTop: sc.element.dom.scrollTop,
30486
                    scrollElmTop: absolute$3(sc.element).top
30487
                  })
30488
                };
30489
              }).getOrThunk(() => ({
30490
                bounds: win(),
30491
                optScrollEnv: Optional.none()
30492
              }));
30493
            }
30494
          })];
30495
      }
30496
    };
30497
    const setup = extras => {
30498
      const editor = extras.editor;
30499
      const isStickyToolbar$1 = isStickyToolbar(editor);
30500
      const alertDialog = setup$2(extras.backstages.dialog);
30501
      const confirmDialog = setup$1(extras.backstages.dialog);
30502
      const open = (config, params, closeWindow) => {
30503
        if (!isUndefined(params)) {
30504
          if (params.inline === 'toolbar') {
30505
            return openInlineDialog(config, extras.backstages.popup.shared.anchors.inlineDialog(), closeWindow, params);
30506
          } else if (params.inline === 'bottom') {
30507
            return openBottomInlineDialog(config, extras.backstages.popup.shared.anchors.inlineBottomDialog(), closeWindow, params);
30508
          } else if (params.inline === 'cursor') {
30509
            return openInlineDialog(config, extras.backstages.popup.shared.anchors.cursor(), closeWindow, params);
30510
          }
30511
        }
30512
        return openModalDialog(config, closeWindow);
30513
      };
30514
      const openUrl = (config, closeWindow) => openModalUrlDialog(config, closeWindow);
30515
      const openModalUrlDialog = (config, closeWindow) => {
30516
        const factory = contents => {
30517
          const dialog = renderUrlDialog(contents, {
30518
            closeWindow: () => {
30519
              ModalDialog.hide(dialog.dialog);
30520
              closeWindow(dialog.instanceApi);
30521
            }
30522
          }, editor, extras.backstages.dialog);
30523
          ModalDialog.show(dialog.dialog);
30524
          return dialog.instanceApi;
30525
        };
30526
        return DialogManager.openUrl(factory, config);
30527
      };
30528
      const openModalDialog = (config, closeWindow) => {
30529
        const factory = (contents, internalInitialData, dataValidator) => {
30530
          const initialData = internalInitialData;
30531
          const dialogInit = {
30532
            dataValidator,
30533
            initialData,
30534
            internalDialog: contents
30535
          };
30536
          const dialog = renderDialog(dialogInit, {
30537
            redial: DialogManager.redial,
30538
            closeWindow: () => {
30539
              ModalDialog.hide(dialog.dialog);
30540
              closeWindow(dialog.instanceApi);
30541
            }
30542
          }, extras.backstages.dialog);
30543
          ModalDialog.show(dialog.dialog);
30544
          dialog.instanceApi.setData(initialData);
30545
          return dialog.instanceApi;
30546
        };
30547
        return DialogManager.open(factory, config);
30548
      };
30549
      const openInlineDialog = (config$1, anchor, closeWindow, windowParams) => {
30550
        const factory = (contents, internalInitialData, dataValidator) => {
30551
          const initialData = validateData(internalInitialData, dataValidator);
30552
          const inlineDialog = value$2();
30553
          const isToolbarLocationTop = extras.backstages.popup.shared.header.isPositionedAtTop();
30554
          const dialogInit = {
30555
            dataValidator,
30556
            initialData,
30557
            internalDialog: contents
30558
          };
30559
          const refreshDocking = () => inlineDialog.on(dialog => {
30560
            InlineView.reposition(dialog);
30561
            if (!isStickyToolbar$1 || !isToolbarLocationTop) {
30562
              Docking.refresh(dialog);
30563
            }
30564
          });
30565
          const dialogUi = renderInlineDialog(dialogInit, {
30566
            redial: DialogManager.redial,
30567
            closeWindow: () => {
30568
              inlineDialog.on(InlineView.hide);
30569
              editor.off('ResizeEditor', refreshDocking);
30570
              inlineDialog.clear();
30571
              closeWindow(dialogUi.instanceApi);
30572
            }
30573
          }, extras.backstages.popup, windowParams.ariaAttrs, refreshDocking);
30574
          const inlineDialogComp = build$1(InlineView.sketch({
30575
            lazySink: extras.backstages.popup.shared.getSink,
30576
            dom: {
30577
              tag: 'div',
30578
              classes: []
30579
            },
30580
            fireDismissalEventInstead: windowParams.persistent ? { event: 'doNotDismissYet' } : {},
30581
            ...isToolbarLocationTop ? {} : { fireRepositionEventInstead: {} },
30582
            inlineBehaviours: derive$1([
30583
              config('window-manager-inline-events', [run$1(dismissRequested(), (_comp, _se) => {
30584
                  emit(dialogUi.dialog, formCancelEvent);
30585
                })]),
30586
              ...inlineAdditionalBehaviours(editor, isStickyToolbar$1, isToolbarLocationTop)
30587
            ]),
30588
            isExtraPart: (_comp, target) => isAlertOrConfirmDialog(target)
30589
          }));
30590
          inlineDialog.set(inlineDialogComp);
30591
          const getInlineDialogBounds = () => {
30592
            const elem = editor.inline ? body() : SugarElement.fromDom(editor.getContainer());
30593
            const bounds = box$1(elem);
30594
            return Optional.some(bounds);
30595
          };
30596
          InlineView.showWithinBounds(inlineDialogComp, premade(dialogUi.dialog), { anchor }, getInlineDialogBounds);
30597
          if (!isStickyToolbar$1 || !isToolbarLocationTop) {
30598
            Docking.refresh(inlineDialogComp);
30599
            editor.on('ResizeEditor', refreshDocking);
30600
          }
30601
          dialogUi.instanceApi.setData(initialData);
30602
          Keying.focusIn(dialogUi.dialog);
30603
          return dialogUi.instanceApi;
30604
        };
30605
        return DialogManager.open(factory, config$1);
30606
      };
30607
      const openBottomInlineDialog = (config$1, anchor, closeWindow, windowParams) => {
30608
        const factory = (contents, internalInitialData, dataValidator) => {
30609
          const initialData = validateData(internalInitialData, dataValidator);
30610
          const inlineDialog = value$2();
30611
          const isToolbarLocationTop = extras.backstages.popup.shared.header.isPositionedAtTop();
30612
          const dialogInit = {
30613
            dataValidator,
30614
            initialData,
30615
            internalDialog: contents
30616
          };
30617
          const refreshDocking = () => inlineDialog.on(dialog => {
30618
            InlineView.reposition(dialog);
30619
            Docking.refresh(dialog);
30620
          });
30621
          const dialogUi = renderInlineDialog(dialogInit, {
30622
            redial: DialogManager.redial,
30623
            closeWindow: () => {
30624
              inlineDialog.on(InlineView.hide);
30625
              editor.off('ResizeEditor ScrollWindow ElementScroll', refreshDocking);
30626
              inlineDialog.clear();
30627
              closeWindow(dialogUi.instanceApi);
30628
            }
30629
          }, extras.backstages.popup, windowParams.ariaAttrs, refreshDocking);
30630
          const inlineDialogComp = build$1(InlineView.sketch({
30631
            lazySink: extras.backstages.popup.shared.getSink,
30632
            dom: {
30633
              tag: 'div',
30634
              classes: []
30635
            },
30636
            fireDismissalEventInstead: windowParams.persistent ? { event: 'doNotDismissYet' } : {},
30637
            ...isToolbarLocationTop ? {} : { fireRepositionEventInstead: {} },
30638
            inlineBehaviours: derive$1([
30639
              config('window-manager-inline-events', [run$1(dismissRequested(), (_comp, _se) => {
30640
                  emit(dialogUi.dialog, formCancelEvent);
30641
                })]),
30642
              Docking.config({
30643
                contextual: {
30644
                  lazyContext: () => Optional.some(box$1(SugarElement.fromDom(editor.getContentAreaContainer()))),
30645
                  fadeInClass: 'tox-dialog-dock-fadein',
30646
                  fadeOutClass: 'tox-dialog-dock-fadeout',
30647
                  transitionClass: 'tox-dialog-dock-transition'
30648
                },
30649
                modes: [
30650
                  'top',
30651
                  'bottom'
30652
                ],
30653
                lazyViewport: comp => {
30654
                  const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
30655
                  return optScrollingContext.map(sc => {
30656
                    const combinedBounds = getBoundsFrom(sc);
30657
                    return {
30658
                      bounds: combinedBounds,
30659
                      optScrollEnv: Optional.some({
30660
                        currentScrollTop: sc.element.dom.scrollTop,
30661
                        scrollElmTop: absolute$3(sc.element).top
30662
                      })
30663
                    };
30664
                  }).getOrThunk(() => ({
30665
                    bounds: win(),
30666
                    optScrollEnv: Optional.none()
30667
                  }));
30668
                }
30669
              })
30670
            ]),
30671
            isExtraPart: (_comp, target) => isAlertOrConfirmDialog(target)
30672
          }));
30673
          inlineDialog.set(inlineDialogComp);
30674
          const getInlineDialogBounds = () => {
30675
            return extras.backstages.popup.shared.getSink().toOptional().bind(s => {
30676
              const optScrollingContext = detectWhenSplitUiMode(editor, s.element);
30677
              const margin = 15;
30678
              const bounds$1 = optScrollingContext.map(sc => getBoundsFrom(sc)).getOr(win());
30679
              const contentAreaContainer = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
30680
              const constrainedBounds = constrain(contentAreaContainer, bounds$1);
30681
              return Optional.some(bounds(constrainedBounds.x, constrainedBounds.y, constrainedBounds.width, constrainedBounds.height - margin));
30682
            });
30683
          };
30684
          InlineView.showWithinBounds(inlineDialogComp, premade(dialogUi.dialog), { anchor }, getInlineDialogBounds);
30685
          Docking.refresh(inlineDialogComp);
30686
          editor.on('ResizeEditor ScrollWindow ElementScroll ResizeWindow', refreshDocking);
30687
          dialogUi.instanceApi.setData(initialData);
30688
          Keying.focusIn(dialogUi.dialog);
30689
          return dialogUi.instanceApi;
30690
        };
30691
        return DialogManager.open(factory, config$1);
30692
      };
30693
      const confirm = (message, callback) => {
30694
        confirmDialog.open(message, callback);
30695
      };
30696
      const alert = (message, callback) => {
30697
        alertDialog.open(message, callback);
30698
      };
30699
      const close = instanceApi => {
30700
        instanceApi.close();
30701
      };
30702
      return {
30703
        open,
30704
        openUrl,
30705
        alert,
30706
        close,
30707
        confirm
30708
      };
30709
    };
30710
 
30711
    const registerOptions = editor => {
30712
      register$e(editor);
30713
      register$d(editor);
30714
      register(editor);
30715
    };
30716
    var Theme = () => {
30717
      global$a.add('silver', editor => {
30718
        registerOptions(editor);
30719
        let popupSinkBounds = () => win();
30720
        const {
30721
          dialogs,
30722
          popups,
30723
          renderUI: renderModeUI
30724
        } = setup$3(editor, { getPopupSinkBounds: () => popupSinkBounds() });
30725
        const renderUI = () => {
30726
          const renderResult = renderModeUI();
30727
          const optScrollingContext = detectWhenSplitUiMode(editor, popups.getMothership().element);
30728
          optScrollingContext.each(sc => {
30729
            popupSinkBounds = () => {
30730
              return getBoundsFrom(sc);
30731
            };
30732
          });
30733
          return renderResult;
30734
        };
30735
        Autocompleter.register(editor, popups.backstage.shared);
30736
        const windowMgr = setup({
30737
          editor,
30738
          backstages: {
30739
            popup: popups.backstage,
30740
            dialog: dialogs.backstage
30741
          }
30742
        });
30743
        const getNotificationManagerImpl = () => NotificationManagerImpl(editor, { backstage: popups.backstage }, popups.getMothership());
30744
        return {
30745
          renderUI,
30746
          getWindowManagerImpl: constant$1(windowMgr),
30747
          getNotificationManagerImpl
30748
        };
30749
      });
30750
    };
30751
 
30752
    Theme();
30753
 
30754
})();