@sonic-equipment/ui 0.0.13 → 0.0.15

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 (41) hide show
  1. package/dist/base.css +4 -5
  2. package/dist/buttons/add-to-cart-button/add-to-cart-button.d.ts +8 -0
  3. package/dist/buttons/add-to-cart-button/add-to-cart-button.stories.d.ts +17 -0
  4. package/dist/buttons/button/button.d.ts +4 -2
  5. package/dist/buttons/button/button.stories.d.ts +4 -1
  6. package/dist/buttons/favorite/favorite-button.stories.d.ts +1 -1
  7. package/dist/buttons/icon-button/icon-button.stories.d.ts +1 -1
  8. package/dist/cards/product-card/product-card.d.ts +12 -7
  9. package/dist/cards/product-card/product-card.stories.d.ts +27 -1
  10. package/dist/display/product-price/product-price.d.ts +4 -8
  11. package/dist/display/product-price/product-price.stories.d.ts +1 -2
  12. package/dist/fonts.css +32 -32
  13. package/dist/{inputs → forms}/checkbox/checkbox.stories.d.ts +1 -1
  14. package/dist/forms/field-error/field-error.d.ts +5 -0
  15. package/dist/forms/field-error/field-error.stories.d.ts +15 -0
  16. package/dist/forms/input/input.d.ts +13 -0
  17. package/dist/forms/input/input.stories.d.ts +27 -0
  18. package/dist/forms/label/label.d.ts +6 -0
  19. package/dist/forms/label/label.stories.d.ts +15 -0
  20. package/dist/forms/number-field/number-field.d.ts +31 -0
  21. package/dist/forms/number-field/number-field.stories.d.ts +32 -0
  22. package/dist/forms/text-field/text-field.d.ts +28 -0
  23. package/dist/forms/text-field/text-field.stories.d.ts +24 -0
  24. package/dist/forms/textarea/textarea.d.ts +13 -0
  25. package/dist/forms/textarea/textarea.stories.d.ts +19 -0
  26. package/dist/icons/dehashed/dehashed-outlined-icon.d.ts +2 -0
  27. package/dist/icons/hashed/hashed-outlined-icon.d.ts +2 -0
  28. package/dist/index.d.ts +149 -29
  29. package/dist/index.js +251 -31
  30. package/dist/lists/product-overview-grid/product-overview-grid.d.ts +5 -0
  31. package/dist/lists/product-overview-grid/product-overview-grid.stories.d.ts +14 -0
  32. package/dist/media/image/image.d.ts +21 -0
  33. package/dist/media/image/image.stories.d.ts +16 -0
  34. package/dist/product-listing/product-listing.d.ts +1 -4
  35. package/dist/product-listing/product-listing.stories.d.ts +2 -2
  36. package/dist/shared/types/price.d.ts +5 -0
  37. package/dist/styles.css +549 -70
  38. package/dist/typography/heading/heading.stories.d.ts +2 -2
  39. package/package.json +50 -34
  40. package/dist/icons/arrows/left-arrow-filled-icon.d.ts +0 -2
  41. /package/dist/{inputs → forms}/checkbox/checkbox.d.ts +0 -0
