@textbus/platform-browser 3.0.0-alpha.49 → 3.0.0-alpha.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { Injector } from '@tanbo/di';
2
- import { Selection, SelectionPaths, AbstractSelection, Scheduler } from '@textbus/core';
2
+ import { Selection, SelectionPaths, AbstractSelection, Renderer } from '@textbus/core';
3
3
  import { SelectionBridge } from '../core/selection-bridge';
4
4
  import { Rect } from '../_utils/uikit';
5
5
  export interface RemoteSelection {
@@ -24,7 +24,7 @@ export declare abstract class CollaborateSelectionAwarenessDelegate {
24
24
  export declare class CollaborateCursor {
25
25
  private injector;
26
26
  private nativeSelection;
27
- private scheduler;
27
+ private renderer;
28
28
  private selection;
29
29
  private awarenessDelegate?;
30
30
  private host;
@@ -36,7 +36,7 @@ export declare class CollaborateCursor {
36
36
  private subscription;
37
37
  private currentSelection;
38
38
  private container;
39
- constructor(injector: Injector, nativeSelection: SelectionBridge, scheduler: Scheduler, selection: Selection, awarenessDelegate?: CollaborateSelectionAwarenessDelegate | undefined);
39
+ constructor(injector: Injector, nativeSelection: SelectionBridge, renderer: Renderer, selection: Selection, awarenessDelegate?: CollaborateSelectionAwarenessDelegate | undefined);
40
40
  refresh(): void;
41
41
  destroy(): void;
42
42
  draw(paths: RemoteSelection[]): void;
@@ -1,6 +1,6 @@
1
1
  import { Observable } from '@tanbo/stream';
2
2
  import { Injector } from '@tanbo/di';
3
- import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
3
+ import { Commander, Controller, Keyboard, Scheduler, Selection, Slot } from '@textbus/core';
4
4
  import { Parser } from '../dom-support/parser';
5
5
  import { Caret, CaretPosition, Input, Scroller } from './types';
6
6
  interface CaretStyle {
@@ -8,12 +8,17 @@ interface CaretStyle {
8
8
  lineHeight: string;
9
9
  fontSize: string;
10
10
  }
11
+ interface CompositionState {
12
+ slot: Slot;
13
+ data: string;
14
+ }
11
15
  declare class ExperimentalCaret implements Caret {
12
16
  private scheduler;
13
17
  private editorMask;
14
18
  onPositionChange: Observable<CaretPosition | null>;
15
19
  onStyleChange: Observable<CaretStyle>;
16
20
  elementRef: HTMLElement;
21
+ compositionState: CompositionState | null;
17
22
  get rect(): DOMRect;
18
23
  private timer;
19
24
  private caret;
@@ -27,6 +32,7 @@ declare class ExperimentalCaret implements Caret {
27
32
  private styleChangeEvent;
28
33
  private oldRange;
29
34
  private isFixed;
35
+ private compositionElement;
30
36
  constructor(scheduler: Scheduler, editorMask: HTMLElement);
31
37
  refresh(isFixedCaret?: boolean): void;
32
38
  show(range: Range, restart: boolean): void;
@@ -51,6 +57,9 @@ export declare class MagicInput extends Input {
51
57
  caret: ExperimentalCaret;
52
58
  set disabled(b: boolean);
53
59
  get disabled(): boolean;
60
+ private isSafari;
61
+ private isMac;
62
+ private isWindows;
54
63
  private _disabled;
55
64
  private container;
56
65
  private subscription;
@@ -58,9 +67,6 @@ export declare class MagicInput extends Input {
58
67
  private textarea;
59
68
  private isFocus;
60
69
  private nativeFocus;
61
- private isSafari;
62
- private isMac;
63
- private isWindows;
64
70
  private isSougouPinYin;
65
71
  constructor(parser: Parser, keyboard: Keyboard, commander: Commander, selection: Selection, controller: Controller, scheduler: Scheduler, injector: Injector);
66
72
  focus(range: Range, restart: boolean): void;
@@ -1,6 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  import { InjectionToken, Injectable, Inject, Injector, Optional } from '@tanbo/di';
3
- import { VTextNode, VElement, Controller, Selection, RootComponentRef, Renderer, Scheduler, Slot, ContentType, Keyboard, Commander, makeError, Starter, NativeRenderer, NativeSelectionBridge, OutputRenderer, Registry, invokeListener, History } from '@textbus/core';
3
+ import { VTextNode, VElement, Controller, Selection, RootComponentRef, Renderer, Slot, ContentType, Keyboard, Commander, Scheduler, makeError, Starter, NativeRenderer, NativeSelectionBridge, OutputRenderer, Registry, invokeListener, History } from '@textbus/core';
4
4
  import { Subject, filter, fromEvent, Subscription, merge, map, Observable, distinctUntilChanged } from '@tanbo/stream';
5
5
 
6
6
  function createElement(tagName, options = {}) {
@@ -59,8 +59,8 @@ function getLayoutRectByRange(range) {
59
59
  }
60
60
  else if (beforeNode.nodeType === Node.TEXT_NODE) {
61
61
  const range2 = document.createRange();
62
- range2.setStart(beforeNode, beforeNode.textContent.length);
63
- range2.setEnd(beforeNode, beforeNode.textContent.length);
62
+ range2.selectNodeContents(beforeNode);
63
+ range2.collapse();
64
64
  return range2.getBoundingClientRect();
65
65
  }
66
66
  }
@@ -776,10 +776,10 @@ SelectionBridge = __decorate([
776
776
  class CollaborateSelectionAwarenessDelegate {
777
777
  }
778
778
  let CollaborateCursor = class CollaborateCursor {
779
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate) {
779
+ constructor(injector, nativeSelection, renderer, selection, awarenessDelegate) {
780
780
  this.injector = injector;
781
781
  this.nativeSelection = nativeSelection;
782
- this.scheduler = scheduler;
782
+ this.renderer = renderer;
783
783
  this.selection = selection;
784
784
  this.awarenessDelegate = awarenessDelegate;
785
785
  this.host = createElement('div', {
@@ -845,7 +845,7 @@ let CollaborateCursor = class CollaborateCursor {
845
845
  }), fromEvent(window, 'resize').subscribe(() => {
846
846
  this.canvas.style.height = document.documentElement.clientHeight + 'px';
847
847
  this.refresh();
848
- }), this.scheduler.onDocChanged.subscribe(() => {
848
+ }), this.renderer.onViewUpdated.subscribe(() => {
849
849
  this.refresh();
850
850
  }));
851
851
  }
@@ -1017,7 +1017,7 @@ CollaborateCursor = __decorate([
1017
1017
  __param(4, Optional()),
1018
1018
  __metadata("design:paramtypes", [Injector,
1019
1019
  SelectionBridge,
1020
- Scheduler,
1020
+ Renderer,
1021
1021
  Selection,
1022
1022
  CollaborateSelectionAwarenessDelegate])
1023
1023
  ], CollaborateCursor);
@@ -1361,6 +1361,7 @@ class ExperimentalCaret {
1361
1361
  constructor(scheduler, editorMask) {
1362
1362
  this.scheduler = scheduler;
1363
1363
  this.editorMask = editorMask;
1364
+ this.compositionState = null;
1364
1365
  this.timer = null;
1365
1366
  this.oldPosition = null;
1366
1367
  this._display = true;
@@ -1370,6 +1371,11 @@ class ExperimentalCaret {
1370
1371
  this.styleChangeEvent = new Subject();
1371
1372
  this.oldRange = null;
1372
1373
  this.isFixed = false;
1374
+ this.compositionElement = createElement('span', {
1375
+ styles: {
1376
+ textDecoration: 'underline'
1377
+ }
1378
+ });
1373
1379
  this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1374
1380
  this.onStyleChange = this.styleChangeEvent.asObservable();
1375
1381
  this.elementRef = createElement('div', {
@@ -1502,6 +1508,14 @@ class ExperimentalCaret {
1502
1508
  this.positionChangeEvent.next(null);
1503
1509
  return;
1504
1510
  }
1511
+ if (this.compositionState) {
1512
+ const compositionElement = this.compositionElement;
1513
+ compositionElement.innerText = this.compositionState.data;
1514
+ nativeRange = nativeRange.cloneRange();
1515
+ nativeRange.insertNode(compositionElement);
1516
+ nativeRange.selectNodeContents(compositionElement);
1517
+ nativeRange.collapse();
1518
+ }
1505
1519
  const rect = getLayoutRectByRange(nativeRange);
1506
1520
  const { fontSize, lineHeight, color } = getComputedStyle(node);
1507
1521
  let height;
@@ -1571,15 +1585,15 @@ let MagicInput = class MagicInput extends Input {
1571
1585
  this.injector = injector;
1572
1586
  this.composition = false;
1573
1587
  this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1588
+ this.isSafari = isSafari();
1589
+ this.isMac = isMac();
1590
+ this.isWindows = isWindows();
1574
1591
  this._disabled = false;
1575
1592
  this.container = this.createEditableFrame();
1576
1593
  this.subscription = new Subscription();
1577
1594
  this.textarea = null;
1578
1595
  this.isFocus = false;
1579
1596
  this.nativeFocus = false;
1580
- this.isSafari = isSafari();
1581
- this.isMac = isMac();
1582
- this.isWindows = isWindows();
1583
1597
  this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1584
1598
  this.onReady = new Promise(resolve => {
1585
1599
  this.subscription.add(fromEvent(this.container, 'load').subscribe(() => {
@@ -1753,6 +1767,20 @@ let MagicInput = class MagicInput extends Input {
1753
1767
  }));
1754
1768
  }
1755
1769
  handleInput(textarea) {
1770
+ this.subscription.add(fromEvent(textarea, 'compositionupdate').subscribe(ev => {
1771
+ if (ev.data === ' ') {
1772
+ // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题
1773
+ return;
1774
+ }
1775
+ const slot = this.selection.startSlot;
1776
+ this.caret.compositionState = {
1777
+ slot,
1778
+ data: ev.data
1779
+ };
1780
+ slot.changeMarker.forceMarkDirtied();
1781
+ }), fromEvent(textarea, 'compositionend').subscribe(() => {
1782
+ this.caret.compositionState = null;
1783
+ }));
1756
1784
  this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
1757
1785
  ev.preventDefault();
1758
1786
  if (this.isSafari) {
@@ -1786,7 +1814,7 @@ let MagicInput = class MagicInput extends Input {
1786
1814
  display: 'block',
1787
1815
  height: '100%',
1788
1816
  position: 'relative',
1789
- top: this.isWindows ? '6px' : '0'
1817
+ top: this.isWindows ? '3px' : '0'
1790
1818
  }
1791
1819
  });
1792
1820
  }
@@ -1908,7 +1936,7 @@ let NativeInput = class NativeInput extends Input {
1908
1936
  set disabled(b) {
1909
1937
  this._disabled = b;
1910
1938
  if (b && !this.controller.readonly) {
1911
- this.documentView.contentEditable = b ? 'true' : 'false';
1939
+ this.documentView.contentEditable = b ? 'false' : 'true';
1912
1940
  }
1913
1941
  }
1914
1942
  get disabled() {
@@ -2609,7 +2637,7 @@ class Viewer extends Starter {
2609
2637
  });
2610
2638
  const styleEl = document.createElement('style');
2611
2639
  docStyles.push(...(options.styleSheets || []));
2612
- editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .2); color:inherit}`, ...(options.editingStyleSheets || []));
2640
+ editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .4); color:inherit}`, ...(options.editingStyleSheets || []));
2613
2641
  this.styleSheet = Viewer.cssMin(docStyles.join(''));
2614
2642
  styleEl.innerHTML = this.styleSheet + Viewer.cssMin(editModeStyles.join(''));
2615
2643
  this.resourceNodes.push(styleEl);
package/bundles/index.js CHANGED
@@ -61,8 +61,8 @@ function getLayoutRectByRange(range) {
61
61
  }
62
62
  else if (beforeNode.nodeType === Node.TEXT_NODE) {
63
63
  const range2 = document.createRange();
64
- range2.setStart(beforeNode, beforeNode.textContent.length);
65
- range2.setEnd(beforeNode, beforeNode.textContent.length);
64
+ range2.selectNodeContents(beforeNode);
65
+ range2.collapse();
66
66
  return range2.getBoundingClientRect();
67
67
  }
68
68
  }
@@ -778,10 +778,10 @@ exports.SelectionBridge = __decorate([
778
778
  class CollaborateSelectionAwarenessDelegate {
779
779
  }
780
780
  exports.CollaborateCursor = class CollaborateCursor {
781
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate) {
781
+ constructor(injector, nativeSelection, renderer, selection, awarenessDelegate) {
782
782
  this.injector = injector;
783
783
  this.nativeSelection = nativeSelection;
784
- this.scheduler = scheduler;
784
+ this.renderer = renderer;
785
785
  this.selection = selection;
786
786
  this.awarenessDelegate = awarenessDelegate;
787
787
  this.host = createElement('div', {
@@ -847,7 +847,7 @@ exports.CollaborateCursor = class CollaborateCursor {
847
847
  }), stream.fromEvent(window, 'resize').subscribe(() => {
848
848
  this.canvas.style.height = document.documentElement.clientHeight + 'px';
849
849
  this.refresh();
850
- }), this.scheduler.onDocChanged.subscribe(() => {
850
+ }), this.renderer.onViewUpdated.subscribe(() => {
851
851
  this.refresh();
852
852
  }));
853
853
  }
@@ -1019,7 +1019,7 @@ exports.CollaborateCursor = __decorate([
1019
1019
  __param(4, di.Optional()),
1020
1020
  __metadata("design:paramtypes", [di.Injector,
1021
1021
  exports.SelectionBridge,
1022
- core.Scheduler,
1022
+ core.Renderer,
1023
1023
  core.Selection,
1024
1024
  CollaborateSelectionAwarenessDelegate])
1025
1025
  ], exports.CollaborateCursor);
@@ -1363,6 +1363,7 @@ class ExperimentalCaret {
1363
1363
  constructor(scheduler, editorMask) {
1364
1364
  this.scheduler = scheduler;
1365
1365
  this.editorMask = editorMask;
1366
+ this.compositionState = null;
1366
1367
  this.timer = null;
1367
1368
  this.oldPosition = null;
1368
1369
  this._display = true;
@@ -1372,6 +1373,11 @@ class ExperimentalCaret {
1372
1373
  this.styleChangeEvent = new stream.Subject();
1373
1374
  this.oldRange = null;
1374
1375
  this.isFixed = false;
1376
+ this.compositionElement = createElement('span', {
1377
+ styles: {
1378
+ textDecoration: 'underline'
1379
+ }
1380
+ });
1375
1381
  this.onPositionChange = this.positionChangeEvent.pipe(stream.distinctUntilChanged());
1376
1382
  this.onStyleChange = this.styleChangeEvent.asObservable();
1377
1383
  this.elementRef = createElement('div', {
@@ -1504,6 +1510,14 @@ class ExperimentalCaret {
1504
1510
  this.positionChangeEvent.next(null);
1505
1511
  return;
1506
1512
  }
1513
+ if (this.compositionState) {
1514
+ const compositionElement = this.compositionElement;
1515
+ compositionElement.innerText = this.compositionState.data;
1516
+ nativeRange = nativeRange.cloneRange();
1517
+ nativeRange.insertNode(compositionElement);
1518
+ nativeRange.selectNodeContents(compositionElement);
1519
+ nativeRange.collapse();
1520
+ }
1507
1521
  const rect = getLayoutRectByRange(nativeRange);
1508
1522
  const { fontSize, lineHeight, color } = getComputedStyle(node);
1509
1523
  let height;
@@ -1573,15 +1587,15 @@ exports.MagicInput = class MagicInput extends Input {
1573
1587
  this.injector = injector;
1574
1588
  this.composition = false;
1575
1589
  this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1590
+ this.isSafari = isSafari();
1591
+ this.isMac = isMac();
1592
+ this.isWindows = isWindows();
1576
1593
  this._disabled = false;
1577
1594
  this.container = this.createEditableFrame();
1578
1595
  this.subscription = new stream.Subscription();
1579
1596
  this.textarea = null;
1580
1597
  this.isFocus = false;
1581
1598
  this.nativeFocus = false;
1582
- this.isSafari = isSafari();
1583
- this.isMac = isMac();
1584
- this.isWindows = isWindows();
1585
1599
  this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1586
1600
  this.onReady = new Promise(resolve => {
1587
1601
  this.subscription.add(stream.fromEvent(this.container, 'load').subscribe(() => {
@@ -1755,6 +1769,20 @@ exports.MagicInput = class MagicInput extends Input {
1755
1769
  }));
1756
1770
  }
1757
1771
  handleInput(textarea) {
1772
+ this.subscription.add(stream.fromEvent(textarea, 'compositionupdate').subscribe(ev => {
1773
+ if (ev.data === ' ') {
1774
+ // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题
1775
+ return;
1776
+ }
1777
+ const slot = this.selection.startSlot;
1778
+ this.caret.compositionState = {
1779
+ slot,
1780
+ data: ev.data
1781
+ };
1782
+ slot.changeMarker.forceMarkDirtied();
1783
+ }), stream.fromEvent(textarea, 'compositionend').subscribe(() => {
1784
+ this.caret.compositionState = null;
1785
+ }));
1758
1786
  this.subscription.add(stream.merge(stream.fromEvent(textarea, 'beforeinput').pipe(stream.filter(ev => {
1759
1787
  ev.preventDefault();
1760
1788
  if (this.isSafari) {
@@ -1788,7 +1816,7 @@ exports.MagicInput = class MagicInput extends Input {
1788
1816
  display: 'block',
1789
1817
  height: '100%',
1790
1818
  position: 'relative',
1791
- top: this.isWindows ? '6px' : '0'
1819
+ top: this.isWindows ? '3px' : '0'
1792
1820
  }
1793
1821
  });
1794
1822
  }
@@ -1910,7 +1938,7 @@ exports.NativeInput = class NativeInput extends Input {
1910
1938
  set disabled(b) {
1911
1939
  this._disabled = b;
1912
1940
  if (b && !this.controller.readonly) {
1913
- this.documentView.contentEditable = b ? 'true' : 'false';
1941
+ this.documentView.contentEditable = b ? 'false' : 'true';
1914
1942
  }
1915
1943
  }
1916
1944
  get disabled() {
@@ -2611,7 +2639,7 @@ class Viewer extends core.Starter {
2611
2639
  });
2612
2640
  const styleEl = document.createElement('style');
2613
2641
  docStyles.push(...(options.styleSheets || []));
2614
- editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .2); color:inherit}`, ...(options.editingStyleSheets || []));
2642
+ editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .4); color:inherit}`, ...(options.editingStyleSheets || []));
2615
2643
  this.styleSheet = Viewer.cssMin(docStyles.join(''));
2616
2644
  styleEl.innerHTML = this.styleSheet + Viewer.cssMin(editModeStyles.join(''));
2617
2645
  this.resourceNodes.push(styleEl);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/platform-browser",
3
- "version": "3.0.0-alpha.49",
3
+ "version": "3.0.0-alpha.51",
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",
@@ -27,7 +27,7 @@
27
27
  "dependencies": {
28
28
  "@tanbo/di": "^1.1.4",
29
29
  "@tanbo/stream": "^1.1.9",
30
- "@textbus/core": "^3.0.0-alpha.49",
30
+ "@textbus/core": "^3.0.0-alpha.51",
31
31
  "reflect-metadata": "^0.1.13"
32
32
  },
33
33
  "devDependencies": {
@@ -48,5 +48,5 @@
48
48
  "bugs": {
49
49
  "url": "https://github.com/textbus/textbus.git/issues"
50
50
  },
51
- "gitHead": "61f5bf6f105709ecb2cc8f1a5f6f0bf7bcac574e"
51
+ "gitHead": "4f2557bae5aa8800130c827f502d4439bddb1ff4"
52
52
  }