@textbus/platform-browser 5.1.6 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2909 +0,0 @@
1
- import 'reflect-metadata';
2
- import { Slot, Textbus, Adapter, Controller, Selection, RootComponentRef, Scheduler, ContentType, Event, invokeListener, Keyboard, Commander, makeError, NativeSelectionBridge, FocusManager, Component, Registry } from '@textbus/core';
3
- import { Subject, filter, fromEvent, delay, Subscription, distinctUntilChanged, merge, map, Observable } from '@tanbo/stream';
4
- import { InjectionToken, Injectable, Inject, Optional } from '@viewfly/core';
5
-
6
- function createElement(tagName, options = {}) {
7
- const el = document.createElement(tagName);
8
- if (options.classes) {
9
- el.classList.add(...options.classes);
10
- }
11
- if (options.attrs) {
12
- Object.keys(options.attrs).forEach(key => {
13
- el.setAttribute(key, options.attrs[key]);
14
- });
15
- }
16
- if (options.props) {
17
- Object.keys(options.props).forEach(key => {
18
- el[key] = options.props[key];
19
- });
20
- }
21
- if (options.styles) {
22
- Object.assign(el.style, options.styles);
23
- }
24
- if (options.children) {
25
- options.children.filter(i => i).forEach(item => {
26
- el.appendChild(item);
27
- });
28
- }
29
- if (options.on) {
30
- Object.keys(options.on).forEach(key => {
31
- el.addEventListener(key, options.on[key]);
32
- });
33
- }
34
- return el;
35
- }
36
- function getLayoutRectByRange(range) {
37
- let { startContainer, startOffset } = range;
38
- if (startContainer.nodeType === Node.TEXT_NODE) {
39
- if (startOffset > 0) {
40
- return range.getBoundingClientRect();
41
- }
42
- const parentNode = startContainer.parentNode;
43
- startOffset = Array.from(parentNode.childNodes).indexOf(startContainer);
44
- startContainer = parentNode;
45
- }
46
- const beforeNode = startContainer.childNodes[startOffset - 1];
47
- if (beforeNode) {
48
- if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== 'br') {
49
- const rect = beforeNode.getBoundingClientRect();
50
- return {
51
- left: rect.right,
52
- top: rect.top,
53
- width: range.collapsed ? 1 : rect.width,
54
- height: rect.height
55
- };
56
- }
57
- else if (beforeNode.nodeType === Node.TEXT_NODE) {
58
- const range2 = document.createRange();
59
- range2.setStart(beforeNode, beforeNode.textContent.length);
60
- range2.setEnd(beforeNode, beforeNode.textContent.length);
61
- const rect = range2.getBoundingClientRect();
62
- return {
63
- left: rect.right,
64
- top: rect.top,
65
- width: range.collapsed ? 1 : rect.width,
66
- height: rect.height
67
- };
68
- }
69
- }
70
- const offsetNode = startContainer.childNodes[startOffset];
71
- let isInsertBefore = false;
72
- if (!offsetNode) {
73
- const lastChild = startContainer.lastChild;
74
- if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) {
75
- const rect = lastChild.getBoundingClientRect();
76
- return {
77
- left: rect.right,
78
- top: rect.top,
79
- width: range.collapsed ? 1 : rect.width,
80
- height: rect.height
81
- };
82
- }
83
- }
84
- if (offsetNode) {
85
- if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') {
86
- const rect = offsetNode.getBoundingClientRect();
87
- return {
88
- left: rect.left,
89
- top: rect.top,
90
- width: range.collapsed ? 1 : rect.width,
91
- height: rect.height
92
- };
93
- }
94
- isInsertBefore = true;
95
- }
96
- const span = startContainer.ownerDocument.createElement('span');
97
- span.innerText = '\u200b';
98
- span.style.display = 'inline-block';
99
- if (isInsertBefore) {
100
- startContainer.insertBefore(span, offsetNode);
101
- }
102
- else {
103
- startContainer.appendChild(span);
104
- }
105
- const rect = span.getBoundingClientRect();
106
- startContainer.removeChild(span);
107
- return {
108
- left: rect.left,
109
- top: rect.top,
110
- width: range.collapsed ? 1 : rect.width,
111
- height: rect.height
112
- };
113
- }
114
-
115
- const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
116
- const isMac = () => /mac os/i.test(navigator.userAgent);
117
- const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
118
- const isFirefox = () => /Firefox/.test(navigator.userAgent);
119
- const isMobileBrowser = () => /Android|iPhone|iPad/.test(navigator.userAgent);
120
-
121
- /******************************************************************************
122
- Copyright (c) Microsoft Corporation.
123
-
124
- Permission to use, copy, modify, and/or distribute this software for any
125
- purpose with or without fee is hereby granted.
126
-
127
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
128
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
129
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
130
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
131
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
132
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
133
- PERFORMANCE OF THIS SOFTWARE.
134
- ***************************************************************************** */
135
- /* global Reflect, Promise, SuppressedError, Symbol */
136
-
137
-
138
- function __decorate(decorators, target, key, desc) {
139
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
140
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
141
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
142
- return c > 3 && r && Object.defineProperty(target, key, r), r;
143
- }
144
-
145
- function __param(paramIndex, decorator) {
146
- return function (target, key) { decorator(target, key, paramIndex); }
147
- }
148
-
149
- function __metadata(metadataKey, metadataValue) {
150
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
151
- }
152
-
153
- function __awaiter(thisArg, _arguments, P, generator) {
154
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
155
- return new (P || (P = Promise))(function (resolve, reject) {
156
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
157
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
158
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
159
- step((generator = generator.apply(thisArg, _arguments || [])).next());
160
- });
161
- }
162
-
163
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
164
- var e = new Error(message);
165
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
166
- };
167
-
168
- /**
169
- * 编辑器可选项依赖注入 token
170
- */
171
- const EDITOR_OPTIONS = new InjectionToken('EDITOR_OPTIONS');
172
- /**
173
- * 编辑器容器依赖注入 token
174
- */
175
- const VIEW_CONTAINER = new InjectionToken('VIEW_CONTAINER');
176
- /**
177
- * 编辑器容器依赖注入 token
178
- */
179
- const VIEW_DOCUMENT = new InjectionToken('VIEW_DOCUMENT');
180
- /**
181
- * 编辑器容器遮罩层 token
182
- */
183
- const VIEW_MASK = new InjectionToken('VIEW_MASK');
184
-
185
- var Parser_1;
186
- /**
187
- * 用于解析 HTML,并把 HTML 内容转换为 Textbus 可以支持的组件或插槽数据
188
- */
189
- let Parser = Parser_1 = class Parser {
190
- static parseHTML(html) {
191
- return new DOMParser().parseFromString(html, 'text/html').body;
192
- }
193
- constructor(options, textbus) {
194
- Object.defineProperty(this, "textbus", {
195
- enumerable: true,
196
- configurable: true,
197
- writable: true,
198
- value: textbus
199
- });
200
- Object.defineProperty(this, "componentLoaders", {
201
- enumerable: true,
202
- configurable: true,
203
- writable: true,
204
- value: void 0
205
- });
206
- Object.defineProperty(this, "formatLoaders", {
207
- enumerable: true,
208
- configurable: true,
209
- writable: true,
210
- value: void 0
211
- });
212
- Object.defineProperty(this, "attributeLoaders", {
213
- enumerable: true,
214
- configurable: true,
215
- writable: true,
216
- value: void 0
217
- });
218
- const componentLoaders = [
219
- ...(options.componentLoaders || [])
220
- ];
221
- const formatLoaders = [
222
- ...(options.formatLoaders || [])
223
- ];
224
- const attributeLoaders = [
225
- ...(options.attributeLoaders || [])
226
- ];
227
- // options.imports?.forEach(i => {
228
- // componentLoaders.push(...(i.componentLoaders || []))
229
- // formatLoaders.push(...(i.formatLoaders || []))
230
- // })
231
- this.componentLoaders = componentLoaders;
232
- this.formatLoaders = formatLoaders;
233
- this.attributeLoaders = attributeLoaders;
234
- }
235
- /**
236
- * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素
237
- * @param html
238
- * @param rootComponentLoader
239
- */
240
- parseDoc(html, rootComponentLoader) {
241
- const element = typeof html === 'string' ? Parser_1.parseHTML(html) : html;
242
- return rootComponentLoader.read(element, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
243
- return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
244
- });
245
- }
246
- /**
247
- * 将一段 HTML 或 DOM 元素解析到指定插槽
248
- * @param html
249
- * @param rootSlot
250
- */
251
- parse(html, rootSlot) {
252
- const element = typeof html === 'string' ? Parser_1.parseHTML(html) : html;
253
- return this.readFormats(element, rootSlot);
254
- }
255
- readComponent(el, slot) {
256
- if (el.nodeType === Node.ELEMENT_NODE) {
257
- if (el.tagName === 'BR') {
258
- slot.insert('\n');
259
- return;
260
- }
261
- const schema = [...slot.schema];
262
- for (const t of this.componentLoaders) {
263
- if (t.match(el, schema)) {
264
- const result = t.read(el, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
265
- return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
266
- });
267
- if (!result) {
268
- return;
269
- }
270
- if (result instanceof Slot) {
271
- result.toDelta().forEach(i => slot.insert(i.insert, i.formats));
272
- return;
273
- }
274
- slot.insert(result);
275
- return;
276
- }
277
- }
278
- this.readFormats(el, slot);
279
- }
280
- else if (el.nodeType === Node.TEXT_NODE) {
281
- this.readText(slot, el);
282
- }
283
- }
284
- readText(slot, el) {
285
- const textContent = el.textContent;
286
- if (/^\s*[\r\n\u200b]+\s*$/.test(textContent)) {
287
- return;
288
- }
289
- slot.insert(textContent);
290
- }
291
- readFormats(el, slot) {
292
- const formats = this.formatLoaders.filter(f => {
293
- return f.match(el);
294
- }).map(f => {
295
- return f.read(el);
296
- });
297
- const startIndex = slot.index;
298
- let startNode = el.firstChild;
299
- while (startNode) {
300
- this.readComponent(startNode, slot);
301
- startNode = startNode.nextSibling;
302
- }
303
- const endIndex = slot.index;
304
- this.applyFormats(slot, formats.map(i => {
305
- return {
306
- formatter: i.formatter,
307
- value: i.value,
308
- startIndex,
309
- endIndex
310
- };
311
- }));
312
- slot.retain(endIndex);
313
- return slot;
314
- }
315
- readSlot(childSlot, slotRootElement, slotContentElement) {
316
- if (slotRootElement.nodeType === Node.ELEMENT_NODE) {
317
- this.attributeLoaders.filter(a => {
318
- return a.match(slotRootElement);
319
- }).forEach(a => {
320
- const r = a.read(slotRootElement);
321
- childSlot.setAttribute(r.attribute, r.value);
322
- });
323
- }
324
- if (slotContentElement.nodeType === Node.ELEMENT_NODE) {
325
- this.readFormats(slotContentElement, childSlot);
326
- }
327
- else {
328
- this.readText(childSlot, slotContentElement);
329
- }
330
- return childSlot;
331
- }
332
- applyFormats(slot, formatItems) {
333
- slot.background(() => {
334
- formatItems.forEach(i => {
335
- slot.retain(i.startIndex);
336
- slot.retain(i.endIndex - i.startIndex, i.formatter, i.value);
337
- });
338
- });
339
- }
340
- };
341
- Parser = Parser_1 = __decorate([
342
- Injectable(),
343
- __param(0, Inject(EDITOR_OPTIONS)),
344
- __metadata("design:paramtypes", [Object, Textbus])
345
- ], Parser);
346
-
347
- class Input {
348
- }
349
-
350
- class DomAdapter extends Adapter {
351
- constructor() {
352
- super(...arguments);
353
- Object.defineProperty(this, "onViewUpdated", {
354
- enumerable: true,
355
- configurable: true,
356
- writable: true,
357
- value: new Subject()
358
- });
359
- Object.defineProperty(this, "host", {
360
- enumerable: true,
361
- configurable: true,
362
- writable: true,
363
- value: createElement('div', {
364
- styles: {
365
- cursor: 'text',
366
- wordBreak: 'break-all',
367
- boxSizing: 'border-box',
368
- flex: 1,
369
- outline: 'none'
370
- },
371
- attrs: {
372
- 'data-textbus-view': VIEW_DOCUMENT,
373
- },
374
- props: {
375
- id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)
376
- }
377
- })
378
- });
379
- }
380
- }
381
-
382
- /**
383
- * Textbus PC 端选区桥接实现
384
- */
385
- let SelectionBridge = class SelectionBridge {
386
- constructor(config, textbus, controller, selection, rootComponentRef, input, scheduler, domAdapter) {
387
- Object.defineProperty(this, "config", {
388
- enumerable: true,
389
- configurable: true,
390
- writable: true,
391
- value: config
392
- });
393
- Object.defineProperty(this, "selection", {
394
- enumerable: true,
395
- configurable: true,
396
- writable: true,
397
- value: selection
398
- });
399
- Object.defineProperty(this, "rootComponentRef", {
400
- enumerable: true,
401
- configurable: true,
402
- writable: true,
403
- value: rootComponentRef
404
- });
405
- Object.defineProperty(this, "input", {
406
- enumerable: true,
407
- configurable: true,
408
- writable: true,
409
- value: input
410
- });
411
- Object.defineProperty(this, "scheduler", {
412
- enumerable: true,
413
- configurable: true,
414
- writable: true,
415
- value: scheduler
416
- });
417
- Object.defineProperty(this, "domAdapter", {
418
- enumerable: true,
419
- configurable: true,
420
- writable: true,
421
- value: domAdapter
422
- });
423
- Object.defineProperty(this, "onSelectionChange", {
424
- enumerable: true,
425
- configurable: true,
426
- writable: true,
427
- value: void 0
428
- });
429
- Object.defineProperty(this, "nativeSelection", {
430
- enumerable: true,
431
- configurable: true,
432
- writable: true,
433
- value: document.getSelection()
434
- });
435
- Object.defineProperty(this, "syncSelectionFromNativeSelectionChange", {
436
- enumerable: true,
437
- configurable: true,
438
- writable: true,
439
- value: true
440
- });
441
- Object.defineProperty(this, "selectionChangeEvent", {
442
- enumerable: true,
443
- configurable: true,
444
- writable: true,
445
- value: new Subject()
446
- });
447
- Object.defineProperty(this, "subs", {
448
- enumerable: true,
449
- configurable: true,
450
- writable: true,
451
- value: []
452
- });
453
- Object.defineProperty(this, "sub", {
454
- enumerable: true,
455
- configurable: true,
456
- writable: true,
457
- value: void 0
458
- });
459
- Object.defineProperty(this, "connector", {
460
- enumerable: true,
461
- configurable: true,
462
- writable: true,
463
- value: null
464
- });
465
- Object.defineProperty(this, "ignoreSelectionChange", {
466
- enumerable: true,
467
- configurable: true,
468
- writable: true,
469
- value: false
470
- });
471
- Object.defineProperty(this, "changeFromUser", {
472
- enumerable: true,
473
- configurable: true,
474
- writable: true,
475
- value: false
476
- });
477
- Object.defineProperty(this, "docContainer", {
478
- enumerable: true,
479
- configurable: true,
480
- writable: true,
481
- value: void 0
482
- });
483
- Object.defineProperty(this, "cacheCaretPositionTimer", {
484
- enumerable: true,
485
- configurable: true,
486
- writable: true,
487
- value: void 0
488
- });
489
- Object.defineProperty(this, "oldCaretPosition", {
490
- enumerable: true,
491
- configurable: true,
492
- writable: true,
493
- value: void 0
494
- });
495
- this.docContainer = textbus.get(VIEW_DOCUMENT);
496
- this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {
497
- return !controller.readonly;
498
- }));
499
- this.sub = this.onSelectionChange.subscribe((r) => {
500
- if (r) {
501
- input.focus(r, this.changeFromUser);
502
- }
503
- else {
504
- input.blur();
505
- }
506
- });
507
- this.sub.add(fromEvent(document, 'focusin').subscribe(ev => {
508
- let target = ev.target;
509
- if (/^(input|textarea|select)$/i.test(target.nodeName)) {
510
- if (target.tagName.toLowerCase() === 'input' && /^(range|date)$/.test(target.type)) {
511
- return;
512
- }
513
- this.ignoreSelectionChange = true;
514
- return;
515
- }
516
- if (!config.useContentEditable) {
517
- while (target) {
518
- if (target.contentEditable === 'true') {
519
- this.ignoreSelectionChange = true;
520
- return;
521
- }
522
- target = target.parentNode;
523
- }
524
- }
525
- }));
526
- this.sub.add(fromEvent(document, 'focusout').subscribe(() => {
527
- this.ignoreSelectionChange = false;
528
- }));
529
- }
530
- connect(connector) {
531
- this.disConnect();
532
- this.connector = connector;
533
- this.syncSelection(connector);
534
- this.listen(connector);
535
- }
536
- disConnect() {
537
- this.connector = null;
538
- this.unListen();
539
- }
540
- getRect(location) {
541
- const { focus, anchor } = this.getPositionByRange({
542
- focusOffset: location.offset,
543
- anchorOffset: location.offset,
544
- focusSlot: location.slot,
545
- anchorSlot: location.slot
546
- });
547
- if (!focus || !anchor) {
548
- return null;
549
- }
550
- const nativeRange = document.createRange();
551
- nativeRange.setStart(focus.node, focus.offset);
552
- nativeRange.collapse();
553
- return getLayoutRectByRange(nativeRange);
554
- }
555
- restore(abstractSelection, fromLocal) {
556
- this.changeFromUser = fromLocal;
557
- if (this.ignoreSelectionChange || !this.connector) {
558
- return;
559
- }
560
- this.unListen();
561
- if (!abstractSelection) {
562
- this.nativeSelection.removeAllRanges();
563
- this.selectionChangeEvent.next(null);
564
- this.listen(this.connector);
565
- return;
566
- }
567
- const { focus, anchor } = this.getPositionByRange(abstractSelection);
568
- if (!focus || !anchor) {
569
- this.nativeSelection.removeAllRanges();
570
- this.selectionChangeEvent.next(null);
571
- this.listen(this.connector);
572
- return;
573
- }
574
- function tryOffset(position) {
575
- if (!position.node) {
576
- return;
577
- }
578
- if (position.node.nodeType === Node.TEXT_NODE) {
579
- const len = position.node.textContent.length;
580
- if (position.offset > len) {
581
- position.offset = len;
582
- }
583
- }
584
- else if (position.node.nodeType === Node.ELEMENT_NODE) {
585
- const len = position.node.childNodes.length;
586
- if (position.offset > len) {
587
- position.offset = len;
588
- }
589
- }
590
- }
591
- try {
592
- tryOffset(focus);
593
- tryOffset(anchor);
594
- this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
595
- }
596
- catch (e) {
597
- setTimeout(() => {
598
- throw e;
599
- });
600
- }
601
- if (this.nativeSelection.rangeCount) {
602
- const nativeRange = this.nativeSelection.getRangeAt(0);
603
- this.selectionChangeEvent.next(nativeRange);
604
- }
605
- else {
606
- this.selectionChangeEvent.next(null);
607
- }
608
- // hack start 浏览器会触发上面选区更改事件
609
- const bind = () => {
610
- if (this.connector) {
611
- this.listen(this.connector);
612
- }
613
- };
614
- if (fromLocal) {
615
- Promise.resolve().then(bind);
616
- return;
617
- }
618
- if (typeof requestIdleCallback === 'function') {
619
- requestIdleCallback(bind);
620
- }
621
- else {
622
- setTimeout(bind, 30);
623
- }
624
- // hack end
625
- }
626
- destroy() {
627
- this.subs.forEach(i => i.unsubscribe());
628
- this.sub.unsubscribe();
629
- }
630
- getPositionByRange(abstractSelection) {
631
- let focus;
632
- let anchor;
633
- try {
634
- focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot, abstractSelection.focusOffset);
635
- anchor = focus;
636
- if (abstractSelection.anchorSlot !== abstractSelection.focusSlot ||
637
- abstractSelection.anchorOffset !== abstractSelection.focusOffset) {
638
- anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot, abstractSelection.anchorOffset);
639
- }
640
- return {
641
- focus,
642
- anchor
643
- };
644
- }
645
- catch (e) {
646
- return {
647
- focus: null,
648
- anchor: null
649
- };
650
- }
651
- }
652
- getPreviousLinePositionByCurrent(position) {
653
- return this.getLinePosition(position, false);
654
- }
655
- getNextLinePositionByCurrent(position) {
656
- return this.getLinePosition(position, true);
657
- }
658
- getLinePosition(currentPosition, toNext) {
659
- clearTimeout(this.cacheCaretPositionTimer);
660
- let p;
661
- if (this.oldCaretPosition) {
662
- p = toNext ?
663
- this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :
664
- this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
665
- }
666
- else {
667
- this.oldCaretPosition = this.getRect(currentPosition);
668
- p = toNext ?
669
- this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :
670
- this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
671
- }
672
- this.cacheCaretPositionTimer = setTimeout(() => {
673
- this.oldCaretPosition = null;
674
- }, 3000);
675
- return p;
676
- }
677
- /**
678
- * 获取选区向上移动一行的位置。
679
- * @param currentPosition
680
- * @param startLeft 参考位置。
681
- */
682
- getPreviousLinePositionByOffset(currentPosition, startLeft) {
683
- let isToPrevLine = false;
684
- let loopCount = 0;
685
- let minLeft = startLeft;
686
- let focusSlot = currentPosition.slot;
687
- let focusOffset = currentPosition.offset;
688
- let minTop = this.getRect({
689
- slot: focusSlot,
690
- offset: focusOffset
691
- }).top;
692
- let position;
693
- let oldPosition;
694
- let oldLeft = 0;
695
- while (true) {
696
- loopCount++;
697
- position = this.selection.getPreviousPositionByPosition(focusSlot, focusOffset);
698
- focusSlot = position.slot;
699
- focusOffset = position.offset;
700
- const rect2 = this.getRect(position);
701
- if (!isToPrevLine) {
702
- if (rect2.left > minLeft || rect2.top + rect2.height <= minTop) {
703
- isToPrevLine = true;
704
- }
705
- else if (rect2.left === minLeft && rect2.top === minTop) {
706
- return position;
707
- }
708
- minLeft = rect2.left;
709
- minTop = rect2.top;
710
- // oldPosition = position
711
- }
712
- if (isToPrevLine) {
713
- if (rect2.left <= startLeft) {
714
- return position;
715
- }
716
- if (oldPosition) {
717
- if (rect2.left >= oldLeft) {
718
- return oldPosition;
719
- }
720
- }
721
- oldLeft = rect2.left;
722
- oldPosition = position;
723
- }
724
- if (loopCount > 10000) {
725
- break;
726
- }
727
- }
728
- return position || {
729
- offset: 0,
730
- slot: focusSlot
731
- };
732
- }
733
- /**
734
- * 获取选区向下移动一行的位置。
735
- * @param currentPosition
736
- * @param startLeft 参考位置。
737
- */
738
- getNextLinePositionByOffset(currentPosition, startLeft) {
739
- let isToNextLine = false;
740
- let loopCount = 0;
741
- let maxRight = startLeft;
742
- let focusSlot = currentPosition.slot;
743
- let focusOffset = currentPosition.offset;
744
- const rect = this.getRect({
745
- slot: focusSlot,
746
- offset: focusOffset
747
- });
748
- let minTop = rect.top;
749
- let oldPosition;
750
- let oldLeft = 0;
751
- while (true) {
752
- loopCount++;
753
- const position = this.selection.getNextPositionByPosition(focusSlot, focusOffset);
754
- focusSlot = position.slot;
755
- focusOffset = position.offset;
756
- const rect2 = this.getRect(position);
757
- if (!isToNextLine) {
758
- if (rect2.left < maxRight || rect2.top >= minTop + rect.height) {
759
- isToNextLine = true;
760
- }
761
- else if (rect2.left === maxRight && rect2.top === minTop) {
762
- return position;
763
- }
764
- maxRight = rect2.left;
765
- minTop = rect2.top;
766
- oldPosition = position;
767
- }
768
- if (isToNextLine) {
769
- if (rect2.left > startLeft) {
770
- return oldPosition;
771
- }
772
- if (oldPosition) {
773
- if (rect2.left <= oldLeft) {
774
- return oldPosition;
775
- }
776
- }
777
- oldPosition = position;
778
- oldLeft = rect2.left;
779
- }
780
- if (loopCount > 10000) {
781
- break;
782
- }
783
- }
784
- return oldPosition || {
785
- offset: focusSlot.length,
786
- slot: focusSlot
787
- };
788
- }
789
- unListen() {
790
- this.subs.forEach(i => i.unsubscribe());
791
- this.subs = [];
792
- }
793
- listen(connector) {
794
- if (!this.config.useContentEditable) {
795
- const selection = this.nativeSelection;
796
- this.subs.push(fromEvent(this.docContainer, 'mousedown').subscribe(ev => {
797
- if (this.ignoreSelectionChange || ev.button === 2) {
798
- return;
799
- }
800
- if (!ev.shiftKey) {
801
- selection.removeAllRanges();
802
- }
803
- }));
804
- }
805
- let isUpdating = false;
806
- this.subs.push(this.scheduler.onDocChange.subscribe(() => {
807
- isUpdating = true;
808
- }), this.scheduler.onDocChanged.pipe(delay()).subscribe(() => {
809
- isUpdating = false;
810
- }), fromEvent(document, 'selectionchange').subscribe(() => {
811
- if (isUpdating) {
812
- return;
813
- }
814
- if (this.syncSelectionFromNativeSelectionChange) {
815
- this.syncSelection(connector);
816
- }
817
- }));
818
- }
819
- syncSelection(connector) {
820
- var _a;
821
- const selection = this.nativeSelection;
822
- this.changeFromUser = true;
823
- if (this.ignoreSelectionChange ||
824
- this.input.composition ||
825
- selection.rangeCount === 0 ||
826
- !this.docContainer.contains(selection.anchorNode) ||
827
- this.rootComponentRef.component.slots.length === 0) {
828
- return;
829
- }
830
- const rawRange = selection.getRangeAt(0);
831
- const nativeRange = rawRange.cloneRange();
832
- const isFocusEnd = selection.focusNode === nativeRange.endContainer && selection.focusOffset === nativeRange.endOffset;
833
- const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset;
834
- if (!this.docContainer.contains(selection.focusNode)) {
835
- if (isFocusEnd) {
836
- const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(0));
837
- if (!nativeNode) {
838
- return;
839
- }
840
- nativeRange.setEndAfter(nativeNode.lastChild);
841
- }
842
- else {
843
- const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(-1));
844
- if (!nativeNode) {
845
- return;
846
- }
847
- nativeRange.setStartBefore(nativeNode.firstChild);
848
- }
849
- }
850
- const startPosition = this.getCorrectedPosition(nativeRange.startContainer, nativeRange.startOffset, isFocusStart);
851
- const endPosition = nativeRange.collapsed ?
852
- startPosition :
853
- this.getCorrectedPosition(nativeRange.endContainer, nativeRange.endOffset, isFocusEnd);
854
- if ([Node.ELEMENT_NODE, Node.TEXT_NODE].includes((_a = nativeRange.commonAncestorContainer) === null || _a === void 0 ? void 0 : _a.nodeType) &&
855
- startPosition && endPosition) {
856
- const abstractSelection = connector.beforeChange(isFocusEnd ? {
857
- anchorSlot: startPosition.slot,
858
- anchorOffset: startPosition.offset,
859
- focusSlot: endPosition.slot,
860
- focusOffset: endPosition.offset
861
- } : {
862
- focusSlot: startPosition.slot,
863
- focusOffset: startPosition.offset,
864
- anchorSlot: endPosition.slot,
865
- anchorOffset: endPosition.offset
866
- });
867
- if (!abstractSelection) {
868
- this.selectionChangeEvent.next(null);
869
- connector.setSelection(null);
870
- return;
871
- }
872
- const { focus, anchor } = this.getPositionByRange(abstractSelection);
873
- if (focus && anchor) {
874
- let start = anchor;
875
- let end = focus;
876
- if (isFocusStart) {
877
- start = focus;
878
- end = anchor;
879
- }
880
- if (nativeRange.startContainer !== start.node || nativeRange.startOffset !== start.offset) {
881
- nativeRange.setStart(start.node, start.offset);
882
- }
883
- if (nativeRange.endContainer !== end.node || nativeRange.endOffset !== end.offset) {
884
- nativeRange.setEnd(end.node, end.offset);
885
- }
886
- connector.setSelection(abstractSelection);
887
- if (selection.isCollapsed && (rawRange.startContainer !== start.node ||
888
- rawRange.startOffset !== start.offset ||
889
- rawRange.endContainer !== end.node ||
890
- rawRange.endOffset !== end.offset)) {
891
- rawRange.setStart(start.node, start.offset);
892
- rawRange.setEnd(end.node, end.offset);
893
- }
894
- this.selectionChangeEvent.next(nativeRange);
895
- }
896
- else {
897
- connector.setSelection(null);
898
- }
899
- return;
900
- }
901
- connector.setSelection(null);
902
- }
903
- findSelectedNodeAndOffset(slot, offset) {
904
- const prev = slot.getContentAtIndex(offset - 1);
905
- const nodes = this.domAdapter.getNodesBySlot(slot);
906
- if (prev) {
907
- if (typeof prev !== 'string') {
908
- const nativeNode = this.domAdapter.getNativeNodeByComponent(prev);
909
- return {
910
- node: nativeNode.parentNode,
911
- offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode) + 1
912
- };
913
- }
914
- else if (prev === '\n') {
915
- for (const node of nodes) {
916
- if (node instanceof Text) {
917
- continue;
918
- }
919
- if (node.nodeName === 'BR') {
920
- const position = this.domAdapter.getLocationByNativeNode(node);
921
- if (position) {
922
- if (position.endIndex === offset) {
923
- const parentNode = node.parentNode;
924
- return {
925
- node: parentNode,
926
- offset: Array.from(parentNode.childNodes).indexOf(node) + 1
927
- };
928
- }
929
- }
930
- }
931
- }
932
- }
933
- }
934
- const current = slot.getContentAtIndex(offset);
935
- if (current && typeof current !== 'string') {
936
- const nativeNode = this.domAdapter.getNativeNodeByComponent(current);
937
- return {
938
- node: nativeNode.parentNode,
939
- offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode)
940
- };
941
- }
942
- for (const node of nodes) {
943
- if (node instanceof Element) {
944
- if (node.tagName === 'BR') {
945
- const position = this.domAdapter.getLocationByNativeNode(node);
946
- if (position) {
947
- if (position.startIndex === offset) {
948
- const parentNode = node.parentNode;
949
- return {
950
- node: parentNode,
951
- offset: Array.from(parentNode.childNodes).indexOf(node)
952
- };
953
- }
954
- }
955
- }
956
- continue;
957
- }
958
- const position = this.domAdapter.getLocationByNativeNode(node);
959
- if (position) {
960
- if (offset >= position.startIndex && offset <= position.endIndex) {
961
- return {
962
- node: node,
963
- offset: offset - position.startIndex
964
- };
965
- }
966
- }
967
- }
968
- return null;
969
- }
970
- getCorrectedPosition(node, offset, toAfter, excludeNodes = []) {
971
- excludeNodes.push(node);
972
- if (node.nodeType === Node.ELEMENT_NODE) {
973
- const containerPosition = this.domAdapter.getLocationByNativeNode(node);
974
- const childNode = node.childNodes[offset];
975
- if (childNode) {
976
- const childPosition = this.domAdapter.getLocationByNativeNode(childNode);
977
- if (childPosition) {
978
- if (containerPosition) {
979
- return {
980
- slot: childPosition.slot,
981
- offset: childPosition.startIndex
982
- };
983
- }
984
- return this.findFocusNode(childNode, toAfter, excludeNodes);
985
- }
986
- return this.findFocusNode(childNode, toAfter, excludeNodes);
987
- }
988
- const prevNode = node.childNodes[offset - 1];
989
- if (prevNode) {
990
- const prevPosition = this.domAdapter.getLocationByNativeNode(prevNode);
991
- if (prevPosition && containerPosition) {
992
- return {
993
- slot: prevPosition.slot,
994
- offset: prevPosition.endIndex
995
- };
996
- }
997
- }
998
- if (containerPosition) {
999
- return {
1000
- slot: containerPosition.slot,
1001
- offset: containerPosition.endIndex
1002
- };
1003
- }
1004
- const nextNode = toAfter ? node.nextSibling : node.previousSibling;
1005
- if (nextNode) {
1006
- return this.findFocusNode(nextNode, toAfter, excludeNodes);
1007
- }
1008
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
1009
- }
1010
- else if (node.nodeType === Node.TEXT_NODE) {
1011
- const containerPosition = this.domAdapter.getLocationByNativeNode(node);
1012
- if (containerPosition) {
1013
- return {
1014
- slot: containerPosition.slot,
1015
- offset: containerPosition.startIndex + offset
1016
- };
1017
- }
1018
- const nextNode = toAfter ? node.nextSibling : node.previousSibling;
1019
- if (nextNode) {
1020
- return this.findFocusNode(nextNode, toAfter, excludeNodes);
1021
- }
1022
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
1023
- }
1024
- return null;
1025
- }
1026
- findFocusNode(node, toAfter = false, excludeNodes = []) {
1027
- if (excludeNodes.includes(node)) {
1028
- const next = toAfter ? node.nextSibling : node.previousSibling;
1029
- if (next) {
1030
- return this.findFocusNode(next, toAfter, excludeNodes);
1031
- }
1032
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
1033
- }
1034
- excludeNodes.push(node);
1035
- const position = this.domAdapter.getLocationByNativeNode(node);
1036
- if (position) {
1037
- return {
1038
- slot: position.slot,
1039
- offset: toAfter ? position.startIndex : position.endIndex
1040
- };
1041
- }
1042
- const firstChild = toAfter ? node.firstChild : node.lastChild;
1043
- if (firstChild) {
1044
- return this.findFocusNode(firstChild, toAfter, excludeNodes);
1045
- }
1046
- const nextSibling = toAfter ? node.nextSibling : node.previousSibling;
1047
- if (nextSibling) {
1048
- return this.findFocusNode(nextSibling, toAfter, excludeNodes);
1049
- }
1050
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
1051
- }
1052
- findFocusNodeByParent(node, toAfter, excludeNodes) {
1053
- const parentNode = node.parentNode;
1054
- if (parentNode) {
1055
- const parentPosition = this.domAdapter.getLocationByNativeNode(parentNode);
1056
- if (parentPosition) {
1057
- return {
1058
- slot: parentPosition.slot,
1059
- offset: toAfter ? parentPosition.endIndex : parentPosition.startIndex
1060
- };
1061
- }
1062
- excludeNodes.push(node);
1063
- return this.findFocusNode(parentNode, toAfter, excludeNodes);
1064
- }
1065
- return null;
1066
- }
1067
- };
1068
- SelectionBridge = __decorate([
1069
- Injectable(),
1070
- __param(0, Inject(EDITOR_OPTIONS)),
1071
- __metadata("design:paramtypes", [Object, Textbus,
1072
- Controller,
1073
- Selection,
1074
- RootComponentRef,
1075
- Input,
1076
- Scheduler,
1077
- DomAdapter])
1078
- ], SelectionBridge);
1079
-
1080
- const iframeHTML = `
1081
- <!DOCTYPE html>
1082
- <html>
1083
- <head>
1084
- <meta charset="UTF-8">
1085
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
1086
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
1087
- <title>Textbus</title>
1088
- <style>
1089
- html {position: fixed; left:0; overflow: hidden}
1090
- html, body{height: 100%;width:100%}
1091
- body{margin:0; overflow: hidden}
1092
- textarea{width: 2000px;height: 100%;opacity: 0; padding: 0; outline: none; border: none; position: absolute; left:0; top:0;}
1093
- </style>
1094
- </head>
1095
- <body>
1096
- </body>
1097
- </html>
1098
- `;
1099
- class ExperimentalCaret {
1100
- get rect() {
1101
- return this.caret.getBoundingClientRect();
1102
- }
1103
- set display(v) {
1104
- this._display = v;
1105
- this.caret.style.visibility = v ? 'visible' : 'hidden';
1106
- }
1107
- get display() {
1108
- return this._display;
1109
- }
1110
- constructor(domRenderer, scheduler, editorMask) {
1111
- Object.defineProperty(this, "domRenderer", {
1112
- enumerable: true,
1113
- configurable: true,
1114
- writable: true,
1115
- value: domRenderer
1116
- });
1117
- Object.defineProperty(this, "scheduler", {
1118
- enumerable: true,
1119
- configurable: true,
1120
- writable: true,
1121
- value: scheduler
1122
- });
1123
- Object.defineProperty(this, "editorMask", {
1124
- enumerable: true,
1125
- configurable: true,
1126
- writable: true,
1127
- value: editorMask
1128
- });
1129
- Object.defineProperty(this, "onPositionChange", {
1130
- enumerable: true,
1131
- configurable: true,
1132
- writable: true,
1133
- value: void 0
1134
- });
1135
- Object.defineProperty(this, "onStyleChange", {
1136
- enumerable: true,
1137
- configurable: true,
1138
- writable: true,
1139
- value: void 0
1140
- });
1141
- Object.defineProperty(this, "elementRef", {
1142
- enumerable: true,
1143
- configurable: true,
1144
- writable: true,
1145
- value: void 0
1146
- });
1147
- Object.defineProperty(this, "changeFromSelf", {
1148
- enumerable: true,
1149
- configurable: true,
1150
- writable: true,
1151
- value: false
1152
- });
1153
- Object.defineProperty(this, "getLimit", {
1154
- enumerable: true,
1155
- configurable: true,
1156
- writable: true,
1157
- value: function () {
1158
- return {
1159
- top: 0,
1160
- bottom: document.documentElement.clientHeight
1161
- };
1162
- }
1163
- });
1164
- Object.defineProperty(this, "timer", {
1165
- enumerable: true,
1166
- configurable: true,
1167
- writable: true,
1168
- value: null
1169
- });
1170
- Object.defineProperty(this, "caret", {
1171
- enumerable: true,
1172
- configurable: true,
1173
- writable: true,
1174
- value: void 0
1175
- });
1176
- Object.defineProperty(this, "_display", {
1177
- enumerable: true,
1178
- configurable: true,
1179
- writable: true,
1180
- value: true
1181
- });
1182
- Object.defineProperty(this, "flashing", {
1183
- enumerable: true,
1184
- configurable: true,
1185
- writable: true,
1186
- value: true
1187
- });
1188
- Object.defineProperty(this, "subscription", {
1189
- enumerable: true,
1190
- configurable: true,
1191
- writable: true,
1192
- value: new Subscription()
1193
- });
1194
- Object.defineProperty(this, "positionChangeEvent", {
1195
- enumerable: true,
1196
- configurable: true,
1197
- writable: true,
1198
- value: new Subject()
1199
- });
1200
- Object.defineProperty(this, "styleChangeEvent", {
1201
- enumerable: true,
1202
- configurable: true,
1203
- writable: true,
1204
- value: new Subject()
1205
- });
1206
- Object.defineProperty(this, "oldRange", {
1207
- enumerable: true,
1208
- configurable: true,
1209
- writable: true,
1210
- value: null
1211
- });
1212
- this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1213
- this.onStyleChange = this.styleChangeEvent.asObservable();
1214
- this.elementRef = createElement('div', {
1215
- styles: {
1216
- position: 'absolute',
1217
- width: '2px',
1218
- pointerEvents: 'none'
1219
- },
1220
- children: [
1221
- this.caret = createElement('span', {
1222
- styles: {
1223
- width: '100%',
1224
- height: '100%',
1225
- position: 'absolute',
1226
- left: 0,
1227
- top: 0
1228
- }
1229
- })
1230
- ]
1231
- });
1232
- this.subscription.add(fromEvent(document, 'mousedown').subscribe(() => {
1233
- this.flashing = false;
1234
- }), fromEvent(document, 'mouseup').subscribe(() => {
1235
- this.flashing = true;
1236
- }));
1237
- this.editorMask.appendChild(this.elementRef);
1238
- }
1239
- refresh() {
1240
- if (this.oldRange) {
1241
- this.show(this.oldRange, false);
1242
- }
1243
- }
1244
- show(range, restart) {
1245
- this.oldRange = range;
1246
- if (restart || this.scheduler.lastChangesHasLocalUpdate) {
1247
- clearTimeout(this.timer);
1248
- }
1249
- this.updateCursorPosition(range);
1250
- if (range.collapsed) {
1251
- if (restart || this.scheduler.lastChangesHasLocalUpdate) {
1252
- this.display = true;
1253
- const toggleShowHide = () => {
1254
- this.display = !this.display || !this.flashing;
1255
- this.timer = setTimeout(toggleShowHide, 400);
1256
- };
1257
- clearTimeout(this.timer);
1258
- this.timer = setTimeout(toggleShowHide, 400);
1259
- }
1260
- }
1261
- else {
1262
- this.display = false;
1263
- clearTimeout(this.timer);
1264
- }
1265
- }
1266
- hide() {
1267
- this.display = false;
1268
- clearTimeout(this.timer);
1269
- this.positionChangeEvent.next(null);
1270
- }
1271
- destroy() {
1272
- clearTimeout(this.timer);
1273
- // this.caret.
1274
- this.subscription.unsubscribe();
1275
- }
1276
- updateCursorPosition(nativeRange) {
1277
- const startContainer = nativeRange.startContainer;
1278
- const node = (startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentNode);
1279
- if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.ELEMENT_NODE) {
1280
- this.positionChangeEvent.next(null);
1281
- return;
1282
- }
1283
- const compositionNode = this.domRenderer.compositionNode;
1284
- if (compositionNode) {
1285
- nativeRange = nativeRange.cloneRange();
1286
- nativeRange.selectNodeContents(compositionNode);
1287
- nativeRange.collapse();
1288
- }
1289
- const rect = getLayoutRectByRange(nativeRange);
1290
- const { fontSize, lineHeight, color, writingMode } = getComputedStyle(node);
1291
- let height;
1292
- if (isNaN(+lineHeight)) {
1293
- const f = parseFloat(lineHeight);
1294
- if (isNaN(f)) {
1295
- height = parseFloat(fontSize);
1296
- }
1297
- else {
1298
- height = f;
1299
- }
1300
- }
1301
- else {
1302
- height = parseFloat(fontSize) * parseFloat(lineHeight);
1303
- }
1304
- const boxHeight = Math.max(Math.floor(Math.max(height, rect.height)), 12);
1305
- // const boxHeight = Math.floor(height)
1306
- let rectTop = rect.top;
1307
- if (rect.height < height) {
1308
- rectTop -= (height - rect.height) / 2;
1309
- }
1310
- rectTop = Math.floor(rectTop);
1311
- const containerRect = this.editorMask.getBoundingClientRect();
1312
- const top = Math.floor(rectTop - containerRect.top);
1313
- const left = Math.floor(rect.left + rect.width / 2 - containerRect.left);
1314
- let rotate = 0;
1315
- if (nativeRange.collapsed) {
1316
- rotate = Math.round(Math.atan2(rect.width, rect.height) * 180 / Math.PI);
1317
- if (rotate !== 0) {
1318
- const hackEle = document.createElement('span');
1319
- // eslint-disable-next-line max-len
1320
- hackEle.style.cssText = 'display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size; writing-mode: inherit';
1321
- const pointEle = document.createElement('span');
1322
- pointEle.style.cssText = 'position: absolute; left: 0; top: 0; width:0;height:0';
1323
- hackEle.append(pointEle);
1324
- node.append(hackEle);
1325
- const p1 = pointEle.getBoundingClientRect();
1326
- pointEle.style.right = '0';
1327
- pointEle.style.left = '';
1328
- const p2 = pointEle.getBoundingClientRect();
1329
- const x = p1.x - p2.x;
1330
- const y = p1.y - p2.y;
1331
- rotate = Math.atan2(y, x) * 180 / Math.PI;
1332
- hackEle.remove();
1333
- }
1334
- }
1335
- if (writingMode === 'vertical-lr' || writingMode === 'vertical-rl') {
1336
- rotate += 90;
1337
- }
1338
- Object.assign(this.elementRef.style, {
1339
- left: left + 'px',
1340
- top: top + 'px',
1341
- height: boxHeight + 'px',
1342
- lineHeight: boxHeight + 'px',
1343
- fontSize,
1344
- transform: `rotate(${rotate}deg)`,
1345
- });
1346
- this.caret.style.backgroundColor = color === 'rgba(0, 0, 0, 0)' ? '#000' : color;
1347
- this.styleChangeEvent.next({
1348
- height: boxHeight + 'px',
1349
- lineHeight: boxHeight + 'px',
1350
- fontSize
1351
- });
1352
- this.positionChangeEvent.next({
1353
- left,
1354
- top: rectTop,
1355
- height: boxHeight
1356
- });
1357
- if (this.changeFromSelf) {
1358
- this.changeFromSelf = false;
1359
- const selfRect = this.elementRef.getBoundingClientRect();
1360
- const scrollContainer = this.getScrollContainer(startContainer);
1361
- const scrollRect = scrollContainer === document.documentElement ?
1362
- { top: 0, bottom: document.documentElement.clientHeight } :
1363
- scrollContainer.getBoundingClientRect();
1364
- const limit = this.getLimit();
1365
- const top = Math.max(limit.top, scrollRect.top);
1366
- const bottom = Math.min(limit.bottom, scrollRect.bottom);
1367
- if (selfRect.top < top) {
1368
- scrollContainer.scrollTop -= top - selfRect.top;
1369
- }
1370
- else if (selfRect.bottom > bottom) {
1371
- scrollContainer.scrollTop += selfRect.bottom - bottom;
1372
- }
1373
- }
1374
- }
1375
- getScrollContainer(container) {
1376
- while (container) {
1377
- if (container instanceof Element) {
1378
- const styles = getComputedStyle(container);
1379
- if (styles.overflow !== 'visible' || styles.overflowX !== 'visible' || styles.overflowY !== 'visible') {
1380
- return container;
1381
- }
1382
- }
1383
- container = container.parentNode;
1384
- }
1385
- return document.documentElement;
1386
- }
1387
- }
1388
- /**
1389
- * Textbus PC 端输入实现
1390
- */
1391
- let MagicInput = class MagicInput extends Input {
1392
- set disabled(b) {
1393
- this._disabled = b;
1394
- if (b && this.textarea) {
1395
- this.textarea.disabled = b;
1396
- }
1397
- }
1398
- get disabled() {
1399
- return this._disabled;
1400
- }
1401
- constructor(domAdapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
1402
- super();
1403
- Object.defineProperty(this, "domAdapter", {
1404
- enumerable: true,
1405
- configurable: true,
1406
- writable: true,
1407
- value: domAdapter
1408
- });
1409
- Object.defineProperty(this, "parser", {
1410
- enumerable: true,
1411
- configurable: true,
1412
- writable: true,
1413
- value: parser
1414
- });
1415
- Object.defineProperty(this, "keyboard", {
1416
- enumerable: true,
1417
- configurable: true,
1418
- writable: true,
1419
- value: keyboard
1420
- });
1421
- Object.defineProperty(this, "commander", {
1422
- enumerable: true,
1423
- configurable: true,
1424
- writable: true,
1425
- value: commander
1426
- });
1427
- Object.defineProperty(this, "selection", {
1428
- enumerable: true,
1429
- configurable: true,
1430
- writable: true,
1431
- value: selection
1432
- });
1433
- Object.defineProperty(this, "controller", {
1434
- enumerable: true,
1435
- configurable: true,
1436
- writable: true,
1437
- value: controller
1438
- });
1439
- Object.defineProperty(this, "scheduler", {
1440
- enumerable: true,
1441
- configurable: true,
1442
- writable: true,
1443
- value: scheduler
1444
- });
1445
- Object.defineProperty(this, "textbus", {
1446
- enumerable: true,
1447
- configurable: true,
1448
- writable: true,
1449
- value: textbus
1450
- });
1451
- Object.defineProperty(this, "composition", {
1452
- enumerable: true,
1453
- configurable: true,
1454
- writable: true,
1455
- value: false
1456
- });
1457
- Object.defineProperty(this, "onReady", {
1458
- enumerable: true,
1459
- configurable: true,
1460
- writable: true,
1461
- value: void 0
1462
- });
1463
- Object.defineProperty(this, "caret", {
1464
- enumerable: true,
1465
- configurable: true,
1466
- writable: true,
1467
- value: new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK))
1468
- });
1469
- Object.defineProperty(this, "isSafari", {
1470
- enumerable: true,
1471
- configurable: true,
1472
- writable: true,
1473
- value: isSafari()
1474
- });
1475
- Object.defineProperty(this, "isFirefox", {
1476
- enumerable: true,
1477
- configurable: true,
1478
- writable: true,
1479
- value: isFirefox()
1480
- });
1481
- Object.defineProperty(this, "isMac", {
1482
- enumerable: true,
1483
- configurable: true,
1484
- writable: true,
1485
- value: isMac()
1486
- });
1487
- Object.defineProperty(this, "isWindows", {
1488
- enumerable: true,
1489
- configurable: true,
1490
- writable: true,
1491
- value: isWindows()
1492
- });
1493
- Object.defineProperty(this, "_disabled", {
1494
- enumerable: true,
1495
- configurable: true,
1496
- writable: true,
1497
- value: false
1498
- });
1499
- Object.defineProperty(this, "container", {
1500
- enumerable: true,
1501
- configurable: true,
1502
- writable: true,
1503
- value: this.createEditableFrame()
1504
- });
1505
- Object.defineProperty(this, "subscription", {
1506
- enumerable: true,
1507
- configurable: true,
1508
- writable: true,
1509
- value: new Subscription()
1510
- });
1511
- Object.defineProperty(this, "doc", {
1512
- enumerable: true,
1513
- configurable: true,
1514
- writable: true,
1515
- value: void 0
1516
- });
1517
- Object.defineProperty(this, "textarea", {
1518
- enumerable: true,
1519
- configurable: true,
1520
- writable: true,
1521
- value: null
1522
- });
1523
- Object.defineProperty(this, "isFocus", {
1524
- enumerable: true,
1525
- configurable: true,
1526
- writable: true,
1527
- value: false
1528
- });
1529
- Object.defineProperty(this, "nativeFocus", {
1530
- enumerable: true,
1531
- configurable: true,
1532
- writable: true,
1533
- value: false
1534
- });
1535
- Object.defineProperty(this, "ignoreComposition", {
1536
- enumerable: true,
1537
- configurable: true,
1538
- writable: true,
1539
- value: false
1540
- }); // 有 bug 版本搜狗拼音
1541
- this.onReady = new Promise(resolve => {
1542
- this.subscription.add(fromEvent(this.container, 'load').subscribe(() => {
1543
- const doc = this.container.contentDocument;
1544
- doc.open();
1545
- doc.write(iframeHTML);
1546
- doc.close();
1547
- this.doc = doc;
1548
- this.init();
1549
- resolve();
1550
- }), controller.onReadonlyStateChange.subscribe(() => {
1551
- if (controller.readonly) {
1552
- this.blur();
1553
- }
1554
- }));
1555
- });
1556
- this.caret.elementRef.append(this.container);
1557
- }
1558
- focus(range, restart) {
1559
- var _a;
1560
- if (!this.disabled) {
1561
- this.caret.show(range, restart);
1562
- }
1563
- if (this.controller.readonly) {
1564
- return;
1565
- }
1566
- if (!this.isFocus) {
1567
- (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
1568
- setTimeout(() => {
1569
- if (!this.nativeFocus && this.isFocus) {
1570
- this.reInit();
1571
- }
1572
- });
1573
- }
1574
- this.isFocus = true;
1575
- }
1576
- blur() {
1577
- var _a;
1578
- this.caret.hide();
1579
- (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.blur();
1580
- this.isFocus = false;
1581
- }
1582
- destroy() {
1583
- this.caret.destroy();
1584
- this.subscription.unsubscribe();
1585
- }
1586
- reInit(delay = false) {
1587
- var _a, _b, _c;
1588
- this.subscription.unsubscribe();
1589
- (_b = (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.textarea);
1590
- this.subscription = new Subscription();
1591
- this.init();
1592
- if (delay) {
1593
- setTimeout(() => {
1594
- var _a;
1595
- (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
1596
- });
1597
- }
1598
- else {
1599
- (_c = this.textarea) === null || _c === void 0 ? void 0 : _c.focus();
1600
- }
1601
- }
1602
- init() {
1603
- const doc = this.doc;
1604
- const contentBody = doc.body;
1605
- const textarea = doc.createElement('textarea');
1606
- textarea.disabled = this.disabled;
1607
- contentBody.appendChild(textarea);
1608
- this.textarea = textarea;
1609
- this.subscription.add(fromEvent(textarea, 'blur').subscribe(() => {
1610
- // if (this.isFocus) {
1611
- // this.isFocus = false
1612
- // this.reInit(true)
1613
- // }
1614
- this.isFocus = false;
1615
- this.nativeFocus = false;
1616
- this.caret.hide();
1617
- if (this.domAdapter.composition) {
1618
- const slot = this.domAdapter.composition.slot;
1619
- this.domAdapter.composition = null;
1620
- this.domAdapter.compositionNode = null;
1621
- slot.__changeMarker__.forceMarkDirtied();
1622
- }
1623
- }), fromEvent(textarea, 'focus').subscribe(() => {
1624
- this.nativeFocus = true;
1625
- }), this.caret.onStyleChange.subscribe(style => {
1626
- Object.assign(textarea.style, style);
1627
- }));
1628
- this.handleInput(textarea);
1629
- this.handleShortcut(textarea);
1630
- this.handleDefaultActions(textarea);
1631
- }
1632
- handleDefaultActions(textarea) {
1633
- this.subscription.add(fromEvent(isFirefox() ? textarea : document, 'copy').subscribe(ev => {
1634
- this.copyHandler(ev);
1635
- }), fromEvent(textarea, 'paste').subscribe(ev => {
1636
- this.pasteHandler(ev);
1637
- }));
1638
- }
1639
- copyHandler(ev) {
1640
- const selection = this.selection;
1641
- if (!selection.isSelected) {
1642
- return;
1643
- }
1644
- if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
1645
- const content = selection.startSlot.getContentAtIndex(selection.startOffset);
1646
- if (typeof content === 'object') {
1647
- const clipboardData = ev.clipboardData;
1648
- const nativeSelection = document.getSelection();
1649
- const range = nativeSelection.getRangeAt(0);
1650
- const div = document.createElement('div');
1651
- const fragment = range.cloneContents();
1652
- div.append(fragment);
1653
- clipboardData.setData('text/html', div.innerHTML);
1654
- clipboardData.setData('text', div.innerText);
1655
- ev.preventDefault();
1656
- }
1657
- }
1658
- }
1659
- pasteHandler(ev) {
1660
- const text = ev.clipboardData.getData('Text');
1661
- const types = Array.from(ev.clipboardData.types || []);
1662
- const files = Array.from(ev.clipboardData.files);
1663
- if (types.every(type => type === 'Files') && files.length) {
1664
- Promise.all(files.filter(i => {
1665
- return /image/i.test(i.type);
1666
- }).map(item => {
1667
- const reader = new FileReader();
1668
- return new Promise(resolve => {
1669
- reader.onload = (event) => {
1670
- resolve(event.target.result);
1671
- };
1672
- reader.readAsDataURL(item);
1673
- });
1674
- })).then(urls => {
1675
- const html = urls.map(i => {
1676
- return `<img src=${i}>`;
1677
- }).join('');
1678
- this.paste(html, text);
1679
- });
1680
- ev.preventDefault();
1681
- return;
1682
- }
1683
- const div = this.doc.createElement('div');
1684
- div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0';
1685
- div.contentEditable = 'true';
1686
- this.doc.body.appendChild(div);
1687
- div.focus();
1688
- setTimeout(() => {
1689
- this.doc.body.removeChild(div);
1690
- div.style.cssText = '';
1691
- this.paste(div, text);
1692
- });
1693
- }
1694
- paste(dom, text) {
1695
- const slot = this.parser.parse(dom, new Slot([
1696
- ContentType.BlockComponent,
1697
- ContentType.InlineComponent,
1698
- ContentType.Text
1699
- ]));
1700
- this.commander.paste(slot, text);
1701
- }
1702
- handleShortcut(textarea) {
1703
- let isWriting = false;
1704
- let isIgnore = false;
1705
- this.subscription.add(fromEvent(textarea, 'compositionstart').subscribe(() => {
1706
- isWriting = true;
1707
- }), fromEvent(textarea, 'compositionend').subscribe(() => {
1708
- isWriting = false;
1709
- }), fromEvent(textarea, 'beforeinput').subscribe(ev => {
1710
- this.ignoreComposition = false;
1711
- if (this.isSafari) {
1712
- if (ev.inputType === 'insertFromComposition') {
1713
- isIgnore = true;
1714
- }
1715
- }
1716
- }), fromEvent(textarea, 'keydown').pipe(filter(() => {
1717
- if (this.isSafari && isIgnore) {
1718
- isIgnore = false;
1719
- return false;
1720
- }
1721
- return !isWriting; // || !this.textarea.value
1722
- })).subscribe(ev => {
1723
- this.ignoreComposition = false;
1724
- let key = ev.key;
1725
- const keys = ')!@#$%^Z&*(';
1726
- const b = key === 'Process' && /Digit\d/.test(ev.code) && ev.shiftKey;
1727
- if (b) {
1728
- // 大小写锁定为大写 + 全角 + shift + 数字键,还存在问题
1729
- key = keys.charAt(+ev.code.substring(5));
1730
- ev.preventDefault();
1731
- }
1732
- this.caret.changeFromSelf = true;
1733
- const is = this.keyboard.execShortcut({
1734
- key: key,
1735
- altKey: ev.altKey,
1736
- shiftKey: ev.shiftKey,
1737
- modKey: this.isMac ? ev.metaKey : ev.ctrlKey,
1738
- agent: {
1739
- key: ev.key,
1740
- code: ev.code,
1741
- keyCode: ev.keyCode,
1742
- }
1743
- });
1744
- if (is) {
1745
- this.ignoreComposition = true;
1746
- ev.preventDefault();
1747
- }
1748
- else {
1749
- this.caret.changeFromSelf = false;
1750
- }
1751
- }));
1752
- }
1753
- handleInput(textarea) {
1754
- let startIndex = 0;
1755
- this.subscription.add(fromEvent(textarea, 'compositionstart').pipe(filter(() => {
1756
- return !this.ignoreComposition;
1757
- })).subscribe(() => {
1758
- if (!this.selection.isCollapsed) {
1759
- this.caret.changeFromSelf = true;
1760
- this.commander.delete();
1761
- }
1762
- this.composition = true;
1763
- startIndex = this.selection.startOffset;
1764
- const startSlot = this.selection.startSlot;
1765
- const event = new Event(startSlot, {
1766
- index: startIndex
1767
- });
1768
- invokeListener(startSlot.parent, 'onCompositionStart', event);
1769
- }), fromEvent(textarea, 'compositionupdate').pipe(filter(() => {
1770
- return !this.ignoreComposition;
1771
- })).pipe(distinctUntilChanged((prev, next) => {
1772
- return prev.data !== next.data;
1773
- })).subscribe(ev => {
1774
- if (ev.data === ' ') {
1775
- // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题
1776
- return;
1777
- }
1778
- const startSlot = this.selection.startSlot;
1779
- this.domAdapter.composition = {
1780
- slot: startSlot,
1781
- text: ev.data,
1782
- offset: ev.data.length,
1783
- index: startIndex
1784
- };
1785
- this.caret.changeFromSelf = true;
1786
- this.caret.refresh();
1787
- const event = new Event(startSlot, {
1788
- index: startIndex,
1789
- data: ev.data
1790
- });
1791
- invokeListener(startSlot.parent, 'onCompositionUpdate', event);
1792
- startSlot.__changeMarker__.forceMarkDirtied();
1793
- }));
1794
- let isCompositionEnd = false;
1795
- this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
1796
- ev.preventDefault();
1797
- if (this.isFirefox && ev.inputType === 'insertFromPaste') {
1798
- return false;
1799
- }
1800
- if (this.isSafari) {
1801
- isCompositionEnd = ev.inputType === 'insertFromComposition';
1802
- return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
1803
- }
1804
- return !ev.isComposing && !!ev.data;
1805
- }), map(ev => {
1806
- return ev.data;
1807
- })), this.isSafari ? new Observable() : fromEvent(textarea, 'compositionend')
1808
- .pipe(filter(() => {
1809
- return !this.ignoreComposition;
1810
- })).pipe(map(ev => {
1811
- isCompositionEnd = true;
1812
- ev.preventDefault();
1813
- textarea.value = '';
1814
- return ev.data;
1815
- }))).subscribe(text => {
1816
- var _a;
1817
- this.composition = false;
1818
- this.domAdapter.composition = null;
1819
- if (text) {
1820
- this.caret.changeFromSelf = true;
1821
- this.commander.write(text);
1822
- }
1823
- else {
1824
- (_a = this.selection.startSlot) === null || _a === void 0 ? void 0 : _a.__changeMarker__.forceMarkDirtied();
1825
- }
1826
- if (isCompositionEnd) {
1827
- const startSlot = this.selection.startSlot;
1828
- if (startSlot) {
1829
- const event = new Event(startSlot, null);
1830
- invokeListener(startSlot.parent, 'onCompositionEnd', event);
1831
- }
1832
- }
1833
- isCompositionEnd = false;
1834
- }));
1835
- }
1836
- createEditableFrame() {
1837
- return createElement('iframe', {
1838
- attrs: {
1839
- scrolling: 'no'
1840
- },
1841
- styles: {
1842
- border: 'none',
1843
- width: '100%',
1844
- display: 'block',
1845
- height: '100%',
1846
- position: 'relative',
1847
- top: this.isWindows ? '3px' : '0'
1848
- }
1849
- });
1850
- }
1851
- };
1852
- MagicInput = __decorate([
1853
- Injectable(),
1854
- __metadata("design:paramtypes", [DomAdapter,
1855
- Parser,
1856
- Keyboard,
1857
- Commander,
1858
- Selection,
1859
- Controller,
1860
- Scheduler,
1861
- Textbus])
1862
- ], MagicInput);
1863
-
1864
- /**
1865
- * 远程光标绘制范围计算代理类,可用于定制特定场景下的远程选区绘制,如表格有选区,不会遵守常见的文档流形式
1866
- */
1867
- class CollaborateSelectionAwarenessDelegate {
1868
- }
1869
- /**
1870
- * 协作光标绘制类
1871
- */
1872
- let CollaborateCursor = class CollaborateCursor {
1873
- constructor(textbus, nativeSelection, scheduler, selection, awarenessDelegate) {
1874
- Object.defineProperty(this, "nativeSelection", {
1875
- enumerable: true,
1876
- configurable: true,
1877
- writable: true,
1878
- value: nativeSelection
1879
- });
1880
- Object.defineProperty(this, "scheduler", {
1881
- enumerable: true,
1882
- configurable: true,
1883
- writable: true,
1884
- value: scheduler
1885
- });
1886
- Object.defineProperty(this, "selection", {
1887
- enumerable: true,
1888
- configurable: true,
1889
- writable: true,
1890
- value: selection
1891
- });
1892
- Object.defineProperty(this, "awarenessDelegate", {
1893
- enumerable: true,
1894
- configurable: true,
1895
- writable: true,
1896
- value: awarenessDelegate
1897
- });
1898
- Object.defineProperty(this, "host", {
1899
- enumerable: true,
1900
- configurable: true,
1901
- writable: true,
1902
- value: createElement('div', {
1903
- styles: {
1904
- position: 'absolute',
1905
- left: 0,
1906
- top: 0,
1907
- width: '100%',
1908
- height: '100%',
1909
- pointerEvents: 'none',
1910
- zIndex: 1
1911
- }
1912
- })
1913
- });
1914
- Object.defineProperty(this, "canvasContainer", {
1915
- enumerable: true,
1916
- configurable: true,
1917
- writable: true,
1918
- value: createElement('div', {
1919
- styles: {
1920
- position: 'absolute',
1921
- left: 0,
1922
- top: 0,
1923
- width: '100%',
1924
- height: '100%',
1925
- overflow: 'hidden'
1926
- }
1927
- })
1928
- });
1929
- Object.defineProperty(this, "canvas", {
1930
- enumerable: true,
1931
- configurable: true,
1932
- writable: true,
1933
- value: createElement('canvas', {
1934
- styles: {
1935
- position: 'absolute',
1936
- opacity: 0.5,
1937
- left: 0,
1938
- top: 0,
1939
- width: '100%',
1940
- height: document.documentElement.clientHeight + 'px',
1941
- pointerEvents: 'none',
1942
- }
1943
- })
1944
- });
1945
- Object.defineProperty(this, "context", {
1946
- enumerable: true,
1947
- configurable: true,
1948
- writable: true,
1949
- value: this.canvas.getContext('2d')
1950
- });
1951
- Object.defineProperty(this, "tooltips", {
1952
- enumerable: true,
1953
- configurable: true,
1954
- writable: true,
1955
- value: createElement('div', {
1956
- styles: {
1957
- position: 'absolute',
1958
- left: 0,
1959
- top: 0,
1960
- width: '100%',
1961
- height: '100%',
1962
- pointerEvents: 'none',
1963
- fontSize: '12px',
1964
- zIndex: 10
1965
- }
1966
- })
1967
- });
1968
- Object.defineProperty(this, "onRectsChange", {
1969
- enumerable: true,
1970
- configurable: true,
1971
- writable: true,
1972
- value: new Subject()
1973
- });
1974
- Object.defineProperty(this, "subscription", {
1975
- enumerable: true,
1976
- configurable: true,
1977
- writable: true,
1978
- value: new Subscription()
1979
- });
1980
- Object.defineProperty(this, "selectionCursors", {
1981
- enumerable: true,
1982
- configurable: true,
1983
- writable: true,
1984
- value: []
1985
- });
1986
- Object.defineProperty(this, "container", {
1987
- enumerable: true,
1988
- configurable: true,
1989
- writable: true,
1990
- value: void 0
1991
- });
1992
- Object.defineProperty(this, "ratio", {
1993
- enumerable: true,
1994
- configurable: true,
1995
- writable: true,
1996
- value: window.devicePixelRatio || 1
1997
- });
1998
- this.container = textbus.get(VIEW_CONTAINER);
1999
- this.canvasContainer.append(this.canvas);
2000
- this.host.append(this.canvasContainer, this.tooltips);
2001
- this.container.prepend(this.host);
2002
- this.subscription.add(this.onRectsChange.subscribe(rects => {
2003
- for (const rect of rects) {
2004
- this.context.fillStyle = rect.color;
2005
- this.context.beginPath();
2006
- this.context.rect(rect.left, rect.top, rect.width, rect.height);
2007
- this.context.fill();
2008
- this.context.closePath();
2009
- }
2010
- }), fromEvent(window, 'resize').subscribe(() => {
2011
- this.canvas.style.height = document.documentElement.clientHeight + 'px';
2012
- this.refresh();
2013
- }), this.scheduler.onDocChanged.subscribe(() => {
2014
- this.refresh();
2015
- }));
2016
- }
2017
- /**
2018
- * 刷新协作光标,由于 Textbus 只会绘制可视区域的光标,当可视区域发生变化时,需要重新绘制
2019
- */
2020
- refresh() {
2021
- this.draw(this.selectionCursors);
2022
- }
2023
- destroy() {
2024
- this.subscription.unsubscribe();
2025
- }
2026
- /**
2027
- * 根据远程用户光标位置,绘制协作光标
2028
- * @param paths
2029
- */
2030
- draw(paths) {
2031
- this.selectionCursors = paths;
2032
- const containerRect = this.container.getBoundingClientRect();
2033
- this.canvas.style.top = containerRect.top * -1 + 'px';
2034
- this.canvas.width = this.canvas.offsetWidth * this.ratio;
2035
- this.canvas.height = this.canvas.offsetHeight * this.ratio;
2036
- this.context.scale(this.ratio, this.ratio);
2037
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
2038
- const users = [];
2039
- paths.filter(i => {
2040
- return i.selection.anchor.length && i.selection.focus.length;
2041
- }).forEach(item => {
2042
- const anchorPaths = [...item.selection.anchor];
2043
- const focusPaths = [...item.selection.focus];
2044
- const anchorOffset = anchorPaths.pop();
2045
- const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
2046
- const focusOffset = focusPaths.pop();
2047
- const focusSlot = this.selection.findSlotByPaths(focusPaths);
2048
- if (!anchorSlot || !focusSlot) {
2049
- return;
2050
- }
2051
- const { focus, anchor } = this.nativeSelection.getPositionByRange({
2052
- focusOffset,
2053
- anchorOffset,
2054
- focusSlot,
2055
- anchorSlot
2056
- });
2057
- if (!focus || !anchor) {
2058
- return;
2059
- }
2060
- const nativeRange = document.createRange();
2061
- try {
2062
- nativeRange.setStart(anchor.node, anchor.offset);
2063
- nativeRange.setEnd(focus.node, focus.offset);
2064
- }
2065
- catch (e) {
2066
- return;
2067
- }
2068
- if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
2069
- nativeRange.setStart(focus.node, focus.offset);
2070
- nativeRange.setEnd(anchor.node, anchor.offset);
2071
- }
2072
- let rects = false;
2073
- if (this.awarenessDelegate) {
2074
- rects = this.awarenessDelegate.getRects({
2075
- focusOffset,
2076
- anchorOffset,
2077
- focusSlot,
2078
- anchorSlot
2079
- }, nativeRange, item);
2080
- }
2081
- if (!rects) {
2082
- rects = nativeRange.getClientRects();
2083
- }
2084
- const selectionRects = [];
2085
- for (let i = rects.length - 1; i >= 0; i--) {
2086
- const rect = rects[i];
2087
- selectionRects.push({
2088
- color: item.color,
2089
- username: item.username,
2090
- left: rect.left - containerRect.left,
2091
- top: rect.top,
2092
- width: rect.width,
2093
- height: rect.height,
2094
- });
2095
- }
2096
- this.onRectsChange.next(selectionRects);
2097
- const cursorRange = nativeRange.cloneRange();
2098
- cursorRange.setStart(focus.node, focus.offset);
2099
- cursorRange.collapse(true);
2100
- const cursorRect = getLayoutRectByRange(cursorRange);
2101
- const rect = {
2102
- username: item.username,
2103
- color: item.color,
2104
- left: cursorRect.left - containerRect.left,
2105
- top: cursorRect.top - containerRect.top,
2106
- width: 1,
2107
- height: cursorRect.height
2108
- };
2109
- if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {
2110
- return;
2111
- }
2112
- users.push(rect);
2113
- });
2114
- this.drawUserCursor(users);
2115
- }
2116
- drawUserCursor(rects) {
2117
- for (let i = 0; i < rects.length; i++) {
2118
- const rect = rects[i];
2119
- const { cursor, userTip, anchor } = this.getUserCursor(i);
2120
- Object.assign(cursor.style, {
2121
- left: rect.left + 'px',
2122
- top: rect.top + 'px',
2123
- width: rect.width + 'px',
2124
- height: rect.height + 'px',
2125
- background: rect.color,
2126
- display: 'block'
2127
- });
2128
- anchor.style.background = rect.color;
2129
- userTip.innerText = rect.username;
2130
- userTip.style.background = rect.color;
2131
- }
2132
- for (let i = rects.length; i < this.tooltips.children.length; i++) {
2133
- this.tooltips.removeChild(this.tooltips.children[i]);
2134
- }
2135
- }
2136
- getUserCursor(index) {
2137
- let child = this.tooltips.children[index];
2138
- if (child) {
2139
- const anchor = child.children[0];
2140
- return {
2141
- cursor: child,
2142
- anchor,
2143
- userTip: anchor.children[0]
2144
- };
2145
- }
2146
- const userTip = createElement('span', {
2147
- styles: {
2148
- position: 'absolute',
2149
- left: '50%',
2150
- transform: 'translateX(-50%)',
2151
- marginBottom: '2px',
2152
- bottom: '100%',
2153
- whiteSpace: 'nowrap',
2154
- color: '#fff',
2155
- boxShadow: '0 1px 2px rgba(0,0,0,.1)',
2156
- opacity: 0.8,
2157
- borderRadius: '3px',
2158
- padding: '3px 5px',
2159
- pointerEvents: 'none',
2160
- }
2161
- });
2162
- const anchor = createElement('span', {
2163
- styles: {
2164
- position: 'absolute',
2165
- top: '-2px',
2166
- left: '-2px',
2167
- width: '5px',
2168
- height: '5px',
2169
- borderRadius: '50%',
2170
- pointerEvents: 'auto',
2171
- pointer: 'cursor',
2172
- },
2173
- children: [userTip]
2174
- });
2175
- child = createElement('span', {
2176
- styles: {
2177
- position: 'absolute',
2178
- },
2179
- children: [
2180
- anchor
2181
- ]
2182
- });
2183
- this.tooltips.append(child);
2184
- return {
2185
- cursor: child,
2186
- anchor,
2187
- userTip
2188
- };
2189
- }
2190
- };
2191
- CollaborateCursor = __decorate([
2192
- Injectable(),
2193
- __param(4, Optional()),
2194
- __metadata("design:paramtypes", [Textbus,
2195
- SelectionBridge,
2196
- Scheduler,
2197
- Selection,
2198
- CollaborateSelectionAwarenessDelegate])
2199
- ], CollaborateCursor);
2200
-
2201
- class NativeCaret {
2202
- set nativeRange(range) {
2203
- this._nativeRange = range;
2204
- if (range) {
2205
- const r = range.cloneRange();
2206
- r.collapse(true);
2207
- const rect = getLayoutRectByRange(r);
2208
- this.positionChangeEvent.next({
2209
- left: rect.left,
2210
- top: rect.top,
2211
- height: rect.height
2212
- });
2213
- }
2214
- else {
2215
- this.positionChangeEvent.next(null);
2216
- }
2217
- }
2218
- get nativeRange() {
2219
- return this._nativeRange;
2220
- }
2221
- get rect() {
2222
- if (this.nativeRange) {
2223
- const range = this.nativeRange.cloneRange();
2224
- range.collapse(true);
2225
- return getLayoutRectByRange(range);
2226
- }
2227
- return {
2228
- left: 0,
2229
- top: 0,
2230
- width: 0,
2231
- height: 0
2232
- };
2233
- }
2234
- constructor() {
2235
- Object.defineProperty(this, "onPositionChange", {
2236
- enumerable: true,
2237
- configurable: true,
2238
- writable: true,
2239
- value: void 0
2240
- });
2241
- Object.defineProperty(this, "_nativeRange", {
2242
- enumerable: true,
2243
- configurable: true,
2244
- writable: true,
2245
- value: null
2246
- });
2247
- Object.defineProperty(this, "subs", {
2248
- enumerable: true,
2249
- configurable: true,
2250
- writable: true,
2251
- value: []
2252
- });
2253
- Object.defineProperty(this, "positionChangeEvent", {
2254
- enumerable: true,
2255
- configurable: true,
2256
- writable: true,
2257
- value: new Subject()
2258
- });
2259
- this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
2260
- }
2261
- refresh() {
2262
- //
2263
- }
2264
- destroy() {
2265
- this.subs.forEach(i => i.unsubscribe());
2266
- this.subs = [];
2267
- }
2268
- }
2269
- let NativeInput = class NativeInput extends Input {
2270
- set disabled(b) {
2271
- this._disabled = b;
2272
- if (this.controller.readonly) {
2273
- this.documentView.contentEditable = 'false';
2274
- return;
2275
- }
2276
- this.documentView.contentEditable = b ? 'false' : 'true';
2277
- }
2278
- get disabled() {
2279
- return this._disabled;
2280
- }
2281
- constructor(textbus, parser, selection, keyboard, domAdapter, commander, controller) {
2282
- super();
2283
- Object.defineProperty(this, "parser", {
2284
- enumerable: true,
2285
- configurable: true,
2286
- writable: true,
2287
- value: parser
2288
- });
2289
- Object.defineProperty(this, "selection", {
2290
- enumerable: true,
2291
- configurable: true,
2292
- writable: true,
2293
- value: selection
2294
- });
2295
- Object.defineProperty(this, "keyboard", {
2296
- enumerable: true,
2297
- configurable: true,
2298
- writable: true,
2299
- value: keyboard
2300
- });
2301
- Object.defineProperty(this, "domAdapter", {
2302
- enumerable: true,
2303
- configurable: true,
2304
- writable: true,
2305
- value: domAdapter
2306
- });
2307
- Object.defineProperty(this, "commander", {
2308
- enumerable: true,
2309
- configurable: true,
2310
- writable: true,
2311
- value: commander
2312
- });
2313
- Object.defineProperty(this, "controller", {
2314
- enumerable: true,
2315
- configurable: true,
2316
- writable: true,
2317
- value: controller
2318
- });
2319
- Object.defineProperty(this, "caret", {
2320
- enumerable: true,
2321
- configurable: true,
2322
- writable: true,
2323
- value: new NativeCaret()
2324
- });
2325
- Object.defineProperty(this, "composition", {
2326
- enumerable: true,
2327
- configurable: true,
2328
- writable: true,
2329
- value: false
2330
- });
2331
- // compositionState: CompositionState | null = null
2332
- Object.defineProperty(this, "onReady", {
2333
- enumerable: true,
2334
- configurable: true,
2335
- writable: true,
2336
- value: Promise.resolve()
2337
- });
2338
- Object.defineProperty(this, "_disabled", {
2339
- enumerable: true,
2340
- configurable: true,
2341
- writable: true,
2342
- value: false
2343
- });
2344
- Object.defineProperty(this, "documentView", {
2345
- enumerable: true,
2346
- configurable: true,
2347
- writable: true,
2348
- value: void 0
2349
- });
2350
- Object.defineProperty(this, "nativeSelection", {
2351
- enumerable: true,
2352
- configurable: true,
2353
- writable: true,
2354
- value: document.getSelection()
2355
- });
2356
- Object.defineProperty(this, "subscription", {
2357
- enumerable: true,
2358
- configurable: true,
2359
- writable: true,
2360
- value: new Subscription()
2361
- });
2362
- Object.defineProperty(this, "nativeRange", {
2363
- enumerable: true,
2364
- configurable: true,
2365
- writable: true,
2366
- value: null
2367
- });
2368
- Object.defineProperty(this, "isSafari", {
2369
- enumerable: true,
2370
- configurable: true,
2371
- writable: true,
2372
- value: isSafari()
2373
- });
2374
- Object.defineProperty(this, "isMac", {
2375
- enumerable: true,
2376
- configurable: true,
2377
- writable: true,
2378
- value: isMac()
2379
- });
2380
- Object.defineProperty(this, "isMobileBrowser", {
2381
- enumerable: true,
2382
- configurable: true,
2383
- writable: true,
2384
- value: isMobileBrowser()
2385
- });
2386
- Object.defineProperty(this, "ignoreComposition", {
2387
- enumerable: true,
2388
- configurable: true,
2389
- writable: true,
2390
- value: false
2391
- }); // 有 bug 版本搜狗拼音
2392
- this.documentView = textbus.get(VIEW_DOCUMENT);
2393
- if (!controller.readonly) {
2394
- this.documentView.contentEditable = 'true';
2395
- }
2396
- this.subscription.add(controller.onReadonlyStateChange.subscribe(() => {
2397
- this.documentView.contentEditable = controller.readonly ? 'false' : 'true';
2398
- }));
2399
- this.handleShortcut(this.documentView);
2400
- this.handleInput(this.documentView);
2401
- this.handleDefaultActions(this.documentView);
2402
- }
2403
- focus(nativeRange) {
2404
- if (this.controller.readonly) {
2405
- return;
2406
- }
2407
- this.caret.nativeRange = nativeRange;
2408
- this.nativeRange = nativeRange;
2409
- }
2410
- blur() {
2411
- if (this.nativeRange && this.nativeSelection.rangeCount > 0) {
2412
- const current = this.nativeSelection.getRangeAt(0);
2413
- if (current === this.nativeRange) {
2414
- this.nativeSelection.removeAllRanges();
2415
- this.nativeRange = null;
2416
- return;
2417
- }
2418
- }
2419
- }
2420
- destroy() {
2421
- this.caret.destroy();
2422
- this.subscription.unsubscribe();
2423
- }
2424
- handleDefaultActions(textarea) {
2425
- this.subscription.add(fromEvent(isFirefox() ? textarea : document, 'copy').subscribe(ev => {
2426
- this.copyHandler(ev);
2427
- }), fromEvent(textarea, 'paste').subscribe(ev => {
2428
- this.pasteHandler(ev);
2429
- }));
2430
- }
2431
- copyHandler(ev) {
2432
- const selection = this.selection;
2433
- if (!selection.isSelected) {
2434
- return;
2435
- }
2436
- if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
2437
- const content = selection.startSlot.getContentAtIndex(selection.startOffset);
2438
- if (typeof content === 'object') {
2439
- const clipboardData = ev.clipboardData;
2440
- const nativeSelection = document.getSelection();
2441
- const range = nativeSelection.getRangeAt(0);
2442
- const div = document.createElement('div');
2443
- const fragment = range.cloneContents();
2444
- div.append(fragment);
2445
- clipboardData.setData('text/html', div.innerHTML);
2446
- clipboardData.setData('text', div.innerText);
2447
- ev.preventDefault();
2448
- }
2449
- }
2450
- }
2451
- pasteHandler(ev) {
2452
- const text = ev.clipboardData.getData('Text');
2453
- const types = Array.from(ev.clipboardData.types || []);
2454
- const files = Array.from(ev.clipboardData.files);
2455
- if (types.every(type => type === 'Files') && files.length) {
2456
- Promise.all(files.filter(i => {
2457
- return /image/i.test(i.type);
2458
- }).map(item => {
2459
- const reader = new FileReader();
2460
- return new Promise(resolve => {
2461
- reader.onload = (event) => {
2462
- resolve(event.target.result);
2463
- };
2464
- reader.readAsDataURL(item);
2465
- });
2466
- })).then(urls => {
2467
- const html = urls.map(i => {
2468
- return `<img src=${i}>`;
2469
- }).join('');
2470
- this.paste(html, text);
2471
- });
2472
- ev.preventDefault();
2473
- return;
2474
- }
2475
- const div = document.createElement('div');
2476
- div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0';
2477
- div.contentEditable = 'true';
2478
- document.body.appendChild(div);
2479
- div.focus();
2480
- setTimeout(() => {
2481
- document.body.removeChild(div);
2482
- div.style.cssText = '';
2483
- this.paste(div, text);
2484
- });
2485
- }
2486
- paste(dom, text) {
2487
- const slot = this.parser.parse(dom, new Slot([
2488
- ContentType.BlockComponent,
2489
- ContentType.InlineComponent,
2490
- ContentType.Text
2491
- ]));
2492
- this.commander.paste(slot, text);
2493
- }
2494
- handleShortcut(input) {
2495
- let isWriting = false;
2496
- let isIgnore = false;
2497
- this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
2498
- isWriting = true;
2499
- }), fromEvent(input, 'compositionend').subscribe(() => {
2500
- isWriting = false;
2501
- }), fromEvent(input, 'beforeinput').subscribe(ev => {
2502
- if (this.isSafari) {
2503
- if (ev.inputType === 'insertFromComposition') {
2504
- isIgnore = true;
2505
- }
2506
- }
2507
- }), fromEvent(input, 'keydown').pipe(filter(() => {
2508
- if (this.isSafari && isIgnore) {
2509
- isIgnore = false;
2510
- return false;
2511
- }
2512
- return !isWriting; // || !this.textarea.value
2513
- })).subscribe(ev => {
2514
- this.ignoreComposition = false;
2515
- let key = ev.key;
2516
- const keys = ')!@#$%^Z&*(';
2517
- const b = key === 'Process' && /Digit\d/.test(ev.code) && ev.shiftKey;
2518
- if (b) {
2519
- key = keys.charAt(+ev.code.substring(5));
2520
- ev.preventDefault();
2521
- }
2522
- const is = this.keyboard.execShortcut({
2523
- key: key,
2524
- altKey: ev.altKey,
2525
- shiftKey: ev.shiftKey,
2526
- modKey: this.isMac ? ev.metaKey : ev.ctrlKey,
2527
- agent: {
2528
- key: ev.key,
2529
- keyCode: ev.keyCode,
2530
- code: ev.code
2531
- }
2532
- });
2533
- if (is) {
2534
- this.ignoreComposition = true;
2535
- ev.preventDefault();
2536
- }
2537
- }));
2538
- }
2539
- handleInput(input) {
2540
- if (this.isMobileBrowser) {
2541
- this.handleMobileInput(input);
2542
- }
2543
- else {
2544
- this.handlePCInput(input);
2545
- }
2546
- }
2547
- handleMobileInput(input) {
2548
- let isCompositionStart = true;
2549
- let startIndex;
2550
- const compositionStart = () => {
2551
- this.composition = true;
2552
- startIndex = this.selection.startOffset;
2553
- const startSlot = this.selection.startSlot;
2554
- const event = new Event(startSlot, {
2555
- index: startIndex
2556
- });
2557
- invokeListener(startSlot.parent, 'onCompositionStart', event);
2558
- };
2559
- const compositionUpdate = (data) => {
2560
- const startSlot = this.selection.startSlot;
2561
- const event = new Event(startSlot, {
2562
- index: startIndex,
2563
- data
2564
- });
2565
- invokeListener(startSlot.parent, 'onCompositionUpdate', event);
2566
- };
2567
- const compositionEnd = (data) => {
2568
- this.composition = false;
2569
- if (data) {
2570
- this.commander.write(data);
2571
- }
2572
- const startSlot = this.selection.startSlot;
2573
- if (startSlot) {
2574
- const event = new Event(startSlot, null);
2575
- invokeListener(startSlot.parent, 'onCompositionEnd', event);
2576
- }
2577
- };
2578
- this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
2579
- compositionStart();
2580
- }), fromEvent(input, 'compositionupdate').subscribe(ev => {
2581
- compositionUpdate(ev.data);
2582
- }), fromEvent(input, 'compositionend').subscribe(ev => {
2583
- compositionEnd(ev.data);
2584
- const startContainer = this.nativeSelection.focusNode;
2585
- if (startContainer instanceof Text && startContainer.textContent === ev.data) {
2586
- startContainer.remove();
2587
- }
2588
- }), fromEvent(input, 'beforeinput').subscribe(ev => {
2589
- var _a;
2590
- switch (ev.inputType) {
2591
- case 'insertText':
2592
- if (ev.data) {
2593
- this.commander.write(ev.data);
2594
- ev.preventDefault();
2595
- }
2596
- break;
2597
- case 'insertCompositionText':
2598
- if (isCompositionStart) {
2599
- isCompositionStart = false;
2600
- compositionStart();
2601
- }
2602
- else {
2603
- compositionUpdate(ev.data || '');
2604
- }
2605
- break;
2606
- case 'deleteCompositionText':
2607
- this.composition = false;
2608
- break;
2609
- case 'deleteContentBackward': {
2610
- this.composition = false;
2611
- const range = ev.getTargetRanges()[0];
2612
- if (!range) {
2613
- break;
2614
- }
2615
- const location = this.domAdapter.getLocationByNativeNode(range.startContainer);
2616
- const startSlot = this.selection.startSlot;
2617
- if (startSlot) {
2618
- this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
2619
- this.commander.delete();
2620
- }
2621
- break;
2622
- }
2623
- case 'insertReplacementText': {
2624
- this.composition = false;
2625
- const range = ev.getTargetRanges()[0];
2626
- const location = this.domAdapter.getLocationByNativeNode(range.startContainer);
2627
- const startSlot = this.selection.startSlot;
2628
- this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
2629
- this.commander.delete();
2630
- const text = ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text')) || ev.data || null;
2631
- if (text) {
2632
- this.commander.write(text);
2633
- }
2634
- break;
2635
- }
2636
- //
2637
- // case 'insertFromComposition': {
2638
- // compositionEnd(ev.data || '')
2639
- // break
2640
- // }
2641
- }
2642
- }));
2643
- }
2644
- handlePCInput(input) {
2645
- let startIndex = 0;
2646
- let isCompositionEnd = false;
2647
- this.subscription.add(fromEvent(input, 'compositionstart').pipe(filter(() => {
2648
- return !this.ignoreComposition;
2649
- })).subscribe(() => {
2650
- this.composition = true;
2651
- startIndex = this.selection.startOffset;
2652
- const startSlot = this.selection.startSlot;
2653
- const event = new Event(startSlot, {
2654
- index: startIndex
2655
- });
2656
- invokeListener(startSlot.parent, 'onCompositionStart', event);
2657
- }), fromEvent(input, 'compositionupdate').pipe(filter(() => {
2658
- return !this.ignoreComposition;
2659
- })).subscribe(ev => {
2660
- const startSlot = this.selection.startSlot;
2661
- const event = new Event(startSlot, {
2662
- index: startIndex,
2663
- data: ev.data
2664
- });
2665
- invokeListener(startSlot.parent, 'onCompositionUpdate', event);
2666
- }), merge(fromEvent(input, 'beforeinput').pipe(map(ev => {
2667
- var _a;
2668
- ev.preventDefault();
2669
- if (ev.inputType === 'insertCompositionText') {
2670
- return null;
2671
- }
2672
- if (ev.inputType === 'insertReplacementText') {
2673
- const range = ev.getTargetRanges()[0];
2674
- const location = this.domAdapter.getLocationByNativeNode(range.startContainer);
2675
- const startSlot = this.selection.startSlot;
2676
- this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
2677
- this.commander.delete();
2678
- return ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text')) || ev.data || null;
2679
- }
2680
- isCompositionEnd = ev.inputType === 'insertFromComposition';
2681
- if (isCompositionEnd && this.composition) {
2682
- return null;
2683
- }
2684
- if (this.isSafari) {
2685
- if (ev.inputType === 'insertText' || isCompositionEnd) {
2686
- return ev.data;
2687
- }
2688
- }
2689
- if (!ev.isComposing && !!ev.data) {
2690
- return ev.data;
2691
- }
2692
- return null;
2693
- }), filter(text => {
2694
- return text;
2695
- })), this.isSafari ? new Observable() :
2696
- fromEvent(input, 'compositionend').pipe(filter(() => {
2697
- return !this.ignoreComposition;
2698
- })).pipe(filter(() => {
2699
- return this.composition;
2700
- }), map(ev => {
2701
- isCompositionEnd = true;
2702
- ev.preventDefault();
2703
- return ev.data;
2704
- }), filter(() => {
2705
- const b = this.ignoreComposition;
2706
- this.ignoreComposition = false;
2707
- return !b;
2708
- }))).subscribe(text => {
2709
- this.composition = false;
2710
- if (text) {
2711
- const startContainer = this.nativeSelection.focusNode;
2712
- if (startContainer instanceof Text && startContainer.textContent === text) {
2713
- startContainer.remove();
2714
- }
2715
- this.commander.write(text);
2716
- }
2717
- if (isCompositionEnd) {
2718
- const startSlot = this.selection.startSlot;
2719
- if (startSlot) {
2720
- const event = new Event(startSlot, null);
2721
- invokeListener(startSlot.parent, 'onCompositionEnd', event);
2722
- }
2723
- }
2724
- isCompositionEnd = false;
2725
- }));
2726
- }
2727
- };
2728
- NativeInput = __decorate([
2729
- Injectable(),
2730
- __metadata("design:paramtypes", [Textbus,
2731
- Parser,
2732
- Selection,
2733
- Keyboard,
2734
- DomAdapter,
2735
- Commander,
2736
- Controller])
2737
- ], NativeInput);
2738
-
2739
- const browserErrorFn = makeError('BrowserModule');
2740
- class BrowserModule {
2741
- constructor(config) {
2742
- Object.defineProperty(this, "config", {
2743
- enumerable: true,
2744
- configurable: true,
2745
- writable: true,
2746
- value: config
2747
- });
2748
- Object.defineProperty(this, "providers", {
2749
- enumerable: true,
2750
- configurable: true,
2751
- writable: true,
2752
- value: void 0
2753
- });
2754
- Object.defineProperty(this, "workbench", {
2755
- enumerable: true,
2756
- configurable: true,
2757
- writable: true,
2758
- value: void 0
2759
- });
2760
- const { mask, wrapper } = BrowserModule.createLayout();
2761
- wrapper.prepend(config.adapter.host);
2762
- if (config.minHeight) {
2763
- config.adapter.host.style.minHeight = config.minHeight;
2764
- }
2765
- this.providers = [{
2766
- provide: EDITOR_OPTIONS,
2767
- useValue: config
2768
- }, {
2769
- provide: VIEW_CONTAINER,
2770
- useValue: wrapper
2771
- }, {
2772
- provide: VIEW_DOCUMENT,
2773
- useValue: config.adapter.host
2774
- }, {
2775
- provide: VIEW_MASK,
2776
- useValue: mask
2777
- }, {
2778
- provide: NativeSelectionBridge,
2779
- useExisting: SelectionBridge
2780
- }, {
2781
- provide: Input,
2782
- useClass: config.useContentEditable ? NativeInput : MagicInput
2783
- }, {
2784
- provide: Adapter,
2785
- useValue: config.adapter
2786
- }, {
2787
- provide: DomAdapter,
2788
- useValue: config.adapter
2789
- }, {
2790
- provide: FocusManager,
2791
- useFactory: (input) => {
2792
- const focusEvent = new Subject();
2793
- const blurEvent = new Subject();
2794
- input.caret.onPositionChange.pipe(map(p => !!p), distinctUntilChanged()).subscribe(b => {
2795
- if (b) {
2796
- focusEvent.next();
2797
- }
2798
- else {
2799
- blurEvent.next();
2800
- }
2801
- });
2802
- return {
2803
- onFocus: focusEvent,
2804
- onBlur: blurEvent
2805
- };
2806
- },
2807
- deps: [Input]
2808
- },
2809
- Parser,
2810
- SelectionBridge,
2811
- CollaborateCursor];
2812
- this.workbench = wrapper;
2813
- }
2814
- /**
2815
- * 解析 HTML 并返回一个组件实例
2816
- * @param html 要解析的 HTML
2817
- * @param rootComponentLoader 文档根组件加载器
2818
- * @param textbus
2819
- */
2820
- readDocumentByHTML(html, rootComponentLoader, textbus) {
2821
- const parser = textbus.get(Parser);
2822
- const doc = parser.parseDoc(html, rootComponentLoader);
2823
- if (doc instanceof Component) {
2824
- return doc;
2825
- }
2826
- throw browserErrorFn('rootComponentLoader must return a component instance.');
2827
- }
2828
- /**
2829
- * 将组件数据解析到组件实例中
2830
- * @param data 要解析的 JSON 数据
2831
- * @param rootComponent 根组件
2832
- * @param textbus
2833
- */
2834
- readDocumentByComponentLiteral(data, rootComponent, textbus) {
2835
- const registry = textbus.get(Registry);
2836
- return registry.createComponentByFactory(data, rootComponent);
2837
- }
2838
- setup(textbus) {
2839
- return __awaiter(this, void 0, void 0, function* () {
2840
- const host = this.config.renderTo();
2841
- if (!(host instanceof HTMLElement)) {
2842
- throw browserErrorFn('view container is not a HTMLElement');
2843
- }
2844
- host.append(this.workbench);
2845
- yield textbus.get(Input).onReady;
2846
- return () => {
2847
- this.workbench.remove();
2848
- };
2849
- });
2850
- }
2851
- onAfterStartup(textbus) {
2852
- if (this.config.autoFocus) {
2853
- textbus.focus();
2854
- }
2855
- }
2856
- onDestroy(textbus) {
2857
- textbus.get(Input).destroy();
2858
- textbus.get(SelectionBridge).destroy();
2859
- textbus.get(CollaborateCursor).destroy();
2860
- }
2861
- static createLayout() {
2862
- const mask = createElement('div', {
2863
- attrs: {
2864
- 'data-textbus-view': VIEW_MASK,
2865
- },
2866
- styles: {
2867
- position: 'absolute',
2868
- left: 0,
2869
- right: 0,
2870
- top: 0,
2871
- bottom: 0,
2872
- pointerEvents: 'none',
2873
- // overflow: 'hidden'
2874
- }
2875
- });
2876
- const maskWrapper = createElement('div', {
2877
- styles: {
2878
- position: 'absolute',
2879
- left: 0,
2880
- right: 0,
2881
- top: 0,
2882
- bottom: 0,
2883
- margin: '0 -2px',
2884
- zIndex: 1,
2885
- pointerEvents: 'none',
2886
- overflow: 'hidden'
2887
- },
2888
- children: [mask]
2889
- });
2890
- const wrapper = createElement('div', {
2891
- attrs: {
2892
- 'data-textbus-view': VIEW_CONTAINER,
2893
- },
2894
- styles: {
2895
- display: 'flex',
2896
- minHeight: '100%',
2897
- position: 'relative',
2898
- flexDirection: 'column'
2899
- },
2900
- children: [maskWrapper]
2901
- });
2902
- return {
2903
- wrapper,
2904
- mask
2905
- };
2906
- }
2907
- }
2908
-
2909
- export { BrowserModule, CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomAdapter, EDITOR_OPTIONS, Input, MagicInput, NativeInput, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, createElement, getLayoutRectByRange, isFirefox, isMac, isMobileBrowser, isSafari, isWindows };