@tapcart/mobile-components 0.7.0 → 0.7.2

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 (81) hide show
  1. package/dist/components/hooks/use-infinite-scroll.d.ts +3 -1
  2. package/dist/components/hooks/use-infinite-scroll.d.ts.map +1 -1
  3. package/dist/components/hooks/use-infinite-scroll.js +34 -11
  4. package/dist/components/hooks/use-nosto-recommendation.d.ts +8 -0
  5. package/dist/components/hooks/use-nosto-recommendation.d.ts.map +1 -0
  6. package/dist/components/hooks/use-nosto-recommendation.js +105 -0
  7. package/dist/components/hooks/use-products.d.ts +3 -1
  8. package/dist/components/hooks/use-products.d.ts.map +1 -1
  9. package/dist/components/hooks/use-products.js +21 -6
  10. package/dist/components/hooks/use-reviews.d.ts +27 -0
  11. package/dist/components/hooks/use-reviews.d.ts.map +1 -0
  12. package/dist/components/hooks/use-reviews.js +130 -0
  13. package/dist/components/templates/ProductCard/utils.d.ts +78 -0
  14. package/dist/components/templates/ProductCard/utils.d.ts.map +1 -0
  15. package/dist/components/templates/ProductCard/utils.js +128 -0
  16. package/dist/components/templates/ProductGrid/index.d.ts +1 -0
  17. package/dist/components/templates/ProductGrid/index.d.ts.map +1 -0
  18. package/dist/components/templates/ProductGrid/index.js +1 -0
  19. package/dist/components/ui/Input/input.d.ts +1 -1
  20. package/dist/components/ui/Input/input.d.ts.map +1 -1
  21. package/dist/components/ui/Input/input.js +23 -5
  22. package/dist/components/ui/Input/types.d.ts +3 -2
  23. package/dist/components/ui/Input/types.d.ts.map +1 -1
  24. package/dist/components/ui/Input/useInput.d.ts +2 -2
  25. package/dist/components/ui/Input/useInput.d.ts.map +1 -1
  26. package/dist/components/ui/Input/useInput.js +24 -10
  27. package/dist/components/ui/ProductCard/utils.d.ts +94 -0
  28. package/dist/components/ui/ProductCard/utils.d.ts.map +1 -0
  29. package/dist/components/ui/ProductCard/utils.js +148 -0
  30. package/dist/components/ui/ProductGrid/index.d.ts +1 -0
  31. package/dist/components/ui/ProductGrid/index.d.ts.map +1 -0
  32. package/dist/components/ui/ProductGrid/index.js +1 -0
  33. package/dist/components/ui/accordion.d.ts +3 -1
  34. package/dist/components/ui/accordion.d.ts.map +1 -1
  35. package/dist/components/ui/accordion.js +2 -2
  36. package/dist/components/ui/button.d.ts +2 -2
  37. package/dist/components/ui/button.d.ts.map +1 -1
  38. package/dist/components/ui/button.js +1 -1
  39. package/dist/components/ui/carousel.d.ts +1 -0
  40. package/dist/components/ui/carousel.d.ts.map +1 -1
  41. package/dist/components/ui/carousel.js +62 -2
  42. package/dist/components/ui/chip.d.ts +2 -2
  43. package/dist/components/ui/icon.d.ts +4 -1
  44. package/dist/components/ui/icon.d.ts.map +1 -1
  45. package/dist/components/ui/icon.js +35 -8
  46. package/dist/components/ui/image.d.ts.map +1 -1
  47. package/dist/components/ui/image.js +3 -3
  48. package/dist/components/ui/radio-group.d.ts +2 -2
  49. package/dist/components/ui/scroll-area.d.ts +1 -0
  50. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  51. package/dist/components/ui/scroll-area.js +2 -2
  52. package/dist/components/ui/toast.d.ts +2 -2
  53. package/dist/components/ui/toggle-group.d.ts +2 -2
  54. package/dist/components/ui/toggle.d.ts +2 -2
  55. package/dist/index.d.ts +9 -2
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +9 -2
  58. package/dist/lib/price.d.ts +29 -0
  59. package/dist/lib/price.d.ts.map +1 -0
  60. package/dist/lib/price.js +66 -0
  61. package/dist/lib/utils.d.ts +18 -0
  62. package/dist/lib/utils.d.ts.map +1 -1
  63. package/dist/lib/utils.js +44 -1
  64. package/dist/styles.css +201 -727
  65. package/dist/tapcart-mobile-components.umd.js +44 -0
  66. package/package.json +4 -3
  67. package/dist/components/templates/product-card.d.ts +0 -33
  68. package/dist/components/templates/product-card.d.ts.map +0 -1
  69. package/dist/components/templates/product-card.js +0 -42
  70. package/dist/components/templates/product-grid.d.ts +0 -14
  71. package/dist/components/templates/product-grid.d.ts.map +0 -1
  72. package/dist/components/templates/product-grid.js +0 -22
  73. package/dist/components/ui/input.d.ts +0 -17
  74. package/dist/components/ui/input.d.ts.map +0 -1
  75. package/dist/components/ui/input.js +0 -35
  76. package/dist/components/ui/product-grid.d.ts +0 -15
  77. package/dist/components/ui/product-grid.d.ts.map +0 -1
  78. package/dist/components/ui/product-grid.js +0 -22
  79. package/dist/components/ui/select.d.ts +0 -14
  80. package/dist/components/ui/select.d.ts.map +0 -1
  81. package/dist/components/ui/select.js +0 -59
