@lime-bundles/react 6.1.0 → 7.0.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.cjs CHANGED
@@ -20,62 +20,60 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- BUNDLES_FOR_PRODUCT_QUERY: () => import_core18.BUNDLES_FOR_PRODUCT_QUERY,
24
- BUNDLE_METAOBJECT_QUERY: () => import_core18.BUNDLE_METAOBJECT_QUERY,
23
+ BUNDLES_FOR_PRODUCT_QUERY: () => import_core17.BUNDLES_FOR_PRODUCT_QUERY,
24
+ BUNDLE_METAOBJECT_QUERY: () => import_core17.BUNDLE_METAOBJECT_QUERY,
25
25
  BogoBundle: () => BogoBundle,
26
- BundleParseError: () => import_core17.BundleParseError,
27
- DEFAULT_OUT_OF_STOCK_BEHAVIOR: () => import_core18.DEFAULT_OUT_OF_STOCK_BEHAVIOR,
26
+ BundleCountdown: () => BundleCountdown,
27
+ BundleParseError: () => import_core16.BundleParseError,
28
28
  FixedBundle: () => FixedBundle,
29
29
  MixMatchBundle: () => MixMatchBundle,
30
30
  MultiStepBundle: () => MultiStepBundle,
31
- SHOP_SETTINGS_QUERY: () => import_core18.SHOP_SETTINGS_QUERY,
32
- StorefrontApiError: () => import_core17.StorefrontApiError,
31
+ SHOP_SETTINGS_QUERY: () => import_core17.SHOP_SETTINGS_QUERY,
32
+ StorefrontApiError: () => import_core16.StorefrontApiError,
33
33
  VariantDropdown: () => VariantDropdown,
34
34
  VolumeBundle: () => VolumeBundle,
35
- WIDGET_CONFIG_DEFAULTS: () => import_core18.WIDGET_CONFIG_DEFAULTS,
36
- applyWidgetConfigVars: () => import_core18.applyWidgetConfigVars,
37
- calculateDiscount: () => import_core18.calculateDiscount,
38
- calculateTierSavings: () => import_core18.calculateTierSavings,
39
- computeBundleSaleCents: () => import_core18.computeBundleSaleCents,
40
- computeFixedPricing: () => import_core18.computeFixedPricing,
41
- createStorefrontClient: () => import_core18.createStorefrontClient,
35
+ WIDGET_CONFIG_DEFAULTS: () => import_core17.WIDGET_CONFIG_DEFAULTS,
36
+ applyWidgetConfigVars: () => import_core17.applyWidgetConfigVars,
37
+ calculateDiscount: () => import_core17.calculateDiscount,
38
+ calculateTierSavings: () => import_core17.calculateTierSavings,
39
+ computeBundleSaleCents: () => import_core17.computeBundleSaleCents,
40
+ computeFixedPricing: () => import_core17.computeFixedPricing,
41
+ createStorefrontClient: () => import_core17.createStorefrontClient,
42
42
  fetchBundleData: () => fetchBundleData,
43
- fetchBundlesForProduct: () => import_core18.fetchBundlesForProduct,
43
+ fetchBundlesForProduct: () => import_core17.fetchBundlesForProduct,
44
44
  fetchShopCustomCss: () => fetchShopCustomCss,
45
45
  fetchShopSettings: () => fetchShopSettings,
46
46
  fetchShopSettingsOrDefault: () => fetchShopSettingsOrDefault,
47
- formatCents: () => import_core18.formatCents,
48
- formatCountdown: () => import_core18.formatCountdown,
49
- formatMoney: () => import_core18.formatMoney,
50
- formatUnitPrice: () => import_core18.formatUnitPrice,
51
- getActiveTier: () => import_core18.getActiveTier,
52
- injectCustomCss: () => import_core18.injectCustomCss,
53
- mergeWidgetConfig: () => import_core18.mergeWidgetConfig,
54
- observeImpression: () => import_core18.observeImpression,
55
- parseCents: () => import_core18.parseCents,
56
- parseMetaobjectBundle: () => import_core18.parseMetaobjectBundle,
57
- parseMetaobjectBundleStrict: () => import_core18.parseMetaobjectBundleStrict,
58
- parseOutOfStockBehavior: () => import_core18.parseOutOfStockBehavior,
59
- percentageDiscountUnit: () => import_core18.percentageDiscountUnit,
60
- productsForStep: () => import_core18.productsForStep,
61
- reportAddToCart: () => import_core18.reportAddToCart,
62
- reportImpression: () => import_core18.reportImpression,
63
- sanitizeCustomCss: () => import_core18.sanitizeCustomCss,
64
- stepHeadroom: () => import_core18.stepHeadroom,
65
- thumbnailRatioVars: () => import_core18.thumbnailRatioVars,
66
- transformImageUrl: () => import_core18.transformImageUrl,
47
+ formatCents: () => import_core17.formatCents,
48
+ formatCountdown: () => import_core17.formatCountdown,
49
+ formatMoney: () => import_core17.formatMoney,
50
+ formatUnitPrice: () => import_core17.formatUnitPrice,
51
+ getActiveTier: () => import_core17.getActiveTier,
52
+ injectCustomCss: () => import_core17.injectCustomCss,
53
+ mergeWidgetConfig: () => import_core17.mergeWidgetConfig,
54
+ observeImpression: () => import_core17.observeImpression,
55
+ parseCents: () => import_core17.parseCents,
56
+ parseMetaobjectBundle: () => import_core17.parseMetaobjectBundle,
57
+ parseMetaobjectBundleStrict: () => import_core17.parseMetaobjectBundleStrict,
58
+ percentageDiscountUnit: () => import_core17.percentageDiscountUnit,
59
+ productsForStep: () => import_core17.productsForStep,
60
+ reportAddToCart: () => import_core17.reportAddToCart,
61
+ reportImpression: () => import_core17.reportImpression,
62
+ sanitizeCustomCss: () => import_core17.sanitizeCustomCss,
63
+ stepHeadroom: () => import_core17.stepHeadroom,
64
+ thumbnailRatioVars: () => import_core17.thumbnailRatioVars,
65
+ transformImageUrl: () => import_core17.transformImageUrl,
67
66
  useAnalytics: () => useAnalytics,
68
67
  useBundleData: () => useBundleData,
69
68
  useBundlesForProduct: () => useBundlesForProduct,
70
- useShopSettings: () => useShopSettings,
71
69
  useVariantSelection: () => useVariantSelection,
72
70
  useWidgetConfigVars: () => useWidgetConfigVars,
73
- validateQuantity: () => import_core18.validateQuantity
71
+ validateQuantity: () => import_core17.validateQuantity
74
72
  });
75
73
  module.exports = __toCommonJS(index_exports);
76
74
 
77
75
  // src/components/FixedBundle.tsx
78
- var import_react7 = require("react");
76
+ var import_react8 = require("react");
79
77
  var import_core8 = require("@lime-bundles/core");
80
78
 
81
79
  // src/hooks/useBundleData.ts
@@ -140,8 +138,7 @@ async function fetchBundleDataWithWarnings(options) {
140
138
  // src/fetchShopSettings.ts
141
139
  var import_core2 = require("@lime-bundles/core");
142
140
  var FALLBACK = {
143
- customCss: null,
144
- outOfStockBehavior: import_core2.DEFAULT_OUT_OF_STOCK_BEHAVIOR
141
+ customCss: null
145
142
  };
146
143
  var cache = /* @__PURE__ */ new Map();
147
144
  async function fetchShopSettings(options) {
@@ -159,10 +156,7 @@ async function fetchShopSettings(options) {
159
156
  { signal: options.signal }
160
157
  );
161
158
  return {
162
- customCss: data.shop?.customCss?.value ?? null,
163
- outOfStockBehavior: (0, import_core2.parseOutOfStockBehavior)(
164
- data.shop?.outOfStockBehavior?.value
165
- )
159
+ customCss: data.shop?.customCss?.value ?? null
166
160
  };
167
161
  })();
168
162
  cache.set(options.shopDomain, promise);
@@ -316,19 +310,25 @@ function useWidgetConfigVars(config) {
316
310
  var import_react4 = require("react");
317
311
  var import_core6 = require("@lime-bundles/core");
318
312
  var { findVariantByOptions, isOptionValueAvailable, toPickerVariant } = import_core6.variants;
319
- function defaultInitial(variants) {
320
- return variants.find((v) => v.availableForSale) ?? variants[0] ?? null;
321
- }
322
313
  function useVariantSelection({
323
314
  variants,
324
315
  optionNames,
325
316
  initialVariant,
326
- optionValuesByPosition
317
+ optionValuesByPosition,
318
+ requiredQtyFor
327
319
  }) {
328
- const seed = (0, import_react4.useMemo)(
329
- () => initialVariant ?? defaultInitial(variants),
330
- [initialVariant, variants]
320
+ const pickerVariants = (0, import_react4.useMemo)(
321
+ () => variants.map((v) => toPickerVariant(v, requiredQtyFor?.(v.id))),
322
+ [variants, requiredQtyFor]
331
323
  );
324
+ const seed = (0, import_react4.useMemo)(() => {
325
+ if (initialVariant) return initialVariant;
326
+ const covered = pickerVariants.find((p) => p.available);
327
+ if (covered) {
328
+ return variants.find((v) => v.id === covered.id) ?? null;
329
+ }
330
+ return variants.find((v) => v.availableForSale) ?? variants[0] ?? null;
331
+ }, [initialVariant, variants, pickerVariants]);
332
332
  const [selectedValues, setSelectedValues] = (0, import_react4.useState)(
333
333
  () => seed ? seed.selectedOptions.map((o) => o.value) : optionNames.map(() => "")
334
334
  );
@@ -336,10 +336,6 @@ function useVariantSelection({
336
336
  if (!seed) return;
337
337
  setSelectedValues(seed.selectedOptions.map((o) => o.value));
338
338
  }, [seed?.id]);
339
- const pickerVariants = (0, import_react4.useMemo)(
340
- () => variants.map((v) => toPickerVariant(v)),
341
- [variants]
342
- );
343
339
  const selectedVariant = (0, import_react4.useMemo)(() => {
344
340
  if (selectedValues.length !== optionNames.length) return null;
345
341
  const match = findVariantByOptions(pickerVariants, selectedValues);
@@ -702,8 +698,48 @@ function VariantDropdown({
702
698
  );
703
699
  }
704
700
 
705
- // src/components/FixedBundle.tsx
701
+ // src/components/BundleCountdown.tsx
702
+ var import_react7 = require("react");
706
703
  var import_jsx_runtime2 = require("react/jsx-runtime");
704
+ function pad(n) {
705
+ return n < 10 ? "0" + n : String(n);
706
+ }
707
+ function formatRemaining(remaining) {
708
+ const days = Math.floor(remaining / 864e5);
709
+ const hours = Math.floor(remaining % 864e5 / 36e5);
710
+ const mins = Math.floor(remaining % 36e5 / 6e4);
711
+ const secs = Math.floor(remaining % 6e4 / 1e3);
712
+ return days > 0 ? days + "d " + pad(hours) + "h " + pad(mins) + "m " + pad(secs) + "s" : pad(hours) + "h " + pad(mins) + "m " + pad(secs) + "s";
713
+ }
714
+ function BundleCountdown({
715
+ endsAt,
716
+ widgetConfig,
717
+ label = "Limited time offer"
718
+ }) {
719
+ const enabled = !!endsAt && widgetConfig?.countdown?.showCountdown !== false;
720
+ const endTime = enabled ? new Date(endsAt).getTime() : NaN;
721
+ const [remaining, setRemaining] = (0, import_react7.useState)(null);
722
+ (0, import_react7.useEffect)(() => {
723
+ if (!enabled || isNaN(endTime)) {
724
+ setRemaining(null);
725
+ return;
726
+ }
727
+ const update = () => setRemaining(endTime - Date.now());
728
+ update();
729
+ const interval = setInterval(update, 1e3);
730
+ return () => clearInterval(interval);
731
+ }, [enabled, endTime]);
732
+ if (!enabled || isNaN(endTime) || remaining === null || remaining <= 0) {
733
+ return null;
734
+ }
735
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "lb-bundle-countdown", "data-countdown": true, children: [
736
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-bundle-countdown__label", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: label }) }),
737
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle-countdown__timer", "data-countdown-timer": true, children: formatRemaining(remaining) })
738
+ ] });
739
+ }
740
+
741
+ // src/components/FixedBundle.tsx
742
+ var import_jsx_runtime3 = require("react/jsx-runtime");
707
743
  function FixedBundle(props) {
708
744
  const {
709
745
  shopDomain,
@@ -727,10 +763,10 @@ function FixedBundle(props) {
727
763
  bundleType: "fixed",
728
764
  enabled: analyticsEnabled !== false
729
765
  });
730
- const [addingToCart, setAddingToCart] = (0, import_react7.useState)(false);
731
- const [cartError, setCartError] = (0, import_react7.useState)(null);
732
- const [selectedVariants, setSelectedVariants] = (0, import_react7.useState)({});
733
- const handleVariantChange = (0, import_react7.useCallback)(
766
+ const [addingToCart, setAddingToCart] = (0, import_react8.useState)(false);
767
+ const [cartError, setCartError] = (0, import_react8.useState)(null);
768
+ const [selectedVariants, setSelectedVariants] = (0, import_react8.useState)({});
769
+ const handleVariantChange = (0, import_react8.useCallback)(
734
770
  (productId, variant) => {
735
771
  setSelectedVariants((prev) => {
736
772
  if (prev[productId] === variant) return prev;
@@ -742,7 +778,7 @@ function FixedBundle(props) {
742
778
  const bundle = result.status === "success" && result.bundle.bundleType === "fixed" ? result.bundle : null;
743
779
  const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
744
780
  const productsEdgeFadeRef = useEdgeFade();
745
- (0, import_react7.useEffect)(() => {
781
+ (0, import_react8.useEffect)(() => {
746
782
  if (result.status === "error") {
747
783
  onError?.(result.error);
748
784
  return;
@@ -755,7 +791,7 @@ function FixedBundle(props) {
755
791
  );
756
792
  }
757
793
  }, [result, onError]);
758
- const oosProductIds = (0, import_react7.useMemo)(() => {
794
+ const oosProductIds = (0, import_react8.useMemo)(() => {
759
795
  if (!bundle) return /* @__PURE__ */ new Set();
760
796
  return new Set(
761
797
  bundle.products.filter(
@@ -765,7 +801,7 @@ function FixedBundle(props) {
765
801
  ).map((p) => p.id)
766
802
  );
767
803
  }, [bundle]);
768
- const handleAddToCart = (0, import_react7.useCallback)(async () => {
804
+ const handleAddToCart = (0, import_react8.useCallback)(async () => {
769
805
  if (!bundle) return;
770
806
  const bundleLines = bundle.products.filter(
771
807
  (p) => p.variants.nodes.some(
@@ -820,9 +856,9 @@ function FixedBundle(props) {
820
856
  }
821
857
  }, [bundle, onAddToCart, onError, trackAddToCart, selectedVariants]);
822
858
  if (result.status === "loading") {
823
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
824
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
825
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
859
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
860
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
861
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
826
862
  ] });
827
863
  }
828
864
  if (result.status === "error") return null;
@@ -849,7 +885,7 @@ function FixedBundle(props) {
849
885
  const savingsPercent = comparePrice > 0 && savings > 0 ? Math.round(savings / comparePrice * 100) : 0;
850
886
  const showCompare = bundle.widgetConfig.pricing.showComparePrice && savings > 0;
851
887
  const showSavings = bundle.widgetConfig.savingsBar.visible && savings > 0;
852
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
888
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
853
889
  "div",
854
890
  {
855
891
  ref: (el) => {
@@ -860,11 +896,18 @@ function FixedBundle(props) {
860
896
  role: "region",
861
897
  "aria-label": bundle.title,
862
898
  children: [
863
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "lb-bundle-header__content", children: [
864
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
865
- bundle.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
899
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-bundle-header__content", children: [
900
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
901
+ bundle.description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
866
902
  ] }) }),
867
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-bundle__products lb-edge-fade", ref: productsEdgeFadeRef, children: bundle.products.map((product) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
903
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
904
+ BundleCountdown,
905
+ {
906
+ endsAt: bundle.endsAt,
907
+ widgetConfig: bundle.widgetConfig
908
+ }
909
+ ),
910
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-bundle__products lb-edge-fade", ref: productsEdgeFadeRef, children: bundle.products.map((product) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
868
911
  FixedProductRow,
869
912
  {
870
913
  bundle,
@@ -875,29 +918,29 @@ function FixedBundle(props) {
875
918
  },
876
919
  product.id
877
920
  )) }),
878
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-bundle-divider" }),
879
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "lb-bundle-summary", children: [
880
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "lb-bundle-summary__text", children: [
881
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle price" }),
882
- showSavings && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
921
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-bundle-divider" }),
922
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-bundle-summary", children: [
923
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-bundle-summary__text", children: [
924
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
925
+ showSavings && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
883
926
  "You save",
884
927
  " ",
885
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "data-savings-amount": true, children: (0, import_core8.formatMoney)(savings, currency) }),
928
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "data-savings-amount": true, children: (0, import_core8.formatMoney)(savings, currency) }),
886
929
  " ",
887
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { "data-savings-percent": true, children: [
930
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { "data-savings-percent": true, children: [
888
931
  "(",
889
932
  savingsPercent,
890
933
  "%)"
891
934
  ] })
892
935
  ] })
893
936
  ] }),
894
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
895
- showCompare && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core8.formatMoney)(comparePrice, currency) }),
896
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core8.formatMoney)(salePrice, currency) })
937
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
938
+ showCompare && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core8.formatMoney)(comparePrice, currency) }),
939
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core8.formatMoney)(salePrice, currency) })
897
940
  ] })
