@propeller-commerce/propeller-v2-react-ui 0.26.1 → 0.28.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.js CHANGED
@@ -2,7 +2,7 @@
2
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, useEffect, useMemo, useContext, useSyncExternalStore } from 'react';
5
+ import { createContext, useState, useContext, useRef, useCallback, useEffect, useMemo, useSyncExternalStore } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
  import { ProductStatus, ProductSortField, SortOrder, CrossupsellType, PriceDisplay, 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';
@@ -21,6 +21,9 @@ function PropellerProvider({ value, children }) {
21
21
  function usePropellerDeps() {
22
22
  return useContext(PropellerDepsContext);
23
23
  }
24
+ function useImgComponent() {
25
+ return useContext(PropellerDepsContext)?.imgComponent;
26
+ }
24
27
  function useRequiredPropellerDeps() {
25
28
  const deps = useContext(PropellerDepsContext);
26
29
  if (!deps) {
@@ -2614,6 +2617,7 @@ function toMatch(item, language) {
2614
2617
  const netPrice = displayItem?.price?.net ?? 0;
2615
2618
  const grossPrice = displayItem?.price?.gross ?? 0;
2616
2619
  const minQuantity = Math.max(1, displayItem?.minimumQuantity ?? 1);
2620
+ const step = Math.max(1, displayItem?.unit ?? 1);
2617
2621
  const imageUrl = isCluster ? getClusterImageUrl(item) : getProductImageUrl(item);
2618
2622
  return {
2619
2623
  productId,
@@ -2623,6 +2627,7 @@ function toMatch(item, language) {
2623
2627
  netPrice,
2624
2628
  grossPrice,
2625
2629
  minQuantity,
2630
+ step,
2626
2631
  imageUrl,
2627
2632
  priceOnRequest: isPriceOnRequest(item)
2628
2633
  };
@@ -4674,8 +4679,25 @@ function ActionCode(rawProps) {
4674
4679
  ] });
4675
4680
  }
4676
4681
  var ActionCode_default = ActionCode;
4682
+ function PropellerImg({ as: Injected, ...props }) {
4683
+ if (Injected) return /* @__PURE__ */ jsx(Injected, { ...props });
4684
+ const { src, alt, className, width, height, loading, onClick } = props;
4685
+ return /* @__PURE__ */ jsx(
4686
+ "img",
4687
+ {
4688
+ src,
4689
+ alt,
4690
+ className,
4691
+ width,
4692
+ height,
4693
+ loading,
4694
+ onClick
4695
+ }
4696
+ );
4697
+ }
4677
4698
  function CartBonusItems(rawProps) {
4678
4699
  const props = useInfraProps(rawProps);
4700
+ const Img = useImgComponent();
4679
4701
  const items = props.bonusItems ?? props.cart?.bonusItems ?? [];
4680
4702
  if (items.length === 0) return null;
4681
4703
  const currency = props.currency ?? "\u20AC";
@@ -4693,20 +4715,21 @@ function CartBonusItems(rawProps) {
4693
4715
  {
4694
4716
  className: "propeller-cart-bonus-item flex items-center gap-4 bg-card p-4 rounded-container shadow-sm border border-border",
4695
4717
  children: [
4696
- /* @__PURE__ */ jsx("div", { className: "propeller-cart-bonus-item__media w-20 h-20 flex-shrink-0 bg-surface-hover rounded-control overflow-hidden flex items-center justify-center", children: img ? /* @__PURE__ */ jsx("img", { className: "propeller-cart-bonus-item__image w-full h-full object-contain p-1", src: img, alt: name }) : /* @__PURE__ */ jsx(
4718
+ /* @__PURE__ */ jsx("div", { className: "propeller-cart-bonus-item__media w-20 h-20 flex-shrink-0 bg-surface-hover rounded-control overflow-hidden flex items-center justify-center", children: img ? /* @__PURE__ */ jsx(PropellerImg, { as: Img, className: "propeller-cart-bonus-item__image w-full h-full object-contain p-1", src: img, alt: name, loading: "lazy" }) : /* @__PURE__ */ jsx(
4697
4719
  "svg",
4698
4720
  {
4721
+ "aria-hidden": "true",
4699
4722
  fill: "none",
4700
4723
  viewBox: "0 0 24 24",
4701
4724
  stroke: "currentColor",
4702
- className: "propeller-cart-bonus-item__image-placeholder w-8 h-8 text-foreground-subtle",
4703
- strokeWidth: 1.5,
4725
+ className: "propeller-cart-bonus-item__image-placeholder w-10 h-10 text-foreground-subtle",
4726
+ strokeWidth: 1,
4704
4727
  children: /* @__PURE__ */ jsx(
4705
4728
  "path",
4706
4729
  {
4707
4730
  strokeLinecap: "round",
4708
4731
  strokeLinejoin: "round",
4709
- d: "M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0022.5 18.75V5.25A2.25 2.25 0 0020.25 3H3.75A2.25 2.25 0 001.5 5.25v13.5A2.25 2.25 0 003.75 21z"
4732
+ d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
4710
4733
  }
4711
4734
  )
4712
4735
  }
@@ -4751,6 +4774,7 @@ function mergeGrouped(p) {
4751
4774
  }
4752
4775
  function AddToCart(rawProps) {
4753
4776
  const props = mergeGrouped(useInfraProps(rawProps));
4777
+ const Img = useImgComponent();
4754
4778
  const { cart, loading, checkoutAllowed, addItem: addItem2, getMinQuantity, getStep } = useCart({
4755
4779
  graphqlClient: props.graphqlClient,
4756
4780
  user: props.user ?? null,
@@ -4759,6 +4783,7 @@ function AddToCart(rawProps) {
4759
4783
  onCartCreated: props.onCartCreated
4760
4784
  });
4761
4785
  const [quantity, setQuantity] = useState(() => getMinQuantity(props.product));
4786
+ const [quantityDraft, setQuantityDraft] = useState(null);
4762
4787
  const [toastMessage, setToastMessage] = useState(() => "");
4763
4788
  const [toastType, setToastType] = useState(() => "");
4764
4789
  const [toastVisible, setToastVisible] = useState(() => false);
@@ -4781,16 +4806,42 @@ function AddToCart(rawProps) {
4781
4806
  function dismissToast() {
4782
4807
  setToastVisible(false);
4783
4808
  }
4809
+ function snapQuantity(value) {
4810
+ const min = getMinQuantity(props.product);
4811
+ const step = getStep(props.product);
4812
+ if (value <= min) return min;
4813
+ return Math.round((value - min) / step) * step + min;
4814
+ }
4784
4815
  function increment() {
4785
- setQuantity(quantity + getStep(props.product));
4816
+ setQuantityDraft(null);
4817
+ const snapped = snapQuantity(quantity);
4818
+ setQuantity(snapped === quantity ? quantity + getStep(props.product) : snapped);
4786
4819
  }
4787
4820
  function decrement() {
4788
4821
  const min = getMinQuantity(props.product);
4789
4822
  const step = getStep(props.product);
4823
+ setQuantityDraft(null);
4824
+ const snapped = snapQuantity(quantity);
4825
+ if (snapped !== quantity) {
4826
+ setQuantity(snapped);
4827
+ return;
4828
+ }
4790
4829
  if (quantity - step >= min) {
4791
4830
  setQuantity(quantity - step);
4792
4831
  }
4793
4832
  }
4833
+ function handleQuantityInput(raw) {
4834
+ setQuantityDraft(raw);
4835
+ const val = parseInt(raw, 10);
4836
+ if (!isNaN(val) && val >= getMinQuantity(props.product)) {
4837
+ setQuantity(snapQuantity(val));
4838
+ }
4839
+ }
4840
+ function handleQuantityBlur() {
4841
+ const val = parseInt(quantityDraft ?? "", 10);
4842
+ setQuantity(isNaN(val) ? getMinQuantity(props.product) : snapQuantity(val));
4843
+ setQuantityDraft(null);
4844
+ }
4794
4845
  function getModalImageUrl() {
4795
4846
  if (addedCartItem) {
4796
4847
  const img = addedCartItem.product?.media?.images?.items?.[0]?.imageVariants?.[0]?.url;
@@ -4920,15 +4971,9 @@ function AddToCart(rawProps) {
4920
4971
  className: "propeller-add-to-cart__quantity flex-1 md:flex-none md:w-12 text-center text-sm bg-transparent border-none focus:ring-0 focus:outline-none h-full [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
4921
4972
  min: getMinQuantity(props.product),
4922
4973
  step: getStep(props.product),
4923
- value: quantity,
4924
- onChange: (e) => {
4925
- const val = parseInt(e.target.value, 10);
4926
- const min = getMinQuantity(props.product);
4927
- const step = getStep(props.product);
4928
- if (!isNaN(val) && val >= min) {
4929
- setQuantity(Math.round((val - min) / step) * step + min);
4930
- }
4931
- }
4974
+ value: quantityDraft ?? quantity,
4975
+ onChange: (e) => handleQuantityInput(e.target.value),
4976
+ onBlur: handleQuantityBlur
4932
4977
  }
4933
4978
  ),
4934
4979
  /* @__PURE__ */ jsxs(
@@ -4953,15 +4998,9 @@ function AddToCart(rawProps) {
4953
4998
  className: "propeller-add-to-cart__quantity w-full md:w-16 h-10 text-center text-sm border border-input rounded-control focus:ring-2 focus:ring-secondary focus:border-transparent [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
4954
4999
  min: getMinQuantity(props.product),
4955
5000
  step: getStep(props.product),
4956
- value: quantity,
4957
- onChange: (e) => {
4958
- const val = parseInt(e.target.value, 10);
4959
- const min = getMinQuantity(props.product);
4960
- const step = getStep(props.product);
4961
- if (!isNaN(val) && val >= min) {
4962
- setQuantity(Math.round((val - min) / step) * step + min);
4963
- }
4964
- }
5001
+ value: quantityDraft ?? quantity,
5002
+ onChange: (e) => handleQuantityInput(e.target.value),
5003
+ onBlur: handleQuantityBlur
4965
5004
  }
4966
5005
  ) : null,
4967
5006
  /* @__PURE__ */ jsxs(
@@ -5092,27 +5131,30 @@ function AddToCart(rawProps) {
5092
5131
  /* @__PURE__ */ jsxs("div", { className: "propeller-add-to-cart__modal-body px-6 py-5", children: [
5093
5132
  /* @__PURE__ */ jsxs("div", { className: "propeller-add-to-cart__modal-product flex items-start gap-4", children: [
5094
5133
  !!getModalImageUrl() ? /* @__PURE__ */ jsx(
5095
- "img",
5134
+ PropellerImg,
5096
5135
  {
5136
+ as: Img,
5097
5137
  className: "propeller-add-to-cart__modal-image w-16 h-16 object-contain rounded border border-border-subtle flex-shrink-0",
5098
5138
  src: getModalImageUrl(),
5099
- alt: getModalName()
5139
+ alt: getModalName(),
5140
+ loading: "lazy"
5100
5141
  }
5101
5142
  ) : null,
5102
5143
  !getModalImageUrl() ? /* @__PURE__ */ jsx("div", { className: "propeller-add-to-cart__modal-image-placeholder w-16 h-16 flex items-center justify-center rounded border border-border-subtle flex-shrink-0 bg-surface-hover", children: /* @__PURE__ */ jsx(
5103
5144
  "svg",
5104
5145
  {
5146
+ "aria-hidden": "true",
5105
5147
  fill: "none",
5106
5148
  viewBox: "0 0 24 24",
5107
5149
  stroke: "currentColor",
5108
5150
  className: "w-8 h-8 text-foreground-subtle",
5109
- strokeWidth: 1.5,
5151
+ strokeWidth: 1,
5110
5152
  children: /* @__PURE__ */ jsx(
5111
5153
  "path",
5112
5154
  {
5113
5155
  strokeLinecap: "round",
5114
5156
  strokeLinejoin: "round",
5115
- d: "M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0022.5 18.75V5.25A2.25 2.25 0 0020.25 3H3.75A2.25 2.25 0 001.5 5.25v13.5A2.25 2.25 0 003.75 21z"
5157
+ d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
5116
5158
  }
5117
5159
  )
5118
5160
  }
@@ -7172,29 +7214,33 @@ function CartItem(rawProps) {
7172
7214
  }
7173
7215
  function CartItemImage(props = {}) {
7174
7216
  const { derived } = useCartItemContext();
7217
+ const Img = useImgComponent();
7175
7218
  return /* @__PURE__ */ jsxs("div", { className: props.className ?? "propeller-cart-item__media w-20 h-20 md:w-24 md:h-24 flex-shrink-0 bg-surface-hover flex items-center justify-center overflow-hidden relative rounded-control", children: [
7176
7219
  !!derived.imageUrl ? /* @__PURE__ */ jsx(
7177
- "img",
7220
+ PropellerImg,
7178
7221
  {
7222
+ as: Img,
7179
7223
  className: "propeller-cart-item__image w-full h-full object-contain p-1",
7180
7224
  src: derived.imageUrl,
7181
- alt: derived.name
7225
+ alt: derived.name,
7226
+ loading: "lazy"
7182
7227
  }
7183
7228
  ) : null,
7184
7229
  !derived.imageUrl ? /* @__PURE__ */ jsx(
7185
7230
  "svg",
7186
7231
  {
7232
+ "aria-hidden": "true",
7187
7233
  fill: "none",
7188
7234
  viewBox: "0 0 24 24",
7189
7235
  stroke: "currentColor",
7190
- className: "propeller-cart-item__image-placeholder w-8 h-8 text-foreground-subtle",
7191
- strokeWidth: 1.5,
7236
+ className: "propeller-cart-item__image-placeholder w-10 h-10 md:w-12 md:h-12 text-foreground-subtle",
7237
+ strokeWidth: 1,
7192
7238
  children: /* @__PURE__ */ jsx(
7193
7239
  "path",
7194
7240
  {
7195
7241
  strokeLinecap: "round",
7196
7242
  strokeLinejoin: "round",
7197
- d: "M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0022.5 18.75V5.25A2.25 2.25 0 0020.25 3H3.75A2.25 2.25 0 001.5 5.25v13.5A2.25 2.25 0 003.75 21z"
7243
+ d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
7198
7244
  }
7199
7245
  )
7200
7246
  }
@@ -7315,6 +7361,7 @@ function CartItemNotes(props = {}) {
7315
7361
  }
7316
7362
  function CartItemCrossupsells(props = {}) {
7317
7363
  const { resolved, state, helpers, handlers } = useCartItemContext();
7364
+ const Img = useImgComponent();
7318
7365
  if (state.visibleCrossupsells.length === 0) return null;
7319
7366
  return /* @__PURE__ */ jsxs("div", { className: props.className ?? "propeller-cart-item__crossupsells mt-3 pt-3 border-t border-border", children: [
7320
7367
  /* @__PURE__ */ jsx("p", { className: "propeller-cart-item__crossupsells-label text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2", children: getLabel(resolved.labels, "crossupsellTitle", "You might also like") }),
@@ -7331,11 +7378,13 @@ function CartItemCrossupsells(props = {}) {
7331
7378
  onClick: (e) => handlers.onCrossupsellClick(item, e),
7332
7379
  children: [
7333
7380
  !!helpers.getCrossupsellImageUrl(item) ? /* @__PURE__ */ jsx(
7334
- "img",
7381
+ PropellerImg,
7335
7382
  {
7383
+ as: Img,
7336
7384
  className: "propeller-cart-item__crossupsell-image w-10 h-10 object-contain rounded flex-shrink-0",
7337
7385
  src: helpers.getCrossupsellImageUrl(item),
7338
- alt: helpers.getCrossupsellName(item)
7386
+ alt: helpers.getCrossupsellName(item),
7387
+ loading: "lazy"
7339
7388
  }
7340
7389
  ) : null,
7341
7390
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
@@ -7764,7 +7813,7 @@ function CartIconAndSidebar(rawProps) {
7764
7813
  includeTax: useTax,
7765
7814
  className: "propeller-cart-icon__item",
7766
7815
  children: [
7767
- /* @__PURE__ */ jsx(CartItem_default.Image, { className: "w-20 h-20 flex-shrink-0 bg-surface-hover rounded-control overflow-hidden border border-border-subtle" }),
7816
+ /* @__PURE__ */ jsx(CartItem_default.Image, { className: "w-20 h-20 flex-shrink-0 bg-surface-hover rounded-control overflow-hidden border border-border-subtle flex items-center justify-center relative" }),
7768
7817
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex flex-col justify-between py-1", children: [
7769
7818
  /* @__PURE__ */ jsxs("div", { children: [
7770
7819
  /* @__PURE__ */ jsx(CartItem_default.Title, { className: "propeller-cart-icon__item-name text-sm font-medium hover:text-primary line-clamp-2" }),
@@ -8531,6 +8580,7 @@ function ClusterCardImage(props) {
8531
8580
  const showFavorite = props.showFavorite ?? !!resolved.enableAddFavorite;
8532
8581
  const isRow = derived.isRow;
8533
8582
  const InjectedImage = resolved.imageComponent;
8583
+ const Img = useImgComponent();
8534
8584
  if (InjectedImage) {
8535
8585
  return /* @__PURE__ */ jsx(
8536
8586
  InjectedImage,
@@ -8549,13 +8599,15 @@ function ClusterCardImage(props) {
8549
8599
  className: props.className ?? `propeller-cluster-card__media relative overflow-hidden bg-surface-hover ${isRow ? "w-20 h-20 flex-shrink-0 p-2" : "aspect-[4/3] sm:aspect-square p-2 sm:p-4"}`,
8550
8600
  children: [
8551
8601
  /* @__PURE__ */ jsx("a", { className: "block h-full w-full", href: derived.clusterUrl, onClick: handleClusterClick, children: derived.imageUrl ? /* @__PURE__ */ jsx(
8552
- "img",
8602
+ PropellerImg,
8553
8603
  {
8604
+ as: Img,
8554
8605
  className: "propeller-cluster-card__image h-full w-full object-contain transition-transform duration-300 group-hover:scale-105",
8555
8606
  src: derived.imageUrl,
8556
- alt: derived.name
8607
+ alt: derived.name,
8608
+ loading: "lazy"
8557
8609
  }
8558
- ) : /* @__PURE__ */ jsx("div", { className: "propeller-cluster-card__image-placeholder flex h-full w-full items-center justify-center text-foreground-subtle", children: /* @__PURE__ */ jsx("svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "h-16 w-16", children: /* @__PURE__ */ jsx(
8610
+ ) : /* @__PURE__ */ jsx("div", { className: "propeller-cluster-card__image-placeholder flex h-full w-full items-center justify-center text-foreground-subtle", children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "h-16 w-16", children: /* @__PURE__ */ jsx(
8559
8611
  "path",
8560
8612
  {
8561
8613
  strokeLinecap: "round",
@@ -8773,6 +8825,7 @@ function getMachineImageUrl(machine) {
8773
8825
  }
8774
8826
  function MachineCard(props) {
8775
8827
  const { machine, href, language } = props;
8828
+ const Img = useImgComponent();
8776
8829
  const Wrapper = href ? "a" : "div";
8777
8830
  const showImage = props.showImage ?? true;
8778
8831
  const showDescription = props.showDescription ?? false;
@@ -8791,8 +8844,9 @@ function MachineCard(props) {
8791
8844
  className: "flex h-full flex-col focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
8792
8845
  children: [
8793
8846
  showImage && /* @__PURE__ */ jsx("div", { className: "propeller-machine-card__image aspect-square w-full overflow-hidden bg-background-subtle", children: imageUrl ? /* @__PURE__ */ jsx(
8794
- "img",
8847
+ PropellerImg,
8795
8848
  {
8849
+ as: Img,
8796
8850
  src: imageUrl,
8797
8851
  alt: name,
8798
8852
  loading: "lazy",
@@ -8809,6 +8863,7 @@ function MachineCard(props) {
8809
8863
  children: /* @__PURE__ */ jsx(
8810
8864
  "svg",
8811
8865
  {
8866
+ "aria-hidden": "true",
8812
8867
  className: "h-12 w-12",
8813
8868
  fill: "none",
8814
8869
  stroke: "currentColor",
@@ -9113,6 +9168,7 @@ function ProductCardImage(props) {
9113
9168
  const showFavorite = props.showFavorite ?? !!resolved.enableAddFavorite;
9114
9169
  const isRow = derived.isRow;
9115
9170
  const InjectedImage = resolved.imageComponent;
9171
+ const Img = useImgComponent();
9116
9172
  if (InjectedImage) {
9117
9173
  return /* @__PURE__ */ jsx(
9118
9174
  InjectedImage,
@@ -9131,13 +9187,15 @@ function ProductCardImage(props) {
9131
9187
  className: props.className ?? `propeller-product-card__media relative overflow-hidden bg-surface-hover ${isRow ? "w-20 h-20 flex-shrink-0 p-2" : "aspect-[4/3] sm:aspect-square p-2 sm:p-4"}`,
9132
9188
  children: [
9133
9189
  /* @__PURE__ */ jsx("a", { className: "block h-full w-full", href: derived.productUrl, onClick: handleProductClick, children: derived.imageUrl ? /* @__PURE__ */ jsx(
9134
- "img",
9190
+ PropellerImg,
9135
9191
  {
9192
+ as: Img,
9136
9193
  className: "propeller-product-card__image h-full w-full object-contain transition-transform duration-300 group-hover:scale-105",
9137
9194
  src: derived.imageUrl,
9138
- alt: derived.name
9195
+ alt: derived.name,
9196
+ loading: "lazy"
9139
9197
  }
9140
- ) : /* @__PURE__ */ jsx("div", { className: "propeller-product-card__image-placeholder flex h-full w-full items-center justify-center text-foreground-subtle", children: /* @__PURE__ */ jsx("svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "h-16 w-16", children: /* @__PURE__ */ jsx(
9198
+ ) : /* @__PURE__ */ jsx("div", { className: "propeller-product-card__image-placeholder flex h-full w-full items-center justify-center text-foreground-subtle", children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "h-16 w-16", children: /* @__PURE__ */ jsx(
9141
9199
  "path",
9142
9200
  {
9143
9201
  strokeLinecap: "round",
@@ -10992,6 +11050,7 @@ function MachinePartsSearch(props) {
10992
11050
  ] });
10993
11051
  }
10994
11052
  function ClusterConfigurator(props) {
11053
+ const Img = useImgComponent();
10995
11054
  const { settingsWithValues, handleAttributeSelect, initFromProduct } = useClusterConfigurator({
10996
11055
  products: props.products,
10997
11056
  config: props.config,
@@ -11082,7 +11141,7 @@ function ClusterConfigurator(props) {
11082
11141
  "data-selected": setting.selectedValue === val ? "true" : "false",
11083
11142
  className: `propeller-cluster-configurator__image-swatch relative w-16 h-16 rounded-control border-2 overflow-hidden transition-all ${setting.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"} ${setting.selectedValue === val ? "border-secondary ring-2 ring-secondary/30 ring-offset-1" : "border-border hover:border-secondary/30"}`,
11084
11143
  children: [
11085
- /* @__PURE__ */ jsx("img", { className: "propeller-cluster-configurator__image w-full h-full object-cover", src: val, alt: val }),
11144
+ /* @__PURE__ */ jsx(PropellerImg, { as: Img, className: "propeller-cluster-configurator__image w-full h-full object-cover", src: val, alt: val, loading: "lazy" }),
11086
11145
  setting.selectedValue === val ? /* @__PURE__ */ jsx("div", { className: "propeller-cluster-configurator__image-check absolute inset-0 bg-secondary bg-opacity-20 flex items-center justify-center", children: /* @__PURE__ */ jsx(
11087
11146
  "svg",
11088
11147
  {
@@ -11182,6 +11241,7 @@ function getProductImageUrl4(product) {
11182
11241
  }
11183
11242
  function ClusterOptions(rawProps) {
11184
11243
  const props = useInfraProps(rawProps);
11244
+ const Img = useImgComponent();
11185
11245
  const [selectedProductIds, setSelectedProductIds] = useState({});
11186
11246
  function getOptionsForRender() {
11187
11247
  const language = props.language;
@@ -11268,20 +11328,23 @@ function ClusterOptions(rawProps) {
11268
11328
  option.hasError ? /* @__PURE__ */ jsx("p", { className: "propeller-cluster-options__error mt-1 text-xs text-destructive", children: getLabel(props.labels, "requiredError", "This option is required") }) : null,
11269
11329
  option.hasSelection ? /* @__PURE__ */ jsxs("div", { className: "propeller-cluster-options__preview mt-3 flex items-center gap-3 rounded-container border border-border-subtle bg-surface-hover p-3", children: [
11270
11330
  !!option.previewImageUrl ? /* @__PURE__ */ jsx(
11271
- "img",
11331
+ PropellerImg,
11272
11332
  {
11333
+ as: Img,
11273
11334
  className: "propeller-cluster-options__preview-image h-12 w-12 flex-shrink-0 rounded border border-border-subtle bg-card object-contain",
11274
11335
  src: option.previewImageUrl,
11275
- alt: option.previewName
11336
+ alt: option.previewName,
11337
+ loading: "lazy"
11276
11338
  }
11277
11339
  ) : null,
11278
11340
  !option.previewImageUrl ? /* @__PURE__ */ jsx("div", { className: "propeller-cluster-options__preview-image-placeholder flex h-12 w-12 flex-shrink-0 items-center justify-center rounded border border-border bg-surface-hover", children: /* @__PURE__ */ jsx(
11279
11341
  "svg",
11280
11342
  {
11343
+ "aria-hidden": "true",
11281
11344
  fill: "none",
11282
11345
  stroke: "currentColor",
11283
11346
  viewBox: "0 0 24 24",
11284
- className: "h-5 w-5 text-foreground-subtle",
11347
+ className: "h-6 w-6 text-foreground-subtle",
11285
11348
  children: /* @__PURE__ */ jsx(
11286
11349
  "path",
11287
11350
  {
@@ -11765,19 +11828,22 @@ function FavoriteListItem(rawProps) {
11765
11828
  }
11766
11829
  function FavoriteListItemImage(props) {
11767
11830
  const { derived, handleItemClick, resolved } = useFavoriteListItemContext();
11831
+ const Img = useImgComponent();
11768
11832
  const { imageUrl, name, productUrl } = derived;
11769
11833
  const linkable = resolved.titleLinkable !== false;
11770
11834
  const wrapperClass = props.className ?? "propeller-favorite-list-item__media relative w-16 h-16 flex-shrink-0 overflow-hidden rounded-control bg-surface-hover p-1";
11771
11835
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
11772
11836
  !!imageUrl ? /* @__PURE__ */ jsx(
11773
- "img",
11837
+ PropellerImg,
11774
11838
  {
11839
+ as: Img,
11775
11840
  className: "propeller-favorite-list-item__image h-full w-full object-contain",
11776
11841
  src: imageUrl,
11777
- alt: name
11842
+ alt: name,
11843
+ loading: "lazy"
11778
11844
  }
11779
11845
  ) : null,
11780
- !imageUrl ? /* @__PURE__ */ jsx("div", { className: "propeller-favorite-list-item__image-placeholder flex h-full w-full items-center justify-center text-foreground-subtle", children: /* @__PURE__ */ jsx("svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "h-8 w-8", children: /* @__PURE__ */ jsx(
11846
+ !imageUrl ? /* @__PURE__ */ jsx("div", { className: "propeller-favorite-list-item__image-placeholder flex h-full w-full items-center justify-center text-foreground-subtle", children: /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "h-10 w-10", children: /* @__PURE__ */ jsx(
11781
11847
  "path",
11782
11848
  {
11783
11849
  strokeLinecap: "round",
@@ -11975,6 +12041,7 @@ FavoriteListItemExport.Actions = FavoriteListItemActions;
11975
12041
  var FavoriteListItem_default = FavoriteListItemExport;
11976
12042
  function FavoriteListDetails(rawProps) {
11977
12043
  const props = useInfraProps(rawProps);
12044
+ const Img = useImgComponent();
11978
12045
  const FavoriteListItemImpl = props.favoriteListItemComponent ?? FavoriteListItem_default;
11979
12046
  const GridPaginationImpl = props.gridPaginationComponent ?? GridPagination_default;
11980
12047
  const { addToList } = useFavorites({
@@ -12556,11 +12623,13 @@ function FavoriteListDetails(rawProps) {
12556
12623
  "data-adding": isAdding ? "true" : "false",
12557
12624
  children: [
12558
12625
  /* @__PURE__ */ jsx("div", { className: "propeller-favorite-list-details__search-item-media h-14 w-14 flex-shrink-0 rounded-control bg-surface-hover overflow-hidden flex items-center justify-center", children: getSearchItemImage(item) ? /* @__PURE__ */ jsx(
12559
- "img",
12626
+ PropellerImg,
12560
12627
  {
12628
+ as: Img,
12561
12629
  src: getSearchItemImage(item),
12562
12630
  alt: getSearchItemName(item),
12563
- className: "h-full w-full object-contain"
12631
+ className: "h-full w-full object-contain",
12632
+ loading: "lazy"
12564
12633
  }
12565
12634
  ) : /* @__PURE__ */ jsxs(
12566
12635
  "svg",
@@ -13268,6 +13337,7 @@ function getBundleNonLeaders(item) {
13268
13337
  }
13269
13338
  function ItemsOverview(rawProps) {
13270
13339
  const props = useInfraProps(rawProps);
13340
+ const Img = useImgComponent();
13271
13341
  const language = props.language;
13272
13342
  const useTax = !!props.includeTax;
13273
13343
  const containerClass = props.itemsOverviewContainerClass || "cart-items-overview";
@@ -13326,26 +13396,29 @@ function ItemsOverview(rawProps) {
13326
13396
  "data-bundle": isBundle ? "true" : "false",
13327
13397
  children: [
13328
13398
  showImage ? /* @__PURE__ */ jsx("div", { className: "propeller-items-overview__item-media w-16 h-16 flex-shrink-0 bg-surface-hover rounded-control overflow-hidden border border-border-subtle flex items-center justify-center", children: getItemImageUrl(item) ? /* @__PURE__ */ jsx(
13329
- "img",
13399
+ PropellerImg,
13330
13400
  {
13401
+ as: Img,
13331
13402
  className: "propeller-items-overview__item-image w-full h-full object-contain p-1.5",
13332
13403
  src: getItemImageUrl(item),
13333
- alt: getItemName(item, language)
13404
+ alt: getItemName(item, language),
13405
+ loading: "lazy"
13334
13406
  }
13335
13407
  ) : /* @__PURE__ */ jsx(
13336
13408
  "svg",
13337
13409
  {
13410
+ "aria-hidden": "true",
13338
13411
  fill: "none",
13339
13412
  viewBox: "0 0 24 24",
13340
13413
  stroke: "currentColor",
13341
- strokeWidth: "1.5",
13342
- className: "propeller-items-overview__item-image-placeholder w-6 h-6 text-foreground-subtle",
13414
+ strokeWidth: "1",
13415
+ className: "propeller-items-overview__item-image-placeholder w-8 h-8 text-foreground-subtle",
13343
13416
  children: /* @__PURE__ */ jsx(
13344
13417
  "path",
13345
13418
  {
13346
13419
  strokeLinecap: "round",
13347
13420
  strokeLinejoin: "round",
13348
- d: "M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0022.5 18.75V5.25A2.25 2.25 0 0020.25 3H3.75A2.25 2.25 0 001.5 5.25v13.5A2.25 2.25 0 003.75 21z"
13421
+ d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
13349
13422
  }
13350
13423
  )
13351
13424
  }
@@ -13883,6 +13956,28 @@ function OrderActions(rawProps) {
13883
13956
  );
13884
13957
  }
13885
13958
  var OrderActions_default = OrderActions;
13959
+ var warnedOnce = /* @__PURE__ */ new Set();
13960
+ function warnOnce(key, message) {
13961
+ if (warnedOnce.has(key)) return;
13962
+ warnedOnce.add(key);
13963
+ console.warn(message);
13964
+ }
13965
+ function warnMissingProps(props) {
13966
+ if (process.env.NODE_ENV === "production") return;
13967
+ if (!props.language) {
13968
+ warnOnce(
13969
+ "language",
13970
+ "[OrderItemCard] No `language` prop: product names resolve in the default catalogue language, whatever page they are on. This component reads no context (it ships from the RSC-safe /pure entry), so the host must pass it."
13971
+ );
13972
+ }
13973
+ const linkable = props.titleLinkable !== void 0 ? props.titleLinkable : true;
13974
+ if (linkable && !props.configuration?.urls) {
13975
+ warnOnce(
13976
+ "urls",
13977
+ "[OrderItemCard] Title is linkable but no `configuration.urls` was passed: links fall back to a literal /product/:id/:slug and lose the locale prefix. Pass the url builders from the host, or set titleLinkable={false}."
13978
+ );
13979
+ }
13980
+ }
13886
13981
  function getProductName3(orderItem, language) {
13887
13982
  return getLocalizedValue(orderItem?.product?.names, language, "") || orderItem?.name || "Unknown Product";
13888
13983
  }
@@ -13906,6 +14001,7 @@ function getProductUrl(orderItem, language, urls) {
13906
14001
  function OrderItemCard(props) {
13907
14002
  const item = props.orderItem;
13908
14003
  const isChildItem = props.isChildItem || false;
14004
+ warnMissingProps(props);
13909
14005
  const titleLinkable = props.titleLinkable !== void 0 ? props.titleLinkable : true;
13910
14006
  const showImage = isChildItem ? false : props.showImage !== void 0 ? props.showImage : true;
13911
14007
  const showSku = isChildItem ? false : props.showSku !== void 0 ? props.showSku : true;
@@ -13946,11 +14042,13 @@ function OrderItemCard(props) {
13946
14042
  className: `propeller-order-item-card__cell propeller-order-item-card__cell--product ${isChildItem ? "px-6 py-2 pl-28" : "px-6 py-4"}`,
13947
14043
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
13948
14044
  showImage ? productImage ? /* @__PURE__ */ jsx("div", { className: "propeller-order-item-card__media relative w-16 h-16 flex-shrink-0 rounded overflow-hidden", children: /* @__PURE__ */ jsx(
13949
- "img",
14045
+ PropellerImg,
13950
14046
  {
14047
+ as: props.imgComponent,
13951
14048
  className: "propeller-order-item-card__image object-cover w-full h-full",
13952
14049
  src: productImage,
13953
- alt: productName
14050
+ alt: productName,
14051
+ loading: "lazy"
13954
14052
  }
13955
14053
  ) }) : /* @__PURE__ */ jsx("div", { className: "propeller-order-item-card__image-placeholder w-16 h-16 bg-surface-hover rounded flex items-center justify-center text-foreground-subtle text-xs", children: getLabel(props.labels, "noImage", "No Img") }) : null,
13956
14054
  /* @__PURE__ */ jsxs("div", { children: [
@@ -14677,6 +14775,10 @@ function RequestPriceButton(props) {
14677
14775
  }
14678
14776
  var RequestPriceButton_default = RequestPriceButton;
14679
14777
  var ROW_SEQ = 0;
14778
+ function snapToStep(value, min, step) {
14779
+ if (!Number.isFinite(value) || value <= min) return min;
14780
+ return Math.round((value - min) / (step || 1)) * (step || 1) + min;
14781
+ }
14680
14782
  function blankRow() {
14681
14783
  ROW_SEQ += 1;
14682
14784
  return {
@@ -14688,6 +14790,7 @@ function blankRow() {
14688
14790
  grossPrice: 0,
14689
14791
  quantity: 1,
14690
14792
  minQuantity: 1,
14793
+ step: 1,
14691
14794
  matches: [],
14692
14795
  searching: false,
14693
14796
  searched: false
@@ -14712,6 +14815,7 @@ function QuickOrderInner(props) {
14712
14815
  className,
14713
14816
  labels
14714
14817
  } = props;
14818
+ const Img = useImgComponent();
14715
14819
  const user = props.user ?? null;
14716
14820
  const graphqlClient = props.graphqlClient;
14717
14821
  const displayPrice = (n) => props.formatPrice ? props.formatPrice(n) : formatPrice(n, { symbol: currency, locale: localeForLanguage(props.language) });
@@ -14781,6 +14885,7 @@ function QuickOrderInner(props) {
14781
14885
  grossPrice: match.grossPrice,
14782
14886
  quantity: match.minQuantity,
14783
14887
  minQuantity: match.minQuantity,
14888
+ step: match.step,
14784
14889
  matches: [],
14785
14890
  searching: false,
14786
14891
  searched: false
@@ -14793,7 +14898,7 @@ function QuickOrderInner(props) {
14793
14898
  const n = parseInt(raw, 10);
14794
14899
  setRows(
14795
14900
  (prev) => prev.map(
14796
- (r) => r.key === key ? { ...r, quantity: Number.isFinite(n) && n > 0 ? Math.max(r.minQuantity, n) : r.minQuantity } : r
14901
+ (r) => r.key === key ? { ...r, quantity: snapToStep(n, r.minQuantity, r.step) } : r
14797
14902
  )
14798
14903
  );
14799
14904
  },
@@ -14846,7 +14951,8 @@ function QuickOrderInner(props) {
14846
14951
  netPrice: exact.netPrice,
14847
14952
  grossPrice: exact.grossPrice,
14848
14953
  quantity: Math.max(exact.minQuantity, line.quantity),
14849
- minQuantity: exact.minQuantity
14954
+ minQuantity: exact.minQuantity,
14955
+ step: exact.step
14850
14956
  });
14851
14957
  }
14852
14958
  if (resolved.length) {
@@ -14941,7 +15047,7 @@ function QuickOrderInner(props) {
14941
15047
  children: [
14942
15048
  m.imageUrl ? (
14943
15049
  // eslint-disable-next-line @next/next/no-img-element
14944
- /* @__PURE__ */ jsx("img", { src: m.imageUrl, alt: "", width: 32, height: 32, className: "rounded object-cover" })
15050
+ /* @__PURE__ */ jsx(PropellerImg, { as: Img, src: m.imageUrl, alt: "", width: 32, height: 32, className: "rounded object-cover", loading: "lazy" })
14945
15051
  ) : null,
14946
15052
  /* @__PURE__ */ jsxs("span", { className: "flex-1", children: [
14947
15053
  /* @__PURE__ */ jsx("span", { className: "block text-foreground", children: m.name }),
@@ -14977,7 +15083,7 @@ function QuickOrderInner(props) {
14977
15083
  {
14978
15084
  type: "number",
14979
15085
  min: r.minQuantity,
14980
- step: 1,
15086
+ step: r.step || 1,
14981
15087
  value: r.productId ? r.quantity : "",
14982
15088
  disabled: !r.productId,
14983
15089
  onChange: (e) => setQuantity(r.key, e.target.value),
@@ -15606,6 +15712,7 @@ function getProductName4(product, language) {
15606
15712
  }
15607
15713
  function ProductBundles(rawProps) {
15608
15714
  const props = useInfraProps(rawProps);
15715
+ const Img = useImgComponent();
15609
15716
  const language = props.language;
15610
15717
  const currencySymbol = props.currency ?? "\u20AC";
15611
15718
  const money = (value) => formatPrice(value, { symbol: currencySymbol, locale: localeForLanguage(props.language) });
@@ -15741,11 +15848,13 @@ function ProductBundles(rawProps) {
15741
15848
  ) }) : null,
15742
15849
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center w-40", children: [
15743
15850
  /* @__PURE__ */ jsx("div", { className: "propeller-product-bundles__item-media w-32 h-32 bg-surface-hover rounded-container overflow-hidden flex-shrink-0 mb-2", children: getProductImage(item.product) ? /* @__PURE__ */ jsx(
15744
- "img",
15851
+ PropellerImg,
15745
15852
  {
15853
+ as: Img,
15746
15854
  className: "propeller-product-bundles__item-image w-full h-full object-contain p-2",
15747
15855
  src: getProductImage(item.product),
15748
- alt: getProductName4(item.product, language)
15856
+ alt: getProductName4(item.product, language),
15857
+ loading: "lazy"
15749
15858
  }
15750
15859
  ) : null }),
15751
15860
  /* @__PURE__ */ jsx("div", { className: "propeller-product-bundles__item-name text-sm font-medium text-muted-foreground leading-tight mb-1", children: getProductName4(item.product, language) || "Product " + item.productId }),
@@ -15910,26 +16019,29 @@ function ProductBundles(rawProps) {
15910
16019
  /* @__PURE__ */ jsxs("div", { className: "propeller-product-bundles__modal-body px-6 py-5", children: [
15911
16020
  /* @__PURE__ */ jsxs("div", { className: "propeller-product-bundles__modal-product flex items-start gap-4", children: [
15912
16021
  lastAddedBundle && lastAddedBundle.items && lastAddedBundle.items.length > 0 && getProductImage(lastAddedBundle.items[0].product) ? /* @__PURE__ */ jsx(
15913
- "img",
16022
+ PropellerImg,
15914
16023
  {
16024
+ as: Img,
15915
16025
  className: "propeller-product-bundles__modal-image w-16 h-16 object-contain rounded border border-border-subtle flex-shrink-0",
15916
16026
  src: lastAddedBundle?.items?.[0] ? getProductImage(lastAddedBundle.items[0].product) : "",
15917
- alt: lastAddedBundle?.name || "Bundle"
16027
+ alt: lastAddedBundle?.name || "Bundle",
16028
+ loading: "lazy"
15918
16029
  }
15919
16030
  ) : /* @__PURE__ */ jsx("div", { className: "propeller-product-bundles__modal-image-placeholder w-16 h-16 flex items-center justify-center rounded border border-border-subtle flex-shrink-0 bg-surface-hover", children: /* @__PURE__ */ jsx(
15920
16031
  "svg",
15921
16032
  {
16033
+ "aria-hidden": "true",
15922
16034
  fill: "none",
15923
16035
  viewBox: "0 0 24 24",
15924
16036
  stroke: "currentColor",
15925
16037
  className: "w-8 h-8 text-foreground-subtle",
15926
- strokeWidth: 1.5,
16038
+ strokeWidth: 1,
15927
16039
  children: /* @__PURE__ */ jsx(
15928
16040
  "path",
15929
16041
  {
15930
16042
  strokeLinecap: "round",
15931
16043
  strokeLinejoin: "round",
15932
- d: "M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0022.5 18.75V5.25A2.25 2.25 0 0020.25 3H3.75A2.25 2.25 0 001.5 5.25v13.5A2.25 2.25 0 003.75 21z"
16044
+ d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
15933
16045
  }
15934
16046
  )
15935
16047
  }
@@ -16094,6 +16206,7 @@ function ProductDownloads(props) {
16094
16206
  }
16095
16207
  var ProductDownloads_default = ProductDownloads;
16096
16208
  function ProductGallery(props) {
16209
+ const Img = useImgComponent();
16097
16210
  const [selectedIndex, setSelectedIndex] = useState(0);
16098
16211
  const [lightboxOpen, setLightboxOpen] = useState(false);
16099
16212
  const images = props.images || [];
@@ -16131,11 +16244,13 @@ function ProductGallery(props) {
16131
16244
  }
16132
16245
  ) }) : null,
16133
16246
  images.length > 0 ? /* @__PURE__ */ jsx(
16134
- "img",
16247
+ PropellerImg,
16135
16248
  {
16249
+ as: Img,
16136
16250
  alt: getLabel(props.labels, "productImageAlt", "Product image"),
16137
16251
  src: mainImage,
16138
16252
  onClick: openLightbox,
16253
+ loading: "eager",
16139
16254
  className: `h-full w-full object-contain p-8 transition-transform duration-200 ${props.enableZoom !== false ? "cursor-zoom-in hover:scale-105" : ""}`
16140
16255
  }
16141
16256
  ) : null
@@ -16147,11 +16262,13 @@ function ProductGallery(props) {
16147
16262
  onClick: () => setSelectedIndex(index),
16148
16263
  className: `propeller-product-gallery__thumbnail relative flex-shrink-0 w-20 h-20 rounded-container border-2 overflow-hidden transition-all bg-card ${selectedIndex === index ? "border-primary ring-2 ring-primary/20" : "border-transparent hover:border-border"}`,
16149
16264
  children: /* @__PURE__ */ jsx(
16150
- "img",
16265
+ PropellerImg,
16151
16266
  {
16267
+ as: Img,
16152
16268
  className: "w-full h-full object-contain p-1",
16153
16269
  src: img,
16154
- alt: `${getLabel(props.labels, "productImageAlt", "Product image")} ${index + 1}`
16270
+ alt: `${getLabel(props.labels, "productImageAlt", "Product image")} ${index + 1}`,
16271
+ loading: "lazy"
16155
16272
  }
16156
16273
  )
16157
16274
  },
@@ -16206,12 +16323,13 @@ function ProductGallery(props) {
16206
16323
  }
16207
16324
  ) : null,
16208
16325
  /* @__PURE__ */ jsx(
16209
- "img",
16326
+ PropellerImg,
16210
16327
  {
16328
+ as: Img,
16211
16329
  alt: getLabel(props.labels, "productImageFullscreenAlt", "Product image fullscreen"),
16212
16330
  className: "max-h-full max-w-full object-contain rounded-lg",
16213
16331
  src: mainImage,
16214
- onClick: (e) => e.stopPropagation()
16332
+ onClick: (e) => e.stopPropagation?.()
16215
16333
  }
16216
16334
  ),
16217
16335
  hasThumbnails ? /* @__PURE__ */ jsx(
@@ -16265,6 +16383,7 @@ function pickImageUrl(mediaItems, target) {
16265
16383
  }
16266
16384
  function DefaultProductImage(props) {
16267
16385
  const { product, cluster, className } = props;
16386
+ const Img = useImgComponent();
16268
16387
  const targetLanguage = props.language ?? "NL";
16269
16388
  const mediaItems = (() => {
16270
16389
  const target = product ?? cluster?.defaultProduct ?? cluster;
@@ -16299,8 +16418,9 @@ function DefaultProductImage(props) {
16299
16418
  );
16300
16419
  }
16301
16420
  return /* @__PURE__ */ jsx(
16302
- "img",
16421
+ PropellerImg,
16303
16422
  {
16423
+ as: Img,
16304
16424
  src: url,
16305
16425
  alt: altText,
16306
16426
  className: className ?? "h-full w-full object-contain",
@@ -19209,6 +19329,7 @@ function mapToSearchBarResult(item, language, urls) {
19209
19329
  }
19210
19330
  function SearchBar(rawProps) {
19211
19331
  const props = useInfraProps(rawProps);
19332
+ const Img = useImgComponent();
19212
19333
  const [showDropdown, setShowDropdown] = useState(false);
19213
19334
  const [localTerm, setLocalTerm] = useState("");
19214
19335
  const containerRef = useRef(null);
@@ -19374,11 +19495,13 @@ function SearchBar(rawProps) {
19374
19495
  ...resultProps,
19375
19496
  children: [
19376
19497
  result.imageUrl || noImageUrl() ? /* @__PURE__ */ jsx("div", { className: "propeller-search-bar__result-media relative w-16 h-16 flex-shrink-0", children: /* @__PURE__ */ jsx(
19377
- "img",
19498
+ PropellerImg,
19378
19499
  {
19500
+ as: Img,
19379
19501
  className: "propeller-search-bar__result-image w-full h-full object-contain",
19380
19502
  src: result.imageUrl || noImageUrl(),
19381
- alt: result.name
19503
+ alt: result.name,
19504
+ loading: "lazy"
19382
19505
  }
19383
19506
  ) }) : null,
19384
19507
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
@@ -19542,6 +19665,6 @@ function UserDetails(rawProps) {
19542
19665
  }
19543
19666
  var UserDetails_default = UserDetails;
19544
19667
 
19545
- export { AccountIconAndMenu_default as AccountIconAndMenu, ActionCode_default as ActionCode, AddToCart_default as AddToCart, AddToFavorite_default as AddToFavorite, AddressCard_default as AddressCard, AddressSelector_default as AddressSelector, BreadcrumbsWithProvider_default as Breadcrumbs, CartBonusItems_default as CartBonusItems, CartCarriers_default as CartCarriers, CartIconAndSidebar_default as CartIconAndSidebar, CartItem_default as CartItem, CartOverview_default as CartOverview, CartPaymethods_default as CartPaymethods, CartSummary_default as CartSummary, CategoryDescription_default as CategoryDescription, CategoryShortDescriptionWithProvider_default as CategoryShortDescription, ClusterCard_default as ClusterCard, ClusterConfigurator_default as ClusterConfigurator, ClusterInfo_default as ClusterInfo, ClusterOptions_default as ClusterOptions, CompanySwitcher_default as CompanySwitcher, AddToCart_default as DefaultAddToCart, AddToFavorite_default as DefaultAddToFavorite, ItemStock_default as DefaultItemStock, DefaultProductBadges, ProductBulkPrices_default as DefaultProductBulkPrices, ProductBundles_default as DefaultProductBundles, DefaultProductImage, ProductPrice_default as DefaultProductPrice, DefaultProductSurcharges, DeliveryDate_default as DeliveryDate, FavoriteListDetails_default as FavoriteListDetails, FavoriteListItem_default as FavoriteListItem, FavoriteLists_default as FavoriteLists, ForgotPassword_default as ForgotPassword, GridFilters_default as GridFilters, GridFiltersPanel, GridPagination_default as GridPagination, GridTitleWithProvider_default as GridTitle, GridToolbar_default as GridToolbar, ItemStock_default as ItemStock, ItemsOverview_default as ItemsOverview, LoginForm_default as LoginForm, LoginToOrderButton_default as LoginToOrderButton, MachineCard, MachineGrid, Menu_default as Menu, OrderActions_default as OrderActions, OrderBonusItems_default as OrderBonusItems, OrderItemCard_default as OrderItemCard, OrderList_default as OrderList, OrderShipments_default as OrderShipments, OrderSummaryWithProvider_default as OrderSummary, OrderTotalsWithProvider_default as OrderTotals, PRICE_REQUEST_STORAGE_KEY, PriceRequestList_default as PriceRequestList, PriceToggle_default as PriceToggle, ProductBulkPricesWithProvider_default as ProductBulkPrices, ProductBundles_default as ProductBundles, ProductCard_default as ProductCard, ProductDescription_default as ProductDescription, ProductDownloads_default as ProductDownloads, ProductGallery_default as ProductGallery, ProductGrid_default as ProductGrid, ProductGridConfigProvider, ProductInfo_default as ProductInfo, ProductPriceWithProvider_default as ProductPrice, ProductShortDescriptionWithProvider_default as ProductShortDescription, ProductSlider_default as ProductSlider, ProductSpecifications_default as ProductSpecifications, ProductTabs_default as ProductTabs, ProductVideos_default as ProductVideos, PropellerDepsProvider, PropellerProvider, PurchaseAuthorizationConfigurator_default as PurchaseAuthorizationConfigurator, PurchaseAuthorizationRequests_default as PurchaseAuthorizationRequests, QuickOrder, QuoteActions_default as QuoteActions, RegisterForm_default as RegisterForm, RequestPriceButton_default as RequestPriceButton, SearchBar_default as SearchBar, UserDetails_default as UserDetails, addItem as addPriceRequestItem, buildRootMachinesQuery, fetchActiveCart, initCart, isPriceOnRequest, mergeAnonymousCart, containsItem as priceRequestContains, removeItem as removePriceRequestItem, setItemQuantity as setPriceRequestItemQuantity, useAddress, useAuth, useCart, useCheckout, useClusterConfigurator, useCompany, useFavorites, useInfraProps, useMachines, useMenu, useOrders, usePriceRequest, useProductBundles, useProductGridConfig, useProductInfo, useProductSearch, useProductSlider, useProductSpecs, usePropellerContext, usePropellerDeps, usePropellerScope, usePurchaseAuthorizationConfigurator, usePurchaseAuthorizationRequests, useQuickOrder, useRequiredPropellerDeps, useResolvedProps, useServices, useSpareParts, useUserMode };
19668
+ export { AccountIconAndMenu_default as AccountIconAndMenu, ActionCode_default as ActionCode, AddToCart_default as AddToCart, AddToFavorite_default as AddToFavorite, AddressCard_default as AddressCard, AddressSelector_default as AddressSelector, BreadcrumbsWithProvider_default as Breadcrumbs, CartBonusItems_default as CartBonusItems, CartCarriers_default as CartCarriers, CartIconAndSidebar_default as CartIconAndSidebar, CartItem_default as CartItem, CartOverview_default as CartOverview, CartPaymethods_default as CartPaymethods, CartSummary_default as CartSummary, CategoryDescription_default as CategoryDescription, CategoryShortDescriptionWithProvider_default as CategoryShortDescription, ClusterCard_default as ClusterCard, ClusterConfigurator_default as ClusterConfigurator, ClusterInfo_default as ClusterInfo, ClusterOptions_default as ClusterOptions, CompanySwitcher_default as CompanySwitcher, AddToCart_default as DefaultAddToCart, AddToFavorite_default as DefaultAddToFavorite, ItemStock_default as DefaultItemStock, DefaultProductBadges, ProductBulkPrices_default as DefaultProductBulkPrices, ProductBundles_default as DefaultProductBundles, DefaultProductImage, ProductPrice_default as DefaultProductPrice, DefaultProductSurcharges, DeliveryDate_default as DeliveryDate, FavoriteListDetails_default as FavoriteListDetails, FavoriteListItem_default as FavoriteListItem, FavoriteLists_default as FavoriteLists, ForgotPassword_default as ForgotPassword, GridFilters_default as GridFilters, GridFiltersPanel, GridPagination_default as GridPagination, GridTitleWithProvider_default as GridTitle, GridToolbar_default as GridToolbar, ItemStock_default as ItemStock, ItemsOverview_default as ItemsOverview, LoginForm_default as LoginForm, LoginToOrderButton_default as LoginToOrderButton, MachineCard, MachineGrid, Menu_default as Menu, OrderActions_default as OrderActions, OrderBonusItems_default as OrderBonusItems, OrderItemCard_default as OrderItemCard, OrderList_default as OrderList, OrderShipments_default as OrderShipments, OrderSummaryWithProvider_default as OrderSummary, OrderTotalsWithProvider_default as OrderTotals, PRICE_REQUEST_STORAGE_KEY, PriceRequestList_default as PriceRequestList, PriceToggle_default as PriceToggle, ProductBulkPricesWithProvider_default as ProductBulkPrices, ProductBundles_default as ProductBundles, ProductCard_default as ProductCard, ProductDescription_default as ProductDescription, ProductDownloads_default as ProductDownloads, ProductGallery_default as ProductGallery, ProductGrid_default as ProductGrid, ProductGridConfigProvider, ProductInfo_default as ProductInfo, ProductPriceWithProvider_default as ProductPrice, ProductShortDescriptionWithProvider_default as ProductShortDescription, ProductSlider_default as ProductSlider, ProductSpecifications_default as ProductSpecifications, ProductTabs_default as ProductTabs, ProductVideos_default as ProductVideos, PropellerDepsProvider, PropellerImg, PropellerProvider, PurchaseAuthorizationConfigurator_default as PurchaseAuthorizationConfigurator, PurchaseAuthorizationRequests_default as PurchaseAuthorizationRequests, QuickOrder, QuoteActions_default as QuoteActions, RegisterForm_default as RegisterForm, RequestPriceButton_default as RequestPriceButton, SearchBar_default as SearchBar, UserDetails_default as UserDetails, addItem as addPriceRequestItem, buildRootMachinesQuery, fetchActiveCart, initCart, isPriceOnRequest, mergeAnonymousCart, containsItem as priceRequestContains, removeItem as removePriceRequestItem, setItemQuantity as setPriceRequestItemQuantity, useAddress, useAuth, useCart, useCheckout, useClusterConfigurator, useCompany, useFavorites, useImgComponent, useInfraProps, useMachines, useMenu, useOrders, usePriceRequest, useProductBundles, useProductGridConfig, useProductInfo, useProductSearch, useProductSlider, useProductSpecs, usePropellerContext, usePropellerDeps, usePropellerScope, usePurchaseAuthorizationConfigurator, usePurchaseAuthorizationRequests, useQuickOrder, useRequiredPropellerDeps, useResolvedProps, useServices, useSpareParts, useUserMode };
19546
19669
  //# sourceMappingURL=index.js.map
19547
19670
  //# sourceMappingURL=index.js.map