@propeller-commerce/propeller-v2-react-ui 0.4.15 → 0.4.16
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 +25 -0
- package/dist/index.cjs +45 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +132 -63
- package/dist/index.d.ts +132 -63
- package/dist/index.js +45 -18
- package/dist/index.js.map +1 -1
- package/dist/pure.cjs.map +1 -1
- package/dist/pure.d.cts +2 -2
- package/dist/pure.d.ts +2 -2
- package/dist/pure.js.map +1 -1
- package/dist/shared.d.cts +1 -1
- package/dist/shared.d.ts +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,31 @@ 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.16] - 2026-07-09
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `ProductGrid`, `SearchBar`, `ProductInfo`: new `orderlistIds?: number[]` and
|
|
16
|
+
`applyOrderlists?: boolean` props to scope the product/search fetch to
|
|
17
|
+
specific orderlists (e.g. a chosen B2B contract). When `orderlistIds` is
|
|
18
|
+
non-empty, orderlists are applied (unless `applyOrderlists` is `false`);
|
|
19
|
+
otherwise `applyOrderlists: false` is sent so an authenticated user without a
|
|
20
|
+
contract still sees the full catalogue. Threaded through `useProductSearch`
|
|
21
|
+
and `useProductInfo` (explicit ids override the composable's default
|
|
22
|
+
all-company-orderlists resolution).
|
|
23
|
+
- `Menu`: new `getUrl?: (category: Category) => string` prop — a custom URL
|
|
24
|
+
builder that overrides `menuLinkFormat` / `configuration.urls.getCategoryUrl`,
|
|
25
|
+
letting hosts inject dynamic query strings (e.g. `?contract=…`). Mirrors the
|
|
26
|
+
existing `Breadcrumbs.getUrl`.
|
|
27
|
+
- `GridToolbar`: new `hidePriceSort?: boolean` prop to hide the price sort
|
|
28
|
+
option entirely (closed B2B portals where prices are "by quotation").
|
|
29
|
+
- `ProductTabs` / `ProductSpecifications`: new
|
|
30
|
+
`specificationsPackageDescription?` (ProductTabs) → `packageDescription?`
|
|
31
|
+
(ProductSpecifications) passthrough, rendering an extra package-description
|
|
32
|
+
string above the specifications table.
|
|
33
|
+
|
|
34
|
+
All additions are additive and backward-compatible.
|
|
35
|
+
|
|
11
36
|
## [0.4.15] - 2026-07-08
|
|
12
37
|
|
|
13
38
|
### Changed
|
package/dist/index.cjs
CHANGED
|
@@ -2045,7 +2045,13 @@ function useProductInfo(options) {
|
|
|
2045
2045
|
setError(null);
|
|
2046
2046
|
try {
|
|
2047
2047
|
let orderlistIds = [];
|
|
2048
|
-
|
|
2048
|
+
let applyOrderlists = true;
|
|
2049
|
+
if (options.orderlistIds && options.orderlistIds.length > 0) {
|
|
2050
|
+
orderlistIds = options.orderlistIds;
|
|
2051
|
+
applyOrderlists = options.applyOrderlists !== false;
|
|
2052
|
+
} else if (options.applyOrderlists === false) {
|
|
2053
|
+
applyOrderlists = false;
|
|
2054
|
+
} else if (options.user && options.companyId) {
|
|
2049
2055
|
const orderlistService = propellerV2CoreUi.createServices(graphqlClient).orderlist;
|
|
2050
2056
|
const searchInput = { companyIds: [options.companyId] };
|
|
2051
2057
|
const orderlists = await orderlistService.getOrderlists(searchInput);
|
|
@@ -2056,7 +2062,7 @@ function useProductInfo(options) {
|
|
|
2056
2062
|
const variables = {
|
|
2057
2063
|
productId,
|
|
2058
2064
|
language,
|
|
2059
|
-
applyOrderlists
|
|
2065
|
+
applyOrderlists,
|
|
2060
2066
|
orderlistIds,
|
|
2061
2067
|
imageSearchFilters: imageSearchFilters ?? configuration.imageSearchFiltersGrid,
|
|
2062
2068
|
imageVariantFilters: imageVariantFilters ?? configuration.imageVariantFiltersLarge ?? configuration.imageVariantFiltersSmall,
|
|
@@ -2240,6 +2246,10 @@ function useProductSearch(options) {
|
|
|
2240
2246
|
const userId = options.user && "contactId" in options.user ? options.user.contactId : options.user && "customerId" in options.user ? options.user.customerId : void 0;
|
|
2241
2247
|
const contactId = options.user && "contactId" in options.user ? options.user.contactId : void 0;
|
|
2242
2248
|
const customerId = options.user && "customerId" in options.user ? options.user.customerId : void 0;
|
|
2249
|
+
const orderlistScope = options.orderlistIds && options.orderlistIds.length > 0 ? {
|
|
2250
|
+
applyOrderlists: options.applyOrderlists !== false,
|
|
2251
|
+
orderlistIds: options.orderlistIds
|
|
2252
|
+
} : { applyOrderlists: false };
|
|
2243
2253
|
const categoryProductSearchInput = {
|
|
2244
2254
|
language: lang,
|
|
2245
2255
|
page: pagination.currentPage,
|
|
@@ -2257,7 +2267,8 @@ function useProductSearch(options) {
|
|
|
2257
2267
|
...priceFilter && { price: priceFilter },
|
|
2258
2268
|
...sortInputs.length && { sortInputs },
|
|
2259
2269
|
...options.companyId && { companyId: options.companyId },
|
|
2260
|
-
...userId !== void 0 && { userId }
|
|
2270
|
+
...userId !== void 0 && { userId },
|
|
2271
|
+
...orderlistScope
|
|
2261
2272
|
};
|
|
2262
2273
|
const priceCalculateProductInput = {
|
|
2263
2274
|
taxZone,
|
|
@@ -7430,7 +7441,7 @@ function CategoryDescription(props) {
|
|
|
7430
7441
|
const plain = html.replace(/<[^>]*>/g, "");
|
|
7431
7442
|
if (plain.length <= maxLen) return html;
|
|
7432
7443
|
const truncated = plain.substring(0, maxLen);
|
|
7433
|
-
return truncated.substring(0, truncated.lastIndexOf(" ")) + "\
|
|
7444
|
+
return truncated.substring(0, truncated.lastIndexOf(" ")) + "\u2026";
|
|
7434
7445
|
}
|
|
7435
7446
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: !!html ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7436
7447
|
"div",
|
|
@@ -10697,7 +10708,8 @@ function GridToolbar(rawProps) {
|
|
|
10697
10708
|
}
|
|
10698
10709
|
function getSortOptions() {
|
|
10699
10710
|
const opts = props.sortOptions || [];
|
|
10700
|
-
|
|
10711
|
+
const base = opts.length > 0 ? opts : ALL_SORT_FIELDS;
|
|
10712
|
+
return props.hidePriceSort ? base.filter((f) => f !== propellerSdkV2.ProductSortField.PRICE) : base;
|
|
10701
10713
|
}
|
|
10702
10714
|
function getOffsetOptions() {
|
|
10703
10715
|
const opts = props.offset || [];
|
|
@@ -11120,10 +11132,12 @@ function Menu(rawProps) {
|
|
|
11120
11132
|
}
|
|
11121
11133
|
function getCategoryUrl(cat) {
|
|
11122
11134
|
const lang = props.language || "NL";
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
lang
|
|
11126
|
-
|
|
11135
|
+
const category = {
|
|
11136
|
+
categoryId: cat.categoryId,
|
|
11137
|
+
slug: [{ value: cat.slug, language: lang }]
|
|
11138
|
+
};
|
|
11139
|
+
if (props.getUrl) return props.getUrl(category);
|
|
11140
|
+
return props.configuration.urls.getCategoryUrl(category, lang);
|
|
11127
11141
|
}
|
|
11128
11142
|
function getSubCategories(cat) {
|
|
11129
11143
|
return (cat.children || []).filter((sub) => sub.name && sub.slug);
|
|
@@ -13938,7 +13952,7 @@ function useProductGrid() {
|
|
|
13938
13952
|
const ctx = React6.useContext(ProductGridSearchContext);
|
|
13939
13953
|
if (!ctx) {
|
|
13940
13954
|
throw new Error(
|
|
13941
|
-
"<ProductGrid.X> must be rendered inside <ProductGrid>. Got null context \
|
|
13955
|
+
"<ProductGrid.X> must be rendered inside <ProductGrid>. Got null context \u2014 wrap the subcomponents in <ProductGrid categoryId={...}>...</ProductGrid>."
|
|
13942
13956
|
);
|
|
13943
13957
|
}
|
|
13944
13958
|
return ctx;
|
|
@@ -13959,6 +13973,8 @@ function ProductGrid(rawProps) {
|
|
|
13959
13973
|
categoryId: props.categoryId,
|
|
13960
13974
|
term: props.term,
|
|
13961
13975
|
brand: props.brand,
|
|
13976
|
+
orderlistIds: props.orderlistIds,
|
|
13977
|
+
applyOrderlists: props.applyOrderlists,
|
|
13962
13978
|
language: props.language,
|
|
13963
13979
|
taxZone: props.taxZone,
|
|
13964
13980
|
user: props.user,
|
|
@@ -14361,9 +14377,15 @@ function useProductInfoContext() {
|
|
|
14361
14377
|
}
|
|
14362
14378
|
function ProductInfo(rawProps) {
|
|
14363
14379
|
const props = useInfraProps(rawProps);
|
|
14364
|
-
const { product: fetchedProduct, loading, fetchProduct } = useProductInfo(
|
|
14365
|
-
|
|
14366
|
-
|
|
14380
|
+
const { product: fetchedProduct, loading, fetchProduct } = useProductInfo({
|
|
14381
|
+
graphqlClient: props.graphqlClient ?? {},
|
|
14382
|
+
language: props.language,
|
|
14383
|
+
configuration: props.configuration,
|
|
14384
|
+
user: props.user,
|
|
14385
|
+
companyId: props.companyId,
|
|
14386
|
+
orderlistIds: props.orderlistIds,
|
|
14387
|
+
applyOrderlists: props.applyOrderlists
|
|
14388
|
+
});
|
|
14367
14389
|
const activeProduct = props.product || fetchedProduct;
|
|
14368
14390
|
function getProductName5() {
|
|
14369
14391
|
if (!activeProduct) return "";
|
|
@@ -15081,13 +15103,14 @@ function ProductSpecifications(rawProps) {
|
|
|
15081
15103
|
if (!props.productId || !props.graphqlClient) return;
|
|
15082
15104
|
fetchSpecs(props.productId);
|
|
15083
15105
|
}, [props.productId]);
|
|
15084
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: !loading && hasPublicAttributes() ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15106
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: !loading && (hasPublicAttributes() || props.packageDescription) ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15085
15107
|
"div",
|
|
15086
15108
|
{
|
|
15087
15109
|
className: `propeller-product-specifications ${props.className || ""}`,
|
|
15088
15110
|
"data-layout": props.layout === "list" ? "list" : "table",
|
|
15089
15111
|
"data-grouped": props.grouping ? "true" : "false",
|
|
15090
15112
|
children: [
|
|
15113
|
+
props.packageDescription ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "propeller-product-specifications__package-description mb-4 text-sm text-muted-foreground", children: props.packageDescription }) : null,
|
|
15091
15114
|
!props.grouping ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15092
15115
|
props.layout !== "list" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border", children: getAttributes()?.map((attr, i) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "propeller-product-specifications__row odd:bg-card even:bg-muted/20", children: [
|
|
15093
15116
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-2 font-medium text-foreground w-1/2", children: getAttributeLabel(attr) }),
|
|
@@ -15316,7 +15339,8 @@ function ProductTabs(rawProps) {
|
|
|
15316
15339
|
attributes: getSpecsAttributes(),
|
|
15317
15340
|
language: props.language,
|
|
15318
15341
|
layout: props.specificationsLayout,
|
|
15319
|
-
grouping: props.specificationsGrouping
|
|
15342
|
+
grouping: props.specificationsGrouping,
|
|
15343
|
+
packageDescription: props.specificationsPackageDescription
|
|
15320
15344
|
}
|
|
15321
15345
|
) }) : null,
|
|
15322
15346
|
isActive("downloads") && isTabVisible("downloads") ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -15419,7 +15443,8 @@ function ProductTabs(rawProps) {
|
|
|
15419
15443
|
attributes: getSpecsAttributes(),
|
|
15420
15444
|
language: props.language,
|
|
15421
15445
|
layout: props.specificationsLayout,
|
|
15422
|
-
grouping: props.specificationsGrouping
|
|
15446
|
+
grouping: props.specificationsGrouping,
|
|
15447
|
+
packageDescription: props.specificationsPackageDescription
|
|
15423
15448
|
}
|
|
15424
15449
|
) }) : null
|
|
15425
15450
|
] }) : null,
|
|
@@ -16206,7 +16231,7 @@ function RegisterForm(rawProps) {
|
|
|
16206
16231
|
const contactLabel = props.labels?.contactLabel || "Company";
|
|
16207
16232
|
const customerLabel = props.labels?.customerLabel || "Consumer";
|
|
16208
16233
|
const emailPlaceholder = props.labels?.emailPlaceholder || "name@example.com";
|
|
16209
|
-
const passwordPlaceholder = props.labels?.passwordPlaceholder || "\
|
|
16234
|
+
const passwordPlaceholder = props.labels?.passwordPlaceholder || "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
16210
16235
|
const passwordMismatchText = props.labels?.passwordMismatch || "Passwords do not match";
|
|
16211
16236
|
const loginText = props.labels?.loginText || "Already have an account?";
|
|
16212
16237
|
const loginLinkText = props.labels?.loginLink || "Log in";
|
|
@@ -17110,7 +17135,9 @@ function SearchBar(rawProps) {
|
|
|
17110
17135
|
graphqlClient: props.graphqlClient,
|
|
17111
17136
|
language: props.language,
|
|
17112
17137
|
configuration: props.configuration || {},
|
|
17113
|
-
companyId: props.companyId
|
|
17138
|
+
companyId: props.companyId,
|
|
17139
|
+
orderlistIds: props.orderlistIds,
|
|
17140
|
+
applyOrderlists: props.applyOrderlists
|
|
17114
17141
|
});
|
|
17115
17142
|
const results = searchResults.slice(0, maxResults).map((item) => mapToSearchBarResult(item));
|
|
17116
17143
|
const itemsFound = searchItemsFound;
|