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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;