@tapcart/mobile-components 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/hooks/use-infinite-scroll.d.ts +25 -0
- package/dist/components/hooks/use-infinite-scroll.d.ts.map +1 -0
- package/dist/components/hooks/use-infinite-scroll.js +49 -0
- package/dist/components/ui/product-card.d.ts +51 -16
- package/dist/components/ui/product-card.d.ts.map +1 -1
- package/dist/components/ui/product-card.js +121 -29
- package/dist/components/ui/product-grid.d.ts +14 -0
- package/dist/components/ui/product-grid.d.ts.map +1 -0
- package/dist/components/ui/product-grid.js +22 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/styles.css +41 -14
- package/package.json +6 -3
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface Product {
|
|
2
|
+
handle: string;
|
|
3
|
+
}
|
|
4
|
+
interface PageData {
|
|
5
|
+
products: Product[];
|
|
6
|
+
cursorBlob?: string;
|
|
7
|
+
}
|
|
8
|
+
interface UseInfiniteScrollProps {
|
|
9
|
+
initialData: PageData[];
|
|
10
|
+
loadMoreProducts: (params: any) => Promise<PageData>;
|
|
11
|
+
queryVariables: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
interface UseInfiniteScrollReturn {
|
|
14
|
+
data: PageData[] | undefined;
|
|
15
|
+
error: any;
|
|
16
|
+
isLoadingInitialData: boolean;
|
|
17
|
+
isLoadingMore: boolean | undefined;
|
|
18
|
+
isEmpty: boolean;
|
|
19
|
+
isReachingEnd: boolean;
|
|
20
|
+
ref: (node?: Element | null | undefined) => void;
|
|
21
|
+
products: Product[];
|
|
22
|
+
}
|
|
23
|
+
declare const useInfiniteScroll: ({ initialData, loadMoreProducts, queryVariables, }: UseInfiniteScrollProps) => UseInfiniteScrollReturn;
|
|
24
|
+
export { useInfiniteScroll };
|
|
25
|
+
//# sourceMappingURL=use-infinite-scroll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAOA,UAAU,OAAO;IACf,MAAM,EAAE,MAAM,CAAA;CAEf;AAED,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,UAAU,sBAAsB;IAC9B,WAAW,EAAE,QAAQ,EAAE,CAAA;IACvB,gBAAgB,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACpC;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAA;IAC5B,KAAK,EAAE,GAAG,CAAA;IACV,oBAAoB,EAAE,OAAO,CAAA;IAC7B,aAAa,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,OAAO,CAAA;IACtB,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAA;IAChD,QAAQ,EAAE,OAAO,EAAE,CAAA;CACpB;AAED,QAAA,MAAM,iBAAiB,uDAIpB,sBAAsB,KAAG,uBAkD3B,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useEffect } from "react";
|
|
3
|
+
import useSWRInfinite from "swr/infinite";
|
|
4
|
+
import { useInView } from "react-intersection-observer";
|
|
5
|
+
const PAGE_SIZE = 8;
|
|
6
|
+
const useInfiniteScroll = ({ initialData, loadMoreProducts, queryVariables, }) => {
|
|
7
|
+
var _a, _b, _c, _d;
|
|
8
|
+
const { ref, inView } = useInView();
|
|
9
|
+
const getKey = (pageIndex, previousPageData) => {
|
|
10
|
+
if (pageIndex === 0)
|
|
11
|
+
return queryVariables;
|
|
12
|
+
if (!previousPageData || !previousPageData.cursorBlob)
|
|
13
|
+
return null;
|
|
14
|
+
return Object.assign(Object.assign({}, queryVariables), { cursorBlob: previousPageData.cursorBlob });
|
|
15
|
+
};
|
|
16
|
+
const { data, error, size, setSize } = useSWRInfinite(getKey, loadMoreProducts, {
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
fallbackData: [initialData],
|
|
19
|
+
revalidateFirstPage: false,
|
|
20
|
+
initialSize: 1,
|
|
21
|
+
});
|
|
22
|
+
const isLoadingInitialData = !data && !error;
|
|
23
|
+
const isLoadingMore = isLoadingInitialData ||
|
|
24
|
+
(size > 0 && data && typeof data[size - 1] === "undefined");
|
|
25
|
+
const isEmpty = ((_b = (_a = data === null || data === void 0 ? void 0 : data[0]) === null || _a === void 0 ? void 0 : _a.products) === null || _b === void 0 ? void 0 : _b.length) === 0;
|
|
26
|
+
const isReachingEnd = isEmpty ||
|
|
27
|
+
((data && ((_d = (_c = data[data.length - 1]) === null || _c === void 0 ? void 0 : _c.products) === null || _d === void 0 ? void 0 : _d.length)) || 0) < PAGE_SIZE;
|
|
28
|
+
const loadMore = useCallback(() => {
|
|
29
|
+
if (!isLoadingMore && !isReachingEnd) {
|
|
30
|
+
setSize(size + 1);
|
|
31
|
+
}
|
|
32
|
+
}, [isLoadingMore, isReachingEnd, size, setSize]);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (inView) {
|
|
35
|
+
loadMore();
|
|
36
|
+
}
|
|
37
|
+
}, [inView, loadMore]);
|
|
38
|
+
return {
|
|
39
|
+
data,
|
|
40
|
+
error,
|
|
41
|
+
isLoadingInitialData,
|
|
42
|
+
isLoadingMore,
|
|
43
|
+
isEmpty,
|
|
44
|
+
isReachingEnd,
|
|
45
|
+
ref,
|
|
46
|
+
products: data ? data.flatMap((page) => page === null || page === void 0 ? void 0 : page.products) : [],
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export { useInfiniteScroll };
|
|
@@ -1,32 +1,67 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
export declare type Config = {
|
|
3
|
+
gridLayout?: string;
|
|
4
|
+
productImage?: {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
cornerRadius: number;
|
|
7
|
+
aspectRatio: "1:1" | "2:3" | "4:5";
|
|
8
|
+
scaling: "fill" | "fit";
|
|
9
|
+
};
|
|
10
|
+
price?: {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
fontSize: number;
|
|
13
|
+
textAlignment: string;
|
|
14
|
+
currency: string;
|
|
15
|
+
locale: string;
|
|
16
|
+
};
|
|
17
|
+
productTitle?: {
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
fontSize: number;
|
|
20
|
+
uppercase: boolean;
|
|
21
|
+
textAlignment: string;
|
|
22
|
+
wrapText: boolean;
|
|
23
|
+
};
|
|
24
|
+
quickAdd?: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
fontSize: number;
|
|
27
|
+
uppercase: boolean;
|
|
28
|
+
textAlignment: string;
|
|
29
|
+
cornerRadius: number;
|
|
30
|
+
quickAdd: (event: React.MouseEvent<HTMLButtonElement>, product: ProductCardProps["product"]) => void;
|
|
31
|
+
};
|
|
32
|
+
badge?: {
|
|
33
|
+
text: string;
|
|
34
|
+
verticalPosition: "top" | "bottom" | "below";
|
|
35
|
+
horizontalPosition: "left" | "right" | "full-width";
|
|
36
|
+
icon: string;
|
|
37
|
+
};
|
|
38
|
+
favoritesIcon?: {
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
layoutType: "topLeft" | "topRight" | "bottomLeft" | "bottomRight" | "default";
|
|
41
|
+
showBackground: boolean;
|
|
42
|
+
cornerRadius: number;
|
|
43
|
+
icon: string;
|
|
44
|
+
size: "small" | "large" | null | undefined;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
2
47
|
declare type ProductCardProps = {
|
|
48
|
+
config: Config;
|
|
3
49
|
product: {
|
|
4
50
|
variants: {
|
|
5
51
|
compare_at_price: number | undefined;
|
|
6
52
|
price: number;
|
|
7
53
|
}[];
|
|
8
54
|
images: {
|
|
9
|
-
|
|
55
|
+
url: string;
|
|
10
56
|
}[];
|
|
11
57
|
title: string;
|
|
12
58
|
tags: string[];
|
|
59
|
+
availableForSale: boolean;
|
|
60
|
+
openProduct: (event: React.MouseEvent<HTMLDivElement>, product: ProductCardProps["product"]) => void;
|
|
13
61
|
};
|
|
14
|
-
className: string;
|
|
15
|
-
scaling: "fit" | "fill";
|
|
16
|
-
isQuickAddProductEnabled: boolean;
|
|
17
62
|
isLoading: boolean;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
variant: "secondary" | "default" | "destructive" | "outline" | null | undefined;
|
|
21
|
-
className?: string;
|
|
22
|
-
position: "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
23
|
-
};
|
|
24
|
-
icon?: {
|
|
25
|
-
name: string;
|
|
26
|
-
position: "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
27
|
-
};
|
|
28
|
-
quickAdd: (event: React.MouseEvent<HTMLButtonElement>, product: ProductCardProps["product"]) => void;
|
|
29
|
-
openProduct: (event: React.MouseEvent<HTMLDivElement>, product: ProductCardProps["product"]) => void;
|
|
63
|
+
favorited?: boolean;
|
|
64
|
+
onFavoriteClick?: () => void;
|
|
30
65
|
};
|
|
31
66
|
declare const ProductCard: React.FC<ProductCardProps>;
|
|
32
67
|
export { ProductCard };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../components/ui/product-card.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../components/ui/product-card.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,oBAAY,MAAM,GAAG;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE;QACb,OAAO,EAAE,OAAO,CAAA;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,WAAW,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;QAClC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAA;KACxB,CAAA;IACD,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,OAAO,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,aAAa,EAAE,MAAM,CAAA;QACrB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,YAAY,CAAC,EAAE;QACb,OAAO,EAAE,OAAO,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,OAAO,CAAA;QAClB,aAAa,EAAE,MAAM,CAAA;QACrB,QAAQ,EAAE,OAAO,CAAA;KAClB,CAAA;IACD,QAAQ,CAAC,EAAE;QACT,OAAO,EAAE,OAAO,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,OAAO,CAAA;QAClB,aAAa,EAAE,MAAM,CAAA;QACrB,YAAY,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,CACR,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAC1C,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,KACjC,IAAI,CAAA;KACV,CAAA;IACD,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAA;QACZ,gBAAgB,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAA;QAC5C,kBAAkB,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,CAAA;QACnD,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAA;QAChB,UAAU,EACN,SAAS,GACT,UAAU,GACV,YAAY,GACZ,aAAa,GACb,SAAS,CAAA;QACb,cAAc,EAAE,OAAO,CAAA;QACvB,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;KAC3C,CAAA;CACF,CAAA;AAED,aAAK,gBAAgB,GAAG;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QACP,QAAQ,EAAE;YAAE,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;QACnE,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;QACzB,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,EAAE,CAAA;QACd,gBAAgB,EAAE,OAAO,CAAA;QACzB,WAAW,EAAE,CACX,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,EACvC,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,KACjC,IAAI,CAAA;KACV,CAAA;IACD,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;CAC7B,CAAA;AAqFD,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA2J3C,CAAA;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -3,38 +3,130 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Badge } from "../../components/ui/badge";
|
|
4
4
|
import { Button } from "../../components/ui/button";
|
|
5
5
|
import { Text } from "../../components/ui/text";
|
|
6
|
+
import * as React from "react";
|
|
6
7
|
import { Price } from "../../components/ui/price";
|
|
7
|
-
import { Icon } from "../../components/ui/icon";
|
|
8
8
|
import { Skeleton } from "../../components/ui/skeleton";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
9
|
+
import { Favorite } from "../../components/ui/favorite";
|
|
10
|
+
import { cn } from "../../lib/utils";
|
|
11
|
+
import { cva } from "class-variance-authority";
|
|
12
|
+
const aspectScalingVariants = cva("w-full", {
|
|
13
|
+
variants: {
|
|
14
|
+
aspectRatio: {
|
|
15
|
+
"1:1": "aspect-square",
|
|
16
|
+
"2:3": "aspect-[2/3]",
|
|
17
|
+
"4:5": "aspect-[4/5]",
|
|
18
|
+
},
|
|
19
|
+
scaling: {
|
|
20
|
+
fill: "object-cover",
|
|
21
|
+
fit: "object-contain",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
aspectRatio: "2:3",
|
|
26
|
+
scaling: "fill",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
const badgeVariants = cva("absolute", {
|
|
30
|
+
variants: {
|
|
31
|
+
horizontalPosition: {
|
|
32
|
+
left: "left-0",
|
|
33
|
+
right: "right-0",
|
|
34
|
+
"full-width": "",
|
|
35
|
+
},
|
|
36
|
+
verticalPosition: {
|
|
37
|
+
top: "top-0 mt-2",
|
|
38
|
+
bottom: "bottom-0 mb-2",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const favoriteVariants = cva("absolute ", {
|
|
43
|
+
variants: {
|
|
44
|
+
iconPosition: {
|
|
45
|
+
topLeft: "top-0 left-2 mt-2",
|
|
46
|
+
topRight: "top-0 right-2 mt-2",
|
|
47
|
+
bottomLeft: "bottom-0 left-2 mb-2",
|
|
48
|
+
bottomRight: "bottom-0 right-2 mb-2",
|
|
49
|
+
default: "",
|
|
50
|
+
},
|
|
51
|
+
badgeHorizontalPosition: {
|
|
52
|
+
left: "",
|
|
53
|
+
right: "",
|
|
54
|
+
"full-width": "",
|
|
55
|
+
},
|
|
56
|
+
badgeVerticalPosition: {
|
|
57
|
+
top: "",
|
|
58
|
+
bottom: "",
|
|
59
|
+
below: "",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
compoundVariants: [
|
|
63
|
+
{
|
|
64
|
+
iconPosition: "topLeft",
|
|
65
|
+
badgeHorizontalPosition: ["left", "full-width"],
|
|
66
|
+
badgeVerticalPosition: "top",
|
|
67
|
+
class: "top-10",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
iconPosition: "topRight",
|
|
71
|
+
badgeHorizontalPosition: ["right", "full-width"],
|
|
72
|
+
badgeVerticalPosition: "top",
|
|
73
|
+
class: "top-10",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
iconPosition: "bottomLeft",
|
|
77
|
+
badgeHorizontalPosition: ["left", "full-width"],
|
|
78
|
+
badgeVerticalPosition: "bottom",
|
|
79
|
+
class: "bottom-10",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
iconPosition: "bottomRight",
|
|
83
|
+
badgeHorizontalPosition: ["right", "full-width"],
|
|
84
|
+
badgeVerticalPosition: "bottom",
|
|
85
|
+
class: "bottom-10",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
defaultVariants: {
|
|
89
|
+
iconPosition: "default",
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const ProductCard = ({ config, product, isLoading, favorited, onFavoriteClick, }) => {
|
|
93
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
94
|
+
const { variants: [variant], images: [{ url }], title, tags, } = product;
|
|
95
|
+
const [isSelected, setIsSelected] = React.useState(false);
|
|
96
|
+
const handleFavoriteClick = () => {
|
|
97
|
+
setIsSelected((prevState) => !prevState);
|
|
98
|
+
};
|
|
99
|
+
const iconPosition = ((_a = config.favoritesIcon) === null || _a === void 0 ? void 0 : _a.layoutType) || "default";
|
|
32
100
|
if (isLoading) {
|
|
33
|
-
return (_jsxs("div", Object.assign({ className: "w-1/2" }, { children: [_jsx(Skeleton, { className: "w-full h-64" }, void 0), _jsx(Skeleton, { className: "h-6 w-1/2 mt-2" }, void 0), _jsx(Skeleton, { className: "h-
|
|
101
|
+
return (_jsxs("div", Object.assign({ className: "w-1/2 rounded" }, { children: [_jsx(Skeleton, { className: "w-full h-64 rounded" }, void 0), _jsx(Skeleton, { className: "h-6 w-1/2 mt-2 rounded" }, void 0), _jsx(Skeleton, { className: "h-4 w-full mt-2 rounded" }, void 0)] }), void 0));
|
|
34
102
|
}
|
|
35
|
-
return (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
103
|
+
return (_jsx("div", { children: _jsxs("div", { children: [((_b = config.productImage) === null || _b === void 0 ? void 0 : _b.enabled) && (_jsxs("div", Object.assign({ className: "relative w-full overflow-hidden", style: {
|
|
104
|
+
borderTopLeftRadius: `${config.productImage.cornerRadius}px`,
|
|
105
|
+
borderTopRightRadius: `${config.productImage.cornerRadius}px`,
|
|
106
|
+
} }, { children: [_jsx("img", { className: cn(aspectScalingVariants({
|
|
107
|
+
aspectRatio: (_c = config.productImage) === null || _c === void 0 ? void 0 : _c.aspectRatio,
|
|
108
|
+
scaling: config.productImage.scaling,
|
|
109
|
+
})), src: url, onClick: (e) => product.openProduct(e, product) }, void 0), config.badge &&
|
|
110
|
+
tags.includes(config.badge.text) &&
|
|
111
|
+
config.badge.verticalPosition !== "below" && (_jsx(Badge, Object.assign({ size: "plp-layout", className: cn(badgeVariants({
|
|
112
|
+
verticalPosition: config.badge.verticalPosition,
|
|
113
|
+
horizontalPosition: config.badge.horizontalPosition,
|
|
114
|
+
})), alignment: config.badge.horizontalPosition, icon: config.badge.icon }, { children: config.badge.text }), void 0)), ((_d = config.favoritesIcon) === null || _d === void 0 ? void 0 : _d.enabled) && iconPosition !== "default" && (_jsx(Favorite, { className: cn(favoriteVariants({
|
|
115
|
+
iconPosition,
|
|
116
|
+
badgeHorizontalPosition: (_e = config === null || config === void 0 ? void 0 : config.badge) === null || _e === void 0 ? void 0 : _e.horizontalPosition,
|
|
117
|
+
badgeVerticalPosition: (_f = config === null || config === void 0 ? void 0 : config.badge) === null || _f === void 0 ? void 0 : _f.verticalPosition,
|
|
118
|
+
})), selected: favorited, onClick: onFavoriteClick || handleFavoriteClick }, void 0))] }), void 0)), ((_g = config.quickAdd) === null || _g === void 0 ? void 0 : _g.enabled) && (_jsx(Button, Object.assign({ className: "outline-0", style: {
|
|
119
|
+
borderBottomLeftRadius: `${config.quickAdd.cornerRadius}px`,
|
|
120
|
+
borderBottomRightRadius: `${config.quickAdd.cornerRadius}px`,
|
|
121
|
+
}, variant: "quickadd", size: "default", onClick: (e) => {
|
|
122
|
+
var _a;
|
|
123
|
+
e.stopPropagation();
|
|
124
|
+
(_a = config.quickAdd) === null || _a === void 0 ? void 0 : _a.quickAdd(e, product);
|
|
125
|
+
} }, { children: "+ Quick add" }), void 0)), _jsxs("div", Object.assign({ className: "mt-2 w-full flex-col justify-start items-start gap-1 inline-flex" }, { children: [config.badge &&
|
|
126
|
+
tags.includes(config.badge.text) &&
|
|
127
|
+
config.badge.verticalPosition === "below" && (_jsx("div", Object.assign({ className: `w-full flex ${config.badge.horizontalPosition === "right"
|
|
128
|
+
? "justify-end"
|
|
129
|
+
: "justify-start"}` }, { children: _jsx(Badge, Object.assign({ size: "plp-layout", alignment: config.badge.horizontalPosition, icon: config.badge.icon, className: "rounded" }, { children: config.badge.text }), void 0) }), void 0)), _jsxs("div", Object.assign({ className: "flex w-full justify-between items-center gap-2" }, { children: [((_h = config.price) === null || _h === void 0 ? void 0 : _h.enabled) && (_jsx(Price, { price: variant.price, isSale: !!variant.compare_at_price, compareAtPrice: variant.compare_at_price, currency: config.price.currency, locale: config.price.locale }, void 0)), _jsx("div", Object.assign({ className: "w-8 h-8 flex items-center justify-center" }, { children: ((_j = config.favoritesIcon) === null || _j === void 0 ? void 0 : _j.enabled) &&
|
|
130
|
+
config.favoritesIcon.layoutType === "default" && (_jsx(Favorite, { selected: isSelected, onClick: handleFavoriteClick, size: "small" }, void 0)) }), void 0)] }), void 0), ((_k = config.productTitle) === null || _k === void 0 ? void 0 : _k.enabled) && (_jsx("div", { children: _jsx(Text, Object.assign({ type: "body-secondary", className: "text-textColors-productTitle" }, { children: title }), void 0) }, void 0))] }), void 0)] }, void 0) }, void 0));
|
|
39
131
|
};
|
|
40
132
|
export { ProductCard };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare type Product = any;
|
|
2
|
+
interface PageData {
|
|
3
|
+
products: Product[];
|
|
4
|
+
cursorBlob?: string;
|
|
5
|
+
}
|
|
6
|
+
interface ProductGridItemsProps {
|
|
7
|
+
initialData: PageData[];
|
|
8
|
+
loadMoreProducts: (params: any) => Promise<PageData>;
|
|
9
|
+
queryVariables: Record<string, any>;
|
|
10
|
+
config: Record<string, any>;
|
|
11
|
+
}
|
|
12
|
+
declare function ProductGrid({ loadMoreProducts, initialData, queryVariables, config, }: ProductGridItemsProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export { ProductGrid };
|
|
14
|
+
//# sourceMappingURL=product-grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-grid.d.ts","sourceRoot":"","sources":["../../../components/ui/product-grid.tsx"],"names":[],"mappings":"AAkBA,aAAK,OAAO,GAAG,GAAG,CAAA;AAClB,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,UAAU,qBAAqB;IAC7B,WAAW,EAAE,QAAQ,EAAE,CAAA;IACvB,gBAAgB,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC5B;AAED,iBAAS,WAAW,CAAC,EACnB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,MAAM,GACP,EAAE,qBAAqB,2CAmCvB;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useInfiniteScroll } from "../../components/hooks/use-infinite-scroll";
|
|
4
|
+
import { ProductCard } from "./product-card";
|
|
5
|
+
const Loader = () => (_jsx("div", Object.assign({ className: "grid-cols-2 lg:grid-cols-3" }, { children: Array(4)
|
|
6
|
+
.fill(0)
|
|
7
|
+
.map((_, index) => (_jsx("div", { className: "aspect-[2/3] animate-pulse bg-neutral-100 dark:bg-neutral-900" }, index))) }), void 0));
|
|
8
|
+
function ProductGrid({ loadMoreProducts, initialData, queryVariables, config, }) {
|
|
9
|
+
const { data, error, isLoadingInitialData, isLoadingMore, isEmpty, isReachingEnd, ref, products, } = useInfiniteScroll({
|
|
10
|
+
initialData,
|
|
11
|
+
loadMoreProducts,
|
|
12
|
+
queryVariables,
|
|
13
|
+
});
|
|
14
|
+
if (error)
|
|
15
|
+
return _jsx("div", { children: "Failed to load data" }, void 0);
|
|
16
|
+
if (isLoadingInitialData)
|
|
17
|
+
return _jsx(Loader, {}, void 0);
|
|
18
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", Object.assign({ className: "grid-cols-2 lg:grid-cols-3" }, { children: products.map((product, i) => (_jsx(ProductCard, {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
product: product, config: config, isLoading: false }, product.handle))) }), void 0), isLoadingMore ? _jsx(Loader, {}, void 0) : _jsx("div", { ref: ref }, void 0)] }, void 0));
|
|
21
|
+
}
|
|
22
|
+
export { ProductGrid };
|
package/dist/index.d.ts
CHANGED
|
@@ -30,5 +30,7 @@ export * from "./components/ui/price";
|
|
|
30
30
|
export * from "./components/ui/favorite";
|
|
31
31
|
export * from "./components/ui/wishlist";
|
|
32
32
|
export * from "./components/ui/product-card";
|
|
33
|
+
export * from "./components/ui/product-grid";
|
|
34
|
+
export * from "./components/hooks/use-infinite-scroll";
|
|
33
35
|
export { cn, cva } from "./lib/utils";
|
|
34
36
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,8BAA8B,CAAA;AAC5C,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wCAAwC,CAAA;AACtD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -31,4 +31,6 @@ export * from "./components/ui/price";
|
|
|
31
31
|
export * from "./components/ui/favorite";
|
|
32
32
|
export * from "./components/ui/wishlist";
|
|
33
33
|
export * from "./components/ui/product-card";
|
|
34
|
+
export * from "./components/ui/product-grid";
|
|
35
|
+
export * from "./components/hooks/use-infinite-scroll";
|
|
34
36
|
export { cn, cva } from "./lib/utils";
|
package/dist/styles.css
CHANGED
|
@@ -667,6 +667,9 @@ video {
|
|
|
667
667
|
.bottom-0 {
|
|
668
668
|
bottom: 0px;
|
|
669
669
|
}
|
|
670
|
+
.bottom-10 {
|
|
671
|
+
bottom: 2.5rem;
|
|
672
|
+
}
|
|
670
673
|
.end-4 {
|
|
671
674
|
inset-inline-end: 1rem;
|
|
672
675
|
}
|
|
@@ -676,6 +679,9 @@ video {
|
|
|
676
679
|
.left-1\/2 {
|
|
677
680
|
left: 50%;
|
|
678
681
|
}
|
|
682
|
+
.left-2 {
|
|
683
|
+
left: 0.5rem;
|
|
684
|
+
}
|
|
679
685
|
.left-\[50\%\] {
|
|
680
686
|
left: 50%;
|
|
681
687
|
}
|
|
@@ -694,6 +700,9 @@ video {
|
|
|
694
700
|
.top-1\/2 {
|
|
695
701
|
top: 50%;
|
|
696
702
|
}
|
|
703
|
+
.top-10 {
|
|
704
|
+
top: 2.5rem;
|
|
705
|
+
}
|
|
697
706
|
.top-2 {
|
|
698
707
|
top: 0.5rem;
|
|
699
708
|
}
|
|
@@ -779,6 +788,12 @@ video {
|
|
|
779
788
|
.grid {
|
|
780
789
|
display: grid;
|
|
781
790
|
}
|
|
791
|
+
.aspect-\[2\/3\] {
|
|
792
|
+
aspect-ratio: 2/3;
|
|
793
|
+
}
|
|
794
|
+
.aspect-\[4\/5\] {
|
|
795
|
+
aspect-ratio: 4/5;
|
|
796
|
+
}
|
|
782
797
|
.aspect-square {
|
|
783
798
|
aspect-ratio: 1 / 1;
|
|
784
799
|
}
|
|
@@ -857,9 +872,6 @@ video {
|
|
|
857
872
|
.w-2\.5 {
|
|
858
873
|
width: 0.625rem;
|
|
859
874
|
}
|
|
860
|
-
.w-3\/4 {
|
|
861
|
-
width: 75%;
|
|
862
|
-
}
|
|
863
875
|
.w-4 {
|
|
864
876
|
width: 1rem;
|
|
865
877
|
}
|
|
@@ -997,6 +1009,12 @@ video {
|
|
|
997
1009
|
.items-center {
|
|
998
1010
|
align-items: center;
|
|
999
1011
|
}
|
|
1012
|
+
.justify-start {
|
|
1013
|
+
justify-content: flex-start;
|
|
1014
|
+
}
|
|
1015
|
+
.justify-end {
|
|
1016
|
+
justify-content: flex-end;
|
|
1017
|
+
}
|
|
1000
1018
|
.justify-center {
|
|
1001
1019
|
justify-content: center;
|
|
1002
1020
|
}
|
|
@@ -1067,9 +1085,6 @@ video {
|
|
|
1067
1085
|
.rounded-full {
|
|
1068
1086
|
border-radius: 9999px;
|
|
1069
1087
|
}
|
|
1070
|
-
.rounded-lg {
|
|
1071
|
-
border-radius: var(--radius);
|
|
1072
|
-
}
|
|
1073
1088
|
.rounded-md {
|
|
1074
1089
|
border-radius: calc(var(--radius) - 2px);
|
|
1075
1090
|
}
|
|
@@ -1083,18 +1098,10 @@ video {
|
|
|
1083
1098
|
border-bottom-right-radius: var(--radius);
|
|
1084
1099
|
border-bottom-left-radius: var(--radius);
|
|
1085
1100
|
}
|
|
1086
|
-
.rounded-b-none {
|
|
1087
|
-
border-bottom-right-radius: 0px;
|
|
1088
|
-
border-bottom-left-radius: 0px;
|
|
1089
|
-
}
|
|
1090
1101
|
.rounded-t-2xl {
|
|
1091
1102
|
border-top-left-radius: 1rem;
|
|
1092
1103
|
border-top-right-radius: 1rem;
|
|
1093
1104
|
}
|
|
1094
|
-
.rounded-t-lg {
|
|
1095
|
-
border-top-left-radius: var(--radius);
|
|
1096
|
-
border-top-right-radius: var(--radius);
|
|
1097
|
-
}
|
|
1098
1105
|
.rounded-bl {
|
|
1099
1106
|
border-bottom-left-radius: 0.25rem;
|
|
1100
1107
|
}
|
|
@@ -1178,6 +1185,10 @@ video {
|
|
|
1178
1185
|
.bg-coreColors-pageColor {
|
|
1179
1186
|
background-color: var(--coreColors-pageColor);
|
|
1180
1187
|
}
|
|
1188
|
+
.bg-neutral-100 {
|
|
1189
|
+
--tw-bg-opacity: 1;
|
|
1190
|
+
background-color: rgb(245 245 245 / var(--tw-bg-opacity));
|
|
1191
|
+
}
|
|
1181
1192
|
.bg-productBadging-fill {
|
|
1182
1193
|
background-color: var(--productBadging-fill);
|
|
1183
1194
|
}
|
|
@@ -1361,6 +1372,9 @@ video {
|
|
|
1361
1372
|
.font-semibold {
|
|
1362
1373
|
font-weight: 600;
|
|
1363
1374
|
}
|
|
1375
|
+
.uppercase {
|
|
1376
|
+
text-transform: uppercase;
|
|
1377
|
+
}
|
|
1364
1378
|
.leading-\[130\%\] {
|
|
1365
1379
|
line-height: 130%;
|
|
1366
1380
|
}
|
|
@@ -1550,6 +1564,9 @@ video {
|
|
|
1550
1564
|
.outline {
|
|
1551
1565
|
outline-style: solid;
|
|
1552
1566
|
}
|
|
1567
|
+
.outline-0 {
|
|
1568
|
+
outline-width: 0px;
|
|
1569
|
+
}
|
|
1553
1570
|
.outline-1 {
|
|
1554
1571
|
outline-width: 1px;
|
|
1555
1572
|
}
|
|
@@ -1948,6 +1965,10 @@ video {
|
|
|
1948
1965
|
.data-\[state\=open\]\:duration-500[data-state=open] {
|
|
1949
1966
|
animation-duration: 500ms;
|
|
1950
1967
|
}
|
|
1968
|
+
:is(.dark .dark\:bg-neutral-900) {
|
|
1969
|
+
--tw-bg-opacity: 1;
|
|
1970
|
+
background-color: rgb(23 23 23 / var(--tw-bg-opacity));
|
|
1971
|
+
}
|
|
1951
1972
|
@media (min-width: 640px) {
|
|
1952
1973
|
|
|
1953
1974
|
.sm\:mt-0 {
|
|
@@ -1976,6 +1997,12 @@ video {
|
|
|
1976
1997
|
text-align: left;
|
|
1977
1998
|
}
|
|
1978
1999
|
}
|
|
2000
|
+
@media (min-width: 1024px) {
|
|
2001
|
+
|
|
2002
|
+
.lg\:grid-cols-3 {
|
|
2003
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
1979
2006
|
.\[\&\+label\]\:text-stateColors-error+label {
|
|
1980
2007
|
color: var(--stateColors-error);
|
|
1981
2008
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tapcart/mobile-components",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
|
-
"module": "dist/index.esm.js",
|
|
6
5
|
"types": "dist/index.d.ts",
|
|
7
6
|
"style": "dist/styles.css",
|
|
8
7
|
"sourceMap": true,
|
|
@@ -17,13 +16,15 @@
|
|
|
17
16
|
"ui:add": "pnpm dlx shadcn-ui@latest add",
|
|
18
17
|
"build:styles": "postcss styles/globals.css -o dist/styles.css",
|
|
19
18
|
"build:ts": "tsc -p tsconfig.json && tsc-alias",
|
|
20
|
-
"build": "pnpm run build:ts && pnpm run build:styles"
|
|
19
|
+
"build": "pnpm run build:ts && pnpm run build:styles",
|
|
20
|
+
"dev": "tsc -w -p tsconfig.json"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"react": "^17.0.2 || ^18.0.0",
|
|
24
24
|
"react-dom": "^17.0.2 || ^18.0.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
+
"@types/lodash": "4.17.5",
|
|
27
28
|
"@types/react": "^18.2.0",
|
|
28
29
|
"@types/react-dom": "^18.2.0",
|
|
29
30
|
"autoprefixer": "^10.4.14",
|
|
@@ -57,6 +58,8 @@
|
|
|
57
58
|
"lucide-react": "^0.248.0",
|
|
58
59
|
"next-themes": "^0.2.1",
|
|
59
60
|
"postcss-cli": "^11.0.0",
|
|
61
|
+
"react-intersection-observer": "^9.10.2",
|
|
62
|
+
"swr": "^2.2.5",
|
|
60
63
|
"tailwind-merge": "^1.13.2",
|
|
61
64
|
"tailwindcss-animate": "^1.0.6",
|
|
62
65
|
"vaul": "^0.9.1"
|