@sonic-equipment/ui 0.0.21 → 0.0.22

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/index.js CHANGED
@@ -1,8 +1,194 @@
1
+ import { useState, useEffect, useRef, useCallback, createContext, useContext, forwardRef, Children, cloneElement, createElement } from 'react';
1
2
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { forwardRef, useState, useEffect, createContext, useContext, Children, cloneElement, useRef, useCallback, createElement } from 'react';
3
- import { Button as Button$1, FieldError as FieldError$1, useContextProps, InputContext, Input as Input$1, Label as Label$1, NumberField as NumberField$1, Link, Checkbox as Checkbox$1, Select as Select$1, SelectValue, Popover, ListBox, Section, Header, ListBoxItem, TextAreaContext, TextArea as TextArea$1, TextField as TextField$1 } from 'react-aria-components';
3
+ import { Button as Button$1, Link, FieldError as FieldError$1, useContextProps, InputContext, Input as Input$1, Label as Label$1, NumberField as NumberField$1, Checkbox as Checkbox$1, Select as Select$1, SelectValue, Popover, ListBox, Section, Header, ListBoxItem, TextAreaContext, TextArea as TextArea$1, TextField as TextField$1 } from 'react-aria-components';
4
4
  import clsx from 'clsx';
5
- import { useCurrentRefinements, useClearRefinements, useRefinementList, useHits, useDynamicWidgets, usePagination, useSortBy } from 'react-instantsearch';
5
+ import { useCurrentRefinements, useClearRefinements, useRefinementList, useHits, useDynamicWidgets, usePagination, useSortBy, InstantSearch, Configure } from 'react-instantsearch';
6
+ import require$$5 from '@algolia/client-search';
7
+ import * as http from 'http';
8
+ import { Agent } from 'http';
9
+ import * as https from 'https';
10
+ import { Agent as Agent$1 } from 'https';
11
+ import { parse } from 'url';
12
+
13
+ const useBreakpoint = () => {
14
+ const [device, setDevice] = useState({
15
+ isDesktop: false,
16
+ isMobile: true,
17
+ isTablet: false,
18
+ });
19
+ useEffect(() => {
20
+ const handleResize = () => {
21
+ setDevice({
22
+ isDesktop: window.innerWidth >= 1024,
23
+ isMobile: window.innerWidth < 768,
24
+ isTablet: window.innerWidth >= 768 && window.innerWidth < 1024,
25
+ });
26
+ };
27
+ handleResize();
28
+ window.addEventListener('resize', handleResize);
29
+ return () => window.removeEventListener('resize', handleResize);
30
+ }, []);
31
+ return device;
32
+ };
33
+
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ function useDebouncedCallback(func, delay) {
36
+ const timeoutId = useRef();
37
+ return function debounced(...args) {
38
+ clearTimeout(timeoutId.current);
39
+ timeoutId.current = setTimeout(() => {
40
+ func(...args);
41
+ }, delay);
42
+ };
43
+ }
44
+
45
+ const useDisclosure = () => {
46
+ const [isOpen, setIsOpen] = useState(false);
47
+ const open = useCallback(() => {
48
+ setIsOpen(true);
49
+ }, []);
50
+ const close = useCallback(() => {
51
+ setIsOpen(false);
52
+ }, []);
53
+ const toggle = useCallback(() => {
54
+ setIsOpen(prevIsOpen => !prevIsOpen);
55
+ }, []);
56
+ return {
57
+ close,
58
+ isClosed: !isOpen,
59
+ isOpen,
60
+ open,
61
+ toggle,
62
+ };
63
+ };
64
+
65
+ const useScrollLock = (lock) => {
66
+ useEffect(() => {
67
+ if (lock) {
68
+ document.body.style.overflow = 'hidden';
69
+ }
70
+ else {
71
+ document.body.style.overflow = 'auto';
72
+ }
73
+ }, [lock]);
74
+ };
75
+
76
+ class EventEmitter {
77
+ constructor() {
78
+ Object.defineProperty(this, "listeners", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: void 0
83
+ });
84
+ this.listeners = new Map();
85
+ }
86
+ addEventListener(event, listener) {
87
+ if (!this.listeners.has(event)) {
88
+ this.listeners.set(event, []);
89
+ }
90
+ this.listeners.get(event).push(listener);
91
+ }
92
+ removeEventListener(event, listener) {
93
+ const listeners = this.listeners.get(event);
94
+ if (!listeners)
95
+ return;
96
+ const index = listeners.indexOf(listener);
97
+ if (index !== -1) {
98
+ listeners.splice(index, 1);
99
+ }
100
+ }
101
+ trigger(event, data) {
102
+ const listeners = this.listeners.get(event);
103
+ if (!listeners)
104
+ return;
105
+ listeners.forEach(listener => listener(data));
106
+ }
107
+ }
108
+
109
+ class State extends EventEmitter {
110
+ constructor(state) {
111
+ super();
112
+ Object.defineProperty(this, "_state", {
113
+ enumerable: true,
114
+ configurable: true,
115
+ writable: true,
116
+ value: void 0
117
+ });
118
+ this._state = state;
119
+ }
120
+ get value() {
121
+ return this._state;
122
+ }
123
+ set value(newState) {
124
+ this._state = newState;
125
+ this.trigger('stateChanged', this._state);
126
+ }
127
+ }
128
+ class GlobalState {
129
+ constructor(
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ states) {
132
+ Object.defineProperty(this, "states", {
133
+ enumerable: true,
134
+ configurable: true,
135
+ writable: true,
136
+ value: states
137
+ });
138
+ }
139
+ get(key, initialState) {
140
+ return (this.states.current[key] ||
141
+ (this.states.current[key] = new State(initialState)));
142
+ }
143
+ set(key, state) {
144
+ this.states.current[key] = state;
145
+ }
146
+ }
147
+ const GlobalStateProviderContext = createContext(undefined);
148
+ function GlobalStateProvider({ children, }) {
149
+ const internalState = useRef({});
150
+ const globalState = useRef(new GlobalState(internalState));
151
+ return (jsx(GlobalStateProviderContext.Provider, { value: globalState.current, children: children }));
152
+ }
153
+ function useGlobalState(key, initialState) {
154
+ const state = useContext(GlobalStateProviderContext).get(key, initialState);
155
+ const [rerenderState, setRerenderState] = useState(state.value);
156
+ useEffect(() => {
157
+ state.addEventListener('stateChanged', setRerenderState);
158
+ return () => {
159
+ state.removeEventListener('stateChanged', setRerenderState);
160
+ };
161
+ }, [state]);
162
+ return [rerenderState, (value) => (state.value = value)];
163
+ }
164
+
165
+ function CartProvider(props) {
166
+ const [, updateState] = useGlobalState('cart', props);
167
+ useEffect(() => {
168
+ updateState(props);
169
+ }, [props, updateState]);
170
+ return null;
171
+ }
172
+ function useCart() {
173
+ const [state] = useGlobalState('cart');
174
+ if (!state) {
175
+ throw new Error('useCart must be used together with the ReduxCartProvider');
176
+ }
177
+ return state;
178
+ }
179
+ function useProductCartLine(productId) {
180
+ const { addToCart, currentCart, isLoaded, isLoading, loadCurrentCart, removeCartLine, updateCartLine, } = useCart();
181
+ return {
182
+ addToCart,
183
+ cartLine: currentCart?.cartLines?.find(cl => cl.productId === productId),
184
+ currentCart,
185
+ isLoaded,
186
+ isLoading,
187
+ loadCurrentCart,
188
+ removeCartLine,
189
+ updateCartLine,
190
+ };
191
+ }
6
192
 
7
193
  function RightArrowFilledIcon(props) {
8
194
  return (jsx("svg", { height: "11", viewBox: "0 0 6 11", width: "6", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M.267 11a.263.263 0 0 1-.226-.402l3.463-5.467a1.2 1.2 0 0 0-.103-1.43L.602.432A.262.262 0 0 1 .805 0h2.181c.078 0 .153.034.203.093l2.081 2.43a3 3 0 0 1 .259 3.575L2.5 10.877a.267.267 0 0 1-.225.123H.266z", fill: "currentColor", fillRule: "evenodd" }) }));
@@ -16,13 +202,44 @@ function Button({ _pseudo = 'none', children, className, color = 'primary', cond
16
202
  return (jsxs(Button$1, { className: clsx(className, styles$r.button, styles$r[variant], styles$r[size], styles$r[color], { [styles$r.condensed]: condensed }, { [styles$r.icon]: icon }, styles$r[_pseudo]), isDisabled: isDisabled, onPress: onPress, type: type, children: [icon && iconPosition === 'left' && (jsx("span", { className: styles$r.icon, children: icon })), children, withArrow && (jsx(RightArrowFilledIcon, { className: styles$r['right-arrow-icon'] })), icon && iconPosition === 'right' && (jsx("span", { className: styles$r.icon, children: icon }))] }));
17
203
  }
18
204
 
19
- var styles$q = {"field-error":"field-error-module-FXnIg"};
205
+ var styles$q = {"icon-button":"icon-button-module-4PDK-","md":"icon-button-module-k3s9J","lg":"icon-button-module-agk6Y","primary":"icon-button-module-fTeP4","secondary":"icon-button-module-dM0eo"};
206
+
207
+ function IconButton({ children, className, color = 'primary', isDisabled, onPress, size = 'md', }) {
208
+ return (jsx(Button$1, { className: clsx(styles$q['icon-button'], styles$q[size], styles$q[color], className), isDisabled: isDisabled, onPress: onPress, children: children }));
209
+ }
210
+
211
+ function FavoriteFilledIcon(props) {
212
+ return (jsx("svg", { height: "24", viewBox: "0 0 24 24", width: "24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M12 22a.667.667 0 0 1-.534-.267L3.227 10.72C2.411 9.599 2 8.46 2 7.327A5.336 5.336 0 0 1 7.333 2c1.892 0 3.669.982 4.667 2.468C12.998 2.982 14.775 2 16.667 2 19.607 2 22 4.39 22 7.327c0 1.133-.411 2.272-1.222 3.387l-8.244 11.019A.667.667 0 0 1 12 22", fill: "currentColor", fillRule: "evenodd" }) }));
213
+ }
214
+
215
+ function FavoriteOutlinedIcon(props) {
216
+ return (jsx("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M7.333 3.33c-2.206 0-4 1.793-4 3.997 0 .857.316 1.71.967 2.604L12 20.223l7.705-10.299c.646-.888.962-1.74.962-2.597a4.003 4.003 0 0 0-4-3.996c-1.813 0-3.545 1.232-4.028 2.865a.666.666 0 0 1-1.278 0C10.878 4.563 9.146 3.33 7.333 3.33M12 22c-.21 0-.408-.1-.534-.267L3.227 10.72C2.411 9.599 2 8.46 2 7.327A5.336 5.336 0 0 1 7.333 2c1.892 0 3.669.982 4.667 2.468C12.998 2.982 14.775 2 16.667 2 19.607 2 22 4.39 22 7.327c0 1.133-.411 2.272-1.222 3.387l-8.245 11.019A.667.667 0 0 1 12 22", fill: "currentColor", fillRule: "evenodd" }) }));
217
+ }
218
+
219
+ var styles$p = {"favorite-button":"favorite-button-module-tXSS3","is-favorite":"favorite-button-module-l557q"};
220
+
221
+ function FavoriteButton({ isFavorite, onPress }) {
222
+ return (jsx(IconButton, { className: clsx(styles$p['favorite-button'], {
223
+ [styles$p['is-favorite']]: isFavorite,
224
+ }), color: "secondary", onPress: onPress, children: isFavorite ? jsx(FavoriteFilledIcon, {}) : jsx(FavoriteOutlinedIcon, {}) }));
225
+ }
226
+
227
+ var styles$o = {"link-button":"link-button-module-6i75g"};
228
+
229
+ function LinkButton({ children, className, href, isDisabled, onPress, target, }) {
230
+ if (href) {
231
+ return (jsx(Link, { className: clsx(styles$o['link-button'], className), href: href, isDisabled: isDisabled, onPress: onPress, target: target, children: children }));
232
+ }
233
+ return (jsx(Button$1, { className: clsx(styles$o['link-button'], className), isDisabled: isDisabled, onPress: onPress, type: "button", children: children }));
234
+ }
235
+
236
+ var styles$n = {"field-error":"field-error-module-FXnIg"};
20
237
 
