@wix/headless-stores 0.0.56 → 0.0.58
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/cjs/dist/react/Category.d.ts +1 -0
- package/cjs/dist/react/Category.js +11 -22
- package/cjs/dist/react/CategoryList.js +2 -3
- package/cjs/dist/react/Product.d.ts +73 -30
- package/cjs/dist/react/Product.js +27 -145
- package/cjs/dist/react/ProductList.d.ts +9 -4
- package/cjs/dist/react/ProductList.js +4 -32
- package/cjs/dist/react/ProductListSort.d.ts +14 -0
- package/cjs/dist/react/ProductListSort.js +14 -0
- package/cjs/dist/react/core/ProductList.d.ts +3 -0
- package/cjs/dist/react/core/ProductList.js +2 -0
- package/cjs/dist/react/core/ProductListFilters.d.ts +8 -180
- package/cjs/dist/react/core/ProductListFilters.js +137 -171
- package/cjs/dist/react/core/ProductListPagination.d.ts +0 -192
- package/cjs/dist/react/core/ProductListPagination.js +2 -160
- package/cjs/dist/react/core/ProductListSort.d.ts +9 -57
- package/cjs/dist/react/core/ProductListSort.js +32 -52
- package/cjs/dist/react/core/SelectedVariant.js +2 -2
- package/cjs/dist/services/index.d.ts +2 -2
- package/cjs/dist/services/products-list-search-service.d.ts +3 -162
- package/cjs/dist/services/products-list-search-service.js +31 -424
- package/cjs/dist/services/products-list-service.d.ts +86 -4
- package/cjs/dist/services/products-list-service.js +125 -4
- package/cjs/dist/utils/renderChildren.d.ts +2 -1
- package/cjs/dist/utils/renderChildren.js +5 -2
- package/dist/react/Category.d.ts +1 -0
- package/dist/react/Category.js +11 -22
- package/dist/react/CategoryList.js +2 -3
- package/dist/react/Product.d.ts +73 -30
- package/dist/react/Product.js +27 -145
- package/dist/react/ProductList.d.ts +9 -4
- package/dist/react/ProductList.js +4 -32
- package/dist/react/ProductListSort.d.ts +14 -0
- package/dist/react/ProductListSort.js +14 -0
- package/dist/react/core/ProductList.d.ts +3 -0
- package/dist/react/core/ProductList.js +2 -0
- package/dist/react/core/ProductListFilters.d.ts +8 -180
- package/dist/react/core/ProductListFilters.js +137 -171
- package/dist/react/core/ProductListPagination.d.ts +0 -192
- package/dist/react/core/ProductListPagination.js +2 -160
- package/dist/react/core/ProductListSort.d.ts +9 -57
- package/dist/react/core/ProductListSort.js +32 -52
- package/dist/react/core/SelectedVariant.js +2 -2
- package/dist/services/index.d.ts +2 -2
- package/dist/services/products-list-search-service.d.ts +3 -162
- package/dist/services/products-list-search-service.js +31 -424
- package/dist/services/products-list-service.d.ts +86 -4
- package/dist/services/products-list-service.js +125 -4
- package/dist/utils/renderChildren.d.ts +2 -1
- package/dist/utils/renderChildren.js +5 -2
- package/package.json +4 -3
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
2
2
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
3
|
-
import { productsV3, readOnlyVariantsV3 } from '@wix/stores';
|
|
3
|
+
import { customizationsV3, productsV3, readOnlyVariantsV3 } from '@wix/stores';
|
|
4
4
|
import { loadCategoriesListServiceConfig } from './categories-list-service.js';
|
|
5
|
-
import { parseUrlToSearchOptions, } from './products-list-search-service.js';
|
|
5
|
+
import { InventoryStatusType, parseUrlToSearchOptions, } from './products-list-search-service.js';
|
|
6
6
|
export const DEFAULT_QUERY_LIMIT = 100;
|
|
7
7
|
/**
|
|
8
8
|
* Loads products list service configuration from the Wix Stores API for SSR initialization.
|
|
@@ -118,10 +118,13 @@ export const DEFAULT_QUERY_LIMIT = 100;
|
|
|
118
118
|
*/
|
|
119
119
|
export async function loadProductsListServiceConfig(input) {
|
|
120
120
|
let searchOptions;
|
|
121
|
+
const { items: customizations = [] } = await customizationsV3
|
|
122
|
+
.queryCustomizations()
|
|
123
|
+
.find();
|
|
121
124
|
if (typeof input === 'string') {
|
|
122
125
|
// URL input - parse it
|
|
123
126
|
const categoriesListConfig = await loadCategoriesListServiceConfig();
|
|
124
|
-
const { searchOptions: parsedOptions } = await parseUrlToSearchOptions(input, categoriesListConfig.categories);
|
|
127
|
+
const { searchOptions: parsedOptions } = await parseUrlToSearchOptions(input, categoriesListConfig.categories, customizations);
|
|
125
128
|
searchOptions = parsedOptions;
|
|
126
129
|
}
|
|
127
130
|
else {
|
|
@@ -139,6 +142,7 @@ export async function loadProductsListServiceConfig(input) {
|
|
|
139
142
|
searchOptions,
|
|
140
143
|
pagingMetadata: resultWithFilter.pagingMetadata,
|
|
141
144
|
aggregations: resultWithoutFilter.aggregationData ?? {},
|
|
145
|
+
customizations,
|
|
142
146
|
};
|
|
143
147
|
}
|
|
144
148
|
/**
|
|
@@ -292,6 +296,14 @@ export const ProductListService = implementService.withConfig()(ProductsListServ
|
|
|
292
296
|
const productsSignal = signalsService.signal(config.products);
|
|
293
297
|
const searchOptionsSignal = signalsService.signal(config.searchOptions);
|
|
294
298
|
const pagingMetadataSignal = signalsService.signal(config.pagingMetadata);
|
|
299
|
+
const minPriceSignal = signalsService.signal(getMinPrice(config.aggregations.results));
|
|
300
|
+
const maxPriceSignal = signalsService.signal(getMaxPrice(config.aggregations.results));
|
|
301
|
+
const availableProductOptionsSignal = signalsService.signal(getAvailableProductOptions(config.aggregations.results, config.customizations));
|
|
302
|
+
const availableInventoryStatusesSignal = signalsService.signal([
|
|
303
|
+
InventoryStatusType.IN_STOCK,
|
|
304
|
+
InventoryStatusType.OUT_OF_STOCK,
|
|
305
|
+
InventoryStatusType.PARTIALLY_OUT_OF_STOCK,
|
|
306
|
+
]);
|
|
295
307
|
const aggregationsSignal = signalsService.signal(config.aggregations);
|
|
296
308
|
const isLoadingSignal = signalsService.signal(false);
|
|
297
309
|
const errorSignal = signalsService.signal(null);
|
|
@@ -331,7 +343,15 @@ export const ProductListService = implementService.withConfig()(ProductsListServ
|
|
|
331
343
|
searchOptions: searchOptionsSignal,
|
|
332
344
|
pagingMetadata: pagingMetadataSignal,
|
|
333
345
|
aggregations: aggregationsSignal,
|
|
334
|
-
|
|
346
|
+
/* Metadata for products list */
|
|
347
|
+
minPrice: minPriceSignal,
|
|
348
|
+
maxPrice: maxPriceSignal,
|
|
349
|
+
availableInventoryStatuses: availableInventoryStatusesSignal,
|
|
350
|
+
availableProductOptions: availableProductOptionsSignal,
|
|
351
|
+
/* End of Metadata for products list */
|
|
352
|
+
setSearchOptions: (searchOptions) => {
|
|
353
|
+
searchOptionsSignal.set(searchOptions);
|
|
354
|
+
},
|
|
335
355
|
setSort: (sort) => {
|
|
336
356
|
const currentOptions = searchOptionsSignal.peek();
|
|
337
357
|
searchOptionsSignal.set({
|
|
@@ -346,7 +366,108 @@ export const ProductListService = implementService.withConfig()(ProductsListServ
|
|
|
346
366
|
filter,
|
|
347
367
|
});
|
|
348
368
|
},
|
|
369
|
+
resetFilter: () => {
|
|
370
|
+
const currentOptions = searchOptionsSignal.peek();
|
|
371
|
+
searchOptionsSignal.set({
|
|
372
|
+
...currentOptions,
|
|
373
|
+
filter: {},
|
|
374
|
+
});
|
|
375
|
+
},
|
|
376
|
+
isFiltered: () => {
|
|
377
|
+
return signalsService.computed(() => {
|
|
378
|
+
const currentOptions = searchOptionsSignal.peek();
|
|
379
|
+
if (!currentOptions.filter)
|
|
380
|
+
return false;
|
|
381
|
+
return (currentOptions.filter !== undefined &&
|
|
382
|
+
Object.keys(currentOptions.filter).length > 0);
|
|
383
|
+
});
|
|
384
|
+
},
|
|
349
385
|
isLoading: isLoadingSignal,
|
|
350
386
|
error: errorSignal,
|
|
387
|
+
loadMore: (count) => {
|
|
388
|
+
const currentOptions = searchOptionsSignal.peek();
|
|
389
|
+
searchOptionsSignal.set({
|
|
390
|
+
...currentOptions,
|
|
391
|
+
cursorPaging: {
|
|
392
|
+
cursor: pagingMetadataSignal.get().cursors?.next,
|
|
393
|
+
limit: currentOptions.cursorPaging?.limit ?? 0 + count,
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
},
|
|
397
|
+
hasMoreProducts: signalsService.computed(() => pagingMetadataSignal.get().hasNext ?? false),
|
|
351
398
|
};
|
|
352
399
|
});
|
|
400
|
+
function getMinPrice(aggregationData) {
|
|
401
|
+
const minPriceAggregation = aggregationData.find((data) => data.fieldPath === 'actualPriceRange.minValue.amount');
|
|
402
|
+
if (minPriceAggregation?.scalar?.value) {
|
|
403
|
+
return Number(minPriceAggregation.scalar.value) || 0;
|
|
404
|
+
}
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
function getMaxPrice(aggregationData) {
|
|
408
|
+
const maxPriceAggregation = aggregationData.find((data) => data.fieldPath === 'actualPriceRange.maxValue.amount');
|
|
409
|
+
if (maxPriceAggregation?.scalar?.value) {
|
|
410
|
+
return Number(maxPriceAggregation.scalar.value) || 0;
|
|
411
|
+
}
|
|
412
|
+
return 0;
|
|
413
|
+
}
|
|
414
|
+
function getAvailableProductOptions(aggregationData = [], customizations = []) {
|
|
415
|
+
const matchesAggregationName = (name, aggregationNames) => {
|
|
416
|
+
return aggregationNames.some((aggName) => aggName.toLowerCase() === name.toLowerCase());
|
|
417
|
+
};
|
|
418
|
+
const sortChoicesIntelligently = (choices) => {
|
|
419
|
+
return [...choices].sort((a, b) => {
|
|
420
|
+
const aIsNumber = /^\d+$/.test(a.name);
|
|
421
|
+
const bIsNumber = /^\d+$/.test(b.name);
|
|
422
|
+
if (aIsNumber && bIsNumber) {
|
|
423
|
+
return parseInt(a.name) - parseInt(b.name);
|
|
424
|
+
}
|
|
425
|
+
if (aIsNumber && !bIsNumber)
|
|
426
|
+
return -1;
|
|
427
|
+
if (!aIsNumber && bIsNumber)
|
|
428
|
+
return 1;
|
|
429
|
+
return a.name.localeCompare(b.name);
|
|
430
|
+
});
|
|
431
|
+
};
|
|
432
|
+
const optionNames = [];
|
|
433
|
+
const choiceNames = [];
|
|
434
|
+
aggregationData.forEach((result) => {
|
|
435
|
+
if (result.name === 'optionNames' && result.values?.results) {
|
|
436
|
+
optionNames.push(...result.values.results
|
|
437
|
+
.map((item) => item.value)
|
|
438
|
+
.filter((value) => typeof value === 'string'));
|
|
439
|
+
}
|
|
440
|
+
if (result.name === 'choiceNames' && result.values?.results) {
|
|
441
|
+
choiceNames.push(...result.values.results
|
|
442
|
+
.map((item) => item.value)
|
|
443
|
+
.filter((value) => typeof value === 'string'));
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
const options = customizations
|
|
447
|
+
.filter((customization) => customization.name &&
|
|
448
|
+
customization._id &&
|
|
449
|
+
customization.customizationType ===
|
|
450
|
+
customizationsV3.CustomizationType.PRODUCT_OPTION &&
|
|
451
|
+
(optionNames.length === 0 ||
|
|
452
|
+
matchesAggregationName(customization.name, optionNames)))
|
|
453
|
+
.map((customization) => {
|
|
454
|
+
const choices = (customization.choicesSettings?.choices || [])
|
|
455
|
+
.filter((choice) => choice._id &&
|
|
456
|
+
choice.name &&
|
|
457
|
+
(choiceNames.length === 0 ||
|
|
458
|
+
matchesAggregationName(choice.name, choiceNames)))
|
|
459
|
+
.map((choice) => ({
|
|
460
|
+
id: choice._id,
|
|
461
|
+
name: choice.name,
|
|
462
|
+
colorCode: choice.colorCode,
|
|
463
|
+
}));
|
|
464
|
+
return {
|
|
465
|
+
id: customization._id,
|
|
466
|
+
name: customization.name,
|
|
467
|
+
choices: sortChoicesIntelligently(choices),
|
|
468
|
+
optionRenderType: customization.customizationRenderType,
|
|
469
|
+
};
|
|
470
|
+
})
|
|
471
|
+
.filter((option) => option.choices.length > 0);
|
|
472
|
+
return options;
|
|
473
|
+
}
|
|
@@ -9,6 +9,7 @@ export interface RenderChildrenParams<THTMLElement = HTMLElement, TProps = any>
|
|
|
9
9
|
props: TProps;
|
|
10
10
|
/** Ref to forward to the rendered element */
|
|
11
11
|
ref: React.Ref<THTMLElement>;
|
|
12
|
+
content?: string | null;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* Utility function to handle children rendering.
|
|
@@ -38,4 +39,4 @@ export interface RenderChildrenParams<THTMLElement = HTMLElement, TProps = any>
|
|
|
38
39
|
* });
|
|
39
40
|
* ```
|
|
40
41
|
*/
|
|
41
|
-
export declare function renderChildren<THTMLElement = HTMLElement, TProps = any>({ children, props, ref, }: RenderChildrenParams<THTMLElement, TProps>): React.ReactNode | null;
|
|
42
|
+
export declare function renderChildren<THTMLElement = HTMLElement, TProps = any>({ children, props, ref, content, }: RenderChildrenParams<THTMLElement, TProps>): React.ReactNode | null;
|
|
@@ -27,13 +27,16 @@ import React from 'react';
|
|
|
27
27
|
* });
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export function renderChildren({ children, props, ref, }) {
|
|
30
|
+
export function renderChildren({ children, props, ref, content, }) {
|
|
31
31
|
// Early return if no children provided
|
|
32
32
|
if (!children)
|
|
33
33
|
return null;
|
|
34
34
|
// Handle React element pattern
|
|
35
35
|
if (React.isValidElement(children)) {
|
|
36
|
-
return children
|
|
36
|
+
return React.cloneElement(children, {
|
|
37
|
+
ref,
|
|
38
|
+
...(content ? { children: content } : {}),
|
|
39
|
+
});
|
|
37
40
|
}
|
|
38
41
|
// Handle render function pattern
|
|
39
42
|
if (typeof children === 'function') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-stores",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.58",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prebuild": "cd ../media && yarn build && cd ../ecom && yarn build",
|
|
@@ -62,8 +62,9 @@
|
|
|
62
62
|
"@wix/auto_sdk_stores_read-only-variants-v-3": "^1.0.23",
|
|
63
63
|
"@wix/ecom": "^1.0.1278",
|
|
64
64
|
"@wix/essentials": "^0.1.24",
|
|
65
|
-
"@wix/headless-ecom": "
|
|
66
|
-
"@wix/headless-media": "^0.0.
|
|
65
|
+
"@wix/headless-ecom": "0.0.17",
|
|
66
|
+
"@wix/headless-media": "^0.0.11",
|
|
67
|
+
"@wix/headless-utils": "^0.0.1",
|
|
67
68
|
"@wix/redirects": "^1.0.83",
|
|
68
69
|
"@wix/services-definitions": "^0.1.4",
|
|
69
70
|
"@wix/services-manager-react": "^0.1.26"
|