898
941
  ] }),
899
- cartError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
900
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
942
+ cartError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
943
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
901
944
  "button",
902
945
  {
903
946
  className: "lb-bundle__cta",
@@ -913,16 +956,20 @@ function FixedBundle(props) {
913
956
  }
914
957
  function FixedProductRow({ bundle, product, currency, isOos, onVariantChange }) {
915
958
  const variants = product.variants.nodes;
916
- const optionNames = (0, import_react7.useMemo)(() => {
959
+ const optionNames = (0, import_react8.useMemo)(() => {
917
960
  const first = variants[0];
918
961
  return first ? first.selectedOptions.map((o) => o.name) : [];
919
962
  }, [variants]);
920
963
  const showPicker = variants.length > 1 && optionNames.length > 0;
921
964
  const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({
922
965
  variants,
923
- optionNames
966
+ optionNames,
967
+ // Quantity-aware dropdown: a variant that can't cover this row's
968
+ // bundle quantity greys out instead of walking the shopper into a
969
+ // cart Shopify caps at add time.
970
+ requiredQtyFor: (variantId) => (0, import_core8.resolveBundleQty)(bundle, product.id, variantId)
924
971
  });
925
- (0, import_react7.useEffect)(() => {
972
+ (0, import_react8.useEffect)(() => {
926
973
  onVariantChange(product.id, selectedVariant ?? null);
927
974
  }, [selectedVariant, product.id, onVariantChange]);
928
975
  const displayVariant = selectedVariant ?? variants.find(
@@ -943,15 +990,15 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
943
990
  bundle.widgetConfig.lowStockThreshold,
944
991
  bundle.widgetConfig.showLowStockBadge
945
992
  );
946
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
993
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
947
994
  "div",
948
995
  {
949
996
  className: isOos ? "lb-bundle-product-row lb-bundle-product-row--oos" : "lb-bundle-product-row",
950
997
  "aria-disabled": isOos || void 0,
951
998
  part: "product",
952
999
  children: [
953
- isOos && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle-product-row__oos", children: "Out of stock" }),
954
- thumbImage && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1000
+ isOos && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle-product-row__oos", children: "Out of stock" }),
1001
+ thumbImage && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
955
1002
  "img",
956
1003
  {
957
1004
  src: thumbImage.url,
@@ -960,11 +1007,11 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
960
1007
  loading: "lazy"
961
1008
  }
962
1009
  ),
963
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "lb-bundle__product-info", children: [
964
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "lb-bundle__product-title", children: product.title }),
965
- !showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle-variant-badge", children: displayVariant.title }),
966
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "lb-bundle-product-prices", children: [
967
- compareAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1010
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-bundle__product-info", children: [
1011
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "lb-bundle__product-title", children: product.title }),
1012
+ !showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle-variant-badge", children: displayVariant.title }),
1013
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "lb-bundle-product-prices", children: [
1014
+ compareAt && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
968
1015
  "span",
969
1016
  {
970
1017
  className: "lb-bundle-product-compare-price",
@@ -972,9 +1019,9 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
972
1019
  children: compareAt
973
1020
  }
974
1021
  ),
975
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "lb-bundle__product-price", "data-product-price": true, children: priceText })
1022
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle__product-price", "data-product-price": true, children: priceText })
976
1023
  ] }),
977
- unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1024
+ unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
978
1025
  "span",
979
1026
  {
980
1027
  className: "lb-bundle__product-unit-price",
@@ -982,18 +1029,18 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
982
1029
  children: unitPriceText
983
1030
  }
984
1031
  ),
985
- showLowStock && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "lb-bundle-low-stock-badge", children: [
1032
+ showLowStock && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "lb-bundle-low-stock-badge", children: [
986
1033
  "Only ",
987
1034
  displayVariant.quantityAvailable,
988
1035
  " left"
989
1036
  ] }),
990
- showPicker && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
1037
+ showPicker && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
991
1038
  const dropdownOptions = optionsFor(optionIndex).map((o) => ({
992
1039
  value: o.value,
993
1040
  label: o.value,
994
1041
  disabled: o.disabled
995
1042
  }));
996
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1043
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
997
1044
  VariantDropdown,
998
1045
  {
999
1046
  options: dropdownOptions,
@@ -1005,7 +1052,7 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
1005
1052
  );
1006
1053
  }) })
1007
1054
  ] }),
1008
- displayVariant && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "lb-bundle-qty-chip", "data-qty-inline": true, children: [
1055
+ displayVariant && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "lb-bundle-qty-chip", "data-qty-inline": true, children: [
1009
1056
  "\xD7",
1010
1057
  displayQty
1011
1058
  ] })
@@ -1016,37 +1063,12 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
1016
1063
 
1017
1064
  // src/components/MixMatchBundle.tsx
1018
1065
  var import_react12 = require("react");
1019
- var import_core11 = require("@lime-bundles/core");
1020
-
1021
- // src/hooks/useShopSettings.ts
1022
- var import_react8 = require("react");
1023
- var import_core9 = require("@lime-bundles/core");
1024
- function useShopSettings(options) {
1025
- const [outOfStockBehavior, setOutOfStockBehavior] = (0, import_react8.useState)(import_core9.DEFAULT_OUT_OF_STOCK_BEHAVIOR);
1026
- const { shopDomain, storefrontAccessToken } = options;
1027
- (0, import_react8.useEffect)(() => {
1028
- const controller = new AbortController();
1029
- let active = true;
1030
- fetchShopSettingsOrDefault({
1031
- shopDomain,
1032
- storefrontAccessToken,
1033
- signal: controller.signal
1034
- }).then((settings) => {
1035
- if (!active || controller.signal.aborted) return;
1036
- setOutOfStockBehavior(settings.outOfStockBehavior);
1037
- });
1038
- return () => {
1039
- active = false;
1040
- controller.abort();
1041
- };
1042
- }, [shopDomain, storefrontAccessToken]);
1043
- return { outOfStockBehavior };
1044
- }
1066
+ var import_core10 = require("@lime-bundles/core");
1045
1067
 
1046
1068
  // src/components/MixMatchPicker.tsx
1047
1069
  var import_react11 = require("react");
1048
1070
  var import_react_dom = require("react-dom");
1049
- var import_core10 = require("@lime-bundles/core");
1071
+ var import_core9 = require("@lime-bundles/core");
1050
1072
 
1051
1073
  // src/hooks/useScrollLock.ts
1052
1074
  var import_react9 = require("react");
