@algolia/autocomplete-js 1.6.1 → 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.
@@ -1,4 +1,4 @@
1
- /*! @algolia/autocomplete-js 1.6.1 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */
1
+ /*! @algolia/autocomplete-js 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) :
@@ -110,6 +110,10 @@
110
110
  return target;
111
111
  }
112
112
 
113
+ function _slicedToArray$1(arr, i) {
114
+ return _arrayWithHoles$1(arr) || _iterableToArrayLimit$1(arr, i) || _unsupportedIterableToArray$6(arr, i) || _nonIterableRest$1();
115
+ }
116
+
113
117
  function _toConsumableArray$5(arr) {
114
118
  return _arrayWithoutHoles$5(arr) || _iterableToArray$5(arr) || _unsupportedIterableToArray$6(arr) || _nonIterableSpread$5();
115
119
  }
@@ -118,10 +122,44 @@
118
122
  if (Array.isArray(arr)) return _arrayLikeToArray$6(arr);
119
123
  }
120
124
 
125
+ function _arrayWithHoles$1(arr) {
126
+ if (Array.isArray(arr)) return arr;
127
+ }
128
+
121
129
  function _iterableToArray$5(iter) {
122
130
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
123
131
  }
124
132
 
133
+ function _iterableToArrayLimit$1(arr, i) {
134
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
135
+
136
+ if (_i == null) return;
137
+ var _arr = [];
138
+ var _n = true;
139
+ var _d = false;
140
+
141
+ var _s, _e;
142
+
143
+ try {
144
+ for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
145
+ _arr.push(_s.value);
146
+
147
+ if (i && _arr.length === i) break;
148
+ }
149
+ } catch (err) {
150
+ _d = true;
151
+ _e = err;
152
+ } finally {
153
+ try {
154
+ if (!_n && _i["return"] != null) _i["return"]();
155
+ } finally {
156
+ if (_d) throw _e;
157
+ }
158
+ }
159
+
160
+ return _arr;
161
+ }
162
+
125
163
  function _unsupportedIterableToArray$6(o, minLen) {
126
164
  if (!o) return;
127
165
  if (typeof o === "string") return _arrayLikeToArray$6(o, minLen);
@@ -143,6 +181,10 @@
143
181
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
144
182
  }
145
183
 
184
+ function _nonIterableRest$1() {
185
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
186
+ }
187
+
146
188
  function createRef(initialValue) {
147
189
  return {
148
190
  current: initialValue
@@ -311,7 +353,7 @@
311
353
 
312
354
  var noop = function noop() {};
313
355
 
314
- var version = '1.6.1';
356
+ var version = '1.7.0';
315
357
 
316
358
  var userAgents$1 = [{
317
359
  segment: 'autocomplete-core',
@@ -1354,7 +1396,7 @@
1354
1396
  });
1355
1397
  }
1356
1398
 
1357
- var _excluded$6 = ["event", "nextState", "props", "query", "refresh", "store"];
1399
+ var _excluded$7 = ["event", "nextState", "props", "query", "refresh", "store"];
1358
1400
 
1359
1401
  function ownKeys$8(object, enumerableOnly) {
1360
1402
  var keys = Object.keys(object);
@@ -1442,7 +1484,7 @@
1442
1484
  query = _ref.query,
1443
1485
  refresh = _ref.refresh,
1444
1486
  store = _ref.store,
1445
- setters = _objectWithoutProperties$3(_ref, _excluded$6);
1487
+ setters = _objectWithoutProperties$3(_ref, _excluded$7);
1446
1488
 
1447
1489
  if (lastStalledId) {
1448
1490
  props.environment.clearTimeout(lastStalledId);
@@ -1552,7 +1594,7 @@
1552
1594
  return store.pendingRequests.add(request);
1553
1595
  }
1554
1596
 
1555
- var _excluded$5 = ["event", "props", "refresh", "store"];
1597
+ var _excluded$6 = ["event", "props", "refresh", "store"];
1556
1598
 
1557
1599
  function ownKeys$7(object, enumerableOnly) {
1558
1600
  var keys = Object.keys(object);
@@ -1635,7 +1677,7 @@
1635
1677
  props = _ref.props,
1636
1678
  refresh = _ref.refresh,
1637
1679
  store = _ref.store,
1638
- setters = _objectWithoutProperties$2(_ref, _excluded$5);
1680
+ setters = _objectWithoutProperties$2(_ref, _excluded$6);
1639
1681
 
1640
1682
  if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
1641
1683
  // eslint-disable-next-line no-inner-declarations
@@ -1709,6 +1751,13 @@
1709
1751
  // pending and could reopen the panel once they resolve, because that would
1710
1752
  // result in an unsolicited UI behavior.
1711
1753
 
1754
+ store.pendingRequests.cancelAll();
1755
+ } else if (event.key === 'Tab') {
1756
+ store.dispatch('blur', null); // Hitting the `Escape` key signals the end of a user interaction with the
1757
+ // autocomplete. At this point, we should ignore any requests that are still
1758
+ // pending and could reopen the panel once they resolve, because that would
1759
+ // result in an unsolicited UI behavior.
1760
+
1712
1761
  store.pendingRequests.cancelAll();
1713
1762
  } else if (event.key === 'Enter') {
1714
1763
  // No active item, so we let the browser handle the native `onSubmit` form
@@ -1716,6 +1765,14 @@
1716
1765
  if (store.getState().activeItemId === null || store.getState().collections.every(function (collection) {
1717
1766
  return collection.items.length === 0;
1718
1767
  })) {
1768
+ // If requests are still pending when the panel closes, they could reopen
1769
+ // the panel once they resolve.
1770
+ // We want to prevent any subsequent query from reopening the panel
1771
+ // because it would result in an unsolicited UI behavior.
1772
+ if (!props.debug) {
1773
+ store.pendingRequests.cancelAll();
1774
+ }
1775
+
1719
1776
  return;
1720
1777
  } // This prevents the `onSubmit` event to be sent because an item is
1721
1778
  // highlighted.
@@ -1806,7 +1863,7 @@
1806
1863
  }
1807
1864
  }
1808
1865
 
1809
- var _excluded$4 = ["props", "refresh", "store"],
1866
+ var _excluded$5 = ["props", "refresh", "store"],
1810
1867
  _excluded2 = ["inputElement", "formElement", "panelElement"],
1811
1868
  _excluded3 = ["inputElement"],
1812
1869
  _excluded4 = ["inputElement", "maxLength"],
@@ -1892,7 +1949,7 @@
1892
1949
  var props = _ref.props,
1893
1950
  refresh = _ref.refresh,
1894
1951
  store = _ref.store,
1895
- setters = _objectWithoutProperties$1(_ref, _excluded$4);
1952
+ setters = _objectWithoutProperties$1(_ref, _excluded$5);
1896
1953
 
1897
1954
  var getEnvironmentProps = function getEnvironmentProps(providedProps) {
1898
1955
  var inputElement = providedProps.inputElement,
@@ -1900,42 +1957,49 @@
1900
1957
  panelElement = providedProps.panelElement,
1901
1958
  rest = _objectWithoutProperties$1(providedProps, _excluded2);
1902
1959
 
1903
- return _objectSpread$6({
1904
- // On touch devices, we do not rely on the native `blur` event of the
1905
- // input to close the panel, but rather on a custom `touchstart` event
1906
- // outside of the autocomplete elements.
1907
- // This ensures a working experience on mobile because we blur the input
1908
- // on touch devices when the user starts scrolling (`touchmove`).
1909
- // @TODO: support cases where there are multiple Autocomplete instances.
1960
+ function onMouseDownOrTouchStart(event) {
1961
+ // The `onTouchStart`/`onMouseDown` events shouldn't trigger the `blur`
1962
+ // handler when it's not an interaction with Autocomplete.
1963
+ // We detect it with the following heuristics:
1964
+ // - the panel is closed AND there are no pending requests
1965
+ // (no interaction with the autocomplete, no future state updates)
1966
+ // - OR the touched target is the input element (should open the panel)
1967
+ var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
1968
+
1969
+ if (!isAutocompleteInteraction || event.target === inputElement) {
1970
+ return;
1971
+ } // @TODO: support cases where there are multiple Autocomplete instances.
1910
1972
  // Right now, a second instance makes this computation return false.
1911
- onTouchStart: function onTouchStart(event) {
1912
- // The `onTouchStart` event shouldn't trigger the `blur` handler when
1913
- // it's not an interaction with Autocomplete. We detect it with the
1914
- // following heuristics:
1915
- // - the panel is closed AND there are no pending requests
1916
- // (no interaction with the autocomplete, no future state updates)
1917
- // - OR the touched target is the input element (should open the panel)
1918
- var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
1919
-
1920
- if (!isAutocompleteInteraction || event.target === inputElement) {
1921
- return;
1922
- }
1923
1973
 
1924
- var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
1925
- return isOrContainsNode(contextNode, event.target);
1926
- });
1927
1974
 
1928
- if (isTargetWithinAutocomplete === false) {
1929
- store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
1930
- // could reopen the panel once they resolve.
1931
- // We want to prevent any subsequent query from reopening the panel
1932
- // because it would result in an unsolicited UI behavior.
1975
+ var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
1976
+ return isOrContainsNode(contextNode, event.target);
1977
+ });
1933
1978
 
1934
- if (!props.debug) {
1935
- store.pendingRequests.cancelAll();
1936
- }
1979
+ if (isTargetWithinAutocomplete === false) {
1980
+ store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
1981
+ // could reopen the panel once they resolve.
1982
+ // We want to prevent any subsequent query from reopening the panel
1983
+ // because it would result in an unsolicited UI behavior.
1984
+
1985
+ if (!props.debug) {
1986
+ store.pendingRequests.cancelAll();
1937
1987
  }
1938
- },
1988
+ }
1989
+ }
1990
+
1991
+ return _objectSpread$6({
1992
+ // We do not rely on the native `blur` event of the input to close the
1993
+ // panel, but rather on a custom `touchstart`/`mousedown` event outside
1994
+ // of the autocomplete elements.
1995
+ // This ensures we don't mistakenly interpret interactions within the
1996
+ // autocomplete (but outside of the input) as a signal to close the panel.
1997
+ // For example, clicking reset button causes an input blur, but if
1998
+ // `openOnFocus=true`, it shouldn't close the panel.
1999
+ // On touch devices, scrolling results (`touchmove`) causes an input blur
2000
+ // but shouldn't close the panel.
2001
+ onTouchStart: onMouseDownOrTouchStart,
2002
+ onMouseDown: onMouseDownOrTouchStart,
1939
2003
  // When scrolling on touch devices (mobiles, tablets, etc.), we want to
1940
2004
  // mimic the native platform behavior where the input is blurred to
1941
2005
  // hide the virtual keyboard. This gives more vertical space to
@@ -2014,8 +2078,6 @@
2014
2078
  store.dispatch('focus', null);
2015
2079
  }
2016
2080
 
2017
- var isTouchDevice = ('ontouchstart' in props.environment);
2018
-
2019
2081
  var _ref2 = providedProps || {};
2020
2082
  _ref2.inputElement;
2021
2083
  var _ref2$maxLength = _ref2.maxLength,
@@ -2060,20 +2122,10 @@
2060
2122
  }, setters));
2061
2123
  },
2062
2124
  onFocus: onFocus,
2063
- onBlur: function onBlur() {
2064
- // We do rely on the `blur` event on touch devices.
2065
- // See explanation in `onTouchStart`.
2066
- if (!isTouchDevice) {
2067
- store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
2068
- // could reopen the panel once they resolve.
2069
- // We want to prevent any subsequent query from reopening the panel
2070
- // because it would result in an unsolicited UI behavior.
2071
-
2072
- if (!props.debug) {
2073
- store.pendingRequests.cancelAll();
2074
- }
2075
- }
2076
- },
2125
+ // We don't rely on the `blur` event.
2126
+ // See explanation in `onTouchStart`/`onMouseDown`.
2127
+ // @MAJOR See if we need to keep this handler.
2128
+ onBlur: noop,
2077
2129
  onClick: function onClick(event) {
2078
2130
  // When the panel is closed and you click on the input while
2079
2131
  // the input is focused, the `onFocus` event is not triggered
@@ -2667,6 +2719,23 @@
2667
2719
  }, {});
2668
2720
  }
2669
2721
 
2722
+ function pickBy(obj, predicate) {
2723
+ return Object.entries(obj).reduce(function (acc, _ref) {
2724
+ var _ref2 = _slicedToArray$1(_ref, 2),
2725
+ key = _ref2[0],
2726
+ value = _ref2[1];
2727
+
2728
+ if (predicate({
2729
+ key: key,
2730
+ value: value
2731
+ })) {
2732
+ return _objectSpread2(_objectSpread2({}, acc), {}, _defineProperty$g({}, key, value));
2733
+ }
2734
+
2735
+ return acc;
2736
+ }, {});
2737
+ }
2738
+
2670
2739
  /* eslint-disable */
