Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

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