@propeller-commerce/propeller-v2-react-ui 0.4.25 → 0.4.27
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 +56 -0
- package/dist/index.cjs +92 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +92 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,62 @@ 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.27] - 2026-07-21
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **`SearchBar` autosuggest now respects orderlist (contract) scoping.** The
|
|
16
|
+
debounced live-search query built a plain `ProductSearchInput` that never
|
|
17
|
+
passed `orderlistIds`/`applyOrderlists`, so the dropdown previewed the full
|
|
18
|
+
catalogue even inside a B2B contract catalogue (the submitted results were
|
|
19
|
+
already correctly scoped — only the preview leaked). It now threads the same
|
|
20
|
+
orderlist scope as the grid fetch, so previews and results agree and a PDP
|
|
21
|
+
outside the contract is no longer reachable from the preview.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **`SearchBar`: `renderPrice` + `showPrice` props.** `renderPrice(result)`
|
|
26
|
+
replaces the price cell of each result with custom content (return any node,
|
|
27
|
+
or `null` to render nothing) — e.g. a "Price by quotation" label for a
|
|
28
|
+
contract catalogue where prices are quote-only; it fully overrides the
|
|
29
|
+
default price rendering. `showPrice` (default `true`) is a simpler boolean to
|
|
30
|
+
hide the price column outright. Both default to the previous behaviour, so
|
|
31
|
+
the change is backward-compatible.
|
|
32
|
+
|
|
33
|
+
## [0.4.26] - 2026-07-21
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **`SearchBar`: real anchor links for navigation.** New optional
|
|
38
|
+
`getResultHref(result)` and `getViewAllHref(term)` props. When provided, the
|
|
39
|
+
autosuggest result rows and the "View all results" CTA render as real
|
|
40
|
+
`<a href>` elements — middle-clickable, open-in-new-tab, hover-preview,
|
|
41
|
+
crawlable — while the existing `onResultClick`/`onViewAllClick` callbacks
|
|
42
|
+
still fire for SPA navigation (modified clicks fall through to the browser).
|
|
43
|
+
Omit the props to keep the previous behaviour.
|
|
44
|
+
- **`OrderList`: URL-persistable filters.** New optional `initialSearchForm`
|
|
45
|
+
(seed the filter form on mount, e.g. rehydrated from the URL) and
|
|
46
|
+
`onSearchApply(form)` (fires when the user applies/clears filters) props, so
|
|
47
|
+
the consuming page can keep the filter state in the URL — bookmarkable,
|
|
48
|
+
shareable, back-button-friendly. `useOrders` gained the matching
|
|
49
|
+
`initialSearchForm` option.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- **`AccountIconAndMenu`: account-menu items are now `<a href>` instead of
|
|
54
|
+
`<button>`** (both the sidebar and dropdown variants). They use each link's
|
|
55
|
+
existing `href`, so they are middle-clickable / new-tab-able / crawlable;
|
|
56
|
+
`onMenuItemClick` still handles plain-click SPA navigation.
|
|
57
|
+
- **`SearchBar`: the "View all results" fallback is now a `<button>`** (was a
|
|
58
|
+
non-focusable `<div>`), so it is keyboard-accessible even without the new
|
|
59
|
+
`getViewAllHref` prop.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- **`OrderList`: clickable rows now show `cursor: pointer`.** When
|
|
64
|
+
`rowsClickable` is set, the row cursor matches its behaviour (was `auto`,
|
|
65
|
+
inconsistent with the favourites cards).
|
|
66
|
+
|
|
11
67
|
## [0.4.25] - 2026-07-20
|
|
12
68
|
|
|
13
69
|
### Fixed
|
package/dist/index.cjs
CHANGED
|
@@ -1718,7 +1718,9 @@ function useOrders(options) {
|
|
|
1718
1718
|
const [orders, setOrders] = React6.useState([]);
|
|
1719
1719
|
const [loading, setLoading] = React6.useState(false);
|
|
1720
1720
|
const [error, setError] = React6.useState(null);
|
|
1721
|
-
const [searchForm, setSearchForm] = React6.useState(
|
|
1721
|
+
const [searchForm, setSearchForm] = React6.useState(
|
|
1722
|
+
options.initialSearchForm ?? {}
|
|
1723
|
+
);
|
|
1722
1724
|
const pagination = usePagination(options.itemsPerPage ?? 10);
|
|
1723
1725
|
const fetchOrders = React6.useCallback(
|
|
1724
1726
|
async (page = 1) => {
|
|
@@ -2363,6 +2365,10 @@ function useProductSearch(options) {
|
|
|
2363
2365
|
setSearchLoading(true);
|
|
2364
2366
|
try {
|
|
2365
2367
|
const service = propellerV2CoreUi.createServices(graphqlClient).product;
|
|
2368
|
+
const orderlistScope = options.orderlistIds && options.orderlistIds.length > 0 ? {
|
|
2369
|
+
applyOrderlists: options.applyOrderlists !== false,
|
|
2370
|
+
orderlistIds: options.orderlistIds
|
|
2371
|
+
} : { applyOrderlists: false };
|
|
2366
2372
|
const input = {
|
|
2367
2373
|
term,
|
|
2368
2374
|
language,
|
|
@@ -2374,6 +2380,7 @@ function useProductSearch(options) {
|
|
|
2374
2380
|
propellerSdkV2.ProductStatus.T,
|
|
2375
2381
|
propellerSdkV2.ProductStatus.S
|
|
2376
2382
|
],
|
|
2383
|
+
...orderlistScope,
|
|
2377
2384
|
sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
|
|
2378
2385
|
searchFields: [
|
|
2379
2386
|
{
|
|
@@ -2420,7 +2427,8 @@ function useProductSearch(options) {
|
|
|
2420
2427
|
}
|
|
2421
2428
|
}, 300);
|
|
2422
2429
|
},
|
|
2423
|
-
|
|
2430
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2431
|
+
[graphqlClient, language, configuration, userKey, JSON.stringify(options.orderlistIds ?? []), options.applyOrderlists]
|
|
2424
2432
|
);
|
|
2425
2433
|
React6.useEffect(() => {
|
|
2426
2434
|
if (!isControlled) fetchProducts();
|
|
@@ -3575,6 +3583,13 @@ function AccountIconAndMenu(rawProps) {
|
|
|
3575
3583
|
setMenuOpen(false);
|
|
3576
3584
|
if (props.onMenuItemClick) props.onMenuItemClick(href);
|
|
3577
3585
|
}
|
|
3586
|
+
function handleMenuLinkClick(event, href) {
|
|
3587
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
3588
|
+
return;
|
|
3589
|
+
}
|
|
3590
|
+
event.preventDefault();
|
|
3591
|
+
handleMenuItemClick(href);
|
|
3592
|
+
}
|
|
3578
3593
|
function handleLogoutClick() {
|
|
3579
3594
|
setMenuOpen(false);
|
|
3580
3595
|
if (props.onLogoutClick) props.onLogoutClick();
|
|
@@ -3623,10 +3638,10 @@ function AccountIconAndMenu(rawProps) {
|
|
|
3623
3638
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "propeller-account-menu__user-name font-medium text-foreground truncate", children: getUserName() })
|
|
3624
3639
|
] }),
|
|
3625
3640
|
/* @__PURE__ */ jsxRuntime.jsx("nav", { className: "propeller-account-menu__nav py-2", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "propeller-account-menu__list space-y-0.5", children: getMenuLinks()?.map((link) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "propeller-account-menu__item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3626
|
-
"
|
|
3641
|
+
"a",
|
|
3627
3642
|
{
|
|
3628
|
-
|
|
3629
|
-
onClick: (event) =>
|
|
3643
|
+
href: link.href,
|
|
3644
|
+
onClick: (event) => handleMenuLinkClick(event, link.href),
|
|
3630
3645
|
"data-active": isActiveLink(link.href) ? "true" : "false",
|
|
3631
3646
|
className: `propeller-account-menu__link flex w-full items-center gap-3 px-4 py-2.5 text-sm font-medium transition-colors ${isActiveLink(link.href) ? "bg-secondary/5 text-secondary border-l-2 border-secondary" : "text-muted-foreground hover:bg-surface-hover hover:text-foreground"}`,
|
|
3632
3647
|
children: link.label
|
|
@@ -3689,11 +3704,11 @@ function AccountIconAndMenu(rawProps) {
|
|
|
3689
3704
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "propeller-account-menu__user-name font-medium text-foreground truncate", children: getUserName() })
|
|
3690
3705
|
] }),
|
|
3691
3706
|
/* @__PURE__ */ jsxRuntime.jsx("nav", { className: "propeller-account-menu__nav", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "propeller-account-menu__list space-y-0.5", children: getMenuLinks()?.map((link) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "propeller-account-menu__item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3692
|
-
"
|
|
3707
|
+
"a",
|
|
3693
3708
|
{
|
|
3694
|
-
|
|
3709
|
+
href: link.href,
|
|
3695
3710
|
className: "propeller-account-menu__link flex w-full items-center gap-3 px-3 py-2 text-sm font-medium rounded-control text-muted-foreground hover:bg-surface-hover hover:text-foreground transition-colors",
|
|
3696
|
-
onClick: (event) =>
|
|
3711
|
+
onClick: (event) => handleMenuLinkClick(event, link.href),
|
|
3697
3712
|
children: link.label
|
|
3698
3713
|
}
|
|
3699
3714
|
) }, link.href)) }) }),
|
|
@@ -11850,7 +11865,8 @@ function OrderList(rawProps) {
|
|
|
11850
11865
|
orderStatuses: props.orderStatus,
|
|
11851
11866
|
termFields: props.termFields,
|
|
11852
11867
|
itemsPerPage: props.initialItemsPerPage || 10,
|
|
11853
|
-
channelIds: props.channelIds
|
|
11868
|
+
channelIds: props.channelIds,
|
|
11869
|
+
initialSearchForm: props.initialSearchForm
|
|
11854
11870
|
});
|
|
11855
11871
|
function handlePageChange(newPage) {
|
|
11856
11872
|
if (newPage >= 1 && newPage <= totalPages) {
|
|
@@ -12163,6 +12179,7 @@ function OrderList(rawProps) {
|
|
|
12163
12179
|
onClick: (event) => {
|
|
12164
12180
|
setSearchForm({});
|
|
12165
12181
|
fetchOrders(1);
|
|
12182
|
+
props.onSearchApply?.({});
|
|
12166
12183
|
},
|
|
12167
12184
|
children: propellerV2CoreUi.getLabel(props.labels, "clearButton", "Clear")
|
|
12168
12185
|
}
|
|
@@ -12171,7 +12188,10 @@ function OrderList(rawProps) {
|
|
|
12171
12188
|
"button",
|
|
12172
12189
|
{
|
|
12173
12190
|
className: "propeller-order-list__search-btn inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-control shadow-sm text-primary-foreground bg-primary hover:bg-primary/80 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary",
|
|
12174
|
-
onClick: (event) =>
|
|
12191
|
+
onClick: (event) => {
|
|
12192
|
+
fetchOrders(1);
|
|
12193
|
+
props.onSearchApply?.(searchForm);
|
|
12194
|
+
},
|
|
12175
12195
|
children: propellerV2CoreUi.getLabel(props.labels, "searchButton", "Search")
|
|
12176
12196
|
}
|
|
12177
12197
|
)
|
|
@@ -12191,7 +12211,7 @@ function OrderList(rawProps) {
|
|
|
12191
12211
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "propeller-order-list__tbody bg-card divide-y divide-border", children: orders?.map((order) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12192
12212
|
"tr",
|
|
12193
12213
|
{
|
|
12194
|
-
className:
|
|
12214
|
+
className: `propeller-order-list__row hover:bg-surface-hover ${rowsClickable ? "cursor-pointer" : ""}`,
|
|
12195
12215
|
"data-clickable": rowsClickable ? "true" : "false",
|
|
12196
12216
|
onClick: (event) => rowsClickable && props.onOrderClick(order.id),
|
|
12197
12217
|
children: columns?.map((col) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -17281,6 +17301,9 @@ function SearchBar(rawProps) {
|
|
|
17281
17301
|
}
|
|
17282
17302
|
setShowDropdown(false);
|
|
17283
17303
|
}
|
|
17304
|
+
function isModifiedClick(event) {
|
|
17305
|
+
return event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
|
17306
|
+
}
|
|
17284
17307
|
React6.useEffect(() => {
|
|
17285
17308
|
const listener = (e) => {
|
|
17286
17309
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
@@ -17334,39 +17357,68 @@ function SearchBar(rawProps) {
|
|
|
17334
17357
|
] }) }),
|
|
17335
17358
|
showDropdown ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__dropdown absolute top-full left-0 right-0 mt-2 bg-card rounded-container shadow-xl border border-border z-50 flex flex-col max-h-96", children: [
|
|
17336
17359
|
results.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
17337
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__results flex-1 overflow-y-auto", children: results?.map((result, index) =>
|
|
17338
|
-
"div"
|
|
17360
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__results flex-1 overflow-y-auto", children: results?.map((result, index) => {
|
|
17361
|
+
const ResultTag = props.getResultHref ? "a" : "div";
|
|
17362
|
+
const resultProps = props.getResultHref ? {
|
|
17363
|
+
href: props.getResultHref(result),
|
|
17364
|
+
onClick: (event) => {
|
|
17365
|
+
if (isModifiedClick(event)) return;
|
|
17366
|
+
event.preventDefault();
|
|
17367
|
+
handleResultClick(result);
|
|
17368
|
+
}
|
|
17369
|
+
} : { onClick: (_event) => handleResultClick(result) };
|
|
17370
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17371
|
+
ResultTag,
|
|
17372
|
+
{
|
|
17373
|
+
className: "propeller-search-bar__result flex items-center gap-4 p-3 hover:bg-surface-hover cursor-pointer border-b border-border-subtle last:border-b-0",
|
|
17374
|
+
...resultProps,
|
|
17375
|
+
children: [
|
|
17376
|
+
result.imageUrl || noImageUrl() ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__result-media relative w-16 h-16 flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17377
|
+
"img",
|
|
17378
|
+
{
|
|
17379
|
+
className: "propeller-search-bar__result-image w-full h-full object-contain",
|
|
17380
|
+
src: result.imageUrl || noImageUrl(),
|
|
17381
|
+
alt: result.name
|
|
17382
|
+
}
|
|
17383
|
+
) }) : null,
|
|
17384
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
17385
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__result-name font-semibold truncate", children: result.name }),
|
|
17386
|
+
result.sku ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__result-sku text-sm text-muted-foreground", children: [
|
|
17387
|
+
"SKU: ",
|
|
17388
|
+
result.sku
|
|
17389
|
+
] }) : null
|
|
17390
|
+
] }),
|
|
17391
|
+
props.renderPrice ? props.renderPrice(result) : props.showPrice !== false && result.price !== void 0 && result.price !== null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__result-price text-sm font-semibold text-foreground flex-shrink-0 text-right", children: [
|
|
17392
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-search-bar__result-price-value", children: formatItemPrice(leadingPrice(result)) }),
|
|
17393
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-search-bar__result-price-label block text-xs font-normal text-muted-foreground", children: priceTaxLabel() })
|
|
17394
|
+
] }) : null
|
|
17395
|
+
]
|
|
17396
|
+
},
|
|
17397
|
+
result.id + "-" + index
|
|
17398
|
+
);
|
|
17399
|
+
}) }),
|
|
17400
|
+
itemsFound > results.length ? props.getViewAllHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17401
|
+
"a",
|
|
17339
17402
|
{
|
|
17340
|
-
|
|
17341
|
-
|
|
17403
|
+
href: props.getViewAllHref(localTerm),
|
|
17404
|
+
className: "propeller-search-bar__view-all block flex-shrink-0 p-3 text-center text-primary hover:bg-primary/5 cursor-pointer font-semibold border-t border-border bg-card rounded-b-container",
|
|
17405
|
+
onClick: (event) => {
|
|
17406
|
+
if (isModifiedClick(event)) return;
|
|
17407
|
+
event.preventDefault();
|
|
17408
|
+
handleViewAllClick();
|
|
17409
|
+
},
|
|
17342
17410
|
children: [
|
|
17343
|
-
|
|
17344
|
-
|
|
17345
|
-
|
|
17346
|
-
|
|
17347
|
-
src: result.imageUrl || noImageUrl(),
|
|
17348
|
-
alt: result.name
|
|
17349
|
-
}
|
|
17350
|
-
) }) : null,
|
|
17351
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
17352
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__result-name font-semibold truncate", children: result.name }),
|
|
17353
|
-
result.sku ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__result-sku text-sm text-muted-foreground", children: [
|
|
17354
|
-
"SKU: ",
|
|
17355
|
-
result.sku
|
|
17356
|
-
] }) : null
|
|
17357
|
-
] }),
|
|
17358
|
-
result.price !== void 0 && result.price !== null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__result-price text-sm font-semibold text-foreground flex-shrink-0 text-right", children: [
|
|
17359
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-search-bar__result-price-value", children: formatItemPrice(leadingPrice(result)) }),
|
|
17360
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-search-bar__result-price-label block text-xs font-normal text-muted-foreground", children: priceTaxLabel() })
|
|
17361
|
-
] }) : null
|
|
17411
|
+
propellerV2CoreUi.getLabel(props.labels, "viewAll", "View all results"),
|
|
17412
|
+
" (",
|
|
17413
|
+
itemsFound,
|
|
17414
|
+
")"
|
|
17362
17415
|
]
|
|
17363
|
-
}
|
|
17364
|
-
|
|
17365
|
-
|
|
17366
|
-
itemsFound > results.length ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17367
|
-
"div",
|
|
17416
|
+
}
|
|
17417
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17418
|
+
"button",
|
|
17368
17419
|
{
|
|
17369
|
-
|
|
17420
|
+
type: "button",
|
|
17421
|
+
className: "propeller-search-bar__view-all block w-full flex-shrink-0 p-3 text-center text-primary hover:bg-primary/5 cursor-pointer font-semibold border-t border-border bg-card rounded-b-container",
|
|
17370
17422
|
onClick: (event) => handleViewAllClick(),
|
|
17371
17423
|
children: [
|
|
17372
17424
|
propellerV2CoreUi.getLabel(props.labels, "viewAll", "View all results"),
|