@sonic-equipment/ui 0.0.20 → 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.
Files changed (35) hide show
  1. package/dist/algolia/algolia-active-filters.d.ts +6 -0
  2. package/dist/algolia/algolia-categories.d.ts +1 -0
  3. package/dist/algolia/algolia-filter-panel.d.ts +4 -1
  4. package/dist/algolia/algolia-provider.d.ts +13 -0
  5. package/dist/algolia/algolia-sort-by.d.ts +1 -1
  6. package/dist/algolia/algolia.stories.d.ts +2 -2
  7. package/dist/buttons/add-to-cart-button/add-to-cart-button.stories.d.ts +1 -0
  8. package/dist/buttons/add-to-cart-button/connected-add-to-cart-button.d.ts +5 -0
  9. package/dist/buttons/icon-button/icon-button.d.ts +2 -1
  10. package/dist/cards/product-card/connected-product-cart.d.ts +6 -0
  11. package/dist/cards/product-card/product-card.stories.d.ts +1 -0
  12. package/dist/collapsables/accordion/accordion-item.d.ts +2 -1
  13. package/dist/collapsables/accordion/accordion.d.ts +2 -1
  14. package/dist/collapsables/accordion/accordion.stories.d.ts +1 -0
  15. package/dist/filters/active-filters/active-filters.d.ts +9 -8
  16. package/dist/filters/active-filters/active-filters.stories.d.ts +2 -2
  17. package/dist/filters/pagination/pagination.d.ts +6 -0
  18. package/dist/filters/pagination/pagination.stories.d.ts +18 -0
  19. package/dist/icons/arrows/right-arrow-filled-icon.d.ts +0 -1
  20. package/dist/icons/chevrons/chevron-left-filled-icon.d.ts +2 -0
  21. package/dist/icons/chevrons/chevron-right-filled-icon.d.ts +2 -0
  22. package/dist/index.d.ts +182 -34
  23. package/dist/index.js +1917 -102
  24. package/dist/intl/translation-id.d.ts +1 -1
  25. package/dist/product-listing/product-listing.d.ts +1 -25
  26. package/dist/product-listing/product-listing.stories.d.ts +7 -3
  27. package/dist/shared/hooks/{use-device.d.ts → use-breakpoint.d.ts} +1 -1
  28. package/dist/shared/hooks/use-debounce-callback.d.ts +1 -0
  29. package/dist/shared/providers/cart-provider.d.ts +33 -0
  30. package/dist/shared/providers/global-state-provider.d.ts +23 -0
  31. package/dist/shared/types/cart.d.ts +8 -0
  32. package/dist/shared/utils/event-emitter.d.ts +9 -0
  33. package/dist/styles.css +309 -97
  34. package/dist/typography/heading/heading.d.ts +1 -1
  35. package/package.json +25 -24
package/dist/index.js CHANGED
@@ -1,27 +1,245 @@
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 } 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, 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, 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
+ }
5
192
 
6
193
  function RightArrowFilledIcon(props) {
7
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" }) }));
8
195
  }
9
196
 
10
- var styles$n = {"button":"button-module-V4meK","icon":"button-module-XaNWz","sm":"button-module-Pbwz7","md":"button-module-GVTEW","condensed":"button-module-GKHQc","lg":"button-module-nyNY8","primary":"button-module-tmyk8","outline":"button-module-vq9GI","solid":"button-module-AjvlY","hover":"button-module-YzPAr","focus":"button-module--xzsY","active":"button-module-XMFzj","ghost":"button-module-f4UVe","right-arrow-icon":"button-module-ydQAo","secondary":"button-module--1bCH"};
197
+ var styles$r = {"button":"button-module-V4meK","icon":"button-module-XaNWz","sm":"button-module-Pbwz7","md":"button-module-GVTEW","condensed":"button-module-GKHQc","lg":"button-module-nyNY8","primary":"button-module-tmyk8","outline":"button-module-vq9GI","solid":"button-module-AjvlY","hover":"button-module-YzPAr","focus":"button-module--xzsY","active":"button-module-XMFzj","ghost":"button-module-f4UVe","right-arrow-icon":"button-module-ydQAo","secondary":"button-module--1bCH"};
11
198
 
12
199
  function Button({ _pseudo = 'none', children, className, color = 'primary', condensed, icon, iconPosition = 'left', isDisabled, onPress, size = 'lg', type = 'button', variant = 'solid', withArrow = false, }) {
13
200
  if (children && icon)
14
201
  console.warn('Button should not have both children and icon. Icon has precedence.');
15
- return (jsxs(Button$1, { className: clsx(className, styles$n.button, styles$n[variant], styles$n[size], styles$n[color], { [styles$n.condensed]: condensed }, { [styles$n.icon]: icon }, styles$n[_pseudo]), isDisabled: isDisabled, onPress: onPress, type: type, children: [icon && iconPosition === 'left' && (jsx("span", { className: styles$n.icon, children: icon })), children, withArrow && (jsx(RightArrowFilledIcon, { className: styles$n['right-arrow-icon'] })), icon && iconPosition === 'right' && (jsx("span", { className: styles$n.icon, children: icon }))] }));
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 }))] }));
203
+ }
204
+
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 }));
16
234
  }
17
235
 
18
- var styles$m = {"field-error":"field-error-module-FXnIg"};
236
+ var styles$n = {"field-error":"field-error-module-FXnIg"};
19
237
 
20
238
  function FieldError({ children }) {
21
- return (jsx(FieldError$1, { className: styles$m['field-error'], children: children }));
239
+ return (jsx(FieldError$1, { className: styles$n['field-error'], children: children }));
22
240
  }
23
241
 
24
- var styles$l = {"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"};
25
243
 
26
244
  /**
27
245
  * This component is used to create an input that grows as the user types.
@@ -36,33 +254,33 @@ const Input = forwardRef(({ _pseudo = 'none', autoGrow, size = 'lg', ...inputPro
36
254
  const handleChange = (event) => isControlled
37
255
  ? onChange?.(event)
38
256
  : setUncontrolledValue(event.target.value);
39
- return (jsx("div", { className: clsx(styles$l['input-container'], styles$l[size], styles$l[_pseudo]), children: jsxs("div", { className: clsx({ [styles$l['growing-input']]: autoGrow }), children: [jsx(Input$1, { size: autoGrow ? 1 : undefined, ...props, ref: ref, onChange: handleChange }), autoGrow && jsx("span", { className: styles$l['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 })] }) }));
40
258
  });
41
259
  Input.displayName = 'Input';
42
260
 
43
- var styles$k = {"label":"label-module-LGfJt","required":"label-module-oTWaS"};
261
+ var styles$l = {"label":"label-module-LGfJt","required":"label-module-oTWaS"};
44
262
 
45
263
  function Label({ children, isRequired }) {
46
264
  if (!children)
47
265
  return null;
48
- return (jsxs(Label$1, { className: styles$k.label, children: [children, isRequired && jsx("span", { className: styles$k.required, children: "*" })] }));
266
+ return (jsxs(Label$1, { className: styles$l.label, children: [children, isRequired && jsx("span", { className: styles$l.required, children: "*" })] }));
49
267
  }
50
268
 
51
- var styles$j = {"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"};
52
270
 
53
271
  /**
54
272
  * This component is used to create a number field.
55
273
  * This field can also grow when a user types in text.
56
274
  */