2671
2740
 
2672
2741
  /**
@@ -2778,12 +2847,12 @@
2778
2847
  }
2779
2848
  }
2780
2849
 
2781
- var _excluded$3 = ["children"];
2850
+ var _excluded$4 = ["children"];
2782
2851
  function getCreateDomElement(environment) {
2783
2852
  return function createDomElement(tagName, _ref) {
2784
2853
  var _ref$children = _ref.children,
2785
2854
  children = _ref$children === void 0 ? [] : _ref$children,
2786
- props = _objectWithoutProperties$4(_ref, _excluded$3);
2855
+ props = _objectWithoutProperties$4(_ref, _excluded$4);
2787
2856
 
2788
2857
  var element = environment.document.createElement(tagName);
2789
2858
  setProperties(element, props);
@@ -2792,16 +2861,16 @@
2792
2861
  };
2793
2862
  }
2794
2863
 
2795
- var _excluded$2 = ["autocompleteScopeApi", "environment", "classNames", "getInputProps", "getInputPropsCore", "onDetachedEscape", "state"];
2864
+ var _excluded$3 = ["autocompleteScopeApi", "environment", "classNames", "getInputProps", "getInputPropsCore", "isDetached", "state"];
2796
2865
  var Input = function Input(_ref) {
2797
2866
  var autocompleteScopeApi = _ref.autocompleteScopeApi,
2798
2867
  environment = _ref.environment;
2799
2868
  _ref.classNames;
2800
2869
  var getInputProps = _ref.getInputProps,
2801
2870
  getInputPropsCore = _ref.getInputPropsCore,
2802
- onDetachedEscape = _ref.onDetachedEscape,
2871
+ isDetached = _ref.isDetached,
2803
2872
  state = _ref.state,
2804
- props = _objectWithoutProperties$4(_ref, _excluded$2);
2873
+ props = _objectWithoutProperties$4(_ref, _excluded$3);
2805
2874
 
2806
2875
  var createDomElement = getCreateDomElement(environment);
2807
2876
  var element = createDomElement('input', props);
@@ -2814,9 +2883,8 @@
2814
2883
  }, autocompleteScopeApi));
2815
2884
  setProperties(element, _objectSpread2(_objectSpread2({}, inputProps), {}, {
2816
2885
  onKeyDown: function onKeyDown(event) {
2817
- if (onDetachedEscape && event.key === 'Escape') {
2818
- event.preventDefault();
2819
- onDetachedEscape();
2886
+ // In detached mode we don't want to close the panel when hittin `Tab`.
2887
+ if (isDetached && event.key === 'Tab') {
2820
2888
  return;
2821
2889
  }
2822
2890
 
@@ -2922,10 +2990,7 @@
2922
2990
  getInputProps: propGetters.getInputProps,
2923
2991
  getInputPropsCore: autocomplete.getInputProps,
2924
2992
  autocompleteScopeApi: autocompleteScopeApi,
2925
- onDetachedEscape: isDetached ? function () {
2926
- autocomplete.setIsOpen(false);
2927
- setIsModalOpen(false);
2928
- } : undefined
2993
+ isDetached: isDetached
2929
2994
  });
2930
2995
  var inputWrapperPrefix = createDomElement('div', {
2931
2996
  class: classNames.inputWrapperPrefix,
@@ -3408,7 +3473,7 @@
3408
3473
  };
3409
3474
  }
3410
3475
 
3411
- var _excluded$1 = ["params"];
3476
+ var _excluded$2 = ["params"];
3412
3477
 
3413
3478
  function ownKeys(object, enumerableOnly) {
3414
3479
  var keys = Object.keys(object);
@@ -3538,7 +3603,7 @@
3538
3603
 
3539
3604
  return searchClient.search(queries.map(function (searchParameters) {
3540
3605
  var params = searchParameters.params,
3541
- headers = _objectWithoutProperties(searchParameters, _excluded$1);
3606
+ headers = _objectWithoutProperties(searchParameters, _excluded$2);
3542
3607
 
3543
3608
  return _objectSpread(_objectSpread({}, headers), {}, {
3544
3609
  params: _objectSpread({
@@ -3555,7 +3620,8 @@
3555
3620
  function createHighlightComponent(_ref) {
3556
3621
  var createElement = _ref.createElement,
3557
3622
  Fragment = _ref.Fragment;
3558
- return function Highlight(_ref2) {
3623
+
3624
+ function Highlight(_ref2) {
3559
3625
  var hit = _ref2.hit,
3560
3626
  attribute = _ref2.attribute,
3561
3627
  _ref2$tagName = _ref2.tagName,
@@ -3568,13 +3634,17 @@
3568
3634
  key: index
3569
3635
  }, x.value) : x.value;
3570
3636
  }));
3571
- };
3637
+ }
3638
+
3639
+ Highlight.__autocomplete_componentName = 'Highlight';
3640
+ return Highlight;
3572
3641
  }
3573
3642
 
3574
3643
  function createReverseHighlightComponent(_ref) {
3575
3644
  var createElement = _ref.createElement,
3576
3645
  Fragment = _ref.Fragment;
3577
- return function ReverseHighlight(_ref2) {
3646
+
3647
+ function ReverseHighlight(_ref2) {
3578
3648
  var hit = _ref2.hit,
3579
3649
  attribute = _ref2.attribute,
3580
3650
  _ref2$tagName = _ref2.tagName,
@@ -3587,13 +3657,17 @@
3587
3657
  key: index
3588
3658
  }, x.value) : x.value;
3589
3659
  }));
3590
- };
3660
+ }
3661
+
3662
+ ReverseHighlight.__autocomplete_componentName = 'ReverseHighlight';
3663
+ return ReverseHighlight;
3591
3664
  }
3592
3665
 
3593
3666
  function createReverseSnippetComponent(_ref) {
3594
3667
  var createElement = _ref.createElement,
3595
3668
  Fragment = _ref.Fragment;
3596
- return function ReverseSnippet(_ref2) {
3669
+
3670
+ function ReverseSnippet(_ref2) {
3597
3671
  var hit = _ref2.hit,
3598
3672
  attribute = _ref2.attribute,
3599
3673
  _ref2$tagName = _ref2.tagName,
@@ -3606,13 +3680,17 @@
3606
3680
  key: index
3607
3681
  }, x.value) : x.value;
3608
3682
  }));
3609
- };
3683
+ }
3684
+
3685
+ ReverseSnippet.__autocomplete_componentName = 'ReverseSnippet';
3686
+ return ReverseSnippet;
3610
3687
  }
3611
3688
 
3612
3689
  function createSnippetComponent(_ref) {
3613
3690
  var createElement = _ref.createElement,
3614
3691
  Fragment = _ref.Fragment;
3615
- return function Snippet(_ref2) {
3692
+
3693
+ function Snippet(_ref2) {
3616
3694
  var hit = _ref2.hit,
3617
3695
  attribute = _ref2.attribute,
3618
3696
  _ref2$tagName = _ref2.tagName,
@@ -3625,10 +3703,13 @@
3625
3703
  key: index
3626
3704
  }, x.value) : x.value;
3627
3705
  }));
3628
- };
3706
+ }
3707
+
3708
+ Snippet.__autocomplete_componentName = 'Snippet';
3709
+ return Snippet;
3629
3710
  }
3630
3711
 
3631
- var _excluded = ["classNames", "container", "getEnvironmentProps", "getFormProps", "getInputProps", "getItemProps", "getLabelProps", "getListProps", "getPanelProps", "getRootProps", "panelContainer", "panelPlacement", "render", "renderNoResults", "renderer", "detachedMediaQuery", "components", "translations"];
3712
+ var _excluded$1 = ["classNames", "container", "getEnvironmentProps", "getFormProps", "getInputProps", "getItemProps", "getLabelProps", "getListProps", "getPanelProps", "getRootProps", "panelContainer", "panelPlacement", "render", "renderNoResults", "renderer", "detachedMediaQuery", "components", "translations"];
3632
3713
  var defaultClassNames = {
3633
3714
  clearButton: 'aa-ClearButton',
3634
3715
  detachedCancelButton: 'aa-DetachedCancelButton',
@@ -3689,7 +3770,7 @@
3689
3770
  detachedMediaQuery = options.detachedMediaQuery,
3690
3771
  components = options.components,
3691
3772
  translations = options.translations,
3692
- core = _objectWithoutProperties$4(options, _excluded);
3773
+ core = _objectWithoutProperties$4(options, _excluded$1);
3693
3774
  /* eslint-disable no-restricted-globals */