@@ -1109,6 +1131,7 @@ function useFocusTrap({
1109
1131
  active,
1110
1132
  containerRef,
1111
1133
  onEscape,
1134
+ initialFocusRef,
1112
1135
  returnFocusRef
1113
1136
  }) {
1114
1137
  const previouslyFocused = (0, import_react10.useRef)(null);
@@ -1116,7 +1139,8 @@ function useFocusTrap({
1116
1139
  if (!active) return;
1117
1140
  const container = containerRef.current;
1118
1141
  previouslyFocused.current = document.activeElement ?? null;
1119
- container?.focus();
1142
+ const initial = initialFocusRef?.current ?? container;
1143
+ initial?.focus();
1120
1144
  function onKeyDown(e) {
1121
1145
  if (e.key === "Escape") {
1122
1146
  e.preventDefault();
@@ -1154,13 +1178,13 @@ function useFocusTrap({
1154
1178
  }
1155
1179
 
1156
1180
  // src/components/MixMatchPicker.tsx
1157
- var import_jsx_runtime3 = require("react/jsx-runtime");
1181
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1158
1182
  function ruleFor(bundle, productId, variantId) {
1159
1183
  if (variantId) {
1160
1184
  const vRule = bundle.variantRules[variantId];
1161
1185
  if (vRule) return vRule;
1162
1186
  }
1163
- return bundle.productRules[productId] ?? import_core10.DEFAULT_PRODUCT_RULE;
1187
+ return bundle.productRules[productId] ?? import_core9.DEFAULT_PRODUCT_RULE;
1164
1188
  }
1165
1189
  function variantRuleFor(bundle, variantId) {
1166
1190
  return variantId ? bundle.variantRules[variantId] : void 0;
@@ -1168,7 +1192,7 @@ function variantRuleFor(bundle, variantId) {
1168
1192
  function sanitizeId(gid) {
1169
1193
  return gid.replace(/[^a-zA-Z0-9_-]/g, "-");
1170
1194
  }
1171
- function buildEligibleProducts(bundle, oosBehavior) {
1195
+ function buildEligibleProducts(bundle) {
1172
1196
  const result = [];
1173
1197
  const seen = /* @__PURE__ */ new Set();
1174
1198
  for (const product of bundle.products) {
@@ -1176,10 +1200,9 @@ function buildEligibleProducts(bundle, oosBehavior) {
1176
1200
  seen.add(product.id);
1177
1201
  const rule = ruleFor(bundle, product.id);
1178
1202
  const available = product.variants.nodes.filter(
1179
- (v) => (0, import_core10.isVariantFulfillable)(v, rule.min)
1203
+ (v) => (0, import_core9.isVariantFulfillable)(v, rule.min)
1180
1204
  );
1181
1205
  const isOos = available.length === 0;
1182
- if (isOos && oosBehavior === "hide") continue;
1183
1206
  result.push({
1184
1207
  product,
1185
1208
  variants: product.variants.nodes,
@@ -1194,7 +1217,6 @@ function normalizeText(str) {
1194
1217
  }
1195
1218
  var FILTERS_ALL = "__all__";
1196
1219
  function MixMatchPicker({
1197
- outOfStockBehavior,
1198
1220
  bundle,
1199
1221
  currency,
1200
1222
  requiredQty,
@@ -1212,13 +1234,14 @@ function MixMatchPicker({
1212
1234
  const wc = bundle.widgetConfig;
1213
1235
  const overlayRef = (0, import_react11.useRef)(null);
1214
1236
  const dialogRef = (0, import_react11.useRef)(null);
1237
+ const closeBtnRef = (0, import_react11.useRef)(null);
1215
1238
  const mouseDownTarget = (0, import_react11.useRef)(null);
1216
1239
  const [open, setOpen] = (0, import_react11.useState)(false);
1217
1240
  const [query, setQuery] = (0, import_react11.useState)("");
1218
1241
  const [activeType, setActiveType] = (0, import_react11.useState)(FILTERS_ALL);
1219
1242
  const eligible = (0, import_react11.useMemo)(
1220
- () => buildEligibleProducts(bundle, outOfStockBehavior),
1221
- [bundle, outOfStockBehavior]
1243
+ () => buildEligibleProducts(bundle),
1244
+ [bundle]
1222
1245
  );
1223
1246
  const productTypes = (0, import_react11.useMemo)(() => {
1224
1247
  const types = [];
@@ -1244,6 +1267,7 @@ function MixMatchPicker({
1244
1267
  useFocusTrap({
1245
1268
  active: true,
1246
1269
  containerRef: dialogRef,
1270
+ initialFocusRef: closeBtnRef,
1247
1271
  onEscape: onClose
1248
1272
  });
1249
1273
  const remaining = Math.max(0, requiredQty - shownUnits);
@@ -1252,14 +1276,25 @@ function MixMatchPicker({
1252
1276
  const pct = bundle.discountConfig.discountType === "percentage" && bundle.discountConfig.discountValue ? Math.round(bundle.discountConfig.discountValue) : 0;
1253
1277
  return pct > 0 ? `Choose ${remaining} more to unlock ${pct}% off` : `Choose ${remaining} more to complete your bundle`;
1254
1278
  })();
1279
+ const [selectedAtOpen] = (0, import_react11.useState)(
1280
+ () => new Set(selections.map((s) => s.productId))
1281
+ );
1282
+ const ordered = (0, import_react11.useMemo)(() => {
1283
+ const front = [];
1284
+ const back = [];
1285
+ for (const ep of eligible) {
1286
+ (selectedAtOpen.has(ep.product.id) ? back : front).push(ep);
1287
+ }
1288
+ return front.concat(back);
1289
+ }, [eligible, selectedAtOpen]);
1255
1290
  const filtered = (0, import_react11.useMemo)(() => {
1256
1291
  const nq = normalizeText(query.trim());
1257
- return eligible.filter((ep) => {
1292
+ return ordered.filter((ep) => {
1258
1293
  const matchesQuery = !nq || normalizeText(ep.product.title).includes(nq);
1259
1294
  const matchesType = activeType === FILTERS_ALL || (ep.product.productType ?? "") === activeType;
1260
1295
  return matchesQuery && matchesType;
1261
1296
  });
1262
- }, [eligible, query, activeType]);
1297
+ }, [ordered, query, activeType]);
1263
1298
  const showEmpty = filtered.length === 0 && query.trim().length > 0;
1264
1299
  function onOverlayMouseDown(e) {
1265
1300
  mouseDownTarget.current = e.target;
@@ -1277,7 +1312,7 @@ function MixMatchPicker({
1277
1312
  // inside carries the interactive role + focus trap. So the static-element
1278
1313
  // interaction lint does not apply to this backdrop.
1279
1314
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
1280
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1315
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1281
1316
  "div",
1282
1317
  {
1283
1318
  ref: (el) => {
@@ -1289,7 +1324,7 @@ function MixMatchPicker({
1289
1324
  "data-bundle-gid": bundle.id,
1290
1325
  onMouseDown: onOverlayMouseDown,
1291
1326
  onMouseUp: onOverlayMouseUp,
1292
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1327
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1293
1328
  "div",
1294
1329
  {
1295
1330
  ref: dialogRef,
@@ -1299,30 +1334,31 @@ function MixMatchPicker({
1299
1334
  "aria-labelledby": titleId,
1300
1335
  tabIndex: -1,
1301
1336
  children: [
1302
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-header", children: [
1303
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-header-top", children: [
1304
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-heading", children: [
1305
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h4", { className: "lb-mix-match__modal-title", id: titleId, children: "Add to your bundle" }),
1306
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "lb-mix-match__modal-subtitle", "data-modal-subtitle": true, children: subtitle })
1337
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-header", children: [
1338
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-header-top", children: [
1339
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-heading", children: [
1340
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h4", { className: "lb-mix-match__modal-title", id: titleId, children: "Add to your bundle" }),
1341
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "lb-mix-match__modal-subtitle", "data-modal-subtitle": true, children: subtitle })
1307
1342
  ] }),
1308
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1343
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1309
1344
  "button",
1310
1345
  {
1346
+ ref: closeBtnRef,
1311
1347
  type: "button",
1312
1348
  className: "lb-mix-match__modal-close",
1313
1349
  "data-modal-close": true,
1314
1350
  "aria-label": "Close",
1315
1351
  onClick: onClose,
1316
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CloseIcon, {})
1352
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, {})
1317
1353
  }
1318
1354
  )
1319
1355
  ] }),
1320
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1356
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1321
1357
  "div",
1322
1358
  {
1323
1359
  className: "lb-mix-match__progress lb-mix-match__modal-progress",
1324
1360
  "data-progress": true,
1325
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1361
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1326
1362
  "div",
1327
1363
  {
1328
1364
  className: "lb-mix-match__progress-segments",
@@ -1330,7 +1366,7 @@ function MixMatchPicker({
1330
1366
  "aria-valuenow": shownUnits,
1331
1367
  "aria-valuemin": 0,
1332
1368
  "aria-valuemax": requiredQty,
1333
- children: Array.from({ length: requiredQty }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1369
+ children: Array.from({ length: requiredQty }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1334
1370
  "span",
1335
1371
  {
1336
1372
  className: `lb-mix-match__progress-segment${i < shownUnits ? " lb-mix-match__progress-segment--filled" : ""}`,
@@ -1343,8 +1379,8 @@ function MixMatchPicker({
1343
1379
  }
1344
1380
  )
1345
1381
  ] }),
1346
- wc.showSearch && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-search", children: [
1347
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1382
+ wc.showSearch && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-search", children: [
1383
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1348
1384
  "input",
1349
1385
  {
1350
1386
  type: "text",
@@ -1358,7 +1394,7 @@ function MixMatchPicker({
1358
1394
  onChange: (e) => setQuery(e.target.value)
1359
1395
  }
1360
1396
  ),
1361
- query.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1397
+ query.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1362
1398
  "button",
1363
1399
  {
1364
1400
  type: "button",
@@ -1366,11 +1402,11 @@ function MixMatchPicker({
1366
1402
  "data-modal-search-clear": true,
1367
1403
  "aria-label": "Clear search",
1368
1404
  onClick: () => setQuery(""),
1369
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SearchClearIcon, {})
1405
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SearchClearIcon, {})
1370
1406
  }
1371
1407
  )
1372
1408
  ] }),
1373
- showFilters && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1409
+ showFilters && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1374
1410
  "div",
1375
1411
  {
1376
1412
  className: "lb-mix-match__filters",
@@ -1379,7 +1415,7 @@ function MixMatchPicker({
1379
1415
  "aria-label": "Filter by product type",
1380
1416
  children: [FILTERS_ALL, ...productTypes].map((value) => {
1381
1417
  const isActive = value === activeType;
1382
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1418
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1383
1419
  "button",
1384
1420
  {
1385
1421
  type: "button",
@@ -1394,7 +1430,7 @@ function MixMatchPicker({
1394
1430
  })
1395
1431
  }
1396
1432
  ),
1397
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-mix-match__modal-list", "data-modal-list": true, children: filtered.map((ep) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1433
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-mix-match__modal-list", "data-modal-list": true, children: filtered.map((ep) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1398
1434
  MixMatchPickerRow,
1399
1435
  {
1400
1436
  bundle,
@@ -1413,10 +1449,10 @@ function MixMatchPicker({
1413
1449
  },
1414
1450
  ep.product.id
1415
1451
  )) }),
1416
- showEmpty && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-mix-match__modal-empty", "data-modal-empty": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "No products match your search" }) }),
1417
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "data-modal-live": true, "aria-live": "polite", className: "lb-visually-hidden", children: `${filtered.length} products shown` }),
1418
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-footer", children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1452
+ showEmpty && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-mix-match__modal-empty", "data-modal-empty": true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: "No products match your search" }) }),
1453
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-modal-live": true, "aria-live": "polite", className: "lb-visually-hidden", children: `${filtered.length} products shown` }),
1454
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-footer", children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1420
1456
  "span",
1421
1457
  {
1422
1458
  className: "lb-mix-match__modal-footer-count",
@@ -1425,7 +1461,7 @@ function MixMatchPicker({
1425
1461
  children: `${shownUnits} of ${requiredQty} added`
1426
1462
  }
1427
1463
  ),
1428
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1464
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1429
1465
  "button",
1430
1466
  {
1431
1467
  type: "button",
@@ -1468,7 +1504,7 @@ function MixMatchPickerRow({
1468
1504
  }, [variants]);
1469
1505
  const showPicker = variants.length > 1 && optionNames.length > 0;
1470
1506
  const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
1471
- const currentVariant = selectedVariant ?? variants.find((v) => (0, import_core10.isVariantFulfillable)(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
1507
+ const currentVariant = selectedVariant ?? variants.find((v) => (0, import_core9.isVariantFulfillable)(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
1472
1508
  const vRule = ruleFor(bundle, product.id, currentVariant?.id);
1473
1509
  const variantMax = variantRuleFor(bundle, currentVariant?.id)?.max;
1474
1510
  const alreadyInBundle = (0, import_react11.useMemo)(() => {
@@ -1504,7 +1540,7 @@ function MixMatchPickerRow({
1504
1540
  committedQty + remainingUnits,
1505
1541
  variantMax ?? Infinity
1506
1542
  );
1507
- const cap = currentVariant ? (0, import_core10.maxAddableQuantity)(
1543
+ const cap = currentVariant ? (0, import_core9.maxAddableQuantity)(
1508
1544
  currentVariant,
1509
1545
  spotCeiling,
1510
1546
  Math.max(0, alreadyInBundle - committedQty)
@@ -1520,7 +1556,7 @@ function MixMatchPickerRow({
1520
1556
  }, [variantInBundle, currentVariantId, vRule.min]);
1521
1557
  if (!currentVariant) return null;
1522
1558
  const thumbImage = currentVariant.image ?? product.featuredImage ?? null;
1523
- const unitPriceText = (0, import_core10.formatUnitPrice)(
1559
+ const unitPriceText = (0, import_core9.formatUnitPrice)(
1524
1560
  currentVariant.unitPrice,
1525
1561
  currentVariant.unitPriceMeasurement,
1526
1562
  currency
@@ -1559,7 +1595,7 @@ function MixMatchPickerRow({
1559
1595
  }
1560
1596
  const priceCents = parseFloat(currentVariant.price.amount);
1561
1597
  const compareCents = currentVariant.compareAtPrice ? parseFloat(currentVariant.compareAtPrice.amount) : null;
1562
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1598
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1563
1599
  "div",
1564
1600
  {
1565
1601
  className: `lb-mix-match__modal-product${isOos ? " lb-mix-match__modal-product--sold-out" : ""}${variantInBundle ? " lb-mix-match__modal-product--in-bundle" : ""}`,
@@ -1568,8 +1604,8 @@ function MixMatchPickerRow({
1568
1604
  "data-type": product.productType ?? "",
1569
1605
  "aria-disabled": isOos || void 0,
1570
1606
  children: [
1571
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-product-thumb", children: [
1572
- thumbImage && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1607
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-product-thumb", children: [
1608
+ thumbImage && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1573
1609
  "img",
1574
1610
  {
1575
1611
  src: thumbImage.url,
@@ -1577,10 +1613,10 @@ function MixMatchPickerRow({
1577
1613
  loading: "lazy"
1578
1614
  }
1579
1615
  ),
1580
- variantInBundle && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-mix-match__modal-added-badge", children: "Added" })
1616
+ variantInBundle && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__modal-added-badge", children: "Added" })
1581
1617
  ] }),
1582
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-product-info", children: [
1583
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "lb-mix-match__modal-product-title", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1618
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-product-info", children: [
1619
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "lb-mix-match__modal-product-title", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1584
1620
  "a",
1585
1621
  {
1586
1622
  href: `/products/${product.handle}`,
@@ -1589,24 +1625,24 @@ function MixMatchPickerRow({
1589
1625
  children: product.title
1590
1626
  }
1591
1627
  ) }),
1592
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "lb-mix-match__modal-product-price", children: [
1593
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "data-row-price-sale": true, children: (0, import_core10.formatMoney)(priceCents, currency) }),
1594
- compareCents !== null && compareCents > priceCents && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("s", { className: "lb-mix-match__modal-product-compare", "data-row-compare": true, children: (0, import_core10.formatMoney)(compareCents, currency) })
1628
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "lb-mix-match__modal-product-price", children: [
1629
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-row-price-sale": true, children: (0, import_core9.formatMoney)(priceCents, currency) }),
1630
+ compareCents !== null && compareCents > priceCents && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("s", { className: "lb-mix-match__modal-product-compare", "data-row-compare": true, children: (0, import_core9.formatMoney)(compareCents, currency) })
1595
1631
  ] }),
1596
- unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price", children: unitPriceText }),
1597
- showPicker && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-bundle-variant-option-groups", children: optionNames.map((optionName, optionIndex) => {
1632
+ unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price", children: unitPriceText }),
1633
+ showPicker && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-bundle-variant-option-groups", children: optionNames.map((optionName, optionIndex) => {
1598
1634
  const dropdownOptions = optionsFor(optionIndex).map((o) => ({
1599
1635
  value: o.value,
1600
1636
  label: o.value,
1601
1637
  disabled: o.disabled
1602
1638
  }));
1603
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1639
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1604
1640
  "div",
1605
1641
  {
1606
1642
  className: "lb-bundle-variant-option-group",
1607
1643
  children: [
1608
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle-variant-option-label", children: optionName }),
1609
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1644
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-variant-option-label", children: optionName }),
1645
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1610
1646
  VariantDropdown,
1611
1647
  {
1612
1648
  className: "lb-mix-match__variant-select-dropdown",
@@ -1621,17 +1657,17 @@ function MixMatchPickerRow({
1621
1657
  optionName
1622
1658
  );
1623
1659
  }) }),
1624
- !showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
1625
- !isOos && needsMoreSpots && remainingUnits > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-mix-match__modal-needs-spots", children: rule.min === 1 ? "Needs 1 spot" : `Needs ${rule.min} spots` }),
1626
- isOos ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "lb-mix-match__modal-product-actions", children: [
1627
- showStepper && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1660
+ !showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
1661
+ !isOos && needsMoreSpots && remainingUnits > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__modal-needs-spots", children: rule.min === 1 ? "Needs 1 spot" : `Needs ${rule.min} spots` }),
1662
+ isOos ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__modal-product-actions", children: [
1663
+ showStepper && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1628
1664
  "div",
1629
1665
  {
1630
1666
  className: "lb-mix-match__qty-stepper",
1631
1667
  role: "group",
1632
1668
  "aria-label": "Quantity",
1633
1669
  children: [
1634
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1670
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1635
1671
  "button",
1636
1672
  {
1637
1673
  type: "button",
@@ -1652,7 +1688,7 @@ function MixMatchPickerRow({
1652
1688
  children: "\u2212"
1653
1689
  }
1654
1690
  ),
1655
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1691
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1656
1692
  "span",
1657
1693
  {
1658
1694
  className: "lb-mix-match__qty-stepper-value",
@@ -1661,7 +1697,7 @@ function MixMatchPickerRow({
1661
1697
  children: shownQty
1662
1698
  }
1663
1699
  ),
1664
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1700
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1665
1701
  "button",
1666
1702
  {
1667
1703
  type: "button",
@@ -1685,7 +1721,7 @@ function MixMatchPickerRow({
1685
1721
  ]
1686
1722
  }
1687
1723
  ) }),
1688
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1724
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1689
1725
  "button",
1690
1726
  {
1691
1727
  type: "button",
@@ -1704,7 +1740,7 @@ function MixMatchPickerRow({
1704
1740
  );
1705
1741
  }
1706
1742
  function CloseIcon() {
1707
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1743
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1708
1744
  "svg",
1709
1745
  {
1710
1746
  width: "20",
@@ -1714,14 +1750,14 @@ function CloseIcon() {
1714
1750
  xmlns: "http://www.w3.org/2000/svg",
1715
1751
  "aria-hidden": "true",
1716
1752
  children: [
1717
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1718
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
1753
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1754
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
1719
1755
  ]
1720
1756
  }
1721
1757
  );
1722
1758
  }
1723
1759
  function SearchClearIcon() {
1724
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1760
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1725
1761
  "svg",
1726
1762
  {
1727
1763
  width: "16",
@@ -1730,19 +1766,19 @@ function SearchClearIcon() {
1730
1766
  fill: "currentColor",
1731
1767
  xmlns: "http://www.w3.org/2000/svg",
1732
1768
  "aria-hidden": "true",
1733
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M14.348 5.652a.5.5 0 0 0-.707 0L10 9.293 6.36 5.652a.5.5 0 1 0-.708.707L9.293 10l-3.641 3.641a.5.5 0 0 0 .708.707L10 10.707l3.641 3.641a.5.5 0 0 0 .707-.707L10.707 10l3.641-3.641a.5.5 0 0 0 0-.707z" })
1769
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M14.348 5.652a.5.5 0 0 0-.707 0L10 9.293 6.36 5.652a.5.5 0 1 0-.708.707L9.293 10l-3.641 3.641a.5.5 0 0 0 .708.707L10 10.707l3.641 3.641a.5.5 0 0 0 .707-.707L10.707 10l3.641-3.641a.5.5 0 0 0 0-.707z" })
1734
1770
  }
1735
1771
  );
1736
1772
  }
1737
1773
 
1738
1774
  // src/components/MixMatchBundle.tsx
1739
- var import_jsx_runtime4 = require("react/jsx-runtime");
1775
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1740
1776
  function ruleFor2(bundle, productId, variantId) {
1741
1777
  if (variantId) {
1742
1778
  const vRule = bundle.variantRules[variantId];
1743
1779
  if (vRule) return vRule;
1744
1780
  }
1745
- return bundle.productRules[productId] ?? import_core11.DEFAULT_PRODUCT_RULE;
1781
+ return bundle.productRules[productId] ?? import_core10.DEFAULT_PRODUCT_RULE;
1746
1782
  }
1747
1783
  function variantRuleFor2(bundle, variantId) {
1748
1784
  return variantId ? bundle.variantRules[variantId] : void 0;
@@ -1769,17 +1805,14 @@ function MixMatchBundle(props) {
1769
1805
  analyticsEnabled,
1770
1806
  onAddToCart,
1771
1807
  onError,
1772
- className
1808
+ className,
1809
+ productHandle
1773
1810
  } = props;
1774
1811
  const result = useBundleData({
1775
1812
  shopDomain,
1776
1813
  storefrontAccessToken,
1777
1814
  bundleGid
1778
1815
  });
1779
- const { outOfStockBehavior } = useShopSettings({
1780
- shopDomain,
1781
- storefrontAccessToken
1782
- });
1783
1816
  const { elementRef, trackAddToCart } = useAnalytics({
1784
1817
  shopDomain,
1785
1818
  appUrl: appUrl ?? `https://${shopDomain}`,
@@ -1813,33 +1846,60 @@ function MixMatchBundle(props) {
1813
1846
  if (!bundle || seededFor === bundle.id) return;
1814
1847
  setSeededFor(bundle.id);
1815
1848
  const seedCurrency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
1849
+ const pick = (product, variant, quantity) => ({
1850
+ productId: product.id,
1851
+ variantId: variant.id,
1852
+ title: product.title,
1853
+ url: `/products/${product.handle}`,
1854
+ variantTitle: variant.title,
1855
+ featuredImage: variant.image?.url ?? product.featuredImage?.url ?? null,
1856
+ price: parseFloat(variant.price.amount),
1857
+ compareAtPrice: variant.compareAtPrice ? parseFloat(variant.compareAtPrice.amount) : null,
1858
+ unitPrice: (0, import_core10.formatUnitPrice)(
1859
+ variant.unitPrice,
1860
+ variant.unitPriceMeasurement,
1861
+ seedCurrency
1862
+ ),
1863
+ quantity
1864
+ });
1816
1865
  const seeds = [];
1817
- for (const [pid, rule] of Object.entries(bundle.productRules)) {
1818
- if (!rule.required) continue;
1819
- const product = bundle.products.find((p) => p.id === pid);
1820
- const variant = product?.variants.nodes.find(
1821
- (v) => (0, import_core11.isVariantFulfillable)(v, rule.min)
1866
+ for (const product of bundle.products) {
1867
+ let seededVariant = false;
1868
+ for (const variant2 of product.variants.nodes) {
1869
+ const vRule = bundle.variantRules[variant2.id];
1870
+ if (!vRule?.required) continue;
1871
+ if (!(0, import_core10.isVariantFulfillable)(variant2, Math.max(1, vRule.min))) continue;
1872
+ seeds.push(pick(product, variant2, Math.max(1, vRule.min)));
1873
+ seededVariant = true;
1874
+ }
1875
+ if (seededVariant) continue;
1876
+ const rule = bundle.productRules[product.id];
1877
+ if (!rule?.required) continue;
1878
+ const variant = product.variants.nodes.find(
1879
+ (v) => (0, import_core10.isVariantFulfillable)(v, rule.min)
1822
1880
  );
1823
- if (!product || !variant) continue;
1824
- seeds.push({
1825
- productId: product.id,
1826
- variantId: variant.id,
1827
- title: product.title,
1828
- url: `/products/${product.handle}`,
1829
- variantTitle: variant.title,
1830
- featuredImage: variant.image?.url ?? product.featuredImage?.url ?? null,
1831
- price: parseFloat(variant.price.amount),
1832
- compareAtPrice: variant.compareAtPrice ? parseFloat(variant.compareAtPrice.amount) : null,
1833
- unitPrice: (0, import_core11.formatUnitPrice)(
1834
- variant.unitPrice,
1835
- variant.unitPriceMeasurement,
1836
- seedCurrency
1837
- ),
1838
- quantity: rule.min
1839
- });
1881
+ if (!variant) continue;
1882
+ seeds.push(pick(product, variant, rule.min));
1883
+ }
1884
+ if (seeds.length === 0 && productHandle) {
1885
+ const requiredUnits2 = bundle.minQuantity ?? 0;
1886
+ const qualifies = (p) => {
1887
+ const min = bundle.productRules[p.id]?.min ?? 1;
1888
+ return min <= requiredUnits2 && p.variants.nodes.some((v) => (0, import_core10.isVariantFulfillable)(v, min));
1889
+ };
1890
+ const seed = bundle.products.find(
1891
+ (p) => p.handle === productHandle && qualifies(p)
1892
+ ) ?? bundle.products.find(qualifies);
1893
+ if (seed) {
1894
+ const min = bundle.productRules[seed.id]?.min ?? 1;
1895
+ const variant = seed.variants.nodes.find(
1896
+ (v) => (0, import_core10.isVariantFulfillable)(v, min)
1897
+ );
1898
+ if (variant) seeds.push(pick(seed, variant, min));
1899
+ }
1840
1900
  }
1841
1901
  if (seeds.length > 0) setSelections(seeds);
1842
- }, [bundle, seededFor]);
1902
+ }, [bundle, seededFor, productHandle]);
1843
1903
  const showStepper = bundle?.widgetConfig.mixMatchShowQuantitySelector !== false;
1844
1904
  const requiredUnits = bundle?.minQuantity ?? 0;
1845
1905
  const totalQuantity = (0, import_react12.useMemo)(
@@ -1857,7 +1917,7 @@ function MixMatchBundle(props) {
1857
1917
  if (sel.quantity <= 0) continue;
1858
1918
  comparePrice += sel.price * sel.quantity;
1859
1919
  if (bundle) {
1860
- salePrice += (0, import_core11.calculateDiscount)(
1920
+ salePrice += (0, import_core10.calculateDiscount)(
1861
1921
  sel.price,
1862
1922
  bundle.discountConfig.discountType,
1863
1923
  bundle.discountConfig.discountValue
@@ -1999,9 +2059,9 @@ function MixMatchBundle(props) {
1999
2059
  }
2000
2060
  }, [bundle, selections, valid, onAddToCart, onError, trackAddToCart, totalQuantity]);
2001
2061
  if (result.status === "loading") {
2002
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
2003
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
2004
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
2062
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
2063
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
2064
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
2005
2065
  ] });
2006
2066
  }
2007
2067
  if (result.status === "error") return null;
@@ -2013,14 +2073,14 @@ function MixMatchBundle(props) {
2013
2073
  if (!rule.required) return false;
2014
2074
  const product = bundle.products.find((p) => p.id === pid);
2015
2075
  return !product?.variants.nodes.some(
2016
- (v) => (0, import_core11.isVariantFulfillable)(v, rule.min)
2076
+ (v) => (0, import_core10.isVariantFulfillable)(v, rule.min)
2017
2077
  );
2018
2078
  }
2019
2079
  );
2020
2080
  if (requiredBlocked) return null;
2021
2081
  const currency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
2022
2082
  const ctaLabel = addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText || "Add to cart";
2023
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2083
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2024
2084
  "div",
2025
2085
  {
2026
2086
  ref: (el) => {
@@ -2032,12 +2092,19 @@ function MixMatchBundle(props) {
2032
2092
  "aria-label": bundle.title,
2033
2093
  "data-required-quantity": requiredUnits,
2034
2094
  children: [
2035
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-bundle-header__content", children: [
2036
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
2037
- bundle.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
2095
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-header__content", children: [
2096
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
2097
+ bundle.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
2038
2098
  ] }) }),
2039
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__progress", "data-progress": true, children: [
2040
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2099
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2100
+ BundleCountdown,
2101
+ {
2102
+ endsAt: bundle.endsAt,
2103
+ widgetConfig: bundle.widgetConfig
2104
+ }
2105
+ ),
2106
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-mix-match__progress", "data-progress": true, children: [
2107
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2041
2108
  "div",
2042
2109
  {
2043
2110
  className: "lb-mix-match__progress-segments",
@@ -2045,7 +2112,7 @@ function MixMatchBundle(props) {
2045
2112
  "aria-valuenow": shownUnits,
2046
2113
  "aria-valuemin": 0,
2047
2114
  "aria-valuemax": requiredUnits,
2048
- children: Array.from({ length: requiredUnits }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2115
+ children: Array.from({ length: requiredUnits }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2049
2116
  "span",
2050
2117
  {
2051
2118
  className: `lb-mix-match__progress-segment${i < shownUnits ? " lb-mix-match__progress-segment--filled" : ""}`,
@@ -2055,8 +2122,8 @@ function MixMatchBundle(props) {
2055
2122
  ))
2056
2123
  }
2057
2124
  ),
2058
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__progress-labels", children: [
2059
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2125
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-mix-match__progress-labels", children: [
2126
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2060
2127
  "span",
2061
2128
  {
2062
2129
  className: "lb-mix-match__progress-count",
@@ -2065,7 +2132,7 @@ function MixMatchBundle(props) {
2065
2132
  children: `${shownUnits} of ${requiredUnits} added`
2066
2133
  }
2067
2134
  ),
2068
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2135
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2069
2136
  "span",
2070
2137
  {
2071
2138
  className: "lb-mix-match__progress-remaining",
@@ -2076,7 +2143,7 @@ function MixMatchBundle(props) {
2076
2143
  )
2077
2144
  ] })
2078
2145
  ] }),
2079
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2146
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2080
2147
  "div",
2081
2148
  {
2082
2149
  className: "lb-mix-match__slots lb-edge-fade",
@@ -2087,15 +2154,15 @@ function MixMatchBundle(props) {
2087
2154
  button provides the keyboard/AT path (its activation bubbles
2088
2155
  here); × stops propagation. */
2089
2156
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions -- keyboard path is the inner "Edit selection" title button whose activation bubbles to this handler
2090
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2157
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2091
2158
  "div",
2092
2159
  {
2093
2160
  className: "lb-mix-match__slot lb-mix-match__slot--filled",
2094
2161
  onClick: () => setPickerOpen(true),
2095
2162
  children: [
2096
- item.featuredImage && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-bundle-thumbnail", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: item.featuredImage, alt: item.title, loading: "lazy" }) }),
2097
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-mix-match__filled-info", children: [
2098
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2163
+ item.featuredImage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-bundle-thumbnail", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: item.featuredImage, alt: item.title, loading: "lazy" }) }),
2164
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-mix-match__filled-info", children: [
2165
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2099
2166
  "button",
2100
2167
  {
2101
2168
  type: "button",
@@ -2104,15 +2171,15 @@ function MixMatchBundle(props) {
2104
2171
  children: item.title
2105
2172
  }
2106
2173
  ),
2107
- item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__filled-variant", children: item.variantTitle }),
2108
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "lb-mix-match__filled-price", children: [
2109
- item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("s", { className: "lb-mix-match__filled-compare", children: (0, import_core11.formatMoney)(item.compareAtPrice, currency) }),
2110
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-product-price", children: (0, import_core11.formatMoney)(item.price, currency) }),
2111
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-qty-inline", children: `\xD7${item.quantity}` })
2174
+ item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-mix-match__filled-variant", children: item.variantTitle }),
2175
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-mix-match__filled-price", children: [
2176
+ item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("s", { className: "lb-mix-match__filled-compare", children: (0, import_core10.formatMoney)(item.compareAtPrice, currency) }),
2177
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-product-price", children: (0, import_core10.formatMoney)(item.price, currency) }),
2178
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-qty-inline", children: `\xD7${item.quantity}` })
2112
2179
  ] }),
2113
- item.unitPrice && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-product-unit-price", children: item.unitPrice })
2180
+ item.unitPrice && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-product-unit-price", children: item.unitPrice })
2114
2181
  ] }),
2115
- canRemoveItem(bundle, selections, item) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2182
+ canRemoveItem(bundle, selections, item) ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2116
2183
  "button",
2117
2184
  {
2118
2185
  type: "button",
@@ -2122,13 +2189,13 @@ function MixMatchBundle(props) {
2122
2189
  e.stopPropagation();
2123
2190
  removeSlot(index);
2124
2191
  },
2125
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon2, {})
2192
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CloseIcon2, {})
2126
2193
  }
2127
2194
  ) : (
2128
2195
  /* Required pick at its floor — quiet state chip instead of
2129
2196
  the ×; removal returns once another slot covers the
2130
2197
  product's minimum (variant swap flow). */
2131
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__slot-required", children: "Required" })
2198
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-mix-match__slot-required", children: "Required" })
2132
2199
  )
2133
2200
  ]
2134
2201
  },
@@ -2137,7 +2204,7 @@ function MixMatchBundle(props) {
2137
2204
  ))
2138
2205
  }
2139
2206
  ),
2140
- totalQuantity < requiredUnits && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2207
+ totalQuantity < requiredUnits && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2141
2208
  "button",
2142
2209
  {
2143
2210
  type: "button",
@@ -2145,34 +2212,34 @@ function MixMatchBundle(props) {
2145
2212
  "data-add-product-trigger": true,
2146
2213
  onClick: () => setPickerOpen(true),
2147
2214
  children: [
2148
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__add-product-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PlusIcon, {}) }),
2149
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-mix-match__add-product-label", children: "Add a product" })
2215
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-mix-match__add-product-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PlusIcon, {}) }),
2216
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-mix-match__add-product-label", children: "Add a product" })
2150
2217
  ]
2151
2218
  }
2152
2219
  ),
2153
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lb-bundle-divider" }),
2154
- selections.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-bundle-summary", "data-pricing-section": true, children: [
2155
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lb-bundle-summary__text", children: [
2156
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
2157
- bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
2220
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-bundle-divider" }),
2221
+ selections.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-summary", "data-pricing-section": true, children: [
2222
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-summary__text", children: [
2223
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
2224
+ bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
2158
2225
  "You save",
2159
2226
  " ",
2160
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-savings-amount": true, children: (0, import_core11.formatMoney)(summary.savings, currency) }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "data-savings-amount": true, children: (0, import_core10.formatMoney)(summary.savings, currency) }),
2161
2228
  " ",
2162
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { "data-savings-percent": true, children: [
2229
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-savings-percent": true, children: [
2163
2230
  "(",
2164
2231
  summary.savingsPercent,
2165
2232
  "%)"
2166
2233
  ] })
2167
2234
  ] })
2168
2235
  ] }),
2169
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
2170
- bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core11.formatMoney)(summary.comparePrice, currency) }),
2171
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core11.formatMoney)(summary.salePrice, currency) })
2236
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
2237
+ bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core10.formatMoney)(summary.comparePrice, currency) }),
2238
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core10.formatMoney)(summary.salePrice, currency) })
2172
2239
  ] })
