@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.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 >= rule.min;
1469
- const spotCeiling = inSwapState ? swapUnits : Math.min(rule.max - productOtherUnits, committedQty + remainingUnits);
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(rule.min, cap);
1476
- const [qty, setQty] = useState7(rule.min);
1488
+ const stepperMax = Math.max(vRule.min, cap);
1489
+ const [qty, setQty] = useState7(vRule.min);
1477
1490
  useEffect10(() => {
1478
- setQty((prev) => Math.max(rule.min, Math.min(prev, stepperMax)));
1479
- }, [stepperMax, rule.min]);
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(rule.min);
1483
- }, [variantInBundle, currentVariantId, rule.min]);
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 < rule.min;
1492
- const needsMoreSpots = !variantInBundle && !inSwapState && rule.min > remainingUnits;
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 : rule.min;
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 >= rule.min;
3320
+ const inSwapState = swapUnits >= vRule.min;
3291
3321
  const room = stepHeadroom(step?.maxQuantity ?? null, unitsInStep);
3292
- const productHeadroom = rule.max - productOtherUnits;
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(rule.min, cap);
3300
- const [qty, setQty] = useState11(rule.min);
3332
+ const stepperMax = Math.max(vRule.min, cap);
3333
+ const [qty, setQty] = useState11(vRule.min);
3301
3334
  useEffect14(() => {
3302
- setQty((prev) => Math.max(rule.min, Math.min(prev, stepperMax)));
3303
- }, [stepperMax, rule.min]);
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(rule.min);
3307
- }, [variantInStep, currentVariantId, rule.min]);
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 < rule.min;
3316
- const needsMoreSpots = !variantInStep && !inSwapState && room !== Number.POSITIVE_INFINITY && rule.min > room;
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 : rule.min;
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: rule.min === 1 ? "Needs 1 spot" : `Needs ${rule.min} spots` }),
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 <= rule.min,
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(rule.min, committedQty - 1)
3467
+ Math.max(vRule.min, committedQty - 1)
3435
3468
  );
3436
3469
  } else {
3437
- setQty((q) => Math.max(rule.min, q - 1));
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;