@textbus/platform-browser 3.0.0-alpha.58 → 3.0.0-alpha.59

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,18 +1,13 @@
1
1
  import { Observable } from '@tanbo/stream';
2
2
  import { Injector } from '@tanbo/di';
3
- import { Commander, Controller, Keyboard, Scheduler, Selection, Slot } from '@textbus/core';
3
+ import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
4
4
  import { Parser } from '../dom-support/parser';
5
- import { Caret, CaretPosition, Input, Scroller } from './types';
5
+ import { Caret, CaretPosition, CompositionState, Input, Scroller } from './types';
6
6
  interface CaretStyle {
7
7
  height: string;
8
8
  lineHeight: string;
9
9
  fontSize: string;
10
10
  }
11
- interface CompositionState {
12
- slot: Slot;
13
- index: number;
14
- data: string;
15
- }
16
11
  declare class ExperimentalCaret implements Caret {
17
12
  private scheduler;
18
13
  private editorMask;
@@ -54,6 +49,7 @@ export declare class MagicInput extends Input {
54
49
  private scheduler;
55
50
  private injector;
56
51
  composition: boolean;
52
+ compositionState: CompositionState | null;
57
53
  onReady: Promise<void>;
58
54
  caret: ExperimentalCaret;
59
55
  set disabled(b: boolean);
@@ -1,7 +1,7 @@
1
1
  import { Injector } from '@tanbo/di';
2
2
  import { Observable } from '@tanbo/stream';
3
3
  import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
4
- import { Caret, CaretPosition, Input, Scroller } from './types';
4
+ import { Caret, CaretPosition, CompositionState, Input, Scroller } from './types';
5
5
  import { Parser } from '../dom-support/parser';
6
6
  declare class NativeCaret implements Caret {
7
7
  private scheduler;
@@ -33,6 +33,7 @@ export declare class NativeInput extends Input {
33
33
  private controller;
34
34
  caret: NativeCaret;
35
35
  composition: boolean;
36
+ compositionState: CompositionState | null;
36
37
  onReady: Promise<void>;
37
38
  set disabled(b: boolean);
38
39
  get disabled(): boolean;
@@ -1,4 +1,4 @@
1
- import { ComponentLiteral, Module, TextbusConfig } from '@textbus/core';
1
+ import { ComponentLiteral, Module, Slot, TextbusConfig } from '@textbus/core';
2
2
  import { Observable } from '@tanbo/stream';
3
3
  import { FormatLoader, ComponentLoader, AttributeLoader } from '../dom-support/parser';
4
4
  import { Rect } from '../_utils/uikit';
@@ -51,8 +51,14 @@ export interface Caret {
51
51
  refresh(isFixedCaret: boolean): void;
52
52
  correctScrollTop(scroller: Scroller): void;
53
53
  }
54
+ export interface CompositionState {
55
+ slot: Slot;
56
+ index: number;
57
+ data: string;
58
+ }
54
59
  export declare abstract class Input {
55
60
  abstract composition: boolean;
61
+ abstract compositionState: CompositionState | null;
56
62
  abstract onReady: Promise<void>;
57
63
  abstract caret: Caret;
58
64
  abstract disabled: boolean;
@@ -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, Scheduler, Slot, ContentType, Event, invokeListener, Keyboard, Commander, makeError, Starter, NativeRenderer, NativeSelectionBridge, OutputRenderer, Registry, 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 = {}) {
@@ -1585,6 +1585,7 @@ let MagicInput = class MagicInput extends Input {
1585
1585
  this.scheduler = scheduler;
1586
1586
  this.injector = injector;
1587
1587
  this.composition = false;
1588
+ this.compositionState = null;
1588
1589
  this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1589
1590
  this.isSafari = isSafari();
1590
1591
  this.isFirefox = isFirefox();
@@ -1718,7 +1719,7 @@ let MagicInput = class MagicInput extends Input {
1718
1719
  setTimeout(() => {
1719
1720
  let html = div.innerHTML;
1720
1721
  if (!html && text && this.isFirefox) {
1721
- html = `<p>${text}</p>`;
1722
+ html = text;
1722
1723
  }
1723
1724
  this.handlePaste(html, text);
1724
1725
  this.doc.body.removeChild(div);
@@ -1775,32 +1776,46 @@ let MagicInput = class MagicInput extends Input {
1775
1776
  let startIndex = 0;
1776
1777
  this.subscription.add(fromEvent(textarea, 'compositionstart').subscribe(() => {
1777
1778
  this.composition = true;
1779
+ this.caret.compositionState = this.compositionState = null;
1778
1780
  startIndex = this.selection.startOffset;
1781
+ const startSlot = this.selection.startSlot;
1782
+ const event = new Event(startSlot, {
1783
+ index: startIndex
1784
+ });
1785
+ invokeListener(startSlot.parent, 'onCompositionStart', event);
1779
1786
  }), fromEvent(textarea, 'compositionupdate').subscribe(ev => {
1780
1787
  if (ev.data === ' ') {
1781
1788
  // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题
1782
1789
  return;
1783
1790
  }
1784
- this.caret.compositionState = {
1785
- slot: this.selection.startSlot,
1791
+ const startSlot = this.selection.startSlot;
1792
+ this.caret.compositionState = this.compositionState = {
1793
+ slot: startSlot,
1786
1794
  index: startIndex,
1787
1795
  data: ev.data
1788
1796
  };
1789
1797
  this.caret.refresh(true);
1790
- }), fromEvent(textarea, 'compositionend').subscribe(() => {
1791
- var _a;
1792
- this.caret.compositionState = null;
1793
- (_a = this.caret.compositionElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.caret.compositionElement);
1798
+ const event = new Event(startSlot, {
1799
+ index: startIndex,
1800
+ data: ev.data
1801
+ });
1802
+ invokeListener(startSlot.parent, 'onCompositionUpdate', event);
1794
1803
  }));
1804
+ let isCompositionEnd = false;
1795
1805
  this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
1796
1806
  ev.preventDefault();
1807
+ if (this.isFirefox && ev.inputType === 'insertFromPaste') {
1808
+ return false;
1809
+ }
1797
1810
  if (this.isSafari) {
1811
+ isCompositionEnd = ev.inputType === 'insertFromComposition';
1798
1812
  return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
1799
1813
  }
1800
1814
  return !ev.isComposing && !!ev.data;
1801
1815
  }), map(ev => {
1802
1816
  return ev.data;
1803
1817
  })), this.isSafari ? new Observable() : fromEvent(textarea, 'compositionend').pipe(map(ev => {
1818
+ isCompositionEnd = true;
1804
1819
  ev.preventDefault();
1805
1820
  textarea.value = '';
1806
1821
  return ev.data;
@@ -1809,10 +1824,21 @@ let MagicInput = class MagicInput extends Input {
1809
1824
  this.isSougouPinYin = false;
1810
1825
  return !b;
1811
1826
  }))).subscribe(text => {
1827
+ var _a;
1812
1828
  this.composition = false;
1829
+ this.caret.compositionState = this.compositionState = null;
1830
+ (_a = this.caret.compositionElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.caret.compositionElement);
1813
1831
  if (text) {
1814
1832
  this.commander.write(text);
1815
1833
  }
1834
+ if (isCompositionEnd) {
1835
+ const startSlot = this.selection.startSlot;
1836
+ if (startSlot) {
1837
+ const event = new Event(startSlot, null);
1838
+ invokeListener(startSlot.parent, 'onCompositionEnd', event);
1839
+ }
1840
+ }
1841
+ isCompositionEnd = false;
1816
1842
  }));
1817
1843
  }
1818
1844
  createEditableFrame() {
@@ -1965,6 +1991,7 @@ let NativeInput = class NativeInput extends Input {
1965
1991
  this.controller = controller;
1966
1992
  this.caret = new NativeCaret(this.scheduler);
1967
1993
  this.composition = false;
1994
+ this.compositionState = null;
1968
1995
  this.onReady = Promise.resolve();
1969
1996
  this._disabled = false;
1970
1997
  this.nativeSelection = document.getSelection();
@@ -2107,17 +2134,40 @@ let NativeInput = class NativeInput extends Input {
2107
2134
  }));
2108
2135
  }
2109
2136
  handleInput(input) {
2137
+ let startIndex = 0;
2138
+ let isCompositionEnd = false;
2110
2139
  this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
2111
2140
  this.composition = true;
2141
+ this.compositionState = null;
2142
+ startIndex = this.selection.startOffset;
2143
+ const startSlot = this.selection.startSlot;
2144
+ const event = new Event(startSlot, {
2145
+ index: startIndex
2146
+ });
2147
+ invokeListener(startSlot.parent, 'onCompositionStart', event);
2148
+ }), fromEvent(input, 'compositionupdate').subscribe(ev => {
2149
+ const startSlot = this.selection.startSlot;
2150
+ this.compositionState = {
2151
+ slot: startSlot,
2152
+ index: startIndex,
2153
+ data: ev.data
2154
+ };
2155
+ const event = new Event(startSlot, {
2156
+ index: startIndex,
2157
+ data: ev.data
2158
+ });
2159
+ invokeListener(startSlot.parent, 'onCompositionUpdate', event);
2112
2160
  }), merge(fromEvent(input, 'beforeinput').pipe(filter(ev => {
2113
2161
  ev.preventDefault();
2114
2162
  if (this.isSafari) {
2163
+ isCompositionEnd = ev.inputType === 'insertFromComposition';
2115
2164
  return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
2116
2165
  }
2117
2166
  return !ev.isComposing && !!ev.data;
2118
2167
  }), map(ev => {
2119
2168
  return ev.data;
2120
2169
  })), this.isSafari ? new Observable() : fromEvent(input, 'compositionend').pipe(map(ev => {
2170
+ isCompositionEnd = true;
2121
2171
  ev.preventDefault();
2122
2172
  return ev.data;
2123
2173
  }), filter(() => {
@@ -2126,9 +2176,18 @@ let NativeInput = class NativeInput extends Input {
2126
2176
  return !b;
2127
2177
  }))).subscribe(text => {
2128
2178
  this.composition = false;
2179
+ this.compositionState = null;
2129
2180
  if (text) {
2130
2181
  this.commander.write(text);
2131
2182
  }
2183
+ if (isCompositionEnd) {
2184
+ const startSlot = this.selection.startSlot;
2185
+ if (startSlot) {
2186
+ const event = new Event(startSlot, null);
2187
+ invokeListener(startSlot.parent, 'onCompositionEnd', event);
2188
+ }
2189
+ }
2190
+ isCompositionEnd = false;
2132
2191
  }));
2133
2192
  }
2134
2193
  };
package/bundles/index.js CHANGED
@@ -1587,6 +1587,7 @@ exports.MagicInput = class MagicInput extends Input {
1587
1587
  this.scheduler = scheduler;
1588
1588
  this.injector = injector;
1589
1589
  this.composition = false;
1590
+ this.compositionState = null;
1590
1591
  this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1591
1592
  this.isSafari = isSafari();
1592
1593
  this.isFirefox = isFirefox();
@@ -1720,7 +1721,7 @@ exports.MagicInput = class MagicInput extends Input {
1720
1721
  setTimeout(() => {
1721
1722
  let html = div.innerHTML;
1722
1723
  if (!html && text && this.isFirefox) {
1723
- html = `<p>${text}</p>`;
1724
+ html = text;
1724
1725
  }
1725
1726
  this.handlePaste(html, text);
1726
1727
  this.doc.body.removeChild(div);
@@ -1777,32 +1778,46 @@ exports.MagicInput = class MagicInput extends Input {
1777
1778
  let startIndex = 0;
1778
1779
  this.subscription.add(stream.fromEvent(textarea, 'compositionstart').subscribe(() => {
1779
1780
  this.composition = true;
1781
+ this.caret.compositionState = this.compositionState = null;
1780
1782
  startIndex = this.selection.startOffset;
1783
+ const startSlot = this.selection.startSlot;
1784
+ const event = new core.Event(startSlot, {
1785
+ index: startIndex
1786
+ });
1787
+ core.invokeListener(startSlot.parent, 'onCompositionStart', event);
1781
1788
  }), stream.fromEvent(textarea, 'compositionupdate').subscribe(ev => {
1782
1789
  if (ev.data === ' ') {
1783
1790
  // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题
1784
1791
  return;
1785
1792
  }
1786
- this.caret.compositionState = {
1787
- slot: this.selection.startSlot,
1793
+ const startSlot = this.selection.startSlot;
1794
+ this.caret.compositionState = this.compositionState = {
1795
+ slot: startSlot,
1788
1796
  index: startIndex,
1789
1797
  data: ev.data
1790
1798
  };
1791
1799
  this.caret.refresh(true);
1792
- }), stream.fromEvent(textarea, 'compositionend').subscribe(() => {
1793
- var _a;
1794
- this.caret.compositionState = null;
1795
- (_a = this.caret.compositionElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.caret.compositionElement);
1800
+ const event = new core.Event(startSlot, {
1801
+ index: startIndex,
1802
+ data: ev.data
1803
+ });
1804
+ core.invokeListener(startSlot.parent, 'onCompositionUpdate', event);
1796
1805
  }));
1806
+ let isCompositionEnd = false;
1797
1807
  this.subscription.add(stream.merge(stream.fromEvent(textarea, 'beforeinput').pipe(stream.filter(ev => {
1798
1808
  ev.preventDefault();
1809
+ if (this.isFirefox && ev.inputType === 'insertFromPaste') {
1810
+ return false;
1811
+ }
1799
1812
  if (this.isSafari) {
1813
+ isCompositionEnd = ev.inputType === 'insertFromComposition';
1800
1814
  return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
1801
1815
  }
1802
1816
  return !ev.isComposing && !!ev.data;
1803
1817
  }), stream.map(ev => {
1804
1818
  return ev.data;
1805
1819
  })), this.isSafari ? new stream.Observable() : stream.fromEvent(textarea, 'compositionend').pipe(stream.map(ev => {
1820
+ isCompositionEnd = true;
1806
1821
  ev.preventDefault();
1807
1822
  textarea.value = '';
1808
1823
  return ev.data;
@@ -1811,10 +1826,21 @@ exports.MagicInput = class MagicInput extends Input {
1811
1826
  this.isSougouPinYin = false;
1812
1827
  return !b;
1813
1828
  }))).subscribe(text => {
1829
+ var _a;
1814
1830
  this.composition = false;
1831
+ this.caret.compositionState = this.compositionState = null;
1832
+ (_a = this.caret.compositionElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.caret.compositionElement);
1815
1833
  if (text) {
1816
1834
  this.commander.write(text);
1817
1835
  }
1836
+ if (isCompositionEnd) {
1837
+ const startSlot = this.selection.startSlot;
1838
+ if (startSlot) {
1839
+ const event = new core.Event(startSlot, null);
1840
+ core.invokeListener(startSlot.parent, 'onCompositionEnd', event);
1841
+ }
1842
+ }
1843
+ isCompositionEnd = false;
1818
1844
  }));
1819
1845
  }
1820
1846
  createEditableFrame() {
@@ -1967,6 +1993,7 @@ exports.NativeInput = class NativeInput extends Input {
1967
1993
  this.controller = controller;
1968
1994
  this.caret = new NativeCaret(this.scheduler);
1969
1995
  this.composition = false;
1996
+ this.compositionState = null;
1970
1997
  this.onReady = Promise.resolve();
1971
1998
  this._disabled = false;
1972
1999
  this.nativeSelection = document.getSelection();
@@ -2109,17 +2136,40 @@ exports.NativeInput = class NativeInput extends Input {
2109
2136
  }));
2110
2137
  }
2111
2138
  handleInput(input) {
2139
+ let startIndex = 0;
2140
+ let isCompositionEnd = false;
2112
2141
  this.subscription.add(stream.fromEvent(input, 'compositionstart').subscribe(() => {
2113
2142
  this.composition = true;
2143
+ this.compositionState = null;
2144
+ startIndex = this.selection.startOffset;
2145
+ const startSlot = this.selection.startSlot;
2146
+ const event = new core.Event(startSlot, {
2147
+ index: startIndex
2148
+ });
2149
+ core.invokeListener(startSlot.parent, 'onCompositionStart', event);
2150
+ }), stream.fromEvent(input, 'compositionupdate').subscribe(ev => {
2151
+ const startSlot = this.selection.startSlot;
2152
+ this.compositionState = {
2153
+ slot: startSlot,
2154
+ index: startIndex,
2155
+ data: ev.data
2156
+ };
2157
+ const event = new core.Event(startSlot, {
2158
+ index: startIndex,
2159
+ data: ev.data
2160
+ });
2161
+ core.invokeListener(startSlot.parent, 'onCompositionUpdate', event);
2114
2162
  }), stream.merge(stream.fromEvent(input, 'beforeinput').pipe(stream.filter(ev => {
2115
2163
  ev.preventDefault();
2116
2164
  if (this.isSafari) {
2165
+ isCompositionEnd = ev.inputType === 'insertFromComposition';
2117
2166
  return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
2118
2167
  }
2119
2168
  return !ev.isComposing && !!ev.data;
2120
2169
  }), stream.map(ev => {
2121
2170
  return ev.data;
2122
2171
  })), this.isSafari ? new stream.Observable() : stream.fromEvent(input, 'compositionend').pipe(stream.map(ev => {
2172
+ isCompositionEnd = true;
2123
2173
  ev.preventDefault();
2124
2174
  return ev.data;
2125
2175
  }), stream.filter(() => {
@@ -2128,9 +2178,18 @@ exports.NativeInput = class NativeInput extends Input {
2128
2178
  return !b;
2129
2179
  }))).subscribe(text => {
2130
2180
  this.composition = false;
2181
+ this.compositionState = null;
2131
2182
  if (text) {
2132
2183
  this.commander.write(text);
2133
2184
  }
2185
+ if (isCompositionEnd) {
2186
+ const startSlot = this.selection.startSlot;
2187
+ if (startSlot) {
2188
+ const event = new core.Event(startSlot, null);
2189
+ core.invokeListener(startSlot.parent, 'onCompositionEnd', event);
2190
+ }
2191
+ }
2192
+ isCompositionEnd = false;
2134
2193
  }));
2135
2194
  }
2136
2195
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/platform-browser",
3
- "version": "3.0.0-alpha.58",
3
+ "version": "3.0.0-alpha.59",
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.57",
30
+ "@textbus/core": "^3.0.0-alpha.59",
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": "a4b64281a947ebc09ed3d6f5d357baef89493648"
51
+ "gitHead": "7b4fd0eb4680416ddf112c8cec1432ea51919d19"
52
52
  }