@tapcart/mobile-components 0.12.9 → 0.12.11
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-block-conditional-rendering.d.ts.map +1 -1
- package/dist/components/hooks/use-block-conditional-rendering.js +30 -17
- package/dist/components/hooks/use-infinite-scroll.d.ts.map +1 -1
- package/dist/components/hooks/use-infinite-scroll.js +26 -14
- package/dist/components/hooks/use-infinite-wishlist.d.ts +27 -12
- package/dist/components/hooks/use-infinite-wishlist.d.ts.map +1 -1
- package/dist/components/hooks/use-infinite-wishlist.js +158 -37
- package/dist/components/hooks/use-infinite-wishlist.test.d.ts +2 -0
- package/dist/components/hooks/use-infinite-wishlist.test.d.ts.map +1 -0
- package/dist/components/hooks/use-infinite-wishlist.test.js +1244 -0
- package/dist/components/hooks/use-product-options.d.ts +7 -1
- package/dist/components/hooks/use-product-options.d.ts.map +1 -1
- package/dist/components/hooks/use-product-options.js +7 -1
- package/dist/components/hooks/use-reviews.d.ts.map +1 -1
- package/dist/components/hooks/use-reviews.js +8 -7
- package/dist/components/ui/carousel.d.ts.map +1 -1
- package/dist/components/ui/carousel.js +48 -25
- package/dist/components/ui/text.js +1 -1
- package/dist/components/ui/virtual-grid.d.ts.map +1 -1
- package/dist/components/ui/virtual-grid.js +44 -2
- package/dist/lib/utils.d.ts +3 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +4 -3
- package/dist/styles.css +12 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-block-conditional-rendering.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-block-conditional-rendering.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,YAAY,EAGb,MAAM,kBAAkB,CAAA;AAezB,eAAO,MAAM,4BAA4B,WAC/B;IACN,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,GAAG,CAAA;IACpB,iBAAiB,EAAE,GAAG,CAAA;CACvB,UACO,YAAY,6BACO,GAAG;;;
|
|
1
|
+
{"version":3,"file":"use-block-conditional-rendering.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-block-conditional-rendering.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,YAAY,EAGb,MAAM,kBAAkB,CAAA;AAezB,eAAO,MAAM,4BAA4B,WAC/B;IACN,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,GAAG,CAAA;IACpB,iBAAiB,EAAE,GAAG,CAAA;CACvB,UACO,YAAY,6BACO,GAAG;;;CAiT/B,CAAA"}
|
|
@@ -29,11 +29,7 @@ export const useBlockConditionalRendering = (_props, _block, mobileComponentOver
|
|
|
29
29
|
const { id: deviceId = "" } = deviceVariables || {};
|
|
30
30
|
const productId = (_f = searchParams === null || searchParams === void 0 ? void 0 : searchParams.get("productId")) !== null && _f !== void 0 ? _f : undefined;
|
|
31
31
|
const productHandle = (_g = searchParams === null || searchParams === void 0 ? void 0 : searchParams.get("productHandle")) !== null && _g !== void 0 ? _g : undefined;
|
|
32
|
-
const location = {
|
|
33
|
-
country,
|
|
34
|
-
language,
|
|
35
|
-
deviceId,
|
|
36
|
-
};
|
|
32
|
+
const location = useMemo(() => ({ country, language, deviceId }), [country, language, deviceId]);
|
|
37
33
|
const productMetafieldsQuery = useMemo(() => {
|
|
38
34
|
var _a;
|
|
39
35
|
if (!isConditionalsEnabled) {
|
|
@@ -67,7 +63,7 @@ export const useBlockConditionalRendering = (_props, _block, mobileComponentOver
|
|
|
67
63
|
]);
|
|
68
64
|
const shouldFetchProduct = isConditionalsEnabled && (productId || productHandle);
|
|
69
65
|
const useProducts = (mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useProducts) || mclUseProducts;
|
|
70
|
-
const useProductsArguments = (mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useProducts)
|
|
66
|
+
const useProductsArguments = useMemo(() => (mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useProducts)
|
|
71
67
|
? {
|
|
72
68
|
productIds: productId ? [gidFromId(productId)] : [],
|
|
73
69
|
productHandles: productHandle ? [productHandle] : [],
|
|
@@ -82,13 +78,20 @@ export const useBlockConditionalRendering = (_props, _block, mobileComponentOver
|
|
|
82
78
|
language,
|
|
83
79
|
country,
|
|
84
80
|
},
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
}, [
|
|
82
|
+
mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useProducts,
|
|
83
|
+
productId,
|
|
84
|
+
productHandle,
|
|
85
|
+
apiUrl,
|
|
86
|
+
language,
|
|
87
|
+
country,
|
|
88
|
+
productMetafieldsQuery,
|
|
89
|
+
]);
|
|
90
|
+
const useProductsSkipArguments = useMemo(() => (mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useProducts)
|
|
91
|
+
? { skip: true }
|
|
92
|
+
: null, [mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useProducts]);
|
|
93
|
+
const useProductsInput = useMemo(() => shouldFetchProduct ? useProductsArguments : useProductsSkipArguments, [shouldFetchProduct, useProductsArguments, useProductsSkipArguments]);
|
|
94
|
+
const { products, error: useProductsError, isLoading: isProductsLoading, } = useProducts(useProductsInput);
|
|
92
95
|
const blockCollectionMetafields = useMemo(() => {
|
|
93
96
|
var _a;
|
|
94
97
|
if (!isConditionalsEnabled) {
|
|
@@ -144,20 +147,30 @@ export const useBlockConditionalRendering = (_props, _block, mobileComponentOver
|
|
|
144
147
|
const collectionHandle = (_j = searchParams === null || searchParams === void 0 ? void 0 : searchParams.get("collectionHandle")) !== null && _j !== void 0 ? _j : undefined;
|
|
145
148
|
const shouldFetchCollection = isConditionalsEnabled && (collectionId || collectionHandle);
|
|
146
149
|
const useCollection = (mobileComponentOverrides === null || mobileComponentOverrides === void 0 ? void 0 : mobileComponentOverrides.useCollection) || mclUseCollection;
|
|
147
|
-
const
|
|
150
|
+
const useCollectionArguments = useMemo(() => ({
|
|
148
151
|
appId,
|
|
149
152
|
apiUrl,
|
|
150
153
|
collectionId: shouldFetchCollection ? collectionId : undefined,
|
|
151
154
|
collectionHandle: shouldFetchCollection ? collectionHandle : undefined,
|
|
152
155
|
language: location === null || location === void 0 ? void 0 : location.language,
|
|
153
156
|
metafields: shouldFetchCollection ? memoizedMetafields : undefined,
|
|
154
|
-
})
|
|
157
|
+
}), [
|
|
158
|
+
appId,
|
|
159
|
+
apiUrl,
|
|
160
|
+
shouldFetchCollection,
|
|
161
|
+
collectionId,
|
|
162
|
+
collectionHandle,
|
|
163
|
+
location === null || location === void 0 ? void 0 : location.language,
|
|
164
|
+
memoizedMetafields,
|
|
165
|
+
]);
|
|
166
|
+
const { specificCollection = {}, error: useCollectionError, loading: isCollectionLoading, } = useCollection(useCollectionArguments);
|
|
155
167
|
const isLoading = isProductsLoading || isCollectionLoading;
|
|
156
168
|
if (useProductsError || useCollectionError) {
|
|
157
169
|
console.error("Unable to load products in conditional block rendering hook: ", useProductsError !== null && useProductsError !== void 0 ? useProductsError : useCollectionError);
|
|
158
170
|
}
|
|
171
|
+
const disabledResult = useMemo(() => ({ shouldShow: true, isLoading: false }), []);
|
|
159
172
|
if (!isConditionalsEnabled) {
|
|
160
|
-
return
|
|
173
|
+
return disabledResult;
|
|
161
174
|
}
|
|
162
175
|
let shouldShow = true;
|
|
163
176
|
const blockHasTags = countNumberOfTagsInState(blockState) > 0;
|
|
@@ -200,5 +213,5 @@ export const useBlockConditionalRendering = (_props, _block, mobileComponentOver
|
|
|
200
213
|
console.error("Error evaluating block visibility conditions:", e);
|
|
201
214
|
shouldShow = true; // Fail-safe to show block
|
|
202
215
|
}
|
|
203
|
-
return { shouldShow, isLoading };
|
|
216
|
+
return useMemo(() => ({ shouldShow, isLoading }), [shouldShow, isLoading]);
|
|
204
217
|
};
|
|
@@ -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,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE5D,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,GAAG,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAA;CACxC;AAED,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAGxC,WAAW,CAAC,EAAE,QAAQ,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGpC,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAA;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAChD,YAAY,CAAC,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,GAAG,GAAG,IAAI,EAC5B,GAAG,IAAI,EAAE,GAAG,EAAE,KACX,GAAG,CAAA;IACR,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;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,oBAAoB,EAAE,GAAG,EAAE,CAAA;IAC3B,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,wLAgBpB,sBAAsB,KAAG,
|
|
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,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE5D,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,GAAG,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAA;CACxC;AAED,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAGxC,WAAW,CAAC,EAAE,QAAQ,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGpC,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAA;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAChD,YAAY,CAAC,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,GAAG,GAAG,IAAI,EAC5B,GAAG,IAAI,EAAE,GAAG,EAAE,KACX,GAAG,CAAA;IACR,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;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,oBAAoB,EAAE,GAAG,EAAE,CAAA;IAC3B,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,wLAgBpB,sBAAsB,KAAG,uBAqS3B,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -49,7 +49,7 @@ initialData, queryVariables: queryVariableProps,
|
|
|
49
49
|
// Common props
|
|
50
50
|
direction = "vertical", productLimit = Infinity, threshold = 0.01, interval = 33, // ~2 frames
|
|
51
51
|
customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
52
|
-
var _a, _b, _c, _d, _e;
|
|
52
|
+
var _a, _b, _c, _d, _e, _f;
|
|
53
53
|
const searchParams = useSearchParams();
|
|
54
54
|
const productCount = useRef(0);
|
|
55
55
|
const isFirstRender = useRef(true);
|
|
@@ -102,7 +102,7 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
|
102
102
|
return Object.assign(Object.assign({}, queryVariables), { cursorBlob: previousPageData.pageData.cursorBlob });
|
|
103
103
|
};
|
|
104
104
|
const apiFetcher = (body) => __awaiter(void 0, void 0, void 0, function* () {
|
|
105
|
-
var
|
|
105
|
+
var _g, _h;
|
|
106
106
|
if (!(initialData === null || initialData === void 0 ? void 0 : initialData.apiURL)) {
|
|
107
107
|
throw new Error("initialData.apiURL is required for API mode");
|
|
108
108
|
}
|
|
@@ -111,7 +111,7 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
|
111
111
|
body: JSON.stringify(body),
|
|
112
112
|
});
|
|
113
113
|
const data = yield res.json();
|
|
114
|
-
productCount.current += (
|
|
114
|
+
productCount.current += (_h = (_g = data === null || data === void 0 ? void 0 : data.products) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0;
|
|
115
115
|
return data;
|
|
116
116
|
});
|
|
117
117
|
// Return null from getKey to conditionally skip fetching
|
|
@@ -134,20 +134,23 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
|
134
134
|
};
|
|
135
135
|
const fetcher = usingSearchClient
|
|
136
136
|
? (...args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
137
|
-
var
|
|
137
|
+
var _j, _k;
|
|
138
138
|
if (!searchClientFetcher)
|
|
139
139
|
return null;
|
|
140
140
|
const result = yield searchClientFetcher(...args);
|
|
141
|
-
productCount.current += (
|
|
141
|
+
productCount.current += (_k = (_j = result === null || result === void 0 ? void 0 : result.products) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : 0;
|
|
142
142
|
return result;
|
|
143
143
|
})
|
|
144
144
|
: (...args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
145
145
|
const effectiveFetcher = customFetcher || apiFetcher;
|
|
146
146
|
return effectiveFetcher(...args);
|
|
147
147
|
});
|
|
148
|
+
// Check if caller provided pre-fetched products to display while SWR fetches
|
|
149
|
+
const hasInitialProducts = Boolean((_a = initialData === null || initialData === void 0 ? void 0 : initialData.products) === null || _a === void 0 ? void 0 : _a.length);
|
|
148
150
|
const { data, error, size, setSize, isLoading, isValidating, mutate, } = useSWRInfinite(getKey, fetcher, {
|
|
149
151
|
revalidateFirstPage: false,
|
|
150
152
|
initialSize: 1,
|
|
153
|
+
keepPreviousData: true,
|
|
151
154
|
});
|
|
152
155
|
// Detect when params change and force cache invalidation
|
|
153
156
|
useEffect(() => {
|
|
@@ -166,15 +169,19 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
|
166
169
|
// Skip reset on first render, but force it for any subsequent transitions to valid params
|
|
167
170
|
if (!isFirstRender.current && hasValidCurrentParams) {
|
|
168
171
|
productCount.current = 0;
|
|
169
|
-
mutate(
|
|
172
|
+
mutate();
|
|
170
173
|
}
|
|
171
174
|
}
|
|
172
175
|
isFirstRender.current = false;
|
|
173
176
|
}, [currentCollectionId, currentCollectionHandle, currentSearchQuery, mutate]);
|
|
174
|
-
|
|
177
|
+
// When we have pre-fetched products, don't report as "loading initial data"
|
|
178
|
+
// so the grid renders immediately with those products
|
|
179
|
+
const isLoadingInitialData = !data && !error && !hasInitialProducts;
|
|
175
180
|
const isLoadingMore = isLoadingInitialData ||
|
|
176
181
|
(size > 0 && data && typeof data[size - 1] === "undefined");
|
|
177
|
-
const isEmpty =
|
|
182
|
+
const isEmpty = data
|
|
183
|
+
? ((_d = (_c = (_b = data === null || data === void 0 ? void 0 : data[0]) === null || _b === void 0 ? void 0 : _b.products) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) === 0
|
|
184
|
+
: !hasInitialProducts;
|
|
178
185
|
let isEndPointer;
|
|
179
186
|
if (!data) {
|
|
180
187
|
isEndPointer = true;
|
|
@@ -183,7 +190,7 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
|
183
190
|
isEndPointer = !(searchClient === null || searchClient === void 0 ? void 0 : searchClient.getHasMore());
|
|
184
191
|
}
|
|
185
192
|
else {
|
|
186
|
-
isEndPointer = !((
|
|
193
|
+
isEndPointer = !((_f = (_e = data[data.length - 1]) === null || _e === void 0 ? void 0 : _e.pageData) === null || _f === void 0 ? void 0 : _f.cursorBlob);
|
|
187
194
|
}
|
|
188
195
|
const isReachingEnd = isEmpty || isEndPointer;
|
|
189
196
|
const isRefreshing = isValidating && data && data.length === size;
|
|
@@ -214,15 +221,20 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
|
|
|
214
221
|
return;
|
|
215
222
|
const unsubscribeAllChanges = searchClient.onSearchStateChange(() => {
|
|
216
223
|
productCount.current = 0;
|
|
217
|
-
mutate(
|
|
224
|
+
mutate();
|
|
218
225
|
});
|
|
219
226
|
return unsubscribeAllChanges;
|
|
220
227
|
}, [searchClient, mutate, usingSearchClient]);
|
|
221
228
|
const products = useMemo(() => {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
229
|
+
if (data) {
|
|
230
|
+
return data.flatMap((page) => page === null || page === void 0 ? void 0 : page.products).slice(0, productLimit);
|
|
231
|
+
}
|
|
232
|
+
// Use pre-fetched products while SWR fetches the real paginated data
|
|
233
|
+
if (hasInitialProducts) {
|
|
234
|
+
return initialData.products;
|
|
235
|
+
}
|
|
236
|
+
return [];
|
|
237
|
+
}, [data, productLimit, hasInitialProducts, initialData === null || initialData === void 0 ? void 0 : initialData.products]);
|
|
226
238
|
// Collect all integration responses per page when using search client
|
|
227
239
|
const integrationResponses = useMemo(() => {
|
|
228
240
|
if (!usingSearchClient)
|
|
@@ -1,16 +1,40 @@
|
|
|
1
|
+
export type WishlistItemRef = {
|
|
2
|
+
productId: string;
|
|
3
|
+
variantId?: string;
|
|
4
|
+
};
|
|
1
5
|
type QueryVariables = {
|
|
2
6
|
language?: string;
|
|
3
7
|
country?: string;
|
|
4
8
|
appId?: string;
|
|
5
9
|
collectionId?: string;
|
|
6
10
|
};
|
|
11
|
+
/** Preferred: item-level refs. Legacy: parallel arrays (converted to initialItems internally). */
|
|
7
12
|
type UseInFiniteProductsOptions = {
|
|
8
|
-
|
|
13
|
+
/** Item-level refs (productId + optional variantId). Use this for multi-variant support. */
|
|
14
|
+
initialItems?: WishlistItemRef[];
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Use initialItems instead. If initialItems is not provided, these are converted to initialItems (with variantIds by position).
|
|
17
|
+
*/
|
|
18
|
+
initialProductIds?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Use initialItems instead. When using with initialProductIds, same-length array by position.
|
|
21
|
+
*/
|
|
22
|
+
variantIds?: string[];
|
|
9
23
|
chunkSize: number;
|
|
10
24
|
apiUrl: string;
|
|
11
25
|
shouldMock: boolean;
|
|
12
26
|
queryVariables?: QueryVariables;
|
|
13
|
-
|
|
27
|
+
};
|
|
28
|
+
/** Return type of useInfiniteWishlist. Do not remove fields — forked blocks may depend on them. */
|
|
29
|
+
export type UseInfiniteWishlistResult = {
|
|
30
|
+
products: Product[];
|
|
31
|
+
isLoading: boolean;
|
|
32
|
+
isLoadingMore: boolean;
|
|
33
|
+
error: Error | null;
|
|
34
|
+
hasMore: boolean;
|
|
35
|
+
loadMore: () => Promise<void>;
|
|
36
|
+
loadMoreRef: (node?: Element | null) => void;
|
|
37
|
+
reset: () => void;
|
|
14
38
|
};
|
|
15
39
|
type ProductVariant = {
|
|
16
40
|
id: string;
|
|
@@ -49,15 +73,6 @@ type Product = {
|
|
|
49
73
|
height: number;
|
|
50
74
|
};
|
|
51
75
|
};
|
|
52
|
-
export declare function useInfiniteWishlist(
|
|
53
|
-
products: Product[];
|
|
54
|
-
isLoading: boolean;
|
|
55
|
-
isLoadingMore: boolean;
|
|
56
|
-
error: Error | null;
|
|
57
|
-
hasMore: boolean;
|
|
58
|
-
loadMore: () => Promise<void>;
|
|
59
|
-
loadMoreRef: (node?: Element | null | undefined) => void;
|
|
60
|
-
reset: () => void;
|
|
61
|
-
};
|
|
76
|
+
export declare function useInfiniteWishlist(options: UseInFiniteProductsOptions): UseInfiniteWishlistResult;
|
|
62
77
|
export {};
|
|
63
78
|
//# sourceMappingURL=use-infinite-wishlist.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-infinite-wishlist.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-wishlist.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-infinite-wishlist.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-wishlist.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,eAAe,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvE,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,kGAAkG;AAClG,KAAK,0BAA0B,GAAG;IAChC,4FAA4F;IAC5F,YAAY,CAAC,EAAE,eAAe,EAAE,CAAA;IAChC;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC,CAAA;AAED,mGAAmG;AACnG,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,aAAa,EAAE,OAAO,CAAA;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7B,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAA;IAC5C,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,cAAc,EAAE;QACd,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,gBAAgB,EAAE,OAAO,CAAA;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,KAAK,CAAC;QACrB,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;IACF,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF,CAAA;AAED,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,OAAO,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,aAAa,CAAC,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF,CAAA;AAgDD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,yBAAyB,CAmW3B"}
|
|
@@ -8,20 +8,53 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
import {
|
|
11
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
12
12
|
import { useInView } from "react-intersection-observer";
|
|
13
|
-
import { getProductGidsFromIds } from "../../lib/utils";
|
|
13
|
+
import { getProductGidsFromIds, getVariantGidsFromIds } from "../../lib/utils";
|
|
14
14
|
import { useCollection } from "./use-collection";
|
|
15
15
|
const extractVariantId = (fullId) => fullId.split("/").pop() || "";
|
|
16
|
-
|
|
16
|
+
const ensureVariantGID = (id) => getVariantGidsFromIds([id])[0];
|
|
17
|
+
const toItemKey = (item) => item.variantId
|
|
18
|
+
? ensureVariantGID(item.variantId)
|
|
19
|
+
: getProductGidsFromIds([item.productId])[0];
|
|
20
|
+
/** Unique key for a product card: variant GID when narrowed to one variant, else product GID. */
|
|
21
|
+
const getProductOrVariantKey = (p) => { var _a; return ((_a = p === null || p === void 0 ? void 0 : p.variants) === null || _a === void 0 ? void 0 : _a.length) === 1 ? p.variants[0].id : p.id; };
|
|
22
|
+
const buildIdSnapshot = (ids) => ({
|
|
23
|
+
ids,
|
|
24
|
+
key: ids.join("\0"),
|
|
25
|
+
set: new Set(ids),
|
|
26
|
+
indexMap: new Map(ids.map((id, i) => [id, i])),
|
|
27
|
+
});
|
|
28
|
+
/** Normalize options: prefer initialItems; fall back to legacy initialProductIds + variantIds. */
|
|
29
|
+
function normalizeInitialItems(options) {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
if (options.initialItems != null && Array.isArray(options.initialItems)) {
|
|
32
|
+
return options.initialItems;
|
|
33
|
+
}
|
|
34
|
+
const ids = (_a = options.initialProductIds) !== null && _a !== void 0 ? _a : [];
|
|
35
|
+
const variantIds = (_b = options.variantIds) !== null && _b !== void 0 ? _b : [];
|
|
36
|
+
return ids.map((productId, i) => ({
|
|
37
|
+
productId,
|
|
38
|
+
variantId: variantIds[i],
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
export function useInfiniteWishlist(options) {
|
|
17
42
|
var _a;
|
|
43
|
+
const { chunkSize, apiUrl, shouldMock = false, queryVariables = {} } = options;
|
|
44
|
+
const initialItems = normalizeInitialItems(options);
|
|
18
45
|
const isInitialMount = useRef(true);
|
|
19
|
-
const
|
|
46
|
+
const itemKeys = initialItems.map(toItemKey);
|
|
47
|
+
const prevSnapshotRef = useRef(buildIdSnapshot(itemKeys));
|
|
48
|
+
const loadedIndexRef = useRef(0);
|
|
49
|
+
const [allItemKeys, setAllItemKeys] = useState(itemKeys);
|
|
20
50
|
const [loadedIndex, setLoadedIndex] = useState(0);
|
|
21
51
|
const [products, setProducts] = useState([]);
|
|
22
52
|
const [isLoading, setIsLoading] = useState(false);
|
|
23
53
|
const [error, setError] = useState(null);
|
|
24
54
|
const loadingRef = useRef(false);
|
|
55
|
+
// Kept in sync via a dedicated effect so loadMore callbacks can detect
|
|
56
|
+
// whether the wishlist changed while an async fetch was in-flight.
|
|
57
|
+
const allItemKeysRef = useRef(allItemKeys);
|
|
25
58
|
//Fetching collections are necessary only for the mock data. Since we pass the collectionId to the API, it will return the products for the collection.
|
|
26
59
|
const { collections } = useCollection({
|
|
27
60
|
apiUrl: apiUrl,
|
|
@@ -32,16 +65,83 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
32
65
|
limit: 1,
|
|
33
66
|
});
|
|
34
67
|
const collectionToFetchID = (_a = collections[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
68
|
+
// Keep loadedIndexRef in sync so the delta-detection effect below can read
|
|
69
|
+
// the current value without adding loadedIndex as a dependency (which would
|
|
70
|
+
// cause the effect to re-run on every pagination step).
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
loadedIndexRef.current = loadedIndex;
|
|
73
|
+
}, [loadedIndex]);
|
|
74
|
+
// Keep allItemKeysRef in sync so in-flight loadMore callbacks can bail out
|
|
75
|
+
// when the wishlist changes before their fetch completes.
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
allItemKeysRef.current = allItemKeys;
|
|
78
|
+
}, [allItemKeys]);
|
|
79
|
+
// Stable key so the delta effect runs only when list content changes, not on every
|
|
80
|
+
// new initialItems reference (avoids CPU spike from repeated effect runs after removal).
|
|
81
|
+
const itemKeysKey = useMemo(() => initialItems.map(toItemKey).join("\0"), [initialItems]);
|
|
35
82
|
useEffect(() => {
|
|
83
|
+
var _a;
|
|
84
|
+
const nextKeys = initialItems.map(toItemKey);
|
|
36
85
|
if (isInitialMount.current) {
|
|
37
86
|
isInitialMount.current = false;
|
|
87
|
+
prevSnapshotRef.current = buildIdSnapshot(nextKeys);
|
|
88
|
+
return;
|
|
38
89
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
90
|
+
// Webbridge data has no stable refs (JSON deserialization always produces
|
|
91
|
+
// new objects). Build a snapshot for the incoming item keys so all
|
|
92
|
+
// comparisons use O(1) Set/Map lookups rather than repeated array walks.
|
|
93
|
+
const prev = prevSnapshotRef.current;
|
|
94
|
+
const next = buildIdSnapshot(nextKeys);
|
|
95
|
+
prevSnapshotRef.current = next;
|
|
96
|
+
// O(1) same-content check via precomputed key — avoids walking the array
|
|
97
|
+
// on every variables/updated notification (cart, customer, etc.).
|
|
98
|
+
if (next.key === prev.key)
|
|
99
|
+
return;
|
|
100
|
+
const isPureRemoval = next.ids.length < prev.ids.length &&
|
|
101
|
+
next.ids.every((id) => prev.set.has(id)); // O(1) per lookup
|
|
102
|
+
const currentLoadedIndex = loadedIndexRef.current;
|
|
103
|
+
const isPureAddition = next.ids.length > prev.ids.length &&
|
|
104
|
+
prev.ids.every((id) => next.set.has(id));
|
|
105
|
+
if (isPureRemoval) {
|
|
106
|
+
// Filter removed items out of the current list without resetting,
|
|
107
|
+
// so the grid never goes to skeleton for a simple item removal.
|
|
108
|
+
const removedKeys = new Set(prev.ids.filter((k) => !next.set.has(k)));
|
|
109
|
+
setProducts((curr) => curr.filter((p) => !removedKeys.has(getProductOrVariantKey(p))));
|
|
110
|
+
setAllItemKeys(next.ids);
|
|
111
|
+
// Recalculate loadedIndex: count surviving keys that were already in the
|
|
112
|
+
// loaded range of the old array. O(1) per lookup via prev.indexMap.
|
|
113
|
+
const newLoadedIndex = next.ids.filter((id) => { var _a; return ((_a = prev.indexMap.get(id)) !== null && _a !== void 0 ? _a : Infinity) < currentLoadedIndex; }).length;
|
|
114
|
+
setLoadedIndex(newLoadedIndex);
|
|
115
|
+
return;
|
|
43
116
|
}
|
|
44
|
-
|
|
117
|
+
if (isPureAddition) {
|
|
118
|
+
// Walk next.ids from the start to find the new contiguous loaded prefix.
|
|
119
|
+
// We stop at the first ID that either (a) wasn't fetched yet in the old
|
|
120
|
+
// list or (b) is one of the newly added items. Everything from that point
|
|
121
|
+
// onwards will be picked up by the next loadMore.
|
|
122
|
+
let newLoadedIndex = 0;
|
|
123
|
+
for (const id of next.ids) {
|
|
124
|
+
if (prev.set.has(id) &&
|
|
125
|
+
((_a = prev.indexMap.get(id)) !== null && _a !== void 0 ? _a : Infinity) < currentLoadedIndex) {
|
|
126
|
+
newLoadedIndex++;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
setAllItemKeys(next.ids);
|
|
133
|
+
setLoadedIndex(newLoadedIndex);
|
|
134
|
+
// products are unchanged — scroll position preserved, no skeleton.
|
|
135
|
+
// The inView effect re-evaluates after these state updates and will
|
|
136
|
+
// auto-trigger loadMore if the sentinel is already in view.
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
setAllItemKeys(next.ids);
|
|
140
|
+
setLoadedIndex(0);
|
|
141
|
+
setProducts([]);
|
|
142
|
+
// Intentionally depend on itemKeysKey (not initialItems) so we only run when list content changes, not on every new array ref
|
|
143
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
144
|
+
}, [itemKeysKey]);
|
|
45
145
|
const handleFetchError = (err, context) => {
|
|
46
146
|
const error = err instanceof Error ? err : new Error(`Failed to ${context}`);
|
|
47
147
|
setError(error);
|
|
@@ -84,14 +184,13 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
84
184
|
queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.country,
|
|
85
185
|
queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.appId,
|
|
86
186
|
]);
|
|
87
|
-
const fetchProducts = useCallback((
|
|
88
|
-
if (!
|
|
187
|
+
const fetchProducts = useCallback((chunkItemKeys, chunkProductGids) => __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
if (!chunkItemKeys.length)
|
|
89
189
|
return [];
|
|
90
190
|
if (shouldMock)
|
|
91
191
|
return fetchMockedProducts();
|
|
92
192
|
const queryParams = new URLSearchParams();
|
|
93
|
-
queryParams.set("ids",
|
|
94
|
-
// Add country and language parameters for correct currency/pricing
|
|
193
|
+
queryParams.set("ids", chunkProductGids.join(","));
|
|
95
194
|
if (queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.country) {
|
|
96
195
|
queryParams.set("country", queryVariables.country);
|
|
97
196
|
}
|
|
@@ -104,36 +203,47 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
104
203
|
if (!response.ok) {
|
|
105
204
|
throw new Error(`HTTP error: ${response.status}`);
|
|
106
205
|
}
|
|
107
|
-
const products = yield response.json();
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
206
|
+
const products = (yield response.json());
|
|
207
|
+
// One card per item key, in chunkItemKeys order. Variant keys get
|
|
208
|
+
// product narrowed to that variant; product keys get product as-is.
|
|
209
|
+
const keyVariantId = (k) => { var _a; return (_a = k.split("/").pop()) !== null && _a !== void 0 ? _a : k; };
|
|
210
|
+
return chunkItemKeys
|
|
211
|
+
.map((key) => {
|
|
212
|
+
var _a;
|
|
213
|
+
const isVariantKey = key.includes("ProductVariant");
|
|
214
|
+
if (isVariantKey) {
|
|
215
|
+
const keyId = keyVariantId(key);
|
|
112
216
|
const product = products.find((p) => {
|
|
113
217
|
var _a;
|
|
114
|
-
return (_a = p.variants) === null || _a === void 0 ? void 0 : _a.some((v) =>
|
|
218
|
+
return (_a = p.variants) === null || _a === void 0 ? void 0 : _a.some((v) => v.id === key || keyVariantId(v.id) === keyId);
|
|
115
219
|
});
|
|
116
220
|
if (!product)
|
|
117
221
|
return null;
|
|
118
|
-
const matchingVariant = (_a = product.variants) === null || _a === void 0 ? void 0 : _a.find((v) =>
|
|
222
|
+
const matchingVariant = (_a = product.variants) === null || _a === void 0 ? void 0 : _a.find((v) => v.id === key || keyVariantId(v.id) === keyId);
|
|
119
223
|
if (!matchingVariant)
|
|
120
224
|
return null;
|
|
121
225
|
return Object.assign(Object.assign({}, product), { variants: [matchingVariant] });
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
226
|
+
}
|
|
227
|
+
const product = products.find((p) => p.id === key);
|
|
228
|
+
return product !== null && product !== void 0 ? product : null;
|
|
229
|
+
})
|
|
230
|
+
.filter((p) => p !== null);
|
|
126
231
|
}
|
|
127
232
|
catch (err) {
|
|
128
233
|
handleFetchError(err, "fetch products");
|
|
129
234
|
return [];
|
|
130
235
|
}
|
|
131
|
-
}), [apiUrl, shouldMock, fetchMockedProducts,
|
|
236
|
+
}), [apiUrl, shouldMock, fetchMockedProducts, queryVariables]);
|
|
237
|
+
const itemKeyToProductGid = useMemo(() => new Map(initialItems.map((item) => [
|
|
238
|
+
toItemKey(item),
|
|
239
|
+
getProductGidsFromIds([item.productId])[0],
|
|
240
|
+
])), [initialItems]);
|
|
132
241
|
const loadMore = useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
|
133
242
|
if (loadingRef.current ||
|
|
134
|
-
(!shouldMock && !(
|
|
243
|
+
(!shouldMock && !(allItemKeys.length - loadedIndex > 0))) {
|
|
135
244
|
return;
|
|
136
245
|
}
|
|
246
|
+
const capturedAllItemKeys = allItemKeysRef.current;
|
|
137
247
|
loadingRef.current = true;
|
|
138
248
|
setIsLoading(true);
|
|
139
249
|
try {
|
|
@@ -145,13 +255,25 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
145
255
|
}
|
|
146
256
|
}
|
|
147
257
|
else {
|
|
148
|
-
const remainingItems =
|
|
258
|
+
const remainingItems = allItemKeys.length - loadedIndex;
|
|
149
259
|
const loadCount = Math.min(remainingItems, chunkSize);
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
260
|
+
const chunkItemKeys = allItemKeys.slice(loadedIndex, loadedIndex + loadCount);
|
|
261
|
+
if (chunkItemKeys.length === 0)
|
|
152
262
|
return;
|
|
153
|
-
const
|
|
154
|
-
|
|
263
|
+
const chunkProductGids = Array.from(new Set(chunkItemKeys.map((k) => itemKeyToProductGid.get(k))));
|
|
264
|
+
const newProducts = yield fetchProducts(chunkItemKeys, chunkProductGids);
|
|
265
|
+
if (allItemKeysRef.current !== capturedAllItemKeys)
|
|
266
|
+
return;
|
|
267
|
+
setProducts((prev) => {
|
|
268
|
+
const merged = new Map(prev.map((p) => [getProductOrVariantKey(p), p]));
|
|
269
|
+
for (let i = 0; i < newProducts.length; i++) {
|
|
270
|
+
merged.set(chunkItemKeys[i], newProducts[i]);
|
|
271
|
+
}
|
|
272
|
+
return capturedAllItemKeys.flatMap((key) => {
|
|
273
|
+
const p = merged.get(key);
|
|
274
|
+
return p ? [p] : [];
|
|
275
|
+
});
|
|
276
|
+
});
|
|
155
277
|
setLoadedIndex((prev) => prev + loadCount);
|
|
156
278
|
}
|
|
157
279
|
}
|
|
@@ -164,11 +286,12 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
164
286
|
}
|
|
165
287
|
}), [
|
|
166
288
|
shouldMock,
|
|
167
|
-
|
|
289
|
+
allItemKeys,
|
|
168
290
|
loadedIndex,
|
|
169
291
|
chunkSize,
|
|
170
292
|
fetchProducts,
|
|
171
293
|
fetchMockedProducts,
|
|
294
|
+
itemKeyToProductGid,
|
|
172
295
|
]);
|
|
173
296
|
useEffect(() => {
|
|
174
297
|
if (shouldMock && collectionToFetchID && products.length === 0) {
|
|
@@ -182,16 +305,14 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
182
305
|
useEffect(() => {
|
|
183
306
|
if (inView &&
|
|
184
307
|
!loadingRef.current &&
|
|
185
|
-
(shouldMock
|
|
186
|
-
? products.length < 2
|
|
187
|
-
: allProductIds.length - loadedIndex > 0)) {
|
|
308
|
+
(shouldMock ? products.length < 2 : allItemKeys.length - loadedIndex > 0)) {
|
|
188
309
|
loadMore();
|
|
189
310
|
}
|
|
190
311
|
}, [
|
|
191
312
|
inView,
|
|
192
313
|
shouldMock,
|
|
193
314
|
products.length,
|
|
194
|
-
|
|
315
|
+
allItemKeys.length,
|
|
195
316
|
loadedIndex,
|
|
196
317
|
loadMore,
|
|
197
318
|
]);
|
|
@@ -202,7 +323,7 @@ export function useInfiniteWishlist({ initialProductIds, chunkSize, apiUrl, shou
|
|
|
202
323
|
error,
|
|
203
324
|
hasMore: shouldMock
|
|
204
325
|
? products.length < 2
|
|
205
|
-
:
|
|
326
|
+
: allItemKeys.length - loadedIndex > 0,
|
|
206
327
|
loadMore,
|
|
207
328
|
loadMoreRef,
|
|
208
329
|
reset: () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-infinite-wishlist.test.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-wishlist.test.ts"],"names":[],"mappings":""}
|