@textbus/platform-browser 4.0.0-alpha.1 → 4.0.0-alpha.11

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/README.md CHANGED
@@ -4,120 +4,6 @@ Textbus PC 浏览器支持模块
4
4
  Textbus 是一套用于构建富交互的富文本编辑框架。和大多数富文本编辑器不同的是,Textbus 以组件为核心,格式为辅助,并大幅简化了富文本编辑器开发中常见
5
5
  API,且提供了更高的抽象层,使 Textbus 不仅易于上手,同时还能驱动复杂的富文本应用。
6
6
 
7
- 本项目为 Textbus PC 端浏览器中间层实现,提供了 Textbus PC 端所需要的编辑器基本支持能力。如光标、选区桥接、DOM 解析及渲染能力桥接等。
8
-
9
- 如果你需要一个开箱即用的编辑器,请参考[官方文档](https://textbus.io)。
10
-
11
- ## 安装
12
-
13
- ```
14
- npm install @textbus/core @textbus/platform-browser
15
- ```
16
-
17
- ## 创建编辑器
18
-
19
- ```ts
20
- import { Viewer, ViewOptions } from '@textbus/browser'
21
-
22
- import { rootComponent, rootComponentLoader } from './root.component'
23
-
24
- const config: ViewOptions = {
25
- // ...配置项
26
- }
27
-
28
- const editor = new Viewer(rootComponent, rootComponentLoader, config)
29
- ```
30
-
31
- 其中 `rootComponent`,`rootComponentLoader` 实现请参考[官方文档](https://textbus.io/docs/guide)。
32
-
33
- ### 配置项
34
-
35
- 配置项接口如下:
36
-
37
- ```ts
38
- export interface ViewModule extends Module {
39
- componentLoaders?: ComponentLoader[]
40
- formatLoaders?: FormatLoader[]
41
- }
42
-
43
- /**
44
- * Textbus PC 端配置接口
45
- */
46
- export interface ViewOptions extends TextbusConfig {
47
- imports?: ViewModule[]
48
- /** 自动获取焦点 */
49
- autoFocus?: boolean
50
- /** 编辑区最小高度 */
51
- minHeight?: string
52
- /** 组件加载器 */
53
- componentLoaders?: ComponentLoader[]
54
- /** 格式加载器 */
55
- formatLoaders?: FormatLoader[]
56
- /** 默认内容 */
57
- content?: string | ComponentLiteral
58
- /** 文档默认样式表 */
59
- styleSheets?: string[]
60
- /** 配置文档编辑状态下用到的样式 */
61
- editingStyleSheets?: string[]
62
- }
63
- ```
64
-
65
- ### 启动
66
-
67
- ```ts
68
- const host = document.getElementById('editor')
69
-
70
- editor.mount(host).then(() => {
71
- console.log('编辑器创建成功!')
72
- })
73
- ```
74
-
75
- ### 销毁编辑器
76
-
77
- ```ts
78
- editor.destroy()
79
- ```
80
-
81
- ### 获取焦点
82
-
83
- ```ts
84
- editor.focus()
85
- ```
86
-
87
- ### 取消焦点
88
-
89
- ```ts
90
- editor.blur()
91
- ```
92
-
93
- ### 获取 HTML 内容
94
-
95
- ```ts
96
- const content = editor.getContents().content
97
- ```
98
-
99
- ### 获取 JSON 内容
100
-
101
- ```ts
102
- const json = editor.getJSON().content
103
- ```
104
-
105
- ### 替换内容
106
-
107
- ```ts
108
- editor.replaceContent('<p>新内容!</p>')
109
-
110
- editor.replaceContent({
111
- // 必须为 Textbus 导出的 JSON 格式
112
- })
113
- ```
114
-
115
- ### 清空编辑器
116
-
117
- ```ts
118
- editor.replaceContent('')
119
- ```
120
-
121
7
  ### 官方文档
122
8
 
123
9
  更多文档请参考:[中文文档](https://textbus.io)
@@ -1,5 +1,4 @@
1
- import { Injector } from '@viewfly/core';
2
- import { Selection, SelectionPaths, AbstractSelection, Scheduler } from '@textbus/core';
1
+ import { Selection, SelectionPaths, AbstractSelection, Scheduler, Textbus } from '@textbus/core';
3
2
  import { SelectionBridge } from './selection-bridge';
4
3
  import { Rect } from './_utils/uikit';
5
4
  /**
@@ -44,7 +43,7 @@ export declare class CollaborateCursor {
44
43
  private subscription;
45
44
  private currentSelection;
46
45
  private container;
47
- constructor(injector: Injector, nativeSelection: SelectionBridge, scheduler: Scheduler, selection: Selection, awarenessDelegate?: CollaborateSelectionAwarenessDelegate | undefined);
46
+ constructor(textbus: Textbus, nativeSelection: SelectionBridge, scheduler: Scheduler, selection: Selection, awarenessDelegate?: CollaborateSelectionAwarenessDelegate | undefined);
48
47
  /**
49
48
  * 刷新协作光标,由于 Textbus 只会绘制可视区域的光标,当可视区域发生变化时,需要重新绘制
50
49
  */
@@ -31,7 +31,7 @@ export declare abstract class DomAdapter<ViewComponent, ViewElement> extends Vie
31
31
  protected constructor(mount: (host: HTMLElement, viewComponent: ViewComponent) => (void | (() => void)));
32
32
  render(rootComponent: ComponentInstance): void | (() => void);
33
33
  abstract componentRender(component: ComponentInstance): ViewComponent;
34
- abstract slotRender(slot: Slot, slotHostRender: (children: Array<VElement | VTextNode | ComponentInstance>) => VElement): ViewElement;
34
+ abstract slotRender(slot: Slot, slotHostRender: (children: Array<VElement | VTextNode | ComponentInstance>) => VElement, renderEnv: any): ViewElement;
35
35
  copy(): void;
36
36
  /**
37
37
  * 根据组件获取组件的根 DOM 节点
@@ -1,7 +1,7 @@
1
1
  import 'reflect-metadata';
2
- import { Slot, ViewAdapter, createBidirectionalMapping, ComponentInstance, VElement, VTextNode, Controller, Selection, RootComponentRef, ContentType, Event, invokeListener, Keyboard, Commander, Scheduler, NativeSelectionBridge } from '@textbus/core';
3
- import { InjectionToken, Injectable, Inject, Injector, Optional } from '@viewfly/core';
2
+ import { Slot, Textbus, ViewAdapter, createBidirectionalMapping, ComponentInstance, VElement, VTextNode, Controller, Selection, RootComponentRef, ContentType, Event, invokeListener, Keyboard, Commander, Scheduler, NativeSelectionBridge, FocusManager } from '@textbus/core';
4
3
  import { Subject, filter, fromEvent, Subscription, distinctUntilChanged, merge, map, Observable } from '@tanbo/stream';
4
+ import { InjectionToken, Injectable, Inject, Optional } from '@viewfly/core';
5
5
 
6
6
  function createElement(tagName, options = {}) {
7
7
  const el = document.createElement(tagName);
@@ -166,9 +166,9 @@ let Parser = Parser_1 = class Parser {
166
166
  static parseHTML(html) {
167
167
  return new DOMParser().parseFromString(html, 'text/html').body;
168
168
  }
169
- constructor(options, injector) {
169
+ constructor(options, textbus) {
170
170
  this.options = options;
171
- this.injector = injector;
171
+ this.textbus = textbus;
172
172
  const componentLoaders = [
173
173
  ...(options.componentLoaders || [])
174
174
  ];
@@ -187,23 +187,23 @@ let Parser = Parser_1 = class Parser {
187
187
  this.attributeLoaders = attributeLoaders;
188
188
  }
189
189
  /**
190
- * 使用指定的组件加载器解析一段 HTML 字符串
190
+ * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素
191
191
  * @param html
192
192
  * @param rootComponentLoader
193
193
  */
194
194
  parseDoc(html, rootComponentLoader) {
195
- const element = Parser_1.parseHTML(html);
196
- return rootComponentLoader.read(element, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
195
+ const element = typeof html === 'string' ? Parser_1.parseHTML(html) : html;
196
+ return rootComponentLoader.read(element, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
197
197
  return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
198
198
  });
199
199
  }
200
200
  /**
201
- * 将一段 HTML 解析到指定插槽
201
+ * 将一段 HTML 或 DOM 元素解析到指定插槽
202
202
  * @param html
203
203
  * @param rootSlot
204
204
  */
205
205
  parse(html, rootSlot) {
206
- const element = Parser_1.parseHTML(html);
206
+ const element = typeof html === 'string' ? Parser_1.parseHTML(html) : html;
207
207
  return this.readFormats(element, rootSlot);
208
208
  }
209
209
  readComponent(el, slot) {
@@ -214,7 +214,7 @@ let Parser = Parser_1 = class Parser {
214
214
  }
215
215
  for (const t of this.componentLoaders) {
216
216
  if (t.match(el)) {
217
- const result = t.read(el, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
217
+ const result = t.read(el, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
218
218
  return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
219
219
  });
220
220
  if (!result) {
@@ -294,7 +294,7 @@ let Parser = Parser_1 = class Parser {
294
294
  Parser = Parser_1 = __decorate([
295
295
  Injectable(),
296
296
  __param(0, Inject(EDITOR_OPTIONS)),
297
- __metadata("design:paramtypes", [Object, Injector])
297
+ __metadata("design:paramtypes", [Object, Textbus])
298
298
  ], Parser);
299
299
 
300
300
  class Input {
@@ -449,7 +449,7 @@ class DomAdapter extends ViewAdapter {
449
449
  * Textbus PC 端选区桥接实现
450
450
  */
451
451
  let SelectionBridge = class SelectionBridge {
452
- constructor(config, injector, controller, selection, rootComponentRef, input, domAdapter) {
452
+ constructor(config, textbus, controller, selection, rootComponentRef, input, domAdapter) {
453
453
  this.config = config;
454
454
  this.selection = selection;
455
455
  this.rootComponentRef = rootComponentRef;
@@ -461,7 +461,7 @@ let SelectionBridge = class SelectionBridge {
461
461
  this.connector = null;
462
462
  this.ignoreSelectionChange = false;
463
463
  this.changeFromUser = false;
464
- this.docContainer = injector.get(VIEW_DOCUMENT);
464
+ this.docContainer = textbus.get(VIEW_DOCUMENT);
465
465
  this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {
466
466
  return !controller.readonly;
467
467
  }));
@@ -990,7 +990,7 @@ let SelectionBridge = class SelectionBridge {
990
990
  SelectionBridge = __decorate([
991
991
  Injectable(),
992
992
  __param(0, Inject(EDITOR_OPTIONS)),
993
- __metadata("design:paramtypes", [Object, Injector,
993
+ __metadata("design:paramtypes", [Object, Textbus,
994
994
  Controller,
995
995
  Selection,
996
996
  RootComponentRef,
@@ -1246,7 +1246,7 @@ let MagicInput = class MagicInput extends Input {
1246
1246
  get disabled() {
1247
1247
  return this._disabled;
1248
1248
  }
1249
- constructor(parser, keyboard, commander, selection, controller, scheduler, injector) {
1249
+ constructor(parser, keyboard, commander, selection, controller, scheduler, textbus) {
1250
1250
  super();
1251
1251
  this.parser = parser;
1252
1252
  this.keyboard = keyboard;
@@ -1254,10 +1254,10 @@ let MagicInput = class MagicInput extends Input {
1254
1254
  this.selection = selection;
1255
1255
  this.controller = controller;
1256
1256
  this.scheduler = scheduler;
1257
- this.injector = injector;
1257
+ this.textbus = textbus;
1258
1258
  this.composition = false;
1259
1259
  this.compositionState = null;
1260
- this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1260
+ this.caret = new ExperimentalCaret(this.scheduler, this.textbus.get(VIEW_MASK));
1261
1261
  this.isSafari = isSafari();
1262
1262
  this.isFirefox = isFirefox();
1263
1263
  this.isMac = isMac();
@@ -1388,17 +1388,14 @@ let MagicInput = class MagicInput extends Input {
1388
1388
  this.doc.body.appendChild(div);
1389
1389
  div.focus();
1390
1390
  setTimeout(() => {
1391
- let html = div.innerHTML;
1392
- if (!html && text && this.isFirefox) {
1393
- html = text;
1394
- }
1395
- this.handlePaste(html, text);
1396
1391
  this.doc.body.removeChild(div);
1392
+ div.style.cssText = '';
1393
+ this.handlePaste(div, text);
1397
1394
  });
1398
1395
  }));
1399
1396
  }
1400
- handlePaste(html, text) {
1401
- const slot = this.parser.parse(html, new Slot([
1397
+ handlePaste(dom, text) {
1398
+ const slot = this.parser.parse(dom, new Slot([
1402
1399
  ContentType.BlockComponent,
1403
1400
  ContentType.InlineComponent,
1404
1401
  ContentType.Text
@@ -1558,7 +1555,7 @@ MagicInput = __decorate([
1558
1555
  Selection,
1559
1556
  Controller,
1560
1557
  Scheduler,
1561
- Injector])
1558
+ Textbus])
1562
1559
  ], MagicInput);
1563
1560
 
1564
1561
  /**
@@ -1570,7 +1567,7 @@ class CollaborateSelectionAwarenessDelegate {
1570
1567
  * 协作光标绘制类
1571
1568
  */
1572
1569
  let CollaborateCursor = class CollaborateCursor {
1573
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate) {
1570
+ constructor(textbus, nativeSelection, scheduler, selection, awarenessDelegate) {
1574
1571
  this.nativeSelection = nativeSelection;
1575
1572
  this.scheduler = scheduler;
1576
1573
  this.selection = selection;
@@ -1623,7 +1620,7 @@ let CollaborateCursor = class CollaborateCursor {
1623
1620
  this.onRectsChange = new Subject();
1624
1621
  this.subscription = new Subscription();
1625
1622
  this.currentSelection = [];
1626
- this.container = injector.get(VIEW_CONTAINER);
1623
+ this.container = textbus.get(VIEW_CONTAINER);
1627
1624
  this.canvasContainer.append(this.canvas);
1628
1625
  this.host.append(this.canvasContainer, this.tooltips);
1629
1626
  this.container.prepend(this.host);
@@ -1815,7 +1812,7 @@ let CollaborateCursor = class CollaborateCursor {
1815
1812
  CollaborateCursor = __decorate([
1816
1813
  Injectable(),
1817
1814
  __param(4, Optional()),
1818
- __metadata("design:paramtypes", [Injector,
1815
+ __metadata("design:paramtypes", [Textbus,
1819
1816
  SelectionBridge,
1820
1817
  Scheduler,
1821
1818
  Selection,
@@ -1936,7 +1933,7 @@ let NativeInput = class NativeInput extends Input {
1936
1933
  get disabled() {
1937
1934
  return this._disabled;
1938
1935
  }
1939
- constructor(injector, parser, scheduler, selection, keyboard, domAdapter, commander, controller) {
1936
+ constructor(textbus, parser, scheduler, selection, keyboard, domAdapter, commander, controller) {
1940
1937
  super();
1941
1938
  this.parser = parser;
1942
1939
  this.scheduler = scheduler;
@@ -1957,7 +1954,7 @@ let NativeInput = class NativeInput extends Input {
1957
1954
  this.isMac = isMac();
1958
1955
  this.isMobileBrowser = isMobileBrowser();
1959
1956
  this.ignoreComposition = false; // 有 bug 版本搜狗拼音
1960
- this.documentView = injector.get(VIEW_DOCUMENT);
1957
+ this.documentView = textbus.get(VIEW_DOCUMENT);
1961
1958
  if (!controller.readonly) {
1962
1959
  this.documentView.contentEditable = 'true';
1963
1960
  }
@@ -2038,9 +2035,9 @@ let NativeInput = class NativeInput extends Input {
2038
2035
  document.body.appendChild(div);
2039
2036
  div.focus();
2040
2037
  setTimeout(() => {
2041
- const html = div.innerHTML;
2042
- this.handlePaste(html, text);
2043
2038
  document.body.removeChild(div);
2039
+ div.style.cssText = '';
2040
+ this.handlePaste(div, text);
2044
2041
  });
2045
2042
  }));
2046
2043
  }
@@ -2288,7 +2285,7 @@ let NativeInput = class NativeInput extends Input {
2288
2285
  };
2289
2286
  NativeInput = __decorate([
2290
2287
  Injectable(),
2291
- __metadata("design:paramtypes", [Injector,
2288
+ __metadata("design:paramtypes", [Textbus,
2292
2289
  Parser,
2293
2290
  Scheduler,
2294
2291
  Selection,
@@ -2334,11 +2331,29 @@ class BrowserModule {
2334
2331
  }, {
2335
2332
  provide: DomAdapter,
2336
2333
  useValue: config.adapter
2334
+ }, {
2335
+ provide: FocusManager,
2336
+ useFactory: (input) => {
2337
+ const focusEvent = new Subject();
2338
+ const blurEvent = new Subject();
2339
+ input.caret.onPositionChange.pipe(map(p => !!p), distinctUntilChanged()).subscribe(b => {
2340
+ if (b) {
2341
+ focusEvent.next();
2342
+ }
2343
+ else {
2344
+ blurEvent.next();
2345
+ }
2346
+ });
2347
+ return {
2348
+ onFocus: focusEvent,
2349
+ onBlur: blurEvent
2350
+ };
2351
+ },
2352
+ deps: [Input]
2337
2353
  },
2338
2354
  Parser,
2339
2355
  SelectionBridge,
2340
- CollaborateCursor
2341
- ];
2356
+ CollaborateCursor];
2342
2357
  this.workbench = wrapper;
2343
2358
  this.host.append(wrapper);
2344
2359
  }
package/bundles/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  require('reflect-metadata');
4
4
  var core$1 = require('@textbus/core');
5
- var core = require('@viewfly/core');
6
5
  var stream = require('@tanbo/stream');
6
+ var core = require('@viewfly/core');
7
7
 
8
8
  function createElement(tagName, options = {}) {
9
9
  const el = document.createElement(tagName);
@@ -168,9 +168,9 @@ exports.Parser = Parser_1 = class Parser {
168
168
  static parseHTML(html) {
169
169
  return new DOMParser().parseFromString(html, 'text/html').body;
170
170
  }
171
- constructor(options, injector) {
171
+ constructor(options, textbus) {
172
172
  this.options = options;
173
- this.injector = injector;
173
+ this.textbus = textbus;
174
174
  const componentLoaders = [
175
175
  ...(options.componentLoaders || [])
176
176
  ];
@@ -189,23 +189,23 @@ exports.Parser = Parser_1 = class Parser {
189
189
  this.attributeLoaders = attributeLoaders;
190
190
  }
191
191
  /**
192
- * 使用指定的组件加载器解析一段 HTML 字符串
192
+ * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素
193
193
  * @param html
194
194
  * @param rootComponentLoader
195
195
  */
196
196
  parseDoc(html, rootComponentLoader) {
197
- const element = Parser_1.parseHTML(html);
198
- return rootComponentLoader.read(element, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
197
+ const element = typeof html === 'string' ? Parser_1.parseHTML(html) : html;
198
+ return rootComponentLoader.read(element, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
199
199
  return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
200
200
  });
201
201
  }
202
202
  /**
203
- * 将一段 HTML 解析到指定插槽
203
+ * 将一段 HTML 或 DOM 元素解析到指定插槽
204
204
  * @param html
205
205
  * @param rootSlot
206
206
  */
207
207
  parse(html, rootSlot) {
208
- const element = Parser_1.parseHTML(html);
208
+ const element = typeof html === 'string' ? Parser_1.parseHTML(html) : html;
209
209
  return this.readFormats(element, rootSlot);
210
210
  }
211
211
  readComponent(el, slot) {
@@ -216,7 +216,7 @@ exports.Parser = Parser_1 = class Parser {
216
216
  }
217
217
  for (const t of this.componentLoaders) {
218
218
  if (t.match(el)) {
219
- const result = t.read(el, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
219
+ const result = t.read(el, this.textbus, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
220
220
  return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
221
221
  });
222
222
  if (!result) {
@@ -296,7 +296,7 @@ exports.Parser = Parser_1 = class Parser {
296
296
  exports.Parser = Parser_1 = __decorate([
297
297
  core.Injectable(),
298
298
  __param(0, core.Inject(EDITOR_OPTIONS)),
299
- __metadata("design:paramtypes", [Object, core.Injector])
299
+ __metadata("design:paramtypes", [Object, core$1.Textbus])
300
300
  ], exports.Parser);
301
301
 
302
302
  class Input {
@@ -451,7 +451,7 @@ class DomAdapter extends core$1.ViewAdapter {
451
451
  * Textbus PC 端选区桥接实现
452
452
  */
453
453
  exports.SelectionBridge = class SelectionBridge {
454
- constructor(config, injector, controller, selection, rootComponentRef, input, domAdapter) {
454
+ constructor(config, textbus, controller, selection, rootComponentRef, input, domAdapter) {
455
455
  this.config = config;
456
456
  this.selection = selection;
457
457
  this.rootComponentRef = rootComponentRef;
@@ -463,7 +463,7 @@ exports.SelectionBridge = class SelectionBridge {
463
463
  this.connector = null;
464
464
  this.ignoreSelectionChange = false;
465
465
  this.changeFromUser = false;
466
- this.docContainer = injector.get(VIEW_DOCUMENT);
466
+ this.docContainer = textbus.get(VIEW_DOCUMENT);
467
467
  this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(stream.filter(() => {
468
468
  return !controller.readonly;
469
469
  }));
@@ -992,7 +992,7 @@ exports.SelectionBridge = class SelectionBridge {
992
992
  exports.SelectionBridge = __decorate([
993
993
  core.Injectable(),
994
994
  __param(0, core.Inject(EDITOR_OPTIONS)),
995
- __metadata("design:paramtypes", [Object, core.Injector,
995
+ __metadata("design:paramtypes", [Object, core$1.Textbus,
996
996
  core$1.Controller,
997
997
  core$1.Selection,
998
998
  core$1.RootComponentRef,
@@ -1248,7 +1248,7 @@ exports.MagicInput = class MagicInput extends Input {
1248
1248
  get disabled() {
1249
1249
  return this._disabled;
1250
1250
  }
1251
- constructor(parser, keyboard, commander, selection, controller, scheduler, injector) {
1251
+ constructor(parser, keyboard, commander, selection, controller, scheduler, textbus) {
1252
1252
  super();
1253
1253
  this.parser = parser;
1254
1254
  this.keyboard = keyboard;
@@ -1256,10 +1256,10 @@ exports.MagicInput = class MagicInput extends Input {
1256
1256
  this.selection = selection;
1257
1257
  this.controller = controller;
1258
1258
  this.scheduler = scheduler;
1259
- this.injector = injector;
1259
+ this.textbus = textbus;
1260
1260
  this.composition = false;
1261
1261
  this.compositionState = null;
1262
- this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1262
+ this.caret = new ExperimentalCaret(this.scheduler, this.textbus.get(VIEW_MASK));
1263
1263
  this.isSafari = isSafari();
1264
1264
  this.isFirefox = isFirefox();
1265
1265
  this.isMac = isMac();
@@ -1390,17 +1390,14 @@ exports.MagicInput = class MagicInput extends Input {
1390
1390
  this.doc.body.appendChild(div);
1391
1391
  div.focus();
1392
1392
  setTimeout(() => {
1393
- let html = div.innerHTML;
1394
- if (!html && text && this.isFirefox) {
1395
- html = text;
1396
- }
1397
- this.handlePaste(html, text);
1398
1393
  this.doc.body.removeChild(div);
1394
+ div.style.cssText = '';
1395
+ this.handlePaste(div, text);
1399
1396
  });
1400
1397
  }));
1401
1398
  }
1402
- handlePaste(html, text) {
1403
- const slot = this.parser.parse(html, new core$1.Slot([
1399
+ handlePaste(dom, text) {
1400
+ const slot = this.parser.parse(dom, new core$1.Slot([
1404
1401
  core$1.ContentType.BlockComponent,
1405
1402
  core$1.ContentType.InlineComponent,
1406
1403
  core$1.ContentType.Text
@@ -1560,7 +1557,7 @@ exports.MagicInput = __decorate([
1560
1557
  core$1.Selection,
1561
1558
  core$1.Controller,
1562
1559
  core$1.Scheduler,
1563
- core.Injector])
1560
+ core$1.Textbus])
1564
1561
  ], exports.MagicInput);
1565
1562
 
1566
1563
  /**
@@ -1572,7 +1569,7 @@ class CollaborateSelectionAwarenessDelegate {
1572
1569
  * 协作光标绘制类
1573
1570
  */
1574
1571
  exports.CollaborateCursor = class CollaborateCursor {
1575
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate) {
1572
+ constructor(textbus, nativeSelection, scheduler, selection, awarenessDelegate) {
1576
1573
  this.nativeSelection = nativeSelection;
1577
1574
  this.scheduler = scheduler;
1578
1575
  this.selection = selection;
@@ -1625,7 +1622,7 @@ exports.CollaborateCursor = class CollaborateCursor {
1625
1622
  this.onRectsChange = new stream.Subject();
1626
1623
  this.subscription = new stream.Subscription();
1627
1624
  this.currentSelection = [];
1628
- this.container = injector.get(VIEW_CONTAINER);
1625
+ this.container = textbus.get(VIEW_CONTAINER);
1629
1626
  this.canvasContainer.append(this.canvas);
1630
1627
  this.host.append(this.canvasContainer, this.tooltips);
1631
1628
  this.container.prepend(this.host);
@@ -1817,7 +1814,7 @@ exports.CollaborateCursor = class CollaborateCursor {
1817
1814
  exports.CollaborateCursor = __decorate([
1818
1815
  core.Injectable(),
1819
1816
  __param(4, core.Optional()),
1820
- __metadata("design:paramtypes", [core.Injector,
1817
+ __metadata("design:paramtypes", [core$1.Textbus,
1821
1818
  exports.SelectionBridge,
1822
1819
  core$1.Scheduler,
1823
1820
  core$1.Selection,
@@ -1938,7 +1935,7 @@ let NativeInput = class NativeInput extends Input {
1938
1935
  get disabled() {
1939
1936
  return this._disabled;
1940
1937
  }
1941
- constructor(injector, parser, scheduler, selection, keyboard, domAdapter, commander, controller) {
1938
+ constructor(textbus, parser, scheduler, selection, keyboard, domAdapter, commander, controller) {
1942
1939
  super();
1943
1940
  this.parser = parser;
1944
1941
  this.scheduler = scheduler;
@@ -1959,7 +1956,7 @@ let NativeInput = class NativeInput extends Input {
1959
1956
  this.isMac = isMac();
1960
1957
  this.isMobileBrowser = isMobileBrowser();
1961
1958
  this.ignoreComposition = false; // 有 bug 版本搜狗拼音
1962
- this.documentView = injector.get(VIEW_DOCUMENT);
1959
+ this.documentView = textbus.get(VIEW_DOCUMENT);
1963
1960
  if (!controller.readonly) {
1964
1961
  this.documentView.contentEditable = 'true';
1965
1962
  }
@@ -2040,9 +2037,9 @@ let NativeInput = class NativeInput extends Input {
2040
2037
  document.body.appendChild(div);
2041
2038
  div.focus();
2042
2039
  setTimeout(() => {
2043
- const html = div.innerHTML;
2044
- this.handlePaste(html, text);
2045
2040
  document.body.removeChild(div);
2041
+ div.style.cssText = '';
2042
+ this.handlePaste(div, text);
2046
2043
  });
2047
2044
  }));
2048
2045
  }
@@ -2290,7 +2287,7 @@ let NativeInput = class NativeInput extends Input {
2290
2287
  };
2291
2288
  NativeInput = __decorate([
2292
2289
  core.Injectable(),
2293
- __metadata("design:paramtypes", [core.Injector,
2290
+ __metadata("design:paramtypes", [core$1.Textbus,
2294
2291
  exports.Parser,
2295
2292
  core$1.Scheduler,
2296
2293
  core$1.Selection,
@@ -2336,11 +2333,29 @@ class BrowserModule {
2336
2333
  }, {
2337
2334
  provide: DomAdapter,
2338
2335
  useValue: config.adapter
2336
+ }, {
2337
+ provide: core$1.FocusManager,
2338
+ useFactory: (input) => {
2339
+ const focusEvent = new stream.Subject();
2340
+ const blurEvent = new stream.Subject();
2341
+ input.caret.onPositionChange.pipe(stream.map(p => !!p), stream.distinctUntilChanged()).subscribe(b => {
2342
+ if (b) {
2343
+ focusEvent.next();
2344
+ }
2345
+ else {
2346
+ blurEvent.next();
2347
+ }
2348
+ });
2349
+ return {
2350
+ onFocus: focusEvent,
2351
+ onBlur: blurEvent
2352
+ };
2353
+ },
2354
+ deps: [Input]
2339
2355
  },
2340
2356
  exports.Parser,
2341
2357
  exports.SelectionBridge,
2342
- exports.CollaborateCursor
2343
- ];
2358
+ exports.CollaborateCursor];
2344
2359
  this.workbench = wrapper;
2345
2360
  this.host.append(wrapper);
2346
2361
  }
@@ -1,6 +1,5 @@
1
1
  import { Observable } from '@tanbo/stream';
2
- import { Injector } from '@viewfly/core';
3
- import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
2
+ import { Commander, Controller, Keyboard, Scheduler, Selection, Textbus } from '@textbus/core';
4
3
  import { Parser } from './parser';
5
4
  import { Caret, CaretPosition, CompositionState, Input, Scroller } from './types';
6
5
  interface CaretStyle {
@@ -48,7 +47,7 @@ export declare class MagicInput extends Input {
48
47
  private selection;
49
48
  private controller;
50
49
  private scheduler;
51
- private injector;
50
+ private textbus;
52
51
  composition: boolean;
53
52
  compositionState: CompositionState | null;
54
53
  onReady: Promise<void>;
@@ -67,7 +66,7 @@ export declare class MagicInput extends Input {
67
66
  private isFocus;
68
67
  private nativeFocus;
69
68
  private ignoreComposition;
70
- constructor(parser: Parser, keyboard: Keyboard, commander: Commander, selection: Selection, controller: Controller, scheduler: Scheduler, injector: Injector);
69
+ constructor(parser: Parser, keyboard: Keyboard, commander: Commander, selection: Selection, controller: Controller, scheduler: Scheduler, textbus: Textbus);
71
70
  focus(range: Range, restart: boolean): void;
72
71
  blur(): void;
73
72
  destroy(): void;
@@ -1,6 +1,5 @@
1
- import { Injector } from '@viewfly/core';
2
1
  import { Observable } from '@tanbo/stream';
3
- import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
2
+ import { Commander, Controller, Keyboard, Scheduler, Selection, Textbus } from '@textbus/core';
4
3
  import { Caret, CaretPosition, CompositionState, Input, Scroller } from './types';
5
4
  import { Parser } from './parser';
6
5
  import { DomAdapter } from './dom-adapter';
@@ -42,7 +41,7 @@ export declare class NativeInput extends Input {
42
41
  private isMac;
43
42
  private isMobileBrowser;
44
43
  private ignoreComposition;
45
- constructor(injector: Injector, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, domAdapter: DomAdapter<any, any>, commander: Commander, controller: Controller);
44
+ constructor(textbus: Textbus, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, domAdapter: DomAdapter<any, any>, commander: Commander, controller: Controller);
46
45
  focus(nativeRange: Range): void;
47
46
  blur(): void;
48
47
  destroy(): void;
@@ -1,5 +1,4 @@
1
- import { Injector } from '@viewfly/core';
2
- import { Attribute, ComponentInstance, Formatter, FormatValue, Slot } from '@textbus/core';
1
+ import { Attribute, ComponentInstance, Formatter, FormatValue, Slot, Textbus } from '@textbus/core';
3
2
  import { ViewOptions } from './browser-module';
4
3
  /**
5
4
  * 插槽解析器
@@ -21,16 +20,16 @@ export interface ComponentLoader {
21
20
  /** 识别组件的匹配方法 */
22
21
  match(element: HTMLElement): boolean;
23
22
  /** 读取组件内容的方法 */
24
- read(element: HTMLElement, injector: Injector, slotParser: SlotParser): ComponentInstance | Slot | void;
23
+ read(element: HTMLElement, textbus: Textbus, slotParser: SlotParser): ComponentInstance | Slot | void;
25
24
  }
26
- export interface FormatLoaderReadResult<T extends FormatValue> {
25
+ export interface FormatLoaderReadResult<T = FormatValue> {
27
26
  formatter: Formatter<T>;
28
27
  value: T;
29
28
  }
30
29
  /**
31
30
  * 格式加载器
32
31
  */
33
- export interface FormatLoader<T extends FormatValue> {
32
+ export interface FormatLoader<T = FormatValue> {
34
33
  /**
35
34
  * 匹配一个 DOM 节点是否是某个格式节点
36
35
  * @param element
@@ -42,14 +41,14 @@ export interface FormatLoader<T extends FormatValue> {
42
41
  */
43
42
  read(element: HTMLElement): FormatLoaderReadResult<T>;
44
43
  }
45
- export interface AttributeLoaderReadResult<T extends FormatValue> {
44
+ export interface AttributeLoaderReadResult<T = FormatValue> {
46
45
  attribute: Attribute<T>;
47
46
  value: T;
48
47
  }
49
48
  /**
50
49
  * 属性加载器
51
50
  */
52
- export interface AttributeLoader<T extends FormatValue> {
51
+ export interface AttributeLoader<T = FormatValue> {
53
52
  /**
54
53
  * 匹配一个 DOM 节点是否是某个属性节点
55
54
  * @param element
@@ -66,24 +65,24 @@ export interface AttributeLoader<T extends FormatValue> {
66
65
  */
67
66
  export declare class Parser {
68
67
  private options;
69
- private injector;
68
+ private textbus;
70
69
  static parseHTML(html: string): HTMLElement;
71
70
  componentLoaders: ComponentLoader[];
72
71
  formatLoaders: FormatLoader<any>[];
73
72
  attributeLoaders: AttributeLoader<any>[];
74
- constructor(options: ViewOptions, injector: Injector);
73
+ constructor(options: ViewOptions, textbus: Textbus);
75
74
  /**
76
- * 使用指定的组件加载器解析一段 HTML 字符串
75
+ * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素
77
76
  * @param html
78
77
  * @param rootComponentLoader
79
78
  */
80
- parseDoc(html: string, rootComponentLoader: ComponentLoader): void | Slot<any> | ComponentInstance<unknown, unknown, unknown>;
79
+ parseDoc(html: string | HTMLElement, rootComponentLoader: ComponentLoader): void | Slot<any> | ComponentInstance<unknown, unknown, unknown>;
81
80
  /**
82
- * 将一段 HTML 解析到指定插槽
81
+ * 将一段 HTML 或 DOM 元素解析到指定插槽
83
82
  * @param html
84
83
  * @param rootSlot
85
84
  */
86
- parse(html: string, rootSlot: Slot): Slot<any>;
85
+ parse(html: string | HTMLElement, rootSlot: Slot): Slot<any>;
87
86
  private readComponent;
88
87
  private readText;
89
88
  private readFormats;
@@ -1,6 +1,5 @@
1
1
  import { Observable } from '@tanbo/stream';
2
- import { Injector } from '@viewfly/core';
3
- import { NativeSelectionBridge, NativeSelectionConnector, SelectionPosition, AbstractSelection, RootComponentRef, Controller, Selection } from '@textbus/core';
2
+ import { NativeSelectionBridge, NativeSelectionConnector, SelectionPosition, AbstractSelection, RootComponentRef, Controller, Selection, Textbus } from '@textbus/core';
4
3
  import { Rect } from './_utils/uikit';
5
4
  import { Input } from './types';
6
5
  import { DomAdapter } from './dom-adapter';
@@ -25,7 +24,7 @@ export declare class SelectionBridge implements NativeSelectionBridge {
25
24
  private docContainer;
26
25
  private cacheCaretPositionTimer;
27
26
  private oldCaretPosition;
28
- constructor(config: ViewOptions, injector: Injector, controller: Controller, selection: Selection, rootComponentRef: RootComponentRef, input: Input, domAdapter: DomAdapter<any, any>);
27
+ constructor(config: ViewOptions, textbus: Textbus, controller: Controller, selection: Selection, rootComponentRef: RootComponentRef, input: Input, domAdapter: DomAdapter<any, any>);
29
28
  connect(connector: NativeSelectionConnector): void;
30
29
  disConnect(): void;
31
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.1",
3
+ "version": "4.0.0-alpha.11",
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.0",
29
- "@textbus/core": "^4.0.0-alpha.1",
30
- "@viewfly/core": "^0.2.0",
29
+ "@textbus/core": "^4.0.0-alpha.11",
30
+ "@viewfly/core": "^0.3.0",
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": "c66a476c5776f8cf719ebb0f9e7adebb391f82c1"
51
+ "gitHead": "8940269cbb7aaac5a5b0d9dc4936896ab210ed80"
52
52
  }