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
    var global$1 = tinymce.util.Tools.resolve('tinymce.ModelManager');
9
 
10
    const hasProto = (v, constructor, predicate) => {
11
      var _a;
12
      if (predicate(v, constructor.prototype)) {
13
        return true;
14
      } else {
15
        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
16
      }
17
    };
18
    const typeOf = x => {
19
      const t = typeof x;
20
      if (x === null) {
21
        return 'null';
22
      } else if (t === 'object' && Array.isArray(x)) {
23
        return 'array';
24
      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
25
        return 'string';
26
      } else {
27
        return t;
28
      }
29
    };
30
    const isType$1 = type => value => typeOf(value) === type;
31
    const isSimpleType = type => value => typeof value === type;
32
    const eq$2 = t => a => t === a;
33
    const isString = isType$1('string');
34
    const isObject = isType$1('object');
35
    const isArray = isType$1('array');
36
    const isNull = eq$2(null);
37
    const isBoolean = isSimpleType('boolean');
38
    const isUndefined = eq$2(undefined);
39
    const isNullable = a => a === null || a === undefined;
40
    const isNonNullable = a => !isNullable(a);
41
    const isFunction = isSimpleType('function');
42
    const isNumber = isSimpleType('number');
43
 
44
    const noop = () => {
45
    };
46
    const compose = (fa, fb) => {
47
      return (...args) => {
48
        return fa(fb.apply(null, args));
49
      };
50
    };
51
    const compose1 = (fbc, fab) => a => fbc(fab(a));
52
    const constant = value => {
53
      return () => {
54
        return value;
55
      };
56
    };
57
    const identity = x => {
58
      return x;
59
    };
60
    const tripleEquals = (a, b) => {
61
      return a === b;
62
    };
63
    function curry(fn, ...initialArgs) {
64
      return (...restArgs) => {
65
        const all = initialArgs.concat(restArgs);
66
        return fn.apply(null, all);
67
      };
68
    }
69
    const not = f => t => !f(t);
70
    const die = msg => {
71
      return () => {
72
        throw new Error(msg);
73
      };
74
    };
75
    const apply = f => {
76
      return f();
77
    };
78
    const never = constant(false);
79
    const always = constant(true);
80
 
81
    class Optional {
82
      constructor(tag, value) {
83
        this.tag = tag;
84
        this.value = value;
85
      }
86
      static some(value) {
87
        return new Optional(true, value);
88
      }
89
      static none() {
90
        return Optional.singletonNone;
91
      }
92
      fold(onNone, onSome) {
93
        if (this.tag) {
94
          return onSome(this.value);
95
        } else {
96
          return onNone();
97
        }
98
      }
99
      isSome() {
100
        return this.tag;
101
      }
102
      isNone() {
103
        return !this.tag;
104
      }
105
      map(mapper) {
106
        if (this.tag) {
107
          return Optional.some(mapper(this.value));
108
        } else {
109
          return Optional.none();
110
        }
111
      }
112
      bind(binder) {
113
        if (this.tag) {
114
          return binder(this.value);
115
        } else {
116
          return Optional.none();
117
        }
118
      }
119
      exists(predicate) {
120
        return this.tag && predicate(this.value);
121
      }
122
      forall(predicate) {
123
        return !this.tag || predicate(this.value);
124
      }
125
      filter(predicate) {
126
        if (!this.tag || predicate(this.value)) {
127
          return this;
128
        } else {
129
          return Optional.none();
130
        }
131
      }
132
      getOr(replacement) {
133
        return this.tag ? this.value : replacement;
134
      }
135
      or(replacement) {
136
        return this.tag ? this : replacement;
137
      }
138
      getOrThunk(thunk) {
139
        return this.tag ? this.value : thunk();
140
      }
141
      orThunk(thunk) {
142
        return this.tag ? this : thunk();
143
      }
144
      getOrDie(message) {
145
        if (!this.tag) {
146
          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
147
        } else {
148
          return this.value;
149
        }
150
      }
151
      static from(value) {
152
        return isNonNullable(value) ? Optional.some(value) : Optional.none();
153
      }
154
      getOrNull() {
155
        return this.tag ? this.value : null;
156
      }
157
      getOrUndefined() {
158
        return this.value;
159
      }
160
      each(worker) {
161
        if (this.tag) {
162
          worker(this.value);
163
        }
164
      }
165
      toArray() {
166
        return this.tag ? [this.value] : [];
167
      }
168
      toString() {
169
        return this.tag ? `some(${ this.value })` : 'none()';
170
      }
171
    }
172
    Optional.singletonNone = new Optional(false);
173
 
174
    const nativeSlice = Array.prototype.slice;
175
    const nativeIndexOf = Array.prototype.indexOf;
176
    const nativePush = Array.prototype.push;
177
    const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
178
    const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
179
    const exists = (xs, pred) => {
180
      for (let i = 0, len = xs.length; i < len; i++) {
181
        const x = xs[i];
182
        if (pred(x, i)) {
183
          return true;
184
        }
185
      }
186
      return false;
187
    };
188
    const range$1 = (num, f) => {
189
      const r = [];
190
      for (let i = 0; i < num; i++) {
191
        r.push(f(i));
192
      }
193
      return r;
194
    };
195
    const map$1 = (xs, f) => {
196
      const len = xs.length;
197
      const r = new Array(len);
198
      for (let i = 0; i < len; i++) {
199
        const x = xs[i];
200
        r[i] = f(x, i);
201
      }
202
      return r;
203
    };
204
    const each$2 = (xs, f) => {
205
      for (let i = 0, len = xs.length; i < len; i++) {
206
        const x = xs[i];
207
        f(x, i);
208
      }
209
    };
210
    const eachr = (xs, f) => {
211
      for (let i = xs.length - 1; i >= 0; i--) {
212
        const x = xs[i];
213
        f(x, i);
214
      }
215
    };
216
    const partition = (xs, pred) => {
217
      const pass = [];
218
      const fail = [];
219
      for (let i = 0, len = xs.length; i < len; i++) {
220
        const x = xs[i];
221
        const arr = pred(x, i) ? pass : fail;
222
        arr.push(x);
223
      }
224
      return {
225
        pass,
226
        fail
227
      };
228
    };
229
    const filter$2 = (xs, pred) => {
230
      const r = [];
231
      for (let i = 0, len = xs.length; i < len; i++) {
232
        const x = xs[i];
233
        if (pred(x, i)) {
234
          r.push(x);
235
        }
236
      }
237
      return r;
238
    };
239
    const foldr = (xs, f, acc) => {
240
      eachr(xs, (x, i) => {
241
        acc = f(acc, x, i);
242
      });
243
      return acc;
244
    };
245
    const foldl = (xs, f, acc) => {
246
      each$2(xs, (x, i) => {
247
        acc = f(acc, x, i);
248
      });
249
      return acc;
250
    };
251
    const findUntil = (xs, pred, until) => {
252
      for (let i = 0, len = xs.length; i < len; i++) {
253
        const x = xs[i];
254
        if (pred(x, i)) {
255
          return Optional.some(x);
256
        } else if (until(x, i)) {
257
          break;
258
        }
259
      }
260
      return Optional.none();
261
    };
262
    const find$1 = (xs, pred) => {
263
      return findUntil(xs, pred, never);
264
    };
265
    const findIndex = (xs, pred) => {
266
      for (let i = 0, len = xs.length; i < len; i++) {
267
        const x = xs[i];
268
        if (pred(x, i)) {
269
          return Optional.some(i);
270
        }
271
      }
272
      return Optional.none();
273
    };
274
    const flatten = xs => {
275
      const r = [];
276
      for (let i = 0, len = xs.length; i < len; ++i) {
277
        if (!isArray(xs[i])) {
278
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
279
        }
280
        nativePush.apply(r, xs[i]);
281
      }
282
      return r;
283
    };
284
    const bind$2 = (xs, f) => flatten(map$1(xs, f));
285
    const forall = (xs, pred) => {
286
      for (let i = 0, len = xs.length; i < len; ++i) {
287
        const x = xs[i];
288
        if (pred(x, i) !== true) {
289
          return false;
290
        }
291
      }
292
      return true;
293
    };
294
    const reverse = xs => {
295
      const r = nativeSlice.call(xs, 0);
296
      r.reverse();
297
      return r;
298
    };
299
    const mapToObject = (xs, f) => {
300
      const r = {};
301
      for (let i = 0, len = xs.length; i < len; i++) {
302
        const x = xs[i];
303
        r[String(x)] = f(x, i);
304
      }
305
      return r;
306
    };
307
    const sort$1 = (xs, comparator) => {
308
      const copy = nativeSlice.call(xs, 0);
309
      copy.sort(comparator);
310
      return copy;
311
    };
312
    const get$d = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
313
    const head = xs => get$d(xs, 0);
314
    const last$2 = xs => get$d(xs, xs.length - 1);
315
    const findMap = (arr, f) => {
316
      for (let i = 0; i < arr.length; i++) {
317
        const r = f(arr[i], i);
318
        if (r.isSome()) {
319
          return r;
320
        }
321
      }
322
      return Optional.none();
323
    };
324
 
325
    const keys = Object.keys;
326
    const hasOwnProperty = Object.hasOwnProperty;
327
    const each$1 = (obj, f) => {
328
      const props = keys(obj);
329
      for (let k = 0, len = props.length; k < len; k++) {
330
        const i = props[k];
331
        const x = obj[i];
332
        f(x, i);
333
      }
334
    };
335
    const map = (obj, f) => {
336
      return tupleMap(obj, (x, i) => ({
337
        k: i,
338
        v: f(x, i)
339
      }));
340
    };
341
    const tupleMap = (obj, f) => {
342
      const r = {};
343
      each$1(obj, (x, i) => {
344
        const tuple = f(x, i);
345
        r[tuple.k] = tuple.v;
346
      });
347
      return r;
348
    };
349
    const objAcc = r => (x, i) => {
350
      r[i] = x;
351
    };
352
    const internalFilter = (obj, pred, onTrue, onFalse) => {
353
      each$1(obj, (x, i) => {
354
        (pred(x, i) ? onTrue : onFalse)(x, i);
355
      });
356
    };
357
    const filter$1 = (obj, pred) => {
358
      const t = {};
359
      internalFilter(obj, pred, objAcc(t), noop);
360
      return t;
361
    };
362
    const mapToArray = (obj, f) => {
363
      const r = [];
364
      each$1(obj, (value, name) => {
365
        r.push(f(value, name));
366
      });
367
      return r;
368
    };
369
    const values = obj => {
370
      return mapToArray(obj, identity);
371
    };
372
    const get$c = (obj, key) => {
373
      return has$1(obj, key) ? Optional.from(obj[key]) : Optional.none();
374
    };
375
    const has$1 = (obj, key) => hasOwnProperty.call(obj, key);
376
    const hasNonNullableKey = (obj, key) => has$1(obj, key) && obj[key] !== undefined && obj[key] !== null;
377
    const isEmpty = r => {
378
      for (const x in r) {
379
        if (hasOwnProperty.call(r, x)) {
380
          return false;
381
        }
382
      }
383
      return true;
384
    };
385
 
386
    const Global = typeof window !== 'undefined' ? window : Function('return this;')();
387
 
388
    const path = (parts, scope) => {
389
      let o = scope !== undefined && scope !== null ? scope : Global;
390
      for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
391
        o = o[parts[i]];
392
      }
393
      return o;
394
    };
395
    const resolve$2 = (p, scope) => {
396
      const parts = p.split('.');
397
      return path(parts, scope);
398
    };
399
 
400
    const unsafe = (name, scope) => {
401
      return resolve$2(name, scope);
402
    };
403
    const getOrDie = (name, scope) => {
404
      const actual = unsafe(name, scope);
405
      if (actual === undefined || actual === null) {
406
        throw new Error(name + ' not available on this browser');
407
      }
408
      return actual;
409
    };
410
 
411
    const getPrototypeOf = Object.getPrototypeOf;
412
    const sandHTMLElement = scope => {
413
      return getOrDie('HTMLElement', scope);
414
    };
415
    const isPrototypeOf = x => {
416
      const scope = resolve$2('ownerDocument.defaultView', x);
417
      return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf(x).constructor.name));
418
    };
419
 
420
    const COMMENT = 8;
421
    const DOCUMENT = 9;
422
    const DOCUMENT_FRAGMENT = 11;
423
    const ELEMENT = 1;
424
    const TEXT = 3;
425
 
426
    const name = element => {
427
      const r = element.dom.nodeName;
428
      return r.toLowerCase();
429
    };
430
    const type = element => element.dom.nodeType;
431
    const isType = t => element => type(element) === t;
432
    const isComment = element => type(element) === COMMENT || name(element) === '#comment';
433
    const isHTMLElement = element => isElement(element) && isPrototypeOf(element.dom);
434
    const isElement = isType(ELEMENT);
435
    const isText = isType(TEXT);
436
    const isDocument = isType(DOCUMENT);
437
    const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
438
    const isTag = tag => e => isElement(e) && name(e) === tag;
439
 
440
    const rawSet = (dom, key, value) => {
441
      if (isString(value) || isBoolean(value) || isNumber(value)) {
442
        dom.setAttribute(key, value + '');
443
      } else {
444
        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
445
        throw new Error('Attribute value was not simple');
446
      }
447
    };
448
    const set$2 = (element, key, value) => {
449
      rawSet(element.dom, key, value);
450
    };
451
    const setAll$1 = (element, attrs) => {
452
      const dom = element.dom;
453
      each$1(attrs, (v, k) => {
454
        rawSet(dom, k, v);
455
      });
456
    };
457
    const setOptions = (element, attrs) => {
458
      each$1(attrs, (v, k) => {
459
        v.fold(() => {
460
          remove$7(element, k);
461
        }, value => {
462
          rawSet(element.dom, k, value);
463
        });
464
      });
465
    };
466
    const get$b = (element, key) => {
467
      const v = element.dom.getAttribute(key);
468
      return v === null ? undefined : v;
469
    };
470
    const getOpt = (element, key) => Optional.from(get$b(element, key));
471
    const remove$7 = (element, key) => {
472
      element.dom.removeAttribute(key);
473
    };
474
    const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
475
      acc[attr.name] = attr.value;
476
      return acc;
477
    }, {});
478
 
479
    const fromHtml$1 = (html, scope) => {
480
      const doc = scope || document;
481
      const div = doc.createElement('div');
482
      div.innerHTML = html;
483
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
484
        const message = 'HTML does not have a single root node';
485
        console.error(message, html);
486
        throw new Error(message);
487
      }
488
      return fromDom$1(div.childNodes[0]);
489
    };
490
    const fromTag = (tag, scope) => {
491
      const doc = scope || document;
492
      const node = doc.createElement(tag);
493
      return fromDom$1(node);
494
    };
495
    const fromText = (text, scope) => {
496
      const doc = scope || document;
497
      const node = doc.createTextNode(text);
498
      return fromDom$1(node);
499
    };
500
    const fromDom$1 = node => {
501
      if (node === null || node === undefined) {
502
        throw new Error('Node cannot be null or undefined');
503
      }
504
      return { dom: node };
505
    };
506
    const fromPoint$1 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1);
507
    const SugarElement = {
508
      fromHtml: fromHtml$1,
509
      fromTag,
510
      fromText,
511
      fromDom: fromDom$1,
512
      fromPoint: fromPoint$1
513
    };
514
 
515
    const is$2 = (element, selector) => {
516
      const dom = element.dom;
517
      if (dom.nodeType !== ELEMENT) {
518
        return false;
519
      } else {
520
        const elem = dom;
521
        if (elem.matches !== undefined) {
522
          return elem.matches(selector);
523
        } else if (elem.msMatchesSelector !== undefined) {
524
          return elem.msMatchesSelector(selector);
525
        } else if (elem.webkitMatchesSelector !== undefined) {
526
          return elem.webkitMatchesSelector(selector);
527
        } else if (elem.mozMatchesSelector !== undefined) {
528
          return elem.mozMatchesSelector(selector);
529
        } else {
530
          throw new Error('Browser lacks native selectors');
531
        }
532
      }
533
    };
534
    const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
535
    const all$1 = (selector, scope) => {
536
      const base = scope === undefined ? document : scope.dom;
537
      return bypassSelector(base) ? [] : map$1(base.querySelectorAll(selector), SugarElement.fromDom);
538
    };
539
    const one = (selector, scope) => {
540
      const base = scope === undefined ? document : scope.dom;
541
      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
542
    };
543
 
544
    const eq$1 = (e1, e2) => e1.dom === e2.dom;
545
    const contains$1 = (e1, e2) => {
546
      const d1 = e1.dom;
547
      const d2 = e2.dom;
548
      return d1 === d2 ? false : d1.contains(d2);
549
    };
550
    const is$1 = is$2;
551
 
552
    const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
553
    const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
554
    const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
555
    const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
556
    const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
557
    const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
558
    const parents = (element, isRoot) => {
559
      const stop = isFunction(isRoot) ? isRoot : never;
560
      let dom = element.dom;
561
      const ret = [];
562
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
563
        const rawParent = dom.parentNode;
564
        const p = SugarElement.fromDom(rawParent);
565
        ret.push(p);
566
        if (stop(p) === true) {
567
          break;
568
        } else {
569
          dom = rawParent;
570
        }
571
      }
572
      return ret;
573
    };
574
    const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
575
    const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
576
    const children$2 = element => map$1(element.dom.childNodes, SugarElement.fromDom);
577
    const child$2 = (element, index) => {
578
      const cs = element.dom.childNodes;
579
      return Optional.from(cs[index]).map(SugarElement.fromDom);
580
    };
581
    const firstChild = element => child$2(element, 0);
582
 
583
    const before$3 = (marker, element) => {
584
      const parent$1 = parent(marker);
585
      parent$1.each(v => {
586
        v.dom.insertBefore(element.dom, marker.dom);
587
      });
588
    };
589
    const after$5 = (marker, element) => {
590
      const sibling = nextSibling(marker);
591
      sibling.fold(() => {
592
        const parent$1 = parent(marker);
593
        parent$1.each(v => {
594
          append$1(v, element);
595
        });
596
      }, v => {
597
        before$3(v, element);
598
      });
599
    };
600
    const prepend = (parent, element) => {
601
      const firstChild$1 = firstChild(parent);
602
      firstChild$1.fold(() => {
603
        append$1(parent, element);
604
      }, v => {
605
        parent.dom.insertBefore(element.dom, v.dom);
606
      });
607
    };
608
    const append$1 = (parent, element) => {
609
      parent.dom.appendChild(element.dom);
610
    };
611
    const appendAt = (parent, element, index) => {
612
      child$2(parent, index).fold(() => {
613
        append$1(parent, element);
614
      }, v => {
615
        before$3(v, element);
616
      });
617
    };
618
    const wrap = (element, wrapper) => {
619
      before$3(element, wrapper);
620
      append$1(wrapper, element);
621
    };
622
 
623
    const after$4 = (marker, elements) => {
624
      each$2(elements, (x, i) => {
625
        const e = i === 0 ? marker : elements[i - 1];
626
        after$5(e, x);
627
      });
628
    };
629
    const append = (parent, elements) => {
630
      each$2(elements, x => {
631
        append$1(parent, x);
632
      });
633
    };
634
 
635
    const empty = element => {
636
      element.dom.textContent = '';
637
      each$2(children$2(element), rogue => {
638
        remove$6(rogue);
639
      });
640
    };
641
    const remove$6 = element => {
642
      const dom = element.dom;
643
      if (dom.parentNode !== null) {
644
        dom.parentNode.removeChild(dom);
645
      }
646
    };
647
    const unwrap = wrapper => {
648
      const children = children$2(wrapper);
649
      if (children.length > 0) {
650
        after$4(wrapper, children);
651
      }
652
      remove$6(wrapper);
653
    };
654
 
655
    const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
656
    const shallow = original => clone$1(original, false);
657
    const deep = original => clone$1(original, true);
658
    const shallowAs = (original, tag) => {
659
      const nu = SugarElement.fromTag(tag);
660
      const attributes = clone$2(original);
661
      setAll$1(nu, attributes);
662
      return nu;
663
    };
664
    const copy$2 = (original, tag) => {
665
      const nu = shallowAs(original, tag);
666
      const cloneChildren = children$2(deep(original));
667
      append(nu, cloneChildren);
668
      return nu;
669
    };
670
    const mutate$1 = (original, tag) => {
671
      const nu = shallowAs(original, tag);
672
      after$5(original, nu);
673
      const children = children$2(original);
674
      append(nu, children);
675
      remove$6(original);
676
      return nu;
677
    };
678
 
679
    const validSectionList = [
680
      'tfoot',
681
      'thead',
682
      'tbody',
683
      'colgroup'
684
    ];
685
    const isValidSection = parentName => contains$2(validSectionList, parentName);
686
    const grid = (rows, columns) => ({
687
      rows,
688
      columns
689
    });
690
    const address = (row, column) => ({
691
      row,
692
      column
693
    });
694
    const detail = (element, rowspan, colspan) => ({
695
      element,
696
      rowspan,
697
      colspan
698
    });
699
    const detailnew = (element, rowspan, colspan, isNew) => ({
700
      element,
701
      rowspan,
702
      colspan,
703
      isNew
704
    });
705
    const extended = (element, rowspan, colspan, row, column, isLocked) => ({
706
      element,
707
      rowspan,
708
      colspan,
709
      row,
710
      column,
711
      isLocked
712
    });
713
    const rowdetail = (element, cells, section) => ({
714
      element,
715
      cells,
716
      section
717
    });
718
    const rowdetailnew = (element, cells, section, isNew) => ({
719
      element,
720
      cells,
721
      section,
722
      isNew
723
    });
724
    const elementnew = (element, isNew, isLocked) => ({
725
      element,
726
      isNew,
727
      isLocked
728
    });
729
    const rowcells = (element, cells, section, isNew) => ({
730
      element,
731
      cells,
732
      section,
733
      isNew
734
    });
735
    const bounds = (startRow, startCol, finishRow, finishCol) => ({
736
      startRow,
737
      startCol,
738
      finishRow,
739
      finishCol
740
    });
741
    const columnext = (element, colspan, column) => ({
742
      element,
743
      colspan,
744
      column
745
    });
746
    const colgroup = (element, columns) => ({
747
      element,
748
      columns
749
    });
750
 
751
    const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
752
    const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
753
    const isSupported$1 = constant(supported);
754
    const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
755
    const getShadowRoot = e => {
756
      const r = getRootNode(e);
757
      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
758
    };
759
    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
760
    const getOriginalEventTarget = event => {
761
      if (isSupported$1() && isNonNullable(event.target)) {
762
        const el = SugarElement.fromDom(event.target);
763
        if (isElement(el) && isOpenShadowHost(el)) {
764
          if (event.composed && event.composedPath) {
765
            const composedPath = event.composedPath();
766
            if (composedPath) {
767
              return head(composedPath);
768
            }
769
          }
770
        }
771
      }
772
      return Optional.from(event.target);
773
    };
774
    const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
775
 
776
    const inBody = element => {
777
      const dom = isText(element) ? element.dom.parentNode : element.dom;
778
      if (dom === undefined || dom === null || dom.ownerDocument === null) {
779
        return false;
780
      }
781
      const doc = dom.ownerDocument;
782
      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
783
    };
784
    const body$1 = () => getBody$1(SugarElement.fromDom(document));
785
    const getBody$1 = doc => {
786
      const b = doc.dom.body;
787
      if (b === null || b === undefined) {
788
        throw new Error('Body is not available yet');
789
      }
790
      return SugarElement.fromDom(b);
791
    };
792
 
793
    const ancestors$4 = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate);
794
    const children$1 = (scope, predicate) => filter$2(children$2(scope), predicate);
795
    const descendants$1 = (scope, predicate) => {
796
      let result = [];
797
      each$2(children$2(scope), x => {
798
        if (predicate(x)) {
799
          result = result.concat([x]);
800
        }
801
        result = result.concat(descendants$1(x, predicate));
802
      });
803
      return result;
804
    };
805
 
806
    const ancestors$3 = (scope, selector, isRoot) => ancestors$4(scope, e => is$2(e, selector), isRoot);
807
    const children = (scope, selector) => children$1(scope, e => is$2(e, selector));
808
    const descendants = (scope, selector) => all$1(selector, scope);
809
 
810
    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
811
      if (is(scope, a)) {
812
        return Optional.some(scope);
813
      } else if (isFunction(isRoot) && isRoot(scope)) {
814
        return Optional.none();
815
      } else {
816
        return ancestor(scope, a, isRoot);
817
      }
818
    };
819
 
820
    const ancestor$2 = (scope, predicate, isRoot) => {
821
      let element = scope.dom;
822
      const stop = isFunction(isRoot) ? isRoot : never;
823
      while (element.parentNode) {
824
        element = element.parentNode;
825
        const el = SugarElement.fromDom(element);
826
        if (predicate(el)) {
827
          return Optional.some(el);
828
        } else if (stop(el)) {
829
          break;
830
        }
831
      }
832
      return Optional.none();
833
    };
834
    const closest$2 = (scope, predicate, isRoot) => {
835
      const is = (s, test) => test(s);
836
      return ClosestOrAncestor(is, ancestor$2, scope, predicate, isRoot);
837
    };
838
    const child$1 = (scope, predicate) => {
839
      const pred = node => predicate(SugarElement.fromDom(node));
840
      const result = find$1(scope.dom.childNodes, pred);
841
      return result.map(SugarElement.fromDom);
842
    };
843
    const descendant$1 = (scope, predicate) => {
844
      const descend = node => {
845
        for (let i = 0; i < node.childNodes.length; i++) {
846
          const child = SugarElement.fromDom(node.childNodes[i]);
847
          if (predicate(child)) {
848
            return Optional.some(child);
849
          }
850
          const res = descend(node.childNodes[i]);
851
          if (res.isSome()) {
852
            return res;
853
          }
854
        }
855
        return Optional.none();
856
      };
857
      return descend(scope.dom);
858
    };
859
 
860
    const ancestor$1 = (scope, selector, isRoot) => ancestor$2(scope, e => is$2(e, selector), isRoot);
861
    const child = (scope, selector) => child$1(scope, e => is$2(e, selector));
862
    const descendant = (scope, selector) => one(selector, scope);
863
    const closest$1 = (scope, selector, isRoot) => {
864
      const is = (element, selector) => is$2(element, selector);
865
      return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot);
866
    };
867
 
868
    const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
869
    const cat = arr => {
870
      const r = [];
871
      const push = x => {
872
        r.push(x);
873
      };
874
      for (let i = 0; i < arr.length; i++) {
875
        arr[i].each(push);
876
      }
877
      return r;
878
    };
879
    const bindFrom = (a, f) => a !== undefined && a !== null ? f(a) : Optional.none();
880
    const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
881
 
882
    const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
883
    const contains = (str, substr, start = 0, end) => {
884
      const idx = str.indexOf(substr, start);
885
      if (idx !== -1) {
886
        return isUndefined(end) ? true : idx + substr.length <= end;
887
      } else {
888
        return false;
889
      }
890
    };
891
    const startsWith = (str, prefix) => {
892
      return checkRange(str, prefix, 0);
893
    };
894
    const endsWith = (str, suffix) => {
895
      return checkRange(str, suffix, str.length - suffix.length);
896
    };
897
    const blank = r => s => s.replace(r, '');
898
    const trim = blank(/^\s+|\s+$/g);
899
    const isNotEmpty = s => s.length > 0;
900
    const toFloat = value => {
901
      const num = parseFloat(value);
902
      return isNaN(num) ? Optional.none() : Optional.some(num);
903
    };
904
 
905
    const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
906
 
907
    const internalSet = (dom, property, value) => {
908
      if (!isString(value)) {
909
        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
910
        throw new Error('CSS value must be a string: ' + value);
911
      }
912
      if (isSupported(dom)) {
913
        dom.style.setProperty(property, value);
914
      }
915
    };
916
    const internalRemove = (dom, property) => {
917
      if (isSupported(dom)) {
918
        dom.style.removeProperty(property);
919
      }
920
    };
921
    const set$1 = (element, property, value) => {
922
      const dom = element.dom;
923
      internalSet(dom, property, value);
924
    };
925
    const setAll = (element, css) => {
926
      const dom = element.dom;
927
      each$1(css, (v, k) => {
928
        internalSet(dom, k, v);
929
      });
930
    };
931
    const get$a = (element, property) => {
932
      const dom = element.dom;
933
      const styles = window.getComputedStyle(dom);
934
      const r = styles.getPropertyValue(property);
935
      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
936
    };
937
    const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
938
    const getRaw$2 = (element, property) => {
939
      const dom = element.dom;
940
      const raw = getUnsafeProperty(dom, property);
941
      return Optional.from(raw).filter(r => r.length > 0);
942
    };
943
    const remove$5 = (element, property) => {
944
      const dom = element.dom;
945
      internalRemove(dom, property);
946
      if (is(getOpt(element, 'style').map(trim), '')) {
947
        remove$7(element, 'style');
948
      }
949
    };
950
    const copy$1 = (source, target) => {
951
      const sourceDom = source.dom;
952
      const targetDom = target.dom;
953
      if (isSupported(sourceDom) && isSupported(targetDom)) {
954
        targetDom.style.cssText = sourceDom.style.cssText;
955
      }
956
    };
957
 
958
    const getAttrValue = (cell, name, fallback = 0) => getOpt(cell, name).map(value => parseInt(value, 10)).getOr(fallback);
959
    const getSpan = (cell, type) => getAttrValue(cell, type, 1);
960
    const hasColspan = cellOrCol => {
961
      if (isTag('col')(cellOrCol)) {
962
        return getAttrValue(cellOrCol, 'span', 1) > 1;
963
      } else {
964
        return getSpan(cellOrCol, 'colspan') > 1;
965
      }
966
    };
967
    const hasRowspan = cell => getSpan(cell, 'rowspan') > 1;
968
    const getCssValue = (element, property) => parseInt(get$a(element, property), 10);
969
    const minWidth = constant(10);
970
    const minHeight = constant(10);
971
 
972
    const firstLayer = (scope, selector) => {
973
      return filterFirstLayer(scope, selector, always);
974
    };
975
    const filterFirstLayer = (scope, selector, predicate) => {
976
      return bind$2(children$2(scope), x => {
977
        if (is$2(x, selector)) {
978
          return predicate(x) ? [x] : [];
979
        } else {
980
          return filterFirstLayer(x, selector, predicate);
981
        }
982
      });
983
    };
984
 
985
    const lookup = (tags, element, isRoot = never) => {
986
      if (isRoot(element)) {
987
        return Optional.none();
988
      }
989
      if (contains$2(tags, name(element))) {
990
        return Optional.some(element);
991
      }
992
      const isRootOrUpperTable = elm => is$2(elm, 'table') || isRoot(elm);
993
      return ancestor$1(element, tags.join(','), isRootOrUpperTable);
994
    };
995
    const cell = (element, isRoot) => lookup([
996
      'td',
997
      'th'
998
    ], element, isRoot);
999
    const cells$1 = ancestor => firstLayer(ancestor, 'th,td');
1000
    const columns$1 = ancestor => {
1001
      if (is$2(ancestor, 'colgroup')) {
1002
        return children(ancestor, 'col');
1003
      } else {
1004
        return bind$2(columnGroups(ancestor), columnGroup => children(columnGroup, 'col'));
1005
      }
1006
    };
1007
    const table = (element, isRoot) => closest$1(element, 'table', isRoot);
1008
    const rows$1 = ancestor => firstLayer(ancestor, 'tr');
1009
    const columnGroups = ancestor => table(ancestor).fold(constant([]), table => children(table, 'colgroup'));
1010
 
1011
    const fromRowsOrColGroups = (elems, getSection) => map$1(elems, row => {
1012
      if (name(row) === 'colgroup') {
1013
        const cells = map$1(columns$1(row), column => {
1014
          const colspan = getAttrValue(column, 'span', 1);
1015
          return detail(column, 1, colspan);
1016
        });
1017
        return rowdetail(row, cells, 'colgroup');
1018
      } else {
1019
        const cells = map$1(cells$1(row), cell => {
1020
          const rowspan = getAttrValue(cell, 'rowspan', 1);
1021
          const colspan = getAttrValue(cell, 'colspan', 1);
1022
          return detail(cell, rowspan, colspan);
1023
        });
1024
        return rowdetail(row, cells, getSection(row));
1025
      }
1026
    });
1027
    const getParentSection = group => parent(group).map(parent => {
1028
      const parentName = name(parent);
1029
      return isValidSection(parentName) ? parentName : 'tbody';
1030
    }).getOr('tbody');
1031
    const fromTable$1 = table => {
1032
      const rows = rows$1(table);
1033
      const columnGroups$1 = columnGroups(table);
1034
      const elems = [
1035
        ...columnGroups$1,
1036
        ...rows
1037
      ];
1038
      return fromRowsOrColGroups(elems, getParentSection);
1039
    };
1040
    const fromPastedRows = (elems, section) => fromRowsOrColGroups(elems, () => section);
1041
 
1042
    const cached = f => {
1043
      let called = false;
1044
      let r;
1045
      return (...args) => {
1046
        if (!called) {
1047
          called = true;
1048
          r = f.apply(null, args);
1049
        }
1050
        return r;
1051
      };
1052
    };
1053
 
1054
    const DeviceType = (os, browser, userAgent, mediaMatch) => {
1055
      const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
1056
      const isiPhone = os.isiOS() && !isiPad;
1057
      const isMobile = os.isiOS() || os.isAndroid();
1058
      const isTouch = isMobile || mediaMatch('(pointer:coarse)');
1059
      const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
1060
      const isPhone = isiPhone || isMobile && !isTablet;
1061
      const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
1062
      const isDesktop = !isPhone && !isTablet && !iOSwebview;
1063
      return {
1064
        isiPad: constant(isiPad),
1065
        isiPhone: constant(isiPhone),
1066
        isTablet: constant(isTablet),
1067
        isPhone: constant(isPhone),
1068
        isTouch: constant(isTouch),
1069
        isAndroid: os.isAndroid,
1070
        isiOS: os.isiOS,
1071
        isWebView: constant(iOSwebview),
1072
        isDesktop: constant(isDesktop)
1073
      };
1074
    };
1075
 
1076
    const firstMatch = (regexes, s) => {
1077
      for (let i = 0; i < regexes.length; i++) {
1078
        const x = regexes[i];
1079
        if (x.test(s)) {
1080
          return x;
1081
        }
1082
      }
1083
      return undefined;
1084
    };
1085
    const find = (regexes, agent) => {
1086
      const r = firstMatch(regexes, agent);
1087
      if (!r) {
1088
        return {
1089
          major: 0,
1090
          minor: 0
1091
        };
1092
      }
1093
      const group = i => {
1094
        return Number(agent.replace(r, '$' + i));
1095
      };
1096
      return nu$2(group(1), group(2));
1097
    };
1098
    const detect$5 = (versionRegexes, agent) => {
1099
      const cleanedAgent = String(agent).toLowerCase();
1100
      if (versionRegexes.length === 0) {
1101
        return unknown$2();
1102
      }
1103
      return find(versionRegexes, cleanedAgent);
1104
    };
1105
    const unknown$2 = () => {
1106
      return nu$2(0, 0);
1107
    };
1108
    const nu$2 = (major, minor) => {
1109
      return {
1110
        major,
1111
        minor
1112
      };
1113
    };
1114
    const Version = {
1115
      nu: nu$2,
1116
      detect: detect$5,
1117
      unknown: unknown$2
1118
    };
1119
 
1120
    const detectBrowser$1 = (browsers, userAgentData) => {
1121
      return findMap(userAgentData.brands, uaBrand => {
1122
        const lcBrand = uaBrand.brand.toLowerCase();
1123
        return find$1(browsers, browser => {
1124
          var _a;
1125
          return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
1126
        }).map(info => ({
1127
          current: info.name,
1128
          version: Version.nu(parseInt(uaBrand.version, 10), 0)
1129
        }));
1130
      });
1131
    };
1132
 
1133
    const detect$4 = (candidates, userAgent) => {
1134
      const agent = String(userAgent).toLowerCase();
1135
      return find$1(candidates, candidate => {
1136
        return candidate.search(agent);
1137
      });
1138
    };
1139
    const detectBrowser = (browsers, userAgent) => {
1140
      return detect$4(browsers, userAgent).map(browser => {
1141
        const version = Version.detect(browser.versionRegexes, userAgent);
1142
        return {
1143
          current: browser.name,
1144
          version
1145
        };
1146
      });
1147
    };
1148
    const detectOs = (oses, userAgent) => {
1149
      return detect$4(oses, userAgent).map(os => {
1150
        const version = Version.detect(os.versionRegexes, userAgent);
1151
        return {
1152
          current: os.name,
1153
          version
1154
        };
1155
      });
1156
    };
1157
 
1158
    const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
1159
    const checkContains = target => {
1160
      return uastring => {
1161
        return contains(uastring, target);
1162
      };
1163
    };
1164
    const browsers = [
1165
      {
1166
        name: 'Edge',
1167
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
1168
        search: uastring => {
1169
          return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
1170
        }
1171
      },
1172
      {
1173
        name: 'Chromium',
1174
        brand: 'Chromium',
1175
        versionRegexes: [
1176
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
1177
          normalVersionRegex
1178
        ],
1179
        search: uastring => {
1180
          return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
1181
        }
1182
      },
1183
      {
1184
        name: 'IE',
1185
        versionRegexes: [
1186
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
1187
          /.*?rv:([0-9]+)\.([0-9]+).*/
1188
        ],
1189
        search: uastring => {
1190
          return contains(uastring, 'msie') || contains(uastring, 'trident');
1191
        }
1192
      },
1193
      {
1194
        name: 'Opera',
1195
        versionRegexes: [
1196
          normalVersionRegex,
1197
          /.*?opera\/([0-9]+)\.([0-9]+).*/
1198
        ],
1199
        search: checkContains('opera')
1200
      },
1201
      {
1202
        name: 'Firefox',
1203
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
1204
        search: checkContains('firefox')
1205
      },
1206
      {
1207
        name: 'Safari',
1208
        versionRegexes: [
1209
          normalVersionRegex,
1210
          /.*?cpu os ([0-9]+)_([0-9]+).*/
1211
        ],
1212
        search: uastring => {
1213
          return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
1214
        }
1215
      }
1216
    ];
1217
    const oses = [
1218
      {
1219
        name: 'Windows',
1220
        search: checkContains('win'),
1221
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
1222
      },
1223
      {
1224
        name: 'iOS',
1225
        search: uastring => {
1226
          return contains(uastring, 'iphone') || contains(uastring, 'ipad');
1227
        },
1228
        versionRegexes: [
1229
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
1230
          /.*cpu os ([0-9]+)_([0-9]+).*/,
1231
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
1232
        ]
1233
      },
1234
      {
1235
        name: 'Android',
1236
        search: checkContains('android'),
1237
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
1238
      },
1239
      {
1240
        name: 'macOS',
1241
        search: checkContains('mac os x'),
1242
        versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
1243
      },
1244
      {
1245
        name: 'Linux',
1246
        search: checkContains('linux'),
1247
        versionRegexes: []
1248
      },
1249
      {
1250
        name: 'Solaris',
1251
        search: checkContains('sunos'),
1252
        versionRegexes: []
1253
      },
1254
      {
1255
        name: 'FreeBSD',
1256
        search: checkContains('freebsd'),
1257
        versionRegexes: []
1258
      },
1259
      {
1260
        name: 'ChromeOS',
1261
        search: checkContains('cros'),
1262
        versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
1263
      }
1264
    ];
