@algolia/autocomplete-core 1.6.3 → 1.7.0

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.
@@ -14,6 +14,7 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
14
14
 
15
15
  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; }
16
16
 
17
+ import { noop } from '@algolia/autocomplete-shared';
17
18
  import { onInput } from './onInput';
18
19
  import { onKeyDown as _onKeyDown } from './onKeyDown';
19
20
  import { getActiveItem, isOrContainsNode, isSamsung } from './utils';
@@ -29,42 +30,49 @@ export function getPropGetters(_ref) {
29
30
  panelElement = providedProps.panelElement,
30
31
  rest = _objectWithoutProperties(providedProps, _excluded2);
31
32
 
32
- return _objectSpread({
33
- // On touch devices, we do not rely on the native `blur` event of the
34
- // input to close the panel, but rather on a custom `touchstart` event
35
- // outside of the autocomplete elements.
36
- // This ensures a working experience on mobile because we blur the input
37
- // on touch devices when the user starts scrolling (`touchmove`).
38
- // @TODO: support cases where there are multiple Autocomplete instances.
33
+ function onMouseDownOrTouchStart(event) {
34
+ // The `onTouchStart`/`onMouseDown` events shouldn't trigger the `blur`
35
+ // handler when it's not an interaction with Autocomplete.
36
+ // We detect it with the following heuristics:
37
+ // - the panel is closed AND there are no pending requests
38
+ // (no interaction with the autocomplete, no future state updates)
39
+ // - OR the touched target is the input element (should open the panel)
40
+ var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
41
+
42
+ if (!isAutocompleteInteraction || event.target === inputElement) {
43
+ return;
44
+ } // @TODO: support cases where there are multiple Autocomplete instances.
39
45
  // Right now, a second instance makes this computation return false.
40
- onTouchStart: function onTouchStart(event) {
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 pending 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 isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
48
-
49
- if (!isAutocompleteInteraction || event.target === inputElement) {
50
- return;
51
- }
52
46
 
53
- var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
54
- return isOrContainsNode(contextNode, event.target);
55
- });
56
47
 
57
- if (isTargetWithinAutocomplete === false) {
58
- store.dispatch('blur', null); // If requests are still pending 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.
48
+ var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
49
+ return isOrContainsNode(contextNode, event.target);
50
+ });
62
51
 
63
- if (!props.debug) {
64
- store.pendingRequests.cancelAll();
65
- }
52
+ if (isTargetWithinAutocomplete === false) {
53
+ store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
54
+ // could reopen the panel once they resolve.
55
+ // We want to prevent any subsequent query from reopening the panel
56
+ // because it would result in an unsolicited UI behavior.
57
+
58
+ if (!props.debug) {
59
+ store.pendingRequests.cancelAll();
66
60
  }
67
- },
61
+ }
62
+ }
63
+
64
+ return _objectSpread({
65
+ // We do not rely on the native `blur` event of the input to close the
66
+ // panel, but rather on a custom `touchstart`/`mousedown` event outside
67
+ // of the autocomplete elements.
68
+ // This ensures we don't mistakenly interpret interactions within the
69
+ // autocomplete (but outside of the input) as a signal to close the panel.
70
+ // For example, clicking reset button causes an input blur, but if
71
+ // `openOnFocus=true`, it shouldn't close the panel.
72
+ // On touch devices, scrolling results (`touchmove`) causes an input blur
73
+ // but shouldn't close the panel.
74
+ onTouchStart: onMouseDownOrTouchStart,
75
+ onMouseDown: onMouseDownOrTouchStart,
68
76
  // When scrolling on touch devices (mobiles, tablets, etc.), we want to
69
77
  // mimic the native platform behavior where the input is blurred to
70
78
  // hide the virtual keyboard. This gives more vertical space to
@@ -143,8 +151,6 @@ export function getPropGetters(_ref) {
143
151
  store.dispatch('focus', null);
144
152
  }
145
153
 
146
- var isTouchDevice = ('ontouchstart' in props.environment);
147
-
148
154
  var _ref2 = providedProps || {},
149
155
  inputElement = _ref2.inputElement,
150
156
  _ref2$maxLength = _ref2.maxLength,
@@ -189,20 +195,10 @@ export function getPropGetters(_ref) {
189
195
  }, setters));
190
196
  },
191
197
  onFocus: onFocus,
