@wix/headless-stores 0.0.55 → 0.0.56

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.
@@ -2,6 +2,7 @@ import type { V3Product } from '@wix/auto_sdk_stores_products-v-3';
2
2
  import React from 'react';
3
3
  import type { ProductsListSearchServiceConfig } from '../services/products-list-search-service.js';
4
4
  import type { ProductsListServiceConfig } from '../services/products-list-service.js';
5
+ import { type AsChildProps } from '../utils/renderAsChild.js';
5
6
  /**
6
7
  * Props for the ProductList root component following the documented API
7
8
  */
@@ -114,3 +115,49 @@ export interface ProductRepeaterProps {
114
115
  * ```
115
116
  */
116
117
  export declare const ProductRepeater: React.ForwardRefExoticComponent<ProductRepeaterProps & React.RefAttributes<HTMLElement>>;
118
+ /**
119
+ * Props for ProductList LoadMoreTrigger component
120
+ */
121
+ export interface LoadMoreTriggerProps {
122
+ children?: React.ReactNode;
123
+ asChild?: boolean;
124
+ className?: string;
125
+ }
126
+ /**
127
+ * Displays a button to load more products. Not rendered if infiniteScroll is false or no products are left to load.
128
+ * Follows the architecture rules - does not support asChild as it's a simple trigger component.
129
+ *
130
+ * @component
131
+ * @example
132
+ * ```tsx
133
+ * <ProductList.LoadMoreTrigger asChild>
134
+ * <button>Load More</button>
135
+ * </ProductList.LoadMoreTrigger>
136
+ * ```
137
+ */
138
+ export declare const LoadMoreTrigger: React.ForwardRefExoticComponent<LoadMoreTriggerProps & React.RefAttributes<HTMLElement>>;
139
+ /**
140
+ * Props for ProductList Totals Displayed component
141
+ */
142
+ export interface TotalsDisplayedProps extends AsChildProps<{
143
+ displayedProducts: number;
144
+ }> {
145
+ }
146
+ /**
147
+ * Displays the number of products currently displayed.
148
+ *
149
+ * @component
150
+ * @example
151
+ * ```tsx
152
+ * <ProductList.TotalsDisplayed />
153
+ * // or with asChild
154
+ * <ProductList.TotalsDisplayed asChild>
155
+ * <strong />
156
+ * </ProductList.TotalsDisplayed>
157
+ * // or with render function
158
+ * <ProductList.TotalsDisplayed asChild>
159
+ * {({ displayedProducts }, ref) => <strong ref={ref}>{displayedProducts}</strong>}
160
+ * </ProductList.TotalsDisplayed>
161
+ * ```
162
+ */
163
+ export declare const TotalsDisplayed: React.ForwardRefExoticComponent<TotalsDisplayedProps & React.RefAttributes<HTMLElement>>;
@@ -3,12 +3,16 @@ import { useService } from '@wix/services-manager-react';
3
3
  import React from 'react';
4
4
  import { ProductsListServiceDefinition } from '../services/products-list-service.js';
5
5
  import * as CoreProductList from './core/ProductList.js';
6
+ import * as CoreProductListPagination from './core/ProductListPagination.js';
6
7
  import * as Product from './Product.js';
8
+ import { renderAsChild } from '../utils/renderAsChild.js';
7
9
  var TestIds;
8
10
  (function (TestIds) {
9
11
  TestIds["productListRoot"] = "product-list-root";
10
12
  TestIds["productListProducts"] = "product-list-products";
11
13
  TestIds["productListItem"] = "product-list-item";
14
+ TestIds["productListLoadMore"] = "product-list-load-more";
15
+ TestIds["productListTotalsDisplayed"] = "product-list-totals-displayed";
12
16
  })(TestIds || (TestIds = {}));
13
17
  /**
14
18
  * Root component that provides the ProductList service context for rendering product lists.
@@ -154,3 +158,78 @@ export const ProductRepeater = React.forwardRef((props, _ref) => {
154
158
  return null;
155
159
  return (_jsx(_Fragment, { children: products.map((product) => (_jsx(Product.Root, { product: product, "data-testid": TestIds.productListItem, "data-product-id": product._id, "data-product-available": true, children: children }, product._id))) }));
156
160
  });
161
+ /**
162
+ * Displays a button to load more products. Not rendered if infiniteScroll is false or no products are left to load.
163
+ * Follows the architecture rules - does not support asChild as it's a simple trigger component.
164
+ *
165
+ * @component
166
+ * @example
167
+ * ```tsx
168
+ * <ProductList.LoadMoreTrigger asChild>
169
+ * <button>Load More</button>
170
+ * </ProductList.LoadMoreTrigger>
171
+ * ```
172
+ */
173
+ export const LoadMoreTrigger = React.forwardRef((props, ref) => {
174
+ const { asChild, children, className } = props;
175
+ return (_jsx(CoreProductListPagination.LoadMoreTrigger, { children: ({ loadMore, hasMoreProducts, isLoading }) => {
176
+ // Don't render if no more products to load
177
+ if (!hasMoreProducts)
178
+ return null;
179
+ const handleClick = () => loadMore(10);
180
+ const attributes = {
181
+ 'data-testid': TestIds.productListLoadMore,
182
+ className,
183
+ onClick: handleClick,
184
+ disabled: isLoading,
185
+ };
186
+ if (asChild && React.isValidElement(children)) {
187
+ return React.cloneElement(children, {
188
+ ...attributes,
189
+ onClick: handleClick,
190
+ ref,
191
+ });
192
+ }
193
+ return (_jsx("button", { ...attributes, ref: ref, children: children }));
194
+ } }));
195
+ });
196
+ /**
197
+ * Displays the number of products currently displayed.
198
+ *
199
+ * @component
200
+ * @example
201
+ * ```tsx
202
+ * <ProductList.TotalsDisplayed />
203
+ * // or with asChild
204
+ * <ProductList.TotalsDisplayed asChild>
205
+ * <strong />
206
+ * </ProductList.TotalsDisplayed>
207
+ * // or with render function
208
+ * <ProductList.TotalsDisplayed asChild>
209
+ * {({ displayedProducts }, ref) => <strong ref={ref}>{displayedProducts}</strong>}
210
+ * </ProductList.TotalsDisplayed>
211
+ * ```
212
+ */
213
+ export const TotalsDisplayed = React.forwardRef((props, ref) => {
214
+ const { asChild, children, className } = props;
215
+ const productsListService = useService(ProductsListServiceDefinition);
216
+ const products = productsListService.products.get();
217
+ const displayedProducts = products.length;
218
+ const attributes = {
219
+ 'data-testid': TestIds.productListTotalsDisplayed,
220
+ 'data-displayed': displayedProducts,
221
+ className,
222
+ };
223
+ if (asChild) {
224
+ const rendered = renderAsChild({
225
+ children,
226
+ props: { displayedProducts },
227
+ ref,
228
+ content: displayedProducts.toString(),
229
+ attributes,
230
+ });
231
+ if (rendered)
232
+ return rendered;
233
+ }
234
+ return (_jsx("span", { ...attributes, ref: ref, children: displayedProducts }));
235
+ });
@@ -2,6 +2,7 @@ import type { V3Product } from '@wix/auto_sdk_stores_products-v-3';
2
2
  import React from 'react';
3
3
  import type { ProductsListSearchServiceConfig } from '../services/products-list-search-service.js';
4
4
  import type { ProductsListServiceConfig } from '../services/products-list-service.js';
5
+ import { type AsChildProps } from '../utils/renderAsChild.js';
5
6
  /**
6
7
  * Props for the ProductList root component following the documented API
7
8
  */
@@ -114,3 +115,49 @@ export interface ProductRepeaterProps {
114
115
  * ```
115
116
  */
116
117
  export declare const ProductRepeater: React.ForwardRefExoticComponent<ProductRepeaterProps & React.RefAttributes<HTMLElement>>;
118
+ /**
119
+ * Props for ProductList LoadMoreTrigger component
120
+ */
121
+ export interface LoadMoreTriggerProps {
122
+ children?: React.ReactNode;
123
+ asChild?: boolean;
124
+ className?: string;
125
+ }
126
+ /**
127
+ * Displays a button to load more products. Not rendered if infiniteScroll is false or no products are left to load.
128
+ * Follows the architecture rules - does not support asChild as it's a simple trigger component.
129
+ *
130
+ * @component
131
+ * @example
132
+ * ```tsx
133
+ * <ProductList.LoadMoreTrigger asChild>
134
+ * <button>Load More</button>
135
+ * </ProductList.LoadMoreTrigger>
136
+ * ```
137
+ */
138
+ export declare const LoadMoreTrigger: React.ForwardRefExoticComponent<LoadMoreTriggerProps & React.RefAttributes<HTMLElement>>;
139
+ /**
140
+ * Props for ProductList Totals Displayed component
141
+ */
142
+ export interface TotalsDisplayedProps extends AsChildProps<{
143
+ displayedProducts: number;
144
+ }> {
145
+ }
146
+ /**
147
+ * Displays the number of products currently displayed.
148
+ *
149
+ * @component
150
+ * @example
151
+ * ```tsx
152
+ * <ProductList.TotalsDisplayed />
153
+ * // or with asChild
154
+ * <ProductList.TotalsDisplayed asChild>
155
+ * <strong />
156
+ * </ProductList.TotalsDisplayed>
157
+ * // or with render function
158
+ * <ProductList.TotalsDisplayed asChild>
159
+ * {({ displayedProducts }, ref) => <strong ref={ref}>{displayedProducts}</strong>}
160
+ * </ProductList.TotalsDisplayed>
161
+ * ```
162
+ */
163
+ export declare const TotalsDisplayed: React.ForwardRefExoticComponent<TotalsDisplayedProps & React.RefAttributes<HTMLElement>>;
@@ -3,12 +3,16 @@ import { useService } from '@wix/services-manager-react';
3
3
  import React from 'react';
4
4
  import { ProductsListServiceDefinition } from '../services/products-list-service.js';
5
5
  import * as CoreProductList from './core/ProductList.js';
6
+ import * as CoreProductListPagination from './core/ProductListPagination.js';
6
7
  import * as Product from './Product.js';
8
+ import { renderAsChild } from '../utils/renderAsChild.js';
7
9
  var TestIds;
8
10
  (function (TestIds) {
9
11
  TestIds["productListRoot"] = "product-list-root";
10
12
  TestIds["productListProducts"] = "product-list-products";
11
13
  TestIds["productListItem"] = "product-list-item";
14
+ TestIds["productListLoadMore"] = "product-list-load-more";
15
+ TestIds["productListTotalsDisplayed"] = "product-list-totals-displayed";
12
16
  })(TestIds || (TestIds = {}));
13
17
  /**
14
18
  * Root component that provides the ProductList service context for rendering product lists.
@@ -154,3 +158,78 @@ export const ProductRepeater = React.forwardRef((props, _ref) => {
154
158
  return null;
155
159
  return (_jsx(_Fragment, { children: products.map((product) => (_jsx(Product.Root, { product: product, "data-testid": TestIds.productListItem, "data-product-id": product._id, "data-product-available": true, children: children }, product._id))) }));
156
160
  });
161
+ /**
162
+ * Displays a button to load more products. Not rendered if infiniteScroll is false or no products are left to load.
163
+ * Follows the architecture rules - does not support asChild as it's a simple trigger component.
164
+ *
165
+ * @component
166
+ * @example
167
+ * ```tsx
168
+ * <ProductList.LoadMoreTrigger asChild>
169
+ * <button>Load More</button>
170
+ * </ProductList.LoadMoreTrigger>
171
+ * ```
172
+ */
173
+ export const LoadMoreTrigger = React.forwardRef((props, ref) => {
174
+ const { asChild, children, className } = props;
175
+ return (_jsx(CoreProductListPagination.LoadMoreTrigger, { children: ({ loadMore, hasMoreProducts, isLoading }) => {
176
+ // Don't render if no more products to load
177
+ if (!hasMoreProducts)
178
+ return null;
179
+ const handleClick = () => loadMore(10);
180
+ const attributes = {
181
+ 'data-testid': TestIds.productListLoadMore,
182
+ className,
183
+ onClick: handleClick,
184
+ disabled: isLoading,
185
+ };
186
+ if (asChild && React.isValidElement(children)) {
187
+ return React.cloneElement(children, {
188
+ ...attributes,
189
+ onClick: handleClick,
190
+ ref,
191
+ });
192
+ }
193
+ return (_jsx("button", { ...attributes, ref: ref, children: children }));
194
+ } }));
195
+ });
196
+ /**
197
+ * Displays the number of products currently displayed.
198
+ *
199
+ * @component
200
+ * @example
201
+ * ```tsx
202
+ * <ProductList.TotalsDisplayed />
203
+ * // or with asChild
204
+ * <ProductList.TotalsDisplayed asChild>
205
+ * <strong />
206
+ * </ProductList.TotalsDisplayed>
207
+ * // or with render function
208
+ * <ProductList.TotalsDisplayed asChild>
209
+ * {({ displayedProducts }, ref) => <strong ref={ref}>{displayedProducts}</strong>}
210
+ * </ProductList.TotalsDisplayed>
211
+ * ```
212
+ */
213
+ export const TotalsDisplayed = React.forwardRef((props, ref) => {
214
+ const { asChild, children, className } = props;
215
+ const productsListService = useService(ProductsListServiceDefinition);
216
+ const products = productsListService.products.get();
217
+ const displayedProducts = products.length;
218
+ const attributes = {
219
+ 'data-testid': TestIds.productListTotalsDisplayed,
220
+ 'data-displayed': displayedProducts,
221
+ className,
222
+ };
223
+ if (asChild) {
224
+ const rendered = renderAsChild({
225
+ children,
226
+ props: { displayedProducts },
227
+ ref,
228
+ content: displayedProducts.toString(),
229
+ attributes,
230
+ });
231
+ if (rendered)
232
+ return rendered;
233
+ }
234
+ return (_jsx("span", { ...attributes, ref: ref, children: displayedProducts }));
235
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-stores",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "prebuild": "cd ../media && yarn build && cd ../ecom && yarn build",