@textbus/collaborate 2.0.0-alpha.48 → 2.0.0-alpha.49

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.
@@ -6,17 +6,13 @@ export interface RemoteSelection {
6
6
  paths: SelectionPaths;
7
7
  }
8
8
  export interface SelectionRect {
9
+ color: string;
10
+ username: string;
9
11
  x: number;
10
12
  y: number;
11
13
  width: number;
12
14
  height: number;
13
15
  }
14
- export interface SelectionInfo {
15
- color: string;
16
- username: string;
17
- rects: SelectionRect[];
18
- focusEnd: boolean;
19
- }
20
16
  export interface RemoteSelectionCursor {
21
17
  cursor: HTMLElement;
22
18
  anchor: HTMLElement;
@@ -11,7 +11,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  import { Inject, Injectable } from '@tanbo/di';
14
- import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, SelectionBridge } from '@textbus/browser';
14
+ import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, getLayoutRectByRange, SelectionBridge } from '@textbus/browser';
15
15
  import { Selection } from '@textbus/core';
16
16
  import { Subject } from '@tanbo/stream';
17
17
  let CollaborateCursor = class CollaborateCursor {
@@ -74,7 +74,8 @@ let CollaborateCursor = class CollaborateCursor {
74
74
  width: '100%',
75
75
  height: '100%',
76
76
  pointerEvents: 'none',
77
- fontSize: '12px'
77
+ fontSize: '12px',
78
+ zIndex: 10
78
79
  }
79
80
  })
80
81
  });
@@ -86,11 +87,9 @@ let CollaborateCursor = class CollaborateCursor {
86
87
  });
87
88
  container.appendChild(this.canvas);
88
89
  container.appendChild(this.tooltips);