2173
2240
  ] }),
2174
- cartError && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
2175
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2241
+ cartError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
2242
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2176
2243
  "button",
2177
2244
  {
2178
2245
  className: "lb-bundle__cta",
@@ -2182,10 +2249,9 @@ function MixMatchBundle(props) {
2182
2249
  children: ctaLabel
2183
2250
  }
2184
2251
  ),
2185
- pickerOpen && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2252
+ pickerOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2186
2253
  MixMatchPicker,
2187
2254
  {
2188
- outOfStockBehavior,
2189
2255
  bundle,
2190
2256
  currency,
2191
2257
  requiredQty: requiredUnits,
@@ -2216,14 +2282,14 @@ function countInStockProducts(bundle) {
2216
2282
  seen.add(product.id);
2217
2283
  const rule = ruleFor2(bundle, product.id);
2218
2284
  const fulfillable = product.variants.nodes.some(
2219
- (v) => (0, import_core11.isVariantFulfillable)(v, rule.min)
2285
+ (v) => (0, import_core10.isVariantFulfillable)(v, rule.min)
2220
2286
  );
2221
2287
  if (fulfillable) count += 1;
2222
2288
  }
2223
2289
  return count;
2224
2290
  }
2225
2291
  function PlusIcon() {
2226
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2292
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2227
2293
  "svg",
2228
2294
  {
2229
2295
  width: "18",
@@ -2233,14 +2299,14 @@ function PlusIcon() {
2233
2299
  xmlns: "http://www.w3.org/2000/svg",
2234
2300
  "aria-hidden": "true",
2235
2301
  children: [
2236
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
2237
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2302
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
2303
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2238
2304
  ]
2239
2305
  }
2240
2306
  );
2241
2307
  }
2242
2308
  function CloseIcon2() {
2243
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2309
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2244
2310
  "svg",
2245
2311
  {
2246
2312
  width: "16",
@@ -2250,8 +2316,8 @@ function CloseIcon2() {
2250
2316
  xmlns: "http://www.w3.org/2000/svg",
2251
2317
  "aria-hidden": "true",
2252
2318
  children: [
2253
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
2254
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2319
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
2320
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2255
2321
  ]
2256
2322
  }
2257
2323
  );
@@ -2259,8 +2325,8 @@ function CloseIcon2() {
2259
2325
 
2260
2326
  // src/components/VolumeBundle.tsx
2261
2327
  var import_react13 = require("react");
2262
- var import_core12 = require("@lime-bundles/core");
2263
- var import_jsx_runtime5 = require("react/jsx-runtime");
2328
+ var import_core11 = require("@lime-bundles/core");
2329
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2264
2330
  function VolumeBundle(props) {
2265
2331
  const {
2266
2332
  shopDomain,
@@ -2287,7 +2353,24 @@ function VolumeBundle(props) {
2287
2353
  const [quantity, setQuantity] = (0, import_react13.useState)(1);
2288
2354
  const [addingToCart, setAddingToCart] = (0, import_react13.useState)(false);
2289
2355
  const [cartError, setCartError] = (0, import_react13.useState)(null);
2356
+ const [seededFor, setSeededFor] = (0, import_react13.useState)(null);
2290
2357
  const bundle = result.status === "success" && result.bundle.bundleType === "volume" ? result.bundle : null;
2358
+ (0, import_react13.useEffect)(() => {
2359
+ if (!bundle || seededFor === bundle.id) return;
2360
+ setSeededFor(bundle.id);
2361
+ const tiers = bundle.volumeTiers;
2362
+ if (tiers.length === 0) return;
2363
+ const best = (0, import_core11.bestValueTierIndex)(
2364
+ tiers,
2365
+ bundle.discountConfig.discountType
2366
+ );
2367
+ const idx = (0, import_core11.resolveDefaultTierIndex)(
2368
+ bundle.widgetConfig.defaultTier,
2369
+ tiers.length,
2370
+ best
2371
+ );
2372
+ setQuantity(tiers[idx].minQuantity);
2373
+ }, [bundle, seededFor]);
2291
2374
  const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
2292
2375
  const tiersEdgeFadeRef = useEdgeFade();
2293
2376
  (0, import_react13.useEffect)(() => {
@@ -2311,19 +2394,24 @@ function VolumeBundle(props) {
2311
2394
  }, [variants]);
2312
2395
  const showPicker = variants.length > 1 && optionNames.length > 0;
2313
2396
  const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
2314
- const minTierQty = bundle ? (0, import_core12.getMinTierQuantity)(bundle.volumeTiers) : 1;
2315
- const isSoldOut = variants.length > 0 && !variants.some((v) => (0, import_core12.isVariantFulfillable)(v, minTierQty));
2316
- const displayVariant = selectedVariant ?? variants.find((v) => (0, import_core12.isVariantFulfillable)(v, minTierQty)) ?? variants[0];
2397
+ const minTierQty = bundle ? (0, import_core11.getMinTierQuantity)(bundle.volumeTiers) : 1;
2398
+ const isSoldOut = variants.length > 0 && !variants.some((v) => (0, import_core11.isVariantFulfillable)(v, minTierQty));
2399
+ const displayVariant = selectedVariant ?? variants.find((v) => (0, import_core11.isVariantFulfillable)(v, minTierQty)) ?? variants[0];
2400
+ const tierAvailable = (0, import_react13.useCallback)(
2401
+ (tierQty) => Boolean(displayVariant && (0, import_core11.isVariantFulfillable)(displayVariant, tierQty)),
2402
+ [displayVariant]
2403
+ );
2404
+ const selectedTierUnavailable = !isSoldOut && !tierAvailable(quantity);
2317
2405
  const basePrice = displayVariant ? parseFloat(displayVariant.price.amount) : product ? parseFloat(product.priceRange.minVariantPrice.amount) : 0;
2318
2406
  const currency = product?.priceRange.minVariantPrice.currencyCode ?? "USD";
2319
2407
  const thumbImage = displayVariant?.image ?? product?.featuredImage ?? null;
2320
- const unitPriceText = displayVariant ? (0, import_core12.formatUnitPrice)(
2408
+ const unitPriceText = displayVariant ? (0, import_core11.formatUnitPrice)(
2321
2409
  displayVariant.unitPrice,
2322
2410
  displayVariant.unitPriceMeasurement,
2323
2411
  currency
2324
2412
  ) : null;
2325
2413
  const tierSavings = (0, import_react13.useMemo)(
2326
- () => bundle ? (0, import_core12.calculateTierSavings)(
2414
+ () => bundle ? (0, import_core11.calculateTierSavings)(
2327
2415
  bundle.volumeTiers,
2328
2416
  basePrice,
2329
2417
  quantity,
@@ -2331,21 +2419,18 @@ function VolumeBundle(props) {
2331
2419
  ) : [],
2332
2420
  [bundle, basePrice, quantity]
2333
2421
  );
2334
- const activeTier = bundle ? (0, import_core12.getActiveTier)(bundle.volumeTiers, quantity) : null;
2422
+ const activeTier = bundle ? (0, import_core11.getActiveTier)(bundle.volumeTiers, quantity) : null;
2335
2423
  const popularTierIndex = (0, import_react13.useMemo)(() => {
2336
- if (!bundle?.widgetConfig.popularBadge.visible || tierSavings.length === 0) {
2337
- return -1;
2338
- }
2339
- const pinned = bundle.widgetConfig.popularBadge.tierIndex;
2340
- if (pinned !== void 0) {
2341
- return Math.min(Math.max(pinned, 0), tierSavings.length - 1);
2342
- }
2343
- let best = 0;
2344
- for (let i = 1; i < tierSavings.length; i++) {
2345
- if (tierSavings[i].savings > tierSavings[best].savings) best = i;
2346
- }
2347
- return best;
2348
- }, [bundle, tierSavings]);
2424
+ if (!bundle || bundle.volumeTiers.length === 0) return -1;
2425
+ return (0, import_core11.resolvePopularTierIndex)(
2426
+ bundle.widgetConfig.popularBadge.tierIndex,
2427
+ bundle.widgetConfig.popularBadge.visible !== false,
2428
+ (0, import_core11.bestValueTierIndex)(
2429
+ bundle.volumeTiers,
2430
+ bundle.discountConfig.discountType
2431
+ )
2432
+ );
2433
+ }, [bundle]);
2349
2434
  const activeUnitPrice = tierSavings.find((ts) => ts.tier === activeTier)?.unitPrice ?? basePrice;
2350
2435
  const undiscountedTotal = basePrice * quantity;
2351
2436
  const volumeTotal = activeUnitPrice * quantity;
@@ -2354,7 +2439,7 @@ function VolumeBundle(props) {
2354
2439
  const handleAddToCart = (0, import_react13.useCallback)(async () => {
2355
2440
  if (!bundle || !product) return;
2356
2441
  const variant = selectedVariant ?? product.variants.nodes.find(
2357
- (v) => (0, import_core12.isVariantFulfillable)(v, quantity)
2442
+ (v) => (0, import_core11.isVariantFulfillable)(v, quantity)
2358
2443
  );
2359
2444
  if (!variant) return;
2360
2445
  const lines = [
@@ -2397,15 +2482,15 @@ function VolumeBundle(props) {
2397
2482
  tierSavings
2398
2483
  ]);
2399
2484
  if (result.status === "loading") {
2400
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
2401
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
2402
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-skeleton lb-skeleton--tiers" })
2485
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
2486
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
2487
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-skeleton lb-skeleton--tiers" })
2403
2488
  ] });
2404
2489
  }
2405
2490
  if (result.status === "error") return null;
2406
2491
  if (!bundle) return null;
2407
2492
  if (!product) return null;
2408
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2493
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2409
2494
  "div",
2410
2495
  {
2411
2496
  ref: (el) => {
@@ -2416,12 +2501,19 @@ function VolumeBundle(props) {
2416
2501
  role: "region",
2417
2502
  "aria-label": bundle.title,
2418
2503
  children: [
2419
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-header__content", children: [
2420
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
2421
- bundle.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
2504
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-header__content", children: [
2505
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
2506
+ bundle.description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
2422
2507
  ] }) }),
2423
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-product-row lb-bundle-product-row--volume", children: [
2424
- thumbImage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2508
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2509
+ BundleCountdown,
2510
+ {
2511
+ endsAt: bundle.endsAt,
2512
+ widgetConfig: bundle.widgetConfig
2513
+ }
2514
+ ),
2515
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-product-row lb-bundle-product-row--volume", children: [
2516
+ thumbImage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2425
2517
  "img",
2426
2518
  {
2427
2519
  src: thumbImage.url,
@@ -2430,20 +2522,20 @@ function VolumeBundle(props) {
2430
2522
  loading: "lazy"
2431
2523
  }
2432
2524
  ),
2433
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle__product-info", children: [
2434
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "lb-bundle__product-title", children: product.title }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "lb-bundle__product-price", children: [
2436
- (0, import_core12.formatMoney)(basePrice, currency),
2525
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle__product-info", children: [
2526
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle__product-title", children: product.title }),
2527
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "lb-bundle__product-price", children: [
2528
+ (0, import_core11.formatMoney)(basePrice, currency),
2437
2529
  " each"
2438
2530
  ] }),
2439
- unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "lb-bundle__product-unit-price", children: unitPriceText }),
2440
- showPicker && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
2531
+ unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle__product-unit-price", children: unitPriceText }),
2532
+ showPicker && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
2441
2533
  const dropdownOptions = optionsFor(optionIndex).map((o) => ({
2442
2534
  value: o.value,
2443
2535
  label: o.value,
2444
2536
  disabled: o.disabled
2445
2537
  }));
2446
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2538
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2447
2539
  VariantDropdown,
2448
2540
  {
2449
2541
  options: dropdownOptions,
@@ -2456,37 +2548,51 @@ function VolumeBundle(props) {
2456
2548
  }) })
