@propeller-commerce/propeller-v2-react-ui 0.11.4 → 0.13.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/CHANGELOG.md +65 -0
- package/dist/index.cjs +102 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +103 -10
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,71 @@ 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.13.0] - 2026-08-05
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Availability filter on `<GridFilters>`** — an opt-in section below the
|
|
16
|
+
price block with two checkboxes, In stock and Out of stock, wired to the
|
|
17
|
+
server-side stock filter the SDK exposes on `CategoryProductSearchInput`.
|
|
18
|
+
New props: `showAvailabilityFilter` (defaults `false`),
|
|
19
|
+
`activeAvailability` and `onAvailabilityChange`. Nothing selected sends no
|
|
20
|
+
filter, so the default listing is unchanged.
|
|
21
|
+
|
|
22
|
+
Selecting both buckets means "in stock or out of stock", which is every
|
|
23
|
+
product. The filter has no OR operator and the union is the unfiltered set
|
|
24
|
+
anyway, so both-selected sends no filter — the same as selecting neither.
|
|
25
|
+
The checkboxes stay ticked; only the request collapses.
|
|
26
|
+
|
|
27
|
+
The mapping lives in `propeller-v2-core-ui`'s `buildInventoryFilter`, so
|
|
28
|
+
this package never restates the operator semantics. Requires
|
|
29
|
+
`propeller-v2-core-ui` >= 0.5.0 and `propeller-sdk-v2` >= 0.15.0, where the
|
|
30
|
+
inventory filter was added.
|
|
31
|
+
|
|
32
|
+
- **`availability` and `onAvailabilityFilterRemove` on `<GridToolbar>`** —
|
|
33
|
+
the active-filter row now renders one removable chip per selected bucket,
|
|
34
|
+
so a stock-filtered listing shows why its results are narrowed and can be
|
|
35
|
+
undone from the results area. One chip per bucket, matching the attribute
|
|
36
|
+
chips rather than the price chip which covers a whole range. The row's
|
|
37
|
+
active check accounts for availability, so it appears when availability is
|
|
38
|
+
the only active filter.
|
|
39
|
+
|
|
40
|
+
- **`availability` on `<ProductGrid>`** — forwards the selection to
|
|
41
|
+
`useProductSearch`, which applies it to both the grid fetch and the
|
|
42
|
+
typeahead preview. Filtering only the grid would let the preview offer
|
|
43
|
+
products the grid then hides.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- The availability section is hidden for anonymous visitors in a semi-closed
|
|
48
|
+
portal, the same rule the price filter already follows. Hosts should pass
|
|
49
|
+
their own "show stock" setting through `showAvailabilityFilter`: filtering
|
|
50
|
+
by stock reads as broken when the cards display no stock to filter on.
|
|
51
|
+
|
|
52
|
+
## [0.12.0] - 2026-07-31
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- **`productTrackAttributes` on `<ProductGrid>`, `<SearchBar>` and
|
|
57
|
+
`useProductSearch`.** Pass the attribute names a card renders — e.g.
|
|
58
|
+
`productTrackAttributes={['MPN']}` — and they arrive on
|
|
59
|
+
`product.attributes` for every item in the result, ready to read from a
|
|
60
|
+
card slot like `belowName`. `useProductInfo` has had an option of this name
|
|
61
|
+
since the PDP work; the grid side simply never forwarded one, so hosts that
|
|
62
|
+
set it in their portal config saw it silently ignored on listings and had
|
|
63
|
+
to fetch attributes themselves in a second request.
|
|
64
|
+
|
|
65
|
+
Requires `propeller-sdk-v2` >= 0.16.0, where the `category` and `products`
|
|
66
|
+
operations gained `$attributeResultSearchInput` and `ProductGridFields`
|
|
67
|
+
gained the matching `attributes(input:)` selection.
|
|
68
|
+
|
|
69
|
+
Naming the attributes you render is not just a payload optimisation — it is
|
|
70
|
+
the correct behaviour. With no input the server returns the *first page* of
|
|
71
|
+
a product's attributes (12 per product), so on a product carrying more than
|
|
72
|
+
12 the ones on later pages are missing with no error. Filtering to the names
|
|
73
|
+
you need also cut a 24-product category response from ~168 KB to ~124 KB in
|
|
74
|
+
our testing.
|
|
75
|
+
|
|
11
76
|
## [0.11.4] - 2026-07-31
|
|
12
77
|
|
|
13
78
|
### Fixed
|
package/dist/index.cjs
CHANGED
|
@@ -2090,7 +2090,7 @@ function useProductInfo(options) {
|
|
|
2090
2090
|
if (options.user && "customerId" in options.user) input.customerId = options.user.customerId;
|
|
2091
2091
|
return input;
|
|
2092
2092
|
}
|
|
2093
|
-
function
|
|
2093
|
+
function buildAttributeInput2() {
|
|
2094
2094
|
const names = options.productTrackAttributes;
|
|
2095
2095
|
if (!names || names.length === 0) return void 0;
|
|
2096
2096
|
return { attributeDescription: { names } };
|
|
@@ -2113,7 +2113,7 @@ function useProductInfo(options) {
|
|
|
2113
2113
|
orderlistIds = (orderlists?.items ?? []).map((ol) => ol.id);
|
|
2114
2114
|
}
|
|
2115
2115
|
const service = propellerV2CoreUi.createServices(graphqlClient).product;
|
|
2116
|
-
const attributeInput =
|
|
2116
|
+
const attributeInput = buildAttributeInput2();
|
|
2117
2117
|
const variables = {
|
|
2118
2118
|
productId,
|
|
2119
2119
|
language,
|
|
@@ -2203,6 +2203,10 @@ function useProductInfo(options) {
|
|
|
2203
2203
|
};
|
|
2204
2204
|
}
|
|
2205
2205
|
var inflightFetches2 = /* @__PURE__ */ new Set();
|
|
2206
|
+
function buildAttributeInput(names) {
|
|
2207
|
+
if (!names || names.length === 0) return void 0;
|
|
2208
|
+
return { attributeDescription: { names } };
|
|
2209
|
+
}
|
|
2206
2210
|
function useProductSearch(options) {
|
|
2207
2211
|
const { graphqlClient, configuration } = options;
|
|
2208
2212
|
const isControlled = options.products !== void 0;
|
|
@@ -2257,7 +2261,8 @@ function useProductSearch(options) {
|
|
|
2257
2261
|
userKey,
|
|
2258
2262
|
JSON.stringify(options.textFilters ?? []),
|
|
2259
2263
|
options.priceFilterMin ?? "",
|
|
2260
|
-
options.priceFilterMax ?? ""
|
|
2264
|
+
options.priceFilterMax ?? "",
|
|
2265
|
+
JSON.stringify(options.availability ?? [])
|
|
2261
2266
|
].join("|");
|
|
2262
2267
|
if (inflightFetches2.has(inflightKey)) {
|
|
2263
2268
|
fetchIdRef.current--;
|
|
@@ -2299,6 +2304,7 @@ function useProductSearch(options) {
|
|
|
2299
2304
|
}
|
|
2300
2305
|
] : [];
|
|
2301
2306
|
const priceFilter = options.priceFilterMin !== void 0 || options.priceFilterMax !== void 0 ? { from: options.priceFilterMin ?? 0, to: options.priceFilterMax ?? 999999 } : void 0;
|
|
2307
|
+
const inventoryFilter = propellerV2CoreUi.buildInventoryFilter(options.availability);
|
|
2302
2308
|
const userId = options.user && "contactId" in options.user ? options.user.contactId : options.user && "customerId" in options.user ? options.user.customerId : void 0;
|
|
2303
2309
|
const contactId = options.user && "contactId" in options.user ? options.user.contactId : void 0;
|
|
2304
2310
|
const customerId = options.user && "customerId" in options.user ? options.user.customerId : void 0;
|
|
@@ -2321,6 +2327,7 @@ function useProductSearch(options) {
|
|
|
2321
2327
|
...options.brand && { manufacturers: [options.brand] },
|
|
2322
2328
|
...options.textFilters?.length && { textFilters: options.textFilters },
|
|
2323
2329
|
...priceFilter && { price: priceFilter },
|
|
2330
|
+
...inventoryFilter && { inventory: inventoryFilter },
|
|
2324
2331
|
...sortInputs.length && { sortInputs },
|
|
2325
2332
|
...options.companyId && { companyId: options.companyId },
|
|
2326
2333
|
...userId !== void 0 && { userId },
|
|
@@ -2335,6 +2342,7 @@ function useProductSearch(options) {
|
|
|
2335
2342
|
const filterAvailableAttributeInput = {
|
|
2336
2343
|
isSearchable: true
|
|
2337
2344
|
};
|
|
2345
|
+
const attributeInput = buildAttributeInput(options.productTrackAttributes);
|
|
2338
2346
|
const variables = {
|
|
2339
2347
|
categoryId: catId,
|
|
2340
2348
|
language: lang,
|
|
@@ -2342,7 +2350,8 @@ function useProductSearch(options) {
|
|
|
2342
2350
|
priceCalculateProductInput,
|
|
2343
2351
|
filterAvailableAttributeInput,
|
|
2344
2352
|
imageSearchFilters: configuration?.imageSearchFiltersGrid,
|
|
2345
|
-
imageVariantFilters: configuration?.imageVariantFiltersMedium
|
|
2353
|
+
imageVariantFilters: configuration?.imageVariantFiltersMedium,
|
|
2354
|
+
...attributeInput && { attributeResultSearchInput: attributeInput }
|
|
2346
2355
|
};
|
|
2347
2356
|
const response = await service.getCategory(variables);
|
|
2348
2357
|
if (thisId !== fetchIdRef.current) return;
|
|
@@ -2395,6 +2404,7 @@ function useProductSearch(options) {
|
|
|
2395
2404
|
options.textFilters,
|
|
2396
2405
|
options.priceFilterMin,
|
|
2397
2406
|
options.priceFilterMax,
|
|
2407
|
+
options.availability,
|
|
2398
2408
|
options.sortField,
|
|
2399
2409
|
options.sortOrder,
|
|
2400
2410
|
options.companyId,
|
|
@@ -2403,7 +2413,9 @@ function useProductSearch(options) {
|
|
|
2403
2413
|
taxZone,
|
|
2404
2414
|
pageSize,
|
|
2405
2415
|
pagination.currentPage,
|
|
2406
|
-
configuration
|
|
2416
|
+
configuration,
|
|
2417
|
+
// Stringified: callers pass an array literal, so identity changes each render.
|
|
2418
|
+
JSON.stringify(options.productTrackAttributes ?? [])
|
|
2407
2419
|
]);
|
|
2408
2420
|
const search = React6.useCallback(
|
|
2409
2421
|
(term) => {
|
|
@@ -2432,6 +2444,7 @@ function useProductSearch(options) {
|
|
|
2432
2444
|
const userId = options.user && "contactId" in options.user ? options.user.contactId : options.user && "customerId" in options.user ? options.user.customerId : void 0;
|
|
2433
2445
|
const contactId = options.user && "contactId" in options.user ? options.user.contactId : void 0;
|
|
2434
2446
|
const customerId = options.user && "customerId" in options.user ? options.user.customerId : void 0;
|
|
2447
|
+
const inventoryFilter = propellerV2CoreUi.buildInventoryFilter(options.availability);
|
|
2435
2448
|
const categoryProductSearchInput = {
|
|
2436
2449
|
language,
|
|
2437
2450
|
page: 1,
|
|
@@ -2443,6 +2456,7 @@ function useProductSearch(options) {
|
|
|
2443
2456
|
propellerSdkV2.ProductStatus.S
|
|
2444
2457
|
],
|
|
2445
2458
|
hidden: false,
|
|
2459
|
+
...inventoryFilter && { inventory: inventoryFilter },
|
|
2446
2460
|
term,
|
|
2447
2461
|
searchFields: [
|
|
2448
2462
|
{
|
|
@@ -2482,13 +2496,15 @@ function useProductSearch(options) {
|
|
|
2482
2496
|
...contactId !== void 0 && { contactId },
|
|
2483
2497
|
...customerId !== void 0 && { customerId }
|
|
2484
2498
|
};
|
|
2499
|
+
const attributeInput = buildAttributeInput(options.productTrackAttributes);
|
|
2485
2500
|
const variables = {
|
|
2486
2501
|
categoryId: catId,
|
|
2487
2502
|
language,
|
|
2488
2503
|
categoryProductSearchInput,
|
|
2489
2504
|
priceCalculateProductInput,
|
|
2490
2505
|
imageSearchFilters: configuration?.imageSearchFiltersGrid,
|
|
2491
|
-
imageVariantFilters: configuration?.imageVariantFiltersMedium
|
|
2506
|
+
imageVariantFilters: configuration?.imageVariantFiltersMedium,
|
|
2507
|
+
...attributeInput && { attributeResultSearchInput: attributeInput }
|
|
2492
2508
|
};
|
|
2493
2509
|
const response = await service.getCategory(variables);
|
|
2494
2510
|
const productsResponse = response?.products;
|
|
@@ -2507,7 +2523,7 @@ function useProductSearch(options) {
|
|
|
2507
2523
|
}, 300);
|
|
2508
2524
|
},
|
|
2509
2525
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2510
|
-
[graphqlClient, language, configuration, userKey, JSON.stringify(options.orderlistIds ?? []), options.applyOrderlists]
|
|
2526
|
+
[graphqlClient, language, configuration, userKey, JSON.stringify(options.orderlistIds ?? []), options.applyOrderlists, JSON.stringify(options.productTrackAttributes ?? [])]
|
|
2511
2527
|
);
|
|
2512
2528
|
React6.useEffect(() => {
|
|
2513
2529
|
if (!isControlled) fetchProducts();
|
|
@@ -2520,6 +2536,7 @@ function useProductSearch(options) {
|
|
|
2520
2536
|
JSON.stringify(options.textFilters),
|
|
2521
2537
|
options.priceFilterMin,
|
|
2522
2538
|
options.priceFilterMax,
|
|
2539
|
+
options.availability,
|
|
2523
2540
|
options.sortField,
|
|
2524
2541
|
options.sortOrder,
|
|
2525
2542
|
pageSize,
|
|
@@ -9034,6 +9051,7 @@ function ProductGrid(rawProps) {
|
|
|
9034
9051
|
brand: props.brand,
|
|
9035
9052
|
orderlistIds: props.orderlistIds,
|
|
9036
9053
|
applyOrderlists: props.applyOrderlists,
|
|
9054
|
+
productTrackAttributes: props.productTrackAttributes,
|
|
9037
9055
|
language: props.language,
|
|
9038
9056
|
taxZone: props.taxZone,
|
|
9039
9057
|
user: props.user,
|
|
@@ -9041,6 +9059,7 @@ function ProductGrid(rawProps) {
|
|
|
9041
9059
|
textFilters: props.textFilters,
|
|
9042
9060
|
priceFilterMin: props.priceFilterMin,
|
|
9043
9061
|
priceFilterMax: props.priceFilterMax,
|
|
9062
|
+
availability: props.availability,
|
|
9044
9063
|
sortField: props.sortField,
|
|
9045
9064
|
sortOrder: props.sortOrder,
|
|
9046
9065
|
pageSize: props.pageSize,
|
|
@@ -9343,11 +9362,18 @@ function GridFilters(rawProps) {
|
|
|
9343
9362
|
const [isPending, setIsPending] = React6.useState(() => false);
|
|
9344
9363
|
const [appliedMin, setAppliedMin] = React6.useState(() => void 0);
|
|
9345
9364
|
const [appliedMax, setAppliedMax] = React6.useState(() => void 0);
|
|
9365
|
+
const [availability, setAvailability] = React6.useState(
|
|
9366
|
+
() => [...props.activeAvailability || []]
|
|
9367
|
+
);
|
|
9346
9368
|
function showPriceFilter() {
|
|
9347
9369
|
const mode = props.portalMode || "open";
|
|
9348
9370
|
if (mode === "open") return true;
|
|
9349
9371
|
return !!props.user;
|
|
9350
9372
|
}
|
|
9373
|
+
function showAvailability() {
|
|
9374
|
+
if (!props.showAvailabilityFilter) return false;
|
|
9375
|
+
return !propellerV2CoreUi.isContentHidden(props.portalMode, props.user);
|
|
9376
|
+
}
|
|
9351
9377
|
function getFilterName(filter) {
|
|
9352
9378
|
return filter?.attributeDescription?.name || "";
|
|
9353
9379
|
}
|
|
@@ -9392,6 +9418,13 @@ function GridFilters(rawProps) {
|
|
|
9392
9418
|
props.onFilterChange(filter, value);
|
|
9393
9419
|
if (props.getSelectedFilters) props.getSelectedFilters();
|
|
9394
9420
|
}
|
|
9421
|
+
function handleAvailabilityToggle(value, checked) {
|
|
9422
|
+
const next = checked ? [...availability, value] : availability.filter((v) => v !== value);
|
|
9423
|
+
setAvailability(next);
|
|
9424
|
+
setIsPending(true);
|
|
9425
|
+
if (props.onAvailabilityChange) props.onAvailabilityChange(next);
|
|
9426
|
+
if (props.getSelectedFilters) props.getSelectedFilters();
|
|
9427
|
+
}
|
|
9395
9428
|
function handleMinChange(value) {
|
|
9396
9429
|
const n = value > currentMax ? currentMax : value;
|
|
9397
9430
|
setCurrentMin(n);
|
|
@@ -9465,11 +9498,16 @@ function GridFilters(rawProps) {
|
|
|
9465
9498
|
setCurrentMin(props.priceMin || 0);
|
|
9466
9499
|
setCurrentMax(props.priceMax || 9999);
|
|
9467
9500
|
setExpandedFilters({});
|
|
9501
|
+
setAvailability([]);
|
|
9468
9502
|
}, [props.clearSignal, props.priceMin, props.priceMax]);
|
|
9469
9503
|
React6.useEffect(() => {
|
|
9470
9504
|
if (!props.activeTextFilters) return;
|
|
9471
9505
|
setSelectedFilters(props.activeTextFilters);
|
|
9472
9506
|
}, [props.activeTextFilters]);
|
|
9507
|
+
React6.useEffect(() => {
|
|
9508
|
+
if (!props.activeAvailability) return;
|
|
9509
|
+
setAvailability([...props.activeAvailability]);
|
|
9510
|
+
}, [props.activeAvailability]);
|
|
9473
9511
|
React6.useEffect(() => {
|
|
9474
9512
|
if (props.activePriceMin === void 0 && props.activePriceMax === void 0) {
|
|
9475
9513
|
setCurrentMin(props.priceMin || 0);
|
|
@@ -9569,6 +9607,40 @@ function GridFilters(rawProps) {
|
|
|
9569
9607
|
" ",
|
|
9570
9608
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-grid-filters__divider h-px bg-border-subtle" })
|
|
9571
9609
|
] }) : null,
|
|
9610
|
+
showAvailability() ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9611
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-grid-filters__availability space-y-3", children: [
|
|
9612
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "propeller-grid-filters__availability-title text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "availability", "Availability") }),
|
|
9613
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-grid-filters__availability-options space-y-1.5", children: [
|
|
9614
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "propeller-grid-filters__option flex items-center gap-2 cursor-pointer group", children: [
|
|
9615
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9616
|
+
"input",
|
|
9617
|
+
{
|
|
9618
|
+
type: "checkbox",
|
|
9619
|
+
className: "propeller-grid-filters__checkbox h-4 w-4 rounded border-input text-secondary focus:ring-secondary cursor-pointer flex-shrink-0",
|
|
9620
|
+
checked: availability.includes("in-stock"),
|
|
9621
|
+
disabled: !!props.isLoading,
|
|
9622
|
+
onChange: (e) => handleAvailabilityToggle("in-stock", e.target.checked)
|
|
9623
|
+
}
|
|
9624
|
+
),
|
|
9625
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-grid-filters__option-label flex-1 text-sm text-muted-foreground leading-none select-none group-hover:text-foreground", children: propellerV2CoreUi.getLabel(props.labels, "inStock", "In stock") })
|
|
9626
|
+
] }),
|
|
9627
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "propeller-grid-filters__option flex items-center gap-2 cursor-pointer group", children: [
|
|
9628
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9629
|
+
"input",
|
|
9630
|
+
{
|
|
9631
|
+
type: "checkbox",
|
|
9632
|
+
className: "propeller-grid-filters__checkbox h-4 w-4 rounded border-input text-secondary focus:ring-secondary cursor-pointer flex-shrink-0",
|
|
9633
|
+
checked: availability.includes("out-of-stock"),
|
|
9634
|
+
disabled: !!props.isLoading,
|
|
9635
|
+
onChange: (e) => handleAvailabilityToggle("out-of-stock", e.target.checked)
|
|
9636
|
+
}
|
|
9637
|
+
),
|
|
9638
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-grid-filters__option-label flex-1 text-sm text-muted-foreground leading-none select-none group-hover:text-foreground", children: propellerV2CoreUi.getLabel(props.labels, "outOfStock", "Out of stock") })
|
|
9639
|
+
] })
|
|
9640
|
+
] })
|
|
9641
|
+
] }),
|
|
9642
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-grid-filters__divider h-px bg-border-subtle" })
|
|
9643
|
+
] }) : null,
|
|
9572
9644
|
props.filters.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "propeller-grid-filters__empty text-sm text-foreground-subtle italic", children: propellerV2CoreUi.getLabel(props.labels, "noFiltersAvailable", "No filters available") }) : null,
|
|
9573
9645
|
getFilteredFilters()?.map((filter) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-grid-filters__group border-b border-border-subtle pb-3 last:border-b-0", "data-expanded": isExpanded(getFilterName(filter)) ? "true" : "false", children: [
|
|
9574
9646
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -9744,6 +9816,8 @@ var DEFAULT_LABELS = {
|
|
|
9744
9816
|
results: "results",
|
|
9745
9817
|
perPage: " per page",
|
|
9746
9818
|
price: "Price",
|
|
9819
|
+
inStock: "In stock",
|
|
9820
|
+
outOfStock: "Out of stock",
|
|
9747
9821
|
switchToList: "Switch to list view",
|
|
9748
9822
|
switchToGrid: "Switch to grid view"
|
|
9749
9823
|
};
|
|
@@ -9772,7 +9846,8 @@ function GridToolbar(rawProps) {
|
|
|
9772
9846
|
const text = props.activeTextFilters || {};
|
|
9773
9847
|
const hasText = Object.keys(text).some((k) => (text[k] || []).length > 0);
|
|
9774
9848
|
const hasPrice = props.priceFilterMin !== void 0 || props.priceFilterMax !== void 0;
|
|
9775
|
-
|
|
9849
|
+
const hasAvailability = (props.availability || []).length > 0;
|
|
9850
|
+
return hasText || hasPrice || hasAvailability;
|
|
9776
9851
|
}
|
|
9777
9852
|
function getActiveFilterBadges() {
|
|
9778
9853
|
const text = props.activeTextFilters || {};
|
|
@@ -9790,6 +9865,9 @@ function GridToolbar(rawProps) {
|
|
|
9790
9865
|
function isPriceSortDisabled() {
|
|
9791
9866
|
return propellerV2CoreUi.isContentHidden(props.portalMode, props.user);
|
|
9792
9867
|
}
|
|
9868
|
+
function getAvailabilityLabel(value) {
|
|
9869
|
+
return value === "in-stock" ? getLabel56("inStock") : getLabel56("outOfStock");
|
|
9870
|
+
}
|
|
9793
9871
|
function handleSortFieldChange(field) {
|
|
9794
9872
|
setCurrentSortField(field);
|
|
9795
9873
|
if (props.onSortChange) props.onSortChange(field, currentSortOrder);
|
|
@@ -9963,6 +10041,20 @@ function GridToolbar(rawProps) {
|
|
|
9963
10041
|
]
|
|
9964
10042
|
}
|
|
9965
10043
|
) : null,
|
|
10044
|
+
(props.availability || []).map((value) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10045
|
+
"span",
|
|
10046
|
+
{
|
|
10047
|
+
className: "propeller-grid-toolbar__filter-badge propeller-grid-toolbar__filter-badge--availability inline-flex items-center gap-1 cursor-pointer px-2.5 py-0.5 rounded-full text-xs font-semibold border border-input bg-background hover:bg-primary hover:text-primary-foreground hover:border-primary transition-colors",
|
|
10048
|
+
onClick: (event) => {
|
|
10049
|
+
if (props.onAvailabilityFilterRemove) props.onAvailabilityFilterRemove(value);
|
|
10050
|
+
},
|
|
10051
|
+
children: [
|
|
10052
|
+
getAvailabilityLabel(value),
|
|
10053
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-grid-toolbar__filter-badge-remove", children: "\xD7" })
|
|
10054
|
+
]
|
|
10055
|
+
},
|
|
10056
|
+
value
|
|
10057
|
+
)),
|
|
9966
10058
|
getActiveFilterBadges()?.map((badge) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9967
10059
|
"span",
|
|
9968
10060
|
{
|
|
@@ -18396,7 +18488,8 @@ function SearchBar(rawProps) {
|
|
|
18396
18488
|
user: props.user,
|
|
18397
18489
|
companyId: props.companyId,
|
|
18398
18490
|
orderlistIds: props.orderlistIds,
|
|
18399
|
-
applyOrderlists: props.applyOrderlists
|
|
18491
|
+
applyOrderlists: props.applyOrderlists,
|
|
18492
|
+
productTrackAttributes: props.productTrackAttributes
|
|
18400
18493
|
});
|
|
18401
18494
|
const results = searchResults.slice(0, maxResults).map((item) => mapToSearchBarResult(item, props.language));
|
|
18402
18495
|
const itemsFound = searchItemsFound;
|