@wix/headless-stores 0.0.42 → 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.
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { type ProductOption, InventoryStatusType } from "../services/products-list-search-service.js";
3
+ import { Category } from "@wix/auto_sdk_categories_categories";
3
4
  /**
4
5
  * Props for InventoryStatus headless component
5
6
  */
@@ -168,6 +169,14 @@ export interface PriceRangeRenderProps {
168
169
  * ```
169
170
  */
170
171
  export declare function PriceRange(props: PriceRangeProps): ReactNode;
172
+ export interface CategoryFilterRenderProps {
173
+ selectedCategory: Category | null;
174
+ }
175
+ export interface CategoryFilterProps {
176
+ /** Content to display (can be a render function receiving category data or ReactNode) */
177
+ children: ((props: CategoryFilterRenderProps) => ReactNode) | ReactNode;
178
+ }
179
+ export declare function CategoryFilter(props: CategoryFilterProps): ReactNode;
171
180
  /**
172
181
  * Props for ProductOptions headless component
173
182
  */
@@ -148,6 +148,13 @@ export function PriceRange(props) {
148
148
  })
149
149
  : props.children;
150
150
  }
151
+ export function CategoryFilter(props) {
152
+ const service = useService(ProductsListSearchServiceDefinition);
153
+ const selectedCategory = service.selectedCategory.get();
154
+ return typeof props.children === "function"
155
+ ? props.children({ selectedCategory })
156
+ : props.children;
157
+ }
151
158
  /**
152
159
  * Headless component that renders content for each product option in the list.
153
160
  * Maps over all available product options and provides each option through a render prop.
@@ -1,5 +1,6 @@
1
1
  import type { Signal } from "@wix/services-definitions/core-services/signals";
2
2
  import { productsV3, customizationsV3 } from "@wix/stores";
3
+ import { type Category } from "./category-service.js";
3
4
  import { SortType } from "./../enums/sort-enums.js";
4
5
  export { SortType } from "./../enums/sort-enums.js";
5
6
  /**
@@ -42,7 +43,7 @@ type InitialSearchState = {
42
43
  };
43
44
  inventoryStatuses?: InventoryStatusType[];
44
45
  productOptions?: Record<string, string[]>;
45
- category?: string;
46
+ category?: Category;
46
47
  visible?: boolean;
47
48
  productType?: string;
48
49
  };
@@ -83,12 +84,12 @@ export declare const ProductsListSearchServiceDefinition: string & {
83
84
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
84
85
  availableProductOptions: Signal<ProductOption[]>;
85
86
  selectedProductOptions: Signal<Record<string, string[]>>;
86
- selectedCategory: Signal<string | null>;
87
+ selectedCategory: Signal<Category | null>;
87
88
  setSelectedMinPrice: (minPrice: number) => void;
88
89
  setSelectedMaxPrice: (maxPrice: number) => void;
89
90
  toggleInventoryStatus: (status: InventoryStatusType) => void;
90
91
  toggleProductOption: (optionId: string, choiceId: string) => void;
91
- setSelectedCategory: (category: string | null) => void;
92
+ setSelectedCategory: (category: Category | null) => void;
92
93
  isFiltered: Signal<boolean>;
93
94
  reset: () => void;
94
95
  };
@@ -119,12 +120,12 @@ export declare const ProductsListSearchServiceDefinition: string & {
119
120
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
120
121
  availableProductOptions: Signal<ProductOption[]>;
121
122
  selectedProductOptions: Signal<Record<string, string[]>>;
122
- selectedCategory: Signal<string | null>;
123
+ selectedCategory: Signal<Category | null>;
123
124
  setSelectedMinPrice: (minPrice: number) => void;
124
125
  setSelectedMaxPrice: (maxPrice: number) => void;
125
126
  toggleInventoryStatus: (status: InventoryStatusType) => void;
126
127
  toggleProductOption: (optionId: string, choiceId: string) => void;
127
- setSelectedCategory: (category: string | null) => void;
128
+ setSelectedCategory: (category: Category | null) => void;
128
129
  isFiltered: Signal<boolean>;
129
130
  reset: () => void;
130
131
  };
@@ -135,7 +136,7 @@ export declare function convertUrlSortToSortType(urlSort: string): SortType | nu
135
136
  /**
136
137
  * Parse URL and build complete search options with all filters, sort, and pagination
137
138
  */
138
- export declare function parseUrlForProductsListSearch(url: string, defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
139
+ export declare function parseUrlForProductsListSearch(url: string, categoriesList: Category[], defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
139
140
  searchOptions: productsV3.V3ProductSearch;
140
141
  initialSearchState: InitialSearchState;
141
142
  }>;
@@ -172,12 +173,12 @@ export declare const ProductsListSearchService: import("@wix/services-definition
172
173
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
173
174
  availableProductOptions: Signal<ProductOption[]>;
174
175
  selectedProductOptions: Signal<Record<string, string[]>>;
175
- selectedCategory: Signal<string | null>;
176
+ selectedCategory: Signal<Category | null>;
176
177
  setSelectedMinPrice: (minPrice: number) => void;
177
178
  setSelectedMaxPrice: (maxPrice: number) => void;
178
179
  toggleInventoryStatus: (status: InventoryStatusType) => void;
179
180
  toggleProductOption: (optionId: string, choiceId: string) => void;
180
- setSelectedCategory: (category: string | null) => void;
181
+ setSelectedCategory: (category: Category | null) => void;
181
182
  isFiltered: Signal<boolean>;
182
183
  reset: () => void;
183
184
  };
@@ -208,12 +209,12 @@ export declare const ProductsListSearchService: import("@wix/services-definition
208
209
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
209
210
  availableProductOptions: Signal<ProductOption[]>;
210
211
  selectedProductOptions: Signal<Record<string, string[]>>;
211
- selectedCategory: Signal<string | null>;
212
+ selectedCategory: Signal<Category | null>;
212
213
  setSelectedMinPrice: (minPrice: number) => void;
213
214
  setSelectedMaxPrice: (maxPrice: number) => void;
214
215
  toggleInventoryStatus: (status: InventoryStatusType) => void;
215
216
  toggleProductOption: (optionId: string, choiceId: string) => void;
216
- setSelectedCategory: (category: string | null) => void;
217
+ setSelectedCategory: (category: Category | null) => void;
217
218
  isFiltered: Signal<boolean>;
218
219
  reset: () => void;
219
220
  }, ProductsListSearchServiceConfig>;
@@ -2,6 +2,7 @@ import { defineService, implementService } from "@wix/services-definitions";
2
2
  import { SignalsServiceDefinition } from "@wix/services-definitions/core-services/signals";
3
3
  import { DEFAULT_QUERY_LIMIT, ProductsListServiceDefinition, } from "./products-list-service.js";
4
4
  import { productsV3, customizationsV3 } from "@wix/stores";
5
+ import { loadCategoriesListServiceConfig } from "./categories-list-service.js";
5
6
  const PRICE_FILTER_DEBOUNCE_TIME = 300;
6
7
  import { SortType } from "./../enums/sort-enums.js";
7
8
  export { SortType } from "./../enums/sort-enums.js";
@@ -63,7 +64,7 @@ export function convertUrlSortToSortType(urlSort) {
63
64
  function updateUrlWithSearchState(searchState) {
64
65
  if (typeof window === "undefined")
65
66
  return;
66
- const { sort, filters, customizations, catalogBounds } = searchState;
67
+ const { sort, filters, customizations, catalogBounds, categorySlug } = searchState;
67
68
  // Convert filter IDs back to human-readable names for URL
68
69
  const humanReadableOptions = {};
69
70
  for (const [optionId, choiceIds] of Object.entries(filters?.productOptions ?? {})) {
@@ -91,10 +92,10 @@ function updateUrlWithSearchState(searchState) {
91
92
  "minPrice",
92
93
  "maxPrice",
93
94
  "inventoryStatus",
94
- "category",
95
95
  "visible",
96
96
  "productType",
97
97
  // Product option names will be dynamically added below
98
+ // Note: category is NOT included here as it's handled in the URL path
98
99
  ];
99
100
  // Remove existing search parameters first
100
101
  searchParams.forEach((param) => params.delete(param));
@@ -124,10 +125,6 @@ function updateUrlWithSearchState(searchState) {
124
125
  if (filters.inventoryStatuses && filters.inventoryStatuses.length > 0) {
125
126
  params.set("inventoryStatus", filters.inventoryStatuses.join(","));
126
127
  }
127
- // Add category filter
128
- if (filters.category) {
129
- params.set("category", filters.category);
130
- }
131
128
  // Add visibility filter (only if explicitly false, since true is default)
132
129
  if (filters.visible === false) {
133
130
  params.set("visible", "false");
@@ -142,8 +139,15 @@ function updateUrlWithSearchState(searchState) {
142
139
  params.set(optionName, values.join(","));
143
140
  }
144
141
  }
142
+ // Handle URL path construction with category
143
+ let baseUrl = window.location.pathname;
144
+ // If categorySlug is provided, update the path
145
+ if (categorySlug) {
146
+ if (categorySlug) {
147
+ baseUrl = `/category/${categorySlug}`;
148
+ }
149
+ }
145
150
  // Build the new URL
146
- const baseUrl = window.location.pathname;
147
151
  const newUrl = params.toString()
148
152
  ? `${baseUrl}?${params.toString()}`
149
153
  : baseUrl;
@@ -155,7 +159,7 @@ function updateUrlWithSearchState(searchState) {
155
159
  /**
156
160
  * Parse URL and build complete search options with all filters, sort, and pagination
157
161
  */
158
- export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
162
+ export async function parseUrlForProductsListSearch(url, categoriesList, defaultSearchOptions) {
159
163
  const urlObj = new URL(url);
160
164
  const searchParams = urlObj.searchParams;
161
165
  // Get customizations for product option parsing
@@ -171,6 +175,21 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
171
175
  };
172
176
  // Initialize search state for service
173
177
  const initialSearchState = {};
178
+ // Extract category slug from URL path (e.g., /category/category-slug)
179
+ const pathSegments = urlObj.pathname.split("/");
180
+ const categoryIndex = pathSegments.findIndex((segment) => segment === "category");
181
+ let categorySlug = null;
182
+ let category = undefined;
183
+ if (categoryIndex !== -1 && categoryIndex + 1 < pathSegments.length) {
184
+ categorySlug = pathSegments[categoryIndex + 1] || null;
185
+ // Find the category by slug from the provided categories list
186
+ if (categorySlug) {
187
+ category = categoriesList.find((cat) => cat.slug === categorySlug);
188
+ if (category) {
189
+ initialSearchState.category = category;
190
+ }
191
+ }
192
+ }
174
193
  // Handle text search (q parameter)
175
194
  const query = searchParams.get("q");
176
195
  if (query) {
@@ -252,12 +271,11 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
252
271
  filter["productType"] = productType;
253
272
  initialSearchState.productType = productType;
254
273
  }
255
- const category = searchParams.get("category");
274
+ // Add category filter if found
256
275
  if (category) {
257
276
  filter["allCategoriesInfo.categories"] = {
258
- $matchItems: [{ _id: { $in: [category] } }],
277
+ $matchItems: [{ _id: { $in: [category._id] } }],
259
278
  };
260
- initialSearchState.category = category;
261
279
  }
262
280
  // Price range filtering
263
281
  const minPrice = searchParams.get("minPrice");
@@ -285,7 +303,6 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
285
303
  "maxPrice",
286
304
  "inventory_status",
287
305
  "inventoryStatus",
288
- "category",
289
306
  "visible",
290
307
  "productType",
291
308
  "q",
@@ -378,7 +395,9 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
378
395
  * Load search service configuration from URL
379
396
  */
380
397
  export async function loadProductsListSearchServiceConfig(url) {
381
- const { initialSearchState } = await parseUrlForProductsListSearch(url);
398
+ // Load categories using the categories service
399
+ const categoriesListConfig = await loadCategoriesListServiceConfig();
400
+ const { initialSearchState } = await parseUrlForProductsListSearch(url, categoriesListConfig.categories);
382
401
  const { items: customizations = [] } = await customizationsV3
383
402
  .queryCustomizations()
384
403
  .find();
@@ -550,7 +569,7 @@ export const ProductsListSearchService = implementService.withConfig()(ProductsL
550
569
  }
551
570
  if (selectedCategory) {
552
571
  newSearchOptions.filter["allCategoriesInfo.categories"] = {
553
- $matchItems: [{ _id: { $in: [selectedCategory] } }],
572
+ $matchItems: [{ _id: { $in: [selectedCategory._id] } }],
554
573
  };
555
574
  }
556
575
  if (selectedVisible !== null) {
@@ -571,7 +590,6 @@ export const ProductsListSearchService = implementService.withConfig()(ProductsL
571
590
  priceRange: { min: minPrice, max: maxPrice },
572
591
  inventoryStatuses: selectedInventoryStatuses,
573
592
  productOptions: selectedProductOptions,
574
- ...(selectedCategory && { category: selectedCategory }),
575
593
  ...(selectedVisible !== null && { visible: selectedVisible }),
576
594
  ...(selectedProductType && { productType: selectedProductType }),
577
595
  };
@@ -580,6 +598,7 @@ export const ProductsListSearchService = implementService.withConfig()(ProductsL
580
598
  filters: currentFilters,
581
599
  customizations,
582
600
  catalogBounds,
601
+ categorySlug: selectedCategory?.slug || undefined,
583
602
  });
584
603
  });
585
604
  }
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { type ProductOption, InventoryStatusType } from "../services/products-list-search-service.js";
3
+ import { Category } from "@wix/auto_sdk_categories_categories";
3
4
  /**
4
5
  * Props for InventoryStatus headless component
5
6
  */
@@ -168,6 +169,14 @@ export interface PriceRangeRenderProps {
168
169
  * ```
169
170
  */
170
171
  export declare function PriceRange(props: PriceRangeProps): ReactNode;
172
+ export interface CategoryFilterRenderProps {
173
+ selectedCategory: Category | null;
174
+ }
175
+ export interface CategoryFilterProps {
176
+ /** Content to display (can be a render function receiving category data or ReactNode) */
177
+ children: ((props: CategoryFilterRenderProps) => ReactNode) | ReactNode;
178
+ }
179
+ export declare function CategoryFilter(props: CategoryFilterProps): ReactNode;
171
180
  /**
172
181
  * Props for ProductOptions headless component
173
182
  */
@@ -148,6 +148,13 @@ export function PriceRange(props) {
148
148
  })