2457
2549
  ] })
2458
2550
  ] }),
2459
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2551
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2460
2552
  "div",
2461
2553
  {
2462
2554
  className: "lb-bundle__tiers lb-edge-fade",
2463
- role: "table",
2464
- "aria-label": "Volume discounts",
2555
+ role: "radiogroup",
2556
+ "aria-label": "Select quantity",
2465
2557
  ref: tiersEdgeFadeRef,
2466
2558
  children: tierSavings.map((ts, tierIndex) => {
2467
2559
  const savingsPercent = Math.round(ts.savingsPercent);
2468
2560
  const showCompare = bundle.widgetConfig.pricing.showComparePrice && ts.savings > 0;
2469
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2561
+ const isChecked = activeTier === ts.tier;
2562
+ const available = tierAvailable(ts.tier.minQuantity);
2563
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2470
2564
  "div",
2471
2565
  {
2472
- className: `lb-bundle__tier ${ts.isActive ? "lb-bundle__tier--active" : ""}`,
2473
- role: "row",
2566
+ className: `lb-bundle__tier ${ts.isActive ? "lb-bundle__tier--active" : ""} ${available ? "" : "lb-bundle__tier--oos"}`,
2567
+ role: "radio",
2568
+ "aria-checked": isChecked,
2569
+ "aria-disabled": available ? void 0 : true,
2570
+ tabIndex: isChecked ? 0 : -1,
2571
+ onClick: () => {
2572
+ if (available) setQuantity(ts.tier.minQuantity);
2573
+ },
2574
+ onKeyDown: (e) => {
2575
+ if ((e.key === "Enter" || e.key === " ") && available) {
2576
+ e.preventDefault();
2577
+ setQuantity(ts.tier.minQuantity);
2578
+ }
2579
+ },
2474
2580
  children: [
2475
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle__tier-radio", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle__tier-radio-dot" }) }),
2476
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle__tier-info", role: "cell", children: [
2477
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle__tier-label", children: [
2581
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle__tier-radio", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle__tier-radio-dot" }) }),
2582
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle__tier-info", children: [
2583
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle__tier-label", children: [
2478
2584
  "Buy ",
2479
2585
  ts.tier.minQuantity
2480
2586
  ] }),
2481
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle__tier-price", children: [
2482
- showCompare && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle__tier-compare", children: (0, import_core12.formatMoney)(basePrice, currency) }),
2483
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: (0, import_core12.formatMoney)(ts.unitPrice, currency) }),
2484
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle__tier-unit", children: "each" })
2587
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle__tier-price", children: [
2588
+ showCompare && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle__tier-compare", children: (0, import_core11.formatMoney)(basePrice, currency) }),
2589
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: (0, import_core11.formatMoney)(ts.unitPrice, currency) }),
2590
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle__tier-unit", children: "each" })
2485
2591
  ] })
2486
2592
  ] }),
2487
- (tierIndex === popularTierIndex || savingsPercent > 0) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle__tier-right", role: "cell", children: [
2488
- tierIndex === popularTierIndex && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle__tier-badge", children: bundle.widgetConfig.popularBadge.text }),
2489
- savingsPercent > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle__tier-savings", children: [
2593
+ (tierIndex === popularTierIndex || savingsPercent > 0) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle__tier-right", children: [
2594
+ tierIndex === popularTierIndex && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle__tier-badge", children: bundle.widgetConfig.popularBadge.text }),
2595
+ savingsPercent > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle__tier-savings", children: [
2490
2596
  "Save ",
2491
2597
  savingsPercent,
2492
2598
  "%"
@@ -2499,10 +2605,10 @@ function VolumeBundle(props) {
2499
2605
  })
2500
2606
  }
2501
2607
  ),
2502
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle__quantity-selector", children: [
2503
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { htmlFor: `lb-qty-${bundle.id}`, children: "Quantity" }),
2504
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle__quantity-control", children: [
2505
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2608
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle__quantity-selector", children: [
2609
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("label", { htmlFor: `lb-qty-${bundle.id}`, children: "Quantity" }),
2610
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle__quantity-control", children: [
2611
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2506
2612
  "button",
2507
2613
  {
2508
2614
  "aria-label": "Decrease quantity",
@@ -2510,7 +2616,7 @@ function VolumeBundle(props) {
2510
2616
  children: "\u2212"
2511
2617
  }
2512
2618
  ),
2513
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2619
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2514
2620
  "input",
2515
2621
  {
2516
2622
  id: `lb-qty-${bundle.id}`,
@@ -2524,7 +2630,7 @@ function VolumeBundle(props) {
2524
2630
  className: "lb-bundle__quantity-input"
2525
2631
  }
2526
2632
  ),
2527
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2633
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2528
2634
  "button",
2529
2635
  {
2530
2636
  "aria-label": "Increase quantity",
@@ -2534,23 +2640,23 @@ function VolumeBundle(props) {
2534
2640
  )
2535
2641
  ] })
2536
2642
  ] }),
2537
- cartError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
2538
- bundle && displayVariant && (0, import_core12.shouldShowLowStockBadge)(
2643
+ cartError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
2644
+ bundle && displayVariant && (0, import_core11.shouldShowLowStockBadge)(
2539
2645
  displayVariant,
2540
2646
  minTierQty,
2541
2647
  bundle.widgetConfig.lowStockThreshold,
2542
2648
  bundle.widgetConfig.showLowStockBadge
2543
- ) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle-low-stock-badge", children: [
2649
+ ) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle-low-stock-badge", children: [
2544
2650
  "Only ",
2545
2651
  displayVariant.quantityAvailable,
2546
2652
  " left"
2547
2653
  ] }),
2548
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "lb-bundle-divider" }),
2549
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-summary", children: [
2550
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "lb-bundle-summary__text", children: [
2551
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle-summary__label", "data-total-label": true, children: [
2654
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bundle-divider" }),
2655
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-summary", children: [
2656
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-summary__text", children: [
2657
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle-summary__label", "data-total-label": true, children: [
2552
2658
  "Total",
2553
- bundle.widgetConfig.pricing.showItemCount && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-item-count": true, children: [
2659
+ bundle.widgetConfig.pricing.showItemCount && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { "data-item-count": true, children: [
2554
2660
  " ",
2555
2661
  "(",
2556
2662
  quantity,
@@ -2559,31 +2665,31 @@ function VolumeBundle(props) {
2559
2665
  ")"
2560
2666
  ] })
2561
2667
  ] }),
2562
- bundle.widgetConfig.savingsBar.visible && volumeSavings > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
2668
+ bundle.widgetConfig.savingsBar.visible && volumeSavings > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
2563
2669
  "You save",
2564
2670
  " ",
2565
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "data-savings-amount": true, children: (0, import_core12.formatMoney)(volumeSavings, currency) }),
2671
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "data-savings-amount": true, children: (0, import_core11.formatMoney)(volumeSavings, currency) }),
2566
2672
  " ",
2567
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-savings-percent": true, children: [
2673
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { "data-savings-percent": true, children: [
2568
2674
  "(",
2569
2675
  volumeSavingsPercent,
2570
2676
  "%)"
2571
2677
  ] })
2572
2678
  ] })
2573
2679
  ] }),
2574
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
2575
- bundle.widgetConfig.pricing.showComparePrice && volumeSavings > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core12.formatMoney)(undiscountedTotal, currency) }),
2576
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "lb-bundle-sale-price", "data-total-price": true, children: (0, import_core12.formatMoney)(volumeTotal, currency) })
2680
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
2681
+ bundle.widgetConfig.pricing.showComparePrice && volumeSavings > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core11.formatMoney)(undiscountedTotal, currency) }),
2682
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle-sale-price", "data-total-price": true, children: (0, import_core11.formatMoney)(volumeTotal, currency) })
2577
2683
  ] })
2578
2684
  ] }),
2579
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2685
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2580
2686
  "button",
2581
2687
  {
2582
2688
  className: "lb-bundle__cta",
2583
2689
  onClick: handleAddToCart,
2584
- disabled: addingToCart || isSoldOut,
2690
+ disabled: addingToCart || isSoldOut || selectedTierUnavailable,
2585
2691
  "aria-busy": addingToCart,
2586
- children: addingToCart ? "Adding..." : isSoldOut ? "Sold out" : bundle.widgetConfig.cta.ctaText ?? `Add ${quantity} to Cart`
2692
+ children: addingToCart ? "Adding..." : isSoldOut || selectedTierUnavailable ? "Sold out" : bundle.widgetConfig.cta.ctaText ?? `Add ${quantity} to Cart`
2587
2693
  }
2588
2694
  )
2589
2695
  ]
@@ -2593,8 +2699,8 @@ function VolumeBundle(props) {
2593
2699
 
2594
2700
  // src/components/BogoBundle.tsx
2595
2701
  var import_react14 = require("react");
2596
- var import_core13 = require("@lime-bundles/core");
2597
- var import_jsx_runtime6 = require("react/jsx-runtime");
2702
+ var import_core12 = require("@lime-bundles/core");
2703
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2598
2704
  function discountedUnit(price, percent) {
2599
2705
  const cents = Math.round(price * 100);
2600
2706
  const discounted = cents - Math.floor(cents * percent / 100);
@@ -2662,13 +2768,13 @@ function BogoBundle(props) {
2662
2768
  const resolveVariant = (0, import_react14.useCallback)(
2663
2769
  (product, selected, qty) => {
2664
2770
  if (!product) return null;
2665
- return selected ?? product.variants.nodes.find((v) => (0, import_core13.isVariantFulfillable)(v, qty)) ?? product.variants.nodes[0] ?? null;
2771
+ return selected ?? product.variants.nodes.find((v) => (0, import_core12.isVariantFulfillable)(v, qty)) ?? product.variants.nodes[0] ?? null;
2666
2772
  },
2667
2773
  []
2668
2774
  );
2669
2775
  const oosSides = (0, import_react14.useMemo)(() => {
2670
2776
  if (!bundle) return 0;
2671
- const short = (product, qty) => !!product && !product.variants.nodes.some((v) => (0, import_core13.isVariantFulfillable)(v, qty));
2777
+ const short = (product, qty) => !!product && !product.variants.nodes.some((v) => (0, import_core12.isVariantFulfillable)(v, qty));
2672
2778
  return (short(buyProduct, bundle.buyQuantity) ? 1 : 0) + (short(getProduct, bundle.getQuantity) ? 1 : 0);
2673
2779
  }, [bundle, buyProduct, getProduct]);
2674
2780
  const handleAddToCart = (0, import_react14.useCallback)(async () => {
@@ -2718,9 +2824,9 @@ function BogoBundle(props) {
2718
2824
  }
2719
2825
  }, [bundle, buyProduct, getProduct, selectedVariants, resolveVariant, onAddToCart, onError, trackAddToCart, percent]);
2720
2826
  if (result.status === "loading") {
2721
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
2722
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
2723
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
2827
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
2828
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
2829
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
2724
2830
  ] });
2725
2831
  }
2726
2832
  if (result.status === "error") return null;
@@ -2737,7 +2843,7 @@ function BogoBundle(props) {
2737
2843
  const showCompare = bundle.widgetConfig.pricing.showComparePrice && savings > 0;
2738
2844
  const showSavings = bundle.widgetConfig.savingsBar.visible && savings > 0;
2739
2845
  const badge = percent === 100 ? "Free" : `${percent}% off`;
2740
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2846
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2741
2847
  "div",
2742
2848
  {
2743
2849
  ref: (el) => {
@@ -2748,12 +2854,19 @@ function BogoBundle(props) {
2748
2854
  role: "region",
2749
2855
  "aria-label": bundle.title,
2750
2856
  children: [
2751
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-header__content", children: [
2752
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
2753
- bundle.description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
2857
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-bundle-header__content", children: [
2858
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
2859
+ bundle.description && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
2754
2860
  ] }) }),
2755
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle__products", children: [
2756
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2861
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2862
+ BundleCountdown,
2863
+ {
2864
+ endsAt: bundle.endsAt,
2865
+ widgetConfig: bundle.widgetConfig
2866
+ }
2867
+ ),
2868
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-bundle__products", children: [
2869
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2757
2870
  BogoProductRow,
