@wix/headless-stores 0.0.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/astro/actions/package.json +4 -0
- package/cjs/dist/astro/actions/custom-checkout.d.ts +50 -0
- package/cjs/dist/astro/actions/custom-checkout.js +53 -0
- package/cjs/dist/astro/actions/index.d.ts +1 -0
- package/cjs/dist/astro/actions/index.js +1 -0
- package/cjs/dist/data-component-tags.d.ts +8 -0
- package/cjs/dist/data-component-tags.js +9 -0
- package/cjs/dist/enums/index.d.ts +2 -0
- package/cjs/dist/enums/index.js +2 -0
- package/cjs/dist/enums/social-platform-enums.d.ts +25 -0
- package/cjs/dist/enums/social-platform-enums.js +27 -0
- package/cjs/dist/enums/sort-enums.d.ts +17 -0
- package/cjs/dist/enums/sort-enums.js +18 -0
- package/cjs/dist/react/Category.d.ts +242 -0
- package/cjs/dist/react/Category.js +235 -0
- package/cjs/dist/react/CategoryList.d.ts +107 -0
- package/cjs/dist/react/CategoryList.js +91 -0
- package/cjs/dist/react/Choice.d.ts +211 -0
- package/cjs/dist/react/Choice.js +213 -0
- package/cjs/dist/react/Option.d.ts +242 -0
- package/cjs/dist/react/Option.js +346 -0
- package/cjs/dist/react/Product.d.ts +1065 -0
- package/cjs/dist/react/Product.js +1157 -0
- package/cjs/dist/react/ProductList.d.ts +400 -0
- package/cjs/dist/react/ProductList.js +368 -0
- package/cjs/dist/react/core/CategoryList.d.ts +194 -0
- package/cjs/dist/react/core/CategoryList.js +180 -0
- package/cjs/dist/react/core/Product.d.ts +225 -0
- package/cjs/dist/react/core/Product.js +190 -0
- package/cjs/dist/react/core/ProductList.d.ts +235 -0
- package/cjs/dist/react/core/ProductList.js +217 -0
- package/cjs/dist/react/core/ProductListFilters.d.ts +138 -0
- package/cjs/dist/react/core/ProductListFilters.js +242 -0
- package/cjs/dist/react/core/ProductListPagination.d.ts +49 -0
- package/cjs/dist/react/core/ProductListPagination.js +41 -0
- package/cjs/dist/react/core/ProductListSort.d.ts +19 -0
- package/cjs/dist/react/core/ProductListSort.js +52 -0
- package/cjs/dist/react/core/ProductModifiers.d.ts +416 -0
- package/cjs/dist/react/core/ProductModifiers.js +413 -0
- package/cjs/dist/react/core/ProductVariantSelector.d.ts +313 -0
- package/cjs/dist/react/core/ProductVariantSelector.js +291 -0
- package/cjs/dist/react/core/SelectedVariant.d.ts +230 -0
- package/cjs/dist/react/core/SelectedVariant.js +269 -0
- package/cjs/dist/react/index.d.ts +6 -0
- package/cjs/dist/react/index.js +6 -0
- package/cjs/dist/react/types.d.ts +8 -0
- package/cjs/dist/react/types.js +9 -0
- package/cjs/dist/server-actions/custom-checkout-action.d.ts +49 -0
- package/cjs/dist/server-actions/custom-checkout-action.js +64 -0
- package/cjs/dist/server-actions/index.d.ts +1 -0
- package/cjs/dist/server-actions/index.js +1 -0
- package/cjs/dist/services/buy-now-service.d.ts +346 -0
- package/cjs/dist/services/buy-now-service.js +197 -0
- package/cjs/dist/services/categories-list-service.d.ts +164 -0
- package/cjs/dist/services/categories-list-service.js +148 -0
- package/cjs/dist/services/index.d.ts +5 -0
- package/cjs/dist/services/index.js +5 -0
- package/cjs/dist/services/pay-now-service.d.ts +214 -0
- package/cjs/dist/services/pay-now-service.js +156 -0
- package/cjs/dist/services/product-modifiers-service.d.ts +34 -0
- package/cjs/dist/services/product-modifiers-service.js +107 -0
- package/cjs/dist/services/product-service.d.ts +177 -0
- package/cjs/dist/services/product-service.js +190 -0
- package/cjs/dist/services/products-list-search-service.d.ts +1 -0
- package/cjs/dist/services/products-list-search-service.js +1 -0
- package/cjs/dist/services/products-list-service.d.ts +429 -0
- package/cjs/dist/services/products-list-service.js +893 -0
- package/cjs/dist/services/selected-variant-service.d.ts +66 -0
- package/cjs/dist/services/selected-variant-service.js +527 -0
- package/cjs/dist/utils/index.d.ts +1 -0
- package/cjs/dist/utils/index.js +30 -0
- package/cjs/dist/utils/url-params.d.ts +73 -0
- package/cjs/dist/utils/url-params.js +114 -0
- package/cjs/package.json +3 -0
- package/dist/astro/actions/custom-checkout.d.ts +50 -0
- package/dist/astro/actions/custom-checkout.js +53 -0
- package/dist/astro/actions/index.d.ts +1 -0
- package/dist/astro/actions/index.js +1 -0
- package/dist/data-component-tags.d.ts +8 -0
- package/dist/data-component-tags.js +9 -0
- package/dist/enums/index.d.ts +2 -0
- package/dist/enums/index.js +2 -0
- package/dist/enums/social-platform-enums.d.ts +25 -0
- package/dist/enums/social-platform-enums.js +27 -0
- package/dist/enums/sort-enums.d.ts +17 -0
- package/dist/enums/sort-enums.js +18 -0
- package/dist/react/Category.d.ts +242 -0
- package/dist/react/Category.js +235 -0
- package/dist/react/CategoryList.d.ts +107 -0
- package/dist/react/CategoryList.js +91 -0
- package/dist/react/Choice.d.ts +211 -0
- package/dist/react/Choice.js +213 -0
- package/dist/react/Option.d.ts +242 -0
- package/dist/react/Option.js +346 -0
- package/dist/react/Product.d.ts +1065 -0
- package/dist/react/Product.js +1157 -0
- package/dist/react/ProductList.d.ts +400 -0
- package/dist/react/ProductList.js +368 -0
- package/dist/react/core/CategoryList.d.ts +194 -0
- package/dist/react/core/CategoryList.js +180 -0
- package/dist/react/core/Product.d.ts +225 -0
- package/dist/react/core/Product.js +190 -0
- package/dist/react/core/ProductList.d.ts +235 -0
- package/dist/react/core/ProductList.js +217 -0
- package/dist/react/core/ProductListFilters.d.ts +138 -0
- package/dist/react/core/ProductListFilters.js +242 -0
- package/dist/react/core/ProductListPagination.d.ts +49 -0
- package/dist/react/core/ProductListPagination.js +41 -0
- package/dist/react/core/ProductListSort.d.ts +19 -0
- package/dist/react/core/ProductListSort.js +52 -0
- package/dist/react/core/ProductModifiers.d.ts +416 -0
- package/dist/react/core/ProductModifiers.js +413 -0
- package/dist/react/core/ProductVariantSelector.d.ts +313 -0
- package/dist/react/core/ProductVariantSelector.js +291 -0
- package/dist/react/core/SelectedVariant.d.ts +230 -0
- package/dist/react/core/SelectedVariant.js +269 -0
- package/dist/react/index.d.ts +6 -0
- package/dist/react/index.js +6 -0
- package/dist/react/types.d.ts +8 -0
- package/dist/react/types.js +9 -0
- package/dist/server-actions/custom-checkout-action.d.ts +49 -0
- package/dist/server-actions/custom-checkout-action.js +64 -0
- package/dist/server-actions/index.d.ts +1 -0
- package/dist/server-actions/index.js +1 -0
- package/dist/services/buy-now-service.d.ts +346 -0
- package/dist/services/buy-now-service.js +197 -0
- package/dist/services/categories-list-service.d.ts +164 -0
- package/dist/services/categories-list-service.js +148 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.js +5 -0
- package/dist/services/pay-now-service.d.ts +214 -0
- package/dist/services/pay-now-service.js +156 -0
- package/dist/services/product-modifiers-service.d.ts +34 -0
- package/dist/services/product-modifiers-service.js +107 -0
- package/dist/services/product-service.d.ts +177 -0
- package/dist/services/product-service.js +190 -0
- package/dist/services/products-list-search-service.d.ts +0 -0
- package/dist/services/products-list-search-service.js +1 -0
- package/dist/services/products-list-service.d.ts +429 -0
- package/dist/services/products-list-service.js +893 -0
- package/dist/services/selected-variant-service.d.ts +66 -0
- package/dist/services/selected-variant-service.js +527 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +30 -0
- package/dist/utils/url-params.d.ts +73 -0
- package/dist/utils/url-params.js +114 -0
- package/package.json +89 -0
- package/react/package.json +4 -0
- package/server-actions/package.json +4 -0
- package/services/package.json +4 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Sort as SortPrimitive, GenericList, } from '@wix/headless-components/react';
|
|
3
|
+
import { useService } from '@wix/services-manager-react';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { ProductsListServiceDefinition } from '../services/products-list-service.js';
|
|
6
|
+
import * as CoreProductList from './core/ProductList.js';
|
|
7
|
+
import { ProductListSort as ProductListSortPrimitive } from './core/ProductListSort.js';
|
|
8
|
+
import * as CoreProductListFilters from './core/ProductListFilters.js';
|
|
9
|
+
import * as Product from './Product.js';
|
|
10
|
+
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
11
|
+
import { DataComponentTags } from '../data-component-tags.js';
|
|
12
|
+
var TestIds;
|
|
13
|
+
(function (TestIds) {
|
|
14
|
+
TestIds["productListRoot"] = "product-list-root";
|
|
15
|
+
TestIds["productListProducts"] = "product-list-products";
|
|
16
|
+
TestIds["productListItem"] = "product-list-item";
|
|
17
|
+
TestIds["productListLoadMore"] = "product-list-load-more";
|
|
18
|
+
TestIds["productListTotalsDisplayed"] = "product-list-totals-displayed";
|
|
19
|
+
TestIds["productListSort"] = "product-list-sort";
|
|
20
|
+
TestIds["productListFilter"] = "product-list-filter";
|
|
21
|
+
TestIds["productListFilterResetTrigger"] = "product-list-filter-reset-trigger";
|
|
22
|
+
TestIds["productListError"] = "product-list-error";
|
|
23
|
+
})(TestIds || (TestIds = {}));
|
|
24
|
+
/**
|
|
25
|
+
* Root component that provides the ProductList service context for rendering product lists.
|
|
26
|
+
*
|
|
27
|
+
* @order 1
|
|
28
|
+
* @component
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* import { ProductList } from '@wix/stores/components';
|
|
32
|
+
*
|
|
33
|
+
* function ProductListPage({ products }) {
|
|
34
|
+
* return (
|
|
35
|
+
* <ProductList.Root products={products}>
|
|
36
|
+
* <ProductList.Products>
|
|
37
|
+
* <ProductList.ProductRepeater>
|
|
38
|
+
* <Product.Name />
|
|
39
|
+
* <Product.Price />
|
|
40
|
+
* </ProductList.ProductRepeater>
|
|
41
|
+
* </ProductList.Products>
|
|
42
|
+
* </ProductList.Root>
|
|
43
|
+
* );
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const Root = React.forwardRef((props, ref) => {
|
|
48
|
+
const { children, products, productsListConfig, className, variant } = props;
|
|
49
|
+
const serviceConfig = productsListConfig || {
|
|
50
|
+
products: products || [],
|
|
51
|
+
searchOptions: {
|
|
52
|
+
cursorPaging: { limit: 10 },
|
|
53
|
+
},
|
|
54
|
+
pagingMetadata: {
|
|
55
|
+
count: products?.length || 0,
|
|
56
|
+
},
|
|
57
|
+
aggregations: {
|
|
58
|
+
results: [],
|
|
59
|
+
}, // Empty aggregation data
|
|
60
|
+
customizations: [],
|
|
61
|
+
};
|
|
62
|
+
return (_jsx(CoreProductList.Root, { productsListConfig: serviceConfig, children: _jsx(RootContent, { children: children, className: className, ref: ref, variant: variant }) }));
|
|
63
|
+
});
|
|
64
|
+
Root.displayName = 'ProductList.Root';
|
|
65
|
+
/**
|
|
66
|
+
* Internal component to handle the Root content with service access
|
|
67
|
+
*/
|
|
68
|
+
const RootContent = React.forwardRef((props, ref) => {
|
|
69
|
+
const { children, className, variant } = props;
|
|
70
|
+
const productsListService = useService(ProductsListServiceDefinition);
|
|
71
|
+
const items = productsListService.products.get().map((product) => ({
|
|
72
|
+
...product,
|
|
73
|
+
id: product._id,
|
|
74
|
+
}));
|
|
75
|
+
return (_jsx(GenericList.Root, { items: items, loadMore: () => productsListService.loadMore(10), hasMore: productsListService.hasMoreProducts.get(), isLoading: productsListService.isLoading.get(), className: className, ref: ref, "data-component-tag": DataComponentTags.productListRoot, "data-testid": TestIds.productListRoot, variant: variant, children: children }));
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Raw component that provides direct access to product list data.
|
|
79
|
+
* Similar to Product.Raw, this should only be used when you need custom access to list data.
|
|
80
|
+
*
|
|
81
|
+
* @component
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* <ProductList.Raw>
|
|
85
|
+
* {({ totalProducts, displayedProducts, isFiltered }) => (
|
|
86
|
+
* <div className="text-content-muted">
|
|
87
|
+
* Showing {displayedProducts} of {totalProducts} products
|
|
88
|
+
* {isFiltered && <span className="ml-2 text-brand-primary">(Filtered)</span>}
|
|
89
|
+
* </div>
|
|
90
|
+
* )}
|
|
91
|
+
* </ProductList.Raw>
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export const Raw = React.forwardRef((props, _ref) => {
|
|
95
|
+
const { children } = props;
|
|
96
|
+
const productsListService = useService(ProductsListServiceDefinition);
|
|
97
|
+
const products = productsListService.products.get();
|
|
98
|
+
const pagingMetadata = productsListService.pagingMetadata.get();
|
|
99
|
+
const displayedProducts = products.length;
|
|
100
|
+
const totalProducts = pagingMetadata.count || products.length;
|
|
101
|
+
const isFiltered = false; // TODO: Implement filtering detection
|
|
102
|
+
return typeof children === 'function'
|
|
103
|
+
? children({ totalProducts, displayedProducts, isFiltered })
|
|
104
|
+
: children;
|
|
105
|
+
});
|
|
106
|
+
/**
|
|
107
|
+
* Container for the product list with empty state support.
|
|
108
|
+
* Follows List Container Level pattern.
|
|
109
|
+
*
|
|
110
|
+
* @component
|
|
111
|
+
* @example
|
|
112
|
+
* ```tsx
|
|
113
|
+
* <ProductList.Products emptyState={<div>No products found</div>}>
|
|
114
|
+
* <ProductList.ProductRepeater>
|
|
115
|
+
* <Product.Name />
|
|
116
|
+
* <Product.Price />
|
|
117
|
+
* </ProductList.ProductRepeater>
|
|
118
|
+
* </ProductList.Products>
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export const Products = React.forwardRef((props, ref) => {
|
|
122
|
+
const { children, ...otherProps } = props;
|
|
123
|
+
return (_jsx(GenericList.Items, { ref: ref, "data-testid": TestIds.productListProducts, ...otherProps, children: children }));
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* Repeater component that renders Product.Root for each product.
|
|
127
|
+
* Follows Repeater Level pattern and uses GenericList.Repeater for consistency.
|
|
128
|
+
* Supports asChild pattern for advanced layout components like GalleryWrapper.
|
|
129
|
+
*
|
|
130
|
+
* @component
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* // Standard usage
|
|
134
|
+
* <ProductList.ProductRepeater>
|
|
135
|
+
* <Product.Name />
|
|
136
|
+
* <Product.Price />
|
|
137
|
+
* </ProductList.ProductRepeater>
|
|
138
|
+
*
|
|
139
|
+
* // AsChild usage with GalleryWrapper
|
|
140
|
+
* <ProductList.ProductRepeater asChild>
|
|
141
|
+
* {({ items, variant, itemWrapper }) => (
|
|
142
|
+
* <GalleryWrapper
|
|
143
|
+
* items={items}
|
|
144
|
+
* variant={variant}
|
|
145
|
+
* itemRenderer={(item, index) =>
|
|
146
|
+
* itemWrapper({ item, index, children: <>
|
|
147
|
+
* <Product.Name />
|
|
148
|
+
* <Product.Price />
|
|
149
|
+
* </> })
|
|
150
|
+
* }
|
|
151
|
+
* />
|
|
152
|
+
* )}
|
|
153
|
+
* </ProductList.ProductRepeater>
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export const ProductRepeater = React.forwardRef((props, ref) => {
|
|
157
|
+
const { children, asChild } = props;
|
|
158
|
+
return (_jsx(GenericList.Repeater, { ref: ref, asChild: asChild, itemWrapper: ({ item: product, children }) => (_jsx(Product.Root, { product: product, "data-testid": TestIds.productListItem, "data-product-id": product._id, "data-product-available": true, "data-item-id": product._id, children: children }, product._id)), children: children }));
|
|
159
|
+
});
|
|
160
|
+
/**
|
|
161
|
+
* Displays a button to load more products. Not rendered if infiniteScroll is false or no products are left to load.
|
|
162
|
+
* Follows the architecture rules - does not support asChild as it's a simple trigger component.
|
|
163
|
+
*
|
|
164
|
+
* @component
|
|
165
|
+
* @example
|
|
166
|
+
* ```tsx
|
|
167
|
+
* <ProductList.LoadMoreTrigger asChild>
|
|
168
|
+
* <button>Load More</button>
|
|
169
|
+
* </ProductList.LoadMoreTrigger>
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export const LoadMoreTrigger = React.forwardRef((props, ref) => {
|
|
173
|
+
const { children = _jsx("button", {}), ...otherProps } = props;
|
|
174
|
+
return (_jsx(GenericList.Actions.LoadMore, { ref: ref, "data-testid": TestIds.productListLoadMore, ...otherProps, children: children }));
|
|
175
|
+
});
|
|
176
|
+
/**
|
|
177
|
+
* Displays the number of products currently displayed.
|
|
178
|
+
*
|
|
179
|
+
* @component
|
|
180
|
+
* @example
|
|
181
|
+
* ```tsx
|
|
182
|
+
* <ProductList.TotalsDisplayed />
|
|
183
|
+
* // or with asChild
|
|
184
|
+
* <ProductList.TotalsDisplayed asChild>
|
|
185
|
+
* <strong />
|
|
186
|
+
* </ProductList.TotalsDisplayed>
|
|
187
|
+
* // or with render function
|
|
188
|
+
* <ProductList.TotalsDisplayed asChild>
|
|
189
|
+
* {({ displayedItems }, ref) => <strong ref={ref}>{displayedItems}</strong>}
|
|
190
|
+
* </ProductList.TotalsDisplayed>
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
export const TotalsDisplayed = React.forwardRef((props, ref) => {
|
|
194
|
+
const { children = _jsx("span", {}), ...otherProps } = props;
|
|
195
|
+
return (_jsx(GenericList.Totals, { ref: ref, "data-testid": TestIds.productListTotalsDisplayed, ...otherProps, children: children }));
|
|
196
|
+
});
|
|
197
|
+
/**
|
|
198
|
+
* Sort component for product lists that provides sorting functionality.
|
|
199
|
+
*
|
|
200
|
+
* This component integrates with the ProductList service to provide predefined sort options
|
|
201
|
+
* including name (A-Z, Z-A) and price (low to high, high to low). It supports both
|
|
202
|
+
* controlled rendering via the asChild pattern and default UI rendering.
|
|
203
|
+
*
|
|
204
|
+
* @component
|
|
205
|
+
* @example
|
|
206
|
+
* ```tsx
|
|
207
|
+
* // Default select dropdown
|
|
208
|
+
* <ProductList.Sort />
|
|
209
|
+
*
|
|
210
|
+
* // As list of clickable options
|
|
211
|
+
* <ProductList.Sort as="list" />
|
|
212
|
+
*
|
|
213
|
+
* // With custom styling
|
|
214
|
+
* <ProductList.Sort
|
|
215
|
+
* as="select"
|
|
216
|
+
* className="custom-sort-select"
|
|
217
|
+
* />
|
|
218
|
+
*
|
|
219
|
+
* // Custom implementation using asChild pattern
|
|
220
|
+
* <ProductList.Sort asChild>
|
|
221
|
+
* {({ currentSort, sortOptions, setSort }) => (
|
|
222
|
+
* <div className="custom-sort-container">
|
|
223
|
+
* {sortOptions.map((option) => (
|
|
224
|
+
* <button
|
|
225
|
+
* key={`${option.fieldName}-${option.order}`}
|
|
226
|
+
* onClick={() => setSort([{ fieldName: option.fieldName, order: option.order }])}
|
|
227
|
+
* className={isCurrentSort(option) ? 'active' : ''}
|
|
228
|
+
* >
|
|
229
|
+
* {option.label}
|
|
230
|
+
* </button>
|
|
231
|
+
* ))}
|
|
232
|
+
* </div>
|
|
233
|
+
* )}
|
|
234
|
+
* </ProductList.Sort>
|
|
235
|
+
* ```
|
|
236
|
+
*
|
|
237
|
+
* @see {@link ProductListSortPrimitive} for the underlying sort logic
|
|
238
|
+
* @see {@link SortPrimitive.Root} for the primitive sort component
|
|
239
|
+
*/
|
|
240
|
+
export const Sort = React.forwardRef(({ children, className, as, asChild }, ref) => {
|
|
241
|
+
return (_jsx(ProductListSortPrimitive, { children: ({ currentSort, sortOptions, setSort }) => {
|
|
242
|
+
if (asChild && children) {
|
|
243
|
+
return children({ currentSort, sortOptions, setSort });
|
|
244
|
+
}
|
|
245
|
+
return (_jsx(SortPrimitive.Root, { ref: ref, value: currentSort, onChange: (value) => {
|
|
246
|
+
setSort(value);
|
|
247
|
+
}, sortOptions: sortOptions, as: as, className: className, "data-testid": TestIds.productListSort }));
|
|
248
|
+
} }));
|
|
249
|
+
});
|
|
250
|
+
/**
|
|
251
|
+
* Filter component that provides comprehensive filtering functionality for product lists.
|
|
252
|
+
* This component acts as a provider that integrates with the ProductList service.
|
|
253
|
+
*
|
|
254
|
+
* @component
|
|
255
|
+
* @example
|
|
256
|
+
* ```tsx
|
|
257
|
+
* // Default usage
|
|
258
|
+
* <ProductList.Filter.Root className="filter-container">
|
|
259
|
+
* <Filter.FilterOptions>
|
|
260
|
+
* <Filter.FilterOptionRepeater>
|
|
261
|
+
* <Filter.FilterOption.Label />
|
|
262
|
+
* <Filter.FilterOption.MultiFilter />
|
|
263
|
+
* </Filter.FilterOptionRepeater>
|
|
264
|
+
* </Filter.FilterOptions>
|
|
265
|
+
* </ProductList.Filter.Root>
|
|
266
|
+
*
|
|
267
|
+
* // With custom container using asChild
|
|
268
|
+
* <ProductList.Filter.Root asChild>
|
|
269
|
+
* <aside className="filter-sidebar">
|
|
270
|
+
* <Filter.FilterOptions>
|
|
271
|
+
* <Filter.FilterOptionRepeater>
|
|
272
|
+
* <Filter.FilterOption.Label />
|
|
273
|
+
* <Filter.FilterOption.MultiFilter />
|
|
274
|
+
* </Filter.FilterOptionRepeater>
|
|
275
|
+
* </Filter.FilterOptions>
|
|
276
|
+
* </aside>
|
|
277
|
+
* </ProductList.Filter.Root>
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
const FilterRoot = React.forwardRef((props, ref) => {
|
|
281
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
282
|
+
return (_jsx(CoreProductListFilters.FilterRoot, { asChild: asChild, className: className, children: _jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.productListFilter, customElement: children, ...otherProps, children: _jsx("div", { children: children }) }) }));
|
|
283
|
+
});
|
|
284
|
+
FilterRoot.displayName = 'ProductList.Filter';
|
|
285
|
+
export const Filter = {
|
|
286
|
+
Root: FilterRoot,
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* Reset trigger component for clearing all applied filters.
|
|
290
|
+
* Provides reset functionality and filter state to custom render functions.
|
|
291
|
+
* Only renders when filters are applied.
|
|
292
|
+
*
|
|
293
|
+
* @component
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* // Default usage
|
|
297
|
+
* <ProductList.FilterResetTrigger className="reset-filters-btn" />
|
|
298
|
+
*
|
|
299
|
+
* // With custom label
|
|
300
|
+
* <ProductList.FilterResetTrigger label="Clear Filters" />
|
|
301
|
+
*
|
|
302
|
+
* // Custom rendering with forwardRef
|
|
303
|
+
* <ProductList.FilterResetTrigger asChild>
|
|
304
|
+
* {React.forwardRef(({resetFilters, isFiltered, ...props}, ref) => (
|
|
305
|
+
* <button
|
|
306
|
+
* ref={ref}
|
|
307
|
+
* {...props}
|
|
308
|
+
* onClick={resetFilters}
|
|
309
|
+
* disabled={!isFiltered}
|
|
310
|
+
* className="custom-reset-button disabled:opacity-50"
|
|
311
|
+
* >
|
|
312
|
+
* Reset All Filters
|
|
313
|
+
* </button>
|
|
314
|
+
* ))}
|
|
315
|
+
* </ProductList.FilterResetTrigger>
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
export const FilterResetTrigger = React.forwardRef((props, ref) => {
|
|
319
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
320
|
+
const label = props.label || 'Reset All Filters';
|
|
321
|
+
return (_jsx(CoreProductListFilters.ResetTrigger, { children: ({ resetFilters, isFiltered }) => {
|
|
322
|
+
if (!isFiltered) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, onClick: resetFilters, disabled: !isFiltered, "data-testid": TestIds.productListFilterResetTrigger, "data-filtered": isFiltered ? 'true' : 'false', customElement: children, customElementProps: {
|
|
326
|
+
resetFilters,
|
|
327
|
+
isFiltered,
|
|
328
|
+
}, content: label, ...otherProps, children: _jsx("button", { disabled: !isFiltered, children: label }) }));
|
|
329
|
+
} }));
|
|
330
|
+
});
|
|
331
|
+
FilterResetTrigger.displayName = 'ProductList.FilterResetTrigger';
|
|
332
|
+
/**
|
|
333
|
+
* Error component that displays product list errors.
|
|
334
|
+
* Provides error data to custom render functions.
|
|
335
|
+
* Only renders when there's an error.
|
|
336
|
+
*
|
|
337
|
+
* @component
|
|
338
|
+
* @example
|
|
339
|
+
* ```tsx
|
|
340
|
+
* // Default usage
|
|
341
|
+
* <ProductList.Error className="error-message" />
|
|
342
|
+
*
|
|
343
|
+
* // Custom rendering with forwardRef
|
|
344
|
+
* <ProductList.Error asChild>
|
|
345
|
+
* {React.forwardRef(({error, ...props}, ref) => (
|
|
346
|
+
* <div
|
|
347
|
+
* ref={ref}
|
|
348
|
+
* {...props}
|
|
349
|
+
* className="custom-error-container"
|
|
350
|
+
* >
|
|
351
|
+
* Error: {error}
|
|
352
|
+
* </div>
|
|
353
|
+
* ))}
|
|
354
|
+
* </ProductList.Error>
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
export const Error = React.forwardRef((props, ref) => {
|
|
358
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
359
|
+
return (_jsx(CoreProductList.Error, { children: ({ error }) => {
|
|
360
|
+
if (!error) {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.productListError, "data-error": error, customElement: children, customElementProps: {
|
|
364
|
+
error,
|
|
365
|
+
}, content: error, ...otherProps, children: _jsx("div", { className: "text-status-error text-sm sm:text-base", children: error }) }));
|
|
366
|
+
} }));
|
|
367
|
+
});
|
|
368
|
+
Error.displayName = 'ProductList.Error';
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type CategoriesListServiceConfig } from '../../services/categories-list-service.js';
|
|
3
|
+
import { categories } from '@wix/categories';
|
|
4
|
+
export type Category = categories.Category;
|
|
5
|
+
export interface RootProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
categoriesListConfig: CategoriesListServiceConfig;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Root component that provides the CategoryList service context to its children.
|
|
11
|
+
* This component sets up the necessary services for managing categories list state.
|
|
12
|
+
* Optionally connects to ProductList filtering when connectToProductFilter is enabled.
|
|
13
|
+
*
|
|
14
|
+
* @order 1
|
|
15
|
+
* @component
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* import { CategoryListCore } from '@wix/stores/components';
|
|
19
|
+
*
|
|
20
|
+
* function CategoriesPage() {
|
|
21
|
+
* return (
|
|
22
|
+
* <CategoryList.Root
|
|
23
|
+
* categoriesListConfig={{ categories: myCategories }}
|
|
24
|
+
* connectToProductFilter={true}
|
|
25
|
+
* >
|
|
26
|
+
* <CategoryList.ItemContent>
|
|
27
|
+
* {({ category }) => (
|
|
28
|
+
* <div key={category._id}>
|
|
29
|
+
* <h2>{category.name}</h2>
|
|
30
|
+
* </div>
|
|
31
|
+
* )}
|
|
32
|
+
* </CategoryList.ItemContent>
|
|
33
|
+
* </CategoryList.Root>
|
|
34
|
+
* );
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function Root(props: RootProps): React.ReactNode;
|
|
39
|
+
export declare namespace Root {
|
|
40
|
+
var displayName: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Props for EmptyState headless component
|
|
44
|
+
*/
|
|
45
|
+
export interface EmptyStateProps {
|
|
46
|
+
/** Content to display when categories list is empty (can be a render function or ReactNode) */
|
|
47
|
+
children: ((props: EmptyStateRenderProps) => React.ReactNode) | React.ReactNode;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Render props for EmptyState component
|
|
51
|
+
*/
|
|
52
|
+
export interface EmptyStateRenderProps {
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Component that renders content when the categories list is empty.
|
|
56
|
+
* Only displays its children when there are no categories, no loading state, and no errors.
|
|
57
|
+
*
|
|
58
|
+
* @component
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* import { CategoryListCore } from '@wix/stores/components';
|
|
62
|
+
*
|
|
63
|
+
* function EmptyCategoriesMessage() {
|
|
64
|
+
* return (
|
|
65
|
+
* <CategoryList.EmptyState>
|
|
66
|
+
* {() => (
|
|
67
|
+
* <div className="empty-state">
|
|
68
|
+
* <h3>No categories found</h3>
|
|
69
|
+
* <p>Categories will appear here once they are created</p>
|
|
70
|
+
* </div>
|
|
71
|
+
* )}
|
|
72
|
+
* </CategoryList.EmptyState>
|
|
73
|
+
* );
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function EmptyState(props: EmptyStateProps): React.ReactNode;
|
|
78
|
+
/**
|
|
79
|
+
* Props for Loading headless component
|
|
80
|
+
*/
|
|
81
|
+
export interface LoadingProps {
|
|
82
|
+
/** Content to display during loading (can be a render function or ReactNode) */
|
|
83
|
+
children: ((props: LoadingRenderProps) => React.ReactNode) | React.ReactNode;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Render props for Loading component
|
|
87
|
+
*/
|
|
88
|
+
export interface LoadingRenderProps {
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Component that renders content during loading state.
|
|
92
|
+
* Only displays its children when the categories list is currently loading.
|
|
93
|
+
*
|
|
94
|
+
* @component
|
|
95
|
+
* @example
|
|
96
|
+
* ```tsx
|
|
97
|
+
* import { CategoryListCore } from '@wix/stores/components';
|
|
98
|
+
*
|
|
99
|
+
* function CategoriesLoading() {
|
|
100
|
+
* return (
|
|
101
|
+
* <CategoryList.Loading>
|
|
102
|
+
* {() => (
|
|
103
|
+
* <div className="loading-spinner">
|
|
104
|
+
* <div>Loading categories...</div>
|
|
105
|
+
* <div className="spinner"></div>
|
|
106
|
+
* </div>
|
|
107
|
+
* )}
|
|
108
|
+
* </CategoryList.Loading>
|
|
109
|
+
* );
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function Loading(props: LoadingProps): React.ReactNode;
|
|
114
|
+
/**
|
|
115
|
+
* Props for Error headless component
|
|
116
|
+
*/
|
|
117
|
+
export interface ErrorProps {
|
|
118
|
+
/** Content to display during error state (can be a render function or ReactNode) */
|
|
119
|
+
children: ((props: ErrorRenderProps) => React.ReactNode) | React.ReactNode;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Render props for Error component
|
|
123
|
+
*/
|
|
124
|
+
export interface ErrorRenderProps {
|
|
125
|
+
/** Error message */
|
|
126
|
+
error: string | null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Component that renders content when there's an error loading categories.
|
|
130
|
+
* Only displays its children when an error has occurred.
|
|
131
|
+
*
|
|
132
|
+
* @component
|
|
133
|
+
* @example
|
|
134
|
+
* ```tsx
|
|
135
|
+
* import { CategoryListCore } from '@wix/stores/components';
|
|
136
|
+
*
|
|
137
|
+
* function CategoriesError() {
|
|
138
|
+
* return (
|
|
139
|
+
* <CategoryList.Error>
|
|
140
|
+
* {({ error }) => (
|
|
141
|
+
* <div className="error-state">
|
|
142
|
+
* <h3>Error loading categories</h3>
|
|
143
|
+
* <p>{error}</p>
|
|
144
|
+
* <button onClick={() => window.location.reload()}>
|
|
145
|
+
* Try Again
|
|
146
|
+
* </button>
|
|
147
|
+
* </div>
|
|
148
|
+
* )}
|
|
149
|
+
* </CategoryList.Error>
|
|
150
|
+
* );
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export declare function Error(props: ErrorProps): React.ReactNode;
|
|
155
|
+
/**
|
|
156
|
+
* Props for ItemContent headless component
|
|
157
|
+
*/
|
|
158
|
+
export interface ItemContentProps {
|
|
159
|
+
/** Content to display for each category (can be a render function receiving category data or ReactNode) */
|
|
160
|
+
children: ((props: ItemContentRenderProps) => React.ReactNode) | React.ReactNode;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Render props for ItemContent component
|
|
164
|
+
*/
|
|
165
|
+
export interface ItemContentRenderProps {
|
|
166
|
+
/** Category data */
|
|
167
|
+
category: Category;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Component that renders content for each category in the list.
|
|
171
|
+
* Maps over all categories and provides each category through a service context.
|
|
172
|
+
* Only renders when categories are successfully loaded (not loading, no error, and has categories).
|
|
173
|
+
*
|
|
174
|
+
* @component
|
|
175
|
+
* @example
|
|
176
|
+
* ```tsx
|
|
177
|
+
* import { CategoryListCore } from '@wix/stores/components';
|
|
178
|
+
*
|
|
179
|
+
* function CategoriesGrid() {
|
|
180
|
+
* return (
|
|
181
|
+
* <CategoryList.ItemContent>
|
|
182
|
+
* {({ category }) => (
|
|
183
|
+
* <div className="category-card">
|
|
184
|
+
* <h3>{category.name}</h3>
|
|
185
|
+
* <p>{category.description}</p>
|
|
186
|
+
* <a href={`/categories/${category.slug}`}>View Category</a>
|
|
187
|
+
* </div>
|
|
188
|
+
* )}
|
|
189
|
+
* </CategoryList.ItemContent>
|
|
190
|
+
* );
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export declare function ItemContent(props: ItemContentProps): import("react/jsx-runtime").JSX.Element[] | null;
|