@textbus/platform-browser 4.0.0-alpha.8 → 4.0.1
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.
- package/bundles/_utils/uikit.d.ts +0 -1
- package/bundles/browser-module.d.ts +24 -7
- package/bundles/collaborate-cursor.d.ts +7 -12
- package/bundles/dom-adapter.d.ts +4 -64
- package/bundles/index.esm.js +273 -351
- package/bundles/index.js +275 -354
- package/bundles/magic-input.d.ts +10 -11
- package/bundles/native-input.d.ts +4 -9
- package/bundles/parser.d.ts +9 -10
- package/bundles/public-api.d.ts +1 -0
- package/bundles/selection-bridge.d.ts +2 -2
- package/bundles/types.d.ts +1 -14
- package/package.json +6 -6
package/bundles/index.esm.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import 'reflect-metadata';
|
2
|
-
import { Slot, Textbus,
|
2
|
+
import { Slot, Textbus, Adapter, Controller, Selection, RootComponentRef, ContentType, Event, invokeListener, Keyboard, Commander, Scheduler, makeError, NativeSelectionBridge, FocusManager, Component, Registry } from '@textbus/core';
|
3
3
|
import { Subject, filter, fromEvent, Subscription, distinctUntilChanged, merge, map, Observable } from '@tanbo/stream';
|
4
4
|
import { InjectionToken, Injectable, Inject, Optional } from '@viewfly/core';
|
5
|
+
import { UserActivity } from '@textbus/collaborate';
|
5
6
|
|
6
7
|
function createElement(tagName, options = {}) {
|
7
8
|
const el = document.createElement(tagName);
|
@@ -33,9 +34,6 @@ function createElement(tagName, options = {}) {
|
|
33
34
|
}
|
34
35
|
return el;
|
35
36
|
}
|
36
|
-
function createTextNode(content) {
|
37
|
-
return document.createTextNode(content);
|
38
|
-
}
|
39
37
|
function getLayoutRectByRange(range) {
|
40
38
|
let { startContainer, startOffset } = range;
|
41
39
|
if (startContainer.nodeType === Node.TEXT_NODE) {
|
@@ -53,7 +51,7 @@ function getLayoutRectByRange(range) {
|
|
53
51
|
return {
|
54
52
|
left: rect.right,
|
55
53
|
top: rect.top,
|
56
|
-
width: rect.width,
|
54
|
+
width: range.collapsed ? 0 : rect.width,
|
57
55
|
height: rect.height
|
58
56
|
};
|
59
57
|
}
|
@@ -61,7 +59,13 @@ function getLayoutRectByRange(range) {
|
|
61
59
|
const range2 = document.createRange();
|
62
60
|
range2.setStart(beforeNode, beforeNode.textContent.length);
|
63
61
|
range2.setEnd(beforeNode, beforeNode.textContent.length);
|
64
|
-
|
62
|
+
const rect = range2.getBoundingClientRect();
|
63
|
+
return {
|
64
|
+
left: rect.right,
|
65
|
+
top: rect.top,
|
66
|
+
width: range.collapsed ? 0 : rect.width,
|
67
|
+
height: rect.height
|
68
|
+
};
|
65
69
|
}
|
66
70
|
}
|
67
71
|
const offsetNode = startContainer.childNodes[startOffset];
|
@@ -73,14 +77,20 @@ function getLayoutRectByRange(range) {
|
|
73
77
|
return {
|
74
78
|
left: rect.right,
|
75
79
|
top: rect.top,
|
76
|
-
width: rect.width,
|
80
|
+
width: range.collapsed ? 0 : rect.width,
|
77
81
|
height: rect.height
|
78
82
|
};
|
79
83
|
}
|
80
84
|
}
|
81
85
|
if (offsetNode) {
|
82
86
|
if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') {
|
83
|
-
|
87
|
+
const rect = offsetNode.getBoundingClientRect();
|
88
|
+
return {
|
89
|
+
left: rect.left,
|
90
|
+
top: rect.top,
|
91
|
+
width: range.collapsed ? 0 : rect.width,
|
92
|
+
height: rect.height
|
93
|
+
};
|
84
94
|
}
|
85
95
|
isInsertBefore = true;
|
86
96
|
}
|
@@ -95,7 +105,12 @@ function getLayoutRectByRange(range) {
|
|
95
105
|
}
|
96
106
|
const rect = span.getBoundingClientRect();
|
97
107
|
startContainer.removeChild(span);
|
98
|
-
return
|
108
|
+
return {
|
109
|
+
left: rect.left,
|
110
|
+
top: rect.top,
|
111
|
+
width: range.collapsed ? 0 : rect.width,
|
112
|
+
height: rect.height
|
113
|
+
};
|
99
114
|
}
|
100
115
|
|
101
116
|
const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
|
@@ -167,7 +182,6 @@ let Parser = Parser_1 = class Parser {
|
|
167
182
|
return new DOMParser().parseFromString(html, 'text/html').body;
|
168
183
|
}
|
169
184
|
constructor(options, textbus) {
|
170
|
-
this.options = options;
|
171
185
|
this.textbus = textbus;
|
172
186
|
const componentLoaders = [
|
173
187
|
...(options.componentLoaders || [])
|
@@ -212,8 +226,9 @@ let Parser = Parser_1 = class Parser {
|
|
212
226
|
slot.insert('\n');
|
213
227
|
return;
|
214
228
|
}
|
229
|
+
const schema = [...slot.schema];
|
215
230
|
for (const t of this.componentLoaders) {
|
216
|
-
if (t.match(el)) {
|
231
|
+
if (t.match(el, schema)) {
|
217
232
|
const result = t.read(el, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
|
218
233
|
return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
|
219
234
|
});
|
@@ -300,13 +315,10 @@ Parser = Parser_1 = __decorate([
|
|
300
315
|
class Input {
|
301
316
|
}
|
302
317
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
constructor(mount) {
|
308
|
-
super();
|
309
|
-
this.mount = mount;
|
318
|
+
class DomAdapter extends Adapter {
|
319
|
+
constructor() {
|
320
|
+
super(...arguments);
|
321
|
+
this.onViewUpdated = new Subject();
|
310
322
|
this.host = createElement('div', {
|
311
323
|
styles: {
|
312
324
|
cursor: 'text',
|
@@ -322,126 +334,6 @@ class DomAdapter extends ViewAdapter {
|
|
322
334
|
id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)
|
323
335
|
}
|
324
336
|
});
|
325
|
-
this.componentRootElementCaches = createBidirectionalMapping(a => {
|
326
|
-
return a instanceof ComponentInstance;
|
327
|
-
});
|
328
|
-
this.slotRootNativeElementCaches = createBidirectionalMapping(a => {
|
329
|
-
return a instanceof Slot;
|
330
|
-
});
|
331
|
-
this.slotRootVElementCaches = new WeakMap();
|
332
|
-
}
|
333
|
-
render(rootComponent) {
|
334
|
-
const view = this.componentRender(rootComponent);
|
335
|
-
return this.mount(this.host, view);
|
336
|
-
}
|
337
|
-
copy() {
|
338
|
-
document.execCommand('copy');
|
339
|
-
}
|
340
|
-
/**
|
341
|
-
* 根据组件获取组件的根 DOM 节点
|
342
|
-
* @param component
|
343
|
-
*/
|
344
|
-
getNativeNodeByComponent(component) {
|
345
|
-
return this.componentRootElementCaches.get(component) || null;
|
346
|
-
}
|
347
|
-
/**
|
348
|
-
* 根据 DOM 节点,获对对应的组件根节点,如传入的 DOM 节点不为组件的根节点,则返回 null
|
349
|
-
* @param node
|
350
|
-
*/
|
351
|
-
getComponentByNativeNode(node) {
|
352
|
-
return this.componentRootElementCaches.get(node) || null;
|
353
|
-
}
|
354
|
-
/**
|
355
|
-
* 根据插槽获取插槽的根 DOM 节点
|
356
|
-
* @param slot
|
357
|
-
*/
|
358
|
-
getNativeNodeBySlot(slot) {
|
359
|
-
return this.slotRootNativeElementCaches.get(slot) || null;
|
360
|
-
}
|
361
|
-
/**
|
362
|
-
* 根据 DOM 节点,获对对应的插槽根节点,如传入的 DOM 节点不为插槽的根节点,则返回 null
|
363
|
-
* @param node
|
364
|
-
*/
|
365
|
-
getSlotByNativeNode(node) {
|
366
|
-
return this.slotRootNativeElementCaches.get(node) || null;
|
367
|
-
}
|
368
|
-
/**
|
369
|
-
* 获取插槽内容节点集合
|
370
|
-
* @param slot
|
371
|
-
*/
|
372
|
-
getNodesBySlot(slot) {
|
373
|
-
const rootNativeNode = this.getNativeNodeBySlot(slot);
|
374
|
-
if (!rootNativeNode) {
|
375
|
-
return [];
|
376
|
-
}
|
377
|
-
const rootVNode = this.slotRootVElementCaches.get(slot);
|
378
|
-
const getNodes = (vElement, nativeNode, result) => {
|
379
|
-
if (vElement.location) {
|
380
|
-
result.push(nativeNode);
|
381
|
-
}
|
382
|
-
for (let i = 0; i < vElement.children.length; i++) {
|
383
|
-
const vChild = vElement.children[i];
|
384
|
-
const nativeChild = nativeNode.childNodes[i];
|
385
|
-
if (vChild instanceof VElement) {
|
386
|
-
getNodes(vChild, nativeChild, result);
|
387
|
-
}
|
388
|
-
else if (vChild instanceof VTextNode) {
|
389
|
-
result.push(nativeChild);
|
390
|
-
}
|
391
|
-
else {
|
392
|
-
result.push(this.getNativeNodeByComponent(vChild));
|
393
|
-
}
|
394
|
-
}
|
395
|
-
return result;
|
396
|
-
};
|
397
|
-
return getNodes(rootVNode, rootNativeNode, []);
|
398
|
-
}
|
399
|
-
/**
|
400
|
-
* 获取原生节点的原始数据在文档中的位置
|
401
|
-
* @param node
|
402
|
-
*/
|
403
|
-
getLocationByNativeNode(node) {
|
404
|
-
let slotRootNode = node;
|
405
|
-
while (!this.slotRootNativeElementCaches.get(slotRootNode)) {
|
406
|
-
slotRootNode = slotRootNode.parentNode;
|
407
|
-
if (!slotRootNode) {
|
408
|
-
return null;
|
409
|
-
}
|
410
|
-
}
|
411
|
-
const slot = this.slotRootNativeElementCaches.get(slotRootNode);
|
412
|
-
const rootVNode = this.slotRootVElementCaches.get(slot);
|
413
|
-
const getLocation = (target, tree, vNodeTree) => {
|
414
|
-
if (target === tree) {
|
415
|
-
return Object.assign({}, vNodeTree.location);
|
416
|
-
}
|
417
|
-
const childNodes = tree.childNodes;
|
418
|
-
for (let i = 0; i < childNodes.length; i++) {
|
419
|
-
const child = vNodeTree.children[i];
|
420
|
-
const nativeChild = tree.childNodes[i];
|
421
|
-
if (nativeChild === target) {
|
422
|
-
if (child instanceof ComponentInstance) {
|
423
|
-
const index = child.parent.indexOf(child);
|
424
|
-
return {
|
425
|
-
slot: child.parent,
|
426
|
-
startIndex: index,
|
427
|
-
endIndex: index + 1
|
428
|
-
};
|
429
|
-
}
|
430
|
-
return child.location;
|
431
|
-
}
|
432
|
-
else if (child instanceof VElement) {
|
433
|
-
let r = null;
|
434
|
-
if (nativeChild.nodeType === Node.ELEMENT_NODE) {
|
435
|
-
r = getLocation(target, nativeChild, child);
|
436
|
-
}
|
437
|
-
if (r) {
|
438
|
-
return r;
|
439
|
-
}
|
440
|
-
}
|
441
|
-
}
|
442
|
-
return null;
|
443
|
-
};
|
444
|
-
return getLocation(node, slotRootNode, rootVNode);
|
445
337
|
}
|
446
338
|
}
|
447
339
|
|
@@ -540,7 +432,33 @@ let SelectionBridge = class SelectionBridge {
|
|
540
432
|
this.listen(this.connector);
|
541
433
|
return;
|
542
434
|
}
|
543
|
-
|
435
|
+
function tryOffset(position) {
|
436
|
+
if (!position.node) {
|
437
|
+
return;
|
438
|
+
}
|
439
|
+
if (position.node.nodeType === Node.TEXT_NODE) {
|
440
|
+
const len = position.node.textContent.length;
|
441
|
+
if (position.offset > len) {
|
442
|
+
position.offset = len;
|
443
|
+
}
|
444
|
+
}
|
445
|
+
else if (position.node.nodeType === Node.ELEMENT_NODE) {
|
446
|
+
const len = position.node.childNodes.length;
|
447
|
+
if (position.offset > len) {
|
448
|
+
position.offset = len;
|
449
|
+
}
|
450
|
+
}
|
451
|
+
}
|
452
|
+
try {
|
453
|
+
tryOffset(focus);
|
454
|
+
tryOffset(anchor);
|
455
|
+
this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
|
456
|
+
}
|
457
|
+
catch (e) {
|
458
|
+
setTimeout(() => {
|
459
|
+
throw e;
|
460
|
+
});
|
461
|
+
}
|
544
462
|
if (this.nativeSelection.rangeCount) {
|
545
463
|
const nativeRange = this.nativeSelection.getRangeAt(0);
|
546
464
|
this.selectionChangeEvent.next(nativeRange);
|
@@ -563,6 +481,7 @@ let SelectionBridge = class SelectionBridge {
|
|
563
481
|
// hack end
|
564
482
|
}
|
565
483
|
destroy() {
|
484
|
+
this.subs.forEach(i => i.unsubscribe());
|
566
485
|
this.sub.unsubscribe();
|
567
486
|
}
|
568
487
|
getPositionByRange(abstractSelection) {
|
@@ -645,9 +564,10 @@ let SelectionBridge = class SelectionBridge {
|
|
645
564
|
}
|
646
565
|
minLeft = rect2.left;
|
647
566
|
minTop = rect2.top;
|
567
|
+
// oldPosition = position
|
648
568
|
}
|
649
569
|
if (isToPrevLine) {
|
650
|
-
if (rect2.left
|
570
|
+
if (rect2.left <= startLeft) {
|
651
571
|
return position;
|
652
572
|
}
|
653
573
|
if (oldPosition) {
|
@@ -760,14 +680,14 @@ let SelectionBridge = class SelectionBridge {
|
|
760
680
|
const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset;
|
761
681
|
if (!this.docContainer.contains(selection.focusNode)) {
|
762
682
|
if (isFocusEnd) {
|
763
|
-
const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.
|
683
|
+
const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(0));
|
764
684
|
if (!nativeNode) {
|
765
685
|
return;
|
766
686
|
}
|
767
687
|
nativeRange.setEndAfter(nativeNode.lastChild);
|
768
688
|
}
|
769
689
|
else {
|
770
|
-
const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.
|
690
|
+
const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(-1));
|
771
691
|
if (!nativeNode) {
|
772
692
|
return;
|
773
693
|
}
|
@@ -1028,25 +948,24 @@ class ExperimentalCaret {
|
|
1028
948
|
get display() {
|
1029
949
|
return this._display;
|
1030
950
|
}
|
1031
|
-
constructor(scheduler, editorMask) {
|
951
|
+
constructor(domRenderer, scheduler, editorMask) {
|
952
|
+
this.domRenderer = domRenderer;
|
1032
953
|
this.scheduler = scheduler;
|
1033
954
|
this.editorMask = editorMask;
|
1034
|
-
this.
|
1035
|
-
this.
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
955
|
+
this.changeFromSelf = false;
|
956
|
+
this.getLimit = function () {
|
957
|
+
return {
|
958
|
+
top: 0,
|
959
|
+
bottom: document.documentElement.clientHeight
|
960
|
+
};
|
961
|
+
};
|
1040
962
|
this.timer = null;
|
1041
|
-
this.oldPosition = null;
|
1042
963
|
this._display = true;
|
1043
964
|
this.flashing = true;
|
1044
|
-
this.subs = [];
|
1045
965
|
this.subscription = new Subscription();
|
1046
966
|
this.positionChangeEvent = new Subject();
|
1047
967
|
this.styleChangeEvent = new Subject();
|
1048
968
|
this.oldRange = null;
|
1049
|
-
this.isFixed = false;
|
1050
969
|
this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
|
1051
970
|
this.onStyleChange = this.styleChangeEvent.asObservable();
|
1052
971
|
this.elementRef = createElement('div', {
|
@@ -1074,20 +993,12 @@ class ExperimentalCaret {
|
|
1074
993
|
}));
|
1075
994
|
this.editorMask.appendChild(this.elementRef);
|
1076
995
|
}
|
1077
|
-
refresh(
|
1078
|
-
this.isFixed = isFixedCaret;
|
996
|
+
refresh() {
|
1079
997
|
if (this.oldRange) {
|
1080
998
|
this.show(this.oldRange, false);
|
1081
999
|
}
|
1082
|
-
this.isFixed = false;
|
1083
1000
|
}
|
1084
1001
|
show(range, restart) {
|
1085
|
-
const oldRect = this.elementRef.getBoundingClientRect();
|
1086
|
-
this.oldPosition = {
|
1087
|
-
top: oldRect.top,
|
1088
|
-
left: oldRect.left,
|
1089
|
-
height: oldRect.height
|
1090
|
-
};
|
1091
1002
|
this.oldRange = range;
|
1092
1003
|
if (restart || this.scheduler.lastChangesHasLocalUpdate) {
|
1093
1004
|
clearTimeout(this.timer);
|
@@ -1116,62 +1027,8 @@ class ExperimentalCaret {
|
|
1116
1027
|
}
|
1117
1028
|
destroy() {
|
1118
1029
|
clearTimeout(this.timer);
|
1030
|
+
// this.caret.
|
1119
1031
|
this.subscription.unsubscribe();
|
1120
|
-
this.subs.forEach(i => i.unsubscribe());
|
1121
|
-
}
|
1122
|
-
correctScrollTop(scroller) {
|
1123
|
-
this.subs.forEach(i => i.unsubscribe());
|
1124
|
-
this.subs = [];
|
1125
|
-
const scheduler = this.scheduler;
|
1126
|
-
let docIsChanged = true;
|
1127
|
-
function limitPosition(position) {
|
1128
|
-
const { top, bottom } = scroller.getLimit();
|
1129
|
-
const caretTop = position.top;
|
1130
|
-
if (caretTop + position.height > bottom) {
|
1131
|
-
const offset = caretTop - bottom + position.height;
|
1132
|
-
scroller.setOffset(offset);
|
1133
|
-
}
|
1134
|
-
else if (position.top < top) {
|
1135
|
-
scroller.setOffset(-(top - position.top));
|
1136
|
-
}
|
1137
|
-
}
|
1138
|
-
let isPressed = false;
|
1139
|
-
this.subs.push(scroller.onScroll.subscribe(() => {
|
1140
|
-
if (this.oldPosition) {
|
1141
|
-
const rect = this.rect;
|
1142
|
-
this.oldPosition.top = rect.top;
|
1143
|
-
this.oldPosition.left = rect.left;
|
1144
|
-
this.oldPosition.height = rect.height;
|
1145
|
-
}
|
1146
|
-
}), fromEvent(document, 'mousedown', true).subscribe(() => {
|
1147
|
-
isPressed = true;
|
1148
|
-
}), fromEvent(document, 'mouseup', true).subscribe(() => {
|
1149
|
-
isPressed = false;
|
1150
|
-
}), scheduler.onDocChange.subscribe(() => {
|
1151
|
-
docIsChanged = true;
|
1152
|
-
}), this.onPositionChange.subscribe(position => {
|
1153
|
-
if (position) {
|
1154
|
-
if (docIsChanged) {
|
1155
|
-
if (scheduler.lastChangesHasLocalUpdate) {
|
1156
|
-
limitPosition(position);
|
1157
|
-
}
|
1158
|
-
else if (this.oldPosition) {
|
1159
|
-
const offset = Math.floor(position.top - this.oldPosition.top);
|
1160
|
-
scroller.setOffset(offset);
|
1161
|
-
}
|
1162
|
-
}
|
1163
|
-
else if (!isPressed) {
|
1164
|
-
if (this.isFixed && this.oldPosition) {
|
1165
|
-
const offset = Math.floor(position.top - this.oldPosition.top);
|
1166
|
-
scroller.setOffset(offset);
|
1167
|
-
}
|
1168
|
-
else {
|
1169
|
-
limitPosition(position);
|
1170
|
-
}
|
1171
|
-
}
|
1172
|
-
}
|
1173
|
-
docIsChanged = false;
|
1174
|
-
}));
|
1175
1032
|
}
|
1176
1033
|
updateCursorPosition(nativeRange) {
|
1177
1034
|
const startContainer = nativeRange.startContainer;
|
@@ -1180,12 +1037,10 @@ class ExperimentalCaret {
|
|
1180
1037
|
this.positionChangeEvent.next(null);
|
1181
1038
|
return;
|
1182
1039
|
}
|
1183
|
-
|
1184
|
-
|
1185
|
-
compositionElement.innerText = this.compositionState.data;
|
1040
|
+
const compositionNode = this.domRenderer.compositionNode;
|
1041
|
+
if (compositionNode) {
|
1186
1042
|
nativeRange = nativeRange.cloneRange();
|
1187
|
-
nativeRange.
|
1188
|
-
nativeRange.selectNodeContents(compositionElement);
|
1043
|
+
nativeRange.selectNodeContents(compositionNode);
|
1189
1044
|
nativeRange.collapse();
|
1190
1045
|
}
|
1191
1046
|
const rect = getLayoutRectByRange(nativeRange);
|
@@ -1212,13 +1067,34 @@ class ExperimentalCaret {
|
|
1212
1067
|
rectTop = Math.floor(rectTop);
|
1213
1068
|
const containerRect = this.editorMask.getBoundingClientRect();
|
1214
1069
|
const top = Math.floor(rectTop - containerRect.top);
|
1215
|
-
const left = Math.floor(rect.left - containerRect.left);
|
1070
|
+
const left = Math.floor(rect.left + rect.width / 2 - containerRect.left);
|
1071
|
+
let rotate = 0;
|
1072
|
+
if (nativeRange.collapsed) {
|
1073
|
+
rotate = Math.round(Math.atan2(rect.width, rect.height) * 180 / Math.PI);
|
1074
|
+
if (rotate !== 0) {
|
1075
|
+
const hackEle = document.createElement('span');
|
1076
|
+
hackEle.style.cssText = 'display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size;';
|
1077
|
+
const pointEle = document.createElement('span');
|
1078
|
+
pointEle.style.cssText = 'position: absolute; left: 0; top: 0; width:0;height:0';
|
1079
|
+
hackEle.append(pointEle);
|
1080
|
+
node.append(hackEle);
|
1081
|
+
const t1 = pointEle.getBoundingClientRect().top;
|
1082
|
+
pointEle.style.right = '0';
|
1083
|
+
pointEle.style.left = '';
|
1084
|
+
const t2 = pointEle.getBoundingClientRect().top;
|
1085
|
+
if (t2 < t1) {
|
1086
|
+
rotate = -rotate;
|
1087
|
+
}
|
1088
|
+
hackEle.remove();
|
1089
|
+
}
|
1090
|
+
}
|
1216
1091
|
Object.assign(this.elementRef.style, {
|
1217
1092
|
left: left + 'px',
|
1218
1093
|
top: top + 'px',
|
1219
1094
|
height: boxHeight + 'px',
|
1220
1095
|
lineHeight: boxHeight + 'px',
|
1221
|
-
fontSize
|
1096
|
+
fontSize,
|
1097
|
+
transform: `rotate(${rotate}deg)`,
|
1222
1098
|
});
|
1223
1099
|
this.caret.style.backgroundColor = color;
|
1224
1100
|
this.styleChangeEvent.next({
|
@@ -1231,6 +1107,21 @@ class ExperimentalCaret {
|
|
1231
1107
|
top: rectTop,
|
1232
1108
|
height: boxHeight
|
1233
1109
|
});
|
1110
|
+
if (this.changeFromSelf) {
|
1111
|
+
this.changeFromSelf = false;
|
1112
|
+
const selfRect = this.elementRef.getBoundingClientRect();
|
1113
|
+
const limit = this.getLimit();
|
1114
|
+
if (selfRect.top < limit.top) {
|
1115
|
+
this.elementRef.scrollIntoView({
|
1116
|
+
block: 'start'
|
1117
|
+
});
|
1118
|
+
}
|
1119
|
+
else if (selfRect.bottom > limit.bottom) {
|
1120
|
+
this.elementRef.scrollIntoView({
|
1121
|
+
block: 'end'
|
1122
|
+
});
|
1123
|
+
}
|
1124
|
+
}
|
1234
1125
|
}
|
1235
1126
|
}
|
1236
1127
|
/**
|
@@ -1246,8 +1137,9 @@ let MagicInput = class MagicInput extends Input {
|
|
1246
1137
|
get disabled() {
|
1247
1138
|
return this._disabled;
|
1248
1139
|
}
|
1249
|
-
constructor(parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1140
|
+
constructor(domAdapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1250
1141
|
super();
|
1142
|
+
this.domAdapter = domAdapter;
|
1251
1143
|
this.parser = parser;
|
1252
1144
|
this.keyboard = keyboard;
|
1253
1145
|
this.commander = commander;
|
@@ -1256,8 +1148,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1256
1148
|
this.scheduler = scheduler;
|
1257
1149
|
this.textbus = textbus;
|
1258
1150
|
this.composition = false;
|
1259
|
-
this.
|
1260
|
-
this.caret = new ExperimentalCaret(this.scheduler, this.textbus.get(VIEW_MASK));
|
1151
|
+
this.caret = new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK));
|
1261
1152
|
this.isSafari = isSafari();
|
1262
1153
|
this.isFirefox = isFirefox();
|
1263
1154
|
this.isMac = isMac();
|
@@ -1297,13 +1188,8 @@ let MagicInput = class MagicInput extends Input {
|
|
1297
1188
|
if (!this.isFocus) {
|
1298
1189
|
(_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
|
1299
1190
|
setTimeout(() => {
|
1300
|
-
var _a, _b, _c;
|
1301
1191
|
if (!this.nativeFocus && this.isFocus) {
|
1302
|
-
this.
|
1303
|
-
(_b = (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.textarea);
|
1304
|
-
this.subscription = new Subscription();
|
1305
|
-
this.init();
|
1306
|
-
(_c = this.textarea) === null || _c === void 0 ? void 0 : _c.focus();
|
1192
|
+
this.reInit();
|
1307
1193
|
}
|
1308
1194
|
});
|
1309
1195
|
}
|
@@ -1319,6 +1205,22 @@ let MagicInput = class MagicInput extends Input {
|
|
1319
1205
|
this.caret.destroy();
|
1320
1206
|
this.subscription.unsubscribe();
|
1321
1207
|
}
|
1208
|
+
reInit(delay = false) {
|
1209
|
+
var _a, _b, _c;
|
1210
|
+
this.subscription.unsubscribe();
|
1211
|
+
(_b = (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.textarea);
|
1212
|
+
this.subscription = new Subscription();
|
1213
|
+
this.init();
|
1214
|
+
if (delay) {
|
1215
|
+
setTimeout(() => {
|
1216
|
+
var _a;
|
1217
|
+
(_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
|
1218
|
+
});
|
1219
|
+
}
|
1220
|
+
else {
|
1221
|
+
(_c = this.textarea) === null || _c === void 0 ? void 0 : _c.focus();
|
1222
|
+
}
|
1223
|
+
}
|
1322
1224
|
init() {
|
1323
1225
|
const doc = this.doc;
|
1324
1226
|
const contentBody = doc.body;
|
@@ -1327,9 +1229,19 @@ let MagicInput = class MagicInput extends Input {
|
|
1327
1229
|
contentBody.appendChild(textarea);
|
1328
1230
|
this.textarea = textarea;
|
1329
1231
|
this.subscription.add(fromEvent(textarea, 'blur').subscribe(() => {
|
1232
|
+
// if (this.isFocus) {
|
1233
|
+
// this.isFocus = false
|
1234
|
+
// this.reInit(true)
|
1235
|
+
// }
|
1330
1236
|
this.isFocus = false;
|
1331
1237
|
this.nativeFocus = false;
|
1332
1238
|
this.caret.hide();
|
1239
|
+
if (this.domAdapter.composition) {
|
1240
|
+
const slot = this.domAdapter.composition.slot;
|
1241
|
+
this.domAdapter.composition = null;
|
1242
|
+
this.domAdapter.compositionNode = null;
|
1243
|
+
slot.__changeMarker__.forceMarkDirtied();
|
1244
|
+
}
|
1333
1245
|
}), fromEvent(textarea, 'focus').subscribe(() => {
|
1334
1246
|
this.nativeFocus = true;
|
1335
1247
|
}), this.caret.onStyleChange.subscribe(style => {
|
@@ -1340,7 +1252,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1340
1252
|
this.handleDefaultActions(textarea);
|
1341
1253
|
}
|
1342
1254
|
handleDefaultActions(textarea) {
|
1343
|
-
this.subscription.add(fromEvent(document, 'copy').subscribe(ev => {
|
1255
|
+
this.subscription.add(fromEvent(isFirefox() ? textarea : document, 'copy').subscribe(ev => {
|
1344
1256
|
const selection = this.selection;
|
1345
1257
|
if (!selection.isSelected) {
|
1346
1258
|
return;
|
@@ -1410,6 +1322,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1410
1322
|
}), fromEvent(textarea, 'compositionend').subscribe(() => {
|
1411
1323
|
isWriting = false;
|
1412
1324
|
}), fromEvent(textarea, 'beforeinput').subscribe(ev => {
|
1325
|
+
this.ignoreComposition = false;
|
1413
1326
|
if (this.isSafari) {
|
1414
1327
|
if (ev.inputType === 'insertFromComposition') {
|
1415
1328
|
isIgnore = true;
|
@@ -1431,6 +1344,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1431
1344
|
key = keys.charAt(+ev.code.substring(5));
|
1432
1345
|
ev.preventDefault();
|
1433
1346
|
}
|
1347
|
+
this.caret.changeFromSelf = true;
|
1434
1348
|
const is = this.keyboard.execShortcut({
|
1435
1349
|
key: key,
|
1436
1350
|
altKey: ev.altKey,
|
@@ -1441,6 +1355,9 @@ let MagicInput = class MagicInput extends Input {
|
|
1441
1355
|
this.ignoreComposition = true;
|
1442
1356
|
ev.preventDefault();
|
1443
1357
|
}
|
1358
|
+
else {
|
1359
|
+
this.caret.changeFromSelf = false;
|
1360
|
+
}
|
1444
1361
|
}));
|
1445
1362
|
}
|
1446
1363
|
handleInput(textarea) {
|
@@ -1449,10 +1366,10 @@ let MagicInput = class MagicInput extends Input {
|
|
1449
1366
|
return !this.ignoreComposition;
|
1450
1367
|
})).subscribe(() => {
|
1451
1368
|
if (!this.selection.isCollapsed) {
|
1369
|
+
this.caret.changeFromSelf = true;
|
1452
1370
|
this.commander.delete();
|
1453
1371
|
}
|
1454
1372
|
this.composition = true;
|
1455
|
-
this.caret.compositionState = this.compositionState = null;
|
1456
1373
|
startIndex = this.selection.startOffset;
|
1457
1374
|
const startSlot = this.selection.startSlot;
|
1458
1375
|
const event = new Event(startSlot, {
|
@@ -1469,17 +1386,20 @@ let MagicInput = class MagicInput extends Input {
|
|
1469
1386
|
return;
|
1470
1387
|
}
|
1471
1388
|
const startSlot = this.selection.startSlot;
|
1472
|
-
this.
|
1389
|
+
this.domAdapter.composition = {
|
1473
1390
|
slot: startSlot,
|
1474
|
-
|
1475
|
-
|
1391
|
+
text: ev.data,
|
1392
|
+
offset: ev.data.length,
|
1393
|
+
index: startIndex
|
1476
1394
|
};
|
1477
|
-
this.caret.
|
1395
|
+
this.caret.changeFromSelf = true;
|
1396
|
+
this.caret.refresh();
|
1478
1397
|
const event = new Event(startSlot, {
|
1479
1398
|
index: startIndex,
|
1480
1399
|
data: ev.data
|
1481
1400
|
});
|
1482
1401
|
invokeListener(startSlot.parent, 'onCompositionUpdate', event);
|
1402
|
+
startSlot.__changeMarker__.forceMarkDirtied();
|
1483
1403
|
}));
|
1484
1404
|
let isCompositionEnd = false;
|
1485
1405
|
this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
|
@@ -1503,24 +1423,16 @@ let MagicInput = class MagicInput extends Input {
|
|
1503
1423
|
textarea.value = '';
|
1504
1424
|
return ev.data;
|
1505
1425
|
}))).subscribe(text => {
|
1426
|
+
var _a;
|
1506
1427
|
this.composition = false;
|
1507
|
-
this.
|
1508
|
-
const compositionElement = this.caret.compositionElement;
|
1509
|
-
let nextSibling = compositionElement.nextSibling;
|
1510
|
-
while (nextSibling) {
|
1511
|
-
if (!nextSibling.textContent) {
|
1512
|
-
const next = nextSibling.nextSibling;
|
1513
|
-
nextSibling.remove();
|
1514
|
-
nextSibling = next;
|
1515
|
-
continue;
|
1516
|
-
}
|
1517
|
-
nextSibling.remove();
|
1518
|
-
break;
|
1519
|
-
}
|
1520
|
-
compositionElement.remove();
|
1428
|
+
this.domAdapter.composition = null;
|
1521
1429
|
if (text) {
|
1430
|
+
this.caret.changeFromSelf = true;
|
1522
1431
|
this.commander.write(text);
|
1523
1432
|
}
|
1433
|
+
else {
|
1434
|
+
(_a = this.selection.startSlot) === null || _a === void 0 ? void 0 : _a.__changeMarker__.forceMarkDirtied();
|
1435
|
+
}
|
1524
1436
|
if (isCompositionEnd) {
|
1525
1437
|
const startSlot = this.selection.startSlot;
|
1526
1438
|
if (startSlot) {
|
@@ -1549,7 +1461,8 @@ let MagicInput = class MagicInput extends Input {
|
|
1549
1461
|
};
|
1550
1462
|
MagicInput = __decorate([
|
1551
1463
|
Injectable(),
|
1552
|
-
__metadata("design:paramtypes", [
|
1464
|
+
__metadata("design:paramtypes", [DomAdapter,
|
1465
|
+
Parser,
|
1553
1466
|
Keyboard,
|
1554
1467
|
Commander,
|
1555
1468
|
Selection,
|
@@ -1567,10 +1480,11 @@ class CollaborateSelectionAwarenessDelegate {
|
|
1567
1480
|
* 协作光标绘制类
|
1568
1481
|
*/
|
1569
1482
|
let CollaborateCursor = class CollaborateCursor {
|
1570
|
-
constructor(textbus, nativeSelection, scheduler, selection, awarenessDelegate) {
|
1483
|
+
constructor(textbus, nativeSelection, scheduler, selection, userActivity, awarenessDelegate) {
|
1571
1484
|
this.nativeSelection = nativeSelection;
|
1572
1485
|
this.scheduler = scheduler;
|
1573
1486
|
this.selection = selection;
|
1487
|
+
this.userActivity = userActivity;
|
1574
1488
|
this.awarenessDelegate = awarenessDelegate;
|
1575
1489
|
this.host = createElement('div', {
|
1576
1490
|
styles: {
|
@@ -1620,6 +1534,7 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1620
1534
|
this.onRectsChange = new Subject();
|
1621
1535
|
this.subscription = new Subscription();
|
1622
1536
|
this.currentSelection = [];
|
1537
|
+
this.ratio = window.devicePixelRatio || 1;
|
1623
1538
|
this.container = textbus.get(VIEW_CONTAINER);
|
1624
1539
|
this.canvasContainer.append(this.canvas);
|
1625
1540
|
this.host.append(this.canvasContainer, this.tooltips);
|
@@ -1639,6 +1554,13 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1639
1554
|
this.refresh();
|
1640
1555
|
}));
|
1641
1556
|
}
|
1557
|
+
init() {
|
1558
|
+
if (this.userActivity) {
|
1559
|
+
this.subscription.add(this.userActivity.onStateChange.subscribe(v => {
|
1560
|
+
this.draw(v);
|
1561
|
+
}));
|
1562
|
+
}
|
1563
|
+
}
|
1642
1564
|
/**
|
1643
1565
|
* 刷新协作光标,由于 Textbus 只会绘制可视区域的光标,当可视区域发生变化时,需要重新绘制
|
1644
1566
|
*/
|
@@ -1656,15 +1578,16 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1656
1578
|
this.currentSelection = paths;
|
1657
1579
|
const containerRect = this.container.getBoundingClientRect();
|
1658
1580
|
this.canvas.style.top = containerRect.top * -1 + 'px';
|
1659
|
-
this.canvas.width = this.canvas.offsetWidth;
|
1660
|
-
this.canvas.height = this.canvas.offsetHeight;
|
1581
|
+
this.canvas.width = this.canvas.offsetWidth * this.ratio;
|
1582
|
+
this.canvas.height = this.canvas.offsetHeight * this.ratio;
|
1583
|
+
this.context.scale(this.ratio, this.ratio);
|
1661
1584
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
1662
1585
|
const users = [];
|
1663
1586
|
paths.filter(i => {
|
1664
|
-
return i.
|
1587
|
+
return i.selection.anchor.length && i.selection.focus.length;
|
1665
1588
|
}).forEach(item => {
|
1666
|
-
const anchorPaths = [...item.
|
1667
|
-
const focusPaths = [...item.
|
1589
|
+
const anchorPaths = [...item.selection.anchor];
|
1590
|
+
const focusPaths = [...item.selection.focus];
|
1668
1591
|
const anchorOffset = anchorPaths.pop();
|
1669
1592
|
const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
|
1670
1593
|
const focusOffset = focusPaths.pop();
|
@@ -1682,8 +1605,13 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1682
1605
|
return;
|
1683
1606
|
}
|
1684
1607
|
const nativeRange = document.createRange();
|
1685
|
-
|
1686
|
-
|
1608
|
+
try {
|
1609
|
+
nativeRange.setStart(anchor.node, anchor.offset);
|
1610
|
+
nativeRange.setEnd(focus.node, focus.offset);
|
1611
|
+
}
|
1612
|
+
catch (e) {
|
1613
|
+
return;
|
1614
|
+
}
|
1687
1615
|
if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
|
1688
1616
|
nativeRange.setStart(focus.node, focus.offset);
|
1689
1617
|
nativeRange.setEnd(anchor.node, anchor.offset);
|
@@ -1812,10 +1740,12 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1812
1740
|
CollaborateCursor = __decorate([
|
1813
1741
|
Injectable(),
|
1814
1742
|
__param(4, Optional()),
|
1743
|
+
__param(5, Optional()),
|
1815
1744
|
__metadata("design:paramtypes", [Textbus,
|
1816
1745
|
SelectionBridge,
|
1817
1746
|
Scheduler,
|
1818
1747
|
Selection,
|
1748
|
+
UserActivity,
|
1819
1749
|
CollaborateSelectionAwarenessDelegate])
|
1820
1750
|
], CollaborateCursor);
|
1821
1751
|
|
@@ -1852,9 +1782,7 @@ class NativeCaret {
|
|
1852
1782
|
height: 0
|
1853
1783
|
};
|
1854
1784
|
}
|
1855
|
-
constructor(
|
1856
|
-
this.scheduler = scheduler;
|
1857
|
-
this.oldPosition = null;
|
1785
|
+
constructor() {
|
1858
1786
|
this._nativeRange = null;
|
1859
1787
|
this.subs = [];
|
1860
1788
|
this.positionChangeEvent = new Subject();
|
@@ -1863,59 +1791,6 @@ class NativeCaret {
|
|
1863
1791
|
refresh() {
|
1864
1792
|
//
|
1865
1793
|
}
|
1866
|
-
correctScrollTop(scroller) {
|
1867
|
-
this.destroy();
|
1868
|
-
const scheduler = this.scheduler;
|
1869
|
-
let docIsChanged = true;
|
1870
|
-
function limitPosition(position) {
|
1871
|
-
const { top, bottom } = scroller.getLimit();
|
1872
|
-
const caretTop = position.top;
|
1873
|
-
if (caretTop + position.height > bottom) {
|
1874
|
-
const offset = caretTop - bottom + position.height;
|
1875
|
-
scroller.setOffset(offset);
|
1876
|
-
}
|
1877
|
-
else if (position.top < top) {
|
1878
|
-
scroller.setOffset(-(top - position.top));
|
1879
|
-
}
|
1880
|
-
}
|
1881
|
-
let isPressed = false;
|
1882
|
-
this.subs.push(scroller.onScroll.subscribe(() => {
|
1883
|
-
if (this.oldPosition) {
|
1884
|
-
const rect = this.rect;
|
1885
|
-
this.oldPosition.top = rect.top;
|
1886
|
-
this.oldPosition.left = rect.left;
|
1887
|
-
this.oldPosition.height = rect.height;
|
1888
|
-
}
|
1889
|
-
}), fromEvent(document, 'mousedown', true).subscribe(() => {
|
1890
|
-
isPressed = true;
|
1891
|
-
}), fromEvent(document, 'mouseup', true).subscribe(() => {
|
1892
|
-
isPressed = false;
|
1893
|
-
}), scheduler.onDocChange.subscribe(() => {
|
1894
|
-
docIsChanged = true;
|
1895
|
-
}), this.onPositionChange.subscribe(position => {
|
1896
|
-
if (position) {
|
1897
|
-
if (docIsChanged) {
|
1898
|
-
if (scheduler.lastChangesHasLocalUpdate) {
|
1899
|
-
limitPosition(position);
|
1900
|
-
}
|
1901
|
-
else if (this.oldPosition) {
|
1902
|
-
const offset = Math.floor(position.top - this.oldPosition.top);
|
1903
|
-
scroller.setOffset(offset);
|
1904
|
-
}
|
1905
|
-
}
|
1906
|
-
else if (!isPressed) {
|
1907
|
-
if (this.oldPosition) {
|
1908
|
-
const offset = Math.floor(position.top - this.oldPosition.top);
|
1909
|
-
scroller.setOffset(offset);
|
1910
|
-
}
|
1911
|
-
else {
|
1912
|
-
limitPosition(position);
|
1913
|
-
}
|
1914
|
-
}
|
1915
|
-
}
|
1916
|
-
docIsChanged = false;
|
1917
|
-
}));
|
1918
|
-
}
|
1919
1794
|
destroy() {
|
1920
1795
|
this.subs.forEach(i => i.unsubscribe());
|
1921
1796
|
this.subs = [];
|
@@ -1933,18 +1808,17 @@ let NativeInput = class NativeInput extends Input {
|
|
1933
1808
|
get disabled() {
|
1934
1809
|
return this._disabled;
|
1935
1810
|
}
|
1936
|
-
constructor(textbus, parser,
|
1811
|
+
constructor(textbus, parser, selection, keyboard, domAdapter, commander, controller) {
|
1937
1812
|
super();
|
1938
1813
|
this.parser = parser;
|
1939
|
-
this.scheduler = scheduler;
|
1940
1814
|
this.selection = selection;
|
1941
1815
|
this.keyboard = keyboard;
|
1942
1816
|
this.domAdapter = domAdapter;
|
1943
1817
|
this.commander = commander;
|
1944
1818
|
this.controller = controller;
|
1945
|
-
this.caret = new NativeCaret(
|
1819
|
+
this.caret = new NativeCaret();
|
1946
1820
|
this.composition = false;
|
1947
|
-
|
1821
|
+
// compositionState: CompositionState | null = null
|
1948
1822
|
this.onReady = Promise.resolve();
|
1949
1823
|
this._disabled = false;
|
1950
1824
|
this.nativeSelection = document.getSelection();
|
@@ -1987,7 +1861,7 @@ let NativeInput = class NativeInput extends Input {
|
|
1987
1861
|
this.subscription.unsubscribe();
|
1988
1862
|
}
|
1989
1863
|
handleDefaultActions(textarea) {
|
1990
|
-
this.subscription.add(fromEvent(document, 'copy').subscribe(ev => {
|
1864
|
+
this.subscription.add(fromEvent(isFirefox() ? textarea : document, 'copy').subscribe(ev => {
|
1991
1865
|
const selection = this.selection;
|
1992
1866
|
if (!selection.isSelected) {
|
1993
1867
|
return;
|
@@ -2041,8 +1915,8 @@ let NativeInput = class NativeInput extends Input {
|
|
2041
1915
|
});
|
2042
1916
|
}));
|
2043
1917
|
}
|
2044
|
-
handlePaste(
|
2045
|
-
const slot = this.parser.parse(
|
1918
|
+
handlePaste(dom, text) {
|
1919
|
+
const slot = this.parser.parse(dom, new Slot([
|
2046
1920
|
ContentType.BlockComponent,
|
2047
1921
|
ContentType.InlineComponent,
|
2048
1922
|
ContentType.Text
|
@@ -2102,7 +1976,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2102
1976
|
let startIndex;
|
2103
1977
|
const compositionStart = () => {
|
2104
1978
|
this.composition = true;
|
2105
|
-
this.compositionState = null;
|
2106
1979
|
startIndex = this.selection.startOffset;
|
2107
1980
|
const startSlot = this.selection.startSlot;
|
2108
1981
|
const event = new Event(startSlot, {
|
@@ -2112,11 +1985,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2112
1985
|
};
|
2113
1986
|
const compositionUpdate = (data) => {
|
2114
1987
|
const startSlot = this.selection.startSlot;
|
2115
|
-
this.compositionState = {
|
2116
|
-
slot: startSlot,
|
2117
|
-
index: startIndex,
|
2118
|
-
data
|
2119
|
-
};
|
2120
1988
|
const event = new Event(startSlot, {
|
2121
1989
|
index: startIndex,
|
2122
1990
|
data
|
@@ -2140,6 +2008,10 @@ let NativeInput = class NativeInput extends Input {
|
|
2140
2008
|
compositionUpdate(ev.data);
|
2141
2009
|
}), fromEvent(input, 'compositionend').subscribe(ev => {
|
2142
2010
|
compositionEnd(ev.data);
|
2011
|
+
const startContainer = this.nativeSelection.focusNode;
|
2012
|
+
if (startContainer instanceof Text && startContainer.textContent === ev.data) {
|
2013
|
+
startContainer.remove();
|
2014
|
+
}
|
2143
2015
|
}), fromEvent(input, 'beforeinput').subscribe(ev => {
|
2144
2016
|
var _a;
|
2145
2017
|
switch (ev.inputType) {
|
@@ -2203,7 +2075,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2203
2075
|
return !this.ignoreComposition;
|
2204
2076
|
})).subscribe(() => {
|
2205
2077
|
this.composition = true;
|
2206
|
-
this.compositionState = null;
|
2207
2078
|
startIndex = this.selection.startOffset;
|
2208
2079
|
const startSlot = this.selection.startSlot;
|
2209
2080
|
const event = new Event(startSlot, {
|
@@ -2214,11 +2085,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2214
2085
|
return !this.ignoreComposition;
|
2215
2086
|
})).subscribe(ev => {
|
2216
2087
|
const startSlot = this.selection.startSlot;
|
2217
|
-
this.compositionState = {
|
2218
|
-
slot: startSlot,
|
2219
|
-
index: startIndex,
|
2220
|
-
data: ev.data
|
2221
|
-
};
|
2222
2088
|
const event = new Event(startSlot, {
|
2223
2089
|
index: startIndex,
|
2224
2090
|
data: ev.data
|
@@ -2268,8 +2134,11 @@ let NativeInput = class NativeInput extends Input {
|
|
2268
2134
|
return !b;
|
2269
2135
|
}))).subscribe(text => {
|
2270
2136
|
this.composition = false;
|
2271
|
-
this.compositionState = null;
|
2272
2137
|
if (text) {
|
2138
|
+
const startContainer = this.nativeSelection.focusNode;
|
2139
|
+
if (startContainer instanceof Text && startContainer.textContent === text) {
|
2140
|
+
startContainer.remove();
|
2141
|
+
}
|
2273
2142
|
this.commander.write(text);
|
2274
2143
|
}
|
2275
2144
|
if (isCompositionEnd) {
|
@@ -2287,7 +2156,6 @@ NativeInput = __decorate([
|
|
2287
2156
|
Injectable(),
|
2288
2157
|
__metadata("design:paramtypes", [Textbus,
|
2289
2158
|
Parser,
|
2290
|
-
Scheduler,
|
2291
2159
|
Selection,
|
2292
2160
|
Keyboard,
|
2293
2161
|
DomAdapter,
|
@@ -2295,9 +2163,9 @@ NativeInput = __decorate([
|
|
2295
2163
|
Controller])
|
2296
2164
|
], NativeInput);
|
2297
2165
|
|
2166
|
+
const browserErrorFn = makeError('BrowserModule');
|
2298
2167
|
class BrowserModule {
|
2299
|
-
constructor(
|
2300
|
-
this.host = host;
|
2168
|
+
constructor(config) {
|
2301
2169
|
this.config = config;
|
2302
2170
|
const { mask, wrapper } = BrowserModule.createLayout();
|
2303
2171
|
wrapper.prepend(config.adapter.host);
|
@@ -2323,11 +2191,8 @@ class BrowserModule {
|
|
2323
2191
|
provide: Input,
|
2324
2192
|
useClass: config.useContentEditable ? NativeInput : MagicInput
|
2325
2193
|
}, {
|
2326
|
-
provide:
|
2327
|
-
|
2328
|
-
return v;
|
2329
|
-
},
|
2330
|
-
deps: [DomAdapter]
|
2194
|
+
provide: Adapter,
|
2195
|
+
useValue: config.adapter
|
2331
2196
|
}, {
|
2332
2197
|
provide: DomAdapter,
|
2333
2198
|
useValue: config.adapter
|
@@ -2355,10 +2220,54 @@ class BrowserModule {
|
|
2355
2220
|
SelectionBridge,
|
2356
2221
|
CollaborateCursor];
|
2357
2222
|
this.workbench = wrapper;
|
2358
|
-
this.host.append(wrapper);
|
2359
2223
|
}
|
2360
|
-
|
2361
|
-
|
2224
|
+
/**
|
2225
|
+
* 解析 HTML 并返回一个组件实例
|
2226
|
+
* @param html 要解析的 HTML
|
2227
|
+
* @param rootComponentLoader 文档根组件加载器
|
2228
|
+
* @param textbus
|
2229
|
+
*/
|
2230
|
+
readDocumentByHTML(html, rootComponentLoader, textbus) {
|
2231
|
+
const parser = textbus.get(Parser);
|
2232
|
+
const doc = parser.parseDoc(html, rootComponentLoader);
|
2233
|
+
if (doc instanceof Component) {
|
2234
|
+
return doc;
|
2235
|
+
}
|
2236
|
+
throw browserErrorFn('rootComponentLoader must return a component instance.');
|
2237
|
+
}
|
2238
|
+
/**
|
2239
|
+
* 将组件数据解析到组件实例中
|
2240
|
+
* @param data 要解析的 JSON 数据
|
2241
|
+
* @param rootComponent 根组件
|
2242
|
+
* @param textbus
|
2243
|
+
*/
|
2244
|
+
readDocumentByComponentLiteral(data, rootComponent, textbus) {
|
2245
|
+
const registry = textbus.get(Registry);
|
2246
|
+
return registry.createComponentByFactory(data, rootComponent);
|
2247
|
+
}
|
2248
|
+
setup(textbus) {
|
2249
|
+
this.textbus = textbus;
|
2250
|
+
const host = this.config.renderTo();
|
2251
|
+
if (!(host instanceof HTMLElement)) {
|
2252
|
+
throw browserErrorFn('view container is not a HTMLElement');
|
2253
|
+
}
|
2254
|
+
const cursor = textbus.get(CollaborateCursor);
|
2255
|
+
cursor.init();
|
2256
|
+
host.append(this.workbench);
|
2257
|
+
return () => {
|
2258
|
+
cursor.destroy();
|
2259
|
+
this.workbench.remove();
|
2260
|
+
};
|
2261
|
+
}
|
2262
|
+
onAfterStartup(textbus) {
|
2263
|
+
if (this.config.autoFocus) {
|
2264
|
+
textbus.focus();
|
2265
|
+
}
|
2266
|
+
}
|
2267
|
+
onDestroy(textbus) {
|
2268
|
+
textbus.get(Input).destroy();
|
2269
|
+
textbus.get(SelectionBridge).destroy();
|
2270
|
+
textbus.get(CollaborateCursor).destroy();
|
2362
2271
|
}
|
2363
2272
|
static createLayout() {
|
2364
2273
|
const mask = createElement('div', {
|
@@ -2371,10 +2280,23 @@ class BrowserModule {
|
|
2371
2280
|
right: 0,
|
2372
2281
|
top: 0,
|
2373
2282
|
bottom: 0,
|
2283
|
+
pointerEvents: 'none',
|
2284
|
+
// overflow: 'hidden'
|
2285
|
+
}
|
2286
|
+
});
|
2287
|
+
const maskWrapper = createElement('div', {
|
2288
|
+
styles: {
|
2289
|
+
position: 'absolute',
|
2290
|
+
left: 0,
|
2291
|
+
right: 0,
|
2292
|
+
top: 0,
|
2293
|
+
bottom: 0,
|
2294
|
+
margin: '0 -2px',
|
2374
2295
|
zIndex: 1,
|
2375
2296
|
pointerEvents: 'none',
|
2376
2297
|
overflow: 'hidden'
|
2377
|
-
}
|
2298
|
+
},
|
2299
|
+
children: [mask]
|
2378
2300
|
});
|
2379
2301
|
const wrapper = createElement('div', {
|
2380
2302
|
attrs: {
|
@@ -2386,7 +2308,7 @@ class BrowserModule {
|
|
2386
2308
|
position: 'relative',
|
2387
2309
|
flexDirection: 'column'
|
2388
2310
|
},
|
2389
|
-
children: [
|
2311
|
+
children: [maskWrapper]
|
2390
2312
|
});
|
2391
2313
|
return {
|
2392
2314
|
wrapper,
|
@@ -2395,4 +2317,4 @@ class BrowserModule {
|
|
2395
2317
|
}
|
2396
2318
|
}
|
2397
2319
|
|
2398
|
-
export { BrowserModule, CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomAdapter, EDITOR_OPTIONS, Input, MagicInput, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, createElement,
|
2320
|
+
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 };
|