57
- function NumberField({ autoFocus, autoGrow, defaultValue, formatOptions = { style: 'decimal', useGrouping: false }, isDisabled, isInvalid, isReadOnly, isRequired, label, maxLength, maxValue, minValue, name, onChange, onInput, onKeyUp, placeholder, showLabel = true, size = 'lg', value, withButtons, }) {
58
- return (jsxs(NumberField$1, { "aria-label": label, autoFocus: autoFocus, className: clsx(styles$j.field, styles$j[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$j['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, {})] }));
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, }) {
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, {})] }));
59
277
  }
60
278
 
61
279
  function CartFilledIcon(props) {
62
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" }) }));
63
281
  }
64
282
 
65
- var styles$i = {"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"};
66
284
 
67
285
  function AddToCartButton({ initialState = 'initial', onChange, quantity, }) {
68
286
  const [currentState, setState] = useState(initialState);
@@ -124,50 +342,66 @@ function ManualInputState({ onCancel, onConfirm, quantity, }) {
124
342
  e.key === 'Enter' && onConfirm(updatedQuantity);
125
343
  e.key === 'Escape' && onCancel();
126
344
  };
127
- return (jsxs("div", { className: styles$i['manual-input-container'], children: [jsx("div", { className: styles$i['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: {
128
346
  maximumFractionDigits: 0,
129
347
  style: 'decimal',
130
348
  useGrouping: false,
131
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" })] }));
132
350
  }
133
351
 
134
- var styles$h = {"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"};
135
-
136
- function IconButton({ children, className, color = 'primary', onPress, size = 'md', }) {
137
- return (jsx(Button$1, { className: clsx(styles$h['icon-button'], styles$h[size], styles$h[color], className), onPress: onPress, children: children }));
138
- }
139
-
140
- function FavoriteFilledIcon(props) {
141
- 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" }) }));
142
- }
143
-
144
- function FavoriteOutlinedIcon(props) {
145
- 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" }) }));
146
- }
147
-
148
- var styles$g = {"favorite-button":"favorite-button-module-tXSS3","is-favorite":"favorite-button-module-l557q"};
149
-
150
- function FavoriteButton({ isFavorite, onPress }) {
151
- return (jsx(IconButton, { className: clsx(styles$g['favorite-button'], {
152
- [styles$g['is-favorite']]: isFavorite,
153
- }), color: "secondary", onPress: onPress, children: isFavorite ? jsx(FavoriteFilledIcon, {}) : jsx(FavoriteOutlinedIcon, {}) }));
154
- }
155
-
156
- var styles$f = {"link-button":"link-button-module-6i75g"};
157
-
158
- function LinkButton({ children, className, href, isDisabled, onPress, target, }) {
159
- if (href) {
160
- return (jsx(Link, { className: clsx(styles$f['link-button'], className), href: href, isDisabled: isDisabled, onPress: onPress, target: target, children: children }));
161
- }
162
- return (jsx(Button$1, { className: clsx(styles$f['link-button'], className), isDisabled: isDisabled, onPress: onPress, type: "button", children: children }));
163
- }
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
+ };
164
398
 
165
- var styles$e = {"tag":"tag-module-B7r15","body":"tag-module-4cfCf","shape":"tag-module-c7CRb"};
399
+ var styles$i = {"tag":"tag-module-B7r15","body":"tag-module-4cfCf","shape":"tag-module-c7CRb"};
166
400
 
167
401
  function Tag({ children }) {
168
402
  if (!children)
169
403
  return null;
170
- return (jsxs("div", { className: styles$e.tag, children: [jsx("div", { className: styles$e.body, children: children }), jsx("svg", { className: styles$e.shape, height: "16", viewBox: "0 0 8 16", width: "8", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M.925 0H0v16h5.412l2.463-8.429c.362-1.238-.08-2.576-1.094-3.315L.925 0z", fill: "currentColor", fillRule: "nonzero" }) })] }));
404
+ return (jsxs("div", { className: styles$i.tag, children: [jsx("div", { className: styles$i.body, children: children }), jsx("svg", { className: styles$i.shape, height: "16", viewBox: "0 0 8 16", width: "8", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M.925 0H0v16h5.412l2.463-8.429c.362-1.238-.08-2.576-1.094-3.315L.925 0z", fill: "currentColor", fillRule: "nonzero" }) })] }));
171
405
  }
172
406
 
173
407
  const IntlContext = createContext({
@@ -193,7 +427,7 @@ const useFormattedMessage = () => {
193
427
 
194
428
  const FormattedMessage = ({ id, replacementValues, }) => useFormattedMessage()(id, replacementValues);
195
429
 
196
- var styles$d = {"product-price":"product-price-module-oIU1K","original-price":"product-price-module-til0s","current-price-wrapper":"product-price-module-FfVhl","current-price":"product-price-module-pvy2w","wholes":"product-price-module-GCw07","dot":"product-price-module-N56iV","decimals":"product-price-module-eWOOF","vat":"product-price-module-96DoG"};
430
+ var styles$h = {"product-price":"product-price-module-oIU1K","original-price":"product-price-module-til0s","current-price-wrapper":"product-price-module-FfVhl","current-price":"product-price-module-pvy2w","wholes":"product-price-module-GCw07","dot":"product-price-module-N56iV","decimals":"product-price-module-eWOOF","vat":"product-price-module-96DoG"};
197
431
 
198
432
  const formatPrice = (price) => new Intl.NumberFormat('en-US', {
199
433
  maximumFractionDigits: 2,
@@ -205,16 +439,16 @@ function ProductPrice({ className, current, includeVat, original, }) {
205
439
  const originalPriceCurrency = original ? formatPrice(original) : null;
206
440
  const currentPriceCurrency = formatPrice(current);
207
441
  const [wholes, decimals] = currentPriceCurrency.split('.');
208
- return (jsxs("div", { className: clsx(className, styles$d['product-price']), children: [!!original && (jsx("span", { className: styles$d['original-price'], children: originalPriceCurrency })), jsxs("div", { className: styles$d['current-price-wrapper'], children: [jsxs("div", { className: styles$d['current-price'], children: [jsx("span", { className: styles$d.wholes, children: wholes }), jsx("span", { className: styles$d.dot, children: "." }), jsx("span", { className: styles$d.decimals, children: decimals })] }), jsx("span", { className: styles$d.vat, children: includeVat ? (jsx(FormattedMessage, { id: "Incl. VAT" })) : (jsx(FormattedMessage, { id: "Excl. VAT" })) })] })] }));
442
+ return (jsxs("div", { className: clsx(className, styles$h['product-price']), children: [!!original && (jsx("span", { className: styles$h['original-price'], children: originalPriceCurrency })), jsxs("div", { className: styles$h['current-price-wrapper'], children: [jsxs("div", { className: styles$h['current-price'], children: [jsx("span", { className: styles$h.wholes, children: wholes }), jsx("span", { className: styles$h.dot, children: "." }), jsx("span", { className: styles$h.decimals, children: decimals })] }), jsx("span", { className: styles$h.vat, children: includeVat ? (jsx(FormattedMessage, { id: "Incl. VAT" })) : (jsx(FormattedMessage, { id: "Excl. VAT" })) })] })] }));
209
443
  }
210
444
 
211
- var styles$c = {"product-sku":"product-sku-module-ITb8x"};
445
+ var styles$g = {"product-sku":"product-sku-module-ITb8x"};
212
446
 
213
447
  function ProductSku({ sku }) {
214
- return jsx("p", { className: styles$c['product-sku'], children: sku });
448
+ return jsx("p", { className: styles$g['product-sku'], children: sku });
215
449
  }
216
450
 
217
- var styles$b = {"image":"image-module-lg7Kj","contain":"image-module-KFEgG","cover":"image-module-tVKFe"};
451
+ var styles$f = {"image":"image-module-lg7Kj","contain":"image-module-KFEgG","cover":"image-module-tVKFe"};
218
452
 
219
453
  const breakpointToWidth = {
220
454
  lg: 1440,
@@ -239,19 +473,19 @@ function Image({ alt, className, fallbackSrc = '/images/fallback.svg', fit = 'co
239
473
  const handleError = () => {
240
474
  setCurrentSrc(fallbackSrc);
241
475
  };
242
- return (jsx("img", { alt: alt, className: clsx(styles$b.image, styles$b[fit], className), height: height, loading: loading, onError: handleError, sizes: sizes, src: currentSrc, srcSet: srcSet, title: title, width: width }));
476
+ return (jsx("img", { alt: alt, className: clsx(styles$f.image, styles$f[fit], className), height: height, loading: loading, onError: handleError, sizes: sizes, src: currentSrc, srcSet: srcSet, title: title, width: width }));
243
477
  }
244
478
 
245
- var styles$a = {"product-card":"product-card-module-pLaiB","favorite-button":"product-card-module-tvEdz","content":"product-card-module-e0kMu","top":"product-card-module-Q0VvF","tag":"product-card-module-HkWBE","title":"product-card-module-CStNi","bottom":"product-card-module-kD2tU","image":"product-card-module-p-zoi","price":"product-card-module-irW0D","add-to-cart-button":"product-card-module-SnCvX"};
479
+ var styles$e = {"product-card":"product-card-module-pLaiB","favorite-button":"product-card-module-tvEdz","content":"product-card-module-e0kMu","top":"product-card-module-Q0VvF","tag":"product-card-module-HkWBE","title":"product-card-module-CStNi","bottom":"product-card-module-kD2tU","image":"product-card-module-p-zoi","price":"product-card-module-irW0D","add-to-cart-button":"product-card-module-SnCvX"};
246
480
 
247
481
  function ProductCard({ addToCartButton: AddToCartButton, favoriteButton: FavoriteButton, image: { alt, fit, src, title: imageTitle }, onClick, price, sku, tag, title, }) {
248
- return (jsxs("div", { className: styles$a['product-card'], onClick: onClick, children: [jsx("div", { className: styles$a.image, children: jsx(Image, { alt: alt, fit: fit, src: src, title: imageTitle }) }), jsx("div", { className: styles$a['favorite-button'], children: FavoriteButton && FavoriteButton }), jsxs("div", { className: styles$a.content, children: [jsxs("div", { className: styles$a.top, children: [jsx("div", { className: styles$a.tag, children: tag && jsx(Tag, { children: tag }) }), jsx("h2", { className: styles$a.title, children: title }), jsx(ProductSku, { sku: sku })] }), jsxs("div", { className: styles$a.bottom, children: [jsx("div", { className: styles$a.price, children: jsx(ProductPrice, { current: price.current, includeVat: price.includeVat, original: price.original }) }), jsx("div", { className: styles$a['add-to-cart-button'], children: AddToCartButton })] })] })] }));
482
+ return (jsxs("div", { className: styles$e['product-card'], onClick: onClick, children: [jsx("div", { className: styles$e.image, children: jsx(Image, { alt: alt, fit: fit, src: src, title: imageTitle }) }), jsx("div", { className: styles$e['favorite-button'], children: FavoriteButton && FavoriteButton }), jsxs("div", { className: styles$e.content, children: [jsxs("div", { className: styles$e.top, children: [jsx("div", { className: styles$e.tag, children: tag && jsx(Tag, { children: tag }) }), jsx("h2", { className: styles$e.title, children: title }), jsx(ProductSku, { sku: sku })] }), jsxs("div", { className: styles$e.bottom, children: [jsx("div", { className: styles$e.price, children: jsx(ProductPrice, { current: price.current, includeVat: price.includeVat, original: price.original }) }), jsx("div", { className: styles$e['add-to-cart-button'], children: AddToCartButton })] })] })] }));
249
483
  }
250
484
 
251
- var styles$9 = {"accordion":"accordion-module-9WvAH","white":"accordion-module-CaVdG","accordion-item":"accordion-module-lf9d-","lg":"accordion-module-0qnae","with-seperators":"accordion-module-yOLrW","button":"accordion-module--Rwpb","icon":"accordion-module-Y50uq","focus":"accordion-module-M4BZs","panel":"accordion-module-KZjMo","content":"accordion-module-ejMH3","is-open":"accordion-module-W0F1z"};
485
+ var styles$d = {"accordion":"accordion-module-9WvAH","white":"accordion-module-CaVdG","accordion-item":"accordion-module-lf9d-","lg":"accordion-module-0qnae","with-seperators":"accordion-module-yOLrW","indented":"accordion-module-6CcEH","button":"accordion-module--Rwpb","icon":"accordion-module-Y50uq","focus":"accordion-module-M4BZs","panel":"accordion-module-KZjMo","content":"accordion-module-ejMH3","is-open":"accordion-module-W0F1z"};
252
486
 
253
- function Accordion({ children, color = 'black', hasLineSeparator = true, size = 'md', }) {
254
- return (jsx("div", { className: clsx(styles$9.accordion, styles$9[color], styles$9[size], hasLineSeparator && styles$9['with-seperators']), children: children &&
487
+ function Accordion({ children, color = 'black', hasLineSeparator = true, indented, size = 'md', }) {
488
+ return (jsx("div", { className: clsx({ [styles$d.indented]: indented }, styles$d.accordion, styles$d[color], styles$d[size], hasLineSeparator && styles$d['with-seperators']), children: children &&
255
489
  Children.map(children, child => {
256
490
  return cloneElement(child, { size });
257
491
  }) }));
@@ -261,7 +495,7 @@ function ChevronDownSlim(props) {
261
495
  return (jsx("svg", { viewBox: "0 0 16 17", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "m8 12.648-6.667-6.7a3.11 3.11 0 0 1 .466-.75c.202-.245.444-.477.726-.698l5.459 5.546L13.328 4.5c.288.226.543.459.764.699.222.24.413.489.575.75L8 12.648z", fill: "currentColor", fillRule: "evenodd" }) }));
262
496
  }
263
497
 
264
- var styles$8 = {"show-all":"show-all-module-BDp21","panel":"show-all-module-bEdda","content":"show-all-module-RF--F","has-transparency":"show-all-module-30y7l","button":"show-all-module-58e7Q","icon":"show-all-module-fqncI","is-open":"show-all-module-hQeGI"};
498
+ var styles$c = {"show-all":"show-all-module-BDp21","panel":"show-all-module-bEdda","content":"show-all-module-RF--F","has-transparency":"show-all-module-30y7l","button":"show-all-module-58e7Q","icon":"show-all-module-fqncI","is-open":"show-all-module-hQeGI"};
265
499
 
266
500
  const ShowAll = ({ children, hasTransparency = true, initialHeight = 0, isOpen, onToggle, }) => {
267
501
  const showAllRef = useRef(null);
@@ -270,38 +504,38 @@ const ShowAll = ({ children, hasTransparency = true, initialHeight = 0, isOpen,
270
504
  return;
271
505
  showAllRef.current.style.setProperty('--initital-height', `${initialHeight}px`);
272
506
  }, [initialHeight]);
273
- return (jsxs("div", { ref: showAllRef, className: clsx(styles$8['show-all'], {
274
- [styles$8['is-open']]: isOpen,
275
- }), children: [jsx("div", { className: styles$8.panel, children: jsx("div", { className: clsx(styles$8.content, {
276
- [styles$8['has-transparency']]: hasTransparency,
277
- }), children: children }) }), jsxs(LinkButton, { className: styles$8.button, onPress: () => onToggle(!isOpen), children: [jsx(ChevronDownSlim, { className: styles$8.icon }), isOpen ? (jsx(FormattedMessage, { id: "Show less" })) : (jsx(FormattedMessage, { id: "Show all" }))] })] }));
507
+ return (jsxs("div", { ref: showAllRef, className: clsx(styles$c['show-all'], {
508
+ [styles$c['is-open']]: isOpen,
509
+ }), children: [jsx("div", { className: styles$c.panel, children: jsx("div", { className: clsx(styles$c.content, {
510
+ [styles$c['has-transparency']]: hasTransparency,
511
+ }), children: children }) }), jsxs(LinkButton, { className: styles$c.button, onPress: () => onToggle(!isOpen), children: [jsx(ChevronDownSlim, { className: styles$c.icon }), isOpen ? (jsx(FormattedMessage, { id: "Show less" })) : (jsx(FormattedMessage, { id: "Show all" }))] })] }));
278
512
  };
279
513
 
280
- var styles$7 = {"multi-select":"multi-select-module-DC7Ix","filter-items":"multi-select-module-cwVFb","hidden":"multi-select-module-o7yHU","filter-item":"multi-select-module-OW-NK"};
514
+ var styles$b = {"multi-select":"multi-select-module-DC7Ix","filter-items":"multi-select-module-cwVFb","hidden":"multi-select-module-o7yHU","filter-item":"multi-select-module-OW-NK"};
281
515
 
282
516
  function MultiSelect({ amountShown = 3, isOpen = false, onChange, onToggleOpen, options, render, }) {
283
517
  const shownOptions = options.slice(0, amountShown);
284
518
  const hiddenOptions = options.slice(amountShown);
285
- return (jsxs("div", { className: styles$7['multi-select'], children: [jsx("div", { className: styles$7['filter-items'], children: shownOptions.map(option => (jsxs("div", { className: styles$7['filter-item'], children: [render({ onChange: () => onChange(option), option }), jsxs("span", { children: ["(", option.amount, ")"] })] }, option.value))) }), hiddenOptions?.length > 0 && (jsx(ShowAll, { hasTransparency: false, isOpen: isOpen, onToggle: onToggleOpen, children: jsx("div", { className: clsx(styles$7['filter-items'], styles$7['hidden']), children: hiddenOptions.map(option => (jsxs("div", { className: styles$7['filter-item'], children: [render({ onChange: () => onChange(option), option }), jsxs("span", { children: ["(", option.amount, ")"] })] }, option.value))) }) }))] }));
519
+ return (jsxs("div", { className: styles$b['multi-select'], children: [jsx("div", { className: styles$b['filter-items'], children: shownOptions.map(option => (jsxs("div", { className: styles$b['filter-item'], children: [render({ onChange: () => onChange(option), option }), jsxs("span", { children: ["(", option.amount, ")"] })] }, option.value))) }), hiddenOptions?.length > 0 && (jsx(ShowAll, { hasTransparency: false, isOpen: isOpen, onToggle: onToggleOpen, children: jsx("div", { className: clsx(styles$b['filter-items'], styles$b['hidden']), children: hiddenOptions.map(option => (jsxs("div", { className: styles$b['filter-item'], children: [render({ onChange: () => onChange(option), option }), jsxs("span", { children: ["(", option.amount, ")"] })] }, option.value))) }) }))] }));
286
520
  }
287
521
 
288
- var styles$6 = {"checkbox":"checkbox-module-YNVdd","box":"checkbox-module-UKoyf","checkmark":"checkbox-module-pHIwh","focus":"checkbox-module-v23jy","active":"checkbox-module-7UG-b","color-checkbox":"checkbox-module-nEhvW"};
522
+ var styles$a = {"checkbox":"checkbox-module-YNVdd","box":"checkbox-module-UKoyf","checkmark":"checkbox-module-pHIwh","focus":"checkbox-module-v23jy","active":"checkbox-module-7UG-b","color-checkbox":"checkbox-module-nEhvW"};
289
523
 
290
524
  function Checkbox({ _pseudo = 'none', children, className, isDisabled, isSelected, onChange, value, }) {
291
- return (jsxs(Checkbox$1, { className: clsx(className, styles$6.checkbox, styles$6[_pseudo]), isDisabled: isDisabled, isSelected: isSelected, onChange: onChange, value: value, children: [jsx("div", { className: styles$6.box, children: jsx("svg", { "aria-hidden": "true", className: styles$6.checkmark, viewBox: "0 0 18 18", children: jsx("polyline", { points: "1 9 7 14 15 4" }) }) }), children] }));
525
+ return (jsxs(Checkbox$1, { className: clsx(className, styles$a.checkbox, styles$a[_pseudo]), isDisabled: isDisabled, isSelected: isSelected, onChange: onChange, value: value, children: [jsx("div", { className: styles$a.box, children: jsx("svg", { "aria-hidden": "true", className: styles$a.checkmark, viewBox: "0 0 18 18", children: jsx("polyline", { points: "1 9 7 14 15 4" }) }) }), children] }));
292
526
  }
293
527
 
294
528
  function ColorCheckbox({ _pseudo = 'none', children, className, color, isDisabled, isSelected, onChange, value, }) {
295
- return (jsxs(Checkbox$1, { className: clsx(className, styles$6.checkbox, styles$6['color-checkbox'], styles$6[_pseudo]), isDisabled: isDisabled, isSelected: isSelected, onChange: onChange, style: {
529
+ return (jsxs(Checkbox$1, { className: clsx(className, styles$a.checkbox, styles$a['color-checkbox'], styles$a[_pseudo]), isDisabled: isDisabled, isSelected: isSelected, onChange: onChange, style: {
296
530
  '--selected-color': color,
297
- }, value: value, children: [jsx("div", { className: styles$6.box }), children] }));
531
+ }, value: value, children: [jsx("div", { className: styles$a.box }), children] }));
298
532
  }
299
533
 
300
534
  function CheckmarkFilledIcon(props) {
301
535
  return (jsx("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M10.864 17c-.2 0-.378-.045-.534-.135a1.588 1.588 0 0 1-.446-.407L6.278 12.22c-.185-.233-.278-.474-.278-.722 0-.264.087-.488.262-.672a.86.86 0 0 1 .651-.276c.156 0 .299.033.429.101s.258.188.384.361l3.094 3.71 5.42-8.19c.216-.354.483-.531.802-.531.245 0 .466.08.663.243A.785.785 0 0 1 18 6.88c0 .12-.028.243-.084.367a2.53 2.53 0 0 1-.194.356l-5.934 8.844c-.23.369-.538.553-.924.553z", fill: "currentColor", fillRule: "evenodd" }) }));
302
536
  }
303
537
 
304
- var styles$5 = {"select":"select-module-ui-Wc","button":"select-module-aMQIQ","chevron":"select-module-00uRU","focus":"select-module-XMc0P","popover":"select-module-z8cWq","listbox":"select-module-S21ba","item":"select-module-LgEJO","check":"select-module-lQFw3"};
538
+ var styles$9 = {"select":"select-module-ui-Wc","button":"select-module-aMQIQ","chevron":"select-module-00uRU","focus":"select-module-XMc0P","popover":"select-module-z8cWq","listbox":"select-module-S21ba","header":"select-module-4Bm2j","item":"select-module-LgEJO","check":"select-module-lQFw3"};
305
539
 
306
540
  function Select({ disabled = false, label, onChange, options, selectedOption, showLabel = true, }) {
307
541
  const selectRef = useRef(null);
@@ -316,10 +550,10 @@ function Select({ disabled = false, label, onChange, options, selectedOption, sh
316
550
  window.addEventListener('resize', updateWidth);
317
551
  return () => window.removeEventListener('resize', updateWidth);
318
552
  }, []);
319
- return (jsxs(Select$1, { ref: selectRef, "aria-label": label, className: styles$5.select, isDisabled: disabled, onSelectionChange: selected => onChange(selected), selectedKey: String(selectedOption), children: [showLabel && jsx(Label, { children: label }), jsxs(Button$1, { className: styles$5.button, children: [jsx(SelectValue, {}), jsx(ChevronDownSlim, { "aria-hidden": "true", className: styles$5.chevron })] }), jsx(Popover, { className: styles$5.popover, placement: "bottom left", triggerRef: selectRef, children: jsx(ListBox, { className: styles$5.listbox, children: Object.entries(options).map(([key, value]) => (jsxs(ListBoxItem, { "aria-label": value, className: styles$5.item, id: key, textValue: value, children: [selectedOption === key && (jsx("span", { slot: "description", children: jsx(CheckmarkFilledIcon, { className: styles$5.check }) })), jsx("span", { slot: "label", children: value })] }, key))) }) })] }));
553
+ return (jsxs(Select$1, { ref: selectRef, "aria-label": label, className: styles$9.select, isDisabled: disabled, onSelectionChange: selected => onChange(selected), placeholder: label, selectedKey: String(selectedOption), children: [showLabel && jsx(Label, { children: label }), jsxs(Button$1, { className: styles$9.button, children: [jsx(SelectValue, {}), jsx(ChevronDownSlim, { "aria-hidden": "true", className: styles$9.chevron })] }), jsx(Popover, { className: styles$9.popover, placement: "bottom left", triggerRef: selectRef, children: jsx(ListBox, { className: styles$9.listbox, children: jsxs(Section, { children: [jsx(Header, { className: styles$9.header, children: label }), Object.entries(options).map(([key, value]) => (jsxs(ListBoxItem, { "aria-label": value, className: styles$9.item, id: key, textValue: value, children: [selectedOption === key && (jsx("span", { slot: "description", children: jsx(CheckmarkFilledIcon, { className: styles$9.check }) })), jsx("span", { slot: "label", children: value })] }, key)))] }) }) })] }));
320
554
  }
321
555
 
322
- var styles$4 = {"input-container":"textarea-module-C6Xr1","lg":"textarea-module-vksG-","md":"textarea-module-6JrQJ"};
556
+ var styles$8 = {"input-container":"textarea-module-C6Xr1","lg":"textarea-module-vksG-","md":"textarea-module-6JrQJ"};
323
557
 
324
558
  /**
325
559
  * This component is used to create a textarea that can grow as the user types.
@@ -354,7 +588,7 @@ const TextArea = forwardRef(({ autoGrow, size, ...textAreaProps }, _ref) => {
354
588
  }
355
589
  updateHeight();
356
590
  }, [ref, autoGrow, updateHeight, size]);
357
- return (jsx("div", { className: styles$4['input-container'], children: jsx(TextArea$1, { ...textAreaProps, ref: node => {
591
+ return (jsx("div", { className: styles$8['input-container'], children: jsx(TextArea$1, { ...textAreaProps, ref: node => {
358
592
  ref.current =
359
593
  node;
360
594
  textAreaRef.current = node;
@@ -365,15 +599,15 @@ const TextArea = forwardRef(({ autoGrow, size, ...textAreaProps }, _ref) => {
365
599
  });
366
600
  TextArea.displayName = 'TextArea';
367
601
 
368
- var styles$3 = {"field":"text-field-module-JeaK0"};
602
+ var styles$7 = {"field":"text-field-module-JeaK0"};
369
603
 
370
604
  /**
371
605
  * This component is used to create a text field.
372
606
  * It can be used as a single line input or as a textarea.
373
607
  * This field can also grow when a user types in text.
374
608
  */
375
- function TextField({ autoFocus, autoGrow, defaultValue, isDisabled, isInvalid, isMultiline, isReadOnly, isRequired, label, maxLength, onChange, onInput, onKeyUp, placeholder, rows, showLabel = true, size = 'lg', value, }) {
376
- return (jsxs(TextField$1, { "aria-label": label, autoFocus: autoFocus, className: clsx(styles$3.field, styles$3[size]), defaultValue: defaultValue, isDisabled: isDisabled, isInvalid: isInvalid, isReadOnly: isReadOnly, isRequired: isRequired, maxLength: maxLength, onChange: value => {
609
+ function TextField({ autoFocus, autoGrow, defaultValue, isDisabled, isInvalid, isMultiline, isReadOnly, isRequired, label, maxLength, onChange, onInput, onKeyUp, placeholder, rows, showLabel = false, size = 'lg', value, }) {
610
+ return (jsxs(TextField$1, { "aria-label": label, autoFocus: autoFocus, className: clsx(styles$7.field, styles$7[size]), defaultValue: defaultValue, isDisabled: isDisabled, isInvalid: isInvalid, isReadOnly: isReadOnly, isRequired: isRequired, maxLength: maxLength, onChange: value => {
377
611
  onChange?.(value);
378
612
  }, onInput: onInput, onKeyUp: e => onKeyUp?.(e), value: value, children: [showLabel && jsx(Label, { isRequired: isRequired, children: label }), isMultiline ? (jsx(TextArea, { autoGrow: autoGrow, placeholder: placeholder, rows: rows, size: size })) : (jsx(Input, { autoGrow: autoGrow, placeholder: placeholder, size: size })), jsx(FieldError, {})] }));
379
613
  }
@@ -394,16 +628,155 @@ function IntlProvider({ children, formatMessage }) {
394
628
  return (jsx(IntlContext.Provider, { value: { formatMessage }, children: children }));
395
629
  }
396
630
 
397
- var styles$2 = {"product-grid":"product-overview-grid-module-bzys-","grid-item":"product-overview-grid-module-MlUVA"};
631
+ var styles$6 = {"product-grid":"product-overview-grid-module-bzys-","grid-item":"product-overview-grid-module-MlUVA"};
398
632
 
399
633
  function ProductOverviewGrid({ children }) {
400
- return (jsx("div", { className: styles$2['product-grid'], children: Children.map(children, (child, index) => (jsx("div", { className: styles$2['grid-item'], children: child }, index))) }));
634
+ return (jsx("div", { className: styles$6['product-grid'], children: Children.map(children, (child, index) => (jsx("div", { className: styles$6['grid-item'], children: child }, index))) }));
635
+ }
636
+
637
+ function ChevronDownBold(props) {
638
+ return (jsx("svg", { viewBox: "0 0 14 15", width: "14", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M6.986 11.837 1.166 5.98c.206-.376.542-.798 1.008-1.268.205-.206.41-.394.615-.563a2.91 2.91 0 0 1 .476-.338l.168-.112 3.553 3.576 3.581-3.605c.392.226.811.564 1.26 1.014.204.207.39.413.559.62l.251.32c.045.06.083.113.112.158l.084.17-5.847 5.885z", fill: "currentColor", fillRule: "evenodd" }) }));
639
+ }
640
+
641
+ function AccordionItem({ _pseudo = 'none', children, className, id, isDisabled = false, isOpen: isOpenProp = false, size, title, }) {
642
+ const [isOpen, setIsOpen] = useState(isOpenProp);
643
+ const panelId = `panel-${id}`;
644
+ return (jsxs("div", { className: clsx(className, styles$d['accordion-item'], {
645
+ [styles$d['is-open']]: isOpen,
646
+ }), children: [jsx("h3", { children: jsxs("button", { "aria-controls": panelId, "aria-expanded": isOpen, className: clsx(styles$d.button, styles$d[_pseudo]), disabled: isDisabled, id: id, onClick: () => setIsOpen(!isOpen), type: "button", children: [title, jsx("span", { className: styles$d.icon, children: size === 'lg' ? jsx(ChevronDownBold, {}) : jsx(ChevronDownSlim, {}) })] }) }), jsx("div", { "aria-labelledby": id, className: styles$d.panel, id: panelId, role: "region", children: jsx("div", { className: styles$d.content, children: children }) })] }));
401
647
  }
402
648
 
403
649
  function CloseFilledIcon(props) {
404
650
  return (jsx("svg", { viewBox: "0 0 32 33", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "m10.667 11.14 10.666 10.58m0-10.58L10.667 21.72", fill: "none", fillRule: "evenodd", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.867" }) }));
405
651
  }
406
652
 
653
+ var styles$5 = {"heading":"heading-module-pMC65","uppercase":"heading-module-6spgX","italic":"heading-module-XXMDM","xxl":"heading-module-Kn3ZN","xl":"heading-module--hZs-","l":"heading-module-WrJRY","m":"heading-module-hTexc","s":"heading-module-7W29m","xs":"heading-module-SgaLB","xxs":"heading-module-33en7"};
654
+
655
+ const sizeToTag = {
656
+ l: 'h3',
657
+ m: 'h4',
658
+ s: 'h5',
659
+ xl: 'h2',
660
+ xs: 'h6',
661
+ xxl: 'h1',
662
+ xxs: 'h7',
663
+ };
664
+ function Heading({ children, className, italic, size = 'xxl', tag, uppercase, }) {
665
+ return createElement(tag || sizeToTag[size], {
666
+ className: clsx(className, styles$5.heading, styles$5[size], {
667
+ [styles$5.uppercase]: uppercase,
668
+ [styles$5.italic]: italic,
669
+ }),
670
+ }, children);
671
+ }
672
+
673
+ var styles$4 = {"active-filters":"active-filters-module-1qLjB","header":"active-filters-module-UKKDu","title":"active-filters-module-h29rI","active-filter-item":"active-filters-module-Rrmhy","category":"active-filters-module-u9TTE","active-filter-value":"active-filters-module-CIuPU"};
674
+
675
+ const ActiveFilters = ({ onClearAllFilters, onClearFilter, selectedFilterCategories, }) => {
676
+ if (selectedFilterCategories.length === 0)
677
+ return null;
678
+ return (jsxs("div", { className: styles$4['active-filters'], children: [jsxs("div", { className: styles$4.header, children: [jsx(Heading, { className: styles$4.title, size: "m", children: jsx(FormattedMessage, { id: "Chosen filters" }) }), jsx(LinkButton, { onPress: onClearAllFilters, children: jsx(FormattedMessage, { id: "Clear filters" }) })] }), selectedFilterCategories.map((category, index) => (jsx("section", { className: styles$4.category, children: category.filters.map(filter => (jsxs("div", { className: styles$4['active-filter-item'], children: [jsxs("span", { children: [jsxs("span", { children: [category.label, ": "] }), jsx("span", { className: styles$4['active-filter-value'], children: filter.label })] }), jsx(IconButton, { color: "secondary", onPress: () => onClearFilter(category.label, filter), children: jsx(CloseFilledIcon, {}) })] }, `${category.label}-${filter.value}`))) }, `${category.label}-${index}`)))] }));
679
+ };
680
+
681
+ function AlgoliaActiveFilters() {
682
+ const { items, refine } = useCurrentRefinements();
683
+ const { refine: clearAllFilters } = useClearRefinements();
684
+ const selectedFilterCategories = items
685
+ .sort((a, b) => (a.label.localeCompare(b.label) ? 1 : -1))
686
+ .map((category) => ({
687
+ filters: category.refinements.sort((a, b) =>
688
+ // TODO: Investigate how to sort numerical
689
+ a.value.toString().localeCompare(b.value.toString()) ? 1 : -1),
690
+ label: category.label,
691
+ }));
692
+ function onClearFilter(categoryLabel, filter) {
693
+ selectedFilterCategories
694
+ .filter(category => category.label === categoryLabel)
695
+ .flatMap(category => category.filters)
696
+ .filter(f => f.value === filter.value)
697
+ .forEach(refine);
698
+ }
699
+ return (jsx(ActiveFilters, { onClearAllFilters: clearAllFilters, onClearFilter: onClearFilter, selectedFilterCategories: selectedFilterCategories }));
700
+ }
701
+
702
+ var styles$3 = {"filter-panel":"filter-panel-module-8oxI1","scroll-container":"filter-panel-module-w0hhZ","categories-section":"filter-panel-module-AHlq3","category":"filter-panel-module-TMp3J","count":"filter-panel-module-ykW1a","categories":"filter-panel-module-xvhRz","categories-header":"filter-panel-module-hJVR0","button":"filter-panel-module-hMmIb"};
703
+
704
+ function AlgoliaCategories() {
705
+ const categories = [{ count: 123, href: '#', id: '123', name: 'Hand tools' }];
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))) })] })) }));
707
+ }
708
+
709
+ function AlgoliaMultiSelect({ attribute }) {
710
+ const { items, refine } = useRefinementList({
711
+ attribute,
712
+ limit: 100,
713
+ operator: 'or',
714
+ showMoreLimit: 100,
715
+ });
716
+ const { isOpen, toggle } = useDisclosure();
717
+ const options = items.map(item => ({
718
+ amount: item.count,
719
+ isSelected: item.isRefined,
720
+ label: item.label,
721
+ value: item.value,
722
+ }));
723
+ return (jsx(MultiSelect, { amountShown: 3, isOpen: isOpen, onChange: option => refine(option.value), onToggleOpen: toggle, options: options, render: ({ onChange, option }) => (jsx(Checkbox, { isSelected: option.isSelected, onChange: () => onChange(option.value), value: option.value, children: option.label })) }));
724
+ }
725
+
726
+ function AlgoliaResultsCount() {
727
+ const { results } = useHits();
728
+ const t = useFormattedMessage();
729
+ if (!results)
730
+ return null;
731
+ const count = results.nbHits;
732
+ return `${count} ${count === 1 ? t('article') : t('articles')}`;
733
+ }
734
+
735
+ function AlgoliaFilterPanel({ onShowProducts, }) {
736
+ const { attributesToRender } = useDynamicWidgets();
737
+ const t = useFormattedMessage();
738
+ return (jsx("div", { className: styles$3['filter-panel'], children: jsxs("div", { className: styles$3['scroll-container'], children: [jsx(AlgoliaCategories, {}), jsx(AlgoliaActiveFilters, {}), attributesToRender.length > 0 && (jsx("section", { children: attributesToRender.map((attribute, index) => (jsx(Accordion, { children: jsx(AccordionItem, { id: `attribute-${index}`, title: t(attribute), children: jsx(AlgoliaMultiSelect, { attribute: attribute }) }) }, `attribute-${index}`))) })), jsx("div", { className: styles$3.button, children: jsxs(Button, { withArrow: true, onPress: onShowProducts, size: "md", children: [jsx(FormattedMessage, { id: "Show" }), " ", jsx(AlgoliaResultsCount, {})] }) })] }) }));
739
+ }
740
+
741
+ function ChevronLeftFilledIcon(props) {
742
+ return (jsx("svg", { height: "13", viewBox: "0 0 13 13", width: "13", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "m3.889 6 5.025-5c.19.082.378.198.562.35.184.15.359.332.524.544L5.84 5.988 10 9.996c-.17.216-.344.407-.524.573-.18.166-.367.31-.562.431L3.889 6z", fill: "currentColor", fillRule: "evenodd" }) }));
743
+ }
744
+
745
+ function ChevronRightFilledIcon(props) {
746
+ return (jsx("svg", { height: "13", viewBox: "0 0 13 13", width: "13", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "m9.111 6-5.025 5a2.332 2.332 0 0 1-.562-.35A3.459 3.459 0 0 1 3 10.107l4.16-4.094L3 2.004c.17-.216.344-.407.524-.573.18-.166.367-.31.562-.431l5.025 5z", fill: "currentColor", fillRule: "evenodd" }) }));
747
+ }
748
+
749
+ var styles$2 = {"pagination":"pagination-module-k4OgY","page-number-container":"pagination-module-oq89A"};
750
+
751
+ function Pagination({ currentPage, onChange, totalPages }) {
752
+ return (jsxs("div", { className: styles$2.pagination, children: [jsx(IconButton, { isDisabled: currentPage === 1, onPress: () => onChange(currentPage - 1), children: jsx(ChevronLeftFilledIcon, {}) }), jsxs("div", { className: styles$2['page-number-container'], children: [jsx(NumberField, { autoGrow: true, label: "current-page", maxValue: totalPages, minValue: 1, onChange: onChange, value: currentPage }), jsx(FormattedMessage, { id: "of" }), jsx("div", { children: totalPages })] }), jsx(IconButton, { isDisabled: currentPage >= totalPages, onPress: () => onChange(currentPage + 1), children: jsx(ChevronRightFilledIcon, {}) })] }));
753
+ }
754
+
755
+ function AlgoliaPagination() {
756
+ const { currentRefinement, nbPages, refine } = usePagination();
757
+ return (jsx(Pagination, { currentPage: currentRefinement + 1, onChange: pageNumber => refine(pageNumber - 1), totalPages: nbPages }));
758
+ }
759
+
760
+ function AlgoliaSortBy() {
761
+ const { options: algoliaOptions, refine } = useSortBy({
762
+ items: [
763
+ { label: 'Name', value: 'dev_sonic_products_en' },
764
+ { label: 'Height', value: 'dev_sonic_products_en_height' },
765
+ ],
766
+ });
767
+ if (algoliaOptions.length === 0)
768
+ return null;
769
+ const options = algoliaOptions.reduce((acc, option) => {
770
+ acc[option.value] = option.label;
771
+ return acc;
772
+ }, {});
773
+ return (jsx(Select, { label: "Sort", onChange: value => refine(String(value)), options: options, selectedOption: "dev_sonic_products_en", showLabel: false }));
774
+ }
775
+
776
+ function ConnectedProductCart({ productId, ...props }) {
777
+ return (jsx(ProductCard, { ...props, addToCartButton: jsx(ConnectedAddToCartButton, { productId: productId }) }));
778
+ }
779
+
407
780
  const SidebarContext = createContext({
408
781
  isOpen: false,
409
782
  toggle: () => { },
@@ -421,7 +794,7 @@ var styles$1 = {"sidebar":"sidebar-module-fSa9Q","close":"sidebar-module-2puGC",
421
794
 
422
795
  function Sidebar({ children }) {
423
796
  const { isOpen, toggle } = useSidebar();
424
- return (jsxs("aside", { className: clsx(styles$1.sidebar, { [styles$1['is-open']]: isOpen }), children: [jsx("div", { className: styles$1.close, children: jsx(IconButton, { color: "secondary", onPress: toggle, children: jsx(CloseFilledIcon, {}) }) }), jsx("div", { children: children })] }));
797
+ return (jsxs("aside", { className: clsx(styles$1.sidebar, { [styles$1['is-open']]: isOpen }), children: [jsx("div", { className: styles$1.close, children: jsx(IconButton, { color: "secondary", onPress: toggle, children: jsx(CloseFilledIcon, {}) }) }), children] }));
425
798
  }
426
799
 
427
800
  function FilterOutlinedIcon(props) {
@@ -433,28 +806,38 @@ const ToggleSidebarButton = () => {
433
806
  return (jsx(Button, { color: "secondary", icon: jsx(FilterOutlinedIcon, {}), onPress: toggle, size: "sm", variant: "outline", children: jsx(FormattedMessage, { id: "Show filters" }) }));
434
807
  };
435
808
 
436
- function Filter({ children, title }) {
437
- return (jsxs("div", { children: [jsx("div", { children: jsx("h3", { children: title }) }), jsx("div", { children: children })] }));
438
- }
439
-
440
- function ColorFilter({ onChange, options, value }) {
441
- return (jsx(Filter, { title: "Color", children: jsx("ul", { children: options.map(option => (jsx("li", { children: jsx(Checkbox, { isSelected: value.includes(option.value), onChange: isSelected => onChange(isSelected
442
- ? [...value, option.value]
443
- : value.filter(v => v !== option.value)), value: option.value, children: option.label }) }, option.value))) }) }));
444
- }
445
-
446
- var styles = {"product-listing":"product-listing-module-EmEFw","action-bar":"product-listing-module-rFNcR","count":"product-listing-module-1seez","product-grid-container":"product-listing-module-hZuKD"};
809
+ var styles = {"product-listing":"product-listing-module-EmEFw","header":"product-listing-module-JEjsa","action-bar":"product-listing-module-rFNcR","count":"product-listing-module-1seez","product-grid-container":"product-listing-module-hZuKD","product-grid":"product-listing-module-RRbLO","pagination":"product-listing-module-kkOfB"};
447
810
 
448
- const sortOptions = {
449
- new: 'New',
450
- popular: 'Popular',
451
- price_asc: 'Price: Low - High',
452
- price_desc: 'Price: High - Low',
453
- recommended: 'Recommended',
454
- };
455
- function ProductListing({ activeFilters, filters, isLoading = false, onFilterChange, onSortChange, productCard: ProductCard, products, }) {
456
- const t = useFormattedMessage();
457
- return (jsxs("div", { className: styles['product-listing'], children: [jsx("h1", { children: "Product listing" }), jsxs("section", { className: styles['action-bar'], children: [jsx(ToggleSidebarButton, {}), jsx("span", { className: styles.count, children: "124 articles" }), jsx(Select, { label: t('Sort'), onChange: key => onSortChange(key), options: sortOptions, selectedOption: "new", showLabel: false })] }), jsx("section", { children: isLoading ? (jsx("p", { children: "Loading..." })) : (jsxs("div", { className: styles['product-grid-container'], children: [jsx(Sidebar, { children: jsxs("div", { children: [jsx("h2", { children: "Filter" }), jsx(ColorFilter, { onChange: colors => onFilterChange({ colors }), options: filters.color.options, value: activeFilters.colors })] }) }), jsx(ProductOverviewGrid, { children: products.map(product => (jsx(ProductCard, {}, product.id))) })] })) })] }));
811
+ function ProductListing({ isLoading = false }) {
812
+ const { toggle } = useSidebar();
813
+ const { hits: productHits } = useHits();
814
+ return (jsxs("div", { className: styles['product-listing'], children: [jsx("div", { className: styles.header, children: jsx(Heading, { italic: true, uppercase: true, size: "xl", tag: "h1", children: "Pliers" }) }), jsxs("section", { className: styles['action-bar'], children: [jsx(ToggleSidebarButton, {}), jsx("span", { className: styles.count, children: jsx(AlgoliaResultsCount, {}) }), jsx(AlgoliaSortBy, {})] }), jsx("section", { children: isLoading ? (jsx("p", { children: "Loading..." })) : (jsxs("div", { className: styles['product-grid-container'], children: [jsx(Sidebar, { children: jsx(AlgoliaFilterPanel, { onShowProducts: toggle }) }), jsx("div", { className: styles['product-grid'], children: jsx(ProductOverviewGrid, { children: productHits.map(productHit => (jsx(ConnectedProductCart, { image: {
815
+ alt: productHit.name,
816
+ fit: 'contain',
817
+ sizes: { lg: 288, md: 204, sm: 122 },
818
+ src: productHit.images?.find(image => image.quality === 'large')?.url || '',
819
+ srcSet: [
820
+ {
821
+ url: productHit.images?.find(image => image.quality === 'small')?.url || '',
822
+ width: 122,
823
+ },
824
+ {
825
+ url: productHit.images?.find(image => image.quality === 'medium')?.url || '',
826
+ width: 204,
827
+ },
828
+ {
829
+ url: productHit.images?.find(image => image.quality === 'large')?.url || '',
830
+ width: 288,
831
+ },
832
+ ],
833
+ title: productHit.name,
834
+ },
835
+ // eslint-disable-next-line no-console
836
+ onClick: () => console.log('clicked'), price: {
837
+ current: productHit.discountedPrice,
838
+ includeVat: false,
839
+ original: productHit.price,
840
+ }, productId: productHit.id, sku: productHit.ean, tag: "new", title: productHit.name }, productHit.id))) }) }), jsx("div", { className: styles.pagination, children: jsx(AlgoliaPagination, {}) })] })) })] }));
458
841
  }
459
842
 
460
843
  function createProductListingSearchParams(state) {
@@ -476,4 +859,1436 @@ function parseProductListingSearchParams(params) {
476
859
  };
477
860
  }
478
861
 
479
- 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 };