1265
    const PlatformInfo = {
1266
      browsers: constant(browsers),
1267
      oses: constant(oses)
1268
    };
1269
 
1270
    const edge = 'Edge';
1271
    const chromium = 'Chromium';
1272
    const ie = 'IE';
1273
    const opera = 'Opera';
1274
    const firefox = 'Firefox';
1275
    const safari = 'Safari';
1276
    const unknown$1 = () => {
1277
      return nu$1({
1278
        current: undefined,
1279
        version: Version.unknown()
1280
      });
1281
    };
1282
    const nu$1 = info => {
1283
      const current = info.current;
1284
      const version = info.version;
1285
      const isBrowser = name => () => current === name;
1286
      return {
1287
        current,
1288
        version,
1289
        isEdge: isBrowser(edge),
1290
        isChromium: isBrowser(chromium),
1291
        isIE: isBrowser(ie),
1292
        isOpera: isBrowser(opera),
1293
        isFirefox: isBrowser(firefox),
1294
        isSafari: isBrowser(safari)
1295
      };
1296
    };
1297
    const Browser = {
1298
      unknown: unknown$1,
1299
      nu: nu$1,
1300
      edge: constant(edge),
1301
      chromium: constant(chromium),
1302
      ie: constant(ie),
1303
      opera: constant(opera),
1304
      firefox: constant(firefox),
1305
      safari: constant(safari)
1306
    };
1307
 
1308
    const windows = 'Windows';
1309
    const ios = 'iOS';
1310
    const android = 'Android';
1311
    const linux = 'Linux';
1312
    const macos = 'macOS';
1313
    const solaris = 'Solaris';
1314
    const freebsd = 'FreeBSD';
1315
    const chromeos = 'ChromeOS';
1316
    const unknown = () => {
1317
      return nu({
1318
        current: undefined,
1319
        version: Version.unknown()
1320
      });
1321
    };
1322
    const nu = info => {
1323
      const current = info.current;
1324
      const version = info.version;
1325
      const isOS = name => () => current === name;
1326
      return {
1327
        current,
1328
        version,
1329
        isWindows: isOS(windows),
1330
        isiOS: isOS(ios),
1331
        isAndroid: isOS(android),
1332
        isMacOS: isOS(macos),
1333
        isLinux: isOS(linux),
1334
        isSolaris: isOS(solaris),
1335
        isFreeBSD: isOS(freebsd),
1336
        isChromeOS: isOS(chromeos)
1337
      };
1338
    };
1339
    const OperatingSystem = {
1340
      unknown,
1341
      nu,
1342
      windows: constant(windows),
1343
      ios: constant(ios),
1344
      android: constant(android),
1345
      linux: constant(linux),
1346
      macos: constant(macos),
1347
      solaris: constant(solaris),
1348
      freebsd: constant(freebsd),
1349
      chromeos: constant(chromeos)
1350
    };
1351
 
1352
    const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
1353
      const browsers = PlatformInfo.browsers();
1354
      const oses = PlatformInfo.oses();
1355
      const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
1356
      const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
1357
      const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
1358
      return {
1359
        browser,
1360
        os,
1361
        deviceType
1362
      };
1363
    };
1364
    const PlatformDetection = { detect: detect$3 };
1365
 
1366
    const mediaMatch = query => window.matchMedia(query).matches;
1367
    let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
1368
    const detect$2 = () => platform();
1369
 
1370
    const Dimension = (name, getOffset) => {
1371
      const set = (element, h) => {
1372
        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
1373
          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
1374
        }
1375
        const dom = element.dom;
1376
        if (isSupported(dom)) {
1377
          dom.style[name] = h + 'px';
1378
        }
1379
      };
1380
      const get = element => {
1381
        const r = getOffset(element);
1382
        if (r <= 0 || r === null) {
1383
          const css = get$a(element, name);
1384
          return parseFloat(css) || 0;
1385
        }
1386
        return r;
1387
      };
1388
      const getOuter = get;
1389
      const aggregate = (element, properties) => foldl(properties, (acc, property) => {
1390
        const val = get$a(element, property);
1391
        const value = val === undefined ? 0 : parseInt(val, 10);
1392
        return isNaN(value) ? acc : acc + value;
1393
      }, 0);
1394
      const max = (element, value, properties) => {
1395
        const cumulativeInclusions = aggregate(element, properties);
1396
        const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
1397
        return absoluteMax;
1398
      };
1399
      return {
1400
        set,
1401
        get,
1402
        getOuter,
1403
        aggregate,
1404
        max
1405
      };
1406
    };
1407
 
1408
    const toNumber = (px, fallback) => toFloat(px).getOr(fallback);
1409
    const getProp = (element, name, fallback) => toNumber(get$a(element, name), fallback);
1410
    const calcContentBoxSize = (element, size, upper, lower) => {
1411
      const paddingUpper = getProp(element, `padding-${ upper }`, 0);
1412
      const paddingLower = getProp(element, `padding-${ lower }`, 0);
1413
      const borderUpper = getProp(element, `border-${ upper }-width`, 0);
1414
      const borderLower = getProp(element, `border-${ lower }-width`, 0);
1415
      return size - paddingUpper - paddingLower - borderUpper - borderLower;
1416
    };
1417
    const getCalculatedWidth = (element, boxSizing) => {
1418
      const dom = element.dom;
1419
      const width = dom.getBoundingClientRect().width || dom.offsetWidth;
1420
      return boxSizing === 'border-box' ? width : calcContentBoxSize(element, width, 'left', 'right');
1421
    };
1422
    const getHeight$1 = element => getProp(element, 'height', element.dom.offsetHeight);
1423
    const getWidth = element => getProp(element, 'width', element.dom.offsetWidth);
1424
    const getInnerWidth = element => getCalculatedWidth(element, 'content-box');
1425
 
1426
    const api$2 = Dimension('width', element => element.dom.offsetWidth);
1427
    const get$9 = element => api$2.get(element);
1428
    const getOuter$2 = element => api$2.getOuter(element);
1429
    const getInner = getInnerWidth;
1430
    const getRuntime$1 = getWidth;
1431
 
1432
    const addCells = (gridRow, index, cells) => {
1433
      const existingCells = gridRow.cells;
1434
      const before = existingCells.slice(0, index);
1435
      const after = existingCells.slice(index);
1436
      const newCells = before.concat(cells).concat(after);
1437
      return setCells(gridRow, newCells);
1438
    };
1439
    const addCell = (gridRow, index, cell) => addCells(gridRow, index, [cell]);
1440
    const mutateCell = (gridRow, index, cell) => {
1441
      const cells = gridRow.cells;
1442
      cells[index] = cell;
1443
    };
1444
    const setCells = (gridRow, cells) => rowcells(gridRow.element, cells, gridRow.section, gridRow.isNew);
1445
    const mapCells = (gridRow, f) => {
1446
      const cells = gridRow.cells;
1447
      const r = map$1(cells, f);
1448
      return rowcells(gridRow.element, r, gridRow.section, gridRow.isNew);
1449
    };
1450
    const getCell = (gridRow, index) => gridRow.cells[index];
1451
    const getCellElement = (gridRow, index) => getCell(gridRow, index).element;
1452
    const cellLength = gridRow => gridRow.cells.length;
1453
    const extractGridDetails = grid => {
1454
      const result = partition(grid, row => row.section === 'colgroup');
1455
      return {
1456
        rows: result.fail,
1457
        cols: result.pass
1458
      };
1459
    };
1460
    const clone = (gridRow, cloneRow, cloneCell) => {
1461
      const newCells = map$1(gridRow.cells, cloneCell);
1462
      return rowcells(cloneRow(gridRow.element), newCells, gridRow.section, true);
1463
    };
1464
 
1465
    const LOCKED_COL_ATTR = 'data-snooker-locked-cols';
1466
    const getLockedColumnsFromTable = table => getOpt(table, LOCKED_COL_ATTR).bind(lockedColStr => Optional.from(lockedColStr.match(/\d+/g))).map(lockedCols => mapToObject(lockedCols, always));
1467
    const getLockedColumnsFromGrid = grid => {
1468
      const locked = foldl(extractGridDetails(grid).rows, (acc, row) => {
1469
        each$2(row.cells, (cell, idx) => {
1470
          if (cell.isLocked) {
1471
            acc[idx] = true;
1472
          }
1473
        });
1474
        return acc;
1475
      }, {});
1476
      const lockedArr = mapToArray(locked, (_val, key) => parseInt(key, 10));
1477
      return sort$1(lockedArr);
1478
    };
1479
 
1480
    const key = (row, column) => {
1481
      return row + ',' + column;
1482
    };
1483
    const getAt = (warehouse, row, column) => Optional.from(warehouse.access[key(row, column)]);
1484
    const findItem = (warehouse, item, comparator) => {
1485
      const filtered = filterItems(warehouse, detail => {
1486
        return comparator(item, detail.element);
1487
      });
1488
      return filtered.length > 0 ? Optional.some(filtered[0]) : Optional.none();
1489
    };
1490
    const filterItems = (warehouse, predicate) => {
1491
      const all = bind$2(warehouse.all, r => {
1492
        return r.cells;
1493
      });
1494
      return filter$2(all, predicate);
1495
    };
1496
    const generateColumns = rowData => {
1497
      const columnsGroup = {};
1498
      let index = 0;
1499
      each$2(rowData.cells, column => {
1500
        const colspan = column.colspan;
1501
        range$1(colspan, columnIndex => {
1502
          const colIndex = index + columnIndex;
1503
          columnsGroup[colIndex] = columnext(column.element, colspan, colIndex);
1504
        });
1505
        index += colspan;
1506
      });
1507
      return columnsGroup;
1508
    };
1509
    const generate$1 = list => {
1510
      const access = {};
1511
      const cells = [];
1512
      const tableOpt = head(list).map(rowData => rowData.element).bind(table);
1513
      const lockedColumns = tableOpt.bind(getLockedColumnsFromTable).getOr({});
1514
      let maxRows = 0;
1515
      let maxColumns = 0;
1516
      let rowCount = 0;
1517
      const {
1518
        pass: colgroupRows,
1519
        fail: rows
1520
      } = partition(list, rowData => rowData.section === 'colgroup');
1521
      each$2(rows, rowData => {
1522
        const currentRow = [];
1523
        each$2(rowData.cells, rowCell => {
1524
          let start = 0;
1525
          while (access[key(rowCount, start)] !== undefined) {
1526
            start++;
1527
          }
1528
          const isLocked = hasNonNullableKey(lockedColumns, start.toString());
1529
          const current = extended(rowCell.element, rowCell.rowspan, rowCell.colspan, rowCount, start, isLocked);
1530
          for (let occupiedColumnPosition = 0; occupiedColumnPosition < rowCell.colspan; occupiedColumnPosition++) {
1531
            for (let occupiedRowPosition = 0; occupiedRowPosition < rowCell.rowspan; occupiedRowPosition++) {
1532
              const rowPosition = rowCount + occupiedRowPosition;
1533
              const columnPosition = start + occupiedColumnPosition;
1534
              const newpos = key(rowPosition, columnPosition);
1535
              access[newpos] = current;
1536
              maxColumns = Math.max(maxColumns, columnPosition + 1);
1537
            }
1538
          }
1539
          currentRow.push(current);
1540
        });
1541
        maxRows++;
1542
        cells.push(rowdetail(rowData.element, currentRow, rowData.section));
1543
        rowCount++;
1544
      });
1545
      const {columns, colgroups} = last$2(colgroupRows).map(rowData => {
1546
        const columns = generateColumns(rowData);
1547
        const colgroup$1 = colgroup(rowData.element, values(columns));
1548
        return {
1549
          colgroups: [colgroup$1],
1550
          columns
1551
        };
1552
      }).getOrThunk(() => ({
1553
        colgroups: [],
1554
        columns: {}
1555
      }));
1556
      const grid$1 = grid(maxRows, maxColumns);
1557
      return {
1558
        grid: grid$1,
1559
        access,
1560
        all: cells,
1561
        columns,
1562
        colgroups
1563
      };
1564
    };
1565
    const fromTable = table => {
1566
      const list = fromTable$1(table);
1567
      return generate$1(list);
1568
    };
1569
    const justCells = warehouse => bind$2(warehouse.all, w => w.cells);
1570
    const justColumns = warehouse => values(warehouse.columns);
1571
    const hasColumns = warehouse => keys(warehouse.columns).length > 0;
1572
    const getColumnAt = (warehouse, columnIndex) => Optional.from(warehouse.columns[columnIndex]);
1573
    const Warehouse = {
1574
      fromTable,
1575
      generate: generate$1,
1576
      getAt,
1577
      findItem,
1578
      filterItems,
1579
      justCells,
1580
      justColumns,
1581
      hasColumns,
1582
      getColumnAt
1583
    };
1584
 
1585
    const columns = (warehouse, isValidCell = always) => {
1586
      const grid = warehouse.grid;
1587
      const cols = range$1(grid.columns, identity);
1588
      const rowsArr = range$1(grid.rows, identity);
1589
      return map$1(cols, col => {
1590
        const getBlock = () => bind$2(rowsArr, r => Warehouse.getAt(warehouse, r, col).filter(detail => detail.column === col).toArray());
1591
        const isValid = detail => detail.colspan === 1 && isValidCell(detail.element);
1592
        const getFallback = () => Warehouse.getAt(warehouse, 0, col);
1593
        return decide(getBlock, isValid, getFallback);
1594
      });
1595
    };
1596
    const decide = (getBlock, isValid, getFallback) => {
1597
      const inBlock = getBlock();
1598
      const validInBlock = find$1(inBlock, isValid);
1599
      const detailOption = validInBlock.orThunk(() => Optional.from(inBlock[0]).orThunk(getFallback));
1600
      return detailOption.map(detail => detail.element);
1601
    };
1602
    const rows = warehouse => {
1603
      const grid = warehouse.grid;
1604
      const rowsArr = range$1(grid.rows, identity);
1605
      const cols = range$1(grid.columns, identity);
1606
      return map$1(rowsArr, row => {
1607
        const getBlock = () => bind$2(cols, c => Warehouse.getAt(warehouse, row, c).filter(detail => detail.row === row).fold(constant([]), detail => [detail]));
1608
        const isSingle = detail => detail.rowspan === 1;
1609
        const getFallback = () => Warehouse.getAt(warehouse, row, 0);
1610
        return decide(getBlock, isSingle, getFallback);
1611
      });
1612
    };
1613
 
1614
    const deduce = (xs, index) => {
1615
      if (index < 0 || index >= xs.length - 1) {
1616
        return Optional.none();
1617
      }
1618
      const current = xs[index].fold(() => {
1619
        const rest = reverse(xs.slice(0, index));
1620
        return findMap(rest, (a, i) => a.map(aa => ({
1621
          value: aa,
1622
          delta: i + 1
1623
        })));
1624
      }, c => Optional.some({
1625
        value: c,
1626
        delta: 0
1627
      }));
1628
      const next = xs[index + 1].fold(() => {
1629
        const rest = xs.slice(index + 1);
1630
        return findMap(rest, (a, i) => a.map(aa => ({
1631
          value: aa,
1632
          delta: i + 1
1633
        })));
1634
      }, n => Optional.some({
1635
        value: n,
1636
        delta: 1
1637
      }));
1638
      return current.bind(c => next.map(n => {
1639
        const extras = n.delta + c.delta;
1640
        return Math.abs(n.value - c.value) / extras;
1641
      }));
1642
    };
1643
 
1644
    const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
1645
    const getDirection = element => get$a(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
1646
 
1647
    const api$1 = Dimension('height', element => {
1648
      const dom = element.dom;
1649
      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
1650
    });
1651
    const get$8 = element => api$1.get(element);
1652
    const getOuter$1 = element => api$1.getOuter(element);
1653
    const getRuntime = getHeight$1;
1654
 
1655
    const r = (left, top) => {
1656
      const translate = (x, y) => r(left + x, top + y);
1657
      return {
1658
        left,
1659
        top,
1660
        translate
1661
      };
1662
    };
1663
    const SugarPosition = r;
1664
 
1665
    const boxPosition = dom => {
1666
      const box = dom.getBoundingClientRect();
1667
      return SugarPosition(box.left, box.top);
1668
    };
1669
    const firstDefinedOrZero = (a, b) => {
1670
      if (a !== undefined) {
1671
        return a;
1672
      } else {
1673
        return b !== undefined ? b : 0;
1674
      }
1675
    };
1676
    const absolute = element => {
1677
      const doc = element.dom.ownerDocument;
1678
      const body = doc.body;
1679
      const win = doc.defaultView;
1680
      const html = doc.documentElement;
1681
      if (body === element.dom) {
1682
        return SugarPosition(body.offsetLeft, body.offsetTop);
1683
      }
1684
      const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
1685
      const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
1686
      const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
1687
      const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
1688
      return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
1689
    };
1690
    const viewport = element => {
1691
      const dom = element.dom;
1692
      const doc = dom.ownerDocument;
1693
      const body = doc.body;
1694
      if (body === dom) {
1695
        return SugarPosition(body.offsetLeft, body.offsetTop);
1696
      }
1697
      if (!inBody(element)) {
1698
        return SugarPosition(0, 0);
1699
      }
1700
      return boxPosition(dom);
1701
    };
1702
 
1703
    const rowInfo = (row, y) => ({
1704
      row,
1705
      y
1706
    });
1707
    const colInfo = (col, x) => ({
1708
      col,
1709
      x
1710
    });
1711
    const rtlEdge = cell => {
1712
      const pos = absolute(cell);
1713
      return pos.left + getOuter$2(cell);
1714
    };
1715
    const ltrEdge = cell => {
1716
      return absolute(cell).left;
1717
    };
1718
    const getLeftEdge = (index, cell) => {
1719
      return colInfo(index, ltrEdge(cell));
1720
    };
1721
    const getRightEdge = (index, cell) => {
1722
      return colInfo(index, rtlEdge(cell));
1723
    };
1724
    const getTop$1 = cell => {
1725
      return absolute(cell).top;
1726
    };
1727
    const getTopEdge = (index, cell) => {
1728
      return rowInfo(index, getTop$1(cell));
1729
    };
1730
    const getBottomEdge = (index, cell) => {
1731
      return rowInfo(index, getTop$1(cell) + getOuter$1(cell));
1732
    };
1733
    const findPositions = (getInnerEdge, getOuterEdge, array) => {
1734
      if (array.length === 0) {
1735
        return [];
1736
      }
1737
      const lines = map$1(array.slice(1), (cellOption, index) => {
1738
        return cellOption.map(cell => {
1739
          return getInnerEdge(index, cell);
1740
        });
1741
      });
1742
      const lastLine = array[array.length - 1].map(cell => {
1743
        return getOuterEdge(array.length - 1, cell);
1744
      });
1745
      return lines.concat([lastLine]);
1746
    };
1747
    const negate = step => {
1748
      return -step;
1749
    };
1750
    const height = {
1751
      delta: identity,
1752
      positions: optElements => findPositions(getTopEdge, getBottomEdge, optElements),
1753
      edge: getTop$1
1754
    };
1755
    const ltr$1 = {
1756
      delta: identity,
1757
      edge: ltrEdge,
1758
      positions: optElements => findPositions(getLeftEdge, getRightEdge, optElements)
1759
    };
1760
    const rtl$1 = {
1761
      delta: negate,
1762
      edge: rtlEdge,
1763
      positions: optElements => findPositions(getRightEdge, getLeftEdge, optElements)
1764
    };
1765
    const detect$1 = onDirection(ltr$1, rtl$1);
1766
    const width = {
1767
      delta: (amount, table) => detect$1(table).delta(amount, table),
1768
      positions: (cols, table) => detect$1(table).positions(cols, table),
1769
      edge: cell => detect$1(cell).edge(cell)
1770
    };
1771
 
1772
    const units = {
1773
      unsupportedLength: [
1774
        'em',
1775
        'ex',
1776
        'cap',
1777
        'ch',
1778
        'ic',
1779
        'rem',
1780
        'lh',
1781
        'rlh',
1782
        'vw',
1783
        'vh',
1784
        'vi',
1785
        'vb',
1786
        'vmin',
1787
        'vmax',
1788
        'cm',
1789
        'mm',
1790
        'Q',
1791
        'in',
1792
        'pc',
1793
        'pt',
1794
        'px'
1795
      ],
1796
      fixed: [
1797
        'px',
1798
        'pt'
1799
      ],
1800
      relative: ['%'],
1801
      empty: ['']
1802
    };
1803
    const pattern = (() => {
1804
      const decimalDigits = '[0-9]+';
1805
      const signedInteger = '[+-]?' + decimalDigits;
1806
      const exponentPart = '[eE]' + signedInteger;
1807
      const dot = '\\.';
1808
      const opt = input => `(?:${ input })?`;
1809
      const unsignedDecimalLiteral = [
1810
        'Infinity',
1811
        decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
1812
        dot + decimalDigits + opt(exponentPart),
1813
        decimalDigits + opt(exponentPart)
1814
      ].join('|');
1815
      const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
1816
      return new RegExp(`^(${ float })(.*)$`);
1817
    })();
1818
    const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
1819
    const parse = (input, accepted) => {
1820
      const match = Optional.from(pattern.exec(input));
1821
      return match.bind(array => {
1822
        const value = Number(array[1]);
1823
        const unitRaw = array[2];
1824
        if (isUnit(unitRaw, accepted)) {
1825
          return Optional.some({
1826
            value,
1827
            unit: unitRaw
1828
          });
1829
        } else {
1830
          return Optional.none();
1831
        }
1832
      });
1833
    };
1834
 
1835
    const rPercentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
1836
    const rPixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/;
1837
    const isCol$2 = isTag('col');
1838
    const getPercentSize = (elm, outerGetter, innerGetter) => {
1839
      const relativeParent = parentElement(elm).getOrThunk(() => getBody$1(owner(elm)));
1840
      return outerGetter(elm) / innerGetter(relativeParent) * 100;
1841
    };
1842
    const setPixelWidth = (cell, amount) => {
1843
      set$1(cell, 'width', amount + 'px');
1844
    };
1845
    const setPercentageWidth = (cell, amount) => {
1846
      set$1(cell, 'width', amount + '%');
1847
    };
1848
    const setHeight = (cell, amount) => {
1849
      set$1(cell, 'height', amount + 'px');
1850
    };
1851
    const getHeightValue = cell => getRuntime(cell) + 'px';
1852
    const convert = (cell, number, getter, setter) => {
1853
      const newSize = table(cell).map(table => {
1854
        const total = getter(table);
1855
        return Math.floor(number / 100 * total);
1856
      }).getOr(number);
1857
      setter(cell, newSize);
1858
      return newSize;
1859
    };
1860
    const normalizePixelSize = (value, cell, getter, setter) => {
1861
      const number = parseFloat(value);
1862
      return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number;
1863
    };
1864
    const getTotalHeight = cell => {
1865
      const value = getHeightValue(cell);
1866
      if (!value) {
1867
        return get$8(cell);
1868
      }
1869
      return normalizePixelSize(value, cell, get$8, setHeight);
1870
    };
1871
    const get$7 = (cell, type, f) => {
1872
      const v = f(cell);
1873
      const span = getSpan(cell, type);
1874
      return v / span;
1875
    };
1876
    const getRaw$1 = (element, prop) => {
1877
      return getRaw$2(element, prop).orThunk(() => {
1878
        return getOpt(element, prop).map(val => val + 'px');
1879
      });
1880
    };
1881
    const getRawWidth$1 = element => getRaw$1(element, 'width');
1882
    const getRawHeight = element => getRaw$1(element, 'height');
1883
    const getPercentageWidth = cell => getPercentSize(cell, get$9, getInner);
1884
    const getPixelWidth$1 = cell => isCol$2(cell) ? get$9(cell) : getRuntime$1(cell);
1885
    const getHeight = cell => {
1886
      return get$7(cell, 'rowspan', getTotalHeight);
1887
    };
1888
    const getGenericWidth = cell => {
1889
      const width = getRawWidth$1(cell);
1890
      return width.bind(w => parse(w, [
1891
        'fixed',
1892
        'relative',
1893
        'empty'
1894
      ]));
1895
    };
1896
    const setGenericWidth = (cell, amount, unit) => {
1897
      set$1(cell, 'width', amount + unit);
1898
    };
1899
    const getPixelTableWidth = table => get$9(table) + 'px';
1900
    const getPercentTableWidth = table => getPercentSize(table, get$9, getInner) + '%';
1901
    const isPercentSizing$1 = table => getRawWidth$1(table).exists(size => rPercentageBasedSizeRegex.test(size));
1902
    const isPixelSizing$1 = table => getRawWidth$1(table).exists(size => rPixelBasedSizeRegex.test(size));
1903
    const isNoneSizing$1 = table => getRawWidth$1(table).isNone();
1904
    const percentageBasedSizeRegex = constant(rPercentageBasedSizeRegex);
1905
 
1906
    const isCol$1 = isTag('col');
1907
    const getRawW = cell => {
1908
      return getRawWidth$1(cell).getOrThunk(() => getPixelWidth$1(cell) + 'px');
1909
    };
1910
    const getRawH = cell => {
1911
      return getRawHeight(cell).getOrThunk(() => getHeight(cell) + 'px');
1912
    };
1913
    const justCols = warehouse => map$1(Warehouse.justColumns(warehouse), column => Optional.from(column.element));
1914
    const isValidColumn = cell => {
1915
      const browser = detect$2().browser;
1916
      const supportsColWidths = browser.isChromium() || browser.isFirefox();
1917
      return isCol$1(cell) ? supportsColWidths : true;
1918
    };
1919
    const getDimension = (cellOpt, index, backups, filter, getter, fallback) => cellOpt.filter(filter).fold(() => fallback(deduce(backups, index)), cell => getter(cell));
1920
    const getWidthFrom = (warehouse, table, getWidth, fallback) => {
1921
      const columnCells = columns(warehouse);
1922
      const columns$1 = Warehouse.hasColumns(warehouse) ? justCols(warehouse) : columnCells;
1923
      const backups = [Optional.some(width.edge(table))].concat(map$1(width.positions(columnCells, table), pos => pos.map(p => p.x)));
1924
      const colFilter = not(hasColspan);
1925
      return map$1(columns$1, (cellOption, c) => {
1926
        return getDimension(cellOption, c, backups, colFilter, column => {
1927
          if (isValidColumn(column)) {
1928
            return getWidth(column);
1929
          } else {
1930
            const cell = bindFrom(columnCells[c], identity);
1931
            return getDimension(cell, c, backups, colFilter, cell => fallback(Optional.some(get$9(cell))), fallback);
1932
          }
1933
        }, fallback);
1934
      });
1935
    };
1936
    const getDeduced = deduced => {
1937
      return deduced.map(d => {
1938
        return d + 'px';
1939
      }).getOr('');
1940
    };
1941
    const getRawWidths = (warehouse, table) => {
1942
      return getWidthFrom(warehouse, table, getRawW, getDeduced);
1943
    };
1944
    const getPercentageWidths = (warehouse, table, tableSize) => {
1945
      return getWidthFrom(warehouse, table, getPercentageWidth, deduced => {
1946
        return deduced.fold(() => {
1947
          return tableSize.minCellWidth();
1948
        }, cellWidth => {
1949
          return cellWidth / tableSize.pixelWidth() * 100;
1950
        });
1951
      });
1952
    };
1953
    const getPixelWidths = (warehouse, table, tableSize) => {
1954
      return getWidthFrom(warehouse, table, getPixelWidth$1, deduced => {
1955
        return deduced.getOrThunk(tableSize.minCellWidth);
1956
      });
1957
    };
1958
    const getHeightFrom = (warehouse, table, direction, getHeight, fallback) => {
1959
      const rows$1 = rows(warehouse);
1960
      const backups = [Optional.some(direction.edge(table))].concat(map$1(direction.positions(rows$1, table), pos => pos.map(p => p.y)));
1961
      return map$1(rows$1, (cellOption, c) => {
1962
        return getDimension(cellOption, c, backups, not(hasRowspan), getHeight, fallback);
1963
      });
1964
    };
1965
    const getPixelHeights = (warehouse, table, direction) => {
1966
      return getHeightFrom(warehouse, table, direction, getHeight, deduced => {
1967
        return deduced.getOrThunk(minHeight);
1968
      });
1969
    };
1970
    const getRawHeights = (warehouse, table, direction) => {
1971
      return getHeightFrom(warehouse, table, direction, getRawH, getDeduced);
1972
    };
1973
 
1974
    const widthLookup = (table, getter) => () => {
1975
      if (inBody(table)) {
1976
        return getter(table);
1977
      } else {
1978
        return parseFloat(getRaw$2(table, 'width').getOr('0'));
1979
      }
1980
    };
1981
    const noneSize = table => {
1982
      const getWidth = widthLookup(table, get$9);
1983
      const zero = constant(0);
1984
      const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
1985
      return {
1986
        width: getWidth,
1987
        pixelWidth: getWidth,
1988
        getWidths,
1989
        getCellDelta: zero,
1990
        singleColumnWidth: constant([0]),
1991
        minCellWidth: zero,
1992
        setElementWidth: noop,
1993
        adjustTableWidth: noop,
1994
        isRelative: true,
1995
        label: 'none'
1996
      };
1997
    };
1998
    const percentageSize = table => {
1999
      const getFloatWidth = widthLookup(table, elem => parseFloat(getPercentTableWidth(elem)));
2000
      const getWidth = widthLookup(table, get$9);
2001
      const getCellDelta = delta => delta / getWidth() * 100;
2002
      const singleColumnWidth = (w, _delta) => [100 - w];
2003
      const minCellWidth = () => minWidth() / getWidth() * 100;
2004
      const adjustTableWidth = delta => {
2005
        const currentWidth = getFloatWidth();
2006
        const change = delta / 100 * currentWidth;
2007
        const newWidth = currentWidth + change;
2008
        setPercentageWidth(table, newWidth);
2009
      };
2010
      const getWidths = (warehouse, tableSize) => getPercentageWidths(warehouse, table, tableSize);
2011
      return {
2012
        width: getFloatWidth,
2013
        pixelWidth: getWidth,
2014
        getWidths,
2015
        getCellDelta,
2016
        singleColumnWidth,
2017
        minCellWidth,
2018
        setElementWidth: setPercentageWidth,
2019
        adjustTableWidth,
2020
        isRelative: true,
2021
        label: 'percent'
2022
      };
2023
    };
2024
    const pixelSize = table => {
2025
      const getWidth = widthLookup(table, get$9);
2026
      const getCellDelta = identity;
2027
      const singleColumnWidth = (w, delta) => {
2028
        const newNext = Math.max(minWidth(), w + delta);
2029
        return [newNext - w];
2030
      };
2031
      const adjustTableWidth = delta => {
2032
        const newWidth = getWidth() + delta;
2033
        setPixelWidth(table, newWidth);
2034
      };
2035
      const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
2036
      return {
2037
        width: getWidth,
2038
        pixelWidth: getWidth,
2039
        getWidths,
2040
        getCellDelta,
2041
        singleColumnWidth,
2042
        minCellWidth: minWidth,
2043
        setElementWidth: setPixelWidth,
2044
        adjustTableWidth,
2045
        isRelative: false,
2046
        label: 'pixel'
2047
      };
2048
    };
2049
    const chooseSize = (element, width) => {
2050
      const percentMatch = percentageBasedSizeRegex().exec(width);
2051
      if (percentMatch !== null) {
2052
        return percentageSize(element);
2053
      } else {
2054
        return pixelSize(element);
2055
      }
2056
    };
2057
    const getTableSize = table => {
2058
      const width = getRawWidth$1(table);
2059
      return width.fold(() => noneSize(table), w => chooseSize(table, w));
2060
    };
2061
    const TableSize = {
2062
      getTableSize,
2063
      pixelSize,
2064
      percentageSize,
2065
      noneSize
2066
    };
2067
 
2068
    const statsStruct = (minRow, minCol, maxRow, maxCol, allCells, selectedCells) => ({
2069
      minRow,
2070
      minCol,
2071
      maxRow,
2072
      maxCol,
2073
      allCells,
2074
      selectedCells
2075
    });
2076
    const findSelectedStats = (house, isSelected) => {
2077
      const totalColumns = house.grid.columns;
2078
      const totalRows = house.grid.rows;
2079
      let minRow = totalRows;
2080
      let minCol = totalColumns;
2081
      let maxRow = 0;
2082
      let maxCol = 0;
2083
      const allCells = [];
2084
      const selectedCells = [];
2085
      each$1(house.access, detail => {
2086
        allCells.push(detail);
2087
        if (isSelected(detail)) {
2088
          selectedCells.push(detail);
2089
          const startRow = detail.row;
2090
          const endRow = startRow + detail.rowspan - 1;
2091
          const startCol = detail.column;
2092
          const endCol = startCol + detail.colspan - 1;
2093
          if (startRow < minRow) {
2094
            minRow = startRow;
2095
          } else if (endRow > maxRow) {
2096
            maxRow = endRow;
2097
          }
2098
          if (startCol < minCol) {
2099
            minCol = startCol;
2100
          } else if (endCol > maxCol) {
2101
            maxCol = endCol;
2102
          }
2103
        }
2104
      });
2105
      return statsStruct(minRow, minCol, maxRow, maxCol, allCells, selectedCells);
2106
    };
2107
    const makeCell = (list, seenSelected, rowIndex) => {
2108
      const row = list[rowIndex].element;
2109
      const td = SugarElement.fromTag('td');
2110
      append$1(td, SugarElement.fromTag('br'));
2111
      const f = seenSelected ? append$1 : prepend;
2112
      f(row, td);
2113
    };
2114
    const fillInGaps = (list, house, stats, isSelected) => {
2115
      const rows = filter$2(list, row => row.section !== 'colgroup');
2116
      const totalColumns = house.grid.columns;
2117
      const totalRows = house.grid.rows;
2118
      for (let i = 0; i < totalRows; i++) {
2119
        let seenSelected = false;
2120
        for (let j = 0; j < totalColumns; j++) {
2121
          if (!(i < stats.minRow || i > stats.maxRow || j < stats.minCol || j > stats.maxCol)) {
2122
            const needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone();
2123
            if (needCell) {
2124
              makeCell(rows, seenSelected, i);
2125
            } else {
2126
              seenSelected = true;
2127
            }
2128
          }
2129
        }
2130
      }
2131
    };
2132
    const clean = (replica, stats, house, widthDelta) => {
2133
      each$1(house.columns, col => {
2134
        if (col.column < stats.minCol || col.column > stats.maxCol) {
2135
          remove$6(col.element);
2136
        }
2137
      });
2138
      const emptyRows = filter$2(firstLayer(replica, 'tr'), row => row.dom.childElementCount === 0);
2139
      each$2(emptyRows, remove$6);
2140
      if (stats.minCol === stats.maxCol || stats.minRow === stats.maxRow) {
2141
        each$2(firstLayer(replica, 'th,td'), cell => {
2142
          remove$7(cell, 'rowspan');
2143
          remove$7(cell, 'colspan');
2144
        });
2145
      }
2146
      remove$7(replica, LOCKED_COL_ATTR);
2147
      remove$7(replica, 'data-snooker-col-series');
2148
      const tableSize = TableSize.getTableSize(replica);
2149
      tableSize.adjustTableWidth(widthDelta);
2150
    };
2151
    const getTableWidthDelta = (table, warehouse, tableSize, stats) => {
2152
      if (stats.minCol === 0 && warehouse.grid.columns === stats.maxCol + 1) {
2153
        return 0;
2154
      }
2155
      const colWidths = getPixelWidths(warehouse, table, tableSize);
2156
      const allColsWidth = foldl(colWidths, (acc, width) => acc + width, 0);
2157
      const selectedColsWidth = foldl(colWidths.slice(stats.minCol, stats.maxCol + 1), (acc, width) => acc + width, 0);
2158
      const newWidth = selectedColsWidth / allColsWidth * tableSize.pixelWidth();
2159
      const delta = newWidth - tableSize.pixelWidth();
2160
      return tableSize.getCellDelta(delta);
2161
    };
2162
    const extract$1 = (table, selectedSelector) => {
2163
      const isSelected = detail => is$2(detail.element, selectedSelector);
2164
      const replica = deep(table);
2165
      const list = fromTable$1(replica);
2166
      const tableSize = TableSize.getTableSize(table);
2167
      const replicaHouse = Warehouse.generate(list);
2168
      const replicaStats = findSelectedStats(replicaHouse, isSelected);
2169
      const selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')';
2170
      const unselectedCells = filterFirstLayer(replica, 'th,td', cell => is$2(cell, selector));
2171
      each$2(unselectedCells, remove$6);
2172
      fillInGaps(list, replicaHouse, replicaStats, isSelected);
2173
      const house = Warehouse.fromTable(table);
2174
      const widthDelta = getTableWidthDelta(table, house, tableSize, replicaStats);
2175
      clean(replica, replicaStats, replicaHouse, widthDelta);
2176
      return replica;
2177
    };
2178
 
2179
    const nbsp = '\xA0';
2180
 
2181
    const NodeValue = (is, name) => {
2182
      const get = element => {
2183
        if (!is(element)) {
2184
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
2185
        }
2186
        return getOption(element).getOr('');
2187
      };
2188
      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
2189
      const set = (element, value) => {
2190
        if (!is(element)) {
2191
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
2192
        }
2193
        element.dom.nodeValue = value;
2194
      };
2195
      return {
2196
        get,
2197
        getOption,
2198
        set
2199
      };
2200
    };
2201
 
2202
    const api = NodeValue(isText, 'text');
2203
    const get$6 = element => api.get(element);
2204
    const getOption = element => api.getOption(element);
2205
    const set = (element, value) => api.set(element, value);
2206
 
2207
    const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$2(element).length, v => v.length);
2208
    const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
2209
    const isContentEditableFalse = elem => isHTMLElement(elem) && get$b(elem, 'contenteditable') === 'false';
2210
    const elementsWithCursorPosition = [
2211
      'img',
2212
      'br'
2213
    ];
2214
    const isCursorPosition = elem => {
2215
      const hasCursorPosition = isTextNodeWithCursorPosition(elem);
2216
      return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse(elem);
2217
    };
2218
 
2219
    const first = element => descendant$1(element, isCursorPosition);
2220
    const last$1 = element => descendantRtl(element, isCursorPosition);