192
- onBlur: function onBlur() {
193
- // We do rely on the `blur` event on touch devices.
194
- // See explanation in `onTouchStart`.
195
- if (!isTouchDevice) {
196
- store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
197
- // could reopen the panel once they resolve.
198
- // We want to prevent any subsequent query from reopening the panel
199
- // because it would result in an unsolicited UI behavior.
200
-
201
- if (!props.debug) {
202
- store.pendingRequests.cancelAll();
203
- }
204
- }
205
- },
198
+ // We don't rely on the `blur` event.
199
+ // See explanation in `onTouchStart`/`onMouseDown`.
200
+ // @MAJOR See if we need to keep this handler.
201
+ onBlur: noop,
206
202
  onClick: function onClick(event) {
207
203
  // When the panel is closed and you click on the input while
208
204
  // the input is focused, the `onFocus` event is not triggered
@@ -91,6 +91,13 @@ export function onKeyDown(_ref) {
91
91
  // pending and could reopen the panel once they resolve, because that would
92
92
  // result in an unsolicited UI behavior.
93
93
 
94
+ store.pendingRequests.cancelAll();
95
+ } else if (event.key === 'Tab') {
96
+ store.dispatch('blur', null); // Hitting the `Escape` key signals the end of a user interaction with the
97
+ // autocomplete. At this point, we should ignore any requests that are still
98
+ // pending and could reopen the panel once they resolve, because that would
99
+ // result in an unsolicited UI behavior.
100
+
94
101
  store.pendingRequests.cancelAll();
95
102
  } else if (event.key === 'Enter') {
96
103
  // No active item, so we let the browser handle the native `onSubmit` form
@@ -98,6 +105,14 @@ export function onKeyDown(_ref) {
98
105
  if (store.getState().activeItemId === null || store.getState().collections.every(function (collection) {
99
106
  return collection.items.length === 0;
100
107
  })) {
108
+ // If requests are still pending when the panel closes, they could reopen
109
+ // the panel once they resolve.
110
+ // We want to prevent any subsequent query from reopening the panel
111
+ // because it would result in an unsolicited UI behavior.
112
+ if (!props.debug) {
113
+ store.pendingRequests.cancelAll();
114
+ }
115
+
101
116
  return;
102
117
  } // This prevents the `onSubmit` event to be sent because an item is
103
118
  // highlighted.
@@ -18,6 +18,7 @@ export declare type GetEnvironmentProps = (props: {
18
18
  }) => {
19
19
  onTouchStart(event: TouchEvent): void;
20
20
  onTouchMove(event: TouchEvent): void;
21
+ onMouseDown(event: MouseEvent): void;
21
22
  };
22
23
  export declare type GetRootProps = (props?: {
23
24
  [key: string]: unknown;
@@ -1,7 +1,21 @@
1
1
  import { CancelablePromise } from '.';
2
2
  export declare type CancelablePromiseList<TValue> = {
3
+ /**
4
+ * Add a cancelable promise to the list.
5
+ *
6
+ * @param cancelablePromise The cancelable promise to add.
7
+ */
3
8
  add(cancelablePromise: CancelablePromise<TValue>): CancelablePromise<TValue>;
9
+ /**
10
+ * Cancel all pending promises.
11
+ *
12
+ * Requests aren't actually stopped. All pending promises will settle, but
13
+ * attached handlers won't run.
14
+ */
4
15
  cancelAll(): void;
16
+ /**
17
+ * Whether there are pending promises in the list.
18
+ */
5
19
  isEmpty(): boolean;
6
20
  };
7
21
  export declare function createCancelablePromiseList<TValue>(): CancelablePromiseList<TValue>;
@@ -1,4 +1,4 @@
1
- /*! @algolia/autocomplete-core 1.6.3 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */
1
+ /*! @algolia/autocomplete-core 1.7.0 | 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) :
@@ -264,7 +264,7 @@
264
264
 
265
265
  var noop = function noop() {};
266
266
 
267
- var version = '1.6.3';
267
+ var version = '1.7.0';
268
268
 
269
269
  var userAgents = [{
270
270
  segment: 'autocomplete-core',
@@ -1135,6 +1135,13 @@
1135
1135
  // pending and could reopen the panel once they resolve, because that would
1136
1136
  // result in an unsolicited UI behavior.
1137
1137
 
1138
+ store.pendingRequests.cancelAll();
1139
+ } else if (event.key === 'Tab') {
1140
+ store.dispatch('blur', null); // Hitting the `Escape` key signals the end of a user interaction with the
1141
+ // autocomplete. At this point, we should ignore any requests that are still
1142
+ // pending and could reopen the panel once they resolve, because that would
1143
+ // result in an unsolicited UI behavior.
1144
+
1138
1145
  store.pendingRequests.cancelAll();
1139
1146
  } else if (event.key === 'Enter') {
1140
1147
  // No active item, so we let the browser handle the native `onSubmit` form
@@ -1142,6 +1149,14 @@
1142
1149
  if (store.getState().activeItemId === null || store.getState().collections.every(function (collection) {
1143
1150
  return collection.items.length === 0;
1144
1151
  })) {
1152
+ // If requests are still pending when the panel closes, they could reopen
1153
+ // the panel once they resolve.
1154
+ // We want to prevent any subsequent query from reopening the panel
1155
+ // because it would result in an unsolicited UI behavior.
1156
+ if (!props.debug) {
1157
+ store.pendingRequests.cancelAll();
1158
+ }
1159
+
1145
1160
  return;
1146
1161
  } // This prevents the `onSubmit` event to be sent because an item is
1147
1162
  // highlighted.
@@ -1249,42 +1264,49 @@
1249
1264
  panelElement = providedProps.panelElement,
1250
1265
  rest = _objectWithoutProperties(providedProps, _excluded2);
1251
1266
 
1252
- return _objectSpread2({
1253
- // On touch devices, we do not rely on the native `blur` event of the
1254
- // input to close the panel, but rather on a custom `touchstart` event
1255
- // outside of the autocomplete elements.
1256
- // This ensures a working experience on mobile because we blur the input
1257
- // on touch devices when the user starts scrolling (`touchmove`).
1258
- // @TODO: support cases where there are multiple Autocomplete instances.
1267
+ function onMouseDownOrTouchStart(event) {
1268
+ // The `onTouchStart`/`onMouseDown` events shouldn't trigger the `blur`
1269
+ // handler when it's not an interaction with Autocomplete.
1270
+ // We detect it with the following heuristics:
1271
+ // - the panel is closed AND there are no pending requests
1272
+ // (no interaction with the autocomplete, no future state updates)
1273
+ // - OR the touched target is the input element (should open the panel)
1274
+ var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
1275
+
1276
+ if (!isAutocompleteInteraction || event.target === inputElement) {
1277
+ return;
1278
+ } // @TODO: support cases where there are multiple Autocomplete instances.
1259
1279
  // Right now, a second instance makes this computation return false.
1260
- onTouchStart: function onTouchStart(event) {
1261
- // The `onTouchStart` event shouldn't trigger the `blur` handler when
1262
- // it's not an interaction with Autocomplete. We detect it with the
1263
- // following heuristics:
1264
- // - the panel is closed AND there are no pending requests
1265
- // (no interaction with the autocomplete, no future state updates)
1266
- // - OR the touched target is the input element (should open the panel)
1267
- var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
1268
-
1269
- if (!isAutocompleteInteraction || event.target === inputElement) {
1270
- return;
1271
- }
1272
1280
 
1273
- var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
1274
- return isOrContainsNode(contextNode, event.target);
1275
- });
1276
1281
 
1277
- if (isTargetWithinAutocomplete === false) {
1278
- store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
1279
- // could reopen the panel once they resolve.
1280
- // We want to prevent any subsequent query from reopening the panel
1281
- // because it would result in an unsolicited UI behavior.
1282
+ var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
1283
+ return isOrContainsNode(contextNode, event.target);
1284
+ });
1282
1285
 
1283
- if (!props.debug) {
1284
- store.pendingRequests.cancelAll();
1285
- }
1286
+ if (isTargetWithinAutocomplete === false) {
1287
+ store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
1288
+ // could reopen the panel once they resolve.
1289
+ // We want to prevent any subsequent query from reopening the panel
1290
+ // because it would result in an unsolicited UI behavior.
1291
+
1292
+ if (!props.debug) {
1293
+ store.pendingRequests.cancelAll();
1286
1294
  }
1287
- },
1295
+ }
1296
+ }
1297
+
1298
+ return _objectSpread2({
1299
+ // We do not rely on the native `blur` event of the input to close the
1300
+ // panel, but rather on a custom `touchstart`/`mousedown` event outside
1301
+ // of the autocomplete elements.
1302
+ // This ensures we don't mistakenly interpret interactions within the
1303
+ // autocomplete (but outside of the input) as a signal to close the panel.
1304
+ // For example, clicking reset button causes an input blur, but if
1305
+ // `openOnFocus=true`, it shouldn't close the panel.
1306
+ // On touch devices, scrolling results (`touchmove`) causes an input blur
1307
+ // but shouldn't close the panel.
1308
+ onTouchStart: onMouseDownOrTouchStart,
1309
+ onMouseDown: onMouseDownOrTouchStart,
1288
1310
  // When scrolling on touch devices (mobiles, tablets, etc.), we want to
1289
1311
  // mimic the native platform behavior where the input is blurred to
1290
1312
  // hide the virtual keyboard. This gives more vertical space to
@@ -1363,8 +1385,6 @@
1363
1385
  store.dispatch('focus', null);
1364
1386
  }
1365
1387
 
1366
- var isTouchDevice = ('ontouchstart' in props.environment);
1367
-
1368
1388
  var _ref2 = providedProps || {};
1369
1389
  _ref2.inputElement;
1370
1390
  var _ref2$maxLength = _ref2.maxLength,
@@ -1409,20 +1429,10 @@
1409
1429
  }, setters));
1410
1430
  },
1411
1431
  onFocus: onFocus,
1412
- onBlur: function onBlur() {
1413
- // We do rely on the `blur` event on touch devices.
1414
- // See explanation in `onTouchStart`.
1415
- if (!isTouchDevice) {
1416
- store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
1417
- // could reopen the panel once they resolve.
1418
- // We want to prevent any subsequent query from reopening the panel
1419
- // because it would result in an unsolicited UI behavior.
1420
-
1421
- if (!props.debug) {
1422
- store.pendingRequests.cancelAll();
1423
- }
1424
- }
1425
- },
1432
+ // We don't rely on the `blur` event.
1433
+ // See explanation in `onTouchStart`/`onMouseDown`.
1434
+ // @MAJOR See if we need to keep this handler.
1435
+ onBlur: noop,
1426
1436
  onClick: function onClick(event) {
1427
1437
  // When the panel is closed and you click on the input while
1428
1438
  // the input is focused, the `onFocus` event is not triggered