@cocreate/cursors 1.16.28 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/demo/index.html CHANGED
@@ -24,21 +24,21 @@
24
24
  </head>
25
25
 
26
26
  <body>
27
- <form collection="module_activities" class="margin:20px">
27
+ <form array="module_activities" class="margin:20px">
28
28
  <input
29
29
  type="text"
30
30
  cursors="true"
31
- collection="module_activities"
32
- document_id="5edda7608d5c7a7d656edecd"
33
- name="name"
31
+ array="module_activities"
32
+ object="5edda7608d5c7a7d656edecd"
33
+ key="name"
34
34
  placeholder="Text"
35
35
  class="floating-label" />
36
36
 
37
37
  <textarea
38
38
  cursors="true"
39
- collection="module_activities"
40
- document_id="5edda7608d5c7a7d656edecd"
41
- name="text_area"
39
+ array="module_activities"
40
+ object="5edda7608d5c7a7d656edecd"
41
+ key="text_area"
42
42
  placeholder="Text Area"
43
43
  class="floating-label">
44
44
  </textarea>
package/docs/index.html CHANGED
@@ -11,10 +11,10 @@
11
11
  sizes="32x32"
12
12
  href="https://cocreate.app/images/favicon.ico" />
13
13
  <meta
14
- name="description"
14
+ key="description"
15
15
  content="A simple HTML5 and pure javascript component. Easy configuration using HTML5 attributes or Javscript api and highly styleable." />
16
16
  <meta
17
- name="keywords"
17
+ key="keywords"
18
18
  content="helper classes, utility classes, css framework, css library, inline style classes" />
19
19
  <meta name="robots" content="index,follow" />
20
20
  <meta
@@ -23,9 +23,9 @@
23
23
  <link
24
24
  rel="stylesheet"
25
25
  href="/docs/index.css"
26
- collection="files"
27
- document_id="60888216117c640e7596303f"
28
- name="src"
26
+ array="files"
27
+ object="60888216117c640e7596303f"
28
+ key="src"
29
29
  type="text/css"
30
30
  save="true" />
31
31
  <link rel="manifest" href="/manifest.webmanifest" />
@@ -38,20 +38,20 @@
38
38
  scroll="sticky-nav,hide-nav"
39
39
  scroll-up="10"
40
40
  scroll-down="10"
41
- collection="files"
42
- document_id="60395ef42b3ac232657040fd"
43
- name="src"></nav>
41
+ array="files"
42
+ object="60395ef42b3ac232657040fd"
43
+ key="src"></nav>
44
44
  <sidenav
45
45
  id="menuL"
46
46
  class="position:fixed top:0px left:0px overflow:hidden background:whitesmoke height:100vh width:0px width:300px@xl"
47
47
  resizable
48
- resize-target="[content_id='content']"
48
+ resize-selector="[content_id='content']"
49
49
  resize-property="margin-left"
50
50
  resize-value="width">
51
51
  <menu
52
- collection="files"
53
- document_id="603717b07de7fb350ae9fec8"
54
- name="src"></menu>
52
+ array="files"
53
+ object="603717b07de7fb350ae9fec8"
54
+ key="src"></menu>
55
55
  <div resize="right"></div>
56
56
  </sidenav>
57
57
  <main
@@ -137,12 +137,12 @@
137
137
  <div class="flex-grow:1 min-width:300px width:100%">
138
138
  <pre>
139
139
  <code>
140
- &lt;form collection=&quot;module_activities&quot; class=&quot;margin:20px&quot;&gt;
140
+ &lt;form array=&quot;module_activities&quot; class=&quot;margin:20px&quot;&gt;
141
141
  &lt;textarea
142
142
  cursors=&quot;true&quot;
143
- collection=&quot;module_activities&quot;
144
- document_id=&quot;5edda7608d5c7a7d656edecd&quot;
145
- name=&quot;text_area&quot;
143
+ array=&quot;module_activities&quot;
144
+ object=&quot;5edda7608d5c7a7d656edecd&quot;
145
+ key=&quot;text_area&quot;
146
146
  placeholder=&quot;Text Area&quot;
147
147
  class=&quot;floating-label&quot;&gt;
148
148
  &lt;/textarea&gt;
@@ -196,9 +196,9 @@
196
196
  <textarea
197
197
  type="code"
198
198
  lang="html"
199
- collection="demos"
200
- document_id=""
201
- name="demo"
199
+ array="demos"
200
+ object=""
201
+ key="demo"
202
202
  save="false"
