@algolia/autocomplete-core 1.18.1 → 1.19.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.
@@ -15,7 +15,7 @@ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) r
15
15
  import { noop } from '@algolia/autocomplete-shared';
16
16
  import { onInput } from './onInput';
17
17
  import { onKeyDown as _onKeyDown } from './onKeyDown';
18
- import { getActiveItem, getAutocompleteElementId, isOrContainsNode, isSamsung, getNativeEvent } from './utils';
18
+ import { getPluginSubmitPromise, getActiveItem, getAutocompleteElementId, isOrContainsNode, isSamsung, getNativeEvent } from './utils';
19
19
  export function getPropGetters(_ref) {
20
20
  var props = _ref.props,
21
21
  refresh = _ref.refresh,
@@ -94,20 +94,30 @@ export function getPropGetters(_ref) {
94
94
  var getFormProps = function getFormProps(providedProps) {
95
95
  var inputElement = providedProps.inputElement,
96
96
  rest = _objectWithoutProperties(providedProps, _excluded3);
97
+ var handleSubmit = function handleSubmit(event) {
98
+ var _providedProps$inputE;
99
+ props.onSubmit(_objectSpread({
100
+ event: event,
101
+ refresh: refresh,
102
+ state: store.getState()
103
+ }, setters));
104
+ store.dispatch('submit', null);
105
+ (_providedProps$inputE = providedProps.inputElement) === null || _providedProps$inputE === void 0 ? void 0 : _providedProps$inputE.blur();
106
+ };
97
107
  return _objectSpread({
98
108
  action: '',
99
109
  noValidate: true,
100
110
  role: 'search',
101
111
  onSubmit: function onSubmit(event) {
102
- var _providedProps$inputE;
103
112
  event.preventDefault();
104
- props.onSubmit(_objectSpread({
105
- event: event,
106
- refresh: refresh,
107
- state: store.getState()
108
- }, setters));
109
- store.dispatch('submit', null);
110
- (_providedProps$inputE = providedProps.inputElement) === null || _providedProps$inputE === void 0 ? void 0 : _providedProps$inputE.blur();
113
+ var waitForSubmit = getPluginSubmitPromise(props.plugins, store.pendingRequests);
114
+ if (waitForSubmit !== undefined) {
115
+ waitForSubmit.then(function () {
116
+ return handleSubmit(event);
117
+ });
118
+ } else {
119
+ handleSubmit(event);
120
+ }
111
121
  },
112
122
  onReset: function onReset(event) {
113
123
  var _providedProps$inputE2;
@@ -8,7 +8,7 @@ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input ==
8
8
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
9
9
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
10
10
  import { onInput } from './onInput';
11
- import { getActiveItem, getAutocompleteElementId } from './utils';
11
+ import { getPluginSubmitPromise, getActiveItem, getAutocompleteElementId } from './utils';
12
12
  export function onKeyDown(_ref) {
13
13
  var event = _ref.event,
14
14
  props = _ref.props,
@@ -99,11 +99,14 @@ export function onKeyDown(_ref) {
99
99
  if (store.getState().activeItemId === null || store.getState().collections.every(function (collection) {
100
100
  return collection.items.length === 0;
101
101
  })) {
102
- // If requests are still pending when the panel closes, they could reopen
103
- // the panel once they resolve.
104
- // We want to prevent any subsequent query from reopening the panel
105
- // because it would result in an unsolicited UI behavior.
106
- if (!props.debug) {
102
+ var waitForSubmit = getPluginSubmitPromise(props.plugins, store.pendingRequests);
103
+ if (waitForSubmit !== undefined) {
104
+ waitForSubmit.then(store.pendingRequests.cancelAll); // Cancel the rest if timeout number is provided
105
+ } else if (!props.debug) {
106
+ // If requests are still pending when the panel closes, they could reopen
107
+ // the panel once they resolve.
108
+ // We want to prevent any subsequent query from reopening the panel
109
+ // because it would result in an unsolicited UI behavior.
107
110
  store.pendingRequests.cancelAll();
108
111
  }
109
112
  return;
@@ -17,5 +17,11 @@ export declare type CancelablePromiseList<TValue> = {
17
17
  * Whether there are pending promises in the list.
18
18
  */
19
19
  isEmpty(): boolean;
20
+ /**
21
+ * Waits for all pending promises to be resolved.
22
+ *
23
+ * @param timeout Maximum amount of time allowed to wait for pending promises. Returns early if this time is reached.
24
+ */
25
+ wait(timeout?: number): Promise<void>;
20
26
  };
21
27
  export declare function createCancelablePromiseList<TValue>(): CancelablePromiseList<TValue>;
@@ -1,3 +1,6 @@
1
+ // Ensures multiple callers sync to the same promise.
2
+ var _hasWaitPromiseResolved = true;
3
+ var _waitPromise;
1
4
  export function createCancelablePromiseList() {
2
5
  var list = [];
3
6
  return {
@@ -16,6 +19,22 @@ export function createCancelablePromiseList() {
16
19
  },
17
20
  isEmpty: function isEmpty() {
18
21
  return list.length === 0;
22
+ },
23
+ wait: function wait(timeout) {
24
+ // Reuse promise if already exists. Keeps multiple callers subscribed to the same promise.
25
+ if (!_hasWaitPromiseResolved) {
26
+ return _waitPromise;
27
+ }
28
+
29
+ // Creates a promise which either resolves after all pending requests complete
30
+ // or the timeout is reached (if provided). Whichever comes first.
31
+ _hasWaitPromiseResolved = false;
32
+ _waitPromise = !timeout ? Promise.all(list) : Promise.race([Promise.all(list), new Promise(function (resolve) {
33
+ return setTimeout(resolve, timeout);
34
+ })]);
35
+ return _waitPromise.then(function () {
36
+ _hasWaitPromiseResolved = true;
37
+ });
19
38
  }
20
39
  };
21
40
  }
@@ -0,0 +1,8 @@
1
+ import type { InternalAutocompleteOptions } from '../types';
2
+ import { CancelablePromiseList } from './createCancelablePromiseList';
3
+ /**
4
+ * If a plugin is configured to await a submit event, this returns a promise
5
+ * for either the max timeout value found or until it completes.
6
+ * Otherwise, return undefined.
7
+ */
8
+ export declare const getPluginSubmitPromise: (plugins: InternalAutocompleteOptions<any>['plugins'], pendingRequests: CancelablePromiseList<void>) => Promise<void> | undefined;
@@ -0,0 +1,37 @@
1
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
2
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
3
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
4
+ /**
5
+ * If a plugin is configured to await a submit event, this returns a promise
6
+ * for either the max timeout value found or until it completes.
7
+ * Otherwise, return undefined.
8
+ */
9
+ export var getPluginSubmitPromise = function getPluginSubmitPromise(plugins, pendingRequests) {
10
+ var waitUntilComplete = false;
11
+ var timeouts = [];
12
+ var _iterator = _createForOfIteratorHelper(plugins),
13
+ _step;
14
+ try {
15
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
16
+ var _plugin$__autocomplet, _plugin$__autocomplet2, _plugin$__autocomplet3;
17
+ var plugin = _step.value;
18
+ var value = (_plugin$__autocomplet = plugin.__autocomplete_pluginOptions) === null || _plugin$__autocomplet === void 0 ? void 0 : (_plugin$__autocomplet2 = (_plugin$__autocomplet3 = _plugin$__autocomplet).awaitSubmit) === null || _plugin$__autocomplet2 === void 0 ? void 0 : _plugin$__autocomplet2.call(_plugin$__autocomplet3);
19
+ if (typeof value === 'number') {
20
+ timeouts.push(value);
21
+ } else if (value === true) {
22
+ waitUntilComplete = true;
23
+ break; // break loop as bool overrides num array below
24
+ }
25
+ }
26
+ } catch (err) {
27
+ _iterator.e(err);
28
+ } finally {
29
+ _iterator.f();
30
+ }
31
+ if (waitUntilComplete) {
32
+ return pendingRequests.wait();
33
+ } else if (timeouts.length > 0) {
34
+ return pendingRequests.wait(Math.max.apply(Math, timeouts));
35
+ }
36
+ return undefined;
37
+ };
@@ -3,6 +3,7 @@ export * from './createCancelablePromiseList';
3
3
  export * from './createConcurrentSafePromise';
4
4
  export * from './getNextActiveItemId';
5
5
  export * from './getNormalizedSources';
6
+ export * from './getPluginSubmitPromise';
6
7
  export * from './getActiveItem';
7
8
  export * from './getAutocompleteElementId';
8
9
  export * from './isOrContainsNode';
@@ -3,6 +3,7 @@ export * from './createCancelablePromiseList';
3
3
  export * from './createConcurrentSafePromise';
4
4
  export * from './getNextActiveItemId';
5
5
  export * from './getNormalizedSources';
6
+ export * from './getPluginSubmitPromise';
6
7
  export * from './getActiveItem';
7
8
  export * from './getAutocompleteElementId';
8
9
  export * from './isOrContainsNode';
@@ -1,4 +1,4 @@
1
- /*! @algolia/autocomplete-core 1.18.1 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */
1
+ /*! @algolia/autocomplete-core 1.19.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) :
@@ -101,6 +101,57 @@
101
101
  function _nonIterableSpread$2() {
102
102
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
103
103
  }
104
+ function _createForOfIteratorHelper(o, allowArrayLike) {
105
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
106
+ if (!it) {
107
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray$4(o)) || allowArrayLike && o && typeof o.length === "number") {
108
+ if (it) o = it;
109
+ var i = 0;
110
+ var F = function () {};
111
+ return {
112
+ s: F,
113
+ n: function () {
114
+ if (i >= o.length) return {
115
+ done: true
116
+ };
117
+ return {
118
+ done: false,
119
+ value: o[i++]
120
+ };
121
+ },
122
+ e: function (e) {
123
+ throw e;
124
+ },
125
+ f: F
126
+ };
127
+ }
128
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
129
+ }
130
+ var normalCompletion = true,
131
+ didErr = false,
132
+ err;
133
+ return {
134
+ s: function () {
135
+ it = it.call(o);
136
+ },
137
+ n: function () {
138
+ var step = it.next();
139
+ normalCompletion = step.done;
140
+ return step;
141
+ },
142
+ e: function (e) {
143
+ didErr = true;
144
+ err = e;
145
+ },
146
+ f: function () {
147
+ try {
148
+ if (!normalCompletion && it.return != null) it.return();
149
+ } finally {
150
+ if (didErr) throw err;
151
+ }
152
+ }
153
+ };
154
+ }
104
155
  function _toPrimitive$2(input, hint) {
105
156
  if (typeof input !== "object" || input === null) return input;
106
157
  var prim = input[Symbol.toPrimitive];
@@ -291,7 +342,7 @@
291
342
  return undefined;
292
343
  }
293
344
 
294
- var version = '1.18.1';
345
+ var version = '1.19.1';
295
346
 
296
347
  var userAgents = [{
297
348
  segment: 'autocomplete-core',
@@ -1090,6 +1141,9 @@
1090
1141
  };
1091
1142
  }
1092
1143
 
1144
+ // Ensures multiple callers sync to the same promise.
1145
+ var _hasWaitPromiseResolved = true;
1146
+ var _waitPromise;
1093
1147
  function createCancelablePromiseList() {
1094
1148
  var list = [];
1095
1149
  return {
@@ -1108,6 +1162,22 @@
1108
1162
  },
1109
1163
  isEmpty: function isEmpty() {
1110
1164
  return list.length === 0;
1165
+ },
1166
+ wait: function wait(timeout) {
1167
+ // Reuse promise if already exists. Keeps multiple callers subscribed to the same promise.
1168
+ if (!_hasWaitPromiseResolved) {
1169
+ return _waitPromise;
1170
+ }
1171
+
1172
+ // Creates a promise which either resolves after all pending requests complete
1173
+ // or the timeout is reached (if provided). Whichever comes first.
1174
+ _hasWaitPromiseResolved = false;
1175
+ _waitPromise = !timeout ? Promise.all(list) : Promise.race([Promise.all(list), new Promise(function (resolve) {
1176
+ return setTimeout(resolve, timeout);
1177
+ })]);
1178
+ return _waitPromise.then(function () {
1179
+ _hasWaitPromiseResolved = true;
1180
+ });
1111
1181
  }
1112
1182
  };
1113
1183
  }
@@ -1221,6 +1291,41 @@
1221
1291
  });
1222
1292
  }
1223
1293
 
1294
+ /**
1295
+ * If a plugin is configured to await a submit event, this returns a promise
1296
+ * for either the max timeout value found or until it completes.
1297
+ * Otherwise, return undefined.
1298
+ */
1299
+ var getPluginSubmitPromise = function getPluginSubmitPromise(plugins, pendingRequests) {
1300
+ var waitUntilComplete = false;
1301
+ var timeouts = [];
1302
+ var _iterator = _createForOfIteratorHelper(plugins),
1303
+ _step;
1304
+ try {
1305
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1306
+ var _plugin$__autocomplet, _plugin$__autocomplet2, _plugin$__autocomplet3;
1307
+ var plugin = _step.value;
1308
+ var value = (_plugin$__autocomplet = plugin.__autocomplete_pluginOptions) === null || _plugin$__autocomplet === void 0 ? void 0 : (_plugin$__autocomplet2 = (_plugin$__autocomplet3 = _plugin$__autocomplet).awaitSubmit) === null || _plugin$__autocomplet2 === void 0 ? void 0 : _plugin$__autocomplet2.call(_plugin$__autocomplet3);
1309
+ if (typeof value === 'number') {
1310
+ timeouts.push(value);
1311
+ } else if (value === true) {
1312
+ waitUntilComplete = true;
1313
+ break; // break loop as bool overrides num array below
1314
+ }
1315
+ }
1316
+ } catch (err) {
1317
+ _iterator.e(err);
1318
+ } finally {
1319
+ _iterator.f();
1320
+ }
1321
+ if (waitUntilComplete) {
1322
+ return pendingRequests.wait();
1323
+ } else if (timeouts.length > 0) {
1324
+ return pendingRequests.wait(Math.max.apply(Math, timeouts));
1325
+ }
1326
+ return undefined;
1327
+ };
1328
+
1224
1329
  // We don't have access to the autocomplete source when we call `onKeyDown`
1225
1330
  // or `onClick` because those are native browser events.
1226
1331
  // However, we can get the source from the suggestion index.
@@ -1892,11 +1997,14 @@
1892
1997
  if (store.getState().activeItemId === null || store.getState().collections.every(function (collection) {
1893
1998
  return collection.items.length === 0;
1894
1999
  })) {
1895
- // If requests are still pending when the panel closes, they could reopen
1896
- // the panel once they resolve.
1897
- // We want to prevent any subsequent query from reopening the panel
1898
- // because it would result in an unsolicited UI behavior.
1899
- if (!props.debug) {
2000
+ var waitForSubmit = getPluginSubmitPromise(props.plugins, store.pendingRequests);
2001
+ if (waitForSubmit !== undefined) {
2002
+ waitForSubmit.then(store.pendingRequests.cancelAll); // Cancel the rest if timeout number is provided
2003
+ } else if (!props.debug) {
2004
+ // If requests are still pending when the panel closes, they could reopen
2005
+ // the panel once they resolve.
2006
+ // We want to prevent any subsequent query from reopening the panel
2007
+ // because it would result in an unsolicited UI behavior.
1900
2008
  store.pendingRequests.cancelAll();
1901
2009
  }
1902
2010
  return;
@@ -2070,20 +2178,30 @@
2070
2178
  var getFormProps = function getFormProps(providedProps) {
2071
2179
  providedProps.inputElement;
2072
2180
  var rest = _objectWithoutProperties$1(providedProps, _excluded3);
2181
+ var handleSubmit = function handleSubmit(event) {
2182
+ var _providedProps$inputE;
2183
+ props.onSubmit(_objectSpread2({
2184
+ event: event,
2185
+ refresh: refresh,
2186
+ state: store.getState()
2187
+ }, setters));
2188
+ store.dispatch('submit', null);
2189
+ (_providedProps$inputE = providedProps.inputElement) === null || _providedProps$inputE === void 0 ? void 0 : _providedProps$inputE.blur();
2190
+ };
2073
2191
  return _objectSpread2({
2074
2192
  action: '',
2075
2193
  noValidate: true,
2076
2194
  role: 'search',
2077
2195
  onSubmit: function onSubmit(event) {
2078
- var _providedProps$inputE;
2079
2196
  event.preventDefault();
2080
- props.onSubmit(_objectSpread2({
2081
- event: event,
2082
- refresh: refresh,
2083
- state: store.getState()
2084
- }, setters));
2085
- store.dispatch('submit', null);
2086
- (_providedProps$inputE = providedProps.inputElement) === null || _providedProps$inputE === void 0 ? void 0 : _providedProps$inputE.blur();
2197
+ var waitForSubmit = getPluginSubmitPromise(props.plugins, store.pendingRequests);
2198
+ if (waitForSubmit !== undefined) {
2199
+ waitForSubmit.then(function () {
2200
+ return handleSubmit(event);
2201
+ });
2202
+ } else {
2203
+ handleSubmit(event);
2204
+ }
2087
2205
  },
2088
2206
  onReset: function onReset(event) {
2089
2207
  var _providedProps$inputE2;