@wix/headless-stores 0.0.36 → 0.0.38

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 (129) hide show
  1. package/cjs/dist/react/Category.d.ts +65 -59
  2. package/cjs/dist/react/Category.js +50 -83
  3. package/cjs/dist/react/CategoryList.d.ts +184 -0
  4. package/cjs/dist/react/CategoryList.js +174 -0
  5. package/cjs/dist/react/Product.d.ts +3 -3
  6. package/cjs/dist/react/Product.js +6 -6
  7. package/{dist/react/ProductsList.d.ts → cjs/dist/react/ProductList.d.ts} +71 -38
  8. package/cjs/dist/react/{ProductsList.js → ProductList.js} +30 -26
  9. package/cjs/dist/react/ProductListFilters.d.ts +244 -0
  10. package/cjs/dist/react/ProductListFilters.js +216 -0
  11. package/cjs/dist/react/ProductListPagination.d.ts +246 -0
  12. package/cjs/dist/react/ProductListPagination.js +207 -0
  13. package/cjs/dist/react/ProductListSort.d.ts +87 -0
  14. package/cjs/dist/react/ProductListSort.js +85 -0
  15. package/cjs/dist/react/ProductModifiers.d.ts +5 -5
  16. package/cjs/dist/react/ProductModifiers.js +10 -10
  17. package/cjs/dist/react/ProductVariantSelector.d.ts +5 -5
  18. package/cjs/dist/react/ProductVariantSelector.js +13 -10
  19. package/cjs/dist/react/SelectedVariant.d.ts +66 -3
  20. package/cjs/dist/react/SelectedVariant.js +106 -7
  21. package/cjs/dist/react/index.d.ts +6 -9
  22. package/cjs/dist/react/index.js +6 -9
  23. package/cjs/dist/services/buy-now-service.d.ts +208 -0
  24. package/cjs/dist/services/buy-now-service.js +132 -1
  25. package/cjs/dist/services/categories-list-service.d.ts +163 -0
  26. package/cjs/dist/services/categories-list-service.js +148 -0
  27. package/cjs/dist/services/category-service.d.ts +115 -70
  28. package/cjs/dist/services/category-service.js +101 -110
  29. package/cjs/dist/services/index.d.ts +6 -7
  30. package/cjs/dist/services/index.js +5 -16
  31. package/cjs/dist/services/pay-now-service.d.ts +146 -0
  32. package/cjs/dist/services/pay-now-service.js +112 -1
  33. package/cjs/dist/services/product-service.d.ts +71 -0
  34. package/cjs/dist/services/product-service.js +47 -0
  35. package/cjs/dist/services/products-list-filters-service.d.ts +292 -0
  36. package/cjs/dist/services/products-list-filters-service.js +446 -0
  37. package/cjs/dist/services/products-list-pagination-service.d.ts +186 -0
  38. package/cjs/dist/services/products-list-pagination-service.js +179 -0
  39. package/cjs/dist/services/products-list-service.d.ts +138 -52
  40. package/cjs/dist/services/products-list-service.js +185 -54
  41. package/cjs/dist/services/products-list-sort-service.d.ts +117 -0
  42. package/cjs/dist/services/products-list-sort-service.js +144 -0
  43. package/cjs/dist/utils/url-params.d.ts +68 -0
  44. package/cjs/dist/utils/url-params.js +72 -4
  45. package/dist/react/Category.d.ts +65 -59
  46. package/dist/react/Category.js +50 -83
  47. package/dist/react/CategoryList.d.ts +184 -0
  48. package/dist/react/CategoryList.js +174 -0
  49. package/dist/react/Product.d.ts +3 -3
  50. package/dist/react/Product.js +6 -6
  51. package/{cjs/dist/react/ProductsList.d.ts → dist/react/ProductList.d.ts} +71 -38
  52. package/dist/react/{ProductsList.js → ProductList.js} +30 -26
  53. package/dist/react/ProductListFilters.d.ts +244 -0
  54. package/dist/react/ProductListFilters.js +216 -0
  55. package/dist/react/ProductListPagination.d.ts +246 -0
  56. package/dist/react/ProductListPagination.js +207 -0
  57. package/dist/react/ProductListSort.d.ts +87 -0
  58. package/dist/react/ProductListSort.js +85 -0
  59. package/dist/react/ProductModifiers.d.ts +5 -5
  60. package/dist/react/ProductModifiers.js +10 -10
  61. package/dist/react/ProductVariantSelector.d.ts +5 -5
  62. package/dist/react/ProductVariantSelector.js +13 -10
  63. package/dist/react/SelectedVariant.d.ts +66 -3
  64. package/dist/react/SelectedVariant.js +106 -7
  65. package/dist/react/index.d.ts +6 -9
  66. package/dist/react/index.js +6 -9
  67. package/dist/services/buy-now-service.d.ts +208 -0
  68. package/dist/services/buy-now-service.js +132 -1
  69. package/dist/services/categories-list-service.d.ts +163 -0
  70. package/dist/services/categories-list-service.js +148 -0
  71. package/dist/services/category-service.d.ts +115 -70
  72. package/dist/services/category-service.js +101 -110
  73. package/dist/services/index.d.ts +6 -7
  74. package/dist/services/index.js +5 -16
  75. package/dist/services/pay-now-service.d.ts +146 -0
  76. package/dist/services/pay-now-service.js +112 -1
  77. package/dist/services/product-service.d.ts +71 -0
  78. package/dist/services/product-service.js +47 -0
  79. package/dist/services/products-list-filters-service.d.ts +292 -0
  80. package/dist/services/products-list-filters-service.js +446 -0
  81. package/dist/services/products-list-pagination-service.d.ts +186 -0
  82. package/dist/services/products-list-pagination-service.js +179 -0
  83. package/dist/services/products-list-service.d.ts +138 -52
  84. package/dist/services/products-list-service.js +185 -54
  85. package/dist/services/products-list-sort-service.d.ts +117 -0
  86. package/dist/services/products-list-sort-service.js +144 -0
  87. package/dist/utils/url-params.d.ts +68 -0
  88. package/dist/utils/url-params.js +72 -4
  89. package/package.json +3 -3
  90. package/cjs/dist/react/Collection.d.ts +0 -294
  91. package/cjs/dist/react/Collection.js +0 -345
  92. package/cjs/dist/react/FilteredCollection.d.ts +0 -299
  93. package/cjs/dist/react/FilteredCollection.js +0 -352
  94. package/cjs/dist/react/ProductActions.d.ts +0 -70
  95. package/cjs/dist/react/ProductActions.js +0 -104
  96. package/cjs/dist/react/RelatedProducts.d.ts +0 -169
  97. package/cjs/dist/react/RelatedProducts.js +0 -180
  98. package/cjs/dist/react/Sort.d.ts +0 -37
  99. package/cjs/dist/react/Sort.js +0 -36
  100. package/cjs/dist/services/catalog-service.d.ts +0 -36
  101. package/cjs/dist/services/catalog-service.js +0 -193
  102. package/cjs/dist/services/collection-service.d.ts +0 -124
  103. package/cjs/dist/services/collection-service.js +0 -628
  104. package/cjs/dist/services/filter-service.d.ts +0 -35
  105. package/cjs/dist/services/filter-service.js +0 -119
  106. package/cjs/dist/services/related-products-service.d.ts +0 -100
  107. package/cjs/dist/services/related-products-service.js +0 -127
  108. package/cjs/dist/services/sort-service.d.ts +0 -20
  109. package/cjs/dist/services/sort-service.js +0 -27
  110. package/dist/react/Collection.d.ts +0 -294
  111. package/dist/react/Collection.js +0 -345
  112. package/dist/react/FilteredCollection.d.ts +0 -299
  113. package/dist/react/FilteredCollection.js +0 -352
  114. package/dist/react/ProductActions.d.ts +0 -70
  115. package/dist/react/ProductActions.js +0 -104
  116. package/dist/react/RelatedProducts.d.ts +0 -169
  117. package/dist/react/RelatedProducts.js +0 -180
  118. package/dist/react/Sort.d.ts +0 -37
  119. package/dist/react/Sort.js +0 -36
  120. package/dist/services/catalog-service.d.ts +0 -36
  121. package/dist/services/catalog-service.js +0 -193
  122. package/dist/services/collection-service.d.ts +0 -124
  123. package/dist/services/collection-service.js +0 -628
  124. package/dist/services/filter-service.d.ts +0 -35
  125. package/dist/services/filter-service.js +0 -119
  126. package/dist/services/related-products-service.d.ts +0 -100
  127. package/dist/services/related-products-service.js +0 -127
  128. package/dist/services/sort-service.d.ts +0 -20
  129. package/dist/services/sort-service.js +0 -27
