@propeller-commerce/propeller-v2-react-ui 0.4.27 → 0.4.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,34 @@ once it reaches 1.0. Until then (the `0.x` line) the public API may change
8
8
  between minor versions; breaking changes are called out below and in
9
9
  [MIGRATION.md](./MIGRATION.md).
10
10
 
11
+ ## [0.4.29] - 2026-07-21
12
+
13
+ ### Fixed
14
+
15
+ - **`SearchBar` autosuggest now filters results by the active language.**
16
+ Follow-up to 0.4.28's category-search routing: the backend search matches
17
+ across all languages, so FR/ES-only products leaked into an EN preview. The
18
+ autosuggest now drops results with no name in the active language (and
19
+ adjusts the "View all (N)" total by the dropped count), and the result row
20
+ displays the name in the active language (falling back to the first
21
+ available) instead of always the first name in the array. Restores the
22
+ behaviour of the pre-package local search bar.
23
+
24
+ ## [0.4.28] - 2026-07-21
25
+
26
+ ### Fixed
27
+
28
+ - **`SearchBar` autosuggest orderlist scoping — real fix.** 0.4.27 set
29
+ `orderlistIds`/`applyOrderlists` on the flat `products` search input, but the
30
+ server's `products` resolver does not honour orderlist scoping (only the
31
+ `category.products` resolver does), so the preview still leaked the full
32
+ catalogue inside a contract. The debounced autosuggest now runs the **same
33
+ category term-search the grid uses** (`getCategory` over the base category)
34
+ instead of the flat `getProducts`, so contract scoping is applied server-side
35
+ and the preview matches the grid exactly. Requires
36
+ `configuration.baseCategoryId` (already provided by all consumers); previews
37
+ no-op without it, as before.
38
+
11
39
  ## [0.4.27] - 2026-07-21
12
40
 
13
41
  ### Fixed
package/dist/index.cjs CHANGED
@@ -2177,6 +2177,7 @@ function useProductSearch(options) {
2177
2177
  );
2178
2178
  const isLoading = !isControlled && internalLoading;
