@lime-bundles/widget 2.3.0 → 2.4.1
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 +435 -135
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +414 -115
- package/dist/index.js.map +1 -1
- package/dist/lime-bundle.global.js +115 -44
- package/dist/lime-bundle.global.js.map +1 -1
- package/docs/css-variables.md +6 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,12 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
LimeBundleElement: () => LimeBundleElement
|
|
23
|
+
LimeBundleElement: () => LimeBundleElement,
|
|
24
|
+
trackInputMode: () => trackInputMode
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(index_exports);
|
|
26
27
|
|
|
27
28
|
// src/lime-bundle.ts
|
|
28
|
-
var
|
|
29
|
+
var import_core6 = require("@lime-bundles/core");
|
|
29
30
|
|
|
30
31
|
// src/renderers/fixed.ts
|
|
31
32
|
var import_core4 = require("@lime-bundles/core");
|
|
@@ -211,12 +212,11 @@ function renderFixedBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
211
212
|
}
|
|
212
213
|
function buildRowState(bundle, product, productIndex) {
|
|
213
214
|
const selectedVariantIds = bundle.selectedVariantIds?.[productIndex] ?? null;
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
const
|
|
219
|
-
const selected = eligibleVariants[0] ?? null;
|
|
215
|
+
const merchantScoped = selectedVariantIds && selectedVariantIds.length > 0 ? product.variants.nodes.filter((v) => selectedVariantIds.includes(v.id)) : product.variants.nodes;
|
|
216
|
+
const firstInStock = merchantScoped.find((v) => v.availableForSale) ?? null;
|
|
217
|
+
const eligibleVariants = merchantScoped;
|
|
218
|
+
const isOos = !firstInStock;
|
|
219
|
+
const selected = firstInStock ?? merchantScoped[0] ?? null;
|
|
220
220
|
const qty = selected ? (0, import_core4.resolveBundleQty)(bundle, product.id, selected.id) : 1;
|
|
221
221
|
return { product, eligibleVariants, selected, qty, isOos };
|
|
222
222
|
}
|
|
@@ -365,32 +365,85 @@ function renderProductRow(state, currency, qtyFor, onVariantChange) {
|
|
|
365
365
|
};
|
|
366
366
|
applyVariantToRow(state.selected);
|
|
367
367
|
if (state.eligibleVariants.length > 1) {
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
select.setAttribute("data-variant-select", "");
|
|
371
|
-
select.setAttribute(
|
|
372
|
-
"aria-label",
|
|
373
|
-
`Select variant for ${state.product.title}`
|
|
368
|
+
const optionNames = state.eligibleVariants[0].selectedOptions.map(
|
|
369
|
+
(o) => o.name
|
|
374
370
|
);
|
|
375
|
-
state.
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
371
|
+
const productIdTail = state.product.id.replace(/^.*\//, "");
|
|
372
|
+
const optionSelects = [];
|
|
373
|
+
const resolveVariant = (values) => state.eligibleVariants.find(
|
|
374
|
+
(v) => v.selectedOptions.every((o, i) => o.value === values[i]) && v.selectedOptions.length === values.length
|
|
375
|
+
) ?? null;
|
|
376
|
+
const syncSelectsToVariant = (variant) => {
|
|
377
|
+
variant.selectedOptions.forEach((o, i) => {
|
|
378
|
+
const sel = optionSelects[i];
|
|
379
|
+
if (sel && sel.value !== o.value) sel.value = o.value;
|
|
380
|
+
});
|
|
381
|
+
};
|
|
382
|
+
const isValueAvailable = (optionIndex, value, selected) => state.eligibleVariants.some((v) => {
|
|
383
|
+
if (!v.availableForSale) return false;
|
|
384
|
+
if (v.selectedOptions[optionIndex]?.value !== value) return false;
|
|
385
|
+
return v.selectedOptions.every(
|
|
386
|
+
(o, i) => i === optionIndex || o.value === selected[i]
|
|
385
387
|
);
|
|
386
|
-
|
|
388
|
+
});
|
|
389
|
+
const recomputeDisabled = (selected) => {
|
|
390
|
+
optionSelects.forEach((sel, i) => {
|
|
391
|
+
Array.from(sel.options).forEach((opt) => {
|
|
392
|
+
opt.disabled = !isValueAvailable(i, opt.value, selected);
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
const handleChange = () => {
|
|
397
|
+
const values = optionSelects.map((s) => s.value);
|
|
398
|
+
const variant = resolveVariant(values);
|
|
399
|
+
if (!variant) {
|
|
400
|
+
if (state.selected) {
|
|
401
|
+
syncSelectsToVariant(state.selected);
|
|
402
|
+
recomputeDisabled(state.selected.selectedOptions.map((o) => o.value));
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
387
406
|
state.selected = variant;
|
|
388
407
|
state.qty = qtyFor(state.product.id, variant.id);
|
|
389
408
|
if (qtyBadgeRef) qtyBadgeRef.textContent = String(state.qty);
|
|
390
409
|
applyVariantToRow(variant);
|
|
410
|
+
recomputeDisabled(variant.selectedOptions.map((o) => o.value));
|
|
391
411
|
onVariantChange();
|
|
412
|
+
};
|
|
413
|
+
const groupsContainer = el("div", "lb-bundle-variant-option-groups");
|
|
414
|
+
optionNames.forEach((name2, position) => {
|
|
415
|
+
const group = el("div", "lb-bundle-variant-option-group");
|
|
416
|
+
const label = el("span", "lb-bundle-variant-option-label");
|
|
417
|
+
label.textContent = name2;
|
|
418
|
+
group.appendChild(label);
|
|
419
|
+
const select = document.createElement("select");
|
|
420
|
+
select.className = "lb-bundle-variant-select";
|
|
421
|
+
select.setAttribute("data-variant-option", "");
|
|
422
|
+
select.setAttribute("data-option-position", String(position + 1));
|
|
423
|
+
select.name = `lb-variant-${productIdTail}-${position + 1}`;
|
|
424
|
+
select.setAttribute("aria-label", name2);
|
|
425
|
+
const seen = /* @__PURE__ */ new Set();
|
|
426
|
+
state.eligibleVariants.forEach((v) => {
|
|
427
|
+
const value = v.selectedOptions[position]?.value;
|
|
428
|
+
if (!value || seen.has(value)) return;
|
|
429
|
+
seen.add(value);
|
|
430
|
+
const opt = document.createElement("option");
|
|
431
|
+
opt.value = value;
|
|
432
|
+
opt.textContent = value;
|
|
433
|
+
if (state.selected?.selectedOptions[position]?.value === value) {
|
|
434
|
+
opt.selected = true;
|
|
435
|
+
}
|
|
436
|
+
select.appendChild(opt);
|
|
437
|
+
});
|
|
438
|
+
select.addEventListener("change", handleChange);
|
|
439
|
+
optionSelects.push(select);
|
|
440
|
+
group.appendChild(select);
|
|
441
|
+
groupsContainer.appendChild(group);
|
|
392
442
|
});
|
|
393
|
-
info.appendChild(
|
|
443
|
+
info.appendChild(groupsContainer);
|
|
444
|
+
if (state.selected) {
|
|
445
|
+
recomputeDisabled(state.selected.selectedOptions.map((o) => o.value));
|
|
446
|
+
}
|
|
394
447
|
} else if (state.eligibleVariants.length === 1 && state.product.variants.nodes.length > 1) {
|
|
395
448
|
const badge = el("span", "lb-bundle-variant-badge");
|
|
396
449
|
badge.textContent = state.eligibleVariants[0].title;
|
|
@@ -479,6 +532,7 @@ function computeSale(totalCents, discount, rows) {
|
|
|
479
532
|
}
|
|
480
533
|
|
|
481
534
|
// src/renderers/mix-match.ts
|
|
535
|
+
var import_core5 = require("@lime-bundles/core");
|
|
482
536
|
var PLACEHOLDER_THUMB_SVG2 = `
|
|
483
537
|
<svg class="lb-bundle-placeholder-icon" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
|
|
484
538
|
<rect x="4" y="4" width="20" height="20" rx="3"></rect>
|
|
@@ -546,9 +600,6 @@ function renderMixMatchBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
546
600
|
showSearch: wc.showSearch,
|
|
547
601
|
onAdd: (product, variant) => addSelection(product, variant),
|
|
548
602
|
onRemove: (productId, variantId) => removeSelection(productId, variantId),
|
|
549
|
-
countFor: (productId, variantId) => selections.filter(
|
|
550
|
-
(s) => s.productId === productId && s.variantId === variantId
|
|
551
|
-
).length,
|
|
552
603
|
isOverMax: () => selections.length >= maxQty
|
|
553
604
|
});
|
|
554
605
|
root.appendChild(modal.el);
|
|
@@ -558,7 +609,7 @@ function renderMixMatchBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
558
609
|
if (cta.disabled) return;
|
|
559
610
|
const lines = selections.map((s) => ({
|
|
560
611
|
merchandiseId: s.variantId,
|
|
561
|
-
quantity:
|
|
612
|
+
quantity: s.quantity,
|
|
562
613
|
attributes: [
|
|
563
614
|
{ key: "_lime_bundle_gid", value: bundle.id },
|
|
564
615
|
{ key: "_lime_bundle_type", value: bundle.bundleType }
|
|
@@ -587,7 +638,13 @@ function renderMixMatchBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
587
638
|
variantTitle: firstVariant.title,
|
|
588
639
|
imageUrl: firstEligible.product.featuredImage?.url ?? null,
|
|
589
640
|
priceCents: (0, import_core.parseCents)(firstVariant.price.amount),
|
|
590
|
-
compareCents: firstVariant.compareAtPrice ? (0, import_core.parseCents)(firstVariant.compareAtPrice.amount) : null
|
|
641
|
+
compareCents: firstVariant.compareAtPrice ? (0, import_core.parseCents)(firstVariant.compareAtPrice.amount) : null,
|
|
642
|
+
unitPriceLabel: (0, import_core.formatUnitPrice)(
|
|
643
|
+
firstVariant.unitPrice,
|
|
644
|
+
firstVariant.unitPriceMeasurement,
|
|
645
|
+
currency
|
|
646
|
+
),
|
|
647
|
+
quantity: (0, import_core5.resolveBundleQty)(bundle, firstEligible.product.id, firstVariant.id)
|
|
591
648
|
});
|
|
592
649
|
}
|
|
593
650
|
afterMutation();
|
|
@@ -600,7 +657,13 @@ function renderMixMatchBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
600
657
|
variantTitle: variant.title,
|
|
601
658
|
imageUrl: product.featuredImage?.url ?? null,
|
|
602
659
|
priceCents: (0, import_core.parseCents)(variant.price.amount),
|
|
603
|
-
compareCents: variant.compareAtPrice ? (0, import_core.parseCents)(variant.compareAtPrice.amount) : null
|
|
660
|
+
compareCents: variant.compareAtPrice ? (0, import_core.parseCents)(variant.compareAtPrice.amount) : null,
|
|
661
|
+
unitPriceLabel: (0, import_core.formatUnitPrice)(
|
|
662
|
+
variant.unitPrice,
|
|
663
|
+
variant.unitPriceMeasurement,
|
|
664
|
+
currency
|
|
665
|
+
),
|
|
666
|
+
quantity: (0, import_core5.resolveBundleQty)(bundle, product.id, variant.id)
|
|
604
667
|
});
|
|
605
668
|
afterMutation();
|
|
606
669
|
}
|
|
@@ -767,6 +830,9 @@ function renderFilledSlot(selection, index, currency, onRemove) {
|
|
|
767
830
|
} else {
|
|
768
831
|
thumb.insertAdjacentHTML("beforeend", PLACEHOLDER_THUMB_SVG2);
|
|
769
832
|
}
|
|
833
|
+
const qtyBadge = el("span", "lb-bundle-qty-badge");
|
|
834
|
+
qtyBadge.textContent = String(selection.quantity);
|
|
835
|
+
thumb.appendChild(qtyBadge);
|
|
770
836
|
slot.appendChild(thumb);
|
|
771
837
|
const info = el("div", "lb-mix-match__filled-info");
|
|
772
838
|
const title = el("span", "lb-mix-match__filled-title");
|
|
@@ -777,16 +843,23 @@ function renderFilledSlot(selection, index, currency, onRemove) {
|
|
|
777
843
|
variant.textContent = selection.variantTitle;
|
|
778
844
|
info.appendChild(variant);
|
|
779
845
|
}
|
|
846
|
+
const linePrice = selection.priceCents * selection.quantity;
|
|
847
|
+
const lineCompare = selection.compareCents !== null ? selection.compareCents * selection.quantity : null;
|
|
780
848
|
const priceWrap = el("span", "lb-mix-match__filled-price");
|
|
781
|
-
if (
|
|
849
|
+
if (lineCompare !== null && lineCompare > linePrice) {
|
|
782
850
|
const compare = el("span", "lb-mix-match__filled-compare");
|
|
783
|
-
compare.textContent = (0, import_core.formatCents)(
|
|
851
|
+
compare.textContent = (0, import_core.formatCents)(lineCompare, currency);
|
|
784
852
|
priceWrap.appendChild(compare);
|
|
785
853
|
}
|
|
786
854
|
const priceEl = document.createElement("span");
|
|
787
|
-
priceEl.textContent = (0, import_core.formatCents)(
|
|
855
|
+
priceEl.textContent = (0, import_core.formatCents)(linePrice, currency);
|
|
788
856
|
priceWrap.appendChild(priceEl);
|
|
789
857
|
info.appendChild(priceWrap);
|
|
858
|
+
if (selection.unitPriceLabel) {
|
|
859
|
+
const unitPrice = el("span", "lb-bundle-product-unit-price");
|
|
860
|
+
unitPrice.textContent = selection.unitPriceLabel;
|
|
861
|
+
info.appendChild(unitPrice);
|
|
862
|
+
}
|
|
790
863
|
slot.appendChild(info);
|
|
791
864
|
const remove = document.createElement("button");
|
|
792
865
|
remove.type = "button";
|
|
@@ -820,7 +893,10 @@ function renderPricingSection(showCompareAtPrice) {
|
|
|
820
893
|
return;
|
|
821
894
|
}
|
|
822
895
|
wrap.style.display = "";
|
|
823
|
-
const totalCents = selections.reduce(
|
|
896
|
+
const totalCents = selections.reduce(
|
|
897
|
+
(s, sel) => s + sel.priceCents * sel.quantity,
|
|
898
|
+
0
|
|
899
|
+
);
|
|
824
900
|
const saleCents = (0, import_core.computeBundleSaleCents)(totalCents, bundle.discountConfig);
|
|
825
901
|
if (showCompareAtPrice && totalCents > saleCents) {
|
|
826
902
|
compare.textContent = (0, import_core.formatCents)(totalCents, currency);
|
|
@@ -847,7 +923,10 @@ function renderSavingsBar2() {
|
|
|
847
923
|
wrap.style.display = "none";
|
|
848
924
|
return;
|
|
849
925
|
}
|
|
850
|
-
const totalCents = selections.reduce(
|
|
926
|
+
const totalCents = selections.reduce(
|
|
927
|
+
(s, sel) => s + sel.priceCents * sel.quantity,
|
|
928
|
+
0
|
|
929
|
+
);
|
|
851
930
|
const saleCents = (0, import_core.computeBundleSaleCents)(totalCents, bundle.discountConfig);
|
|
852
931
|
const savings = Math.max(0, totalCents - saleCents);
|
|
853
932
|
if (savings <= 0) {
|
|
@@ -941,8 +1020,10 @@ function renderModal(bundle, eligible, currency, handlers) {
|
|
|
941
1020
|
rowsBuilt = true;
|
|
942
1021
|
list.innerHTML = "";
|
|
943
1022
|
eligible.forEach((ep) => {
|
|
944
|
-
const
|
|
945
|
-
|
|
1023
|
+
const availableVariants = ep.variants;
|
|
1024
|
+
const firstAvailVariant = ep.variants.find((v) => v.availableForSale) ?? ep.firstAvailableVariant ?? ep.variants[0];
|
|
1025
|
+
if (!firstAvailVariant) return;
|
|
1026
|
+
let currentVariant = firstAvailVariant;
|
|
946
1027
|
const productEl = el(
|
|
947
1028
|
"div",
|
|
948
1029
|
ep.isOos ? "lb-mix-match__modal-product lb-mix-match__modal-product--sold-out" : "lb-mix-match__modal-product",
|
|
@@ -964,26 +1045,147 @@ function renderModal(bundle, eligible, currency, handlers) {
|
|
|
964
1045
|
} else {
|
|
965
1046
|
thumb.insertAdjacentHTML("beforeend", PLACEHOLDER_THUMB_SVG2);
|
|
966
1047
|
}
|
|
1048
|
+
const countBadge = el("span", "lb-bundle-qty-badge");
|
|
1049
|
+
countBadge.textContent = String(
|
|
1050
|
+
(0, import_core5.resolveBundleQty)(bundle, ep.product.id, currentVariant.id)
|
|
1051
|
+
);
|
|
1052
|
+
thumb.appendChild(countBadge);
|
|
967
1053
|
productEl.appendChild(thumb);
|
|
968
1054
|
const info = el("div", "lb-mix-match__modal-product-info");
|
|
969
|
-
const title = el("
|
|
1055
|
+
const title = el("p", "lb-mix-match__modal-product-title");
|
|
970
1056
|
title.textContent = ep.product.title;
|
|
971
1057
|
info.appendChild(title);
|
|
972
|
-
const price = el("
|
|
973
|
-
price.textContent = (0, import_core.formatCents)(
|
|
1058
|
+
const price = el("p", "lb-mix-match__modal-product-price");
|
|
1059
|
+
price.textContent = (0, import_core.formatCents)(
|
|
1060
|
+
(0, import_core.parseCents)(currentVariant.price.amount) * (0, import_core5.resolveBundleQty)(bundle, ep.product.id, currentVariant.id),
|
|
1061
|
+
currency
|
|
1062
|
+
);
|
|
974
1063
|
info.appendChild(price);
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
|
|
1064
|
+
const unitPrice = el(
|
|
1065
|
+
"p",
|
|
1066
|
+
"lb-mix-match__modal-product-unit-price lb-bundle-product-unit-price"
|
|
1067
|
+
);
|
|
1068
|
+
const initialUnitText = (0, import_core.formatUnitPrice)(
|
|
1069
|
+
currentVariant.unitPrice,
|
|
1070
|
+
currentVariant.unitPriceMeasurement,
|
|
978
1071
|
currency
|
|
979
1072
|
);
|
|
980
|
-
if (
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1073
|
+
if (initialUnitText) {
|
|
1074
|
+
unitPrice.textContent = initialUnitText;
|
|
1075
|
+
} else {
|
|
1076
|
+
unitPrice.hidden = true;
|
|
1077
|
+
}
|
|
1078
|
+
info.appendChild(unitPrice);
|
|
1079
|
+
const row = {
|
|
1080
|
+
el: productEl,
|
|
1081
|
+
product: ep.product,
|
|
1082
|
+
variant: firstAvailVariant,
|
|
1083
|
+
updateCount: () => {
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
if (availableVariants.length > 1) {
|
|
1087
|
+
const optionNames = availableVariants[0].selectedOptions.map(
|
|
1088
|
+
(o) => o.name
|
|
984
1089
|
);
|
|
985
|
-
|
|
986
|
-
|
|
1090
|
+
const productIdTail = ep.product.id.replace(/^.*\//, "");
|
|
1091
|
+
const optionSelects = [];
|
|
1092
|
+
const resolveVariant = (values) => availableVariants.find(
|
|
1093
|
+
(v) => v.selectedOptions.length === values.length && v.selectedOptions.every((o, i) => o.value === values[i])
|
|
1094
|
+
) ?? null;
|
|
1095
|
+
const syncSelectsToVariant = (v) => {
|
|
1096
|
+
v.selectedOptions.forEach((o, i) => {
|
|
1097
|
+
const sel = optionSelects[i];
|
|
1098
|
+
if (sel && sel.value !== o.value) sel.value = o.value;
|
|
1099
|
+
});
|
|
1100
|
+
};
|
|
1101
|
+
const isValueAvailable = (optionIndex, value, selected) => availableVariants.some((v) => {
|
|
1102
|
+
if (!v.availableForSale) return false;
|
|
1103
|
+
if (v.selectedOptions[optionIndex]?.value !== value) return false;
|
|
1104
|
+
return v.selectedOptions.every(
|
|
1105
|
+
(o, i) => i === optionIndex || o.value === selected[i]
|
|
1106
|
+
);
|
|
1107
|
+
});
|
|
1108
|
+
const recomputeDisabled = (selected) => {
|
|
1109
|
+
optionSelects.forEach((sel, i) => {
|
|
1110
|
+
Array.from(sel.options).forEach((opt) => {
|
|
1111
|
+
opt.disabled = !isValueAvailable(i, opt.value, selected);
|
|
1112
|
+
});
|
|
1113
|
+
});
|
|
1114
|
+
};
|
|
1115
|
+
const handleChange = () => {
|
|
1116
|
+
const values = optionSelects.map((s) => s.value);
|
|
1117
|
+
const next = resolveVariant(values);
|
|
1118
|
+
if (!next) {
|
|
1119
|
+
syncSelectsToVariant(currentVariant);
|
|
1120
|
+
recomputeDisabled(
|
|
1121
|
+
currentVariant.selectedOptions.map((o) => o.value)
|
|
1122
|
+
);
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
currentVariant = next;
|
|
1126
|
+
row.variant = next;
|
|
1127
|
+
const nextQty = (0, import_core5.resolveBundleQty)(
|
|
1128
|
+
bundle,
|
|
1129
|
+
ep.product.id,
|
|
1130
|
+
currentVariant.id
|
|
1131
|
+
);
|
|
1132
|
+
price.textContent = (0, import_core.formatCents)(
|
|
1133
|
+
(0, import_core.parseCents)(currentVariant.price.amount) * nextQty,
|
|
1134
|
+
currency
|
|
1135
|
+
);
|
|
1136
|
+
const nextUnitText = (0, import_core.formatUnitPrice)(
|
|
1137
|
+
currentVariant.unitPrice,
|
|
1138
|
+
currentVariant.unitPriceMeasurement,
|
|
1139
|
+
currency
|
|
1140
|
+
);
|
|
1141
|
+
if (nextUnitText) {
|
|
1142
|
+
unitPrice.textContent = nextUnitText;
|
|
1143
|
+
unitPrice.hidden = false;
|
|
1144
|
+
} else {
|
|
1145
|
+
unitPrice.textContent = "";
|
|
1146
|
+
unitPrice.hidden = true;
|
|
1147
|
+
}
|
|
1148
|
+
recomputeDisabled(next.selectedOptions.map((o) => o.value));
|
|
1149
|
+
rowUpdateCount();
|
|
1150
|
+
};
|
|
1151
|
+
const groupsContainer = el("div", "lb-bundle-variant-option-groups");
|
|
1152
|
+
optionNames.forEach((name, position) => {
|
|
1153
|
+
const group = el("div", "lb-bundle-variant-option-group");
|
|
1154
|
+
const label = el("span", "lb-bundle-variant-option-label");
|
|
1155
|
+
label.textContent = name;
|
|
1156
|
+
group.appendChild(label);
|
|
1157
|
+
const select = document.createElement("select");
|
|
1158
|
+
select.className = "lb-mix-match__variant-select";
|
|
1159
|
+
select.setAttribute("data-variant-option", "");
|
|
1160
|
+
select.setAttribute("data-option-position", String(position + 1));
|
|
1161
|
+
select.name = `lb-variant-${productIdTail}-${position + 1}`;
|
|
1162
|
+
select.setAttribute("aria-label", name);
|
|
1163
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1164
|
+
availableVariants.forEach((v) => {
|
|
1165
|
+
const value = v.selectedOptions[position]?.value;
|
|
1166
|
+
if (!value || seen.has(value)) return;
|
|
1167
|
+
seen.add(value);
|
|
1168
|
+
const opt = document.createElement("option");
|
|
1169
|
+
opt.value = value;
|
|
1170
|
+
opt.textContent = value;
|
|
1171
|
+
if (firstAvailVariant.selectedOptions[position]?.value === value) {
|
|
1172
|
+
opt.selected = true;
|
|
1173
|
+
}
|
|
1174
|
+
select.appendChild(opt);
|
|
1175
|
+
});
|
|
1176
|
+
select.addEventListener("change", handleChange);
|
|
1177
|
+
optionSelects.push(select);
|
|
1178
|
+
group.appendChild(select);
|
|
1179
|
+
groupsContainer.appendChild(group);
|
|
1180
|
+
});
|
|
1181
|
+
info.appendChild(groupsContainer);
|
|
1182
|
+
recomputeDisabled(
|
|
1183
|
+
firstAvailVariant.selectedOptions.map((o) => o.value)
|
|
1184
|
+
);
|
|
1185
|
+
} else if (availableVariants.length === 1 && firstAvailVariant.title !== "Default Title") {
|
|
1186
|
+
const variantLabel = el("span", "lb-mix-match__filled-variant");
|
|
1187
|
+
variantLabel.textContent = firstAvailVariant.title;
|
|
1188
|
+
info.appendChild(variantLabel);
|
|
987
1189
|
}
|
|
988
1190
|
if (ep.isOos) {
|
|
989
1191
|
const soldOut = el("span", "lb-mix-match__modal-sold-out-label");
|
|
@@ -991,56 +1193,26 @@ function renderModal(bundle, eligible, currency, handlers) {
|
|
|
991
1193
|
info.appendChild(soldOut);
|
|
992
1194
|
}
|
|
993
1195
|
productEl.appendChild(info);
|
|
1196
|
+
const rowUpdateCount = () => {
|
|
1197
|
+
countBadge.textContent = String(
|
|
1198
|
+
(0, import_core5.resolveBundleQty)(bundle, ep.product.id, currentVariant.id)
|
|
1199
|
+
);
|
|
1200
|
+
};
|
|
994
1201
|
if (!ep.isOos) {
|
|
995
1202
|
const addBtn = document.createElement("button");
|
|
996
1203
|
addBtn.type = "button";
|
|
997
1204
|
addBtn.className = "lb-mix-match__modal-add";
|
|
998
|
-
addBtn.
|
|
999
|
-
addBtn.innerHTML = PLUS_ICON_SVG;
|
|
1000
|
-
const countBadge = el("span", "lb-bundle-qty-badge");
|
|
1001
|
-
countBadge.style.display = "none";
|
|
1002
|
-
addBtn.appendChild(countBadge);
|
|
1205
|
+
addBtn.textContent = "Add";
|
|
1003
1206
|
addBtn.addEventListener("click", () => {
|
|
1004
1207
|
if (handlers.isOverMax()) return;
|
|
1005
|
-
handlers.onAdd(ep.product,
|
|
1208
|
+
handlers.onAdd(ep.product, currentVariant);
|
|
1209
|
+
close();
|
|
1006
1210
|
});
|
|
1007
1211
|
productEl.appendChild(addBtn);
|
|
1008
|
-
const removeBtn = document.createElement("button");
|
|
1009
|
-
removeBtn.type = "button";
|
|
1010
|
-
removeBtn.className = "lb-mix-match__slot-remove";
|
|
1011
|
-
removeBtn.setAttribute("aria-label", `Remove one ${ep.product.title}`);
|
|
1012
|
-
removeBtn.style.display = "none";
|
|
1013
|
-
removeBtn.innerHTML = CLOSE_ICON_SVG;
|
|
1014
|
-
removeBtn.addEventListener("click", (e) => {
|
|
1015
|
-
e.stopPropagation();
|
|
1016
|
-
handlers.onRemove(ep.product.id, variant.id);
|
|
1017
|
-
});
|
|
1018
|
-
productEl.appendChild(removeBtn);
|
|
1019
|
-
productRows.push({
|
|
1020
|
-
el: productEl,
|
|
1021
|
-
product: ep.product,
|
|
1022
|
-
variant,
|
|
1023
|
-
updateCount: () => {
|
|
1024
|
-
const count = handlers.countFor(ep.product.id, variant.id);
|
|
1025
|
-
if (count > 0) {
|
|
1026
|
-
countBadge.textContent = String(count);
|
|
1027
|
-
countBadge.style.display = "";
|
|
1028
|
-
removeBtn.style.display = "";
|
|
1029
|
-
} else {
|
|
1030
|
-
countBadge.style.display = "none";
|
|
1031
|
-
removeBtn.style.display = "none";
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1035
|
-
} else {
|
|
1036
|
-
productRows.push({
|
|
1037
|
-
el: productEl,
|
|
1038
|
-
product: ep.product,
|
|
1039
|
-
variant,
|
|
1040
|
-
updateCount: () => {
|
|
1041
|
-
}
|
|
1042
|
-
});
|
|
1043
1212
|
}
|
|
1213
|
+
row.updateCount = ep.isOos ? () => {
|
|
1214
|
+
} : rowUpdateCount;
|
|
1215
|
+
productRows.push(row);
|
|
1044
1216
|
list.appendChild(productEl);
|
|
1045
1217
|
});
|
|
1046
1218
|
refreshCounts();
|
|
@@ -1438,7 +1610,62 @@ function clamp(n, min, max) {
|
|
|
1438
1610
|
}
|
|
1439
1611
|
|
|
1440
1612
|
// src/lime-bundle.ts
|
|
1441
|
-
var
|
|
1613
|
+
var import_core7 = require("@lime-bundles/core");
|
|
1614
|
+
|
|
1615
|
+
// src/utils/input-mode.ts
|
|
1616
|
+
var NAV_KEYS = /* @__PURE__ */ new Set([
|
|
1617
|
+
"Tab",
|
|
1618
|
+
"ArrowUp",
|
|
1619
|
+
"ArrowDown",
|
|
1620
|
+
"ArrowLeft",
|
|
1621
|
+
"ArrowRight",
|
|
1622
|
+
"Home",
|
|
1623
|
+
"End",
|
|
1624
|
+
"PageUp",
|
|
1625
|
+
"PageDown",
|
|
1626
|
+
"Enter",
|
|
1627
|
+
" ",
|
|
1628
|
+
"Escape"
|
|
1629
|
+
]);
|
|
1630
|
+
var targets = /* @__PURE__ */ new Set();
|
|
1631
|
+
var listenersAttached = false;
|
|
1632
|
+
function setAll(on) {
|
|
1633
|
+
const off = on === "using-mouse" ? "using-keyboard" : "using-mouse";
|
|
1634
|
+
for (const el2 of targets) {
|
|
1635
|
+
el2.classList.add(on);
|
|
1636
|
+
el2.classList.remove(off);
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
function onKeyDown(e) {
|
|
1640
|
+
if (NAV_KEYS.has(e.key)) setAll("using-keyboard");
|
|
1641
|
+
}
|
|
1642
|
+
function onPointerDown() {
|
|
1643
|
+
setAll("using-mouse");
|
|
1644
|
+
}
|
|
1645
|
+
function attachListeners() {
|
|
1646
|
+
if (listenersAttached) return;
|
|
1647
|
+
listenersAttached = true;
|
|
1648
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
1649
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
1650
|
+
}
|
|
1651
|
+
function detachListeners() {
|
|
1652
|
+
if (!listenersAttached) return;
|
|
1653
|
+
listenersAttached = false;
|
|
1654
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
1655
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
1656
|
+
}
|
|
1657
|
+
function trackInputMode(target) {
|
|
1658
|
+
target.classList.add("using-mouse");
|
|
1659
|
+
target.classList.remove("using-keyboard");
|
|
1660
|
+
targets.add(target);
|
|
1661
|
+
attachListeners();
|
|
1662
|
+
return () => {
|
|
1663
|
+
targets.delete(target);
|
|
1664
|
+
target.classList.remove("using-mouse");
|
|
1665
|
+
target.classList.remove("using-keyboard");
|
|
1666
|
+
if (targets.size === 0) detachListeners();
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1442
1669
|
|
|
1443
1670
|
// src/styles/bundle-css.ts
|
|
1444
1671
|
var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle widget types */
|
|
@@ -1611,15 +1838,18 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1611
1838
|
/* Product rows */
|
|
1612
1839
|
.lb-bundle-product-row {
|
|
1613
1840
|
display: flex;
|
|
1614
|
-
gap:
|
|
1841
|
+
gap: 20px;
|
|
1615
1842
|
padding: 12px 0;
|
|
1616
1843
|
}
|
|
1617
1844
|
|
|
1618
1845
|
.lb-bundle-thumbnail {
|
|
1619
1846
|
position: relative;
|
|
1620
1847
|
width: 48px;
|
|
1621
|
-
height: 48px;
|
|
1622
1848
|
min-width: 48px;
|
|
1849
|
+
/* Aspect-ratio comes from the merchant \`thumbnailRatio\` enum via Liquid;
|
|
1850
|
+
"original" sets it to \`auto\` so the box sizes to the image's intrinsic
|
|
1851
|
+
ratio. Default keeps the historical 1:1 behaviour. */
|
|
1852
|
+
aspect-ratio: var(--lb-thumbnail-aspect-ratio, 1 / 1);
|
|
1623
1853
|
background: var(--lb-thumbnail-bg);
|
|
1624
1854
|
border-radius: 8px;
|
|
1625
1855
|
overflow: hidden;
|
|
@@ -1630,8 +1860,10 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1630
1860
|
|
|
1631
1861
|
.lb-bundle-thumbnail img {
|
|
1632
1862
|
width: 100%;
|
|
1633
|
-
|
|
1634
|
-
|
|
1863
|
+
/* Height + fit come from the same merchant enum; "original" sets them to
|
|
1864
|
+
\`auto\` / \`contain\` so the image renders uncropped at intrinsic ratio. */
|
|
1865
|
+
height: var(--lb-thumbnail-img-height, 100%);
|
|
1866
|
+
object-fit: var(--lb-thumbnail-img-fit, cover);
|
|
1635
1867
|
}
|
|
1636
1868
|
|
|
1637
1869
|
.lb-bundle-thumbnail svg {
|
|
@@ -1662,7 +1894,7 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1662
1894
|
.lb-bundle-product-price {
|
|
1663
1895
|
/* --lb-product-price-display fallback is the "on" branch; Liquid sets 'none' when merchant disables. */
|
|
1664
1896
|
display: var(--lb-product-price-display, block);
|
|
1665
|
-
font-size:
|
|
1897
|
+
font-size: 14px;
|
|
1666
1898
|
font-weight: 400;
|
|
1667
1899
|
line-height: 20px;
|
|
1668
1900
|
color: var(--lb-text);
|
|
@@ -1679,7 +1911,7 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1679
1911
|
.lb-bundle-product-compare-price {
|
|
1680
1912
|
/* --lb-product-compare-display fallback is the "on" branch; Liquid sets 'none' when merchant disables. */
|
|
1681
1913
|
display: var(--lb-product-compare-display, inline);
|
|
1682
|
-
font-size:
|
|
1914
|
+
font-size: 14px;
|
|
1683
1915
|
font-weight: 400;
|
|
1684
1916
|
line-height: 20px;
|
|
1685
1917
|
color: color-mix(in srgb, var(--lb-text) 60%, transparent);
|
|
@@ -1698,7 +1930,7 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1698
1930
|
secondary text beneath the price row so it doesn't compete visually. */
|
|
1699
1931
|
.lb-bundle-product-unit-price {
|
|
1700
1932
|
display: block;
|
|
1701
|
-
font-size:
|
|
1933
|
+
font-size: 12px;
|
|
1702
1934
|
line-height: 16px;
|
|
1703
1935
|
color: color-mix(in srgb, var(--lb-text) 60%, transparent);
|
|
1704
1936
|
margin-top: 2px;
|
|
@@ -1719,6 +1951,56 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1719
1951
|
margin-top: 8px;
|
|
1720
1952
|
}
|
|
1721
1953
|
|
|
1954
|
+
/* Per-option variant pickers. Each option's label + select sit inside a
|
|
1955
|
+
.lb-bundle-variant-option-group (flex column, 2px gap between label and
|
|
1956
|
+
select); the groups stack inside a .lb-bundle-variant-option-groups
|
|
1957
|
+
parent (flex column, 12px gap between groups). The parent owns the top
|
|
1958
|
+
offset from the preceding unit-price line, so individual labels and
|
|
1959
|
+
selects don't carry their own vertical margins. */
|
|
1960
|
+
.lb-bundle-variant-option-groups {
|
|
1961
|
+
display: flex;
|
|
1962
|
+
flex-direction: column;
|
|
1963
|
+
gap: 12px;
|
|
1964
|
+
margin-top: 8px;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
.lb-bundle-variant-option-group {
|
|
1968
|
+
display: flex;
|
|
1969
|
+
flex-direction: column;
|
|
1970
|
+
gap: 2px;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
.lb-bundle-variant-option-label {
|
|
1974
|
+
display: block;
|
|
1975
|
+
margin: 0;
|
|
1976
|
+
font-size: 12px;
|
|
1977
|
+
line-height: 16px;
|
|
1978
|
+
font-weight: 600;
|
|
1979
|
+
letter-spacing: 0.05em;
|
|
1980
|
+
text-transform: uppercase;
|
|
1981
|
+
color: color-mix(in srgb, var(--lb-text) 60%, transparent);
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
.lb-mix-match__modal-product-info .lb-bundle-variant-option-groups {
|
|
1985
|
+
margin-top: 4px;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/* Focus-ring suppression for mouse users. A small JS helper \u2014 see
|
|
1989
|
+
packages/widget/src/utils/input-mode.ts and bundle-widget.js \u2014 toggles
|
|
1990
|
+
.using-mouse / .using-keyboard on the widget root (or html in the Liquid
|
|
1991
|
+
path) based on the customer's current input device. Default is mouse, so
|
|
1992
|
+
click-to-focus doesn't leave a keyboard-style ring. The modal overlay
|
|
1993
|
+
gets its own selector because the Liquid path reparents it to body,
|
|
1994
|
+
outside the widget root. */
|
|
1995
|
+
.using-mouse .lb-bundle-widget :focus,
|
|
1996
|
+
.using-mouse .lb-bundle-widget :focus-visible,
|
|
1997
|
+
.using-mouse .lb-mix-match__modal-overlay :focus,
|
|
1998
|
+
.using-mouse .lb-mix-match__modal-overlay :focus-visible {
|
|
1999
|
+
outline: none;
|
|
2000
|
+
outline-offset: 0;
|
|
2001
|
+
box-shadow: none;
|
|
2002
|
+
}
|
|
2003
|
+
|
|
1722
2004
|
.lb-bundle-quantity {
|
|
1723
2005
|
font-size: 12px;
|
|
1724
2006
|
line-height: 16px;
|
|
@@ -1821,7 +2103,7 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
|
|
|
1821
2103
|
grid-template-rows: 1fr;
|
|
1822
2104
|
grid-template-columns: 1fr;
|
|
1823
2105
|
width: 100%;
|
|
1824
|
-
padding: 16px;
|
|
2106
|
+
padding: 12px 16px;
|
|
1825
2107
|
border: var(--lb-cta-border-width) solid var(--lb-cta-border-color);
|
|
1826
2108
|
border-radius: var(--lb-cta-radius);
|
|
1827
2109
|
font-size: 16px;
|
|
@@ -1956,14 +2238,14 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
|
|
|
1956
2238
|
|
|
1957
2239
|
/* Fixed bundles: product rows */
|
|
1958
2240
|
.lb-fixed .lb-bundle-product-row {
|
|
1959
|
-
gap:
|
|
2241
|
+
gap: 20px;
|
|
1960
2242
|
align-items: center;
|
|
1961
2243
|
}
|
|
1962
2244
|
|
|
1963
|
-
/* Fixed bundles: larger thumbnails
|
|
2245
|
+
/* Fixed bundles: larger thumbnails. Height comes from --lb-thumbnail-aspect-ratio
|
|
2246
|
+
(set on .lb-bundle-widget via Liquid / applyWidgetConfigVars). */
|
|
1964
2247
|
.lb-fixed .lb-bundle-thumbnail {
|
|
1965
2248
|
width: 60px;
|
|
1966
|
-
height: 60px;
|
|
1967
2249
|
min-width: 60px;
|
|
1968
2250
|
border-radius: var(--lb-image-border-radius);
|
|
1969
2251
|
border: var(--lb-image-border-width) solid var(--lb-image-border-color);
|
|
@@ -1976,9 +2258,10 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
|
|
|
1976
2258
|
border: none;
|
|
1977
2259
|
}
|
|
1978
2260
|
|
|
1979
|
-
/* Variant picker select \u2014 styled to match the variant badge aesthetic
|
|
2261
|
+
/* Variant picker select \u2014 styled to match the variant badge aesthetic.
|
|
2262
|
+
Sits inside .lb-bundle-variant-option-group so vertical spacing is owned
|
|
2263
|
+
by the group/groups flex gap, not the select itself. */
|
|
1980
2264
|
.lb-bundle-variant-select {
|
|
1981
|
-
margin-top: 8px;
|
|
1982
2265
|
display: inline-block;
|
|
1983
2266
|
border: var(--lb-variant-border-width) solid var(--lb-variant-border-color);
|
|
1984
2267
|
border-radius: var(--lb-variant-radius);
|
|
@@ -1995,7 +2278,8 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
|
|
|
1995
2278
|
background-repeat: no-repeat;
|
|
1996
2279
|
background-position: right 8px center;
|
|
1997
2280
|
background-size: 12px;
|
|
1998
|
-
|
|
2281
|
+
width: 50%;
|
|
2282
|
+
max-width: 50%;
|
|
1999
2283
|
}
|
|
2000
2284
|
|
|
2001
2285
|
.lb-bundle-variant-select:focus-visible {
|
|
@@ -2064,7 +2348,10 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2064
2348
|
width: 60px;
|
|
2065
2349
|
height: 60px;
|
|
2066
2350
|
min-width: 60px;
|
|
2067
|
-
border
|
|
2351
|
+
/* 2px border is intentionally independent of --lb-image-border-width \u2014
|
|
2352
|
+
empty slots always need a visible dashed outline as an affordance,
|
|
2353
|
+
regardless of how the merchant has styled populated thumbnails. */
|
|
2354
|
+
border: 2px dashed color-mix(in srgb, var(--lb-text) 35%, transparent);
|
|
2068
2355
|
border-radius: var(--lb-image-border-radius);
|
|
2069
2356
|
box-sizing: border-box;
|
|
2070
2357
|
display: flex;
|
|
@@ -2084,9 +2371,10 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2084
2371
|
cursor: default;
|
|
2085
2372
|
}
|
|
2086
2373
|
|
|
2374
|
+
/* Mix-match thumbnails. Height comes from --lb-thumbnail-aspect-ratio
|
|
2375
|
+
(set on .lb-bundle-widget via Liquid / applyWidgetConfigVars). */
|
|
2087
2376
|
.lb-mix-match .lb-bundle-thumbnail {
|
|
2088
2377
|
width: 60px;
|
|
2089
|
-
height: 60px;
|
|
2090
2378
|
min-width: 60px;
|
|
2091
2379
|
border-radius: var(--lb-image-border-radius);
|
|
2092
2380
|
border: var(--lb-image-border-width) solid var(--lb-image-border-color);
|
|
@@ -2321,7 +2609,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2321
2609
|
.lb-mix-match__modal-product {
|
|
2322
2610
|
display: flex;
|
|
2323
2611
|
align-items: center;
|
|
2324
|
-
gap:
|
|
2612
|
+
gap: 20px;
|
|
2325
2613
|
padding: 12px 0;
|
|
2326
2614
|
border-bottom: 1px solid color-mix(in srgb, var(--lb-picker-text) 7%, transparent);
|
|
2327
2615
|
}
|
|
@@ -2333,8 +2621,11 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2333
2621
|
.lb-mix-match__modal-product-thumb {
|
|
2334
2622
|
position: relative;
|
|
2335
2623
|
width: 48px;
|
|
2336
|
-
height: 48px;
|
|
2337
2624
|
min-width: 48px;
|
|
2625
|
+
/* Modal picker thumbs follow the merchant's pickerThumbnailRatio \u2014
|
|
2626
|
+
independent from the main widget's thumbnailRatio so a merchant can
|
|
2627
|
+
e.g. show tall picker thumbs with square main thumbs. */
|
|
2628
|
+
aspect-ratio: var(--lb-picker-thumbnail-aspect-ratio, 1 / 1);
|
|
2338
2629
|
border-radius: var(--lb-picker-product-radius);
|
|
2339
2630
|
border: var(--lb-picker-product-border-width) solid var(--lb-picker-product-border-color);
|
|
2340
2631
|
box-sizing: border-box;
|
|
@@ -2355,8 +2646,10 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2355
2646
|
|
|
2356
2647
|
.lb-mix-match__modal-product-thumb img {
|
|
2357
2648
|
width: 100%;
|
|
2358
|
-
|
|
2359
|
-
|
|
2649
|
+
/* Height + fit come from pickerThumbnailRatio \u2014 "original" sets both
|
|
2650
|
+
to auto/contain so the image renders uncropped at intrinsic ratio. */
|
|
2651
|
+
height: var(--lb-picker-thumbnail-img-height, 100%);
|
|
2652
|
+
object-fit: var(--lb-picker-thumbnail-img-fit, cover);
|
|
2360
2653
|
border-radius: max(0px, calc(var(--lb-picker-product-radius) - var(--lb-picker-product-border-width)));
|
|
2361
2654
|
}
|
|
2362
2655
|
|
|
@@ -2393,7 +2686,6 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2393
2686
|
|
|
2394
2687
|
.lb-mix-match__variant-select {
|
|
2395
2688
|
font-size: 12px;
|
|
2396
|
-
margin: 4px 0 0;
|
|
2397
2689
|
padding: 4px 24px 4px 8px;
|
|
2398
2690
|
border: var(--lb-picker-variant-border-width) solid var(--lb-picker-variant-border-color);
|
|
2399
2691
|
border-radius: var(--lb-picker-variant-radius);
|
|
@@ -2406,7 +2698,8 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2406
2698
|
font-family: inherit;
|
|
2407
2699
|
min-height: 32px;
|
|
2408
2700
|
cursor: pointer;
|
|
2409
|
-
|
|
2701
|
+
width: 50%;
|
|
2702
|
+
max-width: 50%;
|
|
2410
2703
|
appearance: none;
|
|
2411
2704
|
-webkit-appearance: none;
|
|
2412
2705
|
}
|
|
@@ -2490,6 +2783,11 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
|
|
|
2490
2783
|
.lb-mix-match__modal-overlay--open .lb-mix-match__modal {
|
|
2491
2784
|
transform: translateY(0);
|
|
2492
2785
|
}
|
|
2786
|
+
|
|
2787
|
+
.lb-mix-match__variant-select {
|
|
2788
|
+
width: 80%;
|
|
2789
|
+
max-width: 80%;
|
|
2790
|
+
}
|
|
2493
2791
|
}
|
|
2494
2792
|
|
|
2495
2793
|
/* === Reduced Motion === */
|
|
@@ -2591,7 +2889,7 @@ var BUNDLE_VOLUME_CSS = `/* Lime Bundles \u2014 Volume / Quantity Breaks styles
|
|
|
2591
2889
|
|
|
2592
2890
|
.lb-volume__tier-price {
|
|
2593
2891
|
grid-column: 1 / -1;
|
|
2594
|
-
font-size:
|
|
2892
|
+
font-size: 14px;
|
|
2595
2893
|
font-weight: 500;
|
|
2596
2894
|
color: var(--lb-text);
|
|
2597
2895
|
}
|
|
@@ -2603,7 +2901,7 @@ var BUNDLE_VOLUME_CSS = `/* Lime Bundles \u2014 Volume / Quantity Breaks styles
|
|
|
2603
2901
|
|
|
2604
2902
|
/* Compare-at (strikethrough) price */
|
|
2605
2903
|
.lb-volume__tier-compare {
|
|
2606
|
-
font-size:
|
|
2904
|
+
font-size: 14px;
|
|
2607
2905
|
line-height: 16px;
|
|
2608
2906
|
color: color-mix(in srgb, var(--lb-text) 60%, transparent);
|
|
2609
2907
|
text-decoration: line-through;
|
|
@@ -2809,7 +3107,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2809
3107
|
const controller = new AbortController();
|
|
2810
3108
|
this.abortController = controller;
|
|
2811
3109
|
this.renderLoading();
|
|
2812
|
-
const client = (0,
|
|
3110
|
+
const client = (0, import_core6.createStorefrontClient)({
|
|
2813
3111
|
shopDomain: this.shopDomain,
|
|
2814
3112
|
accessToken: this.storefrontToken
|
|
2815
3113
|
});
|
|
@@ -2834,7 +3132,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2834
3132
|
handle
|
|
2835
3133
|
);
|
|
2836
3134
|
}
|
|
2837
|
-
const cssPromise = client.query(
|
|
3135
|
+
const cssPromise = client.query(import_core6.SHOP_CUSTOM_CSS_QUERY, void 0, {
|
|
2838
3136
|
signal: controller.signal
|
|
2839
3137
|
}).catch(() => null);
|
|
2840
3138
|
await bundlePromise;
|
|
@@ -2846,8 +3144,8 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2846
3144
|
}
|
|
2847
3145
|
const css = await cssPromise;
|
|
2848
3146
|
if (css?.shop?.metafield?.value) {
|
|
2849
|
-
(0,
|
|
2850
|
-
const sanitized = (0,
|
|
3147
|
+
(0, import_core6.injectCustomCss)(this.shopDomain, css.shop.metafield.value);
|
|
3148
|
+
const sanitized = (0, import_core6.sanitizeCustomCss)(css.shop.metafield.value);
|
|
2851
3149
|
if (sanitized.ok) this.shopCustomCss = sanitized.css;
|
|
2852
3150
|
}
|
|
2853
3151
|
await this.applyABVariants();
|
|
@@ -2875,14 +3173,14 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2875
3173
|
this.bundles.map(async (bundle) => {
|
|
2876
3174
|
if (!bundle.abTestId || !bundle.abVariantB) return bundle;
|
|
2877
3175
|
try {
|
|
2878
|
-
const assignment = await (0,
|
|
3176
|
+
const assignment = await (0, import_core6.getABTestAssignment)(
|
|
2879
3177
|
this.appUrl,
|
|
2880
3178
|
this.shopDomain,
|
|
2881
3179
|
bundle.abTestId,
|
|
2882
3180
|
bundle.id
|
|
2883
3181
|
);
|
|
2884
3182
|
if (assignment?.variant === "B") {
|
|
2885
|
-
return (0,
|
|
3183
|
+
return (0, import_core6.applyABVariantB)(bundle);
|
|
2886
3184
|
}
|
|
2887
3185
|
} catch (err) {
|
|
2888
3186
|
console.warn(
|
|
@@ -2897,7 +3195,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2897
3195
|
}
|
|
2898
3196
|
async fetchSingleBundle(client, signal) {
|
|
2899
3197
|
const data = await client.query(
|
|
2900
|
-
|
|
3198
|
+
import_core6.BUNDLE_METAOBJECT_QUERY,
|
|
2901
3199
|
{ id: this.bundleGid },
|
|
2902
3200
|
{ signal }
|
|
2903
3201
|
);
|
|
@@ -2905,7 +3203,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2905
3203
|
this.bundles = [];
|
|
2906
3204
|
return;
|
|
2907
3205
|
}
|
|
2908
|
-
const parsed = (0,
|
|
3206
|
+
const parsed = (0, import_core6.parseMetaobjectBundle)(
|
|
2909
3207
|
data.metaobject.id,
|
|
2910
3208
|
data.metaobject.fields
|
|
2911
3209
|
);
|
|
@@ -2913,7 +3211,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2913
3211
|
}
|
|
2914
3212
|
async fetchProductBundles(client, signal, productHandle) {
|
|
2915
3213
|
const data = await client.query(
|
|
2916
|
-
|
|
3214
|
+
import_core6.BUNDLES_FOR_PRODUCT_QUERY,
|
|
2917
3215
|
{ handle: productHandle },
|
|
2918
3216
|
{ signal }
|
|
2919
3217
|
);
|
|
@@ -2924,7 +3222,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2924
3222
|
const refs = data.product.metafield?.references?.nodes ?? [];
|
|
2925
3223
|
const bundles = [];
|
|
2926
3224
|
for (const ref of refs) {
|
|
2927
|
-
const parsed = (0,
|
|
3225
|
+
const parsed = (0, import_core6.parseMetaobjectBundle)(ref.id, ref.fields);
|
|
2928
3226
|
if (parsed) bundles.push(parsed);
|
|
2929
3227
|
}
|
|
2930
3228
|
this.bundles = bundles;
|
|
@@ -2957,7 +3255,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2957
3255
|
*/
|
|
2958
3256
|
async defaultAddToCart(lines) {
|
|
2959
3257
|
if (typeof window === "undefined") return;
|
|
2960
|
-
const client = (0,
|
|
3258
|
+
const client = (0, import_core6.createStorefrontClient)({
|
|
2961
3259
|
shopDomain: this.shopDomain,
|
|
2962
3260
|
accessToken: this.storefrontToken
|
|
2963
3261
|
});
|
|
@@ -2968,7 +3266,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2968
3266
|
let checkoutUrl = null;
|
|
2969
3267
|
if (existingCartId) {
|
|
2970
3268
|
const res = await client.query(
|
|
2971
|
-
|
|
3269
|
+
import_core6.CART_LINES_ADD_MUTATION,
|
|
2972
3270
|
{ cartId: existingCartId, lines }
|
|
2973
3271
|
);
|
|
2974
3272
|
const payload = res.cartLinesAdd;
|
|
@@ -2980,7 +3278,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
2980
3278
|
}
|
|
2981
3279
|
if (!checkoutUrl) {
|
|
2982
3280
|
const res = await client.query(
|
|
2983
|
-
|
|
3281
|
+
import_core6.CART_CREATE_MUTATION,
|
|
2984
3282
|
{ input: { lines } }
|
|
2985
3283
|
);
|
|
2986
3284
|
const payload = res.cartCreate;
|
|
@@ -3026,7 +3324,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
3026
3324
|
const price = variant ? parseFloat(variant.price.amount) : 0;
|
|
3027
3325
|
return sum + price * line.quantity;
|
|
3028
3326
|
}, 0);
|
|
3029
|
-
(0,
|
|
3327
|
+
(0, import_core6.reportAddToCart)(
|
|
3030
3328
|
{ shopDomain: this.shopDomain, appUrl: this.appUrl },
|
|
3031
3329
|
{
|
|
3032
3330
|
bundleGid: bundle.id,
|
|
@@ -3062,7 +3360,8 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
3062
3360
|
container.setAttribute("aria-label", bundle.title);
|
|
3063
3361
|
container.setAttribute("data-bundle-type", bundle.bundleType);
|
|
3064
3362
|
container.setAttribute("data-bundle-gid", bundle.id);
|
|
3065
|
-
(0,
|
|
3363
|
+
(0, import_core7.applyWidgetConfigVars)(container, bundle.widgetConfig);
|
|
3364
|
+
this.renderCleanups.push(trackInputMode(container));
|
|
3066
3365
|
const dispatch = (lines) => this.handleAddToCart(bundle, lines);
|
|
3067
3366
|
const registerCleanup = (fn) => this.renderCleanups.push(fn);
|
|
3068
3367
|
switch (bundle.bundleType) {
|
|
@@ -3097,8 +3396,8 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
3097
3396
|
}
|
|
3098
3397
|
setupImpressionFor(bundle, element) {
|
|
3099
3398
|
if (!this.analyticsEnabled || !this.appUrl) return;
|
|
3100
|
-
const cleanup = (0,
|
|
3101
|
-
(0,
|
|
3399
|
+
const cleanup = (0, import_core6.observeImpression)(element, () => {
|
|
3400
|
+
(0, import_core6.reportImpression)(
|
|
3102
3401
|
{ shopDomain: this.shopDomain, appUrl: this.appUrl },
|
|
3103
3402
|
{
|
|
3104
3403
|
bundleGid: bundle.id,
|
|
@@ -3165,6 +3464,7 @@ if (typeof customElements !== "undefined" && !customElements.get("lime-bundle"))
|
|
|
3165
3464
|
}
|
|
3166
3465
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3167
3466
|
0 && (module.exports = {
|
|
3168
|
-
LimeBundleElement
|
|
3467
|
+
LimeBundleElement,
|
|
3468
|
+
trackInputMode
|
|
3169
3469
|
});
|
|
3170
3470
|
//# sourceMappingURL=index.cjs.map
|