2221
    const descendantRtl = (scope, predicate) => {
2222
      const descend = element => {
2223
        const children = children$2(element);
2224
        for (let i = children.length - 1; i >= 0; i--) {
2225
          const child = children[i];
2226
          if (predicate(child)) {
2227
            return Optional.some(child);
2228
          }
2229
          const res = descend(child);
2230
          if (res.isSome()) {
2231
            return res;
2232
          }
2233
        }
2234
        return Optional.none();
2235
      };
2236
      return descend(scope);
2237
    };
2238
 
2239
    const transferableAttributes = {
2240
      scope: [
2241
        'row',
2242
        'col'
2243
      ]
2244
    };
2245
    const createCell = doc => () => {
2246
      const td = SugarElement.fromTag('td', doc.dom);
2247
      append$1(td, SugarElement.fromTag('br', doc.dom));
2248
      return td;
2249
    };
2250
    const createCol = doc => () => {
2251
      return SugarElement.fromTag('col', doc.dom);
2252
    };
2253
    const createColgroup = doc => () => {
2254
      return SugarElement.fromTag('colgroup', doc.dom);
2255
    };
2256
    const createRow$1 = doc => () => {
2257
      return SugarElement.fromTag('tr', doc.dom);
2258
    };
2259
    const replace$1 = (cell, tag, attrs) => {
2260
      const replica = copy$2(cell, tag);
2261
      each$1(attrs, (v, k) => {
2262
        if (v === null) {
2263
          remove$7(replica, k);
2264
        } else {
2265
          set$2(replica, k, v);
2266
        }
2267
      });
2268
      return replica;
2269
    };
2270
    const pasteReplace = cell => {
2271
      return cell;
2272
    };
2273
    const cloneFormats = (oldCell, newCell, formats) => {
2274
      const first$1 = first(oldCell);
2275
      return first$1.map(firstText => {
2276
        const formatSelector = formats.join(',');
2277
        const parents = ancestors$3(firstText, formatSelector, element => {
2278
          return eq$1(element, oldCell);
2279
        });
2280
        return foldr(parents, (last, parent) => {
2281
          const clonedFormat = shallow(parent);
2282
          append$1(last, clonedFormat);
2283
          return clonedFormat;
2284
        }, newCell);
2285
      }).getOr(newCell);
2286
    };
2287
    const cloneAppropriateAttributes = (original, clone) => {
2288
      each$1(transferableAttributes, (validAttributes, attributeName) => getOpt(original, attributeName).filter(attribute => contains$2(validAttributes, attribute)).each(attribute => set$2(clone, attributeName, attribute)));
2289
    };
2290
    const cellOperations = (mutate, doc, formatsToClone) => {
2291
      const cloneCss = (prev, clone) => {
2292
        copy$1(prev.element, clone);
2293
        remove$5(clone, 'height');
2294
        if (prev.colspan !== 1) {
2295
          remove$5(clone, 'width');
2296
        }
2297
      };
2298
      const newCell = prev => {
2299
        const td = SugarElement.fromTag(name(prev.element), doc.dom);
2300
        const formats = formatsToClone.getOr([
2301
          'strong',
2302
          'em',
2303
          'b',
2304
          'i',
2305
          'span',
2306
          'font',
2307
          'h1',
2308
          'h2',
2309
          'h3',
2310
          'h4',
2311
          'h5',
2312
          'h6',
2313
          'p',
2314
          'div'
2315
        ]);
2316
        const lastNode = formats.length > 0 ? cloneFormats(prev.element, td, formats) : td;
2317
        append$1(lastNode, SugarElement.fromTag('br'));
2318
        cloneCss(prev, td);
2319
        cloneAppropriateAttributes(prev.element, td);
2320
        mutate(prev.element, td);
2321
        return td;
2322
      };
2323
      const newCol = prev => {
2324
        const col = SugarElement.fromTag(name(prev.element), doc.dom);
2325
        cloneCss(prev, col);
2326
        mutate(prev.element, col);
2327
        return col;
2328
      };
2329
      return {
2330
        col: newCol,
2331
        colgroup: createColgroup(doc),
2332
        row: createRow$1(doc),
2333
        cell: newCell,
2334
        replace: replace$1,
2335
        colGap: createCol(doc),
2336
        gap: createCell(doc)
2337
      };
2338
    };
2339
    const paste$1 = doc => {
2340
      return {
2341
        col: createCol(doc),
2342
        colgroup: createColgroup(doc),
2343
        row: createRow$1(doc),
2344
        cell: createCell(doc),
2345
        replace: pasteReplace,
2346
        colGap: createCol(doc),
2347
        gap: createCell(doc)
2348
      };
2349
    };
2350
 
2351
    const fromHtml = (html, scope) => {
2352
      const doc = scope || document;
2353
      const div = doc.createElement('div');
2354
      div.innerHTML = html;
2355
      return children$2(SugarElement.fromDom(div));
2356
    };
2357
    const fromDom = nodes => map$1(nodes, SugarElement.fromDom);
2358
 
2359
    const option = name => editor => editor.options.get(name);
2360
    const defaultWidth = '100%';
2361
    const getPixelForcedWidth = editor => {
2362
      var _a;
2363
      const dom = editor.dom;
2364
      const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
2365
      return getInner(SugarElement.fromDom(parentBlock)) + 'px';
2366
    };
2367
    const determineDefaultTableStyles = (editor, defaultStyles) => {
2368
      if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
2369
        return defaultStyles;
2370
      } else if (isTablePixelsForced(editor)) {
2371
        return {
2372
          ...defaultStyles,
2373
          width: getPixelForcedWidth(editor)
2374
        };
2375
      } else {
2376
        return {
2377
          ...defaultStyles,
2378
          width: defaultWidth
2379
        };
2380
      }
2381
    };
2382
    const determineDefaultTableAttributes = (editor, defaultAttributes) => {
2383
      if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
2384
        return defaultAttributes;
2385
      } else if (isTablePixelsForced(editor)) {
2386
        return {
2387
          ...defaultAttributes,
2388
          width: getPixelForcedWidth(editor)
2389
        };
2390
      } else {
2391
        return {
2392
          ...defaultAttributes,
2393
          width: defaultWidth
2394
        };
2395
      }
2396
    };
2397
    const register = editor => {
2398
      const registerOption = editor.options.register;
2399
      registerOption('table_clone_elements', { processor: 'string[]' });
2400
      registerOption('table_use_colgroups', {
2401
        processor: 'boolean',
2402
        default: true
2403
      });
2404
      registerOption('table_header_type', {
2405
        processor: value => {
2406
          const valid = contains$2([
2407
            'section',
2408
            'cells',
2409
            'sectionCells',
2410
            'auto'
2411
          ], value);
2412
          return valid ? {
2413
            value,
2414
            valid
2415
          } : {
2416
            valid: false,
2417
            message: 'Must be one of: section, cells, sectionCells or auto.'
2418
          };
2419
        },
2420
        default: 'section'
2421
      });
2422
      registerOption('table_sizing_mode', {
2423
        processor: 'string',
2424
        default: 'auto'
2425
      });
2426
      registerOption('table_default_attributes', {
2427
        processor: 'object',
2428
        default: { border: '1' }
2429
      });
2430
      registerOption('table_default_styles', {
2431
        processor: 'object',
2432
        default: { 'border-collapse': 'collapse' }
2433
      });
2434
      registerOption('table_column_resizing', {
2435
        processor: value => {
2436
          const valid = contains$2([
2437
            'preservetable',
2438
            'resizetable'
2439
          ], value);
2440
          return valid ? {
2441
            value,
2442
            valid
2443
          } : {
2444
            valid: false,
2445
            message: 'Must be preservetable, or resizetable.'
2446
          };
2447
        },
2448
        default: 'preservetable'
2449
      });
2450
      registerOption('table_resize_bars', {
2451
        processor: 'boolean',
2452
        default: true
2453
      });
2454
      registerOption('table_style_by_css', {
2455
        processor: 'boolean',
2456
        default: true
2457
      });
2458
      registerOption('table_merge_content_on_paste', {
2459
        processor: 'boolean',
2460
        default: true
2461
      });
2462
    };
2463
    const getTableCloneElements = editor => {
2464
      return Optional.from(editor.options.get('table_clone_elements'));
2465
    };
2466
    const hasTableObjectResizing = editor => {
2467
      const objectResizing = editor.options.get('object_resizing');
2468
      return contains$2(objectResizing.split(','), 'table');
2469
    };
2470
    const getTableHeaderType = option('table_header_type');
2471
    const getTableColumnResizingBehaviour = option('table_column_resizing');
2472
    const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
2473
    const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
2474
    const getTableSizingMode = option('table_sizing_mode');
2475
    const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
2476
    const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
2477
    const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
2478
    const hasTableResizeBars = option('table_resize_bars');
2479
    const shouldStyleWithCss = option('table_style_by_css');
2480
    const shouldMergeContentOnPaste = option('table_merge_content_on_paste');
2481
    const getTableDefaultAttributes = editor => {
2482
      const options = editor.options;
2483
      const defaultAttributes = options.get('table_default_attributes');
2484
      return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
2485
    };
2486
    const getTableDefaultStyles = editor => {
2487
      const options = editor.options;
2488
      const defaultStyles = options.get('table_default_styles');
2489
      return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
2490
    };
2491
    const tableUseColumnGroup = option('table_use_colgroups');
2492
 
2493
    const closest = target => closest$1(target, '[contenteditable]');
2494
    const isEditable$1 = (element, assumeEditable = false) => {
2495
      if (inBody(element)) {
2496
        return element.dom.isContentEditable;
2497
      } else {
2498
        return closest(element).fold(constant(assumeEditable), editable => getRaw(editable) === 'true');
2499
      }
2500
    };
2501
    const getRaw = element => element.dom.contentEditable;
2502
 
2503
    const getBody = editor => SugarElement.fromDom(editor.getBody());
2504
    const getIsRoot = editor => element => eq$1(element, getBody(editor));
2505
    const removeDataStyle = table => {
2506
      remove$7(table, 'data-mce-style');
2507
      const removeStyleAttribute = element => remove$7(element, 'data-mce-style');
2508
      each$2(cells$1(table), removeStyleAttribute);
2509
      each$2(columns$1(table), removeStyleAttribute);
2510
      each$2(rows$1(table), removeStyleAttribute);
2511
    };
2512
    const getSelectionStart = editor => SugarElement.fromDom(editor.selection.getStart());
2513
    const getPixelWidth = elm => elm.getBoundingClientRect().width;
2514
    const getPixelHeight = elm => elm.getBoundingClientRect().height;
2515
    const getRawWidth = (editor, elm) => {
2516
      const raw = editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width');
2517
      return Optional.from(raw).filter(isNotEmpty);
2518
    };
2519
    const isPercentage$1 = value => /^(\d+(\.\d+)?)%$/.test(value);
2520
    const isPixel = value => /^(\d+(\.\d+)?)px$/.test(value);
2521
    const isInEditableContext$1 = cell => closest$2(cell, isTag('table')).exists(isEditable$1);
2522
 
2523
    const inSelection = (bounds, detail) => {
2524
      const leftEdge = detail.column;
2525
      const rightEdge = detail.column + detail.colspan - 1;
2526
      const topEdge = detail.row;
2527
      const bottomEdge = detail.row + detail.rowspan - 1;
2528
      return leftEdge <= bounds.finishCol && rightEdge >= bounds.startCol && (topEdge <= bounds.finishRow && bottomEdge >= bounds.startRow);
2529
    };
2530
    const isWithin = (bounds, detail) => {
2531
      return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow;
2532
    };
2533
    const isRectangular = (warehouse, bounds) => {
2534
      let isRect = true;
2535
      const detailIsWithin = curry(isWithin, bounds);
2536
      for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
2537
        for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
2538
          isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin);
2539
        }
2540
      }
2541
      return isRect ? Optional.some(bounds) : Optional.none();
2542
    };
2543
 
2544
    const getBounds = (detailA, detailB) => {
2545
      return bounds(Math.min(detailA.row, detailB.row), Math.min(detailA.column, detailB.column), Math.max(detailA.row + detailA.rowspan - 1, detailB.row + detailB.rowspan - 1), Math.max(detailA.column + detailA.colspan - 1, detailB.column + detailB.colspan - 1));
2546
    };
2547
    const getAnyBox = (warehouse, startCell, finishCell) => {
2548
      const startCoords = Warehouse.findItem(warehouse, startCell, eq$1);
2549
      const finishCoords = Warehouse.findItem(warehouse, finishCell, eq$1);
2550
      return startCoords.bind(sc => {
2551
        return finishCoords.map(fc => {
2552
          return getBounds(sc, fc);
2553
        });
2554
      });
2555
    };
2556
    const getBox$1 = (warehouse, startCell, finishCell) => {
2557
      return getAnyBox(warehouse, startCell, finishCell).bind(bounds => {
2558
        return isRectangular(warehouse, bounds);
2559
      });
2560
    };
2561
 
2562
    const moveBy$1 = (warehouse, cell, row, column) => {
2563
      return Warehouse.findItem(warehouse, cell, eq$1).bind(detail => {
2564
        const startRow = row > 0 ? detail.row + detail.rowspan - 1 : detail.row;
2565
        const startCol = column > 0 ? detail.column + detail.colspan - 1 : detail.column;
2566
        const dest = Warehouse.getAt(warehouse, startRow + row, startCol + column);
2567
        return dest.map(d => {
2568
          return d.element;
2569
        });
2570
      });
2571
    };
2572
    const intercepts$1 = (warehouse, start, finish) => {
2573
      return getAnyBox(warehouse, start, finish).map(bounds => {
2574
        const inside = Warehouse.filterItems(warehouse, curry(inSelection, bounds));
2575
        return map$1(inside, detail => {
2576
          return detail.element;
2577
        });
2578
      });
2579
    };
2580
    const parentCell = (warehouse, innerCell) => {
2581
      const isContainedBy = (c1, c2) => {
2582
        return contains$1(c2, c1);
2583
      };
2584
      return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(detail => {
2585
        return detail.element;
2586
      });
2587
    };
2588
 
2589
    const moveBy = (cell, deltaRow, deltaColumn) => {
2590
      return table(cell).bind(table => {
2591
        const warehouse = getWarehouse(table);
2592
        return moveBy$1(warehouse, cell, deltaRow, deltaColumn);
2593
      });
2594
    };
2595
    const intercepts = (table, first, last) => {
2596
      const warehouse = getWarehouse(table);
2597
      return intercepts$1(warehouse, first, last);
2598
    };
2599
    const nestedIntercepts = (table, first, firstTable, last, lastTable) => {
2600
      const warehouse = getWarehouse(table);
2601
      const optStartCell = eq$1(table, firstTable) ? Optional.some(first) : parentCell(warehouse, first);
2602
      const optLastCell = eq$1(table, lastTable) ? Optional.some(last) : parentCell(warehouse, last);
2603
      return optStartCell.bind(startCell => optLastCell.bind(lastCell => intercepts$1(warehouse, startCell, lastCell)));
2604
    };
2605
    const getBox = (table, first, last) => {
2606
      const warehouse = getWarehouse(table);
2607
      return getBox$1(warehouse, first, last);
2608
    };
2609
    const getWarehouse = Warehouse.fromTable;
2610
 
2611
    var TagBoundaries = [
2612
      'body',
2613
      'p',
2614
      'div',
2615
      'article',
2616
      'aside',
2617
      'figcaption',
2618
      'figure',
2619
      'footer',
2620
      'header',
2621
      'nav',
2622
      'section',
2623
      'ol',
2624
      'ul',
2625
      'li',
2626
      'table',
2627
      'thead',
2628
      'tbody',
2629
      'tfoot',
2630
      'caption',
2631
      'tr',
2632
      'td',
2633
      'th',
2634
      'h1',
2635
      'h2',
2636
      'h3',
2637
      'h4',
2638
      'h5',
2639
      'h6',
2640
      'blockquote',
2641
      'pre',
2642
      'address'
2643
    ];
2644
 
2645
    var DomUniverse = () => {
2646
      const clone = element => {
2647
        return SugarElement.fromDom(element.dom.cloneNode(false));
2648
      };
2649
      const document = element => documentOrOwner(element).dom;
2650
      const isBoundary = element => {
2651
        if (!isElement(element)) {
2652
          return false;
2653
        }
2654
        if (name(element) === 'body') {
2655
          return true;
2656
        }
2657
        return contains$2(TagBoundaries, name(element));
2658
      };
2659
      const isEmptyTag = element => {
2660
        if (!isElement(element)) {
2661
          return false;
2662
        }
2663
        return contains$2([
2664
          'br',
2665
          'img',
2666
          'hr',
2667
          'input'
2668
        ], name(element));
2669
      };
2670
      const isNonEditable = element => isElement(element) && get$b(element, 'contenteditable') === 'false';
2671
      const comparePosition = (element, other) => {
2672
        return element.dom.compareDocumentPosition(other.dom);
2673
      };
2674
      const copyAttributesTo = (source, destination) => {
2675
        const as = clone$2(source);
2676
        setAll$1(destination, as);
2677
      };
2678
      const isSpecial = element => {
2679
        const tag = name(element);
2680
        return contains$2([
2681
          'script',
2682
          'noscript',
2683
          'iframe',
2684
          'noframes',
2685
          'noembed',
2686
          'title',
2687
          'style',
2688
          'textarea',
2689
          'xmp'
2690
        ], tag);
2691
      };
2692
      const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none();
2693
      return {
2694
        up: constant({
2695
          selector: ancestor$1,
2696
          closest: closest$1,
2697
          predicate: ancestor$2,
2698
          all: parents
2699
        }),
2700
        down: constant({
2701
          selector: descendants,
2702
          predicate: descendants$1
2703
        }),
2704
        styles: constant({
2705
          get: get$a,
2706
          getRaw: getRaw$2,
2707
          set: set$1,
2708
          remove: remove$5
2709
        }),
2710
        attrs: constant({
2711
          get: get$b,
2712
          set: set$2,
2713
          remove: remove$7,
2714
          copyTo: copyAttributesTo
2715
        }),
2716
        insert: constant({
2717
          before: before$3,
2718
          after: after$5,
2719
          afterAll: after$4,
2720
          append: append$1,
2721
          appendAll: append,
2722
          prepend: prepend,
2723
          wrap: wrap
2724
        }),
2725
        remove: constant({
2726
          unwrap: unwrap,
2727
          remove: remove$6
2728
        }),
2729
        create: constant({
2730
          nu: SugarElement.fromTag,
2731
          clone,
2732
          text: SugarElement.fromText
2733
        }),
2734
        query: constant({
2735
          comparePosition,
2736
          prevSibling: prevSibling,
2737
          nextSibling: nextSibling
2738
        }),
2739
        property: constant({
2740
          children: children$2,
2741
          name: name,
2742
          parent: parent,
2743
          document,
2744
          isText: isText,
2745
          isComment: isComment,
2746
          isElement: isElement,
2747
          isSpecial,
2748
          getLanguage,
2749
          getText: get$6,
2750
          setText: set,
2751
          isBoundary,
2752
          isEmptyTag,
2753
          isNonEditable
2754
        }),
2755
        eq: eq$1,
2756
        is: is$1
2757
      };
2758
    };
2759
 
2760
    const all = (universe, look, elements, f) => {
2761
      const head = elements[0];
2762
      const tail = elements.slice(1);
2763
      return f(universe, look, head, tail);
2764
    };
2765
    const oneAll = (universe, look, elements) => {
2766
      return elements.length > 0 ? all(universe, look, elements, unsafeOne) : Optional.none();
2767
    };
2768
    const unsafeOne = (universe, look, head, tail) => {
2769
      const start = look(universe, head);
2770
      return foldr(tail, (b, a) => {
2771
        const current = look(universe, a);
2772
        return commonElement(universe, b, current);
2773
      }, start);
2774
    };
2775
    const commonElement = (universe, start, end) => {
2776
      return start.bind(s => {
2777
        return end.filter(curry(universe.eq, s));
2778
      });
2779
    };
2780
 
2781
    const eq = (universe, item) => {
2782
      return curry(universe.eq, item);
2783
    };
2784
    const ancestors$2 = (universe, start, end, isRoot = never) => {
2785
      const ps1 = [start].concat(universe.up().all(start));
2786
      const ps2 = [end].concat(universe.up().all(end));
2787
      const prune = path => {
2788
        const index = findIndex(path, isRoot);
2789
        return index.fold(() => {
2790
          return path;
2791
        }, ind => {
2792
          return path.slice(0, ind + 1);
2793
        });
2794
      };
2795
      const pruned1 = prune(ps1);
2796
      const pruned2 = prune(ps2);
2797
      const shared = find$1(pruned1, x => {
2798
        return exists(pruned2, eq(universe, x));
2799
      });
2800
      return {
2801
        firstpath: pruned1,
2802
        secondpath: pruned2,
2803
        shared
2804
      };
2805
    };
2806
 
2807
    const sharedOne$1 = oneAll;
2808
    const ancestors$1 = ancestors$2;
2809
 
2810
    const universe$3 = DomUniverse();
2811
    const sharedOne = (look, elements) => {
2812
      return sharedOne$1(universe$3, (_universe, element) => {
2813
        return look(element);
2814
      }, elements);
2815
    };
2816
    const ancestors = (start, finish, isRoot) => {
2817
      return ancestors$1(universe$3, start, finish, isRoot);
2818
    };
2819
 
2820
    const lookupTable = container => {
2821
      return ancestor$1(container, 'table');
2822
    };
2823
    const identify = (start, finish, isRoot) => {
2824
      const getIsRoot = rootTable => {
2825
        return element => {
2826
          return isRoot !== undefined && isRoot(element) || eq$1(element, rootTable);
2827
        };
2828
      };
2829
      if (eq$1(start, finish)) {
2830
        return Optional.some({
2831
          boxes: Optional.some([start]),
2832
          start,
2833
          finish
2834
        });
2835
      } else {
2836
        return lookupTable(start).bind(startTable => {
2837
          return lookupTable(finish).bind(finishTable => {
2838
            if (eq$1(startTable, finishTable)) {
2839
              return Optional.some({
2840
                boxes: intercepts(startTable, start, finish),
2841
                start,
2842
                finish
2843
              });
2844
            } else if (contains$1(startTable, finishTable)) {
2845
              const ancestorCells = ancestors$3(finish, 'td,th', getIsRoot(startTable));
2846
              const finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish;
2847
              return Optional.some({
2848
                boxes: nestedIntercepts(startTable, start, startTable, finish, finishTable),
2849
                start,
2850
                finish: finishCell
2851
              });
2852
            } else if (contains$1(finishTable, startTable)) {
2853
              const ancestorCells = ancestors$3(start, 'td,th', getIsRoot(finishTable));
2854
              const startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start;
2855
              return Optional.some({
2856
                boxes: nestedIntercepts(finishTable, start, startTable, finish, finishTable),
2857
                start,
2858
                finish: startCell
2859
              });
2860
            } else {
2861
              return ancestors(start, finish).shared.bind(lca => {
2862
                return closest$1(lca, 'table', isRoot).bind(lcaTable => {
2863
                  const finishAncestorCells = ancestors$3(finish, 'td,th', getIsRoot(lcaTable));
2864
                  const finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish;
2865
                  const startAncestorCells = ancestors$3(start, 'td,th', getIsRoot(lcaTable));
2866
                  const startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start;
2867
                  return Optional.some({
2868
                    boxes: nestedIntercepts(lcaTable, start, startTable, finish, finishTable),
2869
                    start: startCell,
2870
                    finish: finishCell
2871
                  });
2872
                });
2873
              });
2874
            }
2875
          });
2876
        });
2877
      }
2878
    };
2879
    const retrieve$1 = (container, selector) => {
2880
      const sels = descendants(container, selector);
2881
      return sels.length > 0 ? Optional.some(sels) : Optional.none();
2882
    };
2883
    const getLast = (boxes, lastSelectedSelector) => {
2884
      return find$1(boxes, box => {
2885
        return is$2(box, lastSelectedSelector);
2886
      });
2887
    };
2888
    const getEdges = (container, firstSelectedSelector, lastSelectedSelector) => {
2889
      return descendant(container, firstSelectedSelector).bind(first => {
2890
        return descendant(container, lastSelectedSelector).bind(last => {
2891
          return sharedOne(lookupTable, [
2892
            first,
2893
            last
2894
          ]).map(table => {
2895
            return {
2896
              first,
2897
              last,
2898
              table
2899
            };
2900
          });
2901
        });
2902
      });
2903
    };
2904
    const expandTo = (finish, firstSelectedSelector) => {
2905
      return ancestor$1(finish, 'table').bind(table => {
2906
        return descendant(table, firstSelectedSelector).bind(start => {
2907
          return identify(start, finish).bind(identified => {
2908
            return identified.boxes.map(boxes => {
2909
              return {
2910
                boxes,
2911
                start: identified.start,
2912
                finish: identified.finish
2913
              };
2914
            });
2915
          });
2916
        });
2917
      });
2918
    };
2919
    const shiftSelection = (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) => {
2920
      return getLast(boxes, lastSelectedSelector).bind(last => {
2921
        return moveBy(last, deltaRow, deltaColumn).bind(finish => {
2922
          return expandTo(finish, firstSelectedSelector);
2923
        });
2924
      });
2925
    };
2926
 
2927
    const retrieve = (container, selector) => {
2928
      return retrieve$1(container, selector);
2929
    };
2930
    const retrieveBox = (container, firstSelectedSelector, lastSelectedSelector) => {
2931
      return getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(edges => {
2932
        const isRoot = ancestor => {
2933
          return eq$1(container, ancestor);
2934
        };
2935
        const sectionSelector = 'thead,tfoot,tbody,table';
2936
        const firstAncestor = ancestor$1(edges.first, sectionSelector, isRoot);
2937
        const lastAncestor = ancestor$1(edges.last, sectionSelector, isRoot);
2938
        return firstAncestor.bind(fA => {
2939
          return lastAncestor.bind(lA => {
2940
            return eq$1(fA, lA) ? getBox(edges.table, edges.first, edges.last) : Optional.none();
2941
          });
2942
        });
2943
      });
2944
    };
2945
 
2946
    const selection = identity;
2947
    const unmergable = selectedCells => {
2948
      const hasSpan = (elem, type) => getOpt(elem, type).exists(span => parseInt(span, 10) > 1);
2949
      const hasRowOrColSpan = elem => hasSpan(elem, 'rowspan') || hasSpan(elem, 'colspan');
2950
      return selectedCells.length > 0 && forall(selectedCells, hasRowOrColSpan) ? Optional.some(selectedCells) : Optional.none();
2951
    };
2952
    const mergable = (table, selectedCells, ephemera) => {
2953
      if (selectedCells.length <= 1) {
2954
        return Optional.none();
2955
      } else {
2956
        return retrieveBox(table, ephemera.firstSelectedSelector, ephemera.lastSelectedSelector).map(bounds => ({
2957
          bounds,
2958
          cells: selectedCells
2959
        }));
2960
      }
2961
    };
2962
 
2963
    const strSelected = 'data-mce-selected';
2964
    const strSelectedSelector = 'td[' + strSelected + '],th[' + strSelected + ']';
2965
    const strAttributeSelector = '[' + strSelected + ']';
2966
    const strFirstSelected = 'data-mce-first-selected';
2967
    const strFirstSelectedSelector = 'td[' + strFirstSelected + '],th[' + strFirstSelected + ']';
2968
    const strLastSelected = 'data-mce-last-selected';
2969
    const strLastSelectedSelector = 'td[' + strLastSelected + '],th[' + strLastSelected + ']';
2970
    const attributeSelector = strAttributeSelector;
2971
    const ephemera = {
2972
      selected: strSelected,
2973
      selectedSelector: strSelectedSelector,
2974
      firstSelected: strFirstSelected,
2975
      firstSelectedSelector: strFirstSelectedSelector,
2976
      lastSelected: strLastSelected,
2977
      lastSelectedSelector: strLastSelectedSelector
2978
    };
2979
 
2980
    const forMenu = (selectedCells, table, cell) => ({
2981
      element: cell,
2982
      mergable: mergable(table, selectedCells, ephemera),
2983
      unmergable: unmergable(selectedCells),
2984
      selection: selection(selectedCells)
2985
    });
2986
    const paste = (element, clipboard, generators) => ({
2987
      element,
2988
      clipboard,
2989
      generators
2990
    });
2991
    const pasteRows = (selectedCells, _cell, clipboard, generators) => ({
2992
      selection: selection(selectedCells),
2993
      clipboard,
2994
      generators
2995
    });
2996
 
2997
    const getSelectionCellFallback = element => table(element).bind(table => retrieve(table, ephemera.firstSelectedSelector)).fold(constant(element), cells => cells[0]);
2998
    const getSelectionFromSelector = selector => (initCell, isRoot) => {
2999
      const cellName = name(initCell);
3000
      const cell = cellName === 'col' || cellName === 'colgroup' ? getSelectionCellFallback(initCell) : initCell;
3001
      return closest$1(cell, selector, isRoot);
3002
    };
3003
    const getSelectionCellOrCaption = getSelectionFromSelector('th,td,caption');
3004
    const getSelectionCell = getSelectionFromSelector('th,td');
3005
    const getCellsFromSelection = editor => fromDom(editor.model.table.getSelectedCells());
3006
    const getCellsFromFakeSelection = editor => filter$2(getCellsFromSelection(editor), cell => is$2(cell, ephemera.selectedSelector));
3007
 
3008
    const extractSelected = cells => {
3009
      return table(cells[0]).map(table => {
3010
        const replica = extract$1(table, attributeSelector);
3011
        removeDataStyle(replica);
3012
        return [replica];
3013
      });
3014
    };
3015
    const serializeElements = (editor, elements) => map$1(elements, elm => editor.selection.serializer.serialize(elm.dom, {})).join('');
3016
    const getTextContent = elements => map$1(elements, element => element.dom.innerText).join('');
3017
    const registerEvents = (editor, actions) => {
3018
      editor.on('BeforeGetContent', e => {
3019
        const multiCellContext = cells => {
3020
          e.preventDefault();
3021
          extractSelected(cells).each(elements => {
3022
            e.content = e.format === 'text' ? getTextContent(elements) : serializeElements(editor, elements);
3023
          });
3024
        };
3025
        if (e.selection === true) {
3026
          const cells = getCellsFromFakeSelection(editor);
3027
          if (cells.length >= 1) {
3028
            multiCellContext(cells);
3029
          }
3030
        }
3031
      });
3032
      editor.on('BeforeSetContent', e => {
3033
        if (e.selection === true && e.paste === true) {
3034
          const selectedCells = getCellsFromSelection(editor);
3035
          head(selectedCells).each(cell => {
3036
            table(cell).each(table => {
3037
              const elements = filter$2(fromHtml(e.content), content => {
3038
                return name(content) !== 'meta';
3039
              });
3040
              const isTable = isTag('table');
3041
              if (shouldMergeContentOnPaste(editor) && elements.length === 1 && isTable(elements[0])) {
3042
                e.preventDefault();
3043
                const doc = SugarElement.fromDom(editor.getDoc());
3044
                const generators = paste$1(doc);
3045
                const targets = paste(cell, elements[0], generators);
3046
                actions.pasteCells(table, targets).each(() => {
3047
                  editor.focus();
3048
                });
3049
              }
3050
            });
3051
          });
3052
        }
3053
      });
3054
    };
3055
 
3056
    const point = (element, offset) => ({
3057
      element,
3058
      offset
3059
    });
3060
 
3061
    const scan$1 = (universe, element, direction) => {
3062
      if (universe.property().isText(element) && universe.property().getText(element).trim().length === 0 || universe.property().isComment(element)) {
3063
        return direction(element).bind(elem => {
3064
          return scan$1(universe, elem, direction).orThunk(() => {
3065
            return Optional.some(elem);
3066
          });
3067
        });
3068
      } else {
3069
        return Optional.none();
3070
      }
3071
    };
3072
    const toEnd = (universe, element) => {
3073
      if (universe.property().isText(element)) {
3074
        return universe.property().getText(element).length;
3075
      }
3076
      const children = universe.property().children(element);
3077
      return children.length;
3078
    };
3079
    const freefallRtl$2 = (universe, element) => {
3080
      const candidate = scan$1(universe, element, universe.query().prevSibling).getOr(element);
3081
      if (universe.property().isText(candidate)) {
3082
        return point(candidate, toEnd(universe, candidate));
3083
      }
3084
      const children = universe.property().children(candidate);
3085
      return children.length > 0 ? freefallRtl$2(universe, children[children.length - 1]) : point(candidate, toEnd(universe, candidate));
3086
    };
3087
 
3088
    const freefallRtl$1 = freefallRtl$2;
3089
 
3090
    const universe$2 = DomUniverse();
3091
    const freefallRtl = element => {
3092
      return freefallRtl$1(universe$2, element);
3093
    };
3094
 
3095
    const halve = (main, other) => {
3096
      if (!hasColspan(main)) {
3097
        const width = getGenericWidth(main);
3098
        width.each(w => {
3099
          const newWidth = w.value / 2;
3100
          setGenericWidth(main, newWidth, w.unit);
3101
          setGenericWidth(other, newWidth, w.unit);
3102
        });
3103
      }
3104
    };
3105
 
3106
    const zero = array => map$1(array, constant(0));
3107
    const surround = (sizes, startIndex, endIndex, results, f) => f(sizes.slice(0, startIndex)).concat(results).concat(f(sizes.slice(endIndex)));
3108
    const clampDeltaHelper = predicate => (sizes, index, delta, minCellSize) => {
3109
      if (!predicate(delta)) {
3110
        return delta;
3111
      } else {
3112
        const newSize = Math.max(minCellSize, sizes[index] - Math.abs(delta));
3113
        const diff = Math.abs(newSize - sizes[index]);
3114
        return delta >= 0 ? diff : -diff;
3115
      }
3116
    };
3117
    const clampNegativeDelta = clampDeltaHelper(delta => delta < 0);
3118
    const clampDelta = clampDeltaHelper(always);
3119
    const resizeTable = () => {
3120
      const calcFixedDeltas = (sizes, index, next, delta, minCellSize) => {
3121
        const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
3122
        return surround(sizes, index, next + 1, [
3123
          clampedDelta,
3124
 
3125
        ], zero);
3126
      };
3127
      const calcRelativeDeltas = (sizes, index, delta, minCellSize) => {
3128
        const ratio = (100 + delta) / 100;
3129
        const newThis = Math.max(minCellSize, (sizes[index] + delta) / ratio);
3130
        return map$1(sizes, (size, idx) => {
3131
          const newSize = idx === index ? newThis : size / ratio;
3132
          return newSize - size;
3133
        });
3134
      };
3135
      const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize, isRelative) => {
3136
        if (isRelative) {
3137
          return calcRelativeDeltas(sizes, index, delta, minCellSize);
3138
        } else {
3139
          return calcFixedDeltas(sizes, index, next, delta, minCellSize);
3140
        }
3141
      };
3142
      const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize, isRelative) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize, isRelative);
3143
      const resizeTable = (resizer, delta) => resizer(delta);
3144
      const calcRightEdgeDeltas = (sizes, _prev, index, delta, minCellSize, isRelative) => {
3145
        if (isRelative) {
3146
          return calcRelativeDeltas(sizes, index, delta, minCellSize);
3147
        } else {
3148
          const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
3149
          return zero(sizes.slice(0, index)).concat([clampedDelta]);
3150
        }
3151
      };
3152
      const calcRedestributedWidths = (sizes, totalWidth, pixelDelta, isRelative) => {
3153
        if (isRelative) {
3154
          const tableWidth = totalWidth + pixelDelta;
3155
          const ratio = tableWidth / totalWidth;
3156
          const newSizes = map$1(sizes, size => size / ratio);
3157
          return {
3158
            delta: ratio * 100 - 100,
3159
            newSizes
3160
          };
3161
        } else {
3162
          return {
3163
            delta: pixelDelta,
3164
            newSizes: sizes
3165
          };
3166
        }
3167
      };
3168
      return {
3169
        resizeTable,
3170
        clampTableDelta: clampNegativeDelta,
3171
        calcLeftEdgeDeltas,
3172
        calcMiddleDeltas,
3173
        calcRightEdgeDeltas,
3174
        calcRedestributedWidths
3175
      };
3176
    };
3177
    const preserveTable = () => {
3178
      const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize) => {
3179
        const idx = delta >= 0 ? next : index;
3180
        const clampedDelta = clampDelta(sizes, idx, delta, minCellSize);
3181
        return surround(sizes, index, next + 1, [
3182
          clampedDelta,
3183
          -clampedDelta
3184
        ], zero);
3185
      };
3186
      const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize);
3187
      const resizeTable = (resizer, delta, isLastColumn) => {
3188
        if (isLastColumn) {
3189
          resizer(delta);
3190
        }
3191
      };
3192
      const calcRightEdgeDeltas = (sizes, _prev, _index, delta, _minCellSize, isRelative) => {
3193
        if (isRelative) {
3194
          return zero(sizes);
3195
        } else {
3196
          const diff = delta / sizes.length;
3197
          return map$1(sizes, constant(diff));
3198
        }
3199
      };
3200
      const clampTableDelta = (sizes, index, delta, minCellSize, isLastColumn) => {
3201
        if (isLastColumn) {
3202
          if (delta >= 0) {
3203
            return delta;
3204
          } else {
3205
            const maxDelta = foldl(sizes, (a, b) => a + b - minCellSize, 0);
3206
            return Math.max(-maxDelta, delta);
3207
          }
3208
        } else {
3209
          return clampNegativeDelta(sizes, index, delta, minCellSize);
3210
        }
3211
      };
3212
      const calcRedestributedWidths = (sizes, _totalWidth, _pixelDelta, _isRelative) => ({
3213
        delta: 0,
3214
        newSizes: sizes
3215
      });
3216
      return {
3217
        resizeTable,
3218
        clampTableDelta,
3219
        calcLeftEdgeDeltas,
3220
        calcMiddleDeltas,
3221
        calcRightEdgeDeltas,
3222
        calcRedestributedWidths
3223
      };
3224
    };
3225
 
3226
    const getGridSize = table => {
3227
      const warehouse = Warehouse.fromTable(table);
3228
      return warehouse.grid;
3229
    };
3230
 
3231
    const isHeaderCell = isTag('th');
3232
    const isHeaderCells = cells => forall(cells, cell => isHeaderCell(cell.element));
3233
    const getRowHeaderType = (isHeaderRow, isHeaderCells) => {
3234
      if (isHeaderRow && isHeaderCells) {
3235
        return 'sectionCells';
3236
      } else if (isHeaderRow) {
3237
        return 'section';
3238
      } else {
3239
        return 'cells';
3240
      }
3241
    };
3242
    const getRowType = row => {
3243
      const isHeaderRow = row.section === 'thead';
3244
      const isHeaderCells = is(findCommonCellType(row.cells), 'th');
3245
      if (row.section === 'tfoot') {
3246
        return { type: 'footer' };
3247
      } else if (isHeaderRow || isHeaderCells) {
3248
        return {
3249
          type: 'header',
3250
          subType: getRowHeaderType(isHeaderRow, isHeaderCells)
3251
        };
3252
      } else {
3253
        return { type: 'body' };
3254
      }
3255
    };
