@lime-bundles/widget 4.3.0 → 4.5.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 +327 -41
- package/dist/index.js +327 -41
- package/dist/lime-bundle.global.js +144 -28
- package/dist/lime-bundle.global.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -60,6 +60,14 @@ function toCents(amount) {
|
|
|
60
60
|
const n = parseFloat(amount);
|
|
61
61
|
return Number.isFinite(n) ? Math.round(n * 100) : 0;
|
|
62
62
|
}
|
|
63
|
+
function imageAspectRatio(image) {
|
|
64
|
+
const w = image?.width;
|
|
65
|
+
const h = image?.height;
|
|
66
|
+
if (typeof w !== "number" || typeof h !== "number" || w <= 0 || h <= 0) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return w / h;
|
|
70
|
+
}
|
|
63
71
|
function adaptVariant(v, requiredQty, fallbackCurrency) {
|
|
64
72
|
return {
|
|
65
73
|
id: numericId(v.id),
|
|
@@ -101,6 +109,7 @@ function adaptProduct(product, bundleId, opts) {
|
|
|
101
109
|
title: product.title,
|
|
102
110
|
url: product.handle ? "/products/" + product.handle : null,
|
|
103
111
|
featuredImage: product.featuredImage?.url ?? null,
|
|
112
|
+
featuredImageRatio: imageAspectRatio(product.featuredImage),
|
|
104
113
|
quantity: productQty,
|
|
105
114
|
selectedVariantId: initial ? initial.id : "",
|
|
106
115
|
// Option names come off a variant, since the Storefront product query
|
|
@@ -445,7 +454,12 @@ function buildRowSkeleton(product, t, opts) {
|
|
|
445
454
|
}
|
|
446
455
|
row.setAttribute("data-product-id", String(product.productId));
|
|
447
456
|
if (opts.bogoRole) row.setAttribute("data-bogo-role", opts.bogoRole);
|
|
448
|
-
|
|
457
|
+
const thumb = box("div", "lb-bundle-thumbnail", { "data-thumbnail": "" });
|
|
458
|
+
const ratio = product.featuredImageRatio;
|
|
459
|
+
if (opts.thumbnailRatio === "original" && ratio != null && ratio > 0) {
|
|
460
|
+
thumb.style.setProperty("--lb-row-thumb-ratio", String(ratio));
|
|
461
|
+
}
|
|
462
|
+
row.appendChild(thumb);
|
|
449
463
|
const info = box("div", "lb-bundle-product-info");
|
|
450
464
|
const title = document.createElement(opts.href ? "a" : "span");
|
|
451
465
|
title.className = "lb-bundle-product-name";
|
|
@@ -754,6 +768,16 @@ var DEFAULT_STRINGS = {
|
|
|
754
768
|
chooseMoreComplete: "Choose __COUNT__ more to complete your bundle",
|
|
755
769
|
stepOf: "Step __STEP__ of __TOTAL__",
|
|
756
770
|
stepsCompleted: "__COUNT__ of __TOTAL__ steps completed",
|
|
771
|
+
doorChoose: "Choose your products",
|
|
772
|
+
doorContinue: "Continue building",
|
|
773
|
+
doorQuickSteps: {
|
|
774
|
+
one: "__COUNT__ quick step",
|
|
775
|
+
other: "__COUNT__ quick steps"
|
|
776
|
+
},
|
|
777
|
+
doorStepsToGo: {
|
|
778
|
+
one: "__COUNT__ step to go",
|
|
779
|
+
other: "__COUNT__ steps to go"
|
|
780
|
+
},
|
|
757
781
|
each: " each",
|
|
758
782
|
buyQty: "Buy __COUNT__",
|
|
759
783
|
itemCount: {
|
|
@@ -1211,7 +1235,8 @@ function renderFixedBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
1211
1235
|
const isOos = !product.variants.some((v) => v.available);
|
|
1212
1236
|
const row = buildRowSkeleton(product, t, {
|
|
1213
1237
|
isOos,
|
|
1214
|
-
href: product.url
|
|
1238
|
+
href: product.url,
|
|
1239
|
+
thumbnailRatio: wc.productList?.thumbnailRatio
|
|
1215
1240
|
});
|
|
1216
1241
|
shell.products.appendChild(row);
|
|
1217
1242
|
if (isOos) continue;
|
|
@@ -3217,7 +3242,8 @@ function renderBogoBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
3217
3242
|
href: side.url,
|
|
3218
3243
|
bogoRole: side.role,
|
|
3219
3244
|
inlineQuantity: isGet ? getQty : buyQty,
|
|
3220
|
-
badgeText: isGet && !isOos ? badgeText : null
|
|
3245
|
+
badgeText: isGet && !isOos ? badgeText : null,
|
|
3246
|
+
thumbnailRatio: wc.productList?.thumbnailRatio
|
|
3221
3247
|
});
|
|
3222
3248
|
shell.products.appendChild(row);
|
|
3223
3249
|
if (isOos) return;
|
|
@@ -3286,6 +3312,32 @@ function stepsCompletedLabel(completed, total, t) {
|
|
|
3286
3312
|
function moreToGoLabel(remaining, t) {
|
|
3287
3313
|
return remaining > 0 ? fill(t.moreToGo || "__COUNT__ more to go", { COUNT: remaining }) : t.complete || "Complete";
|
|
3288
3314
|
}
|
|
3315
|
+
function fillPlural(map, count, locale) {
|
|
3316
|
+
const form = new Intl.PluralRules(locale || "en").select(count);
|
|
3317
|
+
return fill(map[form] || map.other || "__COUNT__", { COUNT: count });
|
|
3318
|
+
}
|
|
3319
|
+
function doorLabel(anyPicks, t) {
|
|
3320
|
+
return anyPicks ? t.doorContinue || "Continue building" : t.doorChoose || "Choose your products";
|
|
3321
|
+
}
|
|
3322
|
+
function doorSubLabel(anyPicks, remaining, total, t) {
|
|
3323
|
+
if (!anyPicks) {
|
|
3324
|
+
const quick = t.doorQuickSteps;
|
|
3325
|
+
if (typeof quick === "string") return fill(quick, { COUNT: total });
|
|
3326
|
+
return fillPlural(
|
|
3327
|
+
quick || { one: "__COUNT__ quick step", other: "__COUNT__ quick steps" },
|
|
3328
|
+
total,
|
|
3329
|
+
t.locale
|
|
3330
|
+
);
|
|
3331
|
+
}
|
|
3332
|
+
return fillPlural(
|
|
3333
|
+
t.doorStepsToGo || {
|
|
3334
|
+
one: "__COUNT__ step to go",
|
|
3335
|
+
other: "__COUNT__ steps to go"
|
|
3336
|
+
},
|
|
3337
|
+
remaining,
|
|
3338
|
+
t.locale
|
|
3339
|
+
);
|
|
3340
|
+
}
|
|
3289
3341
|
|
|
3290
3342
|
// ../render/src/multi-step/rules.ts
|
|
3291
3343
|
function unitsInStep(selections, i) {
|
|
@@ -3347,20 +3399,28 @@ function updateStepGroups(deps) {
|
|
|
3347
3399
|
const { container, steps, selections, t } = deps;
|
|
3348
3400
|
for (let i = 0; i < steps.length; i++) {
|
|
3349
3401
|
const min = steps[i].minQuantity || 1;
|
|
3350
|
-
const
|
|
3351
|
-
'[data-step-
|
|
3402
|
+
const section = container.querySelector(
|
|
3403
|
+
'[data-step-group="' + i + '"]'
|
|
3352
3404
|
);
|
|
3353
|
-
if (
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
t
|
|
3358
|
-
);
|
|
3359
|
-
countEl.classList.toggle(
|
|
3360
|
-
"lb-multi-step__group-count--met",
|
|
3361
|
-
stepSatisfied(selections, steps, i)
|
|
3405
|
+
if (section) {
|
|
3406
|
+
section.setAttribute(
|
|
3407
|
+
"data-step-mode",
|
|
3408
|
+
selections[i].length > 0 ? "open" : "row"
|
|
3362
3409
|
);
|
|
3363
3410
|
}
|
|
3411
|
+
const countLabel = ofSelectedLabel(
|
|
3412
|
+
Math.min(unitsInStep(selections, i), min),
|
|
3413
|
+
min,
|
|
3414
|
+
t
|
|
3415
|
+
);
|
|
3416
|
+
const met = stepSatisfied(selections, steps, i);
|
|
3417
|
+
const countEls = container.querySelectorAll(
|
|
3418
|
+
'[data-step-count="' + i + '"]'
|
|
3419
|
+
);
|
|
3420
|
+
for (let c = 0; c < countEls.length; c++) {
|
|
3421
|
+
countEls[c].textContent = countLabel;
|
|
3422
|
+
countEls[c].classList.toggle("lb-multi-step__group-count--met", met);
|
|
3423
|
+
}
|
|
3364
3424
|
const slotsWrap = container.querySelector(
|
|
3365
3425
|
'[data-step-slots="' + i + '"]'
|
|
3366
3426
|
);
|
|
@@ -3382,14 +3442,50 @@ function updateStepGroups(deps) {
|
|
|
3382
3442
|
);
|
|
3383
3443
|
}
|
|
3384
3444
|
}
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3445
|
+
}
|
|
3446
|
+
function updateDoor(deps) {
|
|
3447
|
+
const { container, steps, selections, t } = deps;
|
|
3448
|
+
const door = container.querySelector("[data-step-door]");
|
|
3449
|
+
if (!door) return;
|
|
3450
|
+
let firstUnsatisfied = -1;
|
|
3451
|
+
let remaining = 0;
|
|
3452
|
+
let anyPicks = false;
|
|
3453
|
+
for (let i = 0; i < steps.length; i++) {
|
|
3454
|
+
if (selections[i].length > 0) anyPicks = true;
|
|
3455
|
+
if (!stepSatisfied(selections, steps, i)) {
|
|
3456
|
+
remaining += 1;
|
|
3457
|
+
if (firstUnsatisfied === -1) firstUnsatisfied = i;
|
|
3391
3458
|
}
|
|
3392
3459
|
}
|
|
3460
|
+
if (firstUnsatisfied === -1) {
|
|
3461
|
+
door.style.display = "none";
|
|
3462
|
+
door.classList.add("lb-multi-step__door--hidden");
|
|
3463
|
+
const parent = door.parentElement;
|
|
3464
|
+
if (parent && parent.firstElementChild !== door) {
|
|
3465
|
+
parent.insertBefore(door, parent.firstElementChild);
|
|
3466
|
+
}
|
|
3467
|
+
return;
|
|
3468
|
+
}
|
|
3469
|
+
door.style.display = "";
|
|
3470
|
+
door.classList.remove("lb-multi-step__door--hidden");
|
|
3471
|
+
door.setAttribute("data-step-door", String(firstUnsatisfied));
|
|
3472
|
+
const label = doorLabel(anyPicks, t);
|
|
3473
|
+
const labelEl = door.querySelector(
|
|
3474
|
+
".lb-mix-match__add-product-label"
|
|
3475
|
+
);
|
|
3476
|
+
if (labelEl) labelEl.textContent = label;
|
|
3477
|
+
const subEl = door.querySelector(".lb-multi-step__door-sub");
|
|
3478
|
+
if (subEl) {
|
|
3479
|
+
subEl.textContent = doorSubLabel(anyPicks, remaining, steps.length, t);
|
|
3480
|
+
}
|
|
3481
|
+
const stepName = steps[firstUnsatisfied].name || "";
|
|
3482
|
+
door.setAttribute("aria-label", stepName ? label + ": " + stepName : label);
|
|
3483
|
+
const target = container.querySelector(
|
|
3484
|
+
'[data-step-group="' + firstUnsatisfied + '"]'
|
|
3485
|
+
);
|
|
3486
|
+
if (target && target.parentElement && target.previousElementSibling !== door) {
|
|
3487
|
+
target.parentElement.insertBefore(door, target);
|
|
3488
|
+
}
|
|
3393
3489
|
}
|
|
3394
3490
|
function updatePricing3(deps, data, calcDiscount, paint) {
|
|
3395
3491
|
const { container, steps, selections } = deps;
|
|
@@ -3606,6 +3702,12 @@ function createWizard(deps) {
|
|
|
3606
3702
|
for (const r of rows) r.refresh();
|
|
3607
3703
|
updateModalMeta();
|
|
3608
3704
|
}
|
|
3705
|
+
function maybeAutoAdvance() {
|
|
3706
|
+
if (!deps.autoAdvance) return;
|
|
3707
|
+
if (stepIndex >= steps.length - 1) return;
|
|
3708
|
+
if (stepHeadroom(selections, steps, stepIndex) !== 0) return;
|
|
3709
|
+
goToStep(stepIndex + 1);
|
|
3710
|
+
}
|
|
3609
3711
|
function buildProductList(forStep) {
|
|
3610
3712
|
if (!modalList) return;
|
|
3611
3713
|
deps.dropdown?.unbindAll(modalList);
|
|
@@ -3622,6 +3724,7 @@ function createWizard(deps) {
|
|
|
3622
3724
|
onCommittedQtyChanged: () => {
|
|
3623
3725
|
deps.onSelectionChanged();
|
|
3624
3726
|
refresh();
|
|
3727
|
+
maybeAutoAdvance();
|
|
3625
3728
|
}
|
|
3626
3729
|
});
|
|
3627
3730
|
rows.push(row);
|
|
@@ -3701,6 +3804,7 @@ function createWizard(deps) {
|
|
|
3701
3804
|
selections[stepIndex].push(newItem);
|
|
3702
3805
|
deps.onSelectionChanged();
|
|
3703
3806
|
refresh();
|
|
3807
|
+
maybeAutoAdvance();
|
|
3704
3808
|
}
|
|
3705
3809
|
if (modalList) modalList.addEventListener("click", onListClick);
|
|
3706
3810
|
function buildFilters(forStep) {
|
|
@@ -3833,10 +3937,12 @@ function createWizard(deps) {
|
|
|
3833
3937
|
setTimeout(() => {
|
|
3834
3938
|
if (!modalOpen) overlay.style.display = "none";
|
|
3835
3939
|
}, CLOSE_TRANSITION_MS2);
|
|
3836
|
-
const
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3940
|
+
const visible = (el2) => el2 && el2.offsetParent !== null ? el2 : null;
|
|
3941
|
+
const elToFocus = visible(
|
|
3942
|
+
container.querySelector(
|
|
3943
|
+
'[data-step-row="' + stepIndex + '"]'
|
|
3944
|
+
)
|
|
3945
|
+
) || visible(container.querySelector("[data-step-door]")) || deps.ctaButton;
|
|
3840
3946
|
if (elToFocus && typeof elToFocus.focus === "function") {
|
|
3841
3947
|
setTimeout(() => elToFocus.focus(), 0);
|
|
3842
3948
|
}
|
|
@@ -3889,6 +3995,29 @@ function createWizard(deps) {
|
|
|
3889
3995
|
}
|
|
3890
3996
|
|
|
3891
3997
|
// src/renderers/multi-step.ts
|
|
3998
|
+
function buildPlusIcon() {
|
|
3999
|
+
const NS = "http://www.w3.org/2000/svg";
|
|
4000
|
+
const svg = document.createElementNS(NS, "svg");
|
|
4001
|
+
svg.setAttribute("width", "18");
|
|
4002
|
+
svg.setAttribute("height", "18");
|
|
4003
|
+
svg.setAttribute("viewBox", "0 0 18 18");
|
|
4004
|
+
svg.setAttribute("fill", "none");
|
|
4005
|
+
for (const [x1, y1, x2, y2] of [
|
|
4006
|
+
["9", "3", "9", "15"],
|
|
4007
|
+
["3", "9", "15", "9"]
|
|
4008
|
+
]) {
|
|
4009
|
+
const line = document.createElementNS(NS, "line");
|
|
4010
|
+
line.setAttribute("x1", x1);
|
|
4011
|
+
line.setAttribute("y1", y1);
|
|
4012
|
+
line.setAttribute("x2", x2);
|
|
4013
|
+
line.setAttribute("y2", y2);
|
|
4014
|
+
line.setAttribute("stroke", "currentColor");
|
|
4015
|
+
line.setAttribute("stroke-width", "2");
|
|
4016
|
+
line.setAttribute("stroke-linecap", "round");
|
|
4017
|
+
svg.appendChild(line);
|
|
4018
|
+
}
|
|
4019
|
+
return svg;
|
|
4020
|
+
}
|
|
3892
4021
|
function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
3893
4022
|
const wc = bundle.widgetConfig;
|
|
3894
4023
|
const t = DEFAULT_STRINGS;
|
|
@@ -3943,31 +4072,65 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
3943
4072
|
shell.products.before(buildProgressBar(steps.length));
|
|
3944
4073
|
const groups = document.createElement("div");
|
|
3945
4074
|
groups.className = "lb-multi-step__groups";
|
|
4075
|
+
groups.setAttribute("data-step-groups", "");
|
|
4076
|
+
const door = document.createElement("button");
|
|
4077
|
+
door.type = "button";
|
|
4078
|
+
door.className = "lb-mix-match__add-product lb-multi-step__door";
|
|
4079
|
+
door.setAttribute("data-step-door", "0");
|
|
4080
|
+
const doorIcon = document.createElement("span");
|
|
4081
|
+
doorIcon.className = "lb-mix-match__add-product-icon";
|
|
4082
|
+
doorIcon.setAttribute("aria-hidden", "true");
|
|
4083
|
+
doorIcon.appendChild(buildPlusIcon());
|
|
4084
|
+
door.appendChild(doorIcon);
|
|
4085
|
+
const doorCopy = document.createElement("span");
|
|
4086
|
+
doorCopy.className = "lb-multi-step__door-copy";
|
|
4087
|
+
const doorLabel2 = document.createElement("span");
|
|
4088
|
+
doorLabel2.className = "lb-mix-match__add-product-label";
|
|
4089
|
+
doorCopy.appendChild(doorLabel2);
|
|
4090
|
+
const doorSub = document.createElement("span");
|
|
4091
|
+
doorSub.className = "lb-multi-step__door-sub";
|
|
4092
|
+
doorCopy.appendChild(doorSub);
|
|
4093
|
+
door.appendChild(doorCopy);
|
|
4094
|
+
groups.appendChild(door);
|
|
3946
4095
|
steps.forEach((step, i) => {
|
|
3947
|
-
const group = document.createElement("
|
|
4096
|
+
const group = document.createElement("section");
|
|
3948
4097
|
group.className = "lb-multi-step__group";
|
|
3949
4098
|
group.setAttribute("data-step-group", String(i));
|
|
4099
|
+
group.setAttribute("data-step-mode", "row");
|
|
4100
|
+
const buildCount = () => {
|
|
4101
|
+
const count = document.createElement("span");
|
|
4102
|
+
count.className = "lb-multi-step__group-count";
|
|
4103
|
+
count.setAttribute("data-step-count", String(i));
|
|
4104
|
+
return count;
|
|
4105
|
+
};
|
|
4106
|
+
const row = document.createElement("button");
|
|
4107
|
+
row.type = "button";
|
|
4108
|
+
row.className = "lb-multi-step__step-row";
|
|
4109
|
+
row.setAttribute("data-step-row", String(i));
|
|
4110
|
+
row.setAttribute("aria-label", "Choose products: " + step.name);
|
|
4111
|
+
const ix = document.createElement("span");
|
|
4112
|
+
ix.className = "lb-multi-step__step-ix";
|
|
4113
|
+
ix.setAttribute("aria-hidden", "true");
|
|
4114
|
+
ix.textContent = String(i + 1);
|
|
4115
|
+
row.appendChild(ix);
|
|
4116
|
+
const rowName = document.createElement("span");
|
|
4117
|
+
rowName.className = "lb-multi-step__group-name";
|
|
4118
|
+
rowName.textContent = step.name;
|
|
4119
|
+
row.appendChild(rowName);
|
|
4120
|
+
row.appendChild(buildCount());
|
|
4121
|
+
group.appendChild(row);
|
|
3950
4122
|
const heading = document.createElement("div");
|
|
3951
4123
|
heading.className = "lb-multi-step__group-heading";
|
|
3952
4124
|
const name = document.createElement("span");
|
|
3953
4125
|
name.className = "lb-multi-step__group-name";
|
|
3954
4126
|
name.textContent = step.name;
|
|
3955
4127
|
heading.appendChild(name);
|
|
3956
|
-
|
|
3957
|
-
count.className = "lb-multi-step__group-count";
|
|
3958
|
-
count.setAttribute("data-step-count", String(i));
|
|
3959
|
-
heading.appendChild(count);
|
|
4128
|
+
heading.appendChild(buildCount());
|
|
3960
4129
|
group.appendChild(heading);
|
|
3961
4130
|
const slots = document.createElement("div");
|
|
3962
|
-
slots.className = "lb-mix-match__slots lb-edge-fade";
|
|
4131
|
+
slots.className = "lb-mix-match__slots lb-edge-fade lb-multi-step__group-slots";
|
|
3963
4132
|
slots.setAttribute("data-step-slots", String(i));
|
|
3964
4133
|
group.appendChild(slots);
|
|
3965
|
-
const trigger = document.createElement("button");
|
|
3966
|
-
trigger.type = "button";
|
|
3967
|
-
trigger.className = "lb-mix-match__add-product";
|
|
3968
|
-
trigger.setAttribute("data-step-trigger", String(i));
|
|
3969
|
-
trigger.textContent = "Add a product";
|
|
3970
|
-
group.appendChild(trigger);
|
|
3971
4134
|
groups.appendChild(group);
|
|
3972
4135
|
});
|
|
3973
4136
|
shell.products.replaceWith(groups);
|
|
@@ -4004,6 +4167,7 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
4004
4167
|
};
|
|
4005
4168
|
function updateAll() {
|
|
4006
4169
|
updateStepGroups(bodyDeps);
|
|
4170
|
+
updateDoor(bodyDeps);
|
|
4007
4171
|
updatePricing3(
|
|
4008
4172
|
bodyDeps,
|
|
4009
4173
|
{
|
|
@@ -4024,6 +4188,8 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
4024
4188
|
rulesMap,
|
|
4025
4189
|
showQtySelector: wc.mixMatchShowQuantitySelector !== false,
|
|
4026
4190
|
showTypeFilters: wc.mixMatchShowTypeFilters !== false,
|
|
4191
|
+
// Off by default: a stored config predating the key must not advance.
|
|
4192
|
+
autoAdvance: wc.multiStepAutoAdvance === true,
|
|
4027
4193
|
formatMoney,
|
|
4028
4194
|
dropdown: void 0,
|
|
4029
4195
|
portalTarget: null,
|
|
@@ -4050,10 +4216,14 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
4050
4216
|
},
|
|
4051
4217
|
canRemove: (item) => canRemovePick2(selections, item, rulesMap)
|
|
4052
4218
|
});
|
|
4053
|
-
|
|
4219
|
+
door.addEventListener("click", () => {
|
|
4220
|
+
if (wizard.isOpen()) return;
|
|
4221
|
+
wizard.open(parseInt(door.getAttribute("data-step-door") ?? "", 10) || 0);
|
|
4222
|
+
});
|
|
4223
|
+
shell.root.querySelectorAll("[data-step-row]").forEach((el2) => {
|
|
4054
4224
|
el2.addEventListener("click", () => {
|
|
4055
4225
|
if (wizard.isOpen()) return;
|
|
4056
|
-
wizard.open(parseInt(el2.getAttribute("data-step-
|
|
4226
|
+
wizard.open(parseInt(el2.getAttribute("data-step-row") ?? "", 10) || 0);
|
|
4057
4227
|
});
|
|
4058
4228
|
});
|
|
4059
4229
|
shell.cta.addEventListener("click", () => {
|
|
@@ -6247,12 +6417,19 @@ var BUNDLE_MULTI_STEP_CSS = `/**
|
|
|
6247
6417
|
* Canon: WIDGET-DESIGN.md (spacing scale, radius system, chip family).
|
|
6248
6418
|
*/
|
|
6249
6419
|
|
|
6250
|
-
/* \u2500\u2500 Step groups (widget body) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
6420
|
+
/* \u2500\u2500 Step groups (widget body) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
6421
|
+
One dashed door + one section per step. A step without picks shows a
|
|
6422
|
+
slim checklist row; a step with picks shows the heading + chosen
|
|
6423
|
+
cards. data-step-mode ("row" | "open") on the section picks the
|
|
6424
|
+
representation \u2014 both are in the markup, CSS hides the other, so the
|
|
6425
|
+
server-rendered untouched state IS the hydrated no-selection state.
|
|
6426
|
+
Spacing is per-pair rather than a flat gap: consecutive rows sit
|
|
6427
|
+
flush (hairline-separated), everything else breathes 16px. */
|
|
6251
6428
|
|
|
6252
6429
|
.lb-multi-step__groups {
|
|
6253
6430
|
display: flex;
|
|
6254
6431
|
flex-direction: column;
|
|
6255
|
-
gap:
|
|
6432
|
+
gap: 0;
|
|
6256
6433
|
}
|
|
6257
6434
|
|
|
6258
6435
|
.lb-multi-step__group {
|
|
@@ -6261,8 +6438,117 @@ var BUNDLE_MULTI_STEP_CSS = `/**
|
|
|
6261
6438
|
gap: 8px;
|
|
6262
6439
|
}
|
|
6263
6440
|
|
|
6441
|
+
.lb-multi-step__group + .lb-multi-step__group {
|
|
6442
|
+
margin-top: 16px;
|
|
6443
|
+
}
|
|
6444
|
+
|
|
6445
|
+
/* A run of empty-step rows reads as one checklist: flush, hairlines
|
|
6446
|
+
between (the first row of a run keeps no border). */
|
|
6447
|
+
.lb-multi-step__group[data-step-mode="row"] + .lb-multi-step__group[data-step-mode="row"] {
|
|
6448
|
+
margin-top: 0;
|
|
6449
|
+
}
|
|
6450
|
+
|
|
6451
|
+
.lb-multi-step__group[data-step-mode="row"]
|
|
6452
|
+
+ .lb-multi-step__group[data-step-mode="row"]
|
|
6453
|
+
.lb-multi-step__step-row {
|
|
6454
|
+
border-top: var(--lb-border-width) solid var(--lb-border);
|
|
6455
|
+
}
|
|
6456
|
+
|
|
6457
|
+
/* Mode switch: a row-mode step hides its open chrome and vice versa. */
|
|
6458
|
+
.lb-multi-step__group[data-step-mode="row"] .lb-multi-step__group-heading,
|
|
6459
|
+
.lb-multi-step__group[data-step-mode="row"] .lb-multi-step__group-slots {
|
|
6460
|
+
display: none;
|
|
6461
|
+
}
|
|
6462
|
+
|
|
6463
|
+
.lb-multi-step__group[data-step-mode="open"] .lb-multi-step__step-row {
|
|
6464
|
+
display: none;
|
|
6465
|
+
}
|
|
6466
|
+
|
|
6467
|
+
/* Checklist row \u2014 the empty step's whole representation, and a tap
|
|
6468
|
+
target that deep-links the wizard to that step. Quiet by design: the
|
|
6469
|
+
door above it is the primary action. */
|
|
6470
|
+
.lb-multi-step__step-row {
|
|
6471
|
+
display: flex;
|
|
6472
|
+
align-items: center;
|
|
6473
|
+
gap: 12px;
|
|
6474
|
+
width: 100%;
|
|
6475
|
+
min-height: 48px;
|
|
6476
|
+
padding: 10px 2px;
|
|
6477
|
+
background: none;
|
|
6478
|
+
border: none;
|
|
6479
|
+
font-family: inherit;
|
|
6480
|
+
text-align: left;
|
|
6481
|
+
cursor: pointer;
|
|
6482
|
+
box-sizing: border-box;
|
|
6483
|
+
transition: background-color 0.25s ease;
|
|
6484
|
+
}
|
|
6485
|
+
|
|
6486
|
+
.lb-multi-step__step-row:hover {
|
|
6487
|
+
background: color-mix(in srgb, var(--lb-text) 3%, transparent);
|
|
6488
|
+
}
|
|
6489
|
+
|
|
6490
|
+
.lb-multi-step__step-row:focus-visible {
|
|
6491
|
+
outline: 2px solid var(--lb-primary-color);
|
|
6492
|
+
outline-offset: -2px;
|
|
6493
|
+
border-radius: var(--lb-radius-sm);
|
|
6494
|
+
}
|
|
6495
|
+
|
|
6496
|
+
.lb-multi-step__step-row .lb-multi-step__group-count {
|
|
6497
|
+
margin-left: auto;
|
|
6498
|
+
}
|
|
6499
|
+
|
|
6500
|
+
/* Step number \u2014 quiet index, tabular so multi-digit lists align. */
|
|
6501
|
+
.lb-multi-step__step-ix {
|
|
6502
|
+
width: 18px;
|
|
6503
|
+
min-width: 18px;
|
|
6504
|
+
font-size: 12px;
|
|
6505
|
+
font-weight: 500;
|
|
6506
|
+
color: color-mix(in srgb, var(--lb-text) 45%, transparent);
|
|
6507
|
+
font-variant-numeric: tabular-nums;
|
|
6508
|
+
}
|
|
6509
|
+
|
|
6510
|
+
/* The door \u2014 the single wizard entry point, reusing the dashed
|
|
6511
|
+
add-product recipe with a two-line label. JS moves it directly above
|
|
6512
|
+
the first unsatisfied step and hides it once every step is met. The
|
|
6513
|
+
add-product recipe's own margin-top is for its mix & match position
|
|
6514
|
+
(below the slot list); here the pair rules own all spacing. */
|
|
6515
|
+
.lb-multi-step__door {
|
|
6516
|
+
margin-top: 0;
|
|
6517
|
+
}
|
|
6518
|
+
|
|
6519
|
+
.lb-multi-step__door + .lb-multi-step__group {
|
|
6520
|
+
margin-top: 12px;
|
|
6521
|
+
}
|
|
6522
|
+
|
|
6523
|
+
.lb-multi-step__door + .lb-multi-step__group[data-step-mode="row"] {
|
|
6524
|
+
margin-top: 4px;
|
|
6525
|
+
}
|
|
6526
|
+
|
|
6527
|
+
.lb-multi-step__group + .lb-multi-step__door {
|
|
6528
|
+
margin-top: 16px;
|
|
6529
|
+
}
|
|
6530
|
+
|
|
6531
|
+
/* A hidden door is parked as the container's first child (updateDoor), so
|
|
6532
|
+
the group after it is really the first visible element \u2014 no door gap. */
|
|
6533
|
+
.lb-multi-step__door--hidden:first-child + .lb-multi-step__group {
|
|
6534
|
+
margin-top: 0;
|
|
6535
|
+
}
|
|
6536
|
+
|
|
6537
|
+
.lb-multi-step__door-copy {
|
|
6538
|
+
display: flex;
|
|
6539
|
+
flex-direction: column;
|
|
6540
|
+
gap: 2px;
|
|
6541
|
+
}
|
|
6542
|
+
|
|
6543
|
+
.lb-multi-step__door-sub {
|
|
6544
|
+
font-size: 13px;
|
|
6545
|
+
font-weight: 400;
|
|
6546
|
+
line-height: 1.2;
|
|
6547
|
+
color: color-mix(in srgb, var(--lb-text) 55%, transparent);
|
|
6548
|
+
}
|
|
6549
|
+
|
|
6264
6550
|
/* Heading is a quiet, non-interactive row: step name left, live count
|
|
6265
|
-
chip right. The step's
|
|
6551
|
+
chip right. The step's chosen cards below are the edit targets. */
|
|
6266
6552
|
.lb-multi-step__group-heading {
|
|
6267
6553
|
display: flex;
|
|
6268
6554
|
align-items: center;
|