89
- this.onRectsChange.subscribe(info => {
90
- const color = info.color;
91
- const rects = info.rects;
90
+ this.onRectsChange.subscribe(rects => {
92
91
  for (const rect of rects) {
93
- this.context.fillStyle = color;
92
+ this.context.fillStyle = rect.color;
94
93
  this.context.beginPath();
95
94
  this.context.rect(rect.x, rect.y, rect.width, rect.height);
96
95
  this.context.fill();
@@ -126,54 +125,48 @@ let CollaborateCursor = class CollaborateCursor {
126
125
  for (let i = rects.length - 1; i >= 0; i--) {
127
126
  const rect = rects[i];
128
127
  selectionRects.push({
128
+ color: item.color,
129
+ username: item.username,
129
130
  x: rect.x,
130
131
  y: rect.y,
131
132
  width: rect.width,
132
133
  height: rect.height,
133
134
  });
134
135
  }
135
- if (rects.length === 0) {
136
- const rect = nativeRange.getBoundingClientRect();
137
- if (rect.x !== 0 || rect.y !== 0 || rect.width !== 0 || rect.height !== 0) {
138
- selectionRects.push({
139
- x: rect.x,
140
- y: rect.y,
141
- width: 1,
142
- height: rect.height,
143
- });
144
- }
145
- }
146
- const info = Object.assign(Object.assign({}, item), { rects: selectionRects, focusEnd: item.paths.focusEnd });
147
- this.onRectsChange.next(info);
148
- users.push(info);
136
+ this.onRectsChange.next(selectionRects);
137
+ const cursorRange = nativeRange.cloneRange();
138
+ cursorRange.collapse(!item.paths.focusEnd);
139
+ const cursorRect = getLayoutRectByRange(cursorRange);
140
+ users.push({
141
+ username: item.username,
142
+ color: item.color,
143
+ x: cursorRect.x,
144
+ y: cursorRect.y,
145
+ width: 2,
146
+ height: cursorRect.height
147
+ });
149
148
  }
150
149
  }
151
150
  });
152
151
  this.drawUserCursor(users);
153
152
  }
154
- drawUserCursor(users) {
155
- for (let i = 0; i < users.length; i++) {
156
- const user = users[i];
157
- const child = user.rects[user.focusEnd ? user.rects.length - 1 : 0];
153
+ drawUserCursor(rects) {
154
+ for (let i = 0; i < rects.length; i++) {
155
+ const rect = rects[i];
158
156
  const { cursor, userTip, anchor } = this.getUserCursor(i);
159
- if (!child) {
160
- cursor.style.display = 'none';
161
- }
162
- else {
163
- Object.assign(cursor.style, {
164
- left: child.x + (user.focusEnd ? child.width : 0) + 'px',
165
- top: child.y + 'px',
166
- width: '2px',
167
- height: child.height + 'px',
168
- background: user.color,
169
- display: 'block'
170
- });
171
- anchor.style.background = user.color;
172
- userTip.innerText = user.username;
173
- userTip.style.background = user.color;
174
- }
157
+ Object.assign(cursor.style, {
158
+ left: rect.x + 'px',
159
+ top: rect.y + 'px',
160
+ width: rect.width + 'px',
161
+ height: rect.height + 'px',
162
+ background: rect.color,
163
+ display: 'block'
164
+ });
165
+ anchor.style.background = rect.color;
166
+ userTip.innerText = rect.username;
167
+ userTip.style.background = rect.color;
175
168
  }
176
- for (let i = users.length; i < this.tooltips.children.length; i++) {
169
+ for (let i = rects.length; i < this.tooltips.children.length; i++) {
177
170
  this.tooltips.removeChild(this.tooltips.children[i]);
178
171
  }
179
172
  }
@@ -216,12 +209,10 @@ let CollaborateCursor = class CollaborateCursor {
216
209
  children: [userTip],
217
210
  on: {
218
211
  mouseenter() {
219
- anchor.style.transform = 'scale(1.2)';
220
212
  userTip.style.display = 'block';
221
213
  },
222
214
  mouseleave() {
223
215
  userTip.style.display = 'none';
224
- anchor.style.transform = '';
225
216
  }
226
217
  }
227
218
  });
@@ -1 +1 @@
1
- {"version":3,"file":"collaborate-cursor.js","sourceRoot":"","sources":["../../src/collab/collaborate-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable } from '@tanbo/di'\nimport { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, SelectionBridge } from '@textbus/browser'\nimport { Selection, SelectionPaths } from '@textbus/core'\nimport { Subject } from '@tanbo/stream'\n\nexport interface RemoteSelection {\n color: string\n username: string\n paths: SelectionPaths\n}\n\nexport interface SelectionRect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface SelectionInfo {\n color: string\n username: string\n rects: SelectionRect[]\n focusEnd: boolean\n}\n\nexport interface RemoteSelectionCursor {\n cursor: HTMLElement\n anchor: HTMLElement\n userTip: HTMLElement\n}\n\n@Injectable()\nexport class CollaborateCursor {\n private canvas = createElement('canvas', {\n styles: {\n position: 'absolute',\n opacity: 0.5,\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none'\n }\n }) as HTMLCanvasElement\n private context = this.canvas.getContext('2d')!\n private tooltips = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n fontSize: '12px'\n }\n })\n\n private onRectsChange = new Subject<SelectionInfo>()\n\n constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,\n @Inject(EDITABLE_DOCUMENT) private document: Document,\n private nativeSelection: SelectionBridge,\n private selection: Selection) {\n container.appendChild(this.canvas)\n container.appendChild(this.tooltips)\n this.onRectsChange.subscribe(info => {\n const color = info.color\n const rects = info.rects\n for (const rect of rects) {\n this.context.fillStyle = color\n this.context.beginPath()\n this.context.rect(rect.x, rect.y, rect.width, rect.height)\n this.context.fill()\n this.context.closePath()\n }\n })\n }\n\n draw(paths: RemoteSelection[]) {\n this.canvas.width = this.container.offsetWidth\n this.canvas.height = this.container.offsetHeight\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n const users: SelectionInfo[] = []\n\n paths.filter(i => {\n return i.paths.start.length && i.paths.end.length\n }).forEach(item => {\n const startOffset = item.paths.start.pop()!\n const startSlot = this.selection.findSlotByPaths(item.paths.start)\n const endOffset = item.paths.end.pop()!\n const endSlot = this.selection.findSlotByPaths(item.paths.end)\n\n if (startSlot && endSlot) {\n const position = this.nativeSelection.getPositionByRange({\n startOffset,\n endOffset,\n startSlot,\n endSlot\n })\n if (position.start && position.end) {\n const nativeRange = this.document.createRange()\n nativeRange.setStart(position.start.node, position.start.offset)\n nativeRange.setEnd(position.end.node, position.end.offset)\n\n const rects = nativeRange.getClientRects()\n const selectionRects: SelectionRect[] = []\n for (let i = rects.length - 1; i >= 0; i--) {\n const rect = rects[i]\n selectionRects.push({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n })\n }\n\n if (rects.length === 0) {\n const rect = nativeRange.getBoundingClientRect()\n if (rect.x !== 0 || rect.y !== 0 || rect.width !== 0 || rect.height !== 0) {\n selectionRects.push({\n x: rect.x,\n y: rect.y,\n width: 1,\n height: rect.height,\n })\n }\n }\n const info: SelectionInfo = {\n ...item,\n rects: selectionRects,\n focusEnd: item.paths.focusEnd\n }\n this.onRectsChange.next(info)\n\n users.push(info)\n }\n }\n })\n this.drawUserCursor(users)\n }\n\n private drawUserCursor(users: SelectionInfo[]) {\n for (let i = 0; i < users.length; i++) {\n const user = users[i]\n const child = user.rects[user.focusEnd ? user.rects.length - 1 : 0]\n const {cursor, userTip, anchor} = this.getUserCursor(i)\n if (!child) {\n cursor.style.display = 'none'\n } else {\n Object.assign(cursor.style, {\n left: child.x + (user.focusEnd ? child.width : 0) + 'px',\n top: child.y + 'px',\n width: '2px',\n height: child.height + 'px',\n background: user.color,\n display: 'block'\n })\n anchor.style.background = user.color\n userTip.innerText = user.username\n userTip.style.background = user.color\n }\n }\n\n for (let i = users.length; i < this.tooltips.children.length; i++) {\n this.tooltips.removeChild(this.tooltips.children[i])\n }\n }\n\n private getUserCursor(index: number): RemoteSelectionCursor {\n let child: HTMLElement = this.tooltips.children[index] as HTMLElement\n if (child) {\n const anchor = child.children[0] as HTMLElement\n return {\n cursor: child,\n anchor,\n userTip: anchor.children[0] as HTMLElement\n }\n }\n const userTip = createElement('span', {\n styles: {\n position: 'absolute',\n display: 'none',\n left: '50%',\n transform: 'translateX(-50%)',\n marginBottom: '2px',\n bottom: '100%',\n whiteSpace: 'nowrap',\n color: '#fff',\n boxShadow: '0 1px 2px rgba(0,0,0,.1)',\n borderRadius: '3px',\n padding: '3px 5px',\n pointerEvents: 'none',\n }\n })\n\n const anchor = createElement('span', {\n styles: {\n position: 'absolute',\n top: '-2px',\n left: '-2px',\n width: '6px',\n height: '6px',\n pointerEvents: 'auto',\n pointer: 'cursor',\n },\n children: [userTip],\n on: {\n mouseenter() {\n anchor.style.transform = 'scale(1.2)'\n userTip.style.display = 'block'\n },\n mouseleave() {\n userTip.style.display = 'none'\n anchor.style.transform = ''\n }\n }\n })\n child = createElement('span', {\n styles: {\n position: 'absolute',\n },\n children: [\n anchor\n ]\n })\n this.tooltips.append(child)\n return {\n cursor: child,\n anchor,\n userTip\n }\n }\n}\n"]}
1
+ {"version":3,"file":"collaborate-cursor.js","sourceRoot":"","sources":["../../src/collab/collaborate-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable } from '@tanbo/di'\nimport {\n createElement,\n EDITABLE_DOCUMENT,\n EDITOR_CONTAINER,\n getLayoutRectByRange,\n SelectionBridge\n} from '@textbus/browser'\nimport { Selection, SelectionPaths } from '@textbus/core'\nimport { Subject } from '@tanbo/stream'\n\nexport interface RemoteSelection {\n color: string\n username: string\n paths: SelectionPaths\n}\n\nexport interface SelectionRect {\n color: string\n username: string\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface RemoteSelectionCursor {\n cursor: HTMLElement\n anchor: HTMLElement\n userTip: HTMLElement\n}\n\n@Injectable()\nexport class CollaborateCursor {\n private canvas = createElement('canvas', {\n styles: {\n position: 'absolute',\n opacity: 0.5,\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none'\n }\n }) as HTMLCanvasElement\n private context = this.canvas.getContext('2d')!\n private tooltips = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n fontSize: '12px',\n zIndex: 10\n }\n })\n\n private onRectsChange = new Subject<SelectionRect[]>()\n\n constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,\n @Inject(EDITABLE_DOCUMENT) private document: Document,\n private nativeSelection: SelectionBridge,\n private selection: Selection) {\n container.appendChild(this.canvas)\n container.appendChild(this.tooltips)\n this.onRectsChange.subscribe(rects => {\n for (const rect of rects) {\n this.context.fillStyle = rect.color\n this.context.beginPath()\n this.context.rect(rect.x, rect.y, rect.width, rect.height)\n this.context.fill()\n this.context.closePath()\n }\n })\n }\n\n draw(paths: RemoteSelection[]) {\n this.canvas.width = this.container.offsetWidth\n this.canvas.height = this.container.offsetHeight\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n const users: SelectionRect[] = []\n\n paths.filter(i => {\n return i.paths.start.length && i.paths.end.length\n }).forEach(item => {\n const startOffset = item.paths.start.pop()!\n const startSlot = this.selection.findSlotByPaths(item.paths.start)\n const endOffset = item.paths.end.pop()!\n const endSlot = this.selection.findSlotByPaths(item.paths.end)\n\n if (startSlot && endSlot) {\n const position = this.nativeSelection.getPositionByRange({\n startOffset,\n endOffset,\n startSlot,\n endSlot\n })\n if (position.start && position.end) {\n const nativeRange = this.document.createRange()\n nativeRange.setStart(position.start.node, position.start.offset)\n nativeRange.setEnd(position.end.node, position.end.offset)\n\n const rects = nativeRange.getClientRects()\n const selectionRects: SelectionRect[] = []\n for (let i = rects.length - 1; i >= 0; i--) {\n const rect = rects[i]\n selectionRects.push({\n color: item.color,\n username: item.username,\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n })\n }\n this.onRectsChange.next(selectionRects)\n\n const cursorRange = nativeRange.cloneRange()\n cursorRange.collapse(!item.paths.focusEnd)\n\n const cursorRect = getLayoutRectByRange(cursorRange)\n\n users.push({\n username: item.username,\n color: item.color,\n x: cursorRect.x,\n y: cursorRect.y,\n width: 2,\n height: cursorRect.height\n })\n }\n }\n })\n this.drawUserCursor(users)\n }\n\n private drawUserCursor(rects: SelectionRect[]) {\n for (let i = 0; i < rects.length; i++) {\n const rect = rects[i]\n const {cursor, userTip, anchor} = this.getUserCursor(i)\n Object.assign(cursor.style, {\n left: rect.x + 'px',\n top: rect.y + 'px',\n width: rect.width + 'px',\n height: rect.height + 'px',\n background: rect.color,\n display: 'block'\n })\n anchor.style.background = rect.color\n userTip.innerText = rect.username\n userTip.style.background = rect.color\n }\n\n for (let i = rects.length; i < this.tooltips.children.length; i++) {\n this.tooltips.removeChild(this.tooltips.children[i])\n }\n }\n\n private getUserCursor(index: number): RemoteSelectionCursor {\n let child: HTMLElement = this.tooltips.children[index] as HTMLElement\n if (child) {\n const anchor = child.children[0] as HTMLElement\n return {\n cursor: child,\n anchor,\n userTip: anchor.children[0] as HTMLElement\n }\n }\n const userTip = createElement('span', {\n styles: {\n position: 'absolute',\n display: 'none',\n left: '50%',\n transform: 'translateX(-50%)',\n marginBottom: '2px',\n bottom: '100%',\n whiteSpace: 'nowrap',\n color: '#fff',\n boxShadow: '0 1px 2px rgba(0,0,0,.1)',\n borderRadius: '3px',\n padding: '3px 5px',\n pointerEvents: 'none',\n }\n })\n\n const anchor = createElement('span', {\n styles: {\n position: 'absolute',\n top: '-2px',\n left: '-2px',\n width: '6px',\n height: '6px',\n pointerEvents: 'auto',\n pointer: 'cursor',\n },\n children: [userTip],\n on: {\n mouseenter() {\n userTip.style.display = 'block'\n },\n mouseleave() {\n userTip.style.display = 'none'\n }\n }\n })\n child = createElement('span', {\n styles: {\n position: 'absolute',\n },\n children: [\n anchor\n ]\n })\n this.tooltips.append(child)\n return {\n cursor: child,\n anchor,\n userTip\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "2.0.0-alpha.48",
3
+ "version": "2.0.0-alpha.49",
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/public-api.js",
6
6
  "module": "./bundles/public-api.js",
@@ -27,8 +27,8 @@
27
27
  "dependencies": {
28
28
  "@tanbo/di": "^1.0.5",
29
29
  "@tanbo/stream": "^0.0.12",
30
- "@textbus/browser": "^2.0.0-alpha.48",
31
- "@textbus/core": "^2.0.0-alpha.48",
30
+ "@textbus/browser": "^2.0.0-alpha.49",
31
+ "@textbus/core": "^2.0.0-alpha.49",
32
32
  "reflect-metadata": "^0.1.13",
33
33
  "y-protocols": "^1.0.5",
34
34
  "yjs": "^13.5.27"
@@ -44,5 +44,5 @@
44
44
  "bugs": {
45
45
  "url": "https://github.com/textbus/textbus.git/issues"
46
46
  },
47
- "gitHead": "e9dae4b766b8ead398406487ae7e587cca8164ab"
47
+ "gitHead": "d9380c6a3c90fb72af03b9e16db5edd9c5ea3714"
48
48
  }
@@ -1,5 +1,11 @@
1
1
  import { Inject, Injectable } from '@tanbo/di'
2
- import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, SelectionBridge } from '@textbus/browser'
2
+ import {
3
+ createElement,
4
+ EDITABLE_DOCUMENT,
5
+ EDITOR_CONTAINER,
6
+ getLayoutRectByRange,
7
+ SelectionBridge
8
+ } from '@textbus/browser'
3
9
  import { Selection, SelectionPaths } from '@textbus/core'
4
10
  import { Subject } from '@tanbo/stream'
5
11
 
@@ -10,19 +16,14 @@ export interface RemoteSelection {
10
16
  }
11
17
 
12
18
  export interface SelectionRect {
19
+ color: string
20
+ username: string
13
21
  x: number
14
22
  y: number
15
23
  width: number
16
24
  height: number
17
25
  }
18
26
 
19
- export interface SelectionInfo {
20
- color: string
21
- username: string
22
- rects: SelectionRect[]
23
- focusEnd: boolean
24
- }
25
-
26
27
  export interface RemoteSelectionCursor {
27
28
  cursor: HTMLElement
28
29
  anchor: HTMLElement
@@ -51,11 +52,12 @@ export class CollaborateCursor {
51
52
  width: '100%',
52
53
  height: '100%',
53
54
  pointerEvents: 'none',
54
- fontSize: '12px'
55
+ fontSize: '12px',
56
+ zIndex: 10
55
57
  }
56
58
  })
57
59
 
58
- private onRectsChange = new Subject<SelectionInfo>()
60
+ private onRectsChange = new Subject<SelectionRect[]>()
59
61
 
60
62
  constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,
61
63
  @Inject(EDITABLE_DOCUMENT) private document: Document,
@@ -63,11 +65,9 @@ export class CollaborateCursor {
63
65
  private selection: Selection) {
64
66
  container.appendChild(this.canvas)
65
67
  container.appendChild(this.tooltips)
66
- this.onRectsChange.subscribe(info => {
67
- const color = info.color
68
- const rects = info.rects
68
+ this.onRectsChange.subscribe(rects => {
69
69
  for (const rect of rects) {
70
- this.context.fillStyle = color
70
+ this.context.fillStyle = rect.color
71
71
  this.context.beginPath()
72
72
  this.context.rect(rect.x, rect.y, rect.width, rect.height)
73
73
  this.context.fill()
@@ -81,7 +81,7 @@ export class CollaborateCursor {
81
81
  this.canvas.height = this.container.offsetHeight
82
82
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
83
83
 
84
- const users: SelectionInfo[] = []
84
+ const users: SelectionRect[] = []
85
85
 
86
86
  paths.filter(i => {
87
87
  return i.paths.start.length && i.paths.end.length
@@ -108,61 +108,53 @@ export class CollaborateCursor {
108
108
  for (let i = rects.length - 1; i >= 0; i--) {
109
109
  const rect = rects[i]
110
110
  selectionRects.push({
111
+ color: item.color,
112
+ username: item.username,
111
113
  x: rect.x,
112
114
  y: rect.y,
113
115
  width: rect.width,
114
116
  height: rect.height,
115
117
  })
116
118
  }
119
+ this.onRectsChange.next(selectionRects)
117
120
 
118
- if (rects.length === 0) {
119
- const rect = nativeRange.getBoundingClientRect()
120
- if (rect.x !== 0 || rect.y !== 0 || rect.width !== 0 || rect.height !== 0) {
121
- selectionRects.push({
122
- x: rect.x,
123
- y: rect.y,
124
- width: 1,
125
- height: rect.height,
126
- })
127
- }
128
- }
129
- const info: SelectionInfo = {
130
- ...item,
131
- rects: selectionRects,
132
- focusEnd: item.paths.focusEnd
133
- }
134
- this.onRectsChange.next(info)
121
+ const cursorRange = nativeRange.cloneRange()
122
+ cursorRange.collapse(!item.paths.focusEnd)
123
+
124
+ const cursorRect = getLayoutRectByRange(cursorRange)
135
125
 
136
- users.push(info)
126
+ users.push({
127
+ username: item.username,
128
+ color: item.color,
129
+ x: cursorRect.x,
130
+ y: cursorRect.y,
131
+ width: 2,
132
+ height: cursorRect.height
133
+ })
137
134
  }
138
135
  }
139
136
  })
140
137
  this.drawUserCursor(users)
141
138
  }
142
139
 
143
- private drawUserCursor(users: SelectionInfo[]) {
144
- for (let i = 0; i < users.length; i++) {
145
- const user = users[i]
146
- const child = user.rects[user.focusEnd ? user.rects.length - 1 : 0]
140
+ private drawUserCursor(rects: SelectionRect[]) {
141
+ for (let i = 0; i < rects.length; i++) {
142
+ const rect = rects[i]
147
143
  const {cursor, userTip, anchor} = this.getUserCursor(i)
148
- if (!child) {
149
- cursor.style.display = 'none'
150
- } else {
151
- Object.assign(cursor.style, {
152
- left: child.x + (user.focusEnd ? child.width : 0) + 'px',
153
- top: child.y + 'px',
154
- width: '2px',
155
- height: child.height + 'px',
156
- background: user.color,
157
- display: 'block'
158
- })
159
- anchor.style.background = user.color
160
- userTip.innerText = user.username
161
- userTip.style.background = user.color
162
- }
144
+ Object.assign(cursor.style, {
145
+ left: rect.x + 'px',
146
+ top: rect.y + 'px',
147
+ width: rect.width + 'px',
148
+ height: rect.height + 'px',
149
+ background: rect.color,
150
+ display: 'block'
151
+ })
152
+ anchor.style.background = rect.color
153
+ userTip.innerText = rect.username
154
+ userTip.style.background = rect.color
163
155
  }
164
156
 
165
- for (let i = users.length; i < this.tooltips.children.length; i++) {
157
+ for (let i = rects.length; i < this.tooltips.children.length; i++) {
166
158
  this.tooltips.removeChild(this.tooltips.children[i])
167
159
  }
168
160
  }
@@ -207,12 +199,10 @@ export class CollaborateCursor {
207
199
  children: [userTip],
208
200
  on: {
209
201
  mouseenter() {
210
- anchor.style.transform = 'scale(1.2)'
211
202
  userTip.style.display = 'block'
212
203
  },
213
204
  mouseleave() {
214
205
  userTip.style.display = 'none'
215
- anchor.style.transform = ''
216
206
  }
217
207
  }
218
208
  })