@algolia/autocomplete-core 1.5.1 → 1.5.2
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 +9 -9
- package/dist/esm/onInput.d.ts +2 -4
- package/dist/esm/onInput.js +11 -16
- package/dist/esm/onKeyDown.js +2 -4
- package/dist/esm/types/AutocompleteStore.d.ts +2 -1
- package/dist/esm/utils/createCancelablePromise.d.ts +15 -0
- package/dist/esm/utils/createCancelablePromise.js +70 -0
- package/dist/esm/utils/createCancelablePromiseList.d.ts +7 -0
- package/dist/esm/utils/createCancelablePromiseList.js +21 -0
- package/dist/esm/utils/createConcurrentSafePromise.d.ts +1 -4
- package/dist/esm/utils/createConcurrentSafePromise.js +1 -12
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/index.js +2 -0
- package/dist/umd/index.development.js +154 -96
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @algolia/autocomplete-core 1.5.
|
|
1
|
+
/*! @algolia/autocomplete-core 1.5.2 | 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) :
|
|
@@ -288,7 +288,7 @@
|
|
|
288
288
|
|
|
289
289
|
var noop = function noop() {};
|
|
290
290
|
|
|
291
|
-
var version = '1.5.
|
|
291
|
+
var version = '1.5.2';
|
|
292
292
|
|
|
293
293
|
var userAgents = [{
|
|
294
294
|
segment: 'autocomplete-core',
|
|
@@ -323,75 +323,79 @@
|
|
|
323
323
|
"development" !== 'production' ? warn(!options.debug, 'The `debug` option is meant for development debugging and should not be used in production.') : void 0;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
function
|
|
327
|
-
var state =
|
|
326
|
+
function createInternalCancelablePromise(promise, initialState) {
|
|
327
|
+
var state = initialState;
|
|
328
328
|
return {
|
|
329
|
-
|
|
330
|
-
return state;
|
|
329
|
+
then: function then(onfulfilled, onrejected) {
|
|
330
|
+
return createInternalCancelablePromise(promise.then(createCallback(onfulfilled, state, promise), createCallback(onrejected, state, promise)), state);
|
|
331
331
|
},
|
|
332
|
-
|
|
333
|
-
|
|
332
|
+
catch: function _catch(onrejected) {
|
|
333
|
+
return createInternalCancelablePromise(promise.catch(createCallback(onrejected, state, promise)), state);
|
|
334
|
+
},
|
|
335
|
+
finally: function _finally(onfinally) {
|
|
336
|
+
if (onfinally) {
|
|
337
|
+
state.onCancelList.push(onfinally);
|
|
338
|
+
}
|
|
334
339
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
340
|
+
return createInternalCancelablePromise(promise.finally(createCallback(onfinally && function () {
|
|
341
|
+
state.onCancelList = [];
|
|
342
|
+
return onfinally();
|
|
343
|
+
}, state, promise)), state);
|
|
344
|
+
},
|
|
345
|
+
cancel: function cancel() {
|
|
346
|
+
state.isCanceled = true;
|
|
347
|
+
var callbacks = state.onCancelList;
|
|
348
|
+
state.onCancelList = [];
|
|
349
|
+
callbacks.forEach(function (callback) {
|
|
350
|
+
callback();
|
|
343
351
|
});
|
|
344
352
|
},
|
|
345
|
-
|
|
353
|
+
isCanceled: function isCanceled() {
|
|
354
|
+
return state.isCanceled === true;
|
|
355
|
+
}
|
|
346
356
|
};
|
|
347
357
|
}
|
|
348
358
|
|
|
349
|
-
function
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
var setQuery = function setQuery(value) {
|
|
357
|
-
store.dispatch('setQuery', value);
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
var setCollections = function setCollections(rawValue) {
|
|
361
|
-
var baseItemId = 0;
|
|
362
|
-
var value = rawValue.map(function (collection) {
|
|
363
|
-
return _objectSpread2(_objectSpread2({}, collection), {}, {
|
|
364
|
-
// We flatten the stored items to support calling `getAlgoliaResults`
|
|
365
|
-
// from the source itself.
|
|
366
|
-
items: flatten(collection.items).map(function (item) {
|
|
367
|
-
return _objectSpread2(_objectSpread2({}, item), {}, {
|
|
368
|
-
__autocomplete_id: baseItemId++
|
|
369
|
-
});
|
|
370
|
-
})
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
store.dispatch('setCollections', value);
|
|
374
|
-
};
|
|
359
|
+
function cancelable(promise) {
|
|
360
|
+
return createInternalCancelablePromise(promise, {
|
|
361
|
+
isCanceled: false,
|
|
362
|
+
onCancelList: []
|
|
363
|
+
});
|
|
364
|
+
}
|
|
375
365
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
366
|
+
function createCallback(onResult, state, fallback) {
|
|
367
|
+
if (!onResult) {
|
|
368
|
+
return fallback;
|
|
369
|
+
}
|
|
379
370
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
371
|
+
return function callback(arg) {
|
|
372
|
+
if (state.isCanceled) {
|
|
373
|
+
return arg;
|
|
374
|
+
}
|
|
383
375
|
|
|
384
|
-
|
|
385
|
-
store.dispatch('setContext', value);
|
|
376
|
+
return onResult(arg);
|
|
386
377
|
};
|
|
378
|
+
}
|
|
387
379
|
|
|
380
|
+
function createCancelablePromiseList() {
|
|
381
|
+
var list = [];
|
|
388
382
|
return {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
383
|
+
add: function add(cancelablePromise) {
|
|
384
|
+
list.push(cancelablePromise);
|
|
385
|
+
return cancelablePromise.finally(function () {
|
|
386
|
+
list = list.filter(function (item) {
|
|
387
|
+
return item !== cancelablePromise;
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
},
|
|
391
|
+
cancelAll: function cancelAll() {
|
|
392
|
+
list.forEach(function (promise) {
|
|
393
|
+
return promise.cancel();
|
|
394
|
+
});
|
|
395
|
+
},
|
|
396
|
+
isEmpty: function isEmpty() {
|
|
397
|
+
return list.length === 0;
|
|
398
|
+
}
|
|
395
399
|
};
|
|
396
400
|
}
|
|
397
401
|
|
|
@@ -405,11 +409,8 @@
|
|
|
405
409
|
var basePromiseId = -1;
|
|
406
410
|
var latestResolvedId = -1;
|
|
407
411
|
var latestResolvedValue = undefined;
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
function runConcurrentSafePromise(promise) {
|
|
412
|
+
return function runConcurrentSafePromise(promise) {
|
|
411
413
|
basePromiseId++;
|
|
412
|
-
runningPromisesCount++;
|
|
413
414
|
var currentPromiseId = basePromiseId;
|
|
414
415
|
return Promise.resolve(promise).then(function (x) {
|
|
415
416
|
// The promise might take too long to resolve and get outdated. This would
|
|
@@ -432,16 +433,8 @@
|
|
|
432
433
|
latestResolvedId = currentPromiseId;
|
|
433
434
|
latestResolvedValue = x;
|
|
434
435
|
return x;
|
|
435
|
-
}).finally(function () {
|
|
436
|
-
return runningPromisesCount--;
|
|
437
436
|
});
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
runConcurrentSafePromise.isRunning = function () {
|
|
441
|
-
return runningPromisesCount > 0;
|
|
442
437
|
};
|
|
443
|
-
|
|
444
|
-
return runConcurrentSafePromise;
|
|
445
438
|
}
|
|
446
439
|
|
|
447
440
|
/**
|
|
@@ -646,6 +639,78 @@
|
|
|
646
639
|
};
|
|
647
640
|
}
|
|
648
641
|
|
|
642
|
+
function createStore(reducer, props, onStoreStateChange) {
|
|
643
|
+
var state = props.initialState;
|
|
644
|
+
return {
|
|
645
|
+
getState: function getState() {
|
|
646
|
+
return state;
|
|
647
|
+
},
|
|
648
|
+
dispatch: function dispatch(action, payload) {
|
|
649
|
+
var prevState = _objectSpread2({}, state);
|
|
650
|
+
|
|
651
|
+
state = reducer(state, {
|
|
652
|
+
type: action,
|
|
653
|
+
props: props,
|
|
654
|
+
payload: payload
|
|
655
|
+
});
|
|
656
|
+
onStoreStateChange({
|
|
657
|
+
state: state,
|
|
658
|
+
prevState: prevState
|
|
659
|
+
});
|
|
660
|
+
},
|
|
661
|
+
pendingRequests: createCancelablePromiseList()
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function getAutocompleteSetters(_ref) {
|
|
666
|
+
var store = _ref.store;
|
|
667
|
+
|
|
668
|
+
var setActiveItemId = function setActiveItemId(value) {
|
|
669
|
+
store.dispatch('setActiveItemId', value);
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
var setQuery = function setQuery(value) {
|
|
673
|
+
store.dispatch('setQuery', value);
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
var setCollections = function setCollections(rawValue) {
|
|
677
|
+
var baseItemId = 0;
|
|
678
|
+
var value = rawValue.map(function (collection) {
|
|
679
|
+
return _objectSpread2(_objectSpread2({}, collection), {}, {
|
|
680
|
+
// We flatten the stored items to support calling `getAlgoliaResults`
|
|
681
|
+
// from the source itself.
|
|
682
|
+
items: flatten(collection.items).map(function (item) {
|
|
683
|
+
return _objectSpread2(_objectSpread2({}, item), {}, {
|
|
684
|
+
__autocomplete_id: baseItemId++
|
|
685
|
+
});
|
|
686
|
+
})
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
store.dispatch('setCollections', value);
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
var setIsOpen = function setIsOpen(value) {
|
|
693
|
+
store.dispatch('setIsOpen', value);
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
var setStatus = function setStatus(value) {
|
|
697
|
+
store.dispatch('setStatus', value);
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
var setContext = function setContext(value) {
|
|
701
|
+
store.dispatch('setContext', value);
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
return {
|
|
705
|
+
setActiveItemId: setActiveItemId,
|
|
706
|
+
setQuery: setQuery,
|
|
707
|
+
setCollections: setCollections,
|
|
708
|
+
setIsOpen: setIsOpen,
|
|
709
|
+
setStatus: setStatus,
|
|
710
|
+
setContext: setContext
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
|
|
649
714
|
function getDefaultProps(props, pluginSubscribers) {
|
|
650
715
|
var _props$id;
|
|
651
716
|
|
|
@@ -928,9 +993,11 @@
|
|
|
928
993
|
// updates performed in this code path.
|
|
929
994
|
// We chain with a void promise to respect `onInput`'s expected return type.
|
|
930
995
|
|
|
931
|
-
|
|
996
|
+
var _request = cancelable(runConcurrentSafePromise(collections).then(function () {
|
|
932
997
|
return Promise.resolve();
|
|
933
|
-
});
|
|
998
|
+
}));
|
|
999
|
+
|
|
1000
|
+
return store.pendingRequests.add(_request);
|
|
934
1001
|
}
|
|
935
1002
|
|
|
936
1003
|
setStatus('loading');
|
|
@@ -943,7 +1010,7 @@
|
|
|
943
1010
|
// meaning we should only ever manipulate the state once this concurrent-safe
|
|
944
1011
|
// promise is resolved.
|
|
945
1012
|
|
|
946
|
-
|
|
1013
|
+
var request = cancelable(runConcurrentSafePromise(props.getSources(_objectSpread2({
|
|
947
1014
|
query: query,
|
|
948
1015
|
refresh: refresh,
|
|
949
1016
|
state: store.getState()
|
|
@@ -965,7 +1032,7 @@
|
|
|
965
1032
|
state: store.getState()
|
|
966
1033
|
});
|
|
967
1034
|
});
|
|
968
|
-
})).then(function (collections) {
|
|
1035
|
+
}))).then(function (collections) {
|
|
969
1036
|
var _nextState$isOpen2;
|
|
970
1037
|
|
|
971
1038
|
// Parameters passed to `onInput` could be stale when the following code
|
|
@@ -973,15 +1040,6 @@
|
|
|
973
1040
|
// If it becomes a problem we'll need to save the last passed parameters.
|
|
974
1041
|
// See: https://codesandbox.io/s/agitated-cookies-y290z
|
|
975
1042
|
setStatus('idle');
|
|
976
|
-
|
|
977
|
-
if (store.shouldSkipPendingUpdate) {
|
|
978
|
-
if (!runConcurrentSafePromise.isRunning()) {
|
|
979
|
-
store.shouldSkipPendingUpdate = false;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
return;
|
|
983
|
-
}
|
|
984
|
-
|
|
985
1043
|
setCollections(collections);
|
|
986
1044
|
var isPanelOpen = props.shouldPanelOpen({
|
|
987
1045
|
state: store.getState()
|
|
@@ -1005,12 +1063,14 @@
|
|
|
1005
1063
|
}, setters));
|
|
1006
1064
|
}
|
|
1007
1065
|
}).finally(function () {
|
|
1066
|
+
setStatus('idle');
|
|
1067
|
+
|
|
1008
1068
|
if (lastStalledId) {
|
|
1009
1069
|
props.environment.clearTimeout(lastStalledId);
|
|
1010
1070
|
}
|
|
1011
1071
|
});
|
|
1072
|
+
return store.pendingRequests.add(request);
|
|
1012
1073
|
}
|
|
1013
|
-
onInput.isRunning = runConcurrentSafePromise.isRunning;
|
|
1014
1074
|
|
|
1015
1075
|
var _excluded$1 = ["event", "props", "refresh", "store"];
|
|
1016
1076
|
function onKeyDown(_ref) {
|
|
@@ -1089,12 +1149,10 @@
|
|
|
1089
1149
|
event.preventDefault();
|
|
1090
1150
|
store.dispatch(event.key, null); // Hitting the `Escape` key signals the end of a user interaction with the
|
|
1091
1151
|
// autocomplete. At this point, we should ignore any requests that are still
|
|
1092
|
-
//
|
|
1152
|
+
// pending and could reopen the panel once they resolve, because that would
|
|
1093
1153
|
// result in an unsolicited UI behavior.
|
|
1094
1154
|
|
|
1095
|
-
|
|
1096
|
-
store.shouldSkipPendingUpdate = true;
|
|
1097
|
-
}
|
|
1155
|
+
store.pendingRequests.cancelAll();
|
|
1098
1156
|
} else if (event.key === 'Enter') {
|
|
1099
1157
|
// No active item, so we let the browser handle the native `onSubmit` form
|
|
1100
1158
|
// event.
|
|
@@ -1220,12 +1278,12 @@
|
|
|
1220
1278
|
// The `onTouchStart` event shouldn't trigger the `blur` handler when
|
|
1221
1279
|
// it's not an interaction with Autocomplete. We detect it with the
|
|
1222
1280
|
// following heuristics:
|
|
1223
|
-
// - the panel is closed AND there are no
|
|
1281
|
+
// - the panel is closed AND there are no pending requests
|
|
1224
1282
|
// (no interaction with the autocomplete, no future state updates)
|
|
1225
1283
|
// - OR the touched target is the input element (should open the panel)
|
|
1226
|
-
var
|
|
1284
|
+
var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
|
|
1227
1285
|
|
|
1228
|
-
if (
|
|
1286
|
+
if (!isAutocompleteInteraction || event.target === inputElement) {
|
|
1229
1287
|
return;
|
|
1230
1288
|
}
|
|
1231
1289
|
|
|
@@ -1234,13 +1292,13 @@
|
|
|
1234
1292
|
});
|
|
1235
1293
|
|
|
1236
1294
|
if (isTargetWithinAutocomplete === false) {
|
|
1237
|
-
store.dispatch('blur', null); // If requests are still
|
|
1295
|
+
store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
|
|
1238
1296
|
// could reopen the panel once they resolve.
|
|
1239
1297
|
// We want to prevent any subsequent query from reopening the panel
|
|
1240
1298
|
// because it would result in an unsolicited UI behavior.
|
|
1241
1299
|
|
|
1242
|
-
if (!props.debug
|
|
1243
|
-
store.
|
|
1300
|
+
if (!props.debug) {
|
|
1301
|
+
store.pendingRequests.cancelAll();
|
|
1244
1302
|
}
|
|
1245
1303
|
}
|
|
1246
1304
|
},
|
|
@@ -1367,13 +1425,13 @@
|
|
|
1367
1425
|
// We do rely on the `blur` event on touch devices.
|
|
1368
1426
|
// See explanation in `onTouchStart`.
|
|
1369
1427
|
if (!isTouchDevice) {
|
|
1370
|
-
store.dispatch('blur', null); // If requests are still
|
|
1428
|
+
store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
|
|
1371
1429
|
// could reopen the panel once they resolve.
|
|
1372
1430
|
// We want to prevent any subsequent query from reopening the panel
|
|
1373
1431
|
// because it would result in an unsolicited UI behavior.
|
|
1374
1432
|
|
|
1375
|
-
if (!props.debug
|
|
1376
|
-
store.
|
|
1433
|
+
if (!props.debug) {
|
|
1434
|
+
store.pendingRequests.cancelAll();
|
|
1377
1435
|
}
|
|
1378
1436
|
}
|
|
1379
1437
|
},
|