@atlaskit/editor-plugin-autocomplete 2.4.0 → 2.5.1

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.
Files changed (31) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-products/tsconfig.json +3 -0
  4. package/dist/cjs/analytics/ufo.js +111 -0
  5. package/dist/cjs/pm-plugins/autocomplete-plugin.js +126 -64
  6. package/dist/cjs/pm-plugins/local-slow-lane-client.js +452 -0
  7. package/dist/cjs/pm-plugins/slow-lane-client.js +45 -16
  8. package/dist/cjs/pm-plugins/text-predictor.js +72 -40
  9. package/dist/es2019/analytics/ufo.js +110 -0
  10. package/dist/es2019/pm-plugins/autocomplete-plugin.js +132 -72
  11. package/dist/es2019/pm-plugins/local-slow-lane-client.js +361 -0
  12. package/dist/es2019/pm-plugins/slow-lane-client.js +29 -2
  13. package/dist/es2019/pm-plugins/text-predictor.js +48 -15
  14. package/dist/esm/analytics/ufo.js +105 -0
  15. package/dist/esm/pm-plugins/autocomplete-plugin.js +126 -64
  16. package/dist/esm/pm-plugins/local-slow-lane-client.js +443 -0
  17. package/dist/esm/pm-plugins/slow-lane-client.js +45 -16
  18. package/dist/esm/pm-plugins/text-predictor.js +73 -40
  19. package/dist/types/analytics/ufo.d.ts +38 -0
  20. package/dist/types/pm-plugins/autocomplete-plugin.d.ts +5 -0
  21. package/dist/types/pm-plugins/local-slow-lane-client.d.ts +102 -0
  22. package/dist/types-ts4.5/analytics/ufo.d.ts +38 -0
  23. package/dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts +5 -0
  24. package/dist/types-ts4.5/pm-plugins/local-slow-lane-client.d.ts +102 -0
  25. package/package.json +7 -2
  26. package/src/analytics/ufo.ts +132 -0
  27. package/src/pm-plugins/autocomplete-plugin.ts +125 -64
  28. package/src/pm-plugins/local-slow-lane-client.ts +487 -0
  29. package/src/pm-plugins/slow-lane-client.ts +28 -2
  30. package/src/pm-plugins/text-predictor.ts +42 -12
  31. package/tsconfig.app.json +3 -0
@@ -2,16 +2,20 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
5
+ import { logException } from '@atlaskit/editor-common/monitoring';
5
6
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
6
7
  import { keydownHandler } from '@atlaskit/editor-prosemirror/keymap';
7
8
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
8
9
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
10
  import { createGhostTextDecorationSet } from './ghost-text-decoration';
11
+ import { createLocalSlowLaneClient } from './local-slow-lane-client';
10
12
  import { createSlowLaneClient, setDefaultSlowLaneClient, isWordBoundary } from './slow-lane-client';
11
13
  import { predict, loadDefaultVocabulary, loadVectorsAsync, incrementSessionFreq, ingestDocumentPage } from './text-predictor';
12
- var SLOW_LANE_ENDPOINT = '/gateway/api/v1/autocomplete/typeahead-encodings';
13
14
  export var autocompletePluginKey = new PluginKey('autocomplete');
14
15
  var DEBOUNCE_MS = 150;