@@ -0,0 +1,19 @@
1
+ /// <reference types="react" />
2
+ import type { StoryObj } from '@storybook/react';
3
+ import { TextArea } from './textarea';
4
+ declare const meta: {
5
+ component: import("react").FC<import("./textarea").TextAreaProps>;
6
+ parameters: {
7
+ layout: string;
8
+ };
9
+ tags: string[];
10
+ title: string;
11
+ };
12
+ export default meta;
13
+ type Story = StoryObj<typeof TextArea>;
14
+ export declare const Default: Story;
15
+ export declare const Placeholder: Story;
16
+ export declare const MultlineAutoGrow: Story;
17
+ export declare const MultlineSizeMD: Story;
18
+ export declare const Controlled: Story;
19
+ export declare const Uncontrolled: Story;
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export declare function DehashedOutlinedIcon(props: React.SVGProps<SVGSVGElement>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export declare function HashedOutlinedIcon(props: React.SVGProps<SVGSVGElement>): import("react/jsx-runtime").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -1,20 +1,30 @@
1
1
  /// <reference types="react" />
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { ComponentType, ReactNode } from 'react';
3
+ import { ReactElement, ReactNode, FormEventHandler, KeyboardEvent, ComponentType } from 'react';
4
+
5
+ type AddToCartState = 'initial' | 'spinner' | 'manual-input';
6
+ interface AddToCartButtonProps {
7
+ initialState?: AddToCartState;
8
+ onChange?: (quantity: number) => void;
9
+ quantity: number;
10
+ }
11
+ declare function AddToCartButton({ initialState, onChange, quantity, }: AddToCartButtonProps): react_jsx_runtime.JSX.Element;
4
12
 
5
13
  interface ButtonProps {
6
14
  _pseudo?: 'none' | 'focus' | 'hover' | 'active';
7
- children: string;
15
+ children?: string;
8
16
  className?: string;
9
17
  color?: 'primary' | 'secondary';
18
+ condensed?: boolean;
10
19
  icon?: React.ReactNode;
11
20
  isDisabled?: boolean;
12
21
  onPress?: VoidFunction;
13
22
  size?: 'md' | 'lg';
23
+ type?: 'button' | 'submit' | 'reset';
14
24
  variant?: 'solid' | 'outline' | 'ghost';
15
25
  withArrow?: boolean;
16
26
  }
17
- declare function Button({ _pseudo, children, className, color, icon, isDisabled, onPress, size, variant, withArrow, }: ButtonProps): react_jsx_runtime.JSX.Element;
27
+ declare function Button({ _pseudo, children, className, color, condensed, icon, isDisabled, onPress, size, type, variant, withArrow, }: ButtonProps): react_jsx_runtime.JSX.Element;
18
28
 
19
29
  interface FavoriteButtonProps {
20
30
  isFavorite: boolean;
@@ -31,55 +41,167 @@ interface IconButtonProps {
31
41
  }
32
42
  declare function IconButton({ children, className, color, onPress, size, }: IconButtonProps): react_jsx_runtime.JSX.Element;
33
43
 
34
- interface Product {
35
- id: string
44
+ interface Source$1 {
45
+ url: string
46
+ width: number
47
+ }
48
+
49
+ type Breakpoint$1 = 'lg' | 'md' | 'sm'
50
+
51
+ type Sizes$1 = Record<Breakpoint$1, number>
52
+
53
+ interface ImageProps$1 {
54
+ alt: string
55
+ className?: string
56
+ fallbackSrc?: string
57
+ fit?: 'contain' | 'cover'
58
+ height?: number
59
+ loading?: 'lazy' | 'eager'
60
+ sizes?: Sizes$1
61
+ src: string
62
+ srcSet?: Source$1[]
36
63
  title: string
64
+ width?: number
37
65
  }
38
66
 
39
- interface ProductCardProps {
40
- favoriteButton: ComponentType<{
41
- productId: string;
42
- }>;
43
- product: Product;
67
+ interface ProductPrice$1 {
68
+ current: number
69
+ includeVat?: boolean
70
+ original?: number
44
71
  }
45
- declare function ProductCard({ favoriteButton: FavoriteButton, product, }: ProductCardProps): react_jsx_runtime.JSX.Element;
46
72
 
47
- interface Price {
48
- exclVat: number;
49
- inclVat: number;
73
+ interface ProductCardProps {
74
+ addToCartButton: ReactElement;
75
+ favoriteButton?: ReactElement;
76
+ image: ImageProps$1;
77
+ onClick: React.MouseEventHandler<HTMLDivElement>;
78
+ price: ProductPrice$1;
79
+ sku: string;
80
+ tag?: 'new' | 'sale';
81
+ title: string;
50
82
  }
83
+ declare function ProductCard({ addToCartButton: AddToCartButton, favoriteButton: FavoriteButton, image: { alt, fit, src, title: imageTitle }, onClick, price, sku, tag, title, }: ProductCardProps): react_jsx_runtime.JSX.Element;
84
+
51
85
  interface ProductPriceProps {
52
- current: Price;
86
+ className?: string;
87
+ current: number;
53
88
  includeVat?: boolean;
54
- original?: Price;
89
+ original?: number;
55
90
  }
56
- declare function ProductPrice({ current, includeVat, original, }: ProductPriceProps): react_jsx_runtime.JSX.Element | undefined;
91
+ declare function ProductPrice({ className, current, includeVat, original, }: ProductPriceProps): react_jsx_runtime.JSX.Element | undefined;
57
92
 
58
93
  interface ProductSkuProps {
59
94
  sku: string;
60
95
  }
61
96
  declare function ProductSku({ sku }: ProductSkuProps): react_jsx_runtime.JSX.Element;
62
97
 
98
+ interface CheckboxProps {
99
+ _pseudo?: 'none' | 'focus' | 'hover' | 'active';
100
+ children: ReactNode;
101
+ className?: string;
102
+ isDisabled?: boolean;
103
+ isSelected?: boolean;
104
+ onChange?: (isSelected: boolean) => void;
105
+ value?: string;
106
+ }
107
+ declare function Checkbox({ _pseudo, children, className, isDisabled, isSelected, onChange, value, }: CheckboxProps): react_jsx_runtime.JSX.Element;
108
+
109
+ type NumberFieldSize = 'md' | 'lg';
110
+ interface NumberFieldProps {
111
+ autoFocus?: boolean;
112
+ autoGrow?: boolean;
113
+ defaultValue?: number;
114
+ formatOptions?: Intl.NumberFormatOptions;
115
+ isDisabled?: boolean;
116
+ isInvalid?: boolean;
117
+ isReadOnly?: boolean;
118
+ isRequired?: boolean;
119
+ label: string;
120
+ maxLength?: number;
121
+ maxValue?: number;
122
+ minValue?: number;
123
+ name?: string;
124
+ onChange?: (value: number) => void;
125
+ onInput?: FormEventHandler<HTMLInputElement>;
126
+ onKeyUp?: (e: KeyboardEvent) => void;
127
+ placeholder?: string;
128
+ showLabel?: boolean;
129
+ size?: NumberFieldSize;
130
+ value?: number;
131
+ withButtons?: boolean;
132
+ }
133
+ /**
134
+ * This component is used to create a number field.
135
+ * This field can also grow when a user types in text.
136
+ */
137
+ declare function NumberField({ autoFocus, autoGrow, defaultValue, formatOptions, isDisabled, isInvalid, isReadOnly, isRequired, label, maxLength, maxValue, minValue, name, onChange, onInput, onKeyUp, placeholder, showLabel, size, value, withButtons, }: NumberFieldProps): react_jsx_runtime.JSX.Element;
138
+
139
+ interface TextFieldProps {
140
+ autoFocus?: boolean;
141
+ autoGrow?: boolean;
142
+ defaultValue?: string;
143
+ isDisabled?: boolean;
144
+ isInvalid?: boolean;
145
+ isMultiline?: boolean;
146
+ isReadOnly?: boolean;
147
+ isRequired?: boolean;
148
+ label: string;
149
+ maxLength?: number;
150
+ onChange?: (value: string) => void;
151
+ onInput?: FormEventHandler<HTMLInputElement>;
152
+ onKeyUp?: (e: KeyboardEvent) => void;
153
+ placeholder?: string;
154
+ rows?: number;
155
+ showLabel?: boolean;
156
+ size?: 'md' | 'lg';
157
+ value?: string;
158
+ }
159
+ /**
160
+ * This component is used to create a text field.
161
+ * It can be used as a single line input or as a textarea.
162
+ * This field can also grow when a user types in text.
163
+ */
164
+ declare function TextField({ autoFocus, autoGrow, defaultValue, isDisabled, isInvalid, isMultiline, isReadOnly, isRequired, label, maxLength, onChange, onInput, onKeyUp, placeholder, rows, showLabel, size, value, }: TextFieldProps): react_jsx_runtime.JSX.Element;
165
+
63
166
  declare function RightArrowFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
64
167
 
65
168
  declare function CartFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
66
169
 
67
170
  declare function CartOutlinedIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
68
171
 
172
+ declare function DehashedOutlinedIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
173
+
69
174
  declare function FavoriteFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
70
175
 
71
176
  declare function FavoriteOutlinedIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
72
177
 
73
- interface CheckboxProps {
74
- _pseudo?: 'none' | 'focus' | 'hover' | 'active';
75
- children: ReactNode;
178
+ declare function HashedOutlinedIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
179
+
180
+ interface ProductOverviewGridProps {
181
+ children?: ReactNode;
182
+ }
183
+ declare function ProductOverviewGrid({ children }: ProductOverviewGridProps): react_jsx_runtime.JSX.Element;
184
+
185
+ interface Source {
186
+ url: string;
187
+ width: number;
188
+ }
189
+ type Breakpoint = 'lg' | 'md' | 'sm';
190
+ type Sizes = Record<Breakpoint, number>;
191
+ interface ImageProps {
192
+ alt: string;
76
193
  className?: string;
77
- isDisabled?: boolean;
78
- isSelected?: boolean;
79
- onChange?: (isSelected: boolean) => void;
80
- value?: string;
194
+ fallbackSrc?: string;
195
+ fit?: 'contain' | 'cover';
196
+ height?: number;
197
+ loading?: 'lazy' | 'eager';
198
+ sizes?: Sizes;
199
+ src: string;
200
+ srcSet?: Source[];
201
+ title: string;
202
+ width?: number;
81
203
  }
82
- declare function Checkbox({ _pseudo, children, className, isDisabled, isSelected, onChange, value, }: CheckboxProps): react_jsx_runtime.JSX.Element;
204
+ declare function Image({ alt, className, fallbackSrc, fit, height, loading, sizes: sizesProp, src, srcSet: srcSetProp, title, width, }: ImageProps): react_jsx_runtime.JSX.Element;
83
205
 
84
206
  interface Filters {
85
207
  color: {
@@ -103,9 +225,7 @@ type ProductListingProps = {
103
225
  isLoading?: boolean;
104
226
  onFilterChange: (filters: ActiveFilters) => void;
105
227
  onSortChange: (sort: Sort) => void;
106
- productCard: ComponentType<{
107
- product: Product;
108
- }>;
228
+ productCard: ComponentType<any>;
109
229
  products: {
110
230
  id: string;
111
231
  title: string;
@@ -137,4 +257,4 @@ declare function parseProductListingSearchParams(params: URLSearchParams): {
137
257
  };
138
258
  };
139
259
 
140
- export { type ActiveFilters, Button, type ButtonProps, CartFilledIcon, CartOutlinedIcon, Checkbox, type CheckboxProps, FavoriteButton, type FavoriteButtonProps, FavoriteFilledIcon, FavoriteOutlinedIcon, type Filters, IconButton, type IconButtonProps, ProductCard, type ProductCardProps, ProductListing, type ProductListingProps, ProductPrice, type ProductPriceProps, ProductSku, type ProductSkuProps, RightArrowFilledIcon, type Sort, createProductListingSearchParams, parseProductListingSearchParams };
260
+ export { type ActiveFilters, AddToCartButton, Button, type ButtonProps, CartFilledIcon, CartOutlinedIcon, Checkbox, type CheckboxProps, DehashedOutlinedIcon, FavoriteButton, type FavoriteButtonProps, FavoriteFilledIcon, FavoriteOutlinedIcon, type Filters, HashedOutlinedIcon, IconButton, type IconButtonProps, Image, type ImageProps, NumberField, type NumberFieldSize, ProductCard, type ProductCardProps, ProductListing, type ProductListingProps, ProductOverviewGrid, type ProductOverviewGridProps, ProductPrice, type ProductPriceProps, ProductSku, type ProductSkuProps, RightArrowFilledIcon, type Sort, TextField, createProductListingSearchParams, parseProductListingSearchParams };
package/dist/index.js CHANGED
@@ -1,23 +1,140 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Button as Button$1, Checkbox as Checkbox$1 } from 'react-aria-components';
2
+ import { forwardRef, useState, useEffect, useRef, useCallback, Children } 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, Checkbox as Checkbox$1, TextAreaContext, TextArea as TextArea$1, TextField as TextField$1 } from 'react-aria-components';
3
4
  import clsx from 'clsx';
4
5
 
5
6
  function RightArrowFilledIcon(props) {
6
- return (jsx("svg", { height: "13", viewBox: "0 0 12 13", width: "12", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "M3.24 11.4a.239.239 0 0 1-.203-.365l3.105-4.97c.256-.41.219-.932-.093-1.3L3.54 1.792a.239.239 0 0 1 .183-.393h1.956c.07 0 .137.031.182.085l1.866 2.21c.778.92.871 2.226.232 3.249l-2.715 4.344a.239.239 0 0 1-.202.112H3.239z", fill: "currentColor", fillRule: "evenodd" }) }));
7
+ 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" }) }));
7
8
  }
8
9
 
9
- var styles$5 = {"button":"button-module-V4meK","md":"button-module-GVTEW","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"};
10
+ var styles$g = {"button":"button-module-V4meK","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"};
10
11
 
11
- function Button({ _pseudo = 'none', children, className, color = 'primary', icon, isDisabled, onPress, size = 'md', variant = 'solid', withArrow = false, }) {
12
+ function Button({ _pseudo = 'none', children, className, color = 'primary', condensed, icon, isDisabled, onPress, size = 'lg', type = 'button', variant = 'solid', withArrow = false, }) {
12
13
  if (children && icon)
13
14
  console.warn('Button should not have both children and icon. Icon has precedence.');
14
- return (jsx(Button$1, { className: clsx(className, styles$5.button, styles$5[variant], styles$5[size], styles$5[color], { [styles$5.icon]: icon }, styles$5[_pseudo]), isDisabled: isDisabled, onPress: onPress, children: icon ? (icon) : (jsxs(Fragment, { children: [children, withArrow && (jsx(RightArrowFilledIcon, { className: styles$5['right-arrow-icon'] }))] })) }));
15
+ return (jsx(Button$1, { className: clsx(className, styles$g.button, styles$g[variant], styles$g[size], styles$g[color], { [styles$g.condensed]: condensed }, { [styles$g.icon]: icon }, styles$g[_pseudo]), isDisabled: isDisabled, onPress: onPress, type: type, children: icon ? (icon) : (jsxs(Fragment, { children: [children, withArrow && (jsx(RightArrowFilledIcon, { className: styles$g['right-arrow-icon'] }))] })) }));
15
16
  }
16
17
 
17
- var styles$4 = {"iconButton":"icon-button-module-HJm0i","md":"icon-button-module-k3s9J","lg":"icon-button-module-agk6Y","primary":"icon-button-module-fTeP4","secondary":"icon-button-module-dM0eo"};
18
+ var styles$f = {"field-error":"field-error-module-FXnIg"};
19
+
20
+ function FieldError({ children }) {
21
+ return (jsx(FieldError$1, { className: styles$f['field-error'], children: children }));
22
+ }
23
+
24
+ var styles$e = {"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
+
26
+ /**
27
+ * This component is used to create an input that grows as the user types.
28
+ * It uses a shadow input to calculate the width of the input.
29
+ */
30
+ const Input = forwardRef(({ _pseudo = 'none', autoGrow, size = 'lg', ...inputProps }, inputRef) => {
31
+ const [props, ref] = useContextProps(inputProps, inputRef, InputContext);
32
+ const { defaultValue, onChange, value: controlledValue } = props;
33
+ const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
34
+ const isControlled = controlledValue !== undefined;
35
+ const value = isControlled ? controlledValue : uncontrolledValue;
36
+ const handleChange = (event) => isControlled
37
+ ? onChange?.(event)
38
+ : setUncontrolledValue(event.target.value);
39
+ return (jsx("div", { className: clsx(styles$e['input-container'], styles$e[size], styles$e[_pseudo]), children: jsxs("div", { className: clsx({ [styles$e['growing-input']]: autoGrow }), children: [jsx(Input$1, { size: autoGrow ? 1 : undefined, ...props, ref: ref, onChange: handleChange }), autoGrow && jsx("span", { className: styles$e['shadow-input'], children: value })] }) }));
40
+ });
41
+ Input.displayName = 'Input';
42
+
43
+ var styles$d = {"label":"label-module-LGfJt","required":"label-module-oTWaS"};
44
+
45
+ function Label({ children, isRequired }) {
46
+ if (!children)
47
+ return null;
48
+ return (jsxs(Label$1, { className: styles$d.label, children: [children, isRequired && jsx("span", { className: styles$d.required, children: "*" })] }));
49
+ }
50
+
51
+ var styles$c = {"field":"number-field-module-gmnog","button-input-container":"number-field-module-8Lvgh"};
52
+
53
+ /**
54
+ * This component is used to create a number field.
55
+ * This field can also grow when a user types in text.
56
+ */
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$c.field, styles$c[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$c['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
+ }
60
+
61
+ function CartFilledIcon(props) {
62
+ 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
+ }
64
+
65
+ var styles$b = {"manual-input-container":"add-to-cart-button-module-AWFvQ","left-button-spacer":"add-to-cart-button-module-SS7WM"};
66
+
67
+ function AddToCartButton({ initialState = 'initial', onChange, quantity, }) {
68
+ const [currentState, setState] = useState(initialState);
69
+ const [manualInputQuantity, setManualInputQuantity] = useState(quantity);
70
+ useEffect(() => {
71
+ /* Reset the state when the (initial) quantity changes to zero */
72
+ setState(currentState => {
73
+ if (currentState === 'initial' && quantity > 0)
74
+ return 'spinner';
75
+ if (currentState === 'spinner' && quantity === 0)
76
+ return 'initial';
77
+ if (currentState === 'manual-input' && quantity === 0)
78
+ return 'initial';
79
+ return currentState;
80
+ });
81
+ }, [currentState, quantity]);
82
+ if (currentState === 'initial')
83
+ return (jsx(InitialState, { onAddToCart: () => {
84
+ setState('spinner');
85
+ onChange?.(1);
86
+ } }));
87
+ if (currentState === 'spinner')
88
+ return (jsx(SpinnerState, { onChange: value => {
89
+ if (value === 0)
90
+ setState('initial');
91
+ onChange?.(value);
92
+ }, onManualInput: value => {
93
+ setManualInputQuantity(value);
94
+ setState('manual-input');
95
+ }, quantity: quantity }));
96
+ return (jsx(ManualInputState, { onCancel: () => setState('spinner'), onConfirm: value => {
97
+ onChange?.(value);
98
+ setState(value === 0 ? 'initial' : 'spinner');
99
+ }, quantity: manualInputQuantity }));
100
+ }
101
+ function InitialState({ onAddToCart }) {
102
+ return (jsx(Button, { condensed: true, icon: jsx(CartFilledIcon, {}), onPress: onAddToCart, size: "md" }));
103
+ }
104
+ const ensureNumber = (value) => {
105
+ if (typeof value === 'number')
106
+ return value;
107
+ if (typeof value !== 'string')
108
+ return 0;
109
+ const numberValue = parseFloat(value);
110
+ return !isNaN(numberValue) ? numberValue : 0;
111
+ };
112
+ function SpinnerState({ onChange, onManualInput, quantity, }) {
113
+ return (jsx(NumberField, { withButtons: true, autoGrow: true, formatOptions: {
114
+ maximumFractionDigits: 0,
115
+ style: 'decimal',
116
+ useGrouping: false,
117
+ }, label: "Quantity", maxLength: 4, maxValue: 9999, minValue: 0, onChange: onChange, onInput: e => {
118
+ onManualInput(ensureNumber(e.target.value));
119
+ }, showLabel: false, size: "md", value: quantity }));
120
+ }
121
+ function ManualInputState({ onCancel, onConfirm, quantity, }) {
122
+ const [updatedQuantity, setQuantity] = useState(quantity);
123
+ const onKeyUp = (e) => {
124
+ e.key === 'Enter' && onConfirm(updatedQuantity);
125
+ e.key === 'Escape' && onCancel();
126
+ };
127
+ return (jsxs("div", { className: styles$b['manual-input-container'], children: [jsx("div", { className: styles$b['left-button-spacer'] }), jsx(NumberField, { autoFocus: true, autoGrow: true, defaultValue: quantity, formatOptions: {
128
+ maximumFractionDigits: 0,
129
+ style: 'decimal',
130
+ useGrouping: false,
131
+ }, 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
+ }
133
+
134
+ var styles$a = {"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"};
18
135
 
19
136
  function IconButton({ children, className, color = 'primary', onPress, size = 'md', }) {
20
- return (jsx(Button$1, { className: clsx(styles$4.iconButton, styles$4[size], styles$4[color], className), onPress: onPress, children: children }));
137
+ return (jsx(Button$1, { className: clsx(styles$a['icon-button'], styles$a[size], styles$a[color], className), onPress: onPress, children: children }));
21
138
  }
22
139
 
23
140
  function FavoriteFilledIcon(props) {
@@ -28,55 +145,158 @@ function FavoriteOutlinedIcon(props) {
28
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" }) }));
29
146
  }
30
147
 
31
- var styles$3 = {"favorite-button":"favorite-button-module-tXSS3","isFavorite":"favorite-button-module-6FS3Q"};
148
+ var styles$9 = {"favorite-button":"favorite-button-module-tXSS3","is-favorite":"favorite-button-module-l557q"};
32
149
 
33
150
  function FavoriteButton({ isFavorite, onPress }) {
34
- return (jsx(IconButton, { className: clsx(styles$3['favorite-button'], {
35
- [styles$3.isFavorite]: isFavorite,
151
+ return (jsx(IconButton, { className: clsx(styles$9['favorite-button'], {
152
+ [styles$9['is-favorite']]: isFavorite,
36
153
  }), color: "secondary", onPress: onPress, children: isFavorite ? jsx(FavoriteFilledIcon, {}) : jsx(FavoriteOutlinedIcon, {}) }));
37
154
  }
38
155
 
39
- function ProductCard({ favoriteButton: FavoriteButton, product, }) {
40
- return (jsxs("div", { children: [jsx("div", { children: jsx(FavoriteButton, { productId: product.id }) }), jsx("h2", { children: product.title })] }));
156
+ var styles$8 = {"tag":"tag-module-B7r15","body":"tag-module-4cfCf","shape":"tag-module-c7CRb"};
157
+
158
+ function Tag({ children }) {
159
+ if (!children)
160
+ return null;
161
+ return (jsxs("div", { className: styles$8.tag, children: [jsx("div", { className: styles$8.body, children: children }), jsx("svg", { className: styles$8.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" }) })] }));
41
162
  }
42
163
 
43
- var styles$2 = {"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"};
164
+ var styles$7 = {"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"};
44
165
 
45
166
  const formatPrice = (price) => new Intl.NumberFormat('en-US', {
46
167
  maximumFractionDigits: 2,
47
168
  minimumFractionDigits: 2,
48
169
  }).format(price);
49
- function ProductPrice({ current, includeVat = true, original, }) {
50
- if (!current.inclVat && !current.exclVat)
170
+ function ProductPrice({ className, current, includeVat, original, }) {
171
+ if (!current)
51
172
  return;
52
- const originalPrice = includeVat ? original?.inclVat : original?.exclVat;
53
- const currentPrice = includeVat ? current.inclVat : current.exclVat;
54
- const originalPriceCurrency = originalPrice
55
- ? formatPrice(originalPrice)
56
- : null;
57
- const currentPriceCurrency = formatPrice(currentPrice);
173
+ const originalPriceCurrency = original ? formatPrice(original) : null;
174
+ const currentPriceCurrency = formatPrice(current);
58
175
  const [wholes, decimals] = currentPriceCurrency.split('.');
59
- return (jsxs("div", { className: styles$2['product-price'], children: [!!originalPrice && (jsx("span", { className: styles$2['original-price'], children: originalPriceCurrency })), jsxs("div", { className: styles$2['current-price-wrapper'], children: [jsxs("div", { className: styles$2['current-price'], children: [jsx("span", { className: styles$2.wholes, children: wholes }), jsx("span", { className: styles$2.dot, children: "." }), jsx("span", { className: styles$2.decimals, children: decimals })] }), jsx("span", { className: styles$2.vat, children: includeVat ? 'incl. tax' : 'excl. tax' })] })] }));
176
+ return (jsxs("div", { className: clsx(className, styles$7['product-price']), children: [!!original && (jsx("span", { className: styles$7['original-price'], children: originalPriceCurrency })), jsxs("div", { className: styles$7['current-price-wrapper'], children: [jsxs("div", { className: styles$7['current-price'], children: [jsx("span", { className: styles$7.wholes, children: wholes }), jsx("span", { className: styles$7.dot, children: "." }), jsx("span", { className: styles$7.decimals, children: decimals })] }), jsx("span", { className: styles$7.vat, children: includeVat ? 'incl. tax' : 'excl. tax' })] })] }));
60
177
  }
61
178
 
62
- var styles$1 = {"product-sku":"product-sku-module-ITb8x"};
179
+ var styles$6 = {"product-sku":"product-sku-module-ITb8x"};
63
180
 
64
181
  function ProductSku({ sku }) {
65
- return jsx("p", { className: styles$1['product-sku'], children: sku });
182
+ return jsx("p", { className: styles$6['product-sku'], children: sku });
66
183
  }
67
184
 
68
- function CartFilledIcon(props) {
69
- 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" }) }));
185
+ var styles$5 = {"image":"image-module-lg7Kj","contain":"image-module-KFEgG","cover":"image-module-tVKFe"};
186
+
187
+ const breakpointToWidth = {
188
+ lg: 1440,
189
+ md: 1024,
190
+ sm: 414,
191
+ };
192
+ function Image({ alt, className, fallbackSrc = '/images/fallback.svg', fit = 'cover', height, loading = 'eager', sizes: sizesProp, src, srcSet: srcSetProp, title, width, }) {
193
+ const [currentSrc, setCurrentSrc] = useState(src);
194
+ const srcSet = srcSetProp
195
+ ? srcSetProp.map(({ url, width }) => `${url} ${width}w`).join(', ')
196
+ : undefined;
197
+ const sizes = sizesProp
198
+ ? Object.entries(sizesProp)
199
+ .map(([breakpoint, width]) => {
200
+ const widthValue = breakpointToWidth[breakpoint];
201
+ return widthValue
202
+ ? `${breakpoint !== 'sm' ? `(min-width: ${widthValue}px)` : ''} ${width}px`
203
+ : `${width}px`;
204
+ })
205
+ .join(', ')
206
+ : undefined;
207
+ const handleError = () => {
208
+ setCurrentSrc(fallbackSrc);
209
+ };
210
+ return (jsx("img", { alt: alt, className: clsx(styles$5.image, styles$5[fit], className), height: height, loading: loading, onError: handleError, sizes: sizes, src: currentSrc, srcSet: srcSet, title: title, width: width }));
211
+ }
212
+
213
+ var styles$4 = {"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"};
214
+
215
+ function ProductCard({ addToCartButton: AddToCartButton, favoriteButton: FavoriteButton, image: { alt, fit, src, title: imageTitle }, onClick, price, sku, tag, title, }) {
216
+ return (jsxs("div", { className: styles$4['product-card'], onClick: onClick, children: [jsx("div", { className: styles$4.image, children: jsx(Image, { alt: alt, fit: fit, src: src, title: imageTitle }) }), jsx("div", { className: styles$4['favorite-button'], children: FavoriteButton && FavoriteButton }), jsxs("div", { className: styles$4.content, children: [jsxs("div", { className: styles$4.top, children: [jsx("div", { className: styles$4.tag, children: tag && jsx(Tag, { children: tag }) }), jsx("h2", { className: styles$4.title, children: title }), jsx(ProductSku, { sku: sku })] }), jsxs("div", { className: styles$4.bottom, children: [jsx("div", { className: styles$4.price, children: jsx(ProductPrice, { current: price.current, includeVat: price.includeVat, original: price.original }) }), jsx("div", { className: styles$4['add-to-cart-button'], children: AddToCartButton })] })] })] }));
217
+ }
218
+
219
+ var styles$3 = {"checkbox":"checkbox-module-YNVdd","box":"checkbox-module-UKoyf","checkmark":"checkbox-module-pHIwh","focus":"checkbox-module-v23jy","active":"checkbox-module-7UG-b"};
220
+
221
+ function Checkbox({ _pseudo = 'none', children, className, isDisabled, isSelected, onChange, value, }) {
222
+ return (jsxs(Checkbox$1, { className: clsx(className, styles$3.checkbox, styles$3[_pseudo]), isDisabled: isDisabled, isSelected: isSelected, onChange: onChange, value: value, children: [jsx("div", { className: styles$3.box, children: jsx("svg", { "aria-hidden": "true", className: styles$3.checkmark, viewBox: "0 0 18 18", children: jsx("polyline", { points: "1 9 7 14 15 4" }) }) }), children] }));
223
+ }
224
+
225
+ var styles$2 = {"input-container":"textarea-module-C6Xr1","lg":"textarea-module-vksG-","md":"textarea-module-6JrQJ"};
226
+
227
+ /**
228
+ * This component is used to create a textarea that can grow as the user types.
229
+ * It uses the scrollHeight property to calculate the height of the textarea.
230
+ * The initial height is calculated based on the style of the textarea.
231
+ * The height is updated everytime the user types.
232
+ */
233
+ const TextArea = forwardRef(({ autoGrow, size, ...textAreaProps }, _ref) => {
234
+ const textAreaRef = useRef(null);
235
+ const [props, ref] = useContextProps(textAreaProps, textAreaRef, TextAreaContext);
236
+ const initialHeight = useRef(null);
237
+ const updateHeight = useCallback(() => {
238
+ if (!ref.current)
239
+ return;
240
+ if (!autoGrow)
241
+ return ref.current?.style.removeProperty('height');
242
+ ref.current.style.height = `${initialHeight.current}px`;
243
+ if (ref.current.scrollHeight > (initialHeight.current || 0)) {
244
+ ref.current.style.height = ref.current.scrollHeight + 'px';
245
+ }
246
+ }, [autoGrow, ref]);
247
+ useEffect(() => {
248
+ initialHeight.current = null;
249
+ ref.current?.style.removeProperty('height');
250
+ }, [ref, size]);
251
+ useEffect(() => {
252
+ if (!ref.current)
253
+ return;
254
+ if (initialHeight.current === null) {
255
+ const styleHeight = getComputedStyle(ref.current).height.match(/\d+/)?.[0];
256
+ initialHeight.current = styleHeight ? parseFloat(styleHeight) : null;
257
+ }
258
+ updateHeight();
259
+ }, [ref, autoGrow, updateHeight, size]);
260
+ return (jsx("div", { className: styles$2['input-container'], children: jsx(TextArea$1, { ...textAreaProps, ref: node => {
261
+ ref.current =
262
+ node;
263
+ textAreaRef.current = node;
264
+ }, onInput: e => {
265
+ updateHeight();
266
+ props.onInput?.(e);
267
+ } }) }));
268
+ });
269
+ TextArea.displayName = 'TextArea';
270
+
271
+ var styles$1 = {"field":"text-field-module-JeaK0"};
272
+
273
+ /**
274
+ * This component is used to create a text field.
275
+ * It can be used as a single line input or as a textarea.
276
+ * This field can also grow when a user types in text.
277
+ */
278
+ function TextField({ autoFocus, autoGrow, defaultValue, isDisabled, isInvalid, isMultiline, isReadOnly, isRequired, label, maxLength, onChange, onInput, onKeyUp, placeholder, rows, showLabel = true, size = 'lg', value, }) {
279
+ return (jsxs(TextField$1, { "aria-label": label, autoFocus: autoFocus, className: clsx(styles$1.field, styles$1[size]), defaultValue: defaultValue, isDisabled: isDisabled, isInvalid: isInvalid, isReadOnly: isReadOnly, isRequired: isRequired, maxLength: maxLength, onChange: value => {
280
+ onChange?.(value);
281
+ }, 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, {})] }));
70
282
  }
71
283
 
72
284
  function CartOutlinedIcon(props) {
73
285
  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.434zm15.794 4.741H5.623l.361 4.63h13.334l1.065-4.63z", fill: "currentColor", fillRule: "evenodd" }) }));
74
286
  }
75
287
 
76
- var styles = {"checkbox":"checkbox-module-y3eBg","box":"checkbox-module-TqLux","checkmark":"checkbox-module-Yhrdp","focus":"checkbox-module-zoTSP","active":"checkbox-module-sHmzp"};
288
+ function DehashedOutlinedIcon(props) {
289
+ return (jsx("svg", { height: "24", viewBox: "0 0 24 24", width: "24", xmlns: "http://www.w3.org/2000/svg", ...props, children: jsx("path", { d: "m4.934 4.19 15.069 14.705c.259.253.259.663 0 .915a.67.67 0 0 1-.47.19.67.67 0 0 1-.468-.19L3.995 5.105a.636.636 0 0 1 0-.915.675.675 0 0 1 .939 0zm.012 3.604a.637.637 0 0 1-.022.916C3.88 9.682 3.327 10.82 3.327 12c0 3.152 3.88 5.717 8.65 5.717.834 0 1.664-.081 2.469-.242.36-.071.71.155.783.505a.648.648 0 0 1-.517.764c-.892.177-1.812.268-2.735.268C6.476 19.012 2 15.866 2 11.999c0-1.541.695-3.003 2.008-4.226a.675.675 0 0 1 .938.021zm7.077-2.807c5.501 0 9.977 3.146 9.977 7.012 0 1.542-.695 3.003-2.008 4.227a.67.67 0 0 1-.458.179.67.67 0 0 1-.48-.2.636.636 0 0 1 .022-.916c1.045-.973 1.597-2.11 1.597-3.29 0-3.153-3.88-5.717-8.65-5.717-.834 0-1.665.08-2.469.241a.662.662 0 0 1-.783-.504.648.648 0 0 1 .517-.764 14.019 14.019 0 0 1 2.735-.268zm-4.382 6.14c.047-.225.337-.305.504-.142l4.894 4.776a.29.29 0 0 1-.146.492 4.56 4.56 0 0 1-1.522.046c-1.946-.266-3.503-1.785-3.777-3.685a4.243 4.243 0 0 1 .047-1.486zm3.462-3.381a4.564 4.564 0 0 1 1.524-.047c1.949.266 3.507 1.787 3.78 3.688a4.244 4.244 0 0 1-.048 1.488c-.048.225-.338.305-.505.142l-4.897-4.78a.29.29 0 0 1 .146-.491z", fill: "currentColor", fillRule: "evenodd" }) }));
290
+ }
77
291
 
78
- function Checkbox({ _pseudo = 'none', children, className, isDisabled, isSelected, onChange, value, }) {
79
- return (jsxs(Checkbox$1, { className: clsx(className, styles.checkbox, styles[_pseudo]), isDisabled: isDisabled, isSelected: isSelected, onChange: onChange, value: value, children: [jsx("div", { className: styles.box, children: jsx("svg", { "aria-hidden": "true", className: styles.checkmark, viewBox: "0 0 18 18", children: jsx("polyline", { points: "1 9 7 14 15 4" }) }) }), children] }));
292
+ function HashedOutlinedIcon(props) {
293
+ 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 7.666C9.54 7.666 7.538 9.61 7.538 12c0 2.39 2.001 4.334 4.462 4.334 2.46 0 4.462-1.944 4.462-4.334 0-2.39-2.001-4.334-4.462-4.334M12 5c5.514 0 10 3.14 10 7s-4.486 7-10 7-10-3.14-10-7 4.486-7 10-7zm0 1.292c-2.39 0-4.624.642-6.29 1.809C4.175 9.175 3.33 10.56 3.33 12s.845 2.825 2.38 3.9c1.666 1.166 3.9 1.808 6.29 1.808s4.624-.642 6.29-1.809c1.535-1.074 2.38-2.459 2.38-3.9 0-1.44-.845-2.824-2.38-3.898-1.666-1.167-3.9-1.81-6.29-1.81zm0 3.958c.994 0 1.802.785 1.802 1.75s-.808 1.75-1.802 1.75-1.802-.785-1.802-1.75.808-1.75 1.802-1.75z", fill: "currentColor", fillRule: "evenodd" }) }));
294
+ }
295
+
296
+ var styles = {"product-grid":"product-overview-grid-module-bzys-","grid-item":"product-overview-grid-module-MlUVA"};
297
+
298
+ function ProductOverviewGrid({ children }) {
299
+ return (jsx("div", { className: styles['product-grid'], children: Children.map(children, (child, index) => (jsx("div", { className: styles['grid-item'], children: child }, index))) }));
80
300
  }
81
301
 
82
302
  function Filter({ children, title }) {
@@ -90,7 +310,7 @@ function ColorFilter({ onChange, options, value }) {
90
310
  }
91
311
 
92
312
  function ProductListing({ activeFilters, filters, isLoading = false, onFilterChange, onSortChange, productCard: ProductCard, products, }) {
93
- return (jsxs("div", { children: [jsx("h1", { children: "Product listing" }), jsxs("aside", { children: [jsx("h2", { children: "Filter" }), jsx("div", { children: jsx(ColorFilter, { onChange: colors => onFilterChange({ colors }), options: filters.color.options, value: activeFilters.colors }) })] }), jsx("main", { children: jsxs("select", { onChange: e => onSortChange({ by: e.target.value, direction: 'asc' }), children: [jsx("option", { value: "", children: "Sort By" }), jsx("option", { value: "price", children: "Price" }), jsx("option", { value: "title", children: "Title" })] }) }), isLoading ? (jsx("p", { children: "Loading..." })) : (jsx("ul", { children: products.map(product => (jsx("li", { children: jsx(ProductCard, { product: product }) }, product.id))) }))] }));
313
+ return (jsxs("div", { children: [jsx("h1", { children: "Product listing" }), jsxs("aside", { children: [jsx("h2", { children: "Filter" }), jsx("div", { children: jsx(ColorFilter, { onChange: colors => onFilterChange({ colors }), options: filters.color.options, value: activeFilters.colors }) })] }), jsx("main", { children: jsxs("select", { onChange: e => onSortChange({ by: e.target.value, direction: 'asc' }), children: [jsx("option", { value: "", children: "Sort By" }), jsx("option", { value: "price", children: "Price" }), jsx("option", { value: "title", children: "Title" })] }) }), isLoading ? (jsx("p", { children: "Loading..." })) : (jsx("ul", { children: products.map(product => (jsx("li", { children: jsx(ProductCard, {}) }, product.id))) }))] }));
94
314
  }
95
315
 
96
316
  function createProductListingSearchParams(state) {
@@ -112,4 +332,4 @@ function parseProductListingSearchParams(params) {
112
332
  };
113
333
  }
114
334
 
115
- export { Button, CartFilledIcon, CartOutlinedIcon, Checkbox, FavoriteButton, FavoriteFilledIcon, FavoriteOutlinedIcon, IconButton, ProductCard, ProductListing, ProductPrice, ProductSku, RightArrowFilledIcon, createProductListingSearchParams, parseProductListingSearchParams };
335
+ export { AddToCartButton, Button, CartFilledIcon, CartOutlinedIcon, Checkbox, DehashedOutlinedIcon, FavoriteButton, FavoriteFilledIcon, FavoriteOutlinedIcon, HashedOutlinedIcon, IconButton, Image, NumberField, ProductCard, ProductListing, ProductOverviewGrid, ProductPrice, ProductSku, RightArrowFilledIcon, TextField, createProductListingSearchParams, parseProductListingSearchParams };