3256
    const findCommonCellType = cells => {
3257
      const headerCells = filter$2(cells, cell => isHeaderCell(cell.element));
3258
      if (headerCells.length === 0) {
3259
        return Optional.some('td');
3260
      } else if (headerCells.length === cells.length) {
3261
        return Optional.some('th');
3262
      } else {
3263
        return Optional.none();
3264
      }
3265
    };
3266
    const findCommonRowType = rows => {
3267
      const rowTypes = map$1(rows, row => getRowType(row).type);
3268
      const hasHeader = contains$2(rowTypes, 'header');
3269
      const hasFooter = contains$2(rowTypes, 'footer');
3270
      if (!hasHeader && !hasFooter) {
3271
        return Optional.some('body');
3272
      } else {
3273
        const hasBody = contains$2(rowTypes, 'body');
3274
        if (hasHeader && !hasBody && !hasFooter) {
3275
          return Optional.some('header');
3276
        } else if (!hasHeader && !hasBody && hasFooter) {
3277
          return Optional.some('footer');
3278
        } else {
3279
          return Optional.none();
3280
        }
3281
      }
3282
    };
3283
    const findTableRowHeaderType = warehouse => findMap(warehouse.all, row => {
3284
      const rowType = getRowType(row);
3285
      return rowType.type === 'header' ? Optional.from(rowType.subType) : Optional.none();
3286
    });
3287
 
3288
    const transformCell = (cell, comparator, substitution) => elementnew(substitution(cell.element, comparator), true, cell.isLocked);
3289
    const transformRow = (row, section) => row.section !== section ? rowcells(row.element, row.cells, section, row.isNew) : row;
3290
    const section = () => ({
3291
      transformRow,
3292
      transformCell: (cell, comparator, substitution) => {
3293
        const newCell = substitution(cell.element, comparator);
3294
        const fixedCell = name(newCell) !== 'td' ? mutate$1(newCell, 'td') : newCell;
3295
        return elementnew(fixedCell, cell.isNew, cell.isLocked);
3296
      }
3297
    });
3298
    const sectionCells = () => ({
3299
      transformRow,
3300
      transformCell
3301
    });
3302
    const cells = () => ({
3303
      transformRow: (row, section) => {
3304
        const newSection = section === 'thead' ? 'tbody' : section;
3305
        return transformRow(row, newSection);
3306
      },
3307
      transformCell
3308
    });
3309
    const fallback = () => ({
3310
      transformRow: identity,
3311
      transformCell
3312
    });
3313
    const getTableSectionType = (table, fallback) => {
3314
      const warehouse = Warehouse.fromTable(table);
3315
      const type = findTableRowHeaderType(warehouse).getOr(fallback);
3316
      switch (type) {
3317
      case 'section':
3318
        return section();
3319
      case 'sectionCells':
3320
        return sectionCells();
3321
      case 'cells':
3322
        return cells();
3323
      }
3324
    };
3325
    const TableSection = {
3326
      getTableSectionType,
3327
      section,
3328
      sectionCells,
3329
      cells,
3330
      fallback
3331
    };
3332
 
3333
    const setIfNot = (element, property, value, ignore) => {
3334
      if (value === ignore) {
3335
        remove$7(element, property);
3336
      } else {
3337
        set$2(element, property, value);
3338
      }
3339
    };
3340
    const insert$1 = (table, selector, element) => {
3341
      last$2(children(table, selector)).fold(() => prepend(table, element), child => after$5(child, element));
3342
    };
3343
    const generateSection = (table, sectionName) => {
3344
      const section = child(table, sectionName).getOrThunk(() => {
3345
        const newSection = SugarElement.fromTag(sectionName, owner(table).dom);
3346
        if (sectionName === 'thead') {
3347
          insert$1(table, 'caption,colgroup', newSection);
3348
        } else if (sectionName === 'colgroup') {
3349
          insert$1(table, 'caption', newSection);
3350
        } else {
3351
          append$1(table, newSection);
3352
        }
3353
        return newSection;
3354
      });
3355
      empty(section);
3356
      return section;
3357
    };
3358
    const render$1 = (table, grid) => {
3359
      const newRows = [];
3360
      const newCells = [];
3361
      const syncRows = gridSection => map$1(gridSection, row => {
3362
        if (row.isNew) {
3363
          newRows.push(row.element);
3364
        }
3365
        const tr = row.element;
3366
        empty(tr);
3367
        each$2(row.cells, cell => {
3368
          if (cell.isNew) {
3369
            newCells.push(cell.element);
3370
          }
3371
          setIfNot(cell.element, 'colspan', cell.colspan, 1);
3372
          setIfNot(cell.element, 'rowspan', cell.rowspan, 1);
3373
          append$1(tr, cell.element);
3374
        });
3375
        return tr;
3376
      });
3377
      const syncColGroup = gridSection => bind$2(gridSection, colGroup => map$1(colGroup.cells, col => {
3378
        setIfNot(col.element, 'span', col.colspan, 1);
3379
        return col.element;
3380
      }));
3381
      const renderSection = (gridSection, sectionName) => {
3382
        const section = generateSection(table, sectionName);
3383
        const sync = sectionName === 'colgroup' ? syncColGroup : syncRows;
3384
        const sectionElems = sync(gridSection);
3385
        append(section, sectionElems);
3386
      };
3387
      const removeSection = sectionName => {
3388
        child(table, sectionName).each(remove$6);
3389
      };
3390
      const renderOrRemoveSection = (gridSection, sectionName) => {
3391
        if (gridSection.length > 0) {
3392
          renderSection(gridSection, sectionName);
3393
        } else {
3394
          removeSection(sectionName);
3395
        }
3396
      };
3397
      const headSection = [];
3398
      const bodySection = [];
3399
      const footSection = [];
3400
      const columnGroupsSection = [];
3401
      each$2(grid, row => {
3402
        switch (row.section) {
3403
        case 'thead':
3404
          headSection.push(row);
3405
          break;
3406
        case 'tbody':
3407
          bodySection.push(row);
3408
          break;
3409
        case 'tfoot':
3410
          footSection.push(row);
3411
          break;
3412
        case 'colgroup':
3413
          columnGroupsSection.push(row);
3414
          break;
3415
        }
3416
      });
3417
      renderOrRemoveSection(columnGroupsSection, 'colgroup');
3418
      renderOrRemoveSection(headSection, 'thead');
3419
      renderOrRemoveSection(bodySection, 'tbody');
3420
      renderOrRemoveSection(footSection, 'tfoot');
3421
      return {
3422
        newRows,
3423
        newCells
3424
      };
3425
    };
3426
    const copy = grid => map$1(grid, row => {
3427
      const tr = shallow(row.element);
3428
      each$2(row.cells, cell => {
3429
        const clonedCell = deep(cell.element);
3430
        setIfNot(clonedCell, 'colspan', cell.colspan, 1);
3431
        setIfNot(clonedCell, 'rowspan', cell.rowspan, 1);
3432
        append$1(tr, clonedCell);
3433
      });
3434
      return tr;
3435
    });
3436
 
3437
    const getColumn = (grid, index) => {
3438
      return map$1(grid, row => {
3439
        return getCell(row, index);
3440
      });
3441
    };
3442
    const getRow = (grid, index) => {
3443
      return grid[index];
3444
    };
3445
    const findDiff = (xs, comp) => {
3446
      if (xs.length === 0) {
3447
        return 0;
3448
      }
3449
      const first = xs[0];
3450
      const index = findIndex(xs, x => {
3451
        return !comp(first.element, x.element);
3452
      });
3453
      return index.getOr(xs.length);
3454
    };
3455
    const subgrid = (grid, row, column, comparator) => {
3456
      const gridRow = getRow(grid, row);
3457
      const isColRow = gridRow.section === 'colgroup';
3458
      const colspan = findDiff(gridRow.cells.slice(column), comparator);
3459
      const rowspan = isColRow ? 1 : findDiff(getColumn(grid.slice(row), column), comparator);
3460
      return {
3461
        colspan,
3462
        rowspan
3463
      };
3464
    };
3465
 
3466
    const toDetails = (grid, comparator) => {
3467
      const seen = map$1(grid, row => map$1(row.cells, never));
3468
      const updateSeen = (rowIndex, columnIndex, rowspan, colspan) => {
3469
        for (let row = rowIndex; row < rowIndex + rowspan; row++) {
3470
          for (let column = columnIndex; column < columnIndex + colspan; column++) {
3471
            seen[row][column] = true;
3472
          }
3473
        }
3474
      };
3475
      return map$1(grid, (row, rowIndex) => {
3476
        const details = bind$2(row.cells, (cell, columnIndex) => {
3477
          if (seen[rowIndex][columnIndex] === false) {
3478
            const result = subgrid(grid, rowIndex, columnIndex, comparator);
3479
            updateSeen(rowIndex, columnIndex, result.rowspan, result.colspan);
3480
            return [detailnew(cell.element, result.rowspan, result.colspan, cell.isNew)];
3481
          } else {
3482
            return [];
3483
          }
3484
        });
3485
        return rowdetailnew(row.element, details, row.section, row.isNew);
3486
      });
3487
    };
3488
    const toGrid = (warehouse, generators, isNew) => {
3489
      const grid = [];
3490
      each$2(warehouse.colgroups, colgroup => {
3491
        const colgroupCols = [];
3492
        for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
3493
          const element = Warehouse.getColumnAt(warehouse, columnIndex).map(column => elementnew(column.element, isNew, false)).getOrThunk(() => elementnew(generators.colGap(), true, false));
3494
          colgroupCols.push(element);
3495
        }
3496
        grid.push(rowcells(colgroup.element, colgroupCols, 'colgroup', isNew));
3497
      });
3498
      for (let rowIndex = 0; rowIndex < warehouse.grid.rows; rowIndex++) {
3499
        const rowCells = [];
3500
        for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
3501
          const element = Warehouse.getAt(warehouse, rowIndex, columnIndex).map(item => elementnew(item.element, isNew, item.isLocked)).getOrThunk(() => elementnew(generators.gap(), true, false));
3502
          rowCells.push(element);
3503
        }
3504
        const rowDetail = warehouse.all[rowIndex];
3505
        const row = rowcells(rowDetail.element, rowCells, rowDetail.section, isNew);
3506
        grid.push(row);
3507
      }
3508
      return grid;
3509
    };
3510
 
3511
    const fromWarehouse = (warehouse, generators) => toGrid(warehouse, generators, false);
3512
    const toDetailList = grid => toDetails(grid, eq$1);
3513
    const findInWarehouse = (warehouse, element) => findMap(warehouse.all, r => find$1(r.cells, e => eq$1(element, e.element)));
3514
    const extractCells = (warehouse, target, predicate) => {
3515
      const details = map$1(target.selection, cell$1 => {
3516
        return cell(cell$1).bind(lc => findInWarehouse(warehouse, lc)).filter(predicate);
3517
      });
3518
      const cells = cat(details);
3519
      return someIf(cells.length > 0, cells);
3520
    };
3521
    const run = (operation, extract, adjustment, postAction, genWrappers) => (table, target, generators, behaviours) => {
3522
      const warehouse = Warehouse.fromTable(table);
3523
      const tableSection = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.section).getOrThunk(TableSection.fallback);
3524
      const output = extract(warehouse, target).map(info => {
3525
        const model = fromWarehouse(warehouse, generators);
3526
        const result = operation(model, info, eq$1, genWrappers(generators), tableSection);
3527
        const lockedColumns = getLockedColumnsFromGrid(result.grid);
3528
        const grid = toDetailList(result.grid);
3529
        return {
3530
          info,
3531
          grid,
3532
          cursor: result.cursor,
3533
          lockedColumns
3534
        };
3535
      });
3536
      return output.bind(out => {
3537
        const newElements = render$1(table, out.grid);
3538
        const tableSizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.sizing).getOrThunk(() => TableSize.getTableSize(table));
3539
        const resizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.resize).getOrThunk(preserveTable);
3540
        adjustment(table, out.grid, out.info, {
3541
          sizing: tableSizing,
3542
          resize: resizing,
3543
          section: tableSection
3544
        });
3545
        postAction(table);
3546
        remove$7(table, LOCKED_COL_ATTR);
3547
        if (out.lockedColumns.length > 0) {
3548
          set$2(table, LOCKED_COL_ATTR, out.lockedColumns.join(','));
3549
        }
3550
        return Optional.some({
3551
          cursor: out.cursor,
3552
          newRows: newElements.newRows,
3553
          newCells: newElements.newCells
3554
        });
3555
      });
3556
    };
3557
    const onPaste = (warehouse, target) => cell(target.element).bind(cell => findInWarehouse(warehouse, cell).map(details => {
3558
      const value = {
3559
        ...details,
3560
        generators: target.generators,
3561
        clipboard: target.clipboard
3562
      };
3563
      return value;
3564
    }));
3565
    const onPasteByEditor = (warehouse, target) => extractCells(warehouse, target, always).map(cells => ({
3566
      cells,
3567
      generators: target.generators,
3568
      clipboard: target.clipboard
3569
    }));
3570
    const onMergable = (_warehouse, target) => target.mergable;
3571
    const onUnmergable = (_warehouse, target) => target.unmergable;
3572
    const onCells = (warehouse, target) => extractCells(warehouse, target, always);
3573
    const onUnlockedCells = (warehouse, target) => extractCells(warehouse, target, detail => !detail.isLocked);
3574
    const isUnlockedTableCell = (warehouse, cell) => findInWarehouse(warehouse, cell).exists(detail => !detail.isLocked);
3575
    const allUnlocked = (warehouse, cells) => forall(cells, cell => isUnlockedTableCell(warehouse, cell));
3576
    const onUnlockedMergable = (warehouse, target) => onMergable(warehouse, target).filter(mergeable => allUnlocked(warehouse, mergeable.cells));
3577
    const onUnlockedUnmergable = (warehouse, target) => onUnmergable(warehouse, target).filter(cells => allUnlocked(warehouse, cells));
3578
 
3579
    const merge$2 = (grid, bounds, comparator, substitution) => {
3580
      const rows = extractGridDetails(grid).rows;
3581
      if (rows.length === 0) {
3582
        return grid;
3583
      }
3584
      for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
3585
        for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
3586
          const row = rows[i];
3587
          const isLocked = getCell(row, j).isLocked;
3588
          mutateCell(row, j, elementnew(substitution(), false, isLocked));
3589
        }
3590
      }
3591
      return grid;
3592
    };
3593
    const unmerge = (grid, target, comparator, substitution) => {
3594
      const rows = extractGridDetails(grid).rows;
3595
      let first = true;
3596
      for (let i = 0; i < rows.length; i++) {
3597
        for (let j = 0; j < cellLength(rows[0]); j++) {
3598
          const row = rows[i];
3599
          const currentCell = getCell(row, j);
3600
          const currentCellElm = currentCell.element;
3601
          const isToReplace = comparator(currentCellElm, target);
3602
          if (isToReplace && !first) {
3603
            mutateCell(row, j, elementnew(substitution(), true, currentCell.isLocked));
3604
          } else if (isToReplace) {
3605
            first = false;
3606
          }
3607
        }
3608
      }
3609
      return grid;
3610
    };
3611
    const uniqueCells = (row, comparator) => {
3612
      return foldl(row, (rest, cell) => {
3613
        return exists(rest, currentCell => {
3614
          return comparator(currentCell.element, cell.element);
3615
        }) ? rest : rest.concat([cell]);
3616
      }, []);
3617
    };
3618
    const splitCols = (grid, index, comparator, substitution) => {
3619
      if (index > 0 && index < grid[0].cells.length) {
3620
        each$2(grid, row => {
3621
          const prevCell = row.cells[index - 1];
3622
          let offset = 0;
3623
          const substitute = substitution();
3624
          while (row.cells.length > index + offset && comparator(prevCell.element, row.cells[index + offset].element)) {
3625
            mutateCell(row, index + offset, elementnew(substitute, true, row.cells[index + offset].isLocked));
3626
            offset++;
3627
          }
3628
        });
3629
      }
3630
      return grid;
3631
    };
3632
    const splitRows = (grid, index, comparator, substitution) => {
3633
      const rows = extractGridDetails(grid).rows;
3634
      if (index > 0 && index < rows.length) {
3635
        const rowPrevCells = rows[index - 1].cells;
3636
        const cells = uniqueCells(rowPrevCells, comparator);
3637
        each$2(cells, cell => {
3638
          let replacement = Optional.none();
3639
          for (let i = index; i < rows.length; i++) {
3640
            for (let j = 0; j < cellLength(rows[0]); j++) {
3641
              const row = rows[i];
3642
              const current = getCell(row, j);
3643
              const isToReplace = comparator(current.element, cell.element);
3644
              if (isToReplace) {
3645
                if (replacement.isNone()) {
3646
                  replacement = Optional.some(substitution());
3647
                }
3648
                replacement.each(sub => {
3649
                  mutateCell(row, j, elementnew(sub, true, current.isLocked));
3650
                });
3651
              }
3652
            }
3653
          }
3654
        });
3655
      }
3656
      return grid;
3657
    };
3658
 
3659
    const value$1 = value => {
3660
      const applyHelper = fn => fn(value);
3661
      const constHelper = constant(value);
3662
      const outputHelper = () => output;
3663
      const output = {
3664
        tag: true,
3665
        inner: value,
3666
        fold: (_onError, onValue) => onValue(value),
3667
        isValue: always,
3668
        isError: never,
3669
        map: mapper => Result.value(mapper(value)),
3670
        mapError: outputHelper,
3671
        bind: applyHelper,
3672
        exists: applyHelper,
3673
        forall: applyHelper,
3674
        getOr: constHelper,
3675
        or: outputHelper,
3676
        getOrThunk: constHelper,
3677
        orThunk: outputHelper,
3678
        getOrDie: constHelper,
3679
        each: fn => {
3680
          fn(value);
3681
        },
3682
        toOptional: () => Optional.some(value)
3683
      };
3684
      return output;
3685
    };
3686
    const error = error => {
3687
      const outputHelper = () => output;
3688
      const output = {
3689
        tag: false,
3690
        inner: error,
3691
        fold: (onError, _onValue) => onError(error),
3692
        isValue: never,
3693
        isError: always,
3694
        map: outputHelper,
3695
        mapError: mapper => Result.error(mapper(error)),
3696
        bind: outputHelper,
3697
        exists: never,
3698
        forall: always,
3699
        getOr: identity,
3700
        or: identity,
3701
        getOrThunk: apply,
3702
        orThunk: apply,
3703
        getOrDie: die(String(error)),
3704
        each: noop,
3705
        toOptional: Optional.none
3706
      };
3707
      return output;
3708
    };
3709
    const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
3710
    const Result = {
3711
      value: value$1,
3712
      error,
3713
      fromOption
3714
    };
3715
 
3716
    const measure = (startAddress, gridA, gridB) => {
3717
      if (startAddress.row >= gridA.length || startAddress.column > cellLength(gridA[0])) {
3718
        return Result.error('invalid start address out of table bounds, row: ' + startAddress.row + ', column: ' + startAddress.column);
3719
      }
3720
      const rowRemainder = gridA.slice(startAddress.row);
3721
      const colRemainder = rowRemainder[0].cells.slice(startAddress.column);
3722
      const colRequired = cellLength(gridB[0]);
3723
      const rowRequired = gridB.length;
3724
      return Result.value({
3725
        rowDelta: rowRemainder.length - rowRequired,
3726
        colDelta: colRemainder.length - colRequired
3727
      });
3728
    };
3729
    const measureWidth = (gridA, gridB) => {
3730
      const colLengthA = cellLength(gridA[0]);
3731
      const colLengthB = cellLength(gridB[0]);
3732
      return {
3733
        rowDelta: 0,
3734
        colDelta: colLengthA - colLengthB
3735
      };
3736
    };
3737
    const measureHeight = (gridA, gridB) => {
3738
      const rowLengthA = gridA.length;
3739
      const rowLengthB = gridB.length;
3740
      return {
3741
        rowDelta: rowLengthA - rowLengthB,
3742
        colDelta: 0
3743
      };
3744
    };
3745
    const generateElements = (amount, row, generators, isLocked) => {
3746
      const generator = row.section === 'colgroup' ? generators.col : generators.cell;
3747
      return range$1(amount, idx => elementnew(generator(), true, isLocked(idx)));
3748
    };
3749
    const rowFill = (grid, amount, generators, lockedColumns) => {
3750
      const exampleRow = grid[grid.length - 1];
3751
      return grid.concat(range$1(amount, () => {
3752
        const generator = exampleRow.section === 'colgroup' ? generators.colgroup : generators.row;
3753
        const row = clone(exampleRow, generator, identity);
3754
        const elements = generateElements(row.cells.length, row, generators, idx => has$1(lockedColumns, idx.toString()));
3755
        return setCells(row, elements);
3756
      }));
3757
    };
3758
    const colFill = (grid, amount, generators, startIndex) => map$1(grid, row => {
3759
      const newChildren = generateElements(amount, row, generators, never);
3760
      return addCells(row, startIndex, newChildren);
3761
    });
3762
    const lockedColFill = (grid, generators, lockedColumns) => map$1(grid, row => {
3763
      return foldl(lockedColumns, (acc, colNum) => {
3764
        const newChild = generateElements(1, row, generators, always)[0];
3765
        return addCell(acc, colNum, newChild);
3766
      }, row);
3767
    });
3768
    const tailor = (gridA, delta, generators) => {
3769
      const fillCols = delta.colDelta < 0 ? colFill : identity;
3770
      const fillRows = delta.rowDelta < 0 ? rowFill : identity;
3771
      const lockedColumns = getLockedColumnsFromGrid(gridA);
3772
      const gridWidth = cellLength(gridA[0]);
3773
      const isLastColLocked = exists(lockedColumns, locked => locked === gridWidth - 1);
3774
      const modifiedCols = fillCols(gridA, Math.abs(delta.colDelta), generators, isLastColLocked ? gridWidth - 1 : gridWidth);
3775
      const newLockedColumns = getLockedColumnsFromGrid(modifiedCols);
3776
      return fillRows(modifiedCols, Math.abs(delta.rowDelta), generators, mapToObject(newLockedColumns, always));
3777
    };
3778
 
3779
    const isSpanning = (grid, row, col, comparator) => {
3780
      const candidate = getCell(grid[row], col);
3781
      const matching = curry(comparator, candidate.element);
3782
      const currentRow = grid[row];
3783
      return grid.length > 1 && cellLength(currentRow) > 1 && (col > 0 && matching(getCellElement(currentRow, col - 1)) || col < currentRow.cells.length - 1 && matching(getCellElement(currentRow, col + 1)) || row > 0 && matching(getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(getCellElement(grid[row + 1], col)));
3784
    };
3785
    const mergeTables = (startAddress, gridA, gridBRows, generator, comparator, lockedColumns) => {
3786
      const startRow = startAddress.row;
3787
      const startCol = startAddress.column;
3788
      const mergeHeight = gridBRows.length;
3789
      const mergeWidth = cellLength(gridBRows[0]);
3790
      const endRow = startRow + mergeHeight;
3791
      const endCol = startCol + mergeWidth + lockedColumns.length;
3792
      const lockedColumnObj = mapToObject(lockedColumns, always);
3793
      for (let r = startRow; r < endRow; r++) {
3794
        let skippedCol = 0;
3795
        for (let c = startCol; c < endCol; c++) {
3796
          if (lockedColumnObj[c]) {
3797
            skippedCol++;
3798
            continue;
3799
          }
3800
          if (isSpanning(gridA, r, c, comparator)) {
3801
            unmerge(gridA, getCellElement(gridA[r], c), comparator, generator.cell);
3802
          }
3803
          const gridBColIndex = c - startCol - skippedCol;
3804
          const newCell = getCell(gridBRows[r - startRow], gridBColIndex);
3805
          const newCellElm = newCell.element;
3806
          const replacement = generator.replace(newCellElm);
3807
          mutateCell(gridA[r], c, elementnew(replacement, true, newCell.isLocked));
3808
        }
3809
      }
3810
      return gridA;
3811
    };
3812
    const getValidStartAddress = (currentStartAddress, grid, lockedColumns) => {
3813
      const gridColLength = cellLength(grid[0]);
3814
      const adjustedRowAddress = extractGridDetails(grid).cols.length + currentStartAddress.row;
3815
      const possibleColAddresses = range$1(gridColLength - currentStartAddress.column, num => num + currentStartAddress.column);
3816
      const validColAddress = find$1(possibleColAddresses, num => forall(lockedColumns, col => col !== num)).getOr(gridColLength - 1);
3817
      return {
3818
        row: adjustedRowAddress,
3819
        column: validColAddress
3820
      };
3821
    };
3822
    const getLockedColumnsWithinBounds = (startAddress, rows, lockedColumns) => filter$2(lockedColumns, colNum => colNum >= startAddress.column && colNum <= cellLength(rows[0]) + startAddress.column);
3823
    const merge$1 = (startAddress, gridA, gridB, generator, comparator) => {
3824
      const lockedColumns = getLockedColumnsFromGrid(gridA);
3825
      const validStartAddress = getValidStartAddress(startAddress, gridA, lockedColumns);
3826
      const gridBRows = extractGridDetails(gridB).rows;
3827
      const lockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, lockedColumns);
3828
      const result = measure(validStartAddress, gridA, gridBRows);
3829
      return result.map(diff => {
3830
        const delta = {
3831
          ...diff,
3832
          colDelta: diff.colDelta - lockedColumnsWithinBounds.length
3833
        };
3834
        const fittedGrid = tailor(gridA, delta, generator);
3835
        const newLockedColumns = getLockedColumnsFromGrid(fittedGrid);
3836
        const newLockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, newLockedColumns);
3837
        return mergeTables(validStartAddress, fittedGrid, gridBRows, generator, comparator, newLockedColumnsWithinBounds);
3838
      });
3839
    };
3840
    const insertCols = (index, gridA, gridB, generator, comparator) => {
3841
      splitCols(gridA, index, comparator, generator.cell);
3842
      const delta = measureHeight(gridB, gridA);
3843
      const fittedNewGrid = tailor(gridB, delta, generator);
3844
      const secondDelta = measureHeight(gridA, fittedNewGrid);
3845
      const fittedOldGrid = tailor(gridA, secondDelta, generator);
3846
      return map$1(fittedOldGrid, (gridRow, i) => {
3847
        return addCells(gridRow, index, fittedNewGrid[i].cells);
3848
      });
3849
    };
3850
    const insertRows = (index, gridA, gridB, generator, comparator) => {
3851
      splitRows(gridA, index, comparator, generator.cell);
3852
      const locked = getLockedColumnsFromGrid(gridA);
3853
      const diff = measureWidth(gridA, gridB);
3854
      const delta = {
3855
        ...diff,
3856
        colDelta: diff.colDelta - locked.length
3857
      };
3858
      const fittedOldGrid = tailor(gridA, delta, generator);
3859
      const {
3860
        cols: oldCols,
3861
        rows: oldRows
3862
      } = extractGridDetails(fittedOldGrid);
3863
      const newLocked = getLockedColumnsFromGrid(fittedOldGrid);
3864
      const secondDiff = measureWidth(gridB, gridA);
3865
      const secondDelta = {
3866
        ...secondDiff,
3867
        colDelta: secondDiff.colDelta + newLocked.length
3868
      };
3869
      const fittedGridB = lockedColFill(gridB, generator, newLocked);
3870
      const fittedNewGrid = tailor(fittedGridB, secondDelta, generator);
3871
      return [
3872
        ...oldCols,
3873
        ...oldRows.slice(0, index),
3874
        ...fittedNewGrid,
3875
        ...oldRows.slice(index, oldRows.length)
3876
      ];
3877
    };
3878
 
3879
    const cloneRow = (row, cloneCell, comparator, substitution) => clone(row, elem => substitution(elem, comparator), cloneCell);
3880
    const insertRowAt = (grid, index, example, comparator, substitution) => {
3881
      const {rows, cols} = extractGridDetails(grid);
3882
      const before = rows.slice(0, index);
3883
      const after = rows.slice(index);
3884
      const newRow = cloneRow(rows[example], (ex, c) => {
3885
        const withinSpan = index > 0 && index < rows.length && comparator(getCellElement(rows[index - 1], c), getCellElement(rows[index], c));
3886
        const ret = withinSpan ? getCell(rows[index], c) : elementnew(substitution(ex.element, comparator), true, ex.isLocked);
3887
        return ret;
3888
      }, comparator, substitution);
3889
      return [
3890
        ...cols,
3891
        ...before,
3892
        newRow,
3893
        ...after
3894
      ];
3895
    };
3896
    const getElementFor = (row, column, section, withinSpan, example, comparator, substitution) => {
3897
      if (section === 'colgroup' || !withinSpan) {
3898
        const cell = getCell(row, example);
3899
        return elementnew(substitution(cell.element, comparator), true, false);
3900
      } else {
3901
        return getCell(row, column);
3902
      }
3903
    };
3904
    const insertColumnAt = (grid, index, example, comparator, substitution) => map$1(grid, row => {
3905
      const withinSpan = index > 0 && index < cellLength(row) && comparator(getCellElement(row, index - 1), getCellElement(row, index));
3906
      const sub = getElementFor(row, index, row.section, withinSpan, example, comparator, substitution);
3907
      return addCell(row, index, sub);
3908
    });
3909
    const deleteColumnsAt = (grid, columns) => bind$2(grid, row => {
3910
      const existingCells = row.cells;
3911
      const cells = foldr(columns, (acc, column) => column >= 0 && column < acc.length ? acc.slice(0, column).concat(acc.slice(column + 1)) : acc, existingCells);
3912
      return cells.length > 0 ? [rowcells(row.element, cells, row.section, row.isNew)] : [];
3913
    });
3914
    const deleteRowsAt = (grid, start, finish) => {
3915
      const {rows, cols} = extractGridDetails(grid);
3916
      return [
3917
        ...cols,
3918
        ...rows.slice(0, start),
3919
        ...rows.slice(finish + 1)
3920
      ];
3921
    };
3922
 
3923
    const notInStartRow = (grid, rowIndex, colIndex, comparator) => getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(getCellElement(grid[rowIndex - 1], colIndex), getCellElement(grid[rowIndex], colIndex)));
3924
    const notInStartColumn = (row, index, comparator) => index > 0 && comparator(getCellElement(row, index - 1), getCellElement(row, index));
3925
    const isDuplicatedCell = (grid, rowIndex, colIndex, comparator) => notInStartRow(grid, rowIndex, colIndex, comparator) || notInStartColumn(grid[rowIndex], colIndex, comparator);
3926
    const rowReplacerPredicate = (targetRow, columnHeaders) => {
3927
      const entireTableIsHeader = forall(columnHeaders, identity) && isHeaderCells(targetRow.cells);
3928
      return entireTableIsHeader ? always : (cell, _rowIndex, colIndex) => {
3929
        const type = name(cell.element);
3930
        return !(type === 'th' && columnHeaders[colIndex]);
3931
      };
3932
    };
3933
    const columnReplacePredicate = (targetColumn, rowHeaders) => {
3934
      const entireTableIsHeader = forall(rowHeaders, identity) && isHeaderCells(targetColumn);
3935
      return entireTableIsHeader ? always : (cell, rowIndex, _colIndex) => {
3936
        const type = name(cell.element);
3937
        return !(type === 'th' && rowHeaders[rowIndex]);
3938
      };
3939
    };
3940
    const determineScope = (applyScope, cell, newScope, isInHeader) => {
3941
      const hasSpan = scope => scope === 'row' ? hasRowspan(cell) : hasColspan(cell);
3942
      const getScope = scope => hasSpan(scope) ? `${ scope }group` : scope;
3943
      if (applyScope) {
3944
        return isHeaderCell(cell) ? getScope(newScope) : null;
3945
      } else if (isInHeader && isHeaderCell(cell)) {
3946
        const oppositeScope = newScope === 'row' ? 'col' : 'row';
3947
        return getScope(oppositeScope);
3948
      } else {
3949
        return null;
3950
      }
3951
    };
3952
    const rowScopeGenerator = (applyScope, columnHeaders) => (cell, rowIndex, columnIndex) => Optional.some(determineScope(applyScope, cell.element, 'col', columnHeaders[columnIndex]));
3953
    const columnScopeGenerator = (applyScope, rowHeaders) => (cell, rowIndex) => Optional.some(determineScope(applyScope, cell.element, 'row', rowHeaders[rowIndex]));
3954
    const replace = (cell, comparator, substitute) => elementnew(substitute(cell.element, comparator), true, cell.isLocked);
3955
    const replaceIn = (grid, targets, comparator, substitute, replacer, genScope, shouldReplace) => {
3956
      const isTarget = cell => {
3957
        return exists(targets, target => {
3958
          return comparator(cell.element, target.element);
3959
        });
3960
      };
3961
      return map$1(grid, (row, rowIndex) => {
3962
        return mapCells(row, (cell, colIndex) => {
3963
          if (isTarget(cell)) {
3964
            const newCell = shouldReplace(cell, rowIndex, colIndex) ? replacer(cell, comparator, substitute) : cell;
3965
            genScope(newCell, rowIndex, colIndex).each(scope => {
3966
              setOptions(newCell.element, { scope: Optional.from(scope) });
3967
            });
3968
            return newCell;
3969
          } else {
3970
            return cell;
3971
          }
3972
        });
3973
      });
3974
    };
3975
    const getColumnCells = (rows, columnIndex, comparator) => bind$2(rows, (row, i) => {
3976
      return isDuplicatedCell(rows, i, columnIndex, comparator) ? [] : [getCell(row, columnIndex)];
3977
    });
3978
    const getRowCells = (rows, rowIndex, comparator) => {
3979
      const targetRow = rows[rowIndex];
3980
      return bind$2(targetRow.cells, (item, i) => {
3981
        return isDuplicatedCell(rows, rowIndex, i, comparator) ? [] : [item];
3982
      });
3983
    };
3984
    const replaceColumns = (grid, indexes, applyScope, comparator, substitution) => {
3985
      const rows = extractGridDetails(grid).rows;
3986
      const targets = bind$2(indexes, index => getColumnCells(rows, index, comparator));
3987
      const rowHeaders = map$1(rows, row => isHeaderCells(row.cells));
3988
      const shouldReplaceCell = columnReplacePredicate(targets, rowHeaders);
3989
      const scopeGenerator = columnScopeGenerator(applyScope, rowHeaders);
3990
      return replaceIn(grid, targets, comparator, substitution, replace, scopeGenerator, shouldReplaceCell);
3991
    };
3992
    const replaceRows = (grid, indexes, section, applyScope, comparator, substitution, tableSection) => {
3993
      const {cols, rows} = extractGridDetails(grid);
3994
      const targetRow = rows[indexes[0]];
3995
      const targets = bind$2(indexes, index => getRowCells(rows, index, comparator));
3996
      const columnHeaders = map$1(targetRow.cells, (_cell, index) => isHeaderCells(getColumnCells(rows, index, comparator)));
3997
      const newRows = [...rows];
3998
      each$2(indexes, index => {
3999
        newRows[index] = tableSection.transformRow(rows[index], section);
4000
      });
4001
      const newGrid = [
4002
        ...cols,
4003
        ...newRows
4004
      ];
4005
      const shouldReplaceCell = rowReplacerPredicate(targetRow, columnHeaders);
4006
      const scopeGenerator = rowScopeGenerator(applyScope, columnHeaders);
4007
      return replaceIn(newGrid, targets, comparator, substitution, tableSection.transformCell, scopeGenerator, shouldReplaceCell);
4008
    };
4009
    const replaceCells = (grid, details, comparator, substitution) => {
4010
      const rows = extractGridDetails(grid).rows;
4011
      const targetCells = map$1(details, detail => getCell(rows[detail.row], detail.column));
4012
      return replaceIn(grid, targetCells, comparator, substitution, replace, Optional.none, always);
4013
    };
4014
 
4015
    const generate = cases => {
4016
      if (!isArray(cases)) {
4017
        throw new Error('cases must be an array');
4018
      }
4019
      if (cases.length === 0) {
4020
        throw new Error('there must be at least one case');
4021
      }
4022
      const constructors = [];
4023
      const adt = {};
4024
      each$2(cases, (acase, count) => {
4025
        const keys$1 = keys(acase);
4026
        if (keys$1.length !== 1) {
4027
          throw new Error('one and only one name per case');
4028
        }
4029
        const key = keys$1[0];
4030
        const value = acase[key];
4031
        if (adt[key] !== undefined) {
4032
          throw new Error('duplicate key detected:' + key);
4033
        } else if (key === 'cata') {
4034
          throw new Error('cannot have a case named cata (sorry)');
4035
        } else if (!isArray(value)) {
4036
          throw new Error('case arguments must be an array');
4037
        }
4038
        constructors.push(key);
4039
        adt[key] = (...args) => {
4040
          const argLength = args.length;
4041
          if (argLength !== value.length) {
4042
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
4043
          }
4044
          const match = branches => {
4045
            const branchKeys = keys(branches);
4046
            if (constructors.length !== branchKeys.length) {
4047
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
4048
            }
4049
            const allReqd = forall(constructors, reqKey => {
4050
              return contains$2(branchKeys, reqKey);
4051
            });
4052
            if (!allReqd) {
4053
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
4054
            }
4055
            return branches[key].apply(null, args);
4056
          };
4057
          return {
4058
            fold: (...foldArgs) => {
4059
              if (foldArgs.length !== cases.length) {
4060
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
4061
              }
4062
              const target = foldArgs[count];
4063
              return target.apply(null, args);
4064
            },
4065
            match,
4066
            log: label => {
4067
              console.log(label, {
4068
                constructors,
4069
                constructor: key,
4070
                params: args
4071
              });
4072
            }
4073
          };
4074
        };
4075
      });
4076
      return adt;
4077
    };
4078
    const Adt = { generate };
4079
 
4080
    const adt$6 = Adt.generate([
4081
      { none: [] },
4082
      { only: ['index'] },
4083
      {
4084
        left: [
4085
          'index',
4086
          'next'
4087
        ]
4088
      },
4089
      {
4090
        middle: [
4091
          'prev',
4092
          'index',
4093
          'next'
4094
        ]
4095
      },
4096
      {
4097
        right: [
4098
          'prev',
4099
          'index'
4100
        ]
4101
      }
4102
    ]);
4103
    const ColumnContext = { ...adt$6 };
4104
 
4105
    const neighbours = (input, index) => {
4106
      if (input.length === 0) {
4107
        return ColumnContext.none();
4108
      }
4109
      if (input.length === 1) {
4110
        return ColumnContext.only(0);
4111
      }
4112
      if (index === 0) {
4113
        return ColumnContext.left(0, 1);
4114
      }
4115
      if (index === input.length - 1) {
4116
        return ColumnContext.right(index - 1, index);
4117
      }
4118
      if (index > 0 && index < input.length - 1) {
4119
        return ColumnContext.middle(index - 1, index, index + 1);
4120
      }
4121
      return ColumnContext.none();
4122
    };
