@lime-bundles/react 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +71 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +71 -30
- package/dist/index.js.map +1 -1
- package/docs/css-variables.md +7 -1
- package/docs/hydrogen.md +1 -1
- package/docs/react-nextjs.md +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1131,9 +1131,16 @@ function useFocusTrap({
|
|
|
1131
1131
|
|
|
1132
1132
|
// src/components/MixMatchPicker.tsx
|
|
1133
1133
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1134
|
-
function ruleFor(bundle, productId) {
|
|
1134
|
+
function ruleFor(bundle, productId, variantId) {
|
|
1135
|
+
if (variantId) {
|
|
1136
|
+
const vRule = bundle.variantRules[variantId];
|
|
1137
|
+
if (vRule) return vRule;
|
|
1138
|
+
}
|
|
1135
1139
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE;
|
|
1136
1140
|
}
|
|
1141
|
+
function variantRuleFor(bundle, variantId) {
|
|
1142
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
1143
|
+
}
|
|
1137
1144
|
function sanitizeId(gid) {
|
|
1138
1145
|
return gid.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
1139
1146
|
}
|
|
@@ -1438,6 +1445,8 @@ function MixMatchPickerRow({
|
|
|
1438
1445
|
const showPicker = variants.length > 1 && optionNames.length > 0;
|
|
1439
1446
|
const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
|
|
1440
1447
|
const currentVariant = selectedVariant ?? variants.find((v) => isVariantFulfillable2(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
|
|
1448
|
+
const vRule = ruleFor(bundle, product.id, currentVariant?.id);
|
|
1449
|
+
const variantMax = variantRuleFor(bundle, currentVariant?.id)?.max;
|
|
1441
1450
|
const alreadyInBundle = useMemo5(() => {
|
|
1442
1451
|
if (!currentVariant) return 0;
|
|
1443
1452
|
let sum = 0;
|
|
@@ -1465,22 +1474,26 @@ function MixMatchPickerRow({
|
|
|
1465
1474
|
return sum;
|
|
1466
1475
|
}, [selections, product.id, currentVariant]);
|
|
1467
1476
|
const swapUnits = currentVariant ? swapUnitsFor?.(product.id, currentVariant.id) ?? 0 : 0;
|
|
1468
|
-
const inSwapState = swapUnits >=
|
|
1469
|
-
const spotCeiling = inSwapState ? swapUnits : Math.min(
|
|
1477
|
+
const inSwapState = swapUnits >= vRule.min;
|
|
1478
|
+
const spotCeiling = inSwapState ? swapUnits : Math.min(
|
|
1479
|
+
rule.max - productOtherUnits,
|
|
1480
|
+
committedQty + remainingUnits,
|
|
1481
|
+
variantMax ?? Infinity
|
|
1482
|
+
);
|
|
1470
1483
|
const cap = currentVariant ? maxAddableQuantity(
|
|
1471
1484
|
currentVariant,
|
|
1472
1485
|
spotCeiling,
|
|
1473
1486
|
Math.max(0, alreadyInBundle - committedQty)
|
|
1474
1487
|
) : 0;
|
|
1475
|
-
const stepperMax = Math.max(
|
|
1476
|
-
const [qty, setQty] = useState7(
|
|
1488
|
+
const stepperMax = Math.max(vRule.min, cap);
|
|
1489
|
+
const [qty, setQty] = useState7(vRule.min);
|
|
1477
1490
|
useEffect10(() => {
|
|
1478
|
-
setQty((prev) => Math.max(
|
|
1479
|
-
}, [stepperMax,
|
|
1491
|
+
setQty((prev) => Math.max(vRule.min, Math.min(prev, stepperMax)));
|
|
1492
|
+
}, [stepperMax, vRule.min]);
|
|
1480
1493
|
const currentVariantId = currentVariant?.id ?? null;
|
|
1481
1494
|
useEffect10(() => {
|
|
1482
|
-
if (!variantInBundle) setQty(
|
|
1483
|
-
}, [variantInBundle, currentVariantId,
|
|
1495
|
+
if (!variantInBundle) setQty(vRule.min);
|
|
1496
|
+
}, [variantInBundle, currentVariantId, vRule.min]);
|
|
1484
1497
|
if (!currentVariant) return null;
|
|
1485
1498
|
const thumbImage = currentVariant.image ?? product.featuredImage ?? null;
|
|
1486
1499
|
const unitPriceText = formatUnitPrice2(
|
|
@@ -1488,8 +1501,8 @@ function MixMatchPickerRow({
|
|
|
1488
1501
|
currentVariant.unitPriceMeasurement,
|
|
1489
1502
|
currency
|
|
1490
1503
|
);
|
|
1491
|
-
const noStock = cap <
|
|
1492
|
-
const needsMoreSpots = !variantInBundle && !inSwapState &&
|
|
1504
|
+
const noStock = cap < vRule.min;
|
|
1505
|
+
const needsMoreSpots = !variantInBundle && !inSwapState && vRule.min > remainingUnits;
|
|
1493
1506
|
const addDisabled = !variantInBundle && (inSwapState ? noStock : atCapacity || noStock || needsMoreSpots);
|
|
1494
1507
|
const lockedRequired = variantInBundle && currentVariant != null && !(canRemoveVariant?.(currentVariant.id) ?? true);
|
|
1495
1508
|
const stepperDisabled = isOos || !variantInBundle && addDisabled;
|
|
@@ -1500,7 +1513,7 @@ function MixMatchPickerRow({
|
|
|
1500
1513
|
return;
|
|
1501
1514
|
}
|
|
1502
1515
|
if (!currentVariant || noStock) return;
|
|
1503
|
-
const pickedQty = showStepper ? qty :
|
|
1516
|
+
const pickedQty = showStepper ? qty : vRule.min;
|
|
1504
1517
|
const item = {
|
|
1505
1518
|
productId: product.id,
|
|
1506
1519
|
variantId: currentVariant.id,
|
|
@@ -1700,10 +1713,18 @@ function SearchClearIcon() {
|
|
|
1700
1713
|
|
|
1701
1714
|
// src/components/MixMatchBundle.tsx
|
|
1702
1715
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1703
|
-
function ruleFor2(bundle, productId) {
|
|
1716
|
+
function ruleFor2(bundle, productId, variantId) {
|
|
1717
|
+
if (variantId) {
|
|
1718
|
+
const vRule = bundle.variantRules[variantId];
|
|
1719
|
+
if (vRule) return vRule;
|
|
1720
|
+
}
|
|
1704
1721
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE2;
|
|
1705
1722
|
}
|
|
1723
|
+
function variantRuleFor2(bundle, variantId) {
|
|
1724
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
1725
|
+
}
|
|
1706
1726
|
function canRemoveItem(bundle, selections, item) {
|
|
1727
|
+
if (variantRuleFor2(bundle, item.variantId)?.required) return false;
|
|
1707
1728
|
const rule = ruleFor2(bundle, item.productId);
|
|
1708
1729
|
if (!rule.required) return true;
|
|
1709
1730
|
const unitsElsewhere = selections.filter((s) => s.productId === item.productId && s !== item).reduce((sum, s) => sum + s.quantity, 0);
|
|
@@ -2898,9 +2919,16 @@ import {
|
|
|
2898
2919
|
DEFAULT_PRODUCT_RULE as DEFAULT_PRODUCT_RULE3
|
|
2899
2920
|
} from "@lime-bundles/core";
|
|
2900
2921
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2901
|
-
function ruleFor3(bundle, productId) {
|
|
2922
|
+
function ruleFor3(bundle, productId, variantId) {
|
|
2923
|
+
if (variantId) {
|
|
2924
|
+
const vRule = bundle.variantRules[variantId];
|
|
2925
|
+
if (vRule) return vRule;
|
|
2926
|
+
}
|
|
2902
2927
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE3;
|
|
2903
2928
|
}
|
|
2929
|
+
function variantRuleFor3(bundle, variantId) {
|
|
2930
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
2931
|
+
}
|
|
2904
2932
|
function sanitizeId2(gid) {
|
|
2905
2933
|
return gid.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
2906
2934
|
}
|
|
@@ -3253,6 +3281,8 @@ function MultiStepPickerRow({
|
|
|
3253
3281
|
const showPicker = variants.length > 1 && optionNames.length > 0;
|
|
3254
3282
|
const { selectedValues, selectedVariant, setOptionValue, optionsFor } = useVariantSelection({ variants, optionNames });
|
|
3255
3283
|
const currentVariant = selectedVariant ?? variants.find((v) => isVariantFulfillable6(v, rule.min)) ?? eligible.firstAvailableVariant ?? variants[0] ?? null;
|
|
3284
|
+
const vRule = ruleFor3(bundle, product.id, currentVariant?.id);
|
|
3285
|
+
const variantMax = variantRuleFor3(bundle, currentVariant?.id)?.max;
|
|
3256
3286
|
const stepPicks = useMemo9(
|
|
3257
3287
|
() => selections[stepIndex] ?? [],
|
|
3258
3288
|
[selections, stepIndex]
|
|
@@ -3287,24 +3317,27 @@ function MultiStepPickerRow({
|
|
|
3287
3317
|
return Math.max(0, sum - committedQty);
|
|
3288
3318
|
}, [selections, currentVariant, committedQty]);
|
|
3289
3319
|
const swapUnits = currentVariant ? swapUnitsFor?.(stepIndex, product.id, currentVariant.id) ?? 0 : 0;
|
|
3290
|
-
const inSwapState = swapUnits >=
|
|
3320
|
+
const inSwapState = swapUnits >= vRule.min;
|
|
3291
3321
|
const room = stepHeadroom(step?.maxQuantity ?? null, unitsInStep);
|
|
3292
|
-
const productHeadroom =
|
|
3322
|
+
const productHeadroom = Math.min(
|
|
3323
|
+
rule.max - productOtherUnits,
|
|
3324
|
+
variantMax ?? Infinity
|
|
3325
|
+
);
|
|
3293
3326
|
const spotCeiling = inSwapState ? swapUnits : Math.min(
|
|
3294
3327
|
productHeadroom,
|
|
3295
3328
|
room === Number.POSITIVE_INFINITY ? productHeadroom : committedQty + room
|
|
3296
3329
|
);
|
|
3297
3330
|
const stockRemaining = currentVariant ? maxAddableQuantity2(currentVariant, Number.MAX_SAFE_INTEGER, variantOtherUnits) : 0;
|
|
3298
3331
|
const cap = Math.max(0, Math.min(spotCeiling, stockRemaining));
|
|
3299
|
-
const stepperMax = Math.max(
|
|
3300
|
-
const [qty, setQty] = useState11(
|
|
3332
|
+
const stepperMax = Math.max(vRule.min, cap);
|
|
3333
|
+
const [qty, setQty] = useState11(vRule.min);
|
|
3301
3334
|
useEffect14(() => {
|
|
3302
|
-
setQty((prev) => Math.max(
|
|
3303
|
-
}, [stepperMax,
|
|
3335
|
+
setQty((prev) => Math.max(vRule.min, Math.min(prev, stepperMax)));
|
|
3336
|
+
}, [stepperMax, vRule.min]);
|
|
3304
3337
|
const currentVariantId = currentVariant?.id ?? null;
|
|
3305
3338
|
useEffect14(() => {
|
|
3306
|
-
if (!variantInStep) setQty(
|
|
3307
|
-
}, [variantInStep, currentVariantId,
|
|
3339
|
+
if (!variantInStep) setQty(vRule.min);
|
|
3340
|
+
}, [variantInStep, currentVariantId, vRule.min]);
|
|
3308
3341
|
if (!currentVariant || !step) return null;
|
|
3309
3342
|
const thumbImage = currentVariant.image ?? product.featuredImage ?? null;
|
|
3310
3343
|
const unitPriceText = formatUnitPrice6(
|
|
@@ -3312,8 +3345,8 @@ function MultiStepPickerRow({
|
|
|
3312
3345
|
currentVariant.unitPriceMeasurement,
|
|
3313
3346
|
currency
|
|
3314
3347
|
);
|
|
3315
|
-
const noStock = cap <
|
|
3316
|
-
const needsMoreSpots = !variantInStep && !inSwapState && room !== Number.POSITIVE_INFINITY &&
|
|
3348
|
+
const noStock = cap < vRule.min;
|
|
3349
|
+
const needsMoreSpots = !variantInStep && !inSwapState && room !== Number.POSITIVE_INFINITY && vRule.min > room;
|
|
3317
3350
|
const addDisabled = !variantInStep && (inSwapState ? noStock : noStock || needsMoreSpots);
|
|
3318
3351
|
const lockedRequired = variantInStep && currentVariant != null && !(canRemoveVariant?.(currentVariant.id) ?? true);
|
|
3319
3352
|
const stepperDisabled = isOos || !variantInStep && addDisabled;
|
|
@@ -3324,7 +3357,7 @@ function MultiStepPickerRow({
|
|
|
3324
3357
|
return;
|
|
3325
3358
|
}
|
|
3326
3359
|
if (!currentVariant || noStock) return;
|
|
3327
|
-
const pickedQty = showStepper ? qty :
|
|
3360
|
+
const pickedQty = showStepper ? qty : vRule.min;
|
|
3328
3361
|
const item = {
|
|
3329
3362
|
productId: product.id,
|
|
3330
3363
|
variantId: currentVariant.id,
|
|
@@ -3409,7 +3442,7 @@ function MultiStepPickerRow({
|
|
|
3409
3442
|
);
|
|
3410
3443
|
}) }),
|
|
3411
3444
|
!showPicker && variants.length === 1 && currentVariant.title !== "Default Title" && /* @__PURE__ */ jsx7("span", { className: "lb-mix-match__filled-variant", children: currentVariant.title }),
|
|
3412
|
-
!isOos && needsMoreSpots && room > 0 && /* @__PURE__ */ jsx7("span", { className: "lb-mix-match__modal-needs-spots", children:
|
|
3445
|
+
!isOos && needsMoreSpots && room > 0 && /* @__PURE__ */ jsx7("span", { className: "lb-mix-match__modal-needs-spots", children: vRule.min === 1 ? "Needs 1 spot" : `Needs ${vRule.min} spots` }),
|
|
3413
3446
|
isOos ? /* @__PURE__ */ jsx7("span", { className: "lb-mix-match__modal-sold-out-label", children: "Sold out" }) : /* @__PURE__ */ jsxs7("div", { className: "lb-mix-match__modal-product-actions", children: [
|
|
3414
3447
|
showStepper && /* @__PURE__ */ jsx7("div", { className: "lb-bundle-variant-option-group lb-mix-match__qty-stepper-group", children: /* @__PURE__ */ jsxs7(
|
|
3415
3448
|
"div",
|
|
@@ -3424,17 +3457,17 @@ function MultiStepPickerRow({
|
|
|
3424
3457
|
type: "button",
|
|
3425
3458
|
className: "lb-mix-match__qty-stepper-button lb-mix-match__qty-stepper-button--minus",
|
|
3426
3459
|
"aria-label": "Decrease quantity",
|
|
3427
|
-
disabled: stepperDisabled || shownQty <=
|
|
3460
|
+
disabled: stepperDisabled || shownQty <= vRule.min,
|
|
3428
3461
|
onClick: () => {
|
|
3429
3462
|
if (variantInStep && currentVariant) {
|
|
3430
3463
|
onUpdateQuantity(
|
|
3431
3464
|
stepIndex,
|
|
3432
3465
|
product.id,
|
|
3433
3466
|
currentVariant.id,
|
|
3434
|
-
Math.max(
|
|
3467
|
+
Math.max(vRule.min, committedQty - 1)
|
|
3435
3468
|
);
|
|
3436
3469
|
} else {
|
|
3437
|
-
setQty((q) => Math.max(
|
|
3470
|
+
setQty((q) => Math.max(vRule.min, q - 1));
|
|
3438
3471
|
}
|
|
3439
3472
|
},
|
|
3440
3473
|
children: "\u2212"
|
|
@@ -3526,10 +3559,18 @@ function SearchClearIcon2() {
|
|
|
3526
3559
|
|
|
3527
3560
|
// src/components/MultiStepBundle.tsx
|
|
3528
3561
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3529
|
-
function ruleFor4(bundle, productId) {
|
|
3562
|
+
function ruleFor4(bundle, productId, variantId) {
|
|
3563
|
+
if (variantId) {
|
|
3564
|
+
const vRule = bundle.variantRules[variantId];
|
|
3565
|
+
if (vRule) return vRule;
|
|
3566
|
+
}
|
|
3530
3567
|
return bundle.productRules[productId] ?? DEFAULT_PRODUCT_RULE4;
|
|
3531
3568
|
}
|
|
3569
|
+
function variantRuleFor4(bundle, variantId) {
|
|
3570
|
+
return variantId ? bundle.variantRules[variantId] : void 0;
|
|
3571
|
+
}
|
|
3532
3572
|
function canRemoveItem2(bundle, selections, item) {
|
|
3573
|
+
if (variantRuleFor4(bundle, item.variantId)?.required) return false;
|
|
3533
3574
|
const rule = ruleFor4(bundle, item.productId);
|
|
3534
3575
|
if (!rule.required) return true;
|
|
3535
3576
|
let unitsElsewhere = 0;
|