2179
2179
  function filterByLanguage(products, lang) {
2180
+ if (!lang) return products;
2180
2181
  return products.filter((p) => {
2181
2182
  const names = p.names || p.names || [];
2182
2183
  if (!names || names.length === 0) return true;
@@ -2364,13 +2365,21 @@ function useProductSearch(options) {
2364
2365
  if (!graphqlClient) return;
2365
2366
  setSearchLoading(true);
2366
2367
  try {
2367
- const service = propellerV2CoreUi.createServices(graphqlClient).product;
2368
+ const service = propellerV2CoreUi.createServices(graphqlClient).category;
2369
+ const catId = configuration?.baseCategoryId ?? 0;
2370
+ if (!catId) {
2371
+ setSearchResults([]);
2372
+ setSearchItemsFound(0);
2373
+ return;
2374
+ }
2368
2375
  const orderlistScope = options.orderlistIds && options.orderlistIds.length > 0 ? {
2369
2376
  applyOrderlists: options.applyOrderlists !== false,
2370
2377
  orderlistIds: options.orderlistIds
2371
2378
  } : { applyOrderlists: false };
2372
- const input = {
2373
- term,
2379
+ const userId = options.user && "contactId" in options.user ? options.user.contactId : options.user && "customerId" in options.user ? options.user.customerId : void 0;
2380
+ const contactId = options.user && "contactId" in options.user ? options.user.contactId : void 0;
2381
+ const customerId = options.user && "customerId" in options.user ? options.user.customerId : void 0;
2382
+ const categoryProductSearchInput = {
2374
2383
  language,
2375
2384
  page: 1,
2376
2385
  offset: 10,
@@ -2380,8 +2389,8 @@ function useProductSearch(options) {
2380
2389
  propellerSdkV2.ProductStatus.T,
2381
2390
  propellerSdkV2.ProductStatus.S
2382
2391
  ],
2383
- ...orderlistScope,
2384
- sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
2392
+ hidden: false,
2393
+ term,
2385
2394
  searchFields: [
2386
2395
  {
2387
2396
  fieldNames: [
@@ -2408,17 +2417,34 @@ function useProductSearch(options) {
2408
2417
  ],
2409
2418
  boost: 1
2410
2419
  }
2411
- ]
2420
+ ],
2421
+ sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
2422
+ ...options.companyId && { companyId: options.companyId },
2423
+ ...userId !== void 0 && { userId },
2424
+ ...orderlistScope
2425
+ };
2426
+ const priceCalculateProductInput = {
2427
+ taxZone,
2428
+ ...options.companyId && { companyId: options.companyId },
2429
+ ...contactId !== void 0 && { contactId },
2430
+ ...customerId !== void 0 && { customerId }
2412
2431
  };
2413
2432
  const variables = {
2414
- input,
2433
+ categoryId: catId,
2415
2434
  language,
2435
+ categoryProductSearchInput,
2436
+ priceCalculateProductInput,
2437
+ imageSearchFilters: configuration?.imageSearchFiltersGrid,
2416
2438
  imageVariantFilters: configuration?.imageVariantFiltersMedium
2417
2439
  };
2418
- const result = await service.getProducts(variables);
2419
- const items = result?.items ?? [];
2440
+ const response = await service.getCategory(variables);
2441
+ const productsResponse = response?.products;
2442
+ const rawItems = productsResponse?.items ?? [];
2443
+ const items = filterByLanguage(rawItems, language);
2444
+ const untranslated = rawItems.length - items.length;
2445
+ const apiTotal = productsResponse?.itemsFound ?? rawItems.length;
2420
2446
  setSearchResults(items);
2421
- setSearchItemsFound(result?.itemsFound ?? items.length);
2447
+ setSearchItemsFound(Math.max(0, apiTotal - untranslated));
2422
2448
  } catch {
2423
2449
  setSearchResults([]);
2424
2450
  setSearchItemsFound(0);
@@ -17205,7 +17231,7 @@ function RegisterForm(rawProps) {
17205
17231
  ] });
17206
17232
  }
17207
17233
  var RegisterForm_default = RegisterForm;
17208
- function mapToSearchBarResult(item) {
17234
+ function mapToSearchBarResult(item, language) {
17209
17235
  const isCluster = "clusterId" in item;
17210
17236
  const displayItem = isCluster ? item.defaultProduct : item;
17211
17237
  const id = isCluster ? item.clusterId : item.productId;
@@ -17213,9 +17239,10 @@ function mapToSearchBarResult(item) {
17213
17239
  const url = isCluster ? "/cluster/" + id + "/" + slug : "/product/" + id + "/" + slug;
17214
17240
  const priceNet = displayItem?.price?.net || 0;
17215
17241
  const priceGross = displayItem?.price?.gross || 0;
17242
+ const localizedName = language && item.names?.find((n) => n.language === language)?.value || item.names?.[0]?.value || "Product";
17216
17243
  return {
17217
17244
  id,
17218
- name: item.names?.[0]?.value || "Product",
17245
+ name: localizedName,
17219
17246
  sku: item.sku || displayItem?.sku || "",
17220
17247
  // `price` stays the gross value for back-compat; the row picks net/gross
17221
17248
  // from the two explicit fields below per the toggle.
@@ -17242,7 +17269,7 @@ function SearchBar(rawProps) {
17242
17269
  orderlistIds: props.orderlistIds,
17243
17270
  applyOrderlists: props.applyOrderlists
17244
17271
  });
17245
- const results = searchResults.slice(0, maxResults).map((item) => mapToSearchBarResult(item));
17272
+ const results = searchResults.slice(0, maxResults).map((item) => mapToSearchBarResult(item, props.language));
17246
17273
  const itemsFound = searchItemsFound;
17247
17274
  function formatItemPrice(price) {
17248
17275
  if (props.formatPrice) {