@@ -1,102 +1,89 @@
1
1
  import { defineService, implementService } from "@wix/services-definitions";
2
2
  import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
3
- import { productsV3 } from "@wix/stores";
4
- ;
3
+ import { productsV3, readOnlyVariantsV3 } from "@wix/stores";
5
4
  /**
6
- * Loads products list service configuration from the Wix Products API for SSR initialization.
5
+ * Loads products list service configuration from the Wix Stores API for SSR initialization.
7
6
  * This function is designed to be used during Server-Side Rendering (SSR) to preload
8
- * products based on search criteria that will be used to configure the ProductsListService.
7
+ * a list of products based on search criteria.
9
8
  *
10
- * @param searchOptions Search options for filtering and querying products
11
- * @returns Promise that resolves to ProductsListServiceConfig with products, metadata, and aggregations
9
+ * @param {Parameters<typeof productsV3.searchProducts>[0]} searchOptions - The search options for querying products
10
+ * @returns {Promise<ProductsListServiceConfig>} Promise that resolves to the products list configuration
12
11
  *
13
12
  * @example
14
13
  * ```astro
15
14
  * ---
16
- * // Astro page example - pages/search.astro
15
+ * // Astro page example - pages/products.astro
17
16
  * import { loadProductsListServiceConfig } from '@wix/stores/services';
18
- * import { ProductsList } from '@wix/stores/components';
19
- *
20
- * // Get search query from URL params
21
- * const searchQuery = Astro.url.searchParams.get('q') || '';
22
- * const category = Astro.url.searchParams.get('category');
17
+ * import { ProductList } from '@wix/stores/components';
23
18
  *
24
- * // Build search options
19
+ * // Define search options
25
20
  * const searchOptions = {
26
- * query: { search: searchQuery },
27
- * filter: category ? { categories: [category] } : undefined,
28
- * paging: { limit: 12 }
21
+ * cursorPaging: { limit: 12 },
22
+ * filter: {},
23
+ * sort: [{ fieldName: 'name', order: 'ASC' }]
29
24
  * };
30
25
  *
31
- * // Load products during SSR
32
- * const productsListConfig = await loadProductsListServiceConfig(searchOptions);
26
+ * // Load products data during SSR
27
+ * const productsConfig = await loadProductsListServiceConfig(searchOptions);
33
28
  * ---
34
29
  *
35
- * <ProductsList.Root productsListConfig={productsListConfig}>
36
- * <ProductsList.ItemContent>
30
+ * <ProductList.Root productsConfig={productsConfig}>
31
+ * <ProductList.ItemContent>
37
32
  * {({ product }) => (
38
- * <div class="product-item">
33
+ * <div>
39
34
  * <h3>{product.name}</h3>
35
+ * <p>{product.description}</p>
40
36
  * </div>
41
37
  * )}
42
- * </ProductsList.ItemContent>
43
- * </ProductsList.Root>
38
+ * </ProductList.ItemContent>
39
+ * </ProductList.Root>
44
40
  * ```
45
41
  *
46
42
  * @example
47
43
  * ```tsx
48
- * // Next.js page example - pages/search.tsx
44
+ * // Next.js page example - pages/products.tsx
49
45
  * import { GetServerSideProps } from 'next';
50
46
  * import { loadProductsListServiceConfig } from '@wix/stores/services';
51
47
  * import { ProductsList } from '@wix/stores/components';
52
48
  *
53
- * interface SearchPageProps {
54
- * productsListConfig: Awaited<ReturnType<typeof loadProductsListServiceConfig>>;
55
- * searchQuery: string;
49
+ * interface ProductsPageProps {
50
+ * productsConfig: Awaited<ReturnType<typeof loadProductsListServiceConfig>>;
56
51
  * }
57
52
  *
58
- * export const getServerSideProps: GetServerSideProps<SearchPageProps> = async ({ query }) => {
59
- * const searchQuery = (query.q as string) || '';
60
- * const category = query.category as string;
61
- *
62
- * // Build search options
53
+ * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async () => {
63
54
  * const searchOptions = {
64
- * query: { search: searchQuery },
65
- * filter: category ? { categories: [category] } : undefined,
66
- * paging: { limit: 12 }
55
+ * cursorPaging: { limit: 12 },
56
+ * filter: {},
57
+ * sort: [{ fieldName: 'name', order: 'ASC' }]
67
58
  * };
68
59
  *
69
- * // Load products during SSR
70
- * const productsListConfig = await loadProductsListServiceConfig(searchOptions);
60
+ * const productsConfig = await loadProductsListServiceConfig(searchOptions);
71
61
  *
72
62
  * return {
73
63
  * props: {
74
- * productsListConfig,
75
- * searchQuery,
64
+ * productsConfig,
76
65
  * },
77
66
  * };
78
67
  * };
79
68
  *
80
- * export default function SearchPage({ productsListConfig, searchQuery }: SearchPageProps) {
69
+ * export default function ProductsPage({ productsConfig }: ProductsPageProps) {
81
70
  * return (
82
- * <div>
83
- * <h1>Search Results for "{searchQuery}"</h1>
84
- * <ProductsList.Root productsListConfig={productsListConfig}>
85
- * <ProductsList.ItemContent>
86
- * {({ product }) => (
87
- * <div className="product-item">
88
- * <h3>{product.name}</h3>
89
- * </div>
90
- * )}
91
- * </ProductsList.ItemContent>
92
- * </ProductsList.Root>
93
- * </div>
71
+ * <ProductList.Root productsConfig={productsConfig}>
72
+ * <ProductList.ItemContent>
73
+ * {({ product }) => (
74
+ * <div>
75
+ * <h3>{product.name}</h3>
76
+ * <p>{product.description}</p>
77
+ * </div>
78
+ * )}
79
+ * </ProductList.ItemContent>
80
+ * </ProductList.Root>
94
81
  * );
95
82
  * }
96
83
  * ```
97
84
  */
