@propeller-commerce/propeller-v2-react-ui 0.21.0 → 0.23.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 +78 -0
- package/dist/index.cjs +170 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -12
- package/dist/index.d.ts +94 -12
- package/dist/index.js +172 -56
- package/dist/index.js.map +1 -1
- package/dist/pure.cjs +6 -14
- package/dist/pure.cjs.map +1 -1
- package/dist/pure.d.cts +12 -0
- package/dist/pure.d.ts +12 -0
- package/dist/pure.js +7 -15
- package/dist/pure.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { getLabel, getLocalizedValue, formatPrice, localeForLanguage, getClusterSku, getClusterImageUrl, isContentHidden, getProductSku, getProductImageUrl,
|
|
2
|
+
import { getLabel, getLocalizedValue, formatPrice, localeForLanguage, getClusterSku, getClusterImageUrl, isContentHidden, getProductSku, getProductImageUrl, createServices, isCheckoutAllowed, err, ok, formatSurcharge, deriveUserMode, isContact, isCustomer, getAddresses, attributeNameMatches, getAttributeDisplayName, filterProductsBySelections, extractAttributeValues, buildInventoryFilter, findPurchaserPac, isOverAuthorizationLimit, MIN_STOCK_THRESHOLD, getNettedBonusItems, getLanguageString, collectAttributeValues, getCountryName, resolveLanguageEntry, getLanguageUri } from '@propeller-commerce/propeller-v2-core-ui';
|
|
3
3
|
export * from '@propeller-commerce/propeller-v2-core-ui';
|
|
4
4
|
import * as React6 from 'react';
|
|
5
|
-
import { createContext, useState, useRef, useCallback, useMemo, useContext
|
|
5
|
+
import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext } from 'react';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
import { ProductStatus, ProductSortField, SortOrder, CrossupsellType, CartStatus, CartAddressType, Gender, YesNo, AddressType, MagicTokenService, PaymentStatuses, OrderSearchFields, OrderItemClass, ProductSearchableField, machineService, PurchaseRole, AttributeType, OrderSortField, OrderType, BundleCondition, OrderDiscountType } from '@propeller-commerce/propeller-sdk-v2';
|
|
8
8
|
import { clsx } from 'clsx';
|
|
@@ -747,10 +747,29 @@ function useCart(options) {
|
|
|
747
747
|
const [loading, setLoading] = useState(false);
|
|
748
748
|
const [error, setError] = useState(null);
|
|
749
749
|
const notesTimers = useRef({});
|
|
750
|
-
|
|
751
|
-
(
|
|
752
|
-
|
|
753
|
-
|
|
750
|
+
useEffect(() => {
|
|
751
|
+
if (!graphqlClient || !cartId || cart) return;
|
|
752
|
+
let cancelled = false;
|
|
753
|
+
(async () => {
|
|
754
|
+
try {
|
|
755
|
+
const fetched = await createServices(graphqlClient).cart.getCart({
|
|
756
|
+
cartId,
|
|
757
|
+
imageSearchFilters: imageSearchFilters(),
|
|
758
|
+
imageVariantFilters: imageVariantFilters(),
|
|
759
|
+
language
|
|
760
|
+
});
|
|
761
|
+
if (!cancelled && fetched) setCart(fetched);
|
|
762
|
+
} catch {
|
|
763
|
+
}
|
|
764
|
+
})();
|
|
765
|
+
return () => {
|
|
766
|
+
cancelled = true;
|
|
767
|
+
};
|
|
768
|
+
}, [graphqlClient, cartId, cart, language, imageSearchFilters, imageVariantFilters]);
|
|
769
|
+
const checkoutAllowed = useMemo(() => {
|
|
770
|
+
if (cartId && !cart) return false;
|
|
771
|
+
return isCheckoutAllowed(user, resolvedCompanyId, cart);
|
|
772
|
+
}, [user, resolvedCompanyId, cart, cartId]);
|
|
754
773
|
function getMinQuantity(product) {
|
|
755
774
|
const min = product?.minimumQuantity;
|
|
756
775
|
return min && min > 0 ? min : 1;
|
|
@@ -1571,7 +1590,8 @@ var INFRA_KEYS = [
|
|
|
1571
1590
|
"includeTax",
|
|
1572
1591
|
"currency",
|
|
1573
1592
|
"configuration",
|
|
1574
|
-
"portalMode"
|
|
1593
|
+
"portalMode",
|
|
1594
|
+
"isAuthenticated"
|
|
1575
1595
|
];
|
|
1576
1596
|
function useInfraProps(props) {
|
|
1577
1597
|
const ctx = usePropellerContext();
|
|
@@ -2248,10 +2268,11 @@ function useProductSearch(options) {
|
|
|
2248
2268
|
const isLoading = !isControlled && internalLoading;
|
|
2249
2269
|
function filterByLanguage(products, lang) {
|
|
2250
2270
|
if (!lang) return products;
|
|
2271
|
+
const target = lang.toUpperCase();
|
|
2251
2272
|
return products.filter((p) => {
|
|
2252
2273
|
const names = p.names || p.names || [];
|
|
2253
2274
|
if (!names || names.length === 0) return true;
|
|
2254
|
-
return names.some((n) => n.language ===
|
|
2275
|
+
return names.some((n) => (n.language || "").toUpperCase() === target);
|
|
2255
2276
|
});
|
|
2256
2277
|
}
|
|
2257
2278
|
const fetchProducts = useCallback(async () => {
|
|
@@ -2741,6 +2762,40 @@ function useQuickOrder(options) {
|
|
|
2741
2762
|
);
|
|
2742
2763
|
return { submitting, error, searchProducts, submit };
|
|
2743
2764
|
}
|
|
2765
|
+
|
|
2766
|
+
// src/composables/shared/utils/machineLanguage.ts
|
|
2767
|
+
var MACHINE_NOT_FOUND = "SPARE_PARTS_MACHINE_NOT_FOUND_ERROR";
|
|
2768
|
+
function isMachineNotFound(error) {
|
|
2769
|
+
const entries = error?.errors;
|
|
2770
|
+
if (!Array.isArray(entries)) return false;
|
|
2771
|
+
return entries.some(
|
|
2772
|
+
(e) => e?.extensions?.code === MACHINE_NOT_FOUND || /no machine found for slug and language/i.test(e?.message ?? "")
|
|
2773
|
+
);
|
|
2774
|
+
}
|
|
2775
|
+
function machineLanguageCandidates(machineLanguage, language, extra) {
|
|
2776
|
+
const ordered = [machineLanguage, language, ...extra ?? []];
|
|
2777
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2778
|
+
const out = [];
|
|
2779
|
+
for (const raw of ordered) {
|
|
2780
|
+
const value = raw?.trim().toUpperCase();
|
|
2781
|
+
if (!value || seen.has(value)) continue;
|
|
2782
|
+
seen.add(value);
|
|
2783
|
+
out.push(value);
|
|
2784
|
+
}
|
|
2785
|
+
return out;
|
|
2786
|
+
}
|
|
2787
|
+
async function resolveMachineAcrossLanguages(candidates, fetchOne) {
|
|
2788
|
+
for (const language of candidates) {
|
|
2789
|
+
try {
|
|
2790
|
+
return { machine: await fetchOne(language), language };
|
|
2791
|
+
} catch (error) {
|
|
2792
|
+
if (!isMachineNotFound(error)) throw error;
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
return null;
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
// src/composables/react/useSpareParts.ts
|
|
2744
2799
|
var inflightFetches3 = /* @__PURE__ */ new Set();
|
|
2745
2800
|
var STOREFRONT_STATUSES = [
|
|
2746
2801
|
ProductStatus.A,
|
|
@@ -2757,6 +2812,8 @@ function useSpareParts(options) {
|
|
|
2757
2812
|
const [itemsFound, setItemsFound] = useState(0);
|
|
2758
2813
|
const [internalLoading, setInternalLoading] = useState(false);
|
|
2759
2814
|
const [internalPage, setInternalPage] = useState(1);
|
|
2815
|
+
const [notFound, setNotFound] = useState(false);
|
|
2816
|
+
const machineLanguagesKey = (options.machineLanguages ?? []).join(",");
|
|
2760
2817
|
const currentPage = options.page ?? internalPage;
|
|
2761
2818
|
const [totalPages, setTotalPages] = useState(1);
|
|
2762
2819
|
const fetchIdRef = useRef(0);
|
|
@@ -2822,17 +2879,35 @@ function useSpareParts(options) {
|
|
|
2822
2879
|
const filterAvailableAttributeInput = {
|
|
2823
2880
|
isSearchable: true
|
|
2824
2881
|
};
|
|
2825
|
-
const
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2882
|
+
const resolved = await resolveMachineAcrossLanguages(
|
|
2883
|
+
machineLanguageCandidates(
|
|
2884
|
+
options.machineLanguage,
|
|
2885
|
+
options.language,
|
|
2886
|
+
options.machineLanguages
|
|
2887
|
+
),
|
|
2888
|
+
(language) => service.getMachine({
|
|
2889
|
+
slug: options.slug,
|
|
2890
|
+
// The machine tree's language, NOT the parts' — see `machineLanguage`.
|
|
2891
|
+
language,
|
|
2892
|
+
sparePartsMachineProductSearchInput,
|
|
2893
|
+
filterAvailableAttributeInput,
|
|
2894
|
+
priceCalculateProductInput,
|
|
2895
|
+
imageSearchFilters: options.configuration?.imageSearchFiltersGrid,
|
|
2896
|
+
imageVariantFilters: options.configuration?.imageVariantFiltersMedium
|
|
2897
|
+
})
|
|
2898
|
+
);
|
|
2835
2899
|
if (thisId !== fetchIdRef.current) return;
|
|
2900
|
+
if (!resolved) {
|
|
2901
|
+
setNotFound(true);
|
|
2902
|
+
setInternalParts([]);
|
|
2903
|
+
setChildMachines([]);
|
|
2904
|
+
setItemsFound(0);
|
|
2905
|
+
options.onItemsFoundChange?.(0);
|
|
2906
|
+
setTotalPages(1);
|
|
2907
|
+
return;
|
|
2908
|
+
}
|
|
2909
|
+
setNotFound(false);
|
|
2910
|
+
const machine = resolved.machine;
|
|
2836
2911
|
const partsResponse = machine?.sparePartProducts;
|
|
2837
2912
|
const items = partsResponse?.items ?? [];
|
|
2838
2913
|
setInternalParts(items);
|
|
@@ -2874,6 +2949,7 @@ function useSpareParts(options) {
|
|
|
2874
2949
|
options.term,
|
|
2875
2950
|
options.language,
|
|
2876
2951
|
options.machineLanguage,
|
|
2952
|
+
machineLanguagesKey,
|
|
2877
2953
|
options.taxZone,
|
|
2878
2954
|
options.companyId,
|
|
2879
2955
|
options.textFilters,
|
|
@@ -2894,6 +2970,7 @@ function useSpareParts(options) {
|
|
|
2894
2970
|
options.term,
|
|
2895
2971
|
options.language,
|
|
2896
2972
|
options.machineLanguage,
|
|
2973
|
+
machineLanguagesKey,
|
|
2897
2974
|
options.companyId,
|
|
2898
2975
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2899
2976
|
JSON.stringify(options.textFilters ?? []),
|
|
@@ -2919,7 +2996,8 @@ function useSpareParts(options) {
|
|
|
2919
2996
|
currentPage,
|
|
2920
2997
|
totalPages,
|
|
2921
2998
|
fetchParts,
|
|
2922
|
-
goToPage
|
|
2999
|
+
goToPage,
|
|
3000
|
+
notFound: !isControlled && notFound
|
|
2923
3001
|
};
|
|
2924
3002
|
}
|
|
2925
3003
|
var inflightFetches4 = /* @__PURE__ */ new Set();
|
|
@@ -4208,7 +4286,7 @@ function AccountIconAndMenu(rawProps) {
|
|
|
4208
4286
|
onClick: (event) => handleIconClick(),
|
|
4209
4287
|
"aria-label": getLabel(props.labels, "accountLabel", "Account"),
|
|
4210
4288
|
"data-open": menuOpen ? "true" : "false",
|
|
4211
|
-
className: cn(`propeller-account-menu__trigger inline-flex items-center gap-2 px-3 py-2 rounded-control text-sm font-medium transition-colors text-
|
|
4289
|
+
className: cn(`propeller-account-menu__trigger inline-flex items-center gap-2 px-3 py-2 rounded-control text-sm font-medium transition-colors text-inherit${props.iconClassName ? " " + props.iconClassName : ""}`),
|
|
4212
4290
|
children: [
|
|
4213
4291
|
/* @__PURE__ */ jsx(
|
|
4214
4292
|
"svg",
|
|
@@ -7620,7 +7698,8 @@ function CartIconAndSidebar(rawProps) {
|
|
|
7620
7698
|
] });
|
|
7621
7699
|
}
|
|
7622
7700
|
var CartIconAndSidebar_default = CartIconAndSidebar;
|
|
7623
|
-
function CartOverview(
|
|
7701
|
+
function CartOverview(rawProps) {
|
|
7702
|
+
const props = useInfraProps(rawProps);
|
|
7624
7703
|
const [reference, setReference] = useState("");
|
|
7625
7704
|
const [notes, setNotes] = useState("");
|
|
7626
7705
|
const [termsAccepted, setTermsAccepted] = useState(false);
|
|
@@ -7630,6 +7709,7 @@ function CartOverview(props) {
|
|
|
7630
7709
|
const showReference = props.showReference !== false;
|
|
7631
7710
|
const showTermsAndConditions = props.showTermsAndConditions !== false;
|
|
7632
7711
|
const showPurchaseButton = props.showPurchaseButton !== false;
|
|
7712
|
+
const overLimit = isOverAuthorizationLimit(props.user, props.companyId, props.cart);
|
|
7633
7713
|
const invoiceAddress = props.cart?.invoiceAddress;
|
|
7634
7714
|
const deliveryAddress = props.cart?.deliveryAddress;
|
|
7635
7715
|
const getCountryName$1 = (code) => getCountryName(code, props.countries);
|
|
@@ -7769,7 +7849,12 @@ function CartOverview(props) {
|
|
|
7769
7849
|
] });
|
|
7770
7850
|
})() })
|
|
7771
7851
|
] }) : null,
|
|
7772
|
-
showPurchaseButton ? /* @__PURE__ */
|
|
7852
|
+
showPurchaseButton && overLimit ? /* @__PURE__ */ jsx("p", { className: "propeller-cart-overview__authorization-required text-sm text-muted-foreground mt-2", children: getLabel(
|
|
7853
|
+
props.labels,
|
|
7854
|
+
"authorizationRequired",
|
|
7855
|
+
"This order exceeds your authorization limit. Request authorization from the cart to continue."
|
|
7856
|
+
) }) : null,
|
|
7857
|
+
showPurchaseButton && !overLimit ? /* @__PURE__ */ jsxs(
|
|
7773
7858
|
"button",
|
|
7774
7859
|
{
|
|
7775
7860
|
type: "button",
|
|
@@ -8144,6 +8229,7 @@ var RESOLVE_SPEC = {
|
|
|
8144
8229
|
currency: { infra: "currency", default: "\u20AC" },
|
|
8145
8230
|
user: { infra: "user", default: null },
|
|
8146
8231
|
portalMode: { infra: "portalMode" },
|
|
8232
|
+
isAuthenticated: { infra: "isAuthenticated" },
|
|
8147
8233
|
columns: { grid: "columns", default: 3 },
|
|
8148
8234
|
showPrice: { grid: "showPrice" },
|
|
8149
8235
|
showStock: { grid: "showStock" },
|
|
@@ -8187,7 +8273,7 @@ function ClusterCard(rawProps) {
|
|
|
8187
8273
|
const textLabelValues = resolveAttributeValues(cluster, props.textLabels).map((value) => ({
|
|
8188
8274
|
value
|
|
8189
8275
|
}));
|
|
8190
|
-
const contentHidden = isContentHidden(props.portalMode, props.user);
|
|
8276
|
+
const contentHidden = isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
8191
8277
|
const defaultProductInventory = contentHidden ? void 0 : cluster?.defaultProduct?.inventory;
|
|
8192
8278
|
const useTax = props.includeTax !== void 0 ? !!props.includeTax : false;
|
|
8193
8279
|
const priceObj = contentHidden ? void 0 : cluster?.defaultProduct?.price;
|
|
@@ -8614,7 +8700,7 @@ function LoginToOrderButton(props) {
|
|
|
8614
8700
|
var LoginToOrderButton_default = LoginToOrderButton;
|
|
8615
8701
|
function ProductPriceDisplay(props) {
|
|
8616
8702
|
function isHidden2() {
|
|
8617
|
-
return isContentHidden(props.portalMode, props.user);
|
|
8703
|
+
return isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
8618
8704
|
}
|
|
8619
8705
|
function formatPrice17(value) {
|
|
8620
8706
|
if (value === null || value === void 0) return "";
|
|
@@ -8706,6 +8792,7 @@ var RESOLVE_SPEC2 = {
|
|
|
8706
8792
|
language: { infra: "language", default: "NL" },
|
|
8707
8793
|
includeTax: { infra: "includeTax" },
|
|
8708
8794
|
portalMode: { infra: "portalMode" },
|
|
8795
|
+
isAuthenticated: { infra: "isAuthenticated" },
|
|
8709
8796
|
configuration: { infra: "configuration" },
|
|
8710
8797
|
// Same entry ClusterCard has always had. Without it a shop priced in
|
|
8711
8798
|
// anything but euros had no route to the cards at all: the grid resolved the
|
|
@@ -8764,7 +8851,7 @@ function ProductCardRoot(rawProps) {
|
|
|
8764
8851
|
const language = props.language || "NL";
|
|
8765
8852
|
const product = props.product;
|
|
8766
8853
|
const isRow = props.columns === 1;
|
|
8767
|
-
const contentHidden = isContentHidden(props.portalMode, props.user);
|
|
8854
|
+
const contentHidden = isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
8768
8855
|
const showStock = !!props.showStock && !contentHidden;
|
|
8769
8856
|
const showCta = props.allowAddToCart !== false || contentHidden;
|
|
8770
8857
|
const name = getProductName(product, language);
|
|
@@ -9061,6 +9148,7 @@ function ProductCardPrice(props) {
|
|
|
9061
9148
|
currency: resolved.currency,
|
|
9062
9149
|
language: resolved.language,
|
|
9063
9150
|
portalMode: resolved.portalMode,
|
|
9151
|
+
isAuthenticated: resolved.isAuthenticated,
|
|
9064
9152
|
user: resolved.user,
|
|
9065
9153
|
showLoginPrompt: false
|
|
9066
9154
|
}
|
|
@@ -9068,7 +9156,7 @@ function ProductCardPrice(props) {
|
|
|
9068
9156
|
}
|
|
9069
9157
|
function ProductCardAddToCart(props) {
|
|
9070
9158
|
const { product, resolved } = useProductCard();
|
|
9071
|
-
if (isContentHidden(resolved.portalMode, resolved.user)) {
|
|
9159
|
+
if (isContentHidden(resolved.portalMode, resolved.user, resolved.isAuthenticated)) {
|
|
9072
9160
|
return /* @__PURE__ */ jsx(
|
|
9073
9161
|
LoginToOrderButton_default,
|
|
9074
9162
|
{
|
|
@@ -9089,9 +9177,13 @@ function ProductCardAddToCart(props) {
|
|
|
9089
9177
|
allowIncrDecr: resolved.allowIncrDecr,
|
|
9090
9178
|
showModal: resolved.showModal,
|
|
9091
9179
|
enableStockValidation: resolved.enableStockValidation,
|
|
9180
|
+
onAddToCart: resolved.onAddToCart,
|
|
9092
9181
|
afterAddToCart: resolved.afterAddToCart,
|
|
9093
9182
|
onProceedToCheckout: resolved.onProceedToCheckout,
|
|
9094
9183
|
onRequestQuoteClick: resolved.onRequestQuoteClick,
|
|
9184
|
+
createCart: resolved.createCart,
|
|
9185
|
+
onCartCreated: resolved.onCartCreated,
|
|
9186
|
+
includeTax: resolved.includeTax,
|
|
9095
9187
|
labels: resolved.addToCartLabels
|
|
9096
9188
|
}
|
|
9097
9189
|
);
|
|
@@ -9214,7 +9306,7 @@ function ProductGrid(rawProps) {
|
|
|
9214
9306
|
}
|
|
9215
9307
|
function showAddToCart() {
|
|
9216
9308
|
const allow = props.allowAddToCart !== false;
|
|
9217
|
-
return !isContentHidden(props.portalMode, props.user) && allow;
|
|
9309
|
+
return !isContentHidden(props.portalMode, props.user, props.isAuthenticated) && allow;
|
|
9218
9310
|
}
|
|
9219
9311
|
function getSkeletonItems() {
|
|
9220
9312
|
const cols = props.columns || 3;
|
|
@@ -9492,7 +9584,7 @@ function GridFilters(rawProps) {
|
|
|
9492
9584
|
}
|
|
9493
9585
|
function showAvailability() {
|
|
9494
9586
|
if (!props.showAvailabilityFilter) return false;
|
|
9495
|
-
return !isContentHidden(props.portalMode, props.user);
|
|
9587
|
+
return !isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
9496
9588
|
}
|
|
9497
9589
|
function getFilterName(filter) {
|
|
9498
9590
|
return filter?.attributeDescription?.name || "";
|
|
@@ -10047,7 +10139,7 @@ function GridToolbar(rawProps) {
|
|
|
10047
10139
|
return badges;
|
|
10048
10140
|
}
|
|
10049
10141
|
function isPriceSortDisabled() {
|
|
10050
|
-
return isContentHidden(props.portalMode, props.user);
|
|
10142
|
+
return isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
10051
10143
|
}
|
|
10052
10144
|
function getAvailabilityLabel() {
|
|
10053
10145
|
const qty = props.minStock;
|
|
@@ -10449,13 +10541,14 @@ function MachineGrid(rawProps) {
|
|
|
10449
10541
|
// node query threads through useSpareParts.
|
|
10450
10542
|
imageVariantFilters: configuration?.imageVariantFiltersMedium
|
|
10451
10543
|
});
|
|
10452
|
-
const { displayParts, childMachines, isLoading: partsLoading, currentPage, totalPages } = useSpareParts({
|
|
10544
|
+
const { displayParts, childMachines, isLoading: partsLoading, currentPage, totalPages, notFound } = useSpareParts({
|
|
10453
10545
|
graphqlClient: props.graphqlClient,
|
|
10454
10546
|
// Idle at the root (no slug).
|
|
10455
10547
|
slug: isRoot ? void 0 : currentSlug,
|
|
10456
10548
|
term: term || void 0,
|
|
10457
10549
|
language,
|
|
10458
10550
|
machineLanguage,
|
|
10551
|
+
machineLanguages: rawProps.machineLanguages,
|
|
10459
10552
|
taxZone: props.taxZone,
|
|
10460
10553
|
user: props.user,
|
|
10461
10554
|
companyId: props.companyId,
|
|
@@ -10479,6 +10572,7 @@ function MachineGrid(rawProps) {
|
|
|
10479
10572
|
onMachineChange: setMachine
|
|
10480
10573
|
});
|
|
10481
10574
|
const machineName = machine ? getLocalizedValue(machine.name, machineLanguage) : slugToLabel(currentSlug);
|
|
10575
|
+
const machineLabel = (key, fallback) => rawProps.machineCardLabels?.[key] ?? rawProps.toolbarLabels?.[key] ?? fallback;
|
|
10482
10576
|
const partProducts = useMemo(
|
|
10483
10577
|
() => displayParts.map((p) => p.product).filter(Boolean),
|
|
10484
10578
|
[displayParts]
|
|
@@ -10553,6 +10647,12 @@ function MachineGrid(rawProps) {
|
|
|
10553
10647
|
] });
|
|
10554
10648
|
}
|
|
10555
10649
|
const hasParts = itemsFound > 0 || partProducts.length > 0;
|
|
10650
|
+
if (notFound && !partsLoading) {
|
|
10651
|
+
return /* @__PURE__ */ jsxs("div", { className: rawProps.className, children: [
|
|
10652
|
+
/* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "propeller-breadcrumbs mb-6", children: /* @__PURE__ */ jsx("ol", { className: "flex flex-wrap items-center gap-2 text-sm text-foreground-subtle", children: /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: basePath, className: "hover:text-primary", children: rawProps.rootTitle ?? "Machines" }) }) }) }),
|
|
10653
|
+
/* @__PURE__ */ jsx("p", { className: "py-12 text-center text-foreground-subtle", children: machineLabel("machineNotFound", "This machine could not be found.") })
|
|
10654
|
+
] });
|
|
10655
|
+
}
|
|
10556
10656
|
return /* @__PURE__ */ jsxs("div", { className: rawProps.className, children: [
|
|
10557
10657
|
/* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "propeller-breadcrumbs mb-6", children: /* @__PURE__ */ jsxs("ol", { className: "flex flex-wrap items-center gap-2 text-sm text-foreground-subtle", children: [
|
|
10558
10658
|
/* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: basePath, className: "hover:text-primary", children: rawProps.rootTitle ?? "Machines" }) }),
|
|
@@ -10605,7 +10705,9 @@ function MachineGrid(rawProps) {
|
|
|
10605
10705
|
{
|
|
10606
10706
|
defaultValue: term,
|
|
10607
10707
|
onSubmit: submitSearch,
|
|
10608
|
-
|
|
10708
|
+
searchLabel: machineLabel("searchParts", "Search parts\u2026"),
|
|
10709
|
+
searchAriaLabel: machineLabel("searchParts", "Search parts"),
|
|
10710
|
+
buttonLabel: getLabel(rawProps.toolbarLabels, "search", "Search")
|
|
10609
10711
|
},
|
|
10610
10712
|
term
|
|
10611
10713
|
),
|
|
@@ -10656,7 +10758,7 @@ function MachineGrid(rawProps) {
|
|
|
10656
10758
|
const qty = quantityBySku.get(product.sku);
|
|
10657
10759
|
if (!qty) return null;
|
|
10658
10760
|
return /* @__PURE__ */ jsxs("span", { className: "propeller-spare-part__quantity text-sm text-foreground-subtle", children: [
|
|
10659
|
-
|
|
10761
|
+
machineLabel("quantityInMachine", "Qty in machine"),
|
|
10660
10762
|
": ",
|
|
10661
10763
|
qty
|
|
10662
10764
|
] });
|
|
@@ -10688,8 +10790,8 @@ function MachinePartsSearch(props) {
|
|
|
10688
10790
|
onKeyDown: (e) => {
|
|
10689
10791
|
if (e.key === "Enter") submit();
|
|
10690
10792
|
},
|
|
10691
|
-
placeholder: props.
|
|
10692
|
-
"aria-label": props.
|
|
10793
|
+
placeholder: props.searchLabel,
|
|
10794
|
+
"aria-label": props.searchAriaLabel,
|
|
10693
10795
|
className: "w-full rounded border border-border bg-background px-3 py-2"
|
|
10694
10796
|
}
|
|
10695
10797
|
),
|
|
@@ -10699,7 +10801,7 @@ function MachinePartsSearch(props) {
|
|
|
10699
10801
|
type: "button",
|
|
10700
10802
|
onClick: submit,
|
|
10701
10803
|
className: "rounded bg-primary px-4 py-2 text-primary-foreground",
|
|
10702
|
-
children: props.
|
|
10804
|
+
children: props.buttonLabel
|
|
10703
10805
|
}
|
|
10704
10806
|
)
|
|
10705
10807
|
] });
|
|
@@ -10900,7 +11002,7 @@ function ClusterOptions(rawProps) {
|
|
|
10900
11002
|
const language = props.language;
|
|
10901
11003
|
const options = props.options || [];
|
|
10902
11004
|
const sel = selectedProductIds;
|
|
10903
|
-
const hidePrices = isContentHidden(props.portalMode, props.user);
|
|
11005
|
+
const hidePrices = isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
10904
11006
|
return options.filter((option) => option.hidden !== YesNo.Y).map((option) => {
|
|
10905
11007
|
const idStr = option.id.toString();
|
|
10906
11008
|
const selectedProductId = sel[idStr] || "";
|
|
@@ -11084,7 +11186,11 @@ function CompanySwitcher(props) {
|
|
|
11084
11186
|
type: "button",
|
|
11085
11187
|
"aria-haspopup": "listbox",
|
|
11086
11188
|
"aria-label": getLabel(props.labels, "switchCompanyAriaLabel", "Switch company"),
|
|
11087
|
-
className:
|
|
11189
|
+
className: cn(
|
|
11190
|
+
// `text-inherit`: this sits in the host's header, which may be dark or
|
|
11191
|
+
// light. See the note on AccountIconAndMenu's trigger.
|
|
11192
|
+
`propeller-company-switcher__trigger flex items-center gap-2 rounded-md px-3 py-1.5 text-sm font-medium transition-colors text-inherit${props.triggerClassName ? " " + props.triggerClassName : ""}`
|
|
11193
|
+
),
|
|
11088
11194
|
onClick: (event) => toggleDropdown(),
|
|
11089
11195
|
"aria-expanded": isOpen,
|
|
11090
11196
|
children: [
|
|
@@ -15059,7 +15165,7 @@ function PriceToggle(props) {
|
|
|
15059
15165
|
var PriceToggle_default = PriceToggle;
|
|
15060
15166
|
function ProductBulkPrices(props) {
|
|
15061
15167
|
const includeTax = !!props.includeTax;
|
|
15062
|
-
const isHidden2 = isContentHidden(props.portalMode, props.user);
|
|
15168
|
+
const isHidden2 = isContentHidden(props.portalMode, props.user, props.isAuthenticated);
|
|
15063
15169
|
function getTierQuantity(tier) {
|
|
15064
15170
|
const discount = tier.discount;
|
|
15065
15171
|
return discount?.quantityFrom ?? tier.quantity ?? null;
|
|
@@ -15606,14 +15712,10 @@ function ProductDownloads(props) {
|
|
|
15606
15712
|
const hasItems = items.length > 0;
|
|
15607
15713
|
const lang = props.language || "NL";
|
|
15608
15714
|
function getDocumentUrl(doc) {
|
|
15609
|
-
|
|
15610
|
-
const match = docs.find((d) => d.language === lang);
|
|
15611
|
-
return match?.originalUrl || docs?.[0]?.originalUrl || "";
|
|
15715
|
+
return resolveLanguageEntry(doc.documents, lang)?.originalUrl || "";
|
|
15612
15716
|
}
|
|
15613
15717
|
function getDocumentName(doc) {
|
|
15614
|
-
|
|
15615
|
-
const match = alts.find((a) => a.language === lang);
|
|
15616
|
-
return match?.value || alts?.[0]?.value || "Download";
|
|
15718
|
+
return getLanguageString(doc.alt, lang, "Download");
|
|
15617
15719
|
}
|
|
15618
15720
|
return /* @__PURE__ */ jsxs("div", { className: cn(`propeller-product-downloads ${props.className || ""}`), children: [
|
|
15619
15721
|
hasItems ? /* @__PURE__ */ jsx("h3", { className: "propeller-product-downloads__title text-base font-semibold text-foreground mb-3", children: getLabel(props.labels, "title", "Downloads") }) : null,
|
|
@@ -15819,12 +15921,14 @@ function ProductGallery(props) {
|
|
|
15819
15921
|
var ProductGallery_default = ProductGallery;
|
|
15820
15922
|
function pickImageUrl(mediaItems, target) {
|
|
15821
15923
|
if (!mediaItems || mediaItems.length === 0) return null;
|
|
15924
|
+
const targetUpper = (target || "").toUpperCase();
|
|
15925
|
+
const langMatches = (value) => (value || "").toUpperCase() === targetUpper;
|
|
15822
15926
|
for (const m of mediaItems) {
|
|
15823
|
-
const match = m.imageVariants?.find((v) => v.language
|
|
15927
|
+
const match = m.imageVariants?.find((v) => langMatches(v.language) && v.url);
|
|
15824
15928
|
if (match?.url) return match.url;
|
|
15825
15929
|
}
|
|
15826
15930
|
for (const m of mediaItems) {
|
|
15827
|
-
const match = m.images?.find((i) => i.language
|
|
15931
|
+
const match = m.images?.find((i) => langMatches(i.language) && i.originalUrl);
|
|
15828
15932
|
if (match?.originalUrl) return match.originalUrl;
|
|
15829
15933
|
}
|
|
15830
15934
|
for (const m of mediaItems) {
|
|
@@ -16152,6 +16256,7 @@ function ProductInfoPrice(props = {}) {
|
|
|
16152
16256
|
currency: derived.currency,
|
|
16153
16257
|
taxZone: derived.taxZone,
|
|
16154
16258
|
portalMode: derived.portalMode,
|
|
16259
|
+
isAuthenticated: resolved.isAuthenticated,
|
|
16155
16260
|
user: derived.user,
|
|
16156
16261
|
labels: derived.labels,
|
|
16157
16262
|
className: props.className
|
|
@@ -16161,7 +16266,7 @@ function ProductInfoPrice(props = {}) {
|
|
|
16161
16266
|
function ProductInfoStock(props = {}) {
|
|
16162
16267
|
const { product, resolved, derived } = useProductInfoContext();
|
|
16163
16268
|
if (!product.inventory) return null;
|
|
16164
|
-
if (isContentHidden(derived.portalMode, resolved.user)) return null;
|
|
16269
|
+
if (isContentHidden(derived.portalMode, resolved.user, resolved.isAuthenticated)) return null;
|
|
16165
16270
|
const Injected = resolved.stockComponent;
|
|
16166
16271
|
if (Injected) {
|
|
16167
16272
|
return /* @__PURE__ */ jsx(
|
|
@@ -16188,7 +16293,7 @@ function ProductInfoStock(props = {}) {
|
|
|
16188
16293
|
}
|
|
16189
16294
|
function ProductInfoAddToCart(props = {}) {
|
|
16190
16295
|
const { product, resolved, derived } = useProductInfoContext();
|
|
16191
|
-
if (isContentHidden(derived.portalMode, resolved.user)) {
|
|
16296
|
+
if (isContentHidden(derived.portalMode, resolved.user, resolved.isAuthenticated)) {
|
|
16192
16297
|
return /* @__PURE__ */ jsx(
|
|
16193
16298
|
LoginToOrderButton_default,
|
|
16194
16299
|
{
|
|
@@ -16200,7 +16305,18 @@ function ProductInfoAddToCart(props = {}) {
|
|
|
16200
16305
|
}
|
|
16201
16306
|
const Injected = resolved.addToCartComponent;
|
|
16202
16307
|
if (Injected) {
|
|
16203
|
-
return /* @__PURE__ */ jsx(
|
|
16308
|
+
return /* @__PURE__ */ jsx(
|
|
16309
|
+
Injected,
|
|
16310
|
+
{
|
|
16311
|
+
product,
|
|
16312
|
+
cartId: resolved.cartId,
|
|
16313
|
+
createCart: resolved.createCart,
|
|
16314
|
+
onCartCreated: resolved.onCartCreated,
|
|
16315
|
+
includeTax: derived.useTax,
|
|
16316
|
+
labels: derived.labels,
|
|
16317
|
+
className: props.className
|
|
16318
|
+
}
|
|
16319
|
+
);
|
|
16204
16320
|
}
|
|
16205
16321
|
return /* @__PURE__ */ jsx(
|
|
16206
16322
|
AddToCart_default,
|
|
@@ -16209,6 +16325,9 @@ function ProductInfoAddToCart(props = {}) {
|
|
|
16209
16325
|
user: derived.user,
|
|
16210
16326
|
currency: derived.currency,
|
|
16211
16327
|
product,
|
|
16328
|
+
cartId: resolved.cartId,
|
|
16329
|
+
createCart: resolved.createCart,
|
|
16330
|
+
onCartCreated: resolved.onCartCreated,
|
|
16212
16331
|
configuration: resolved.configuration,
|
|
16213
16332
|
companyId: resolved.companyId,
|
|
16214
16333
|
includeTax: derived.useTax,
|
|
@@ -16262,6 +16381,7 @@ function ProductInfoBulkPrices(props = {}) {
|
|
|
16262
16381
|
bulkPrices: product.bulkPrices,
|
|
16263
16382
|
includeTax: derived.useTax,
|
|
16264
16383
|
portalMode: derived.portalMode,
|
|
16384
|
+
isAuthenticated: resolved.isAuthenticated,
|
|
16265
16385
|
user: derived.user,
|
|
16266
16386
|
taxZone: derived.taxZone,
|
|
16267
16387
|
currency: derived.currency,
|
|
@@ -16424,7 +16544,7 @@ function ProductSlider(rawProps) {
|
|
|
16424
16544
|
}
|
|
16425
16545
|
function showAddToCart() {
|
|
16426
16546
|
const allow = props.allowAddToCart !== false;
|
|
16427
|
-
return !isContentHidden(props.portalMode, props.user) && allow;
|
|
16547
|
+
return !isContentHidden(props.portalMode, props.user, props.isAuthenticated) && allow;
|
|
16428
16548
|
}
|
|
16429
16549
|
function isCluster(item) {
|
|
16430
16550
|
return "clusterId" in item && !("productId" in item);
|
|
@@ -16728,14 +16848,10 @@ function ProductVideos(props) {
|
|
|
16728
16848
|
const hasItems = items.length > 0;
|
|
16729
16849
|
const lang = props.language || "NL";
|
|
16730
16850
|
function getVideoUri(video) {
|
|
16731
|
-
|
|
16732
|
-
const match = vids.find((v) => v.language === lang);
|
|
16733
|
-
return match?.uri || vids?.[0]?.uri || "";
|
|
16851
|
+
return getLanguageUri(video.videos, lang, "");
|
|
16734
16852
|
}
|
|
16735
16853
|
function getVideoTitle(video) {
|
|
16736
|
-
|
|
16737
|
-
const match = alts.find((a) => a.language === lang);
|
|
16738
|
-
return match?.value || alts?.[0]?.value || "Video";
|
|
16854
|
+
return getLanguageString(video.alt, lang, "Video");
|
|
16739
16855
|
}
|
|
16740
16856
|
function isEmbeddable(uri) {
|
|
16741
16857
|
return uri.includes("youtube.com") || uri.includes("youtu.be") || uri.includes("vimeo.com");
|