@@ -11,6 +11,8 @@ interface PageData {
11
11
  interface UseInfiniteScrollProps {
12
12
  initialData: PageData;
13
13
  queryVariables: Record<string, any>;
14
+ direction: "vertical" | "horizontal";
15
+ productLimit: number;
14
16
  }
15
17
  interface UseInfiniteScrollReturn {
16
18
  data: PageData[] | undefined;
@@ -26,6 +28,6 @@ interface UseInfiniteScrollReturn {
26
28
  }
27
29
  export declare const formatSearchParamsAsNextQueryVariables: (searchParams: ReadonlyURLSearchParams) => {};
28
30
  declare const constructURL: (apiURL: string) => string;
29
- declare const useInfiniteScroll: ({ initialData, queryVariables: queryVariableProps, }: UseInfiniteScrollProps) => UseInfiniteScrollReturn;
31
+ declare const useInfiniteScroll: ({ initialData, queryVariables: queryVariableProps, direction, productLimit, }: UseInfiniteScrollProps) => UseInfiniteScrollReturn;
30
32
  export { useInfiniteScroll, constructURL };
31
33
  //# sourceMappingURL=use-infinite-scroll.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAmB,MAAM,iBAAiB,CAAA;AAE1E,UAAU,OAAO;IACf,MAAM,EAAE,MAAM,CAAA;CAEf;AAED,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,GAAG,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf;AAOD,UAAU,sBAAsB;IAC9B,WAAW,EAAE,QAAQ,CAAA;IACrB,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;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,eAAO,MAAM,sCAAsC,iBACnC,uBAAuB,OAsBtC,CAAA;AAED,QAAA,MAAM,YAAY,WAAY,MAAM,WAGnC,CAAA;AAED,QAAA,MAAM,iBAAiB,yDAGpB,sBAAsB,KAAG,uBA4F3B,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAmB,MAAM,iBAAiB,CAAA;AAE1E,UAAU,OAAO;IACf,MAAM,EAAE,MAAM,CAAA;CAEf;AAED,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,GAAG,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf;AAOD,UAAU,sBAAsB;IAC9B,WAAW,EAAE,QAAQ,CAAA;IACrB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,SAAS,EAAE,UAAU,GAAG,YAAY,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;CACrB;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;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,eAAO,MAAM,sCAAsC,iBACnC,uBAAuB,OAsBtC,CAAA;AAED,QAAA,MAAM,YAAY,WAAY,MAAM,WAGnC,CAAA;AAED,QAAA,MAAM,iBAAiB,kFAKpB,sBAAsB,KAAG,uBAuG3B,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA"}
@@ -1,5 +1,14 @@
1
1
  "use client";
2
- import { useCallback, useEffect, useMemo } from "react";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ import { useCallback, useEffect, useMemo, useRef } from "react";
3
12
  import useSWRInfinite from "swr/infinite";
4
13
  import { useInView } from "react-intersection-observer";
5
14
  import { useSearchParams } from "next/navigation";
@@ -31,10 +40,14 @@ const constructURL = (apiURL) => {
31
40
  const url = new URL(apiURL);
32
41
  return url.toString();
33
42
  };
34
- const useInfiniteScroll = ({ initialData, queryVariables: queryVariableProps, }) => {
43
+ const useInfiniteScroll = ({ initialData, queryVariables: queryVariableProps, direction = "vertical", productLimit = Infinity, }) => {
35
44
  var _a, _b, _c, _d, _e;
36
45
  const searchParams = useSearchParams();
37
- const { ref, inView } = useInView({ rootMargin: "600px" }); // controls how early the next page loads
46
+ const productCount = useRef(0);
47
+ const { ref, inView } = useInView({
48
+ rootMargin: direction === "vertical" ? "600px" : "0px 420px 0px 0px",
49
+ threshold: 0,
50
+ });
38
51
  const queryVariables = useMemo(() => {
39
52
  const formattedParams = formatSearchParamsAsNextQueryVariables(searchParams);
40
53
  return Object.assign(Object.assign({}, queryVariableProps), { searchParams: formattedParams });
@@ -48,10 +61,16 @@ const useInfiniteScroll = ({ initialData, queryVariables: queryVariableProps, })
48
61
  return null;
49
62
  return Object.assign(Object.assign({}, queryVariables), { cursorBlob: previousPageData.pageData.cursorBlob });
50
63
  };
51
- const fetcher = (body) => fetch(constructURL(initialData.apiURL), {
52
- method: "POST",
53
- body: JSON.stringify(body),
54
- }).then((res) => res.json());
64
+ const fetcher = (body) => __awaiter(void 0, void 0, void 0, function* () {
65
+ var _f, _g;
66
+ const res = yield fetch(constructURL(initialData.apiURL), {
67
+ method: "POST",
68
+ body: JSON.stringify(body),
69
+ });
70
+ const data = yield res.json();
71
+ productCount.current += (_g = (_f = data === null || data === void 0 ? void 0 : data.products) === null || _f === void 0 ? void 0 : _f.length) !== null && _g !== void 0 ? _g : 0;
72
+ return data;
73
+ });
55
74
  const { data, error, size, setSize, isLoading, isValidating, } = useSWRInfinite((pageIndex, previousPageData) => getKey(pageIndex, previousPageData, queryVariables), fetcher, {
56
75
  revalidateFirstPage: false,
57
76
  initialSize: 1,
@@ -66,9 +85,11 @@ const useInfiniteScroll = ({ initialData, queryVariables: queryVariableProps, })
66
85
  const isReachingEnd = isEmpty || isEndPointer;
67
86
  const isRefreshing = isValidating && data && data.length === size;
68
87
  const loadMore = useCallback(() => {
69
- if (!isLoadingMore && !isReachingEnd && !isRefreshing) {
70
- setSize(size + 1);
71
- }
88
+ if (isLoadingMore || isReachingEnd || isRefreshing)
89
+ return;
90
+ if (productCount.current >= productLimit)
91
+ return;
92
+ setSize(size + 1);
72
93
  }, [isLoadingMore, isReachingEnd, isRefreshing, setSize, size]);
73
94
  useEffect(() => {
74
95
  if (inView) {
@@ -83,7 +104,9 @@ const useInfiniteScroll = ({ initialData, queryVariables: queryVariableProps, })
83
104
  isEmpty,
84
105
  isReachingEnd,
85
106
  ref,
86
- products: data ? data === null || data === void 0 ? void 0 : data.flatMap((page) => page === null || page === void 0 ? void 0 : page.products) : [],
107
+ products: data
108
+ ? data === null || data === void 0 ? void 0 : data.flatMap((page) => page === null || page === void 0 ? void 0 : page.products).slice(0, productLimit)
109
+ : [],
87
110
  isLoading,
88
111
  isValidating,
89
112
  };
@@ -0,0 +1,8 @@
1
+ import { Integrations } from "app-studio-types";
2
+ export declare function useNostoRecommendations(integrations: Integrations, baseURL: string, slotId?: null): {
3
+ recommendations: import("app-studio-types").Product[];
4
+ isLoading: boolean;
5
+ error: any;
6
+ isEmpty: boolean;
7
+ };
8
+ //# sourceMappingURL=use-nosto-recommendation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-nosto-recommendation.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-nosto-recommendation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AA+E/C,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,MAAM,EACf,MAAM,OAAO;;;;;EA4Cd"}
@@ -0,0 +1,105 @@
1
+ "use client";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ import { useState, useEffect } from "react";
12
+ import { useProducts } from "./use-products";
13
+ const getRecommendations = (integrations, slotId = null) => __awaiter(void 0, void 0, void 0, function* () {
14
+ if (!Array.isArray(integrations))
15
+ return [];
16
+ const nosto = integrations.find((integration) => integration.name === "nosto");
17
+ const url = "https://api.nosto.com/v1/graphql";
18
+ const headers = new Headers({
19
+ "Content-Type": "application/json",
20
+ Authorization: "Basic " + btoa(":" + (nosto === null || nosto === void 0 ? void 0 : nosto.key)),
21
+ });
22
+ // Fetch sessionId
23
+ const sessionBody = JSON.stringify({
24
+ query: `mutation { newSession }`,
25
+ });
26
+ const sessionResponse = yield fetch(url, {
27
+ method: "POST",
28
+ headers: headers,
29
+ body: sessionBody,
30
+ });
31
+ const sessionData = yield sessionResponse.json();
32
+ const sessionId = sessionData.data.newSession;
33
+ // Main recommendation query
34
+ const body = JSON.stringify({
35
+ query: `
36
+ mutation {
37
+ updateSession(
38
+ by: BY_CID
39
+ id: "${sessionId}"
40
+ params: {
41
+ event: { type: VIEWED_PAGE, target: "home" }
42
+ }
43
+ ) {
44
+ pages {
45
+ forFrontPage(
46
+ params: {
47
+ isPreview: false
48
+ imageVersion: VERSION_8_400_400
49
+ ${slotId ? `slotIds: ["${slotId}"]` : ""}
50
+ }
51
+ ) {
52
+ primary {
53
+ productId
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ `,
60
+ });
61
+ const response = yield fetch(url, {
62
+ method: "POST",
63
+ headers: headers,
64
+ mode: "cors",
65
+ body,
66
+ });
67
+ const json = yield response.json();
68
+ return json;
69
+ });
70
+ export function useNostoRecommendations(integrations, baseURL, slotId = null) {
71
+ var _a, _b, _c, _d;
72
+ const [nostoData, setNostoData] = useState(null);
73
+ const [isLoading, setIsLoading] = useState(true);
74
+ const [error, setError] = useState(null);
75
+ useEffect(() => {
76
+ function fetchNostoData() {
77
+ return __awaiter(this, void 0, void 0, function* () {
78
+ try {
79
+ const result = yield getRecommendations(integrations, slotId);
80
+ setNostoData(result);
81
+ }
82
+ catch (err) {
83
+ console.error("Error fetching recommendations:", err);
84
+ setError(err);
85
+ }
86
+ finally {
87
+ setIsLoading(false);
88
+ }
89
+ });
90
+ }
91
+ fetchNostoData();
92
+ }, [integrations, slotId]);
93
+ const productIds = ((_d = (_c = (_b = (_a = nostoData === null || nostoData === void 0 ? void 0 : nostoData.data) === null || _a === void 0 ? void 0 : _a.updateSession) === null || _b === void 0 ? void 0 : _b.pages) === null || _c === void 0 ? void 0 : _c.forFrontPage) === null || _d === void 0 ? void 0 : _d.flatMap((page) => page.primary).filter((item) => item && item.productId).map((item) => item.productId)) || [];
94
+ const { products, error: productsError, isLoading: productsLoading, } = useProducts({
95
+ productIds,
96
+ baseURL,
97
+ productHandles: [],
98
+ });
99
+ return {
100
+ recommendations: products,
101
+ isLoading: isLoading || productsLoading,
102
+ error: error || productsError,
103
+ isEmpty: products.length === 0,
104
+ };
105
+ }
@@ -8,7 +8,9 @@ type UseProductsProps = {
8
8
  productIds: string[];
9
9
  productHandles: string[];
10
10
  baseURL: URL;
11
- fetcher?: (url: string) => Promise<any>;
11
+ collection?: string;
12
+ queryVariables?: Record<string, any>;
13
+ fetcher?: (url: string, body?: Record<string, any> | null) => Promise<any>;
12
14
  metafields?: MetafieldInput[];
13
15
  };
14
16
  type UseProductsReturn = {
@@ -1 +1 @@
1
- {"version":3,"file":"use-products.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-products.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE1C,KAAK,GAAG,GAAG,MAAM,CAAA;AACjB,KAAK,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AACxD,KAAK,gBAAgB,GAAG;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,OAAO,EAAE,GAAG,CAAA;IACZ,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B,CAAA;AACD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,KAAK,EAAE,GAAG,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,iBAAiB,CA8B7E"}
1
+ {"version":3,"file":"use-products.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-products.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAG1C,KAAK,GAAG,GAAG,MAAM,CAAA;AACjB,KAAK,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AACxD,KAAK,gBAAgB,GAAG;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,OAAO,EAAE,GAAG,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAC1E,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B,CAAA;AACD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,KAAK,EAAE,GAAG,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,iBAAiB,CAyD7E"}
@@ -1,24 +1,39 @@
1
1
  "use client";
2
2
  import useSWR from "swr";
3
+ import { getProductGidsFromIds } from "../../lib/utils";
3
4
  export function useProducts(props) {
4
5
  let url = null;
6
+ let body = null;
5
7
  if (props) {
6
- const { baseURL, productIds, productHandles, metafields } = props;
8
+ const { baseURL, productIds, productHandles, metafields, collection, queryVariables, } = props;
7
9
  let queryParams = new URLSearchParams();
8
10
  if ((productIds === null || productIds === void 0 ? void 0 : productIds.length) > 0) {
9
- queryParams.set("ids", productIds.join(","));
11
+ queryParams.set("ids", getProductGidsFromIds(productIds).join(","));
10
12
  }
11
- else if ((productHandles === null || productHandles === void 0 ? void 0 : productHandles.length) > 0) {
13
+ if ((productHandles === null || productHandles === void 0 ? void 0 : productHandles.length) > 0) {
12
14
  queryParams.set("handles", productHandles.join(","));
13
15
  }
14
16
  if (metafields && metafields.length > 0) {
15
17
  const metafieldStrings = metafields.map((m) => `${m.namespace}.${m.key}`);
16
18
  queryParams.set("metafields", metafieldStrings.join(","));
17
19
  }
18
- url = `${baseURL}/products/by-ids?${queryParams.toString()}`;
20
+ if (collection) {
21
+ url = `${baseURL}/products/by-page?${queryParams.toString()}`;
22
+ body = queryVariables || {};
23
+ }
24
+ if ((productIds === null || productIds === void 0 ? void 0 : productIds.length) || (productHandles === null || productHandles === void 0 ? void 0 : productHandles.length)) {
25
+ url = `${baseURL}/products/by-ids?${queryParams.toString()}`;
26
+ }
19
27
  }
20
- const fetcher = (props === null || props === void 0 ? void 0 : props.fetcher) || ((url) => fetch(url).then((res) => res.json()));
21
- const { data, error } = useSWR(url, fetcher);
28
+ const defaultFetcher = (url, body) => fetch(url, {
29
+ method: body ? "POST" : "GET",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ },
33
+ body: body ? JSON.stringify(body) : undefined,
34
+ }).then((res) => res.json());
35
+ const fetcher = (props === null || props === void 0 ? void 0 : props.fetcher) || defaultFetcher;
36
+ const { data, error } = useSWR(url ? [url, body] : null, ([url, body]) => fetcher(url, body));
22
37
  return {
23
38
  products: data || [],
24
39
  error,
@@ -0,0 +1,27 @@
1
+ import { ReviewSummaryData, ReviewMetaData, ReviewSearchData } from "app-studio-types";
2
+ type UseReviewsProps = {
3
+ baseURL: string;
4
+ productId: string;
5
+ provider: string;
6
+ fetcher?: (url: string) => Promise<any>;
7
+ dataType: "summary" | "metadata" | "search";
8
+ searchText: string;
9
+ ratings: [number];
10
+ topics: [string];
11
+ sortBy: "date" | "votes_up" | "votes_down" | "time" | "rating" | "reviewer_type";
12
+ ascending: boolean;
13
+ perPage: number;
14
+ page: number;
15
+ };
16
+ type UseReviewsReturn = {
17
+ data: ReviewSummaryData | ReviewMetaData | ReviewSearchData;
18
+ error: any;
19
+ isLoading: boolean;
20
+ };
21
+ export declare function useReviews(props: UseReviewsProps | null): UseReviewsReturn;
22
+ type UseReviewsInfiniteReturn = UseReviewsReturn & {
23
+ ref: (node?: Element | null) => void;
24
+ };
25
+ export declare function useReviewsInfinite(props: UseReviewsProps | null): UseReviewsInfiniteReturn;
26
+ export {};
27
+ //# sourceMappingURL=use-reviews.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-reviews.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-reviews.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGtF,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,QAAQ,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IAClB,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,CAAC;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,iBAAiB,GAAG,cAAc,GAAG,gBAAgB,CAAA;IAC3D,KAAK,EAAE,GAAG,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,gBAAgB,CAwD1E;AAED,KAAK,wBAAwB,GAAG,gBAAgB,GAAG;IACjD,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;CACtC,CAAA;AAGD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,wBAAwB,CA8F1F"}
@@ -0,0 +1,130 @@
1
+ "use client";
2
+ import { useCallback, useEffect } from "react";
3
+ import useSWR from "swr";
4
+ import useSWRInfinite from "swr/infinite";
5
+ import { useInView } from 'react-intersection-observer';
6
+ export function useReviews(props) {
7
+ let url = null;
8
+ if (props) {
9
+ const { baseURL, productId, provider, dataType, searchText, ratings, topics, sortBy, ascending, perPage, page } = props;
10
+ let queryParams = new URLSearchParams();
11
+ if (productId.length > 0) {
12
+ queryParams.set("id", productId);
13
+ }
14
+ if (provider.length > 0) {
15
+ queryParams.set("provider", provider);
16
+ }
17
+ queryParams.set("dataType", dataType);
18
+ if (searchText) {
19
+ queryParams.set("searchText", searchText);
20
+ }
21
+ if (ratings && ratings.length > 0) {
22
+ queryParams.set("ratings", ratings.join(","));
23
+ }
24
+ if (topics && topics.length > 0) {
25
+ queryParams.set("topics", topics.join(","));
26
+ }
27
+ if (sortBy) {
28
+ queryParams.set("sortBy", sortBy);
29
+ }
30
+ if (ascending !== undefined) {
31
+ queryParams.set("ascending", ascending.toString());
32
+ }
33
+ if (perPage) {
34
+ queryParams.set("perPage", String(perPage));
35
+ }
36
+ if (page) {
37
+ queryParams.set("page", String(page));
38
+ }
39
+ if (dataType === null || productId === null || productId.length === 0) {
40
+ url = null;
41
+ }
42
+ else {
43
+ url = `${baseURL}/reviews/by-id?${queryParams.toString()}`;
44
+ }
45
+ }
46
+ const fetcher = (props === null || props === void 0 ? void 0 : props.fetcher) || ((url) => fetch(url).then((res) => res.json()));
47
+ const { data, error } = useSWR(url, fetcher);
48
+ return {
49
+ data: data || {},
50
+ error,
51
+ isLoading: !data && !error,
52
+ };
53
+ }
54
+ export function useReviewsInfinite(props) {
55
+ var _a, _b;
56
+ let url = null;
57
+ const { ref, inView } = useInView({ rootMargin: "800px" });
58
+ let baseURL = "";
59
+ let queryParams = new URLSearchParams();
60
+ if (props) {
61
+ const { productId, provider, dataType, searchText, ratings, topics, sortBy, ascending, perPage } = props; // Destructure all relevant props
62
+ baseURL = props.baseURL;
63
+ if (productId.length > 0) {
64
+ queryParams.set("id", productId);
65
+ }
66
+ if (provider.length > 0) {
67
+ queryParams.set("provider", provider);
68
+ }
69
+ queryParams.set("dataType", dataType);
70
+ if (searchText) {
71
+ queryParams.set("searchText", searchText);
72
+ }
73
+ if (ratings && ratings.length > 0) {
74
+ queryParams.set("ratings", ratings.join(","));
75
+ }
76
+ if (topics && topics.length > 0) {
77
+ queryParams.set("topics", topics.join(","));
78
+ }
79
+ if (sortBy) {
80
+ queryParams.set("sortBy", sortBy);
81
+ }
82
+ if (ascending !== undefined) {
83
+ queryParams.set("ascending", ascending.toString());
84
+ }
85
+ if (perPage) {
86
+ queryParams.set("perPage", String(perPage));
87
+ }
88
+ if (dataType === null || productId === null || productId.length === 0) {
89
+ url = null;
90
+ }
91
+ else {
92
+ url = `${baseURL}/reviews/by-id?${queryParams.toString()}`;
93
+ }
94
+ }
95
+ const getKey = (pageIndex, previousPageData) => {
96
+ const dataType = queryParams.get("dataType") === "null" ? null : queryParams.get("dataType");
97
+ if (dataType == null) {
98
+ return null;
99
+ }
100
+ return `${baseURL}/reviews/by-id?${queryParams.toString()}&page=${pageIndex + 1}`;
101
+ };
102
+ const fetcher = (props === null || props === void 0 ? void 0 : props.fetcher) || ((url) => fetch(url).then((res) => res.json()));
103
+ const { data: dataInfinite, error: errorInfinite, size, setSize, isLoading, isValidating, } = useSWRInfinite(getKey, fetcher);
104
+ let mergedReviews = dataInfinite
105
+ ? dataInfinite
106
+ .filter(page => page && page.reviews)
107
+ .flatMap(page => (page.reviews))
108
+ : [];
109
+ let searchResponse = {
110
+ pagination: (dataInfinite === null || dataInfinite === void 0 ? void 0 : dataInfinite.length) ? dataInfinite[0].pagination : null,
111
+ reviews: mergedReviews
112
+ };
113
+ const isAllReviewsLoaded = (mergedReviews === null || mergedReviews === void 0 ? void 0 : mergedReviews.length) === ((_b = (_a = dataInfinite === null || dataInfinite === void 0 ? void 0 : dataInfinite[0]) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.total);
114
+ const loadMore = useCallback(() => {
115
+ if (!isLoading && !isValidating && !isAllReviewsLoaded) {
116
+ setSize(size + 1);
117
+ }
118
+ }, [isLoading, isValidating, setSize, size, isAllReviewsLoaded]);
119
+ useEffect(() => {
120
+ if (inView) {
121
+ loadMore();
122
+ }
123
+ }, [inView, loadMore]);
124
+ return {
125
+ data: searchResponse || {},
126
+ error: errorInfinite,
127
+ isLoading: isValidating,
128
+ ref
129
+ };
130
+ }
@@ -0,0 +1,78 @@
1
+ interface ProductCardBadgeConfig {
2
+ variants: {
3
+ horizontalPosition: {
4
+ start: string;
5
+ end: string;
6
+ center: string;
7
+ };
8
+ verticalPosition: {
9
+ top: string;
10
+ bottom: string;
11
+ below: string;
12
+ };
13
+ imageSwipeEnabled: {
14
+ true: string;
15
+ false: string;
16
+ };
17
+ };
18
+ compoundVariants: Array<{
19
+ verticalPosition: "bottom";
20
+ imageSwipeEnabled: true;
21
+ class: string;
22
+ }>;
23
+ }
24
+ export declare function getProductCardBadgeVariants(config?: Partial<ProductCardBadgeConfig>): (props?: ({
25
+ horizontalPosition?: "center" | "start" | "end" | null | undefined;
26
+ verticalPosition?: "top" | "bottom" | "below" | null | undefined;
27
+ imageSwipeEnabled?: boolean | null | undefined;
28
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
29
+ interface ProductCardFavoriteConfig {
30
+ variants: {
31
+ iconPosition: {
32
+ "top-left": string;
33
+ "top-right": string;
34
+ "bottom-left": string;
35
+ "bottom-right": string;
36
+ "below-image-on-right": string;
37
+ };
38
+ badgeHorizontalPosition: {
39
+ start: string;
40
+ end: string;
41
+ center: string;
42
+ };
43
+ badgeVerticalPosition: {
44
+ top: string;
45
+ bottom: string;
46
+ below: string;
47
+ };
48
+ isSoldOut: {
49
+ true: string;
50
+ false: string;
51
+ };
52
+ showSoldOutBadge: {
53
+ true: string;
54
+ false: string;
55
+ };
56
+ imageSwipeEnabled: {
57
+ true: string;
58
+ false: string;
59
+ };
60
+ };
61
+ compoundVariants: Array<{
62
+ [key: string]: any;
63
+ class: string;
64
+ }>;
65
+ defaultVariants: {
66
+ iconPosition: "below-image-on-right";
67
+ };
68
+ }
69
+ export declare function getProductCardFavoriteVariants(config?: Partial<ProductCardFavoriteConfig>): (props?: ({
70
+ iconPosition?: "below-image-on-right" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | null | undefined;
71
+ badgeHorizontalPosition?: "center" | "start" | "end" | null | undefined;
72
+ badgeVerticalPosition?: "top" | "bottom" | "below" | null | undefined;
73
+ isSoldOut?: boolean | null | undefined;
74
+ showSoldOutBadge?: boolean | null | undefined;
75
+ imageSwipeEnabled?: boolean | null | undefined;
76
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
77
+ export {};
78
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../components/templates/ProductCard/utils.ts"],"names":[],"mappings":"AAEA,UAAU,sBAAsB;IAC9B,QAAQ,EAAE;QACR,kBAAkB,EAAE;YAClB,KAAK,EAAE,MAAM,CAAA;YACb,GAAG,EAAE,MAAM,CAAA;YACX,MAAM,EAAE,MAAM,CAAA;SACf,CAAA;QACD,gBAAgB,EAAE;YAChB,GAAG,EAAE,MAAM,CAAA;YACX,MAAM,EAAE,MAAM,CAAA;YACd,KAAK,EAAE,MAAM,CAAA;SACd,CAAA;QACD,iBAAiB,EAAE;YACjB,IAAI,EAAE,MAAM,CAAA;YACZ,KAAK,EAAE,MAAM,CAAA;SACd,CAAA;KACF,CAAA;IACD,gBAAgB,EAAE,KAAK,CAAC;QACtB,gBAAgB,EAAE,QAAQ,CAAA;QAC1B,iBAAiB,EAAE,IAAI,CAAA;QACvB,KAAK,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;CACH;AAED,wBAAgB,2BAA2B,CACzC,MAAM,GAAE,OAAO,CAAC,sBAAsB,CAAM;;;;oFAgC7C;AAED,UAAU,yBAAyB;IACjC,QAAQ,EAAE;QACR,YAAY,EAAE;YACZ,UAAU,EAAE,MAAM,CAAA;YAClB,WAAW,EAAE,MAAM,CAAA;YACnB,aAAa,EAAE,MAAM,CAAA;YACrB,cAAc,EAAE,MAAM,CAAA;YACtB,sBAAsB,EAAE,MAAM,CAAA;SAC/B,CAAA;QACD,uBAAuB,EAAE;YACvB,KAAK,EAAE,MAAM,CAAA;YACb,GAAG,EAAE,MAAM,CAAA;YACX,MAAM,EAAE,MAAM,CAAA;SACf,CAAA;QACD,qBAAqB,EAAE;YACrB,GAAG,EAAE,MAAM,CAAA;YACX,MAAM,EAAE,MAAM,CAAA;YACd,KAAK,EAAE,MAAM,CAAA;SACd,CAAA;QACD,SAAS,EAAE;YACT,IAAI,EAAE,MAAM,CAAA;YACZ,KAAK,EAAE,MAAM,CAAA;SACd,CAAA;QACD,gBAAgB,EAAE;YAChB,IAAI,EAAE,MAAM,CAAA;YACZ,KAAK,EAAE,MAAM,CAAA;SACd,CAAA;QACD,iBAAiB,EAAE;YACjB,IAAI,EAAE,MAAM,CAAA;YACZ,KAAK,EAAE,MAAM,CAAA;SACd,CAAA;KACF,CAAA;IACD,gBAAgB,EAAE,KAAK,CAAC;QACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;IACF,eAAe,EAAE;QACf,YAAY,EAAE,sBAAsB,CAAA;KACrC,CAAA;CACF;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,GAAE,OAAO,CAAC,yBAAyB,CAAM;;;;;;;oFAuGhD"}
@@ -0,0 +1,128 @@
1
+ import { cva } from "../../../lib/utils";
2
+ export function getProductCardBadgeVariants(config = {}) {
3
+ const defaultConfig = {
4
+ variants: {
5
+ horizontalPosition: {
6
+ start: "left-0",
7
+ end: "right-0",
8
+ center: "",
9
+ },
10
+ verticalPosition: {
11
+ top: "top-0 mt-2",
12
+ bottom: "bottom-0 mb-2",
13
+ below: "",
14
+ },
15
+ imageSwipeEnabled: {
16
+ true: "",
17
+ false: "",
18
+ },
19
+ },
20
+ compoundVariants: [
21
+ {
22
+ verticalPosition: "bottom",
23
+ imageSwipeEnabled: true,
24
+ class: "bottom-[18px]",
25
+ },
26
+ ],
27
+ };
28
+ return cva("absolute truncate pointer-events-none", Object.assign(Object.assign({}, defaultConfig), config));
29
+ }
30
+ export function getProductCardFavoriteVariants(config = {}) {
31
+ const defaultConfig = {
32
+ variants: {
33
+ iconPosition: {
34
+ "top-left": "top-0 left-2 mt-2",
35
+ "top-right": "top-0 right-2 mt-2",
36
+ "bottom-left": "bottom-0 left-2 mb-2",
37
+ "bottom-right": "bottom-0 right-2 mb-2",
38
+ "below-image-on-right": "",
39
+ },
40
+ badgeHorizontalPosition: {
41
+ start: "",
42
+ end: "",
43
+ center: "",
44
+ },
45
+ badgeVerticalPosition: {
46
+ top: "",
47
+ bottom: "",
48
+ below: "",
49
+ },
50
+ isSoldOut: {
51
+ true: "",
52
+ false: "",
53
+ },
54
+ showSoldOutBadge: {
55
+ true: "",
56
+ false: "",
57
+ },
58
+ imageSwipeEnabled: {
59
+ true: "",
60
+ false: "",
61
+ },
62
+ },
63
+ compoundVariants: [
64
+ {
65
+ iconPosition: "top-left",
66
+ badgeHorizontalPosition: ["start", "center"],
67
+ badgeVerticalPosition: "top",
68
+ showSoldOutBadge: false,
69
+ class: "top-10",
70
+ },
71
+ {
72
+ iconPosition: "top-right",
73
+ badgeHorizontalPosition: ["end", "center"],
74
+ badgeVerticalPosition: "top",
75
+ class: "top-10",
76
+ },
77
+ {
78
+ iconPosition: "bottom-left",
79
+ badgeHorizontalPosition: ["start", "center"],
80
+ badgeVerticalPosition: "bottom",
81
+ class: "bottom-10",
82
+ },
83
+ {
84
+ iconPosition: "bottom-right",
85
+ badgeHorizontalPosition: ["end", "center"],
86
+ badgeVerticalPosition: "bottom",
87
+ class: "bottom-10",
88
+ },
89
+ {
90
+ iconPosition: "bottom-left",
91
+ showSoldOutBadge: true,
92
+ class: "bottom-10",
93
+ },
94
+ {
95
+ iconPosition: ["bottom-left", "bottom-right"],
96
+ imageSwipeEnabled: true,
97
+ class: "bottom-[18px]",
98
+ },
99
+ {
100
+ iconPosition: "bottom-left",
101
+ badgeHorizontalPosition: ["start", "center"],
102
+ badgeVerticalPosition: "bottom",
103
+ isSoldOut: false,
104
+ showSoldOutBadge: false,
105
+ imageSwipeEnabled: true,
106
+ class: "bottom-[58px]",
107
+ },
108
+ {
109
+ iconPosition: "bottom-right",
110
+ badgeHorizontalPosition: ["end", "center"],
111
+ badgeVerticalPosition: "bottom",
112
+ showSoldOutBadge: false,
113
+ imageSwipeEnabled: true,
114
+ class: "bottom-[58px]",
115
+ },
116
+ {
117
+ iconPosition: "bottom-left",
118
+ showSoldOutBadge: true,
119
+ imageSwipeEnabled: true,
120
+ class: "bottom-[58px]",
121
+ },
122
+ ],
123
+ defaultVariants: {
124
+ iconPosition: "below-image-on-right",
125
+ },
126
+ };
127
+ return cva("absolute ", Object.assign(Object.assign({}, defaultConfig), config));
128
+ }