149
149
  : props.children;
150
150
  }
151
+ export function CategoryFilter(props) {
152
+ const service = useService(ProductsListSearchServiceDefinition);
153
+ const selectedCategory = service.selectedCategory.get();
154
+ return typeof props.children === "function"
155
+ ? props.children({ selectedCategory })
156
+ : props.children;
157
+ }
151
158
  /**
152
159
  * Headless component that renders content for each product option in the list.
153
160
  * Maps over all available product options and provides each option through a render prop.
@@ -1,5 +1,6 @@
1
1
  import type { Signal } from "@wix/services-definitions/core-services/signals";
2
2
  import { productsV3, customizationsV3 } from "@wix/stores";
3
+ import { type Category } from "./category-service.js";
3
4
  import { SortType } from "./../enums/sort-enums.js";
4
5
  export { SortType } from "./../enums/sort-enums.js";
5
6
  /**
@@ -42,7 +43,7 @@ type InitialSearchState = {
42
43
  };
43
44
  inventoryStatuses?: InventoryStatusType[];
44
45
  productOptions?: Record<string, string[]>;
45
- category?: string;
46
+ category?: Category;
46
47
  visible?: boolean;
47
48
  productType?: string;
48
49
  };
@@ -83,12 +84,12 @@ export declare const ProductsListSearchServiceDefinition: string & {
83
84
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
84
85
  availableProductOptions: Signal<ProductOption[]>;
85
86
  selectedProductOptions: Signal<Record<string, string[]>>;
86
- selectedCategory: Signal<string | null>;
87
+ selectedCategory: Signal<Category | null>;
87
88
  setSelectedMinPrice: (minPrice: number) => void;
88
89
  setSelectedMaxPrice: (maxPrice: number) => void;
89
90
  toggleInventoryStatus: (status: InventoryStatusType) => void;
90
91
  toggleProductOption: (optionId: string, choiceId: string) => void;
91
- setSelectedCategory: (category: string | null) => void;
92
+ setSelectedCategory: (category: Category | null) => void;
92
93
  isFiltered: Signal<boolean>;
93
94
  reset: () => void;
94
95
  };
@@ -119,12 +120,12 @@ export declare const ProductsListSearchServiceDefinition: string & {
119
120
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
120
121
  availableProductOptions: Signal<ProductOption[]>;
121
122
  selectedProductOptions: Signal<Record<string, string[]>>;
122
- selectedCategory: Signal<string | null>;
123
+ selectedCategory: Signal<Category | null>;
123
124
  setSelectedMinPrice: (minPrice: number) => void;
124
125
  setSelectedMaxPrice: (maxPrice: number) => void;
125
126
  toggleInventoryStatus: (status: InventoryStatusType) => void;
126
127
  toggleProductOption: (optionId: string, choiceId: string) => void;
127
- setSelectedCategory: (category: string | null) => void;
128
+ setSelectedCategory: (category: Category | null) => void;
128
129
  isFiltered: Signal<boolean>;
129
130
  reset: () => void;
130
131
  };
@@ -135,7 +136,7 @@ export declare function convertUrlSortToSortType(urlSort: string): SortType | nu
135
136
  /**
136
137
  * Parse URL and build complete search options with all filters, sort, and pagination
137
138
  */
