@gfed-medusa/sf-lib-products 1.9.5 → 1.10.0
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/behavior-tracker/index.d.ts.map +1 -1
- package/dist/components/behavior-tracker/index.js +38 -4
- package/dist/components/behavior-tracker/index.js.map +1 -1
- package/dist/components/browse-product-preview/index.d.ts +0 -2
- package/dist/components/browse-product-preview/index.d.ts.map +1 -1
- package/dist/components/browse-product-preview/index.js +26 -3
- package/dist/components/browse-product-preview/index.js.map +1 -1
- package/dist/components/image-gallery/index.d.ts +3 -1
- package/dist/components/image-gallery/index.d.ts.map +1 -1
- package/dist/components/image-gallery/index.js +12 -2
- package/dist/components/image-gallery/index.js.map +1 -1
- package/dist/components/pagination/index.d.ts +2 -2
- package/dist/components/product-actions/index.d.ts +2 -2
- package/dist/components/product-actions/index.js +1 -1
- package/dist/components/product-onboarding-cta/index.d.ts +2 -2
- package/dist/components/product-price/index.d.ts +2 -2
- package/dist/components/product-tabs/index.d.ts.map +1 -1
- package/dist/components/product-tabs/index.js +29 -7
- package/dist/components/product-tabs/index.js.map +1 -1
- package/dist/components/refinement-list/index.d.ts.map +1 -1
- package/dist/components/refinement-list/index.js +7 -1
- package/dist/components/refinement-list/index.js.map +1 -1
- package/dist/components/refinement-list/sort-products/index.d.ts +2 -2
- package/dist/components/refinement-list/sort-products/index.d.ts.map +1 -1
- package/dist/components/refinement-list/sort-products/index.js +3 -0
- package/dist/components/refinement-list/sort-products/index.js.map +1 -1
- package/dist/components/skeleton-product-grid/index.d.ts +2 -2
- package/dist/components/skeleton-product-preview/index.d.ts +2 -2
- package/dist/components/skeleton-product-preview/index.d.ts.map +1 -1
- package/dist/components/skeleton-related-products/index.d.ts +2 -2
- package/dist/components/skeleton-related-products/index.d.ts.map +1 -1
- package/dist/lib/data/cart.d.ts +1 -1
- package/dist/lib/data/cart.d.ts.map +1 -1
- package/dist/lib/data/cart.js +15 -5
- package/dist/lib/data/cart.js.map +1 -1
- package/dist/lib/gql/fragments/cart.d.ts +9 -9
- package/dist/lib/gql/fragments/product.d.ts +16 -16
- package/dist/lib/gql/fragments/product.d.ts.map +1 -1
- package/dist/lib/gql/fragments/product.js +1 -0
- package/dist/lib/gql/fragments/product.js.map +1 -1
- package/dist/lib/gql/mutations/cart.d.ts +10 -10
- package/dist/lib/gql/mutations/cart.d.ts.map +1 -1
- package/dist/lib/gql/queries/cart.d.ts +2 -2
- package/dist/lib/gql/queries/cart.d.ts.map +1 -1
- package/dist/lib/gql/queries/cart.js +1 -1
- package/dist/lib/gql/queries/cart.js.map +1 -1
- package/dist/lib/gql/queries/product.d.ts +13 -13
- package/dist/lib/gql/queries/product.d.ts.map +1 -1
- package/dist/templates/paginated-products/client.d.ts +2 -2
- package/dist/templates/paginated-products/client.js +0 -1
- package/dist/templates/paginated-products/client.js.map +1 -1
- package/dist/templates/paginated-products/index.d.ts +2 -2
- package/dist/templates/product-actions-wrapper/index.d.ts +2 -2
- package/dist/templates/product-info/index.d.ts +2 -2
- package/dist/templates/product-template/index.js +5 -2
- package/dist/templates/product-template/index.js.map +1 -1
- package/dist/templates/store-template/index.d.ts +2 -2
- package/dist/types/graphql.d.ts +160 -3
- package/dist/types/graphql.d.ts.map +1 -1
- package/dist/types/graphql.js +56 -2
- package/dist/types/graphql.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/behavior-tracker/index.tsx"],"sourcesContent":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/behavior-tracker/index.tsx"],"sourcesContent":[],"mappings":";;;UAuHiB,oBAAA;WACN;AADX;AAIgB,iBAAA,eAAA,CAAkB;EAAA;AAA+B,CAApB,EAAA,oBAAoB,CAAA,EAAA,IAAA"}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useEffect, useRef } from "react";
|
|
4
|
+
import { sendClientSignal } from "@gfed-medusa/sf-lib-common/lib/personalization/client-signal";
|
|
5
|
+
import { SignalType } from "@gfed-medusa/sf-lib-common/types/graphql";
|
|
4
6
|
import { PERSONALIZATION_CONFIG, getSegmentIdFromCollection } from "@gfed-medusa/sf-lib-common/lib/personalization/config";
|
|
5
7
|
import { getSegmentCookie, setSegmentCookie } from "@gfed-medusa/sf-lib-common/lib/personalization/behavior-tracker";
|
|
6
8
|
import { useStorefrontContext } from "@gfed-medusa/sf-lib-common/lib/data/context";
|
|
9
|
+
import { useTimeOnPage } from "@gfed-medusa/sf-lib-common/lib/hooks/use-time-on-page";
|
|
7
10
|
|
|
8
11
|
//#region src/components/behavior-tracker/index.tsx
|
|
9
12
|
const PDP_HESITATION_MS = PERSONALIZATION_CONFIG.pdpHesitationMs;
|
|
10
13
|
const HIGH_SCROLL_THRESHOLD = PERSONALIZATION_CONFIG.highScrollThreshold;
|
|
11
|
-
const
|
|
14
|
+
const PRICE_THRESHOLD = PERSONALIZATION_CONFIG.priceThreshold;
|
|
12
15
|
function getScrollPercentage() {
|
|
13
16
|
const scrollTop = window.scrollY;
|
|
14
17
|
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
@@ -72,6 +75,9 @@ function BehaviorTracker({ product }) {
|
|
|
72
75
|
const scrollHandlerRef = useRef(null);
|
|
73
76
|
const scrollTrackedRef = useRef(false);
|
|
74
77
|
useRef(false);
|
|
78
|
+
const firedDepthRef = useRef(/* @__PURE__ */ new Set());
|
|
79
|
+
const exitIntentFiredRef = useRef(false);
|
|
80
|
+
useTimeOnPage("pdp", Boolean(product?.id));
|
|
75
81
|
useEffect(() => {
|
|
76
82
|
if (!product?.id) return;
|
|
77
83
|
const collectionHandle = product.collection?.handle;
|
|
@@ -81,16 +87,34 @@ function BehaviorTracker({ product }) {
|
|
|
81
87
|
trackRepeatedCategoryView(segment);
|
|
82
88
|
}
|
|
83
89
|
const productPrice = getCheapestVariantPrice(product);
|
|
90
|
+
sendClientSignal(SignalType.ProductView, {
|
|
91
|
+
productId: product.id,
|
|
92
|
+
productHandle: product.handle,
|
|
93
|
+
category: collectionHandle,
|
|
94
|
+
price: productPrice
|
|
95
|
+
});
|
|
84
96
|
const hasCart = Boolean(cartId);
|
|
85
|
-
if (productPrice && productPrice >=
|
|
97
|
+
if (productPrice && productPrice >= PRICE_THRESHOLD && !hasCart) hesitationTimeoutRef.current = setTimeout(() => {
|
|
86
98
|
emitSignal("pdp-hesitation", {
|
|
87
99
|
productId: product.id,
|
|
88
100
|
price: productPrice
|
|
89
101
|
});
|
|
90
102
|
}, PDP_HESITATION_MS);
|
|
91
103
|
const handleScroll = throttle(() => {
|
|
92
|
-
|
|
93
|
-
|
|
104
|
+
const scrollPct = Math.round(getScrollPercentage() * 100);
|
|
105
|
+
for (const threshold of [
|
|
106
|
+
25,
|
|
107
|
+
50,
|
|
108
|
+
75,
|
|
109
|
+
90
|
|
110
|
+
]) if (scrollPct >= threshold && !firedDepthRef.current.has(threshold)) {
|
|
111
|
+
firedDepthRef.current.add(threshold);
|
|
112
|
+
sendClientSignal(SignalType.ScrollDepth, {
|
|
113
|
+
depth: threshold,
|
|
114
|
+
page: window.location.pathname
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (getScrollPercentage() >= HIGH_SCROLL_THRESHOLD && !hasCart && !scrollTrackedRef.current) {
|
|
94
118
|
scrollTrackedRef.current = true;
|
|
95
119
|
emitSignal("high-scroll-no-action", {
|
|
96
120
|
productId: product.id,
|
|
@@ -112,6 +136,16 @@ function BehaviorTracker({ product }) {
|
|
|
112
136
|
scrollTrackedRef.current = false;
|
|
113
137
|
};
|
|
114
138
|
}, [product, cartId]);
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const handleMouseLeave = (e) => {
|
|
141
|
+
if (e.clientY <= 0 && !exitIntentFiredRef.current) {
|
|
142
|
+
exitIntentFiredRef.current = true;
|
|
143
|
+
sendClientSignal(SignalType.ExitIntent, { page: window.location.pathname });
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
document.documentElement.addEventListener("mouseleave", handleMouseLeave);
|
|
147
|
+
return () => document.documentElement.removeEventListener("mouseleave", handleMouseLeave);
|
|
148
|
+
}, []);
|
|
115
149
|
return null;
|
|
116
150
|
}
|
|
117
151
|
var behavior_tracker_default = BehaviorTracker;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["cheapest: number | null"],"sources":["../../../src/components/behavior-tracker/index.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\n\nimport {\n PERSONALIZATION_CONFIG,\n getSegmentIdFromCollection,\n} from '@gfed-medusa/sf-lib-common/lib/personalization/config';\nimport {\n getSegmentCookie,\n setSegmentCookie,\n} from '@gfed-medusa/sf-lib-common/lib/personalization/behavior-tracker';\nimport { useStorefrontContext } from '@gfed-medusa/sf-lib-common/lib/data/context';\nimport { Product } from '@/types/graphql';\n\nconst PDP_HESITATION_MS = PERSONALIZATION_CONFIG.pdpHesitationMs;\nconst HIGH_SCROLL_THRESHOLD = PERSONALIZATION_CONFIG.highScrollThreshold;\nconst
|
|
1
|
+
{"version":3,"file":"index.js","names":["cheapest: number | null"],"sources":["../../../src/components/behavior-tracker/index.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\n\nimport { sendClientSignal } from '@gfed-medusa/sf-lib-common/lib/personalization/client-signal';\nimport { SignalType } from '@gfed-medusa/sf-lib-common/types/graphql';\n\nimport {\n PERSONALIZATION_CONFIG,\n getSegmentIdFromCollection,\n} from '@gfed-medusa/sf-lib-common/lib/personalization/config';\nimport {\n getSegmentCookie,\n setSegmentCookie,\n} from '@gfed-medusa/sf-lib-common/lib/personalization/behavior-tracker';\nimport { useStorefrontContext } from '@gfed-medusa/sf-lib-common/lib/data/context';\nimport { useTimeOnPage } from '@gfed-medusa/sf-lib-common/lib/hooks/use-time-on-page';\nimport { Product } from '@/types/graphql';\n\nconst PDP_HESITATION_MS = PERSONALIZATION_CONFIG.pdpHesitationMs;\nconst HIGH_SCROLL_THRESHOLD = PERSONALIZATION_CONFIG.highScrollThreshold;\nconst PRICE_THRESHOLD = PERSONALIZATION_CONFIG.priceThreshold;\n\nfunction getScrollPercentage(): number {\n const scrollTop = window.scrollY;\n const docHeight =\n document.documentElement.scrollHeight - window.innerHeight;\n return docHeight > 0 ? scrollTop / docHeight : 0;\n}\n\nfunction getCheapestVariantPrice(product: Product): number | null {\n const variants = product.variants;\n if (!variants || variants.length === 0) return null;\n\n let cheapest: number | null = null;\n\n for (const variant of variants) {\n const priceObj = variant.price;\n if (priceObj && typeof priceObj.amount === 'number') {\n if (cheapest === null || priceObj.amount < cheapest) {\n cheapest = priceObj.amount;\n }\n }\n }\n\n return cheapest;\n}\n\nfunction throttle<T extends (...args: unknown[]) => void>(\n fn: T,\n limit: number\n): T {\n let lastCall = 0;\n return ((...args: unknown[]) => {\n const now = Date.now();\n if (now - lastCall >= limit) {\n lastCall = now;\n fn(...args);\n }\n }) as T;\n}\n\nfunction emitSignal(type: string, payload?: unknown) {\n const data = getSegmentCookie();\n\n if (!data.signals || typeof data.signals !== 'object') {\n data.signals = {};\n }\n\n (data.signals as Record<string, unknown>)[type] = payload ?? true;\n\n setSegmentCookie(data);\n}\n\nconst REPEAT_CATEGORY_THRESHOLD = 3;\n\nfunction trackRepeatedCategoryView(segment: string) {\n try {\n const data = getSegmentCookie();\n\n if (!data.signals || typeof data.signals !== 'object') {\n data.signals = {};\n }\n\n const categoryCounts = (data.signals as Record<string, unknown>)['repeated-category-view'] as Record<string, number> ?? {};\n const currentCount = categoryCounts[segment] ?? 0;\n const newCount = currentCount + 1;\n\n categoryCounts[segment] = newCount;\n (data.signals as Record<string, unknown>)['repeated-category-view'] = categoryCounts;\n\n if (newCount >= REPEAT_CATEGORY_THRESHOLD) {\n emitSignal('repeated-category-view', { segment, count: newCount });\n }\n\n setSegmentCookie(data);\n } catch {\n // Ignore\n }\n}\n\nfunction addHistoryToCookie(segment: string): void {\n try {\n const data = getSegmentCookie();\n\n if (!data.history || !Array.isArray(data.history)) {\n data.history = [];\n }\n\n const history = [...(data.history as string[]), segment].slice(\n -PERSONALIZATION_CONFIG.historyMaxLength\n );\n data.history = history;\n\n setSegmentCookie(data);\n } catch {\n }\n}\n\nexport interface BehaviorTrackerProps {\n product: Product;\n}\n\nexport function BehaviorTracker({ product }: BehaviorTrackerProps) {\n const { cartId } = useStorefrontContext();\n const hesitationTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const scrollHandlerRef = useRef<(() => void) | null>(null);\n const scrollTrackedRef = useRef(false);\n const historyTrackedRef = useRef(false);\n const firedDepthRef = useRef<Set<number>>(new Set());\n const exitIntentFiredRef = useRef(false);\n\n useTimeOnPage('pdp', Boolean(product?.id));\n\n useEffect(() => {\n if (!product?.id) return;\n\n const collectionHandle = product.collection?.handle;\n const segment = getSegmentIdFromCollection(collectionHandle);\n\n if (segment) {\n addHistoryToCookie(segment);\n trackRepeatedCategoryView(segment);\n }\n\n const productPrice = getCheapestVariantPrice(product);\n void sendClientSignal(SignalType.ProductView, {\n productId: product.id,\n productHandle: product.handle,\n category: collectionHandle,\n price: productPrice,\n });\n\n const hasCart = Boolean(cartId);\n\n if (productPrice && productPrice >= PRICE_THRESHOLD && !hasCart) {\n hesitationTimeoutRef.current = setTimeout(() => {\n emitSignal('pdp-hesitation', {\n productId: product.id,\n price: productPrice,\n });\n }, PDP_HESITATION_MS);\n }\n\n const handleScroll = throttle(() => {\n // SCROLL_DEPTH analytics signal — always runs independently\n const scrollPct = Math.round(getScrollPercentage() * 100);\n const depthThresholds = [25, 50, 75, 90];\n for (const threshold of depthThresholds) {\n if (scrollPct >= threshold && !firedDepthRef.current.has(threshold)) {\n firedDepthRef.current.add(threshold);\n void sendClientSignal(SignalType.ScrollDepth, {\n depth: threshold,\n page: window.location.pathname,\n });\n }\n }\n\n if (getScrollPercentage() >= HIGH_SCROLL_THRESHOLD && !hasCart && !scrollTrackedRef.current) {\n scrollTrackedRef.current = true;\n emitSignal('high-scroll-no-action', {\n productId: product.id,\n scrollDepth: HIGH_SCROLL_THRESHOLD,\n });\n }\n }, 500);\n\n scrollHandlerRef.current = handleScroll;\n window.addEventListener('scroll', handleScroll, { passive: true });\n\n return () => {\n if (hesitationTimeoutRef.current !== null) {\n clearTimeout(hesitationTimeoutRef.current);\n hesitationTimeoutRef.current = null;\n }\n if (scrollHandlerRef.current !== null) {\n window.removeEventListener('scroll', scrollHandlerRef.current);\n scrollHandlerRef.current = null;\n }\n scrollTrackedRef.current = false;\n };\n }, [product, cartId]);\n\n useEffect(() => {\n const handleMouseLeave = (e: MouseEvent) => {\n if (e.clientY <= 0 && !exitIntentFiredRef.current) {\n exitIntentFiredRef.current = true;\n void sendClientSignal(SignalType.ExitIntent, {\n page: window.location.pathname,\n });\n }\n };\n document.documentElement.addEventListener('mouseleave', handleMouseLeave);\n return () => document.documentElement.removeEventListener('mouseleave', handleMouseLeave);\n }, []);\n\n return null;\n}\n\nexport default BehaviorTracker;\n"],"mappings":"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"}
|
|
@@ -5,13 +5,11 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
|
5
5
|
type BrowseProductPreviewProps = {
|
|
6
6
|
product: BrowseProductHitFragment;
|
|
7
7
|
isFeatured?: boolean;
|
|
8
|
-
imagePriority?: boolean;
|
|
9
8
|
imageFetchPriority?: 'auto' | 'high' | 'low';
|
|
10
9
|
};
|
|
11
10
|
declare const BrowseProductPreview: ({
|
|
12
11
|
product,
|
|
13
12
|
isFeatured,
|
|
14
|
-
imagePriority,
|
|
15
13
|
imageFetchPriority
|
|
16
14
|
}: BrowseProductPreviewProps) => react_jsx_runtime0.JSX.Element;
|
|
17
15
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/browse-product-preview/index.tsx"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/browse-product-preview/index.tsx"],"sourcesContent":[],"mappings":";;;;KAkBK,yBAAA;WACM;;EADN,kBAAA,CAAA,EAAA,MAAA,GAAyB,MAAA,GAAA,KACnB;AAAwB,CAAA;cAwC7B,oBAAwB,EAAA,CAAA;EAAA,OAAA;EAAA,UAAA;EAAA;AAAA,CAAA,EAI3B,yBAJ2B,EAAA,GAIF,kBAAA,CAAA,GAAA,CAAA,OAJE"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { sendClientSignal } from "@gfed-medusa/sf-lib-common/lib/personalization/client-signal";
|
|
5
|
+
import { SignalType } from "@gfed-medusa/sf-lib-common/types/graphql";
|
|
6
|
+
import { useSearchParams } from "next/navigation";
|
|
1
7
|
import { LocalizedClientLink } from "@gfed-medusa/sf-lib-common/components/localized-client-link";
|
|
2
8
|
import { PreviewPrice } from "@gfed-medusa/sf-lib-common/components/preview-price";
|
|
3
9
|
import { Thumbnail } from "@gfed-medusa/sf-lib-common/components/thumbnail";
|
|
@@ -27,19 +33,36 @@ const getBrowseProductPrice = (product) => {
|
|
|
27
33
|
percentage_diff: isSale && originalPrice > 0 ? getPercentageDiff(originalPrice, product.priceAmount) : "0"
|
|
28
34
|
};
|
|
29
35
|
};
|
|
30
|
-
const BrowseProductPreview = ({ product, isFeatured,
|
|
36
|
+
const BrowseProductPreview = ({ product, isFeatured, imageFetchPriority }) => {
|
|
31
37
|
const price = getBrowseProductPrice(product);
|
|
38
|
+
const hoveredRef = useRef(false);
|
|
39
|
+
const query = useSearchParams()?.get("q") ?? "";
|
|
32
40
|
return /* @__PURE__ */ jsx(LocalizedClientLink, {
|
|
33
|
-
href: `/products/${product.handle}`,
|
|
41
|
+
href: `/products/${product.handle ?? ""}`,
|
|
34
42
|
className: "group",
|
|
43
|
+
onClick: () => {
|
|
44
|
+
sendClientSignal(SignalType.SearchResultClick, {
|
|
45
|
+
productId: product.id ?? "",
|
|
46
|
+
productHandle: product.handle ?? "",
|
|
47
|
+
query
|
|
48
|
+
});
|
|
49
|
+
},
|
|
35
50
|
children: /* @__PURE__ */ jsxs("div", {
|
|
36
51
|
"data-testid": "product-wrapper",
|
|
52
|
+
onMouseEnter: () => {
|
|
53
|
+
if (!hoveredRef.current) {
|
|
54
|
+
hoveredRef.current = true;
|
|
55
|
+
sendClientSignal(SignalType.ProductHover, {
|
|
56
|
+
productId: product.id ?? "",
|
|
57
|
+
productHandle: product.handle ?? ""
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
},
|
|
37
61
|
children: [/* @__PURE__ */ jsx(Thumbnail, {
|
|
38
62
|
thumbnail: product.thumbnail,
|
|
39
63
|
images: [],
|
|
40
64
|
size: "full",
|
|
41
65
|
isFeatured,
|
|
42
|
-
imagePriority,
|
|
43
66
|
imageFetchPriority
|
|
44
67
|
}), /* @__PURE__ */ jsxs("div", {
|
|
45
68
|
className: "txt-compact-medium mt-4 flex min-w-0 flex-col items-start gap-y-1 text-left",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/browse-product-preview/index.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/browse-product-preview/index.tsx"],"sourcesContent":["'use client';\n\nimport { useRef } from 'react';\n\nimport { useSearchParams } from 'next/navigation';\n\nimport { LocalizedClientLink } from '@gfed-medusa/sf-lib-common/components/localized-client-link';\nimport { PreviewPrice } from '@gfed-medusa/sf-lib-common/components/preview-price';\nimport { Thumbnail } from '@gfed-medusa/sf-lib-common/components/thumbnail';\nimport { getPercentageDiff } from '@gfed-medusa/sf-lib-common/lib/utils/get-percentage-diff';\nimport { convertToLocale } from '@gfed-medusa/sf-lib-common/lib/utils/money';\nimport { sendClientSignal } from '@gfed-medusa/sf-lib-common/lib/personalization/client-signal';\nimport { SignalType } from '@gfed-medusa/sf-lib-common/types/graphql';\nimport type { VariantPrice } from '@gfed-medusa/sf-lib-common/types/prices';\nimport { Text } from '@medusajs/ui';\n\nimport type { BrowseProductHitFragment } from '@/types/graphql';\n\ntype BrowseProductPreviewProps = {\n product: BrowseProductHitFragment;\n isFeatured?: boolean;\n imageFetchPriority?: 'auto' | 'high' | 'low';\n};\n\nconst getBrowseProductPrice = (\n product: BrowseProductHitFragment\n): VariantPrice | null => {\n if (\n typeof product.priceAmount !== 'number' ||\n !product.currencyCode ||\n !product.currencyCode.trim()\n ) {\n return null;\n }\n\n const originalPrice = product.originalPriceAmount ?? product.priceAmount;\n const isSale =\n typeof originalPrice === 'number' && originalPrice > product.priceAmount;\n\n return {\n calculated_price_number: product.priceAmount,\n calculated_price: convertToLocale({\n amount: product.priceAmount,\n currency_code: product.currencyCode,\n }),\n original_price_number: originalPrice,\n original_price: convertToLocale({\n amount: originalPrice,\n currency_code: product.currencyCode,\n }),\n currency_code: product.currencyCode,\n price_type: isSale ? 'sale' : 'default',\n percentage_diff:\n isSale && originalPrice > 0\n ? getPercentageDiff(originalPrice, product.priceAmount)\n : '0',\n };\n};\n\nconst BrowseProductPreview = ({\n product,\n isFeatured,\n imageFetchPriority,\n}: BrowseProductPreviewProps) => {\n const price = getBrowseProductPrice(product);\n const hoveredRef = useRef(false);\n const searchParams = useSearchParams();\n const query = searchParams?.get('q') ?? '';\n\n return (\n <LocalizedClientLink\n href={`/products/${product.handle ?? ''}`}\n className=\"group\"\n onClick={() => {\n void sendClientSignal(SignalType.SearchResultClick, {\n productId: product.id ?? '',\n productHandle: product.handle ?? '',\n query,\n });\n }}\n >\n <div\n data-testid=\"product-wrapper\"\n onMouseEnter={() => {\n if (!hoveredRef.current) {\n hoveredRef.current = true;\n void sendClientSignal(SignalType.ProductHover, {\n productId: product.id ?? '',\n productHandle: product.handle ?? '',\n });\n }\n }}\n >\n <Thumbnail\n thumbnail={product.thumbnail}\n images={[]}\n size=\"full\"\n isFeatured={isFeatured}\n imageFetchPriority={imageFetchPriority}\n />\n <div className=\"txt-compact-medium mt-4 flex min-w-0 flex-col items-start gap-y-1 text-left\">\n <Text\n className=\"text-ui-fg-subtle w-full min-w-0 overflow-hidden break-words whitespace-normal [display:-webkit-box] [-webkit-box-orient:vertical] [-webkit-line-clamp:2]\"\n data-testid=\"product-title\"\n >\n {product.title}\n </Text>\n <div className=\"flex w-full min-w-0 flex-wrap items-baseline gap-x-2 gap-y-1 text-left\">\n {price && <PreviewPrice price={price} />}\n </div>\n </div>\n </div>\n </LocalizedClientLink>\n );\n};\n\nexport { BrowseProductPreview };\n"],"mappings":";;;;;;;;;;;;;;;AAwBA,MAAM,yBACJ,YACwB;AACxB,KACE,OAAO,QAAQ,gBAAgB,YAC/B,CAAC,QAAQ,gBACT,CAAC,QAAQ,aAAa,MAAM,CAE5B,QAAO;CAGT,MAAM,gBAAgB,QAAQ,uBAAuB,QAAQ;CAC7D,MAAM,SACJ,OAAO,kBAAkB,YAAY,gBAAgB,QAAQ;AAE/D,QAAO;EACL,yBAAyB,QAAQ;EACjC,kBAAkB,gBAAgB;GAChC,QAAQ,QAAQ;GAChB,eAAe,QAAQ;GACxB,CAAC;EACF,uBAAuB;EACvB,gBAAgB,gBAAgB;GAC9B,QAAQ;GACR,eAAe,QAAQ;GACxB,CAAC;EACF,eAAe,QAAQ;EACvB,YAAY,SAAS,SAAS;EAC9B,iBACE,UAAU,gBAAgB,IACtB,kBAAkB,eAAe,QAAQ,YAAY,GACrD;EACP;;AAGH,MAAM,wBAAwB,EAC5B,SACA,YACA,yBAC+B;CAC/B,MAAM,QAAQ,sBAAsB,QAAQ;CAC5C,MAAM,aAAa,OAAO,MAAM;CAEhC,MAAM,QADe,iBAAiB,EACV,IAAI,IAAI,IAAI;AAExC,QACE,oBAAC;EACC,MAAM,aAAa,QAAQ,UAAU;EACrC,WAAU;EACV,eAAe;AACb,GAAK,iBAAiB,WAAW,mBAAmB;IAClD,WAAW,QAAQ,MAAM;IACzB,eAAe,QAAQ,UAAU;IACjC;IACD,CAAC;;YAGJ,qBAAC;GACC,eAAY;GACZ,oBAAoB;AAClB,QAAI,CAAC,WAAW,SAAS;AACvB,gBAAW,UAAU;AACrB,KAAK,iBAAiB,WAAW,cAAc;MAC7C,WAAW,QAAQ,MAAM;MACzB,eAAe,QAAQ,UAAU;MAClC,CAAC;;;cAIN,oBAAC;IACC,WAAW,QAAQ;IACnB,QAAQ,EAAE;IACV,MAAK;IACO;IACQ;KACpB,EACF,qBAAC;IAAI,WAAU;eACb,oBAAC;KACC,WAAU;KACV,eAAY;eAEX,QAAQ;MACJ,EACP,oBAAC;KAAI,WAAU;eACZ,SAAS,oBAAC,gBAAoB,QAAS;MACpC;KACF;IACF;GACc"}
|
|
@@ -4,9 +4,11 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
|
4
4
|
//#region src/components/image-gallery/index.d.ts
|
|
5
5
|
type ImageGalleryProps = {
|
|
6
6
|
images: ProductImage[];
|
|
7
|
+
productId: string;
|
|
7
8
|
};
|
|
8
9
|
declare const ImageGallery: ({
|
|
9
|
-
images
|
|
10
|
+
images,
|
|
11
|
+
productId
|
|
10
12
|
}: ImageGalleryProps) => react_jsx_runtime0.JSX.Element;
|
|
11
13
|
//#endregion
|
|
12
14
|
export { ImageGallery as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/image-gallery/index.tsx"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/image-gallery/index.tsx"],"sourcesContent":[],"mappings":";;;;KAUK,iBAAA;UACK;;AAHqC,CAAA;AAGzB,cAIhB,YAsCL,EAAA,CAAA;EAAA,MAAA;EAAA;AAAA,CAAA,EAtC4C,iBAsC5C,EAAA,GAtC6D,kBAAA,CAAA,GAAA,CAAA,OAsC7D"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { sendClientSignal } from "@gfed-medusa/sf-lib-common/lib/personalization/client-signal";
|
|
4
|
+
import { SignalType } from "@gfed-medusa/sf-lib-common/types/graphql";
|
|
1
5
|
import { Container } from "@medusajs/ui";
|
|
2
6
|
import { jsx } from "react/jsx-runtime";
|
|
3
7
|
import Image from "next/image";
|
|
4
8
|
|
|
5
9
|
//#region src/components/image-gallery/index.tsx
|
|
6
|
-
const ImageGallery = ({ images }) => {
|
|
10
|
+
const ImageGallery = ({ images, productId }) => {
|
|
7
11
|
return /* @__PURE__ */ jsx("div", {
|
|
8
12
|
className: "relative flex items-start",
|
|
9
13
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -21,7 +25,13 @@ const ImageGallery = ({ images }) => {
|
|
|
21
25
|
quality: 60,
|
|
22
26
|
sizes: "(max-width: 576px) 280px, (max-width: 768px) 360px, (max-width: 992px) 480px, 800px",
|
|
23
27
|
style: { objectFit: "cover" },
|
|
24
|
-
...index === 0 ? { fetchPriority: "high" } : {}
|
|
28
|
+
...index === 0 ? { fetchPriority: "high" } : {},
|
|
29
|
+
onClick: () => {
|
|
30
|
+
sendClientSignal(SignalType.ImageZoom, {
|
|
31
|
+
productId,
|
|
32
|
+
imageUrl: image.url
|
|
33
|
+
});
|
|
34
|
+
}
|
|
25
35
|
})
|
|
26
36
|
}, image.id);
|
|
27
37
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/image-gallery/index.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/image-gallery/index.tsx"],"sourcesContent":["'use client';\n\nimport Image from 'next/image';\n\nimport { Container } from '@medusajs/ui';\n\nimport { sendClientSignal } from '@gfed-medusa/sf-lib-common/lib/personalization/client-signal';\nimport { SignalType } from '@gfed-medusa/sf-lib-common/types/graphql';\nimport { ProductImage } from '@/types/graphql';\n\ntype ImageGalleryProps = {\n images: ProductImage[];\n productId: string;\n};\n\nconst ImageGallery = ({ images, productId }: ImageGalleryProps) => {\n return (\n <div className=\"relative flex items-start\">\n <div className=\"small:mx-16 flex flex-1 flex-col gap-y-4\">\n {images.map((image, index) => {\n return (\n <Container\n key={image.id}\n className=\"bg-ui-bg-subtle relative aspect-[29/34] w-full overflow-hidden\"\n id={image.id}\n >\n {!!image.url && (\n <Image\n src={image.url}\n priority={index <= 2 ? true : false}\n className=\"rounded-rounded absolute inset-0\"\n alt={`Product image ${index + 1}`}\n fill\n quality={60}\n sizes=\"(max-width: 576px) 280px, (max-width: 768px) 360px, (max-width: 992px) 480px, 800px\"\n style={{\n objectFit: 'cover',\n }}\n {...(index === 0 ? { fetchPriority: 'high' } : {})}\n onClick={() => {\n void sendClientSignal(SignalType.ImageZoom, {\n productId,\n imageUrl: image.url,\n });\n }}\n />\n )}\n </Container>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default ImageGallery;\n"],"mappings":";;;;;;;;;AAeA,MAAM,gBAAgB,EAAE,QAAQ,gBAAmC;AACjE,QACE,oBAAC;EAAI,WAAU;YACb,oBAAC;GAAI,WAAU;aACZ,OAAO,KAAK,OAAO,UAAU;AAC5B,WACE,oBAAC;KAEC,WAAU;KACV,IAAI,MAAM;eAET,CAAC,CAAC,MAAM,OACP,oBAAC;MACC,KAAK,MAAM;MACX,UAAU,SAAS,IAAI,OAAO;MAC9B,WAAU;MACV,KAAK,iBAAiB,QAAQ;MAC9B;MACA,SAAS;MACT,OAAM;MACN,OAAO,EACL,WAAW,SACZ;MACD,GAAK,UAAU,IAAI,EAAE,eAAe,QAAQ,GAAG,EAAE;MACjD,eAAe;AACb,OAAK,iBAAiB,WAAW,WAAW;QAC1C;QACA,UAAU,MAAM;QACjB,CAAC;;OAEJ;OAvBC,MAAM,GAyBD;KAEd;IACE;GACF;;AAIV,4BAAe"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/components/pagination/index.d.ts
|
|
4
4
|
declare function Pagination({
|
|
@@ -19,7 +19,7 @@ declare function Pagination({
|
|
|
19
19
|
isLoading?: boolean;
|
|
20
20
|
onLoadMore: () => void;
|
|
21
21
|
'data-testid'?: string;
|
|
22
|
-
}):
|
|
22
|
+
}): react_jsx_runtime2.JSX.Element;
|
|
23
23
|
//#endregion
|
|
24
24
|
export { Pagination };
|
|
25
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProductActionsProduct } from "../../types/index.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime4 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/components/product-actions/index.d.ts
|
|
5
5
|
type ProductActionsProps = {
|
|
@@ -13,7 +13,7 @@ declare function ProductActions({
|
|
|
13
13
|
regionId,
|
|
14
14
|
disabled,
|
|
15
15
|
enableMobileActions
|
|
16
|
-
}: ProductActionsProps):
|
|
16
|
+
}: ProductActionsProps): react_jsx_runtime4.JSX.Element;
|
|
17
17
|
//#endregion
|
|
18
18
|
export { ProductActionsProps, ProductActions as default };
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -7,9 +7,9 @@ import { useProductPrice } from "../../lib/hooks/use-product-price.js";
|
|
|
7
7
|
import { mergeProductPricing } from "../../lib/utils/merge-product-pricing.js";
|
|
8
8
|
import mobile_actions_default from "./mobile-actions.js";
|
|
9
9
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
10
|
+
import { useParams } from "next/navigation";
|
|
10
11
|
import { Button } from "@medusajs/ui";
|
|
11
12
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
import { useParams } from "next/navigation";
|
|
13
13
|
import { isEqual } from "lodash";
|
|
14
14
|
import { ErrorMessage } from "@gfed-medusa/sf-lib-common/components/error-message";
|
|
15
15
|
import { WebComponent } from "@gfed-medusa/sf-lib-common/components/web-component";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime1 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/components/product-onboarding-cta/index.d.ts
|
|
4
|
-
declare function ProductOnboardingCta(): Promise<
|
|
4
|
+
declare function ProductOnboardingCta(): Promise<react_jsx_runtime1.JSX.Element | null>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { ProductOnboardingCta as default };
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ProductVariant } from "../../types/graphql.js";
|
|
2
2
|
import { ProductActionsProduct } from "../../types/index.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as react_jsx_runtime3 from "react/jsx-runtime";
|
|
4
4
|
|
|
5
5
|
//#region src/components/product-price/index.d.ts
|
|
6
6
|
declare function ProductPrice({
|
|
@@ -9,7 +9,7 @@ declare function ProductPrice({
|
|
|
9
9
|
}: {
|
|
10
10
|
product: ProductActionsProduct;
|
|
11
11
|
variant?: ProductVariant;
|
|
12
|
-
}):
|
|
12
|
+
}): react_jsx_runtime3.JSX.Element;
|
|
13
13
|
//#endregion
|
|
14
14
|
export { ProductPrice as default };
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/product-tabs/index.tsx"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/product-tabs/index.tsx"],"sourcesContent":[],"mappings":";;;;KAcK,gBAAA;WACM;;AAL+B,cAQpC,WAJe,EAAA,CAAA;EAAA;AACH,CAAP,EAGuB,gBAHhB,EAAA,GAGgC,kBAAA,CAAA,GAAA,CAAA,OAHhC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import accordion_default from "./accordion.js";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
|
+
import { sendClientSignal } from "@gfed-medusa/sf-lib-common/lib/personalization/client-signal";
|
|
6
|
+
import { SignalType } from "@gfed-medusa/sf-lib-common/types/graphql";
|
|
4
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
8
|
import { Back } from "@gfed-medusa/sf-lib-ui/icons/back";
|
|
6
9
|
import { FastDelivery } from "@gfed-medusa/sf-lib-ui/icons/fast-delivery";
|
|
@@ -8,17 +11,36 @@ import { Refresh } from "@gfed-medusa/sf-lib-ui/icons/refresh";
|
|
|
8
11
|
|
|
9
12
|
//#region src/components/product-tabs/index.tsx
|
|
10
13
|
const ProductTabs = ({ product }) => {
|
|
14
|
+
const hasSentReviewsViewRef = useRef(false);
|
|
15
|
+
const productId = product.id;
|
|
16
|
+
const [openTabValues, setOpenTabValues] = useState([]);
|
|
17
|
+
const tabs = [{
|
|
18
|
+
label: "Product Information",
|
|
19
|
+
component: /* @__PURE__ */ jsx(ProductInfoTab, { product })
|
|
20
|
+
}, {
|
|
21
|
+
label: "Shipping & Returns",
|
|
22
|
+
component: /* @__PURE__ */ jsx(ShippingInfoTab, {})
|
|
23
|
+
}];
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (openTabValues.includes("Shipping & Returns") && !hasSentReviewsViewRef.current) {
|
|
26
|
+
hasSentReviewsViewRef.current = true;
|
|
27
|
+
sendClientSignal(SignalType.ReviewsView, { productId });
|
|
28
|
+
sendClientSignal(SignalType.ReturnPolicyView, { productId });
|
|
29
|
+
}
|
|
30
|
+
}, [openTabValues, productId]);
|
|
11
31
|
return /* @__PURE__ */ jsx("div", {
|
|
12
32
|
className: "w-full",
|
|
13
33
|
children: /* @__PURE__ */ jsx(accordion_default, {
|
|
14
34
|
type: "multiple",
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
value: openTabValues,
|
|
36
|
+
onValueChange: (values) => {
|
|
37
|
+
setOpenTabValues(values);
|
|
38
|
+
sendClientSignal(SignalType.TabSwitch, {
|
|
39
|
+
activeTabs: values,
|
|
40
|
+
productId
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
children: tabs.map((tab, i) => /* @__PURE__ */ jsx(accordion_default.Item, {
|
|
22
44
|
title: tab.label,
|
|
23
45
|
headingSize: "medium",
|
|
24
46
|
value: tab.label,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Accordion"],"sources":["../../../src/components/product-tabs/index.tsx"],"sourcesContent":["'use client';\n\nimport { Back } from '@gfed-medusa/sf-lib-ui/icons/back';\nimport { FastDelivery } from '@gfed-medusa/sf-lib-ui/icons/fast-delivery';\nimport { Refresh } from '@gfed-medusa/sf-lib-ui/icons/refresh';\n\nimport { Product } from '@/types/graphql';\n\nimport Accordion from './accordion';\n\ntype ProductTabsProps = {\n product: Product;\n};\n\nconst ProductTabs = ({ product }: ProductTabsProps) => {\n const tabs = [\n {\n label: 'Product Information',\n component: <ProductInfoTab product={product} />,\n },\n {\n label: 'Shipping & Returns',\n component: <ShippingInfoTab />,\n },\n ];\n\n return (\n <div className=\"w-full\">\n <Accordion
|
|
1
|
+
{"version":3,"file":"index.js","names":["Accordion"],"sources":["../../../src/components/product-tabs/index.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { Back } from '@gfed-medusa/sf-lib-ui/icons/back';\nimport { FastDelivery } from '@gfed-medusa/sf-lib-ui/icons/fast-delivery';\nimport { Refresh } from '@gfed-medusa/sf-lib-ui/icons/refresh';\n\nimport { sendClientSignal } from '@gfed-medusa/sf-lib-common/lib/personalization/client-signal';\nimport { SignalType } from '@gfed-medusa/sf-lib-common/types/graphql';\nimport { Product } from '@/types/graphql';\n\nimport Accordion from './accordion';\n\ntype ProductTabsProps = {\n product: Product;\n};\n\nconst ProductTabs = ({ product }: ProductTabsProps) => {\n const hasSentReviewsViewRef = useRef(false);\n const productId = product.id;\n const [openTabValues, setOpenTabValues] = useState<string[]>([]);\n\n const tabs = [\n {\n label: 'Product Information',\n component: <ProductInfoTab product={product} />,\n },\n {\n label: 'Shipping & Returns',\n component: <ShippingInfoTab />,\n },\n ];\n\n // Fire REVIEWS_VIEW and RETURN_POLICY_VIEW when the\n // \"Shipping & Returns\" tab is open — whether initially\n // (via defaultValue) or via user interaction.\n useEffect(() => {\n if (\n openTabValues.includes('Shipping & Returns') &&\n !hasSentReviewsViewRef.current\n ) {\n hasSentReviewsViewRef.current = true;\n void sendClientSignal(SignalType.ReviewsView, { productId });\n void sendClientSignal(SignalType.ReturnPolicyView, { productId });\n }\n }, [openTabValues, productId]);\n\n return (\n <div className=\"w-full\">\n <Accordion\n type=\"multiple\"\n value={openTabValues}\n onValueChange={(values: string[]) => {\n setOpenTabValues(values);\n void sendClientSignal(SignalType.TabSwitch, {\n activeTabs: values,\n productId,\n });\n }}\n >\n {tabs.map((tab, i) => (\n <Accordion.Item\n key={i}\n title={tab.label}\n headingSize=\"medium\"\n value={tab.label}\n >\n {tab.component}\n </Accordion.Item>\n ))}\n </Accordion>\n </div>\n );\n};\n\nconst ProductInfoTab = ({ product }: ProductTabsProps) => {\n return (\n <div className=\"text-small-regular py-8\">\n <div className=\"grid grid-cols-2 gap-x-8\">\n <div className=\"flex flex-col gap-y-4\">\n <div>\n <span className=\"font-semibold\">Material</span>\n <p>{product.material ? product.material : '-'}</p>\n </div>\n <div>\n <span className=\"font-semibold\">Country of origin</span>\n <p>{product.originCountry ? product.originCountry : '-'}</p>\n </div>\n <div>\n <span className=\"font-semibold\">Type</span>\n <p>{product.type || '-'}</p>\n </div>\n </div>\n <div className=\"flex flex-col gap-y-4\">\n <div>\n <span className=\"font-semibold\">Weight</span>\n <p>{product.weight ? `${product.weight} g` : '-'}</p>\n </div>\n <div>\n <span className=\"font-semibold\">Dimensions</span>\n <p>\n {product.length && product.width && product.height\n ? `${product.length}L x ${product.width}W x ${product.height}H`\n : '-'}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nconst ShippingInfoTab = () => {\n return (\n <div className=\"text-small-regular py-8\">\n <div className=\"grid grid-cols-1 gap-y-8\">\n <div className=\"flex items-start gap-x-2\">\n <FastDelivery />\n <div>\n <span className=\"font-semibold\">Fast delivery</span>\n <p className=\"max-w-sm\">\n Your package will arrive in 3-5 business days at your pick up\n location or in the comfort of your home.\n </p>\n </div>\n </div>\n <div className=\"flex items-start gap-x-2\">\n <Refresh />\n <div>\n <span className=\"font-semibold\">Simple exchanges</span>\n <p className=\"max-w-sm\">\n Is the fit not quite right? No worries - we'll exchange your\n product for a new one.\n </p>\n </div>\n </div>\n <div className=\"flex items-start gap-x-2\">\n <Back />\n <div>\n <span className=\"font-semibold\">Easy returns</span>\n <p className=\"max-w-sm\">\n Just return your product and we'll refund your money. No\n questions asked – we'll do our best to make sure your return\n is hassle-free.\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default ProductTabs;\n"],"mappings":";;;;;;;;;;;;AAkBA,MAAM,eAAe,EAAE,cAAgC;CACrD,MAAM,wBAAwB,OAAO,MAAM;CAC3C,MAAM,YAAY,QAAQ;CAC1B,MAAM,CAAC,eAAe,oBAAoB,SAAmB,EAAE,CAAC;CAEhE,MAAM,OAAO,CACX;EACE,OAAO;EACP,WAAW,oBAAC,kBAAwB,UAAW;EAChD,EACD;EACE,OAAO;EACP,WAAW,oBAAC,oBAAkB;EAC/B,CACF;AAKD,iBAAgB;AACd,MACE,cAAc,SAAS,qBAAqB,IAC5C,CAAC,sBAAsB,SACvB;AACA,yBAAsB,UAAU;AAChC,GAAK,iBAAiB,WAAW,aAAa,EAAE,WAAW,CAAC;AAC5D,GAAK,iBAAiB,WAAW,kBAAkB,EAAE,WAAW,CAAC;;IAElE,CAAC,eAAe,UAAU,CAAC;AAE9B,QACE,oBAAC;EAAI,WAAU;YACb,oBAACA;GACC,MAAK;GACL,OAAO;GACP,gBAAgB,WAAqB;AACnC,qBAAiB,OAAO;AACxB,IAAK,iBAAiB,WAAW,WAAW;KAC1C,YAAY;KACZ;KACD,CAAC;;aAGH,KAAK,KAAK,KAAK,MACd,oBAACA,kBAAU;IAET,OAAO,IAAI;IACX,aAAY;IACZ,OAAO,IAAI;cAEV,IAAI;MALA,EAMU,CACjB;IACQ;GACR;;AAIV,MAAM,kBAAkB,EAAE,cAAgC;AACxD,QACE,oBAAC;EAAI,WAAU;YACb,qBAAC;GAAI,WAAU;cACb,qBAAC;IAAI,WAAU;;KACb,qBAAC,oBACC,oBAAC;MAAK,WAAU;gBAAgB;OAAe,EAC/C,oBAAC,iBAAG,QAAQ,WAAW,QAAQ,WAAW,MAAQ,IAC9C;KACN,qBAAC,oBACC,oBAAC;MAAK,WAAU;gBAAgB;OAAwB,EACxD,oBAAC,iBAAG,QAAQ,gBAAgB,QAAQ,gBAAgB,MAAQ,IACxD;KACN,qBAAC,oBACC,oBAAC;MAAK,WAAU;gBAAgB;OAAW,EAC3C,oBAAC,iBAAG,QAAQ,QAAQ,MAAQ,IACxB;;KACF,EACN,qBAAC;IAAI,WAAU;eACb,qBAAC,oBACC,oBAAC;KAAK,WAAU;eAAgB;MAAa,EAC7C,oBAAC,iBAAG,QAAQ,SAAS,GAAG,QAAQ,OAAO,MAAM,MAAQ,IACjD,EACN,qBAAC,oBACC,oBAAC;KAAK,WAAU;eAAgB;MAAiB,EACjD,oBAAC,iBACE,QAAQ,UAAU,QAAQ,SAAS,QAAQ,SACxC,GAAG,QAAQ,OAAO,MAAM,QAAQ,MAAM,MAAM,QAAQ,OAAO,KAC3D,MACF,IACA;KACF;IACF;GACF;;AAIV,MAAM,wBAAwB;AAC5B,QACE,oBAAC;EAAI,WAAU;YACb,qBAAC;GAAI,WAAU;;IACb,qBAAC;KAAI,WAAU;gBACb,oBAAC,iBAAe,EAChB,qBAAC,oBACC,oBAAC;MAAK,WAAU;gBAAgB;OAAoB,EACpD,oBAAC;MAAE,WAAU;gBAAW;OAGpB,IACA;MACF;IACN,qBAAC;KAAI,WAAU;gBACb,oBAAC,YAAU,EACX,qBAAC,oBACC,oBAAC;MAAK,WAAU;gBAAgB;OAAuB,EACvD,oBAAC;MAAE,WAAU;gBAAW;OAGpB,IACA;MACF;IACN,qBAAC;KAAI,WAAU;gBACb,oBAAC,SAAO,EACR,qBAAC,oBACC,oBAAC;MAAK,WAAU;gBAAgB;OAAmB,EACnD,oBAAC;MAAE,WAAU;gBAAW;OAIpB,IACA;MACF;;IACF;GACF;;AAIV,2BAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/refinement-list/index.tsx"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/refinement-list/index.tsx"],"sourcesContent":[],"mappings":";;;;KAaK,mBAAA;UACK;;EADL,aAAA,CAAA,EAAA,MAAmB;EAOlB,SAAA,CAAA,EAAA,MAmDL;CAnDuB;cAAlB,cAAkB,EAAA,CAAA;EAAA,MAAA;EAAA,aAAA,EAAA,UAAA;EAAA;AAAA,CAAA,EAIrB,mBAJqB,EAAA,GAIF,kBAAA,CAAA,GAAA,CAAA,OAJE"}
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import sort_products_default from "./sort-products/index.js";
|
|
4
4
|
import { useCallback } from "react";
|
|
5
|
+
import { sendClientSignal } from "@gfed-medusa/sf-lib-common/lib/personalization/client-signal";
|
|
6
|
+
import { SignalType } from "@gfed-medusa/sf-lib-common/types/graphql";
|
|
7
|
+
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
5
8
|
import { clx } from "@medusajs/ui";
|
|
6
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
8
10
|
|
|
9
11
|
//#region src/components/refinement-list/index.tsx
|
|
10
12
|
const RefinementList = ({ sortBy, "data-testid": dataTestId, className }) => {
|
|
@@ -19,6 +21,10 @@ const RefinementList = ({ sortBy, "data-testid": dataTestId, className }) => {
|
|
|
19
21
|
}, [searchParams]);
|
|
20
22
|
const setQueryParams = (name, value) => {
|
|
21
23
|
const query = createQueryString(name, value);
|
|
24
|
+
if (name !== "sortBy") sendClientSignal(SignalType.FilterApplied, {
|
|
25
|
+
filterName: name,
|
|
26
|
+
filterValue: value
|
|
27
|
+
});
|
|
22
28
|
router.push(`${pathname}?${query}`);
|
|
23
29
|
};
|
|
24
30
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["SortProducts"],"sources":["../../../src/components/refinement-list/index.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback } from 'react';\n\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\n\nimport { clx } from '@medusajs/ui';\n\nimport SortProducts, { SortOptions } from './sort-products';\n\ntype RefinementListProps = {\n sortBy: SortOptions;\n search?: boolean;\n 'data-testid'?: string;\n className?: string;\n};\n\nconst RefinementList = ({\n sortBy,\n 'data-testid': dataTestId,\n className,\n}: RefinementListProps) => {\n const router = useRouter();\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n const createQueryString = useCallback(\n (name: string, value: string) => {\n const params = new URLSearchParams(searchParams);\n params.set(name, value);\n if (name === 'sortBy') {\n params.delete('page');\n }\n\n return params.toString();\n },\n [searchParams]\n );\n\n const setQueryParams = (name: string, value: string) => {\n const query = createQueryString(name, value);\n router.push(`${pathname}?${query}`);\n };\n\n return (\n <div className={clx('w-full', className)}>\n <div className=\"small:hidden\">\n <SortProducts\n sortBy={sortBy}\n setQueryParams={setQueryParams}\n data-testid={dataTestId}\n variant=\"dropdown\"\n />\n </div>\n <div className=\"small:ml-[1.675rem] small:min-w-[250px] small:flex-col small:px-0 small:py-4 small:pr-6 small:block hidden\">\n <SortProducts\n sortBy={sortBy}\n setQueryParams={setQueryParams}\n data-testid={dataTestId}\n />\n </div>\n </div>\n );\n};\n\nexport default RefinementList;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":["SortProducts"],"sources":["../../../src/components/refinement-list/index.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback } from 'react';\n\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\n\nimport { clx } from '@medusajs/ui';\n\nimport { sendClientSignal } from '@gfed-medusa/sf-lib-common/lib/personalization/client-signal';\nimport { SignalType } from '@gfed-medusa/sf-lib-common/types/graphql';\n\nimport SortProducts, { SortOptions } from './sort-products';\n\ntype RefinementListProps = {\n sortBy: SortOptions;\n search?: boolean;\n 'data-testid'?: string;\n className?: string;\n};\n\nconst RefinementList = ({\n sortBy,\n 'data-testid': dataTestId,\n className,\n}: RefinementListProps) => {\n const router = useRouter();\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n const createQueryString = useCallback(\n (name: string, value: string) => {\n const params = new URLSearchParams(searchParams);\n params.set(name, value);\n if (name === 'sortBy') {\n params.delete('page');\n }\n\n return params.toString();\n },\n [searchParams]\n );\n\n const setQueryParams = (name: string, value: string) => {\n const query = createQueryString(name, value);\n\n if (name !== 'sortBy') {\n void sendClientSignal(SignalType.FilterApplied, { filterName: name, filterValue: value });\n }\n\n router.push(`${pathname}?${query}`);\n };\n\n return (\n <div className={clx('w-full', className)}>\n <div className=\"small:hidden\">\n <SortProducts\n sortBy={sortBy}\n setQueryParams={setQueryParams}\n data-testid={dataTestId}\n variant=\"dropdown\"\n />\n </div>\n <div className=\"small:ml-[1.675rem] small:min-w-[250px] small:flex-col small:px-0 small:py-4 small:pr-6 small:block hidden\">\n <SortProducts\n sortBy={sortBy}\n setQueryParams={setQueryParams}\n data-testid={dataTestId}\n />\n </div>\n </div>\n );\n};\n\nexport default RefinementList;\n"],"mappings":";;;;;;;;;;;AAoBA,MAAM,kBAAkB,EACtB,QACA,eAAe,YACf,gBACyB;CACzB,MAAM,SAAS,WAAW;CAC1B,MAAM,WAAW,aAAa;CAC9B,MAAM,eAAe,iBAAiB;CAEtC,MAAM,oBAAoB,aACvB,MAAc,UAAkB;EAC/B,MAAM,SAAS,IAAI,gBAAgB,aAAa;AAChD,SAAO,IAAI,MAAM,MAAM;AACvB,MAAI,SAAS,SACX,QAAO,OAAO,OAAO;AAGvB,SAAO,OAAO,UAAU;IAE1B,CAAC,aAAa,CACf;CAED,MAAM,kBAAkB,MAAc,UAAkB;EACtD,MAAM,QAAQ,kBAAkB,MAAM,MAAM;AAE5C,MAAI,SAAS,SACX,CAAK,iBAAiB,WAAW,eAAe;GAAE,YAAY;GAAM,aAAa;GAAO,CAAC;AAG3F,SAAO,KAAK,GAAG,SAAS,GAAG,QAAQ;;AAGrC,QACE,qBAAC;EAAI,WAAW,IAAI,UAAU,UAAU;aACtC,oBAAC;GAAI,WAAU;aACb,oBAACA;IACS;IACQ;IAChB,eAAa;IACb,SAAQ;KACR;IACE,EACN,oBAAC;GAAI,WAAU;aACb,oBAACA;IACS;IACQ;IAChB,eAAa;KACb;IACE;GACF;;AAIV,8BAAe"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime11 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/components/refinement-list/sort-products/index.d.ts
|
|
4
4
|
type SortOptions = 'price_asc' | 'price_desc' | 'created_at';
|
|
@@ -13,7 +13,7 @@ declare const SortProducts: ({
|
|
|
13
13
|
sortBy,
|
|
14
14
|
setQueryParams,
|
|
15
15
|
variant
|
|
16
|
-
}: SortProductsProps) =>
|
|
16
|
+
}: SortProductsProps) => react_jsx_runtime11.JSX.Element;
|
|
17
17
|
//#endregion
|
|
18
18
|
export { SortOptions, SortProducts as default };
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/components/refinement-list/sort-products/index.tsx"],"sourcesContent":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/components/refinement-list/sort-products/index.tsx"],"sourcesContent":[],"mappings":";;;KAOY,WAAA;KAEP,iBAAA;UACK;EAHE,cAAW,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAIiB,WAJjB,EAAA,GAAA,IAAA;EAElB,OAAA,CAAA,EAAA,OAAA,GAAiB,UAAA;EAsBhB,aAAA,CAAA,EAyCL,MAAA;CAzCqB;cAAhB,YAAgB,EAAA,CAAA;EAAA,aAAA,EAAA,UAAA;EAAA,MAAA;EAAA,cAAA;EAAA;AAAA,CAAA,EAKnB,iBALmB,EAAA,GAKF,mBAAA,CAAA,GAAA,CAAA,OALE"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { sendClientSignal } from "@gfed-medusa/sf-lib-common/lib/personalization/client-signal";
|
|
4
|
+
import { SignalType } from "@gfed-medusa/sf-lib-common/types/graphql";
|
|
3
5
|
import { jsx } from "react/jsx-runtime";
|
|
4
6
|
import { FilterRadioGroup } from "@gfed-medusa/sf-lib-ui/components/filter-radio-group";
|
|
5
7
|
import NativeSelect from "@gfed-medusa/sf-lib-ui/components/native-select";
|
|
@@ -22,6 +24,7 @@ const sortOptions = [
|
|
|
22
24
|
const SortProducts = ({ "data-testid": dataTestId, sortBy, setQueryParams, variant = "radio" }) => {
|
|
23
25
|
const handleChange = (value) => {
|
|
24
26
|
setQueryParams("sortBy", value);
|
|
27
|
+
sendClientSignal(SignalType.SortChanged, { sortBy: value });
|
|
25
28
|
};
|
|
26
29
|
if (variant === "dropdown") return /* @__PURE__ */ jsx("div", {
|
|
27
30
|
className: "w-fit max-w-full",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/refinement-list/sort-products/index.tsx"],"sourcesContent":["'use client';\n\nimport { FilterRadioGroup } from '@gfed-medusa/sf-lib-ui/components/filter-radio-group';\nimport NativeSelect from '@gfed-medusa/sf-lib-ui/components/native-select';\n\nexport type SortOptions = 'price_asc' | 'price_desc' | 'created_at';\n\ntype SortProductsProps = {\n sortBy: SortOptions;\n setQueryParams: (name: string, value: SortOptions) => void;\n variant?: 'radio' | 'dropdown';\n 'data-testid'?: string;\n};\n\nconst sortOptions = [\n {\n value: 'created_at',\n label: 'Latest Arrivals',\n },\n {\n value: 'price_asc',\n label: 'Price: Low -> High',\n },\n {\n value: 'price_desc',\n label: 'Price: High -> Low',\n },\n];\n\nconst SortProducts = ({\n 'data-testid': dataTestId,\n sortBy,\n setQueryParams,\n variant = 'radio',\n}: SortProductsProps) => {\n const handleChange = (value: SortOptions) => {\n setQueryParams('sortBy', value);\n };\n\n if (variant === 'dropdown') {\n return (\n <div className=\"w-fit max-w-full\">\n <NativeSelect\n aria-label=\"Sort products\"\n placeholder=\"Sort by\"\n value={sortBy}\n className=\"xsmall:w-[280px] w-[220px] max-w-full\"\n onChange={(event) => handleChange(event.target.value as SortOptions)}\n data-testid={dataTestId}\n >\n {sortOptions.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </NativeSelect>\n </div>\n );\n }\n\n return (\n <FilterRadioGroup\n title=\"Sort by\"\n items={sortOptions}\n value={sortBy}\n handleChange={handleChange}\n data-testid={dataTestId}\n />\n );\n};\n\nexport default SortProducts;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/refinement-list/sort-products/index.tsx"],"sourcesContent":["'use client';\n\nimport { FilterRadioGroup } from '@gfed-medusa/sf-lib-ui/components/filter-radio-group';\nimport NativeSelect from '@gfed-medusa/sf-lib-ui/components/native-select';\nimport { sendClientSignal } from '@gfed-medusa/sf-lib-common/lib/personalization/client-signal';\nimport { SignalType } from '@gfed-medusa/sf-lib-common/types/graphql';\n\nexport type SortOptions = 'price_asc' | 'price_desc' | 'created_at';\n\ntype SortProductsProps = {\n sortBy: SortOptions;\n setQueryParams: (name: string, value: SortOptions) => void;\n variant?: 'radio' | 'dropdown';\n 'data-testid'?: string;\n};\n\nconst sortOptions = [\n {\n value: 'created_at',\n label: 'Latest Arrivals',\n },\n {\n value: 'price_asc',\n label: 'Price: Low -> High',\n },\n {\n value: 'price_desc',\n label: 'Price: High -> Low',\n },\n];\n\nconst SortProducts = ({\n 'data-testid': dataTestId,\n sortBy,\n setQueryParams,\n variant = 'radio',\n}: SortProductsProps) => {\n const handleChange = (value: SortOptions) => {\n setQueryParams('sortBy', value);\n void sendClientSignal(SignalType.SortChanged, { sortBy: value });\n };\n\n if (variant === 'dropdown') {\n return (\n <div className=\"w-fit max-w-full\">\n <NativeSelect\n aria-label=\"Sort products\"\n placeholder=\"Sort by\"\n value={sortBy}\n className=\"xsmall:w-[280px] w-[220px] max-w-full\"\n onChange={(event) => handleChange(event.target.value as SortOptions)}\n data-testid={dataTestId}\n >\n {sortOptions.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </NativeSelect>\n </div>\n );\n }\n\n return (\n <FilterRadioGroup\n title=\"Sort by\"\n items={sortOptions}\n value={sortBy}\n handleChange={handleChange}\n data-testid={dataTestId}\n />\n );\n};\n\nexport default SortProducts;\n"],"mappings":";;;;;;;;;AAgBA,MAAM,cAAc;CAClB;EACE,OAAO;EACP,OAAO;EACR;CACD;EACE,OAAO;EACP,OAAO;EACR;CACD;EACE,OAAO;EACP,OAAO;EACR;CACF;AAED,MAAM,gBAAgB,EACpB,eAAe,YACf,QACA,gBACA,UAAU,cACa;CACvB,MAAM,gBAAgB,UAAuB;AAC3C,iBAAe,UAAU,MAAM;AAC/B,EAAK,iBAAiB,WAAW,aAAa,EAAE,QAAQ,OAAO,CAAC;;AAGlE,KAAI,YAAY,WACd,QACE,oBAAC;EAAI,WAAU;YACb,oBAAC;GACC,cAAW;GACX,aAAY;GACZ,OAAO;GACP,WAAU;GACV,WAAW,UAAU,aAAa,MAAM,OAAO,MAAqB;GACpE,eAAa;aAEZ,YAAY,KAAK,WAChB,oBAAC;IAA0B,OAAO,OAAO;cACtC,OAAO;MADG,OAAO,MAEX,CACT;IACW;GACX;AAIV,QACE,oBAAC;EACC,OAAM;EACN,OAAO;EACP,OAAO;EACO;EACd,eAAa;GACb;;AAIN,4BAAe"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime9 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/components/skeleton-product-grid/index.d.ts
|
|
4
4
|
declare const SkeletonProductGrid: ({
|
|
5
5
|
numberOfProducts
|
|
6
6
|
}: {
|
|
7
7
|
numberOfProducts?: number;
|
|
8
|
-
}) =>
|
|
8
|
+
}) => react_jsx_runtime9.JSX.Element;
|
|
9
9
|
//#endregion
|
|
10
10
|
export { SkeletonProductGrid as default };
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime10 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/components/skeleton-product-preview/index.d.ts
|
|
4
|
-
declare const SkeletonProductPreview: () =>
|
|
4
|
+
declare const SkeletonProductPreview: () => react_jsx_runtime10.JSX.Element;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { SkeletonProductPreview as default };
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/skeleton-product-preview/index.tsx"],"sourcesContent":[],"mappings":";;;cAEM,8BAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/skeleton-product-preview/index.tsx"],"sourcesContent":[],"mappings":";;;cAEM,8BAAsB,mBAAA,CAAA,GAAA,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime8 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/components/skeleton-related-products/index.d.ts
|
|
4
|
-
declare const SkeletonRelatedProducts: () =>
|
|
4
|
+
declare const SkeletonRelatedProducts: () => react_jsx_runtime8.JSX.Element;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { SkeletonRelatedProducts as default };
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|