@lime-bundles/react 6.0.0 → 6.2.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/README.md +7 -1
- package/dist/index.cjs +688 -518
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -3
- package/dist/index.d.ts +22 -3
- package/dist/index.js +633 -461
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1901 -0
- package/docs/css-variables.md +7 -1
- package/docs/hydrogen.md +29 -4
- package/docs/react-nextjs.md +24 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/FixedBundle.tsx
|
|
2
|
-
import { useCallback as useCallback5, useEffect as
|
|
2
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo4, useState as useState6 } from "react";
|
|
3
3
|
import {
|
|
4
4
|
formatMoney,
|
|
5
5
|
formatUnitPrice,
|
|
@@ -659,8 +659,48 @@ function VariantDropdown({
|
|
|
659
659
|
);
|
|
660
660
|
}
|
|
661
661
|
|
|
662
|
-
// src/components/
|
|
662
|
+
// src/components/BundleCountdown.tsx
|
|
663
|
+
import { useEffect as useEffect6, useState as useState5 } from "react";
|
|
663
664
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
665
|
+
function pad(n) {
|
|
666
|
+
return n < 10 ? "0" + n : String(n);
|
|
667
|
+
}
|
|
668
|
+
function formatRemaining(remaining) {
|
|
669
|
+
const days = Math.floor(remaining / 864e5);
|
|
670
|
+
const hours = Math.floor(remaining % 864e5 / 36e5);
|
|
671
|
+
const mins = Math.floor(remaining % 36e5 / 6e4);
|
|
672
|
+
const secs = Math.floor(remaining % 6e4 / 1e3);
|
|
673
|
+
return days > 0 ? days + "d " + pad(hours) + "h " + pad(mins) + "m " + pad(secs) + "s" : pad(hours) + "h " + pad(mins) + "m " + pad(secs) + "s";
|
|
674
|
+
}
|
|
675
|
+
function BundleCountdown({
|
|
676
|
+
endsAt,
|
|
677
|
+
widgetConfig,
|
|
678
|
+
label = "Limited time offer"
|
|
679
|
+
}) {
|
|
680
|
+
const enabled = !!endsAt && widgetConfig?.countdown?.showCountdown !== false;
|
|
681
|
+
const endTime = enabled ? new Date(endsAt).getTime() : NaN;
|
|
682
|
+
const [remaining, setRemaining] = useState5(null);
|
|
683
|
+
useEffect6(() => {
|
|
684
|
+
if (!enabled || isNaN(endTime)) {
|
|
685
|
+
setRemaining(null);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
const update = () => setRemaining(endTime - Date.now());
|
|
689
|
+
update();
|
|
690
|
+
const interval = setInterval(update, 1e3);
|
|
691
|
+
return () => clearInterval(interval);
|
|
692
|
+
}, [enabled, endTime]);
|
|
693
|
+
if (!enabled || isNaN(endTime) || remaining === null || remaining <= 0) {
|
|
694
|
+
return null;
|
|
695
|
+
}
|
|
696
|
+
return /* @__PURE__ */ jsxs2("div", { className: "lb-bundle-countdown", "data-countdown": true, children: [
|
|
697
|
+
/* @__PURE__ */ jsx2("div", { className: "lb-bundle-countdown__label", children: /* @__PURE__ */ jsx2("span", { children: label }) }),
|
|
698
|
+
/* @__PURE__ */ jsx2("span", { className: "lb-bundle-countdown__timer", "data-countdown-timer": true, children: formatRemaining(remaining) })
|
|
699
|
+
] });
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/components/FixedBundle.tsx
|
|
703
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
664
704
|
function FixedBundle(props) {
|
|
665
705
|
const {
|
|
666
706
|
shopDomain,
|
|
@@ -684,9 +724,9 @@ function FixedBundle(props) {
|
|
|
684
724
|
bundleType: "fixed",
|
|
685
725
|
enabled: analyticsEnabled !== false
|
|
686
726
|
});
|
|
687
|
-
const [addingToCart, setAddingToCart] =
|
|
688
|
-
const [cartError, setCartError] =
|
|
689
|
-
const [selectedVariants, setSelectedVariants] =
|
|
727
|
+
const [addingToCart, setAddingToCart] = useState6(false);
|
|
728
|
+
const [cartError, setCartError] = useState6(null);
|
|
729
|
+
const [selectedVariants, setSelectedVariants] = useState6({});
|
|
690
730
|
const handleVariantChange = useCallback5(
|
|
691
731
|
(productId, variant) => {
|
|
692
732
|
setSelectedVariants((prev) => {
|
|
@@ -699,7 +739,7 @@ function FixedBundle(props) {
|
|
|
699
739
|
const bundle = result.status === "success" && result.bundle.bundleType === "fixed" ? result.bundle : null;
|
|
700
740
|
const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
701
741
|
const productsEdgeFadeRef = useEdgeFade();
|
|
702
|
-
|
|
742
|
+
useEffect7(() => {
|
|
703
743
|
if (result.status === "error") {
|
|
704
744
|
onError?.(result.error);
|
|
705
745
|
return;
|
|
@@ -777,9 +817,9 @@ function FixedBundle(props) {
|
|
|
777
817
|
}
|
|
778
818
|
}, [bundle, onAddToCart, onError, trackAddToCart, selectedVariants]);
|
|
779
819
|
if (result.status === "loading") {
|
|
780
|
-
return /* @__PURE__ */
|
|
781
|
-
/* @__PURE__ */
|
|
782
|
-
/* @__PURE__ */
|
|
820
|
+
return /* @__PURE__ */ jsxs3("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
|
|
821
|
+
/* @__PURE__ */ jsx3("div", { className: "lb-skeleton lb-skeleton--title" }),
|
|
822
|
+
/* @__PURE__ */ jsx3("div", { className: "lb-skeleton lb-skeleton--products" })
|
|
783
823
|
] });
|
|
784
824
|
}
|
|
785
825
|
if (result.status === "error") return null;
|
|
@@ -806,7 +846,7 @@ function FixedBundle(props) {
|
|
|
806
846
|
const savingsPercent = comparePrice > 0 && savings > 0 ? Math.round(savings / comparePrice * 100) : 0;
|
|
807
847
|
const showCompare = bundle.widgetConfig.pricing.showComparePrice && savings > 0;
|
|
808
848
|
const showSavings = bundle.widgetConfig.savingsBar.visible && savings > 0;
|
|
809
|
-
return /* @__PURE__ */
|
|
849
|
+
return /* @__PURE__ */ jsxs3(
|
|
810
850
|
"div",
|
|
811
851
|
{
|
|
812
852
|
ref: (el) => {
|
|
@@ -817,11 +857,18 @@ function FixedBundle(props) {
|
|
|
817
857
|
role: "region",
|
|
818
858
|
"aria-label": bundle.title,
|
|
819
859
|
children: [
|
|
820
|
-
/* @__PURE__ */
|
|
821
|
-
/* @__PURE__ */
|
|
822
|
-
bundle.description && /* @__PURE__ */
|
|
860
|
+
/* @__PURE__ */ jsx3("div", { className: "lb-bundle-header", children: /* @__PURE__ */ jsxs3("div", { className: "lb-bundle-header__content", children: [
|
|
861
|
+
/* @__PURE__ */ jsx3("h3", { className: "lb-bundle-title", children: bundle.title }),
|
|
862
|
+
bundle.description && /* @__PURE__ */ jsx3("p", { className: "lb-bundle-subtitle", children: bundle.description })
|
|
823
863
|
] }) }),
|
|
824
|
-
/* @__PURE__ */
|
|
864
|
+
/* @__PURE__ */ jsx3(
|
|
865
|
+
BundleCountdown,
|
|
866
|
+
{
|
|
867
|
+
endsAt: bundle.endsAt,
|
|
868
|
+
widgetConfig: bundle.widgetConfig
|
|
869
|
+
}
|
|
870
|
+
),
|
|
871
|
+
/* @__PURE__ */ jsx3("div", { className: "lb-bundle__products lb-edge-fade", ref: productsEdgeFadeRef, children: bundle.products.map((product) => /* @__PURE__ */ jsx3(
|
|
825
872
|
FixedProductRow,
|
|
826
873
|
{
|
|
827
874
|
bundle,
|
|
@@ -832,29 +879,29 @@ function FixedBundle(props) {
|
|
|
832
879
|
},
|
|
833
880
|
product.id
|
|
834
881
|
)) }),
|
|
835
|
-
/* @__PURE__ */
|
|
836
|
-
/* @__PURE__ */
|
|
837
|
-
/* @__PURE__ */
|
|
838
|
-
/* @__PURE__ */
|
|
839
|
-
showSavings && /* @__PURE__ */
|
|
882
|
+
/* @__PURE__ */ jsx3("div", { className: "lb-bundle-divider" }),
|
|
883
|
+
/* @__PURE__ */ jsxs3("div", { className: "lb-bundle-summary", children: [
|
|
884
|
+
/* @__PURE__ */ jsxs3("div", { className: "lb-bundle-summary__text", children: [
|
|
885
|
+
/* @__PURE__ */ jsx3("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
|
|
886
|
+
showSavings && /* @__PURE__ */ jsxs3("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
|
|
840
887
|
"You save",
|
|
841
888
|
" ",
|
|
842
|
-
/* @__PURE__ */
|
|
889
|
+
/* @__PURE__ */ jsx3("span", { "data-savings-amount": true, children: formatMoney(savings, currency) }),
|
|
843
890
|
" ",
|
|
844
|
-
/* @__PURE__ */
|
|
891
|
+
/* @__PURE__ */ jsxs3("span", { "data-savings-percent": true, children: [
|
|
845
892
|
"(",
|
|
846
893
|
savingsPercent,
|
|
847
894
|
"%)"
|
|
848
895
|
] })
|
|
849
896
|
] })
|
|
850
897
|
] }),
|
|
851
|
-
/* @__PURE__ */
|
|
852
|
-
showCompare && /* @__PURE__ */
|
|
853
|
-
/* @__PURE__ */
|
|
898
|
+
/* @__PURE__ */ jsxs3("span", { className: "lb-bundle-summary__prices", children: [
|
|
899
|
+
showCompare && /* @__PURE__ */ jsx3("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: formatMoney(comparePrice, currency) }),
|
|
900
|
+
/* @__PURE__ */ jsx3("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: formatMoney(salePrice, currency) })
|
|
854
901
|
] })
|
|
855
902
|
] }),
|
|
856
|
-
cartError && /* @__PURE__ */
|
|
857
|
-
/* @__PURE__ */
|
|
903
|
+
cartError && /* @__PURE__ */ jsx3("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
|
|
904
|
+
/* @__PURE__ */ jsx3(
|
|
858
905
|
"button",
|
|
859
906
|
{
|
|
860
907
|
className: "lb-bundle__cta",
|
|
@@ -879,7 +926,7 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
879
926
|
variants,
|
|
880
927
|
optionNames
|
|
881
928
|
});
|
|
882
|
-
|
|
929
|
+
useEffect7(() => {
|
|
883
930
|
onVariantChange(product.id, selectedVariant ?? null);
|
|
884
931
|
}, [selectedVariant, product.id, onVariantChange]);
|
|
885
932
|
const displayVariant = selectedVariant ?? variants.find(
|
|
@@ -900,15 +947,15 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
900
947
|
bundle.widgetConfig.lowStockThreshold,
|
|
901
948
|
bundle.widgetConfig.showLowStockBadge
|
|
902
949
|
);
|
|
903
|
-
return /* @__PURE__ */
|
|
950
|
+
return /* @__PURE__ */ jsxs3(
|
|
904
951
|
"div",
|
|
905
952
|
{
|
|
906
953
|
className: isOos ? "lb-bundle-product-row lb-bundle-product-row--oos" : "lb-bundle-product-row",
|
|
907
954
|
"aria-disabled": isOos || void 0,
|
|
908
955
|
part: "product",
|
|
909
956
|
children: [
|
|
910
|
-
isOos && /* @__PURE__ */
|
|
911
|
-
thumbImage && /* @__PURE__ */
|
|
957
|
+
isOos && /* @__PURE__ */ jsx3("span", { className: "lb-bundle-product-row__oos", children: "Out of stock" }),
|
|
958
|
+
thumbImage && /* @__PURE__ */ jsx3(
|
|
912
959
|
"img",
|
|
913
960
|
{
|
|
914
961
|
src: thumbImage.url,
|
|
@@ -917,11 +964,11 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
917
964
|
loading: "lazy"
|
|
918
965
|
}
|
|
919
966
|
),
|
|
920
|
-
/* @__PURE__ */
|
|
921
|
-
/* @__PURE__ */
|
|
922
|
-
!showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */
|
|
923
|
-
/* @__PURE__ */
|
|
924
|
-
compareAt && /* @__PURE__ */
|
|
967
|
+
/* @__PURE__ */ jsxs3("div", { className: "lb-bundle__product-info", children: [
|
|
968
|
+
/* @__PURE__ */ jsx3("p", { className: "lb-bundle__product-title", children: product.title }),
|
|
969
|
+
!showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */ jsx3("span", { className: "lb-bundle-variant-badge", children: displayVariant.title }),
|
|
970
|
+
/* @__PURE__ */ jsxs3("span", { className: "lb-bundle-product-prices", children: [
|
|
971
|
+
compareAt && /* @__PURE__ */ jsx3(
|
|
925
972
|
"span",
|
|
926
973
|
{
|
|
927
974
|
className: "lb-bundle-product-compare-price",
|
|
@@ -929,9 +976,9 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
929
976
|
children: compareAt
|
|
930
977
|
}
|
|
931
978
|
),
|
|
932
|
-
/* @__PURE__ */
|
|
979
|
+
/* @__PURE__ */ jsx3("span", { className: "lb-bundle__product-price", "data-product-price": true, children: priceText })
|
|
933
980
|
] }),
|
|
934
|
-
unitPriceText && /* @__PURE__ */
|
|
981
|
+
unitPriceText && /* @__PURE__ */ jsx3(
|
|
935
982
|
"span",
|
|
936
983
|
{
|
|
937
984
|
className: "lb-bundle__product-unit-price",
|
|
@@ -939,18 +986,18 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
939
986
|
children: unitPriceText
|
|
940
987
|
}
|
|
941
988
|
),
|
|
942
|
-
showLowStock && /* @__PURE__ */
|
|
989
|
+
showLowStock && /* @__PURE__ */ jsxs3("span", { className: "lb-bundle-low-stock-badge", children: [
|
|
943
990
|
"Only ",
|
|
944
991
|
displayVariant.quantityAvailable,
|
|
945
992
|
" left"
|
|
946
993
|
] }),
|
|
947
|
-
showPicker && /* @__PURE__ */
|
|
994
|
+
showPicker && /* @__PURE__ */ jsx3("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
|
|
948
995
|
const dropdownOptions = optionsFor(optionIndex).map((o) => ({
|
|
949
996
|
value: o.value,
|
|
950
997
|
label: o.value,
|
|
951
998
|
disabled: o.disabled
|
|
952
999
|
}));
|
|
953
|
-
return /* @__PURE__ */
|
|
1000
|
+
return /* @__PURE__ */ jsx3(
|
|
954
1001
|
VariantDropdown,
|
|
955
1002
|
{
|
|
956
1003
|
options: dropdownOptions,
|
|
@@ -962,7 +1009,7 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
962
1009
|
);
|
|
963
1010
|
}) })
|
|
964
1011
|
] }),
|
|
965
|
-
displayVariant && /* @__PURE__ */
|
|
1012
|
+
displayVariant && /* @__PURE__ */ jsxs3("span", { className: "lb-bundle-qty-chip", "data-qty-inline": true, children: [
|
|
966
1013
|
"\xD7",
|
|
967
1014
|
displayQty
|
|
968
1015
|
] })
|
|
@@ -972,7 +1019,7 @@ function FixedProductRow({ bundle, product, currency, isOos, onVariantChange })
|
|
|
972
1019
|
}
|
|
973
1020
|
|
|
974
1021
|
// src/components/MixMatchBundle.tsx
|
|
975
|
-
import { useCallback as useCallback6, useEffect as
|
|
1022
|
+
import { useCallback as useCallback6, useEffect as useEffect12, useMemo as useMemo6, useState as useState9 } from "react";
|
|
976
1023
|
import {
|
|
977
1024
|
formatMoney as formatMoney3,
|
|
978
1025
|
formatUnitPrice as formatUnitPrice3,
|
|
@@ -982,14 +1029,14 @@ import {
|
|
|
982
1029
|
} from "@lime-bundles/core";
|
|
983
1030
|
|
|
984
1031
|
// src/hooks/useShopSettings.ts
|
|
985
|
-
import { useEffect as
|
|
1032
|
+
import { useEffect as useEffect8, useState as useState7 } from "react";
|
|
986
1033
|
import {
|
|
987
1034
|
DEFAULT_OUT_OF_STOCK_BEHAVIOR as DEFAULT_OUT_OF_STOCK_BEHAVIOR2
|
|
988
1035
|
} from "@lime-bundles/core";
|
|
989
1036
|
function useShopSettings(options) {
|
|
990
|
-
const [outOfStockBehavior, setOutOfStockBehavior] =
|
|
1037
|
+
const [outOfStockBehavior, setOutOfStockBehavior] = useState7(DEFAULT_OUT_OF_STOCK_BEHAVIOR2);
|
|
991
1038
|
const { shopDomain, storefrontAccessToken } = options;
|
|
992
|
-
|
|
1039
|
+
useEffect8(() => {
|
|
993
1040
|
const controller = new AbortController();
|
|
994
1041
|
let active = true;
|
|
995
1042
|
fetchShopSettingsOrDefault({
|
|
@@ -1010,10 +1057,10 @@ function useShopSettings(options) {
|
|
|
1010
1057
|
|
|
1011
1058
|
// src/components/MixMatchPicker.tsx
|
|
1012
1059
|
import {
|
|
1013
|
-
useEffect as
|
|
1060
|
+
useEffect as useEffect11,
|
|
1014
1061
|
useMemo as useMemo5,
|
|
1015
1062
|
useRef as useRef6,
|
|
1016
|
-
useState as
|
|
1063
|
+
useState as useState8
|
|
1017
1064
|
} from "react";
|
|
1018
1065
|
import { createPortal } from "react-dom";
|
|
1019
1066
|
import {
|
|
@@ -1025,7 +1072,7 @@ import {
|
|
|
1025
1072
|
} from "@lime-bundles/core";
|
|
1026
1073
|
|
|
1027
1074
|
// src/hooks/useScrollLock.ts
|
|
1028
|
-
import { useEffect as
|
|
1075
|
+
import { useEffect as useEffect9 } from "react";
|
|
1029
1076
|
var lockCount = 0;
|
|
1030
1077
|
var savedY = 0;
|
|
1031
1078
|
function lock() {
|
|
@@ -1054,7 +1101,7 @@ function unlock() {
|
|
|
1054
1101
|
window.scrollTo(0, savedY);
|
|
1055
1102
|
}
|
|
1056
1103
|
function useScrollLock(active) {
|
|
1057
|
-
|
|
1104
|
+
useEffect9(() => {
|
|
1058
1105
|
if (!active) return;
|
|
1059
1106
|
lock();
|
|
1060
1107
|
return unlock;
|
|
@@ -1062,7 +1109,7 @@ function useScrollLock(active) {
|
|
|
1062
1109
|
}
|
|
1063
1110
|
|
|
1064
1111
|
// src/hooks/useFocusTrap.ts
|
|
1065
|
-
import { useEffect as
|
|
1112
|
+
import { useEffect as useEffect10, useRef as useRef5 } from "react";
|
|
1066
1113
|
var FOCUSABLE_SELECTOR = [
|
|
1067
1114
|
"a[href]",
|
|
1068
1115
|
"button:not([disabled])",
|
|
@@ -1088,7 +1135,7 @@ function useFocusTrap({
|
|
|
1088
1135
|
returnFocusRef
|
|
1089
1136
|
}) {
|
|
1090
1137
|
const previouslyFocused = useRef5(null);
|
|
1091
|
-
|
|
1138
|
+
useEffect10(() => {
|
|
1092
1139
|
if (!active) return;
|
|
1093
1140
|
const container = containerRef.current;
|
|
1094
1141
|
previouslyFocused.current = document.activeElement ?? null;
|
|
@@ -1130,10 +1177,17 @@ function useFocusTrap({
|
|
|
1130
1177
|
}
|
|
1131
1178
|
|
|
1132
1179
|
// src/components/MixMatchPicker.tsx
|
|
1133
|
-
import { jsx as
|
|
1134
|
-
function ruleFor(bundle, productId) {
|
|
1180
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1181
|
+
function ruleFor(bundle, productId, variantId) {
|
|
1182
|
+
if (variantId) {
|
|
1183
|
+
const vRule = bundle.variantRules[variantId];
|
|
1184
|
+
if (vRule) return vRule;
|
|
1185
|
+
}
|
|
1135
1186
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE;
|
|
1136
1187
|
}
|
|
1188
|
+
function variantRuleFor(bundle, variantId) {
|
|
1189
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
1190
|
+
}
|
|
1137
1191
|
function sanitizeId(gid) {
|
|
1138
1192
|
return gid.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
1139
1193
|
}
|
|
@@ -1182,9 +1236,9 @@ function MixMatchPicker({
|
|
|
1182
1236
|
const overlayRef = useRef6(null);
|
|
1183
1237
|
const dialogRef = useRef6(null);
|
|
1184
1238
|
const mouseDownTarget = useRef6(null);
|
|
1185
|
-
const [open, setOpen] =
|
|
1186
|
-
const [query, setQuery] =
|
|
1187
|
-
const [activeType, setActiveType] =
|
|
1239
|
+
const [open, setOpen] = useState8(false);
|
|
1240
|
+
const [query, setQuery] = useState8("");
|
|
1241
|
+
const [activeType, setActiveType] = useState8(FILTERS_ALL);
|
|
1188
1242
|
const eligible = useMemo5(
|
|
1189
1243
|
() => buildEligibleProducts(bundle, outOfStockBehavior),
|
|
1190
1244
|
[bundle, outOfStockBehavior]
|
|
@@ -1205,7 +1259,7 @@ function MixMatchPicker({
|
|
|
1205
1259
|
const totalUnits = selections.reduce((sum, s) => sum + s.quantity, 0);
|
|
1206
1260
|
const atCapacity = totalUnits >= requiredQty;
|
|
1207
1261
|
const shownUnits = Math.min(totalUnits, requiredQty);
|
|
1208
|
-
|
|
1262
|
+
useEffect11(() => {
|
|
1209
1263
|
const id = requestAnimationFrame(() => setOpen(true));
|
|
1210
1264
|
return () => cancelAnimationFrame(id);
|
|
1211
1265
|
}, []);
|
|
@@ -1246,7 +1300,7 @@ function MixMatchPicker({
|
|
|
1246
1300
|
// inside carries the interactive role + focus trap. So the static-element
|
|
1247
1301
|
// interaction lint does not apply to this backdrop.
|
|
1248
1302
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
1249
|
-
/* @__PURE__ */
|
|
1303
|
+
/* @__PURE__ */ jsx4(
|
|
1250
1304
|
"div",
|
|
1251
1305
|
{
|
|
1252
1306
|
ref: (el) => {
|
|
@@ -1258,7 +1312,7 @@ function MixMatchPicker({
|
|
|
1258
1312
|
"data-bundle-gid": bundle.id,
|
|
1259
1313
|
onMouseDown: onOverlayMouseDown,
|
|
1260
1314
|
onMouseUp: onOverlayMouseUp,
|
|
1261
|
-
children: /* @__PURE__ */
|
|
1315
|
+
children: /* @__PURE__ */ jsxs4(
|
|
1262
1316
|
"div",
|
|
1263
1317
|
{
|
|
1264
1318
|
ref: dialogRef,
|
|
@@ -1268,13 +1322,13 @@ function MixMatchPicker({
|
|
|
1268
1322
|
"aria-labelledby": titleId,
|
|
1269
1323
|
tabIndex: -1,
|
|
1270
1324
|
children: [
|
|
1271
|
-
/* @__PURE__ */
|
|
1272
|
-
/* @__PURE__ */
|
|
1273
|
-
/* @__PURE__ */
|
|
1274
|
-
/* @__PURE__ */
|
|
1275
|
-
/* @__PURE__ */
|
|
1325
|
+
/* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-header", children: [
|
|
1326
|
+
/* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-header-top", children: [
|
|
1327
|
+
/* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-heading", children: [
|
|
1328
|
+
/* @__PURE__ */ jsx4("h4", { className: "lb-mix-match__modal-title", id: titleId, children: "Add to your bundle" }),
|
|
1329
|
+
/* @__PURE__ */ jsx4("p", { className: "lb-mix-match__modal-subtitle", "data-modal-subtitle": true, children: subtitle })
|
|
1276
1330
|
] }),
|
|
1277
|
-
/* @__PURE__ */
|
|
1331
|
+
/* @__PURE__ */ jsx4(
|
|
1278
1332
|
"button",
|
|
1279
1333
|
{
|
|
1280
1334
|
type: "button",
|
|
@@ -1282,16 +1336,16 @@ function MixMatchPicker({
|
|
|
1282
1336
|
"data-modal-close": true,
|
|
1283
1337
|
"aria-label": "Close",
|
|
1284
1338
|
onClick: onClose,
|
|
1285
|
-
children: /* @__PURE__ */
|
|
1339
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, {})
|
|
1286
1340
|
}
|
|
1287
1341
|
)
|
|
1288
1342
|
] }),
|
|
1289
|
-
/* @__PURE__ */
|
|
1343
|
+
/* @__PURE__ */ jsx4(
|
|
1290
1344
|
"div",
|
|
1291
1345
|
{
|
|
1292
1346
|
className: "lb-mix-match__progress lb-mix-match__modal-progress",
|
|
1293
1347
|
"data-progress": true,
|
|
1294
|
-
children: /* @__PURE__ */
|
|
1348
|
+
children: /* @__PURE__ */ jsx4(
|
|
1295
1349
|
"div",
|
|
1296
1350
|
{
|
|
1297
1351
|
className: "lb-mix-match__progress-segments",
|
|
@@ -1299,7 +1353,7 @@ function MixMatchPicker({
|
|
|
1299
1353
|
"aria-valuenow": shownUnits,
|
|
1300
1354
|
"aria-valuemin": 0,
|
|
1301
1355
|
"aria-valuemax": requiredQty,
|
|
1302
|
-
children: Array.from({ length: requiredQty }).map((_, i) => /* @__PURE__ */
|
|
1356
|
+
children: Array.from({ length: requiredQty }).map((_, i) => /* @__PURE__ */ jsx4(
|
|
1303
1357
|
"span",
|
|
1304
1358
|
{
|
|
1305
1359
|
className: `lb-mix-match__progress-segment${i < shownUnits ? " lb-mix-match__progress-segment--filled" : ""}`,
|
|
@@ -1312,8 +1366,8 @@ function MixMatchPicker({
|
|
|
1312
1366
|
}
|
|
1313
1367
|
)
|
|
1314
1368
|
] }),
|
|
1315
|
-
wc.showSearch && /* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1369
|
+
wc.showSearch && /* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-search", children: [
|
|
1370
|
+
/* @__PURE__ */ jsx4(
|
|
1317
1371
|
"input",
|
|
1318
1372
|
{
|
|
1319
1373
|
type: "text",
|
|
@@ -1327,7 +1381,7 @@ function MixMatchPicker({
|
|
|
1327
1381
|
onChange: (e) => setQuery(e.target.value)
|
|
1328
1382
|
}
|
|
1329
1383
|
),
|
|
1330
|
-
query.length > 0 && /* @__PURE__ */
|
|
1384
|
+
query.length > 0 && /* @__PURE__ */ jsx4(
|
|
1331
1385
|
"button",
|
|
1332
1386
|
{
|
|
1333
1387
|
type: "button",
|
|
@@ -1335,11 +1389,11 @@ function MixMatchPicker({
|
|
|
1335
1389
|
"data-modal-search-clear": true,
|
|
1336
1390
|
"aria-label": "Clear search",
|
|
1337
1391
|
onClick: () => setQuery(""),
|
|
1338
|
-
children: /* @__PURE__ */
|
|
1392
|
+
children: /* @__PURE__ */ jsx4(SearchClearIcon, {})
|
|
1339
1393
|
}
|
|
1340
1394
|
)
|
|
1341
1395
|
] }),
|
|
1342
|
-
showFilters && /* @__PURE__ */
|
|
1396
|
+
showFilters && /* @__PURE__ */ jsx4(
|
|
1343
1397
|
"div",
|
|
1344
1398
|
{
|
|
1345
1399
|
className: "lb-mix-match__filters",
|
|
@@ -1348,7 +1402,7 @@ function MixMatchPicker({
|
|
|
1348
1402
|
"aria-label": "Filter by product type",
|
|
1349
1403
|
children: [FILTERS_ALL, ...productTypes].map((value) => {
|
|
1350
1404
|
const isActive = value === activeType;
|
|
1351
|
-
return /* @__PURE__ */
|
|
1405
|
+
return /* @__PURE__ */ jsx4(
|
|
1352
1406
|
"button",
|
|
1353
1407
|
{
|
|
1354
1408
|
type: "button",
|
|
@@ -1363,7 +1417,7 @@ function MixMatchPicker({
|
|
|
1363
1417
|
})
|
|
1364
1418
|
}
|
|
1365
1419
|
),
|
|
1366
|
-
/* @__PURE__ */
|
|
1420
|
+
/* @__PURE__ */ jsx4("div", { className: "lb-mix-match__modal-list", "data-modal-list": true, children: filtered.map((ep) => /* @__PURE__ */ jsx4(
|
|
1367
1421
|
MixMatchPickerRow,
|
|
1368
1422
|
{
|
|
1369
1423
|
bundle,
|
|
@@ -1382,10 +1436,10 @@ function MixMatchPicker({
|
|
|
1382
1436
|
},
|
|
1383
1437
|
ep.product.id
|
|
1384
1438
|
)) }),
|
|
1385
|
-
showEmpty && /* @__PURE__ */
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1388
|
-
/* @__PURE__ */
|
|
1439
|
+
showEmpty && /* @__PURE__ */ jsx4("div", { className: "lb-mix-match__modal-empty", "data-modal-empty": true, children: /* @__PURE__ */ jsx4("p", { children: "No products match your search" }) }),
|
|
1440
|
+
/* @__PURE__ */ jsx4("span", { "data-modal-live": true, "aria-live": "polite", className: "lb-visually-hidden", children: `${filtered.length} products shown` }),
|
|
1441
|
+
/* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-footer", children: [
|
|
1442
|
+
/* @__PURE__ */ jsx4(
|
|
1389
1443
|
"span",
|
|
1390
1444
|
{
|
|
1391
1445
|
className: "lb-mix-match__modal-footer-count",
|
|
@@ -1394,7 +1448,7 @@ function MixMatchPicker({
|
|
|
1394
1448
|
children: `${shownUnits} of ${requiredQty} added`
|
|
1395
1449
|
}
|
|
1396
1450
|
),
|
|
1397
|
-
/* @__PURE__ */
|
|
1451
|
+
/* @__PURE__ */ jsx4(
|
|
1398
1452
|
"button",
|
|
1399
1453
|
{
|
|
1400
1454
|
type: "button",
|
|
@@ -1438,6 +1492,8 @@ function MixMatchPickerRow({
|
|
|
1438
1492
|
const showPicker = variants.length > 1 && optionNames.length > 0;
|
|
1439
1493
|
const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
|
|
1440
1494
|
const currentVariant = selectedVariant ?? variants.find((v) => isVariantFulfillable2(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
|
|
1495
|
+
const vRule = ruleFor(bundle, product.id, currentVariant?.id);
|
|
1496
|
+
const variantMax = variantRuleFor(bundle, currentVariant?.id)?.max;
|
|
1441
1497
|
const alreadyInBundle = useMemo5(() => {
|
|
1442
1498
|
if (!currentVariant) return 0;
|
|
1443
1499
|
let sum = 0;
|
|
@@ -1465,22 +1521,26 @@ function MixMatchPickerRow({
|
|
|
1465
1521
|
return sum;
|
|
1466
1522
|
}, [selections, product.id, currentVariant]);
|
|
1467
1523
|
const swapUnits = currentVariant ? swapUnitsFor?.(product.id, currentVariant.id) ?? 0 : 0;
|
|
1468
|
-
const inSwapState = swapUnits >=
|
|
1469
|
-
const spotCeiling = inSwapState ? swapUnits : Math.min(
|
|
1524
|
+
const inSwapState = swapUnits >= vRule.min;
|
|
1525
|
+
const spotCeiling = inSwapState ? swapUnits : Math.min(
|
|
1526
|
+
rule.max - productOtherUnits,
|
|
1527
|
+
committedQty + remainingUnits,
|
|
1528
|
+
variantMax ?? Infinity
|
|
1529
|
+
);
|
|
1470
1530
|
const cap = currentVariant ? maxAddableQuantity(
|
|
1471
1531
|
currentVariant,
|
|
1472
1532
|
spotCeiling,
|
|
1473
1533
|
Math.max(0, alreadyInBundle - committedQty)
|
|
1474
1534
|
) : 0;
|
|
1475
|
-
const stepperMax = Math.max(
|
|
1476
|
-
const [qty, setQty] =
|
|
1477
|
-
|
|
1478
|
-
setQty((prev) => Math.max(
|
|
1479
|
-
}, [stepperMax,
|
|
1535
|
+
const stepperMax = Math.max(vRule.min, cap);
|
|
1536
|
+
const [qty, setQty] = useState8(vRule.min);
|
|
1537
|
+
useEffect11(() => {
|
|
1538
|
+
setQty((prev) => Math.max(vRule.min, Math.min(prev, stepperMax)));
|
|
1539
|
+
}, [stepperMax, vRule.min]);
|
|
1480
1540
|
const currentVariantId = currentVariant?.id ?? null;
|
|
1481
|
-
|
|
1482
|
-
if (!variantInBundle) setQty(
|
|
1483
|
-
}, [variantInBundle, currentVariantId,
|
|
1541
|
+
useEffect11(() => {
|
|
1542
|
+
if (!variantInBundle) setQty(vRule.min);
|
|
1543
|
+
}, [variantInBundle, currentVariantId, vRule.min]);
|
|
1484
1544
|
if (!currentVariant) return null;
|
|
1485
1545
|
const thumbImage = currentVariant.image ?? product.featuredImage ?? null;
|
|
1486
1546
|
const unitPriceText = formatUnitPrice2(
|
|
@@ -1488,8 +1548,8 @@ function MixMatchPickerRow({
|
|
|
1488
1548
|
currentVariant.unitPriceMeasurement,
|
|
1489
1549
|
currency
|
|
1490
1550
|
);
|
|
1491
|
-
const noStock = cap <
|
|
1492
|
-
const needsMoreSpots = !variantInBundle && !inSwapState &&
|
|
1551
|
+
const noStock = cap < vRule.min;
|
|
1552
|
+
const needsMoreSpots = !variantInBundle && !inSwapState && vRule.min > remainingUnits;
|
|
1493
1553
|
const addDisabled = !variantInBundle && (inSwapState ? noStock : atCapacity || noStock || needsMoreSpots);
|
|
1494
1554
|
const lockedRequired = variantInBundle && currentVariant != null && !(canRemoveVariant?.(currentVariant.id) ?? true);
|
|
1495
1555
|
const stepperDisabled = isOos || !variantInBundle && addDisabled;
|
|
@@ -1500,7 +1560,7 @@ function MixMatchPickerRow({
|
|
|
1500
1560
|
return;
|
|
1501
1561
|
}
|
|
1502
1562
|
if (!currentVariant || noStock) return;
|
|
1503
|
-
const pickedQty = showStepper ? qty :
|
|
1563
|
+
const pickedQty = showStepper ? qty : vRule.min;
|
|
1504
1564
|
const item = {
|
|
1505
1565
|
productId: product.id,
|
|
1506
1566
|
variantId: currentVariant.id,
|
|
@@ -1522,7 +1582,7 @@ function MixMatchPickerRow({
|
|
|
1522
1582
|
}
|
|
1523
1583
|
const priceCents = parseFloat(currentVariant.price.amount);
|
|
1524
1584
|
const compareCents = currentVariant.compareAtPrice ? parseFloat(currentVariant.compareAtPrice.amount) : null;
|
|
1525
|
-
return /* @__PURE__ */
|
|
1585
|
+
return /* @__PURE__ */ jsxs4(
|
|
1526
1586
|
"div",
|
|
1527
1587
|
{
|
|
1528
1588
|
className: `lb-mix-match__modal-product${isOos ? " lb-mix-match__modal-product--sold-out" : ""}${variantInBundle ? " lb-mix-match__modal-product--in-bundle" : ""}`,
|
|
@@ -1531,8 +1591,8 @@ function MixMatchPickerRow({
|
|
|
1531
1591
|
"data-type": product.productType ?? "",
|
|
1532
1592
|
"aria-disabled": isOos || void 0,
|
|
1533
1593
|
children: [
|
|
1534
|
-
/* @__PURE__ */
|
|
1535
|
-
thumbImage && /* @__PURE__ */
|
|
1594
|
+
/* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-product-thumb", children: [
|
|
1595
|
+
thumbImage && /* @__PURE__ */ jsx4(
|
|
1536
1596
|
"img",
|
|
1537
1597
|
{
|
|
1538
1598
|
src: thumbImage.url,
|
|
@@ -1540,10 +1600,10 @@ function MixMatchPickerRow({
|
|
|
1540
1600
|
loading: "lazy"
|
|
1541
1601
|
}
|
|
1542
1602
|
),
|
|
1543
|
-
variantInBundle && /* @__PURE__ */
|
|
1603
|
+
variantInBundle && /* @__PURE__ */ jsx4("span", { className: "lb-mix-match__modal-added-badge", children: "Added" })
|
|
1544
1604
|
] }),
|
|
1545
|
-
/* @__PURE__ */
|
|
1546
|
-
/* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-product-info", children: [
|
|
1606
|
+
/* @__PURE__ */ jsx4("p", { className: "lb-mix-match__modal-product-title", children: /* @__PURE__ */ jsx4(
|
|
1547
1607
|
"a",
|
|
1548
1608
|
{
|
|
1549
1609
|
href: `/products/${product.handle}`,
|
|
@@ -1552,24 +1612,24 @@ function MixMatchPickerRow({
|
|
|
1552
1612
|
children: product.title
|
|
1553
1613
|
}
|
|
1554
1614
|
) }),
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1557
|
-
compareCents !== null && compareCents > priceCents && /* @__PURE__ */
|
|
1615
|
+
/* @__PURE__ */ jsxs4("p", { className: "lb-mix-match__modal-product-price", children: [
|
|
1616
|
+
/* @__PURE__ */ jsx4("span", { "data-row-price-sale": true, children: formatMoney2(priceCents, currency) }),
|
|
1617
|
+
compareCents !== null && compareCents > priceCents && /* @__PURE__ */ jsx4("s", { className: "lb-mix-match__modal-product-compare", "data-row-compare": true, children: formatMoney2(compareCents, currency) })
|
|
1558
1618
|
] }),
|
|
1559
|
-
unitPriceText && /* @__PURE__ */
|
|
1560
|
-
showPicker && /* @__PURE__ */
|
|
1619
|
+
unitPriceText && /* @__PURE__ */ jsx4("p", { className: "lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price", children: unitPriceText }),
|
|
1620
|
+
showPicker && /* @__PURE__ */ jsx4("div", { className: "lb-bundle-variant-option-groups", children: optionNames.map((optionName, optionIndex) => {
|
|
1561
1621
|
const dropdownOptions = optionsFor(optionIndex).map((o) => ({
|
|
1562
1622
|
value: o.value,
|
|
1563
1623
|
label: o.value,
|
|
1564
1624
|
disabled: o.disabled
|
|
1565
1625
|
}));
|
|
1566
|
-
return /* @__PURE__ */
|
|
1626
|
+
return /* @__PURE__ */ jsxs4(
|
|
1567
1627
|
"div",
|
|
1568
1628
|
{
|
|
1569
1629
|
className: "lb-bundle-variant-option-group",
|
|
1570
1630
|
children: [
|
|
1571
|
-
/* @__PURE__ */
|
|
1572
|
-
/* @__PURE__ */
|
|
1631
|
+
/* @__PURE__ */ jsx4("span", { className: "lb-bundle-variant-option-label", children: optionName }),
|
|
1632
|
+
/* @__PURE__ */ jsx4(
|
|
1573
1633
|
VariantDropdown,
|
|
1574
1634
|
{
|
|
1575
1635
|
className: "lb-mix-match__variant-select-dropdown",
|
|
@@ -1584,17 +1644,17 @@ function MixMatchPickerRow({
|
|
|
1584
1644
|
optionName
|
|
1585
1645
|
);
|
|
1586
1646
|
}) }),
|
|
1587
|
-
!showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */
|
|
1588
|
-
!isOos && needsMoreSpots && remainingUnits > 0 && /* @__PURE__ */
|
|
1589
|
-
isOos ? /* @__PURE__ */
|
|
1590
|
-
showStepper && /* @__PURE__ */
|
|
1647
|
+
!showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ jsx4("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
|
|
1648
|
+
!isOos && needsMoreSpots && remainingUnits > 0 && /* @__PURE__ */ jsx4("span", { className: "lb-mix-match__modal-needs-spots", children: rule.min === 1 ? "Needs 1 spot" : `Needs ${rule.min} spots` }),
|
|
1649
|
+
isOos ? /* @__PURE__ */ jsx4("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ jsxs4("div", { className: "lb-mix-match__modal-product-actions", children: [
|
|
1650
|
+
showStepper && /* @__PURE__ */ jsx4("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ jsxs4(
|
|
1591
1651
|
"div",
|
|
1592
1652
|
{
|
|
1593
1653
|
className: "lb-mix-match__qty-stepper",
|
|
1594
1654
|
role: "group",
|
|
1595
1655
|
"aria-label": "Quantity",
|
|
1596
1656
|
children: [
|
|
1597
|
-
/* @__PURE__ */
|
|
1657
|
+
/* @__PURE__ */ jsx4(
|
|
1598
1658
|
"button",
|
|
1599
1659
|
{
|
|
1600
1660
|
type: "button",
|
|
@@ -1615,7 +1675,7 @@ function MixMatchPickerRow({
|
|
|
1615
1675
|
children: "\u2212"
|
|
1616
1676
|
}
|
|
1617
1677
|
),
|
|
1618
|
-
/* @__PURE__ */
|
|
1678
|
+
/* @__PURE__ */ jsx4(
|
|
1619
1679
|
"span",
|
|
1620
1680
|
{
|
|
1621
1681
|
className: "lb-mix-match__qty-stepper-value",
|
|
@@ -1624,7 +1684,7 @@ function MixMatchPickerRow({
|
|
|
1624
1684
|
children: shownQty
|
|
1625
1685
|
}
|
|
1626
1686
|
),
|
|
1627
|
-
/* @__PURE__ */
|
|
1687
|
+
/* @__PURE__ */ jsx4(
|
|
1628
1688
|
"button",
|
|
1629
1689
|
{
|
|
1630
1690
|
type: "button",
|
|
@@ -1648,7 +1708,7 @@ function MixMatchPickerRow({
|
|
|
1648
1708
|
]
|
|
1649
1709
|
}
|
|
1650
1710
|
) }),
|
|
1651
|
-
/* @__PURE__ */
|
|
1711
|
+
/* @__PURE__ */ jsx4(
|
|
1652
1712
|
"button",
|
|
1653
1713
|
{
|
|
1654
1714
|
type: "button",
|
|
@@ -1667,7 +1727,7 @@ function MixMatchPickerRow({
|
|
|
1667
1727
|
);
|
|
1668
1728
|
}
|
|
1669
1729
|
function CloseIcon() {
|
|
1670
|
-
return /* @__PURE__ */
|
|
1730
|
+
return /* @__PURE__ */ jsxs4(
|
|
1671
1731
|
"svg",
|
|
1672
1732
|
{
|
|
1673
1733
|
width: "20",
|
|
@@ -1677,14 +1737,14 @@ function CloseIcon() {
|
|
|
1677
1737
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1678
1738
|
"aria-hidden": "true",
|
|
1679
1739
|
children: [
|
|
1680
|
-
/* @__PURE__ */
|
|
1681
|
-
/* @__PURE__ */
|
|
1740
|
+
/* @__PURE__ */ jsx4("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
1741
|
+
/* @__PURE__ */ jsx4("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
1682
1742
|
]
|
|
1683
1743
|
}
|
|
1684
1744
|
);
|
|
1685
1745
|
}
|
|
1686
1746
|
function SearchClearIcon() {
|
|
1687
|
-
return /* @__PURE__ */
|
|
1747
|
+
return /* @__PURE__ */ jsx4(
|
|
1688
1748
|
"svg",
|
|
1689
1749
|
{
|
|
1690
1750
|
width: "16",
|
|
@@ -1693,17 +1753,25 @@ function SearchClearIcon() {
|
|
|
1693
1753
|
fill: "currentColor",
|
|
1694
1754
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1695
1755
|
"aria-hidden": "true",
|
|
1696
|
-
children: /* @__PURE__ */
|
|
1756
|
+
children: /* @__PURE__ */ jsx4("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" })
|
|
1697
1757
|
}
|
|
1698
1758
|
);
|
|
1699
1759
|
}
|
|
1700
1760
|
|
|
1701
1761
|
// src/components/MixMatchBundle.tsx
|
|
1702
|
-
import { jsx as
|
|
1703
|
-
function ruleFor2(bundle, productId) {
|
|
1762
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1763
|
+
function ruleFor2(bundle, productId, variantId) {
|
|
1764
|
+
if (variantId) {
|
|
1765
|
+
const vRule = bundle.variantRules[variantId];
|
|
1766
|
+
if (vRule) return vRule;
|
|
1767
|
+
}
|
|
1704
1768
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE2;
|
|
1705
1769
|
}
|
|
1770
|
+
function variantRuleFor2(bundle, variantId) {
|
|
1771
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
1772
|
+
}
|
|
1706
1773
|
function canRemoveItem(bundle, selections, item) {
|
|
1774
|
+
if (variantRuleFor2(bundle, item.variantId)?.required) return false;
|
|
1707
1775
|
const rule = ruleFor2(bundle, item.productId);
|
|
1708
1776
|
if (!rule.required) return true;
|
|
1709
1777
|
const unitsElsewhere = selections.filter((s) => s.productId === item.productId && s !== item).reduce((sum, s) => sum + s.quantity, 0);
|
|
@@ -1724,7 +1792,8 @@ function MixMatchBundle(props) {
|
|
|
1724
1792
|
analyticsEnabled,
|
|
1725
1793
|
onAddToCart,
|
|
1726
1794
|
onError,
|
|
1727
|
-
className
|
|
1795
|
+
className,
|
|
1796
|
+
productHandle
|
|
1728
1797
|
} = props;
|
|
1729
1798
|
const result = useBundleData({
|
|
1730
1799
|
shopDomain,
|
|
@@ -1742,16 +1811,16 @@ function MixMatchBundle(props) {
|
|
|
1742
1811
|
bundleType: "mix_match",
|
|
1743
1812
|
enabled: analyticsEnabled !== false
|
|
1744
1813
|
});
|
|
1745
|
-
const [selections, setSelections] =
|
|
1746
|
-
const [seededFor, setSeededFor] =
|
|
1747
|
-
const [pickerOpen, setPickerOpen] =
|
|
1748
|
-
const [addingToCart, setAddingToCart] =
|
|
1749
|
-
const [cartError, setCartError] =
|
|
1814
|
+
const [selections, setSelections] = useState9([]);
|
|
1815
|
+
const [seededFor, setSeededFor] = useState9(null);
|
|
1816
|
+
const [pickerOpen, setPickerOpen] = useState9(false);
|
|
1817
|
+
const [addingToCart, setAddingToCart] = useState9(false);
|
|
1818
|
+
const [cartError, setCartError] = useState9(null);
|
|
1750
1819
|
const bundle = result.status === "success" && result.bundle.bundleType === "mix_match" ? result.bundle : null;
|
|
1751
1820
|
const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
1752
1821
|
const setModalConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
1753
1822
|
const slotsEdgeFadeRef = useEdgeFade();
|
|
1754
|
-
|
|
1823
|
+
useEffect12(() => {
|
|
1755
1824
|
if (result.status === "error") {
|
|
1756
1825
|
onError?.(result.error);
|
|
1757
1826
|
return;
|
|
@@ -1764,37 +1833,64 @@ function MixMatchBundle(props) {
|
|
|
1764
1833
|
);
|
|
1765
1834
|
}
|
|
1766
1835
|
}, [result, onError]);
|
|
1767
|
-
|
|
1836
|
+
useEffect12(() => {
|
|
1768
1837
|
if (!bundle || seededFor === bundle.id) return;
|
|
1769
1838
|
setSeededFor(bundle.id);
|
|
1770
1839
|
const seedCurrency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
|
|
1840
|
+
const pick = (product, variant, quantity) => ({
|
|
1841
|
+
productId: product.id,
|
|
1842
|
+
variantId: variant.id,
|
|
1843
|
+
title: product.title,
|
|
1844
|
+
url: `/products/${product.handle}`,
|
|
1845
|
+
variantTitle: variant.title,
|
|
1846
|
+
featuredImage: variant.image?.url ?? product.featuredImage?.url ?? null,
|
|
1847
|
+
price: parseFloat(variant.price.amount),
|
|
1848
|
+
compareAtPrice: variant.compareAtPrice ? parseFloat(variant.compareAtPrice.amount) : null,
|
|
1849
|
+
unitPrice: formatUnitPrice3(
|
|
1850
|
+
variant.unitPrice,
|
|
1851
|
+
variant.unitPriceMeasurement,
|
|
1852
|
+
seedCurrency
|
|
1853
|
+
),
|
|
1854
|
+
quantity
|
|
1855
|
+
});
|
|
1771
1856
|
const seeds = [];
|
|
1772
|
-
for (const
|
|
1773
|
-
|
|
1774
|
-
const
|
|
1775
|
-
|
|
1857
|
+
for (const product of bundle.products) {
|
|
1858
|
+
let seededVariant = false;
|
|
1859
|
+
for (const variant2 of product.variants.nodes) {
|
|
1860
|
+
const vRule = bundle.variantRules[variant2.id];
|
|
1861
|
+
if (!vRule?.required) continue;
|
|
1862
|
+
if (!isVariantFulfillable3(variant2, Math.max(1, vRule.min))) continue;
|
|
1863
|
+
seeds.push(pick(product, variant2, Math.max(1, vRule.min)));
|
|
1864
|
+
seededVariant = true;
|
|
1865
|
+
}
|
|
1866
|
+
if (seededVariant) continue;
|
|
1867
|
+
const rule = bundle.productRules[product.id];
|
|
1868
|
+
if (!rule?.required) continue;
|
|
1869
|
+
const variant = product.variants.nodes.find(
|
|
1776
1870
|
(v) => isVariantFulfillable3(v, rule.min)
|
|
1777
1871
|
);
|
|
1778
|
-
if (!
|
|
1779
|
-
seeds.push(
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1872
|
+
if (!variant) continue;
|
|
1873
|
+
seeds.push(pick(product, variant, rule.min));
|
|
1874
|
+
}
|
|
1875
|
+
if (seeds.length === 0 && productHandle) {
|
|
1876
|
+
const requiredUnits2 = bundle.minQuantity ?? 0;
|
|
1877
|
+
const qualifies = (p) => {
|
|
1878
|
+
const min = bundle.productRules[p.id]?.min ?? 1;
|
|
1879
|
+
return min <= requiredUnits2 && p.variants.nodes.some((v) => isVariantFulfillable3(v, min));
|
|
1880
|
+
};
|
|
1881
|
+
const seed = bundle.products.find(
|
|
1882
|
+
(p) => p.handle === productHandle && qualifies(p)
|
|
1883
|
+
) ?? bundle.products.find(qualifies);
|
|
1884
|
+
if (seed) {
|
|
1885
|
+
const min = bundle.productRules[seed.id]?.min ?? 1;
|
|
1886
|
+
const variant = seed.variants.nodes.find(
|
|
1887
|
+
(v) => isVariantFulfillable3(v, min)
|
|
1888
|
+
);
|
|
1889
|
+
if (variant) seeds.push(pick(seed, variant, min));
|
|
1890
|
+
}
|
|
1795
1891
|
}
|
|
1796
1892
|
if (seeds.length > 0) setSelections(seeds);
|
|
1797
|
-
}, [bundle, seededFor]);
|
|
1893
|
+
}, [bundle, seededFor, productHandle]);
|
|
1798
1894
|
const showStepper = bundle?.widgetConfig.mixMatchShowQuantitySelector !== false;
|
|
1799
1895
|
const requiredUnits = bundle?.minQuantity ?? 0;
|
|
1800
1896
|
const totalQuantity = useMemo6(
|
|
@@ -1954,9 +2050,9 @@ function MixMatchBundle(props) {
|
|
|
1954
2050
|
}
|
|
1955
2051
|
}, [bundle, selections, valid, onAddToCart, onError, trackAddToCart, totalQuantity]);
|
|
1956
2052
|
if (result.status === "loading") {
|
|
1957
|
-
return /* @__PURE__ */
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
/* @__PURE__ */
|
|
2053
|
+
return /* @__PURE__ */ jsxs5("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
|
|
2054
|
+
/* @__PURE__ */ jsx5("div", { className: "lb-skeleton lb-skeleton--title" }),
|
|
2055
|
+
/* @__PURE__ */ jsx5("div", { className: "lb-skeleton lb-skeleton--products" })
|
|
1960
2056
|
] });
|
|
1961
2057
|
}
|
|
1962
2058
|
if (result.status === "error") return null;
|
|
@@ -1975,7 +2071,7 @@ function MixMatchBundle(props) {
|
|
|
1975
2071
|
if (requiredBlocked) return null;
|
|
1976
2072
|
const currency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
|
|
1977
2073
|
const ctaLabel = addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText || "Add to cart";
|
|
1978
|
-
return /* @__PURE__ */
|
|
2074
|
+
return /* @__PURE__ */ jsxs5(
|
|
1979
2075
|
"div",
|
|
1980
2076
|
{
|
|
1981
2077
|
ref: (el) => {
|
|
@@ -1987,12 +2083,19 @@ function MixMatchBundle(props) {
|
|
|
1987
2083
|
"aria-label": bundle.title,
|
|
1988
2084
|
"data-required-quantity": requiredUnits,
|
|
1989
2085
|
children: [
|
|
1990
|
-
/* @__PURE__ */
|
|
1991
|
-
/* @__PURE__ */
|
|
1992
|
-
bundle.description && /* @__PURE__ */
|
|
2086
|
+
/* @__PURE__ */ jsx5("div", { className: "lb-bundle-header", children: /* @__PURE__ */ jsxs5("div", { className: "lb-bundle-header__content", children: [
|
|
2087
|
+
/* @__PURE__ */ jsx5("h3", { className: "lb-bundle-title", children: bundle.title }),
|
|
2088
|
+
bundle.description && /* @__PURE__ */ jsx5("p", { className: "lb-bundle-subtitle", children: bundle.description })
|
|
1993
2089
|
] }) }),
|
|
1994
|
-
/* @__PURE__ */
|
|
1995
|
-
|
|
2090
|
+
/* @__PURE__ */ jsx5(
|
|
2091
|
+
BundleCountdown,
|
|
2092
|
+
{
|
|
2093
|
+
endsAt: bundle.endsAt,
|
|
2094
|
+
widgetConfig: bundle.widgetConfig
|
|
2095
|
+
}
|
|
2096
|
+
),
|
|
2097
|
+
/* @__PURE__ */ jsxs5("div", { className: "lb-mix-match__progress", "data-progress": true, children: [
|
|
2098
|
+
/* @__PURE__ */ jsx5(
|
|
1996
2099
|
"div",
|
|
1997
2100
|
{
|
|
1998
2101
|
className: "lb-mix-match__progress-segments",
|
|
@@ -2000,7 +2103,7 @@ function MixMatchBundle(props) {
|
|
|
2000
2103
|
"aria-valuenow": shownUnits,
|
|
2001
2104
|
"aria-valuemin": 0,
|
|
2002
2105
|
"aria-valuemax": requiredUnits,
|
|
2003
|
-
children: Array.from({ length: requiredUnits }).map((_, i) => /* @__PURE__ */
|
|
2106
|
+
children: Array.from({ length: requiredUnits }).map((_, i) => /* @__PURE__ */ jsx5(
|
|
2004
2107
|
"span",
|
|
2005
2108
|
{
|
|
2006
2109
|
className: `lb-mix-match__progress-segment${i < shownUnits ? " lb-mix-match__progress-segment--filled" : ""}`,
|
|
@@ -2010,8 +2113,8 @@ function MixMatchBundle(props) {
|
|
|
2010
2113
|
))
|
|
2011
2114
|
}
|
|
2012
2115
|
),
|
|
2013
|
-
/* @__PURE__ */
|
|
2014
|
-
/* @__PURE__ */
|
|
2116
|
+
/* @__PURE__ */ jsxs5("div", { className: "lb-mix-match__progress-labels", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx5(
|
|
2015
2118
|
"span",
|
|
2016
2119
|
{
|
|
2017
2120
|
className: "lb-mix-match__progress-count",
|
|
@@ -2020,7 +2123,7 @@ function MixMatchBundle(props) {
|
|
|
2020
2123
|
children: `${shownUnits} of ${requiredUnits} added`
|
|
2021
2124
|
}
|
|
2022
2125
|
),
|
|
2023
|
-
/* @__PURE__ */
|
|
2126
|
+
/* @__PURE__ */ jsx5(
|
|
2024
2127
|
"span",
|
|
2025
2128
|
{
|
|
2026
2129
|
className: "lb-mix-match__progress-remaining",
|
|
@@ -2031,7 +2134,7 @@ function MixMatchBundle(props) {
|
|
|
2031
2134
|
)
|
|
2032
2135
|
] })
|
|
2033
2136
|
] }),
|
|
2034
|
-
/* @__PURE__ */
|
|
2137
|
+
/* @__PURE__ */ jsx5(
|
|
2035
2138
|
"div",
|
|
2036
2139
|
{
|
|
2037
2140
|
className: "lb-mix-match__slots lb-edge-fade",
|
|
@@ -2042,15 +2145,15 @@ function MixMatchBundle(props) {
|
|
|
2042
2145
|
button provides the keyboard/AT path (its activation bubbles
|
|
2043
2146
|
here); × stops propagation. */
|
|
2044
2147
|
// 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
|
|
2045
|
-
/* @__PURE__ */
|
|
2148
|
+
/* @__PURE__ */ jsxs5(
|
|
2046
2149
|
"div",
|
|
2047
2150
|
{
|
|
2048
2151
|
className: "lb-mix-match__slot lb-mix-match__slot--filled",
|
|
2049
2152
|
onClick: () => setPickerOpen(true),
|
|
2050
2153
|
children: [
|
|
2051
|
-
item.featuredImage && /* @__PURE__ */
|
|
2052
|
-
/* @__PURE__ */
|
|
2053
|
-
/* @__PURE__ */
|
|
2154
|
+
item.featuredImage && /* @__PURE__ */ jsx5("div", { className: "lb-bundle-thumbnail", children: /* @__PURE__ */ jsx5("img", { src: item.featuredImage, alt: item.title, loading: "lazy" }) }),
|
|
2155
|
+
/* @__PURE__ */ jsxs5("div", { className: "lb-mix-match__filled-info", children: [
|
|
2156
|
+
/* @__PURE__ */ jsx5(
|
|
2054
2157
|
"button",
|
|
2055
2158
|
{
|
|
2056
2159
|
type: "button",
|
|
@@ -2059,15 +2162,15 @@ function MixMatchBundle(props) {
|
|
|
2059
2162
|
children: item.title
|
|
2060
2163
|
}
|
|
2061
2164
|
),
|
|
2062
|
-
item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */
|
|
2063
|
-
/* @__PURE__ */
|
|
2064
|
-
item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */
|
|
2065
|
-
/* @__PURE__ */
|
|
2066
|
-
/* @__PURE__ */
|
|
2165
|
+
item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */ jsx5("span", { className: "lb-mix-match__filled-variant", children: item.variantTitle }),
|
|
2166
|
+
/* @__PURE__ */ jsxs5("span", { className: "lb-mix-match__filled-price", children: [
|
|
2167
|
+
item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */ jsx5("s", { className: "lb-mix-match__filled-compare", children: formatMoney3(item.compareAtPrice, currency) }),
|
|
2168
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-bundle-product-price", children: formatMoney3(item.price, currency) }),
|
|
2169
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-bundle-qty-inline", children: `\xD7${item.quantity}` })
|
|
2067
2170
|
] }),
|
|
2068
|
-
item.unitPrice && /* @__PURE__ */
|
|
2171
|
+
item.unitPrice && /* @__PURE__ */ jsx5("span", { className: "lb-bundle-product-unit-price", children: item.unitPrice })
|
|
2069
2172
|
] }),
|
|
2070
|
-
canRemoveItem(bundle, selections, item) ? /* @__PURE__ */
|
|
2173
|
+
canRemoveItem(bundle, selections, item) ? /* @__PURE__ */ jsx5(
|
|
2071
2174
|
"button",
|
|
2072
2175
|
{
|
|
2073
2176
|
type: "button",
|
|
@@ -2077,13 +2180,13 @@ function MixMatchBundle(props) {
|
|
|
2077
2180
|
e.stopPropagation();
|
|
2078
2181
|
removeSlot(index);
|
|
2079
2182
|
},
|
|
2080
|
-
children: /* @__PURE__ */
|
|
2183
|
+
children: /* @__PURE__ */ jsx5(CloseIcon2, {})
|
|
2081
2184
|
}
|
|
2082
2185
|
) : (
|
|
2083
2186
|
/* Required pick at its floor — quiet state chip instead of
|
|
2084
2187
|
the ×; removal returns once another slot covers the
|
|
2085
2188
|
product's minimum (variant swap flow). */
|
|
2086
|
-
/* @__PURE__ */
|
|
2189
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-mix-match__slot-required", children: "Required" })
|
|
2087
2190
|
)
|
|
2088
2191
|
]
|
|
2089
2192
|
},
|
|
@@ -2092,7 +2195,7 @@ function MixMatchBundle(props) {
|
|
|
2092
2195
|
))
|
|
2093
2196
|
}
|
|
2094
2197
|
),
|
|
2095
|
-
totalQuantity < requiredUnits && /* @__PURE__ */
|
|
2198
|
+
totalQuantity < requiredUnits && /* @__PURE__ */ jsxs5(
|
|
2096
2199
|
"button",
|
|
2097
2200
|
{
|
|
2098
2201
|
type: "button",
|
|
@@ -2100,34 +2203,34 @@ function MixMatchBundle(props) {
|
|
|
2100
2203
|
"data-add-product-trigger": true,
|
|
2101
2204
|
onClick: () => setPickerOpen(true),
|
|
2102
2205
|
children: [
|
|
2103
|
-
/* @__PURE__ */
|
|
2104
|
-
/* @__PURE__ */
|
|
2206
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-mix-match__add-product-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(PlusIcon, {}) }),
|
|
2207
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-mix-match__add-product-label", children: "Add a product" })
|
|
2105
2208
|
]
|
|
2106
2209
|
}
|
|
2107
2210
|
),
|
|
2108
|
-
/* @__PURE__ */
|
|
2109
|
-
selections.length > 0 && /* @__PURE__ */
|
|
2110
|
-
/* @__PURE__ */
|
|
2111
|
-
/* @__PURE__ */
|
|
2112
|
-
bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */
|
|
2211
|
+
/* @__PURE__ */ jsx5("div", { className: "lb-bundle-divider" }),
|
|
2212
|
+
selections.length > 0 && /* @__PURE__ */ jsxs5("div", { className: "lb-bundle-summary", "data-pricing-section": true, children: [
|
|
2213
|
+
/* @__PURE__ */ jsxs5("div", { className: "lb-bundle-summary__text", children: [
|
|
2214
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
|
|
2215
|
+
bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */ jsxs5("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
|
|
2113
2216
|
"You save",
|
|
2114
2217
|
" ",
|
|
2115
|
-
/* @__PURE__ */
|
|
2218
|
+
/* @__PURE__ */ jsx5("span", { "data-savings-amount": true, children: formatMoney3(summary.savings, currency) }),
|
|
2116
2219
|
" ",
|
|
2117
|
-
/* @__PURE__ */
|
|
2220
|
+
/* @__PURE__ */ jsxs5("span", { "data-savings-percent": true, children: [
|
|
2118
2221
|
"(",
|
|
2119
2222
|
summary.savingsPercent,
|
|
2120
2223
|
"%)"
|
|
2121
2224
|
] })
|
|
2122
2225
|
] })
|
|
2123
2226
|
] }),
|
|
2124
|
-
/* @__PURE__ */
|
|
2125
|
-
bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
2227
|
+
/* @__PURE__ */ jsxs5("span", { className: "lb-bundle-summary__prices", children: [
|
|
2228
|
+
bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */ jsx5("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: formatMoney3(summary.comparePrice, currency) }),
|
|
2229
|
+
/* @__PURE__ */ jsx5("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: formatMoney3(summary.salePrice, currency) })
|
|
2127
2230
|
] })
|
|
2128
2231
|
] }),
|
|
2129
|
-
cartError && /* @__PURE__ */
|
|
2130
|
-
/* @__PURE__ */
|
|
2232
|
+
cartError && /* @__PURE__ */ jsx5("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
|
|
2233
|
+
/* @__PURE__ */ jsx5(
|
|
2131
2234
|
"button",
|
|
2132
2235
|
{
|
|
2133
2236
|
className: "lb-bundle__cta",
|
|
@@ -2137,7 +2240,7 @@ function MixMatchBundle(props) {
|
|
|
2137
2240
|
children: ctaLabel
|
|
2138
2241
|
}
|
|
2139
2242
|
),
|
|
2140
|
-
pickerOpen && /* @__PURE__ */
|
|
2243
|
+
pickerOpen && /* @__PURE__ */ jsx5(
|
|
2141
2244
|
MixMatchPicker,
|
|
2142
2245
|
{
|
|
2143
2246
|
outOfStockBehavior,
|
|
@@ -2178,7 +2281,7 @@ function countInStockProducts(bundle) {
|
|
|
2178
2281
|
return count;
|
|
2179
2282
|
}
|
|
2180
2283
|
function PlusIcon() {
|
|
2181
|
-
return /* @__PURE__ */
|
|
2284
|
+
return /* @__PURE__ */ jsxs5(
|
|
2182
2285
|
"svg",
|
|
2183
2286
|
{
|
|
2184
2287
|
width: "18",
|
|
@@ -2188,14 +2291,14 @@ function PlusIcon() {
|
|
|
2188
2291
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2189
2292
|
"aria-hidden": "true",
|
|
2190
2293
|
children: [
|
|
2191
|
-
/* @__PURE__ */
|
|
2192
|
-
/* @__PURE__ */
|
|
2294
|
+
/* @__PURE__ */ jsx5("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2295
|
+
/* @__PURE__ */ jsx5("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
2193
2296
|
]
|
|
2194
2297
|
}
|
|
2195
2298
|
);
|
|
2196
2299
|
}
|
|
2197
2300
|
function CloseIcon2() {
|
|
2198
|
-
return /* @__PURE__ */
|
|
2301
|
+
return /* @__PURE__ */ jsxs5(
|
|
2199
2302
|
"svg",
|
|
2200
2303
|
{
|
|
2201
2304
|
width: "16",
|
|
@@ -2205,25 +2308,28 @@ function CloseIcon2() {
|
|
|
2205
2308
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2206
2309
|
"aria-hidden": "true",
|
|
2207
2310
|
children: [
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
/* @__PURE__ */
|
|
2311
|
+
/* @__PURE__ */ jsx5("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2312
|
+
/* @__PURE__ */ jsx5("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
2210
2313
|
]
|
|
2211
2314
|
}
|
|
2212
2315
|
);
|
|
2213
2316
|
}
|
|
2214
2317
|
|
|
2215
2318
|
// src/components/VolumeBundle.tsx
|
|
2216
|
-
import { useCallback as useCallback7, useEffect as
|
|
2319
|
+
import { useCallback as useCallback7, useEffect as useEffect13, useMemo as useMemo7, useState as useState10 } from "react";
|
|
2217
2320
|
import {
|
|
2218
2321
|
formatMoney as formatMoney4,
|
|
2219
2322
|
formatUnitPrice as formatUnitPrice4,
|
|
2220
2323
|
calculateTierSavings,
|
|
2221
2324
|
getActiveTier,
|
|
2222
2325
|
getMinTierQuantity,
|
|
2326
|
+
bestValueTierIndex,
|
|
2327
|
+
resolveDefaultTierIndex,
|
|
2328
|
+
resolvePopularTierIndex,
|
|
2223
2329
|
isVariantFulfillable as isVariantFulfillable4,
|
|
2224
2330
|
shouldShowLowStockBadge as shouldShowLowStockBadge2
|
|
2225
2331
|
} from "@lime-bundles/core";
|
|
2226
|
-
import { jsx as
|
|
2332
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2227
2333
|
function VolumeBundle(props) {
|
|
2228
2334
|
const {
|
|
2229
2335
|
shopDomain,
|
|
@@ -2247,13 +2353,30 @@ function VolumeBundle(props) {
|
|
|
2247
2353
|
bundleType: "volume",
|
|
2248
2354
|
enabled: analyticsEnabled !== false
|
|
2249
2355
|
});
|
|
2250
|
-
const [quantity, setQuantity] =
|
|
2251
|
-
const [addingToCart, setAddingToCart] =
|
|
2252
|
-
const [cartError, setCartError] =
|
|
2356
|
+
const [quantity, setQuantity] = useState10(1);
|
|
2357
|
+
const [addingToCart, setAddingToCart] = useState10(false);
|
|
2358
|
+
const [cartError, setCartError] = useState10(null);
|
|
2359
|
+
const [seededFor, setSeededFor] = useState10(null);
|
|
2253
2360
|
const bundle = result.status === "success" && result.bundle.bundleType === "volume" ? result.bundle : null;
|
|
2361
|
+
useEffect13(() => {
|
|
2362
|
+
if (!bundle || seededFor === bundle.id) return;
|
|
2363
|
+
setSeededFor(bundle.id);
|
|
2364
|
+
const tiers = bundle.volumeTiers;
|
|
2365
|
+
if (tiers.length === 0) return;
|
|
2366
|
+
const best = bestValueTierIndex(
|
|
2367
|
+
tiers,
|
|
2368
|
+
bundle.discountConfig.discountType
|
|
2369
|
+
);
|
|
2370
|
+
const idx = resolveDefaultTierIndex(
|
|
2371
|
+
bundle.widgetConfig.defaultTier,
|
|
2372
|
+
tiers.length,
|
|
2373
|
+
best
|
|
2374
|
+
);
|
|
2375
|
+
setQuantity(tiers[idx].minQuantity);
|
|
2376
|
+
}, [bundle, seededFor]);
|
|
2254
2377
|
const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
2255
2378
|
const tiersEdgeFadeRef = useEdgeFade();
|
|
2256
|
-
|
|
2379
|
+
useEffect13(() => {
|
|
2257
2380
|
if (result.status === "error") {
|
|
2258
2381
|
onError?.(result.error);
|
|
2259
2382
|
return;
|
|
@@ -2296,19 +2419,16 @@ function VolumeBundle(props) {
|
|
|
2296
2419
|
);
|
|
2297
2420
|
const activeTier = bundle ? getActiveTier(bundle.volumeTiers, quantity) : null;
|
|
2298
2421
|
const popularTierIndex = useMemo7(() => {
|
|
2299
|
-
if (!bundle
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
}
|
|
2310
|
-
return best;
|
|
2311
|
-
}, [bundle, tierSavings]);
|
|
2422
|
+
if (!bundle || bundle.volumeTiers.length === 0) return -1;
|
|
2423
|
+
return resolvePopularTierIndex(
|
|
2424
|
+
bundle.widgetConfig.popularBadge.tierIndex,
|
|
2425
|
+
bundle.widgetConfig.popularBadge.visible !== false,
|
|
2426
|
+
bestValueTierIndex(
|
|
2427
|
+
bundle.volumeTiers,
|
|
2428
|
+
bundle.discountConfig.discountType
|
|
2429
|
+
)
|
|
2430
|
+
);
|
|
2431
|
+
}, [bundle]);
|
|
2312
2432
|
const activeUnitPrice = tierSavings.find((ts) => ts.tier === activeTier)?.unitPrice ?? basePrice;
|
|
2313
2433
|
const undiscountedTotal = basePrice * quantity;
|
|
2314
2434
|
const volumeTotal = activeUnitPrice * quantity;
|
|
@@ -2360,15 +2480,15 @@ function VolumeBundle(props) {
|
|
|
2360
2480
|
tierSavings
|
|
2361
2481
|
]);
|
|
2362
2482
|
if (result.status === "loading") {
|
|
2363
|
-
return /* @__PURE__ */
|
|
2364
|
-
/* @__PURE__ */
|
|
2365
|
-
/* @__PURE__ */
|
|
2483
|
+
return /* @__PURE__ */ jsxs6("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
|
|
2484
|
+
/* @__PURE__ */ jsx6("div", { className: "lb-skeleton lb-skeleton--title" }),
|
|
2485
|
+
/* @__PURE__ */ jsx6("div", { className: "lb-skeleton lb-skeleton--tiers" })
|
|
2366
2486
|
] });
|
|
2367
2487
|
}
|
|
2368
2488
|
if (result.status === "error") return null;
|
|
2369
2489
|
if (!bundle) return null;
|
|
2370
2490
|
if (!product) return null;
|
|
2371
|
-
return /* @__PURE__ */
|
|
2491
|
+
return /* @__PURE__ */ jsxs6(
|
|
2372
2492
|
"div",
|
|
2373
2493
|
{
|
|
2374
2494
|
ref: (el) => {
|
|
@@ -2379,12 +2499,19 @@ function VolumeBundle(props) {
|
|
|
2379
2499
|
role: "region",
|
|
2380
2500
|
"aria-label": bundle.title,
|
|
2381
2501
|
children: [
|
|
2382
|
-
/* @__PURE__ */
|
|
2383
|
-
/* @__PURE__ */
|
|
2384
|
-
bundle.description && /* @__PURE__ */
|
|
2502
|
+
/* @__PURE__ */ jsx6("div", { className: "lb-bundle-header", children: /* @__PURE__ */ jsxs6("div", { className: "lb-bundle-header__content", children: [
|
|
2503
|
+
/* @__PURE__ */ jsx6("h3", { className: "lb-bundle-title", children: bundle.title }),
|
|
2504
|
+
bundle.description && /* @__PURE__ */ jsx6("p", { className: "lb-bundle-subtitle", children: bundle.description })
|
|
2385
2505
|
] }) }),
|
|
2386
|
-
/* @__PURE__ */
|
|
2387
|
-
|
|
2506
|
+
/* @__PURE__ */ jsx6(
|
|
2507
|
+
BundleCountdown,
|
|
2508
|
+
{
|
|
2509
|
+
endsAt: bundle.endsAt,
|
|
2510
|
+
widgetConfig: bundle.widgetConfig
|
|
2511
|
+
}
|
|
2512
|
+
),
|
|
2513
|
+
/* @__PURE__ */ jsxs6("div", { className: "lb-bundle-product-row lb-bundle-product-row--volume", children: [
|
|
2514
|
+
thumbImage && /* @__PURE__ */ jsx6(
|
|
2388
2515
|
"img",
|
|
2389
2516
|
{
|
|
2390
2517
|
src: thumbImage.url,
|
|
@@ -2393,20 +2520,20 @@ function VolumeBundle(props) {
|
|
|
2393
2520
|
loading: "lazy"
|
|
2394
2521
|
}
|
|
2395
2522
|
),
|
|
2396
|
-
/* @__PURE__ */
|
|
2397
|
-
/* @__PURE__ */
|
|
2398
|
-
/* @__PURE__ */
|
|
2523
|
+
/* @__PURE__ */ jsxs6("div", { className: "lb-bundle__product-info", children: [
|
|
2524
|
+
/* @__PURE__ */ jsx6("p", { className: "lb-bundle__product-title", children: product.title }),
|
|
2525
|
+
/* @__PURE__ */ jsxs6("p", { className: "lb-bundle__product-price", children: [
|
|
2399
2526
|
formatMoney4(basePrice, currency),
|
|
2400
2527
|
" each"
|
|
2401
2528
|
] }),
|
|
2402
|
-
unitPriceText && /* @__PURE__ */
|
|
2403
|
-
showPicker && /* @__PURE__ */
|
|
2529
|
+
unitPriceText && /* @__PURE__ */ jsx6("p", { className: "lb-bundle__product-unit-price", children: unitPriceText }),
|
|
2530
|
+
showPicker && /* @__PURE__ */ jsx6("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
|
|
2404
2531
|
const dropdownOptions = optionsFor(optionIndex).map((o) => ({
|
|
2405
2532
|
value: o.value,
|
|
2406
2533
|
label: o.value,
|
|
2407
2534
|
disabled: o.disabled
|
|
2408
2535
|
}));
|
|
2409
|
-
return /* @__PURE__ */
|
|
2536
|
+
return /* @__PURE__ */ jsx6(
|
|
2410
2537
|
VariantDropdown,
|
|
2411
2538
|
{
|
|
2412
2539
|
options: dropdownOptions,
|
|
@@ -2419,37 +2546,47 @@ function VolumeBundle(props) {
|
|
|
2419
2546
|
}) })
|
|
2420
2547
|
] })
|
|
2421
2548
|
] }),
|
|
2422
|
-
/* @__PURE__ */
|
|
2549
|
+
/* @__PURE__ */ jsx6(
|
|
2423
2550
|
"div",
|
|
2424
2551
|
{
|
|
2425
2552
|
className: "lb-bundle__tiers lb-edge-fade",
|
|
2426
|
-
role: "
|
|
2427
|
-
"aria-label": "
|
|
2553
|
+
role: "radiogroup",
|
|
2554
|
+
"aria-label": "Select quantity",
|
|
2428
2555
|
ref: tiersEdgeFadeRef,
|
|
2429
2556
|
children: tierSavings.map((ts, tierIndex) => {
|
|
2430
2557
|
const savingsPercent = Math.round(ts.savingsPercent);
|
|
2431
2558
|
const showCompare = bundle.widgetConfig.pricing.showComparePrice && ts.savings > 0;
|
|
2432
|
-
|
|
2559
|
+
const isChecked = activeTier === ts.tier;
|
|
2560
|
+
return /* @__PURE__ */ jsxs6(
|
|
2433
2561
|
"div",
|
|
2434
2562
|
{
|
|
2435
2563
|
className: `lb-bundle__tier ${ts.isActive ? "lb-bundle__tier--active" : ""}`,
|
|
2436
|
-
role: "
|
|
2564
|
+
role: "radio",
|
|
2565
|
+
"aria-checked": isChecked,
|
|
2566
|
+
tabIndex: isChecked ? 0 : -1,
|
|
2567
|
+
onClick: () => setQuantity(ts.tier.minQuantity),
|
|
2568
|
+
onKeyDown: (e) => {
|
|
2569
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2570
|
+
e.preventDefault();
|
|
2571
|
+
setQuantity(ts.tier.minQuantity);
|
|
2572
|
+
}
|
|
2573
|
+
},
|
|
2437
2574
|
children: [
|
|
2438
|
-
/* @__PURE__ */
|
|
2439
|
-
/* @__PURE__ */
|
|
2440
|
-
/* @__PURE__ */
|
|
2575
|
+
/* @__PURE__ */ jsx6("span", { className: "lb-bundle__tier-radio", "aria-hidden": "true", children: /* @__PURE__ */ jsx6("span", { className: "lb-bundle__tier-radio-dot" }) }),
|
|
2576
|
+
/* @__PURE__ */ jsxs6("span", { className: "lb-bundle__tier-info", children: [
|
|
2577
|
+
/* @__PURE__ */ jsxs6("span", { className: "lb-bundle__tier-label", children: [
|
|
2441
2578
|
"Buy ",
|
|
2442
2579
|
ts.tier.minQuantity
|
|
2443
2580
|
] }),
|
|
2444
|
-
/* @__PURE__ */
|
|
2445
|
-
showCompare && /* @__PURE__ */
|
|
2446
|
-
/* @__PURE__ */
|
|
2447
|
-
/* @__PURE__ */
|
|
2581
|
+
/* @__PURE__ */ jsxs6("span", { className: "lb-bundle__tier-price", children: [
|
|
2582
|
+
showCompare && /* @__PURE__ */ jsx6("span", { className: "lb-bundle__tier-compare", children: formatMoney4(basePrice, currency) }),
|
|
2583
|
+
/* @__PURE__ */ jsx6("span", { children: formatMoney4(ts.unitPrice, currency) }),
|
|
2584
|
+
/* @__PURE__ */ jsx6("span", { className: "lb-bundle__tier-unit", children: "each" })
|
|
2448
2585
|
] })
|
|
2449
2586
|
] }),
|
|
2450
|
-
(tierIndex === popularTierIndex || savingsPercent > 0) && /* @__PURE__ */
|
|
2451
|
-
tierIndex === popularTierIndex && /* @__PURE__ */
|
|
2452
|
-
savingsPercent > 0 && /* @__PURE__ */
|
|
2587
|
+
(tierIndex === popularTierIndex || savingsPercent > 0) && /* @__PURE__ */ jsxs6("span", { className: "lb-bundle__tier-right", children: [
|
|
2588
|
+
tierIndex === popularTierIndex && /* @__PURE__ */ jsx6("span", { className: "lb-bundle__tier-badge", children: bundle.widgetConfig.popularBadge.text }),
|
|
2589
|
+
savingsPercent > 0 && /* @__PURE__ */ jsxs6("span", { className: "lb-bundle__tier-savings", children: [
|
|
2453
2590
|
"Save ",
|
|
2454
2591
|
savingsPercent,
|
|
2455
2592
|
"%"
|
|
@@ -2462,10 +2599,10 @@ function VolumeBundle(props) {
|
|
|
2462
2599
|
})
|
|
2463
2600
|
}
|
|
2464
2601
|
),
|
|
2465
|
-
/* @__PURE__ */
|
|
2466
|
-
/* @__PURE__ */
|
|
2467
|
-
/* @__PURE__ */
|
|
2468
|
-
/* @__PURE__ */
|
|
2602
|
+
/* @__PURE__ */ jsxs6("div", { className: "lb-bundle__quantity-selector", children: [
|
|
2603
|
+
/* @__PURE__ */ jsx6("label", { htmlFor: `lb-qty-${bundle.id}`, children: "Quantity" }),
|
|
2604
|
+
/* @__PURE__ */ jsxs6("div", { className: "lb-bundle__quantity-control", children: [
|
|
2605
|
+
/* @__PURE__ */ jsx6(
|
|
2469
2606
|
"button",
|
|
2470
2607
|
{
|
|
2471
2608
|
"aria-label": "Decrease quantity",
|
|
@@ -2473,7 +2610,7 @@ function VolumeBundle(props) {
|
|
|
2473
2610
|
children: "\u2212"
|
|
2474
2611
|
}
|
|
2475
2612
|
),
|
|
2476
|
-
/* @__PURE__ */
|
|
2613
|
+
/* @__PURE__ */ jsx6(
|
|
2477
2614
|
"input",
|
|
2478
2615
|
{
|
|
2479
2616
|
id: `lb-qty-${bundle.id}`,
|
|
@@ -2487,7 +2624,7 @@ function VolumeBundle(props) {
|
|
|
2487
2624
|
className: "lb-bundle__quantity-input"
|
|
2488
2625
|
}
|
|
2489
2626
|
),
|
|
2490
|
-
/* @__PURE__ */
|
|
2627
|
+
/* @__PURE__ */ jsx6(
|
|
2491
2628
|
"button",
|
|
2492
2629
|
{
|
|
2493
2630
|
"aria-label": "Increase quantity",
|
|
@@ -2497,23 +2634,23 @@ function VolumeBundle(props) {
|
|
|
2497
2634
|
)
|
|
2498
2635
|
] })
|
|
2499
2636
|
] }),
|
|
2500
|
-
cartError && /* @__PURE__ */
|
|
2637
|
+
cartError && /* @__PURE__ */ jsx6("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
|
|
2501
2638
|
bundle && displayVariant && shouldShowLowStockBadge2(
|
|
2502
2639
|
displayVariant,
|
|
2503
2640
|
minTierQty,
|
|
2504
2641
|
bundle.widgetConfig.lowStockThreshold,
|
|
2505
2642
|
bundle.widgetConfig.showLowStockBadge
|
|
2506
|
-
) && /* @__PURE__ */
|
|
2643
|
+
) && /* @__PURE__ */ jsxs6("span", { className: "lb-bundle-low-stock-badge", children: [
|
|
2507
2644
|
"Only ",
|
|
2508
2645
|
displayVariant.quantityAvailable,
|
|
2509
2646
|
" left"
|
|
2510
2647
|
] }),
|
|
2511
|
-
/* @__PURE__ */
|
|
2512
|
-
/* @__PURE__ */
|
|
2513
|
-
/* @__PURE__ */
|
|
2514
|
-
/* @__PURE__ */
|
|
2648
|
+
/* @__PURE__ */ jsx6("div", { className: "lb-bundle-divider" }),
|
|
2649
|
+
/* @__PURE__ */ jsxs6("div", { className: "lb-bundle-summary", children: [
|
|
2650
|
+
/* @__PURE__ */ jsxs6("div", { className: "lb-bundle-summary__text", children: [
|
|
2651
|
+
/* @__PURE__ */ jsxs6("span", { className: "lb-bundle-summary__label", "data-total-label": true, children: [
|
|
2515
2652
|
"Total",
|
|
2516
|
-
bundle.widgetConfig.pricing.showItemCount && /* @__PURE__ */
|
|
2653
|
+
bundle.widgetConfig.pricing.showItemCount && /* @__PURE__ */ jsxs6("span", { "data-item-count": true, children: [
|
|
2517
2654
|
" ",
|
|
2518
2655
|
"(",
|
|
2519
2656
|
quantity,
|
|
@@ -2522,24 +2659,24 @@ function VolumeBundle(props) {
|
|
|
2522
2659
|
")"
|
|
2523
2660
|
] })
|
|
2524
2661
|
] }),
|
|
2525
|
-
bundle.widgetConfig.savingsBar.visible && volumeSavings > 0 && /* @__PURE__ */
|
|
2662
|
+
bundle.widgetConfig.savingsBar.visible && volumeSavings > 0 && /* @__PURE__ */ jsxs6("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
|
|
2526
2663
|
"You save",
|
|
2527
2664
|
" ",
|
|
2528
|
-
/* @__PURE__ */
|
|
2665
|
+
/* @__PURE__ */ jsx6("span", { "data-savings-amount": true, children: formatMoney4(volumeSavings, currency) }),
|
|
2529
2666
|
" ",
|
|
2530
|
-
/* @__PURE__ */
|
|
2667
|
+
/* @__PURE__ */ jsxs6("span", { "data-savings-percent": true, children: [
|
|
2531
2668
|
"(",
|
|
2532
2669
|
volumeSavingsPercent,
|
|
2533
2670
|
"%)"
|
|
2534
2671
|
] })
|
|
2535
2672
|
] })
|
|
2536
2673
|
] }),
|
|
2537
|
-
/* @__PURE__ */
|
|
2538
|
-
bundle.widgetConfig.pricing.showComparePrice && volumeSavings > 0 && /* @__PURE__ */
|
|
2539
|
-
/* @__PURE__ */
|
|
2674
|
+
/* @__PURE__ */ jsxs6("span", { className: "lb-bundle-summary__prices", children: [
|
|
2675
|
+
bundle.widgetConfig.pricing.showComparePrice && volumeSavings > 0 && /* @__PURE__ */ jsx6("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: formatMoney4(undiscountedTotal, currency) }),
|
|
2676
|
+
/* @__PURE__ */ jsx6("span", { className: "lb-bundle-sale-price", "data-total-price": true, children: formatMoney4(volumeTotal, currency) })
|
|
2540
2677
|
] })
|
|
2541
2678
|
] }),
|
|
2542
|
-
/* @__PURE__ */
|
|
2679
|
+
/* @__PURE__ */ jsx6(
|
|
2543
2680
|
"button",
|
|
2544
2681
|
{
|
|
2545
2682
|
className: "lb-bundle__cta",
|
|
@@ -2555,13 +2692,13 @@ function VolumeBundle(props) {
|
|
|
2555
2692
|
}
|
|
2556
2693
|
|
|
2557
2694
|
// src/components/BogoBundle.tsx
|
|
2558
|
-
import { useCallback as useCallback8, useEffect as
|
|
2695
|
+
import { useCallback as useCallback8, useEffect as useEffect14, useMemo as useMemo8, useState as useState11 } from "react";
|
|
2559
2696
|
import {
|
|
2560
2697
|
formatMoney as formatMoney5,
|
|
2561
2698
|
formatUnitPrice as formatUnitPrice5,
|
|
2562
2699
|
isVariantFulfillable as isVariantFulfillable5
|
|
2563
2700
|
} from "@lime-bundles/core";
|
|
2564
|
-
import { jsx as
|
|
2701
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2565
2702
|
function discountedUnit(price, percent) {
|
|
2566
2703
|
const cents = Math.round(price * 100);
|
|
2567
2704
|
const discounted = cents - Math.floor(cents * percent / 100);
|
|
@@ -2590,9 +2727,9 @@ function BogoBundle(props) {
|
|
|
2590
2727
|
bundleType: "bogo",
|
|
2591
2728
|
enabled: analyticsEnabled !== false
|
|
2592
2729
|
});
|
|
2593
|
-
const [addingToCart, setAddingToCart] =
|
|
2594
|
-
const [cartError, setCartError] =
|
|
2595
|
-
const [selectedVariants, setSelectedVariants] =
|
|
2730
|
+
const [addingToCart, setAddingToCart] = useState11(false);
|
|
2731
|
+
const [cartError, setCartError] = useState11(null);
|
|
2732
|
+
const [selectedVariants, setSelectedVariants] = useState11({ buy: null, get: null });
|
|
2596
2733
|
const handleVariantChange = useCallback8(
|
|
2597
2734
|
(role, variant) => {
|
|
2598
2735
|
setSelectedVariants((prev) => {
|
|
@@ -2604,7 +2741,7 @@ function BogoBundle(props) {
|
|
|
2604
2741
|
);
|
|
2605
2742
|
const bundle = result.status === "success" && result.bundle.bundleType === "bogo" ? result.bundle : null;
|
|
2606
2743
|
const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
2607
|
-
|
|
2744
|
+
useEffect14(() => {
|
|
2608
2745
|
if (result.status === "error") {
|
|
2609
2746
|
onError?.(result.error);
|
|
2610
2747
|
return;
|
|
@@ -2685,9 +2822,9 @@ function BogoBundle(props) {
|
|
|
2685
2822
|
}
|
|
2686
2823
|
}, [bundle, buyProduct, getProduct, selectedVariants, resolveVariant, onAddToCart, onError, trackAddToCart, percent]);
|
|
2687
2824
|
if (result.status === "loading") {
|
|
2688
|
-
return /* @__PURE__ */
|
|
2689
|
-
/* @__PURE__ */
|
|
2690
|
-
/* @__PURE__ */
|
|
2825
|
+
return /* @__PURE__ */ jsxs7("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
|
|
2826
|
+
/* @__PURE__ */ jsx7("div", { className: "lb-skeleton lb-skeleton--title" }),
|
|
2827
|
+
/* @__PURE__ */ jsx7("div", { className: "lb-skeleton lb-skeleton--products" })
|
|
2691
2828
|
] });
|
|
2692
2829
|
}
|
|
2693
2830
|
if (result.status === "error") return null;
|
|
@@ -2704,7 +2841,7 @@ function BogoBundle(props) {
|
|
|
2704
2841
|
const showCompare = bundle.widgetConfig.pricing.showComparePrice && savings > 0;
|
|
2705
2842
|
const showSavings = bundle.widgetConfig.savingsBar.visible && savings > 0;
|
|
2706
2843
|
const badge = percent === 100 ? "Free" : `${percent}% off`;
|
|
2707
|
-
return /* @__PURE__ */
|
|
2844
|
+
return /* @__PURE__ */ jsxs7(
|
|
2708
2845
|
"div",
|
|
2709
2846
|
{
|
|
2710
2847
|
ref: (el) => {
|
|
@@ -2715,12 +2852,19 @@ function BogoBundle(props) {
|
|
|
2715
2852
|
role: "region",
|
|
2716
2853
|
"aria-label": bundle.title,
|
|
2717
2854
|
children: [
|
|
2718
|
-
/* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
bundle.description && /* @__PURE__ */
|
|
2855
|
+
/* @__PURE__ */ jsx7("div", { className: "lb-bundle-header", children: /* @__PURE__ */ jsxs7("div", { className: "lb-bundle-header__content", children: [
|
|
2856
|
+
/* @__PURE__ */ jsx7("h3", { className: "lb-bundle-title", children: bundle.title }),
|
|
2857
|
+
bundle.description && /* @__PURE__ */ jsx7("p", { className: "lb-bundle-subtitle", children: bundle.description })
|
|
2721
2858
|
] }) }),
|
|
2722
|
-
/* @__PURE__ */
|
|
2723
|
-
|
|
2859
|
+
/* @__PURE__ */ jsx7(
|
|
2860
|
+
BundleCountdown,
|
|
2861
|
+
{
|
|
2862
|
+
endsAt: bundle.endsAt,
|
|
2863
|
+
widgetConfig: bundle.widgetConfig
|
|
2864
|
+
}
|
|
2865
|
+
),
|
|
2866
|
+
/* @__PURE__ */ jsxs7("div", { className: "lb-bundle__products", children: [
|
|
2867
|
+
/* @__PURE__ */ jsx7(
|
|
2724
2868
|
BogoProductRow,
|
|
2725
2869
|
{
|
|
2726
2870
|
side: "buy",
|
|
@@ -2732,11 +2876,11 @@ function BogoBundle(props) {
|
|
|
2732
2876
|
onVariantChange: handleVariantChange
|
|
2733
2877
|
}
|
|
2734
2878
|
),
|
|
2735
|
-
/* @__PURE__ */
|
|
2736
|
-
/* @__PURE__ */
|
|
2737
|
-
/* @__PURE__ */
|
|
2879
|
+
/* @__PURE__ */ jsx7("div", { className: "lb-bogo__plus", "aria-hidden": "true", children: /* @__PURE__ */ jsxs7("svg", { width: "12", height: "12", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
2880
|
+
/* @__PURE__ */ jsx7("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2881
|
+
/* @__PURE__ */ jsx7("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
2738
2882
|
] }) }),
|
|
2739
|
-
/* @__PURE__ */
|
|
2883
|
+
/* @__PURE__ */ jsx7(
|
|
2740
2884
|
BogoProductRow,
|
|
2741
2885
|
{
|
|
2742
2886
|
side: "get",
|
|
@@ -2749,29 +2893,29 @@ function BogoBundle(props) {
|
|
|
2749
2893
|
}
|
|
2750
2894
|
)
|
|
2751
2895
|
] }),
|
|
2752
|
-
/* @__PURE__ */
|
|
2753
|
-
/* @__PURE__ */
|
|
2754
|
-
/* @__PURE__ */
|
|
2755
|
-
/* @__PURE__ */
|
|
2756
|
-
showSavings && /* @__PURE__ */
|
|
2896
|
+
/* @__PURE__ */ jsx7("div", { className: "lb-bundle-divider" }),
|
|
2897
|
+
/* @__PURE__ */ jsxs7("div", { className: "lb-bundle-summary", children: [
|
|
2898
|
+
/* @__PURE__ */ jsxs7("div", { className: "lb-bundle-summary__text", children: [
|
|
2899
|
+
/* @__PURE__ */ jsx7("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
|
|
2900
|
+
showSavings && /* @__PURE__ */ jsxs7("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
|
|
2757
2901
|
"You save",
|
|
2758
2902
|
" ",
|
|
2759
|
-
/* @__PURE__ */
|
|
2903
|
+
/* @__PURE__ */ jsx7("span", { "data-savings-amount": true, children: formatMoney5(savings, currency) }),
|
|
2760
2904
|
" ",
|
|
2761
|
-
/* @__PURE__ */
|
|
2905
|
+
/* @__PURE__ */ jsxs7("span", { "data-savings-percent": true, children: [
|
|
2762
2906
|
"(",
|
|
2763
2907
|
savingsPercent,
|
|
2764
2908
|
"%)"
|
|
2765
2909
|
] })
|
|
2766
2910
|
] })
|
|
2767
2911
|
] }),
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
showCompare && /* @__PURE__ */
|
|
2770
|
-
/* @__PURE__ */
|
|
2912
|
+
/* @__PURE__ */ jsxs7("span", { className: "lb-bundle-summary__prices", children: [
|
|
2913
|
+
showCompare && /* @__PURE__ */ jsx7("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: formatMoney5(comparePrice, currency) }),
|
|
2914
|
+
/* @__PURE__ */ jsx7("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: formatMoney5(salePrice, currency) })
|
|
2771
2915
|
] })
|
|
2772
2916
|
] }),
|
|
2773
|
-
cartError && /* @__PURE__ */
|
|
2774
|
-
/* @__PURE__ */
|
|
2917
|
+
cartError && /* @__PURE__ */ jsx7("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
|
|
2918
|
+
/* @__PURE__ */ jsx7(
|
|
2775
2919
|
"button",
|
|
2776
2920
|
{
|
|
2777
2921
|
className: "lb-bundle__cta",
|
|
@@ -2796,7 +2940,7 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
|
|
|
2796
2940
|
variants,
|
|
2797
2941
|
optionNames
|
|
2798
2942
|
});
|
|
2799
|
-
|
|
2943
|
+
useEffect14(() => {
|
|
2800
2944
|
onVariantChange(side, selectedVariant ?? null);
|
|
2801
2945
|
}, [selectedVariant, side, onVariantChange]);
|
|
2802
2946
|
const displayVariant = selectedVariant ?? variants.find((v) => isVariantFulfillable5(v, quantity)) ?? variants[0];
|
|
@@ -2810,8 +2954,8 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
|
|
|
2810
2954
|
currency
|
|
2811
2955
|
) : null;
|
|
2812
2956
|
const thumbImage = displayVariant?.image ?? product.featuredImage;
|
|
2813
|
-
return /* @__PURE__ */
|
|
2814
|
-
thumbImage && /* @__PURE__ */
|
|
2957
|
+
return /* @__PURE__ */ jsxs7("div", { className: "lb-bundle-product-row", part: "product", "data-bogo-role": side, children: [
|
|
2958
|
+
thumbImage && /* @__PURE__ */ jsx7(
|
|
2815
2959
|
"img",
|
|
2816
2960
|
{
|
|
2817
2961
|
src: thumbImage.url,
|
|
@@ -2820,11 +2964,11 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
|
|
|
2820
2964
|
loading: "lazy"
|
|
2821
2965
|
}
|
|
2822
2966
|
),
|
|
2823
|
-
/* @__PURE__ */
|
|
2824
|
-
/* @__PURE__ */
|
|
2825
|
-
!showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */
|
|
2826
|
-
/* @__PURE__ */
|
|
2827
|
-
compareAt && /* @__PURE__ */
|
|
2967
|
+
/* @__PURE__ */ jsxs7("div", { className: "lb-bundle__product-info", children: [
|
|
2968
|
+
/* @__PURE__ */ jsx7("p", { className: "lb-bundle__product-title", children: product.title }),
|
|
2969
|
+
!showPicker && displayVariant && variants.length > 1 && /* @__PURE__ */ jsx7("span", { className: "lb-bundle-variant-badge", children: displayVariant.title }),
|
|
2970
|
+
/* @__PURE__ */ jsxs7("span", { className: "lb-bundle-product-prices", children: [
|
|
2971
|
+
compareAt && /* @__PURE__ */ jsx7(
|
|
2828
2972
|
"span",
|
|
2829
2973
|
{
|
|
2830
2974
|
className: "lb-bundle-product-compare-price",
|
|
@@ -2832,13 +2976,13 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
|
|
|
2832
2976
|
children: compareAt
|
|
2833
2977
|
}
|
|
2834
2978
|
),
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
2979
|
+
/* @__PURE__ */ jsx7("span", { className: "lb-bundle__product-price", "data-product-price": true, children: priceText }),
|
|
2980
|
+
/* @__PURE__ */ jsxs7("span", { className: "lb-bundle-qty-inline", "data-qty-inline": true, children: [
|
|
2837
2981
|
"\xD7",
|
|
2838
2982
|
quantity
|
|
2839
2983
|
] })
|
|
2840
2984
|
] }),
|
|
2841
|
-
unitPriceText && /* @__PURE__ */
|
|
2985
|
+
unitPriceText && /* @__PURE__ */ jsx7(
|
|
2842
2986
|
"span",
|
|
2843
2987
|
{
|
|
2844
2988
|
className: "lb-bundle__product-unit-price",
|
|
@@ -2846,13 +2990,13 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
|
|
|
2846
2990
|
children: unitPriceText
|
|
2847
2991
|
}
|
|
2848
2992
|
),
|
|
2849
|
-
showPicker && /* @__PURE__ */
|
|
2993
|
+
showPicker && /* @__PURE__ */ jsx7("div", { className: "lb-bundle__product-variant-pickers", children: optionNames.map((optionName, optionIndex) => {
|
|
2850
2994
|
const dropdownOptions = optionsFor(optionIndex).map((o) => ({
|
|
2851
2995
|
value: o.value,
|
|
2852
2996
|
label: o.value,
|
|
2853
2997
|
disabled: o.disabled
|
|
2854
2998
|
}));
|
|
2855
|
-
return /* @__PURE__ */
|
|
2999
|
+
return /* @__PURE__ */ jsx7(
|
|
2856
3000
|
VariantDropdown,
|
|
2857
3001
|
{
|
|
2858
3002
|
options: dropdownOptions,
|
|
@@ -2864,12 +3008,12 @@ function BogoProductRow({ side, product, quantity, percent, badge, currency, onV
|
|
|
2864
3008
|
);
|
|
2865
3009
|
}) })
|
|
2866
3010
|
] }),
|
|
2867
|
-
badge && /* @__PURE__ */
|
|
3011
|
+
badge && /* @__PURE__ */ jsx7("span", { className: "lb-bogo__badge", children: badge })
|
|
2868
3012
|
] });
|
|
2869
3013
|
}
|
|
2870
3014
|
|
|
2871
3015
|
// src/components/MultiStepBundle.tsx
|
|
2872
|
-
import { useCallback as useCallback9, useEffect as
|
|
3016
|
+
import { useCallback as useCallback9, useEffect as useEffect16, useMemo as useMemo10, useState as useState13 } from "react";
|
|
2873
3017
|
import {
|
|
2874
3018
|
formatMoney as formatMoney7,
|
|
2875
3019
|
formatUnitPrice as formatUnitPrice7,
|
|
@@ -2882,10 +3026,10 @@ import {
|
|
|
2882
3026
|
|
|
2883
3027
|
// src/components/MultiStepPicker.tsx
|
|
2884
3028
|
import {
|
|
2885
|
-
useEffect as
|
|
3029
|
+
useEffect as useEffect15,
|
|
2886
3030
|
useMemo as useMemo9,
|
|
2887
3031
|
useRef as useRef7,
|
|
2888
|
-
useState as
|
|
3032
|
+
useState as useState12
|
|
2889
3033
|
} from "react";
|
|
2890
3034
|
import { createPortal as createPortal2 } from "react-dom";
|
|
2891
3035
|
import {
|
|
@@ -2897,10 +3041,17 @@ import {
|
|
|
2897
3041
|
stepHeadroom,
|
|
2898
3042
|
DEFAULT_PRODUCT_RULE as DEFAULT_PRODUCT_RULE3
|
|
2899
3043
|
} from "@lime-bundles/core";
|
|
2900
|
-
import { jsx as
|
|
2901
|
-
function ruleFor3(bundle, productId) {
|
|
3044
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3045
|
+
function ruleFor3(bundle, productId, variantId) {
|
|
3046
|
+
if (variantId) {
|
|
3047
|
+
const vRule = bundle.variantRules[variantId];
|
|
3048
|
+
if (vRule) return vRule;
|
|
3049
|
+
}
|
|
2902
3050
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE3;
|
|
2903
3051
|
}
|
|
3052
|
+
function variantRuleFor3(bundle, variantId) {
|
|
3053
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
3054
|
+
}
|
|
2904
3055
|
function sanitizeId2(gid) {
|
|
2905
3056
|
return gid.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
2906
3057
|
}
|
|
@@ -2948,13 +3099,13 @@ function MultiStepPicker({
|
|
|
2948
3099
|
const dialogRef = useRef7(null);
|
|
2949
3100
|
const titleRef = useRef7(null);
|
|
2950
3101
|
const mouseDownTarget = useRef7(null);
|
|
2951
|
-
const [open, setOpen] =
|
|
2952
|
-
const [stepIndex, setStepIndex] =
|
|
3102
|
+
const [open, setOpen] = useState12(false);
|
|
3103
|
+
const [stepIndex, setStepIndex] = useState12(
|
|
2953
3104
|
() => Math.max(0, Math.min(steps.length - 1, initialStep))
|
|
2954
3105
|
);
|
|
2955
|
-
const [query, setQuery] =
|
|
2956
|
-
const [activeType, setActiveType] =
|
|
2957
|
-
const [announcement, setAnnouncement] =
|
|
3106
|
+
const [query, setQuery] = useState12("");
|
|
3107
|
+
const [activeType, setActiveType] = useState12(FILTERS_ALL2);
|
|
3108
|
+
const [announcement, setAnnouncement] = useState12("");
|
|
2958
3109
|
const step = steps[stepIndex];
|
|
2959
3110
|
const stepMin = step?.minQuantity ?? 1;
|
|
2960
3111
|
const stepPicks = selections[stepIndex] ?? [];
|
|
@@ -2979,7 +3130,7 @@ function MultiStepPicker({
|
|
|
2979
3130
|
return types;
|
|
2980
3131
|
}, [eligible]);
|
|
2981
3132
|
const showFilters = wc.mixMatchShowTypeFilters && productTypes.length >= 2;
|
|
2982
|
-
|
|
3133
|
+
useEffect15(() => {
|
|
2983
3134
|
const id = requestAnimationFrame(() => setOpen(true));
|
|
2984
3135
|
return () => cancelAnimationFrame(id);
|
|
2985
3136
|
}, []);
|
|
@@ -3028,7 +3179,7 @@ function MultiStepPicker({
|
|
|
3028
3179
|
// inside carries the interactive role + focus trap. So the static-element
|
|
3029
3180
|
// interaction lint does not apply to this backdrop.
|
|
3030
3181
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
3031
|
-
/* @__PURE__ */
|
|
3182
|
+
/* @__PURE__ */ jsx8(
|
|
3032
3183
|
"div",
|
|
3033
3184
|
{
|
|
3034
3185
|
ref: (el) => {
|
|
@@ -3040,7 +3191,7 @@ function MultiStepPicker({
|
|
|
3040
3191
|
"data-bundle-gid": bundle.id,
|
|
3041
3192
|
onMouseDown: onOverlayMouseDown,
|
|
3042
3193
|
onMouseUp: onOverlayMouseUp,
|
|
3043
|
-
children: /* @__PURE__ */
|
|
3194
|
+
children: /* @__PURE__ */ jsxs8(
|
|
3044
3195
|
"div",
|
|
3045
3196
|
{
|
|
3046
3197
|
ref: dialogRef,
|
|
@@ -3050,10 +3201,10 @@ function MultiStepPicker({
|
|
|
3050
3201
|
"aria-labelledby": titleId,
|
|
3051
3202
|
tabIndex: -1,
|
|
3052
3203
|
children: [
|
|
3053
|
-
/* @__PURE__ */
|
|
3054
|
-
/* @__PURE__ */
|
|
3055
|
-
/* @__PURE__ */
|
|
3056
|
-
/* @__PURE__ */
|
|
3204
|
+
/* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-header", children: [
|
|
3205
|
+
/* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-header-top", children: [
|
|
3206
|
+
/* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-heading", children: [
|
|
3207
|
+
/* @__PURE__ */ jsx8(
|
|
3057
3208
|
"h4",
|
|
3058
3209
|
{
|
|
3059
3210
|
className: "lb-mix-match__modal-title",
|
|
@@ -3063,9 +3214,9 @@ function MultiStepPicker({
|
|
|
3063
3214
|
children: "Add to your bundle"
|
|
3064
3215
|
}
|
|
3065
3216
|
),
|
|
3066
|
-
/* @__PURE__ */
|
|
3217
|
+
/* @__PURE__ */ jsx8("p", { className: "lb-mix-match__modal-subtitle", "data-modal-subtitle": true, children: subtitle })
|
|
3067
3218
|
] }),
|
|
3068
|
-
/* @__PURE__ */
|
|
3219
|
+
/* @__PURE__ */ jsx8(
|
|
3069
3220
|
"button",
|
|
3070
3221
|
{
|
|
3071
3222
|
type: "button",
|
|
@@ -3073,16 +3224,16 @@ function MultiStepPicker({
|
|
|
3073
3224
|
"data-modal-close": true,
|
|
3074
3225
|
"aria-label": "Close",
|
|
3075
3226
|
onClick: onClose,
|
|
3076
|
-
children: /* @__PURE__ */
|
|
3227
|
+
children: /* @__PURE__ */ jsx8(CloseIcon3, {})
|
|
3077
3228
|
}
|
|
3078
3229
|
)
|
|
3079
3230
|
] }),
|
|
3080
|
-
/* @__PURE__ */
|
|
3231
|
+
/* @__PURE__ */ jsx8(
|
|
3081
3232
|
"div",
|
|
3082
3233
|
{
|
|
3083
3234
|
className: "lb-mix-match__progress lb-mix-match__modal-progress",
|
|
3084
3235
|
"data-progress": true,
|
|
3085
|
-
children: /* @__PURE__ */
|
|
3236
|
+
children: /* @__PURE__ */ jsx8(
|
|
3086
3237
|
"div",
|
|
3087
3238
|
{
|
|
3088
3239
|
className: "lb-mix-match__progress-segments",
|
|
@@ -3091,7 +3242,7 @@ function MultiStepPicker({
|
|
|
3091
3242
|
"aria-valuenow": shownUnits,
|
|
3092
3243
|
"aria-valuemin": 0,
|
|
3093
3244
|
"aria-valuemax": stepMin,
|
|
3094
|
-
children: Array.from({ length: stepMin }).map((_, i) => /* @__PURE__ */
|
|
3245
|
+
children: Array.from({ length: stepMin }).map((_, i) => /* @__PURE__ */ jsx8(
|
|
3095
3246
|
"span",
|
|
3096
3247
|
{
|
|
3097
3248
|
className: `lb-mix-match__progress-segment${i < shownUnits ? " lb-mix-match__progress-segment--filled" : ""}`,
|
|
@@ -3104,8 +3255,8 @@ function MultiStepPicker({
|
|
|
3104
3255
|
}
|
|
3105
3256
|
)
|
|
3106
3257
|
] }),
|
|
3107
|
-
wc.showSearch && /* @__PURE__ */
|
|
3108
|
-
/* @__PURE__ */
|
|
3258
|
+
wc.showSearch && /* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-search", children: [
|
|
3259
|
+
/* @__PURE__ */ jsx8(
|
|
3109
3260
|
"input",
|
|
3110
3261
|
{
|
|
3111
3262
|
type: "text",
|
|
@@ -3119,7 +3270,7 @@ function MultiStepPicker({
|
|
|
3119
3270
|
onChange: (e) => setQuery(e.target.value)
|
|
3120
3271
|
}
|
|
3121
3272
|
),
|
|
3122
|
-
query.length > 0 && /* @__PURE__ */
|
|
3273
|
+
query.length > 0 && /* @__PURE__ */ jsx8(
|
|
3123
3274
|
"button",
|
|
3124
3275
|
{
|
|
3125
3276
|
type: "button",
|
|
@@ -3127,11 +3278,11 @@ function MultiStepPicker({
|
|
|
3127
3278
|
"data-modal-search-clear": true,
|
|
3128
3279
|
"aria-label": "Clear search",
|
|
3129
3280
|
onClick: () => setQuery(""),
|
|
3130
|
-
children: /* @__PURE__ */
|
|
3281
|
+
children: /* @__PURE__ */ jsx8(SearchClearIcon2, {})
|
|
3131
3282
|
}
|
|
3132
3283
|
)
|
|
3133
3284
|
] }),
|
|
3134
|
-
showFilters && /* @__PURE__ */
|
|
3285
|
+
showFilters && /* @__PURE__ */ jsx8(
|
|
3135
3286
|
"div",
|
|
3136
3287
|
{
|
|
3137
3288
|
className: "lb-mix-match__filters",
|
|
@@ -3140,7 +3291,7 @@ function MultiStepPicker({
|
|
|
3140
3291
|
"aria-label": "Filter by product type",
|
|
3141
3292
|
children: [FILTERS_ALL2, ...productTypes].map((value) => {
|
|
3142
3293
|
const isActive = value === activeType;
|
|
3143
|
-
return /* @__PURE__ */
|
|
3294
|
+
return /* @__PURE__ */ jsx8(
|
|
3144
3295
|
"button",
|
|
3145
3296
|
{
|
|
3146
3297
|
type: "button",
|
|
@@ -3155,7 +3306,7 @@ function MultiStepPicker({
|
|
|
3155
3306
|
})
|
|
3156
3307
|
}
|
|
3157
3308
|
),
|
|
3158
|
-
/* @__PURE__ */
|
|
3309
|
+
/* @__PURE__ */ jsx8("div", { className: "lb-mix-match__modal-list", "data-modal-list": true, children: filtered.map((ep) => /* @__PURE__ */ jsx8(
|
|
3159
3310
|
MultiStepPickerRow,
|
|
3160
3311
|
{
|
|
3161
3312
|
bundle,
|
|
@@ -3173,10 +3324,10 @@ function MultiStepPicker({
|
|
|
3173
3324
|
},
|
|
3174
3325
|
`${stepIndex}:${ep.product.id}`
|
|
3175
3326
|
)) }),
|
|
3176
|
-
showEmpty && /* @__PURE__ */
|
|
3177
|
-
/* @__PURE__ */
|
|
3178
|
-
/* @__PURE__ */
|
|
3179
|
-
stepIndex > 0 && /* @__PURE__ */
|
|
3327
|
+
showEmpty && /* @__PURE__ */ jsx8("div", { className: "lb-mix-match__modal-empty", "data-modal-empty": true, children: /* @__PURE__ */ jsx8("p", { children: "No products match your search" }) }),
|
|
3328
|
+
/* @__PURE__ */ jsx8("span", { "data-modal-live": true, "aria-live": "polite", className: "lb-visually-hidden", children: announcement || (query.trim() ? `${filtered.length} products shown` : "") }),
|
|
3329
|
+
/* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-footer lb-multi-step__modal-footer", children: [
|
|
3330
|
+
stepIndex > 0 && /* @__PURE__ */ jsx8(
|
|
3180
3331
|
"button",
|
|
3181
3332
|
{
|
|
3182
3333
|
type: "button",
|
|
@@ -3186,7 +3337,7 @@ function MultiStepPicker({
|
|
|
3186
3337
|
children: "Back"
|
|
3187
3338
|
}
|
|
3188
3339
|
),
|
|
3189
|
-
/* @__PURE__ */
|
|
3340
|
+
/* @__PURE__ */ jsx8(
|
|
3190
3341
|
"span",
|
|
3191
3342
|
{
|
|
3192
3343
|
className: "lb-mix-match__modal-footer-count",
|
|
@@ -3195,7 +3346,7 @@ function MultiStepPicker({
|
|
|
3195
3346
|
children: `${shownUnits} of ${stepMin} added`
|
|
3196
3347
|
}
|
|
3197
3348
|
),
|
|
3198
|
-
!isLastStep && /* @__PURE__ */
|
|
3349
|
+
!isLastStep && /* @__PURE__ */ jsx8(
|
|
3199
3350
|
"button",
|
|
3200
3351
|
{
|
|
3201
3352
|
type: "button",
|
|
@@ -3208,7 +3359,7 @@ function MultiStepPicker({
|
|
|
3208
3359
|
children: "Next"
|
|
3209
3360
|
}
|
|
3210
3361
|
),
|
|
3211
|
-
isLastStep && /* @__PURE__ */
|
|
3362
|
+
isLastStep && /* @__PURE__ */ jsx8(
|
|
3212
3363
|
"button",
|
|
3213
3364
|
{
|
|
3214
3365
|
type: "button",
|
|
@@ -3253,6 +3404,8 @@ function MultiStepPickerRow({
|
|
|
3253
3404
|
const showPicker = variants.length > 1 && optionNames.length > 0;
|
|
3254
3405
|
const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
|
|
3255
3406
|
const currentVariant = selectedVariant ?? variants.find((v) => isVariantFulfillable6(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
|
|
3407
|
+
const vRule = ruleFor3(bundle, product.id, currentVariant?.id);
|
|
3408
|
+
const variantMax = variantRuleFor3(bundle, currentVariant?.id)?.max;
|
|
3256
3409
|
const stepPicks = useMemo9(
|
|
3257
3410
|
() => selections[stepIndex] ?? [],
|
|
3258
3411
|
[selections, stepIndex]
|
|
@@ -3287,24 +3440,27 @@ function MultiStepPickerRow({
|
|
|
3287
3440
|
return Math.max(0, sum - committedQty);
|
|
3288
3441
|
}, [selections, currentVariant, committedQty]);
|
|
3289
3442
|
const swapUnits = currentVariant ? swapUnitsFor?.(stepIndex, product.id, currentVariant.id) ?? 0 : 0;
|
|
3290
|
-
const inSwapState = swapUnits >=
|
|
3443
|
+
const inSwapState = swapUnits >= vRule.min;
|
|
3291
3444
|
const room = stepHeadroom(step?.maxQuantity ?? null, unitsInStep);
|
|
3292
|
-
const productHeadroom =
|
|
3445
|
+
const productHeadroom = Math.min(
|
|
3446
|
+
rule.max - productOtherUnits,
|
|
3447
|
+
variantMax ?? Infinity
|
|
3448
|
+
);
|
|
3293
3449
|
const spotCeiling = inSwapState ? swapUnits : Math.min(
|
|
3294
3450
|
productHeadroom,
|
|
3295
3451
|
room === Number.POSITIVE_INFINITY ? productHeadroom : committedQty + room
|
|
3296
3452
|
);
|
|
3297
3453
|
const stockRemaining = currentVariant ? maxAddableQuantity2(currentVariant, Number.MAX_SAFE_INTEGER, variantOtherUnits) : 0;
|
|
3298
3454
|
const cap = Math.max(0, Math.min(spotCeiling, stockRemaining));
|
|
3299
|
-
const stepperMax = Math.max(
|
|
3300
|
-
const [qty, setQty] =
|
|
3301
|
-
|
|
3302
|
-
setQty((prev) => Math.max(
|
|
3303
|
-
}, [stepperMax,
|
|
3455
|
+
const stepperMax = Math.max(vRule.min, cap);
|
|
3456
|
+
const [qty, setQty] = useState12(vRule.min);
|
|
3457
|
+
useEffect15(() => {
|
|
3458
|
+
setQty((prev) => Math.max(vRule.min, Math.min(prev, stepperMax)));
|
|
3459
|
+
}, [stepperMax, vRule.min]);
|
|
3304
3460
|
const currentVariantId = currentVariant?.id ?? null;
|
|
3305
|
-
|
|
3306
|
-
if (!variantInStep) setQty(
|
|
3307
|
-
}, [variantInStep, currentVariantId,
|
|
3461
|
+
useEffect15(() => {
|
|
3462
|
+
if (!variantInStep) setQty(vRule.min);
|
|
3463
|
+
}, [variantInStep, currentVariantId, vRule.min]);
|
|
3308
3464
|
if (!currentVariant || !step) return null;
|
|
3309
3465
|
const thumbImage = currentVariant.image ?? product.featuredImage ?? null;
|
|
3310
3466
|
const unitPriceText = formatUnitPrice6(
|
|
@@ -3312,8 +3468,8 @@ function MultiStepPickerRow({
|
|
|
3312
3468
|
currentVariant.unitPriceMeasurement,
|
|
3313
3469
|
currency
|
|
3314
3470
|
);
|
|
3315
|
-
const noStock = cap <
|
|
3316
|
-
const needsMoreSpots = !variantInStep && !inSwapState && room !== Number.POSITIVE_INFINITY &&
|
|
3471
|
+
const noStock = cap < vRule.min;
|
|
3472
|
+
const needsMoreSpots = !variantInStep && !inSwapState && room !== Number.POSITIVE_INFINITY && vRule.min > room;
|
|
3317
3473
|
const addDisabled = !variantInStep && (inSwapState ? noStock : noStock || needsMoreSpots);
|
|
3318
3474
|
const lockedRequired = variantInStep && currentVariant != null && !(canRemoveVariant?.(currentVariant.id) ?? true);
|
|
3319
3475
|
const stepperDisabled = isOos || !variantInStep && addDisabled;
|
|
@@ -3324,7 +3480,7 @@ function MultiStepPickerRow({
|
|
|
3324
3480
|
return;
|
|
3325
3481
|
}
|
|
3326
3482
|
if (!currentVariant || noStock) return;
|
|
3327
|
-
const pickedQty = showStepper ? qty :
|
|
3483
|
+
const pickedQty = showStepper ? qty : vRule.min;
|
|
3328
3484
|
const item = {
|
|
3329
3485
|
productId: product.id,
|
|
3330
3486
|
variantId: currentVariant.id,
|
|
@@ -3346,7 +3502,7 @@ function MultiStepPickerRow({
|
|
|
3346
3502
|
}
|
|
3347
3503
|
const priceCents = parseFloat(currentVariant.price.amount);
|
|
3348
3504
|
const compareCents = currentVariant.compareAtPrice ? parseFloat(currentVariant.compareAtPrice.amount) : null;
|
|
3349
|
-
return /* @__PURE__ */
|
|
3505
|
+
return /* @__PURE__ */ jsxs8(
|
|
3350
3506
|
"div",
|
|
3351
3507
|
{
|
|
3352
3508
|
className: `lb-mix-match__modal-product${isOos ? " lb-mix-match__modal-product--sold-out" : ""}${variantInStep ? " lb-mix-match__modal-product--in-bundle" : ""}`,
|
|
@@ -3355,8 +3511,8 @@ function MultiStepPickerRow({
|
|
|
3355
3511
|
"data-type": product.productType ?? "",
|
|
3356
3512
|
"aria-disabled": isOos || void 0,
|
|
3357
3513
|
children: [
|
|
3358
|
-
/* @__PURE__ */
|
|
3359
|
-
thumbImage && /* @__PURE__ */
|
|
3514
|
+
/* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-product-thumb", children: [
|
|
3515
|
+
thumbImage && /* @__PURE__ */ jsx8(
|
|
3360
3516
|
"img",
|
|
3361
3517
|
{
|
|
3362
3518
|
src: thumbImage.url,
|
|
@@ -3364,10 +3520,10 @@ function MultiStepPickerRow({
|
|
|
3364
3520
|
loading: "lazy"
|
|
3365
3521
|
}
|
|
3366
3522
|
),
|
|
3367
|
-
variantInStep && /* @__PURE__ */
|
|
3523
|
+
variantInStep && /* @__PURE__ */ jsx8("span", { className: "lb-mix-match__modal-added-badge", children: "Added" })
|
|
3368
3524
|
] }),
|
|
3369
|
-
/* @__PURE__ */
|
|
3370
|
-
/* @__PURE__ */
|
|
3525
|
+
/* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-product-info", children: [
|
|
3526
|
+
/* @__PURE__ */ jsx8("p", { className: "lb-mix-match__modal-product-title", children: /* @__PURE__ */ jsx8(
|
|
3371
3527
|
"a",
|
|
3372
3528
|
{
|
|
3373
3529
|
href: `/products/${product.handle}`,
|
|
@@ -3376,24 +3532,24 @@ function MultiStepPickerRow({
|
|
|
3376
3532
|
children: product.title
|
|
3377
3533
|
}
|
|
3378
3534
|
) }),
|
|
3379
|
-
/* @__PURE__ */
|
|
3380
|
-
/* @__PURE__ */
|
|
3381
|
-
compareCents !== null && compareCents > priceCents && /* @__PURE__ */
|
|
3535
|
+
/* @__PURE__ */ jsxs8("p", { className: "lb-mix-match__modal-product-price", children: [
|
|
3536
|
+
/* @__PURE__ */ jsx8("span", { "data-row-price-sale": true, children: formatMoney6(priceCents, currency) }),
|
|
3537
|
+
compareCents !== null && compareCents > priceCents && /* @__PURE__ */ jsx8("s", { className: "lb-mix-match__modal-product-compare", "data-row-compare": true, children: formatMoney6(compareCents, currency) })
|
|
3382
3538
|
] }),
|
|
3383
|
-
unitPriceText && /* @__PURE__ */
|
|
3384
|
-
showPicker && /* @__PURE__ */
|
|
3539
|
+
unitPriceText && /* @__PURE__ */ jsx8("p", { className: "lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price", children: unitPriceText }),
|
|
3540
|
+
showPicker && /* @__PURE__ */ jsx8("div", { className: "lb-bundle-variant-option-groups", children: optionNames.map((optionName, optionIndex) => {
|
|
3385
3541
|
const dropdownOptions = optionsFor(optionIndex).map((o) => ({
|
|
3386
3542
|
value: o.value,
|
|
3387
3543
|
label: o.value,
|
|
3388
3544
|
disabled: o.disabled
|
|
3389
3545
|
}));
|
|
3390
|
-
return /* @__PURE__ */
|
|
3546
|
+
return /* @__PURE__ */ jsxs8(
|
|
3391
3547
|
"div",
|
|
3392
3548
|
{
|
|
3393
3549
|
className: "lb-bundle-variant-option-group",
|
|
3394
3550
|
children: [
|
|
3395
|
-
/* @__PURE__ */
|
|
3396
|
-
/* @__PURE__ */
|
|
3551
|
+
/* @__PURE__ */ jsx8("span", { className: "lb-bundle-variant-option-label", children: optionName }),
|
|
3552
|
+
/* @__PURE__ */ jsx8(
|
|
3397
3553
|
VariantDropdown,
|
|
3398
3554
|
{
|
|
3399
3555
|
className: "lb-mix-match__variant-select-dropdown",
|
|
@@ -3408,39 +3564,39 @@ function MultiStepPickerRow({
|
|
|
3408
3564
|
optionName
|
|
3409
3565
|
);
|
|
3410
3566
|
}) }),
|
|
3411
|
-
!showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */
|
|
3412
|
-
!isOos && needsMoreSpots && room > 0 && /* @__PURE__ */
|
|
3413
|
-
isOos ? /* @__PURE__ */
|
|
3414
|
-
showStepper && /* @__PURE__ */
|
|
3567
|
+
!showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ jsx8("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
|
|
3568
|
+
!isOos && needsMoreSpots && room > 0 && /* @__PURE__ */ jsx8("span", { className: "lb-mix-match__modal-needs-spots", children: vRule.min === 1 ? "Needs 1 spot" : `Needs ${vRule.min} spots` }),
|
|
3569
|
+
isOos ? /* @__PURE__ */ jsx8("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ jsxs8("div", { className: "lb-mix-match__modal-product-actions", children: [
|
|
3570
|
+
showStepper && /* @__PURE__ */ jsx8("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ jsxs8(
|
|
3415
3571
|
"div",
|
|
3416
3572
|
{
|
|
3417
3573
|
className: "lb-mix-match__qty-stepper",
|
|
3418
3574
|
role: "group",
|
|
3419
3575
|
"aria-label": "Quantity",
|
|
3420
3576
|
children: [
|
|
3421
|
-
/* @__PURE__ */
|
|
3577
|
+
/* @__PURE__ */ jsx8(
|
|
3422
3578
|
"button",
|
|
3423
3579
|
{
|
|
3424
3580
|
type: "button",
|
|
3425
3581
|
className: "lb-mix-match__qty-stepper-button lb-mix-match__qty-stepper-button--minus",
|
|
3426
3582
|
"aria-label": "Decrease quantity",
|
|
3427
|
-
disabled: stepperDisabled || shownQty <=
|
|
3583
|
+
disabled: stepperDisabled || shownQty <= vRule.min,
|
|
3428
3584
|
onClick: () => {
|
|
3429
3585
|
if (variantInStep && currentVariant) {
|
|
3430
3586
|
onUpdateQuantity(
|
|
3431
3587
|
stepIndex,
|
|
3432
3588
|
product.id,
|
|
3433
3589
|
currentVariant.id,
|
|
3434
|
-
Math.max(
|
|
3590
|
+
Math.max(vRule.min, committedQty - 1)
|
|
3435
3591
|
);
|
|
3436
3592
|
} else {
|
|
3437
|
-
setQty((q) => Math.max(
|
|
3593
|
+
setQty((q) => Math.max(vRule.min, q - 1));
|
|
3438
3594
|
}
|
|
3439
3595
|
},
|
|
3440
3596
|
children: "\u2212"
|
|
3441
3597
|
}
|
|
3442
3598
|
),
|
|
3443
|
-
/* @__PURE__ */
|
|
3599
|
+
/* @__PURE__ */ jsx8(
|
|
3444
3600
|
"span",
|
|
3445
3601
|
{
|
|
3446
3602
|
className: "lb-mix-match__qty-stepper-value",
|
|
@@ -3449,7 +3605,7 @@ function MultiStepPickerRow({
|
|
|
3449
3605
|
children: shownQty
|
|
3450
3606
|
}
|
|
3451
3607
|
),
|
|
3452
|
-
/* @__PURE__ */
|
|
3608
|
+
/* @__PURE__ */ jsx8(
|
|
3453
3609
|
"button",
|
|
3454
3610
|
{
|
|
3455
3611
|
type: "button",
|
|
@@ -3474,7 +3630,7 @@ function MultiStepPickerRow({
|
|
|
3474
3630
|
]
|
|
3475
3631
|
}
|
|
3476
3632
|
) }),
|
|
3477
|
-
/* @__PURE__ */
|
|
3633
|
+
/* @__PURE__ */ jsx8(
|
|
3478
3634
|
"button",
|
|
3479
3635
|
{
|
|
3480
3636
|
type: "button",
|
|
@@ -3493,7 +3649,7 @@ function MultiStepPickerRow({
|
|
|
3493
3649
|
);
|
|
3494
3650
|
}
|
|
3495
3651
|
function CloseIcon3() {
|
|
3496
|
-
return /* @__PURE__ */
|
|
3652
|
+
return /* @__PURE__ */ jsxs8(
|
|
3497
3653
|
"svg",
|
|
3498
3654
|
{
|
|
3499
3655
|
width: "20",
|
|
@@ -3503,14 +3659,14 @@ function CloseIcon3() {
|
|
|
3503
3659
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3504
3660
|
"aria-hidden": "true",
|
|
3505
3661
|
children: [
|
|
3506
|
-
/* @__PURE__ */
|
|
3507
|
-
/* @__PURE__ */
|
|
3662
|
+
/* @__PURE__ */ jsx8("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
3663
|
+
/* @__PURE__ */ jsx8("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
3508
3664
|
]
|
|
3509
3665
|
}
|
|
3510
3666
|
);
|
|
3511
3667
|
}
|
|
3512
3668
|
function SearchClearIcon2() {
|
|
3513
|
-
return /* @__PURE__ */
|
|
3669
|
+
return /* @__PURE__ */ jsx8(
|
|
3514
3670
|
"svg",
|
|
3515
3671
|
{
|
|
3516
3672
|
width: "16",
|
|
@@ -3519,17 +3675,25 @@ function SearchClearIcon2() {
|
|
|
3519
3675
|
fill: "currentColor",
|
|
3520
3676
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3521
3677
|
"aria-hidden": "true",
|
|
3522
|
-
children: /* @__PURE__ */
|
|
3678
|
+
children: /* @__PURE__ */ jsx8("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" })
|
|
3523
3679
|
}
|
|
3524
3680
|
);
|
|
3525
3681
|
}
|
|
3526
3682
|
|
|
3527
3683
|
// src/components/MultiStepBundle.tsx
|
|
3528
|
-
import { jsx as
|
|
3529
|
-
function ruleFor4(bundle, productId) {
|
|
3684
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3685
|
+
function ruleFor4(bundle, productId, variantId) {
|
|
3686
|
+
if (variantId) {
|
|
3687
|
+
const vRule = bundle.variantRules[variantId];
|
|
3688
|
+
if (vRule) return vRule;
|
|
3689
|
+
}
|
|
3530
3690
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE4;
|
|
3531
3691
|
}
|
|
3692
|
+
function variantRuleFor4(bundle, variantId) {
|
|
3693
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
3694
|
+
}
|
|
3532
3695
|
function canRemoveItem2(bundle, selections, item) {
|
|
3696
|
+
if (variantRuleFor4(bundle, item.variantId)?.required) return false;
|
|
3533
3697
|
const rule = ruleFor4(bundle, item.productId);
|
|
3534
3698
|
if (!rule.required) return true;
|
|
3535
3699
|
let unitsElsewhere = 0;
|
|
@@ -3576,14 +3740,14 @@ function MultiStepBundle(props) {
|
|
|
3576
3740
|
bundleType: "multi_step",
|
|
3577
3741
|
enabled: analyticsEnabled !== false
|
|
3578
3742
|
});
|
|
3579
|
-
const [selections, setSelections] =
|
|
3580
|
-
const [pickerOpenAt, setPickerOpenAt] =
|
|
3581
|
-
const [addingToCart, setAddingToCart] =
|
|
3582
|
-
const [cartError, setCartError] =
|
|
3743
|
+
const [selections, setSelections] = useState13([]);
|
|
3744
|
+
const [pickerOpenAt, setPickerOpenAt] = useState13(null);
|
|
3745
|
+
const [addingToCart, setAddingToCart] = useState13(false);
|
|
3746
|
+
const [cartError, setCartError] = useState13(null);
|
|
3583
3747
|
const bundle = result.status === "success" && result.bundle.bundleType === "multi_step" ? result.bundle : null;
|
|
3584
3748
|
const setConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
3585
3749
|
const setModalConfigVarsRef = useWidgetConfigVars(bundle?.widgetConfig);
|
|
3586
|
-
|
|
3750
|
+
useEffect16(() => {
|
|
3587
3751
|
if (result.status === "error") {
|
|
3588
3752
|
onError?.(result.error);
|
|
3589
3753
|
return;
|
|
@@ -3597,7 +3761,7 @@ function MultiStepBundle(props) {
|
|
|
3597
3761
|
}
|
|
3598
3762
|
}, [result, onError]);
|
|
3599
3763
|
const steps = useMemo10(() => bundle?.steps ?? [], [bundle]);
|
|
3600
|
-
|
|
3764
|
+
useEffect16(() => {
|
|
3601
3765
|
const seeded = steps.map(() => []);
|
|
3602
3766
|
if (bundle) {
|
|
3603
3767
|
const seedCurrency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
|
|
@@ -3807,9 +3971,9 @@ function MultiStepBundle(props) {
|
|
|
3807
3971
|
}
|
|
3808
3972
|
}, [bundle, selections, valid, onAddToCart, onError, trackAddToCart, totalQuantity, steps]);
|
|
3809
3973
|
if (result.status === "loading") {
|
|
3810
|
-
return /* @__PURE__ */
|
|
3811
|
-
/* @__PURE__ */
|
|
3812
|
-
/* @__PURE__ */
|
|
3974
|
+
return /* @__PURE__ */ jsxs9("div", { className: `lb-bundle lb-bundle--loading ${className ?? ""}`, children: [
|
|
3975
|
+
/* @__PURE__ */ jsx9("div", { className: "lb-skeleton lb-skeleton--title" }),
|
|
3976
|
+
/* @__PURE__ */ jsx9("div", { className: "lb-skeleton lb-skeleton--products" })
|
|
3813
3977
|
] });
|
|
3814
3978
|
}
|
|
3815
3979
|
if (result.status === "error") return null;
|
|
@@ -3830,7 +3994,7 @@ function MultiStepBundle(props) {
|
|
|
3830
3994
|
if (requiredBlocked) return null;
|
|
3831
3995
|
const currency = bundle.products[0]?.priceRange.minVariantPrice.currencyCode ?? "USD";
|
|
3832
3996
|
const ctaLabel = addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText || "Add to cart";
|
|
3833
|
-
return /* @__PURE__ */
|
|
3997
|
+
return /* @__PURE__ */ jsxs9(
|
|
3834
3998
|
"div",
|
|
3835
3999
|
{
|
|
3836
4000
|
ref: (el) => {
|
|
@@ -3842,12 +4006,19 @@ function MultiStepBundle(props) {
|
|
|
3842
4006
|
"aria-label": bundle.title,
|
|
3843
4007
|
"data-required-quantity": totalMin,
|
|
3844
4008
|
children: [
|
|
3845
|
-
/* @__PURE__ */
|
|
3846
|
-
/* @__PURE__ */
|
|
3847
|
-
bundle.description && /* @__PURE__ */
|
|
4009
|
+
/* @__PURE__ */ jsx9("div", { className: "lb-bundle-header", children: /* @__PURE__ */ jsxs9("div", { className: "lb-bundle-header__content", children: [
|
|
4010
|
+
/* @__PURE__ */ jsx9("h3", { className: "lb-bundle-title", children: bundle.title }),
|
|
4011
|
+
bundle.description && /* @__PURE__ */ jsx9("p", { className: "lb-bundle-subtitle", children: bundle.description })
|
|
3848
4012
|
] }) }),
|
|
3849
|
-
/* @__PURE__ */
|
|
3850
|
-
|
|
4013
|
+
/* @__PURE__ */ jsx9(
|
|
4014
|
+
BundleCountdown,
|
|
4015
|
+
{
|
|
4016
|
+
endsAt: bundle.endsAt,
|
|
4017
|
+
widgetConfig: bundle.widgetConfig
|
|
4018
|
+
}
|
|
4019
|
+
),
|
|
4020
|
+
/* @__PURE__ */ jsxs9("div", { className: "lb-mix-match__progress", "data-progress": true, children: [
|
|
4021
|
+
/* @__PURE__ */ jsx9(
|
|
3851
4022
|
"div",
|
|
3852
4023
|
{
|
|
3853
4024
|
className: "lb-mix-match__progress-segments",
|
|
@@ -3855,7 +4026,7 @@ function MultiStepBundle(props) {
|
|
|
3855
4026
|
"aria-valuenow": completedSteps,
|
|
3856
4027
|
"aria-valuemin": 0,
|
|
3857
4028
|
"aria-valuemax": steps.length,
|
|
3858
|
-
children: Array.from({ length: steps.length }).map((_, i) => /* @__PURE__ */
|
|
4029
|
+
children: Array.from({ length: steps.length }).map((_, i) => /* @__PURE__ */ jsx9(
|
|
3859
4030
|
"span",
|
|
3860
4031
|
{
|
|
3861
4032
|
className: `lb-mix-match__progress-segment${i < completedSteps ? " lb-mix-match__progress-segment--filled" : ""}`,
|
|
@@ -3865,8 +4036,8 @@ function MultiStepBundle(props) {
|
|
|
3865
4036
|
))
|
|
3866
4037
|
}
|
|
3867
4038
|
),
|
|
3868
|
-
/* @__PURE__ */
|
|
3869
|
-
/* @__PURE__ */
|
|
4039
|
+
/* @__PURE__ */ jsxs9("div", { className: "lb-mix-match__progress-labels", children: [
|
|
4040
|
+
/* @__PURE__ */ jsx9(
|
|
3870
4041
|
"span",
|
|
3871
4042
|
{
|
|
3872
4043
|
className: "lb-mix-match__progress-count",
|
|
@@ -3875,7 +4046,7 @@ function MultiStepBundle(props) {
|
|
|
3875
4046
|
children: `${completedSteps} of ${steps.length} steps completed`
|
|
3876
4047
|
}
|
|
3877
4048
|
),
|
|
3878
|
-
/* @__PURE__ */
|
|
4049
|
+
/* @__PURE__ */ jsx9(
|
|
3879
4050
|
"span",
|
|
3880
4051
|
{
|
|
3881
4052
|
className: "lb-mix-match__progress-remaining",
|
|
@@ -3886,15 +4057,15 @@ function MultiStepBundle(props) {
|
|
|
3886
4057
|
)
|
|
3887
4058
|
] })
|
|
3888
4059
|
] }),
|
|
3889
|
-
/* @__PURE__ */
|
|
4060
|
+
/* @__PURE__ */ jsx9("div", { className: "lb-multi-step__groups", "data-step-groups": true, children: steps.map((step, i) => /* @__PURE__ */ jsxs9(
|
|
3890
4061
|
"section",
|
|
3891
4062
|
{
|
|
3892
4063
|
className: "lb-multi-step__group",
|
|
3893
4064
|
"data-step-group": i,
|
|
3894
4065
|
children: [
|
|
3895
|
-
/* @__PURE__ */
|
|
3896
|
-
/* @__PURE__ */
|
|
3897
|
-
/* @__PURE__ */
|
|
4066
|
+
/* @__PURE__ */ jsxs9("div", { className: "lb-multi-step__group-heading", children: [
|
|
4067
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-multi-step__group-name", children: step.name }),
|
|
4068
|
+
/* @__PURE__ */ jsx9(
|
|
3898
4069
|
"span",
|
|
3899
4070
|
{
|
|
3900
4071
|
className: `lb-multi-step__group-count${stepSatisfied(i) ? " lb-multi-step__group-count--met" : ""}`,
|
|
@@ -3903,7 +4074,7 @@ function MultiStepBundle(props) {
|
|
|
3903
4074
|
}
|
|
3904
4075
|
)
|
|
3905
4076
|
] }),
|
|
3906
|
-
/* @__PURE__ */
|
|
4077
|
+
/* @__PURE__ */ jsx9(
|
|
3907
4078
|
"div",
|
|
3908
4079
|
{
|
|
3909
4080
|
className: "lb-mix-match__slots lb-edge-fade lb-multi-step__group-slots",
|
|
@@ -3913,13 +4084,13 @@ function MultiStepBundle(props) {
|
|
|
3913
4084
|
title button provides the keyboard/AT path (its
|
|
3914
4085
|
activation bubbles here); × stops propagation. */
|
|
3915
4086
|
// 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
|
|
3916
|
-
/* @__PURE__ */
|
|
4087
|
+
/* @__PURE__ */ jsxs9(
|
|
3917
4088
|
"div",
|
|
3918
4089
|
{
|
|
3919
4090
|
className: "lb-mix-match__slot lb-mix-match__slot--filled",
|
|
3920
4091
|
onClick: () => setPickerOpenAt(i),
|
|
3921
4092
|
children: [
|
|
3922
|
-
item.featuredImage && /* @__PURE__ */
|
|
4093
|
+
item.featuredImage && /* @__PURE__ */ jsx9("div", { className: "lb-bundle-thumbnail", children: /* @__PURE__ */ jsx9(
|
|
3923
4094
|
"img",
|
|
3924
4095
|
{
|
|
3925
4096
|
src: item.featuredImage,
|
|
@@ -3927,8 +4098,8 @@ function MultiStepBundle(props) {
|
|
|
3927
4098
|
loading: "lazy"
|
|
3928
4099
|
}
|
|
3929
4100
|
) }),
|
|
3930
|
-
/* @__PURE__ */
|
|
3931
|
-
/* @__PURE__ */
|
|
4101
|
+
/* @__PURE__ */ jsxs9("div", { className: "lb-mix-match__filled-info", children: [
|
|
4102
|
+
/* @__PURE__ */ jsx9(
|
|
3932
4103
|
"button",
|
|
3933
4104
|
{
|
|
3934
4105
|
type: "button",
|
|
@@ -3937,15 +4108,15 @@ function MultiStepBundle(props) {
|
|
|
3937
4108
|
children: item.title
|
|
3938
4109
|
}
|
|
3939
4110
|
),
|
|
3940
|
-
item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */
|
|
3941
|
-
/* @__PURE__ */
|
|
3942
|
-
item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */
|
|
3943
|
-
/* @__PURE__ */
|
|
3944
|
-
/* @__PURE__ */
|
|
4111
|
+
item.variantTitle && item.variantTitle !== "Default Title" && /* @__PURE__ */ jsx9("span", { className: "lb-mix-match__filled-variant", children: item.variantTitle }),
|
|
4112
|
+
/* @__PURE__ */ jsxs9("span", { className: "lb-mix-match__filled-price", children: [
|
|
4113
|
+
item.compareAtPrice !== null && item.compareAtPrice > item.price && /* @__PURE__ */ jsx9("s", { className: "lb-mix-match__filled-compare", children: formatMoney7(item.compareAtPrice, currency) }),
|
|
4114
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-bundle-product-price", children: formatMoney7(item.price, currency) }),
|
|
4115
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-bundle-qty-inline", children: `\xD7${item.quantity}` })
|
|
3945
4116
|
] }),
|
|
3946
|
-
item.unitPrice && /* @__PURE__ */
|
|
4117
|
+
item.unitPrice && /* @__PURE__ */ jsx9("span", { className: "lb-bundle-product-unit-price", children: item.unitPrice })
|
|
3947
4118
|
] }),
|
|
3948
|
-
canRemoveItem2(bundle, selections, item) ? /* @__PURE__ */
|
|
4119
|
+
canRemoveItem2(bundle, selections, item) ? /* @__PURE__ */ jsx9(
|
|
3949
4120
|
"button",
|
|
3950
4121
|
{
|
|
3951
4122
|
type: "button",
|
|
@@ -3955,13 +4126,13 @@ function MultiStepBundle(props) {
|
|
|
3955
4126
|
e.stopPropagation();
|
|
3956
4127
|
removeSlot(i, index);
|
|
3957
4128
|
},
|
|
3958
|
-
children: /* @__PURE__ */
|
|
4129
|
+
children: /* @__PURE__ */ jsx9(CloseIcon4, {})
|
|
3959
4130
|
}
|
|
3960
4131
|
) : (
|
|
3961
4132
|
/* Required pick at its floor — quiet state chip instead
|
|
3962
4133
|
of the ×; removal returns once another slot covers
|
|
3963
4134
|
the product's minimum (variant swap flow). */
|
|
3964
|
-
/* @__PURE__ */
|
|
4135
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-mix-match__slot-required", children: "Required" })
|
|
3965
4136
|
)
|
|
3966
4137
|
]
|
|
3967
4138
|
},
|
|
@@ -3970,7 +4141,7 @@ function MultiStepBundle(props) {
|
|
|
3970
4141
|
))
|
|
3971
4142
|
}
|
|
3972
4143
|
),
|
|
3973
|
-
stepHeadroom2(step.maxQuantity, unitsByStep[i] ?? 0) !== 0 && /* @__PURE__ */
|
|
4144
|
+
stepHeadroom2(step.maxQuantity, unitsByStep[i] ?? 0) !== 0 && /* @__PURE__ */ jsxs9(
|
|
3974
4145
|
"button",
|
|
3975
4146
|
{
|
|
3976
4147
|
type: "button",
|
|
@@ -3979,15 +4150,15 @@ function MultiStepBundle(props) {
|
|
|
3979
4150
|
"aria-label": `${step.minQuantity === 1 && step.maxQuantity === 1 ? "Choose a product" : "Choose products"}: ${step.name}`,
|
|
3980
4151
|
onClick: () => setPickerOpenAt(i),
|
|
3981
4152
|
children: [
|
|
3982
|
-
/* @__PURE__ */
|
|
4153
|
+
/* @__PURE__ */ jsx9(
|
|
3983
4154
|
"span",
|
|
3984
4155
|
{
|
|
3985
4156
|
className: "lb-mix-match__add-product-icon",
|
|
3986
4157
|
"aria-hidden": "true",
|
|
3987
|
-
children: /* @__PURE__ */
|
|
4158
|
+
children: /* @__PURE__ */ jsx9(PlusIcon2, {})
|
|
3988
4159
|
}
|
|
3989
4160
|
),
|
|
3990
|
-
/* @__PURE__ */
|
|
4161
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-mix-match__add-product-label", children: step.minQuantity === 1 && step.maxQuantity === 1 ? "Choose a product" : "Choose products" })
|
|
3991
4162
|
]
|
|
3992
4163
|
}
|
|
3993
4164
|
)
|
|
@@ -3995,29 +4166,29 @@ function MultiStepBundle(props) {
|
|
|
3995
4166
|
},
|
|
3996
4167
|
i
|
|
3997
4168
|
)) }),
|
|
3998
|
-
/* @__PURE__ */
|
|
3999
|
-
allSatisfied && /* @__PURE__ */
|
|
4000
|
-
/* @__PURE__ */
|
|
4001
|
-
/* @__PURE__ */
|
|
4002
|
-
bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */
|
|
4169
|
+
/* @__PURE__ */ jsx9("div", { className: "lb-bundle-divider" }),
|
|
4170
|
+
allSatisfied && /* @__PURE__ */ jsxs9("div", { className: "lb-bundle-summary", "data-pricing-section": true, children: [
|
|
4171
|
+
/* @__PURE__ */ jsxs9("div", { className: "lb-bundle-summary__text", children: [
|
|
4172
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-bundle-summary__label", children: "Bundle total" }),
|
|
4173
|
+
bundle.widgetConfig.savingsBar.visible && summary.savings > 0 && /* @__PURE__ */ jsxs9("p", { className: "lb-bundle-savings-line", "data-savings-bar": true, children: [
|
|
4003
4174
|
"You save",
|
|
4004
4175
|
" ",
|
|
4005
|
-
/* @__PURE__ */
|
|
4176
|
+
/* @__PURE__ */ jsx9("span", { "data-savings-amount": true, children: formatMoney7(summary.savings, currency) }),
|
|
4006
4177
|
" ",
|
|
4007
|
-
/* @__PURE__ */
|
|
4178
|
+
/* @__PURE__ */ jsxs9("span", { "data-savings-percent": true, children: [
|
|
4008
4179
|
"(",
|
|
4009
4180
|
summary.savingsPercent,
|
|
4010
4181
|
"%)"
|
|
4011
4182
|
] })
|
|
4012
4183
|
] })
|
|
4013
4184
|
] }),
|
|
4014
|
-
/* @__PURE__ */
|
|
4015
|
-
bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */
|
|
4016
|
-
/* @__PURE__ */
|
|
4185
|
+
/* @__PURE__ */ jsxs9("span", { className: "lb-bundle-summary__prices", children: [
|
|
4186
|
+
bundle.widgetConfig.pricing.showComparePrice && summary.savings > 0 && /* @__PURE__ */ jsx9("span", { className: "lb-bundle-compare-price", "data-compare-price": true, children: formatMoney7(summary.comparePrice, currency) }),
|
|
4187
|
+
/* @__PURE__ */ jsx9("span", { className: "lb-bundle-sale-price", "data-sale-price": true, children: formatMoney7(summary.salePrice, currency) })
|
|
4017
4188
|
] })
|
|
4018
4189
|
] }),
|
|
4019
|
-
cartError && /* @__PURE__ */
|
|
4020
|
-
/* @__PURE__ */
|
|
4190
|
+
cartError && /* @__PURE__ */ jsx9("p", { className: "lb-bundle__error", role: "alert", children: cartError }),
|
|
4191
|
+
/* @__PURE__ */ jsx9(
|
|
4021
4192
|
"button",
|
|
4022
4193
|
{
|
|
4023
4194
|
className: "lb-bundle__cta",
|
|
@@ -4027,7 +4198,7 @@ function MultiStepBundle(props) {
|
|
|
4027
4198
|
children: ctaLabel
|
|
4028
4199
|
}
|
|
4029
4200
|
),
|
|
4030
|
-
pickerOpenAt !== null && /* @__PURE__ */
|
|
4201
|
+
pickerOpenAt !== null && /* @__PURE__ */ jsx9(
|
|
4031
4202
|
MultiStepPicker,
|
|
4032
4203
|
{
|
|
4033
4204
|
outOfStockBehavior,
|
|
@@ -4063,7 +4234,7 @@ function stepHasInStockProduct(bundle, stepIndex) {
|
|
|
4063
4234
|
});
|
|
4064
4235
|
}
|
|
4065
4236
|
function PlusIcon2() {
|
|
4066
|
-
return /* @__PURE__ */
|
|
4237
|
+
return /* @__PURE__ */ jsxs9(
|
|
4067
4238
|
"svg",
|
|
4068
4239
|
{
|
|
4069
4240
|
width: "18",
|
|
@@ -4073,14 +4244,14 @@ function PlusIcon2() {
|
|
|
4073
4244
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4074
4245
|
"aria-hidden": "true",
|
|
4075
4246
|
children: [
|
|
4076
|
-
/* @__PURE__ */
|
|
4077
|
-
/* @__PURE__ */
|
|
4247
|
+
/* @__PURE__ */ jsx9("line", { x1: "9", y1: "3", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
4248
|
+
/* @__PURE__ */ jsx9("line", { x1: "3", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
4078
4249
|
]
|
|
4079
4250
|
}
|
|
4080
4251
|
);
|
|
4081
4252
|
}
|
|
4082
4253
|
function CloseIcon4() {
|
|
4083
|
-
return /* @__PURE__ */
|
|
4254
|
+
return /* @__PURE__ */ jsxs9(
|
|
4084
4255
|
"svg",
|
|
4085
4256
|
{
|
|
4086
4257
|
width: "16",
|
|
@@ -4090,8 +4261,8 @@ function CloseIcon4() {
|
|
|
4090
4261
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4091
4262
|
"aria-hidden": "true",
|
|
4092
4263
|
children: [
|
|
4093
|
-
/* @__PURE__ */
|
|
4094
|
-
/* @__PURE__ */
|
|
4264
|
+
/* @__PURE__ */ jsx9("line", { x1: "5", y1: "5", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
4265
|
+
/* @__PURE__ */ jsx9("line", { x1: "15", y1: "5", x2: "5", y2: "15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
4095
4266
|
]
|
|
4096
4267
|
}
|
|
4097
4268
|
);
|
|
@@ -4104,7 +4275,7 @@ async function fetchShopCustomCss(options) {
|
|
|
4104
4275
|
}
|
|
4105
4276
|
|
|
4106
4277
|
// src/hooks/useBundlesForProduct.ts
|
|
4107
|
-
import { useState as
|
|
4278
|
+
import { useState as useState14, useEffect as useEffect17 } from "react";
|
|
4108
4279
|
import {
|
|
4109
4280
|
fetchBundlesForProduct,
|
|
4110
4281
|
injectCustomCss as injectCustomCss2
|
|
@@ -4115,10 +4286,10 @@ var INITIAL_STATE2 = {
|
|
|
4115
4286
|
error: null
|
|
4116
4287
|
};
|
|
4117
4288
|
function useBundlesForProduct(options) {
|
|
4118
|
-
const [state, setState] =
|
|
4289
|
+
const [state, setState] = useState14(
|
|
4119
4290
|
INITIAL_STATE2
|
|
4120
4291
|
);
|
|
4121
|
-
|
|
4292
|
+
useEffect17(() => {
|
|
4122
4293
|
const controller = new AbortController();
|
|
4123
4294
|
setState(INITIAL_STATE2);
|
|
4124
4295
|
fetchBundlesForProduct({
|
|
@@ -4200,6 +4371,7 @@ export {
|
|
|
4200
4371
|
BUNDLES_FOR_PRODUCT_QUERY,
|
|
4201
4372
|
BUNDLE_METAOBJECT_QUERY2 as BUNDLE_METAOBJECT_QUERY,
|
|
4202
4373
|
BogoBundle,
|
|
4374
|
+
BundleCountdown,
|
|
4203
4375
|
BundleParseError2 as BundleParseError,
|
|
4204
4376
|
DEFAULT_OUT_OF_STOCK_BEHAVIOR3 as DEFAULT_OUT_OF_STOCK_BEHAVIOR,
|
|
4205
4377
|
FixedBundle,
|