@wix/headless-stores 0.0.41 → 0.0.43

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.
Files changed (41) hide show
  1. package/cjs/dist/react/ProductList.d.ts +31 -3
  2. package/cjs/dist/react/ProductList.js +33 -5
  3. package/cjs/dist/react/ProductListFilters.d.ts +100 -111
  4. package/cjs/dist/react/ProductListFilters.js +105 -115
  5. package/cjs/dist/react/ProductListPagination.d.ts +89 -96
  6. package/cjs/dist/react/ProductListPagination.js +96 -104
  7. package/cjs/dist/react/ProductListSort.d.ts +26 -57
  8. package/cjs/dist/react/ProductListSort.js +26 -58
  9. package/cjs/dist/services/index.d.ts +1 -3
  10. package/cjs/dist/services/index.js +1 -3
  11. package/cjs/dist/services/products-list-search-service.d.ts +220 -0
  12. package/cjs/dist/services/products-list-search-service.js +813 -0
  13. package/cjs/dist/services/products-list-service.d.ts +28 -11
  14. package/cjs/dist/services/products-list-service.js +26 -6
  15. package/dist/react/ProductList.d.ts +31 -3
  16. package/dist/react/ProductList.js +33 -5
  17. package/dist/react/ProductListFilters.d.ts +100 -111
  18. package/dist/react/ProductListFilters.js +105 -115
  19. package/dist/react/ProductListPagination.d.ts +89 -96
  20. package/dist/react/ProductListPagination.js +96 -104
  21. package/dist/react/ProductListSort.d.ts +26 -57
  22. package/dist/react/ProductListSort.js +26 -58
  23. package/dist/services/index.d.ts +1 -3
  24. package/dist/services/index.js +1 -3
  25. package/dist/services/products-list-search-service.d.ts +220 -0
  26. package/dist/services/products-list-search-service.js +813 -0
  27. package/dist/services/products-list-service.d.ts +28 -11
  28. package/dist/services/products-list-service.js +26 -6
  29. package/package.json +2 -2
  30. package/cjs/dist/services/products-list-filters-service.d.ts +0 -309
  31. package/cjs/dist/services/products-list-filters-service.js +0 -504
  32. package/cjs/dist/services/products-list-pagination-service.d.ts +0 -186
  33. package/cjs/dist/services/products-list-pagination-service.js +0 -179
  34. package/cjs/dist/services/products-list-sort-service.d.ts +0 -117
  35. package/cjs/dist/services/products-list-sort-service.js +0 -144
  36. package/dist/services/products-list-filters-service.d.ts +0 -309
  37. package/dist/services/products-list-filters-service.js +0 -504
  38. package/dist/services/products-list-pagination-service.d.ts +0 -186
  39. package/dist/services/products-list-pagination-service.js +0 -179
  40. package/dist/services/products-list-sort-service.d.ts +0 -117
  41. package/dist/services/products-list-sort-service.js +0 -144
