@textbus/collaborate 3.0.0-alpha.19 → 3.0.0-alpha.21

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,7 +1,6 @@
1
1
  import { Observable, Subject, Subscription } from '@tanbo/stream';
2
2
  import { ComponentInstance, Controller, Factory, History, RootComponentRef, Scheduler, Selection, SelectionPaths, Slot, Starter } from '@textbus/core';
3
3
  import { Array as YArray, Doc as YDoc, Map as YMap, RelativePosition, Text as YText, Transaction, UndoManager } from 'yjs';
4
- import { CollaborateCursor, RemoteSelection } from './collaborate-cursor';
5
4
  interface CursorPosition {
6
5
  anchor: RelativePosition;
7
6
  focus: RelativePosition;
@@ -22,13 +21,11 @@ interface UpdateItem {
22
21
  export declare class Collaborate implements History {
23
22
  protected stackSize: number;
24
23
  protected rootComponentRef: RootComponentRef;
25
- protected collaborateCursor: CollaborateCursor;
26
24
  protected controller: Controller;
27
25
  protected scheduler: Scheduler;
28
26
  protected factory: Factory;
29
27
  protected selection: Selection;
30
28
  protected starter: Starter;
31
- onSelectionChange: Observable<SelectionPaths>;
32
29
  yDoc: YDoc;
33
30
  onBack: Observable<void>;
34
31
  onForward: Observable<void>;
@@ -51,9 +48,8 @@ export declare class Collaborate implements History {
51
48
  protected contentMap: ContentMap;
52
49
  protected updateRemoteActions: Array<UpdateItem>;
53
50
  protected noRecord: {};
54
- constructor(stackSize: number, rootComponentRef: RootComponentRef, collaborateCursor: CollaborateCursor, controller: Controller, scheduler: Scheduler, factory: Factory, selection: Selection, starter: Starter);
51
+ constructor(stackSize: number, rootComponentRef: RootComponentRef, controller: Controller, scheduler: Scheduler, factory: Factory, selection: Selection, starter: Starter);
55
52
  listen(): void;
56
- updateRemoteSelection(paths: RemoteSelection[]): void;
57
53
  back(): void;
58
54
  forward(): void;
59
55
  clear(): void;
@@ -69,7 +65,7 @@ export declare class Collaborate implements History {
69
65
  protected runRemoteUpdate(tr: Transaction, fn: () => void): void;
70
66
  protected createSharedComponentByComponent(component: ComponentInstance): YMap<any>;
71
67
  protected createSharedSlotBySlot(slot: Slot): YMap<any>;
72
- protected createComponentBySharedComponent(yMap: YMap<any>, canInsertInlineComponent: boolean): ComponentInstance;
68
+ protected createComponentBySharedComponent(yMap: YMap<any>): ComponentInstance;
73
69
  protected createSlotBySharedSlot(sharedSlot: YMap<any>): Slot;
74
70
  protected cleanSubscriptionsBySlot(slot: Slot): void;
75
71
  protected cleanSubscriptionsByComponent(component: ComponentInstance): void;
@@ -1,10 +1,9 @@
1
- import { Scheduler, Selection, defineComponent, ContentType, VElement, makeError, HISTORY_STACK_SIZE, ChangeOrigin, Slot, RootComponentRef, Controller, Factory, Starter, History } from '@textbus/core';
2
- import { Injectable, Optional, Injector, Inject } from '@tanbo/di';
3
- import { Subject, Subscription, fromEvent, delay, map, filter } from '@tanbo/stream';
1
+ import { makeError, HISTORY_STACK_SIZE, ChangeOrigin, Slot, RootComponentRef, Controller, Scheduler, Factory, Selection, Starter, History } from '@textbus/core';
2
+ import { Injectable, Inject } from '@tanbo/di';
3
+ import { Subject, map, filter } from '@tanbo/stream';
4
4
  import { Doc, UndoManager, Array, createAbsolutePositionFromRelativePosition, createRelativePositionFromTypeIndex, Map, Text } from 'yjs';
5
- import { createElement, VIEW_CONTAINER, getLayoutRectByRange, SelectionBridge } from '@textbus/browser';
6
5
 
7
- /*! *****************************************************************************
6
+ /******************************************************************************
8
7
  Copyright (c) Microsoft Corporation.
9
8
 
10
9
  Permission to use, copy, modify, and/or distribute this software for any
@@ -34,282 +33,6 @@ function __metadata(metadataKey, metadataValue) {
34
33
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
35
34
  }
36
35
 
37
- class CollaborateSelectionAwarenessDelegate {
38
- }
39
- let CollaborateCursor = class CollaborateCursor {
40
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate = null) {
41
- this.injector = injector;
42
- this.nativeSelection = nativeSelection;
43
- this.scheduler = scheduler;
44
- this.selection = selection;
45
- this.awarenessDelegate = awarenessDelegate;
46
- this.host = createElement('div', {
47
- styles: {
48
- position: 'absolute',
49
- left: 0,
50
- top: 0,
51
- width: '100%',
52
- height: '100%',
53
- pointerEvents: 'none',
54
- zIndex: 1
55
- }
56
- });
57
- this.canvasContainer = createElement('div', {
58
- styles: {
59
- position: 'absolute',
60
- left: 0,
61
- top: 0,
62
- width: '100%',
63
- height: '100%',
64
- overflow: 'hidden'
65
- }
66
- });
67
- this.canvas = createElement('canvas', {
68
- styles: {
69
- position: 'absolute',
70
- opacity: 0.5,
71
- left: 0,
72
- top: 0,
73
- width: '100%',
74
- height: document.documentElement.clientHeight + 'px',
75
- pointerEvents: 'none',
76
- }
77
- });
78
- this.context = this.canvas.getContext('2d');
79
- this.tooltips = createElement('div', {
80
- styles: {
81
- position: 'absolute',
82
- left: 0,
83
- top: 0,
84
- width: '100%',
85
- height: '100%',
86
- pointerEvents: 'none',
87
- fontSize: '12px',
88
- zIndex: 10
89
- }
90
- });
91
- this.onRectsChange = new Subject();
92
- this.subscription = new Subscription();
93
- this.currentSelection = [];
94
- this.container = injector.get(VIEW_CONTAINER);
95
- this.canvasContainer.append(this.canvas);
96
- this.host.append(this.canvasContainer, this.tooltips);
97
- this.container.prepend(this.host);
98
- this.subscription.add(this.onRectsChange.subscribe(rects => {
99
- for (const rect of rects) {
100
- this.context.fillStyle = rect.color;
101
- this.context.beginPath();
102
- this.context.rect(rect.left, rect.top, rect.width, rect.height);
103
- this.context.fill();
104
- this.context.closePath();
105
- }
106
- }), fromEvent(window, 'resize').subscribe(() => {
107
- this.canvas.style.height = document.documentElement.clientHeight + 'px';
108
- this.refresh();
109
- }), this.scheduler.onDocChanged.subscribe(() => {
110
- this.refresh();
111
- }));
112
- }
113
- refresh() {
114
- this.draw(this.currentSelection);
115
- }
116
- destroy() {
117
- this.subscription.unsubscribe();
118
- }
119
- draw(paths) {
120
- this.currentSelection = paths;
121
- const containerRect = this.container.getBoundingClientRect();
122
- this.canvas.style.top = containerRect.top * -1 + 'px';
123
- this.canvas.width = this.canvas.offsetWidth;
124
- this.canvas.height = this.canvas.offsetHeight;
125
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
126
- const users = [];
127
- paths.filter(i => {
128
- return i.paths.anchor.length && i.paths.focus.length;
129
- }).forEach(item => {
130
- const anchorPaths = [...item.paths.anchor];
131
- const focusPaths = [...item.paths.focus];
132
- const anchorOffset = anchorPaths.pop();
133
- const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
134
- const focusOffset = focusPaths.pop();
135
- const focusSlot = this.selection.findSlotByPaths(focusPaths);
136
- if (!anchorSlot || !focusSlot) {
137
- return;
138
- }
139
- const { focus, anchor } = this.nativeSelection.getPositionByRange({
140
- focusOffset,
141
- anchorOffset,
142
- focusSlot,
143
- anchorSlot
144
- });
145
- if (!focus || !anchor) {
146
- return;
147
- }
148
- const nativeRange = document.createRange();
149
- nativeRange.setStart(anchor.node, anchor.offset);
150
- nativeRange.setEnd(focus.node, focus.offset);
151
- if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
152
- nativeRange.setStart(focus.node, focus.offset);
153
- nativeRange.setEnd(anchor.node, anchor.offset);
154
- }
155
- let rects = false;
156
- if (this.awarenessDelegate) {
157
- rects = this.awarenessDelegate.getRects({
158
- focusOffset,
159
- anchorOffset,
160
- focusSlot,
161
- anchorSlot
162
- }, nativeRange);
163
- }
164
- if (!rects) {
165
- rects = nativeRange.getClientRects();
166
- }
167
- const selectionRects = [];
168
- for (let i = rects.length - 1; i >= 0; i--) {
169
- const rect = rects[i];
170
- selectionRects.push({
171
- id: item.id,
172
- color: item.color,
173
- username: item.username,
174
- left: rect.left - containerRect.left,
175
- top: rect.top,
176
- width: rect.width,
177
- height: rect.height,
178
- });
179
- }
180
- this.onRectsChange.next(selectionRects);
181
- const cursorRange = nativeRange.cloneRange();
182
- cursorRange.setStart(focus.node, focus.offset);
183
- cursorRange.collapse(true);
184
- const cursorRect = getLayoutRectByRange(cursorRange);
185
- const rect = {
186
- id: item.id,
187
- username: item.username,
188
- color: item.color,
189
- left: cursorRect.left - containerRect.left,
190
- top: cursorRect.top - containerRect.top,
191
- width: 2,
192
- height: cursorRect.height
193
- };
194
- if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {
195
- return;
196
- }
197
- users.push(rect);
198
- });
199
- this.drawUserCursor(users);
200
- }
201
- drawUserCursor(rects) {
202
- for (let i = 0; i < rects.length; i++) {
203
- const rect = rects[i];
204
- const { cursor, userTip, anchor } = this.getUserCursor(i);
205
- Object.assign(cursor.style, {
206
- left: rect.left + 'px',
207
- top: rect.top + 'px',
208
- width: rect.width + 'px',
209
- height: rect.height + 'px',
210
- background: rect.color,
211
- display: 'block'
212
- });
213
- anchor.style.background = rect.color;
214
- userTip.innerText = rect.username;
215
- userTip.style.background = rect.color;
216
- }
217
- for (let i = rects.length; i < this.tooltips.children.length; i++) {
218
- this.tooltips.removeChild(this.tooltips.children[i]);
219
- }
220
- }
221
- getUserCursor(index) {
222
- let child = this.tooltips.children[index];
223
- if (child) {
224
- const anchor = child.children[0];
225
- return {
226
- cursor: child,
227
- anchor,
228
- userTip: anchor.children[0]
229
- };
230
- }
231
- const userTip = createElement('span', {
232
- styles: {
233
- position: 'absolute',
234
- display: 'none',
235
- left: '50%',
236
- transform: 'translateX(-50%)',
237
- marginBottom: '2px',
238
- bottom: '100%',
239
- whiteSpace: 'nowrap',
240
- color: '#fff',
241
- boxShadow: '0 1px 2px rgba(0,0,0,.1)',
242
- borderRadius: '3px',
243
- padding: '3px 5px',
244
- pointerEvents: 'none',
245
- }
246
- });
247
- const anchor = createElement('span', {
248
- styles: {
249
- position: 'absolute',
250
- top: '-2px',
251
- left: '-2px',
252
- width: '6px',
253
- height: '6px',
254
- pointerEvents: 'auto',
255
- pointer: 'cursor',
256
- },
257
- children: [userTip],
258
- on: {
259
- mouseenter() {
260
- userTip.style.display = 'block';
261
- },
262
- mouseleave() {
263
- userTip.style.display = 'none';
264
- }
265
- }
266
- });
267
- child = createElement('span', {
268
- styles: {
269
- position: 'absolute',
270
- },
271
- children: [
272
- anchor
273
- ]
274
- });
275
- this.tooltips.append(child);
276
- return {
277
- cursor: child,
278
- anchor,
279
- userTip
280
- };
281
- }
282
- };
283
- CollaborateCursor = __decorate([
284
- Injectable(),
285
- __param(4, Optional()),
286
- __metadata("design:paramtypes", [Injector,
287
- SelectionBridge,
288
- Scheduler,
289
- Selection, Object])
290
- ], CollaborateCursor);
291
-
292
- function createUnknownComponent(factoryName, canInsertInlineComponent) {
293
- const unknownComponent = defineComponent({
294
- type: canInsertInlineComponent ? ContentType.InlineComponent : ContentType.BlockComponent,
295
- name: 'UnknownComponent',
296
- setup() {
297
- console.error(`cannot find component factory \`${factoryName}\`.`);
298
- return {
299
- render() {
300
- return VElement.createElement('textbus-unknown-component', {
301
- style: {
302
- display: canInsertInlineComponent ? 'inline' : 'block',
303
- color: '#f00'
304
- }
305
- }, unknownComponent.name);
306
- }
307
- };
308
- }
309
- });
310
- return unknownComponent;
311
- }
312
-
313
36
  const collaborateErrorFn = makeError('Collaborate');
314
37
  class ContentMap {
315
38
  constructor() {
@@ -350,10 +73,9 @@ class ContentMap {
350
73
  }
351
74
  }
352
75
  let Collaborate = class Collaborate {
353
- constructor(stackSize, rootComponentRef, collaborateCursor, controller, scheduler, factory, selection, starter) {
76
+ constructor(stackSize, rootComponentRef, controller, scheduler, factory, selection, starter) {
354
77
  this.stackSize = stackSize;
355
78
  this.rootComponentRef = rootComponentRef;
356
- this.collaborateCursor = collaborateCursor;
357
79
  this.controller = controller;
358
80
  this.scheduler = scheduler;
359
81
  this.factory = factory;
@@ -375,7 +97,6 @@ let Collaborate = class Collaborate {
375
97
  this.contentMap = new ContentMap();
376
98
  this.updateRemoteActions = [];
377
99
  this.noRecord = {};
378
- this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(delay());
379
100
  this.onBack = this.backEvent.asObservable();
380
101
  this.onForward = this.forwardEvent.asObservable();
381
102
  this.onChange = this.changeEvent.asObservable();
@@ -454,9 +175,6 @@ let Collaborate = class Collaborate {
454
175
  }));
455
176
  this.syncRootComponent(root, rootComponent);
456
177
  }
457
- updateRemoteSelection(paths) {
458
- this.collaborateCursor.draw(paths);
459
- }
460
178
  back() {
461
179
  var _a;
462
180
  if (this.canBack) {
@@ -479,7 +197,6 @@ let Collaborate = class Collaborate {
479
197
  destroy() {
480
198
  var _a;
481
199
  this.subscriptions.forEach(i => i.unsubscribe());
482
- this.collaborateCursor.destroy();
483
200
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
484
201
  }
485
202
  syncRootComponent(root, rootComponent) {
@@ -600,8 +317,7 @@ let Collaborate = class Collaborate {
600
317
  }
601
318
  else {
602
319
  const sharedComponent = action.insert;
603
- const canInsertInlineComponent = slot.schema.includes(ContentType.InlineComponent);
604
- const component = this.createComponentBySharedComponent(sharedComponent, canInsertInlineComponent);
320
+ const component = this.createComponentBySharedComponent(sharedComponent);
605
321
  this.syncComponentSlots(sharedComponent.get('slots'), component);
606
322
  this.syncComponentState(sharedComponent, component);
607
323
  slot.insert(component);
@@ -895,7 +611,7 @@ let Collaborate = class Collaborate {
895
611
  this.syncSlotState(sharedSlot, slot);
896
612
  return sharedSlot;
897
613
  }
898
- createComponentBySharedComponent(yMap, canInsertInlineComponent) {
614
+ createComponentBySharedComponent(yMap) {
899
615
  const sharedSlots = yMap.get('slots');
900
616
  const slots = [];
901
617
  sharedSlots.forEach(sharedSlot => {
@@ -920,7 +636,7 @@ let Collaborate = class Collaborate {
920
636
  });
921
637
  return instance;
922
638
  }
923
- return createUnknownComponent(name, canInsertInlineComponent).createInstance(this.starter);
639
+ throw collaborateErrorFn(`cannot find component factory \`${name}\`.`);
924
640
  }
925
641
  createSlotBySharedSlot(sharedSlot) {
926
642
  const content = sharedSlot.get('content');
@@ -947,8 +663,7 @@ let Collaborate = class Collaborate {
947
663
  }
948
664
  else {
949
665
  const sharedComponent = action.insert;
950
- const canInsertInlineComponent = slot.schema.includes(ContentType.InlineComponent);
951
- const component = this.createComponentBySharedComponent(sharedComponent, canInsertInlineComponent);
666
+ const component = this.createComponentBySharedComponent(sharedComponent);
952
667
  slot.insert(component, remoteFormatsToLocal(this.factory, action.attributes));
953
668
  this.syncComponentSlots(sharedComponent.get('slots'), component);
954
669
  this.syncComponentState(sharedComponent, component);
@@ -988,7 +703,6 @@ Collaborate = __decorate([
988
703
  Injectable(),
989
704
  __param(0, Inject(HISTORY_STACK_SIZE)),
990
705
  __metadata("design:paramtypes", [Number, RootComponentRef,
991
- CollaborateCursor,
992
706
  Controller,
993
707
  Scheduler,
994
708
  Factory,
@@ -1011,7 +725,6 @@ function remoteFormatsToLocal(factory, attrs) {
1011
725
  const collaborateModule = {
1012
726
  providers: [
1013
727
  Collaborate,
1014
- CollaborateCursor,
1015
728
  {
1016
729
  provide: History,
1017
730
  useClass: Collaborate
@@ -1019,4 +732,4 @@ const collaborateModule = {
1019
732
  ]
1020
733
  };
1021
734
 
1022
- export { Collaborate, CollaborateCursor, CollaborateSelectionAwarenessDelegate, collaborateModule };
735
+ export { Collaborate, collaborateModule };
package/bundles/index.js CHANGED
@@ -4,9 +4,8 @@ var core = require('@textbus/core');
4
4
  var di = require('@tanbo/di');
5
5
  var stream = require('@tanbo/stream');
6
6
  var yjs = require('yjs');
7
- var browser = require('@textbus/browser');
8
7
 
9
- /*! *****************************************************************************
8
+ /******************************************************************************
10
9
  Copyright (c) Microsoft Corporation.
11
10
 
12
11
  Permission to use, copy, modify, and/or distribute this software for any
@@ -36,282 +35,6 @@ function __metadata(metadataKey, metadataValue) {
36
35
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
37
36
  }
38
37
 
39
- class CollaborateSelectionAwarenessDelegate {
40
- }
41
- exports.CollaborateCursor = class CollaborateCursor {
42
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate = null) {
43
- this.injector = injector;
44
- this.nativeSelection = nativeSelection;
45
- this.scheduler = scheduler;
46
- this.selection = selection;
47
- this.awarenessDelegate = awarenessDelegate;
48
- this.host = browser.createElement('div', {
49
- styles: {
50
- position: 'absolute',
51
- left: 0,
52
- top: 0,
53
- width: '100%',
54
- height: '100%',
55
- pointerEvents: 'none',
56
- zIndex: 1
57
- }
58
- });
59
- this.canvasContainer = browser.createElement('div', {
60
- styles: {
61
- position: 'absolute',
62
- left: 0,
63
- top: 0,
64
- width: '100%',
65
- height: '100%',
66
- overflow: 'hidden'
67
- }
68
- });
69
- this.canvas = browser.createElement('canvas', {
70
- styles: {
71
- position: 'absolute',
72
- opacity: 0.5,
73
- left: 0,
74
- top: 0,
75
- width: '100%',
76
- height: document.documentElement.clientHeight + 'px',
77
- pointerEvents: 'none',
78
- }
79
- });
80
- this.context = this.canvas.getContext('2d');
81
- this.tooltips = browser.createElement('div', {
82
- styles: {
83
- position: 'absolute',
84
- left: 0,
85
- top: 0,
86
- width: '100%',
87
- height: '100%',
88
- pointerEvents: 'none',
89
- fontSize: '12px',
90
- zIndex: 10
91
- }
92
- });
93
- this.onRectsChange = new stream.Subject();
94
- this.subscription = new stream.Subscription();
95
- this.currentSelection = [];
96
- this.container = injector.get(browser.VIEW_CONTAINER);
97
- this.canvasContainer.append(this.canvas);
98
- this.host.append(this.canvasContainer, this.tooltips);
99
- this.container.prepend(this.host);
100
- this.subscription.add(this.onRectsChange.subscribe(rects => {
101
- for (const rect of rects) {
102
- this.context.fillStyle = rect.color;
103
- this.context.beginPath();
104
- this.context.rect(rect.left, rect.top, rect.width, rect.height);
105
- this.context.fill();
106
- this.context.closePath();
107
- }
108
- }), stream.fromEvent(window, 'resize').subscribe(() => {
109
- this.canvas.style.height = document.documentElement.clientHeight + 'px';
110
- this.refresh();
111
- }), this.scheduler.onDocChanged.subscribe(() => {
112
- this.refresh();
113
- }));
114
- }
115
- refresh() {
116
- this.draw(this.currentSelection);
117
- }
118
- destroy() {
119
- this.subscription.unsubscribe();
120
- }
121
- draw(paths) {
122
- this.currentSelection = paths;
123
- const containerRect = this.container.getBoundingClientRect();
124
- this.canvas.style.top = containerRect.top * -1 + 'px';
125
- this.canvas.width = this.canvas.offsetWidth;
126
- this.canvas.height = this.canvas.offsetHeight;
127
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
128
- const users = [];
129
- paths.filter(i => {
130
- return i.paths.anchor.length && i.paths.focus.length;
131
- }).forEach(item => {
132
- const anchorPaths = [...item.paths.anchor];
133
- const focusPaths = [...item.paths.focus];
134
- const anchorOffset = anchorPaths.pop();
135
- const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
136
- const focusOffset = focusPaths.pop();
137
- const focusSlot = this.selection.findSlotByPaths(focusPaths);
138
- if (!anchorSlot || !focusSlot) {
139
- return;
140
- }
141
- const { focus, anchor } = this.nativeSelection.getPositionByRange({
142
- focusOffset,
143
- anchorOffset,
144
- focusSlot,
145
- anchorSlot
146
- });
147
- if (!focus || !anchor) {
148
- return;
149
- }
150
- const nativeRange = document.createRange();
151
- nativeRange.setStart(anchor.node, anchor.offset);
152
- nativeRange.setEnd(focus.node, focus.offset);
153
- if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
154
- nativeRange.setStart(focus.node, focus.offset);
155
- nativeRange.setEnd(anchor.node, anchor.offset);
156
- }
157
- let rects = false;
158
- if (this.awarenessDelegate) {
159
- rects = this.awarenessDelegate.getRects({
160
- focusOffset,
161
- anchorOffset,
162
- focusSlot,
163
- anchorSlot
164
- }, nativeRange);
165
- }
166
- if (!rects) {
167
- rects = nativeRange.getClientRects();
168
- }
169
- const selectionRects = [];
170
- for (let i = rects.length - 1; i >= 0; i--) {
171
- const rect = rects[i];
172
- selectionRects.push({
173
- id: item.id,
174
- color: item.color,
175
- username: item.username,
176
- left: rect.left - containerRect.left,
177
- top: rect.top,
178
- width: rect.width,
179
- height: rect.height,
180
- });
181
- }
182
- this.onRectsChange.next(selectionRects);
183
- const cursorRange = nativeRange.cloneRange();
184
- cursorRange.setStart(focus.node, focus.offset);
185
- cursorRange.collapse(true);
186
- const cursorRect = browser.getLayoutRectByRange(cursorRange);
187
- const rect = {
188
- id: item.id,
189
- username: item.username,
190
- color: item.color,
191
- left: cursorRect.left - containerRect.left,
192
- top: cursorRect.top - containerRect.top,
193
- width: 2,
194
- height: cursorRect.height
195
- };
196
- if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {
197
- return;
198
- }
199
- users.push(rect);
200
- });
201
- this.drawUserCursor(users);
202
- }
203
- drawUserCursor(rects) {
204
- for (let i = 0; i < rects.length; i++) {
205
- const rect = rects[i];
206
- const { cursor, userTip, anchor } = this.getUserCursor(i);
207
- Object.assign(cursor.style, {
208
- left: rect.left + 'px',
209
- top: rect.top + 'px',
210
- width: rect.width + 'px',
211
- height: rect.height + 'px',
212
- background: rect.color,
213
- display: 'block'
214
- });
215
- anchor.style.background = rect.color;
216
- userTip.innerText = rect.username;
217
- userTip.style.background = rect.color;
218
- }
219
- for (let i = rects.length; i < this.tooltips.children.length; i++) {
220
- this.tooltips.removeChild(this.tooltips.children[i]);
221
- }
222
- }
223
- getUserCursor(index) {
224
- let child = this.tooltips.children[index];
225
- if (child) {
226
- const anchor = child.children[0];
227
- return {
228
- cursor: child,
229
- anchor,
230
- userTip: anchor.children[0]
231
- };
232
- }
233
- const userTip = browser.createElement('span', {
234
- styles: {
235
- position: 'absolute',
236
- display: 'none',
237
- left: '50%',
238
- transform: 'translateX(-50%)',
239
- marginBottom: '2px',
240
- bottom: '100%',
241
- whiteSpace: 'nowrap',
242
- color: '#fff',
243
- boxShadow: '0 1px 2px rgba(0,0,0,.1)',
244
- borderRadius: '3px',
245
- padding: '3px 5px',
246
- pointerEvents: 'none',
247
- }
248
- });
249
- const anchor = browser.createElement('span', {
250
- styles: {
251
- position: 'absolute',
252
- top: '-2px',
253
- left: '-2px',
254
- width: '6px',
255
- height: '6px',
256
- pointerEvents: 'auto',
257
- pointer: 'cursor',
258
- },
259
- children: [userTip],
260
- on: {
261
- mouseenter() {
262
- userTip.style.display = 'block';
263
- },
264
- mouseleave() {
265
- userTip.style.display = 'none';
266
- }
267
- }
268
- });
269
- child = browser.createElement('span', {
270
- styles: {
271
- position: 'absolute',
272
- },
273
- children: [
274
- anchor
275
- ]
276
- });
277
- this.tooltips.append(child);
278
- return {
279
- cursor: child,
280
- anchor,
281
- userTip
282
- };
283
- }
284
- };
285
- exports.CollaborateCursor = __decorate([
286
- di.Injectable(),
287
- __param(4, di.Optional()),
288
- __metadata("design:paramtypes", [di.Injector,
289
- browser.SelectionBridge,
290
- core.Scheduler,
291
- core.Selection, Object])
292
- ], exports.CollaborateCursor);
293
-
294
- function createUnknownComponent(factoryName, canInsertInlineComponent) {
295
- const unknownComponent = core.defineComponent({
296
- type: canInsertInlineComponent ? core.ContentType.InlineComponent : core.ContentType.BlockComponent,
297
- name: 'UnknownComponent',
298
- setup() {
299
- console.error(`cannot find component factory \`${factoryName}\`.`);
300
- return {
301
- render() {
302
- return core.VElement.createElement('textbus-unknown-component', {
303
- style: {
304
- display: canInsertInlineComponent ? 'inline' : 'block',
305
- color: '#f00'
306
- }
307
- }, unknownComponent.name);
308
- }
309
- };
310
- }
311
- });
312
- return unknownComponent;
313
- }
314
-
315
38
  const collaborateErrorFn = core.makeError('Collaborate');
316
39
  class ContentMap {
317
40
  constructor() {
@@ -352,10 +75,9 @@ class ContentMap {
352
75
  }
353
76
  }
354
77
  exports.Collaborate = class Collaborate {
355
- constructor(stackSize, rootComponentRef, collaborateCursor, controller, scheduler, factory, selection, starter) {
78
+ constructor(stackSize, rootComponentRef, controller, scheduler, factory, selection, starter) {
356
79
  this.stackSize = stackSize;
357
80
  this.rootComponentRef = rootComponentRef;
358
- this.collaborateCursor = collaborateCursor;
359
81
  this.controller = controller;
360
82
  this.scheduler = scheduler;
361
83
  this.factory = factory;
@@ -377,7 +99,6 @@ exports.Collaborate = class Collaborate {
377
99
  this.contentMap = new ContentMap();
378
100
  this.updateRemoteActions = [];
379
101
  this.noRecord = {};
380
- this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(stream.delay());
381
102
  this.onBack = this.backEvent.asObservable();
382
103
  this.onForward = this.forwardEvent.asObservable();
383
104
  this.onChange = this.changeEvent.asObservable();
@@ -456,9 +177,6 @@ exports.Collaborate = class Collaborate {
456
177
  }));
457
178
  this.syncRootComponent(root, rootComponent);
458
179
  }
459
- updateRemoteSelection(paths) {
460
- this.collaborateCursor.draw(paths);
461
- }
462
180
  back() {
463
181
  var _a;
464
182
  if (this.canBack) {
@@ -481,7 +199,6 @@ exports.Collaborate = class Collaborate {
481
199
  destroy() {
482
200
  var _a;
483
201
  this.subscriptions.forEach(i => i.unsubscribe());
484
- this.collaborateCursor.destroy();
485
202
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
486
203
  }
487
204
  syncRootComponent(root, rootComponent) {
@@ -602,8 +319,7 @@ exports.Collaborate = class Collaborate {
602
319
  }
603
320
  else {
604
321
  const sharedComponent = action.insert;
605
- const canInsertInlineComponent = slot.schema.includes(core.ContentType.InlineComponent);
606
- const component = this.createComponentBySharedComponent(sharedComponent, canInsertInlineComponent);
322
+ const component = this.createComponentBySharedComponent(sharedComponent);
607
323
  this.syncComponentSlots(sharedComponent.get('slots'), component);
608
324
  this.syncComponentState(sharedComponent, component);
609
325
  slot.insert(component);
@@ -897,7 +613,7 @@ exports.Collaborate = class Collaborate {
897
613
  this.syncSlotState(sharedSlot, slot);
898
614
  return sharedSlot;
899
615
  }
900
- createComponentBySharedComponent(yMap, canInsertInlineComponent) {
616
+ createComponentBySharedComponent(yMap) {
901
617
  const sharedSlots = yMap.get('slots');
902
618
  const slots = [];
903
619
  sharedSlots.forEach(sharedSlot => {
@@ -922,7 +638,7 @@ exports.Collaborate = class Collaborate {
922
638
  });
923
639
  return instance;
924
640
  }
925
- return createUnknownComponent(name, canInsertInlineComponent).createInstance(this.starter);
641
+ throw collaborateErrorFn(`cannot find component factory \`${name}\`.`);
926
642
  }
927
643
  createSlotBySharedSlot(sharedSlot) {
928
644
  const content = sharedSlot.get('content');
@@ -949,8 +665,7 @@ exports.Collaborate = class Collaborate {
949
665
  }
950
666
  else {
951
667
  const sharedComponent = action.insert;
952
- const canInsertInlineComponent = slot.schema.includes(core.ContentType.InlineComponent);
953
- const component = this.createComponentBySharedComponent(sharedComponent, canInsertInlineComponent);
668
+ const component = this.createComponentBySharedComponent(sharedComponent);
954
669
  slot.insert(component, remoteFormatsToLocal(this.factory, action.attributes));
955
670
  this.syncComponentSlots(sharedComponent.get('slots'), component);
956
671
  this.syncComponentState(sharedComponent, component);
@@ -990,7 +705,6 @@ exports.Collaborate = __decorate([
990
705
  di.Injectable(),
991
706
  __param(0, di.Inject(core.HISTORY_STACK_SIZE)),
992
707
  __metadata("design:paramtypes", [Number, core.RootComponentRef,
993
- exports.CollaborateCursor,
994
708
  core.Controller,
995
709
  core.Scheduler,
996
710
  core.Factory,
@@ -1013,7 +727,6 @@ function remoteFormatsToLocal(factory, attrs) {
1013
727
  const collaborateModule = {
1014
728
  providers: [
1015
729
  exports.Collaborate,
1016
- exports.CollaborateCursor,
1017
730
  {
1018
731
  provide: core.History,
1019
732
  useClass: exports.Collaborate
@@ -1021,5 +734,4 @@ const collaborateModule = {
1021
734
  ]
1022
735
  };
1023
736
 
1024
- exports.CollaborateSelectionAwarenessDelegate = CollaborateSelectionAwarenessDelegate;
1025
737
  exports.collaborateModule = collaborateModule;
@@ -1,4 +1,3 @@
1
1
  import { Module } from '@textbus/core';
2
2
  export * from './collaborate';
3
- export * from './collaborate-cursor';
4
3
  export declare const collaborateModule: Module;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "3.0.0-alpha.19",
3
+ "version": "3.0.0-alpha.21",
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,8 +27,7 @@
27
27
  "dependencies": {
28
28
  "@tanbo/di": "^1.1.3",
29
29
  "@tanbo/stream": "^1.1.8",
30
- "@textbus/browser": "^3.0.0-alpha.19",
31
- "@textbus/core": "^3.0.0-alpha.19",
30
+ "@textbus/core": "^3.0.0-alpha.21",
32
31
  "reflect-metadata": "^0.1.13",
33
32
  "y-protocols": "^1.0.5",
34
33
  "yjs": "^13.5.39"
@@ -36,7 +35,9 @@
36
35
  "devDependencies": {
37
36
  "@rollup/plugin-commonjs": "^23.0.2",
38
37
  "@rollup/plugin-typescript": "^9.0.2",
39
- "rollup": "^3.2.5"
38
+ "rimraf": "^3.0.2",
39
+ "rollup": "^3.2.5",
40
+ "tslib": "^2.4.1"
40
41
  },
41
42
  "author": {
42
43
  "name": "Tanbo",
@@ -49,5 +50,5 @@
49
50
  "bugs": {
50
51
  "url": "https://github.com/textbus/textbus.git/issues"
51
52
  },
52
- "gitHead": "98b8264421cc3ba40cbbb58a72414587cfa42715"
53
+ "gitHead": "dfce833a3f0c718166d4b51376accb79e79344e6"
53
54
  }
@@ -1,44 +0,0 @@
1
- import { Injector } from '@tanbo/di';
2
- import { SelectionBridge } from '@textbus/browser';
3
- import { Selection, SelectionPaths, AbstractSelection, Scheduler, Rect } from '@textbus/core';
4
- export interface RemoteSelection {
5
- id: string;
6
- color: string;
7
- username: string;
8
- paths: SelectionPaths;
9
- }
10
- export interface SelectionRect extends Rect {
11
- color: string;
12
- username: string;
13
- id: string;
14
- }
15
- export interface RemoteSelectionCursor {
16
- cursor: HTMLElement;
17
- anchor: HTMLElement;
18
- userTip: HTMLElement;
19
- }
20
- export declare abstract class CollaborateSelectionAwarenessDelegate {
21
- abstract getRects(abstractSelection: AbstractSelection, nativeRange: Range): false | Rect[];
22
- }
23
- export declare class CollaborateCursor {
24
- private injector;
25
- private nativeSelection;
26
- private scheduler;
27
- private selection;
28
- private awarenessDelegate;
29
- private host;
30
- private canvasContainer;
31
- private canvas;
32
- private context;
33
- private tooltips;
34
- private onRectsChange;
35
- private subscription;
36
- private currentSelection;
37
- private container;
38
- constructor(injector: Injector, nativeSelection: SelectionBridge, scheduler: Scheduler, selection: Selection, awarenessDelegate?: CollaborateSelectionAwarenessDelegate | null);
39
- refresh(): void;
40
- destroy(): void;
41
- draw(paths: RemoteSelection[]): void;
42
- protected drawUserCursor(rects: SelectionRect[]): void;
43
- private getUserCursor;
44
- }
@@ -1 +0,0 @@
1
- export declare function createUnknownComponent(factoryName: string, canInsertInlineComponent: boolean): any;