@textbus/platform-browser 4.0.0-alpha.41 → 4.0.0-alpha.42
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/browser-module.d.ts +2 -2
- package/bundles/dom-adapter.d.ts +4 -75
- package/bundles/index.esm.js +20 -215
- package/bundles/index.js +22 -217
- package/bundles/magic-input.d.ts +4 -4
- package/bundles/native-input.d.ts +1 -1
- package/bundles/public-api.d.ts +1 -0
- package/bundles/selection-bridge.d.ts +2 -2
- package/package.json +4 -4
package/bundles/dom-adapter.d.ts
CHANGED
@@ -1,77 +1,6 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
offset: number;
|
6
|
-
index: number;
|
7
|
-
}
|
8
|
-
/**
|
9
|
-
* Textbus PC 端浏览器渲染能力桥接器抽象类,提供了 DOM 元素查询能力,具体渲染能力由各前端框架实现相应桥接
|
10
|
-
*/
|
11
|
-
export declare abstract class DomAdapter<ViewComponent, ViewElement> extends ViewAdapter {
|
12
|
-
private mount;
|
1
|
+
import { Adapter } from '@textbus/core';
|
2
|
+
import { Subject } from '@tanbo/stream';
|
3
|
+
export declare abstract class DomAdapter<ViewComponent extends object = object, ViewElement extends object = object> extends Adapter<HTMLElement, Node, ViewComponent, ViewElement> {
|
4
|
+
onViewUpdated: Subject<void>;
|
13
5
|
host: HTMLElement;
|
14
|
-
compositionNode: HTMLElement | null;
|
15
|
-
composition: CompositionState | null;
|
16
|
-
protected firstRending: boolean;
|
17
|
-
protected componentRootElementCaches: {
|
18
|
-
set: {
|
19
|
-
(key: Component<import("@textbus/core").State>, value: HTMLElement): void;
|
20
|
-
(key: HTMLElement, value: Component<import("@textbus/core").State>): void;
|
21
|
-
};
|
22
|
-
get: {
|
23
|
-
(key: Component<import("@textbus/core").State>): HTMLElement;
|
24
|
-
(key: HTMLElement): Component<import("@textbus/core").State>;
|
25
|
-
};
|
26
|
-
remove: (key: HTMLElement | Component<import("@textbus/core").State>) => void;
|
27
|
-
};
|
28
|
-
protected slotRootNativeElementCaches: {
|
29
|
-
set: {
|
30
|
-
(key: Slot, value: HTMLElement): void;
|
31
|
-
(key: HTMLElement, value: Slot): void;
|
32
|
-
};
|
33
|
-
get: {
|
34
|
-
(key: Slot): HTMLElement;
|
35
|
-
(key: HTMLElement): Slot;
|
36
|
-
};
|
37
|
-
remove: (key: HTMLElement | Slot) => void;
|
38
|
-
};
|
39
|
-
protected slotRootVElementCaches: WeakMap<Slot, VElement>;
|
40
|
-
protected renderedSlotCache: WeakMap<Slot, true>;
|
41
|
-
protected constructor(mount: (host: HTMLElement, viewComponent: ViewComponent, textbus: Textbus) => (void | (() => void)));
|
42
|
-
render(rootComponent: Component, textbus: Textbus): void | (() => void);
|
43
|
-
abstract componentRender(component: Component): ViewComponent;
|
44
|
-
abstract slotRender(slot: Slot, slotHostRender: (children: Array<VElement | VTextNode | Component>) => VElement, renderEnv: any): ViewElement;
|
45
|
-
copy(): void;
|
46
|
-
/**
|
47
|
-
* 根据组件获取组件的根 DOM 节点
|
48
|
-
* @param component
|
49
|
-
*/
|
50
|
-
getNativeNodeByComponent(component: Component): HTMLElement | null;
|
51
|
-
/**
|
52
|
-
* 根据 DOM 节点,获对对应的组件根节点,如传入的 DOM 节点不为组件的根节点,则返回 null
|
53
|
-
* @param node
|
54
|
-
*/
|
55
|
-
getComponentByNativeNode(node: HTMLElement): Component | null;
|
56
|
-
/**
|
57
|
-
* 根据插槽获取插槽的根 DOM 节点
|
58
|
-
* @param slot
|
59
|
-
*/
|
60
|
-
getNativeNodeBySlot(slot: Slot): HTMLElement | null;
|
61
|
-
/**
|
62
|
-
* 根据 DOM 节点,获对对应的插槽根节点,如传入的 DOM 节点不为插槽的根节点,则返回 null
|
63
|
-
* @param node
|
64
|
-
*/
|
65
|
-
getSlotByNativeNode(node: HTMLElement): Slot | null;
|
66
|
-
/**
|
67
|
-
* 获取插槽内容节点集合
|
68
|
-
* @param slot
|
69
|
-
*/
|
70
|
-
getNodesBySlot(slot: Slot): Node[];
|
71
|
-
/**
|
72
|
-
* 获取原生节点的原始数据在文档中的位置
|
73
|
-
* @param node
|
74
|
-
*/
|
75
|
-
getLocationByNativeNode(node: Node): NodeLocation | null;
|
76
|
-
protected insertCompositionByIndex(slot: Slot, vNode: VElement, composition: CompositionState, createCompositionNode: (composition: CompositionState) => VElement): void;
|
77
6
|
}
|
package/bundles/index.esm.js
CHANGED
@@ -1,5 +1,5 @@
|
|
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
5
|
import { UserActivity } from '@textbus/collaborate';
|
@@ -301,13 +301,10 @@ Parser = Parser_1 = __decorate([
|
|
301
301
|
class Input {
|
302
302
|
}
|
303
303
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
constructor(mount) {
|
309
|
-
super();
|
310
|
-
this.mount = mount;
|
304
|
+
class DomAdapter extends Adapter {
|
305
|
+
constructor() {
|
306
|
+
super(...arguments);
|
307
|
+
this.onViewUpdated = new Subject();
|
311
308
|
this.host = createElement('div', {
|
312
309
|
styles: {
|
313
310
|
cursor: 'text',
|
@@ -323,197 +320,8 @@ class DomAdapter extends ViewAdapter {
|
|
323
320
|
id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)
|
324
321
|
}
|
325
322
|
});
|
326
|
-
this.compositionNode = null;
|
327
|
-
this.composition = null;
|
328
|
-
this.firstRending = true;
|
329
|
-
this.componentRootElementCaches = createBidirectionalMapping(a => {
|
330
|
-
return a instanceof Component;
|
331
|
-
});
|
332
|
-
this.slotRootNativeElementCaches = createBidirectionalMapping(a => {
|
333
|
-
return a instanceof Slot;
|
334
|
-
});
|
335
|
-
this.slotRootVElementCaches = new WeakMap();
|
336
|
-
this.renderedSlotCache = new WeakMap();
|
337
|
-
}
|
338
|
-
render(rootComponent, textbus) {
|
339
|
-
const view = this.componentRender(rootComponent);
|
340
|
-
this.firstRending = false;
|
341
|
-
return this.mount(this.host, view, textbus);
|
342
|
-
}
|
343
|
-
copy() {
|
344
|
-
document.execCommand('copy');
|
345
|
-
}
|
346
|
-
/**
|
347
|
-
* 根据组件获取组件的根 DOM 节点
|
348
|
-
* @param component
|
349
|
-
*/
|
350
|
-
getNativeNodeByComponent(component) {
|
351
|
-
return this.componentRootElementCaches.get(component) || null;
|
352
|
-
}
|
353
|
-
/**
|
354
|
-
* 根据 DOM 节点,获对对应的组件根节点,如传入的 DOM 节点不为组件的根节点,则返回 null
|
355
|
-
* @param node
|
356
|
-
*/
|
357
|
-
getComponentByNativeNode(node) {
|
358
|
-
return this.componentRootElementCaches.get(node) || null;
|
359
|
-
}
|
360
|
-
/**
|
361
|
-
* 根据插槽获取插槽的根 DOM 节点
|
362
|
-
* @param slot
|
363
|
-
*/
|
364
|
-
getNativeNodeBySlot(slot) {
|
365
|
-
return this.slotRootNativeElementCaches.get(slot) || null;
|
366
|
-
}
|
367
|
-
/**
|
368
|
-
* 根据 DOM 节点,获对对应的插槽根节点,如传入的 DOM 节点不为插槽的根节点,则返回 null
|
369
|
-
* @param node
|
370
|
-
*/
|
371
|
-
getSlotByNativeNode(node) {
|
372
|
-
return this.slotRootNativeElementCaches.get(node) || null;
|
373
|
-
}
|
374
|
-
/**
|
375
|
-
* 获取插槽内容节点集合
|
376
|
-
* @param slot
|
377
|
-
*/
|
378
|
-
getNodesBySlot(slot) {
|
379
|
-
const rootNativeNode = this.getNativeNodeBySlot(slot);
|
380
|
-
if (!rootNativeNode) {
|
381
|
-
return [];
|
382
|
-
}
|
383
|
-
const rootVNode = this.slotRootVElementCaches.get(slot);
|
384
|
-
return getNodes(this, rootVNode, rootNativeNode, []);
|
385
|
-
}
|
386
|
-
/**
|
387
|
-
* 获取原生节点的原始数据在文档中的位置
|
388
|
-
* @param node
|
389
|
-
*/
|
390
|
-
getLocationByNativeNode(node) {
|
391
|
-
let slotRootNode = node;
|
392
|
-
while (!this.slotRootNativeElementCaches.get(slotRootNode)) {
|
393
|
-
slotRootNode = slotRootNode.parentNode;
|
394
|
-
if (!slotRootNode) {
|
395
|
-
return null;
|
396
|
-
}
|
397
|
-
}
|
398
|
-
const slot = this.slotRootNativeElementCaches.get(slotRootNode);
|
399
|
-
const rootVNode = this.slotRootVElementCaches.get(slot);
|
400
|
-
return getLocation(node, slotRootNode, rootVNode);
|
401
|
-
}
|
402
|
-
insertCompositionByIndex(slot, vNode, composition, createCompositionNode) {
|
403
|
-
const location = vNode.location;
|
404
|
-
const nodes = vNode.children;
|
405
|
-
if (location && location.slot === composition.slot) {
|
406
|
-
for (let i = 0; i < nodes.length; i++) {
|
407
|
-
const child = nodes[i];
|
408
|
-
if (child instanceof VTextNode) {
|
409
|
-
const childLocation = child.location;
|
410
|
-
if (childLocation) {
|
411
|
-
if (composition.index > childLocation.startIndex && composition.index <= childLocation.endIndex) {
|
412
|
-
const compositionNode = createCompositionNode(composition);
|
413
|
-
if (composition.index === childLocation.endIndex) {
|
414
|
-
nodes.splice(i + 1, 0, compositionNode);
|
415
|
-
break;
|
416
|
-
}
|
417
|
-
const splitIndex = composition.index - childLocation.startIndex;
|
418
|
-
const beforeNode = new VTextNode(child.textContent.slice(0, splitIndex));
|
419
|
-
beforeNode.location = {
|
420
|
-
slot: childLocation.slot,
|
421
|
-
startIndex: childLocation.startIndex,
|
422
|
-
endIndex: childLocation.startIndex + splitIndex
|
423
|
-
};
|
424
|
-
const afterNode = new VTextNode(child.textContent.slice(splitIndex));
|
425
|
-
afterNode.location = {
|
426
|
-
slot: childLocation.slot,
|
427
|
-
startIndex: composition.index,
|
428
|
-
endIndex: childLocation.endIndex
|
429
|
-
};
|
430
|
-
nodes.splice(i, 1, beforeNode, compositionNode, afterNode);
|
431
|
-
break;
|
432
|
-
}
|
433
|
-
else if (composition.index === 0 && childLocation.startIndex === 0) {
|
434
|
-
nodes.splice(i, 0, createCompositionNode(composition));
|
435
|
-
break;
|
436
|
-
}
|
437
|
-
}
|
438
|
-
}
|
439
|
-
else if (child instanceof Component) {
|
440
|
-
const componentIndex = slot.indexOf(child);
|
441
|
-
if (composition.index === componentIndex + 1) {
|
442
|
-
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
443
|
-
break;
|
444
|
-
}
|
445
|
-
else if (componentIndex === 0 && composition.index === 0) {
|
446
|
-
nodes.splice(i, 0, createCompositionNode(composition));
|
447
|
-
break;
|
448
|
-
}
|
449
|
-
}
|
450
|
-
else if (child.tagName === 'br') {
|
451
|
-
const location = child.location;
|
452
|
-
if (location) {
|
453
|
-
if (location.endIndex === composition.index) {
|
454
|
-
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
455
|
-
break;
|
456
|
-
}
|
457
|
-
else if (location.startIndex === 0 && composition.index === 0) {
|
458
|
-
nodes.splice(i, 0, createCompositionNode(composition));
|
459
|
-
break;
|
460
|
-
}
|
461
|
-
}
|
462
|
-
}
|
463
|
-
}
|
464
|
-
}
|
465
323
|
}
|
466
324
|
}
|
467
|
-
function getNodes(adapter, vElement, nativeNode, result) {
|
468
|
-
if (vElement.location) {
|
469
|
-
result.push(nativeNode);
|
470
|
-
}
|
471
|
-
for (let i = 0; i < vElement.children.length; i++) {
|
472
|
-
const vChild = vElement.children[i];
|
473
|
-
const nativeChild = nativeNode.childNodes[i];
|
474
|
-
if (vChild instanceof VElement) {
|
475
|
-
getNodes(adapter, vChild, nativeChild, result);
|
476
|
-
}
|
477
|
-
else if (vChild instanceof VTextNode) {
|
478
|
-
result.push(nativeChild);
|
479
|
-
}
|
480
|
-
else {
|
481
|
-
result.push(adapter.getNativeNodeByComponent(vChild));
|
482
|
-
}
|
483
|
-
}
|
484
|
-
return result;
|
485
|
-
}
|
486
|
-
function getLocation(target, tree, vNodeTree) {
|
487
|
-
if (target === tree) {
|
488
|
-
return Object.assign({}, vNodeTree.location);
|
489
|
-
}
|
490
|
-
const childNodes = tree.childNodes;
|
491
|
-
for (let i = 0; i < childNodes.length; i++) {
|
492
|
-
const child = vNodeTree.children[i];
|
493
|
-
const nativeChild = tree.childNodes[i];
|
494
|
-
if (nativeChild === target) {
|
495
|
-
if (child instanceof Component) {
|
496
|
-
const index = child.parent.indexOf(child);
|
497
|
-
return {
|
498
|
-
slot: child.parent,
|
499
|
-
startIndex: index,
|
500
|
-
endIndex: index + 1
|
501
|
-
};
|
502
|
-
}
|
503
|
-
return child.location;
|
504
|
-
}
|
505
|
-
else if (child instanceof VElement) {
|
506
|
-
let r = null;
|
507
|
-
if (nativeChild.nodeType === Node.ELEMENT_NODE) {
|
508
|
-
r = getLocation(target, nativeChild, child);
|
509
|
-
}
|
510
|
-
if (r) {
|
511
|
-
return r;
|
512
|
-
}
|
513
|
-
}
|
514
|
-
}
|
515
|
-
return null;
|
516
|
-
}
|
517
325
|
|
518
326
|
/**
|
519
327
|
* Textbus PC 端选区桥接实现
|
@@ -1099,8 +907,8 @@ class ExperimentalCaret {
|
|
1099
907
|
get display() {
|
1100
908
|
return this._display;
|
1101
909
|
}
|
1102
|
-
constructor(
|
1103
|
-
this.
|
910
|
+
constructor(domRenderer, scheduler, editorMask) {
|
911
|
+
this.domRenderer = domRenderer;
|
1104
912
|
this.scheduler = scheduler;
|
1105
913
|
this.editorMask = editorMask;
|
1106
914
|
this.timer = null;
|
@@ -1246,7 +1054,7 @@ class ExperimentalCaret {
|
|
1246
1054
|
this.positionChangeEvent.next(null);
|
1247
1055
|
return;
|
1248
1056
|
}
|
1249
|
-
const compositionNode = this.
|
1057
|
+
const compositionNode = this.domRenderer.compositionNode;
|
1250
1058
|
if (compositionNode) {
|
1251
1059
|
nativeRange = nativeRange.cloneRange();
|
1252
1060
|
nativeRange.selectNodeContents(compositionNode);
|
@@ -1310,9 +1118,9 @@ let MagicInput = class MagicInput extends Input {
|
|
1310
1118
|
get disabled() {
|
1311
1119
|
return this._disabled;
|
1312
1120
|
}
|
1313
|
-
constructor(
|
1121
|
+
constructor(domAdapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1314
1122
|
super();
|
1315
|
-
this.
|
1123
|
+
this.domAdapter = domAdapter;
|
1316
1124
|
this.parser = parser;
|
1317
1125
|
this.keyboard = keyboard;
|
1318
1126
|
this.commander = commander;
|
@@ -1321,7 +1129,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1321
1129
|
this.scheduler = scheduler;
|
1322
1130
|
this.textbus = textbus;
|
1323
1131
|
this.composition = false;
|
1324
|
-
this.caret = new ExperimentalCaret(this.
|
1132
|
+
this.caret = new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK));
|
1325
1133
|
this.isSafari = isSafari();
|
1326
1134
|
this.isFirefox = isFirefox();
|
1327
1135
|
this.isMac = isMac();
|
@@ -1409,10 +1217,10 @@ let MagicInput = class MagicInput extends Input {
|
|
1409
1217
|
this.isFocus = false;
|
1410
1218
|
this.nativeFocus = false;
|
1411
1219
|
this.caret.hide();
|
1412
|
-
if (this.
|
1413
|
-
const slot = this.
|
1414
|
-
this.
|
1415
|
-
this.
|
1220
|
+
if (this.domAdapter.composition) {
|
1221
|
+
const slot = this.domAdapter.composition.slot;
|
1222
|
+
this.domAdapter.composition = null;
|
1223
|
+
this.domAdapter.compositionNode = null;
|
1416
1224
|
slot.__changeMarker__.forceMarkDirtied();
|
1417
1225
|
}
|
1418
1226
|
}), fromEvent(textarea, 'focus').subscribe(() => {
|
@@ -1553,7 +1361,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1553
1361
|
return;
|
1554
1362
|
}
|
1555
1363
|
const startSlot = this.selection.startSlot;
|
1556
|
-
this.
|
1364
|
+
this.domAdapter.composition = {
|
1557
1365
|
slot: startSlot,
|
1558
1366
|
text: ev.data,
|
1559
1367
|
offset: ev.data.length,
|
@@ -1591,7 +1399,7 @@ let MagicInput = class MagicInput extends Input {
|
|
1591
1399
|
}))).subscribe(text => {
|
1592
1400
|
var _a;
|
1593
1401
|
this.composition = false;
|
1594
|
-
this.
|
1402
|
+
this.domAdapter.composition = null;
|
1595
1403
|
if (text) {
|
1596
1404
|
this.commander.write(text);
|
1597
1405
|
}
|
@@ -2405,11 +2213,8 @@ class BrowserModule {
|
|
2405
2213
|
provide: Input,
|
2406
2214
|
useClass: config.useContentEditable ? NativeInput : MagicInput
|
2407
2215
|
}, {
|
2408
|
-
provide:
|
2409
|
-
|
2410
|
-
return v;
|
2411
|
-
},
|
2412
|
-
deps: [DomAdapter]
|
2216
|
+
provide: Adapter,
|
2217
|
+
useValue: config.adapter
|
2413
2218
|
}, {
|
2414
2219
|
provide: DomAdapter,
|
2415
2220
|
useValue: config.adapter
|
@@ -2515,4 +2320,4 @@ class BrowserModule {
|
|
2515
2320
|
}
|
2516
2321
|
}
|
2517
2322
|
|
2518
|
-
export { BrowserModule, CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomAdapter, EDITOR_OPTIONS, Input, MagicInput, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, createElement, createTextNode, getLayoutRectByRange, isFirefox, isMac, isMobileBrowser, isSafari, isWindows };
|
2323
|
+
export { BrowserModule, CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomAdapter, EDITOR_OPTIONS, Input, MagicInput, NativeInput, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, createElement, createTextNode, getLayoutRectByRange, isFirefox, isMac, isMobileBrowser, isSafari, isWindows };
|
package/bundles/index.js
CHANGED
@@ -303,13 +303,10 @@ exports.Parser = Parser_1 = __decorate([
|
|
303
303
|
class Input {
|
304
304
|
}
|
305
305
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
constructor(mount) {
|
311
|
-
super();
|
312
|
-
this.mount = mount;
|
306
|
+
class DomAdapter extends core$1.Adapter {
|
307
|
+
constructor() {
|
308
|
+
super(...arguments);
|
309
|
+
this.onViewUpdated = new stream.Subject();
|
313
310
|
this.host = createElement('div', {
|
314
311
|
styles: {
|
315
312
|
cursor: 'text',
|
@@ -325,197 +322,8 @@ class DomAdapter extends core$1.ViewAdapter {
|
|
325
322
|
id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)
|
326
323
|
}
|
327
324
|
});
|
328
|
-
this.compositionNode = null;
|
329
|
-
this.composition = null;
|
330
|
-
this.firstRending = true;
|
331
|
-
this.componentRootElementCaches = core$1.createBidirectionalMapping(a => {
|
332
|
-
return a instanceof core$1.Component;
|
333
|
-
});
|
334
|
-
this.slotRootNativeElementCaches = core$1.createBidirectionalMapping(a => {
|
335
|
-
return a instanceof core$1.Slot;
|
336
|
-
});
|
337
|
-
this.slotRootVElementCaches = new WeakMap();
|
338
|
-
this.renderedSlotCache = new WeakMap();
|
339
|
-
}
|
340
|
-
render(rootComponent, textbus) {
|
341
|
-
const view = this.componentRender(rootComponent);
|
342
|
-
this.firstRending = false;
|
343
|
-
return this.mount(this.host, view, textbus);
|
344
|
-
}
|
345
|
-
copy() {
|
346
|
-
document.execCommand('copy');
|
347
|
-
}
|
348
|
-
/**
|
349
|
-
* 根据组件获取组件的根 DOM 节点
|
350
|
-
* @param component
|
351
|
-
*/
|
352
|
-
getNativeNodeByComponent(component) {
|
353
|
-
return this.componentRootElementCaches.get(component) || null;
|
354
|
-
}
|
355
|
-
/**
|
356
|
-
* 根据 DOM 节点,获对对应的组件根节点,如传入的 DOM 节点不为组件的根节点,则返回 null
|
357
|
-
* @param node
|
358
|
-
*/
|
359
|
-
getComponentByNativeNode(node) {
|
360
|
-
return this.componentRootElementCaches.get(node) || null;
|
361
|
-
}
|
362
|
-
/**
|
363
|
-
* 根据插槽获取插槽的根 DOM 节点
|
364
|
-
* @param slot
|
365
|
-
*/
|
366
|
-
getNativeNodeBySlot(slot) {
|
367
|
-
return this.slotRootNativeElementCaches.get(slot) || null;
|
368
|
-
}
|
369
|
-
/**
|
370
|
-
* 根据 DOM 节点,获对对应的插槽根节点,如传入的 DOM 节点不为插槽的根节点,则返回 null
|
371
|
-
* @param node
|
372
|
-
*/
|
373
|
-
getSlotByNativeNode(node) {
|
374
|
-
return this.slotRootNativeElementCaches.get(node) || null;
|
375
|
-
}
|
376
|
-
/**
|
377
|
-
* 获取插槽内容节点集合
|
378
|
-
* @param slot
|
379
|
-
*/
|
380
|
-
getNodesBySlot(slot) {
|
381
|
-
const rootNativeNode = this.getNativeNodeBySlot(slot);
|
382
|
-
if (!rootNativeNode) {
|
383
|
-
return [];
|
384
|
-
}
|
385
|
-
const rootVNode = this.slotRootVElementCaches.get(slot);
|
386
|
-
return getNodes(this, rootVNode, rootNativeNode, []);
|
387
|
-
}
|
388
|
-
/**
|
389
|
-
* 获取原生节点的原始数据在文档中的位置
|
390
|
-
* @param node
|
391
|
-
*/
|
392
|
-
getLocationByNativeNode(node) {
|
393
|
-
let slotRootNode = node;
|
394
|
-
while (!this.slotRootNativeElementCaches.get(slotRootNode)) {
|
395
|
-
slotRootNode = slotRootNode.parentNode;
|
396
|
-
if (!slotRootNode) {
|
397
|
-
return null;
|
398
|
-
}
|
399
|
-
}
|
400
|
-
const slot = this.slotRootNativeElementCaches.get(slotRootNode);
|
401
|
-
const rootVNode = this.slotRootVElementCaches.get(slot);
|
402
|
-
return getLocation(node, slotRootNode, rootVNode);
|
403
|
-
}
|
404
|
-
insertCompositionByIndex(slot, vNode, composition, createCompositionNode) {
|
405
|
-
const location = vNode.location;
|
406
|
-
const nodes = vNode.children;
|
407
|
-
if (location && location.slot === composition.slot) {
|
408
|
-
for (let i = 0; i < nodes.length; i++) {
|
409
|
-
const child = nodes[i];
|
410
|
-
if (child instanceof core$1.VTextNode) {
|
411
|
-
const childLocation = child.location;
|
412
|
-
if (childLocation) {
|
413
|
-
if (composition.index > childLocation.startIndex && composition.index <= childLocation.endIndex) {
|
414
|
-
const compositionNode = createCompositionNode(composition);
|
415
|
-
if (composition.index === childLocation.endIndex) {
|
416
|
-
nodes.splice(i + 1, 0, compositionNode);
|
417
|
-
break;
|
418
|
-
}
|
419
|
-
const splitIndex = composition.index - childLocation.startIndex;
|
420
|
-
const beforeNode = new core$1.VTextNode(child.textContent.slice(0, splitIndex));
|
421
|
-
beforeNode.location = {
|
422
|
-
slot: childLocation.slot,
|
423
|
-
startIndex: childLocation.startIndex,
|
424
|
-
endIndex: childLocation.startIndex + splitIndex
|
425
|
-
};
|
426
|
-
const afterNode = new core$1.VTextNode(child.textContent.slice(splitIndex));
|
427
|
-
afterNode.location = {
|
428
|
-
slot: childLocation.slot,
|
429
|
-
startIndex: composition.index,
|
430
|
-
endIndex: childLocation.endIndex
|
431
|
-
};
|
432
|
-
nodes.splice(i, 1, beforeNode, compositionNode, afterNode);
|
433
|
-
break;
|
434
|
-
}
|
435
|
-
else if (composition.index === 0 && childLocation.startIndex === 0) {
|
436
|
-
nodes.splice(i, 0, createCompositionNode(composition));
|
437
|
-
break;
|
438
|
-
}
|
439
|
-
}
|
440
|
-
}
|
441
|
-
else if (child instanceof core$1.Component) {
|
442
|
-
const componentIndex = slot.indexOf(child);
|
443
|
-
if (composition.index === componentIndex + 1) {
|
444
|
-
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
445
|
-
break;
|
446
|
-
}
|
447
|
-
else if (componentIndex === 0 && composition.index === 0) {
|
448
|
-
nodes.splice(i, 0, createCompositionNode(composition));
|
449
|
-
break;
|
450
|
-
}
|
451
|
-
}
|
452
|
-
else if (child.tagName === 'br') {
|
453
|
-
const location = child.location;
|
454
|
-
if (location) {
|
455
|
-
if (location.endIndex === composition.index) {
|
456
|
-
nodes.splice(i + 1, 0, createCompositionNode(composition));
|
457
|
-
break;
|
458
|
-
}
|
459
|
-
else if (location.startIndex === 0 && composition.index === 0) {
|
460
|
-
nodes.splice(i, 0, createCompositionNode(composition));
|
461
|
-
break;
|
462
|
-
}
|
463
|
-
}
|
464
|
-
}
|
465
|
-
}
|
466
|
-
}
|
467
325
|
}
|
468
326
|
}
|
469
|
-
function getNodes(adapter, vElement, nativeNode, result) {
|
470
|
-
if (vElement.location) {
|
471
|
-
result.push(nativeNode);
|
472
|
-
}
|
473
|
-
for (let i = 0; i < vElement.children.length; i++) {
|
474
|
-
const vChild = vElement.children[i];
|
475
|
-
const nativeChild = nativeNode.childNodes[i];
|
476
|
-
if (vChild instanceof core$1.VElement) {
|
477
|
-
getNodes(adapter, vChild, nativeChild, result);
|
478
|
-
}
|
479
|
-
else if (vChild instanceof core$1.VTextNode) {
|
480
|
-
result.push(nativeChild);
|
481
|
-
}
|
482
|
-
else {
|
483
|
-
result.push(adapter.getNativeNodeByComponent(vChild));
|
484
|
-
}
|
485
|
-
}
|
486
|
-
return result;
|
487
|
-
}
|
488
|
-
function getLocation(target, tree, vNodeTree) {
|
489
|
-
if (target === tree) {
|
490
|
-
return Object.assign({}, vNodeTree.location);
|
491
|
-
}
|
492
|
-
const childNodes = tree.childNodes;
|
493
|
-
for (let i = 0; i < childNodes.length; i++) {
|
494
|
-
const child = vNodeTree.children[i];
|
495
|
-
const nativeChild = tree.childNodes[i];
|
496
|
-
if (nativeChild === target) {
|
497
|
-
if (child instanceof core$1.Component) {
|
498
|
-
const index = child.parent.indexOf(child);
|
499
|
-
return {
|
500
|
-
slot: child.parent,
|
501
|
-
startIndex: index,
|
502
|
-
endIndex: index + 1
|
503
|
-
};
|
504
|
-
}
|
505
|
-
return child.location;
|
506
|
-
}
|
507
|
-
else if (child instanceof core$1.VElement) {
|
508
|
-
let r = null;
|
509
|
-
if (nativeChild.nodeType === Node.ELEMENT_NODE) {
|
510
|
-
r = getLocation(target, nativeChild, child);
|
511
|
-
}
|
512
|
-
if (r) {
|
513
|
-
return r;
|
514
|
-
}
|
515
|
-
}
|
516
|
-
}
|
517
|
-
return null;
|
518
|
-
}
|
519
327
|
|
520
328
|
/**
|
521
329
|
* Textbus PC 端选区桥接实现
|
@@ -1101,8 +909,8 @@ class ExperimentalCaret {
|
|
1101
909
|
get display() {
|
1102
910
|
return this._display;
|
1103
911
|
}
|
1104
|
-
constructor(
|
1105
|
-
this.
|
912
|
+
constructor(domRenderer, scheduler, editorMask) {
|
913
|
+
this.domRenderer = domRenderer;
|
1106
914
|
this.scheduler = scheduler;
|
1107
915
|
this.editorMask = editorMask;
|
1108
916
|
this.timer = null;
|
@@ -1248,7 +1056,7 @@ class ExperimentalCaret {
|
|
1248
1056
|
this.positionChangeEvent.next(null);
|
1249
1057
|
return;
|
1250
1058
|
}
|
1251
|
-
const compositionNode = this.
|
1059
|
+
const compositionNode = this.domRenderer.compositionNode;
|
1252
1060
|
if (compositionNode) {
|
1253
1061
|
nativeRange = nativeRange.cloneRange();
|
1254
1062
|
nativeRange.selectNodeContents(compositionNode);
|
@@ -1312,9 +1120,9 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1312
1120
|
get disabled() {
|
1313
1121
|
return this._disabled;
|
1314
1122
|
}
|
1315
|
-
constructor(
|
1123
|
+
constructor(domAdapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
1316
1124
|
super();
|
1317
|
-
this.
|
1125
|
+
this.domAdapter = domAdapter;
|
1318
1126
|
this.parser = parser;
|
1319
1127
|
this.keyboard = keyboard;
|
1320
1128
|
this.commander = commander;
|
@@ -1323,7 +1131,7 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1323
1131
|
this.scheduler = scheduler;
|
1324
1132
|
this.textbus = textbus;
|
1325
1133
|
this.composition = false;
|
1326
|
-
this.caret = new ExperimentalCaret(this.
|
1134
|
+
this.caret = new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK));
|
1327
1135
|
this.isSafari = isSafari();
|
1328
1136
|
this.isFirefox = isFirefox();
|
1329
1137
|
this.isMac = isMac();
|
@@ -1411,10 +1219,10 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1411
1219
|
this.isFocus = false;
|
1412
1220
|
this.nativeFocus = false;
|
1413
1221
|
this.caret.hide();
|
1414
|
-
if (this.
|
1415
|
-
const slot = this.
|
1416
|
-
this.
|
1417
|
-
this.
|
1222
|
+
if (this.domAdapter.composition) {
|
1223
|
+
const slot = this.domAdapter.composition.slot;
|
1224
|
+
this.domAdapter.composition = null;
|
1225
|
+
this.domAdapter.compositionNode = null;
|
1418
1226
|
slot.__changeMarker__.forceMarkDirtied();
|
1419
1227
|
}
|
1420
1228
|
}), stream.fromEvent(textarea, 'focus').subscribe(() => {
|
@@ -1555,7 +1363,7 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1555
1363
|
return;
|
1556
1364
|
}
|
1557
1365
|
const startSlot = this.selection.startSlot;
|
1558
|
-
this.
|
1366
|
+
this.domAdapter.composition = {
|
1559
1367
|
slot: startSlot,
|
1560
1368
|
text: ev.data,
|
1561
1369
|
offset: ev.data.length,
|
@@ -1593,7 +1401,7 @@ exports.MagicInput = class MagicInput extends Input {
|
|
1593
1401
|
}))).subscribe(text => {
|
1594
1402
|
var _a;
|
1595
1403
|
this.composition = false;
|
1596
|
-
this.
|
1404
|
+
this.domAdapter.composition = null;
|
1597
1405
|
if (text) {
|
1598
1406
|
this.commander.write(text);
|
1599
1407
|
}
|
@@ -2018,7 +1826,7 @@ class NativeCaret {
|
|
2018
1826
|
this.subs = [];
|
2019
1827
|
}
|
2020
1828
|
}
|
2021
|
-
|
1829
|
+
exports.NativeInput = class NativeInput extends Input {
|
2022
1830
|
set disabled(b) {
|
2023
1831
|
this._disabled = b;
|
2024
1832
|
if (this.controller.readonly) {
|
@@ -2367,7 +2175,7 @@ let NativeInput = class NativeInput extends Input {
|
|
2367
2175
|
}));
|
2368
2176
|
}
|
2369
2177
|
};
|
2370
|
-
NativeInput = __decorate([
|
2178
|
+
exports.NativeInput = __decorate([
|
2371
2179
|
core.Injectable(),
|
2372
2180
|
__metadata("design:paramtypes", [core$1.Textbus,
|
2373
2181
|
exports.Parser,
|
@@ -2377,7 +2185,7 @@ NativeInput = __decorate([
|
|
2377
2185
|
DomAdapter,
|
2378
2186
|
core$1.Commander,
|
2379
2187
|
core$1.Controller])
|
2380
|
-
], NativeInput);
|
2188
|
+
], exports.NativeInput);
|
2381
2189
|
|
2382
2190
|
const browserErrorFn = core$1.makeError('BrowserModule');
|
2383
2191
|
class BrowserModule {
|
@@ -2405,13 +2213,10 @@ class BrowserModule {
|
|
2405
2213
|
useExisting: exports.SelectionBridge
|
2406
2214
|
}, {
|
2407
2215
|
provide: Input,
|
2408
|
-
useClass: config.useContentEditable ? NativeInput : exports.MagicInput
|
2216
|
+
useClass: config.useContentEditable ? exports.NativeInput : exports.MagicInput
|
2409
2217
|
}, {
|
2410
|
-
provide: core$1.
|
2411
|
-
|
2412
|
-
return v;
|
2413
|
-
},
|
2414
|
-
deps: [DomAdapter]
|
2218
|
+
provide: core$1.Adapter,
|
2219
|
+
useValue: config.adapter
|
2415
2220
|
}, {
|
2416
2221
|
provide: DomAdapter,
|
2417
2222
|
useValue: config.adapter
|
package/bundles/magic-input.d.ts
CHANGED
@@ -9,7 +9,7 @@ interface CaretStyle {
|
|
9
9
|
fontSize: string;
|
10
10
|
}
|
11
11
|
declare class ExperimentalCaret implements Caret {
|
12
|
-
private
|
12
|
+
private domRenderer;
|
13
13
|
private scheduler;
|
14
14
|
private editorMask;
|
15
15
|
onPositionChange: Observable<CaretPosition | null>;
|
@@ -29,7 +29,7 @@ declare class ExperimentalCaret implements Caret {
|
|
29
29
|
private styleChangeEvent;
|
30
30
|
private oldRange;
|
31
31
|
private isFixed;
|
32
|
-
constructor(
|
32
|
+
constructor(domRenderer: DomAdapter, scheduler: Scheduler, editorMask: HTMLElement);
|
33
33
|
refresh(isFixedCaret?: boolean): void;
|
34
34
|
show(range: Range, restart: boolean): void;
|
35
35
|
hide(): void;
|
@@ -41,7 +41,7 @@ declare class ExperimentalCaret implements Caret {
|
|
41
41
|
* Textbus PC 端输入实现
|
42
42
|
*/
|
43
43
|
export declare class MagicInput extends Input {
|
44
|
-
private
|
44
|
+
private domAdapter;
|
45
45
|
private parser;
|
46
46
|
private keyboard;
|
47
47
|
private commander;
|
@@ -66,7 +66,7 @@ export declare class MagicInput extends Input {
|
|
66
66
|
private isFocus;
|
67
67
|
private nativeFocus;
|
68
68
|
private ignoreComposition;
|
69
|
-
constructor(
|
69
|
+
constructor(domAdapter: DomAdapter, 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;
|
@@ -40,7 +40,7 @@ export declare class NativeInput extends Input {
|
|
40
40
|
private isMac;
|
41
41
|
private isMobileBrowser;
|
42
42
|
private ignoreComposition;
|
43
|
-
constructor(textbus: Textbus, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, domAdapter: DomAdapter
|
43
|
+
constructor(textbus: Textbus, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, domAdapter: DomAdapter, commander: Commander, controller: Controller);
|
44
44
|
focus(nativeRange: Range): void;
|
45
45
|
blur(): void;
|
46
46
|
destroy(): void;
|
package/bundles/public-api.d.ts
CHANGED
@@ -6,6 +6,7 @@ export * from './collaborate-cursor';
|
|
6
6
|
export * from './dom-adapter';
|
7
7
|
export * from './injection-tokens';
|
8
8
|
export * from './magic-input';
|
9
|
+
export * from './native-input';
|
9
10
|
export * from './parser';
|
10
11
|
export * from './selection-bridge';
|
11
12
|
export * from './types';
|
@@ -2,8 +2,8 @@ import { Observable } from '@tanbo/stream';
|
|
2
2
|
import { NativeSelectionBridge, NativeSelectionConnector, SelectionPosition, AbstractSelection, RootComponentRef, Controller, Selection, Textbus } from '@textbus/core';
|
3
3
|
import { Rect } from './_utils/uikit';
|
4
4
|
import { Input } from './types';
|
5
|
-
import { DomAdapter } from './dom-adapter';
|
6
5
|
import { ViewOptions } from './browser-module';
|
6
|
+
import { DomAdapter } from './dom-adapter';
|
7
7
|
/**
|
8
8
|
* Textbus PC 端选区桥接实现
|
9
9
|
*/
|
@@ -24,7 +24,7 @@ export declare class SelectionBridge implements NativeSelectionBridge {
|
|
24
24
|
private docContainer;
|
25
25
|
private cacheCaretPositionTimer;
|
26
26
|
private oldCaretPosition;
|
27
|
-
constructor(config: ViewOptions, textbus: Textbus, controller: Controller, selection: Selection, rootComponentRef: RootComponentRef, input: Input, domAdapter: DomAdapter
|
27
|
+
constructor(config: ViewOptions, textbus: Textbus, controller: Controller, selection: Selection, rootComponentRef: RootComponentRef, input: Input, domAdapter: DomAdapter);
|
28
28
|
connect(connector: NativeSelectionConnector): void;
|
29
29
|
disConnect(): void;
|
30
30
|
getRect(location: SelectionPosition): Rect | null;
|
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.42",
|
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,8 +26,8 @@
|
|
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.
|
29
|
+
"@textbus/collaborate": "^4.0.0-alpha.42",
|
30
|
+
"@textbus/core": "^4.0.0-alpha.42",
|
31
31
|
"@viewfly/core": "^1.0.0-alpha.1",
|
32
32
|
"reflect-metadata": "^0.1.13"
|
33
33
|
},
|
@@ -49,5 +49,5 @@
|
|
49
49
|
"bugs": {
|
50
50
|
"url": "https://github.com/textbus/textbus.git/issues"
|
51
51
|
},
|
52
|
-
"gitHead": "
|
52
|
+
"gitHead": "690f066925bac5379883f54f470684c74645d12e"
|
53
53
|
}
|