21
238
  function FieldError({ children }) {
22
- return (jsx(FieldError$1, { className: styles$q['field-error'], children: children }));
239
+ return (jsx(FieldError$1, { className: styles$n['field-error'], children: children }));
23
240
  }
24
241
 
25
- var styles$p = {"input-container":"input-module-2woJR","shadow-input":"input-module-pNKEt","lg":"input-module-Dx2qC","md":"input-module-sH6e7","focus":"input-module-hEEuy","growing-input":"input-module-6HwY4"};
242
+ var styles$m = {"input-container":"input-module-2woJR","shadow-input":"input-module-pNKEt","lg":"input-module-Dx2qC","md":"input-module-sH6e7","focus":"input-module-hEEuy","growing-input":"input-module-6HwY4"};
26
243
 
27
244
  /**
28
245
  * This component is used to create an input that grows as the user types.
@@ -37,33 +254,33 @@ const Input = forwardRef(({ _pseudo = 'none', autoGrow, size = 'lg', ...inputPro
37
254
  const handleChange = (event) => isControlled
38
255
  ? onChange?.(event)
39
256
  : setUncontrolledValue(event.target.value);
40
- return (jsx("div", { className: clsx(styles$p['input-container'], styles$p[size], styles$p[_pseudo]), children: jsxs("div", { className: clsx({ [styles$p['growing-input']]: autoGrow }), children: [jsx(Input$1, { size: autoGrow ? 1 : undefined, ...props, ref: ref, onChange: handleChange }), autoGrow && jsx("span", { className: styles$p['shadow-input'], children: value })] }) }));
257
+ return (jsx("div", { className: clsx(styles$m['input-container'], styles$m[size], styles$m[_pseudo]), children: jsxs("div", { className: clsx({ [styles$m['growing-input']]: autoGrow }), children: [jsx(Input$1, { size: autoGrow ? 1 : undefined, ...props, ref: ref, onChange: handleChange }), autoGrow && jsx("span", { className: styles$m['shadow-input'], children: value })] }) }));
41
258
  });
42
259
  Input.displayName = 'Input';
43
260
 
44
- var styles$o = {"label":"label-module-LGfJt","required":"label-module-oTWaS"};
261
+ var styles$l = {"label":"label-module-LGfJt","required":"label-module-oTWaS"};
45
262
 
46
263
  function Label({ children, isRequired }) {
47
264
  if (!children)
48
265
  return null;
49
- return (jsxs(Label$1, { className: styles$o.label, children: [children, isRequired && jsx("span", { className: styles$o.required, children: "*" })] }));
266
+ return (jsxs(Label$1, { className: styles$l.label, children: [children, isRequired && jsx("span", { className: styles$l.required, children: "*" })] }));
50
267
  }
51
268
 
52
- var styles$n = {"field":"number-field-module-gmnog","button-input-container":"number-field-module-8Lvgh"};
269
+ var styles$k = {"field":"number-field-module-gmnog","button-input-container":"number-field-module-8Lvgh"};
53
270
 
54
271
  /**
55
272
  * This component is used to create a number field.
56
273
  * This field can also grow when a user types in text.
57
274
  */
58
275
  function NumberField({ autoFocus, autoGrow, defaultValue, formatOptions = { style: 'decimal', useGrouping: false }, isDisabled, isInvalid, isReadOnly, isRequired, label, maxLength, maxValue, minValue, name, onChange, onInput, onKeyUp, placeholder, showLabel = false, size = 'lg', value, withButtons, }) {
59
- return (jsxs(NumberField$1, { "aria-label": label, autoFocus: autoFocus, className: clsx(styles$n.field, styles$n[size]), defaultValue: defaultValue, formatOptions: formatOptions, isDisabled: isDisabled, isInvalid: isInvalid, isReadOnly: isReadOnly, isRequired: isRequired, maxValue: maxValue, minValue: minValue, name: name, onChange: onChange, onInput: onInput, onKeyUp: e => onKeyUp?.(e), value: value, children: [showLabel && jsx(Label, { isRequired: isRequired, children: label }), jsxs("div", { className: styles$n['button-input-container'], children: [withButtons && jsx(Button$1, { slot: "decrement", children: "-" }), jsx(Input, { autoGrow: autoGrow, maxLength: maxLength, placeholder: placeholder, size: size }), withButtons && jsx(Button$1, { slot: "increment", children: "+" })] }), jsx(FieldError, {})] }));
276
+ return (jsxs(NumberField$1, { "aria-label": label, autoFocus: autoFocus, className: clsx(styles$k.field, styles$k[size]), defaultValue: defaultValue, formatOptions: formatOptions, isDisabled: isDisabled, isInvalid: isInvalid, isReadOnly: isReadOnly, isRequired: isRequired, maxValue: maxValue, minValue: minValue, name: name, onChange: onChange, onInput: onInput, onKeyUp: e => onKeyUp?.(e), value: value, children: [showLabel && jsx(Label, { isRequired: isRequired, children: label }), jsxs("div", { className: styles$k['button-input-container'], children: [withButtons && jsx(Button$1, { slot: "decrement", children: "-" }), jsx(Input, { autoGrow: autoGrow, maxLength: maxLength, placeholder: placeholder, size: size }), withButtons && jsx(Button$1, { slot: "increment", children: "+" })] }), jsx(FieldError, {})] }));
60
277
  }
61
278
 
62
279
  function CartFilledIcon(props) {
63
280
  return (jsx("svg", { height: "24", viewBox: "0 0 24 24", width: "24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M7.896 16.666a2.603 2.603 0 1 1 0 5.207 2.603 2.603 0 0 1 0-5.207zm8.925 0a2.603 2.603 0 1 1 0 5.207 2.603 2.603 0 0 1 0-5.207zM7.896 18.1c-.645 0-1.17.524-1.17 1.169s.525 1.17 1.17 1.17a1.171 1.171 0 0 0 0-2.34zm8.925 0c-.645 0-1.17.524-1.17 1.169s.525 1.17 1.17 1.17a1.171 1.171 0 0 0 0-2.34zM4.589 3c.016 0 .032.004.048.005a.714.714 0 0 1 .146.025l.05.016a.7.7 0 0 1 .083.037l.04.021a.712.712 0 0 1 .076.053l.035.03a.699.699 0 0 1 .168.223.703.703 0 0 1 .061.209c.002.014.007.027.008.042l.207 2.646h15.776c.027.001.05.006.073.008.026.003.052.004.077.01.022.004.036.011.05.016.03.008.058.016.085.028.02.009.037.02.056.03.022.012.044.024.065.038.019.013.035.029.053.044.017.015.036.029.052.046.015.016.028.034.042.051.015.019.03.037.044.057.011.018.02.038.03.057.012.021.024.042.033.065.009.022.014.044.021.067.006.022.014.043.018.066.006.027.007.054.009.081.001.018.005.035.005.053-.001.031-.005.054-.008.077-.003.026-.004.052-.01.077l-1.39 6.054-.004.017a.698.698 0 0 1-.033.1l-.008.024a.716.716 0 0 1-.06.11l-.024.03a.707.707 0 0 1-.057.07l-.035.033a.695.695 0 0 1-.175.117l-.048.022a.723.723 0 0 1-.083.026c-.014.003-.027.008-.041.01a.707.707 0 0 1-.134.014H6.096l.112 1.427H19.41a.717.717 0 0 1 0 1.434H5.544a.714.714 0 0 1-.14-.015c-.015-.003-.03-.008-.044-.012-.03-.008-.06-.016-.087-.027-.018-.008-.034-.017-.05-.026-.024-.012-.048-.023-.07-.037-.016-.011-.03-.024-.046-.036-.02-.016-.04-.03-.058-.048-.015-.014-.027-.03-.04-.044-.017-.02-.033-.038-.048-.058-.012-.017-.021-.034-.032-.052a.678.678 0 0 1-.035-.065c-.009-.02-.016-.04-.023-.06a.715.715 0 0 1-.033-.136l-.008-.045-.904-11.571H2.717a.717.717 0 1 1 0-1.434z", fill: "currentColor", fillRule: "evenodd" }) }));
64
281
  }
65
282
 
66
- var styles$m = {"manual-input-container":"add-to-cart-button-module-AWFvQ","left-button-spacer":"add-to-cart-button-module-SS7WM"};
283
+ var styles$j = {"manual-input-container":"add-to-cart-button-module-AWFvQ","left-button-spacer":"add-to-cart-button-module-SS7WM"};
67
284
 
