@algolia/autocomplete-core 1.5.0 → 1.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.
@@ -22,6 +22,7 @@ export function createStore(reducer, props, onStoreStateChange) {
22
22
  state: state,
23
23
  prevState: prevState
24
24
  });
25
- }
25
+ },
26
+ shouldSkipPendingUpdate: false
26
27
  };
27
28
  }
@@ -38,7 +38,15 @@ export function getPropGetters(_ref) {
38
38
  // @TODO: support cases where there are multiple Autocomplete instances.
39
39
  // Right now, a second instance makes this computation return false.
40
40
  onTouchStart: function onTouchStart(event) {
41
- if (store.getState().isOpen === false || event.target === inputElement) {
41
+ // The `onTouchStart` event shouldn't trigger the `blur` handler when
42
+ // it's not an interaction with Autocomplete. We detect it with the
43
+ // following heuristics:
44
+ // - the panel is closed AND there are no running requests
45
+ // (no interaction with the autocomplete, no future state updates)
46
+ // - OR the touched target is the input element (should open the panel)
47
+ var isNotAutocompleteInteraction = store.getState().isOpen === false && !onInput.isRunning();
48
+
49
+ if (isNotAutocompleteInteraction || event.target === inputElement) {
42
50
  return;
43
51
  }
44
52
 
@@ -47,7 +55,14 @@ export function getPropGetters(_ref) {
47
55
  });
48
56
 
49
57
  if (isTargetWithinAutocomplete === false) {
50
- store.dispatch('blur', null);
58
+ store.dispatch('blur', null); // If requests are still running when the user closes the panel, they
59
+ // could reopen the panel once they resolve.
60
+ // We want to prevent any subsequent query from reopening the panel
61
+ // because it would result in an unsolicited UI behavior.
62
+
63
+ if (!props.debug && onInput.isRunning()) {
64
+ store.shouldSkipPendingUpdate = true;
65
+ }
51
66
  }
52
67
  },
53
68
  // When scrolling on touch devices (mobiles, tablets, etc.), we want to
@@ -173,7 +188,14 @@ export function getPropGetters(_ref) {
173
188
  // We do rely on the `blur` event on touch devices.
174
189
  // See explanation in `onTouchStart`.
175
190
  if (!isTouchDevice) {
176
- store.dispatch('blur', null);
191
+ store.dispatch('blur', null); // If requests are still running when the user closes the panel, they
192
+ // could reopen the panel once they resolve.
193
+ // We want to prevent any subsequent query from reopening the panel
194
+ // because it would result in an unsolicited UI behavior.
195
+
196
+ if (!props.debug && onInput.isRunning()) {
197
+ store.shouldSkipPendingUpdate = true;
198
+ }
177
199
  }
178
200
  },
179
201
  onClick: function onClick(event) {
@@ -14,4 +14,7 @@ interface OnInputParams<TItem extends BaseItem> extends AutocompleteScopeApi<TIt
14
14
  store: AutocompleteStore<TItem>;
15
15
  }
16
16
  export declare function onInput<TItem extends BaseItem>({ event, nextState, props, query, refresh, store, ...setters }: OnInputParams<TItem>): Promise<void>;
17
+ export declare namespace onInput {
18
+ var isRunning: () => boolean;
19
+ }
17
20
  export {};
@@ -94,7 +94,20 @@ export function onInput(_ref) {
94
94
  })).then(function (collections) {
95
95
  var _nextState$isOpen2;
96
96
 
97
+ // Parameters passed to `onInput` could be stale when the following code
98
+ // executes, because `onInput` calls may not resolve in order.
99
+ // If it becomes a problem we'll need to save the last passed parameters.
100
+ // See: https://codesandbox.io/s/agitated-cookies-y290z
97
101
  setStatus('idle');
102
+
103
+ if (store.shouldSkipPendingUpdate) {
104
+ if (!runConcurrentSafePromise.isRunning()) {
105
+ store.shouldSkipPendingUpdate = false;
106
+ }
107
+
108
+ return;
109
+ }
110
+
98
111
  setCollections(collections);
99
112
  var isPanelOpen = props.shouldPanelOpen({
100
113
  state: store.getState()
@@ -122,4 +135,5 @@ export function onInput(_ref) {
122
135
  props.environment.clearTimeout(lastStalledId);
123
136
  }
124
137
  });
125
- }
138
+ }
139
+ onInput.isRunning = runConcurrentSafePromise.isRunning;
@@ -86,7 +86,14 @@ export function onKeyDown(_ref) {
86
86
  // from removing the query right away because we first want to close the
87
87
  // panel.
88
88
  event.preventDefault();
89
- store.dispatch(event.key, null);
89
+ store.dispatch(event.key, null); // Hitting the `Escape` key signals the end of a user interaction with the
90
+ // autocomplete. At this point, we should ignore any requests that are still
91
+ // running and could reopen the panel once they resolve, because that would
92
+ // result in an unsolicited UI behavior.
93
+
94
+ if (onInput.isRunning()) {
95
+ store.shouldSkipPendingUpdate = true;
96
+ }
90
97
  } else if (event.key === 'Enter') {
91
98
  // No active item, so we let the browser handle the native `onSubmit` form
92
99
  // event.
@@ -4,6 +4,7 @@ import { AutocompleteState } from './AutocompleteState';
4
4
  export interface AutocompleteStore<TItem extends BaseItem> {
5
5
  getState(): AutocompleteState<TItem>;
6
6
  dispatch(action: ActionType, payload: any): void;
7
+ shouldSkipPendingUpdate: boolean;
7
8
  }
8
9
  export declare type Reducer = <TItem extends BaseItem>(state: AutocompleteState<TItem>, action: Action<TItem, any>) => AutocompleteState<TItem>;
9
10
  declare type Action<TItem extends BaseItem, TPayload> = {
@@ -5,4 +5,7 @@ import { MaybePromise } from '@algolia/autocomplete-shared';
5
5
  * This is useful to prevent older promises to resolve after a newer promise,
6
6
  * otherwise resulting in stale resolved values.
7
7
  */
8
- export declare function createConcurrentSafePromise(): <TValue>(promise: MaybePromise<TValue>) => Promise<TValue>;
8
+ export declare function createConcurrentSafePromise(): {
9
+ <TValue>(promise: MaybePromise<TValue>): Promise<TValue>;
10
+ isRunning(): boolean;
11
+ };
@@ -8,8 +8,11 @@ export function createConcurrentSafePromise() {
8
8
  var basePromiseId = -1;
9
9
  var latestResolvedId = -1;
10
10
  var latestResolvedValue = undefined;
11
- return function runConcurrentSafePromise(promise) {
11
+ var runningPromisesCount = 0;
12
+
13
+ function runConcurrentSafePromise(promise) {
12
14
  basePromiseId++;
15
+ runningPromisesCount++;
13
16
  var currentPromiseId = basePromiseId;
14
17
  return Promise.resolve(promise).then(function (x) {
15
18
  // The promise might take too long to resolve and get outdated. This would
@@ -32,6 +35,14 @@ export function createConcurrentSafePromise() {
32
35
  latestResolvedId = currentPromiseId;
33
36
  latestResolvedValue = x;
34
37
  return x;
38
+ }).finally(function () {
39
+ return runningPromisesCount--;
35
40
  });
41
+ }
42
+
43
+ runConcurrentSafePromise.isRunning = function () {
44
+ return runningPromisesCount > 0;
36
45
  };
46
+
47
+ return runConcurrentSafePromise;
37
48
  }
@@ -1,9 +1,9 @@
1
- /*! @algolia/autocomplete-core 1.5.0 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */
1
+ /*! @algolia/autocomplete-core 1.5.1 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
5
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['@algolia/autocomplete-core'] = {}));
6
- }(this, (function (exports) { 'use strict';
5
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@algolia/autocomplete-core"] = {}));
6
+ })(this, (function (exports) { 'use strict';
7
7
 
8
8
  function ownKeys(object, enumerableOnly) {
9
9
  var keys = Object.keys(object);
@@ -43,20 +43,20 @@
43
43
  return target;
44
44
  }
45
45
 
46
- function _typeof(obj) {
46
+ function _typeof$1(obj) {
47
47
  "@babel/helpers - typeof";
48
48
 
49
49
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
50
- _typeof = function (obj) {
50
+ _typeof$1 = function (obj) {
51
51
  return typeof obj;
52
52
  };
53
53
  } else {
54
- _typeof = function (obj) {
54
+ _typeof$1 = function (obj) {
55
55
  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
56
56
  };
57
57
  }
58
58
 
59
- return _typeof(obj);
59
+ return _typeof$1(obj);
60
60
  }
61
61
 
62
62
  function _defineProperty(obj, key, value) {
@@ -111,27 +111,27 @@
111
111
  }
112
112
 
113
113
  function _toConsumableArray(arr) {
114
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
114
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread();
115
115
  }
116
116
 
117
117
  function _arrayWithoutHoles(arr) {
118
- if (Array.isArray(arr)) return _arrayLikeToArray(arr);
118
+ if (Array.isArray(arr)) return _arrayLikeToArray$1(arr);
119
119
  }
120
120
 
121
121
  function _iterableToArray(iter) {
122
122
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
123
123
  }
124
124
 
125
- function _unsupportedIterableToArray(o, minLen) {
125
+ function _unsupportedIterableToArray$1(o, minLen) {
126
126
  if (!o) return;
127
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
127
+ if (typeof o === "string") return _arrayLikeToArray$1(o, minLen);
128
128
  var n = Object.prototype.toString.call(o).slice(8, -1);
129
129
  if (n === "Object" && o.constructor) n = o.constructor.name;
130
130
  if (n === "Map" || n === "Set") return Array.from(o);
131
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
131
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen);
132
132
  }
133
133
 
134
- function _arrayLikeToArray(arr, len) {
134
+ function _arrayLikeToArray$1(arr, len) {
135
135
  if (len == null || len > arr.length) len = arr.length;
136
136
 
137
137
  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
@@ -144,23 +144,23 @@
144
144
  }
145
145
 
146
146
  function _slicedToArray(arr, i) {
147
- return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray$1(arr, i) || _nonIterableRest();
147
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
148
148
  }
149
149
 
150
150
  function _nonIterableRest() {
151
151
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
152
152
  }
153
153
 
154
- function _unsupportedIterableToArray$1(o, minLen) {
154
+ function _unsupportedIterableToArray(o, minLen) {
155
155
  if (!o) return;
156
- if (typeof o === "string") return _arrayLikeToArray$1(o, minLen);
156
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
157
157
  var n = Object.prototype.toString.call(o).slice(8, -1);
158
158
  if (n === "Object" && o.constructor) n = o.constructor.name;
159
159
  if (n === "Map" || n === "Set") return Array.from(o);
160
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen);
160
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
161
161
  }
162
162
 
163
- function _arrayLikeToArray$1(arr, len) {
163
+ function _arrayLikeToArray(arr, len) {
164
164
  if (len == null || len > arr.length) len = arr.length;
165
165
 
166
166
  for (var i = 0, arr2 = new Array(len); i < len; i++) {
@@ -204,20 +204,20 @@
204
204
  if (Array.isArray(arr)) return arr;
205
205
  }
206
206
 
207
- function _typeof$1(obj) {
207
+ function _typeof(obj) {
208
208
  "@babel/helpers - typeof";
209
209
 
210
210
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
211
- _typeof$1 = function _typeof(obj) {
211
+ _typeof = function _typeof(obj) {
212
212
  return typeof obj;
213
213
  };
214
214
  } else {
215
- _typeof$1 = function _typeof(obj) {
215
+ _typeof = function _typeof(obj) {
216
216
  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
217
217
  };
218
218
  }
219
219
 
220
- return _typeof$1(obj);
220
+ return _typeof(obj);
221
221
  }
222
222
  /**
223
223
  * Decycles objects with circular references.
@@ -228,7 +228,7 @@
228
228
  function decycle(obj) {
229
229
  var seen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
230
230
 
231
- if ( !obj || _typeof$1(obj) !== 'object') {
231
+ if (!obj || _typeof(obj) !== 'object') {
232
232
  return obj;
233
233
  }
234
234
 
@@ -288,7 +288,7 @@
288
288
 
289
289
  var noop = function noop() {};
290
290
 
291
- var version = '1.5.0';
291
+ var version = '1.5.1';
292
292
 
293
293
  var userAgents = [{
294
294
  segment: 'autocomplete-core',
@@ -341,7 +341,8 @@
341
341
  state: state,
342
342
  prevState: prevState
343
343
  });
344
- }
344
+ },
345
+ shouldSkipPendingUpdate: false
345
346
  };
346
347
  }
347
348
 
@@ -404,8 +405,11 @@
404
405
  var basePromiseId = -1;
405
406
  var latestResolvedId = -1;
406
407
  var latestResolvedValue = undefined;
407
- return function runConcurrentSafePromise(promise) {
408
+ var runningPromisesCount = 0;
409
+
410
+ function runConcurrentSafePromise(promise) {
408
411
  basePromiseId++;
412
+ runningPromisesCount++;
409
413
  var currentPromiseId = basePromiseId;
410
414
  return Promise.resolve(promise).then(function (x) {
411
415
  // The promise might take too long to resolve and get outdated. This would
@@ -428,8 +432,16 @@
428
432
  latestResolvedId = currentPromiseId;
429
433
  latestResolvedValue = x;
430
434
  return x;
435
+ }).finally(function () {
436
+ return runningPromisesCount--;
431
437
  });
438
+ }
439
+
440
+ runConcurrentSafePromise.isRunning = function () {
441
+ return runningPromisesCount > 0;
432
442
  };
443
+
444
+ return runConcurrentSafePromise;
433
445
  }
434
446
 
435
447
  /**
@@ -470,7 +482,7 @@
470
482
  var seenSourceIds = [];
471
483
  return Promise.resolve(getSources(params)).then(function (sources) {
472
484
  invariant(Array.isArray(sources), function () {
473
- return "The `getSources` function must return an array of sources but returned type ".concat(JSON.stringify(_typeof(sources)), ":\n\n").concat(JSON.stringify(decycle(sources), null, 2));
485
+ return "The `getSources` function must return an array of sources but returned type ".concat(JSON.stringify(_typeof$1(sources)), ":\n\n").concat(JSON.stringify(decycle(sources), null, 2));
474
486
  });
475
487
  return Promise.all(sources // We allow `undefined` and `false` sources to allow users to use
476
488
  // `Boolean(query) && source` (=> `false`).
@@ -864,7 +876,7 @@
864
876
  var transform = matches[0].transformResponse;
865
877
  var items = transform ? transform(mapToAlgoliaResponse(results)) : results;
866
878
  invariant(Array.isArray(items), function () {
867
- return "The `getItems` function from source \"".concat(source.sourceId, "\" must return an array of items but returned type ").concat(JSON.stringify(_typeof(items)), ":\n\n").concat(JSON.stringify(decycle(items), null, 2), ".\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems");
879
+ return "The `getItems` function from source \"".concat(source.sourceId, "\" must return an array of items but returned type ").concat(JSON.stringify(_typeof$1(items)), ":\n\n").concat(JSON.stringify(decycle(items), null, 2), ".\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems");
868
880
  });
869
881
  invariant(items.every(Boolean), "The `getItems` function from source \"".concat(source.sourceId, "\" must return an array of items but returned ").concat(JSON.stringify(undefined), ".\n\nDid you forget to return items?\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems"));
870
882
  return {
@@ -874,7 +886,7 @@
874
886
  });
875
887
  }
876
888
 
877
- var _excluded = ["event", "nextState", "props", "query", "refresh", "store"];
889
+ var _excluded$2 = ["event", "nextState", "props", "query", "refresh", "store"];
878
890
  var lastStalledId = null;
879
891
  var runConcurrentSafePromise = createConcurrentSafePromise();
880
892
  function onInput(_ref) {
@@ -885,7 +897,7 @@
885
897
  query = _ref.query,
886
898
  refresh = _ref.refresh,
887
899
  store = _ref.store,
888
- setters = _objectWithoutProperties(_ref, _excluded);
900
+ setters = _objectWithoutProperties(_ref, _excluded$2);
889
901
 
890
902
  if (lastStalledId) {
891
903
  props.environment.clearTimeout(lastStalledId);
@@ -956,7 +968,20 @@
956
968
  })).then(function (collections) {
957
969
  var _nextState$isOpen2;
958
970
 
971
+ // Parameters passed to `onInput` could be stale when the following code
972
+ // executes, because `onInput` calls may not resolve in order.
973
+ // If it becomes a problem we'll need to save the last passed parameters.
974
+ // See: https://codesandbox.io/s/agitated-cookies-y290z
959
975
  setStatus('idle');
976
+
977
+ if (store.shouldSkipPendingUpdate) {
978
+ if (!runConcurrentSafePromise.isRunning()) {
979
+ store.shouldSkipPendingUpdate = false;
980
+ }
981
+
982
+ return;
983
+ }
984
+
960
985
  setCollections(collections);
961
986
  var isPanelOpen = props.shouldPanelOpen({
962
987
  state: store.getState()
@@ -985,6 +1010,7 @@
985
1010
  }
986
1011
  });
987
1012
  }
1013
+ onInput.isRunning = runConcurrentSafePromise.isRunning;
988
1014
 
989
1015
  var _excluded$1 = ["event", "props", "refresh", "store"];
990
1016
  function onKeyDown(_ref) {
@@ -1061,7 +1087,14 @@
1061
1087
  // from removing the query right away because we first want to close the
1062
1088
  // panel.
1063
1089
  event.preventDefault();
1064
- store.dispatch(event.key, null);
1090
+ store.dispatch(event.key, null); // Hitting the `Escape` key signals the end of a user interaction with the
1091
+ // autocomplete. At this point, we should ignore any requests that are still
1092
+ // running and could reopen the panel once they resolve, because that would
1093
+ // result in an unsolicited UI behavior.
1094
+
1095
+ if (onInput.isRunning()) {
1096
+ store.shouldSkipPendingUpdate = true;
1097
+ }
1065
1098
  } else if (event.key === 'Enter') {
1066
1099
  // No active item, so we let the browser handle the native `onSubmit` form
1067
1100
  // event.
@@ -1158,7 +1191,7 @@
1158
1191
  }
1159
1192
  }
1160
1193
 
1161
- var _excluded$2 = ["props", "refresh", "store"],
1194
+ var _excluded = ["props", "refresh", "store"],
1162
1195
  _excluded2 = ["inputElement", "formElement", "panelElement"],
1163
1196
  _excluded3 = ["inputElement"],
1164
1197
  _excluded4 = ["inputElement", "maxLength"],
@@ -1167,7 +1200,7 @@
1167
1200
  var props = _ref.props,
1168
1201
  refresh = _ref.refresh,
1169
1202
  store = _ref.store,
1170
- setters = _objectWithoutProperties(_ref, _excluded$2);
1203
+ setters = _objectWithoutProperties(_ref, _excluded);
1171
1204
 
1172
1205
  var getEnvironmentProps = function getEnvironmentProps(providedProps) {
1173
1206
  var inputElement = providedProps.inputElement,
@@ -1184,7 +1217,15 @@
1184
1217
  // @TODO: support cases where there are multiple Autocomplete instances.
1185
1218
  // Right now, a second instance makes this computation return false.
1186
1219
  onTouchStart: function onTouchStart(event) {
1187
- if (store.getState().isOpen === false || event.target === inputElement) {
1220
+ // The `onTouchStart` event shouldn't trigger the `blur` handler when
1221
+ // it's not an interaction with Autocomplete. We detect it with the
1222
+ // following heuristics:
1223
+ // - the panel is closed AND there are no running requests
1224
+ // (no interaction with the autocomplete, no future state updates)
1225
+ // - OR the touched target is the input element (should open the panel)
1226
+ var isNotAutocompleteInteraction = store.getState().isOpen === false && !onInput.isRunning();
1227
+
1228
+ if (isNotAutocompleteInteraction || event.target === inputElement) {
1188
1229
  return;
1189
1230
  }
1190
1231
 
@@ -1193,7 +1234,14 @@
1193
1234
  });
1194
1235
 
1195
1236
  if (isTargetWithinAutocomplete === false) {
1196
- store.dispatch('blur', null);
1237
+ store.dispatch('blur', null); // If requests are still running when the user closes the panel, they
1238
+ // could reopen the panel once they resolve.
1239
+ // We want to prevent any subsequent query from reopening the panel
1240
+ // because it would result in an unsolicited UI behavior.
1241
+
1242
+ if (!props.debug && onInput.isRunning()) {
1243
+ store.shouldSkipPendingUpdate = true;
1244
+ }
1197
1245
  }
1198
1246
  },
1199
1247
  // When scrolling on touch devices (mobiles, tablets, etc.), we want to
@@ -1221,8 +1269,8 @@
1221
1269
  };
1222
1270
 
1223
1271
  var getFormProps = function getFormProps(providedProps) {
1224
- var inputElement = providedProps.inputElement,
1225
- rest = _objectWithoutProperties(providedProps, _excluded3);
1272
+ providedProps.inputElement;
1273
+ var rest = _objectWithoutProperties(providedProps, _excluded3);
1226
1274
 
1227
1275
  return _objectSpread2({
1228
1276
  action: '',
@@ -1274,9 +1322,9 @@
1274
1322
 
1275
1323
  var isTouchDevice = ('ontouchstart' in props.environment);
1276
1324
 
1277
- var _ref2 = providedProps || {},
1278
- inputElement = _ref2.inputElement,
1279
- _ref2$maxLength = _ref2.maxLength,
1325
+ var _ref2 = providedProps || {};
1326
+ _ref2.inputElement;
1327
+ var _ref2$maxLength = _ref2.maxLength,
1280
1328
  maxLength = _ref2$maxLength === void 0 ? 512 : _ref2$maxLength,
1281
1329
  rest = _objectWithoutProperties(_ref2, _excluded4);
1282
1330
 
@@ -1319,7 +1367,14 @@
1319
1367
  // We do rely on the `blur` event on touch devices.
1320
1368
  // See explanation in `onTouchStart`.
1321
1369
  if (!isTouchDevice) {
1322
- store.dispatch('blur', null);
1370
+ store.dispatch('blur', null); // If requests are still running when the user closes the panel, they
1371
+ // could reopen the panel once they resolve.
1372
+ // We want to prevent any subsequent query from reopening the panel
1373
+ // because it would result in an unsolicited UI behavior.
1374
+
1375
+ if (!props.debug && onInput.isRunning()) {
1376
+ store.shouldSkipPendingUpdate = true;
1377
+ }
1323
1378
  }
1324
1379
  },
1325
1380
  onClick: function onClick(event) {
@@ -1730,5 +1785,5 @@
1730
1785
 
1731
1786
  Object.defineProperty(exports, '__esModule', { value: true });
1732
1787
 
1733
- })));
1788
+ }));
1734
1789
  //# sourceMappingURL=index.development.js.map