@textbus/platform-browser 4.0.0-alpha.32 → 4.0.0-alpha.33
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/collaborate-cursor.d.ts +1 -0
- package/bundles/dom-adapter.d.ts +9 -0
- package/bundles/index.esm.js +111 -57
- package/bundles/index.js +110 -56
- package/bundles/magic-input.d.ts +6 -6
- package/bundles/native-input.d.ts +1 -2
- package/bundles/types.d.ts +0 -7
- package/package.json +5 -5
@@ -36,6 +36,7 @@ export declare class CollaborateCursor {
|
|
36
36
|
private subscription;
|
37
37
|
private currentSelection;
|
38
38
|
private container;
|
39
|
+
private ratio;
|
39
40
|
constructor(textbus: Textbus, nativeSelection: SelectionBridge, scheduler: Scheduler, selection: Selection, userActivity: UserActivity, awarenessDelegate?: CollaborateSelectionAwarenessDelegate | undefined);
|
40
41
|
init(): void;
|
41
42
|
/**
|
package/bundles/dom-adapter.d.ts
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
import { Component, Slot, ViewAdapter, NodeLocation, VElement, VTextNode, Textbus } from '@textbus/core';
|
2
|
+
export interface CompositionState {
|
3
|
+
slot: Slot;
|
4
|
+
text: string;
|
5
|
+
offset: number;
|
6
|
+
index: number;
|
7
|
+
}
|
2
8
|
/**
|
3
9
|
* Textbus PC 端浏览器渲染能力桥接器抽象类,提供了 DOM 元素查询能力,具体渲染能力由各前端框架实现相应桥接
|
4
10
|
*/
|
5
11
|
export declare abstract class DomAdapter<ViewComponent, ViewElement> extends ViewAdapter {
|
6
12
|
private mount;
|
7
13
|
host: HTMLElement;
|
14
|
+
compositionNode: HTMLElement | null;
|
15
|
+
composition: CompositionState | null;
|
8
16
|
protected firstRending: boolean;
|
9
17
|
protected componentRootElementCaches: {
|
10
18
|
set: {
|
@@ -64,4 +72,5 @@ export declare abstract class DomAdapter<ViewComponent, ViewElement> extends Vie
|
|
64
72
|
* @param node
|
65
73
|
*/
|
66
74
|
getLocationByNativeNode(node: Node): NodeLocation | null;
|
75
|
+
protected insertCompositionByIndex(slot: Slot, vNode: VElement, composition: CompositionState, createCompositionNode: (composition: CompositionState) => VElement): void;
|
67
76
|
}
|
package/bundles/index.esm.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import 'reflect-metadata';
|
2
|
-
import { Slot, Textbus, ViewAdapter, createBidirectionalMapping, Component,
|
2
|
+
import { Slot, Textbus, ViewAdapter, createBidirectionalMapping, Component, VTextNode, VElement, Controller, Selection, RootComponentRef, ContentType, Event, invokeListener, Keyboard, Commander, Scheduler, makeError, NativeSelectionBridge, FocusManager, 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
5
|
import { UserActivity } from '@textbus/collaborate';
|
@@ -323,6 +323,8 @@ class DomAdapter extends ViewAdapter {
|
|
323
323
|
id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)
|
324
324
|
}
|
325
325
|
});
|
326
|
+
this.compositionNode = null;
|
327
|
+
this.composition = null;
|
326
328
|
this.firstRending = true;
|
327
329
|
this.componentRootElementCaches = createBidirectionalMapping(a => {
|
328
330
|
return a instanceof Component;
|
@@ -396,6 +398,70 @@ class DomAdapter extends ViewAdapter {
|
|
396
398
|
const rootVNode = this.slotRootVElementCaches.get(slot);
|
397
399
|
return getLocation(node, slotRootNode, rootVNode);
|
398
400
|
}
|
401
|
+
insertCompositionByIndex(slot, vNode, composition, createCompositionNode) {
|
402
|
+
const location = vNode.location;
|
403
|
+
const nodes = vNode.children;
|
404
|
+
if (location && location.slot === composition.slot) {
|
405
|
+
for (let i = 0; i < nodes.length; i++) {
|
406
|
+
const child = nodes[i];
|
407
|
+
if (child instanceof VTextNode) {
|
408
|
+
const childLocation = child.location;
|
409
|
+
if (childLocation) {
|
410
|
+
if (composition.index > childLocation.startIndex && composition.index <= childLocation.endIndex) {
|
411
|
+
const compositionNode = createCompositionNode(composition);
|
412
|
+
if (composition.index === childLocation.endIndex) {
|
413
|
+
nodes.splice(i + 1, 0, compositionNode);
|
414
|
+
break;
|
415
|
+
}
|
416
|
+
const splitIndex = composition.index - childLocation.startIndex;
|
417
|
+
const beforeNode = new VTextNode(child.textContent.slice(0, splitIndex));
|
418
|
+
beforeNode.location = {
|
419
|
+
slot: childLocation.slot,
|
420
|
+
startIndex: childLocation.startIndex,
|
421
|
+
endIndex: childLocation.startIndex + splitIndex
|
422
|
+
};
|
423
|
+
const afterNode = new VTextNode(child.textContent.slice(splitIndex));
|
424
|
+
afterNode.location = {
|
425
|
+
slot: childLocation.slot,
|
426
|
+
startIndex: composition.index,
|
427
|
+
endIndex: childLocation.endIndex
|
428
|
+
};
|
429
|
+
nodes.splice(i, 1, beforeNode, compositionNode, afterNode);
|
430
|
+
break;
|
431
|
+
}
|
432
|
+
else if (composition.index === 0 && childLocation.startIndex === 0) {
|
433
|
+
nodes.unshift(createCompositionNode(composition));
|
434
|
+
break;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
}
|
438
|
+
else if (child instanceof Component) {
|
439
|
+
const componentIndex = slot.indexOf(child);
|
440
|
+
if (composition.index === componentIndex + 1) {
|
441
|
+
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
442
|
+
break;
|
443
|
+
}
|
444
|
+
else if (componentIndex === 0 && composition.index === 0) {
|
445
|
+
nodes.unshift(createCompositionNode(composition));
|
446
|
+
break;
|
447
|
+
}
|
448
|
+
}
|
449
|
+
else if (child.tagName === 'br') {
|
450
|
+
const location = child.location;
|
451
|
+
if (location) {
|
452
|
+
if (location.endIndex === composition.index) {
|
453
|
+
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
454
|
+
break;
|
455
|
+
}
|
456
|
+
else if (location.startIndex === 0 && composition.index === 0) {
|
457
|
+
nodes.unshift(createCompositionNode(composition));
|
458
|
+
break;
|
459
|
+
}
|
460
|
+
}
|
461
|
+
}
|
462
|
+
}
|
463
|
+
}
|
464
|
+
}
|
399
465
|
}
|
400
466
|
function getNodes(adapter, vElement, nativeNode, result) {
|
401
467
|
if (vElement.location) {
|
@@ -1032,15 +1098,10 @@ class ExperimentalCaret {
|
|
1032
1098
|
get display() {
|
1033
1099
|
return this._display;
|
1034
1100
|
}
|
1035
|
-
constructor(scheduler, editorMask) {
|
1101
|
+
constructor(adapter, scheduler, editorMask) {
|
1102
|
+
this.adapter = adapter;
|
1036
1103
|
this.scheduler = scheduler;
|
1037
1104
|
this.editorMask = editorMask;
|
1038
|
-
this.compositionState = null;
|
1039
|
-
this.compositionElement = createElement('span', {
|
1040
|
-
styles: {
|
1041
|
-
textDecoration: 'underline'
|
1042
|
-
}
|
1043
|
-
});
|
1044
1105
|
this.timer = null;
|
1045
1106
|
this.oldPosition = null;
|
1046
1107
|
this._display = true;
|
@@ -1184,12 +1245,11 @@ class ExperimentalCaret {
|
|
1184
1245
|
this.positionChangeEvent.next(null);
|
1185
1246
|
return;
|
1186
1247
|
}
|
1187
|
-
|
1188
|
-
|
1189
|
-
compositionElement.innerText = this.compositionState.data;
|
1248
|
+
const compositionNode = this.adapter.compositionNode;
|
1249
|
+
if (compositionNode) {
|
1190
1250
|
nativeRange = nativeRange.cloneRange();
|
1191
|
-
nativeRange.insertNode(
|
1192
|
-
nativeRange.selectNodeContents(
|
1251
|
+
nativeRange.insertNode(compositionNode);
|
1252
|
+
nativeRange.selectNodeContents(compositionNode);
|
1193
1253
|
nativeRange.collapse();
|
1194
1254
|
}
|
1195
1255
|
const rect = getLayoutRectByRange(nativeRange);
|
@@ -1250,8 +1310,9 @@ let MagicInput = class MagicInput extends Input {
|
|
1250
1310
|
get disabled() {
|
1251
1311
|
return this._disabled;
|
1252
1312
|
}
|
1253
|
-
constructor(parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1313
|
+
constructor(adapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1254
1314
|
super();
|
1315
|
+
this.adapter = adapter;
|
1255
1316
|
this.parser = parser;
|
1256
1317
|
this.keyboard = keyboard;
|
1257
1318
|
this.commander = commander;
|
@@ -1260,8 +1321,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1260
1321
|
this.scheduler = scheduler;
|
1261
1322
|
this.textbus = textbus;
|
1262
1323
|
this.composition = false;
|
1263
|
-
this.
|
1264
|
-
this.caret = new ExperimentalCaret(this.scheduler, this.textbus.get(VIEW_MASK));
|
1324
|
+
this.caret = new ExperimentalCaret(this.adapter, this.scheduler, this.textbus.get(VIEW_MASK));
|
1265
1325
|
this.isSafari = isSafari();
|
1266
1326
|
this.isFirefox = isFirefox();
|
1267
1327
|
this.isMac = isMac();
|
@@ -1342,12 +1402,19 @@ let MagicInput = class MagicInput extends Input {
|
|
1342
1402
|
contentBody.appendChild(textarea);
|
1343
1403
|
this.textarea = textarea;
|
1344
1404
|
this.subscription.add(fromEvent(textarea, 'blur').subscribe(() => {
|
1345
|
-
if (this.isFocus) {
|
1346
|
-
|
1347
|
-
|
1348
|
-
}
|
1405
|
+
// if (this.isFocus) {
|
1406
|
+
// this.isFocus = false
|
1407
|
+
// this.reInit(true)
|
1408
|
+
// }
|
1409
|
+
this.isFocus = false;
|
1349
1410
|
this.nativeFocus = false;
|
1350
1411
|
this.caret.hide();
|
1412
|
+
if (this.adapter.composition) {
|
1413
|
+
const slot = this.adapter.composition.slot;
|
1414
|
+
this.adapter.composition = null;
|
1415
|
+
this.adapter.compositionNode = null;
|
1416
|
+
slot.changeMarker.forceMarkDirtied();
|
1417
|
+
}
|
1351
1418
|
}), fromEvent(textarea, 'focus').subscribe(() => {
|
1352
1419
|
this.nativeFocus = true;
|
1353
1420
|
}), this.caret.onStyleChange.subscribe(style => {
|
@@ -1470,7 +1537,6 @@ let MagicInput = class MagicInput extends Input {
|
|
1470
1537
|
this.commander.delete();
|
1471
1538
|
}
|
1472
1539
|
this.composition = true;
|
1473
|
-
this.caret.compositionState = this.compositionState = null;
|
1474
1540
|
startIndex = this.selection.startOffset;
|
1475
1541
|
const startSlot = this.selection.startSlot;
|
1476
1542
|
const event = new Event(startSlot, {
|
@@ -1487,10 +1553,11 @@ let MagicInput = class MagicInput extends Input {
|
|
1487
1553
|
return;
|
1488
1554
|
}
|
1489
1555
|
const startSlot = this.selection.startSlot;
|
1490
|
-
this.
|
1556
|
+
this.adapter.composition = {
|
1491
1557
|
slot: startSlot,
|
1492
|
-
|
1493
|
-
|
1558
|
+
text: ev.data,
|
1559
|
+
offset: ev.data.length,
|
1560
|
+
index: startIndex
|
1494
1561
|
};
|
1495
1562
|
this.caret.refresh(true);
|
1496
1563
|
const event = new Event(startSlot, {
|
@@ -1498,6 +1565,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1498
1565
|
data: ev.data
|
1499
1566
|
});
|
1500
1567
|
invokeListener(startSlot.parent, 'onCompositionUpdate', event);
|
1568
|
+
startSlot.changeMarker.forceMarkDirtied();
|
1501
1569
|
}));
|
1502
1570
|
let isCompositionEnd = false;
|
1503
1571
|
this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
|
@@ -1521,24 +1589,15 @@ let MagicInput = class MagicInput extends Input {
|
|
1521
1589
|
textarea.value = '';
|
1522
1590
|
return ev.data;
|
1523
1591
|
}))).subscribe(text => {
|
1592
|
+
var _a;
|
1524
1593
|
this.composition = false;
|
1525
|
-
this.
|
1526
|
-
const compositionElement = this.caret.compositionElement;
|
1527
|
-
let nextSibling = compositionElement.nextSibling;
|
1528
|
-
while (nextSibling) {
|
1529
|
-
if (!nextSibling.textContent) {
|
1530
|
-
const next = nextSibling.nextSibling;
|
1531
|
-
nextSibling.remove();
|
1532
|
-
nextSibling = next;
|
1533
|
-
continue;
|
1534
|
-
}
|
1535
|
-
nextSibling.remove();
|
1536
|
-
break;
|
1537
|
-
}
|
1538
|
-
compositionElement.remove();
|
1594
|
+
this.adapter.composition = null;
|
1539
1595
|
if (text) {
|
1540
1596
|
this.commander.write(text);
|
1541
1597
|
}
|
1598
|
+
else {
|
1599
|
+
(_a = this.selection.startSlot) === null || _a === void 0 ? void 0 : _a.changeMarker.forceMarkDirtied();
|
1600
|
+
}
|
1542
1601
|
if (isCompositionEnd) {
|
1543
1602
|
const startSlot = this.selection.startSlot;
|
1544
1603
|
if (startSlot) {
|
@@ -1567,7 +1626,8 @@ let MagicInput = class MagicInput extends Input {
|
|
1567
1626
|
};
|
1568
1627
|
MagicInput = __decorate([
|
1569
1628
|
Injectable(),
|
1570
|
-
__metadata("design:paramtypes", [
|
1629
|
+
__metadata("design:paramtypes", [DomAdapter,
|
1630
|
+
Parser,
|
1571
1631
|
Keyboard,
|
1572
1632
|
Commander,
|
1573
1633
|
Selection,
|
@@ -1639,6 +1699,7 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1639
1699
|
this.onRectsChange = new Subject();
|
1640
1700
|
this.subscription = new Subscription();
|
1641
1701
|
this.currentSelection = [];
|
1702
|
+
this.ratio = window.devicePixelRatio || 1;
|
1642
1703
|
this.container = textbus.get(VIEW_CONTAINER);
|
1643
1704
|
this.canvasContainer.append(this.canvas);
|
1644
1705
|
this.host.append(this.canvasContainer, this.tooltips);
|
@@ -1682,8 +1743,9 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1682
1743
|
this.currentSelection = paths;
|
1683
1744
|
const containerRect = this.container.getBoundingClientRect();
|
1684
1745
|
this.canvas.style.top = containerRect.top * -1 + 'px';
|
1685
|
-
this.canvas.width = this.canvas.offsetWidth;
|
1686
|
-
this.canvas.height = this.canvas.offsetHeight;
|
1746
|
+
this.canvas.width = this.canvas.offsetWidth * this.ratio;
|
1747
|
+
this.canvas.height = this.canvas.offsetHeight * this.ratio;
|
1748
|
+
this.context.scale(this.ratio, this.ratio);
|
1687
1749
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
1688
1750
|
const users = [];
|
1689
1751
|
paths.filter(i => {
|
@@ -1708,8 +1770,13 @@ let CollaborateCursor = class CollaborateCursor {
|
|
1708
1770
|
return;
|
1709
1771
|
}
|
1710
1772
|
const nativeRange = document.createRange();
|
1711
|
-
|
1712
|
-
|
1773
|
+
try {
|
1774
|
+
nativeRange.setStart(anchor.node, anchor.offset);
|
1775
|
+
nativeRange.setEnd(focus.node, focus.offset);
|
1776
|
+
}
|
1777
|
+
catch (e) {
|
1778
|
+
return;
|
1779
|
+
}
|
1713
1780
|
if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
|
1714
1781
|
nativeRange.setStart(focus.node, focus.offset);
|
1715
1782
|
nativeRange.setEnd(anchor.node, anchor.offset);
|
@@ -1972,7 +2039,7 @@ let NativeInput = class NativeInput extends Input {
|
|
1972
2039
|
this.controller = controller;
|
1973
2040
|
this.caret = new NativeCaret(this.scheduler);
|
1974
2041
|
this.composition = false;
|
1975
|
-
|
2042
|
+
// compositionState: CompositionState | null = null
|
1976
2043
|
this.onReady = Promise.resolve();
|
1977
2044
|
this._disabled = false;
|
1978
2045
|
this.nativeSelection = document.getSelection();
|
@@ -2130,7 +2197,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2130
2197
|
let startIndex;
|
2131
2198
|
const compositionStart = () => {
|
2132
2199
|
this.composition = true;
|
2133
|
-
this.compositionState = null;
|
2134
2200
|
startIndex = this.selection.startOffset;
|
2135
2201
|
const startSlot = this.selection.startSlot;
|
2136
2202
|
const event = new Event(startSlot, {
|
@@ -2140,11 +2206,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2140
2206
|
};
|
2141
2207
|
const compositionUpdate = (data) => {
|
2142
2208
|
const startSlot = this.selection.startSlot;
|
2143
|
-
this.compositionState = {
|
2144
|
-
slot: startSlot,
|
2145
|
-
index: startIndex,
|
2146
|
-
data
|
2147
|
-
};
|
2148
2209
|
const event = new Event(startSlot, {
|
2149
2210
|
index: startIndex,
|
2150
2211
|
data
|
@@ -2231,7 +2292,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2231
2292
|
return !this.ignoreComposition;
|
2232
2293
|
})).subscribe(() => {
|
2233
2294
|
this.composition = true;
|
2234
|
-
this.compositionState = null;
|
2235
2295
|
startIndex = this.selection.startOffset;
|
2236
2296
|
const startSlot = this.selection.startSlot;
|
2237
2297
|
const event = new Event(startSlot, {
|
@@ -2242,11 +2302,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2242
2302
|
return !this.ignoreComposition;
|
2243
2303
|
})).subscribe(ev => {
|
2244
2304
|
const startSlot = this.selection.startSlot;
|
2245
|
-
this.compositionState = {
|
2246
|
-
slot: startSlot,
|
2247
|
-
index: startIndex,
|
2248
|
-
data: ev.data
|
2249
|
-
};
|
2250
2305
|
const event = new Event(startSlot, {
|
2251
2306
|
index: startIndex,
|
2252
2307
|
data: ev.data
|
@@ -2296,7 +2351,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2296
2351
|
return !b;
|
2297
2352
|
}))).subscribe(text => {
|
2298
2353
|
this.composition = false;
|
2299
|
-
this.compositionState = null;
|
2300
2354
|
if (text) {
|
2301
2355
|
this.commander.write(text);
|
2302
2356
|
}
|
package/bundles/index.js
CHANGED
@@ -325,6 +325,8 @@ class DomAdapter extends core$1.ViewAdapter {
|
|
325
325
|
id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)
|
326
326
|
}
|
327
327
|
});
|
328
|
+
this.compositionNode = null;
|
329
|
+
this.composition = null;
|
328
330
|
this.firstRending = true;
|
329
331
|
this.componentRootElementCaches = core$1.createBidirectionalMapping(a => {
|
330
332
|
return a instanceof core$1.Component;
|
@@ -398,6 +400,70 @@ class DomAdapter extends core$1.ViewAdapter {
|
|
398
400
|
const rootVNode = this.slotRootVElementCaches.get(slot);
|
399
401
|
return getLocation(node, slotRootNode, rootVNode);
|
400
402
|
}
|
403
|
+
insertCompositionByIndex(slot, vNode, composition, createCompositionNode) {
|
404
|
+
const location = vNode.location;
|
405
|
+
const nodes = vNode.children;
|
406
|
+
if (location && location.slot === composition.slot) {
|
407
|
+
for (let i = 0; i < nodes.length; i++) {
|
408
|
+
const child = nodes[i];
|
409
|
+
if (child instanceof core$1.VTextNode) {
|
410
|
+
const childLocation = child.location;
|
411
|
+
if (childLocation) {
|
412
|
+
if (composition.index > childLocation.startIndex && composition.index <= childLocation.endIndex) {
|
413
|
+
const compositionNode = createCompositionNode(composition);
|
414
|
+
if (composition.index === childLocation.endIndex) {
|
415
|
+
nodes.splice(i + 1, 0, compositionNode);
|
416
|
+
break;
|
417
|
+
}
|
418
|
+
const splitIndex = composition.index - childLocation.startIndex;
|
419
|
+
const beforeNode = new core$1.VTextNode(child.textContent.slice(0, splitIndex));
|
420
|
+
beforeNode.location = {
|
421
|
+
slot: childLocation.slot,
|
422
|
+
startIndex: childLocation.startIndex,
|
423
|
+
endIndex: childLocation.startIndex + splitIndex
|
424
|
+
};
|
425
|
+
const afterNode = new core$1.VTextNode(child.textContent.slice(splitIndex));
|
426
|
+
afterNode.location = {
|
427
|
+
slot: childLocation.slot,
|
428
|
+
startIndex: composition.index,
|
429
|
+
endIndex: childLocation.endIndex
|
430
|
+
};
|
431
|
+
nodes.splice(i, 1, beforeNode, compositionNode, afterNode);
|
432
|
+
break;
|
433
|
+
}
|
434
|
+
else if (composition.index === 0 && childLocation.startIndex === 0) {
|
435
|
+
nodes.unshift(createCompositionNode(composition));
|
436
|
+
break;
|
437
|
+
}
|
438
|
+
}
|
439
|
+
}
|
440
|
+
else if (child instanceof core$1.Component) {
|
441
|
+
const componentIndex = slot.indexOf(child);
|
442
|
+
if (composition.index === componentIndex + 1) {
|
443
|
+
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
444
|
+
break;
|
445
|
+
}
|
446
|
+
else if (componentIndex === 0 && composition.index === 0) {
|
447
|
+
nodes.unshift(createCompositionNode(composition));
|
448
|
+
break;
|
449
|
+
}
|
450
|
+
}
|
451
|
+
else if (child.tagName === 'br') {
|
452
|
+
const location = child.location;
|
453
|
+
if (location) {
|
454
|
+
if (location.endIndex === composition.index) {
|
455
|
+
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
456
|
+
break;
|
457
|
+
}
|
458
|
+
else if (location.startIndex === 0 && composition.index === 0) {
|
459
|
+
nodes.unshift(createCompositionNode(composition));
|
460
|
+
break;
|
461
|
+
}
|
462
|
+
}
|
463
|
+
}
|
464
|
+
}
|
465
|
+
}
|
466
|
+
}
|
401
467
|
}
|
402
468
|
function getNodes(adapter, vElement, nativeNode, result) {
|
403
469
|
if (vElement.location) {
|
@@ -1034,15 +1100,10 @@ class ExperimentalCaret {
|
|
1034
1100
|
get display() {
|
1035
1101
|
return this._display;
|
1036
1102
|
}
|
1037
|
-
constructor(scheduler, editorMask) {
|
1103
|
+
constructor(adapter, scheduler, editorMask) {
|
1104
|
+
this.adapter = adapter;
|
1038
1105
|
this.scheduler = scheduler;
|
1039
1106
|
this.editorMask = editorMask;
|
1040
|
-
this.compositionState = null;
|
1041
|
-
this.compositionElement = createElement('span', {
|
1042
|
-
styles: {
|
1043
|
-
textDecoration: 'underline'
|
1044
|
-
}
|
1045
|
-
});
|
1046
1107
|
this.timer = null;
|
1047
1108
|
this.oldPosition = null;
|
1048
1109
|
this._display = true;
|
@@ -1186,12 +1247,11 @@ class ExperimentalCaret {
|
|
1186
1247
|
this.positionChangeEvent.next(null);
|
1187
1248
|
return;
|
1188
1249
|
}
|
1189
|
-
|
1190
|
-
|
1191
|
-
compositionElement.innerText = this.compositionState.data;
|
1250
|
+
const compositionNode = this.adapter.compositionNode;
|
1251
|
+
if (compositionNode) {
|
1192
1252
|
nativeRange = nativeRange.cloneRange();
|
1193
|
-
nativeRange.insertNode(
|
1194
|
-
nativeRange.selectNodeContents(
|
1253
|
+
nativeRange.insertNode(compositionNode);
|
1254
|
+
nativeRange.selectNodeContents(compositionNode);
|
1195
1255
|
nativeRange.collapse();
|
1196
1256
|
}
|
1197
1257
|
const rect = getLayoutRectByRange(nativeRange);
|
@@ -1252,8 +1312,9 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1252
1312
|
get disabled() {
|
1253
1313
|
return this._disabled;
|
1254
1314
|
}
|
1255
|
-
constructor(parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1315
|
+
constructor(adapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1256
1316
|
super();
|
1317
|
+
this.adapter = adapter;
|
1257
1318
|
this.parser = parser;
|
1258
1319
|
this.keyboard = keyboard;
|
1259
1320
|
this.commander = commander;
|
@@ -1262,8 +1323,7 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1262
1323
|
this.scheduler = scheduler;
|
1263
1324
|
this.textbus = textbus;
|
1264
1325
|
this.composition = false;
|
1265
|
-
this.
|
1266
|
-
this.caret = new ExperimentalCaret(this.scheduler, this.textbus.get(VIEW_MASK));
|
1326
|
+
this.caret = new ExperimentalCaret(this.adapter, this.scheduler, this.textbus.get(VIEW_MASK));
|
1267
1327
|
this.isSafari = isSafari();
|
1268
1328
|
this.isFirefox = isFirefox();
|
1269
1329
|
this.isMac = isMac();
|
@@ -1344,12 +1404,19 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1344
1404
|
contentBody.appendChild(textarea);
|
1345
1405
|
this.textarea = textarea;
|
1346
1406
|
this.subscription.add(stream.fromEvent(textarea, 'blur').subscribe(() => {
|
1347
|
-
if (this.isFocus) {
|
1348
|
-
|
1349
|
-
|
1350
|
-
}
|
1407
|
+
// if (this.isFocus) {
|
1408
|
+
// this.isFocus = false
|
1409
|
+
// this.reInit(true)
|
1410
|
+
// }
|
1411
|
+
this.isFocus = false;
|
1351
1412
|
this.nativeFocus = false;
|
1352
1413
|
this.caret.hide();
|
1414
|
+
if (this.adapter.composition) {
|
1415
|
+
const slot = this.adapter.composition.slot;
|
1416
|
+
this.adapter.composition = null;
|
1417
|
+
this.adapter.compositionNode = null;
|
1418
|
+
slot.changeMarker.forceMarkDirtied();
|
1419
|
+
}
|
1353
1420
|
}), stream.fromEvent(textarea, 'focus').subscribe(() => {
|
1354
1421
|
this.nativeFocus = true;
|
1355
1422
|
}), this.caret.onStyleChange.subscribe(style => {
|
@@ -1472,7 +1539,6 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1472
1539
|
this.commander.delete();
|
1473
1540
|
}
|
1474
1541
|
this.composition = true;
|
1475
|
-
this.caret.compositionState = this.compositionState = null;
|
1476
1542
|
startIndex = this.selection.startOffset;
|
1477
1543
|
const startSlot = this.selection.startSlot;
|
1478
1544
|
const event = new core$1.Event(startSlot, {
|
@@ -1489,10 +1555,11 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1489
1555
|
return;
|
1490
1556
|
}
|
1491
1557
|
const startSlot = this.selection.startSlot;
|
1492
|
-
this.
|
1558
|
+
this.adapter.composition = {
|
1493
1559
|
slot: startSlot,
|
1494
|
-
|
1495
|
-
|
1560
|
+
text: ev.data,
|
1561
|
+
offset: ev.data.length,
|
1562
|
+
index: startIndex
|
1496
1563
|
};
|
1497
1564
|
this.caret.refresh(true);
|
1498
1565
|
const event = new core$1.Event(startSlot, {
|
@@ -1500,6 +1567,7 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1500
1567
|
data: ev.data
|
1501
1568
|
});
|
1502
1569
|
core$1.invokeListener(startSlot.parent, 'onCompositionUpdate', event);
|
1570
|
+
startSlot.changeMarker.forceMarkDirtied();
|
1503
1571
|
}));
|
1504
1572
|
let isCompositionEnd = false;
|
1505
1573
|
this.subscription.add(stream.merge(stream.fromEvent(textarea, 'beforeinput').pipe(stream.filter(ev => {
|
@@ -1523,24 +1591,15 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1523
1591
|
textarea.value = '';
|
1524
1592
|
return ev.data;
|
1525
1593
|
}))).subscribe(text => {
|
1594
|
+
var _a;
|
1526
1595
|
this.composition = false;
|
1527
|
-
this.
|
1528
|
-
const compositionElement = this.caret.compositionElement;
|
1529
|
-
let nextSibling = compositionElement.nextSibling;
|
1530
|
-
while (nextSibling) {
|
1531
|
-
if (!nextSibling.textContent) {
|
1532
|
-
const next = nextSibling.nextSibling;
|
1533
|
-
nextSibling.remove();
|
1534
|
-
nextSibling = next;
|
1535
|
-
continue;
|
1536
|
-
}
|
1537
|
-
nextSibling.remove();
|
1538
|
-
break;
|
1539
|
-
}
|
1540
|
-
compositionElement.remove();
|
1596
|
+
this.adapter.composition = null;
|
1541
1597
|
if (text) {
|
1542
1598
|
this.commander.write(text);
|
1543
1599
|
}
|
1600
|
+
else {
|
1601
|
+
(_a = this.selection.startSlot) === null || _a === void 0 ? void 0 : _a.changeMarker.forceMarkDirtied();
|
1602
|
+
}
|
1544
1603
|
if (isCompositionEnd) {
|
1545
1604
|
const startSlot = this.selection.startSlot;
|
1546
1605
|
if (startSlot) {
|
@@ -1569,7 +1628,8 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1569
1628
|
};
|
1570
1629
|
exports.MagicInput = __decorate([
|
1571
1630
|
core.Injectable(),
|
1572
|
-
__metadata("design:paramtypes", [
|
1631
|
+
__metadata("design:paramtypes", [DomAdapter,
|
1632
|
+
exports.Parser,
|
1573
1633
|
core$1.Keyboard,
|
1574
1634
|
core$1.Commander,
|
1575
1635
|
core$1.Selection,
|
@@ -1641,6 +1701,7 @@ exports.CollaborateCursor = class CollaborateCursor {
|
|
1641
1701
|
this.onRectsChange = new stream.Subject();
|
1642
1702
|
this.subscription = new stream.Subscription();
|
1643
1703
|
this.currentSelection = [];
|
1704
|
+
this.ratio = window.devicePixelRatio || 1;
|
1644
1705
|
this.container = textbus.get(VIEW_CONTAINER);
|
1645
1706
|
this.canvasContainer.append(this.canvas);
|
1646
1707
|
this.host.append(this.canvasContainer, this.tooltips);
|
@@ -1684,8 +1745,9 @@ exports.CollaborateCursor = class CollaborateCursor {
|
|
1684
1745
|
this.currentSelection = paths;
|
1685
1746
|
const containerRect = this.container.getBoundingClientRect();
|
1686
1747
|
this.canvas.style.top = containerRect.top * -1 + 'px';
|
1687
|
-
this.canvas.width = this.canvas.offsetWidth;
|
1688
|
-
this.canvas.height = this.canvas.offsetHeight;
|
1748
|
+
this.canvas.width = this.canvas.offsetWidth * this.ratio;
|
1749
|
+
this.canvas.height = this.canvas.offsetHeight * this.ratio;
|
1750
|
+
this.context.scale(this.ratio, this.ratio);
|
1689
1751
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
1690
1752
|
const users = [];
|
1691
1753
|
paths.filter(i => {
|
@@ -1710,8 +1772,13 @@ exports.CollaborateCursor = class CollaborateCursor {
|
|
1710
1772
|
return;
|
1711
1773
|
}
|
1712
1774
|
const nativeRange = document.createRange();
|
1713
|
-
|
1714
|
-
|
1775
|
+
try {
|
1776
|
+
nativeRange.setStart(anchor.node, anchor.offset);
|
1777
|
+
nativeRange.setEnd(focus.node, focus.offset);
|
1778
|
+
}
|
1779
|
+
catch (e) {
|
1780
|
+
return;
|
1781
|
+
}
|
1715
1782
|
if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
|
1716
1783
|
nativeRange.setStart(focus.node, focus.offset);
|
1717
1784
|
nativeRange.setEnd(anchor.node, anchor.offset);
|
@@ -1974,7 +2041,7 @@ let NativeInput = class NativeInput extends Input {
|
|
1974
2041
|
this.controller = controller;
|
1975
2042
|
this.caret = new NativeCaret(this.scheduler);
|
1976
2043
|
this.composition = false;
|
1977
|
-
|
2044
|
+
// compositionState: CompositionState | null = null
|
1978
2045
|
this.onReady = Promise.resolve();
|
1979
2046
|
this._disabled = false;
|
1980
2047
|
this.nativeSelection = document.getSelection();
|
@@ -2132,7 +2199,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2132
2199
|
let startIndex;
|
2133
2200
|
const compositionStart = () => {
|
2134
2201
|
this.composition = true;
|
2135
|
-
this.compositionState = null;
|
2136
2202
|
startIndex = this.selection.startOffset;
|
2137
2203
|
const startSlot = this.selection.startSlot;
|
2138
2204
|
const event = new core$1.Event(startSlot, {
|
@@ -2142,11 +2208,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2142
2208
|
};
|
2143
2209
|
const compositionUpdate = (data) => {
|
2144
2210
|
const startSlot = this.selection.startSlot;
|
2145
|
-
this.compositionState = {
|
2146
|
-
slot: startSlot,
|
2147
|
-
index: startIndex,
|
2148
|
-
data
|
2149
|
-
};
|
2150
2211
|
const event = new core$1.Event(startSlot, {
|
2151
2212
|
index: startIndex,
|
2152
2213
|
data
|
@@ -2233,7 +2294,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2233
2294
|
return !this.ignoreComposition;
|
2234
2295
|
})).subscribe(() => {
|
2235
2296
|
this.composition = true;
|
2236
|
-
this.compositionState = null;
|
2237
2297
|
startIndex = this.selection.startOffset;
|
2238
2298
|
const startSlot = this.selection.startSlot;
|
2239
2299
|
const event = new core$1.Event(startSlot, {
|
@@ -2244,11 +2304,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2244
2304
|
return !this.ignoreComposition;
|
2245
2305
|
})).subscribe(ev => {
|
2246
2306
|
const startSlot = this.selection.startSlot;
|
2247
|
-
this.compositionState = {
|
2248
|
-
slot: startSlot,
|
2249
|
-
index: startIndex,
|
2250
|
-
data: ev.data
|
2251
|
-
};
|
2252
2307
|
const event = new core$1.Event(startSlot, {
|
2253
2308
|
index: startIndex,
|
2254
2309
|
data: ev.data
|
@@ -2298,7 +2353,6 @@ let NativeInput = class NativeInput extends Input {
|
|
2298
2353
|
return !b;
|
2299
2354
|
}))).subscribe(text => {
|
2300
2355
|
this.composition = false;
|
2301
|
-
this.compositionState = null;
|
2302
2356
|
if (text) {
|
2303
2357
|
this.commander.write(text);
|
2304
2358
|
}
|
package/bundles/magic-input.d.ts
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
import { Observable } from '@tanbo/stream';
|
2
2
|
import { Commander, Controller, Keyboard, Scheduler, Selection, Textbus } from '@textbus/core';
|
3
3
|
import { Parser } from './parser';
|
4
|
-
import { Caret, CaretPosition,
|
4
|
+
import { Caret, CaretPosition, Input, Scroller } from './types';
|
5
|
+
import { DomAdapter } from './dom-adapter';
|
5
6
|
interface CaretStyle {
|
6
7
|
height: string;
|
7
8
|
lineHeight: string;
|
8
9
|
fontSize: string;
|
9
10
|
}
|
10
11
|
declare class ExperimentalCaret implements Caret {
|
12
|
+
private adapter;
|
11
13
|
private scheduler;
|
12
14
|
private editorMask;
|
13
15
|
onPositionChange: Observable<CaretPosition | null>;
|
14
16
|
onStyleChange: Observable<CaretStyle>;
|
15
17
|
elementRef: HTMLElement;
|
16
|
-
compositionState: CompositionState | null;
|
17
18
|
get rect(): DOMRect;
|
18
|
-
compositionElement: HTMLElement;
|
19
19
|
private timer;
|
20
20
|
private caret;
|
21
21
|
private oldPosition;
|
@@ -29,7 +29,7 @@ declare class ExperimentalCaret implements Caret {
|
|
29
29
|
private styleChangeEvent;
|
30
30
|
private oldRange;
|
31
31
|
private isFixed;
|
32
|
-
constructor(scheduler: Scheduler, editorMask: HTMLElement);
|
32
|
+
constructor(adapter: DomAdapter<any, any>, scheduler: Scheduler, editorMask: HTMLElement);
|
33
33
|
refresh(isFixedCaret?: boolean): void;
|
34
34
|
show(range: Range, restart: boolean): void;
|
35
35
|
hide(): void;
|
@@ -41,6 +41,7 @@ declare class ExperimentalCaret implements Caret {
|
|
41
41
|
* Textbus PC 端输入实现
|
42
42
|
*/
|
43
43
|
export declare class MagicInput extends Input {
|
44
|
+
private adapter;
|
44
45
|
private parser;
|
45
46
|
private keyboard;
|
46
47
|
private commander;
|
@@ -49,7 +50,6 @@ export declare class MagicInput extends Input {
|
|
49
50
|
private scheduler;
|
50
51
|
private textbus;
|
51
52
|
composition: boolean;
|
52
|
-
compositionState: CompositionState | null;
|
53
53
|
onReady: Promise<void>;
|
54
54
|
caret: ExperimentalCaret;
|
55
55
|
set disabled(b: boolean);
|
@@ -66,7 +66,7 @@ export declare class MagicInput extends Input {
|
|
66
66
|
private isFocus;
|
67
67
|
private nativeFocus;
|
68
68
|
private ignoreComposition;
|
69
|
-
constructor(parser: Parser, keyboard: Keyboard, commander: Commander, selection: Selection, controller: Controller, scheduler: Scheduler, textbus: Textbus);
|
69
|
+
constructor(adapter: DomAdapter<any, any>, parser: Parser, keyboard: Keyboard, commander: Commander, selection: Selection, controller: Controller, scheduler: Scheduler, textbus: Textbus);
|
70
70
|
focus(range: Range, restart: boolean): void;
|
71
71
|
blur(): void;
|
72
72
|
destroy(): void;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Observable } from '@tanbo/stream';
|
2
2
|
import { Commander, Controller, Keyboard, Scheduler, Selection, Textbus } from '@textbus/core';
|
3
|
-
import { Caret, CaretPosition,
|
3
|
+
import { Caret, CaretPosition, Input, Scroller } from './types';
|
4
4
|
import { Parser } from './parser';
|
5
5
|
import { DomAdapter } from './dom-adapter';
|
6
6
|
declare class NativeCaret implements Caret {
|
@@ -28,7 +28,6 @@ export declare class NativeInput extends Input {
|
|
28
28
|
private controller;
|
29
29
|
caret: NativeCaret;
|
30
30
|
composition: boolean;
|
31
|
-
compositionState: CompositionState | null;
|
32
31
|
onReady: Promise<void>;
|
33
32
|
set disabled(b: boolean);
|
34
33
|
get disabled(): boolean;
|
package/bundles/types.d.ts
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import { Slot } from '@textbus/core';
|
2
1
|
import { Observable } from '@tanbo/stream';
|
3
2
|
import { Rect } from './_utils/uikit';
|
4
3
|
export interface CaretLimit {
|
@@ -21,11 +20,6 @@ export interface Caret {
|
|
21
20
|
refresh(isFixedCaret: boolean): void;
|
22
21
|
correctScrollTop(scroller: Scroller): void;
|
23
22
|
}
|
24
|
-
export interface CompositionState {
|
25
|
-
slot: Slot;
|
26
|
-
index: number;
|
27
|
-
data: string;
|
28
|
-
}
|
29
23
|
export declare abstract class Input {
|
30
24
|
/**
|
31
25
|
* @experimental
|
@@ -34,7 +28,6 @@ export declare abstract class Input {
|
|
34
28
|
/**
|
35
29
|
* @experimental
|
36
30
|
*/
|
37
|
-
abstract compositionState: CompositionState | null;
|
38
31
|
abstract onReady: Promise<void>;
|
39
32
|
abstract caret: Caret;
|
40
33
|
abstract disabled: boolean;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@textbus/platform-browser",
|
3
|
-
"version": "4.0.0-alpha.
|
3
|
+
"version": "4.0.0-alpha.33",
|
4
4
|
"description": "Textbus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.",
|
5
5
|
"main": "./bundles/index.js",
|
6
6
|
"module": "./bundles/index.esm.js",
|
@@ -26,9 +26,9 @@
|
|
26
26
|
],
|
27
27
|
"dependencies": {
|
28
28
|
"@tanbo/stream": "^1.2.3",
|
29
|
-
"@textbus/collaborate": "^4.0.0-alpha.
|
30
|
-
"@textbus/core": "^4.0.0-alpha.
|
31
|
-
"@viewfly/core": "^0.6.
|
29
|
+
"@textbus/collaborate": "^4.0.0-alpha.33",
|
30
|
+
"@textbus/core": "^4.0.0-alpha.33",
|
31
|
+
"@viewfly/core": "^0.6.3",
|
32
32
|
"reflect-metadata": "^0.1.13"
|
33
33
|
},
|
34
34
|
"devDependencies": {
|
@@ -49,5 +49,5 @@
|
|
49
49
|
"bugs": {
|
50
50
|
"url": "https://github.com/textbus/textbus.git/issues"
|
51
51
|
},
|
52
|
-
"gitHead": "
|
52
|
+
"gitHead": "5eb73f9a388d331946a8579aa6eaa23cc44bffe0"
|
53
53
|
}
|