2758
2871
  {
2759
2872
  side: "buy",
@@ -2765,11 +2878,11 @@ function BogoBundle(props) {
2765
2878
  onVariantChange: handleVariantChange
2766
2879
  }
2767
2880
  ),
2768
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bogo__plus", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
2769
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
2770
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2881
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-bogo__plus", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
2882
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
2883
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2771
2884
  ] }) }),
2772
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2885
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2773
2886
  BogoProductRow,
2774
2887
  {
2775
2888
  side: "get",
@@ -2782,29 +2895,29 @@ function BogoBundle(props) {
2782
2895
  }
2783
2896
  )
2784
2897
  ] }),
2785
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bundle-divider" }),
2786
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-summary", children: [
2787
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-summary__text", children: [
2788
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle price" }),
2789
- showSavings && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
2898
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-bundle-divider" }),
2899
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-bundle-summary", children: [
2900
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-bundle-summary__text", children: [
2901
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
2902
+ showSavings && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
2790
2903
  "You save",
2791
2904
  " ",
2792
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "data-savings-amount": true, children: (0, import_core13.formatMoney)(savings, currency) }),
2905
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "data-savings-amount": true, children: (0, import_core12.formatMoney)(savings, currency) }),
2793
2906
  " ",
2794
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { "data-savings-percent": true, children: [
2907
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { "data-savings-percent": true, children: [
2795
2908
  "(",
2796
2909
  savingsPercent,
2797
2910
  "%)"
2798
2911
  ] })
2799
2912
  ] })
2800
2913
  ] }),
2801
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
2802
- showCompare && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core13.formatMoney)(comparePrice, currency) }),
2803
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core13.formatMoney)(salePrice, currency) })
2914
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
2915
+ showCompare && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core12.formatMoney)(comparePrice, currency) }),
2916
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core12.formatMoney)(salePrice, currency) })
2804
2917
  ] })
2805
2918
  ] }),
2806
- cartError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
2807
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2919
+ cartError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
2920
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2808
2921
  "button",
2809
2922
  {
2810
2923
  className: "lb-bundle__cta",
@@ -2832,19 +2945,19 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
2832
2945
  (0, import_react14.useEffect)(() => {
2833
2946
  onVariantChange(side, selectedVariant ?? null);
2834
2947
  }, [selectedVariant, side, onVariantChange]);
2835
- const displayVariant = selectedVariant ?? variants.find((v) => (0, import_core13.isVariantFulfillable)(v, quantity)) ?? variants[0];
2948
+ const displayVariant = selectedVariant ?? variants.find((v) => (0, import_core12.isVariantFulfillable)(v, quantity)) ?? variants[0];
2836
2949
  const unit = displayVariant ? parseFloat(displayVariant.price.amount) : 0;
2837
2950
  const isGet = side === "get" && percent > 0;
2838
- const priceText = isGet ? (0, import_core13.formatMoney)(discountedUnit(unit, percent), currency) : (0, import_core13.formatMoney)(unit, currency);
2839
- const compareAt = isGet ? (0, import_core13.formatMoney)(unit, currency) : displayVariant?.compareAtPrice && parseFloat(displayVariant.compareAtPrice.amount) > unit ? (0, import_core13.formatMoney)(displayVariant.compareAtPrice.amount, currency) : null;
2840
- const unitPriceText = displayVariant ? (0, import_core13.formatUnitPrice)(
2951
+ const priceText = isGet ? (0, import_core12.formatMoney)(discountedUnit(unit, percent), currency) : (0, import_core12.formatMoney)(unit, currency);
2952
+ const compareAt = isGet ? (0, import_core12.formatMoney)(unit, currency) : displayVariant?.compareAtPrice && parseFloat(displayVariant.compareAtPrice.amount) > unit ? (0, import_core12.formatMoney)(displayVariant.compareAtPrice.amount, currency) : null;
2953
+ const unitPriceText = displayVariant ? (0, import_core12.formatUnitPrice)(
2841
2954
  displayVariant.unitPrice,
2842
2955
  displayVariant.unitPriceMeasurement,
2843
2956
  currency
2844
2957
  ) : null;
2845
2958
  const thumbImage = displayVariant?.image ?? product.featuredImage;
2846
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle-product-row", part: "product", "data-bogo-role": side, children: [
2847
- thumbImage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2959
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-bundle-product-row", part: "product", "data-bogo-role": side, children: [
2960
+ thumbImage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2848
2961
  "img",
2849
2962
  {
2850
2963
  src: thumbImage.url,
@@ -2853,11 +2966,11 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
2853
2966
  loading: "lazy"
2854
2967
  }
2855
2968
  ),
2856
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "lb-bundle__product-info", children: [
2857
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "lb-bundle__product-title", children: product.title }),
2858
- !showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle-variant-badge", children: displayVariant.title }),
2859
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle-product-prices", children: [
2860
- compareAt && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2969
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-bundle__product-info", children: [
2970
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "lb-bundle__product-title", children: product.title }),
2971
+ !showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bundle-variant-badge", children: displayVariant.title }),
2972
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "lb-bundle-product-prices", children: [
2973
+ compareAt && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2861
2974
  "span",
2862
2975
  {
2863
2976
  className: "lb-bundle-product-compare-price",
@@ -2865,13 +2978,13 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
2865
2978
  children: compareAt
2866
2979
  }
2867
2980
  ),
2868
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bundle__product-price", "data-product-price": true, children: priceText }),
2869
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "lb-bundle-qty-inline", "data-qty-inline": true, children: [
2981
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bundle__product-price", "data-product-price": true, children: priceText }),
2982
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "lb-bundle-qty-inline", "data-qty-inline": true, children: [
2870
2983
  "\xD7",
2871
2984
  quantity
2872
2985
  ] })
2873
2986
  ] }),
2874
- unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2987
+ unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2875
2988
  "span",
2876
2989
  {
2877
2990
  className: "lb-bundle__product-unit-price",
@@ -2879,13 +2992,13 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
2879
2992
  children: unitPriceText
2880
2993
  }
2881
2994
  ),
2882
- showPicker && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
2995
+ showPicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
2883
2996
  const dropdownOptions = optionsFor(optionIndex).map((o) => ({
2884
2997
  value: o.value,
2885
2998
  label: o.value,
2886
2999
  disabled: o.disabled
2887
3000
  }));
2888
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3001
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2889
3002
  VariantDropdown,
2890
3003
  {
2891
3004
  options: dropdownOptions,
@@ -2897,25 +3010,25 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
2897
3010
  );
2898
3011
  }) })
2899
3012
  ] }),
2900
- badge && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "lb-bogo__badge", children: badge })
3013
+ badge && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bogo__badge", children: badge })
2901
3014
  ] });
2902
3015
  }
2903
3016
 
2904
3017
  // src/components/MultiStepBundle.tsx
2905
3018
  var import_react16 = require("react");
2906
- var import_core15 = require("@lime-bundles/core");
3019
+ var import_core14 = require("@lime-bundles/core");
2907
3020
 
2908
3021
  // src/components/MultiStepPicker.tsx
2909
3022
  var import_react15 = require("react");
2910
3023
  var import_react_dom2 = require("react-dom");
2911
- var import_core14 = require("@lime-bundles/core");
2912
- var import_jsx_runtime7 = require("react/jsx-runtime");
3024
+ var import_core13 = require("@lime-bundles/core");
3025
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2913
3026
  function ruleFor3(bundle, productId, variantId) {
2914
3027
  if (variantId) {
2915
3028
  const vRule = bundle.variantRules[variantId];
2916
3029
  if (vRule) return vRule;
2917
3030
  }
2918
- return bundle.productRules[productId] ?? import_core14.DEFAULT_PRODUCT_RULE;
3031
+ return bundle.productRules[productId] ?? import_core13.DEFAULT_PRODUCT_RULE;
2919
3032
  }