203
203
  id="demo"
204
204
  class="height:100% width:100% outline:none border:none resize:none padding:5px"></textarea>
@@ -221,7 +221,7 @@
221
221
  show="#eye-slash"
222
222
  hide="#eye, #demo-preview"
223
223
  toggle="code-height"
224
- toggle-target="#demo-code"
224
+ toggle-selector="#demo-code"
225
225
  ><i
226
226
  class="height:18px fill:#505050"
227
227
  src="/assets/svg/eye.svg"></i
@@ -233,7 +233,7 @@
233
233
  show="#eye, #demo-preview"
234
234
  hide="#eye-slash"
235
235
  toggle="code-height"
236
- toggle-target="#demo-code"
236
+ toggle-selector="#demo-code"
237
237
  ><i
238
238
  class="height:20px fill:#505050"
239
239
  src="/assets/svg/eye-slash.svg"></i
@@ -260,7 +260,7 @@
260
260
  <a
261
261
  class="margin-right:5px"
262
262
  fullscreen
263
- fullscreen-target="#playground"></a>
263
+ fullscreen-selector="#playground"></a>
264
264
  </div>
265
265
  </div>
266
266
  <!-- End SandBox -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/cursors",
3
- "version": "1.16.28",
3
+ "version": "1.17.0",
4
4
  "description": "Collaborative user cursor position for inputs, textarea's and contenteditable elements.",
5
5
  "keywords": [
6
6
  "cursors",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "scripts": {
28
28
  "start": "npx webpack --config webpack.config.js",
29
- "build": "NODE_ENV=production npx webpack --config webpack.config.js",
29
+ "build": "npx webpack --mode=production --config webpack.config.js",
30
30
  "dev": "npx webpack --config webpack.config.js --watch",
31
31
  "postinstall": "node -e \"const { execSync } = require('child_process'); try { execSync('coc --version', { stdio: 'ignore' }); } catch (error) { try { execSync('npm install -g @cocreate/cli', { stdio: 'inherit' }); console.log('Installed \"@cocreate/cli\" globally.'); } catch (error) { console.error('Failed to install \"@cocreate/cli\" globally:', error); } }\""
32
32
  },
@@ -35,7 +35,7 @@
35
35
  "url": "git+https://github.com/CoCreate-app/CoCreate-cursors.git"
36
36
  },
37
37
  "author": "CoCreate LLC",
38
- "license": "SEE LICENSE",
38
+ "license": "AGPL-3.0",
39
39
  "bugs": {
40
40
  "url": "https://github.com/CoCreate-app/CoCreate-cursors/issues"
41
41
  },
@@ -59,13 +59,12 @@
59
59
  "webpack-log": "^3.0.1"
60
60
  },
61
61
  "dependencies": {
62
- "@cocreate/cli": "^1.33.8",
63
- "@cocreate/crud-client": "^1.21.22",
64
- "@cocreate/local-storage": "^1.7.19",
65
- "@cocreate/message-client": "^1.3.27",
66
- "@cocreate/observer": "^1.8.17",
67
- "@cocreate/random-color": "^1.4.24",
68
- "@cocreate/selection": "^1.6.26",
69
- "@cocreate/uuid": "^1.4.26"
62
+ "@cocreate/local-storage": "^1.7.21",
63
+ "@cocreate/message-client": "^1.3.29",
64
+ "@cocreate/observer": "^1.8.19",
65
+ "@cocreate/random-color": "^1.4.26",
66
+ "@cocreate/selection": "^1.6.28",
67
+ "@cocreate/utils": "^1.21.16",
68
+ "@cocreate/uuid": "^1.4.28"
70
69
  }
71
70
  }
package/src/index.js CHANGED
@@ -1,11 +1,33 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2023 CoCreate and Contributors.
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Affero General Public License as published
6
+ * by the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+ ********************************************************************************/
17
+
18
+ // Commercial Licensing Information:
19
+ // For commercial use of this software without the copyleft provisions of the AGPLv3,
20
+ // you must obtain a commercial license from CoCreate LLC.
21
+ // For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
22
+
1
23
  /*globals ResizeObserver*/
2
24
  import observer from '@cocreate/observer';
3
- import crud from '@cocreate/crud-client';
25
+ import { getAttributeNames } from '@cocreate/utils';
4
26
  import message from '@cocreate/message-client';
5
27
  import uuid from '@cocreate/uuid';
6
28
  import localStorage from '@cocreate/local-storage';