3694
3775
 
3695
3776
 
@@ -3698,7 +3779,7 @@
3698
3779
 
3699
3780
  var containerElement = getHTMLElement(environment, container);
3700
3781
  invariant(containerElement.tagName !== 'INPUT', 'The `container` option does not support `input` elements. You need to change the container to a `div`.');
3701
- "development" !== 'production' ? warn(Boolean(!render || (renderer === null || renderer === void 0 ? void 0 : renderer.render)), "You provided the `render` option but did not provide a `renderer.render`. Since v1.6.0, you can provide a `render` function directly in `renderer`." + "\nTo get rid of this warning, do any of the following depending on your use case." + "\n- If you are using the `render` option only to override Autocomplete's default `render` function, pass the `render` function into `renderer` and remove the `render` option." + '\n- If you are using the `render` option to customize the layout, pass your `render` function into `renderer` and use it from the provided parameters of the `render` option.' + '\nSee https://www.algolia.com/doc/ui-libraries/autocomplete/api-reference/autocomplete-js/autocomplete/#param-render') : void 0;
3782
+ "development" !== 'production' ? warn(!(render && renderer && !(renderer !== null && renderer !== void 0 && renderer.render)), "You provided the `render` option but did not provide a `renderer.render`. Since v1.6.0, you can provide a `render` function directly in `renderer`." + "\nTo get rid of this warning, do any of the following depending on your use case." + "\n- If you are using the `render` option only to override Autocomplete's default `render` function, pass the `render` function into `renderer` and remove the `render` option." + '\n- If you are using the `render` option to customize the layout, pass your `render` function into `renderer` and use it from the provided parameters of the `render` option.' + '\n- If you are using the `render` option to work with React 18, pass an empty `render` function into `renderer`.' + '\nSee https://www.algolia.com/doc/ui-libraries/autocomplete/api-reference/autocomplete-js/autocomplete/#param-render') : void 0;
3702
3783
  "development" !== 'production' ? warn(!renderer || render || renderer.Fragment && renderer.createElement && renderer.render, "You provided an incomplete `renderer` (missing: ".concat([!(renderer !== null && renderer !== void 0 && renderer.createElement) && '`renderer.createElement`', !(renderer !== null && renderer !== void 0 && renderer.Fragment) && '`renderer.Fragment`', !(renderer !== null && renderer !== void 0 && renderer.render) && '`renderer.render`'].filter(Boolean).join(', '), "). This can cause rendering issues.") + '\nSee https://www.algolia.com/doc/ui-libraries/autocomplete/api-reference/autocomplete-js/autocomplete/#param-renderer') : void 0;
