@wix/headless-stores 0.0.57 → 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/ProductList.js +1 -0
- 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/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/dist/react/ProductList.js +1 -0
- 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/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/package.json +4 -4
|
@@ -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
|
+
}
|
|
@@ -48,6 +48,7 @@ export const Root = React.forwardRef((props, ref) => {
|
|
|
48
48
|
count: products?.length || 0,
|
|
49
49
|
},
|
|
50
50
|
aggregations: {}, // Empty aggregation data
|
|
51
|
+
customizations: [],
|
|
51
52
|
};
|
|
52
53
|
return (_jsx(CoreProductList.Root, { productsListConfig: serviceConfig, productsListSearchConfig: productsListSearchConfig, children: _jsx(RootContent, { children: children, className: className, ref: ref }) }));
|
|
53
54
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Sort as SortPrimitive } from '@wix/headless-components/react';
|
|
2
|
+
import { productsV3 } from '@wix/stores';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
export interface ProductListSortProps {
|
|
5
|
+
children?: (props: {
|
|
6
|
+
currentSort: productsV3.V3ProductSearch['sort'];
|
|
7
|
+
sortOptions: SortPrimitive.SortOption[];
|
|
8
|
+
setSort: (sort: productsV3.V3ProductSearch['sort']) => void;
|
|
9
|
+
}) => React.ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
as?: 'select' | 'list';
|
|
12
|
+
asChild?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const ProductListSort: React.ForwardRefExoticComponent<ProductListSortProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Sort as SortPrimitive } from '@wix/headless-components/react';
|
|
3
|
+
import { ProductListSort as ProductListSortPrimitive } from './core/ProductListSort.js';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export const ProductListSort = React.forwardRef(({ children, className, as, asChild }, ref) => {
|
|
6
|
+
return (_jsx(ProductListSortPrimitive, { children: ({ currentSort, sortOptions, setSort }) => {
|
|
7
|
+
if (asChild && children) {
|
|
8
|
+
return children({ currentSort, sortOptions, setSort });
|
|
9
|
+
}
|
|
10
|
+
return (_jsx(SortPrimitive.Root, { ref: ref, value: currentSort, onChange: (value) => {
|
|
11
|
+
setSort(value);
|
|
12
|
+
}, sortOptions: sortOptions, as: as, className: className }));
|
|
13
|
+
} }));
|
|
14
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ProductsListServiceConfig } from '../../services/products-list-service.js';
|
|
2
2
|
import { productsV3 } from '@wix/stores';
|
|
3
3
|
import { ProductsListSearchServiceConfig } from '../../services/products-list-search-service.js';
|
|
4
|
+
import { CategoriesListServiceConfig } from '../../services/categories-list-service.js';
|
|
4
5
|
/**
|
|
5
6
|
* Props for Root headless component
|
|
6
7
|
*/
|
|
@@ -11,6 +12,8 @@ export interface RootProps {
|
|
|
11
12
|
productsListConfig: ProductsListServiceConfig;
|
|
12
13
|
/** Configuration for the ProductListSearch service */
|
|
13
14
|
productsListSearchConfig?: ProductsListSearchServiceConfig;
|
|
15
|
+
/** Configuration for the CategoriesList service */
|
|
16
|
+
categoriesListConfig?: CategoriesListServiceConfig;
|
|
14
17
|
}
|
|
15
18
|
/**
|
|
16
19
|
* Root component that provides both ProductList and ProductListSearch service contexts to its children.
|
|
@@ -4,6 +4,7 @@ import { createServicesMap } from '@wix/services-manager';
|
|
|
4
4
|
import { ProductListService, ProductsListServiceDefinition, } from '../../services/products-list-service.js';
|
|
5
5
|
import { ProductService, ProductServiceDefinition, } from '../../services/product-service.js';
|
|
6
6
|
import { ProductsListSearchService, ProductsListSearchServiceDefinition, } from '../../services/products-list-search-service.js';
|
|
7
|
+
import { CategoriesListService, CategoriesListServiceDefinition, } from '../../services/categories-list-service.js';
|
|
7
8
|
/**
|
|
8
9
|
* Root component that provides both ProductList and ProductListSearch service contexts to its children.
|
|
9
10
|
* This component sets up the necessary services for managing products list state, including search,
|
|
@@ -64,6 +65,7 @@ import { ProductsListSearchService, ProductsListSearchServiceDefinition, } from
|
|
|
64
65
|
*/
|
|
65
66
|
export function Root(props) {
|
|
66
67
|
return (_jsx(WixServices, { servicesMap: createServicesMap()
|
|
68
|
+
.addService(CategoriesListServiceDefinition, CategoriesListService, props.categoriesListConfig)
|
|
67
69
|
.addService(ProductsListServiceDefinition, ProductListService, props.productsListConfig)
|
|
68
70
|
.addService(ProductsListSearchServiceDefinition, ProductsListSearchService, props.productsListSearchConfig), children: props.children }));
|
|
69
71
|
}
|
|
@@ -1,61 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import { type ProductOption, InventoryStatusType } from '../../services/products-list-search-service.js';
|
|
3
2
|
import { Category } from '@wix/auto_sdk_categories_categories';
|
|
4
|
-
|
|
5
|
-
* Props for InventoryStatus headless component
|
|
6
|
-
*/
|
|
7
|
-
export interface InventoryStatusProps {
|
|
8
|
-
/** Content to display (can be a render function receiving inventory status controls or ReactNode) */
|
|
9
|
-
children: ((props: InventoryStatusRenderProps) => ReactNode) | ReactNode;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Render props for InventoryStatus component
|
|
13
|
-
*/
|
|
14
|
-
export interface InventoryStatusRenderProps {
|
|
15
|
-
/** Available inventory status options */
|
|
16
|
-
availableInventoryStatuses: InventoryStatusType[];
|
|
17
|
-
/** Currently selected inventory statuses */
|
|
18
|
-
selectedInventoryStatuses: InventoryStatusType[];
|
|
19
|
-
/** Function to toggle an inventory status filter */
|
|
20
|
-
toggleInventoryStatus: (status: InventoryStatusType) => void;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Headless component for managing inventory status filters
|
|
24
|
-
*
|
|
25
|
-
* @component
|
|
26
|
-
* @example
|
|
27
|
-
* ```tsx
|
|
28
|
-
* import { ProductList, ProductListFilters } from '@wix/stores/components';
|
|
29
|
-
*
|
|
30
|
-
* function InventoryStatusFilter() {
|
|
31
|
-
* return (
|
|
32
|
-
* <ProductList.Root
|
|
33
|
-
* productsListConfig={{ products: [], searchOptions: {}, pagingMetadata: {}, aggregations: {} }}
|
|
34
|
-
* productsListSearchConfig={{ customizations: [] }}
|
|
35
|
-
* >
|
|
36
|
-
* <ProductListFilters.InventoryStatus>
|
|
37
|
-
* {({ availableInventoryStatuses, selectedInventoryStatuses, toggleInventoryStatus }) => (
|
|
38
|
-
* <div>
|
|
39
|
-
* <h4>Inventory Status:</h4>
|
|
40
|
-
* {availableInventoryStatuses.map(status => (
|
|
41
|
-
* <label key={status}>
|
|
42
|
-
* <input
|
|
43
|
-
* type="checkbox"
|
|
44
|
-
* checked={selectedInventoryStatuses.includes(status)}
|
|
45
|
-
* onChange={() => toggleInventoryStatus(status)}
|
|
46
|
-
* />
|
|
47
|
-
* {status}
|
|
48
|
-
* </label>
|
|
49
|
-
* ))}
|
|
50
|
-
* </div>
|
|
51
|
-
* )}
|
|
52
|
-
* </ProductListFilters.InventoryStatus>
|
|
53
|
-
* </ProductList.Root>
|
|
54
|
-
* );
|
|
55
|
-
* }
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export declare function InventoryStatus(props: InventoryStatusProps): ReactNode;
|
|
3
|
+
import React from 'react';
|
|
59
4
|
/**
|
|
60
5
|
* Props for ResetTrigger headless component
|
|
61
6
|
*/
|
|
@@ -103,136 +48,19 @@ export interface ResetTriggerRenderProps {
|
|
|
103
48
|
* ```
|
|
104
49
|
*/
|
|
105
50
|
export declare function ResetTrigger(props: ResetTriggerProps): ReactNode;
|
|
106
|
-
/**
|
|
107
|
-
* Props for PriceRange headless component
|
|
108
|
-
*/
|
|
109
|
-
export interface PriceRangeProps {
|
|
110
|
-
/** Content to display (can be a render function receiving price range controls or ReactNode) */
|
|
111
|
-
children: ((props: PriceRangeRenderProps) => ReactNode) | ReactNode;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Render props for PriceRange component
|
|
115
|
-
*/
|
|
116
|
-
export interface PriceRangeRenderProps {
|
|
117
|
-
/** Current minimum price filter value */
|
|
118
|
-
selectedMinPrice: number;
|
|
119
|
-
/** Current maximum price filter value */
|
|
120
|
-
selectedMaxPrice: number;
|
|
121
|
-
/** Catalog minimum price */
|
|
122
|
-
availableMinPrice: number;
|
|
123
|
-
/** Catalog maximum price */
|
|
124
|
-
availableMaxPrice: number;
|
|
125
|
-
/** Function to update the minimum price filter */
|
|
126
|
-
setSelectedMinPrice: (minPrice: number) => void;
|
|
127
|
-
/** Function to update the maximum price filter */
|
|
128
|
-
setSelectedMaxPrice: (maxPrice: number) => void;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Headless component for managing price range filters (combined min/max)
|
|
132
|
-
*
|
|
133
|
-
* @component
|
|
134
|
-
* @example
|
|
135
|
-
* ```tsx
|
|
136
|
-
* import { ProductList, ProductListFilters } from '@wix/stores/components';
|
|
137
|
-
*
|
|
138
|
-
* function PriceRangeFilter() {
|
|
139
|
-
* return (
|
|
140
|
-
* <ProductList.Root
|
|
141
|
-
* productsListConfig={{ products: [], searchOptions: {}, pagingMetadata: {}, aggregations: {} }}
|
|
142
|
-
* productsListSearchConfig={{ customizations: [] }}
|
|
143
|
-
* >
|
|
144
|
-
* <ProductListFilters.PriceRange>
|
|
145
|
-
* {({ minPrice, maxPrice, setSelectedMinPrice, setSelectedMaxPrice }) => (
|
|
146
|
-
* <div className="price-range">
|
|
147
|
-
* <h4>Price Range:</h4>
|
|
148
|
-
* <div className="price-inputs">
|
|
149
|
-
* <input
|
|
150
|
-
* type="number"
|
|
151
|
-
* value={minPrice}
|
|
152
|
-
* onChange={(e) => setSelectedMinPrice(Number(e.target.value))}
|
|
153
|
-
* placeholder="Min"
|
|
154
|
-
* />
|
|
155
|
-
* <span>to</span>
|
|
156
|
-
* <input
|
|
157
|
-
* type="number"
|
|
158
|
-
* value={maxPrice}
|
|
159
|
-
* onChange={(e) => setSelectedMaxPrice(Number(e.target.value))}
|
|
160
|
-
* placeholder="Max"
|
|
161
|
-
* />
|
|
162
|
-
* </div>
|
|
163
|
-
* </div>
|
|
164
|
-
* )}
|
|
165
|
-
* </ProductListFilters.PriceRange>
|
|
166
|
-
* </ProductList.Root>
|
|
167
|
-
* );
|
|
168
|
-
* }
|
|
169
|
-
* ```
|
|
170
|
-
*/
|
|
171
|
-
export declare function PriceRange(props: PriceRangeProps): ReactNode;
|
|
172
51
|
export interface CategoryFilterRenderProps {
|
|
173
52
|
selectedCategory: Category | null;
|
|
174
|
-
setSelectedCategory: (category: Category
|
|
53
|
+
setSelectedCategory: (category: Category) => void;
|
|
175
54
|
}
|
|
176
55
|
export interface CategoryFilterProps {
|
|
177
56
|
/** Content to display (can be a render function receiving category data or ReactNode) */
|
|
178
57
|
children: ((props: CategoryFilterRenderProps) => ReactNode) | ReactNode;
|
|
179
58
|
}
|
|
180
59
|
export declare function CategoryFilter(props: CategoryFilterProps): ReactNode;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
/** Content to display (can be a render function receiving product option data or ReactNode) */
|
|
186
|
-
children: ((props: ProductOptionRenderProps) => ReactNode) | ReactNode;
|
|
60
|
+
interface FilterProps {
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
asChild?: boolean;
|
|
63
|
+
className?: string;
|
|
187
64
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
*/
|
|
191
|
-
export interface ProductOptionRenderProps {
|
|
192
|
-
/** Product option data */
|
|
193
|
-
option: ProductOption;
|
|
194
|
-
/** Currently selected choice IDs for this option */
|
|
195
|
-
selectedChoices: string[];
|
|
196
|
-
/** Function to toggle a choice selection */
|
|
197
|
-
toggleChoice: (choiceId: string) => void;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Headless component that renders content for each product option in the list.
|
|
201
|
-
* Maps over all available product options and provides each option through a render prop.
|
|
202
|
-
* Only renders when options are available (not loading, no error, and has options).
|
|
203
|
-
* This follows the same collection pattern as ProductList.ItemContent and CategoryList.ItemContent.
|
|
204
|
-
*
|
|
205
|
-
* @component
|
|
206
|
-
* @example
|
|
207
|
-
* ```tsx
|
|
208
|
-
* import { ProductList, ProductListFilters } from '@wix/stores/components';
|
|
209
|
-
*
|
|
210
|
-
* function ProductOptionsFilter() {
|
|
211
|
-
* return (
|
|
212
|
-
* <ProductList.Root
|
|
213
|
-
* productsListConfig={{ products: [], searchOptions: {}, pagingMetadata: {}, aggregations: {} }}
|
|
214
|
-
* productsListSearchConfig={{ customizations: [] }}
|
|
215
|
-
* >
|
|
216
|
-
* <ProductListFilters.ProductOptions>
|
|
217
|
-
* {({ option, selectedChoices, toggleChoice }) => (
|
|
218
|
-
* <div key={option.id}>
|
|
219
|
-
* <h4>{option.name}</h4>
|
|
220
|
-
* {option.choices.map(choice => (
|
|
221
|
-
* <label key={choice.id}>
|
|
222
|
-
* <input
|
|
223
|
-
* type="checkbox"
|
|
224
|
-
* checked={selectedChoices.includes(choice.id)}
|
|
225
|
-
* onChange={() => toggleChoice(choice.id)}
|
|
226
|
-
* />
|
|
227
|
-
* {choice.name}
|
|
228
|
-
* </label>
|
|
229
|
-
* ))}
|
|
230
|
-
* </div>
|
|
231
|
-
* )}
|
|
232
|
-
* </ProductListFilters.ProductOptions>
|
|
233
|
-
* </ProductList.Root>
|
|
234
|
-
* );
|
|
235
|
-
* }
|
|
236
|
-
* ```
|
|
237
|
-
*/
|
|
238
|
-
export declare function ProductOptions(props: ProductOptionsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
65
|
+
export declare const Filter: React.ForwardRefExoticComponent<FilterProps & React.RefAttributes<HTMLDivElement>>;
|
|
66
|
+
export {};
|