@textbus/collaborate 3.0.0-alpha.18 → 3.0.0-alpha.20

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