16
+ var hasDestroy = function hasDestroy(client) {
17
+ return 'destroy' in client && typeof client.destroy === 'function';
18
+ };
15
19
  var createInitialState = function createInitialState() {
16
20
  return {
17
21
  ghostText: '',
@@ -64,15 +68,21 @@ var setAutocompleteMeta = function setAutocompleteMeta(tr, meta) {
64
68
  */
65
69
  var lastShownGhostText = '';
66
70
  var showGhostText = function showGhostText(view, text, position) {
67
- var state = view.state,
68
- dispatch = view.dispatch;
69
- var decorationSet = createGhostTextDecorationSet(state, position, text);
70
- var tr = setAutocompleteMeta(state.tr, {
71
- ghostText: text,
72
- ghostPosition: position,
73
- decorationSet: decorationSet
74
- });
75
- dispatch(tr);
71
+ try {
72
+ var state = view.state,
73
+ dispatch = view.dispatch;
74
+ var decorationSet = createGhostTextDecorationSet(state, position, text);
75
+ var tr = setAutocompleteMeta(state.tr, {
76
+ ghostText: text,
77
+ ghostPosition: position,
78
+ decorationSet: decorationSet
79
+ });
80
+ dispatch(tr);
81
+ } catch (error) {
82
+ logException(error, {
83
+ location: 'editor-plugin-autocomplete/showGhostText'
84
+ });
85
+ }
76
86
  };
77
87
 
78
88
  /**
@@ -84,12 +94,19 @@ var clearGhostText = function clearGhostText(state, dispatch) {
84
94
  return false;
85
95
  }
86
96
  if (dispatch) {
87
- var tr = setAutocompleteMeta(state.tr, {
88
- ghostText: '',
89
- ghostPosition: -1,
90
- decorationSet: DecorationSet.empty
91
- });
92
- dispatch(tr);
97
+ try {
98
+ var tr = setAutocompleteMeta(state.tr, {
99
+ ghostText: '',
100
+ ghostPosition: -1,
101
+ decorationSet: DecorationSet.empty
102
+ });
103
+ dispatch(tr);
104
+ } catch (error) {
105
+ logException(error, {
106
+ location: 'editor-plugin-autocomplete/clearGhostText'
107
+ });
108
+ return false;
109
+ }
93
110
  }
94
111
  return true;
95
112
  };
@@ -103,15 +120,22 @@ var acceptGhostText = function acceptGhostText(state, dispatch) {
103
120
  return false;
104
121
  }
105
122
  if (dispatch) {
106
- var ghostText = pluginState.ghostText,
107
- ghostPosition = pluginState.ghostPosition;
108
- var tr = state.tr.insertText(ghostText, ghostPosition);
109
- tr = setAutocompleteMeta(tr, {
110
- ghostText: '',
111
- ghostPosition: -1,
112
- decorationSet: DecorationSet.empty
113
- });
114
- dispatch(tr);
123
+ try {
124
+ var ghostText = pluginState.ghostText,
125
+ ghostPosition = pluginState.ghostPosition;
126
+ var tr = state.tr.insertText(ghostText, ghostPosition);
127
+ tr = setAutocompleteMeta(tr, {
128
+ ghostText: '',
129
+ ghostPosition: -1,
130
+ decorationSet: DecorationSet.empty
131
+ });
132
+ dispatch(tr);
133
+ } catch (error) {
134
+ logException(error, {
135
+ location: 'editor-plugin-autocomplete/acceptGhostText'
136
+ });
137
+ return false;
138
+ }
115
139
  }
116
140
  return true;
117
141
  };
@@ -170,12 +194,23 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
170
194
  var dismissedContext = null;
171
195
  var lastSuggestionTypedLength = 0;
172
196
  var lastSuggestionLength = 0;
173
- var fireSuggestionInsertedAnalytics = function fireSuggestionInsertedAnalytics(ghostText) {
197
+ var fireSuggestionDismissedAnalytics = function fireSuggestionDismissedAnalytics(reason) {
174
198
  var _api$analytics;
199
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
200
+ action: ACTION.SUGGESTION_DISMISSED,
201
+ actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
202
+ eventType: EVENT_TYPE.TRACK,
203
+ attributes: {
204
+ reason: reason
205
+ }
206
+ });
207
+ };
208
+ var fireSuggestionInsertedAnalytics = function fireSuggestionInsertedAnalytics(ghostText) {
209
+ var _api$analytics2;
175
210
  var typedLength = lastSuggestionTypedLength;
176
211
  var suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
177
212
  var kssDelta = suggestionLength - typedLength;
178
- api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
213
+ api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
179
214
  action: ACTION.SUGGESTION_INSERTED,
180
215
  actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
181
216
  eventType: EVENT_TYPE.TRACK,
@@ -186,9 +221,11 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
186
221
  }
187
222
  });
188
223
  };
189
- var slowLaneClient = createSlowLaneClient({
224
+ var slowLaneClient = options !== null && options !== void 0 && options.useLocalModel ? createLocalSlowLaneClient({
225
+ debounceMs: 300
226
+ }) : createSlowLaneClient({
190
227
  baseUrl: '',
191
- endpoint: SLOW_LANE_ENDPOINT
228
+ debounceMs: 300
192
229
  });
193
230
  setDefaultSlowLaneClient(slowLaneClient);
194
231
 
@@ -202,43 +239,49 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
202
239
  clearTimeout(debounceTimer);
203
240
  }
204
241
  debounceTimer = setTimeout(function () {
205
- var state = view.state;
206
- var selection = state.selection;
242
+ try {
243
+ var state = view.state;
244
+ var selection = state.selection;
207
245
 
208
- // Only predict for cursor selections (not range selections)
209
- if (!selection.empty) {
210
- return;
211
- }
212
- var textBefore = getTextBeforeCursor(state);
246
+ // Only predict for cursor selections (not range selections)
247
+ if (!selection.empty) {
248
+ return;
249
+ }
250
+ var textBefore = getTextBeforeCursor(state);
213
251
 
214
- // Suppress re-showing the same suggestion the user just dismissed.
215
- // Once the text context changes (user types or deletes), this clears automatically.
216
- if (textBefore === dismissedContext) {
217
- return;
218
- }
219
- dismissedContext = null;
252
+ // Suppress re-showing the same suggestion the user just dismissed.
253
+ // Once the text context changes (user types or deletes), this clears automatically.
254
+ if (textBefore === dismissedContext) {
255
+ return;
256
+ }
257
+ dismissedContext = null;
220
258
 
221
- // Don't predict if there's not enough context
222
- if (textBefore.trim().length < 3) {
223
- return;
224
- }
259
+ // Don't predict if there's not enough context
260
+ if (textBefore.trim().length < 3) {
261
+ return;
262
+ }
225
263
 
226
- // Tier 1 prediction is synchronous -- no async needed
227
- var prediction = predict(textBefore);
228
- if (prediction && prediction.length > 0) {
229
- var typedLength = getTypedLengthForPrediction(textBefore);
230
- lastSuggestionTypedLength = typedLength;
231
- lastSuggestionLength = typedLength + prediction.length;
232
- showGhostText(view, prediction, selection.from);
233
- if (prediction !== lastShownGhostText) {
234
- var _api$analytics2;
235
- lastShownGhostText = prediction;
236
- api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
237
- action: ACTION.SUGGESTION_VIEWED,
238
- actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
239
- eventType: EVENT_TYPE.TRACK
240
- });
264
+ // Tier 1 prediction is synchronous -- no async needed
265
+ var prediction = predict(textBefore);
266
+ if (prediction && prediction.length > 0) {
267
+ var typedLength = getTypedLengthForPrediction(textBefore);
268
+ lastSuggestionTypedLength = typedLength;
269
+ lastSuggestionLength = typedLength + prediction.length;
270
+ showGhostText(view, prediction, selection.from);
271
+ if (prediction !== lastShownGhostText) {
272
+ var _api$analytics3;
273
+ lastShownGhostText = prediction;
274
+ api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.fireAnalyticsEvent({
275
+ action: ACTION.SUGGESTION_VIEWED,
276
+ actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
277
+ eventType: EVENT_TYPE.TRACK
278
+ });
279
+ }
241
280
  }
281
+ } catch (error) {
282
+ logException(error, {
283
+ location: 'editor-plugin-autocomplete/schedulePrediction'
284
+ });
242
285
  }
243
286
  }, DEBOUNCE_MS);
244
287
  };
@@ -336,6 +379,7 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
336
379
  var didClear = clearGhostText(state, dispatch);
337
380
  if (didClear) {
338
381
  dismissedContext = getTextBeforeCursor(state);
382
+ fireSuggestionDismissedAnalytics('escape');
339
383
  }
340
384
  return didClear;
341
385
  }
@@ -345,14 +389,25 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
345
389
  var pluginState = autocompletePluginKey.getState(view.state);
346
390
  if (pluginState !== null && pluginState !== void 0 && pluginState.ghostText) {
347
391
  clearGhostText(view.state, view.dispatch);
392
+ fireSuggestionDismissedAnalytics('blur');
348
393
  }
349
394
  return false;
350
395
  },
351
396
  focus: function focus() {
352
- loadDefaultVocabulary();
397
+ try {
398
+ loadDefaultVocabulary();
399
+ } catch (error) {
400
+ logException(error, {
401
+ location: 'editor-plugin-autocomplete/loadDefaultVocabulary'
402
+ });
403
+ }
353
404
  loadVectorsAsync({
354
405
  getBinaryUrl: options === null || options === void 0 ? void 0 : options.getVectorsBinaryUrl
355
- }).catch(function () {});
406
+ }).catch(function (error) {
407
+ logException(error, {
408
+ location: 'editor-plugin-autocomplete/loadVectorsAsync'
409
+ });
410
+ });
356
411
  if (!hasIngestedPage) {
357
412
  hasIngestedPage = true;
358
413
  if (options !== null && options !== void 0 && options.getContext) {
@@ -369,7 +424,11 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
369
424
  ingestDocumentPage(context.parentCommentContent);
370
425
  }
371
426
  (_context$siblingComme4 = context.siblingCommentsContents) === null || _context$siblingComme4 === void 0 || _context$siblingComme4.forEach(ingestDocumentPage);
372
- }).catch(function () {});
427
+ }).catch(function (error) {
428
+ logException(error, {
429
+ location: 'editor-plugin-autocomplete/getContext'
430
+ });
431
+ });
373
432
  }
374
433
  }
375
434
  return false;
@@ -406,6 +465,9 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
406
465
  if (debounceTimer) {
407
466
  clearTimeout(debounceTimer);
408
467
  }
468
+ if (hasDestroy(slowLaneClient)) {
469
+ slowLaneClient.destroy();
470
+ }
409
471
  setDefaultSlowLaneClient(null);
410
472
  }
411
473
  };