2920
3033
  function variantRuleFor3(bundle, variantId) {
2921
3034
  return variantId ? bundle.variantRules[variantId] : void 0;
@@ -2923,15 +3036,14 @@ function variantRuleFor3(bundle, variantId) {
2923
3036
  function sanitizeId2(gid) {
2924
3037
  return gid.replace(/[^a-zA-Z0-9_-]/g, "-");
2925
3038
  }
2926
- function buildEligibleProducts2(bundle, stepIndex, oosBehavior) {
3039
+ function buildEligibleProducts2(bundle, stepIndex) {
2927
3040
  const result = [];
2928
- for (const product of (0, import_core14.productsForStep)(bundle, stepIndex)) {
3041
+ for (const product of (0, import_core13.productsForStep)(bundle, stepIndex)) {
2929
3042
  const rule = ruleFor3(bundle, product.id);
2930
3043
  const available = product.variants.nodes.filter(
2931
- (v) => (0, import_core14.isVariantFulfillable)(v, rule.min)
3044
+ (v) => (0, import_core13.isVariantFulfillable)(v, rule.min)
2932
3045
  );
2933
3046
  const isOos = available.length === 0;
2934
- if (isOos && oosBehavior === "hide") continue;
2935
3047
  result.push({
2936
3048
  product,
2937
3049
  variants: product.variants.nodes,
@@ -2946,7 +3058,6 @@ function normalizeText2(str) {
2946
3058
  }
2947
3059
  var FILTERS_ALL2 = "__all__";
2948
3060
  function MultiStepPicker({
2949
- outOfStockBehavior,
2950
3061
  bundle,
2951
3062
  currency,
2952
3063
  initialStep,
@@ -2966,6 +3077,8 @@ function MultiStepPicker({
2966
3077
  const overlayRef = (0, import_react15.useRef)(null);
2967
3078
  const dialogRef = (0, import_react15.useRef)(null);
2968
3079
  const titleRef = (0, import_react15.useRef)(null);
3080
+ const closeBtnRef = (0, import_react15.useRef)(null);
3081
+ const listRef = (0, import_react15.useRef)(null);
2969
3082
  const mouseDownTarget = (0, import_react15.useRef)(null);
2970
3083
  const [open, setOpen] = (0, import_react15.useState)(false);
2971
3084
  const [stepIndex, setStepIndex] = (0, import_react15.useState)(
@@ -2982,8 +3095,8 @@ function MultiStepPicker({
2982
3095
  const isLastStep = stepIndex === steps.length - 1;
2983
3096
  const shownUnits = Math.min(unitsInStep, stepMin);
2984
3097
  const eligible = (0, import_react15.useMemo)(
2985
- () => buildEligibleProducts2(bundle, stepIndex, outOfStockBehavior),
2986
- [bundle, stepIndex, outOfStockBehavior]
3098
+ () => buildEligibleProducts2(bundle, stepIndex),
3099
+ [bundle, stepIndex]
2987
3100
  );
2988
3101
  const productTypes = (0, import_react15.useMemo)(() => {
2989
3102
  const types = [];
@@ -3006,8 +3119,23 @@ function MultiStepPicker({
3006
3119
  useFocusTrap({
3007
3120
  active: true,
3008
3121
  containerRef: dialogRef,
3122
+ initialFocusRef: closeBtnRef,
3009
3123
  onEscape: onClose
3010
3124
  });
3125
+ (0, import_react15.useEffect)(() => {
3126
+ if (listRef.current) listRef.current.scrollTop = 0;
3127
+ }, [stepIndex]);
3128
+ const [selectedAtLoad, setSelectedAtLoad] = (0, import_react15.useState)(
3129
+ () => new Set((selections[stepIndex] ?? []).map((s) => s.productId))
3130
+ );
3131
+ const ordered = (0, import_react15.useMemo)(() => {
3132
+ const front = [];
3133
+ const back = [];
3134
+ for (const ep of eligible) {
3135
+ (selectedAtLoad.has(ep.product.id) ? back : front).push(ep);
3136
+ }
3137
+ return front.concat(back);
3138
+ }, [eligible, selectedAtLoad]);
3011
3139
  function goToStep(i) {
3012
3140
  const clamped = Math.max(0, Math.min(steps.length - 1, i));
3013
3141
  setStepIndex(clamped);
@@ -3015,6 +3143,7 @@ function MultiStepPicker({
3015
3143
  setActiveType(FILTERS_ALL2);
3016
3144
  const target = steps[clamped];
3017
3145
  const targetPicks = selections[clamped] ?? [];
3146
+ setSelectedAtLoad(new Set(targetPicks.map((s) => s.productId)));
3018
3147
  const targetUnits = targetPicks.reduce((sum, s) => sum + s.quantity, 0);
3019
3148
  setAnnouncement(
3020
3149
  `Step ${clamped + 1} of ${steps.length}. ${target.name}. ${Math.min(targetUnits, target.minQuantity)} of ${target.minQuantity} added`
@@ -3024,12 +3153,12 @@ function MultiStepPicker({
3024
3153
  const subtitle = `Step ${stepIndex + 1} of ${steps.length} \xB7 ${step?.name ?? ""}`;
3025
3154
  const filtered = (0, import_react15.useMemo)(() => {
3026
3155
  const nq = normalizeText2(query.trim());
3027
- return eligible.filter((ep) => {
3156
+ return ordered.filter((ep) => {
3028
3157
  const matchesQuery = !nq || normalizeText2(ep.product.title).includes(nq);
3029
3158
  const matchesType = activeType === FILTERS_ALL2 || (ep.product.productType ?? "") === activeType;
3030
3159
  return matchesQuery && matchesType;
3031
3160
  });
3032
- }, [eligible, query, activeType]);
3161
+ }, [ordered, query, activeType]);
3033
3162
  const showEmpty = filtered.length === 0 && query.trim().length > 0;
3034
3163
  function onOverlayMouseDown(e) {
3035
3164
  mouseDownTarget.current = e.target;
@@ -3047,7 +3176,7 @@ function MultiStepPicker({
3047
3176
  // inside carries the interactive role + focus trap. So the static-element
3048
3177
  // interaction lint does not apply to this backdrop.
3049
3178
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
3050
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3179
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3051
3180
  "div",
3052
3181
  {
3053
3182
  ref: (el) => {
@@ -3059,7 +3188,7 @@ function MultiStepPicker({
3059
3188
  "data-bundle-gid": bundle.id,
3060
3189
  onMouseDown: onOverlayMouseDown,
3061
3190
  onMouseUp: onOverlayMouseUp,
3062
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3191
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3063
3192
  "div",
3064
3193
  {
3065
3194
  ref: dialogRef,
@@ -3069,10 +3198,10 @@ function MultiStepPicker({
3069
3198
  "aria-labelledby": titleId,
3070
3199
  tabIndex: -1,
3071
3200
  children: [
3072
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-header", children: [
3073
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-header-top", children: [
3074
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-heading", children: [
3075
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3201
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-header", children: [
3202
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-header-top", children: [
3203
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-heading", children: [
3204
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3076
3205
  "h4",
3077
3206
  {
3078
3207
  className: "lb-mix-match__modal-title",
@@ -3082,26 +3211,27 @@ function MultiStepPicker({
3082
3211
  children: "Add to your bundle"
3083
3212
  }
3084
3213
  ),
3085
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "lb-mix-match__modal-subtitle", "data-modal-subtitle": true, children: subtitle })
3214
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "lb-mix-match__modal-subtitle", "data-modal-subtitle": true, children: subtitle })
3086
3215
  ] }),
3087
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3216
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3088
3217
  "button",
3089
3218
  {
3219
+ ref: closeBtnRef,
3090
3220
  type: "button",
3091
3221
  className: "lb-mix-match__modal-close",
3092
3222
  "data-modal-close": true,
3093
3223
  "aria-label": "Close",
3094
3224
  onClick: onClose,
3095
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon3, {})
3225
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon3, {})
3096
3226
  }
3097
3227
  )
3098
3228
  ] }),
3099
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3229
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3100
3230
  "div",
3101
3231
  {
3102
3232
  className: "lb-mix-match__progress lb-mix-match__modal-progress",
3103
3233
  "data-progress": true,
3104
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3234
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3105
3235
  "div",
3106
3236
  {
3107
3237
  className: "lb-mix-match__progress-segments",
@@ -3110,7 +3240,7 @@ function MultiStepPicker({
3110
3240
  "aria-valuenow": shownUnits,
3111
3241
  "aria-valuemin": 0,
3112
3242
  "aria-valuemax": stepMin,
3113
- children: Array.from({ length: stepMin }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3243
+ children: Array.from({ length: stepMin }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3114
3244
  "span",
3115
3245
  {
3116
3246
  className: `lb-mix-match__progress-segment${i < shownUnits ? " lb-mix-match__progress-segment--filled" : ""}`,
@@ -3123,8 +3253,8 @@ function MultiStepPicker({
3123
3253
  }
3124
3254
  )
3125
3255
  ] }),
3126
- wc.showSearch && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-search", children: [
3127
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3256
+ wc.showSearch && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-search", children: [
3257
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3128
3258
  "input",
3129
3259
  {
3130
3260
  type: "text",
@@ -3138,7 +3268,7 @@ function MultiStepPicker({
3138
3268
  onChange: (e) => setQuery(e.target.value)
3139
3269
  }
3140
3270
  ),
3141
- query.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3271
+ query.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3142
3272
  "button",
3143
3273
  {
3144
3274
  type: "button",
@@ -3146,11 +3276,11 @@ function MultiStepPicker({
3146
3276
  "data-modal-search-clear": true,
3147
3277
  "aria-label": "Clear search",
3148
3278
  onClick: () => setQuery(""),
3149
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SearchClearIcon2, {})
3279
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SearchClearIcon2, {})
3150
3280
  }
3151
3281
  )
3152
3282
  ] }),
3153
- showFilters && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3283
+ showFilters && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3154
3284
  "div",
3155
3285
  {
3156
3286
  className: "lb-mix-match__filters",
@@ -3159,7 +3289,7 @@ function MultiStepPicker({
3159
3289
  "aria-label": "Filter by product type",
3160
3290
  children: [FILTERS_ALL2, ...productTypes].map((value) => {
3161
3291
  const isActive = value === activeType;
3162
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3292
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3163
3293
  "button",
3164
3294
  {
3165
3295
  type: "button",
@@ -3174,7 +3304,7 @@ function MultiStepPicker({
3174
3304
  })
3175
3305
  }
3176
3306
  ),
3177
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-mix-match__modal-list", "data-modal-list": true, children: filtered.map((ep) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3307
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-mix-match__modal-list", "data-modal-list": true, ref: listRef, children: filtered.map((ep) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3178
3308
  MultiStepPickerRow,
3179
3309
  {
3180
3310
  bundle,
@@ -3192,10 +3322,10 @@ function MultiStepPicker({
3192
3322
  },
3193
3323
  `${stepIndex}:${ep.product.id}`
3194
3324
  )) }),
3195
- showEmpty && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-mix-match__modal-empty", "data-modal-empty": true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { children: "No products match your search" }) }),
3196
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "data-modal-live": true, "aria-live": "polite", className: "lb-visually-hidden", children: announcement || (query.trim() ? `${filtered.length} products shown` : "") }),
3197
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-footer lb-multi-step__modal-footer", children: [
3198
- stepIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3325
+ showEmpty && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-mix-match__modal-empty", "data-modal-empty": true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: "No products match your search" }) }),
3326
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-modal-live": true, "aria-live": "polite", className: "lb-visually-hidden", children: announcement || (query.trim() ? `${filtered.length} products shown` : "") }),
3327
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-footer lb-multi-step__modal-footer", children: [
3328
+ stepIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3199
3329
  "button",
3200
3330
  {
3201
3331
  type: "button",
@@ -3205,7 +3335,7 @@ function MultiStepPicker({
3205
3335
  children: "Back"
3206
3336
  }
3207
3337
  ),
3208
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3338
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3209
3339
  "span",
3210
3340
  {
3211
3341
  className: "lb-mix-match__modal-footer-count",
@@ -3214,7 +3344,7 @@ function MultiStepPicker({
3214
3344
  children: `${shownUnits} of ${stepMin} added`
3215
3345
  }
3216
3346
  ),
3217
- !isLastStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3347
+ !isLastStep && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3218
3348
  "button",
3219
3349
  {
3220
3350
  type: "button",
@@ -3227,7 +3357,7 @@ function MultiStepPicker({
3227
3357
  children: "Next"
3228
3358
  }
3229
3359
  ),
3230
- isLastStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3360
+ isLastStep && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3231
3361
  "button",
3232
3362
  {
3233
3363
  type: "button",
@@ -3271,7 +3401,7 @@ function MultiStepPickerRow({
3271
3401
  }, [variants]);
3272
3402
  const showPicker = variants.length > 1 && optionNames.length > 0;
3273
3403
  const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
3274
- const currentVariant = selectedVariant ?? variants.find((v) => (0, import_core14.isVariantFulfillable)(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
3404
+ const currentVariant = selectedVariant ?? variants.find((v) => (0, import_core13.isVariantFulfillable)(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
3275
3405
  const vRule = ruleFor3(bundle, product.id, currentVariant?.id);
3276
3406
  const variantMax = variantRuleFor3(bundle, currentVariant?.id)?.max;
3277
3407
  const stepPicks = (0, import_react15.useMemo)(
@@ -3309,7 +3439,7 @@ function MultiStepPickerRow({
3309
3439
  }, [selections, currentVariant, committedQty]);
3310
3440
  const swapUnits = currentVariant ? swapUnitsFor?.(stepIndex, product.id, currentVariant.id) ?? 0 : 0;
3311
3441
  const inSwapState = swapUnits >= vRule.min;
3312
- const room = (0, import_core14.stepHeadroom)(step?.maxQuantity ?? null, unitsInStep);
3442
+ const room = (0, import_core13.stepHeadroom)(step?.maxQuantity ?? null, unitsInStep);
3313
3443
  const productHeadroom = Math.min(
3314
3444
  rule.max - productOtherUnits,
3315
3445
  variantMax ?? Infinity
@@ -3318,7 +3448,7 @@ function MultiStepPickerRow({
3318
3448
  productHeadroom,
3319
3449
  room === Number.POSITIVE_INFINITY ? productHeadroom : committedQty + room
3320
3450
  );
3321
- const stockRemaining = currentVariant ? (0, import_core14.maxAddableQuantity)(currentVariant, Number.MAX_SAFE_INTEGER, variantOtherUnits) : 0;
3451
+ const stockRemaining = currentVariant ? (0, import_core13.maxAddableQuantity)(currentVariant, Number.MAX_SAFE_INTEGER, variantOtherUnits) : 0;
3322
3452
  const cap = Math.max(0, Math.min(spotCeiling, stockRemaining));
3323
3453
  const stepperMax = Math.max(vRule.min, cap);
3324
3454
  const [qty, setQty] = (0, import_react15.useState)(vRule.min);
@@ -3331,7 +3461,7 @@ function MultiStepPickerRow({
3331
3461
  }, [variantInStep, currentVariantId, vRule.min]);
3332
3462
  if (!currentVariant || !step) return null;
3333
3463
  const thumbImage = currentVariant.image ?? product.featuredImage ?? null;
3334
- const unitPriceText = (0, import_core14.formatUnitPrice)(
3464
+ const unitPriceText = (0, import_core13.formatUnitPrice)(
3335
3465
  currentVariant.unitPrice,
3336
3466
  currentVariant.unitPriceMeasurement,
3337
3467
  currency
@@ -3370,7 +3500,7 @@ function MultiStepPickerRow({
3370
3500
  }
3371
3501
  const priceCents = parseFloat(currentVariant.price.amount);
3372
3502
  const compareCents = currentVariant.compareAtPrice ? parseFloat(currentVariant.compareAtPrice.amount) : null;
3373
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3503
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3374
3504
  "div",
3375
3505
  {
3376
3506
  className: `lb-mix-match__modal-product${isOos ? " lb-mix-match__modal-product--sold-out" : ""}${variantInStep ? " lb-mix-match__modal-product--in-bundle" : ""}`,
@@ -3379,8 +3509,8 @@ function MultiStepPickerRow({
3379
3509
  "data-type": product.productType ?? "",
3380
3510
  "aria-disabled": isOos || void 0,
3381
3511
  children: [
3382
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-product-thumb", children: [
3383
- thumbImage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3512
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-product-thumb", children: [
3513
+ thumbImage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3384
3514
  "img",
3385
3515
  {
3386
3516
  src: thumbImage.url,
@@ -3388,10 +3518,10 @@ function MultiStepPickerRow({
3388
3518
  loading: "lazy"
3389
3519
  }
3390
3520
  ),
3391
- variantInStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-mix-match__modal-added-badge", children: "Added" })
3521
+ variantInStep && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__modal-added-badge", children: "Added" })
3392
3522
  ] }),
3393
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-product-info", children: [
3394
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "lb-mix-match__modal-product-title", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3523
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-product-info", children: [
3524
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "lb-mix-match__modal-product-title", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3395
3525
  "a",
3396
3526
  {
3397
3527
  href: `/products/${product.handle}`,
@@ -3400,24 +3530,24 @@ function MultiStepPickerRow({
3400
3530
  children: product.title
3401
3531
  }
3402
3532
  ) }),
3403
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "lb-mix-match__modal-product-price", children: [
3404
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "data-row-price-sale": true, children: (0, import_core14.formatMoney)(priceCents, currency) }),
3405
- compareCents !== null && compareCents > priceCents && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("s", { className: "lb-mix-match__modal-product-compare", "data-row-compare": true, children: (0, import_core14.formatMoney)(compareCents, currency) })
3533
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { className: "lb-mix-match__modal-product-price", children: [
3534
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-row-price-sale": true, children: (0, import_core13.formatMoney)(priceCents, currency) }),
3535
+ compareCents !== null && compareCents > priceCents && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("s", { className: "lb-mix-match__modal-product-compare", "data-row-compare": true, children: (0, import_core13.formatMoney)(compareCents, currency) })
3406
3536
  ] }),
3407
- unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price", children: unitPriceText }),
3408
- showPicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-bundle-variant-option-groups", children: optionNames.map((optionName, optionIndex) => {
3537
+ unitPriceText && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price", children: unitPriceText }),
3538
+ showPicker && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-bundle-variant-option-groups", children: optionNames.map((optionName, optionIndex) => {
3409
3539
  const dropdownOptions = optionsFor(optionIndex).map((o) => ({
3410
3540
  value: o.value,
3411
3541
  label: o.value,
3412
3542
  disabled: o.disabled
3413
3543
  }));
3414
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3544
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3415
3545
  "div",
3416
3546
  {
3417
3547
  className: "lb-bundle-variant-option-group",
3418
3548
  children: [
3419
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-bundle-variant-option-label", children: optionName }),
3420
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3549
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-variant-option-label", children: optionName }),
3550
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3421
3551
  VariantDropdown,
3422
3552
  {
3423
3553
  className: "lb-mix-match__variant-select-dropdown",
@@ -3432,17 +3562,17 @@ function MultiStepPickerRow({
3432
3562
  optionName
3433
3563
  );
3434
3564
  }) }),
3435
- !showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
3436
- !isOos && needsMoreSpots && room > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-mix-match__modal-needs-spots", children: vRule.min === 1 ? "Needs 1 spot" : `Needs ${vRule.min} spots` }),
3437
- isOos ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lb-mix-match__modal-product-actions", children: [
3438
- showStepper && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3565
+ !showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
3566
+ !isOos && needsMoreSpots && room > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__modal-needs-spots", children: vRule.min === 1 ? "Needs 1 spot" : `Needs ${vRule.min} spots` }),
3567
+ isOos ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__modal-product-actions", children: [
3568
+ showStepper && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3439
3569
  "div",
3440
3570
  {
3441
3571
  className: "lb-mix-match__qty-stepper",
3442
3572
  role: "group",
3443
3573
  "aria-label": "Quantity",
3444
3574
  children: [
3445
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3575
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3446
3576
  "button",
3447
3577
  {
3448
3578
  type: "button",
@@ -3464,7 +3594,7 @@ function MultiStepPickerRow({
3464
3594
  children: "\u2212"
3465
3595
  }
3466
3596
  ),
3467
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3597
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3468
3598
  "span",
3469
3599
  {
3470
3600
  className: "lb-mix-match__qty-stepper-value",
@@ -3473,7 +3603,7 @@ function MultiStepPickerRow({
3473
3603
  children: shownQty
3474
3604
  }
3475
3605
  ),
3476
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3606
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3477
3607
  "button",
3478
3608
  {
3479
3609
  type: "button",
@@ -3498,7 +3628,7 @@ function MultiStepPickerRow({
3498
3628
  ]
3499
3629
  }
3500
3630
  ) }),
3501
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3631
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3502
3632
  "button",
3503
3633
  {
3504
3634
  type: "button",
@@ -3517,7 +3647,7 @@ function MultiStepPickerRow({
3517
3647
  );
3518
3648
  }
3519
3649
  function CloseIcon3() {
3520
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3650
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3521
3651
  "svg",
3522
3652
  {
3523
3653
  width: "20",
@@ -3527,14 +3657,14 @@ function CloseIcon3() {
3527
3657
  xmlns: "http://www.w3.org/2000/svg",
3528
3658
  "aria-hidden": "true",
3529
3659
  children: [
3530
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
3531
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
3660
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
3661
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
3532
3662
  ]
3533
3663
  }
3534
3664
  );
3535
3665
  }
3536
3666
  function SearchClearIcon2() {
3537
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3667
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3538
3668
  "svg",
3539
3669
  {
3540
3670
  width: "16",
@@ -3543,19 +3673,19 @@ function SearchClearIcon2() {
3543
3673
  fill: "currentColor",
3544
3674
  xmlns: "http://www.w3.org/2000/svg",
3545
3675
  "aria-hidden": "true",
3546
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M14.348 5.652a.5.5 0 0 0-.707 0L10 9.293 6.36 5.652a.5.5 0 1 0-.708.707L9.293 10l-3.641 3.641a.5.5 0 0 0 .708.707L10 10.707l3.641 3.641a.5.5 0 0 0 .707-.707L10.707 10l3.641-3.641a.5.5 0 0 0 0-.707z" })
3676
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M14.348 5.652a.5.5 0 0 0-.707 0L10 9.293 6.36 5.652a.5.5 0 1 0-.708.707L9.293 10l-3.641 3.641a.5.5 0 0 0 .708.707L10 10.707l3.641 3.641a.5.5 0 0 0 .707-.707L10.707 10l3.641-3.641a.5.5 0 0 0 0-.707z" })
3547
3677
  }
3548
3678
  );
3549
3679
  }
3550
3680
 
3551
3681
  // src/components/MultiStepBundle.tsx
3552
- var import_jsx_runtime8 = require("react/jsx-runtime");
3682
+ var import_jsx_runtime9 = require("react/jsx-runtime");
3553
3683
  function ruleFor4(bundle, productId, variantId) {
3554
3684
  if (variantId) {
3555
3685
  const vRule = bundle.variantRules[variantId];
3556
3686
  if (vRule) return vRule;
3557
3687
  }
3558
- return bundle.productRules[productId] ?? import_core15.DEFAULT_PRODUCT_RULE;
3688
+ return bundle.productRules[productId] ?? import_core14.DEFAULT_PRODUCT_RULE;
3559
3689
  }
3560
3690
  function variantRuleFor4(bundle, variantId) {
3561
3691
  return variantId ? bundle.variantRules[variantId] : void 0;
@@ -3597,10 +3727,6 @@ function MultiStepBundle(props) {
3597
3727
  storefrontAccessToken,
3598
3728
  bundleGid
3599
3729
  });
3600
- const { outOfStockBehavior } = useShopSettings({
3601
- shopDomain,
3602
- storefrontAccessToken
3603
- });
3604
3730
  const { elementRef, trackAddToCart } = useAnalytics({
3605
3731
  shopDomain,
3606
3732
  appUrl: appUrl ?? `https://${shopDomain}`,
@@ -3636,9 +3762,9 @@ function MultiStepBundle(props) {
3636
3762
  for (const [pid, rule] of Object.entries(bundle.productRules)) {
3637
3763
  if (!rule.required) continue;
3638
3764
  for (let i = 0; i < steps.length; i++) {
3639
- const product = (0, import_core15.productsForStep)(bundle, i).find((p) => p.id === pid);
3765
+ const product = (0, import_core14.productsForStep)(bundle, i).find((p) => p.id === pid);
3640
3766
  const variant = product?.variants.nodes.find(
3641
- (v) => (0, import_core15.isVariantFulfillable)(v, rule.min)
3767
+ (v) => (0, import_core14.isVariantFulfillable)(v, rule.min)
3642
3768
  );
3643
3769
  if (!product || !variant) continue;
3644
3770
  seeded[i].push({
@@ -3650,7 +3776,7 @@ function MultiStepBundle(props) {
3650
3776
  featuredImage: variant.image?.url ?? product.featuredImage?.url ?? null,
3651
3777
  price: parseFloat(variant.price.amount),
3652
3778
  compareAtPrice: variant.compareAtPrice ? parseFloat(variant.compareAtPrice.amount) : null,
3653
- unitPrice: (0, import_core15.formatUnitPrice)(
3779
+ unitPrice: (0, import_core14.formatUnitPrice)(
3654
3780
  variant.unitPrice,
3655
3781
  variant.unitPriceMeasurement,
3656
3782
  seedCurrency
@@ -3691,7 +3817,7 @@ function MultiStepBundle(props) {
3691
3817
  if (sel.quantity <= 0) continue;
3692
3818
  comparePrice += sel.price * sel.quantity;
3693
3819
  if (bundle) {
3694
- salePrice += (0, import_core15.calculateDiscount)(
3820
+ salePrice += (0, import_core14.calculateDiscount)(
3695
3821
  sel.price,
3696
3822
  bundle.discountConfig.discountType,
3697
3823
  bundle.discountConfig.discountValue
@@ -3839,9 +3965,9 @@ function MultiStepBundle(props) {
3839
3965
  }
3840
3966
  }, [bundle, selections, valid, onAddToCart, onError, trackAddToCart, totalQuantity, steps]);
3841
3967
  if (result.status === "loading") {
3842
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
3843
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
3844
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
3968
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
3969
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "lb-skeleton lb-skeleton--title" }),
3970
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "lb-skeleton lb-skeleton--products" })
3845
3971
  ] });
3846
3972
  }
3847
3973
  if (result.status === "error") return null;
@@ -3853,8 +3979,8 @@ function MultiStepBundle(props) {
3853
3979
  ([pid, rule]) => {
3854
3980
  if (!rule.required) return false;
3855
3981
  return !steps.some(
3856
- (_, i) => (0, import_core15.productsForStep)(bundle, i).some(
3857
- (p) => p.id === pid && p.variants.nodes.some((v) => (0, import_core15.isVariantFulfillable)(v, rule.min))
3982
+ (_, i) => (0, import_core14.productsForStep)(bundle, i).some(
3983
+ (p) => p.id === pid && p.variants.nodes.some((v) => (0, import_core14.isVariantFulfillable)(v, rule.min))
3858
3984
  )
3859
3985
  );
3860
3986
  }
@@ -3862,7 +3988,7 @@ function MultiStepBundle(props) {
3862
3988
  if (requiredBlocked) return null;
3863
3989
  const currency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
3864
3990
  const ctaLabel = addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText || "Add to cart";
3865
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3991
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3866
3992
  "div",
3867
3993
  {
3868
3994
  ref: (el) => {
@@ -3874,12 +4000,19 @@ function MultiStepBundle(props) {
3874
4000
  "aria-label": bundle.title,
3875
4001
  "data-required-quantity": totalMin,
3876
4002
  children: [
3877
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-bundle-header__content", children: [
3878
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
3879
- bundle.description && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
4003
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "lb-bundle-header", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-bundle-header__content", children: [
4004
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "lb-bundle-title", children: bundle.title }),
4005
+ bundle.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "lb-bundle-subtitle", children: bundle.description })
3880
4006
  ] }) }),
3881
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__progress", "data-progress": true, children: [
3882
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4007
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4008
+ BundleCountdown,
4009
+ {
4010
+ endsAt: bundle.endsAt,
4011
+ widgetConfig: bundle.widgetConfig
4012
+ }
4013
+ ),
4014
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-mix-match__progress", "data-progress": true, children: [
4015
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3883
4016
  "div",
3884
4017
  {
3885
4018
  className: "lb-mix-match__progress-segments",
@@ -3887,7 +4020,7 @@ function MultiStepBundle(props) {
3887
4020
  "aria-valuenow": completedSteps,
3888
4021
  "aria-valuemin": 0,
3889
4022
  "aria-valuemax": steps.length,
3890
- children: Array.from({ length: steps.length }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4023
+ children: Array.from({ length: steps.length }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3891
4024
  "span",
3892
4025
  {
3893
4026
  className: `lb-mix-match__progress-segment${i < completedSteps ? " lb-mix-match__progress-segment--filled" : ""}`,
@@ -3897,8 +4030,8 @@ function MultiStepBundle(props) {
3897
4030
  ))
3898
4031
  }
3899
4032
  ),
3900
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__progress-labels", children: [
3901
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4033
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-mix-match__progress-labels", children: [
4034
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3902
4035
  "span",
3903
4036
  {
3904
4037
  className: "lb-mix-match__progress-count",
@@ -3907,7 +4040,7 @@ function MultiStepBundle(props) {
3907
4040
  children: `${completedSteps} of ${steps.length} steps completed`
3908
4041
  }
3909
4042
  ),
3910
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4043
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3911
4044
  "span",
3912
4045
  {
3913
4046
  className: "lb-mix-match__progress-remaining",
@@ -3918,15 +4051,15 @@ function MultiStepBundle(props) {
3918
4051
  )
3919
4052
  ] })
3920
4053
  ] }),
3921
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-multi-step__groups", "data-step-groups": true, children: steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4054
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "lb-multi-step__groups", "data-step-groups": true, children: steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3922
4055
  "section",
3923
4056
  {
3924
4057
  className: "lb-multi-step__group",
3925
4058
  "data-step-group": i,
3926
4059
  children: [
3927
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-multi-step__group-heading", children: [
3928
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-multi-step__group-name", children: step.name }),
3929
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4060
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-multi-step__group-heading", children: [
4061
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-multi-step__group-name", children: step.name }),
4062
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3930
4063
  "span",
3931
4064
  {
3932
4065
  className: `lb-multi-step__group-count${stepSatisfied(i) ? " lb-multi-step__group-count--met" : ""}`,
@@ -3935,7 +4068,7 @@ function MultiStepBundle(props) {
3935
4068
  }
3936
4069
  )
3937
4070
  ] }),
3938
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4071
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3939
4072
  "div",
3940
4073
  {
3941
4074
  className: "lb-mix-match__slots lb-edge-fade lb-multi-step__group-slots",
@@ -3945,13 +4078,13 @@ function MultiStepBundle(props) {
3945
4078
  title button provides the keyboard/AT path (its
3946
4079
  activation bubbles here); × stops propagation. */
3947
4080
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions -- keyboard path is the inner "Edit selection" title button whose activation bubbles to this handler
3948
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4081
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3949
4082
  "div",
3950
4083
  {
3951
4084
  className: "lb-mix-match__slot lb-mix-match__slot--filled",
3952
4085
  onClick: () => setPickerOpenAt(i),
3953
4086
  children: [
3954
- item.featuredImage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-bundle-thumbnail", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4087
+ item.featuredImage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "lb-bundle-thumbnail", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3955
4088
  "img",
3956
4089
  {
3957
4090
  src: item.featuredImage,
@@ -3959,8 +4092,8 @@ function MultiStepBundle(props) {
3959
4092
  loading: "lazy"
3960
4093
  }
3961
4094
  ) }),
3962
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-mix-match__filled-info", children: [
3963
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4095
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-mix-match__filled-info", children: [
4096
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3964
4097
  "button",
3965
4098
  {
3966
4099
  type: "button",
@@ -3969,15 +4102,15 @@ function MultiStepBundle(props) {
3969
4102
  children: item.title
3970
4103
  }
3971
4104
  ),
3972
- item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__filled-variant", children: item.variantTitle }),
3973
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "lb-mix-match__filled-price", children: [
3974
- item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("s", { className: "lb-mix-match__filled-compare", children: (0, import_core15.formatMoney)(item.compareAtPrice, currency) }),
3975
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-product-price", children: (0, import_core15.formatMoney)(item.price, currency) }),
3976
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-qty-inline", children: `\xD7${item.quantity}` })
4105
+ item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-mix-match__filled-variant", children: item.variantTitle }),
4106
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "lb-mix-match__filled-price", children: [
4107
+ item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("s", { className: "lb-mix-match__filled-compare", children: (0, import_core14.formatMoney)(item.compareAtPrice, currency) }),
4108
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-bundle-product-price", children: (0, import_core14.formatMoney)(item.price, currency) }),
4109
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-bundle-qty-inline", children: `\xD7${item.quantity}` })
3977
4110
  ] }),
3978
- item.unitPrice && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-product-unit-price", children: item.unitPrice })
4111
+ item.unitPrice && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-bundle-product-unit-price", children: item.unitPrice })
3979
4112
  ] }),
3980
- canRemoveItem2(bundle, selections, item) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4113
+ canRemoveItem2(bundle, selections, item) ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3981
4114
  "button",
3982
4115
  {
3983
4116
  type: "button",
@@ -3987,13 +4120,13 @@ function MultiStepBundle(props) {
3987
4120
  e.stopPropagation();
3988
4121
  removeSlot(i, index);
3989
4122
  },
3990
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon4, {})
4123
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon4, {})
3991
4124
  }
3992
4125
  ) : (
3993
4126
  /* Required pick at its floor — quiet state chip instead
3994
4127
  of the ×; removal returns once another slot covers
3995
4128
  the product's minimum (variant swap flow). */
3996
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__slot-required", children: "Required" })
4129
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-mix-match__slot-required", children: "Required" })
3997
4130
  )
3998
4131
  ]
3999
4132
  },
@@ -4002,7 +4135,7 @@ function MultiStepBundle(props) {
4002
4135
  ))
4003
4136
  }
4004
4137
  ),
4005
- (0, import_core15.stepHeadroom)(step.maxQuantity, unitsByStep[i] ?? 0) !== 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4138
+ (0, import_core14.stepHeadroom)(step.maxQuantity, unitsByStep[i] ?? 0) !== 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4006
4139
  "button",
4007
4140
  {
4008
4141
  type: "button",
@@ -4011,15 +4144,15 @@ function MultiStepBundle(props) {
4011
4144
  "aria-label": `${step.minQuantity === 1 && step.maxQuantity === 1 ? "Choose a product" : "Choose products"}: ${step.name}`,
4012
4145
  onClick: () => setPickerOpenAt(i),
4013
4146
  children: [
4014
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4147
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4015
4148
  "span",
4016
4149
  {
4017
4150
  className: "lb-mix-match__add-product-icon",
4018
4151
  "aria-hidden": "true",
4019
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PlusIcon2, {})
4152
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PlusIcon2, {})
4020
4153
  }
4021
4154
  ),
4022
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-mix-match__add-product-label", children: step.minQuantity === 1 && step.maxQuantity === 1 ? "Choose a product" : "Choose products" })
4155
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-mix-match__add-product-label", children: step.minQuantity === 1 && step.maxQuantity === 1 ? "Choose a product" : "Choose products" })
4023
4156
  ]
4024
4157
  }
4025
4158
  )
@@ -4027,29 +4160,29 @@ function MultiStepBundle(props) {
4027
4160
  },
4028
4161
  i
4029
4162
  )) }),
4030
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "lb-bundle-divider" }),
4031
- allSatisfied && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-bundle-summary", "data-pricing-section": true, children: [
4032
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lb-bundle-summary__text", children: [
4033
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
4034
- bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
4163
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "lb-bundle-divider" }),
4164
+ allSatisfied && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-bundle-summary", "data-pricing-section": true, children: [
4165
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "lb-bundle-summary__text", children: [
4166
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
4167
+ bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
4035
4168
  "You save",
4036
4169
  " ",
4037
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-savings-amount": true, children: (0, import_core15.formatMoney)(summary.savings, currency) }),
4170
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-savings-amount": true, children: (0, import_core14.formatMoney)(summary.savings, currency) }),
4038
4171
  " ",
4039
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { "data-savings-percent": true, children: [
4172
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { "data-savings-percent": true, children: [
4040
4173
  "(",
4041
4174
  summary.savingsPercent,
4042
4175
  "%)"
4043
4176
  ] })
4044
4177
  ] })
4045
4178
  ] }),
4046
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
4047
- bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core15.formatMoney)(summary.comparePrice, currency) }),
4048
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core15.formatMoney)(summary.salePrice, currency) })
4179
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "lb-bundle-summary__prices", children: [
4180
+ bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: (0, import_core14.formatMoney)(summary.comparePrice, currency) }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: (0, import_core14.formatMoney)(summary.salePrice, currency) })
4049
4182
  ] })
4050
4183
  ] }),