4123
    const determine = (input, column, step, tableSize, resize) => {
4124
      const result = input.slice(0);
4125
      const context = neighbours(input, column);
4126
      const onNone = constant(map$1(result, constant(0)));
4127
      const onOnly = index => tableSize.singleColumnWidth(result[index], step);
4128
      const onLeft = (index, next) => resize.calcLeftEdgeDeltas(result, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
4129
      const onMiddle = (prev, index, next) => resize.calcMiddleDeltas(result, prev, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
4130
      const onRight = (prev, index) => resize.calcRightEdgeDeltas(result, prev, index, step, tableSize.minCellWidth(), tableSize.isRelative);
4131
      return context.fold(onNone, onOnly, onLeft, onMiddle, onRight);
4132
    };
4133
 
4134
    const total = (start, end, measures) => {
4135
      let r = 0;
4136
      for (let i = start; i < end; i++) {
4137
        r += measures[i] !== undefined ? measures[i] : 0;
4138
      }
4139
      return r;
4140
    };
4141
    const recalculateWidthForCells = (warehouse, widths) => {
4142
      const all = Warehouse.justCells(warehouse);
4143
      return map$1(all, cell => {
4144
        const width = total(cell.column, cell.column + cell.colspan, widths);
4145
        return {
4146
          element: cell.element,
4147
          width,
4148
          colspan: cell.colspan
4149
        };
4150
      });
4151
    };
4152
    const recalculateWidthForColumns = (warehouse, widths) => {
4153
      const groups = Warehouse.justColumns(warehouse);
4154
      return map$1(groups, (column, index) => ({
4155
        element: column.element,
4156
        width: widths[index],
4157
        colspan: column.colspan
4158
      }));
4159
    };
4160
    const recalculateHeightForCells = (warehouse, heights) => {
4161
      const all = Warehouse.justCells(warehouse);
4162
      return map$1(all, cell => {
4163
        const height = total(cell.row, cell.row + cell.rowspan, heights);
4164
        return {
4165
          element: cell.element,
4166
          height,
4167
          rowspan: cell.rowspan
4168
        };
4169
      });
4170
    };
4171
    const matchRowHeight = (warehouse, heights) => {
4172
      return map$1(warehouse.all, (row, i) => {
4173
        return {
4174
          element: row.element,
4175
          height: heights[i]
4176
        };
4177
      });
4178
    };
4179
 
4180
    const sumUp = newSize => foldr(newSize, (b, a) => b + a, 0);
4181
    const recalculate = (warehouse, widths) => {
4182
      if (Warehouse.hasColumns(warehouse)) {
4183
        return recalculateWidthForColumns(warehouse, widths);
4184
      } else {
4185
        return recalculateWidthForCells(warehouse, widths);
4186
      }
4187
    };
4188
    const recalculateAndApply = (warehouse, widths, tableSize) => {
4189
      const newSizes = recalculate(warehouse, widths);
4190
      each$2(newSizes, cell => {
4191
        tableSize.setElementWidth(cell.element, cell.width);
4192
      });
4193
    };
4194
    const adjustWidth = (table, delta, index, resizing, tableSize) => {
4195
      const warehouse = Warehouse.fromTable(table);
4196
      const step = tableSize.getCellDelta(delta);
4197
      const widths = tableSize.getWidths(warehouse, tableSize);
4198
      const isLastColumn = index === warehouse.grid.columns - 1;
4199
      const clampedStep = resizing.clampTableDelta(widths, index, step, tableSize.minCellWidth(), isLastColumn);
4200
      const deltas = determine(widths, index, clampedStep, tableSize, resizing);
4201
      const newWidths = map$1(deltas, (dx, i) => dx + widths[i]);
4202
      recalculateAndApply(warehouse, newWidths, tableSize);
4203
      resizing.resizeTable(tableSize.adjustTableWidth, clampedStep, isLastColumn);
4204
    };
4205
    const adjustHeight = (table, delta, index, direction) => {
4206
      const warehouse = Warehouse.fromTable(table);
4207
      const heights = getPixelHeights(warehouse, table, direction);
4208
      const newHeights = map$1(heights, (dy, i) => index === i ? Math.max(delta + dy, minHeight()) : dy);
4209
      const newCellSizes = recalculateHeightForCells(warehouse, newHeights);
4210
      const newRowSizes = matchRowHeight(warehouse, newHeights);
4211
      each$2(newRowSizes, row => {
4212
        setHeight(row.element, row.height);
4213
      });
4214
      each$2(newCellSizes, cell => {
4215
        setHeight(cell.element, cell.height);
4216
      });
4217
      const total = sumUp(newHeights);
4218
      setHeight(table, total);
4219
    };
4220
    const adjustAndRedistributeWidths$1 = (_table, list, details, tableSize, resizeBehaviour) => {
4221
      const warehouse = Warehouse.generate(list);
4222
      const sizes = tableSize.getWidths(warehouse, tableSize);
4223
      const tablePixelWidth = tableSize.pixelWidth();
4224
      const {newSizes, delta} = resizeBehaviour.calcRedestributedWidths(sizes, tablePixelWidth, details.pixelDelta, tableSize.isRelative);
4225
      recalculateAndApply(warehouse, newSizes, tableSize);
4226
      tableSize.adjustTableWidth(delta);
4227
    };
4228
    const adjustWidthTo = (_table, list, _info, tableSize) => {
4229
      const warehouse = Warehouse.generate(list);
4230
      const widths = tableSize.getWidths(warehouse, tableSize);
4231
      recalculateAndApply(warehouse, widths, tableSize);
4232
    };
4233
 
4234
    const uniqueColumns = details => {
4235
      const uniqueCheck = (rest, detail) => {
4236
        const columnExists = exists(rest, currentDetail => currentDetail.column === detail.column);
4237
        return columnExists ? rest : rest.concat([detail]);
4238
      };
4239
      return foldl(details, uniqueCheck, []).sort((detailA, detailB) => detailA.column - detailB.column);
4240
    };
4241
 
4242
    const isCol = isTag('col');
4243
    const isColgroup = isTag('colgroup');
4244
    const isRow$1 = element => name(element) === 'tr' || isColgroup(element);
4245
    const elementToData = element => {
4246
      const colspan = getAttrValue(element, 'colspan', 1);
4247
      const rowspan = getAttrValue(element, 'rowspan', 1);
4248
      return {
4249
        element,
4250
        colspan,
4251
        rowspan
4252
      };
4253
    };
4254
    const modification = (generators, toData = elementToData) => {
4255
      const nuCell = data => isCol(data.element) ? generators.col(data) : generators.cell(data);
4256
      const nuRow = data => isColgroup(data.element) ? generators.colgroup(data) : generators.row(data);
4257
      const add = element => {
4258
        if (isRow$1(element)) {
4259
          return nuRow({ element });
4260
        } else {
4261
          const cell = element;
4262
          const replacement = nuCell(toData(cell));
4263
          recent = Optional.some({
4264
            item: cell,
4265
            replacement
4266
          });
4267
          return replacement;
4268
        }
4269
      };
4270
      let recent = Optional.none();
4271
      const getOrInit = (element, comparator) => {
4272
        return recent.fold(() => {
4273
          return add(element);
4274
        }, p => {
4275
          return comparator(element, p.item) ? p.replacement : add(element);
4276
        });
4277
      };
4278
      return { getOrInit };
4279
    };
4280
    const transform$1 = tag => {
4281
      return generators => {
4282
        const list = [];
4283
        const find = (element, comparator) => {
4284
          return find$1(list, x => {
4285
            return comparator(x.item, element);
4286
          });
4287
        };
4288
        const makeNew = element => {
4289
          const attrs = tag === 'td' ? { scope: null } : {};
4290
          const cell = generators.replace(element, tag, attrs);
4291
          list.push({
4292
            item: element,
4293
            sub: cell
4294
          });
4295
          return cell;
4296
        };
4297
        const replaceOrInit = (element, comparator) => {
4298
          if (isRow$1(element) || isCol(element)) {
4299
            return element;
4300
          } else {
4301
            const cell = element;
4302
            return find(cell, comparator).fold(() => {
4303
              return makeNew(cell);
4304
            }, p => {
4305
              return comparator(element, p.item) ? p.sub : makeNew(cell);
4306
            });
4307
          }
4308
        };
4309
        return { replaceOrInit };
4310
      };
4311
    };
4312
    const getScopeAttribute = cell => getOpt(cell, 'scope').map(attribute => attribute.substr(0, 3));
4313
    const merging = generators => {
4314
      const unmerge = cell => {
4315
        const scope = getScopeAttribute(cell);
4316
        scope.each(attribute => set$2(cell, 'scope', attribute));
4317
        return () => {
4318
          const raw = generators.cell({
4319
            element: cell,
4320
            colspan: 1,
4321
            rowspan: 1
4322
          });
4323
          remove$5(raw, 'width');
4324
          remove$5(cell, 'width');
4325
          scope.each(attribute => set$2(raw, 'scope', attribute));
4326
          return raw;
4327
        };
4328
      };
4329
      const merge = cells => {
4330
        const getScopeProperty = () => {
4331
          const stringAttributes = cat(map$1(cells, getScopeAttribute));
4332
          if (stringAttributes.length === 0) {
4333
            return Optional.none();
4334
          } else {
4335
            const baseScope = stringAttributes[0];
4336
            const scopes = [
4337
              'row',
4338
              'col'
4339
            ];
4340
            const isMixed = exists(stringAttributes, attribute => {
4341
              return attribute !== baseScope && contains$2(scopes, attribute);
4342
            });
4343
            return isMixed ? Optional.none() : Optional.from(baseScope);
4344
          }
4345
        };
4346
        remove$5(cells[0], 'width');
4347
        getScopeProperty().fold(() => remove$7(cells[0], 'scope'), attribute => set$2(cells[0], 'scope', attribute + 'group'));
4348
        return constant(cells[0]);
4349
      };
4350
      return {
4351
        unmerge,
4352
        merge
4353
      };
4354
    };
4355
    const Generators = {
4356
      modification,
4357
      transform: transform$1,
4358
      merging
4359
    };
4360
 
4361
    const blockList = [
4362
      'body',
4363
      'p',
4364
      'div',
4365
      'article',
4366
      'aside',
4367
      'figcaption',
4368
      'figure',
4369
      'footer',
4370
      'header',
4371
      'nav',
4372
      'section',
4373
      'ol',
4374
      'ul',
4375
      'table',
4376
      'thead',
4377
      'tfoot',
4378
      'tbody',
4379
      'caption',
4380
      'tr',
4381
      'td',
4382
      'th',
4383
      'h1',
4384
      'h2',
4385
      'h3',
4386
      'h4',
4387
      'h5',
4388
      'h6',
4389
      'blockquote',
4390
      'pre',
4391
      'address'
4392
    ];
4393
    const isList$1 = (universe, item) => {
4394
      const tagName = universe.property().name(item);
4395
      return contains$2([
4396
        'ol',
4397
        'ul'
4398
      ], tagName);
4399
    };
4400
    const isBlock$1 = (universe, item) => {
4401
      const tagName = universe.property().name(item);
4402
      return contains$2(blockList, tagName);
4403
    };
4404
    const isEmptyTag$1 = (universe, item) => {
4405
      return contains$2([
4406
        'br',
4407
        'img',
4408
        'hr',
4409
        'input'
4410
      ], universe.property().name(item));
4411
    };
4412
 
4413
    const universe$1 = DomUniverse();
4414
    const isBlock = element => {
4415
      return isBlock$1(universe$1, element);
4416
    };
4417
    const isList = element => {
4418
      return isList$1(universe$1, element);
4419
    };
4420
    const isEmptyTag = element => {
4421
      return isEmptyTag$1(universe$1, element);
4422
    };
4423
 
4424
    const merge = cells => {
4425
      const isBr = isTag('br');
4426
      const advancedBr = children => {
4427
        return forall(children, c => {
4428
          return isBr(c) || isText(c) && get$6(c).trim().length === 0;
4429
        });
4430
      };
4431
      const isListItem = el => {
4432
        return name(el) === 'li' || ancestor$2(el, isList).isSome();
4433
      };
4434
      const siblingIsBlock = el => {
4435
        return nextSibling(el).map(rightSibling => {
4436
          if (isBlock(rightSibling)) {
4437
            return true;
4438
          }
4439
          if (isEmptyTag(rightSibling)) {
4440
            return name(rightSibling) === 'img' ? false : true;
4441
          }
4442
          return false;
4443
        }).getOr(false);
4444
      };
4445
      const markCell = cell => {
4446
        return last$1(cell).bind(rightEdge => {
4447
          const rightSiblingIsBlock = siblingIsBlock(rightEdge);
4448
          return parent(rightEdge).map(parent => {
4449
            return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || isBlock(parent) && !eq$1(cell, parent) ? [] : [SugarElement.fromTag('br')];
4450
          });
4451
        }).getOr([]);
4452
      };
4453
      const markContent = () => {
4454
        const content = bind$2(cells, cell => {
4455
          const children = children$2(cell);
4456
          return advancedBr(children) ? [] : children.concat(markCell(cell));
4457
        });
4458
        return content.length === 0 ? [SugarElement.fromTag('br')] : content;
4459
      };
4460
      const contents = markContent();
4461
      empty(cells[0]);
4462
      append(cells[0], contents);
4463
    };
4464
 
4465
    const isEditable = elem => isEditable$1(elem, true);
4466
    const prune = table => {
4467
      const cells = cells$1(table);
4468
      if (cells.length === 0) {
4469
        remove$6(table);
4470
      }
4471
    };
4472
    const outcome = (grid, cursor) => ({
4473
      grid,
4474
      cursor
4475
    });
4476
    const findEditableCursorPosition = rows => findMap(rows, row => findMap(row.cells, cell => {
4477
      const elem = cell.element;
4478
      return someIf(isEditable(elem), elem);
4479
    }));
4480
    const elementFromGrid = (grid, row, column) => {
4481
      var _a, _b;
4482
      const rows = extractGridDetails(grid).rows;
4483
      return Optional.from((_b = (_a = rows[row]) === null || _a === void 0 ? void 0 : _a.cells[column]) === null || _b === void 0 ? void 0 : _b.element).filter(isEditable).orThunk(() => findEditableCursorPosition(rows));
4484
    };
4485
    const bundle = (grid, row, column) => {
4486
      const cursorElement = elementFromGrid(grid, row, column);
4487
      return outcome(grid, cursorElement);
4488
    };
4489
    const uniqueRows = details => {
4490
      const rowCompilation = (rest, detail) => {
4491
        const rowExists = exists(rest, currentDetail => currentDetail.row === detail.row);
4492
        return rowExists ? rest : rest.concat([detail]);
4493
      };
4494
      return foldl(details, rowCompilation, []).sort((detailA, detailB) => detailA.row - detailB.row);
4495
    };
4496
    const opInsertRowsBefore = (grid, details, comparator, genWrappers) => {
4497
      const targetIndex = details[0].row;
4498
      const rows = uniqueRows(details);
4499
      const newGrid = foldr(rows, (acc, row) => {
4500
        const newG = insertRowAt(acc.grid, targetIndex, row.row + acc.delta, comparator, genWrappers.getOrInit);
4501
        return {
4502
          grid: newG,
4503
          delta: acc.delta + 1
4504
        };
4505
      }, {
4506
        grid,
4507
        delta: 0
4508
      }).grid;
4509
      return bundle(newGrid, targetIndex, details[0].column);
4510
    };
4511
    const opInsertRowsAfter = (grid, details, comparator, genWrappers) => {
4512
      const rows = uniqueRows(details);
4513
      const target = rows[rows.length - 1];
4514
      const targetIndex = target.row + target.rowspan;
4515
      const newGrid = foldr(rows, (newG, row) => {
4516
        return insertRowAt(newG, targetIndex, row.row, comparator, genWrappers.getOrInit);
4517
      }, grid);
4518
      return bundle(newGrid, targetIndex, details[0].column);
4519
    };
4520
    const opInsertColumnsBefore = (grid, extractDetail, comparator, genWrappers) => {
4521
      const details = extractDetail.details;
4522
      const columns = uniqueColumns(details);
4523
      const targetIndex = columns[0].column;
4524
      const newGrid = foldr(columns, (acc, col) => {
4525
        const newG = insertColumnAt(acc.grid, targetIndex, col.column + acc.delta, comparator, genWrappers.getOrInit);
4526
        return {
4527
          grid: newG,
4528
          delta: acc.delta + 1
4529
        };
4530
      }, {
4531
        grid,
4532
        delta: 0
4533
      }).grid;
4534
      return bundle(newGrid, details[0].row, targetIndex);
4535
    };
4536
    const opInsertColumnsAfter = (grid, extractDetail, comparator, genWrappers) => {
4537
      const details = extractDetail.details;
4538
      const target = details[details.length - 1];
4539
      const targetIndex = target.column + target.colspan;
4540
      const columns = uniqueColumns(details);
4541
      const newGrid = foldr(columns, (newG, col) => {
4542
        return insertColumnAt(newG, targetIndex, col.column, comparator, genWrappers.getOrInit);
4543
      }, grid);
4544
      return bundle(newGrid, details[0].row, targetIndex);
4545
    };
4546
    const opMakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
4547
      const columns = uniqueColumns(details);
4548
      const columnIndexes = map$1(columns, detail => detail.column);
4549
      const newGrid = replaceColumns(initialGrid, columnIndexes, true, comparator, genWrappers.replaceOrInit);
4550
      return bundle(newGrid, details[0].row, details[0].column);
4551
    };
4552
    const opMakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
4553
      const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
4554
      return bundle(newGrid, details[0].row, details[0].column);
4555
    };
4556
    const opUnmakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
4557
      const columns = uniqueColumns(details);
4558
      const columnIndexes = map$1(columns, detail => detail.column);
4559
      const newGrid = replaceColumns(initialGrid, columnIndexes, false, comparator, genWrappers.replaceOrInit);
4560
      return bundle(newGrid, details[0].row, details[0].column);
4561
    };
4562
    const opUnmakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
4563
      const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
4564
      return bundle(newGrid, details[0].row, details[0].column);
4565
    };
4566
    const makeRowsSection = (section, applyScope) => (initialGrid, details, comparator, genWrappers, tableSection) => {
4567
      const rows = uniqueRows(details);
4568
      const rowIndexes = map$1(rows, detail => detail.row);
4569
      const newGrid = replaceRows(initialGrid, rowIndexes, section, applyScope, comparator, genWrappers.replaceOrInit, tableSection);
4570
      return bundle(newGrid, details[0].row, details[0].column);
4571
    };
4572
    const opMakeRowsHeader = makeRowsSection('thead', true);
4573
    const opMakeRowsBody = makeRowsSection('tbody', false);
4574
    const opMakeRowsFooter = makeRowsSection('tfoot', false);
4575
    const opEraseColumns = (grid, extractDetail, _comparator, _genWrappers) => {
4576
      const columns = uniqueColumns(extractDetail.details);
4577
      const newGrid = deleteColumnsAt(grid, map$1(columns, column => column.column));
4578
      const maxColIndex = newGrid.length > 0 ? newGrid[0].cells.length - 1 : 0;
4579
      return bundle(newGrid, columns[0].row, Math.min(columns[0].column, maxColIndex));
4580
    };
4581
    const opEraseRows = (grid, details, _comparator, _genWrappers) => {
4582
      const rows = uniqueRows(details);
4583
      const newGrid = deleteRowsAt(grid, rows[0].row, rows[rows.length - 1].row);
4584
      const maxRowIndex = newGrid.length > 0 ? newGrid.length - 1 : 0;
4585
      return bundle(newGrid, Math.min(details[0].row, maxRowIndex), details[0].column);
4586
    };
4587
    const opMergeCells = (grid, mergable, comparator, genWrappers) => {
4588
      const cells = mergable.cells;
4589
      merge(cells);
4590
      const newGrid = merge$2(grid, mergable.bounds, comparator, genWrappers.merge(cells));
4591
      return outcome(newGrid, Optional.from(cells[0]));
4592
    };
4593
    const opUnmergeCells = (grid, unmergable, comparator, genWrappers) => {
4594
      const unmerge$1 = (b, cell) => unmerge(b, cell, comparator, genWrappers.unmerge(cell));
4595
      const newGrid = foldr(unmergable, unmerge$1, grid);
4596
      return outcome(newGrid, Optional.from(unmergable[0]));
4597
    };
4598
    const opPasteCells = (grid, pasteDetails, comparator, _genWrappers) => {
4599
      const gridify = (table, generators) => {
4600
        const wh = Warehouse.fromTable(table);
4601
        return toGrid(wh, generators, true);
4602
      };
4603
      const gridB = gridify(pasteDetails.clipboard, pasteDetails.generators);
4604
      const startAddress = address(pasteDetails.row, pasteDetails.column);
4605
      const mergedGrid = merge$1(startAddress, grid, gridB, pasteDetails.generators, comparator);
4606
      return mergedGrid.fold(() => outcome(grid, Optional.some(pasteDetails.element)), newGrid => {
4607
        return bundle(newGrid, pasteDetails.row, pasteDetails.column);
4608
      });
4609
    };
4610
    const gridifyRows = (rows, generators, context) => {
4611
      const pasteDetails = fromPastedRows(rows, context.section);
4612
      const wh = Warehouse.generate(pasteDetails);
4613
      return toGrid(wh, generators, true);
4614
    };
4615
    const opPasteColsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
4616
      const rows = extractGridDetails(grid).rows;
4617
      const index = pasteDetails.cells[0].column;
4618
      const context = rows[pasteDetails.cells[0].row];
4619
      const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
4620
      const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
4621
      return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
4622
    };
4623
    const opPasteColsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
4624
      const rows = extractGridDetails(grid).rows;
4625
      const index = pasteDetails.cells[pasteDetails.cells.length - 1].column + pasteDetails.cells[pasteDetails.cells.length - 1].colspan;
4626
      const context = rows[pasteDetails.cells[0].row];
4627
      const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
4628
      const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
4629
      return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
4630
    };
4631
    const opPasteRowsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
4632
      const rows = extractGridDetails(grid).rows;
4633
      const index = pasteDetails.cells[0].row;
4634
      const context = rows[index];
4635
      const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
4636
      const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
4637
      return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
4638
    };
4639
    const opPasteRowsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
4640
      const rows = extractGridDetails(grid).rows;
4641
      const index = pasteDetails.cells[pasteDetails.cells.length - 1].row + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan;
4642
      const context = rows[pasteDetails.cells[0].row];
4643
      const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
4644
      const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
4645
      return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
4646
    };
4647
    const opGetColumnsType = (table, target) => {
4648
      const house = Warehouse.fromTable(table);
4649
      const details = onCells(house, target);
4650
      return details.bind(selectedCells => {
4651
        const lastSelectedCell = selectedCells[selectedCells.length - 1];
4652
        const minColRange = selectedCells[0].column;
4653
        const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
4654
        const selectedColumnCells = flatten(map$1(house.all, row => filter$2(row.cells, cell => cell.column >= minColRange && cell.column < maxColRange)));
4655
        return findCommonCellType(selectedColumnCells);
4656
      }).getOr('');
4657
    };
4658
    const opGetCellsType = (table, target) => {
4659
      const house = Warehouse.fromTable(table);
4660
      const details = onCells(house, target);
4661
      return details.bind(findCommonCellType).getOr('');
4662
    };
4663
    const opGetRowsType = (table, target) => {
4664
      const house = Warehouse.fromTable(table);
4665
      const details = onCells(house, target);
4666
      return details.bind(selectedCells => {
4667
        const lastSelectedCell = selectedCells[selectedCells.length - 1];
4668
        const minRowRange = selectedCells[0].row;
4669
        const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan;
4670
        const selectedRows = house.all.slice(minRowRange, maxRowRange);
4671
        return findCommonRowType(selectedRows);
4672
      }).getOr('');
4673
    };
4674
    const resize = (table, list, details, behaviours) => adjustWidthTo(table, list, details, behaviours.sizing);
4675
    const adjustAndRedistributeWidths = (table, list, details, behaviours) => adjustAndRedistributeWidths$1(table, list, details, behaviours.sizing, behaviours.resize);
4676
    const firstColumnIsLocked = (_warehouse, details) => exists(details, detail => detail.column === 0 && detail.isLocked);
4677
    const lastColumnIsLocked = (warehouse, details) => exists(details, detail => detail.column + detail.colspan >= warehouse.grid.columns && detail.isLocked);
4678
    const getColumnsWidth = (warehouse, details) => {
4679
      const columns$1 = columns(warehouse);
4680
      const uniqueCols = uniqueColumns(details);
4681
      return foldl(uniqueCols, (acc, detail) => {
4682
        const column = columns$1[detail.column];
4683
        const colWidth = column.map(getOuter$2).getOr(0);
4684
        return acc + colWidth;
4685
      }, 0);
4686
    };
4687
    const insertColumnsExtractor = before => (warehouse, target) => onCells(warehouse, target).filter(details => {
4688
      const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
4689
      return !checkLocked(warehouse, details);
4690
    }).map(details => ({
4691
      details,
4692
      pixelDelta: getColumnsWidth(warehouse, details)
4693
    }));
4694
    const eraseColumnsExtractor = (warehouse, target) => onUnlockedCells(warehouse, target).map(details => ({
4695
      details,
4696
      pixelDelta: -getColumnsWidth(warehouse, details)
4697
    }));
4698
    const pasteColumnsExtractor = before => (warehouse, target) => onPasteByEditor(warehouse, target).filter(details => {
4699
      const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
4700
      return !checkLocked(warehouse, details.cells);
4701
    });
4702
    const headerCellGenerator = Generators.transform('th');
4703
    const bodyCellGenerator = Generators.transform('td');
4704
    const insertRowsBefore = run(opInsertRowsBefore, onCells, noop, noop, Generators.modification);
4705
    const insertRowsAfter = run(opInsertRowsAfter, onCells, noop, noop, Generators.modification);
4706
    const insertColumnsBefore = run(opInsertColumnsBefore, insertColumnsExtractor(true), adjustAndRedistributeWidths, noop, Generators.modification);
4707
    const insertColumnsAfter = run(opInsertColumnsAfter, insertColumnsExtractor(false), adjustAndRedistributeWidths, noop, Generators.modification);
4708
    const eraseColumns = run(opEraseColumns, eraseColumnsExtractor, adjustAndRedistributeWidths, prune, Generators.modification);
4709
    const eraseRows = run(opEraseRows, onCells, noop, prune, Generators.modification);
