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