7
29
  import { getElementPosition } from '@cocreate/selection';
8
- import {randomColor} from '@cocreate/random-color';
30
+ import { randomColor } from '@cocreate/random-color';
9
31
  import './index.css';
10
32
 
11
33
  const clientId = message.socket.clientId || uuid.generate(12);
@@ -13,7 +35,7 @@ const cursorBackground = randomColor();
13
35
 
14
36
  let environment_prod = true;
15
37
 
16
- let selector = "[collection][document_id][name]:not([contentEditable='false'])";
38
+ let selector = "[array][object][key]:not([contentEditable='false'])";
17
39
 
18
40
  function init() {
19
41
  let elements = document.querySelectorAll(selector);
@@ -38,15 +60,15 @@ function initDocument(doc) {
38
60
  let documents;
39
61
  try {
40
62
  documents = window.top.cursorDocuments;
41
- } catch(e) {
63
+ } catch (e) {
42
64
  console.log('cross-origin failed')
43
65
  }
44
66
 
45
- if (!documents){
67
+ if (!documents) {
46
68
  documents = new Map();
47
69
  try {
48
- window.top.cursorDocuments = documents;
49
- } catch(e) {
70
+ window.top.cursorDocuments = documents;
71
+ } catch (e) {
50
72
  console.log('cross-origin failed')
51
73
  }
52
74
  }
@@ -58,14 +80,14 @@ function initDocument(doc) {
58
80
 
59
81
  function drawCursors(selection) {
60
82
  const socket_id = selection['clientId'];
61
- const collection = selection['collection'];
62
- const document_id = selection['document_id'];
63
- const name = selection['name'];
83
+ const array = selection['array'];
84
+ const object = selection['object'];
85
+ const key = selection['key'];
64
86
  let start = selection['start'];
65
87
  let end = selection['end'];
66
88
  let elements = selection.element;
67
89
  if (!elements) {
68
- let selector = '[collection="' + collection + '"][document_id="' + document_id + '"][name="' + name + '"]';
90
+ let selector = '[array="' + array + '"][object="' + object + '"][key="' + key + '"]';
69
91
  selector += ':not(.codemirror, .monaco, [actions])';
70
92
  elements = document.querySelectorAll(selector);
71
93
  }
@@ -80,10 +102,10 @@ function drawCursors(selection) {
80
102
  if (element.tagName != 'INPUT' && element.tagName != 'TEXTAREA')
81
103
  if (contenteditable == 'false' || contenteditable == null)
82
104
  if (cursors != 'true') continue;
83
-
105
+
84
106
  if (element.hasAttribute('contenteditable')) {
85
107
  let domTextEditor = element;
86
- if (element.tagName == 'IFRAME'){
108
+ if (element.tagName == 'IFRAME') {
87
109
  // let frameClientId = element.contentDocument.defaultView.CoCreateSockets.clientId;
88
110
  // if (frameClientId == selection.clientId) continue;
89
111
  domTextEditor = element.contentDocument.documentElement;
@@ -107,10 +129,10 @@ function drawCursors(selection) {
107
129
  let document = element.ownerDocument;
108
130
  let mirrorDiv;
109
131
  let id_mirror = element.getAttribute('mirror_id');
110
- if (!id_mirror){
132
+ if (!id_mirror) {
111
133
  id_mirror = uuid.generate(8);
112
134
  element.setAttribute('mirror_id', id_mirror);
113
-
135
+
114
136
  mirrorDiv = document.createElement('cursor-container');
115
137
  mirrorDiv.id = id_mirror;
116
138
  mirrorDiv.className = (environment_prod) ? 'mirror mirror_scroll mirror_color' : 'mirror mirror_scroll';
@@ -131,16 +153,16 @@ function drawCursors(selection) {
131
153
  }
132
154
  else
133
155
  mirrorDiv = document.getElementById(id_mirror);
134
-
156
+
135
157
  let computed = getComputedStyle(element);
136
158
  let rect = element.getBoundingClientRect();
137
-
159
+
138
160
  let borderWidth = parseInt(computed['border-width']) * 2;
139
161
  let scrollBarWidth = 0;
140
162
  if (element.clientWidth != 0)
141
163
  scrollBarWidth = element.offsetWidth - element.clientWidth - borderWidth;
142
-
143
- let style = mirrorDiv.style;
164
+
165
+ let style = mirrorDiv.style;
144
166
  style.position = 'absolute';
145
167
  style.width = rect.width + 'px';
146
168
  style.height = rect.height + 'px';
@@ -154,7 +176,7 @@ function drawCursors(selection) {
154
176
  style.outlineColor = 'transparent';
155
177
  style.boxSizing = computed['boxSizing'];
156
178
  style.lineHeight = computed['lineHeight'];
157
-
179
+
158
180
  if (element.parentElement.style['display'] == 'inline') {
159
181
  style.top = element.clientTop + 'px';
160
182
  style.left = element.clientLeft + 'px';
@@ -162,39 +184,39 @@ function drawCursors(selection) {
162
184
  style.top = element.offsetTop + 'px';
163
185
  style.left = element.offsetLeft + 'px';
164
186
  }
165
-
187
+
166
188
  if (element.nodeName !== 'INPUT') {
167
189
  style.wordWrap = 'break-word';
168
190
  style.whiteSpace = 'pre-wrap';
169
191
  } else {
170
192
  style.whiteSpace = 'pre';
171
193
  }
172
-
194
+
173
195
  let properties = ['fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize', 'fontFamily', 'letterSpacing', 'lineHeight', 'textAlign', 'textTransform', 'textIndent', 'textDecoration', 'textRendering', 'textTransform', 'textIndent', 'overflowWrap', 'tabSize', 'webkitWritingMode', 'wordSpacing'];
174
-
175
- properties.forEach(function(prop) {
196
+
197
+ properties.forEach(function (prop) {
176
198
  if (['left', 'top'].indexOf(prop.toLowerCase()) === -1)
177
199
  style[prop] = computed[prop];
178
200
  });
179
-
201
+
180
202
  let spanText = mirrorDiv.querySelector('span-text');
181
203
  if (!spanText)
182
204
  spanText = document.createElement('span-text');
183
- spanText.style['display'] = 'block';
205
+ spanText.style['display'] = 'block';
184
206
  let value_element = (['TEXTAREA', 'INPUT'].indexOf(element.nodeName) == -1) ? element.innerHTML : element.value;
185
-
207
+
186
208
  spanText.textContent = value_element;
187
209
  if (element.nodeName === 'INPUT')
188
210
  spanText.textContent = mirrorDiv.textContent.replace(/\s/g, " ");
189
211
  mirrorDiv.appendChild(spanText);
190
212
  let cursor, cursorFlag;
191
- let details = {collection, document_id, name};
213
+ let details = { array, object, key };
192
214
  if (socket_id) {
193
215
  let userSelection = mirrorDiv.querySelector(`selection[socket_id="${socket_id}"]`);
194
216
  if (userSelection && userSelection.details != details)
195
217
  userSelection.remove();
196
218
  let selection_user = mirrorDiv.querySelector(`selection[socket_id="${socket_id}"]`);
197
- if (!selection_user){
219
+ if (!selection_user) {
198
220
  selection_user = document.createElement('selection');
199
221
  selection_user.setAttribute('socket_id', socket_id);
200
222
  selection_user.style["position"] = "absolute";
@@ -202,18 +224,18 @@ function drawCursors(selection) {
202
224
  selection_user.style["top"] = style_mirror.paddingTop;
203
225
  selection_user.style["left"] = style_mirror.paddingLeft;
204
226
  selection_user.style["width"] = mirrorDiv.clientWidth - parseInt(computed['padding-left']) - parseInt(computed['padding-right']) - scrollBarWidth + 'px';
205
- selection_user.details = {collection, document_id, name};
206
-
227
+ selection_user.details = { array, object, key };
228
+
207
229
  mirrorDiv.appendChild(selection_user);
208
230
  }
209
-
231
+
210
232
  let value_element = (['TEXTAREA', 'INPUT'].indexOf(element.nodeName) == -1) ? element.innerHTML : element.value;
211
233
  selection_user.textContent = value_element.substring(0, start);
212
-
234
+
213
235
  let value_end = value_element.substring(end) || '';
214
236
  let span_end = document.createElement('span-end');
215
237
  span_end.textContent = value_end;
216
-
238
+
217
239
  cursor = document.createElement('cursor');
218
240
  cursor.setAttribute('socket_id', socket_id);
219
241
  cursor.dataset.start = start;
@@ -222,23 +244,23 @@ function drawCursors(selection) {
222
244
  cursor.setAttribute('user-background', selection.background);
223
245
  cursor.setAttribute('user-color', selection.color);
224
246
  cursor.style["background"] = selection.background;
225
- cursor.details = {collection, document_id, name};
247
+ cursor.details = { array, object, key };
226
248
  cursor.textContent = "1";
227
249
  span_end.prepend(cursor);
228
-
250
+
229
251
  let selectedText = document.createElement('selected-text');
230
252
  selectedText.style["backgroundColor"] = selection.background;
231
253
  selectedText.textContent = value_element.substring(start, end) || '';
232
254
  span_end.prepend(selectedText);
233
-
255
+
234
256
  cursorFlag = document.createElement('cursor-flag');
235
- cursorFlag.setAttribute('collection', 'users');
236
- cursorFlag.setAttribute('document_id', selection.user_id);
237
- cursorFlag.setAttribute('name', 'name');
257
+ cursorFlag.setAttribute('array', 'users');
258
+ cursorFlag.setAttribute('object', selection.user_id);
259
+ cursorFlag.setAttribute('key', 'name');
238
260
  cursorFlag.style["background"] = selection.background;
239
261
  cursorFlag.innerHTML = selection.userName;
240
262
  cursor.appendChild(cursorFlag);
241
-
263
+
242
264
  selection_user.appendChild(span_end);
243
265
  }
244
266
  scrollMirror(element);
@@ -260,7 +282,7 @@ function updateCursors(element) {
260
282
  element = mirrorDiv.element;
261
283
  let cursors = mirrorDiv.querySelectorAll('cursor');
262
284
 
263
- cursors.forEach(function(child_cursor, index, array) {
285
+ cursors.forEach(function (child_cursor, index, array) {
264
286
  let clientId = child_cursor.getAttribute('socket_id');
265
287
  let userName = child_cursor.getAttribute('user-name');
266
288
  let background = child_cursor.getAttribute('user-background');
@@ -283,22 +305,22 @@ function updateCursors(element) {
283
305
 
284
306
  function removeCursor(clientId) {
285
307
  let elements = document.querySelectorAll(`cursor[socket_id="${clientId}"]`);
286
- elements.forEach(function(element, index, array) {
308
+ elements.forEach(function (element, index, array) {
287
309
  element.parentNode.removeChild(element);
288
310
  });
289
311
 
290
312
  let sel_elements = document.querySelectorAll(`selection[socket_id="${clientId}"]`);
291
- sel_elements.forEach(function(sel_element, index, array) {
313
+ sel_elements.forEach(function (sel_element, index, array) {
292
314
  sel_element.parentNode.removeChild(sel_element);
293
315
  });
294
316
  }
295
317
 
296
318
  function _initEvents(element) {
297
- element.addEventListener('keydown', function(event) {
319
+ element.addEventListener('keydown', function (event) {
298
320
  scrollMirror(element);
299
321
  });
300
322
 
301
- element.addEventListener('scroll', function() {
323
+ element.addEventListener('scroll', function () {
302
324
  scrollMirror(element);
303
325
  });
304
326
 
@@ -324,9 +346,9 @@ function sendPosition(info) {
324
346
  room: "",
325
347
  message: "cursor",
326
348
  data: {
327
- collection: info.collection,
328
- document_id: info.document_id,
329
- name: info.name,
349
+ array: info.array,
350
+ object: info.object,
351
+ key: info.key,
330
352
  start: info.start,
331
353
  end: info.end,
332
354
  clientId: clientId,
@@ -344,7 +366,7 @@ function sendPosition(info) {
344
366
  }
345
367
 
346
368
 
347
- message.listen('cursor', function(response) {
369
+ message.listen('cursor', function (response) {
348
370
  // if (selection.clientId == clientId) return;
349
371
  let selection = response.data
350
372
  if (selection.start != null && selection.end != null)
@@ -356,8 +378,8 @@ message.listen('cursor', function(response) {
356
378
  observer.init({
357
379
  name: 'CoCreateCursor',
358
380
  observe: ['addedNodes'],
359
- target: '[collection][document_id][name]',
360
- callback: function(mutation) {
381
+ target: '[array][object][key]',
382
+ callback: function (mutation) {
361
383
  initElement(mutation.target);
362
384
  }
363
385
  });
@@ -365,8 +387,8 @@ observer.init({
365
387
  observer.init({
366
388
  name: 'CoCreateCursorAtt',
367
389
  observe: ['attributes'],
368
- attributeName: crud.getAttributeNames(['collection', 'document_id', 'name']),
369
- callback: function(mutation) {
390
+ attributeName: getAttributeNames(['array', 'object', 'key']),
391
+ callback: function (mutation) {
370
392
  initElement(mutation.target);
371
393
  }
372
394
  });