@sonic-equipment/ui 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -18
- package/dist/badges/tag/tag.d.ts +5 -0
- package/dist/badges/tag/tag.stories.d.ts +18 -0
- package/dist/base.css +18 -0
- package/dist/buttons/button/button.d.ts +13 -8
- package/dist/buttons/button/button.stories.d.ts +11 -6
- package/dist/buttons/favorite/favorite-button.d.ts +2 -2
- package/dist/buttons/favorite/favorite-button.stories.d.ts +6 -6
- package/dist/buttons/icon-button/icon-button.d.ts +9 -7
- package/dist/buttons/icon-button/icon-button.stories.d.ts +6 -6
- package/dist/cards/product-card/product-card.d.ts +9 -9
- package/dist/cards/product-card/product-card.stories.d.ts +3 -3
- package/dist/display/product-price/product-price.d.ts +11 -0
- package/dist/display/product-price/product-price.stories.d.ts +15 -0
- package/dist/display/product-sku/product-sku.d.ts +4 -0
- package/dist/display/product-sku/product-sku.stories.d.ts +13 -0
- package/dist/fonts.css +96 -49
- package/dist/icons/arrows/left-arrow-filled-icon.d.ts +2 -0
- package/dist/icons/arrows/right-arrow-filled-icon.d.ts +2 -0
- package/dist/icons/cart/cart-filled-icon.d.ts +2 -0
- package/dist/icons/cart/cart-outlined-icon.d.ts +2 -0
- package/dist/index.d.ts +89 -45
- package/dist/index.js +72 -31
- package/dist/inputs/checkbox/checkbox.d.ts +11 -4
- package/dist/inputs/checkbox/checkbox.stories.d.ts +8 -6
- package/dist/product-listing/filters/colors/color-filter.d.ts +5 -5
- package/dist/product-listing/filters/filter/filter.d.ts +4 -4
- package/dist/product-listing/product-listing.d.ts +16 -13
- package/dist/product-listing/product-listing.stories.d.ts +7 -7
- package/dist/product-listing/search-params.d.ts +3 -3
- package/dist/shared/types/product.d.ts +4 -0
- package/dist/styles.css +296 -89
- package/dist/tokens/tokens.d.ts +2 -0
- package/dist/typography/heading/heading.d.ts +17 -0
- package/dist/typography/heading/heading.stories.d.ts +37 -0
- package/package.json +50 -30
- package/dist/reset.css +0 -384
- /package/dist/icons/favorite/{favorite-outline-icon.d.ts → favorite-outlined-icon.d.ts} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,53 +1,95 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
-
import {
|
|
4
|
-
import { ComponentPropsWithoutRef, ComponentType } from 'react';
|
|
3
|
+
import { ComponentType, ReactNode } from 'react';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
interface ButtonProps {
|
|
6
|
+
_pseudo?: 'none' | 'focus' | 'hover' | 'active';
|
|
7
|
+
children: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
color?: 'primary' | 'secondary';
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
isDisabled?: boolean;
|
|
12
|
+
onPress?: VoidFunction;
|
|
13
|
+
size?: 'md' | 'lg';
|
|
14
|
+
variant?: 'solid' | 'outline' | 'ghost';
|
|
10
15
|
withArrow?: boolean;
|
|
11
|
-
}
|
|
12
|
-
declare function Button({ children,
|
|
13
|
-
|
|
14
|
-
declare function FavoriteFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
|
|
16
|
+
}
|
|
17
|
+
declare function Button({ _pseudo, children, className, color, icon, isDisabled, onPress, size, variant, withArrow, }: ButtonProps): react_jsx_runtime.JSX.Element;
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type FavoriteButtonProps = {
|
|
19
|
+
interface FavoriteButtonProps {
|
|
19
20
|
isFavorite: boolean;
|
|
20
21
|
onPress: () => void;
|
|
21
|
-
}
|
|
22
|
+
}
|
|
22
23
|
declare function FavoriteButton({ isFavorite, onPress }: FavoriteButtonProps): react_jsx_runtime.JSX.Element;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
interface IconButtonProps {
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
className?: string;
|
|
28
|
+
color?: 'primary' | 'secondary';
|
|
29
|
+
onPress?: VoidFunction;
|
|
30
|
+
size?: 'md' | 'lg';
|
|
31
|
+
}
|
|
32
|
+
declare function IconButton({ children, className, color, onPress, size, }: IconButtonProps): react_jsx_runtime.JSX.Element;
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
35
|
-
favoriteButton: ComponentType<any>;
|
|
36
|
-
};
|
|
37
|
-
declare function ProductCard({ product, favoriteButton: FavoriteButton, }: ProductCardProps): react_jsx_runtime.JSX.Element;
|
|
34
|
+
interface Product {
|
|
35
|
+
id: string
|
|
36
|
+
title: string
|
|
37
|
+
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
interface ProductCardProps {
|
|
40
|
+
favoriteButton: ComponentType<{
|
|
41
|
+
productId: string;
|
|
42
|
+
}>;
|
|
43
|
+
product: Product;
|
|
44
|
+
}
|
|
45
|
+
declare function ProductCard({ favoriteButton: FavoriteButton, product, }: ProductCardProps): react_jsx_runtime.JSX.Element;
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
interface Price {
|
|
48
|
+
exclVat: number;
|
|
49
|
+
inclVat: number;
|
|
50
|
+
}
|
|
51
|
+
interface ProductPriceProps {
|
|
52
|
+
current: Price;
|
|
53
|
+
includeVat?: boolean;
|
|
54
|
+
original?: Price;
|
|
55
|
+
}
|
|
56
|
+
declare function ProductPrice({ current, includeVat, original, }: ProductPriceProps): react_jsx_runtime.JSX.Element | undefined;
|
|
57
|
+
|
|
58
|
+
interface ProductSkuProps {
|
|
59
|
+
sku: string;
|
|
60
|
+
}
|
|
61
|
+
declare function ProductSku({ sku }: ProductSkuProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
declare function RightArrowFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
|
|
64
|
+
|
|
65
|
+
declare function CartFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
|
|
66
|
+
|
|
67
|
+
declare function CartOutlinedIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
|
|
68
|
+
|
|
69
|
+
declare function FavoriteFilledIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
|
|
70
|
+
|
|
71
|
+
declare function FavoriteOutlinedIcon(props: React.SVGProps<SVGSVGElement>): react_jsx_runtime.JSX.Element;
|
|
72
|
+
|
|
73
|
+
interface CheckboxProps {
|
|
74
|
+
_pseudo?: 'none' | 'focus' | 'hover' | 'active';
|
|
75
|
+
children: ReactNode;
|
|
76
|
+
className?: string;
|
|
77
|
+
isDisabled?: boolean;
|
|
78
|
+
isSelected?: boolean;
|
|
79
|
+
onChange?: (isSelected: boolean) => void;
|
|
80
|
+
value?: string;
|
|
81
|
+
}
|
|
82
|
+
declare function Checkbox({ _pseudo, children, className, isDisabled, isSelected, onChange, value, }: CheckboxProps): react_jsx_runtime.JSX.Element;
|
|
83
|
+
|
|
84
|
+
interface Filters {
|
|
43
85
|
color: {
|
|
44
86
|
options: {
|
|
45
|
-
value: string;
|
|
46
|
-
label: string;
|
|
47
87
|
count: number;
|
|
88
|
+
label: string;
|
|
89
|
+
value: string;
|
|
48
90
|
}[];
|
|
49
91
|
};
|
|
50
|
-
}
|
|
92
|
+
}
|
|
51
93
|
type ActiveFilters = {
|
|
52
94
|
colors: string[];
|
|
53
95
|
};
|
|
@@ -56,32 +98,34 @@ type Sort = {
|
|
|
56
98
|
direction: string;
|
|
57
99
|
};
|
|
58
100
|
type ProductListingProps = {
|
|
59
|
-
|
|
101
|
+
activeFilters: ActiveFilters;
|
|
102
|
+
filters: Filters;
|
|
103
|
+
isLoading?: boolean;
|
|
104
|
+
onFilterChange: (filters: ActiveFilters) => void;
|
|
105
|
+
onSortChange: (sort: Sort) => void;
|
|
106
|
+
productCard: ComponentType<{
|
|
107
|
+
product: Product;
|
|
108
|
+
}>;
|
|
60
109
|
products: {
|
|
61
110
|
id: string;
|
|
62
111
|
title: string;
|
|
63
112
|
}[];
|
|
64
|
-
total: number;
|
|
65
|
-
filters: Filters;
|
|
66
|
-
activeFilters: ActiveFilters;
|
|
67
113
|
sort: {
|
|
68
114
|
by: string;
|
|
69
115
|
direction: string;
|
|
70
116
|
};
|
|
71
|
-
|
|
72
|
-
onFilterChange: (filters: ActiveFilters) => void;
|
|
73
|
-
onSortChange: (sort: Sort) => void;
|
|
117
|
+
total: number;
|
|
74
118
|
};
|
|
75
|
-
declare function ProductListing({
|
|
119
|
+
declare function ProductListing({ activeFilters, filters, isLoading, onFilterChange, onSortChange, productCard: ProductCard, products, }: ProductListingProps): react_jsx_runtime.JSX.Element;
|
|
76
120
|
|
|
77
121
|
declare function createProductListingSearchParams(state: {
|
|
122
|
+
filters: {
|
|
123
|
+
colors: string[];
|
|
124
|
+
};
|
|
78
125
|
sort: {
|
|
79
126
|
by: string;
|
|
80
127
|
direction: string;
|
|
81
128
|
};
|
|
82
|
-
filters: {
|
|
83
|
-
colors: string[];
|
|
84
|
-
};
|
|
85
129
|
}): URLSearchParams;
|
|
86
130
|
declare function parseProductListingSearchParams(params: URLSearchParams): {
|
|
87
131
|
filters: {
|
|
@@ -93,4 +137,4 @@ declare function parseProductListingSearchParams(params: URLSearchParams): {
|
|
|
93
137
|
};
|
|
94
138
|
};
|
|
95
139
|
|
|
96
|
-
export { type ActiveFilters, Button, type ButtonProps, Checkbox, type CheckboxProps, FavoriteButton, type FavoriteButtonProps, FavoriteFilledIcon, FavoriteOutlinedIcon, type Filters, IconButton, type IconButtonProps, ProductCard, type ProductCardProps, ProductListing, type ProductListingProps, type Sort, createProductListingSearchParams, parseProductListingSearchParams };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,74 +1,115 @@
|
|
|
1
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import clsx from 'clsx';
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
2
|
import { Button as Button$1, Checkbox as Checkbox$1 } from 'react-aria-components';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
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
|
+
}
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
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
|
+
|
|
11
|
+
function Button({ _pseudo = 'none', children, className, color = 'primary', icon, isDisabled, onPress, size = 'md', variant = 'solid', withArrow = false, }) {
|
|
12
|
+
if (children && icon)
|
|
13
|
+
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
|
+
}
|
|
16
|
+
|
|
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
|
+
|
|
19
|
+
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 }));
|
|
9
21
|
}
|
|
10
22
|
|
|
11
23
|
function FavoriteFilledIcon(props) {
|
|
12
|
-
return (jsx("svg", {
|
|
24
|
+
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" }) }));
|
|
13
25
|
}
|
|
14
26
|
|
|
15
27
|
function FavoriteOutlinedIcon(props) {
|
|
16
|
-
return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg",
|
|
28
|
+
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" }) }));
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
var styles$
|
|
31
|
+
var styles$3 = {"favorite-button":"favorite-button-module-tXSS3","isFavorite":"favorite-button-module-6FS3Q"};
|
|
20
32
|
|
|
21
|
-
function
|
|
22
|
-
return (jsx(
|
|
33
|
+
function FavoriteButton({ isFavorite, onPress }) {
|
|
34
|
+
return (jsx(IconButton, { className: clsx(styles$3['favorite-button'], {
|
|
35
|
+
[styles$3.isFavorite]: isFavorite,
|
|
36
|
+
}), color: "secondary", onPress: onPress, children: isFavorite ? jsx(FavoriteFilledIcon, {}) : jsx(FavoriteOutlinedIcon, {}) }));
|
|
23
37
|
}
|
|
24
38
|
|
|
25
|
-
|
|
39
|
+
function ProductCard({ favoriteButton: FavoriteButton, product, }) {
|
|
40
|
+
return (jsxs("div", { children: [jsx("div", { children: jsx(FavoriteButton, { productId: product.id }) }), jsx("h2", { children: product.title })] }));
|
|
41
|
+
}
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
|
|
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"};
|
|
44
|
+
|
|
45
|
+
const formatPrice = (price) => new Intl.NumberFormat('en-US', {
|
|
46
|
+
maximumFractionDigits: 2,
|
|
47
|
+
minimumFractionDigits: 2,
|
|
48
|
+
}).format(price);
|
|
49
|
+
function ProductPrice({ current, includeVat = true, original, }) {
|
|
50
|
+
if (!current.inclVat && !current.exclVat)
|
|
51
|
+
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);
|
|
58
|
+
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' })] })] }));
|
|
29
60
|
}
|
|
30
61
|
|
|
31
|
-
|
|
32
|
-
|
|
62
|
+
var styles$1 = {"product-sku":"product-sku-module-ITb8x"};
|
|
63
|
+
|
|
64
|
+
function ProductSku({ sku }) {
|
|
65
|
+
return jsx("p", { className: styles$1['product-sku'], children: sku });
|
|
66
|
+
}
|
|
67
|
+
|
|
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" }) }));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function CartOutlinedIcon(props) {
|
|
73
|
+
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" }) }));
|
|
33
74
|
}
|
|
34
75
|
|
|
35
|
-
var styles = {"checkbox":"checkbox-module-y3eBg","box":"checkbox-module-TqLux","checkmark":"checkbox-module-Yhrdp"};
|
|
76
|
+
var styles = {"checkbox":"checkbox-module-y3eBg","box":"checkbox-module-TqLux","checkmark":"checkbox-module-Yhrdp","focus":"checkbox-module-zoTSP","active":"checkbox-module-sHmzp"};
|
|
36
77
|
|
|
37
|
-
function Checkbox({ children,
|
|
38
|
-
return (jsxs(Checkbox$1, {
|
|
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] }));
|
|
39
80
|
}
|
|
40
81
|
|
|
41
|
-
function Filter({
|
|
82
|
+
function Filter({ children, title }) {
|
|
42
83
|
return (jsxs("div", { children: [jsx("div", { children: jsx("h3", { children: title }) }), jsx("div", { children: children })] }));
|
|
43
84
|
}
|
|
44
85
|
|
|
45
|
-
function ColorFilter({ options, value
|
|
46
|
-
return (jsx(Filter, { title: "Color", children: jsx("ul", { children: options.map(
|
|
86
|
+
function ColorFilter({ onChange, options, value }) {
|
|
87
|
+
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
|
|
47
88
|
? [...value, option.value]
|
|
48
|
-
: value.filter(
|
|
89
|
+
: value.filter(v => v !== option.value)), value: option.value, children: option.label }) }, option.value))) }) }));
|
|
49
90
|
}
|
|
50
91
|
|
|
51
|
-
function ProductListing({
|
|
52
|
-
return (jsxs("div", { children: [jsx("h1", { children: "Product listing" }), jsxs("aside", { children: [jsx("h2", { children: "Filter" }), jsx("div", { children: jsx(ColorFilter, { options: filters.color.options, value: activeFilters.colors
|
|
92
|
+
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))) }))] }));
|
|
53
94
|
}
|
|
54
95
|
|
|
55
96
|
function createProductListingSearchParams(state) {
|
|
56
97
|
const params = new URLSearchParams();
|
|
57
98
|
if (state.filters.colors.length > 0) {
|
|
58
|
-
params.set(
|
|
99
|
+
params.set('colors', state.filters.colors.join(','));
|
|
59
100
|
}
|
|
60
|
-
params.set(
|
|
61
|
-
params.set(
|
|
101
|
+
params.set('sortBy', state.sort.by);
|
|
102
|
+
params.set('sortDirection', state.sort.direction);
|
|
62
103
|
return params;
|
|
63
104
|
}
|
|
64
105
|
function parseProductListingSearchParams(params) {
|
|
65
106
|
return {
|
|
66
|
-
filters: { colors: params.get(
|
|
107
|
+
filters: { colors: params.get('colors')?.split(',') ?? [] },
|
|
67
108
|
sort: {
|
|
68
|
-
by: params.get(
|
|
69
|
-
direction: params.get(
|
|
109
|
+
by: params.get('sortBy') ?? 'relevance',
|
|
110
|
+
direction: params.get('sortDirection') ?? 'asc',
|
|
70
111
|
},
|
|
71
112
|
};
|
|
72
113
|
}
|
|
73
114
|
|
|
74
|
-
export { Button, Checkbox, FavoriteButton, FavoriteFilledIcon, FavoriteOutlinedIcon, IconButton, ProductCard, ProductListing, createProductListingSearchParams, parseProductListingSearchParams };
|
|
115
|
+
export { Button, CartFilledIcon, CartOutlinedIcon, Checkbox, FavoriteButton, FavoriteFilledIcon, FavoriteOutlinedIcon, IconButton, ProductCard, ProductListing, ProductPrice, ProductSku, RightArrowFilledIcon, createProductListingSearchParams, parseProductListingSearchParams };
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface CheckboxProps {
|
|
3
|
+
_pseudo?: 'none' | 'focus' | 'hover' | 'active';
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
isDisabled?: boolean;
|
|
7
|
+
isSelected?: boolean;
|
|
8
|
+
onChange?: (isSelected: boolean) => void;
|
|
9
|
+
value?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function Checkbox({ _pseudo, children, className, isDisabled, isSelected, onChange, value, }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import type { StoryObj } from
|
|
2
|
-
import { Checkbox } from
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
import { Checkbox } from './checkbox';
|
|
3
3
|
declare const meta: {
|
|
4
|
-
|
|
4
|
+
args: {
|
|
5
|
+
onChange: import("@vitest/spy").Mock<[isSelected: boolean], void>;
|
|
6
|
+
};
|
|
5
7
|
component: typeof Checkbox;
|
|
6
8
|
parameters: {
|
|
7
9
|
layout: string;
|
|
8
10
|
};
|
|
9
11
|
tags: string[];
|
|
10
|
-
|
|
11
|
-
onChange: import("@storybook/test").Mock<[isSelected: boolean], void>;
|
|
12
|
-
};
|
|
12
|
+
title: string;
|
|
13
13
|
};
|
|
14
14
|
export default meta;
|
|
15
15
|
type Story = StoryObj<typeof Checkbox>;
|
|
16
16
|
export declare const Unchecked: Story;
|
|
17
17
|
export declare const Checked: Story;
|
|
18
|
+
export declare const CheckedDisabled: Story;
|
|
19
|
+
export declare const CheckedFocus: Story;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { FilterProps } from
|
|
1
|
+
import { FilterProps } from 'product-listing/filters/filter/filter';
|
|
2
2
|
export type ColorFilterProps = FilterProps & {
|
|
3
|
+
onChange: (value: string[]) => void;
|
|
3
4
|
options: {
|
|
4
|
-
value: string;
|
|
5
|
-
label: string;
|
|
6
5
|
count: number;
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
7
8
|
}[];
|
|
8
9
|
value: string[];
|
|
9
|
-
onChange: (value: string[]) => void;
|
|
10
10
|
};
|
|
11
|
-
export declare function ColorFilter({ options, value
|
|
11
|
+
export declare function ColorFilter({ onChange, options, value }: ColorFilterProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PropsWithChildren } from
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
2
|
export type FilterProps = PropsWithChildren<{
|
|
3
|
-
title?: string;
|
|
4
|
-
isCollapseable?: boolean;
|
|
5
3
|
initialIsCollapsed?: boolean;
|
|
4
|
+
isCollapseable?: boolean;
|
|
5
|
+
title?: string;
|
|
6
6
|
}>;
|
|
7
|
-
export declare function Filter({
|
|
7
|
+
export declare function Filter({ children, title }: FilterProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { ComponentType } from
|
|
2
|
-
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
import type { Product } from 'shared/types/product';
|
|
3
|
+
export interface Filters {
|
|
3
4
|
color: {
|
|
4
5
|
options: {
|
|
5
|
-
value: string;
|
|
6
|
-
label: string;
|
|
7
6
|
count: number;
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
8
9
|
}[];
|
|
9
10
|
};
|
|
10
|
-
}
|
|
11
|
+
}
|
|
11
12
|
export type ActiveFilters = {
|
|
12
13
|
colors: string[];
|
|
13
14
|
};
|
|
@@ -16,20 +17,22 @@ export type Sort = {
|
|
|
16
17
|
direction: string;
|
|
17
18
|
};
|
|
18
19
|
export type ProductListingProps = {
|
|
19
|
-
|
|
20
|
+
activeFilters: ActiveFilters;
|
|
21
|
+
filters: Filters;
|
|
22
|
+
isLoading?: boolean;
|
|
23
|
+
onFilterChange: (filters: ActiveFilters) => void;
|
|
24
|
+
onSortChange: (sort: Sort) => void;
|
|
25
|
+
productCard: ComponentType<{
|
|
26
|
+
product: Product;
|
|
27
|
+
}>;
|
|
20
28
|
products: {
|
|
21
29
|
id: string;
|
|
22
30
|
title: string;
|
|
23
31
|
}[];
|
|
24
|
-
total: number;
|
|
25
|
-
filters: Filters;
|
|
26
|
-
activeFilters: ActiveFilters;
|
|
27
32
|
sort: {
|
|
28
33
|
by: string;
|
|
29
34
|
direction: string;
|
|
30
35
|
};
|
|
31
|
-
|
|
32
|
-
onFilterChange: (filters: ActiveFilters) => void;
|
|
33
|
-
onSortChange: (sort: Sort) => void;
|
|
36
|
+
total: number;
|
|
34
37
|
};
|
|
35
|
-
export declare function ProductListing({
|
|
38
|
+
export declare function ProductListing({ activeFilters, filters, isLoading, onFilterChange, onSortChange, productCard: ProductCard, products, }: ProductListingProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { StoryObj } from
|
|
2
|
-
import { ProductListing } from
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
import { ProductListing } from './product-listing';
|
|
3
3
|
declare const meta: {
|
|
4
|
-
title: string;
|
|
5
|
-
component: typeof ProductListing;
|
|
6
|
-
tags: string[];
|
|
7
4
|
args: {
|
|
8
|
-
onFilterChange: import("@
|
|
9
|
-
onSortChange: import("@
|
|
5
|
+
onFilterChange: import("@vitest/spy").Mock<[filters: import("./product-listing").ActiveFilters], void>;
|
|
6
|
+
onSortChange: import("@vitest/spy").Mock<[sort: import("./product-listing").Sort], void>;
|
|
10
7
|
};
|
|
8
|
+
component: typeof ProductListing;
|
|
9
|
+
tags: string[];
|
|
10
|
+
title: string;
|
|
11
11
|
};
|
|
12
12
|
export default meta;
|
|
13
13
|
type Story = StoryObj<typeof ProductListing>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export declare function createProductListingSearchParams(state: {
|
|
2
|
+
filters: {
|
|
3
|
+
colors: string[];
|
|
4
|
+
};
|
|
2
5
|
sort: {
|
|
3
6
|
by: string;
|
|
4
7
|
direction: string;
|
|
5
8
|
};
|
|
6
|
-
filters: {
|
|
7
|
-
colors: string[];
|
|
8
|
-
};
|
|
9
9
|
}): URLSearchParams;
|
|
10
10
|
export declare function parseProductListingSearchParams(params: URLSearchParams): {
|
|
11
11
|
filters: {
|