4710
    const makeColumnsHeader = run(opMakeColumnsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
4711
    const unmakeColumnsHeader = run(opUnmakeColumnsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
4712
    const makeRowsHeader = run(opMakeRowsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
4713
    const makeRowsBody = run(opMakeRowsBody, onUnlockedCells, noop, noop, bodyCellGenerator);
4714
    const makeRowsFooter = run(opMakeRowsFooter, onUnlockedCells, noop, noop, bodyCellGenerator);
4715
    const makeCellsHeader = run(opMakeCellsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
4716
    const unmakeCellsHeader = run(opUnmakeCellsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
4717
    const mergeCells = run(opMergeCells, onUnlockedMergable, resize, noop, Generators.merging);
4718
    const unmergeCells = run(opUnmergeCells, onUnlockedUnmergable, resize, noop, Generators.merging);
4719
    const pasteCells = run(opPasteCells, onPaste, resize, noop, Generators.modification);
4720
    const pasteColsBefore = run(opPasteColsBefore, pasteColumnsExtractor(true), noop, noop, Generators.modification);
4721
    const pasteColsAfter = run(opPasteColsAfter, pasteColumnsExtractor(false), noop, noop, Generators.modification);
4722
    const pasteRowsBefore = run(opPasteRowsBefore, onPasteByEditor, noop, noop, Generators.modification);
4723
    const pasteRowsAfter = run(opPasteRowsAfter, onPasteByEditor, noop, noop, Generators.modification);
4724
    const getColumnsType = opGetColumnsType;
4725
    const getCellsType = opGetCellsType;
4726
    const getRowsType = opGetRowsType;
4727
 
4728
    const fireNewRow = (editor, row) => editor.dispatch('NewRow', { node: row });
4729
    const fireNewCell = (editor, cell) => editor.dispatch('NewCell', { node: cell });
4730
    const fireTableModified = (editor, table, data) => {
4731
      editor.dispatch('TableModified', {
4732
        ...data,
4733
        table
4734
      });
4735
    };
4736
    const fireTableSelectionChange = (editor, cells, start, finish, otherCells) => {
4737
      editor.dispatch('TableSelectionChange', {
4738
        cells,
4739
        start,
4740
        finish,
4741
        otherCells
4742
      });
4743
    };
4744
    const fireTableSelectionClear = editor => {
4745
      editor.dispatch('TableSelectionClear');
4746
    };
4747
    const fireObjectResizeStart = (editor, target, width, height, origin) => {
4748
      editor.dispatch('ObjectResizeStart', {
4749
        target,
4750
        width,
4751
        height,
4752
        origin
4753
      });
4754
    };
4755
    const fireObjectResized = (editor, target, width, height, origin) => {
4756
      editor.dispatch('ObjectResized', {
4757
        target,
4758
        width,
4759
        height,
4760
        origin
4761
      });
4762
    };
4763
    const styleModified = {
4764
      structure: false,
4765
      style: true
4766
    };
4767
    const structureModified = {
4768
      structure: true,
4769
      style: false
4770
    };
4771
    const styleAndStructureModified = {
4772
      structure: true,
4773
      style: true
4774
    };
4775
 
4776
    const get$5 = (editor, table) => {
4777
      if (isTablePercentagesForced(editor)) {
4778
        return TableSize.percentageSize(table);
4779
      } else if (isTablePixelsForced(editor)) {
4780
        return TableSize.pixelSize(table);
4781
      } else {
4782
        return TableSize.getTableSize(table);
4783
      }
4784
    };
4785
 
4786
    const TableActions = (editor, resizeHandler, cellSelectionHandler) => {
4787
      const isTableBody = editor => name(getBody(editor)) === 'table';
4788
      const lastRowGuard = table => !isTableBody(editor) || getGridSize(table).rows > 1;
4789
      const lastColumnGuard = table => !isTableBody(editor) || getGridSize(table).columns > 1;
4790
      const cloneFormats = getTableCloneElements(editor);
4791
      const colMutationOp = isResizeTableColumnResizing(editor) ? noop : halve;
4792
      const getTableSectionType = table => {
4793
        switch (getTableHeaderType(editor)) {
4794
        case 'section':
4795
          return TableSection.section();
4796
        case 'sectionCells':
4797
          return TableSection.sectionCells();
4798
        case 'cells':
4799
          return TableSection.cells();
4800
        default:
4801
          return TableSection.getTableSectionType(table, 'section');
4802
        }
4803
      };
4804
      const setSelectionFromAction = (table, result) => result.cursor.fold(() => {
4805
        const cells = cells$1(table);
4806
        return head(cells).filter(inBody).map(firstCell => {
4807
          cellSelectionHandler.clearSelectedCells(table.dom);
4808
          const rng = editor.dom.createRng();
4809
          rng.selectNode(firstCell.dom);
4810
          editor.selection.setRng(rng);
4811
          set$2(firstCell, 'data-mce-selected', '1');
4812
          return rng;
4813
        });
4814
      }, cell => {
4815
        const des = freefallRtl(cell);
4816
        const rng = editor.dom.createRng();
4817
        rng.setStart(des.element.dom, des.offset);
4818
        rng.setEnd(des.element.dom, des.offset);
4819
        editor.selection.setRng(rng);
4820
        cellSelectionHandler.clearSelectedCells(table.dom);
4821
        return Optional.some(rng);
4822
      });
4823
      const execute = (operation, guard, mutate, effect) => (table, target, noEvents = false) => {
4824
        removeDataStyle(table);
4825
        const doc = SugarElement.fromDom(editor.getDoc());
4826
        const generators = cellOperations(mutate, doc, cloneFormats);
4827
        const behaviours = {
4828
          sizing: get$5(editor, table),
4829
          resize: isResizeTableColumnResizing(editor) ? resizeTable() : preserveTable(),
4830
          section: getTableSectionType(table)
4831
        };
4832
        return guard(table) ? operation(table, target, generators, behaviours).bind(result => {
4833
          resizeHandler.refresh(table.dom);
4834
          each$2(result.newRows, row => {
4835
            fireNewRow(editor, row.dom);
4836
          });
4837
          each$2(result.newCells, cell => {
4838
            fireNewCell(editor, cell.dom);
4839
          });
4840
          const range = setSelectionFromAction(table, result);
4841
          if (inBody(table)) {
4842
            removeDataStyle(table);
4843
            if (!noEvents) {
4844
              fireTableModified(editor, table.dom, effect);
4845
            }
4846
          }
4847
          return range.map(rng => ({
4848
            rng,
4849
            effect
4850
          }));
4851
        }) : Optional.none();
4852
      };
4853
      const deleteRow = execute(eraseRows, lastRowGuard, noop, structureModified);
4854
      const deleteColumn = execute(eraseColumns, lastColumnGuard, noop, structureModified);
4855
      const insertRowsBefore$1 = execute(insertRowsBefore, always, noop, structureModified);
4856
      const insertRowsAfter$1 = execute(insertRowsAfter, always, noop, structureModified);
4857
      const insertColumnsBefore$1 = execute(insertColumnsBefore, always, colMutationOp, structureModified);
4858
      const insertColumnsAfter$1 = execute(insertColumnsAfter, always, colMutationOp, structureModified);
4859
      const mergeCells$1 = execute(mergeCells, always, noop, structureModified);
4860
      const unmergeCells$1 = execute(unmergeCells, always, noop, structureModified);
4861
      const pasteColsBefore$1 = execute(pasteColsBefore, always, noop, structureModified);
4862
      const pasteColsAfter$1 = execute(pasteColsAfter, always, noop, structureModified);
4863
      const pasteRowsBefore$1 = execute(pasteRowsBefore, always, noop, structureModified);
4864
      const pasteRowsAfter$1 = execute(pasteRowsAfter, always, noop, structureModified);
4865
      const pasteCells$1 = execute(pasteCells, always, noop, styleAndStructureModified);
4866
      const makeCellsHeader$1 = execute(makeCellsHeader, always, noop, structureModified);
4867
      const unmakeCellsHeader$1 = execute(unmakeCellsHeader, always, noop, structureModified);
4868
      const makeColumnsHeader$1 = execute(makeColumnsHeader, always, noop, structureModified);
4869
      const unmakeColumnsHeader$1 = execute(unmakeColumnsHeader, always, noop, structureModified);
4870
      const makeRowsHeader$1 = execute(makeRowsHeader, always, noop, structureModified);
4871
      const makeRowsBody$1 = execute(makeRowsBody, always, noop, structureModified);
4872
      const makeRowsFooter$1 = execute(makeRowsFooter, always, noop, structureModified);
4873
      const getTableCellType = getCellsType;
4874
      const getTableColType = getColumnsType;
4875
      const getTableRowType = getRowsType;
4876
      return {
4877
        deleteRow,
4878
        deleteColumn,
4879
        insertRowsBefore: insertRowsBefore$1,
4880
        insertRowsAfter: insertRowsAfter$1,
4881
        insertColumnsBefore: insertColumnsBefore$1,
4882
        insertColumnsAfter: insertColumnsAfter$1,
4883
        mergeCells: mergeCells$1,
4884
        unmergeCells: unmergeCells$1,
4885
        pasteColsBefore: pasteColsBefore$1,
4886
        pasteColsAfter: pasteColsAfter$1,
4887
        pasteRowsBefore: pasteRowsBefore$1,
4888
        pasteRowsAfter: pasteRowsAfter$1,
4889
        pasteCells: pasteCells$1,
4890
        makeCellsHeader: makeCellsHeader$1,
4891
        unmakeCellsHeader: unmakeCellsHeader$1,
4892
        makeColumnsHeader: makeColumnsHeader$1,
4893
        unmakeColumnsHeader: unmakeColumnsHeader$1,
4894
        makeRowsHeader: makeRowsHeader$1,
4895
        makeRowsBody: makeRowsBody$1,
4896
        makeRowsFooter: makeRowsFooter$1,
4897
        getTableRowType,
4898
        getTableCellType,
4899
        getTableColType
4900
      };
4901
    };
4902
 
4903
    const constrainSpan = (element, property, value) => {
4904
      const currentColspan = getAttrValue(element, property, 1);
4905
      if (value === 1 || currentColspan <= 1) {
4906
        remove$7(element, property);
4907
      } else {
4908
        set$2(element, property, Math.min(value, currentColspan));
4909
      }
4910
    };
4911
    const isColInRange = (minColRange, maxColRange) => cell => {
4912
      const endCol = cell.column + cell.colspan - 1;
4913
      const startCol = cell.column;
4914
      return endCol >= minColRange && startCol < maxColRange;
4915
    };
4916
    const generateColGroup = (house, minColRange, maxColRange) => {
4917
      if (Warehouse.hasColumns(house)) {
4918
        const colsToCopy = filter$2(Warehouse.justColumns(house), isColInRange(minColRange, maxColRange));
4919
        const copiedCols = map$1(colsToCopy, c => {
4920
          const clonedCol = deep(c.element);
4921
          constrainSpan(clonedCol, 'span', maxColRange - minColRange);
4922
          return clonedCol;
4923
        });
4924
        const fakeColgroup = SugarElement.fromTag('colgroup');
4925
        append(fakeColgroup, copiedCols);
4926
        return [fakeColgroup];
4927
      } else {
4928
        return [];
4929
      }
4930
    };
4931
    const generateRows = (house, minColRange, maxColRange) => map$1(house.all, row => {
4932
      const cellsToCopy = filter$2(row.cells, isColInRange(minColRange, maxColRange));
4933
      const copiedCells = map$1(cellsToCopy, cell => {
4934
        const clonedCell = deep(cell.element);
4935
        constrainSpan(clonedCell, 'colspan', maxColRange - minColRange);
4936
        return clonedCell;
4937
      });
4938
      const fakeTR = SugarElement.fromTag('tr');
4939
      append(fakeTR, copiedCells);
4940
      return fakeTR;
4941
    });
4942
    const copyCols = (table, target) => {
4943
      const house = Warehouse.fromTable(table);
4944
      const details = onUnlockedCells(house, target);
4945
      return details.map(selectedCells => {
4946
        const lastSelectedCell = selectedCells[selectedCells.length - 1];
4947
        const minColRange = selectedCells[0].column;
4948
        const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
4949
        const fakeColGroups = generateColGroup(house, minColRange, maxColRange);
4950
        const fakeRows = generateRows(house, minColRange, maxColRange);
4951
        return [
4952
          ...fakeColGroups,
4953
          ...fakeRows
4954
        ];
4955
      });
4956
    };
4957
 
4958
    const copyRows = (table, target, generators) => {
4959
      const warehouse = Warehouse.fromTable(table);
4960
      const details = onCells(warehouse, target);
4961
      return details.bind(selectedCells => {
4962
        const grid = toGrid(warehouse, generators, false);
4963
        const rows = extractGridDetails(grid).rows;
4964
        const slicedGrid = rows.slice(selectedCells[0].row, selectedCells[selectedCells.length - 1].row + selectedCells[selectedCells.length - 1].rowspan);
4965
        const filteredGrid = bind$2(slicedGrid, row => {
4966
          const newCells = filter$2(row.cells, cell => !cell.isLocked);
4967
          return newCells.length > 0 ? [{
4968
              ...row,
4969
              cells: newCells
4970
            }] : [];
4971
        });
4972
        const slicedDetails = toDetailList(filteredGrid);
4973
        return someIf(slicedDetails.length > 0, slicedDetails);
4974
      }).map(slicedDetails => copy(slicedDetails));
4975
    };
4976
 
4977
    const adt$5 = Adt.generate([
4978
      { invalid: ['raw'] },
4979
      { pixels: ['value'] },
4980
      { percent: ['value'] }
4981
    ]);
4982
    const validateFor = (suffix, type, value) => {
4983
      const rawAmount = value.substring(0, value.length - suffix.length);
4984
      const amount = parseFloat(rawAmount);
4985
      return rawAmount === amount.toString() ? type(amount) : adt$5.invalid(value);
4986
    };
4987
    const from = value => {
4988
      if (endsWith(value, '%')) {
4989
        return validateFor('%', adt$5.percent, value);
4990
      }
4991
      if (endsWith(value, 'px')) {
4992
        return validateFor('px', adt$5.pixels, value);
4993
      }
4994
      return adt$5.invalid(value);
4995
    };
4996
    const Size = {
4997
      ...adt$5,
4998
      from
4999
    };
5000
 
5001
    const redistributeToPercent = (widths, totalWidth) => {
5002
      return map$1(widths, w => {
5003
        const colType = Size.from(w);
5004
        return colType.fold(() => {
5005
          return w;
5006
        }, px => {
5007
          const ratio = px / totalWidth * 100;
5008
          return ratio + '%';
5009
        }, pc => {
5010
          return pc + '%';
5011
        });
5012
      });
5013
    };
5014
    const redistributeToPx = (widths, totalWidth, newTotalWidth) => {
5015
      const scale = newTotalWidth / totalWidth;
5016
      return map$1(widths, w => {
5017
        const colType = Size.from(w);
5018
        return colType.fold(() => {
5019
          return w;
5020
        }, px => {
5021
          return px * scale + 'px';
5022
        }, pc => {
5023
          return pc / 100 * newTotalWidth + 'px';
5024
        });
5025
      });
5026
    };
5027
    const redistributeEmpty = (newWidthType, columns) => {
5028
      const f = newWidthType.fold(() => constant(''), pixels => {
5029
        const num = pixels / columns;
5030
        return constant(num + 'px');
5031
      }, () => {
5032
        const num = 100 / columns;
5033
        return constant(num + '%');
5034
      });
5035
      return range$1(columns, f);
5036
    };
5037
    const redistributeValues = (newWidthType, widths, totalWidth) => {
5038
      return newWidthType.fold(() => {
5039
        return widths;
5040
      }, px => {
5041
        return redistributeToPx(widths, totalWidth, px);
5042
      }, _pc => {
5043
        return redistributeToPercent(widths, totalWidth);
5044
      });
5045
    };
5046
    const redistribute$1 = (widths, totalWidth, newWidth) => {
5047
      const newType = Size.from(newWidth);
5048
      const floats = forall(widths, s => {
5049
        return s === '0px';
5050
      }) ? redistributeEmpty(newType, widths.length) : redistributeValues(newType, widths, totalWidth);
5051
      return normalize(floats);
5052
    };
5053
    const sum = (values, fallback) => {
5054
      if (values.length === 0) {
5055
        return fallback;
5056
      }
5057
      return foldr(values, (rest, v) => {
5058
        return Size.from(v).fold(constant(0), identity, identity) + rest;
5059
      }, 0);
5060
    };
5061
    const roundDown = (num, unit) => {
5062
      const floored = Math.floor(num);
5063
      return {
5064
        value: floored + unit,
5065
        remainder: num - floored
5066
      };
5067
    };
5068
    const add$3 = (value, amount) => {
5069
      return Size.from(value).fold(constant(value), px => {
5070
        return px + amount + 'px';
5071
      }, pc => {
5072
        return pc + amount + '%';
5073
      });
5074
    };
5075
    const normalize = values => {
5076
      if (values.length === 0) {
5077
        return values;
5078
      }
5079
      const scan = foldr(values, (rest, value) => {
5080
        const info = Size.from(value).fold(() => ({
5081
          value,
5082
          remainder: 0
5083
        }), num => roundDown(num, 'px'), num => ({
5084
          value: num + '%',
5085
          remainder: 0
5086
        }));
5087
        return {
5088
          output: [info.value].concat(rest.output),
5089
          remainder: rest.remainder + info.remainder
5090
        };
5091
      }, {
5092
        output: [],
5093
        remainder: 0
5094
      });
5095
      const r = scan.output;
5096
      return r.slice(0, r.length - 1).concat([add$3(r[r.length - 1], Math.round(scan.remainder))]);
5097
    };
5098
    const validate = Size.from;
5099
 
5100
    const redistributeToW = (newWidths, cells, unit) => {
5101
      each$2(cells, cell => {
5102
        const widths = newWidths.slice(cell.column, cell.colspan + cell.column);
5103
        const w = sum(widths, minWidth());
5104
        set$1(cell.element, 'width', w + unit);
5105
      });
5106
    };
5107
    const redistributeToColumns = (newWidths, columns, unit) => {
5108
      each$2(columns, (column, index) => {
5109
        const width = sum([newWidths[index]], minWidth());
5110
        set$1(column.element, 'width', width + unit);
5111
      });
5112
    };
5113
    const redistributeToH = (newHeights, rows, cells, unit) => {
5114
      each$2(cells, cell => {
5115
        const heights = newHeights.slice(cell.row, cell.rowspan + cell.row);
5116
        const h = sum(heights, minHeight());
5117
        set$1(cell.element, 'height', h + unit);
5118
      });
5119
      each$2(rows, (row, i) => {
5120
        set$1(row.element, 'height', newHeights[i]);
5121
      });
5122
    };
5123
    const getUnit = newSize => {
5124
      return validate(newSize).fold(constant('px'), constant('px'), constant('%'));
5125
    };
5126
    const redistribute = (table, optWidth, optHeight) => {
5127
      const warehouse = Warehouse.fromTable(table);
5128
      const rows = warehouse.all;
5129
      const cells = Warehouse.justCells(warehouse);
5130
      const columns = Warehouse.justColumns(warehouse);
5131
      optWidth.each(newWidth => {
5132
        const widthUnit = getUnit(newWidth);
5133
        const totalWidth = get$9(table);
5134
        const oldWidths = getRawWidths(warehouse, table);
5135
        const nuWidths = redistribute$1(oldWidths, totalWidth, newWidth);
5136
        if (Warehouse.hasColumns(warehouse)) {
5137
          redistributeToColumns(nuWidths, columns, widthUnit);
5138
        } else {
5139
          redistributeToW(nuWidths, cells, widthUnit);
5140
        }
5141
        set$1(table, 'width', newWidth);
5142
      });
5143
      optHeight.each(newHeight => {
5144
        const hUnit = getUnit(newHeight);
5145
        const totalHeight = get$8(table);
5146
        const oldHeights = getRawHeights(warehouse, table, height);
5147
        const nuHeights = redistribute$1(oldHeights, totalHeight, newHeight);
5148
        redistributeToH(nuHeights, rows, cells, hUnit);
5149
        set$1(table, 'height', newHeight);
5150
      });
5151
    };
5152
    const isPercentSizing = isPercentSizing$1;
5153
    const isPixelSizing = isPixelSizing$1;
5154
    const isNoneSizing = isNoneSizing$1;
5155
 
5156
    const cleanupLegacyAttributes = element => {
5157
      remove$7(element, 'width');
5158
    };
5159
    const convertToPercentSize = table => {
5160
      const newWidth = getPercentTableWidth(table);
5161
      redistribute(table, Optional.some(newWidth), Optional.none());
5162
      cleanupLegacyAttributes(table);
5163
    };
5164
    const convertToPixelSize = table => {
5165
      const newWidth = getPixelTableWidth(table);
5166
      redistribute(table, Optional.some(newWidth), Optional.none());
5167
      cleanupLegacyAttributes(table);
5168
    };
5169
    const convertToNoneSize = table => {
5170
      remove$5(table, 'width');
5171
      const columns = columns$1(table);
5172
      const rowElements = columns.length > 0 ? columns : cells$1(table);
5173
      each$2(rowElements, cell => {
5174
        remove$5(cell, 'width');
5175
        cleanupLegacyAttributes(cell);
5176
      });
5177
      cleanupLegacyAttributes(table);
5178
    };
5179
 
5180
    const DefaultRenderOptions = {
5181
      styles: {
5182
        'border-collapse': 'collapse',
5183
        'width': '100%'
5184
      },
5185
      attributes: { border: '1' },
5186
      colGroups: false
5187
    };
5188
    const tableHeaderCell = () => SugarElement.fromTag('th');
5189
    const tableCell = () => SugarElement.fromTag('td');
5190
    const tableColumn = () => SugarElement.fromTag('col');
5191
    const createRow = (columns, rowHeaders, columnHeaders, rowIndex) => {
5192
      const tr = SugarElement.fromTag('tr');
5193
      for (let j = 0; j < columns; j++) {
5194
        const td = rowIndex < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell();
5195
        if (j < columnHeaders) {
5196
          set$2(td, 'scope', 'row');
5197
        }
5198
        if (rowIndex < rowHeaders) {
5199
          set$2(td, 'scope', 'col');
5200
        }
5201
        append$1(td, SugarElement.fromTag('br'));
5202
        append$1(tr, td);
5203
      }
5204
      return tr;
5205
    };
5206
    const createGroupRow = columns => {
5207
      const columnGroup = SugarElement.fromTag('colgroup');
5208
      range$1(columns, () => append$1(columnGroup, tableColumn()));
5209
      return columnGroup;
5210
    };
5211
    const createRows = (rows, columns, rowHeaders, columnHeaders) => range$1(rows, r => createRow(columns, rowHeaders, columnHeaders, r));
5212
    const render = (rows, columns, rowHeaders, columnHeaders, headerType, renderOpts = DefaultRenderOptions) => {
5213
      const table = SugarElement.fromTag('table');
5214
      const rowHeadersGoInThead = headerType !== 'cells';
5215
      setAll(table, renderOpts.styles);
5216
      setAll$1(table, renderOpts.attributes);
5217
      if (renderOpts.colGroups) {
5218
        append$1(table, createGroupRow(columns));
5219
      }
5220
      const actualRowHeaders = Math.min(rows, rowHeaders);
5221
      if (rowHeadersGoInThead && rowHeaders > 0) {
5222
        const thead = SugarElement.fromTag('thead');
5223
        append$1(table, thead);
5224
        const theadRowHeaders = headerType === 'sectionCells' ? actualRowHeaders : 0;
5225
        const theadRows = createRows(rowHeaders, columns, theadRowHeaders, columnHeaders);
5226
        append(thead, theadRows);
5227
      }
5228
      const tbody = SugarElement.fromTag('tbody');
5229
      append$1(table, tbody);
5230
      const numRows = rowHeadersGoInThead ? rows - actualRowHeaders : rows;
5231
      const numRowHeaders = rowHeadersGoInThead ? 0 : rowHeaders;
5232
      const tbodyRows = createRows(numRows, columns, numRowHeaders, columnHeaders);
5233
      append(tbody, tbodyRows);
5234
      return table;
5235
    };
5236
 
5237
    const get$4 = element => element.dom.innerHTML;
5238
    const getOuter = element => {
5239
      const container = SugarElement.fromTag('div');
5240
      const clone = SugarElement.fromDom(element.dom.cloneNode(true));
5241
      append$1(container, clone);
5242
      return get$4(container);
5243
    };
5244
 
5245
    const placeCaretInCell = (editor, cell) => {
5246
      editor.selection.select(cell.dom, true);
5247
      editor.selection.collapse(true);
5248
    };
5249
    const selectFirstCellInTable = (editor, tableElm) => {
5250
      descendant(tableElm, 'td,th').each(curry(placeCaretInCell, editor));
5251
    };
5252
    const fireEvents = (editor, table) => {
5253
      each$2(descendants(table, 'tr'), row => {
5254
        fireNewRow(editor, row.dom);
5255
        each$2(descendants(row, 'th,td'), cell => {
5256
          fireNewCell(editor, cell.dom);
5257
        });
5258
      });
5259
    };
5260
    const isPercentage = width => isString(width) && width.indexOf('%') !== -1;
5261
    const insert = (editor, columns, rows, colHeaders, rowHeaders) => {
5262
      const defaultStyles = getTableDefaultStyles(editor);
5263
      const options = {
5264
        styles: defaultStyles,
5265
        attributes: getTableDefaultAttributes(editor),
5266
        colGroups: tableUseColumnGroup(editor)
5267
      };
5268
      editor.undoManager.ignore(() => {
5269
        const table = render(rows, columns, rowHeaders, colHeaders, getTableHeaderType(editor), options);
5270
        set$2(table, 'data-mce-id', '__mce');
5271
        const html = getOuter(table);
5272
        editor.insertContent(html);
5273
        editor.addVisual();
5274
      });
5275
      return descendant(getBody(editor), 'table[data-mce-id="__mce"]').map(table => {
5276
        if (isTablePixelsForced(editor)) {
5277
          convertToPixelSize(table);
5278
        } else if (isTableResponsiveForced(editor)) {
5279
          convertToNoneSize(table);
5280
        } else if (isTablePercentagesForced(editor) || isPercentage(defaultStyles.width)) {
5281
          convertToPercentSize(table);
5282
        }
5283
        removeDataStyle(table);
5284
        remove$7(table, 'data-mce-id');
5285
        fireEvents(editor, table);
5286
        selectFirstCellInTable(editor, table);
5287
        return table.dom;
5288
      }).getOrNull();
5289
    };
5290
    const insertTable = (editor, rows, columns, options = {}) => {
5291
      const checkInput = val => isNumber(val) && val > 0;
5292
      if (checkInput(rows) && checkInput(columns)) {
5293
        const headerRows = options.headerRows || 0;
5294
        const headerColumns = options.headerColumns || 0;
5295
        return insert(editor, columns, rows, headerColumns, headerRows);
5296
      } else {
5297
        console.error('Invalid values for mceInsertTable - rows and columns values are required to insert a table.');
5298
        return null;
5299
      }
5300
    };
5301
 
5302
    var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard');
5303
 
5304
    const tableTypeBase = 'x-tinymce/dom-table-';
5305
    const tableTypeRow = tableTypeBase + 'rows';
5306
    const tableTypeColumn = tableTypeBase + 'columns';
5307
    const setData = items => {
5308
      const fakeClipboardItem = global.FakeClipboardItem(items);
5309
      global.write([fakeClipboardItem]);
5310
    };
5311
    const getData = type => {
5312
      var _a;
5313
      const items = (_a = global.read()) !== null && _a !== void 0 ? _a : [];
5314
      return findMap(items, item => Optional.from(item.getType(type)));
5315
    };
5316
    const clearData = type => {
5317
      if (getData(type).isSome()) {
5318
        global.clear();
5319
      }
5320
    };
5321
    const setRows = rowsOpt => {
5322
      rowsOpt.fold(clearRows, rows => setData({ [tableTypeRow]: rows }));
5323
    };
5324
    const getRows = () => getData(tableTypeRow);
5325
    const clearRows = () => clearData(tableTypeRow);
5326
    const setColumns = columnsOpt => {
5327
      columnsOpt.fold(clearColumns, columns => setData({ [tableTypeColumn]: columns }));
5328
    };
5329
    const getColumns = () => getData(tableTypeColumn);
5330
    const clearColumns = () => clearData(tableTypeColumn);
5331
 
5332
    const getSelectionStartCellOrCaption = editor => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
5333
    const getSelectionStartCell = editor => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
5334
    const registerCommands = (editor, actions) => {
5335
      const isRoot = getIsRoot(editor);
5336
      const eraseTable = () => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
5337
        table(cellOrCaption, isRoot).filter(not(isRoot)).each(table => {
5338
          const cursor = SugarElement.fromText('');
5339
          after$5(table, cursor);
5340
          remove$6(table);
5341
          if (editor.dom.isEmpty(editor.getBody())) {
5342
            editor.setContent('');
5343
            editor.selection.setCursorLocation();
5344
          } else {
5345
            const rng = editor.dom.createRng();
5346
            rng.setStart(cursor.dom, 0);
5347
            rng.setEnd(cursor.dom, 0);
5348
            editor.selection.setRng(rng);
5349
            editor.nodeChanged();
5350
          }
5351
        });
5352
      });
5353
      const setSizingMode = sizing => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
5354
        const isForcedSizing = isTableResponsiveForced(editor) || isTablePixelsForced(editor) || isTablePercentagesForced(editor);
5355
        if (!isForcedSizing) {
5356
          table(cellOrCaption, isRoot).each(table => {
5357
            if (sizing === 'relative' && !isPercentSizing(table)) {
5358
              convertToPercentSize(table);
5359
            } else if (sizing === 'fixed' && !isPixelSizing(table)) {
5360
              convertToPixelSize(table);
5361
            } else if (sizing === 'responsive' && !isNoneSizing(table)) {
5362
              convertToNoneSize(table);
5363
            }
5364
            removeDataStyle(table);
5365
            fireTableModified(editor, table.dom, structureModified);
5366
          });
5367
        }
5368
      });
5369
      const getTableFromCell = cell => table(cell, isRoot);
5370
      const performActionOnSelection = action => getSelectionStartCell(editor).bind(cell => getTableFromCell(cell).map(table => action(table, cell)));
5371
      const toggleTableClass = (_ui, clazz) => {
5372
        performActionOnSelection(table => {
5373
          editor.formatter.toggle('tableclass', { value: clazz }, table.dom);
5374
          fireTableModified(editor, table.dom, styleModified);
5375
        });
5376
      };
5377
      const toggleTableCellClass = (_ui, clazz) => {
5378
        performActionOnSelection(table => {
5379
          const selectedCells = getCellsFromSelection(editor);
5380
          const allHaveClass = forall(selectedCells, cell => editor.formatter.match('tablecellclass', { value: clazz }, cell.dom));
5381
          const formatterAction = allHaveClass ? editor.formatter.remove : editor.formatter.apply;
5382
          each$2(selectedCells, cell => formatterAction('tablecellclass', { value: clazz }, cell.dom));
5383
          fireTableModified(editor, table.dom, styleModified);
5384
        });
5385
      };
5386
      const toggleCaption = () => {
5387
        getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
5388
          table(cellOrCaption, isRoot).each(table => {
5389
            child(table, 'caption').fold(() => {
5390
              const caption = SugarElement.fromTag('caption');
5391
              append$1(caption, SugarElement.fromText('Caption'));
5392
              appendAt(table, caption, 0);
5393
              editor.selection.setCursorLocation(caption.dom, 0);
5394
            }, caption => {
5395
              if (isTag('caption')(cellOrCaption)) {
5396
                one('td', table).each(td => editor.selection.setCursorLocation(td.dom, 0));
5397
              }
5398
              remove$6(caption);
5399
            });
5400
            fireTableModified(editor, table.dom, structureModified);
5401
          });
5402
        });
5403
      };
5404
      const postExecute = _data => {
5405
        editor.focus();
5406
      };
5407
      const actOnSelection = (execute, noEvents = false) => performActionOnSelection((table, startCell) => {
5408
        const targets = forMenu(getCellsFromSelection(editor), table, startCell);
5409
        execute(table, targets, noEvents).each(postExecute);
5410
      });
5411
      const copyRowSelection = () => performActionOnSelection((table, startCell) => {
5412
        const targets = forMenu(getCellsFromSelection(editor), table, startCell);
5413
        const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), Optional.none());
5414
        return copyRows(table, targets, generators);
5415
      });
5416
      const copyColSelection = () => performActionOnSelection((table, startCell) => {
5417
        const targets = forMenu(getCellsFromSelection(editor), table, startCell);
5418
        return copyCols(table, targets);
5419
      });
5420
      const pasteOnSelection = (execute, getRows) => getRows().each(rows => {
5421
        const clonedRows = map$1(rows, row => deep(row));
5422
        performActionOnSelection((table, startCell) => {
5423
          const generators = paste$1(SugarElement.fromDom(editor.getDoc()));
5424
          const targets = pasteRows(getCellsFromSelection(editor), startCell, clonedRows, generators);
5425
          execute(table, targets).each(postExecute);
5426
        });
5427
      });
5428
      const actOnType = getAction => (_ui, args) => get$c(args, 'type').each(type => {
5429
        actOnSelection(getAction(type), args.no_events);
5430
      });
5431
      each$1({
5432
        mceTableSplitCells: () => actOnSelection(actions.unmergeCells),
5433
        mceTableMergeCells: () => actOnSelection(actions.mergeCells),
5434
        mceTableInsertRowBefore: () => actOnSelection(actions.insertRowsBefore),
5435
        mceTableInsertRowAfter: () => actOnSelection(actions.insertRowsAfter),
5436
        mceTableInsertColBefore: () => actOnSelection(actions.insertColumnsBefore),
5437
        mceTableInsertColAfter: () => actOnSelection(actions.insertColumnsAfter),
5438
        mceTableDeleteCol: () => actOnSelection(actions.deleteColumn),
5439
        mceTableDeleteRow: () => actOnSelection(actions.deleteRow),
5440
        mceTableCutCol: () => copyColSelection().each(selection => {
5441
          setColumns(selection);
5442
          actOnSelection(actions.deleteColumn);
5443
        }),
5444
        mceTableCutRow: () => copyRowSelection().each(selection => {
5445
          setRows(selection);
5446
          actOnSelection(actions.deleteRow);
5447
        }),
5448
        mceTableCopyCol: () => copyColSelection().each(selection => setColumns(selection)),
5449
        mceTableCopyRow: () => copyRowSelection().each(selection => setRows(selection)),
5450
        mceTablePasteColBefore: () => pasteOnSelection(actions.pasteColsBefore, getColumns),
5451
        mceTablePasteColAfter: () => pasteOnSelection(actions.pasteColsAfter, getColumns),
5452
        mceTablePasteRowBefore: () => pasteOnSelection(actions.pasteRowsBefore, getRows),
5453
        mceTablePasteRowAfter: () => pasteOnSelection(actions.pasteRowsAfter, getRows),
5454
        mceTableDelete: eraseTable,
5455
        mceTableCellToggleClass: toggleTableCellClass,
5456
        mceTableToggleClass: toggleTableClass,
5457
        mceTableToggleCaption: toggleCaption,
5458
        mceTableSizingMode: (_ui, sizing) => setSizingMode(sizing),
5459
        mceTableCellType: actOnType(type => type === 'th' ? actions.makeCellsHeader : actions.unmakeCellsHeader),
5460
        mceTableColType: actOnType(type => type === 'th' ? actions.makeColumnsHeader : actions.unmakeColumnsHeader),
5461
        mceTableRowType: actOnType(type => {
5462
          switch (type) {
5463
          case 'header':
5464
            return actions.makeRowsHeader;
5465
          case 'footer':
5466
            return actions.makeRowsFooter;
5467
          default:
5468
            return actions.makeRowsBody;
5469
          }
5470
        })
5471
      }, (func, name) => editor.addCommand(name, func));
5472
      editor.addCommand('mceInsertTable', (_ui, args) => {
5473
        insertTable(editor, args.rows, args.columns, args.options);
5474
      });
5475
      editor.addCommand('mceTableApplyCellStyle', (_ui, args) => {
5476
        const getFormatName = style => 'tablecell' + style.toLowerCase().replace('-', '');
5477
        if (!isObject(args)) {
5478
          return;
5479
        }
5480
        const cells = filter$2(getCellsFromSelection(editor), isInEditableContext$1);
5481
        if (cells.length === 0) {
5482
          return;
5483
        }
5484
        const validArgs = filter$1(args, (value, style) => editor.formatter.has(getFormatName(style)) && isString(value));
5485
        if (isEmpty(validArgs)) {
5486
          return;
5487
        }
5488
        each$1(validArgs, (value, style) => {
5489
          const formatName = getFormatName(style);
5490
          each$2(cells, cell => {
5491
            if (value === '') {
5492
              editor.formatter.remove(formatName, { value: null }, cell.dom, true);
5493
            } else {
5494
              editor.formatter.apply(formatName, { value }, cell.dom);
5495
            }
5496
          });
5497
        });
5498
        getTableFromCell(cells[0]).each(table => fireTableModified(editor, table.dom, styleModified));
5499
      });
5500
    };
5501
 
5502
    const registerQueryCommands = (editor, actions) => {
5503
      const isRoot = getIsRoot(editor);
5504
      const lookupOnSelection = action => getSelectionCell(getSelectionStart(editor)).bind(cell => table(cell, isRoot).map(table => {
5505
        const targets = forMenu(getCellsFromSelection(editor), table, cell);
5506
        return action(table, targets);
5507
      })).getOr('');
5508
      each$1({
5509
        mceTableRowType: () => lookupOnSelection(actions.getTableRowType),
5510
        mceTableCellType: () => lookupOnSelection(actions.getTableCellType),
5511
        mceTableColType: () => lookupOnSelection(actions.getTableColType)
5512
      }, (func, name) => editor.addQueryValueHandler(name, func));
5513
    };
5514
 
5515
    const adt$4 = Adt.generate([
5516
      { before: ['element'] },
5517
      {
5518
        on: [
5519
          'element',
5520
          'offset'
5521
        ]
5522
      },
5523
      { after: ['element'] }
5524
    ]);
5525
    const cata$1 = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
5526
    const getStart$1 = situ => situ.fold(identity, identity, identity);
5527
    const before$2 = adt$4.before;
5528
    const on = adt$4.on;
5529
    const after$3 = adt$4.after;
5530
    const Situ = {
5531
      before: before$2,
5532
      on,
5533
      after: after$3,
5534
      cata: cata$1,
5535
      getStart: getStart$1
5536
    };
5537
 
5538
    const create$4 = (selection, kill) => ({
5539
      selection,
5540
      kill
5541
    });
5542
    const Response = { create: create$4 };
5543
 
5544
    const selectNode = (win, element) => {
5545
      const rng = win.document.createRange();
5546
      rng.selectNode(element.dom);
5547
      return rng;
5548
    };
5549
    const selectNodeContents = (win, element) => {
5550
      const rng = win.document.createRange();
5551
      selectNodeContentsUsing(rng, element);
5552
      return rng;
5553
    };
5554
    const selectNodeContentsUsing = (rng, element) => rng.selectNodeContents(element.dom);
5555
    const setStart = (rng, situ) => {
5556
      situ.fold(e => {
5557
        rng.setStartBefore(e.dom);
5558
      }, (e, o) => {
5559
        rng.setStart(e.dom, o);
5560
      }, e => {
5561
        rng.setStartAfter(e.dom);
5562
      });
5563
    };
5564
    const setFinish = (rng, situ) => {
5565
      situ.fold(e => {
5566
        rng.setEndBefore(e.dom);
5567
      }, (e, o) => {
5568
        rng.setEnd(e.dom, o);
5569
      }, e => {
5570
        rng.setEndAfter(e.dom);
5571
      });
5572
    };
5573
    const relativeToNative = (win, startSitu, finishSitu) => {
5574
      const range = win.document.createRange();
5575
      setStart(range, startSitu);
5576
      setFinish(range, finishSitu);
5577
      return range;
5578
    };
5579
    const exactToNative = (win, start, soffset, finish, foffset) => {
5580
      const rng = win.document.createRange();
5581
      rng.setStart(start.dom, soffset);
5582
      rng.setEnd(finish.dom, foffset);
5583
      return rng;
5584
    };
5585
    const toRect = rect => ({
5586
      left: rect.left,
5587
      top: rect.top,
5588
      right: rect.right,
5589
      bottom: rect.bottom,
5590
      width: rect.width,
5591
      height: rect.height
5592
    });
5593
    const getFirstRect$1 = rng => {
5594
      const rects = rng.getClientRects();
5595
      const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
5596
      return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
5597
    };
5598
 
5599
    const adt$3 = Adt.generate([
5600
      {
5601
        ltr: [
5602
          'start',
5603
          'soffset',
5604
          'finish',
5605
          'foffset'
5606
        ]
5607
      },
5608
      {
5609
        rtl: [
5610
          'start',
5611
          'soffset',
5612
          'finish',
5613
          'foffset'
5614
        ]
5615
      }
5616
    ]);
5617
    const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
5618
    const getRanges = (win, selection) => selection.match({
5619
      domRange: rng => {
5620
        return {
5621
          ltr: constant(rng),
5622
          rtl: Optional.none
5623
        };
5624
      },
5625
      relative: (startSitu, finishSitu) => {
5626
        return {
5627
          ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
5628
          rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
5629
        };
5630
      },
5631
      exact: (start, soffset, finish, foffset) => {
5632
        return {
5633
          ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
5634
          rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
5635
        };
5636
      }
5637
    });
5638
    const doDiagnose = (win, ranges) => {
5639
      const rng = ranges.ltr();
5640
      if (rng.collapsed) {
5641
        const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
5642
        return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
5643
      } else {
5644
        return fromRange(win, adt$3.ltr, rng);
5645
      }
5646
    };
5647
    const diagnose = (win, selection) => {
5648
      const ranges = getRanges(win, selection);
5649
      return doDiagnose(win, ranges);
5650
    };
5651
    const asLtrRange = (win, selection) => {
5652
      const diagnosis = diagnose(win, selection);
5653
      return diagnosis.match({
5654
        ltr: (start, soffset, finish, foffset) => {
5655
          const rng = win.document.createRange();
5656
          rng.setStart(start.dom, soffset);
5657
          rng.setEnd(finish.dom, foffset);
5658
          return rng;
5659
        },
5660
        rtl: (start, soffset, finish, foffset) => {
5661
          const rng = win.document.createRange();
5662
          rng.setStart(finish.dom, foffset);
5663
          rng.setEnd(start.dom, soffset);
5664
          return rng;
5665
        }
5666
      });
5667
    };
5668
    adt$3.ltr;
5669
    adt$3.rtl;
5670
 
5671
    const create$3 = (start, soffset, finish, foffset) => ({
5672
      start,
5673
      soffset,
5674
      finish,
5675
      foffset
5676
    });
5677
    const SimRange = { create: create$3 };
5678
 
5679
    const create$2 = (start, soffset, finish, foffset) => {
5680
      return {
5681
        start: Situ.on(start, soffset),
5682
        finish: Situ.on(finish, foffset)
5683
      };
5684
    };
5685
    const Situs = { create: create$2 };
5686
 
5687
    const convertToRange = (win, selection) => {
5688
      const rng = asLtrRange(win, selection);
5689
      return SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset);
5690
    };
5691
    const makeSitus = Situs.create;
5692
 
5693
    const sync = (container, isRoot, start, soffset, finish, foffset, selectRange) => {
5694
      if (!(eq$1(start, finish) && soffset === foffset)) {
5695
        return closest$1(start, 'td,th', isRoot).bind(s => {
5696
          return closest$1(finish, 'td,th', isRoot).bind(f => {
5697
            return detect(container, isRoot, s, f, selectRange);
5698
          });
5699
        });
5700
      } else {
5701
        return Optional.none();
5702
      }
5703
    };
5704
    const detect = (container, isRoot, start, finish, selectRange) => {
5705
      if (!eq$1(start, finish)) {
5706
        return identify(start, finish, isRoot).bind(cellSel => {
5707
          const boxes = cellSel.boxes.getOr([]);
5708
          if (boxes.length > 1) {
5709
            selectRange(container, boxes, cellSel.start, cellSel.finish);
5710
            return Optional.some(Response.create(Optional.some(makeSitus(start, 0, start, getEnd(start))), true));
5711
          } else {
5712
            return Optional.none();
5713
          }
5714
        });
5715
      } else {
5716
        return Optional.none();
5717
      }
5718
    };
5719
    const update = (rows, columns, container, selected, annotations) => {
5720
      const updateSelection = newSels => {
5721
        annotations.clearBeforeUpdate(container);
5722
        annotations.selectRange(container, newSels.boxes, newSels.start, newSels.finish);
5723
        return newSels.boxes;
5724
      };
5725
      return shiftSelection(selected, rows, columns, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(updateSelection);
5726
    };
5727
 
5728
    const traverse = (item, mode) => ({
5729
      item,
5730
      mode
5731
    });
5732
    const backtrack = (universe, item, _direction, transition = sidestep) => {
5733
      return universe.property().parent(item).map(p => {
5734
        return traverse(p, transition);
5735
      });
5736
    };
5737
    const sidestep = (universe, item, direction, transition = advance) => {
5738
      return direction.sibling(universe, item).map(p => {
5739
        return traverse(p, transition);
5740
      });
5741
    };
5742
    const advance = (universe, item, direction, transition = advance) => {
5743
      const children = universe.property().children(item);
5744
      const result = direction.first(children);
5745
      return result.map(r => {
5746
        return traverse(r, transition);
5747
      });
5748
    };
5749
    const successors = [
5750
      {
5751
        current: backtrack,
5752
        next: sidestep,
5753
        fallback: Optional.none()
5754
      },
5755
      {
5756
        current: sidestep,
5757
        next: advance,
5758
        fallback: Optional.some(backtrack)
5759
      },
5760
      {
5761
        current: advance,
5762
        next: advance,
5763
        fallback: Optional.some(sidestep)
5764
      }
5765
    ];
5766
    const go = (universe, item, mode, direction, rules = successors) => {
5767
      const ruleOpt = find$1(rules, succ => {
5768
        return succ.current === mode;
5769
      });
5770
      return ruleOpt.bind(rule => {
5771
        return rule.current(universe, item, direction, rule.next).orThunk(() => {
5772
          return rule.fallback.bind(fb => {
5773
            return go(universe, item, fb, direction);
5774
          });
5775
        });
5776
      });
5777
    };
5778
 
5779
    const left$1 = () => {
5780
      const sibling = (universe, item) => {
5781
        return universe.query().prevSibling(item);
5782
      };
5783
      const first = children => {
5784
        return children.length > 0 ? Optional.some(children[children.length - 1]) : Optional.none();
5785
      };
5786
      return {
5787
        sibling,
5788
        first
5789
      };
5790
    };
5791
    const right$1 = () => {
5792
      const sibling = (universe, item) => {
5793
        return universe.query().nextSibling(item);
5794
      };
5795
      const first = children => {
5796
        return children.length > 0 ? Optional.some(children[0]) : Optional.none();
5797
      };
5798
      return {
5799
        sibling,
5800
        first
5801
      };
5802
    };
5803
    const Walkers = {
5804
      left: left$1,
5805
      right: right$1
5806
    };
5807
 
5808
    const hone = (universe, item, predicate, mode, direction, isRoot) => {
5809
      const next = go(universe, item, mode, direction);
5810
      return next.bind(n => {
5811
        if (isRoot(n.item)) {
5812
          return Optional.none();
5813
        } else {
5814
          return predicate(n.item) ? Optional.some(n.item) : hone(universe, n.item, predicate, n.mode, direction, isRoot);
5815
        }
5816
      });
5817
    };
5818
    const left = (universe, item, predicate, isRoot) => {
5819
      return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot);
5820
    };
5821
    const right = (universe, item, predicate, isRoot) => {
5822
      return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot);
5823
    };
5824
 
5825
    const isLeaf = universe => element => universe.property().children(element).length === 0;
5826
    const before$1 = (universe, item, isRoot) => {
5827
      return seekLeft$1(universe, item, isLeaf(universe), isRoot);
5828
    };
5829
    const after$2 = (universe, item, isRoot) => {
5830
      return seekRight$1(universe, item, isLeaf(universe), isRoot);
5831
    };
5832
    const seekLeft$1 = left;
5833
    const seekRight$1 = right;
5834
 
5835
    const universe = DomUniverse();
5836
    const before = (element, isRoot) => {
5837
      return before$1(universe, element, isRoot);
5838
    };
5839
    const after$1 = (element, isRoot) => {
5840
      return after$2(universe, element, isRoot);
5841
    };
5842
    const seekLeft = (element, predicate, isRoot) => {
5843
      return seekLeft$1(universe, element, predicate, isRoot);
5844
    };
5845
    const seekRight = (element, predicate, isRoot) => {
5846
      return seekRight$1(universe, element, predicate, isRoot);
5847
    };
5848
 
5849
    const ancestor = (scope, predicate, isRoot) => ancestor$2(scope, predicate, isRoot).isSome();
5850
 
5851
    const adt$2 = Adt.generate([
5852
      { none: ['message'] },
5853
      { success: [] },
5854
      { failedUp: ['cell'] },
5855
      { failedDown: ['cell'] }
5856
    ]);
5857
    const isOverlapping = (bridge, before, after) => {
5858
      const beforeBounds = bridge.getRect(before);
5859
      const afterBounds = bridge.getRect(after);
5860
      return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right;
5861
    };
5862
    const isRow = elem => {
5863
      return closest$1(elem, 'tr');
5864
    };
5865
    const verify = (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) => {
5866
      return closest$1(after, 'td,th', isRoot).bind(afterCell => {
5867
        return closest$1(before, 'td,th', isRoot).map(beforeCell => {
5868
          if (!eq$1(afterCell, beforeCell)) {
5869
            return sharedOne(isRow, [
5870
              afterCell,
5871
              beforeCell
5872
            ]).fold(() => {
5873
              return isOverlapping(bridge, beforeCell, afterCell) ? adt$2.success() : failure(beforeCell);
5874
            }, _sharedRow => {
5875
              return failure(beforeCell);
5876
            });
5877
          } else {
5878
            return eq$1(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$2.none('in same cell');
5879
          }
5880
        });
5881
      }).getOr(adt$2.none('default'));
5882
    };
5883
    const cata = (subject, onNone, onSuccess, onFailedUp, onFailedDown) => {
5884
      return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown);
5885
    };
5886
    const BeforeAfter = {
5887
      ...adt$2,
5888
      verify,
5889
      cata
5890
    };
5891
 
5892
    const inParent = (parent, children, element, index) => ({
5893
      parent,
5894
      children,
5895
      element,
5896
      index
5897
    });
5898
    const indexInParent = element => parent(element).bind(parent => {
5899
      const children = children$2(parent);
5900
      return indexOf(children, element).map(index => inParent(parent, children, element, index));
5901
    });
5902
    const indexOf = (elements, element) => findIndex(elements, curry(eq$1, element));
5903
 
5904
    const isBr = isTag('br');
