@propeller-commerce/propeller-v2-react-ui 0.11.3 → 0.12.0

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/dist/index.d.cts CHANGED
@@ -1383,6 +1383,12 @@ interface UseProductSearchOptions {
1383
1383
  * without a contract still sees the full catalogue.
1384
1384
  */
1385
1385
  applyOrderlists?: boolean;
1386
+ /**
1387
+ * Attribute names to request per product, e.g. `['MPN']`. Unset returns the
1388
+ * first page of ALL attributes (12 per product), so products with more than
1389
+ * 12 silently lose the rest — name what you render.
1390
+ */
1391
+ productTrackAttributes?: string[];
1386
1392
  /** Attribute text filters applied to the category search. */
1387
1393
  textFilters?: ProductTextFilterInput[];
1388
1394
  /** Lower price bound filter. */
@@ -6146,6 +6152,13 @@ interface ProductGridProps {
6146
6152
  * still sees the full catalogue.
6147
6153
  */
6148
6154
  applyOrderlists?: boolean;
6155
+ /**
6156
+ * Attribute names to request per product, e.g. `['MPN']` — makes
6157
+ * `product.attributes` usable in card slots like `belowName`. Unset returns
6158
+ * the first page of ALL attributes (12 per product), so products with more
6159
+ * than 12 silently lose the rest.
6160
+ */
6161
+ productTrackAttributes?: string[];
6149
6162
  /** Number of columns in the grid. Accepts 2, 3, 4, 5, or 6. Defaults to 3. */
6150
6163
  columns?: number;
6151
6164
  /**
@@ -7300,6 +7313,8 @@ interface SearchBarProps {
7300
7313
  * still sees the full catalogue.
7301
7314
  */
7302
7315
  applyOrderlists?: boolean;
7316
+ /** Attribute names to request per product, e.g. `['MPN']`. See ProductGrid. */
7317
+ productTrackAttributes?: string[];
7303
7318
  /**
7304
7319
  * Bump this counter to clear the search input from outside (e.g. on route
7305
7320
  * change). Each unique value triggers a one-time reset of the local term.
package/dist/index.d.ts CHANGED
@@ -1383,6 +1383,12 @@ interface UseProductSearchOptions {
1383
1383
  * without a contract still sees the full catalogue.
1384
1384
  */
1385
1385
  applyOrderlists?: boolean;
1386
+ /**
1387
+ * Attribute names to request per product, e.g. `['MPN']`. Unset returns the
1388
+ * first page of ALL attributes (12 per product), so products with more than
1389
+ * 12 silently lose the rest — name what you render.
1390
+ */
1391
+ productTrackAttributes?: string[];
1386
1392
  /** Attribute text filters applied to the category search. */
1387
1393
  textFilters?: ProductTextFilterInput[];
1388
1394
  /** Lower price bound filter. */
@@ -6146,6 +6152,13 @@ interface ProductGridProps {
6146
6152
  * still sees the full catalogue.
6147
6153
  */
6148
6154
  applyOrderlists?: boolean;
6155
+ /**
6156
+ * Attribute names to request per product, e.g. `['MPN']` — makes
6157
+ * `product.attributes` usable in card slots like `belowName`. Unset returns
6158
+ * the first page of ALL attributes (12 per product), so products with more
6159
+ * than 12 silently lose the rest.
6160
+ */
6161
+ productTrackAttributes?: string[];
6149
6162
  /** Number of columns in the grid. Accepts 2, 3, 4, 5, or 6. Defaults to 3. */
6150
6163
  columns?: number;
6151
6164
  /**
@@ -7300,6 +7313,8 @@ interface SearchBarProps {
7300
7313
  * still sees the full catalogue.
7301
7314
  */
7302
7315
  applyOrderlists?: boolean;
7316
+ /** Attribute names to request per product, e.g. `['MPN']`. See ProductGrid. */
7317
+ productTrackAttributes?: string[];
7303
7318
  /**
7304
7319
  * Bump this counter to clear the search input from outside (e.g. on route
7305
7320
  * change). Each unique value triggers a one-time reset of the local term.
package/dist/index.js CHANGED
@@ -2070,7 +2070,7 @@ function useProductInfo(options) {
2070
2070
  if (options.user && "customerId" in options.user) input.customerId = options.user.customerId;
2071
2071
  return input;
2072
2072
  }
2073
- function buildAttributeInput() {
2073
+ function buildAttributeInput2() {
2074
2074
  const names = options.productTrackAttributes;
2075
2075
  if (!names || names.length === 0) return void 0;
2076
2076
  return { attributeDescription: { names } };
@@ -2093,7 +2093,7 @@ function useProductInfo(options) {
2093
2093
  orderlistIds = (orderlists?.items ?? []).map((ol) => ol.id);
2094
2094
  }
2095
2095
  const service = createServices(graphqlClient).product;
2096
- const attributeInput = buildAttributeInput();
2096
+ const attributeInput = buildAttributeInput2();
2097
2097
  const variables = {
2098
2098
  productId,
2099
2099
  language,
@@ -2183,6 +2183,10 @@ function useProductInfo(options) {
2183
2183
  };
2184
2184
  }
2185
2185
  var inflightFetches2 = /* @__PURE__ */ new Set();
2186
+ function buildAttributeInput(names) {
2187
+ if (!names || names.length === 0) return void 0;
2188
+ return { attributeDescription: { names } };
2189
+ }
2186
2190
  function useProductSearch(options) {
2187
2191
  const { graphqlClient, configuration } = options;
2188
2192
  const isControlled = options.products !== void 0;
@@ -2315,6 +2319,7 @@ function useProductSearch(options) {
2315
2319
  const filterAvailableAttributeInput = {
2316
2320
  isSearchable: true
2317
2321
  };
2322
+ const attributeInput = buildAttributeInput(options.productTrackAttributes);
2318
2323
  const variables = {
2319
2324
  categoryId: catId,
2320
2325
  language: lang,
@@ -2322,7 +2327,8 @@ function useProductSearch(options) {
2322
2327
  priceCalculateProductInput,
2323
2328
  filterAvailableAttributeInput,
2324
2329
  imageSearchFilters: configuration?.imageSearchFiltersGrid,
2325
- imageVariantFilters: configuration?.imageVariantFiltersMedium
2330
+ imageVariantFilters: configuration?.imageVariantFiltersMedium,
2331
+ ...attributeInput && { attributeResultSearchInput: attributeInput }
2326
2332
  };
2327
2333
  const response = await service.getCategory(variables);
2328
2334
  if (thisId !== fetchIdRef.current) return;
@@ -2383,7 +2389,9 @@ function useProductSearch(options) {
2383
2389
  taxZone,
2384
2390
  pageSize,
2385
2391
  pagination.currentPage,
2386
- configuration
2392
+ configuration,
2393
+ // Stringified: callers pass an array literal, so identity changes each render.
2394
+ JSON.stringify(options.productTrackAttributes ?? [])
2387
2395
  ]);
2388
2396
  const search = useCallback(
2389
2397
  (term) => {
@@ -2462,13 +2470,15 @@ function useProductSearch(options) {
2462
2470
  ...contactId !== void 0 && { contactId },
2463
2471
  ...customerId !== void 0 && { customerId }
2464
2472
  };
2473
+ const attributeInput = buildAttributeInput(options.productTrackAttributes);
2465
2474
  const variables = {
2466
2475
  categoryId: catId,
2467
2476
  language,
2468
2477
  categoryProductSearchInput,
2469
2478
  priceCalculateProductInput,
2470
2479
  imageSearchFilters: configuration?.imageSearchFiltersGrid,
2471
- imageVariantFilters: configuration?.imageVariantFiltersMedium
2480
+ imageVariantFilters: configuration?.imageVariantFiltersMedium,
2481
+ ...attributeInput && { attributeResultSearchInput: attributeInput }
2472
2482
  };
2473
2483
  const response = await service.getCategory(variables);
2474
2484
  const productsResponse = response?.products;
@@ -2487,7 +2497,7 @@ function useProductSearch(options) {
2487
2497
  }, 300);
2488
2498
  },
2489
2499
  // eslint-disable-next-line react-hooks/exhaustive-deps
2490
- [graphqlClient, language, configuration, userKey, JSON.stringify(options.orderlistIds ?? []), options.applyOrderlists]
2500
+ [graphqlClient, language, configuration, userKey, JSON.stringify(options.orderlistIds ?? []), options.applyOrderlists, JSON.stringify(options.productTrackAttributes ?? [])]
2491
2501
  );
2492
2502
  useEffect(() => {
2493
2503
  if (!isControlled) fetchProducts();
@@ -4587,7 +4597,7 @@ function AddToCart(rawProps) {
4587
4597
  "button",
4588
4598
  {
4589
4599
  type: "button",
4590
- className: "propeller-add-to-cart__submit flex-1 basis-full md:basis-auto inline-flex justify-center items-center gap-2 h-10 px-6 border border-transparent text-sm font-medium rounded-control text-secondary-foreground bg-secondary hover:bg-secondary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-secondary disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
4600
+ className: "propeller-add-to-cart__submit flex-1 min-w-0 basis-full md:basis-auto inline-flex justify-center items-center gap-2 h-10 px-3 sm:px-6 border border-transparent text-sm font-medium rounded-control text-secondary-foreground bg-secondary hover:bg-secondary/80 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-secondary disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
4591
4601
  onClick: () => handleAddToCart(),
4592
4602
  disabled: loading,
4593
4603
  children: [
@@ -4609,8 +4619,7 @@ function AddToCart(rawProps) {
4609
4619
  ]
4610
4620
  }
4611
4621
  ),
4612
- loading ? /* @__PURE__ */ jsx(Fragment, { children: getLabel(props.labels, "adding", "Adding...") }) : null,
4613
- !loading ? /* @__PURE__ */ jsx(Fragment, { children: getLabel(props.labels, "add", "Add") }) : null
4622
+ /* @__PURE__ */ jsx("span", { className: "propeller-add-to-cart__submit-label min-w-0 truncate", children: loading ? getLabel(props.labels, "adding", "Adding...") : getLabel(props.labels, "add", "Add") })
4614
4623
  ]
4615
4624
  }
4616
4625
  )
@@ -8363,8 +8372,8 @@ function ClusterCardViewClusterLink(props) {
8363
8372
  {
8364
8373
  href: derived.clusterUrl,
8365
8374
  onClick: handleClusterClick,
8366
- className: props.className ?? "propeller-cluster-card__cta-link flex w-full items-center justify-center rounded-control bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/80 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
8367
- children: props.label ?? derived.viewClusterLabel
8375
+ className: props.className ?? "propeller-cluster-card__cta-link flex w-full min-w-0 items-center justify-center rounded-control bg-primary px-3 sm:px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/80 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
8376
+ children: /* @__PURE__ */ jsx("span", { className: "propeller-cluster-card__cta-label min-w-0 truncate", children: props.label ?? derived.viewClusterLabel })
8368
8377
  }
8369
8378
  );
8370
8379
  }
@@ -9015,6 +9024,7 @@ function ProductGrid(rawProps) {
9015
9024
  brand: props.brand,
9016
9025
  orderlistIds: props.orderlistIds,
9017
9026
  applyOrderlists: props.applyOrderlists,
9027
+ productTrackAttributes: props.productTrackAttributes,
9018
9028
  language: props.language,
9019
9029
  taxZone: props.taxZone,
9020
9030
  user: props.user,
@@ -18377,7 +18387,8 @@ function SearchBar(rawProps) {
18377
18387
  user: props.user,
18378
18388
  companyId: props.companyId,
18379
18389
  orderlistIds: props.orderlistIds,
18380
- applyOrderlists: props.applyOrderlists
18390
+ applyOrderlists: props.applyOrderlists,
18391
+ productTrackAttributes: props.productTrackAttributes
18381
18392
  });
18382
18393
  const results = searchResults.slice(0, maxResults).map((item) => mapToSearchBarResult(item, props.language));
18383
18394
  const itemsFound = searchItemsFound;