3703
3784
 
3704
3785
  var defaultedRenderer = _objectSpread2(_objectSpread2({}, defaultRenderer), renderer);
@@ -3969,6 +4050,7 @@
3969
4050
  version: version
3970
4051
  }];
3971
4052
 
4053
+ var _excluded = ["components"];
3972
4054
  function autocomplete(options) {
3973
4055
  var _createEffectWrapper = createEffectWrapper(),
3974
4056
  runEffect = _createEffectWrapper.runEffect,
@@ -4227,7 +4309,21 @@
4227
4309
  function update() {
4228
4310
  var updatedOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4229
4311
  cleanupEffects();
4230
- optionsRef.current = mergeDeep(props.value.renderer, props.value.core, {
4312
+
4313
+ var _props$value$renderer = props.value.renderer,
4314
+ components = _props$value$renderer.components,
4315
+ rendererProps = _objectWithoutProperties$4(_props$value$renderer, _excluded);
4316
+
4317
+ optionsRef.current = mergeDeep(rendererProps, props.value.core, {
4318
+ // We need to filter out default components so they can be replaced with
4319
+ // a new `renderer`, without getting rid of user components.
4320
+ // @MAJOR Deal with registering components with the same name as the
4321
+ // default ones. If we disallow overriding default components, we'd just
4322
+ // need to pass all `components` here.
4323
+ components: pickBy(components, function (_ref4) {
4324
+ var value = _ref4.value;
4325
+ return !value.hasOwnProperty('__autocomplete_componentName');
4326
+ }),
4231
4327
  initialState: lastStateRef.current
4232
4328
  }, updatedOptions);
4233
4329
  runReactives();