5905
    const gatherer = (cand, gather, isRoot) => {
5906
      return gather(cand, isRoot).bind(target => {
5907
        return isText(target) && get$6(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Optional.some(target);
5908
      });
5909
    };
5910
    const handleBr = (isRoot, element, direction) => {
5911
      return direction.traverse(element).orThunk(() => {
5912
        return gatherer(element, direction.gather, isRoot);
5913
      }).map(direction.relative);
5914
    };
5915
    const findBr = (element, offset) => {
5916
      return child$2(element, offset).filter(isBr).orThunk(() => {
5917
        return child$2(element, offset - 1).filter(isBr);
5918
      });
5919
    };
5920
    const handleParent = (isRoot, element, offset, direction) => {
5921
      return findBr(element, offset).bind(br => {
5922
        return direction.traverse(br).fold(() => {
5923
          return gatherer(br, direction.gather, isRoot).map(direction.relative);
5924
        }, adjacent => {
5925
          return indexInParent(adjacent).map(info => {
5926
            return Situ.on(info.parent, info.index);
5927
          });
5928
        });
5929
      });
5930
    };
5931
    const tryBr = (isRoot, element, offset, direction) => {
5932
      const target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction);
5933
      return target.map(tgt => {
5934
        return {
5935
          start: tgt,
5936
          finish: tgt
5937
        };
5938
      });
5939
    };
5940
    const process = analysis => {
5941
      return BeforeAfter.cata(analysis, _message => {
5942
        return Optional.none();
5943
      }, () => {
5944
        return Optional.none();
5945
      }, cell => {
5946
        return Optional.some(point(cell, 0));
5947
      }, cell => {
5948
        return Optional.some(point(cell, getEnd(cell)));
5949
      });
5950
    };
5951
 
5952
    const moveDown = (caret, amount) => {
5953
      return {
5954
        left: caret.left,
5955
        top: caret.top + amount,
5956
        right: caret.right,
5957
        bottom: caret.bottom + amount
5958
      };
5959
    };
5960
    const moveUp = (caret, amount) => {
5961
      return {
5962
        left: caret.left,
5963
        top: caret.top - amount,
5964
        right: caret.right,
5965
        bottom: caret.bottom - amount
5966
      };
5967
    };
5968
    const translate = (caret, xDelta, yDelta) => {
5969
      return {
5970
        left: caret.left + xDelta,
5971
        top: caret.top + yDelta,
5972
        right: caret.right + xDelta,
5973
        bottom: caret.bottom + yDelta
5974
      };
5975
    };
5976
    const getTop = caret => {
5977
      return caret.top;
5978
    };
5979
    const getBottom = caret => {
5980
      return caret.bottom;
5981
    };
5982
 
5983
    const getPartialBox = (bridge, element, offset) => {
5984
      if (offset >= 0 && offset < getEnd(element)) {
5985
        return bridge.getRangedRect(element, offset, element, offset + 1);
5986
      } else if (offset > 0) {
5987
        return bridge.getRangedRect(element, offset - 1, element, offset);
5988
      }
5989
      return Optional.none();
5990
    };
5991
    const toCaret = rect => ({
5992
      left: rect.left,
5993
      top: rect.top,
5994
      right: rect.right,
5995
      bottom: rect.bottom
5996
    });
5997
    const getElemBox = (bridge, element) => {
5998
      return Optional.some(bridge.getRect(element));
5999
    };
6000
    const getBoxAt = (bridge, element, offset) => {
6001
      if (isElement(element)) {
6002
        return getElemBox(bridge, element).map(toCaret);
6003
      } else if (isText(element)) {
6004
        return getPartialBox(bridge, element, offset).map(toCaret);
6005
      } else {
6006
        return Optional.none();
6007
      }
6008
    };
6009
    const getEntireBox = (bridge, element) => {
6010
      if (isElement(element)) {
6011
        return getElemBox(bridge, element).map(toCaret);
6012
      } else if (isText(element)) {
6013
        return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret);
6014
      } else {
6015
        return Optional.none();
6016
      }
6017
    };
6018
 
6019
    const JUMP_SIZE = 5;
6020
    const NUM_RETRIES = 100;
6021
    const adt$1 = Adt.generate([
6022
      { none: [] },
6023
      { retry: ['caret'] }
6024
    ]);
6025
    const isOutside = (caret, box) => {
6026
      return caret.left < box.left || Math.abs(box.right - caret.left) < 1 || caret.left > box.right;
6027
    };
6028
    const inOutsideBlock = (bridge, element, caret) => {
6029
      return closest$2(element, isBlock).fold(never, cell => {
6030
        return getEntireBox(bridge, cell).exists(box => {
6031
          return isOutside(caret, box);
6032
        });
6033
      });
6034
    };
6035
    const adjustDown = (bridge, element, guessBox, original, caret) => {
6036
      const lowerCaret = moveDown(caret, JUMP_SIZE);
6037
      if (Math.abs(guessBox.bottom - original.bottom) < 1) {
6038
        return adt$1.retry(lowerCaret);
6039
      } else if (guessBox.top > caret.bottom) {
6040
        return adt$1.retry(lowerCaret);
6041
      } else if (guessBox.top === caret.bottom) {
6042
        return adt$1.retry(moveDown(caret, 1));
6043
      } else {
6044
        return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(lowerCaret, JUMP_SIZE, 0)) : adt$1.none();
6045
      }
6046
    };
6047
    const adjustUp = (bridge, element, guessBox, original, caret) => {
6048
      const higherCaret = moveUp(caret, JUMP_SIZE);
6049
      if (Math.abs(guessBox.top - original.top) < 1) {
6050
        return adt$1.retry(higherCaret);
6051
      } else if (guessBox.bottom < caret.top) {
6052
        return adt$1.retry(higherCaret);
6053
      } else if (guessBox.bottom === caret.top) {
6054
        return adt$1.retry(moveUp(caret, 1));
6055
      } else {
6056
        return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(higherCaret, JUMP_SIZE, 0)) : adt$1.none();
6057
      }
6058
    };
6059
    const upMovement = {
6060
      point: getTop,
6061
      adjuster: adjustUp,
6062
      move: moveUp,
6063
      gather: before
6064
    };
6065
    const downMovement = {
6066
      point: getBottom,
6067
      adjuster: adjustDown,
6068
      move: moveDown,
6069
      gather: after$1
6070
    };
6071
    const isAtTable = (bridge, x, y) => {
6072
      return bridge.elementFromPoint(x, y).filter(elm => {
6073
        return name(elm) === 'table';
6074
      }).isSome();
6075
    };
6076
    const adjustForTable = (bridge, movement, original, caret, numRetries) => {
6077
      return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries);
6078
    };
6079
    const adjustTil = (bridge, movement, original, caret, numRetries) => {
6080
      if (numRetries === 0) {
6081
        return Optional.some(caret);
6082
      }
6083
      if (isAtTable(bridge, caret.left, movement.point(caret))) {
6084
        return adjustForTable(bridge, movement, original, caret, numRetries - 1);
6085
      }
6086
      return bridge.situsFromPoint(caret.left, movement.point(caret)).bind(guess => {
6087
        return guess.start.fold(Optional.none, element => {
6088
          return getEntireBox(bridge, element).bind(guessBox => {
6089
            return movement.adjuster(bridge, element, guessBox, original, caret).fold(Optional.none, newCaret => {
6090
              return adjustTil(bridge, movement, original, newCaret, numRetries - 1);
6091
            });
6092
          }).orThunk(() => {
6093
            return Optional.some(caret);
6094
          });
6095
        }, Optional.none);
6096
      });
6097
    };
6098
    const checkScroll = (movement, adjusted, bridge) => {
6099
      if (movement.point(adjusted) > bridge.getInnerHeight()) {
6100
        return Optional.some(movement.point(adjusted) - bridge.getInnerHeight());
6101
      } else if (movement.point(adjusted) < 0) {
6102
        return Optional.some(-movement.point(adjusted));
6103
      } else {
6104
        return Optional.none();
6105
      }
6106
    };
6107
    const retry = (movement, bridge, caret) => {
6108
      const moved = movement.move(caret, JUMP_SIZE);
6109
      const adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved);
6110
      return checkScroll(movement, adjusted, bridge).fold(() => {
6111
        return bridge.situsFromPoint(adjusted.left, movement.point(adjusted));
6112
      }, delta => {
6113
        bridge.scrollBy(0, delta);
6114
        return bridge.situsFromPoint(adjusted.left, movement.point(adjusted) - delta);
6115
      });
6116
    };
6117
    const Retries = {
6118
      tryUp: curry(retry, upMovement),
6119
      tryDown: curry(retry, downMovement),
6120
      getJumpSize: constant(JUMP_SIZE)
6121
    };
6122
 
6123
    const MAX_RETRIES = 20;
6124
    const findSpot = (bridge, isRoot, direction) => {
6125
      return bridge.getSelection().bind(sel => {
6126
        return tryBr(isRoot, sel.finish, sel.foffset, direction).fold(() => {
6127
          return Optional.some(point(sel.finish, sel.foffset));
6128
        }, brNeighbour => {
6129
          const range = bridge.fromSitus(brNeighbour);
6130
          const analysis = BeforeAfter.verify(bridge, sel.finish, sel.foffset, range.finish, range.foffset, direction.failure, isRoot);
6131
          return process(analysis);
6132
        });
6133
      });
6134
    };
6135
    const scan = (bridge, isRoot, element, offset, direction, numRetries) => {
6136
      if (numRetries === 0) {
6137
        return Optional.none();
6138
      }
6139
      return tryCursor(bridge, isRoot, element, offset, direction).bind(situs => {
6140
        const range = bridge.fromSitus(situs);
6141
        const analysis = BeforeAfter.verify(bridge, element, offset, range.finish, range.foffset, direction.failure, isRoot);
6142
        return BeforeAfter.cata(analysis, () => {
6143
          return Optional.none();
6144
        }, () => {
6145
          return Optional.some(situs);
6146
        }, cell => {
6147
          if (eq$1(element, cell) && offset === 0) {
6148
            return tryAgain(bridge, element, offset, moveUp, direction);
6149
          } else {
6150
            return scan(bridge, isRoot, cell, 0, direction, numRetries - 1);
6151
          }
6152
        }, cell => {
6153
          if (eq$1(element, cell) && offset === getEnd(cell)) {
6154
            return tryAgain(bridge, element, offset, moveDown, direction);
6155
          } else {
6156
            return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1);
6157
          }
6158
        });
6159
      });
6160
    };
6161
    const tryAgain = (bridge, element, offset, move, direction) => {
6162
      return getBoxAt(bridge, element, offset).bind(box => {
6163
        return tryAt(bridge, direction, move(box, Retries.getJumpSize()));
6164
      });
6165
    };
6166
    const tryAt = (bridge, direction, box) => {
6167
      const browser = detect$2().browser;
6168
      if (browser.isChromium() || browser.isSafari() || browser.isFirefox()) {
6169
        return direction.retry(bridge, box);
6170
      } else {
6171
        return Optional.none();
6172
      }
6173
    };
6174
    const tryCursor = (bridge, isRoot, element, offset, direction) => {
6175
      return getBoxAt(bridge, element, offset).bind(box => {
6176
        return tryAt(bridge, direction, box);
6177
      });
6178
    };
6179
    const handle$1 = (bridge, isRoot, direction) => {
6180
      return findSpot(bridge, isRoot, direction).bind(spot => {
6181
        return scan(bridge, isRoot, spot.element, spot.offset, direction, MAX_RETRIES).map(bridge.fromSitus);
6182
      });
6183
    };
6184
 
6185
    const inSameTable = (elem, table) => {
6186
      return ancestor(elem, e => {
6187
        return parent(e).exists(p => {
6188
          return eq$1(p, table);
6189
        });
6190
      });
6191
    };
6192
    const simulate = (bridge, isRoot, direction, initial, anchor) => {
6193
      return closest$1(initial, 'td,th', isRoot).bind(start => {
6194
        return closest$1(start, 'table', isRoot).bind(table => {
6195
          if (!inSameTable(anchor, table)) {
6196
            return Optional.none();
6197
          }
6198
          return handle$1(bridge, isRoot, direction).bind(range => {
6199
            return closest$1(range.finish, 'td,th', isRoot).map(finish => {
6200
              return {
6201
                start,
6202
                finish,
6203
                range
6204
              };
6205
            });
6206
          });
6207
        });
6208
      });
6209
    };
6210
    const navigate = (bridge, isRoot, direction, initial, anchor, precheck) => {
6211
      return precheck(initial, isRoot).orThunk(() => {
6212
        return simulate(bridge, isRoot, direction, initial, anchor).map(info => {
6213
          const range = info.range;
6214
          return Response.create(Optional.some(makeSitus(range.start, range.soffset, range.finish, range.foffset)), true);
6215
        });
6216
      });
6217
    };
6218
    const firstUpCheck = (initial, isRoot) => {
6219
      return closest$1(initial, 'tr', isRoot).bind(startRow => {
6220
        return closest$1(startRow, 'table', isRoot).bind(table => {
6221
          const rows = descendants(table, 'tr');
6222
          if (eq$1(startRow, rows[0])) {
6223
            return seekLeft(table, element => {
6224
              return last$1(element).isSome();
6225
            }, isRoot).map(last => {
6226
              const lastOffset = getEnd(last);
6227
              return Response.create(Optional.some(makeSitus(last, lastOffset, last, lastOffset)), true);
6228
            });
6229
          } else {
6230
            return Optional.none();
6231
          }
6232
        });
6233
      });
6234
    };
6235
    const lastDownCheck = (initial, isRoot) => {
6236
      return closest$1(initial, 'tr', isRoot).bind(startRow => {
6237
        return closest$1(startRow, 'table', isRoot).bind(table => {
6238
          const rows = descendants(table, 'tr');
6239
          if (eq$1(startRow, rows[rows.length - 1])) {
6240
            return seekRight(table, element => {
6241
              return first(element).isSome();
6242
            }, isRoot).map(first => {
6243
              return Response.create(Optional.some(makeSitus(first, 0, first, 0)), true);
6244
            });
6245
          } else {
6246
            return Optional.none();
6247
          }
6248
        });
6249
      });
6250
    };
6251
    const select = (bridge, container, isRoot, direction, initial, anchor, selectRange) => {
6252
      return simulate(bridge, isRoot, direction, initial, anchor).bind(info => {
6253
        return detect(container, isRoot, info.start, info.finish, selectRange);
6254
      });
6255
    };
6256
 
6257
    const Cell = initial => {
6258
      let value = initial;
6259
      const get = () => {
6260
        return value;
6261
      };
6262
      const set = v => {
6263
        value = v;
6264
      };
6265
      return {
6266
        get,
6267
        set
6268
      };
6269
    };
6270
 
6271
    const singleton = doRevoke => {
6272
      const subject = Cell(Optional.none());
6273
      const revoke = () => subject.get().each(doRevoke);
6274
      const clear = () => {
6275
        revoke();
6276
        subject.set(Optional.none());
6277
      };
6278
      const isSet = () => subject.get().isSome();
6279
      const get = () => subject.get();
6280
      const set = s => {
6281
        revoke();
6282
        subject.set(Optional.some(s));
6283
      };
6284
      return {
6285
        clear,
6286
        isSet,
6287
        get,
6288
        set
6289
      };
6290
    };
6291
    const value = () => {
6292
      const subject = singleton(noop);
6293
      const on = f => subject.get().each(f);
6294
      return {
6295
        ...subject,
6296
        on
6297
      };
6298
    };
6299
 
6300
    const findCell = (target, isRoot) => closest$1(target, 'td,th', isRoot);
6301
    const isInEditableContext = cell => parentElement(cell).exists(isEditable$1);
6302
    const MouseSelection = (bridge, container, isRoot, annotations) => {
6303
      const cursor = value();
6304
      const clearstate = cursor.clear;
6305
      const applySelection = event => {
6306
        cursor.on(start => {
6307
          annotations.clearBeforeUpdate(container);
6308
          findCell(event.target, isRoot).each(finish => {
6309
            identify(start, finish, isRoot).each(cellSel => {
6310
              const boxes = cellSel.boxes.getOr([]);
6311
              if (boxes.length === 1) {
6312
                const singleCell = boxes[0];
6313
                const isNonEditableCell = getRaw(singleCell) === 'false';
6314
                const isCellClosestContentEditable = is(closest(event.target), singleCell, eq$1);
6315
                if (isNonEditableCell && isCellClosestContentEditable) {
6316
                  annotations.selectRange(container, boxes, singleCell, singleCell);
6317
                  bridge.selectContents(singleCell);
6318
                }
6319
              } else if (boxes.length > 1) {
6320
                annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
6321
                bridge.selectContents(finish);
6322
              }
6323
            });
6324
          });
6325
        });
6326
      };
6327
      const mousedown = event => {
6328
        annotations.clear(container);
6329
        findCell(event.target, isRoot).filter(isInEditableContext).each(cursor.set);
6330
      };
6331
      const mouseover = event => {
6332
        applySelection(event);
6333
      };
6334
      const mouseup = event => {
6335
        applySelection(event);
6336
        clearstate();
6337
      };
6338
      return {
6339
        clearstate,
6340
        mousedown,
6341
        mouseover,
6342
        mouseup
6343
      };
6344
    };
6345
 
6346
    const down = {
6347
      traverse: nextSibling,
6348
      gather: after$1,
6349
      relative: Situ.before,
6350
      retry: Retries.tryDown,
6351
      failure: BeforeAfter.failedDown
6352
    };
6353
    const up = {
6354
      traverse: prevSibling,
6355
      gather: before,
6356
      relative: Situ.before,
6357
      retry: Retries.tryUp,
6358
      failure: BeforeAfter.failedUp
6359
    };
6360
 
6361
    const isKey = key => {
6362
      return keycode => {
6363
        return keycode === key;
6364
      };
6365
    };
6366
    const isUp = isKey(38);
6367
    const isDown = isKey(40);
6368
    const isNavigation = keycode => {
6369
      return keycode >= 37 && keycode <= 40;
6370
    };
6371
    const ltr = {
6372
      isBackward: isKey(37),
6373
      isForward: isKey(39)
6374
    };
6375
    const rtl = {
6376
      isBackward: isKey(39),
6377
      isForward: isKey(37)
6378
    };
6379
 
6380
    const get$3 = _DOC => {
6381
      const doc = _DOC !== undefined ? _DOC.dom : document;
6382
      const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
6383
      const y = doc.body.scrollTop || doc.documentElement.scrollTop;
6384
      return SugarPosition(x, y);
6385
    };
6386
    const by = (x, y, _DOC) => {
6387
      const doc = _DOC !== undefined ? _DOC.dom : document;
6388
      const win = doc.defaultView;
6389
      if (win) {
6390
        win.scrollBy(x, y);
6391
      }
6392
    };
6393
 
6394
    const adt = Adt.generate([
6395
      { domRange: ['rng'] },
6396
      {
6397
        relative: [
6398
          'startSitu',
6399
          'finishSitu'
6400
        ]
6401
      },
6402
      {
6403
        exact: [
6404
          'start',
6405
          'soffset',
6406
          'finish',
6407
          'foffset'
6408
        ]
6409
      }
6410
    ]);
6411
    const exactFromRange = simRange => adt.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
6412
    const getStart = selection => selection.match({
6413
      domRange: rng => SugarElement.fromDom(rng.startContainer),
6414
      relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
6415
      exact: (start, _soffset, _finish, _foffset) => start
6416
    });
6417
    const domRange = adt.domRange;
6418
    const relative = adt.relative;
6419
    const exact = adt.exact;
6420
    const getWin = selection => {
6421
      const start = getStart(selection);
6422
      return defaultView(start);
6423
    };
6424
    const range = SimRange.create;
6425
    const SimSelection = {
6426
      domRange,
6427
      relative,
6428
      exact,
6429
      exactFromRange,
6430
      getWin,
6431
      range
6432
    };
6433
 
6434
    const caretPositionFromPoint = (doc, x, y) => {
6435
      var _a, _b;
6436
      return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
6437
        if (pos.offsetNode === null) {
6438
          return Optional.none();
6439
        }
6440
        const r = doc.dom.createRange();
6441
        r.setStart(pos.offsetNode, pos.offset);
6442
        r.collapse();
6443
        return Optional.some(r);
6444
      });
6445
    };
6446
    const caretRangeFromPoint = (doc, x, y) => {
6447
      var _a, _b;
6448
      return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
6449
    };
6450
    const availableSearch = (() => {
6451
      if (document.caretPositionFromPoint) {
6452
        return caretPositionFromPoint;
6453
      } else if (document.caretRangeFromPoint) {
6454
        return caretRangeFromPoint;
6455
      } else {
6456
        return Optional.none;
6457
      }
6458
    })();
6459
    const fromPoint = (win, x, y) => {
6460
      const doc = SugarElement.fromDom(win.document);
6461
      return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
6462
    };
6463
 
6464
    const beforeSpecial = (element, offset) => {
6465
      const name$1 = name(element);
6466
      if ('input' === name$1) {
6467
        return Situ.after(element);
6468
      } else if (!contains$2([
6469
          'br',
6470
          'img'
6471
        ], name$1)) {
6472
        return Situ.on(element, offset);
6473
      } else {
6474
        return offset === 0 ? Situ.before(element) : Situ.after(element);
6475
      }
6476
    };
6477
    const preprocessRelative = (startSitu, finishSitu) => {
6478
      const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
6479
      const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
6480
      return SimSelection.relative(start, finish);
6481
    };
6482
    const preprocessExact = (start, soffset, finish, foffset) => {
6483
      const startSitu = beforeSpecial(start, soffset);
6484
      const finishSitu = beforeSpecial(finish, foffset);
6485
      return SimSelection.relative(startSitu, finishSitu);
6486
    };
6487
 
6488
    const makeRange = (start, soffset, finish, foffset) => {
6489
      const doc = owner(start);
6490
      const rng = doc.dom.createRange();
6491
      rng.setStart(start.dom, soffset);
6492
      rng.setEnd(finish.dom, foffset);
6493
      return rng;
6494
    };
6495
    const after = (start, soffset, finish, foffset) => {
6496
      const r = makeRange(start, soffset, finish, foffset);
6497
      const same = eq$1(start, finish) && soffset === foffset;
6498
      return r.collapsed && !same;
6499
    };
6500
 
6501
    const getNativeSelection = win => Optional.from(win.getSelection());
6502
    const doSetNativeRange = (win, rng) => {
6503
      getNativeSelection(win).each(selection => {
6504
        selection.removeAllRanges();
6505
        selection.addRange(rng);
6506
      });
6507
    };
6508
    const doSetRange = (win, start, soffset, finish, foffset) => {
6509
      const rng = exactToNative(win, start, soffset, finish, foffset);
6510
      doSetNativeRange(win, rng);
6511
    };
6512
    const setLegacyRtlRange = (win, selection, start, soffset, finish, foffset) => {
6513
      selection.collapse(start.dom, soffset);
6514
      selection.extend(finish.dom, foffset);
6515
    };
6516
    const setRangeFromRelative = (win, relative) => diagnose(win, relative).match({
6517
      ltr: (start, soffset, finish, foffset) => {
6518
        doSetRange(win, start, soffset, finish, foffset);
6519
      },
6520
      rtl: (start, soffset, finish, foffset) => {
6521
        getNativeSelection(win).each(selection => {
6522
          if (selection.setBaseAndExtent) {
6523
            selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset);
6524
          } else if (selection.extend) {
6525
            try {
6526
              setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
6527
            } catch (e) {
6528
              doSetRange(win, finish, foffset, start, soffset);
6529
            }
6530
          } else {
6531
            doSetRange(win, finish, foffset, start, soffset);
6532
          }
6533
        });
6534
      }
6535
    });
6536
    const setExact = (win, start, soffset, finish, foffset) => {
6537
      const relative = preprocessExact(start, soffset, finish, foffset);
6538
      setRangeFromRelative(win, relative);
6539
    };
6540
    const setRelative = (win, startSitu, finishSitu) => {
6541
      const relative = preprocessRelative(startSitu, finishSitu);
6542
      setRangeFromRelative(win, relative);
6543
    };
6544
    const readRange = selection => {
6545
      if (selection.rangeCount > 0) {
6546
        const firstRng = selection.getRangeAt(0);
6547
        const lastRng = selection.getRangeAt(selection.rangeCount - 1);
6548
        return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
6549
      } else {
6550
        return Optional.none();
6551
      }
6552
    };
6553
    const doGetExact = selection => {
6554
      if (selection.anchorNode === null || selection.focusNode === null) {
6555
        return readRange(selection);
6556
      } else {
6557
        const anchor = SugarElement.fromDom(selection.anchorNode);
6558
        const focus = SugarElement.fromDom(selection.focusNode);
6559
        return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
6560
      }
6561
    };
6562
    const setToElement = (win, element, selectNodeContents$1 = true) => {
6563
      const rngGetter = selectNodeContents$1 ? selectNodeContents : selectNode;
6564
      const rng = rngGetter(win, element);
6565
      doSetNativeRange(win, rng);
6566
    };
6567
    const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
6568
    const get$2 = win => getExact(win).map(range => SimSelection.exact(range.start, range.soffset, range.finish, range.foffset));
6569
    const getFirstRect = (win, selection) => {
6570
      const rng = asLtrRange(win, selection);
6571
      return getFirstRect$1(rng);
6572
    };
6573
    const getAtPoint = (win, x, y) => fromPoint(win, x, y);
6574
    const clear = win => {
6575
      getNativeSelection(win).each(selection => selection.removeAllRanges());
6576
    };
6577
 
6578
    const WindowBridge = win => {
6579
      const elementFromPoint = (x, y) => {
6580
        return SugarElement.fromPoint(SugarElement.fromDom(win.document), x, y);
6581
      };
6582
      const getRect = element => {
6583
        return element.dom.getBoundingClientRect();
6584
      };
6585
      const getRangedRect = (start, soffset, finish, foffset) => {
6586
        const sel = SimSelection.exact(start, soffset, finish, foffset);
6587
        return getFirstRect(win, sel);
6588
      };
6589
      const getSelection = () => {
6590
        return get$2(win).map(exactAdt => {
6591
          return convertToRange(win, exactAdt);
6592
        });
6593
      };
6594
      const fromSitus = situs => {
6595
        const relative = SimSelection.relative(situs.start, situs.finish);
6596
        return convertToRange(win, relative);
6597
      };
6598
      const situsFromPoint = (x, y) => {
6599
        return getAtPoint(win, x, y).map(exact => {
6600
          return Situs.create(exact.start, exact.soffset, exact.finish, exact.foffset);
6601
        });
6602
      };
6603
      const clearSelection = () => {
6604
        clear(win);
6605
      };
6606
      const collapseSelection = (toStart = false) => {
6607
        get$2(win).each(sel => sel.fold(rng => rng.collapse(toStart), (startSitu, finishSitu) => {
6608
          const situ = toStart ? startSitu : finishSitu;
6609
          setRelative(win, situ, situ);
6610
        }, (start, soffset, finish, foffset) => {
6611
          const node = toStart ? start : finish;
6612
          const offset = toStart ? soffset : foffset;
6613
          setExact(win, node, offset, node, offset);
6614
        }));
6615
      };
6616
      const selectNode = element => {
6617
        setToElement(win, element, false);
6618
      };
6619
      const selectContents = element => {
6620
        setToElement(win, element);
6621
      };
6622
      const setSelection = sel => {
6623
        setExact(win, sel.start, sel.soffset, sel.finish, sel.foffset);
6624
      };
6625
      const setRelativeSelection = (start, finish) => {
6626
        setRelative(win, start, finish);
6627
      };
6628
      const getInnerHeight = () => {
6629
        return win.innerHeight;
6630
      };
6631
      const getScrollY = () => {
6632
        const pos = get$3(SugarElement.fromDom(win.document));
6633
        return pos.top;
6634
      };
6635
      const scrollBy = (x, y) => {
6636
        by(x, y, SugarElement.fromDom(win.document));
6637
      };
6638
      return {
6639
        elementFromPoint,
6640
        getRect,
6641
        getRangedRect,
6642
        getSelection,
6643
        fromSitus,
6644
        situsFromPoint,
6645
        clearSelection,
6646
        collapseSelection,
6647
        setSelection,
6648
        setRelativeSelection,
6649
        selectNode,
6650
        selectContents,
6651
        getInnerHeight,
6652
        getScrollY,
6653
        scrollBy
6654
      };
6655
    };
6656
 
6657
    const rc = (rows, cols) => ({
6658
      rows,
6659
      cols
6660
    });
6661
    const mouse = (win, container, isRoot, annotations) => {
6662
      const bridge = WindowBridge(win);
6663
      const handlers = MouseSelection(bridge, container, isRoot, annotations);
6664
      return {
6665
        clearstate: handlers.clearstate,
6666
        mousedown: handlers.mousedown,
6667
        mouseover: handlers.mouseover,
6668
        mouseup: handlers.mouseup
6669
      };
6670
    };
6671
    const isEditableNode = node => closest$2(node, isHTMLElement).exists(isEditable$1);
6672
    const isEditableSelection = (start, finish) => isEditableNode(start) || isEditableNode(finish);
6673
    const keyboard = (win, container, isRoot, annotations) => {
6674
      const bridge = WindowBridge(win);
6675
      const clearToNavigate = () => {
6676
        annotations.clear(container);
6677
        return Optional.none();
6678
      };
6679
      const keydown = (event, start, soffset, finish, foffset, direction) => {
6680
        const realEvent = event.raw;
6681
        const keycode = realEvent.which;
6682
        const shiftKey = realEvent.shiftKey === true;
6683
        const handler = retrieve$1(container, annotations.selectedSelector).fold(() => {
6684
          if (isNavigation(keycode) && !shiftKey) {
6685
            annotations.clearBeforeUpdate(container);
6686
          }
6687
          if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
6688
            return Optional.none;
6689
          } else if (isDown(keycode) && shiftKey) {
6690
            return curry(select, bridge, container, isRoot, down, finish, start, annotations.selectRange);
6691
          } else if (isUp(keycode) && shiftKey) {
6692
            return curry(select, bridge, container, isRoot, up, finish, start, annotations.selectRange);
6693
          } else if (isDown(keycode)) {
6694
            return curry(navigate, bridge, isRoot, down, finish, start, lastDownCheck);
6695
          } else if (isUp(keycode)) {
6696
            return curry(navigate, bridge, isRoot, up, finish, start, firstUpCheck);
6697
          } else {
6698
            return Optional.none;
6699
          }
6700
        }, selected => {
6701
          const update$1 = attempts => {
6702
            return () => {
6703
              const navigation = findMap(attempts, delta => {
6704
                return update(delta.rows, delta.cols, container, selected, annotations);
6705
              });
6706
              return navigation.fold(() => {
6707
                return getEdges(container, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(edges => {
6708
                  const relative = isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before;
6709
                  bridge.setRelativeSelection(Situ.on(edges.first, 0), relative(edges.table));
6710
                  annotations.clear(container);
6711
                  return Response.create(Optional.none(), true);
6712
                });
6713
              }, _ => {
6714
                return Optional.some(Response.create(Optional.none(), true));
6715
              });
6716
            };
6717
          };
6718
          if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
6719
            return Optional.none;
6720
          } else if (isDown(keycode) && shiftKey) {
6721
            return update$1([rc(+1, 0)]);
6722
          } else if (isUp(keycode) && shiftKey) {
6723
            return update$1([rc(-1, 0)]);
6724
          } else if (direction.isBackward(keycode) && shiftKey) {
6725
            return update$1([
6726
              rc(0, -1),
6727
              rc(-1, 0)
6728
            ]);
6729
          } else if (direction.isForward(keycode) && shiftKey) {
6730
            return update$1([
6731
              rc(0, +1),
6732
              rc(+1, 0)
6733
            ]);
6734
          } else if (isNavigation(keycode) && !shiftKey) {
6735
            return clearToNavigate;
6736
          } else {
6737
            return Optional.none;
6738
          }
6739
        });
6740
        return handler();
6741
      };
6742
      const keyup = (event, start, soffset, finish, foffset) => {
6743
        return retrieve$1(container, annotations.selectedSelector).fold(() => {
6744
          const realEvent = event.raw;
6745
          const keycode = realEvent.which;
6746
          const shiftKey = realEvent.shiftKey === true;
6747
          if (!shiftKey) {
6748
            return Optional.none();
6749
          }
6750
          if (isNavigation(keycode) && isEditableSelection(start, finish)) {
6751
            return sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange);
6752
          } else {
6753
            return Optional.none();
6754
          }
6755
        }, Optional.none);
6756
      };
6757
      return {
6758
        keydown,
6759
        keyup
6760
      };
6761
    };
6762
    const external = (win, container, isRoot, annotations) => {
6763
      const bridge = WindowBridge(win);
6764
      return (start, finish) => {
6765
        annotations.clearBeforeUpdate(container);
6766
        identify(start, finish, isRoot).each(cellSel => {
6767
          const boxes = cellSel.boxes.getOr([]);
6768
          annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
6769
          bridge.selectContents(finish);
6770
          bridge.collapseSelection();
6771
        });
6772
      };
6773
    };
6774
 
6775
    const read = (element, attr) => {
6776
      const value = get$b(element, attr);
6777
      return value === undefined || value === '' ? [] : value.split(' ');
6778
    };
6779
    const add$2 = (element, attr, id) => {
6780
      const old = read(element, attr);
6781
      const nu = old.concat([id]);
6782
      set$2(element, attr, nu.join(' '));
6783
      return true;
6784
    };
6785
    const remove$4 = (element, attr, id) => {
6786
      const nu = filter$2(read(element, attr), v => v !== id);
6787
      if (nu.length > 0) {
6788
        set$2(element, attr, nu.join(' '));
6789
      } else {
6790
        remove$7(element, attr);
6791
      }
6792
      return false;
6793
    };
6794
 
6795
    const supports = element => element.dom.classList !== undefined;
6796
    const get$1 = element => read(element, 'class');
6797
    const add$1 = (element, clazz) => add$2(element, 'class', clazz);
6798
    const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
6799
 
6800
    const add = (element, clazz) => {
6801
      if (supports(element)) {
6802
        element.dom.classList.add(clazz);
6803
      } else {
6804
        add$1(element, clazz);
6805
      }
6806
    };
6807
    const cleanClass = element => {
6808
      const classList = supports(element) ? element.dom.classList : get$1(element);
6809
      if (classList.length === 0) {
6810
        remove$7(element, 'class');
6811
      }
6812
    };
6813
    const remove$2 = (element, clazz) => {
6814
      if (supports(element)) {
6815
        const classList = element.dom.classList;
6816
        classList.remove(clazz);
6817
      } else {
6818
        remove$3(element, clazz);
6819
      }
6820
      cleanClass(element);
6821
    };
6822
    const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
6823
 
6824
    const remove$1 = (element, classes) => {
6825
      each$2(classes, x => {
6826
        remove$2(element, x);
6827
      });
6828
    };
6829
 
6830
    const addClass = clazz => element => {
6831
      add(element, clazz);
6832
    };
6833
    const removeClasses = classes => element => {
6834
      remove$1(element, classes);
6835
    };
6836
 
6837
    const byClass = ephemera => {
6838
      const addSelectionClass = addClass(ephemera.selected);
6839
      const removeSelectionClasses = removeClasses([
6840
        ephemera.selected,
6841
        ephemera.lastSelected,
6842
        ephemera.firstSelected
6843
      ]);
6844
      const clear = container => {
6845
        const sels = descendants(container, ephemera.selectedSelector);
6846
        each$2(sels, removeSelectionClasses);
6847
      };
6848
      const selectRange = (container, cells, start, finish) => {
6849
        clear(container);
6850
        each$2(cells, addSelectionClass);
6851
        add(start, ephemera.firstSelected);
6852
        add(finish, ephemera.lastSelected);
6853
      };
6854
      return {
6855
        clearBeforeUpdate: clear,
6856
        clear,
6857
        selectRange,
6858
        selectedSelector: ephemera.selectedSelector,
6859
        firstSelectedSelector: ephemera.firstSelectedSelector,
6860
        lastSelectedSelector: ephemera.lastSelectedSelector
6861
      };
6862
    };
6863
    const byAttr = (ephemera, onSelection, onClear) => {
6864
      const removeSelectionAttributes = element => {
6865
        remove$7(element, ephemera.selected);
6866
        remove$7(element, ephemera.firstSelected);
6867
        remove$7(element, ephemera.lastSelected);
6868
      };
6869
      const addSelectionAttribute = element => {
6870
        set$2(element, ephemera.selected, '1');
6871
      };
6872
      const clear = container => {
6873
        clearBeforeUpdate(container);
6874
        onClear();
6875
      };
6876
      const clearBeforeUpdate = container => {
6877
        const sels = descendants(container, `${ ephemera.selectedSelector },${ ephemera.firstSelectedSelector },${ ephemera.lastSelectedSelector }`);
6878
        each$2(sels, removeSelectionAttributes);
6879
      };
6880
      const selectRange = (container, cells, start, finish) => {
6881
        clear(container);
6882
        each$2(cells, addSelectionAttribute);
6883
        set$2(start, ephemera.firstSelected, '1');
6884
        set$2(finish, ephemera.lastSelected, '1');
6885
        onSelection(cells, start, finish);
6886
      };
6887
      return {
6888
        clearBeforeUpdate,
6889
        clear,
6890
        selectRange,
6891
        selectedSelector: ephemera.selectedSelector,
6892
        firstSelectedSelector: ephemera.firstSelectedSelector,
6893
        lastSelectedSelector: ephemera.lastSelectedSelector
6894
      };
6895
    };
6896
    const SelectionAnnotation = {
6897
      byClass,
6898
      byAttr
6899
    };
6900
 
6901
    const fold = (subject, onNone, onMultiple, onSingle) => {
6902
      switch (subject.tag) {
6903
      case 'none':
6904
        return onNone();
6905
      case 'single':
6906
        return onSingle(subject.element);
6907
      case 'multiple':
6908
        return onMultiple(subject.elements);
6909
      }
6910
    };
6911
    const none = () => ({ tag: 'none' });
6912
    const multiple = elements => ({
6913
      tag: 'multiple',
6914
      elements
6915
    });
6916
    const single = element => ({
6917
      tag: 'single',
6918
      element
6919
    });
6920
 
6921
    const Selections = (lazyRoot, getStart, selectedSelector) => {
6922
      const get = () => retrieve(lazyRoot(), selectedSelector).fold(() => getStart().fold(none, single), multiple);
6923
      return { get };
6924
    };
6925
 
6926
    const getUpOrLeftCells = (grid, selectedCells) => {
6927
      const upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row + 1);
6928
      const upDetails = toDetailList(upGrid);
6929
      return bind$2(upDetails, detail => {
6930
        const slicedCells = detail.cells.slice(0, selectedCells[selectedCells.length - 1].column + 1);
6931
        return map$1(slicedCells, cell => cell.element);
6932
      });
6933
    };
6934
    const getDownOrRightCells = (grid, selectedCells) => {
6935
      const downGrid = grid.slice(selectedCells[0].row + selectedCells[0].rowspan - 1, grid.length);
6936
      const downDetails = toDetailList(downGrid);
6937
      return bind$2(downDetails, detail => {
6938
        const slicedCells = detail.cells.slice(selectedCells[0].column + selectedCells[0].colspan - 1, detail.cells.length);
6939
        return map$1(slicedCells, cell => cell.element);
6940
      });
6941
    };
