@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.
- package/dist/esm/createStore.js +2 -1
- package/dist/esm/getPropGetters.js +25 -3
- package/dist/esm/onInput.d.ts +3 -0
- package/dist/esm/onInput.js +15 -1
- package/dist/esm/onKeyDown.js +8 -1
- package/dist/esm/types/AutocompleteStore.d.ts +1 -0
- package/dist/esm/utils/createConcurrentSafePromise.d.ts +4 -1
- package/dist/esm/utils/createConcurrentSafePromise.js +12 -1
- package/dist/umd/index.development.js +97 -42
- package/dist/umd/index.development.js.map +1 -1
- package/dist/umd/index.production.js +2 -2
- package/dist/umd/index.production.js.map +1 -1
- package/package.json +3 -3
package/dist/esm/createStore.js
CHANGED
|
@@ -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
|
-
|
|
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) {
|
package/dist/esm/onInput.d.ts
CHANGED
|
@@ -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 {};
|
package/dist/esm/onInput.js
CHANGED
|
@@ -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;
|
package/dist/esm/onKeyDown.js
CHANGED
|
@@ -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():
|
|
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
|
-
|
|
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.
|
|
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[
|
|
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
|
|
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
|
|
154
|
+
function _unsupportedIterableToArray(o, minLen) {
|
|
155
155
|
if (!o) return;
|
|
156
|
-
if (typeof o === "string") return _arrayLikeToArray
|
|
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
|
|
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
|
|
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
|
|
207
|
+
function _typeof(obj) {
|
|
208
208
|
"@babel/helpers - typeof";
|
|
209
209
|
|
|
210
210
|
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
211
|
-
_typeof
|
|
211
|
+
_typeof = function _typeof(obj) {
|
|
212
212
|
return typeof obj;
|
|
213
213
|
};
|
|
214
214
|
} else {
|
|
215
|
-
_typeof
|
|
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
|
|
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 (
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|