138
- export declare function parseUrlForProductsListSearch(url: string, defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
139
+ export declare function parseUrlForProductsListSearch(url: string, categoriesList: Category[], defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
139
140
  searchOptions: productsV3.V3ProductSearch;
140
141
  initialSearchState: InitialSearchState;
141
142
  }>;
@@ -172,12 +173,12 @@ export declare const ProductsListSearchService: import("@wix/services-definition
172
173
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
173
174
  availableProductOptions: Signal<ProductOption[]>;
174
175
  selectedProductOptions: Signal<Record<string, string[]>>;
175
- selectedCategory: Signal<string | null>;
176
+ selectedCategory: Signal<Category | null>;
176
177
  setSelectedMinPrice: (minPrice: number) => void;
177
178
  setSelectedMaxPrice: (maxPrice: number) => void;
178
179
  toggleInventoryStatus: (status: InventoryStatusType) => void;
179
180
  toggleProductOption: (optionId: string, choiceId: string) => void;
180
- setSelectedCategory: (category: string | null) => void;
181
+ setSelectedCategory: (category: Category | null) => void;
181
182
  isFiltered: Signal<boolean>;
182
183
  reset: () => void;
183
184
  };
@@ -208,12 +209,12 @@ export declare const ProductsListSearchService: import("@wix/services-definition
208
209
  selectedInventoryStatuses: Signal<InventoryStatusType[]>;
209
210
  availableProductOptions: Signal<ProductOption[]>;
210
211
  selectedProductOptions: Signal<Record<string, string[]>>;
211
- selectedCategory: Signal<string | null>;
212
+ selectedCategory: Signal<Category | null>;
212
213
  setSelectedMinPrice: (minPrice: number) => void;
213
214
  setSelectedMaxPrice: (maxPrice: number) => void;
214
215
  toggleInventoryStatus: (status: InventoryStatusType) => void;
215
216
  toggleProductOption: (optionId: string, choiceId: string) => void;
216
- setSelectedCategory: (category: string | null) => void;
217
+ setSelectedCategory: (category: Category | null) => void;
217
218
  isFiltered: Signal<boolean>;
218
219
  reset: () => void;
219
220
  }, ProductsListSearchServiceConfig>;
@@ -2,6 +2,7 @@ import { defineService, implementService } from "@wix/services-definitions";
2
2
  import { SignalsServiceDefinition } from "@wix/services-definitions/core-services/signals";
3
3
  import { DEFAULT_QUERY_LIMIT, ProductsListServiceDefinition, } from "./products-list-service.js";
4
4
  import { productsV3, customizationsV3 } from "@wix/stores";
5
+ import { loadCategoriesListServiceConfig } from "./categories-list-service.js";
5
6
  const PRICE_FILTER_DEBOUNCE_TIME = 300;
6
7
  import { SortType } from "./../enums/sort-enums.js";
7
8
  export { SortType } from "./../enums/sort-enums.js";
@@ -63,7 +64,7 @@ export function convertUrlSortToSortType(urlSort) {
63
64
  function updateUrlWithSearchState(searchState) {
64
65
  if (typeof window === "undefined")
65
66
  return;
66
- const { sort, filters, customizations, catalogBounds } = searchState;
67
+ const { sort, filters, customizations, catalogBounds, categorySlug } = searchState;
67
68
  // Convert filter IDs back to human-readable names for URL
68
69
  const humanReadableOptions = {};
69
70
  for (const [optionId, choiceIds] of Object.entries(filters?.productOptions ?? {})) {
@@ -91,10 +92,10 @@ function updateUrlWithSearchState(searchState) {
91
92
  "minPrice",
92
93
  "maxPrice",
93
94
  "inventoryStatus",
94
- "category",
95
95
  "visible",
96
96
  "productType",
97
97
  // Product option names will be dynamically added below
98
+ // Note: category is NOT included here as it's handled in the URL path
98
99
  ];
99
100
  // Remove existing search parameters first
100
101
  searchParams.forEach((param) => params.delete(param));
@@ -124,10 +125,6 @@ function updateUrlWithSearchState(searchState) {
124
125
  if (filters.inventoryStatuses && filters.inventoryStatuses.length > 0) {
125
126
  params.set("inventoryStatus", filters.inventoryStatuses.join(","));
126
127
  }
127
- // Add category filter
128
- if (filters.category) {
129
- params.set("category", filters.category);
130
- }
131
128
  // Add visibility filter (only if explicitly false, since true is default)
132
129
  if (filters.visible === false) {
133
130
  params.set("visible", "false");
@@ -142,8 +139,15 @@ function updateUrlWithSearchState(searchState) {
142
139
  params.set(optionName, values.join(","));
143
140
  }
144
141
  }
142
+ // Handle URL path construction with category
143
+ let baseUrl = window.location.pathname;
144
+ // If categorySlug is provided, update the path
145
+ if (categorySlug) {
146
+ if (categorySlug) {
147
+ baseUrl = `/category/${categorySlug}`;
148
+ }
149
+ }
145
150
  // Build the new URL
146
- const baseUrl = window.location.pathname;
147
151
  const newUrl = params.toString()
148
152
  ? `${baseUrl}?${params.toString()}`
149
153
  : baseUrl;
@@ -155,7 +159,7 @@ function updateUrlWithSearchState(searchState) {
155
159
  /**
156
160
  * Parse URL and build complete search options with all filters, sort, and pagination
157
161
  */
158
- export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
162
+ export async function parseUrlForProductsListSearch(url, categoriesList, defaultSearchOptions) {
159
163
  const urlObj = new URL(url);
160
164
  const searchParams = urlObj.searchParams;
161
165
  // Get customizations for product option parsing
@@ -171,6 +175,21 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
171
175
  };
172
176
  // Initialize search state for service
173
177
  const initialSearchState = {};
178
+ // Extract category slug from URL path (e.g., /category/category-slug)
179
+ const pathSegments = urlObj.pathname.split("/");
180
+ const categoryIndex = pathSegments.findIndex((segment) => segment === "category");
181
+ let categorySlug = null;
182
+ let category = undefined;
183
+ if (categoryIndex !== -1 && categoryIndex + 1 < pathSegments.length) {
184
+ categorySlug = pathSegments[categoryIndex + 1] || null;
185
+ // Find the category by slug from the provided categories list
186
+ if (categorySlug) {
187
+ category = categoriesList.find((cat) => cat.slug === categorySlug);
188
+ if (category) {
189
+ initialSearchState.category = category;
190
+ }
191
+ }
192
+ }
174
193
  // Handle text search (q parameter)
175
194
  const query = searchParams.get("q");
176
195
  if (query) {
@@ -252,12 +271,11 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
252
271
  filter["productType"] = productType;
253
272
  initialSearchState.productType = productType;
254
273
  }
255
- const category = searchParams.get("category");
274
+ // Add category filter if found
256
275
  if (category) {
257
276
  filter["allCategoriesInfo.categories"] = {
258
- $matchItems: [{ _id: { $in: [category] } }],
277
+ $matchItems: [{ _id: { $in: [category._id] } }],
259
278
  };
260
- initialSearchState.category = category;
261
279
  }
262
280
  // Price range filtering
263
281
  const minPrice = searchParams.get("minPrice");
@@ -285,7 +303,6 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
285
303
  "maxPrice",
286
304
  "inventory_status",
287
305
  "inventoryStatus",
288
- "category",
289
306
  "visible",
290
307
  "productType",
291
308
  "q",
@@ -378,7 +395,9 @@ export async function parseUrlForProductsListSearch(url, defaultSearchOptions) {
378
395
  * Load search service configuration from URL
379
396
  */
380
397
  export async function loadProductsListSearchServiceConfig(url) {
381
- const { initialSearchState } = await parseUrlForProductsListSearch(url);
398
+ // Load categories using the categories service
399
+ const categoriesListConfig = await loadCategoriesListServiceConfig();
400
+ const { initialSearchState } = await parseUrlForProductsListSearch(url, categoriesListConfig.categories);
382
401
  const { items: customizations = [] } = await customizationsV3
383
402
  .queryCustomizations()
384
403
  .find();
@@ -550,7 +569,7 @@ export const ProductsListSearchService = implementService.withConfig()(ProductsL
550
569
  }
551
570
  if (selectedCategory) {
552
571
  newSearchOptions.filter["allCategoriesInfo.categories"] = {
553
- $matchItems: [{ _id: { $in: [selectedCategory] } }],
572
+ $matchItems: [{ _id: { $in: [selectedCategory._id] } }],
554
573
  };
555
574
  }
556
575
  if (selectedVisible !== null) {
@@ -571,7 +590,6 @@ export const ProductsListSearchService = implementService.withConfig()(ProductsL
571
590
  priceRange: { min: minPrice, max: maxPrice },
572
591
  inventoryStatuses: selectedInventoryStatuses,
573
592
  productOptions: selectedProductOptions,
574
- ...(selectedCategory && { category: selectedCategory }),
575
593
  ...(selectedVisible !== null && { visible: selectedVisible }),
576
594
  ...(selectedProductType && { productType: selectedProductType }),
577
595
  };
@@ -580,6 +598,7 @@ export const ProductsListSearchService = implementService.withConfig()(ProductsL
580
598
  filters: currentFilters,
581
599
  customizations,
582
600
  catalogBounds,
601
+ categorySlug: selectedCategory?.slug || undefined,
583
602
  });
584
603
  });
585
604
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-stores",
3
- "version": "0.0.42",
3
+ "version": "0.0.43",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "prebuild": "cd ../media && yarn build && cd ../ecom && yarn build",