@@ -1,504 +0,0 @@
1
- import { defineService } from "@wix/services-definitions";
2
- import { implementService } from "@wix/services-definitions";
3
- import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
4
- import { productsV3 } from "@wix/stores";
5
- import { ProductsListServiceDefinition } from "./products-list-service.js";
6
- import { customizationsV3 } from "@wix/stores";
7
- const PRICE_FILTER_DEBOUNCE_TIME = 300;
8
- /**
9
- * Enumeration of inventory status types available for filtering.
10
- * Maps to the Wix Stores API inventory availability statuses.
11
- *
12
- * @enum {string}
13
- */
14
- export var InventoryStatusType;
15
- (function (InventoryStatusType) {
16
- /** Product is in stock and available for purchase */
17
- InventoryStatusType["IN_STOCK"] = "IN_STOCK";
18
- /** Product is out of stock */
19
- InventoryStatusType["OUT_OF_STOCK"] = "OUT_OF_STOCK";
20
- /** Product is partially out of stock (some variants available) */
21
- InventoryStatusType["PARTIALLY_OUT_OF_STOCK"] = "PARTIALLY_OUT_OF_STOCK";
22
- })(InventoryStatusType || (InventoryStatusType = {}));
23
- /**
24
- * Loads products list filters service configuration from the Wix Stores API for SSR initialization.
25
- * This function fetches customization data that will be used to build product filter options.
26
- *
27
- * @returns {Promise<ProductsListFiltersServiceConfig>} Promise that resolves to the filters configuration
28
- *
29
- * @example
30
- * ```astro
31
- * ---
32
- * // Astro page example - pages/products.astro
33
- * import { loadProductsListFiltersServiceConfig } from '@wix/stores/services';
34
- * import { ProductsListFilters } from '@wix/stores/components';
35
- *
36
- * // Load filters configuration during SSR
37
- * const filtersConfig = await loadProductsListFiltersServiceConfig();
38
- * ---
39
- *
40
- * <ProductsListFilters.Root filtersConfig={filtersConfig}>
41
- * <ProductsListFilters.MinPrice>
42
- * {({ minPrice, setMinPrice }) => (
43
- * <input
44
- * type="number"
45
- * value={minPrice}
46
- * onChange={(e) => setMinPrice(parseFloat(e.target.value))}
47
- * placeholder="Min Price"
48
- * />
49
- * )}
50
- * </ProductsListFilters.MinPrice>
51
- * </ProductsListFilters.Root>
52
- * ```
53
- *
54
- * @example
55
- * ```tsx
56
- * // Next.js page example
57
- * import { GetServerSideProps } from 'next';
58
- * import { loadProductsListFiltersServiceConfig } from '@wix/stores/services';
59
- *
60
- * export const getServerSideProps: GetServerSideProps = async () => {
61
- * const filtersConfig = await loadProductsListFiltersServiceConfig();
62
- *
63
- * return {
64
- * props: {
65
- * filtersConfig,
66
- * },
67
- * };
68
- * };
69
- * ```
70
- */
71
- export async function loadProductsListFiltersServiceConfig() {
72
- const { items: customizations = [] } = await customizationsV3
73
- .queryCustomizations()
74
- .find();
75
- return {
76
- customizations,
77
- };
78
- }
79
- /**
80
- * Service definition for the Products List Filters service.
81
- * This defines the reactive API contract for managing product list filtering capabilities
82
- * including price, inventory status, and product option filters.
83
- *
84
- * @constant
85
- */
86
- export const ProductsListFiltersServiceDefinition = defineService("products-list-filters");
87
- /**
88
- * Implementation of the Products List Filters service that manages reactive filtering state.
89
- * This service provides signals for all filter types (price, inventory, product options) and
90
- * automatically updates the products list search options when filters change.
91
- *
92
- * @example
93
- * ```tsx
94
- * import { ProductsListFiltersService, ProductsListFiltersServiceDefinition } from '@wix/stores/services';
95
- * import { useService } from '@wix/services-manager-react';
96
- *
97
- * function FiltersComponent({ filtersConfig }) {
98
- * return (
99
- * <ServiceProvider services={createServicesMap([
100
- * [ProductsListFiltersServiceDefinition, ProductsListFiltersService.withConfig(filtersConfig)]
101
- * ])}>
102
- * <FilterControls />
103
- * </ServiceProvider>
104
- * );
105
- * }
106
- *
107
- * function FilterControls() {
108
- * const filtersService = useService(ProductsListFiltersServiceDefinition);
109
- * const minPrice = filtersService.minPrice.get();
110
- * const maxPrice = filtersService.maxPrice.get();
111
- * const selectedInventoryStatuses = filtersService.selectedInventoryStatuses.get();
112
- * const availableProductOptions = filtersService.availableProductOptions.get();
113
- * const isFiltered = filtersService.isFiltered.get();
114
- *
115
- * return (
116
- * <div>
117
- * <div>
118
- * <input
119
- * type="number"
120
- * value={minPrice}
121
- * onChange={(e) => filtersService.setMinPrice(parseFloat(e.target.value))}
122
- * placeholder="Min Price"
123
- * />
124
- * <input
125
- * type="number"
126
- * value={maxPrice}
127
- * onChange={(e) => filtersService.setMaxPrice(parseFloat(e.target.value))}
128
- * placeholder="Max Price"
129
- * />
130
- * </div>
131
- *
132
- * {availableProductOptions.map(option => (
133
- * <div key={option.id}>
134
- * <h4>{option.name}</h4>
135
- * {option.choices.map(choice => (
136
- * <label key={choice.id}>
137
- * <input
138
- * type="checkbox"
139
- * onChange={() => filtersService.toggleProductOption(option.id, choice.id)}
140
- * />
141
- * {choice.name}
142
- * </label>
143
- * ))}
144
- * </div>
145
- * ))}
146
- *
147
- * {isFiltered && (
148
- * <button onClick={() => filtersService.reset()}>
149
- * Clear All Filters
150
- * </button>
151
- * )}
152
- * </div>
153
- * );
154
- * }
155
- * }
156
- * ```
157
- */
158
- export const ProductsListFiltersService = implementService.withConfig()(ProductsListFiltersServiceDefinition, ({ getService, config }) => {
159
- let firstRun = true;
160
- const signalsService = getService(SignalsServiceDefinition);
161
- const productsListService = getService(ProductsListServiceDefinition);
162
- const { customizations } = config;
163
- const aggregationData = productsListService.aggregations.get()?.results;
164
- const currentSearchOptions = productsListService.searchOptions.get();
165
- // Get the full catalog price range from initial aggregation data (before any filters)
166
- const catalogPriceRange = getCatalogPriceRange(aggregationData || []);
167
- // Initialize signals with user's current filter selections (or 0 if no filters)
168
- const userFilterMinPriceSignal = signalsService.signal(getSelectedMinPrice(currentSearchOptions) ?? catalogPriceRange.minPrice);
169
- const userFilterMaxPriceSignal = signalsService.signal(getSelectedMaxPrice(currentSearchOptions) ?? catalogPriceRange.maxPrice);
170
- // Separate signals for the available catalog range (for UI bounds)
171
- const catalogMinPriceSignal = signalsService.signal(catalogPriceRange.minPrice);
172
- const catalogMaxPriceSignal = signalsService.signal(catalogPriceRange.maxPrice);
173
- const availableInventoryStatusesSignal = signalsService.signal([
174
- InventoryStatusType.IN_STOCK,
175
- InventoryStatusType.OUT_OF_STOCK,
176
- InventoryStatusType.PARTIALLY_OUT_OF_STOCK,
177
- ]);
178
- const selectedInventoryStatusesSignal = signalsService.signal(getSelectedInventoryStatuses(currentSearchOptions));
179
- // TODO: Get product options from aggregations data
180
- const availableProductOptionsSignal = signalsService.signal(getAvailableProductOptions(aggregationData, customizations));
181
- const selectedProductOptionsSignal = signalsService.signal(getSelectedProductOptions(currentSearchOptions));
182
- const isFilteredSignal = signalsService.signal(false);
183
- // Debounce timeout IDs for price filters
184
- let minPriceTimeoutId = null;
185
- let maxPriceTimeoutId = null;
186
- if (typeof window !== "undefined") {
187
- signalsService.effect(() => {
188
- // CRITICAL: Read the signals FIRST to establish dependencies, even on first run
189
- const minPrice = userFilterMinPriceSignal.get();
190
- const maxPrice = userFilterMaxPriceSignal.get();
191
- const selectedInventoryStatuses = selectedInventoryStatusesSignal.get();
192
- const selectedProductOptions = selectedProductOptionsSignal.get();
193
- if (firstRun) {
194
- firstRun = false;
195
- return;
196
- }
197
- doFirstRunInit(isFilteredSignal, productsListService, minPrice, maxPrice, selectedInventoryStatuses, selectedProductOptions);
198
- });
199
- }
200
- return {
201
- selectedMinPrice: userFilterMinPriceSignal,
202
- selectedMaxPrice: userFilterMaxPriceSignal,
203
- availableMinPrice: catalogMinPriceSignal,
204
- availableMaxPrice: catalogMaxPriceSignal,
205
- availableInventoryStatuses: availableInventoryStatusesSignal,
206
- selectedInventoryStatuses: selectedInventoryStatusesSignal,
207
- availableProductOptions: availableProductOptionsSignal,
208
- selectedProductOptions: selectedProductOptionsSignal,
209
- setSelectedMinPrice: (minPrice) => {
210
- // Clear any existing timeout
211
- if (minPriceTimeoutId) {
212
- clearTimeout(minPriceTimeoutId);
213
- }
214
- // Set new debounced timeout
215
- minPriceTimeoutId = setTimeout(() => {
216
- userFilterMinPriceSignal.set(minPrice);
217
- minPriceTimeoutId = null;
218
- }, PRICE_FILTER_DEBOUNCE_TIME);
219
- },
220
- setSelectedMaxPrice: (maxPrice) => {
221
- // Clear any existing timeout
222
- if (maxPriceTimeoutId) {
223
- clearTimeout(maxPriceTimeoutId);
224
- }
225
- // Set new debounced timeout
226
- maxPriceTimeoutId = setTimeout(() => {
227
- userFilterMaxPriceSignal.set(maxPrice);
228
- maxPriceTimeoutId = null;
229
- }, PRICE_FILTER_DEBOUNCE_TIME);
230
- },
231
- toggleInventoryStatus: (status) => {
232
- const current = selectedInventoryStatusesSignal.get();
233
- const isSelected = current.includes(status);
234
- if (isSelected) {
235
- selectedInventoryStatusesSignal.set(current.filter((s) => s !== status));
236
- }
237
- else {
238
- selectedInventoryStatusesSignal.set([...current, status]);
239
- }
240
- },
241
- toggleProductOption: (optionId, choiceId) => {
242
- const current = selectedProductOptionsSignal.get();
243
- const currentChoices = current[optionId] || [];
244
- const isSelected = currentChoices.includes(choiceId);
245
- if (isSelected) {
246
- // Remove the choice
247
- const newChoices = currentChoices.filter((id) => id !== choiceId);
248
- if (newChoices.length === 0) {
249
- const newOptions = { ...current };
250
- delete newOptions[optionId];
251
- selectedProductOptionsSignal.set(newOptions);
252
- }
253
- else {
254
- selectedProductOptionsSignal.set({
255
- ...current,
256
- [optionId]: newChoices,
257
- });
258
- }
259
- }
260
- else {
261
- // Add the choice
262
- selectedProductOptionsSignal.set({
263
- ...current,
264
- [optionId]: [...currentChoices, choiceId],
265
- });
266
- }
267
- },
268
- isFiltered: isFilteredSignal,
269
- reset: () => {
270
- // Reset user selections but keep catalog bounds intact
271
- userFilterMinPriceSignal.set(catalogMinPriceSignal.get());
272
- userFilterMaxPriceSignal.set(catalogMaxPriceSignal.get());
273
- selectedInventoryStatusesSignal.set([]);
274
- selectedProductOptionsSignal.set({});
275
- isFilteredSignal.set(false);
276
- },
277
- };
278
- });
279
- function doFirstRunInit(isFilteredSignal, productsListService, minPrice, maxPrice, selectedInventoryStatuses, selectedProductOptions) {
280
- isFilteredSignal.set(true);
281
- // Build new search options with updated price filters
282
- const newSearchOptions = {
283
- ...productsListService.searchOptions.peek(),
284
- };
285
- delete newSearchOptions.cursorPaging?.cursor;
286
- // Initialize filter if it doesn't exist
287
- if (!newSearchOptions.filter) {
288
- newSearchOptions.filter = {};
289
- }
290
- else {
291
- // Copy existing filter to avoid mutation
292
- newSearchOptions.filter = { ...newSearchOptions.filter };
293
- }
294
- // Remove existing price filters
295
- delete newSearchOptions.filter["actualPriceRange.minValue.amount"];
296
- delete newSearchOptions.filter["actualPriceRange.maxValue.amount"];
297
- // Remove existing inventory filter
298
- delete newSearchOptions.filter["inventory.availabilityStatus"];
299
- // Remove existing product option filters
300
- // First, find and remove any existing option filters
301
- Object.keys(newSearchOptions.filter).forEach((key) => {
302
- if (key.startsWith("options.")) {
303
- delete newSearchOptions.filter[key];
304
- }
305
- });
306
- // Add new price filters if they have valid values
307
- if (minPrice > 0) {
308
- newSearchOptions.filter["actualPriceRange.minValue.amount"] = {
309
- $gte: minPrice,
310
- };
311
- }
312
- if (maxPrice > 0) {
313
- newSearchOptions.filter["actualPriceRange.maxValue.amount"] = {
314
- $lte: maxPrice,
315
- };
316
- }
317
- // Add new inventory filter if there are selected statuses
318
- if (selectedInventoryStatuses.length > 0) {
319
- if (selectedInventoryStatuses.length === 1) {
320
- newSearchOptions.filter["inventory.availabilityStatus"] =
321
- selectedInventoryStatuses[0];
322
- }
323
- else {
324
- newSearchOptions.filter["inventory.availabilityStatus"] = {
325
- $in: selectedInventoryStatuses,
326
- };
327
- }
328
- }
329
- // Add new product option filters if there are selected options
330
- if (selectedProductOptions &&
331
- Object.keys(selectedProductOptions).length > 0) {
332
- for (const [optionId, choiceIds] of Object.entries(selectedProductOptions)) {
333
- if (choiceIds && choiceIds.length > 0) {
334
- // Handle inventory filter separately
335
- if (optionId === "inventory-filter") {
336
- newSearchOptions.filter["inventory.availabilityStatus"] = {
337
- $in: choiceIds,
338
- };
339
- }
340
- else {
341
- // Regular product options filter
342
- newSearchOptions.filter["options.choicesSettings.choices.choiceId"] = {
343
- $hasSome: choiceIds,
344
- };
345
- }
346
- }
347
- }
348
- }
349
- // Use callback to update search options
350
- productsListService.setSearchOptions(newSearchOptions);
351
- }
352
- /**
353
- * Gets the full catalog price range from aggregation data (before any filters applied)
354
- */
355
- function getCatalogPriceRange(aggregationData) {
356
- const minPrice = getMinPrice(aggregationData);
357
- const maxPrice = getMaxPrice(aggregationData);
358
- return { minPrice, maxPrice };
359
- }
360
- /**
361
- * Gets the user's currently selected minimum price filter from search options
362
- */
363
- function getSelectedMinPrice(searchOptions) {
364
- const filter = searchOptions.filter;
365
- if (!filter)
366
- return 0;
367
- const minPriceFilter = filter["actualPriceRange.minValue.amount"];
368
- if (typeof minPriceFilter === "object" &&
369
- minPriceFilter !== null &&
370
- "$gte" in minPriceFilter) {
371
- return Number(minPriceFilter.$gte);
372
- }
373
- }
374
- /**
375
- * Gets the user's currently selected maximum price filter from search options
376
- */
377
- function getSelectedMaxPrice(searchOptions) {
378
- const filter = searchOptions.filter;
379
- if (!filter)
380
- return 0;
381
- const maxPriceFilter = filter["actualPriceRange.maxValue.amount"];
382
- if (typeof maxPriceFilter === "object" &&
383
- maxPriceFilter !== null &&
384
- "$lte" in maxPriceFilter) {
385
- return Number(maxPriceFilter.$lte);
386
- }
387
- }
388
- function getMinPrice(aggregationData) {
389
- const minPriceAggregation = aggregationData.find((data) => data.fieldPath === "actualPriceRange.minValue.amount");
390
- if (minPriceAggregation?.scalar?.value) {
391
- return Number(minPriceAggregation.scalar.value) || 0;
392
- }
393
- return 0;
394
- }
395
- function getMaxPrice(aggregationData) {
396
- const maxPriceAggregation = aggregationData.find((data) => data.fieldPath === "actualPriceRange.maxValue.amount");
397
- if (maxPriceAggregation?.scalar?.value) {
398
- return Number(maxPriceAggregation.scalar.value) || 0;
399
- }
400
- return 0;
401
- }
402
- function getSelectedInventoryStatuses(searchOptions) {
403
- const filter = searchOptions.filter;
404
- if (!filter)
405
- return [];
406
- const inventoryFilter = filter["inventory.availabilityStatus"];
407
- if (typeof inventoryFilter === "string" && inventoryFilter.length > 0) {
408
- return [inventoryFilter];
409
- }
410
- if (typeof inventoryFilter === "object" &&
411
- inventoryFilter !== null &&
412
- "$in" in inventoryFilter) {
413
- return Array.isArray(inventoryFilter.$in) ? inventoryFilter.$in : [];
414
- }
415
- return [];
416
- }
417
- function getSelectedProductOptions(searchOptions) {
418
- const filter = searchOptions.filter;
419
- if (!filter)
420
- return {};
421
- const selectedOptions = {};
422
- // Look for options.{optionId}.choice filters
423
- Object.keys(filter).forEach((key) => {
424
- if (key.startsWith("options.") && key.endsWith(".choice")) {
425
- const optionId = key.slice(8, -7); // Remove "options." and ".choice"
426
- const optionFilter = filter[key];
427
- if (typeof optionFilter === "string" && optionFilter.length > 0) {
428
- selectedOptions[optionId] = [optionFilter];
429
- }
430
- else if (typeof optionFilter === "object" &&
431
- optionFilter !== null &&
432
- "$in" in optionFilter &&
433
- Array.isArray(optionFilter.$in)) {
434
- selectedOptions[optionId] = optionFilter.$in;
435
- }
436
- }
437
- });
438
- return selectedOptions;
439
- }
440
- function getAvailableProductOptions(aggregationData = [], customizations = []) {
441
- // Helper function to match aggregation names case-insensitively
442
- const matchesAggregationName = (name, aggregationNames) => {
443
- return aggregationNames.some((aggName) => aggName.toLowerCase() === name.toLowerCase());
444
- };
445
- // Helper function to sort choices intelligently (numbers first, then alphabetically)
446
- const sortChoicesIntelligently = (choices) => {
447
- return [...choices].sort((a, b) => {
448
- const aIsNumber = /^\d+$/.test(a.name);
449
- const bIsNumber = /^\d+$/.test(b.name);
450
- if (aIsNumber && bIsNumber) {
451
- return parseInt(b.name) - parseInt(a.name);
452
- }
453
- if (aIsNumber && !bIsNumber)
454
- return -1;
455
- if (!aIsNumber && bIsNumber)
456
- return 1;
457
- return a.name.localeCompare(b.name);
458
- });
459
- };
460
- // Extract option names from aggregation data
461
- const optionNames = [];
462
- const choiceNames = [];
463
- // Process aggregation results to extract available option and choice names
464
- aggregationData.forEach((result) => {
465
- if (result.name === "optionNames" && result.values?.results) {
466
- optionNames.push(...result.values.results
467
- .map((item) => item.value)
468
- .filter((value) => typeof value === "string"));
469
- }
470
- if (result.name === "choiceNames" && result.values?.results) {
471
- choiceNames.push(...result.values.results
472
- .map((item) => item.value)
473
- .filter((value) => typeof value === "string"));
474
- }
475
- });
476
- // Build options by matching customizations with aggregation data
477
- const options = customizations
478
- .filter((customization) => customization.name &&
479
- customization._id &&
480
- customization.customizationType ===
481
- customizationsV3.CustomizationType.PRODUCT_OPTION &&
482
- (optionNames.length === 0 ||
483
- matchesAggregationName(customization.name, optionNames)))
484
- .map((customization) => {
485
- const choices = (customization.choicesSettings?.choices || [])
486
- .filter((choice) => choice._id &&
487
- choice.name &&
488
- (choiceNames.length === 0 ||
489
- matchesAggregationName(choice.name, choiceNames)))
490
- .map((choice) => ({
491
- id: choice._id,
492
- name: choice.name,
493
- colorCode: choice.colorCode,
494
- }));
495
- return {
496
- id: customization._id,
497
- name: customization.name,
498
- choices: sortChoicesIntelligently(choices),
499
- optionRenderType: customization.customizationRenderType,
500
- };
501
- })
502
- .filter((option) => option.choices.length > 0);
503
- return options;
504
- }
@@ -1,186 +0,0 @@
1
- import { type Signal } from "@wix/services-definitions/core-services/signals";
2
- /**
3
- * Service definition for the Products List Pagination service.
4
- * This defines the reactive API contract for managing product list pagination state and navigation.
5
- *
6
- * @constant
7
- */
8
- export declare const ProductsListPaginationServiceDefinition: string & {
9
- __api: {
10
- /** Reactive signal containing the current page size limit */
11
- currentLimit: Signal<number>;
12
- /** Reactive signal containing the current cursor for pagination */
13
- currentCursor: Signal<string | null>;
14
- /** Computed signal indicating if there's a next page available */
15
- hasNextPage: {
16
- get: () => boolean;
17
- };
18
- /** Computed signal indicating if there's a previous page available */
19
- hasPrevPage: {
20
- get: () => boolean;
21
- };
22
- /** Function to set the page size limit */
23
- setLimit: (limit: number) => void;
24
- /** Function to navigate to the next page */
25
- nextPage: () => void;
26
- /** Function to navigate to the previous page */
27
- prevPage: () => void;
28
- /** Function to navigate to the first page */
29
- navigateToFirstPage: () => void;
30
- /** Function to load more items (increase the limit) */
31
- loadMore: (count: number) => void;
32
- };
33
- __config: {};
34
- isServiceDefinition?: boolean;
35
- } & {
36
- /** Reactive signal containing the current page size limit */
37
- currentLimit: Signal<number>;
38
- /** Reactive signal containing the current cursor for pagination */
39
- currentCursor: Signal<string | null>;
40
- /** Computed signal indicating if there's a next page available */
41
- hasNextPage: {
42
- get: () => boolean;
43
- };
44
- /** Computed signal indicating if there's a previous page available */
45
- hasPrevPage: {
46
- get: () => boolean;
47
- };
48
- /** Function to set the page size limit */
49
- setLimit: (limit: number) => void;
50
- /** Function to navigate to the next page */
51
- nextPage: () => void;
52
- /** Function to navigate to the previous page */
53
- prevPage: () => void;
54
- /** Function to navigate to the first page */
55
- navigateToFirstPage: () => void;
56
- /** Function to load more items (increase the limit) */
57
- loadMore: (count: number) => void;
58
- };
59
- /**
60
- * Configuration interface for the Products List Pagination service.
61
- * Currently empty as this service doesn't require initial configuration.
62
- *
63
- * @interface ProductsListPaginationServiceConfig
64
- */
65
- export type ProductsListPaginationServiceConfig = {};
66
- /**
67
- * Implementation of the Products List Pagination service that manages reactive pagination state.
68
- * This service provides signals for pagination state and automatically updates the products list
69
- * search options when pagination settings change. It supports both cursor-based pagination
70
- * and load-more functionality.
71
- *
72
- * @example
73
- * ```tsx
74
- * import { ProductsListPaginationService, ProductsListPaginationServiceDefinition } from '@wix/stores/services';
75
- * import { useService } from '@wix/services-manager-react';
76
- *
77
- * function PaginationComponent() {
78
- * return (
79
- * <ServiceProvider services={createServicesMap([
80
- * [ProductsListPaginationServiceDefinition, ProductsListPaginationService.withConfig({})]
81
- * ])}>
82
- * <PaginationControls />
83
- * </ServiceProvider>
84
- * );
85
- * }
86
- *
87
- * function PaginationControls() {
88
- * const paginationService = useService(ProductsListPaginationServiceDefinition);
89
- * const currentLimit = paginationService.currentLimit.get();
90
- * const hasNextPage = paginationService.hasNextPage.get();
91
- * const hasPrevPage = paginationService.hasPrevPage.get();
92
- *
93
- * return (
94
- * <div>
95
- * <div>
96
- * Items per page:
97
- * <select
98
- * value={currentLimit}
99
- * onChange={(e) => paginationService.setLimit(parseInt(e.target.value))}
100
- * >
101
- * <option value={12}>12</option>
102
- * <option value={24}>24</option>
103
- * <option value={48}>48</option>
104
- * </select>
105
- * </div>
106
- *
107
- * <div>
108
- * <button
109
- * onClick={() => paginationService.navigateToFirstPage()}
110
- * disabled={!hasPrevPage}
111
- * >
112
- * First
113
- * </button>
114
- * <button
115
- * onClick={() => paginationService.prevPage()}
116
- * disabled={!hasPrevPage}
117
- * >
118
- * Previous
119
- * </button>
120
- * <button
121
- * onClick={() => paginationService.nextPage()}
122
- * disabled={!hasNextPage}
123
- * >
124
- * Next
125
- * </button>
126
- * </div>
127
- *
128
- * <button onClick={() => paginationService.loadMore(12)}>
129
- * Load More
130
- * </button>
131
- * </div>
132
- * );
133
- * }
134
- * ```
135
- */
136
- export declare const ProductsListPaginationService: import("@wix/services-definitions").ServiceFactory<string & {
137
- __api: {
138
- /** Reactive signal containing the current page size limit */
139
- currentLimit: Signal<number>;
140
- /** Reactive signal containing the current cursor for pagination */
141
- currentCursor: Signal<string | null>;
142
- /** Computed signal indicating if there's a next page available */
143
- hasNextPage: {
144
- get: () => boolean;
145
- };
146
- /** Computed signal indicating if there's a previous page available */
147
- hasPrevPage: {
148
- get: () => boolean;
149
- };
150
- /** Function to set the page size limit */
151
- setLimit: (limit: number) => void;
152
- /** Function to navigate to the next page */
153
- nextPage: () => void;
154
- /** Function to navigate to the previous page */
155
- prevPage: () => void;
156
- /** Function to navigate to the first page */
157
- navigateToFirstPage: () => void;
158
- /** Function to load more items (increase the limit) */
159
- loadMore: (count: number) => void;
160
- };
161
- __config: {};
162
- isServiceDefinition?: boolean;
163
- } & {
164
- /** Reactive signal containing the current page size limit */
165
- currentLimit: Signal<number>;
166
- /** Reactive signal containing the current cursor for pagination */
167
- currentCursor: Signal<string | null>;
168
- /** Computed signal indicating if there's a next page available */
169
- hasNextPage: {
170
- get: () => boolean;
171
- };
172
- /** Computed signal indicating if there's a previous page available */
173
- hasPrevPage: {
174
- get: () => boolean;
175
- };
176
- /** Function to set the page size limit */
177
- setLimit: (limit: number) => void;
178
- /** Function to navigate to the next page */
179
- nextPage: () => void;
180
- /** Function to navigate to the previous page */
181
- prevPage: () => void;
182
- /** Function to navigate to the first page */
183
- navigateToFirstPage: () => void;
184
- /** Function to load more items (increase the limit) */
185
- loadMore: (count: number) => void;
186
- }, ProductsListPaginationServiceConfig>;