98
85
  export async function loadProductsListServiceConfig(searchOptions) {
99
- const result = await productsV3.searchProducts(searchOptions);
86
+ const result = await fetchProducts(searchOptions);
100
87
  return {
101
88
  products: result.products ?? [],
102
89
  searchOptions,
@@ -104,7 +91,151 @@ export async function loadProductsListServiceConfig(searchOptions) {
104
91
  aggregations: result.aggregationData,
105
92
  };
106
93
  }
94
+ /**
95
+ * Fetches products and their missing variants in one optimized request.
96
+ * This function wraps the standard searchProducts call and automatically
97
+ * fetches missing variant data for all products that need it.
98
+ *
99
+ * @param searchOptions - The search options for querying products
100
+ * @returns Promise that resolves to the search result with complete variant data
101
+ */
102
+ const fetchProducts = async (searchOptions) => {
103
+ const result = await productsV3.searchProducts(searchOptions);
104
+ // Fetch missing variants for all products in one batch request
105
+ if (result.products) {
106
+ result.products = await fetchMissingVariants(result.products);
107
+ }
108
+ return result;
109
+ };
110
+ /**
111
+ * Fetches missing variants for all products in one batch request.
112
+ * This function identifies products that need variant data and fetches
113
+ * all variants efficiently using the readOnlyVariantsV3 API.
114
+ *
115
+ * @param products - Array of products that may need variant data
116
+ * @returns Promise that resolves to products with complete variant information
117
+ */
118
+ const fetchMissingVariants = async (products) => {
119
+ // Find products that need variants (both single and multi-variant products)
120
+ const productsNeedingVariants = products.filter((product) => !product.variantsInfo?.variants &&
121
+ product.variantSummary?.variantCount &&
122
+ product.variantSummary.variantCount > 0);
123
+ if (productsNeedingVariants.length === 0) {
124
+ return products;
125
+ }
126
+ try {
127
+ const productIds = productsNeedingVariants
128
+ .map((p) => p._id)
129
+ .filter(Boolean);
130
+ if (productIds.length === 0) {
131
+ return products;
132
+ }
133
+ const items = [];
134
+ const res = await readOnlyVariantsV3
135
+ .queryVariants({})
136
+ .in("productData.productId", productIds)
137
+ .limit(100)
138
+ .find();
139
+ items.push(...res.items);
140
+ let nextRes = res;
141
+ while (nextRes.hasNext()) {
142
+ nextRes = await nextRes.next();
143
+ items.push(...nextRes.items);
144
+ }
145
+ const variantsByProductId = new Map();
146
+ items.forEach((item) => {
147
+ const productId = item.productData?.productId;
148
+ if (productId) {
149
+ if (!variantsByProductId.has(productId)) {
150
+ variantsByProductId.set(productId, []);
151
+ }
152
+ variantsByProductId.get(productId).push({
153
+ ...item,
154
+ choices: item.optionChoices,
155
+ });
156
+ }
157
+ });
158
+ // Update products with their variants
159
+ return products.map((product) => {
160
+ const variants = variantsByProductId.get(product._id || "");
161
+ if (variants && variants.length > 0) {
162
+ return {
163
+ ...product,
164
+ variantsInfo: {
165
+ ...product.variantsInfo,
166
+ variants,
167
+ },
168
+ };
169
+ }
170
+ return product;
171
+ });
172
+ }
173
+ catch (error) {
174
+ console.error("Failed to fetch missing variants:", error);
175
+ return products;
176
+ }
177
+ };
178
+ /**
179
+ * Service definition for the Products List service.
180
+ * This defines the reactive API contract for managing a list of products with search, pagination, and filtering capabilities.
181
+ *
182
+ * @constant
183
+ */
107
184
  export const ProductsListServiceDefinition = defineService("products-list");
185
+ /**
186
+ * Implementation of the Products List service that manages reactive products data.
187
+ * This service provides signals for products data, search options, pagination, aggregations,
188
+ * loading state, and error handling. It automatically re-fetches products when search options change.
189
+ *
190
+ * @example
191
+ * ```tsx
192
+ * import { ProductListService, ProductsListServiceDefinition } from '@wix/stores/services';
193
+ * import { useService } from '@wix/services-manager-react';
194
+ *
195
+ * function ProductsComponent({ productsConfig }) {
196
+ * return (
197
+ * <ServiceProvider services={createServicesMap([
198
+ * [ProductsListServiceDefinition, ProductListService.withConfig(productsConfig)]
199
+ * ])}>
200
+ * <ProductsDisplay />
201
+ * </ServiceProvider>
202
+ * );
203
+ * }
204
+ *
205
+ * function ProductsDisplay() {
206
+ * const productsService = useService(ProductsListServiceDefinition);
207
+ * const products = productsService.products.get();
208
+ * const isLoading = productsService.isLoading.get();
209
+ * const error = productsService.error.get();
210
+ *
211
+ * // Update search options to filter by category
212
+ * const filterByCategory = (categoryId: string) => {
213
+ * const currentOptions = productsService.searchOptions.get();
214
+ * productsService.setSearchOptions({
215
+ * ...currentOptions,
216
+ * filter: {
217
+ * ...currentOptions.filter,
218
+ * categoryIds: [categoryId]
219
+ * }
220
+ * });
221
+ * };
222
+ *
223
+ * if (isLoading) return <div>Loading products...</div>;
224
+ * if (error) return <div>Error: {error}</div>;
225
+ *
226
+ * return (
227
+ * <div>
228
+ * {products.map(product => (
229
+ * <div key={product._id}>
230
+ * <h3>{product.name}</h3>
231
+ * <p>{product.description}</p>
232
+ * </div>
233
+ * ))}
234
+ * </div>
235
+ * );
236
+ * }
237
+ * ```
238
+ */
108
239
  export const ProductListService = implementService.withConfig()(ProductsListServiceDefinition, ({ getService, config }) => {
109
240
  let firstRun = true;
110
241
  const signalsService = getService(SignalsServiceDefinition);
@@ -132,7 +263,7 @@ export const ProductListService = implementService.withConfig()(ProductsListServ
132
263
  },
133
264
  }
134
265
  : searchOptions;
135
- const result = await productsV3.searchProducts(affectiveSearchOptions);
266
+ const result = await fetchProducts(affectiveSearchOptions);
136
267
  productsSignal.set(result.products ?? []);
137
268
  pagingMetadataSignal.set(result.pagingMetadata);
138
269
  }
@@ -0,0 +1,117 @@
1
+ import type { Signal } from "@wix/services-definitions/core-services/signals";
2
+ /**
3
+ * Service definition for the Products List Sort service.
4
+ * This defines the reactive API contract for managing product list sorting options.
5
+ *
6
+ * @constant
7
+ */
8
+ export declare const ProductsListSortServiceDefinition: string & {
9
+ __api: {
10
+ /** Reactive signal containing the currently selected sort option */
11
+ selectedSortOption: Signal<string>;
12
+ /** Function to update the selected sort option */
13
+ setSelectedSortOption: (sort: string) => void;
14
+ /** Array of available sort types */
15
+ sortOptions: SortType[];
16
+ };
17
+ __config: {};
18
+ isServiceDefinition?: boolean;
19
+ } & {
20
+ /** Reactive signal containing the currently selected sort option */
21
+ selectedSortOption: Signal<string>;
22
+ /** Function to update the selected sort option */
23
+ setSelectedSortOption: (sort: string) => void;
24
+ /** Array of available sort types */
25
+ sortOptions: SortType[];
26
+ };
27
+ /**
28
+ * Configuration interface for the Products List Sort service.
29
+ * Currently empty as this service doesn't require initial configuration.
30
+ *
31
+ * @interface ProductsListSortServiceConfig
32
+ */
33
+ export type ProductsListSortServiceConfig = {};
34
+ /**
35
+ * Enumeration of available product sort types.
36
+ * These values correspond to how products can be sorted in the product list.
37
+ *
38
+ * @enum {string}
39
+ */
40
+ export declare enum SortType {
41
+ /** Sort by newest products first */
42
+ NEWEST = "newest",
43
+ /** Sort by product name in ascending order (A-Z) */
44
+ NAME_ASC = "name_asc",
45
+ /** Sort by product name in descending order (Z-A) */
46
+ NAME_DESC = "name_desc",
47
+ /** Sort by price in ascending order (lowest first) */
48
+ PRICE_ASC = "price_asc",
49
+ /** Sort by price in descending order (highest first) */
50
+ PRICE_DESC = "price_desc",
51
+ /** Sort by recommended products (algorithm-based) */
52
+ RECOMMENDED = "recommended"
53
+ }
54
+ /**
55
+ * Implementation of the Products List Sort service that manages reactive sorting state.
56
+ * This service provides signals for the current sort option and automatically updates
57
+ * the products list search options when the sort selection changes.
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * import { ProductsListSortService, ProductsListSortServiceDefinition, SortType } from '@wix/stores/services';
62
+ * import { useService } from '@wix/services-manager-react';
63
+ *
64
+ * function SortComponent() {
65
+ * return (
66
+ * <ServiceProvider services={createServicesMap([
67
+ * [ProductsListSortServiceDefinition, ProductsListSortService.withConfig({})]
68
+ * ])}>
69
+ * <SortSelector />
70
+ * </ServiceProvider>
71
+ * );
72
+ * }
73
+ *
74
+ * function SortSelector() {
75
+ * const sortService = useService(ProductsListSortServiceDefinition);
76
+ * const selectedSort = sortService.selectedSortOption.get();
77
+ * const sortOptions = sortService.sortOptions;
78
+ *
79
+ * return (
80
+ * <select
81
+ * value={selectedSort}
82
+ * onChange={(e) => sortService.setSelectedSortOption(e.target.value)}
83
+ * >
84
+ * {sortOptions.map(option => (
85
+ * <option key={option} value={option}>
86
+ * {option === SortType.NAME_ASC ? 'Name A-Z' :
87
+ * option === SortType.NAME_DESC ? 'Name Z-A' :
88
+ * option === SortType.PRICE_ASC ? 'Price Low to High' :
89
+ * option === SortType.PRICE_DESC ? 'Price High to Low' :
90
+ * option === SortType.NEWEST ? 'Newest First' :
91
+ * 'Recommended'}
92
+ * </option>
93
+ * ))}
94
+ * </select>
95
+ * );
96
+ * }
97
+ * ```
98
+ */
99
+ export declare const ProductsListSortService: import("@wix/services-definitions").ServiceFactory<string & {
100
+ __api: {
101
+ /** Reactive signal containing the currently selected sort option */
102
+ selectedSortOption: Signal<string>;
103
+ /** Function to update the selected sort option */
104
+ setSelectedSortOption: (sort: string) => void;
105
+ /** Array of available sort types */
106
+ sortOptions: SortType[];
107
+ };
108
+ __config: {};
109
+ isServiceDefinition?: boolean;
110
+ } & {
111
+ /** Reactive signal containing the currently selected sort option */
112
+ selectedSortOption: Signal<string>;
113
+ /** Function to update the selected sort option */
114
+ setSelectedSortOption: (sort: string) => void;
115
+ /** Array of available sort types */
116
+ sortOptions: SortType[];
117
+ }, ProductsListSortServiceConfig>;
@@ -0,0 +1,144 @@
1
+ import { defineService, implementService } from "@wix/services-definitions";
2
+ import { SignalsServiceDefinition } from "@wix/services-definitions/core-services/signals";
3
+ import { ProductsListServiceDefinition } from "./products-list-service.js";
4
+ import { productsV3 } from "@wix/stores";
5
+ /**
6
+ * Service definition for the Products List Sort service.
7
+ * This defines the reactive API contract for managing product list sorting options.
8
+ *
9
+ * @constant
10
+ */
11
+ export const ProductsListSortServiceDefinition = defineService("products-list-sort");
12
+ /**
13
+ * Enumeration of available product sort types.
14
+ * These values correspond to how products can be sorted in the product list.
15
+ *
16
+ * @enum {string}
17
+ */
18
+ export var SortType;
19
+ (function (SortType) {
20
+ /** Sort by newest products first */
21
+ SortType["NEWEST"] = "newest";
22
+ /** Sort by product name in ascending order (A-Z) */
23
+ SortType["NAME_ASC"] = "name_asc";
24
+ /** Sort by product name in descending order (Z-A) */
25
+ SortType["NAME_DESC"] = "name_desc";
26
+ /** Sort by price in ascending order (lowest first) */
27
+ SortType["PRICE_ASC"] = "price_asc";
28
+ /** Sort by price in descending order (highest first) */
29
+ SortType["PRICE_DESC"] = "price_desc";
30
+ /** Sort by recommended products (algorithm-based) */
31
+ SortType["RECOMMENDED"] = "recommended";
32
+ })(SortType || (SortType = {}));
33
+ /**
34
+ * Implementation of the Products List Sort service that manages reactive sorting state.
35
+ * This service provides signals for the current sort option and automatically updates
36
+ * the products list search options when the sort selection changes.
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * import { ProductsListSortService, ProductsListSortServiceDefinition, SortType } from '@wix/stores/services';
41
+ * import { useService } from '@wix/services-manager-react';
42
+ *
43
+ * function SortComponent() {
44
+ * return (
45
+ * <ServiceProvider services={createServicesMap([
46
+ * [ProductsListSortServiceDefinition, ProductsListSortService.withConfig({})]
47
+ * ])}>
48
+ * <SortSelector />
49
+ * </ServiceProvider>
50
+ * );
51
+ * }
52
+ *
53
+ * function SortSelector() {
54
+ * const sortService = useService(ProductsListSortServiceDefinition);
55
+ * const selectedSort = sortService.selectedSortOption.get();
56
+ * const sortOptions = sortService.sortOptions;
57
+ *
58
+ * return (
59
+ * <select
60
+ * value={selectedSort}
61
+ * onChange={(e) => sortService.setSelectedSortOption(e.target.value)}
62
+ * >
63
+ * {sortOptions.map(option => (
64
+ * <option key={option} value={option}>
65
+ * {option === SortType.NAME_ASC ? 'Name A-Z' :
66
+ * option === SortType.NAME_DESC ? 'Name Z-A' :
67
+ * option === SortType.PRICE_ASC ? 'Price Low to High' :
68
+ * option === SortType.PRICE_DESC ? 'Price High to Low' :
69
+ * option === SortType.NEWEST ? 'Newest First' :
70
+ * 'Recommended'}
71
+ * </option>
72
+ * ))}
73
+ * </select>
74
+ * );
75
+ * }
76
+ * ```
77
+ */
78
+ export const ProductsListSortService = implementService.withConfig()(ProductsListSortServiceDefinition, ({ getService }) => {
79
+ let firstRun = true;
80
+ const signalsService = getService(SignalsServiceDefinition);
81
+ const productsListService = getService(ProductsListServiceDefinition);
82
+ const selectedSortOptionSignal = signalsService.signal("name");
83
+ if (typeof window !== "undefined") {
84
+ signalsService.effect(() => {
85
+ const sort = selectedSortOptionSignal.get();
86
+ if (firstRun) {
87
+ firstRun = false;
88
+ return;
89
+ }
90
+ const newSearchOptions = {
91
+ ...productsListService.searchOptions.peek(),
92
+ };
93
+ if (!newSearchOptions.sort) {
94
+ newSearchOptions.sort = [];
95
+ }
96
+ else {
97
+ // Copy existing filter to avoid mutation
98
+ newSearchOptions.sort = [...newSearchOptions.sort];
99
+ }
100
+ switch (sort) {
101
+ case SortType.NAME_ASC:
102
+ newSearchOptions.sort = [
103
+ { fieldName: "name", order: productsV3.SortDirection.ASC },
104
+ ];
105
+ break;
106
+ case SortType.NAME_DESC:
107
+ newSearchOptions.sort = [
108
+ { fieldName: "name", order: productsV3.SortDirection.DESC },
109
+ ];
110
+ break;
111
+ case SortType.PRICE_ASC:
112
+ newSearchOptions.sort = [
113
+ {
114
+ fieldName: "actualPriceRange.minValue.amount",
115
+ order: productsV3.SortDirection.ASC,
116
+ },
117
+ ];
118
+ break;
119
+ case SortType.PRICE_DESC:
120
+ newSearchOptions.sort = [
121
+ {
122
+ fieldName: "actualPriceRange.minValue.amount",
123
+ order: productsV3.SortDirection.DESC,
124
+ },
125
+ ];
126
+ break;
127
+ case SortType.RECOMMENDED:
128
+ newSearchOptions.sort = [
129
+ {
130
+ fieldName: "name",
131
+ order: productsV3.SortDirection.DESC,
132
+ },
133
+ ];
134
+ break;
135
+ }
136
+ productsListService.setSearchOptions(newSearchOptions);
137
+ });
138
+ }
139
+ return {
140
+ selectedSortOption: selectedSortOptionSignal,
141
+ sortOptions: Object.values(SortType),
142
+ setSelectedSortOption: (sort) => selectedSortOptionSignal.set(sort),
143
+ };
144
+ });
@@ -1,5 +1,73 @@
1
+ /**
2
+ * Utility class for managing URL parameters in web applications.
3
+ * Provides methods to parse, update, and retrieve URL search parameters with support for multiple values.
4
+ *
5
+ * @class URLParamsUtils
6
+ */
1
7
  export declare class URLParamsUtils {
8
+ /**
9
+ * Parses URLSearchParams into a more convenient format that supports multiple values for the same key.
10
+ * Converts multiple parameters with the same key into an array.
11
+ *
12
+ * @static
13
+ * @param {URLSearchParams} searchParams - The URLSearchParams object to parse
14
+ * @returns {Record<string, string | string[]>} Object with parameter names as keys and values as strings or arrays
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // URL: ?color=red&color=blue&size=large
19
+ * const params = new URLSearchParams('color=red&color=blue&size=large');
20
+ * const parsed = URLParamsUtils.parseSearchParams(params);
21
+ * // Result: { color: ['red', 'blue'], size: 'large' }
22
+ * ```
23
+ */
2
24
  static parseSearchParams(searchParams: URLSearchParams): Record<string, string | string[]>;
25
+ /**
26
+ * Updates the current page URL with new parameters without causing a page reload.
27
+ * Supports multiple values for the same parameter key.
28
+ *
29
+ * @static
30
+ * @param {Record<string, string | string[]>} params - Object with parameter names and values to set
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * // Update URL with single and multiple values
35
+ * URLParamsUtils.updateURL({
36
+ * category: 'electronics',
37
+ * color: ['red', 'blue'],
38
+ * price: '100'
39
+ * });
40
+ * // URL becomes: ?category=electronics&color=red&color=blue&price=100
41
+ * ```
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // Clear all parameters by passing empty object
46
+ * URLParamsUtils.updateURL({});
47
+ * // URL becomes: current-path (no query string)
48
+ * ```
49
+ */
3
50
  static updateURL(params: Record<string, string | string[]>): void;
51
+ /**
52
+ * Gets the current URL parameters parsed into a convenient format.
53
+ * Returns an empty object when running in server-side environment.
54
+ *
55
+ * @static
56
+ * @returns {Record<string, string | string[]>} Object with current URL parameters
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // Current URL: ?category=electronics&color=red&color=blue
61
+ * const params = URLParamsUtils.getURLParams();
62
+ * // Result: { category: 'electronics', color: ['red', 'blue'] }
63
+ * ```
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Server-side usage
68
+ * const params = URLParamsUtils.getURLParams();
69
+ * // Result: {} (empty object)
70
+ * ```
71
+ */
4
72
  static getURLParams(): Record<string, string | string[]>;
5
73
  }