4051
- cartError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
4052
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4184
+ cartError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
4185
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4053
4186
  "button",
4054
4187
  {
4055
4188
  className: "lb-bundle__cta",
@@ -4059,10 +4192,9 @@ function MultiStepBundle(props) {
4059
4192
  children: ctaLabel
4060
4193
  }
4061
4194
  ),
4062
- pickerOpenAt !== null && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4195
+ pickerOpenAt !== null && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4063
4196
  MultiStepPicker,
4064
4197
  {
4065
- outOfStockBehavior,
4066
4198
  bundle,
4067
4199
  currency,
4068
4200
  initialStep: pickerOpenAt,
@@ -4089,13 +4221,13 @@ function MultiStepBundle(props) {
4089
4221
  );
4090
4222
  }
4091
4223
  function stepHasInStockProduct(bundle, stepIndex) {
4092
- return (0, import_core15.productsForStep)(bundle, stepIndex).some((product) => {
4224
+ return (0, import_core14.productsForStep)(bundle, stepIndex).some((product) => {
4093
4225
  const rule = ruleFor4(bundle, product.id);
4094
- return product.variants.nodes.some((v) => (0, import_core15.isVariantFulfillable)(v, rule.min));
4226
+ return product.variants.nodes.some((v) => (0, import_core14.isVariantFulfillable)(v, rule.min));
4095
4227
  });
4096
4228
  }
4097
4229
  function PlusIcon2() {
4098
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4230
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4099
4231
  "svg",
4100
4232
  {
4101
4233
  width: "18",
@@ -4105,14 +4237,14 @@ function PlusIcon2() {
4105
4237
  xmlns: "http://www.w3.org/2000/svg",
4106
4238
  "aria-hidden": "true",
4107
4239
  children: [
4108
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
4109
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
4240
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
4241
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
4110
4242
  ]
4111
4243
  }
4112
4244
  );
4113
4245
  }
4114
4246
  function CloseIcon4() {
4115
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4247
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4116
4248
  "svg",
4117
4249
  {
4118
4250
  width: "16",
@@ -4122,8 +4254,8 @@ function CloseIcon4() {
4122
4254
  xmlns: "http://www.w3.org/2000/svg",
4123
4255
  "aria-hidden": "true",
4124
4256
  children: [
4125
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
4126
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
4257
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
4258
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
4127
4259
  ]
4128
4260
  }
4129
4261
  );
@@ -4137,7 +4269,7 @@ async function fetchShopCustomCss(options) {
4137
4269
 
4138
4270
  // src/hooks/useBundlesForProduct.ts
4139
4271
  var import_react17 = require("react");
4140
- var import_core16 = require("@lime-bundles/core");
4272
+ var import_core15 = require("@lime-bundles/core");
4141
4273
  var INITIAL_STATE2 = {
4142
4274
  status: "loading",
4143
4275
  bundles: null,
@@ -4150,7 +4282,7 @@ function useBundlesForProduct(options) {
4150
4282
  (0, import_react17.useEffect)(() => {
4151
4283
  const controller = new AbortController();
4152
4284
  setState(INITIAL_STATE2);
4153
- (0, import_core16.fetchBundlesForProduct)({
4285
+ (0, import_core15.fetchBundlesForProduct)({
4154
4286
  shopDomain: options.shopDomain,
4155
4287
  storefrontAccessToken: options.storefrontAccessToken,
4156
4288
  productHandle: options.productHandle,
@@ -4173,7 +4305,7 @@ function useBundlesForProduct(options) {
4173
4305
  signal: controller.signal
4174
4306
  }).then((settings) => {
4175
4307
  if (controller.signal.aborted) return;
4176
- (0, import_core16.injectCustomCss)(options.shopDomain, settings.customCss);
4308
+ (0, import_core15.injectCustomCss)(options.shopDomain, settings.customCss);
4177
4309
  }).catch(() => {
4178
4310
  });
4179
4311
  return () => {
@@ -4189,15 +4321,15 @@ function useBundlesForProduct(options) {
4189
4321
  }
4190
4322
 
4191
4323
  // src/index.ts
4324
+ var import_core16 = require("@lime-bundles/core");
4192
4325
  var import_core17 = require("@lime-bundles/core");
4193
- var import_core18 = require("@lime-bundles/core");
4194
4326
  // Annotate the CommonJS export names for ESM import in node:
4195
4327
  0 && (module.exports = {
4196
4328
  BUNDLES_FOR_PRODUCT_QUERY,
4197
4329
  BUNDLE_METAOBJECT_QUERY,
4198
4330
  BogoBundle,
4331
+ BundleCountdown,
4199
4332
  BundleParseError,
4200
- DEFAULT_OUT_OF_STOCK_BEHAVIOR,
4201
4333
  FixedBundle,
4202
4334
  MixMatchBundle,
4203
4335
  MultiStepBundle,
@@ -4228,7 +4360,6 @@ var import_core18 = require("@lime-bundles/core");
4228
4360
  parseCents,
4229
4361
  parseMetaobjectBundle,
4230
4362
  parseMetaobjectBundleStrict,
4231
- parseOutOfStockBehavior,
4232
4363
  percentageDiscountUnit,
4233
4364
  productsForStep,
4234
4365
  reportAddToCart,
@@ -4240,7 +4371,6 @@ var import_core18 = require("@lime-bundles/core");
4240
4371
  useAnalytics,
4241
4372
  useBundleData,
4242
4373
  useBundlesForProduct,
4243
- useShopSettings,
4244
4374
  useVariantSelection,
4245
4375
  useWidgetConfigVars,
4246
4376
  validateQuantity