68
285
  function AddToCartButton({ initialState = 'initial', onChange, quantity, }) {
69
286
  const [currentState, setState] = useState(initialState);
@@ -125,43 +342,59 @@ function ManualInputState({ onCancel, onConfirm, quantity, }) {
125
342
  e.key === 'Enter' && onConfirm(updatedQuantity);
126
343
  e.key === 'Escape' && onCancel();
127
344
  };
128
- return (jsxs("div", { className: styles$m['manual-input-container'], children: [jsx("div", { className: styles$m['left-button-spacer'] }), jsx(NumberField, { autoFocus: true, autoGrow: true, defaultValue: quantity, formatOptions: {
345
+ return (jsxs("div", { className: styles$j['manual-input-container'], children: [jsx("div", { className: styles$j['left-button-spacer'] }), jsx(NumberField, { autoFocus: true, autoGrow: true, defaultValue: quantity, formatOptions: {
129
346
  maximumFractionDigits: 0,
130
347
  style: 'decimal',
131
348
  useGrouping: false,
132
349
  }, label: "Quantity", maxLength: 4, maxValue: 9999, minValue: 0, name: "quantity", onChange: setQuantity, onKeyUp: onKeyUp, showLabel: false, size: "md" }), jsx(Button, { condensed: true, onPress: () => onConfirm(updatedQuantity), size: "md", children: "OK" })] }));
133
350
  }
134
351
 
135
- var styles$l = {"icon-button":"icon-button-module-4PDK-","md":"icon-button-module-k3s9J","lg":"icon-button-module-agk6Y","primary":"icon-button-module-fTeP4","secondary":"icon-button-module-dM0eo"};
136
-
137
- function IconButton({ children, className, color = 'primary', isDisabled, onPress, size = 'md', }) {
138
- return (jsx(Button$1, { className: clsx(styles$l['icon-button'], styles$l[size], styles$l[color], className), isDisabled: isDisabled, onPress: onPress, children: children }));
139
- }
140
-
141
- function FavoriteFilledIcon(props) {
142
- return (jsx("svg", { height: "24", viewBox: "0 0 24 24", width: "24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M12 22a.667.667 0 0 1-.534-.267L3.227 10.72C2.411 9.599 2 8.46 2 7.327A5.336 5.336 0 0 1 7.333 2c1.892 0 3.669.982 4.667 2.468C12.998 2.982 14.775 2 16.667 2 19.607 2 22 4.39 22 7.327c0 1.133-.411 2.272-1.222 3.387l-8.244 11.019A.667.667 0 0 1 12 22", fill: "currentColor", fillRule: "evenodd" }) }));
143
- }
144
-
145
- function FavoriteOutlinedIcon(props) {
146
- return (jsx("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M7.333 3.33c-2.206 0-4 1.793-4 3.997 0 .857.316 1.71.967 2.604L12 20.223l7.705-10.299c.646-.888.962-1.74.962-2.597a4.003 4.003 0 0 0-4-3.996c-1.813 0-3.545 1.232-4.028 2.865a.666.666 0 0 1-1.278 0C10.878 4.563 9.146 3.33 7.333 3.33M12 22c-.21 0-.408-.1-.534-.267L3.227 10.72C2.411 9.599 2 8.46 2 7.327A5.336 5.336 0 0 1 7.333 2c1.892 0 3.669.982 4.667 2.468C12.998 2.982 14.775 2 16.667 2 19.607 2 22 4.39 22 7.327c0 1.133-.411 2.272-1.222 3.387l-8.245 11.019A.667.667 0 0 1 12 22", fill: "currentColor", fillRule: "evenodd" }) }));
147
- }
148
-
149
- var styles$k = {"favorite-button":"favorite-button-module-tXSS3","is-favorite":"favorite-button-module-l557q"};
150
-
151
- function FavoriteButton({ isFavorite, onPress }) {
152
- return (jsx(IconButton, { className: clsx(styles$k['favorite-button'], {
153
- [styles$k['is-favorite']]: isFavorite,
154
- }), color: "secondary", onPress: onPress, children: isFavorite ? jsx(FavoriteFilledIcon, {}) : jsx(FavoriteOutlinedIcon, {}) }));
155
- }
156
-
157
- var styles$j = {"link-button":"link-button-module-6i75g"};
158
-
159
- function LinkButton({ children, className, href, isDisabled, onPress, target, }) {
160
- if (href) {
161
- return (jsx(Link, { className: clsx(styles$j['link-button'], className), href: href, isDisabled: isDisabled, onPress: onPress, target: target, children: children }));
162
- }
163
- return (jsx(Button$1, { className: clsx(styles$j['link-button'], className), isDisabled: isDisabled, onPress: onPress, type: "button", children: children }));
164
- }
352
+ const ConnectedAddToCartButton = ({ productId }) => {
353
+ const [quantity, setQuantity] = useState(0);
354
+ const { addToCart, cartLine: _cartLine, isLoaded, isLoading, loadCurrentCart, removeCartLine, updateCartLine, } = useProductCartLine(productId);
355
+ const [cartLine, setCartLineState] = useState(_cartLine);
356
+ const setCartLineStateDebounced = useDebouncedCallback(setCartLineState, 4000);
357
+ useEffect(() => {
358
+ if (isLoading || isLoaded)
359
+ return;
360
+ loadCurrentCart();
361
+ // eslint-disable-next-line react-hooks/exhaustive-deps
362
+ }, []);
363
+ useEffect(() => {
364
+ setQuantity(cartLine?.qtyOrdered || 0);
365
+ }, [cartLine]);
366
+ useEffect(() => {
367
+ /* Debounce updating the internal cart line state.
368
+ * This is necessary when a user mutates the cart multiple times in quick succession.
369
+ * A response from the server may take a while to come back, so we need to wait for it.
370
+ * If we don't debounce, the cart line state will be updated multiple times, causing the UI to flicker.
371
+ */
372
+ if (!cartLine) {
373
+ setCartLineState(_cartLine);
374
+ }
375
+ else {
376
+ setCartLineStateDebounced(_cartLine);
377
+ }
378
+ }, [_cartLine, cartLine, setCartLineStateDebounced]);
379
+ const updateCart = useDebouncedCallback((quantity) => {
380
+ if (cartLine) {
381
+ if (quantity === 0) {
382
+ removeCartLine({ cartLineId: cartLine.id });
383
+ }
384
+ else {
385
+ updateCartLine({ ...cartLine, qtyOrdered: quantity });
386
+ }
387
+ }
388
+ else {
389
+ addToCart({ productId, quantity });
390
+ }
391
+ }, 300);
392
+ const handleChange = (quantity) => {
393
+ setQuantity(quantity);
394
+ updateCart(quantity);
395
+ };
396
+ return jsx(AddToCartButton, { onChange: handleChange, quantity: quantity });
397
+ };
165
398
 
166
399
  var styles$i = {"tag":"tag-module-B7r15","body":"tag-module-4cfCf","shape":"tag-module-c7CRb"};
167
400
 
@@ -473,26 +706,6 @@ function AlgoliaCategories() {
473
706
  return (jsx("div", { children: categories?.length > 0 && (jsxs("section", { className: styles$3['categories-section'], children: [jsx("h4", { className: styles$3['categories-header'], children: "Categories" }), jsx("div", { className: styles$3.categories, children: categories.map(({ count, href, id, name }) => (jsxs("a", { className: styles$3['category'], href: href, children: [jsx("span", { children: name }), ' ', jsxs("span", { className: styles$3.count, children: ["(", count, ")"] })] }, id))) })] })) }));
474
707
  }
475
708
 
476
- const useDisclosure = () => {
477
- const [isOpen, setIsOpen] = useState(false);
478
- const open = useCallback(() => {
479
- setIsOpen(true);
480
- }, []);
481
- const close = useCallback(() => {
482
- setIsOpen(false);
483
- }, []);
484
- const toggle = useCallback(() => {
485
- setIsOpen(prevIsOpen => !prevIsOpen);
486
- }, []);
487
- return {
488
- close,
489
- isClosed: !isOpen,
490
- isOpen,
491
- open,
492
- toggle,
493
- };
494
- };
495
-
496
709
  function AlgoliaMultiSelect({ attribute }) {
497
710
  const { items, refine } = useRefinementList({
498
711
  attribute,
@@ -560,98 +773,6 @@ function AlgoliaSortBy() {
560
773
  return (jsx(Select, { label: "Sort", onChange: value => refine(String(value)), options: options, selectedOption: "dev_sonic_products_en", showLabel: false }));
561
774
  }
562
775
 
563
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
564
- function useDebouncedCallback(func, delay) {
565
- const timeoutId = useRef();
566
- return function debounced(...args) {
567
- clearTimeout(timeoutId.current);
568
- timeoutId.current = setTimeout(() => {
569
- func(...args);
570
- }, delay);
571
- };
572
- }
573
-
574
- const GlobalStateProviderContext = createContext(undefined);
575
- function useGlobalState(key, initialState) {
576
- const state = useContext(GlobalStateProviderContext).get(key, initialState);
577
- const [rerenderState, setRerenderState] = useState(state.value);
578
- useEffect(() => {
579
- state.addEventListener('stateChanged', setRerenderState);
580
- return () => {
581
- state.removeEventListener('stateChanged', setRerenderState);
582
- };
583
- }, [state]);
584
- return [rerenderState, (value) => (state.value = value)];
585
- }
586
-
587
- function useCart() {
588
- const [state] = useGlobalState('cart');
589
- if (!state) {
590
- throw new Error('useCart must be used together with the ReduxCartProvider');
591
- }
592
- return state;
593
- }
594
- function useProductCartLine(productId) {
595
- const { addToCart, currentCart, isLoaded, isLoading, loadCurrentCart, removeCartLine, updateCartLine, } = useCart();
596
- return {
597
- addToCart,
598
- cartLine: currentCart?.cartLines?.find(cl => cl.productId === productId),
599
- currentCart,
600
- isLoaded,
601
- isLoading,
602
- loadCurrentCart,
603
- removeCartLine,
604
- updateCartLine,
605
- };
606
- }
607
-
608
- const ConnectedAddToCartButton = ({ productId }) => {
609
- const [quantity, setQuantity] = useState(0);
610
- const { addToCart, cartLine: _cartLine, isLoaded, isLoading, loadCurrentCart, removeCartLine, updateCartLine, } = useProductCartLine(productId);
611
- const [cartLine, setCartLineState] = useState(_cartLine);
612
- const setCartLineStateDebounced = useDebouncedCallback(setCartLineState, 4000);
613
- useEffect(() => {
614
- if (isLoading || isLoaded)
615
- return;
616
- loadCurrentCart();
617
- // eslint-disable-next-line react-hooks/exhaustive-deps
618
- }, []);
619
- useEffect(() => {
620
- setQuantity(cartLine?.qtyOrdered || 0);
621
- }, [cartLine]);
622
- useEffect(() => {
623
- /* Debounce updating the internal cart line state.
624
- * This is necessary when a user mutates the cart multiple times in quick succession.
625
- * A response from the server may take a while to come back, so we need to wait for it.
626
- * If we don't debounce, the cart line state will be updated multiple times, causing the UI to flicker.
627
- */
628
- if (!cartLine) {
629
- setCartLineState(_cartLine);
630
- }
631
- else {
632
- setCartLineStateDebounced(_cartLine);
633
- }
634
- }, [_cartLine, cartLine, setCartLineStateDebounced]);
635
- const updateCart = useDebouncedCallback((quantity) => {
636
- if (cartLine) {
637
- if (quantity === 0) {
638
- removeCartLine({ cartLineId: cartLine.id });
639
- }
640
- else {
641
- updateCartLine({ ...cartLine, qtyOrdered: quantity });
642
- }
643
- }
644
- else {
645
- addToCart({ productId, quantity });
646
- }
647
- }, 300);
648
- const handleChange = (quantity) => {
649
- setQuantity(quantity);
650
- updateCart(quantity);
651
- };
652
- return jsx(AddToCartButton, { onChange: handleChange, quantity: quantity });
653
- };
654
-
655
776
  function ConnectedProductCart({ productId, ...props }) {
656
777
  return (jsx(ProductCard, { ...props, addToCartButton: jsx(ConnectedAddToCartButton, { productId: productId }) }));
657
778
  }
@@ -738,4 +859,1436 @@ function parseProductListingSearchParams(params) {
738
859
  };
739
860
  }
740
861
 
741
- export { Accordion, AddToCartButton, Button, CartFilledIcon, CartOutlinedIcon, Checkbox, ColorCheckbox, DehashedOutlinedIcon, FavoriteButton, FavoriteFilledIcon, FavoriteOutlinedIcon, FormattedMessage, HashedOutlinedIcon, IconButton, Image, IntlProvider, LinkButton, MultiSelect, NumberField, ProductCard, ProductListing, ProductOverviewGrid, ProductPrice, ProductSku, RightArrowFilledIcon, Select, ShowAll, Sidebar, TextField, createProductListingSearchParams, parseProductListingSearchParams, useFormattedMessage };
862
+ function AlgoliaProductList() {
863
+ const r = useHits();
864
+ const { hits } = r;
865
+ r.results?.nbHits;
866
+ return (jsxs("div", { children: [jsx("h2", { children: "Product List" }), hits.map(hit => (jsxs("div", { children: [jsx("h3", { children: hit.name }), jsxs("div", { children: ["W x H x L: ", hit.width, " x ", hit.height, " x ", hit.length] })] }, hit.objectID)))] }));
867
+ }
868
+
869
+ function getDefaultExportFromCjs (x) {
870
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
871
+ }
872
+
873
+ function getAugmentedNamespace(n) {
874
+ if (n.__esModule) return n;
875
+ var f = n.default;
876
+ if (typeof f == "function") {
877
+ var a = function a () {
878
+ if (this instanceof a) {
879
+ return Reflect.construct(f, arguments, this.constructor);
880
+ }
881
+ return f.apply(this, arguments);
882
+ };
883
+ a.prototype = f.prototype;
884
+ } else a = {};
885
+ Object.defineProperty(a, '__esModule', {value: true});
886
+ Object.keys(n).forEach(function (k) {
887
+ var d = Object.getOwnPropertyDescriptor(n, k);
888
+ Object.defineProperty(a, k, d.get ? d : {
889
+ enumerable: true,
890
+ get: function () {
891
+ return n[k];
892
+ }
893
+ });
894
+ });
895
+ return a;
896
+ }
897
+
898
+ var algoliasearch$3 = {exports: {}};
899
+
900
+ // @todo Add logger on options to debug when caches go wrong.
901
+ function createFallbackableCache(options) {
902
+ const caches = [...options.caches];
903
+ const current = caches.shift(); // eslint-disable-line functional/immutable-data
904
+ if (current === undefined) {
905
+ return createNullCache();
906
+ }
907
+ return {
908
+ get(key, defaultValue, events = {
909
+ miss: () => Promise.resolve(),
910
+ }) {
911
+ return current.get(key, defaultValue, events).catch(() => {
912
+ return createFallbackableCache({ caches }).get(key, defaultValue, events);
913
+ });
914
+ },
915
+ set(key, value) {
916
+ return current.set(key, value).catch(() => {
917
+ return createFallbackableCache({ caches }).set(key, value);
918
+ });
919
+ },
920
+ delete(key) {
921
+ return current.delete(key).catch(() => {
922
+ return createFallbackableCache({ caches }).delete(key);
923
+ });
924
+ },
925
+ clear() {
926
+ return current.clear().catch(() => {
927
+ return createFallbackableCache({ caches }).clear();
928
+ });
929
+ },
930
+ };
931
+ }
932
+
933
+ function createNullCache() {
934
+ return {
935
+ get(_key, defaultValue, events = {
936
+ miss: () => Promise.resolve(),
937
+ }) {
938
+ const value = defaultValue();
939
+ return value
940
+ .then(result => Promise.all([result, events.miss(result)]))
941
+ .then(([result]) => result);
942
+ },
943
+ set(_key, value) {
944
+ return Promise.resolve(value);
945
+ },
946
+ delete(_key) {
947
+ return Promise.resolve();
948
+ },
949
+ clear() {
950
+ return Promise.resolve();
951
+ },
952
+ };
953
+ }
954
+
955
+ var cacheCommon_esm = /*#__PURE__*/Object.freeze({
956
+ __proto__: null,
957
+ createFallbackableCache: createFallbackableCache,
958
+ createNullCache: createNullCache
959
+ });
960
+
961
+ var require$$0 = /*@__PURE__*/getAugmentedNamespace(cacheCommon_esm);
962
+
963
+ function createInMemoryCache(options = { serializable: true }) {
964
+ // eslint-disable-next-line functional/no-let
965
+ let cache = {};
966
+ return {
967
+ get(key, defaultValue, events = {
968
+ miss: () => Promise.resolve(),
969
+ }) {
970
+ const keyAsString = JSON.stringify(key);
971
+ if (keyAsString in cache) {
972
+ return Promise.resolve(options.serializable ? JSON.parse(cache[keyAsString]) : cache[keyAsString]);
973
+ }
974
+ const promise = defaultValue();
975
+ const miss = (events && events.miss) || (() => Promise.resolve());
976
+ return promise.then((value) => miss(value)).then(() => promise);
977
+ },
978
+ set(key, value) {
979
+ // eslint-disable-next-line functional/immutable-data
980
+ cache[JSON.stringify(key)] = options.serializable ? JSON.stringify(value) : value;
981
+ return Promise.resolve(value);
982
+ },
983
+ delete(key) {
984
+ // eslint-disable-next-line functional/immutable-data
985
+ delete cache[JSON.stringify(key)];
986
+ return Promise.resolve();
987
+ },
988
+ clear() {
989
+ cache = {};
990
+ return Promise.resolve();
991
+ },
992
+ };
993
+ }
994
+
995
+ var cacheInMemory_esm = /*#__PURE__*/Object.freeze({
996
+ __proto__: null,
997
+ createInMemoryCache: createInMemoryCache
998
+ });
999
+
1000
+ var require$$1 = /*@__PURE__*/getAugmentedNamespace(cacheInMemory_esm);
1001
+
1002
+ function createAuth(authMode, appId, apiKey) {
1003
+ const credentials = {
1004
+ 'x-algolia-api-key': apiKey,
1005
+ 'x-algolia-application-id': appId,
1006
+ };
1007
+ return {
1008
+ headers() {
1009
+ return authMode === AuthMode.WithinHeaders ? credentials : {};
1010
+ },
1011
+ queryParameters() {
1012
+ return authMode === AuthMode.WithinQueryParameters ? credentials : {};
1013
+ },
1014
+ };
1015
+ }
1016
+
1017
+ function createRetryablePromise(callback) {
1018
+ let retriesCount = 0; // eslint-disable-line functional/no-let
1019
+ const retry = () => {
1020
+ retriesCount++;
1021
+ return new Promise((resolve) => {
1022
+ setTimeout(() => {
1023
+ resolve(callback(retry));
1024
+ }, Math.min(100 * retriesCount, 1000));
1025
+ });
1026
+ };
1027
+ return callback(retry);
1028
+ }
1029
+
1030
+ function createWaitablePromise(promise, wait = (_response, _requestOptions) => {
1031
+ return Promise.resolve();
1032
+ }) {
1033
+ // eslint-disable-next-line functional/immutable-data
1034
+ return Object.assign(promise, {
1035
+ wait(requestOptions) {
1036
+ return createWaitablePromise(promise
1037
+ .then(response => Promise.all([wait(response, requestOptions), response]))
1038
+ .then(promiseResults => promiseResults[1]));
1039
+ },
1040
+ });
1041
+ }
1042
+
1043
+ // eslint-disable-next-line functional/prefer-readonly-type
1044
+ function shuffle(array) {
1045
+ let c = array.length - 1; // eslint-disable-line functional/no-let
1046
+ // eslint-disable-next-line functional/no-loop-statement
1047
+ for (c; c > 0; c--) {
1048
+ const b = Math.floor(Math.random() * (c + 1));
1049
+ const a = array[c];
1050
+ array[c] = array[b]; // eslint-disable-line functional/immutable-data, no-param-reassign
1051
+ array[b] = a; // eslint-disable-line functional/immutable-data, no-param-reassign
1052
+ }
1053
+ return array;
1054
+ }
1055
+ function addMethods(base, methods) {
1056
+ if (!methods) {
1057
+ return base;
1058
+ }
1059
+ Object.keys(methods).forEach(key => {
1060
+ // eslint-disable-next-line functional/immutable-data, no-param-reassign
1061
+ base[key] = methods[key](base);
1062
+ });
1063
+ return base;
1064
+ }
1065
+ function encode$1(format, ...args) {
1066
+ // eslint-disable-next-line functional/no-let
1067
+ let i = 0;
1068
+ return format.replace(/%s/g, () => encodeURIComponent(args[i++]));
1069
+ }
1070
+
1071
+ const version = '4.23.3';
1072
+
1073
+ const destroy = (base) => {
1074
+ return () => {
1075
+ return base.transporter.requester.destroy();
1076
+ };
1077
+ };
1078
+
1079
+ const AuthMode = {
1080
+ /**
1081
+ * If auth credentials should be in query parameters.
1082
+ */
1083
+ WithinQueryParameters: 0,
1084
+ /**
1085
+ * If auth credentials should be in headers.
1086
+ */
1087
+ WithinHeaders: 1,
1088
+ };
1089
+
1090
+ var clientCommon_esm = /*#__PURE__*/Object.freeze({
1091
+ __proto__: null,
1092
+ AuthMode: AuthMode,
1093
+ addMethods: addMethods,
1094
+ createAuth: createAuth,
1095
+ createRetryablePromise: createRetryablePromise,
1096
+ createWaitablePromise: createWaitablePromise,
1097
+ destroy: destroy,
1098
+ encode: encode$1,
1099
+ shuffle: shuffle,
1100
+ version: version
1101
+ });
1102
+
1103
+ const MethodEnum = {
1104
+ Delete: 'DELETE',
1105
+ Get: 'GET',
1106
+ Post: 'POST',
1107
+ Put: 'PUT',
1108
+ };
1109
+
1110
+ var requesterCommon_esm = /*#__PURE__*/Object.freeze({
1111
+ __proto__: null,
1112
+ MethodEnum: MethodEnum
1113
+ });
1114
+
1115
+ function createMappedRequestOptions(requestOptions, timeout) {
1116
+ const options = requestOptions || {};
1117
+ const data = options.data || {};
1118
+ Object.keys(options).forEach(key => {
1119
+ if (['timeout', 'headers', 'queryParameters', 'data', 'cacheable'].indexOf(key) === -1) {
1120
+ data[key] = options[key]; // eslint-disable-line functional/immutable-data
1121
+ }
1122
+ });
1123
+ return {
1124
+ data: Object.entries(data).length > 0 ? data : undefined,
1125
+ timeout: options.timeout || timeout,
1126
+ headers: options.headers || {},
1127
+ queryParameters: options.queryParameters || {},
1128
+ cacheable: options.cacheable,
1129
+ };
1130
+ }
1131
+
1132
+ const CallEnum = {
1133
+ /**
1134
+ * If the host is read only.
1135
+ */
1136
+ Read: 1,
1137
+ /**
1138
+ * If the host is write only.
1139
+ */
1140
+ Write: 2,
1141
+ /**
1142
+ * If the host is both read and write.
1143
+ */
1144
+ Any: 3,
1145
+ };
1146
+
1147
+ const HostStatusEnum = {
1148
+ Up: 1,
1149
+ Down: 2,
1150
+ Timeouted: 3,
1151
+ };
1152
+
1153
+ // By default, API Clients at Algolia have expiration delay
1154
+ // of 5 mins. In the JavaScript client, we have 2 mins.
1155
+ const EXPIRATION_DELAY = 2 * 60 * 1000;
1156
+ function createStatefulHost(host, status = HostStatusEnum.Up) {
1157
+ return {
1158
+ ...host,
1159
+ status,
1160
+ lastUpdate: Date.now(),
1161
+ };
1162
+ }
1163
+ function isStatefulHostUp(host) {
1164
+ return host.status === HostStatusEnum.Up || Date.now() - host.lastUpdate > EXPIRATION_DELAY;
1165
+ }
1166
+ function isStatefulHostTimeouted(host) {
1167
+ return (host.status === HostStatusEnum.Timeouted && Date.now() - host.lastUpdate <= EXPIRATION_DELAY);
1168
+ }
1169
+
1170
+ function createStatelessHost(options) {
1171
+ if (typeof options === 'string') {
1172
+ return {
1173
+ protocol: 'https',
1174
+ url: options,
1175
+ accept: CallEnum.Any,
1176
+ };
1177
+ }
1178
+ return {
1179
+ protocol: options.protocol || 'https',
1180
+ url: options.url,
1181
+ accept: options.accept || CallEnum.Any,
1182
+ };
1183
+ }
1184
+
1185
+ function createRetryableOptions(hostsCache, statelessHosts) {
1186
+ return Promise.all(statelessHosts.map(statelessHost => {
1187
+ return hostsCache.get(statelessHost, () => {
1188
+ return Promise.resolve(createStatefulHost(statelessHost));
1189
+ });
1190
+ })).then(statefulHosts => {
1191
+ const hostsUp = statefulHosts.filter(host => isStatefulHostUp(host));
1192
+ const hostsTimeouted = statefulHosts.filter(host => isStatefulHostTimeouted(host));
1193
+ /**
1194
+ * Note, we put the hosts that previously timeouted on the end of the list.
1195
+ */
1196
+ const hostsAvailable = [...hostsUp, ...hostsTimeouted];
1197
+ const statelessHostsAvailable = hostsAvailable.length > 0
1198
+ ? hostsAvailable.map(host => createStatelessHost(host))
1199
+ : statelessHosts;
1200
+ return {
1201
+ getTimeout(timeoutsCount, baseTimeout) {
1202
+ /**
1203
+ * Imagine that you have 4 hosts, if timeouts will increase
1204
+ * on the following way: 1 (timeouted) > 4 (timeouted) > 5 (200)
1205
+ *
1206
+ * Note that, the very next request, we start from the previous timeout
1207
+ *
1208
+ * 5 (timeouted) > 6 (timeouted) > 7 ...
1209
+ *
1210
+ * This strategy may need to be reviewed, but is the strategy on the our
1211
+ * current v3 version.
1212
+ */
1213
+ const timeoutMultiplier = hostsTimeouted.length === 0 && timeoutsCount === 0
1214
+ ? 1
1215
+ : hostsTimeouted.length + 3 + timeoutsCount;
1216
+ return timeoutMultiplier * baseTimeout;
1217
+ },
1218
+ statelessHosts: statelessHostsAvailable,
1219
+ };
1220
+ });
1221
+ }
1222
+
1223
+ const isNetworkError = ({ isTimedOut, status }) => {
1224
+ return !isTimedOut && ~~status === 0;
1225
+ };
1226
+ const isRetryable = (response) => {
1227
+ const status = response.status;
1228
+ const isTimedOut = response.isTimedOut;
1229
+ return (isTimedOut || isNetworkError(response) || (~~(status / 100) !== 2 && ~~(status / 100) !== 4));
1230
+ };
1231
+ const isSuccess = ({ status }) => {
1232
+ return ~~(status / 100) === 2;
1233
+ };
1234
+ const retryDecision = (response, outcomes) => {
1235
+ if (isRetryable(response)) {
1236
+ return outcomes.onRetry(response);
1237
+ }
1238
+ if (isSuccess(response)) {
1239
+ return outcomes.onSuccess(response);
1240
+ }
1241
+ return outcomes.onFail(response);
1242
+ };
1243
+
1244
+ function retryableRequest(transporter, statelessHosts, request, requestOptions) {
1245
+ const stackTrace = []; // eslint-disable-line functional/prefer-readonly-type
1246
+ /**
1247
+ * First we prepare the payload that do not depend from hosts.
1248
+ */
1249
+ const data = serializeData(request, requestOptions);
1250
+ const headers = serializeHeaders(transporter, requestOptions);
1251
+ const method = request.method;
1252
+ // On `GET`, the data is proxied to query parameters.
1253
+ const dataQueryParameters = request.method !== MethodEnum.Get
1254
+ ? {}
1255
+ : {
1256
+ ...request.data,
1257
+ ...requestOptions.data,
1258
+ };
1259
+ const queryParameters = {
1260
+ 'x-algolia-agent': transporter.userAgent.value,
1261
+ ...transporter.queryParameters,
1262
+ ...dataQueryParameters,
1263
+ ...requestOptions.queryParameters,
1264
+ };
1265
+ let timeoutsCount = 0; // eslint-disable-line functional/no-let
1266
+ const retry = (hosts, // eslint-disable-line functional/prefer-readonly-type
1267
+ getTimeout) => {
1268
+ /**
1269
+ * We iterate on each host, until there is no host left.
1270
+ */
1271
+ const host = hosts.pop(); // eslint-disable-line functional/immutable-data
1272
+ if (host === undefined) {
1273
+ throw createRetryError(stackTraceWithoutCredentials(stackTrace));
1274
+ }
1275
+ const payload = {
1276
+ data,
1277
+ headers,
1278
+ method,
1279
+ url: serializeUrl(host, request.path, queryParameters),
1280
+ connectTimeout: getTimeout(timeoutsCount, transporter.timeouts.connect),
1281
+ responseTimeout: getTimeout(timeoutsCount, requestOptions.timeout),
1282
+ };
1283
+ /**
1284
+ * The stackFrame is pushed to the stackTrace so we
1285
+ * can have information about onRetry and onFailure
1286
+ * decisions.
1287
+ */
1288
+ const pushToStackTrace = (response) => {
1289
+ const stackFrame = {
1290
+ request: payload,
1291
+ response,
1292
+ host,
1293
+ triesLeft: hosts.length,
1294
+ };
1295
+ // eslint-disable-next-line functional/immutable-data
1296
+ stackTrace.push(stackFrame);
1297
+ return stackFrame;
1298
+ };
1299
+ const decisions = {
1300
+ onSuccess: response => deserializeSuccess(response),
1301
+ onRetry(response) {
1302
+ const stackFrame = pushToStackTrace(response);
1303
+ /**
1304
+ * If response is a timeout, we increaset the number of
1305
+ * timeouts so we can increase the timeout later.
1306
+ */
1307
+ if (response.isTimedOut) {
1308
+ timeoutsCount++;
1309
+ }
1310
+ return Promise.all([
1311
+ /**
1312
+ * Failures are individually send the logger, allowing
1313
+ * the end user to debug / store stack frames even
1314
+ * when a retry error does not happen.
1315
+ */
1316
+ transporter.logger.info('Retryable failure', stackFrameWithoutCredentials(stackFrame)),
1317
+ /**
1318
+ * We also store the state of the host in failure cases. If the host, is
1319
+ * down it will remain down for the next 2 minutes. In a timeout situation,
1320
+ * this host will be added end of the list of hosts on the next request.
1321
+ */
1322
+ transporter.hostsCache.set(host, createStatefulHost(host, response.isTimedOut ? HostStatusEnum.Timeouted : HostStatusEnum.Down)),
1323
+ ]).then(() => retry(hosts, getTimeout));
1324
+ },
1325
+ onFail(response) {
1326
+ pushToStackTrace(response);
1327
+ throw deserializeFailure(response, stackTraceWithoutCredentials(stackTrace));
1328
+ },
1329
+ };
1330
+ return transporter.requester.send(payload).then(response => {
1331
+ return retryDecision(response, decisions);
1332
+ });
1333
+ };
1334
+ /**
1335
+ * Finally, for each retryable host perform request until we got a non
1336
+ * retryable response. Some notes here:
1337
+ *
1338
+ * 1. The reverse here is applied so we can apply a `pop` later on => more performant.
1339
+ * 2. We also get from the retryable options a timeout multiplier that is tailored
1340
+ * for the current context.
1341
+ */
1342
+ return createRetryableOptions(transporter.hostsCache, statelessHosts).then(options => {
1343
+ return retry([...options.statelessHosts].reverse(), options.getTimeout);
1344
+ });
1345
+ }
1346
+
1347
+ function createTransporter(options) {
1348
+ const { hostsCache, logger, requester, requestsCache, responsesCache, timeouts, userAgent, hosts, queryParameters, headers, } = options;
1349
+ const transporter = {
1350
+ hostsCache,
1351
+ logger,
1352
+ requester,
1353
+ requestsCache,
1354
+ responsesCache,
1355
+ timeouts,
1356
+ userAgent,
1357
+ headers,
1358
+ queryParameters,
1359
+ hosts: hosts.map(host => createStatelessHost(host)),
1360
+ read(request, requestOptions) {
1361
+ /**
1362
+ * First, we compute the user request options. Now, keep in mind,
1363
+ * that using request options the user is able to modified the intire
1364
+ * payload of the request. Such as headers, query parameters, and others.
1365
+ */
1366
+ const mappedRequestOptions = createMappedRequestOptions(requestOptions, transporter.timeouts.read);
1367
+ const createRetryableRequest = () => {
1368
+ /**
1369
+ * Then, we prepare a function factory that contains the construction of
1370
+ * the retryable request. At this point, we may *not* perform the actual
1371
+ * request. But we want to have the function factory ready.
1372
+ */
1373
+ return retryableRequest(transporter, transporter.hosts.filter(host => (host.accept & CallEnum.Read) !== 0), request, mappedRequestOptions);
1374
+ };
1375
+ /**
1376
+ * Once we have the function factory ready, we need to determine of the
1377
+ * request is "cacheable" - should be cached. Note that, once again,
1378
+ * the user can force this option.
1379
+ */
1380
+ const cacheable = mappedRequestOptions.cacheable !== undefined
1381
+ ? mappedRequestOptions.cacheable
1382
+ : request.cacheable;
1383
+ /**
1384
+ * If is not "cacheable", we immediatly trigger the retryable request, no
1385
+ * need to check cache implementations.
1386
+ */
1387
+ if (cacheable !== true) {
1388
+ return createRetryableRequest();
1389
+ }
1390
+ /**
1391
+ * If the request is "cacheable", we need to first compute the key to ask
1392
+ * the cache implementations if this request is on progress or if the
1393
+ * response already exists on the cache.
1394
+ */
1395
+ const key = {
1396
+ request,
1397
+ mappedRequestOptions,
1398
+ transporter: {
1399
+ queryParameters: transporter.queryParameters,
1400
+ headers: transporter.headers,
1401
+ },
1402
+ };
1403
+ /**
1404
+ * With the computed key, we first ask the responses cache
1405
+ * implemention if this request was been resolved before.
1406
+ */
1407
+ return transporter.responsesCache.get(key, () => {
1408
+ /**
1409
+ * If the request has never resolved before, we actually ask if there
1410
+ * is a current request with the same key on progress.
1411
+ */
1412
+ return transporter.requestsCache.get(key, () => {
1413
+ return (transporter.requestsCache
1414
+ /**
1415
+ * Finally, if there is no request in progress with the same key,
1416
+ * this `createRetryableRequest()` will actually trigger the
1417
+ * retryable request.
1418
+ */
1419
+ .set(key, createRetryableRequest())
1420
+ .then(response => Promise.all([transporter.requestsCache.delete(key), response]), err => Promise.all([transporter.requestsCache.delete(key), Promise.reject(err)]))
1421
+ .then(([_, response]) => response));
1422
+ });
1423
+ }, {
1424
+ /**
1425
+ * Of course, once we get this response back from the server, we
1426
+ * tell response cache to actually store the received response
1427
+ * to be used later.
1428
+ */
1429
+ miss: response => transporter.responsesCache.set(key, response),
1430
+ });
1431
+ },
1432
+ write(request, requestOptions) {
1433
+ /**
1434
+ * On write requests, no cache mechanisms are applied, and we
1435
+ * proxy the request immediately to the requester.
1436
+ */
1437
+ return retryableRequest(transporter, transporter.hosts.filter(host => (host.accept & CallEnum.Write) !== 0), request, createMappedRequestOptions(requestOptions, transporter.timeouts.write));
1438
+ },
1439
+ };
1440
+ return transporter;
1441
+ }
1442
+
1443
+ function createUserAgent(version) {
1444
+ const userAgent = {
1445
+ value: `Algolia for JavaScript (${version})`,
1446
+ add(options) {
1447
+ const addedUserAgent = `; ${options.segment}${options.version !== undefined ? ` (${options.version})` : ''}`;
1448
+ if (userAgent.value.indexOf(addedUserAgent) === -1) {
1449
+ // eslint-disable-next-line functional/immutable-data
1450
+ userAgent.value = `${userAgent.value}${addedUserAgent}`;
1451
+ }
1452
+ return userAgent;
1453
+ },
1454
+ };
1455
+ return userAgent;
1456
+ }
1457
+
1458
+ function deserializeSuccess(response) {
1459
+ // eslint-disable-next-line functional/no-try-statement
1460
+ try {
1461
+ return JSON.parse(response.content);
1462
+ }
1463
+ catch (e) {
1464
+ throw createDeserializationError(e.message, response);
1465
+ }
1466
+ }
1467
+ function deserializeFailure({ content, status }, stackFrame) {
1468
+ // eslint-disable-next-line functional/no-let
1469
+ let message = content;
1470
+ // eslint-disable-next-line functional/no-try-statement
1471
+ try {
1472
+ message = JSON.parse(content).message;
1473
+ }
1474
+ catch (e) {
1475
+ // ..
1476
+ }
1477
+ return createApiError(message, status, stackFrame);
1478
+ }
1479
+
1480
+ // eslint-disable-next-line functional/prefer-readonly-type
1481
+ function encode(format, ...args) {
1482
+ // eslint-disable-next-line functional/no-let
1483
+ let i = 0;
1484
+ return format.replace(/%s/g, () => encodeURIComponent(args[i++]));
1485
+ }
1486
+
1487
+ function serializeUrl(host, path, queryParameters) {
1488
+ const queryParametersAsString = serializeQueryParameters(queryParameters);
1489
+ // eslint-disable-next-line functional/no-let
1490
+ let url = `${host.protocol}://${host.url}/${path.charAt(0) === '/' ? path.substr(1) : path}`;
1491
+ if (queryParametersAsString.length) {
1492
+ url += `?${queryParametersAsString}`;
1493
+ }
1494
+ return url;
1495
+ }
1496
+ function serializeQueryParameters(parameters) {
1497
+ const isObjectOrArray = (value) => Object.prototype.toString.call(value) === '[object Object]' ||
1498
+ Object.prototype.toString.call(value) === '[object Array]';
1499
+ return Object.keys(parameters)
1500
+ .map(key => encode('%s=%s', key, isObjectOrArray(parameters[key]) ? JSON.stringify(parameters[key]) : parameters[key]))
1501
+ .join('&');
1502
+ }
1503
+ function serializeData(request, requestOptions) {
1504
+ if (request.method === MethodEnum.Get ||
1505
+ (request.data === undefined && requestOptions.data === undefined)) {
1506
+ return undefined;
1507
+ }
1508
+ const data = Array.isArray(request.data)
1509
+ ? request.data
1510
+ : { ...request.data, ...requestOptions.data };
1511
+ return JSON.stringify(data);
1512
+ }
1513
+ function serializeHeaders(transporter, requestOptions) {
1514
+ const headers = {
1515
+ ...transporter.headers,
1516
+ ...requestOptions.headers,
1517
+ };
1518
+ const serializedHeaders = {};
1519
+ Object.keys(headers).forEach(header => {
1520
+ const value = headers[header];
1521
+ // @ts-ignore
1522
+ // eslint-disable-next-line functional/immutable-data
1523
+ serializedHeaders[header.toLowerCase()] = value;
1524
+ });
1525
+ return serializedHeaders;
1526
+ }
1527
+
1528
+ function stackTraceWithoutCredentials(stackTrace) {
1529
+ return stackTrace.map(stackFrame => stackFrameWithoutCredentials(stackFrame));
1530
+ }
1531
+ function stackFrameWithoutCredentials(stackFrame) {
1532
+ const modifiedHeaders = stackFrame.request.headers['x-algolia-api-key']
1533
+ ? { 'x-algolia-api-key': '*****' }
1534
+ : {};
1535
+ return {
1536
+ ...stackFrame,
1537
+ request: {
1538
+ ...stackFrame.request,
1539
+ headers: {
1540
+ ...stackFrame.request.headers,
1541
+ ...modifiedHeaders,
1542
+ },
1543
+ },
1544
+ };
1545
+ }
1546
+
1547
+ function createApiError(message, status, transporterStackTrace) {
1548
+ return {
1549
+ name: 'ApiError',
1550
+ message,
1551
+ status,
1552
+ transporterStackTrace,
1553
+ };
1554
+ }
1555
+
1556
+ function createDeserializationError(message, response) {
1557
+ return {
1558
+ name: 'DeserializationError',
1559
+ message,
1560
+ response,
1561
+ };
1562
+ }
1563
+
1564
+ function createRetryError(transporterStackTrace) {
1565
+ return {
1566
+ name: 'RetryError',
1567
+ message: 'Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.',
1568
+ transporterStackTrace,
1569
+ };
1570
+ }
1571
+
1572
+ var transporter_esm = /*#__PURE__*/Object.freeze({
1573
+ __proto__: null,
1574
+ CallEnum: CallEnum,
1575
+ HostStatusEnum: HostStatusEnum,
1576
+ createApiError: createApiError,
1577
+ createDeserializationError: createDeserializationError,
1578
+ createMappedRequestOptions: createMappedRequestOptions,
1579
+ createRetryError: createRetryError,
1580
+ createStatefulHost: createStatefulHost,
1581
+ createStatelessHost: createStatelessHost,
1582
+ createTransporter: createTransporter,
1583
+ createUserAgent: createUserAgent,
1584
+ deserializeFailure: deserializeFailure,
1585
+ deserializeSuccess: deserializeSuccess,
1586
+ isStatefulHostTimeouted: isStatefulHostTimeouted,
1587
+ isStatefulHostUp: isStatefulHostUp,
1588
+ serializeData: serializeData,
1589
+ serializeHeaders: serializeHeaders,
1590
+ serializeQueryParameters: serializeQueryParameters,
1591
+ serializeUrl: serializeUrl,
1592
+ stackFrameWithoutCredentials: stackFrameWithoutCredentials,
1593
+ stackTraceWithoutCredentials: stackTraceWithoutCredentials
1594
+ });
1595
+
1596
+ const createAnalyticsClient = options => {
1597
+ const region = options.region || 'us';
1598
+ const auth = createAuth(AuthMode.WithinHeaders, options.appId, options.apiKey);
1599
+ const transporter = createTransporter({
1600
+ hosts: [{ url: `analytics.${region}.algolia.com` }],
1601
+ ...options,
1602
+ headers: {
1603
+ ...auth.headers(),
1604
+ ...{ 'content-type': 'application/json' },
1605
+ ...options.headers,
1606
+ },
1607
+ queryParameters: {
1608
+ ...auth.queryParameters(),
1609
+ ...options.queryParameters,
1610
+ },
1611
+ });
1612
+ const appId = options.appId;
1613
+ return addMethods({ appId, transporter }, options.methods);
1614
+ };
1615
+
1616
+ const addABTest = (base) => {
1617
+ return (abTest, requestOptions) => {
1618
+ return base.transporter.write({
1619
+ method: MethodEnum.Post,
1620
+ path: '2/abtests',
1621
+ data: abTest,
1622
+ }, requestOptions);
1623
+ };
1624
+ };
1625
+
1626
+ const deleteABTest = (base) => {
1627
+ return (abTestID, requestOptions) => {
1628
+ return base.transporter.write({
1629
+ method: MethodEnum.Delete,
1630
+ path: encode$1('2/abtests/%s', abTestID),
1631
+ }, requestOptions);
1632
+ };
1633
+ };
1634
+
1635
+ const getABTest = (base) => {
1636
+ return (abTestID, requestOptions) => {
1637
+ return base.transporter.read({
1638
+ method: MethodEnum.Get,
1639
+ path: encode$1('2/abtests/%s', abTestID),
1640
+ }, requestOptions);
1641
+ };
1642
+ };
1643
+
1644
+ const getABTests = (base) => {
1645
+ return (requestOptions) => {
1646
+ return base.transporter.read({
1647
+ method: MethodEnum.Get,
1648
+ path: '2/abtests',
1649
+ }, requestOptions);
1650
+ };
1651
+ };
1652
+
1653
+ const stopABTest = (base) => {
1654
+ return (abTestID, requestOptions) => {
1655
+ return base.transporter.write({
1656
+ method: MethodEnum.Post,
1657
+ path: encode$1('2/abtests/%s/stop', abTestID),
1658
+ }, requestOptions);
1659
+ };
1660
+ };
1661
+
1662
+ var clientAnalytics_esm = /*#__PURE__*/Object.freeze({
1663
+ __proto__: null,
1664
+ addABTest: addABTest,
1665
+ createAnalyticsClient: createAnalyticsClient,
1666
+ deleteABTest: deleteABTest,
1667
+ getABTest: getABTest,
1668
+ getABTests: getABTests,
1669
+ stopABTest: stopABTest
1670
+ });
1671
+
1672
+ var require$$2 = /*@__PURE__*/getAugmentedNamespace(clientAnalytics_esm);
1673
+
1674
+ var require$$3 = /*@__PURE__*/getAugmentedNamespace(clientCommon_esm);
1675
+
1676
+ const createPersonalizationClient = options => {
1677
+ const region = options.region || 'us';
1678
+ const auth = createAuth(AuthMode.WithinHeaders, options.appId, options.apiKey);
1679
+ const transporter = createTransporter({
1680
+ hosts: [{ url: `personalization.${region}.algolia.com` }],
1681
+ ...options,
1682
+ headers: {
1683
+ ...auth.headers(),
1684
+ ...{ 'content-type': 'application/json' },
1685
+ ...options.headers,
1686
+ },
1687
+ queryParameters: {
1688
+ ...auth.queryParameters(),
1689
+ ...options.queryParameters,
1690
+ },
1691
+ });
1692
+ return addMethods({ appId: options.appId, transporter }, options.methods);
1693
+ };
1694
+
1695
+ const getPersonalizationStrategy = (base) => {
1696
+ return (requestOptions) => {
1697
+ return base.transporter.read({
1698
+ method: MethodEnum.Get,
1699
+ path: '1/strategies/personalization',
1700
+ }, requestOptions);
1701
+ };
1702
+ };
1703
+
1704
+ const setPersonalizationStrategy = (base) => {
1705
+ return (personalizationStrategy, requestOptions) => {
1706
+ return base.transporter.write({
1707
+ method: MethodEnum.Post,
1708
+ path: '1/strategies/personalization',
1709
+ data: personalizationStrategy,
1710
+ }, requestOptions);
1711
+ };
1712
+ };
1713
+
1714
+ var clientPersonalization_esm = /*#__PURE__*/Object.freeze({
1715
+ __proto__: null,
1716
+ createPersonalizationClient: createPersonalizationClient,
1717
+ getPersonalizationStrategy: getPersonalizationStrategy,
1718
+ setPersonalizationStrategy: setPersonalizationStrategy
1719
+ });
1720
+
1721
+ var require$$4 = /*@__PURE__*/getAugmentedNamespace(clientPersonalization_esm);
1722
+
1723
+ function createNullLogger() {
1724
+ return {
1725
+ debug(_message, _args) {
1726
+ return Promise.resolve();
1727
+ },
1728
+ info(_message, _args) {
1729
+ return Promise.resolve();
1730
+ },
1731
+ error(_message, _args) {
1732
+ return Promise.resolve();
1733
+ },
1734
+ };
1735
+ }
1736
+
1737
+ const LogLevelEnum = {
1738
+ Debug: 1,
1739
+ Info: 2,
1740
+ Error: 3,
1741
+ };
1742
+
1743
+ var loggerCommon_esm = /*#__PURE__*/Object.freeze({
1744
+ __proto__: null,
1745
+ LogLevelEnum: LogLevelEnum,
1746
+ createNullLogger: createNullLogger
1747
+ });
1748
+
1749
+ var require$$6$1 = /*@__PURE__*/getAugmentedNamespace(loggerCommon_esm);
1750
+
1751
+ var recommend$3 = {exports: {}};
1752
+
1753
+ /* eslint functional/prefer-readonly-type: 0 */
1754
+ const agentOptions = { keepAlive: true };
1755
+ const defaultHttpAgent = new Agent(agentOptions);
1756
+ const defaultHttpsAgent = new Agent$1(agentOptions);
1757
+ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAgent, httpsAgent: userHttpsAgent, requesterOptions = {}, } = {}) {
1758
+ const httpAgent = userHttpAgent || userGlobalAgent || defaultHttpAgent;
1759
+ const httpsAgent = userHttpsAgent || userGlobalAgent || defaultHttpsAgent;
1760
+ return {
1761
+ send(request) {
1762
+ return new Promise(resolve => {
1763
+ const url = parse(request.url);
1764
+ const path = url.query === null ? url.pathname : `${url.pathname}?${url.query}`;
1765
+ const options = {
1766
+ ...requesterOptions,
1767
+ agent: url.protocol === 'https:' ? httpsAgent : httpAgent,
1768
+ hostname: url.hostname,
1769
+ path,
1770
+ method: request.method,
1771
+ headers: {
1772
+ ...(requesterOptions && requesterOptions.headers ? requesterOptions.headers : {}),
1773
+ ...request.headers,
1774
+ },
1775
+ ...(url.port !== undefined ? { port: url.port || '' } : {}),
1776
+ };
1777
+ const req = (url.protocol === 'https:' ? https : http).request(options, response => {
1778
+ // eslint-disable-next-line functional/no-let
1779
+ let contentBuffers = [];
1780
+ response.on('data', chunk => {
1781
+ contentBuffers = contentBuffers.concat(chunk);
1782
+ });
1783
+ response.on('end', () => {
1784
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
1785
+ clearTimeout(connectTimeout);
1786
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
1787
+ clearTimeout(responseTimeout);
1788
+ resolve({
1789
+ status: response.statusCode || 0,
1790
+ content: Buffer.concat(contentBuffers).toString(),
1791
+ isTimedOut: false,
1792
+ });
1793
+ });
1794
+ });
1795
+ const createTimeout = (timeout, content) => {
1796
+ return setTimeout(() => {
1797
+ req.abort();
1798
+ resolve({
1799
+ status: 0,
1800
+ content,
1801
+ isTimedOut: true,
1802
+ });
1803
+ }, timeout * 1000);
1804
+ };
1805
+ const connectTimeout = createTimeout(request.connectTimeout, 'Connection timeout');
1806
+ // eslint-disable-next-line functional/no-let
1807
+ let responseTimeout;
1808
+ req.on('error', error => {
1809
+ clearTimeout(connectTimeout);
1810
+ clearTimeout(responseTimeout);
1811
+ resolve({ status: 0, content: error.message, isTimedOut: false });
1812
+ });
1813
+ req.once('response', () => {
1814
+ clearTimeout(connectTimeout);
1815
+ responseTimeout = createTimeout(request.responseTimeout, 'Socket timeout');
1816
+ });
1817
+ if (request.data !== undefined) {
1818
+ req.write(request.data);
1819
+ }
1820
+ req.end();
1821
+ });
1822
+ },
1823
+ destroy() {
1824
+ httpAgent.destroy();
1825
+ httpsAgent.destroy();
1826
+ return Promise.resolve();
1827
+ },
1828
+ };
1829
+ }
1830
+
1831
+ var requesterNodeHttp_esm = /*#__PURE__*/Object.freeze({
1832
+ __proto__: null,
1833
+ createNodeHttpRequester: createNodeHttpRequester
1834
+ });
1835
+
1836
+ var require$$8 = /*@__PURE__*/getAugmentedNamespace(requesterNodeHttp_esm);
1837
+
1838
+ var require$$9 = /*@__PURE__*/getAugmentedNamespace(transporter_esm);
1839
+
1840
+ var require$$6 = /*@__PURE__*/getAugmentedNamespace(requesterCommon_esm);
1841
+
1842
+ var cacheCommon$1 = require$$0;
1843
+ var cacheInMemory$1 = require$$1;
1844
+ var clientCommon$1 = require$$3;
1845
+ var loggerCommon$1 = require$$6$1;
1846
+ var requesterNodeHttp$1 = require$$8;
1847
+ var transporter$1 = require$$9;
1848
+ var requesterCommon = require$$6;
1849
+
1850
+ const createRecommendClient = options => {
1851
+ const appId = options.appId;
1852
+ const auth = clientCommon$1.createAuth(options.authMode !== undefined ? options.authMode : clientCommon$1.AuthMode.WithinHeaders, appId, options.apiKey);
1853
+ const transporter$1$1 = transporter$1.createTransporter({
1854
+ hosts: [
1855
+ { url: `${appId}-dsn.algolia.net`, accept: transporter$1.CallEnum.Read },
1856
+ { url: `${appId}.algolia.net`, accept: transporter$1.CallEnum.Write },
1857
+ ].concat(clientCommon$1.shuffle([
1858
+ { url: `${appId}-1.algolianet.com` },
1859
+ { url: `${appId}-2.algolianet.com` },
1860
+ { url: `${appId}-3.algolianet.com` },
1861
+ ])),
1862
+ ...options,
1863
+ headers: {
1864
+ ...auth.headers(),
1865
+ ...{ 'content-type': 'application/x-www-form-urlencoded' },
1866
+ ...options.headers,
1867
+ },
1868
+ queryParameters: {
1869
+ ...auth.queryParameters(),
1870
+ ...options.queryParameters,
1871
+ },
1872
+ });
1873
+ const base = {
1874
+ transporter: transporter$1$1,
1875
+ appId,
1876
+ addAlgoliaAgent(segment, version) {
1877
+ transporter$1$1.userAgent.add({ segment, version });
1878
+ },
1879
+ clearCache() {
1880
+ return Promise.all([
1881
+ transporter$1$1.requestsCache.clear(),
1882
+ transporter$1$1.responsesCache.clear(),
1883
+ ]).then(() => undefined);
1884
+ },
1885
+ };
1886
+ return clientCommon$1.addMethods(base, options.methods);
1887
+ };
1888
+
1889
+ const getRecommendations = base => {
1890
+ return (queries, requestOptions) => {
1891
+ const requests = queries.map(query => ({
1892
+ ...query,
1893
+ // The `threshold` param is required by the endpoint to make it easier
1894
+ // to provide a default value later, so we default it in the client
1895
+ // so that users don't have to provide a value.
1896
+ threshold: query.threshold || 0,
1897
+ }));
1898
+ return base.transporter.read({
1899
+ method: requesterCommon.MethodEnum.Post,
1900
+ path: '1/indexes/*/recommendations',
1901
+ data: {
1902
+ requests,
1903
+ },
1904
+ cacheable: true,
1905
+ }, requestOptions);
1906
+ };
1907
+ };
1908
+
1909
+ const getFrequentlyBoughtTogether = base => {
1910
+ return (queries, requestOptions) => {
1911
+ return getRecommendations(base)(queries.map(query => ({
1912
+ ...query,
1913
+ fallbackParameters: {},
1914
+ model: 'bought-together',
1915
+ })), requestOptions);
1916
+ };
1917
+ };
1918
+
1919
+ const getRelatedProducts = base => {
1920
+ return (queries, requestOptions) => {
1921
+ return getRecommendations(base)(queries.map(query => ({
1922
+ ...query,
1923
+ model: 'related-products',
1924
+ })), requestOptions);
1925
+ };
1926
+ };
1927
+
1928
+ const getTrendingFacets = base => {
1929
+ return (queries, requestOptions) => {
1930
+ const requests = queries.map(query => ({
1931
+ ...query,
1932
+ model: 'trending-facets',
1933
+ // The `threshold` param is required by the endpoint to make it easier
1934
+ // to provide a default value later, so we default it in the client
1935
+ // so that users don't have to provide a value.
1936
+ threshold: query.threshold || 0,
1937
+ }));
1938
+ return base.transporter.read({
1939
+ method: requesterCommon.MethodEnum.Post,
1940
+ path: '1/indexes/*/recommendations',
1941
+ data: {
1942
+ requests,
1943
+ },
1944
+ cacheable: true,
1945
+ }, requestOptions);
1946
+ };
1947
+ };
1948
+
1949
+ const getTrendingItems = base => {
1950
+ return (queries, requestOptions) => {
1951
+ const requests = queries.map(query => ({
1952
+ ...query,
1953
+ model: 'trending-items',
1954
+ // The `threshold` param is required by the endpoint to make it easier
1955
+ // to provide a default value later, so we default it in the client
1956
+ // so that users don't have to provide a value.
1957
+ threshold: query.threshold || 0,
1958
+ }));
1959
+ return base.transporter.read({
1960
+ method: requesterCommon.MethodEnum.Post,
1961
+ path: '1/indexes/*/recommendations',
1962
+ data: {
1963
+ requests,
1964
+ },
1965
+ cacheable: true,
1966
+ }, requestOptions);
1967
+ };
1968
+ };
1969
+
1970
+ const getLookingSimilar = base => {
1971
+ return (queries, requestOptions) => {
1972
+ return getRecommendations(base)(queries.map(query => ({
1973
+ ...query,
1974
+ model: 'looking-similar',
1975
+ })), requestOptions);
1976
+ };
1977
+ };
1978
+
1979
+ const getRecommendedForYou = base => {
1980
+ return (queries, requestOptions) => {
1981
+ const requests = queries.map(query => ({
1982
+ ...query,
1983
+ model: 'recommended-for-you',
1984
+ threshold: query.threshold || 0,
1985
+ }));
1986
+ return base.transporter.read({
1987
+ method: requesterCommon.MethodEnum.Post,
1988
+ path: '1/indexes/*/recommendations',
1989
+ data: {
1990
+ requests,
1991
+ },
1992
+ cacheable: true,
1993
+ }, requestOptions);
1994
+ };
1995
+ };
1996
+
1997
+ function recommend$2(appId, apiKey, options) {
1998
+ const commonOptions = {
1999
+ appId,
2000
+ apiKey,
2001
+ timeouts: {
2002
+ connect: 2,
2003
+ read: 5,
2004
+ write: 30,
2005
+ },
2006
+ requester: requesterNodeHttp$1.createNodeHttpRequester(),
2007
+ logger: loggerCommon$1.createNullLogger(),
2008
+ responsesCache: cacheCommon$1.createNullCache(),
2009
+ requestsCache: cacheCommon$1.createNullCache(),
2010
+ hostsCache: cacheInMemory$1.createInMemoryCache(),
2011
+ userAgent: transporter$1.createUserAgent(clientCommon$1.version)
2012
+ .add({ segment: 'Recommend', version: clientCommon$1.version })
2013
+ .add({ segment: 'Node.js', version: process.versions.node }),
2014
+ };
2015
+ return createRecommendClient({
2016
+ ...commonOptions,
2017
+ ...options,
2018
+ methods: {
2019
+ destroy: clientCommon$1.destroy,
2020
+ getFrequentlyBoughtTogether,
2021
+ getRecommendations,
2022
+ getRelatedProducts,
2023
+ getTrendingFacets,
2024
+ getTrendingItems,
2025
+ getLookingSimilar,
2026
+ getRecommendedForYou,
2027
+ },
2028
+ });
2029
+ }
2030
+ /* eslint-disable functional/immutable-data */
2031
+ recommend$2.version = clientCommon$1.version;
2032
+ recommend$2.getFrequentlyBoughtTogether = getFrequentlyBoughtTogether;
2033
+ recommend$2.getRecommendations = getRecommendations;
2034
+ recommend$2.getRelatedProducts = getRelatedProducts;
2035
+ recommend$2.getTrendingFacets = getTrendingFacets;
2036
+ recommend$2.getTrendingItems = getTrendingItems;
2037
+ recommend$2.getLookingSimilar = getLookingSimilar;
2038
+ recommend$2.getRecommendedForYou = getRecommendedForYou;
2039
+
2040
+ var recommend_cjs = recommend$2;
2041
+
2042
+ /* eslint-disable functional/immutable-data, import/no-commonjs */
2043
+
2044
+ const recommend$1 = recommend_cjs;
2045
+
2046
+ /**
2047
+ * The Common JS build is the default entry point for the Node environment. Keep in
2048
+ * in mind, that for the browser environment, we hint the bundler to use the UMD
2049
+ * build instead as specified on the key `browser` of our `package.json` file.
2050
+ */
2051
+ recommend$3.exports = recommend$1;
2052
+
2053
+ /**
2054
+ * In addition, we also set explicitly the default export below making
2055
+ * this Common JS module in compliance with es6 modules specification.
2056
+ */
2057
+ recommend$3.exports.default = recommend$1;
2058
+
2059
+ var recommendExports = recommend$3.exports;
2060
+
2061
+ var cacheCommon = require$$0;
2062
+ var cacheInMemory = require$$1;
2063
+ var clientAnalytics = require$$2;
2064
+ var clientCommon = require$$3;
2065
+ var clientPersonalization = require$$4;
2066
+ var clientSearch = require$$5;
2067
+ var loggerCommon = require$$6$1;
2068
+ var recommend = recommendExports;
2069
+ var requesterNodeHttp = require$$8;
2070
+ var transporter = require$$9;
2071
+
2072
+ function algoliasearch$2(appId, apiKey, options) {
2073
+ const commonOptions = {
2074
+ appId,
2075
+ apiKey,
2076
+ timeouts: {
2077
+ connect: 2,
2078
+ read: 5,
2079
+ write: 30,
2080
+ },
2081
+ requester: requesterNodeHttp.createNodeHttpRequester(),
2082
+ logger: loggerCommon.createNullLogger(),
2083
+ responsesCache: cacheCommon.createNullCache(),
2084
+ requestsCache: cacheCommon.createNullCache(),
2085
+ hostsCache: cacheInMemory.createInMemoryCache(),
2086
+ userAgent: transporter.createUserAgent(clientCommon.version).add({
2087
+ segment: 'Node.js',
2088
+ version: process.versions.node,
2089
+ }),
2090
+ };
2091
+ const searchClientOptions = { ...commonOptions, ...options };
2092
+ const initPersonalization = () => (clientOptions) => {
2093
+ return clientPersonalization.createPersonalizationClient({
2094
+ ...commonOptions,
2095
+ ...clientOptions,
2096
+ methods: {
2097
+ getPersonalizationStrategy: clientPersonalization.getPersonalizationStrategy,
2098
+ setPersonalizationStrategy: clientPersonalization.setPersonalizationStrategy,
2099
+ },
2100
+ });
2101
+ };
2102
+ return clientSearch.createSearchClient({
2103
+ ...searchClientOptions,
2104
+ methods: {
2105
+ search: clientSearch.multipleQueries,
2106
+ searchForFacetValues: clientSearch.multipleSearchForFacetValues,
2107
+ multipleBatch: clientSearch.multipleBatch,
2108
+ multipleGetObjects: clientSearch.multipleGetObjects,
2109
+ multipleQueries: clientSearch.multipleQueries,
2110
+ copyIndex: clientSearch.copyIndex,
2111
+ copySettings: clientSearch.copySettings,
2112
+ copyRules: clientSearch.copyRules,
2113
+ copySynonyms: clientSearch.copySynonyms,
2114
+ moveIndex: clientSearch.moveIndex,
2115
+ listIndices: clientSearch.listIndices,
2116
+ getLogs: clientSearch.getLogs,
2117
+ listClusters: clientSearch.listClusters,
2118
+ multipleSearchForFacetValues: clientSearch.multipleSearchForFacetValues,
2119
+ getApiKey: clientSearch.getApiKey,
2120
+ addApiKey: clientSearch.addApiKey,
2121
+ listApiKeys: clientSearch.listApiKeys,
2122
+ updateApiKey: clientSearch.updateApiKey,
2123
+ deleteApiKey: clientSearch.deleteApiKey,
2124
+ restoreApiKey: clientSearch.restoreApiKey,
2125
+ assignUserID: clientSearch.assignUserID,
2126
+ assignUserIDs: clientSearch.assignUserIDs,
2127
+ getUserID: clientSearch.getUserID,
2128
+ searchUserIDs: clientSearch.searchUserIDs,
2129
+ listUserIDs: clientSearch.listUserIDs,
2130
+ getTopUserIDs: clientSearch.getTopUserIDs,
2131
+ removeUserID: clientSearch.removeUserID,
2132
+ hasPendingMappings: clientSearch.hasPendingMappings,
2133
+ generateSecuredApiKey: clientSearch.generateSecuredApiKey,
2134
+ getSecuredApiKeyRemainingValidity: clientSearch.getSecuredApiKeyRemainingValidity,
2135
+ destroy: clientCommon.destroy,
2136
+ clearDictionaryEntries: clientSearch.clearDictionaryEntries,
2137
+ deleteDictionaryEntries: clientSearch.deleteDictionaryEntries,
2138
+ getDictionarySettings: clientSearch.getDictionarySettings,
2139
+ getAppTask: clientSearch.getAppTask,
2140
+ replaceDictionaryEntries: clientSearch.replaceDictionaryEntries,
2141
+ saveDictionaryEntries: clientSearch.saveDictionaryEntries,
2142
+ searchDictionaryEntries: clientSearch.searchDictionaryEntries,
2143
+ setDictionarySettings: clientSearch.setDictionarySettings,
2144
+ waitAppTask: clientSearch.waitAppTask,
2145
+ customRequest: clientSearch.customRequest,
2146
+ initIndex: base => (indexName) => {
2147
+ return clientSearch.initIndex(base)(indexName, {
2148
+ methods: {
2149
+ batch: clientSearch.batch,
2150
+ delete: clientSearch.deleteIndex,
2151
+ findAnswers: clientSearch.findAnswers,
2152
+ getObject: clientSearch.getObject,
2153
+ getObjects: clientSearch.getObjects,
2154
+ saveObject: clientSearch.saveObject,
2155
+ saveObjects: clientSearch.saveObjects,
2156
+ search: clientSearch.search,
2157
+ searchForFacetValues: clientSearch.searchForFacetValues,
2158
+ waitTask: clientSearch.waitTask,
2159
+ setSettings: clientSearch.setSettings,
2160
+ getSettings: clientSearch.getSettings,
2161
+ partialUpdateObject: clientSearch.partialUpdateObject,
2162
+ partialUpdateObjects: clientSearch.partialUpdateObjects,
2163
+ deleteObject: clientSearch.deleteObject,
2164
+ deleteObjects: clientSearch.deleteObjects,
2165
+ deleteBy: clientSearch.deleteBy,
2166
+ clearObjects: clientSearch.clearObjects,
2167
+ browseObjects: clientSearch.browseObjects,
2168
+ getObjectPosition: clientSearch.getObjectPosition,
2169
+ findObject: clientSearch.findObject,
2170
+ exists: clientSearch.exists,
2171
+ saveSynonym: clientSearch.saveSynonym,
2172
+ saveSynonyms: clientSearch.saveSynonyms,
2173
+ getSynonym: clientSearch.getSynonym,
2174
+ searchSynonyms: clientSearch.searchSynonyms,
2175
+ browseSynonyms: clientSearch.browseSynonyms,
2176
+ deleteSynonym: clientSearch.deleteSynonym,
2177
+ clearSynonyms: clientSearch.clearSynonyms,
2178
+ replaceAllObjects: clientSearch.replaceAllObjects,
2179
+ replaceAllSynonyms: clientSearch.replaceAllSynonyms,
2180
+ searchRules: clientSearch.searchRules,
2181
+ getRule: clientSearch.getRule,
2182
+ deleteRule: clientSearch.deleteRule,
2183
+ saveRule: clientSearch.saveRule,
2184
+ saveRules: clientSearch.saveRules,
2185
+ replaceAllRules: clientSearch.replaceAllRules,
2186
+ browseRules: clientSearch.browseRules,
2187
+ clearRules: clientSearch.clearRules,
2188
+ },
2189
+ });
2190
+ },
2191
+ initAnalytics: () => (clientOptions) => {
2192
+ return clientAnalytics.createAnalyticsClient({
2193
+ ...commonOptions,
2194
+ ...clientOptions,
2195
+ methods: {
2196
+ addABTest: clientAnalytics.addABTest,
2197
+ getABTest: clientAnalytics.getABTest,
2198
+ getABTests: clientAnalytics.getABTests,
2199
+ stopABTest: clientAnalytics.stopABTest,
2200
+ deleteABTest: clientAnalytics.deleteABTest,
2201
+ },
2202
+ });
2203
+ },
2204
+ initPersonalization,
2205
+ initRecommendation: () => (clientOptions) => {
2206
+ searchClientOptions.logger.info('The `initRecommendation` method is deprecated. Use `initPersonalization` instead.');
2207
+ return initPersonalization()(clientOptions);
2208
+ },
2209
+ getRecommendations: recommend.getRecommendations,
2210
+ getFrequentlyBoughtTogether: recommend.getFrequentlyBoughtTogether,
2211
+ getLookingSimilar: recommend.getLookingSimilar,
2212
+ getRecommendedForYou: recommend.getRecommendedForYou,
2213
+ getRelatedProducts: recommend.getRelatedProducts,
2214
+ getTrendingFacets: recommend.getTrendingFacets,
2215
+ getTrendingItems: recommend.getTrendingItems,
2216
+ },
2217
+ });
2218
+ }
2219
+ // eslint-disable-next-line functional/immutable-data
2220
+ algoliasearch$2.version = clientCommon.version;
2221
+
2222
+ var algoliasearch_cjs = algoliasearch$2;
2223
+
2224
+ /* eslint-disable functional/immutable-data, import/no-commonjs */
2225
+
2226
+ const algoliasearch$1 = algoliasearch_cjs;
2227
+
2228
+ /**
2229
+ * The Common JS build is the default entry point for the Node environment. Keep in
2230
+ * in mind, that for the browser environment, we hint the bundler to use the UMD
2231
+ * build instead as specified on the key `browser` of our `package.json` file.
2232
+ */
2233
+ algoliasearch$3.exports = algoliasearch$1;
2234
+
2235
+ /**
2236
+ * In addition, we also set explicitly the default export below making
2237
+ * this Common JS module in compliance with es6 modules specification.
2238
+ */
2239
+ algoliasearch$3.exports.default = algoliasearch$1;
2240
+
2241
+ var algoliasearchExports = algoliasearch$3.exports;
2242
+
2243
+ // eslint-disable-next-line functional/immutable-data, import/no-commonjs
2244
+ var lite = algoliasearchExports;
2245
+
2246
+ var algoliasearch = /*@__PURE__*/getDefaultExportFromCjs(lite);
2247
+
2248
+ const onlineSearchClient = algoliasearch('testing9VXJ0U4GSV', 'f3c57c730433f5cf7825b62545eccb05');
2249
+ const searchClient = ({ online }) => ({
2250
+ search(queries, requestOptions) {
2251
+ if (online)
2252
+ return onlineSearchClient
2253
+ .search(queries, requestOptions)
2254
+ .then(result => {
2255
+ // eslint-disable-next-line no-console
2256
+ console.log('search', result);
2257
+ return result;
2258
+ });
2259
+ return fetch('data/algolia.json').then(response => response.json());
2260
+ },
2261
+ async searchForFacetValues(queries, requestOptions) {
2262
+ if (online)
2263
+ return onlineSearchClient
2264
+ .searchForFacetValues(queries, requestOptions)
2265
+ .then(result => {
2266
+ // eslint-disable-next-line no-console
2267
+ console.log('searchForFacetValues', result);
2268
+ return result;
2269
+ });
2270
+ return [];
2271
+ },
2272
+ });
2273
+
2274
+ const AlgoliaContext = createContext({
2275
+ online: false,
2276
+ setOnline: () => { },
2277
+ toggleOnline: () => { },
2278
+ });
2279
+ function AlgoliaProvider({ children, online: _online = false, }) {
2280
+ const [online, setOnline] = useState(_online);
2281
+ return (jsx(AlgoliaContext.Provider, { value: {
2282
+ online,
2283
+ setOnline,
2284
+ toggleOnline: () => setOnline(online => !online),
2285
+ }, children: jsxs(InstantSearch, { future: {
2286
+ persistHierarchicalRootCount: true,
2287
+ preserveSharedStateOnUnmount: true,
2288
+ }, indexName: "dev_sonic_products_en", searchClient: searchClient({ online }), children: [jsx(Configure, { analytics: false, filters: "categoryPageId: Toolbox", hitsPerPage: 9, maxValuesPerFacet: 100 }), children] }) }));
2289
+ }
2290
+ function useAlgolia() {
2291
+ return useContext(AlgoliaContext);
2292
+ }
2293
+
2294
+ export { Accordion, AddToCartButton, AlgoliaCategories, AlgoliaFilterPanel, AlgoliaMultiSelect, AlgoliaPagination, AlgoliaProductList, AlgoliaProvider, AlgoliaResultsCount, AlgoliaSortBy, Button, CartFilledIcon, CartOutlinedIcon, CartProvider, Checkbox, ColorCheckbox, ConnectedAddToCartButton, DehashedOutlinedIcon, FavoriteButton, FavoriteFilledIcon, FavoriteOutlinedIcon, FormattedMessage, GlobalStateProvider, GlobalStateProviderContext, HashedOutlinedIcon, IconButton, Image, IntlProvider, LinkButton, MultiSelect, NumberField, ProductCard, ProductListing, ProductOverviewGrid, ProductPrice, ProductSku, RightArrowFilledIcon, Select, ShowAll, Sidebar, TextField, createProductListingSearchParams, parseProductListingSearchParams, useAlgolia, useBreakpoint, useCart, useDebouncedCallback, useDisclosure, useFormattedMessage, useGlobalState, useProductCartLine, useScrollLock };