6942
    const getOtherCells = (table, target, generators) => {
6943
      const warehouse = Warehouse.fromTable(table);
6944
      const details = onCells(warehouse, target);
6945
      return details.map(selectedCells => {
6946
        const grid = toGrid(warehouse, generators, false);
6947
        const {rows} = extractGridDetails(grid);
6948
        const upOrLeftCells = getUpOrLeftCells(rows, selectedCells);
6949
        const downOrRightCells = getDownOrRightCells(rows, selectedCells);
6950
        return {
6951
          upOrLeftCells,
6952
          downOrRightCells
6953
        };
6954
      });
6955
    };
6956
 
6957
    const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
6958
      target,
6959
      x,
6960
      y,
6961
      stop,
6962
      prevent,
6963
      kill,
6964
      raw
6965
    });
6966
    const fromRawEvent$1 = rawEvent => {
6967
      const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
6968
      const stop = () => rawEvent.stopPropagation();
6969
      const prevent = () => rawEvent.preventDefault();
6970
      const kill = compose(prevent, stop);
6971
      return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
6972
    };
6973
    const handle = (filter, handler) => rawEvent => {
6974
      if (filter(rawEvent)) {
6975
        handler(fromRawEvent$1(rawEvent));
6976
      }
6977
    };
6978
    const binder = (element, event, filter, handler, useCapture) => {
6979
      const wrapped = handle(filter, handler);
6980
      element.dom.addEventListener(event, wrapped, useCapture);
6981
      return { unbind: curry(unbind, element, event, wrapped, useCapture) };
6982
    };
6983
    const bind$1 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
6984
    const unbind = (element, event, handler, useCapture) => {
6985
      element.dom.removeEventListener(event, handler, useCapture);
6986
    };
6987
 
6988
    const filter = always;
6989
    const bind = (element, event, handler) => bind$1(element, event, filter, handler);
6990
    const fromRawEvent = fromRawEvent$1;
6991
 
6992
    const hasInternalTarget = e => !has(SugarElement.fromDom(e.target), 'ephox-snooker-resizer-bar');
6993
    const TableCellSelectionHandler = (editor, resizeHandler) => {
6994
      const cellSelection = Selections(() => SugarElement.fromDom(editor.getBody()), () => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)), ephemera.selectedSelector);
6995
      const onSelection = (cells, start, finish) => {
6996
        const tableOpt = table(start);
6997
        tableOpt.each(table => {
6998
          const cloneFormats = getTableCloneElements(editor);
6999
          const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), cloneFormats);
7000
          const selectedCells = getCellsFromSelection(editor);
7001
          const otherCells = getOtherCells(table, { selection: selectedCells }, generators);
7002
          fireTableSelectionChange(editor, cells, start, finish, otherCells);
7003
        });
7004
      };
7005
      const onClear = () => fireTableSelectionClear(editor);
7006
      const annotations = SelectionAnnotation.byAttr(ephemera, onSelection, onClear);
7007
      editor.on('init', _e => {
7008
        const win = editor.getWin();
7009
        const body = getBody(editor);
7010
        const isRoot = getIsRoot(editor);
7011
        const syncSelection = () => {
7012
          const sel = editor.selection;
7013
          const start = SugarElement.fromDom(sel.getStart());
7014
          const end = SugarElement.fromDom(sel.getEnd());
7015
          const shared = sharedOne(table, [
7016
            start,
7017
            end
7018
          ]);
7019
          shared.fold(() => annotations.clear(body), noop);
7020
        };
7021
        const mouseHandlers = mouse(win, body, isRoot, annotations);
7022
        const keyHandlers = keyboard(win, body, isRoot, annotations);
7023
        const external$1 = external(win, body, isRoot, annotations);
7024
        const hasShiftKey = event => event.raw.shiftKey === true;
7025
        editor.on('TableSelectorChange', e => external$1(e.start, e.finish));
7026
        const handleResponse = (event, response) => {
7027
          if (!hasShiftKey(event)) {
7028
            return;
7029
          }
7030
          if (response.kill) {
7031
            event.kill();
7032
          }
7033
          response.selection.each(ns => {
7034
            const relative = SimSelection.relative(ns.start, ns.finish);
7035
            const rng = asLtrRange(win, relative);
7036
            editor.selection.setRng(rng);
7037
          });
7038
        };
7039
        const keyup = event => {
7040
          const wrappedEvent = fromRawEvent(event);
7041
          if (wrappedEvent.raw.shiftKey && isNavigation(wrappedEvent.raw.which)) {
7042
            const rng = editor.selection.getRng();
7043
            const start = SugarElement.fromDom(rng.startContainer);
7044
            const end = SugarElement.fromDom(rng.endContainer);
7045
            keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(response => {
7046
              handleResponse(wrappedEvent, response);
7047
            });
7048
          }
7049
        };
7050
        const keydown = event => {
7051
          const wrappedEvent = fromRawEvent(event);
7052
          resizeHandler.hide();
7053
          const rng = editor.selection.getRng();
7054
          const start = SugarElement.fromDom(rng.startContainer);
7055
          const end = SugarElement.fromDom(rng.endContainer);
7056
          const direction = onDirection(ltr, rtl)(SugarElement.fromDom(editor.selection.getStart()));
7057
          keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(response => {
7058
            handleResponse(wrappedEvent, response);
7059
          });
7060
          resizeHandler.show();
7061
        };
7062
        const isLeftMouse = raw => raw.button === 0;
7063
        const isLeftButtonPressed = raw => {
7064
          if (raw.buttons === undefined) {
7065
            return true;
7066
          }
7067
          return (raw.buttons & 1) !== 0;
7068
        };
7069
        const dragStart = _e => {
7070
          mouseHandlers.clearstate();
7071
        };
7072
        const mouseDown = e => {
7073
          if (isLeftMouse(e) && hasInternalTarget(e)) {
7074
            mouseHandlers.mousedown(fromRawEvent(e));
7075
          }
7076
        };
7077
        const mouseOver = e => {
7078
          if (isLeftButtonPressed(e) && hasInternalTarget(e)) {
7079
            mouseHandlers.mouseover(fromRawEvent(e));
7080
          }
7081
        };
7082
        const mouseUp = e => {
7083
          if (isLeftMouse(e) && hasInternalTarget(e)) {
7084
            mouseHandlers.mouseup(fromRawEvent(e));
7085
          }
7086
        };
7087
        const getDoubleTap = () => {
7088
          const lastTarget = Cell(SugarElement.fromDom(body));
7089
          const lastTimeStamp = Cell(0);
7090
          const touchEnd = t => {
7091
            const target = SugarElement.fromDom(t.target);
7092
            if (isTag('td')(target) || isTag('th')(target)) {
7093
              const lT = lastTarget.get();
7094
              const lTS = lastTimeStamp.get();
7095
              if (eq$1(lT, target) && t.timeStamp - lTS < 300) {
7096
                t.preventDefault();
7097
                external$1(target, target);
7098
              }
7099
            }
7100
            lastTarget.set(target);
7101
            lastTimeStamp.set(t.timeStamp);
7102
          };
7103
          return { touchEnd };
7104
        };
7105
        const doubleTap = getDoubleTap();
7106
        editor.on('dragstart', dragStart);
7107
        editor.on('mousedown', mouseDown);
7108
        editor.on('mouseover', mouseOver);
7109
        editor.on('mouseup', mouseUp);
7110
        editor.on('touchend', doubleTap.touchEnd);
7111
        editor.on('keyup', keyup);
7112
        editor.on('keydown', keydown);
7113
        editor.on('NodeChange', syncSelection);
7114
      });
7115
      editor.on('PreInit', () => {
7116
        editor.serializer.addTempAttr(ephemera.firstSelected);
7117
        editor.serializer.addTempAttr(ephemera.lastSelected);
7118
      });
7119
      const clearSelectedCells = container => annotations.clear(SugarElement.fromDom(container));
7120
      const getSelectedCells = () => fold(cellSelection.get(), constant([]), cells => {
7121
        return map$1(cells, cell => cell.dom);
7122
      }, cell => [cell.dom]);
7123
      return {
7124
        getSelectedCells,
7125
        clearSelectedCells
7126
      };
7127
    };
7128
 
7129
    const Event = fields => {
7130
      let handlers = [];
7131
      const bind = handler => {
7132
        if (handler === undefined) {
7133
          throw new Error('Event bind error: undefined handler');
7134
        }
7135
        handlers.push(handler);
7136
      };
7137
      const unbind = handler => {
7138
        handlers = filter$2(handlers, h => {
7139
          return h !== handler;
7140
        });
7141
      };
7142
      const trigger = (...args) => {
7143
        const event = {};
7144
        each$2(fields, (name, i) => {
7145
          event[name] = args[i];
7146
        });
7147
        each$2(handlers, handler => {
7148
          handler(event);
7149
        });
7150
      };
7151
      return {
7152
        bind,
7153
        unbind,
7154
        trigger
7155
      };
7156
    };
7157
 
7158
    const create$1 = typeDefs => {
7159
      const registry = map(typeDefs, event => {
7160
        return {
7161
          bind: event.bind,
7162
          unbind: event.unbind
7163
        };
7164
      });
7165
      const trigger = map(typeDefs, event => {
7166
        return event.trigger;
7167
      });
7168
      return {
7169
        registry,
7170
        trigger
7171
      };
7172
    };
7173
 
7174
    const last = (fn, rate) => {
7175
      let timer = null;
7176
      const cancel = () => {
7177
        if (!isNull(timer)) {
7178
          clearTimeout(timer);
7179
          timer = null;
7180
        }
7181
      };
7182
      const throttle = (...args) => {
7183
        cancel();
7184
        timer = setTimeout(() => {
7185
          timer = null;
7186
          fn.apply(null, args);
7187
        }, rate);
7188
      };
7189
      return {
7190
        cancel,
7191
        throttle
7192
      };
7193
    };
7194
 
7195
    const sort = arr => {
7196
      return arr.slice(0).sort();
7197
    };
7198
    const reqMessage = (required, keys) => {
7199
      throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
7200
    };
7201
    const unsuppMessage = unsupported => {
7202
      throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
7203
    };
7204
    const validateStrArr = (label, array) => {
7205
      if (!isArray(array)) {
7206
        throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
7207
      }
7208
      each$2(array, a => {
7209
        if (!isString(a)) {
7210
          throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
7211
        }
7212
      });
7213
    };
7214
    const invalidTypeMessage = (incorrect, type) => {
7215
      throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
7216
    };
7217
    const checkDupes = everything => {
7218
      const sorted = sort(everything);
7219
      const dupe = find$1(sorted, (s, i) => {
7220
        return i < sorted.length - 1 && s === sorted[i + 1];
7221
      });
7222
      dupe.each(d => {
7223
        throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
7224
      });
7225
    };
7226
 
7227
    const base = (handleUnsupported, required) => {
7228
      return baseWith(handleUnsupported, required, {
7229
        validate: isFunction,
7230
        label: 'function'
7231
      });
7232
    };
7233
    const baseWith = (handleUnsupported, required, pred) => {
7234
      if (required.length === 0) {
7235
        throw new Error('You must specify at least one required field.');
7236
      }
7237
      validateStrArr('required', required);
7238
      checkDupes(required);
7239
      return obj => {
7240
        const keys$1 = keys(obj);
7241
        const allReqd = forall(required, req => {
7242
          return contains$2(keys$1, req);
7243
        });
7244
        if (!allReqd) {
7245
          reqMessage(required, keys$1);
7246
        }
7247
        handleUnsupported(required, keys$1);
7248
        const invalidKeys = filter$2(required, key => {
7249
          return !pred.validate(obj[key], key);
7250
        });
7251
        if (invalidKeys.length > 0) {
7252
          invalidTypeMessage(invalidKeys, pred.label);
7253
        }
7254
        return obj;
7255
      };
7256
    };
7257
    const handleExact = (required, keys) => {
7258
      const unsupported = filter$2(keys, key => {
7259
        return !contains$2(required, key);
7260
      });
7261
      if (unsupported.length > 0) {
7262
        unsuppMessage(unsupported);
7263
      }
7264
    };
7265
    const exactly = required => base(handleExact, required);
7266
 
7267
    const DragMode = exactly([
7268
      'compare',
7269
      'extract',
7270
      'mutate',
7271
      'sink'
7272
    ]);
7273
    const DragSink = exactly([
7274
      'element',
7275
      'start',
7276
      'stop',
7277
      'destroy'
7278
    ]);
7279
    const DragApi = exactly([
7280
      'forceDrop',
7281
      'drop',
7282
      'move',
7283
      'delayDrop'
7284
    ]);
7285
 
7286
    const InDrag = () => {
7287
      let previous = Optional.none();
7288
      const reset = () => {
7289
        previous = Optional.none();
7290
      };
7291
      const update = (mode, nu) => {
7292
        const result = previous.map(old => {
7293
          return mode.compare(old, nu);
7294
        });
7295
        previous = Optional.some(nu);
7296
        return result;
7297
      };
7298
      const onEvent = (event, mode) => {
7299
        const dataOption = mode.extract(event);
7300
        dataOption.each(data => {
7301
          const offset = update(mode, data);
7302
          offset.each(d => {
7303
            events.trigger.move(d);
7304
          });
7305
        });
7306
      };
7307
      const events = create$1({ move: Event(['info']) });
7308
      return {
7309
        onEvent,
7310
        reset,
7311
        events: events.registry
7312
      };
7313
    };
7314
 
7315
    const NoDrag = () => {
7316
      const events = create$1({ move: Event(['info']) });
7317
      return {
7318
        onEvent: noop,
7319
        reset: noop,
7320
        events: events.registry
7321
      };
7322
    };
7323
 
7324
    const Movement = () => {
7325
      const noDragState = NoDrag();
7326
      const inDragState = InDrag();
7327
      let dragState = noDragState;
7328
      const on = () => {
7329
        dragState.reset();
7330
        dragState = inDragState;
7331
      };
7332
      const off = () => {
7333
        dragState.reset();
7334
        dragState = noDragState;
7335
      };
7336
      const onEvent = (event, mode) => {
7337
        dragState.onEvent(event, mode);
7338
      };
7339
      const isOn = () => {
7340
        return dragState === inDragState;
7341
      };
7342
      return {
7343
        on,
7344
        off,
7345
        isOn,
7346
        onEvent,
7347
        events: inDragState.events
7348
      };
7349
    };
7350
 
7351
    const setup = (mutation, mode, settings) => {
7352
      let active = false;
7353
      const events = create$1({
7354
        start: Event([]),
7355
        stop: Event([])
7356
      });
7357
      const movement = Movement();
7358
      const drop = () => {
7359
        sink.stop();
7360
        if (movement.isOn()) {
7361
          movement.off();
7362
          events.trigger.stop();
7363
        }
7364
      };
7365
      const throttledDrop = last(drop, 200);
7366
      const go = parent => {
7367
        sink.start(parent);
7368
        movement.on();
7369
        events.trigger.start();
7370
      };
7371
      const mousemove = event => {
7372
        throttledDrop.cancel();
7373
        movement.onEvent(event, mode);
7374
      };
7375
      movement.events.move.bind(event => {
7376
        mode.mutate(mutation, event.info);
7377
      });
7378
      const on = () => {
7379
        active = true;
7380
      };
7381
      const off = () => {
7382
        active = false;
7383
      };
7384
      const isActive = () => active;
7385
      const runIfActive = f => {
7386
        return (...args) => {
7387
          if (active) {
7388
            f.apply(null, args);
7389
          }
7390
        };
7391
      };
7392
      const sink = mode.sink(DragApi({
7393
        forceDrop: drop,
7394
        drop: runIfActive(drop),
7395
        move: runIfActive(mousemove),
7396
        delayDrop: runIfActive(throttledDrop.throttle)
7397
      }), settings);
7398
      const destroy = () => {
7399
        sink.destroy();
7400
      };
7401
      return {
7402
        element: sink.element,
7403
        go,
7404
        on,
7405
        off,
7406
        isActive,
7407
        destroy,
7408
        events: events.registry
7409
      };
7410
    };
7411
 
7412
    const css = namespace => {
7413
      const dashNamespace = namespace.replace(/\./g, '-');
7414
      const resolve = str => {
7415
        return dashNamespace + '-' + str;
7416
      };
7417
      return { resolve };
7418
    };
7419
 
7420
    const styles$1 = css('ephox-dragster');
7421
    const resolve$1 = styles$1.resolve;
7422
 
7423
    const Blocker = options => {
7424
      const settings = {
7425
        layerClass: resolve$1('blocker'),
7426
        ...options
7427
      };
7428
      const div = SugarElement.fromTag('div');
7429
      set$2(div, 'role', 'presentation');
7430
      setAll(div, {
7431
        position: 'fixed',
7432
        left: '0px',
7433
        top: '0px',
7434
        width: '100%',
7435
        height: '100%'
7436
      });
7437
      add(div, resolve$1('blocker'));
7438
      add(div, settings.layerClass);
7439
      const element = constant(div);
7440
      const destroy = () => {
7441
        remove$6(div);
7442
      };
7443
      return {
7444
        element,
7445
        destroy
7446
      };
7447
    };
7448
 
7449
    const compare = (old, nu) => {
7450
      return SugarPosition(nu.left - old.left, nu.top - old.top);
7451
    };
7452
    const extract = event => {
7453
      return Optional.some(SugarPosition(event.x, event.y));
7454
    };
7455
    const mutate = (mutation, info) => {
7456
      mutation.mutate(info.left, info.top);
7457
    };
7458
    const sink = (dragApi, settings) => {
7459
      const blocker = Blocker(settings);
7460
      const mdown = bind(blocker.element(), 'mousedown', dragApi.forceDrop);
7461
      const mup = bind(blocker.element(), 'mouseup', dragApi.drop);
7462
      const mmove = bind(blocker.element(), 'mousemove', dragApi.move);
7463
      const mout = bind(blocker.element(), 'mouseout', dragApi.delayDrop);
7464
      const destroy = () => {
7465
        blocker.destroy();
7466
        mup.unbind();
7467
        mmove.unbind();
7468
        mout.unbind();
7469
        mdown.unbind();
7470
      };
7471
      const start = parent => {
7472
        append$1(parent, blocker.element());
7473
      };
7474
      const stop = () => {
7475
        remove$6(blocker.element());
7476
      };
7477
      return DragSink({
7478
        element: blocker.element,
7479
        start,
7480
        stop,
7481
        destroy
7482
      });
7483
    };
7484
    var MouseDrag = DragMode({
7485
      compare,
7486
      extract,
7487
      sink,
7488
      mutate
7489
    });
7490
 
7491
    const transform = (mutation, settings = {}) => {
7492
      var _a;
7493
      const mode = (_a = settings.mode) !== null && _a !== void 0 ? _a : MouseDrag;
7494
      return setup(mutation, mode, settings);
7495
    };
7496
 
7497
    const styles = css('ephox-snooker');
7498
    const resolve = styles.resolve;
7499
 
7500
    const Mutation = () => {
7501
      const events = create$1({
7502
        drag: Event([
7503
          'xDelta',
7504
          'yDelta'
7505
        ])
7506
      });
7507
      const mutate = (x, y) => {
7508
        events.trigger.drag(x, y);
7509
      };
7510
      return {
7511
        mutate,
7512
        events: events.registry
7513
      };
7514
    };
7515
 
7516
    const BarMutation = () => {
7517
      const events = create$1({
7518
        drag: Event([
7519
          'xDelta',
7520
          'yDelta',
7521
          'target'
7522
        ])
7523
      });
7524
      let target = Optional.none();
7525
      const delegate = Mutation();
7526
      delegate.events.drag.bind(event => {
7527
        target.each(t => {
7528
          events.trigger.drag(event.xDelta, event.yDelta, t);
7529
        });
7530
      });
7531
      const assign = t => {
7532
        target = Optional.some(t);
7533
      };
7534
      const get = () => {
7535
        return target;
7536
      };
7537
      return {
7538
        assign,
7539
        get,
7540
        mutate: delegate.mutate,
7541
        events: events.registry
7542
      };
7543
    };
7544
 
7545
    const col = (column, x, y, w, h) => {
7546
      const bar = SugarElement.fromTag('div');
7547
      setAll(bar, {
7548
        position: 'absolute',
7549
        left: x - w / 2 + 'px',
7550
        top: y + 'px',
7551
        height: h + 'px',
7552
        width: w + 'px'
7553
      });
7554
      setAll$1(bar, {
7555
        'data-column': column,
7556
        'role': 'presentation'
7557
      });
7558
      return bar;
7559
    };
7560
    const row = (r, x, y, w, h) => {
7561
      const bar = SugarElement.fromTag('div');
7562
      setAll(bar, {
7563
        position: 'absolute',
7564
        left: x + 'px',
7565
        top: y - h / 2 + 'px',
7566
        height: h + 'px',
7567
        width: w + 'px'
7568
      });
7569
      setAll$1(bar, {
7570
        'data-row': r,
7571
        'role': 'presentation'
7572
      });
7573
      return bar;
7574
    };
7575
 
7576
    const resizeBar = resolve('resizer-bar');
7577
    const resizeRowBar = resolve('resizer-rows');
7578
    const resizeColBar = resolve('resizer-cols');
7579
    const BAR_THICKNESS = 7;
7580
    const resizableRows = (warehouse, isResizable) => bind$2(warehouse.all, (row, i) => isResizable(row.element) ? [i] : []);
7581
    const resizableColumns = (warehouse, isResizable) => {
7582
      const resizableCols = [];
7583
      range$1(warehouse.grid.columns, index => {
7584
        const colElmOpt = Warehouse.getColumnAt(warehouse, index).map(col => col.element);
7585
        if (colElmOpt.forall(isResizable)) {
7586
          resizableCols.push(index);
7587
        }
7588
      });
7589
      return filter$2(resizableCols, colIndex => {
7590
        const columnCells = Warehouse.filterItems(warehouse, cell => cell.column === colIndex);
7591
        return forall(columnCells, cell => isResizable(cell.element));
7592
      });
7593
    };
7594
    const destroy = wire => {
7595
      const previous = descendants(wire.parent(), '.' + resizeBar);
7596
      each$2(previous, remove$6);
7597
    };
7598
    const drawBar = (wire, positions, create) => {
7599
      const origin = wire.origin();
7600
      each$2(positions, cpOption => {
7601
        cpOption.each(cp => {
7602
          const bar = create(origin, cp);
7603
          add(bar, resizeBar);
7604
          append$1(wire.parent(), bar);
7605
        });
7606
      });
7607
    };
7608
    const refreshCol = (wire, colPositions, position, tableHeight) => {
7609
      drawBar(wire, colPositions, (origin, cp) => {
7610
        const colBar = col(cp.col, cp.x - origin.left, position.top - origin.top, BAR_THICKNESS, tableHeight);
7611
        add(colBar, resizeColBar);
7612
        return colBar;
7613
      });
7614
    };
7615
    const refreshRow = (wire, rowPositions, position, tableWidth) => {
7616
      drawBar(wire, rowPositions, (origin, cp) => {
7617
        const rowBar = row(cp.row, position.left - origin.left, cp.y - origin.top, tableWidth, BAR_THICKNESS);
7618
        add(rowBar, resizeRowBar);
7619
        return rowBar;
7620
      });
7621
    };
7622
    const refreshGrid = (warhouse, wire, table, rows, cols) => {
7623
      const position = absolute(table);
7624
      const isResizable = wire.isResizable;
7625
      const rowPositions = rows.length > 0 ? height.positions(rows, table) : [];
7626
      const resizableRowBars = rowPositions.length > 0 ? resizableRows(warhouse, isResizable) : [];
7627
      const resizableRowPositions = filter$2(rowPositions, (_pos, i) => exists(resizableRowBars, barIndex => i === barIndex));
7628
      refreshRow(wire, resizableRowPositions, position, getOuter$2(table));
7629
      const colPositions = cols.length > 0 ? width.positions(cols, table) : [];
7630
      const resizableColBars = colPositions.length > 0 ? resizableColumns(warhouse, isResizable) : [];
7631
      const resizableColPositions = filter$2(colPositions, (_pos, i) => exists(resizableColBars, barIndex => i === barIndex));
7632
      refreshCol(wire, resizableColPositions, position, getOuter$1(table));
7633
    };
7634
    const refresh = (wire, table) => {
7635
      destroy(wire);
7636
      if (wire.isResizable(table)) {
7637
        const warehouse = Warehouse.fromTable(table);
7638
        const rows$1 = rows(warehouse);
7639
        const cols = columns(warehouse);
7640
        refreshGrid(warehouse, wire, table, rows$1, cols);
7641
      }
7642
    };
7643
    const each = (wire, f) => {
7644
      const bars = descendants(wire.parent(), '.' + resizeBar);
7645
      each$2(bars, f);
7646
    };
7647
    const hide = wire => {
7648
      each(wire, bar => {
7649
        set$1(bar, 'display', 'none');
7650
      });
7651
    };
7652
    const show = wire => {
7653
      each(wire, bar => {
7654
        set$1(bar, 'display', 'block');
7655
      });
7656
    };
7657
    const isRowBar = element => {
7658
      return has(element, resizeRowBar);
7659
    };
7660
    const isColBar = element => {
7661
      return has(element, resizeColBar);
7662
    };
7663
 
7664
    const resizeBarDragging = resolve('resizer-bar-dragging');
7665
    const BarManager = wire => {
7666
      const mutation = BarMutation();
7667
      const resizing = transform(mutation, {});
7668
      let hoverTable = Optional.none();
7669
      const getResizer = (element, type) => {
7670
        return Optional.from(get$b(element, type));
7671
      };
7672
      mutation.events.drag.bind(event => {
7673
        getResizer(event.target, 'data-row').each(_dataRow => {
7674
          const currentRow = getCssValue(event.target, 'top');
7675
          set$1(event.target, 'top', currentRow + event.yDelta + 'px');
7676
        });
7677
        getResizer(event.target, 'data-column').each(_dataCol => {
7678
          const currentCol = getCssValue(event.target, 'left');
7679
          set$1(event.target, 'left', currentCol + event.xDelta + 'px');
7680
        });
7681
      });
7682
      const getDelta = (target, dir) => {
7683
        const newX = getCssValue(target, dir);
7684
        const oldX = getAttrValue(target, 'data-initial-' + dir, 0);
7685
        return newX - oldX;
7686
      };
7687
      resizing.events.stop.bind(() => {
7688
        mutation.get().each(target => {
7689
          hoverTable.each(table => {
7690
            getResizer(target, 'data-row').each(row => {
7691
              const delta = getDelta(target, 'top');
7692
              remove$7(target, 'data-initial-top');
7693
              events.trigger.adjustHeight(table, delta, parseInt(row, 10));
7694
            });
7695
            getResizer(target, 'data-column').each(column => {
7696
              const delta = getDelta(target, 'left');
7697
              remove$7(target, 'data-initial-left');
7698
              events.trigger.adjustWidth(table, delta, parseInt(column, 10));
7699
            });
7700
            refresh(wire, table);
7701
          });
7702
        });
7703
      });
7704
      const handler = (target, dir) => {
7705
        events.trigger.startAdjust();
7706
        mutation.assign(target);
7707
        set$2(target, 'data-initial-' + dir, getCssValue(target, dir));
7708
        add(target, resizeBarDragging);
7709
        set$1(target, 'opacity', '0.2');
7710
        resizing.go(wire.parent());
7711
      };
7712
      const mousedown = bind(wire.parent(), 'mousedown', event => {
7713
        if (isRowBar(event.target)) {
7714
          handler(event.target, 'top');
7715
        }
7716
        if (isColBar(event.target)) {
7717
          handler(event.target, 'left');
7718
        }
7719
      });
7720
      const isRoot = e => {
7721
        return eq$1(e, wire.view());
7722
      };
7723
      const findClosestEditableTable = target => closest$1(target, 'table', isRoot).filter(isEditable$1);
7724
      const mouseover = bind(wire.view(), 'mouseover', event => {
7725
        findClosestEditableTable(event.target).fold(() => {
7726
          if (inBody(event.target)) {
7727
            destroy(wire);
7728
          }
7729
        }, table => {
7730
          if (resizing.isActive()) {
7731
            hoverTable = Optional.some(table);
7732
            refresh(wire, table);
7733
          }
7734
        });
7735
      });
7736
      const destroy$1 = () => {
7737
        mousedown.unbind();
7738
        mouseover.unbind();
7739
        resizing.destroy();
7740
        destroy(wire);
7741
      };
7742
      const refresh$1 = tbl => {
7743
        refresh(wire, tbl);
7744
      };
7745
      const events = create$1({
7746
        adjustHeight: Event([
7747
          'table',
7748
          'delta',
7749
          'row'
7750
        ]),
7751
        adjustWidth: Event([
7752
          'table',
7753
          'delta',
7754
          'column'
7755
        ]),
7756
        startAdjust: Event([])
7757
      });
7758
      return {
7759
        destroy: destroy$1,
7760
        refresh: refresh$1,
7761
        on: resizing.on,
7762
        off: resizing.off,
7763
        hideBars: curry(hide, wire),
7764
        showBars: curry(show, wire),
7765
        events: events.registry
7766
      };
7767
    };
7768
 
7769
    const create = (wire, resizing, lazySizing) => {
7770
      const hdirection = height;
7771
      const vdirection = width;
7772
      const manager = BarManager(wire);
7773
      const events = create$1({
7774
        beforeResize: Event([
7775
          'table',
7776
          'type'
7777
        ]),
7778
        afterResize: Event([
7779
          'table',
7780
          'type'
7781
        ]),
7782
        startDrag: Event([])
7783
      });
7784
      manager.events.adjustHeight.bind(event => {
7785
        const table = event.table;
7786
        events.trigger.beforeResize(table, 'row');
7787
        const delta = hdirection.delta(event.delta, table);
7788
        adjustHeight(table, delta, event.row, hdirection);
7789
        events.trigger.afterResize(table, 'row');
7790
      });
7791
      manager.events.startAdjust.bind(_event => {
7792
        events.trigger.startDrag();
7793
      });
7794
      manager.events.adjustWidth.bind(event => {
7795
        const table = event.table;
7796
        events.trigger.beforeResize(table, 'col');
7797
        const delta = vdirection.delta(event.delta, table);
7798
        const tableSize = lazySizing(table);
7799
        adjustWidth(table, delta, event.column, resizing, tableSize);
7800
        events.trigger.afterResize(table, 'col');
7801
      });
7802
      return {
7803
        on: manager.on,
7804
        off: manager.off,
7805
        refreshBars: manager.refresh,
7806
        hideBars: manager.hideBars,
7807
        showBars: manager.showBars,
7808
        destroy: manager.destroy,
7809
        events: events.registry
7810
      };
7811
    };
7812
    const TableResize = { create };
7813
 
7814
    const only = (element, isResizable) => {
7815
      const parent = isDocument(element) ? documentElement(element) : element;
7816
      return {
7817
        parent: constant(parent),
7818
        view: constant(element),
7819
        origin: constant(SugarPosition(0, 0)),
7820
        isResizable
7821
      };
7822
    };
7823
    const detached = (editable, chrome, isResizable) => {
7824
      const origin = () => absolute(chrome);
7825
      return {
7826
        parent: constant(chrome),
7827
        view: constant(editable),
7828
        origin,
7829
        isResizable
7830
      };
7831
    };
7832
    const body = (editable, chrome, isResizable) => {
7833
      return {
7834
        parent: constant(chrome),
7835
        view: constant(editable),
7836
        origin: constant(SugarPosition(0, 0)),
7837
        isResizable
7838
      };
7839
    };
7840
    const ResizeWire = {
7841
      only,
7842
      detached,
7843
      body
7844
    };
7845
 
7846
    const createContainer = () => {
7847
      const container = SugarElement.fromTag('div');
7848
      setAll(container, {
7849
        position: 'static',
7850
        height: '0',
7851
        width: '0',
7852
        padding: '0',
7853
        margin: '0',
7854
        border: '0'
7855
      });
7856
      append$1(body$1(), container);
7857
      return container;
7858
    };
7859
    const get = (editor, isResizable) => {
7860
      return editor.inline ? ResizeWire.body(SugarElement.fromDom(editor.getBody()), createContainer(), isResizable) : ResizeWire.only(SugarElement.fromDom(editor.getDoc()), isResizable);
7861
    };
7862
    const remove = (editor, wire) => {
7863
      if (editor.inline) {
7864
        remove$6(wire.parent());
7865
      }
7866
    };
7867
 
7868
    const isTable = node => isNonNullable(node) && node.nodeName === 'TABLE';
7869
    const barResizerPrefix = 'bar-';
7870
    const isResizable = elm => get$b(elm, 'data-mce-resize') !== 'false';
7871
    const syncPixels = table => {
7872
      const warehouse = Warehouse.fromTable(table);
7873
      if (!Warehouse.hasColumns(warehouse)) {
7874
        each$2(cells$1(table), cell => {
7875
          const computedWidth = get$a(cell, 'width');
7876
          set$1(cell, 'width', computedWidth);
7877
          remove$7(cell, 'width');
7878
        });
7879
      }
7880
    };
7881
    const TableResizeHandler = editor => {
7882
      const selectionRng = value();
7883
      const tableResize = value();
7884
      const resizeWire = value();
7885
      let startW;
7886
      let startRawW;
7887
      const lazySizing = table => get$5(editor, table);
7888
      const lazyResizingBehaviour = () => isPreserveTableColumnResizing(editor) ? preserveTable() : resizeTable();
7889
      const getNumColumns = table => getGridSize(table).columns;
7890
      const afterCornerResize = (table, origin, width) => {
7891
        const isRightEdgeResize = endsWith(origin, 'e');
7892
        if (startRawW === '') {
7893
          convertToPercentSize(table);
7894
        }
7895
        if (width !== startW && startRawW !== '') {
7896
          set$1(table, 'width', startRawW);
7897
          const resizing = lazyResizingBehaviour();
7898
          const tableSize = lazySizing(table);
7899
          const col = isPreserveTableColumnResizing(editor) || isRightEdgeResize ? getNumColumns(table) - 1 : 0;
7900
          adjustWidth(table, width - startW, col, resizing, tableSize);
7901
        } else if (isPercentage$1(startRawW)) {
7902
          const percentW = parseFloat(startRawW.replace('%', ''));
7903
          const targetPercentW = width * percentW / startW;
7904
          set$1(table, 'width', targetPercentW + '%');
7905
        }
7906
        if (isPixel(startRawW)) {
7907
          syncPixels(table);
7908
        }
7909
      };
7910
      const destroy = () => {
7911
        tableResize.on(sz => {
7912
          sz.destroy();
7913
        });
7914
        resizeWire.on(w => {
7915
          remove(editor, w);
7916
        });
7917
      };
7918
      editor.on('init', () => {
7919
        const rawWire = get(editor, isResizable);
7920
        resizeWire.set(rawWire);
7921
        if (hasTableObjectResizing(editor) && hasTableResizeBars(editor)) {
7922
          const resizing = lazyResizingBehaviour();
7923
          const sz = TableResize.create(rawWire, resizing, lazySizing);
7924
          sz.on();
7925
          sz.events.startDrag.bind(_event => {
7926
            selectionRng.set(editor.selection.getRng());
7927
          });
7928
          sz.events.beforeResize.bind(event => {
7929
            const rawTable = event.table.dom;
7930
            fireObjectResizeStart(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
7931
          });
7932
          sz.events.afterResize.bind(event => {
7933
            const table = event.table;
7934
            const rawTable = table.dom;
7935
            removeDataStyle(table);
7936
            selectionRng.on(rng => {
7937
              editor.selection.setRng(rng);
7938
              editor.focus();
7939
            });
7940
            fireObjectResized(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
7941
            editor.undoManager.add();
7942
          });
7943
          tableResize.set(sz);
7944
        }
7945
      });
7946
      editor.on('ObjectResizeStart', e => {
7947
        const targetElm = e.target;
7948
        if (isTable(targetElm)) {
7949
          const table = SugarElement.fromDom(targetElm);
7950
          each$2(editor.dom.select('.mce-clonedresizable'), clone => {
7951
            editor.dom.addClass(clone, 'mce-' + getTableColumnResizingBehaviour(editor) + '-columns');
7952
          });
7953
          if (!isPixelSizing(table) && isTablePixelsForced(editor)) {
7954
            convertToPixelSize(table);
7955
          } else if (!isPercentSizing(table) && isTablePercentagesForced(editor)) {
7956
            convertToPercentSize(table);
7957
          }
7958
          if (isNoneSizing(table) && startsWith(e.origin, barResizerPrefix)) {
7959
            convertToPercentSize(table);
7960
          }
7961
          startW = e.width;
7962
          startRawW = isTableResponsiveForced(editor) ? '' : getRawWidth(editor, targetElm).getOr('');
7963
        }
7964
      });
7965
      editor.on('ObjectResized', e => {
7966
        const targetElm = e.target;
7967
        if (isTable(targetElm)) {
7968
          const table = SugarElement.fromDom(targetElm);
7969
          const origin = e.origin;
7970
          if (startsWith(origin, 'corner-')) {
7971
            afterCornerResize(table, origin, e.width);
7972
          }
7973
          removeDataStyle(table);
7974
          fireTableModified(editor, table.dom, styleModified);
7975
        }
7976
      });
7977
      editor.on('SwitchMode', () => {
7978
        tableResize.on(resize => {
7979
          if (editor.mode.isReadOnly()) {
7980
            resize.hideBars();
7981
          } else {
7982
            resize.showBars();
7983
          }
7984
        });
7985
      });
7986
      editor.on('dragstart dragend', e => {
7987
        tableResize.on(resize => {
7988
          if (e.type === 'dragstart') {
7989
            resize.hideBars();
7990
            resize.off();
7991
          } else {
7992
            resize.on();
7993
            resize.showBars();
7994
          }
7995
        });
7996
      });
7997
      editor.on('remove', () => {
7998
        destroy();
7999
      });
8000
      const refresh = table => {
8001
        tableResize.on(resize => resize.refreshBars(SugarElement.fromDom(table)));
8002
      };
8003
      const hide = () => {
8004
        tableResize.on(resize => resize.hideBars());
8005
      };
8006
      const show = () => {
8007
        tableResize.on(resize => resize.showBars());
8008
      };
8009
      return {
8010
        refresh,
8011
        hide,
8012
        show
8013
      };
8014
    };
8015
 
8016
    const setupTable = editor => {
8017
      register(editor);
8018
      const resizeHandler = TableResizeHandler(editor);
8019
      const cellSelectionHandler = TableCellSelectionHandler(editor, resizeHandler);
8020
      const actions = TableActions(editor, resizeHandler, cellSelectionHandler);
8021
      registerCommands(editor, actions);
8022
      registerQueryCommands(editor, actions);
8023
      registerEvents(editor, actions);
8024
      return {
8025
        getSelectedCells: cellSelectionHandler.getSelectedCells,
8026
        clearSelectedCells: cellSelectionHandler.clearSelectedCells
8027
      };
8028
    };
8029
 
8030
    const DomModel = editor => {
8031
      const table = setupTable(editor);
8032
      return { table };
8033
    };
8034
    var Model = () => {
8035
      global$1.add('dom', DomModel);
8036
    };
8037
 
8038
    Model();
8039
 
8040
})();