@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.cjs
CHANGED
|
@@ -62,6 +62,14 @@ function toCents(amount) {
|
|
|
62
62
|
const n = parseFloat(amount);
|
|
63
63
|
return Number.isFinite(n) ? Math.round(n * 100) : 0;
|
|
64
64
|
}
|
|
65
|
+
function imageAspectRatio(image) {
|
|
66
|
+
const w = image?.width;
|
|
67
|
+
const h = image?.height;
|
|
68
|
+
if (typeof w !== "number" || typeof h !== "number" || w <= 0 || h <= 0) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return w / h;
|
|
72
|
+
}
|
|
65
73
|
function adaptVariant(v, requiredQty, fallbackCurrency) {
|
|
66
74
|
return {
|
|
67
75
|
id: numericId(v.id),
|
|
@@ -103,6 +111,7 @@ function adaptProduct(product, bundleId, opts) {
|
|
|
103
111
|
title: product.title,
|
|
104
112
|
url: product.handle ? "/products/" + product.handle : null,
|
|
105
113
|
featuredImage: product.featuredImage?.url ?? null,
|
|
114
|
+
featuredImageRatio: imageAspectRatio(product.featuredImage),
|
|
106
115
|
quantity: productQty,
|
|
107
116
|
selectedVariantId: initial ? initial.id : "",
|
|
108
117
|
// Option names come off a variant, since the Storefront product query
|
|
@@ -447,7 +456,12 @@ function buildRowSkeleton(product, t, opts) {
|
|
|
447
456
|
}
|
|
448
457
|
row.setAttribute("data-product-id", String(product.productId));
|
|
449
458
|
if (opts.bogoRole) row.setAttribute("data-bogo-role", opts.bogoRole);
|
|
450
|
-
|
|
459
|
+
const thumb = box("div", "lb-bundle-thumbnail", { "data-thumbnail": "" });
|
|
460
|
+
const ratio = product.featuredImageRatio;
|
|
461
|
+
if (opts.thumbnailRatio === "original" && ratio != null && ratio > 0) {
|
|
462
|
+
thumb.style.setProperty("--lb-row-thumb-ratio", String(ratio));
|
|
463
|
+
}
|
|
464
|
+
row.appendChild(thumb);
|
|
451
465
|
const info = box("div", "lb-bundle-product-info");
|
|
452
466
|
const title = document.createElement(opts.href ? "a" : "span");
|
|
453
467
|
title.className = "lb-bundle-product-name";
|
|
@@ -756,6 +770,16 @@ var DEFAULT_STRINGS = {
|
|
|
756
770
|
chooseMoreComplete: "Choose __COUNT__ more to complete your bundle",
|
|
757
771
|
stepOf: "Step __STEP__ of __TOTAL__",
|
|
758
772
|
stepsCompleted: "__COUNT__ of __TOTAL__ steps completed",
|
|
773
|
+
doorChoose: "Choose your products",
|
|
774
|
+
doorContinue: "Continue building",
|
|
775
|
+
doorQuickSteps: {
|
|
776
|
+
one: "__COUNT__ quick step",
|
|
777
|
+
other: "__COUNT__ quick steps"
|
|
778
|
+
},
|
|
779
|
+
doorStepsToGo: {
|
|
780
|
+
one: "__COUNT__ step to go",
|
|
781
|
+
other: "__COUNT__ steps to go"
|
|
782
|
+
},
|
|
759
783
|
each: " each",
|
|
760
784
|
buyQty: "Buy __COUNT__",
|
|
761
785
|
itemCount: {
|
|
@@ -1213,7 +1237,8 @@ function renderFixedBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
1213
1237
|
const isOos = !product.variants.some((v) => v.available);
|
|
1214
1238
|
const row = buildRowSkeleton(product, t, {
|
|
1215
1239
|
isOos,
|
|
1216
|
-
href: product.url
|
|
1240
|
+
href: product.url,
|
|
1241
|
+
thumbnailRatio: wc.productList?.thumbnailRatio
|
|
1217
1242
|
});
|
|
1218
1243
|
shell.products.appendChild(row);
|
|
1219
1244
|
if (isOos) continue;
|
|
@@ -3212,7 +3237,8 @@ function renderBogoBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
3212
3237
|
href: side.url,
|
|
3213
3238
|
bogoRole: side.role,
|
|
3214
3239
|
inlineQuantity: isGet ? getQty : buyQty,
|
|
3215
|
-
badgeText: isGet && !isOos ? badgeText : null
|
|
3240
|
+
badgeText: isGet && !isOos ? badgeText : null,
|
|
3241
|
+
thumbnailRatio: wc.productList?.thumbnailRatio
|
|
3216
3242
|
});
|
|
3217
3243
|
shell.products.appendChild(row);
|
|
3218
3244
|
if (isOos) return;
|
|
@@ -3278,6 +3304,32 @@ function stepsCompletedLabel(completed, total, t) {
|
|
|
3278
3304
|
function moreToGoLabel(remaining, t) {
|
|
3279
3305
|
return remaining > 0 ? fill(t.moreToGo || "__COUNT__ more to go", { COUNT: remaining }) : t.complete || "Complete";
|
|
3280
3306
|
}
|
|
3307
|
+
function fillPlural(map, count, locale) {
|
|
3308
|
+
const form = new Intl.PluralRules(locale || "en").select(count);
|
|
3309
|
+
return fill(map[form] || map.other || "__COUNT__", { COUNT: count });
|
|
3310
|
+
}
|
|
3311
|
+
function doorLabel(anyPicks, t) {
|
|
3312
|
+
return anyPicks ? t.doorContinue || "Continue building" : t.doorChoose || "Choose your products";
|
|
3313
|
+
}
|
|
3314
|
+
function doorSubLabel(anyPicks, remaining, total, t) {
|
|
3315
|
+
if (!anyPicks) {
|
|
3316
|
+
const quick = t.doorQuickSteps;
|
|
3317
|
+
if (typeof quick === "string") return fill(quick, { COUNT: total });
|
|
3318
|
+
return fillPlural(
|
|
3319
|
+
quick || { one: "__COUNT__ quick step", other: "__COUNT__ quick steps" },
|
|
3320
|
+
total,
|
|
3321
|
+
t.locale
|
|
3322
|
+
);
|
|
3323
|
+
}
|
|
3324
|
+
return fillPlural(
|
|
3325
|
+
t.doorStepsToGo || {
|
|
3326
|
+
one: "__COUNT__ step to go",
|
|
3327
|
+
other: "__COUNT__ steps to go"
|
|
3328
|
+
},
|
|
3329
|
+
remaining,
|
|
3330
|
+
t.locale
|
|
3331
|
+
);
|
|
3332
|
+
}
|
|
3281
3333
|
|
|
3282
3334
|
// ../render/src/multi-step/rules.ts
|
|
3283
3335
|
function unitsInStep(selections, i) {
|
|
@@ -3339,20 +3391,28 @@ function updateStepGroups(deps) {
|
|
|
3339
3391
|
const { container, steps, selections, t } = deps;
|
|
3340
3392
|
for (let i = 0; i < steps.length; i++) {
|
|
3341
3393
|
const min = steps[i].minQuantity || 1;
|
|
3342
|
-
const
|
|
3343
|
-
'[data-step-
|
|
3394
|
+
const section = container.querySelector(
|
|
3395
|
+
'[data-step-group="' + i + '"]'
|
|
3344
3396
|
);
|
|
3345
|
-
if (
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
t
|
|
3350
|
-
);
|
|
3351
|
-
countEl.classList.toggle(
|
|
3352
|
-
"lb-multi-step__group-count--met",
|
|
3353
|
-
stepSatisfied(selections, steps, i)
|
|
3397
|
+
if (section) {
|
|
3398
|
+
section.setAttribute(
|
|
3399
|
+
"data-step-mode",
|
|
3400
|
+
selections[i].length > 0 ? "open" : "row"
|
|
3354
3401
|
);
|
|
3355
3402
|
}
|
|
3403
|
+
const countLabel = ofSelectedLabel(
|
|
3404
|
+
Math.min(unitsInStep(selections, i), min),
|
|
3405
|
+
min,
|
|
3406
|
+
t
|
|
3407
|
+
);
|
|
3408
|
+
const met = stepSatisfied(selections, steps, i);
|
|
3409
|
+
const countEls = container.querySelectorAll(
|
|
3410
|
+
'[data-step-count="' + i + '"]'
|
|
3411
|
+
);
|
|
3412
|
+
for (let c = 0; c < countEls.length; c++) {
|
|
3413
|
+
countEls[c].textContent = countLabel;
|
|
3414
|
+
countEls[c].classList.toggle("lb-multi-step__group-count--met", met);
|
|
3415
|
+
}
|
|
3356
3416
|
const slotsWrap = container.querySelector(
|
|
3357
3417
|
'[data-step-slots="' + i + '"]'
|
|
3358
3418
|
);
|
|
@@ -3374,14 +3434,50 @@ function updateStepGroups(deps) {
|
|
|
3374
3434
|
);
|
|
3375
3435
|
}
|
|
3376
3436
|
}
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3437
|
+
}
|
|
3438
|
+
function updateDoor(deps) {
|
|
3439
|
+
const { container, steps, selections, t } = deps;
|
|
3440
|
+
const door = container.querySelector("[data-step-door]");
|
|
3441
|
+
if (!door) return;
|
|
3442
|
+
let firstUnsatisfied = -1;
|
|
3443
|
+
let remaining = 0;
|
|
3444
|
+
let anyPicks = false;
|
|
3445
|
+
for (let i = 0; i < steps.length; i++) {
|
|
3446
|
+
if (selections[i].length > 0) anyPicks = true;
|
|
3447
|
+
if (!stepSatisfied(selections, steps, i)) {
|
|
3448
|
+
remaining += 1;
|
|
3449
|
+
if (firstUnsatisfied === -1) firstUnsatisfied = i;
|
|
3383
3450
|
}
|
|
3384
3451
|
}
|
|
3452
|
+
if (firstUnsatisfied === -1) {
|
|
3453
|
+
door.style.display = "none";
|
|
3454
|
+
door.classList.add("lb-multi-step__door--hidden");
|
|
3455
|
+
const parent = door.parentElement;
|
|
3456
|
+
if (parent && parent.firstElementChild !== door) {
|
|
3457
|
+
parent.insertBefore(door, parent.firstElementChild);
|
|
3458
|
+
}
|
|
3459
|
+
return;
|
|
3460
|
+
}
|
|
3461
|
+
door.style.display = "";
|
|
3462
|
+
door.classList.remove("lb-multi-step__door--hidden");
|
|
3463
|
+
door.setAttribute("data-step-door", String(firstUnsatisfied));
|
|
3464
|
+
const label = doorLabel(anyPicks, t);
|
|
3465
|
+
const labelEl = door.querySelector(
|
|
3466
|
+
".lb-mix-match__add-product-label"
|
|
3467
|
+
);
|
|
3468
|
+
if (labelEl) labelEl.textContent = label;
|
|
3469
|
+
const subEl = door.querySelector(".lb-multi-step__door-sub");
|
|
3470
|
+
if (subEl) {
|
|
3471
|
+
subEl.textContent = doorSubLabel(anyPicks, remaining, steps.length, t);
|
|
3472
|
+
}
|
|
3473
|
+
const stepName = steps[firstUnsatisfied].name || "";
|
|
3474
|
+
door.setAttribute("aria-label", stepName ? label + ": " + stepName : label);
|
|
3475
|
+
const target = container.querySelector(
|
|
3476
|
+
'[data-step-group="' + firstUnsatisfied + '"]'
|
|
3477
|
+
);
|
|
3478
|
+
if (target && target.parentElement && target.previousElementSibling !== door) {
|
|
3479
|
+
target.parentElement.insertBefore(door, target);
|
|
3480
|
+
}
|
|
3385
3481
|
}
|
|
3386
3482
|
function updatePricing3(deps, data, calcDiscount, paint) {
|
|
3387
3483
|
const { container, steps, selections } = deps;
|
|
@@ -3598,6 +3694,12 @@ function createWizard(deps) {
|
|
|
3598
3694
|
for (const r of rows) r.refresh();
|
|
3599
3695
|
updateModalMeta();
|
|
3600
3696
|
}
|
|
3697
|
+
function maybeAutoAdvance() {
|
|
3698
|
+
if (!deps.autoAdvance) return;
|
|
3699
|
+
if (stepIndex >= steps.length - 1) return;
|
|
3700
|
+
if (stepHeadroom(selections, steps, stepIndex) !== 0) return;
|
|
3701
|
+
goToStep(stepIndex + 1);
|
|
3702
|
+
}
|
|
3601
3703
|
function buildProductList(forStep) {
|
|
3602
3704
|
if (!modalList) return;
|
|
3603
3705
|
deps.dropdown?.unbindAll(modalList);
|
|
@@ -3614,6 +3716,7 @@ function createWizard(deps) {
|
|
|
3614
3716
|
onCommittedQtyChanged: () => {
|
|
3615
3717
|
deps.onSelectionChanged();
|
|
3616
3718
|
refresh();
|
|
3719
|
+
maybeAutoAdvance();
|
|
3617
3720
|
}
|
|
3618
3721
|
});
|
|
3619
3722
|
rows.push(row);
|
|
@@ -3693,6 +3796,7 @@ function createWizard(deps) {
|
|
|
3693
3796
|
selections[stepIndex].push(newItem);
|
|
3694
3797
|
deps.onSelectionChanged();
|
|
3695
3798
|
refresh();
|
|
3799
|
+
maybeAutoAdvance();
|
|
3696
3800
|
}
|
|
3697
3801
|
if (modalList) modalList.addEventListener("click", onListClick);
|
|
3698
3802
|
function buildFilters(forStep) {
|
|
@@ -3825,10 +3929,12 @@ function createWizard(deps) {
|
|
|
3825
3929
|
setTimeout(() => {
|
|
3826
3930
|
if (!modalOpen) overlay.style.display = "none";
|
|
3827
3931
|
}, CLOSE_TRANSITION_MS2);
|
|
3828
|
-
const
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3932
|
+
const visible = (el2) => el2 && el2.offsetParent !== null ? el2 : null;
|
|
3933
|
+
const elToFocus = visible(
|
|
3934
|
+
container.querySelector(
|
|
3935
|
+
'[data-step-row="' + stepIndex + '"]'
|
|
3936
|
+
)
|
|
3937
|
+
) || visible(container.querySelector("[data-step-door]")) || deps.ctaButton;
|
|
3832
3938
|
if (elToFocus && typeof elToFocus.focus === "function") {
|
|
3833
3939
|
setTimeout(() => elToFocus.focus(), 0);
|
|
3834
3940
|
}
|
|
@@ -3881,6 +3987,29 @@ function createWizard(deps) {
|
|
|
3881
3987
|
}
|
|
3882
3988
|
|
|
3883
3989
|
// src/renderers/multi-step.ts
|
|
3990
|
+
function buildPlusIcon() {
|
|
3991
|
+
const NS = "http://www.w3.org/2000/svg";
|
|
3992
|
+
const svg = document.createElementNS(NS, "svg");
|
|
3993
|
+
svg.setAttribute("width", "18");
|
|
3994
|
+
svg.setAttribute("height", "18");
|
|
3995
|
+
svg.setAttribute("viewBox", "0 0 18 18");
|
|
3996
|
+
svg.setAttribute("fill", "none");
|
|
3997
|
+
for (const [x1, y1, x2, y2] of [
|
|
3998
|
+
["9", "3", "9", "15"],
|
|
3999
|
+
["3", "9", "15", "9"]
|
|
4000
|
+
]) {
|
|
4001
|
+
const line = document.createElementNS(NS, "line");
|
|
4002
|
+
line.setAttribute("x1", x1);
|
|
4003
|
+
line.setAttribute("y1", y1);
|
|
4004
|
+
line.setAttribute("x2", x2);
|
|
4005
|
+
line.setAttribute("y2", y2);
|
|
4006
|
+
line.setAttribute("stroke", "currentColor");
|
|
4007
|
+
line.setAttribute("stroke-width", "2");
|
|
4008
|
+
line.setAttribute("stroke-linecap", "round");
|
|
4009
|
+
svg.appendChild(line);
|
|
4010
|
+
}
|
|
4011
|
+
return svg;
|
|
4012
|
+
}
|
|
3884
4013
|
function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
3885
4014
|
const wc = bundle.widgetConfig;
|
|
3886
4015
|
const t = DEFAULT_STRINGS;
|
|
@@ -3935,31 +4064,65 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
3935
4064
|
shell.products.before(buildProgressBar(steps.length));
|
|
3936
4065
|
const groups = document.createElement("div");
|
|
3937
4066
|
groups.className = "lb-multi-step__groups";
|
|
4067
|
+
groups.setAttribute("data-step-groups", "");
|
|
4068
|
+
const door = document.createElement("button");
|
|
4069
|
+
door.type = "button";
|
|
4070
|
+
door.className = "lb-mix-match__add-product lb-multi-step__door";
|
|
4071
|
+
door.setAttribute("data-step-door", "0");
|
|
4072
|
+
const doorIcon = document.createElement("span");
|
|
4073
|
+
doorIcon.className = "lb-mix-match__add-product-icon";
|
|
4074
|
+
doorIcon.setAttribute("aria-hidden", "true");
|
|
4075
|
+
doorIcon.appendChild(buildPlusIcon());
|
|
4076
|
+
door.appendChild(doorIcon);
|
|
4077
|
+
const doorCopy = document.createElement("span");
|
|
4078
|
+
doorCopy.className = "lb-multi-step__door-copy";
|
|
4079
|
+
const doorLabel2 = document.createElement("span");
|
|
4080
|
+
doorLabel2.className = "lb-mix-match__add-product-label";
|
|
4081
|
+
doorCopy.appendChild(doorLabel2);
|
|
4082
|
+
const doorSub = document.createElement("span");
|
|
4083
|
+
doorSub.className = "lb-multi-step__door-sub";
|
|
4084
|
+
doorCopy.appendChild(doorSub);
|
|
4085
|
+
door.appendChild(doorCopy);
|
|
4086
|
+
groups.appendChild(door);
|
|
3938
4087
|
steps.forEach((step, i) => {
|
|
3939
|
-
const group = document.createElement("
|
|
4088
|
+
const group = document.createElement("section");
|
|
3940
4089
|
group.className = "lb-multi-step__group";
|
|
3941
4090
|
group.setAttribute("data-step-group", String(i));
|
|
4091
|
+
group.setAttribute("data-step-mode", "row");
|
|
4092
|
+
const buildCount = () => {
|
|
4093
|
+
const count = document.createElement("span");
|
|
4094
|
+
count.className = "lb-multi-step__group-count";
|
|
4095
|
+
count.setAttribute("data-step-count", String(i));
|
|
4096
|
+
return count;
|
|
4097
|
+
};
|
|
4098
|
+
const row = document.createElement("button");
|
|
4099
|
+
row.type = "button";
|
|
4100
|
+
row.className = "lb-multi-step__step-row";
|
|
4101
|
+
row.setAttribute("data-step-row", String(i));
|
|
4102
|
+
row.setAttribute("aria-label", "Choose products: " + step.name);
|
|
4103
|
+
const ix = document.createElement("span");
|
|
4104
|
+
ix.className = "lb-multi-step__step-ix";
|
|
4105
|
+
ix.setAttribute("aria-hidden", "true");
|
|
4106
|
+
ix.textContent = String(i + 1);
|
|
4107
|
+
row.appendChild(ix);
|
|
4108
|
+
const rowName = document.createElement("span");
|
|
4109
|
+
rowName.className = "lb-multi-step__group-name";
|
|
4110
|
+
rowName.textContent = step.name;
|
|
4111
|
+
row.appendChild(rowName);
|
|
4112
|
+
row.appendChild(buildCount());
|
|
4113
|
+
group.appendChild(row);
|
|
3942
4114
|
const heading = document.createElement("div");
|
|
3943
4115
|
heading.className = "lb-multi-step__group-heading";
|
|
3944
4116
|
const name = document.createElement("span");
|
|
3945
4117
|
name.className = "lb-multi-step__group-name";
|
|
3946
4118
|
name.textContent = step.name;
|
|
3947
4119
|
heading.appendChild(name);
|
|
3948
|
-
|
|
3949
|
-
count.className = "lb-multi-step__group-count";
|
|
3950
|
-
count.setAttribute("data-step-count", String(i));
|
|
3951
|
-
heading.appendChild(count);
|
|
4120
|
+
heading.appendChild(buildCount());
|
|
3952
4121
|
group.appendChild(heading);
|
|
3953
4122
|
const slots = document.createElement("div");
|
|
3954
|
-
slots.className = "lb-mix-match__slots lb-edge-fade";
|
|
4123
|
+
slots.className = "lb-mix-match__slots lb-edge-fade lb-multi-step__group-slots";
|
|
3955
4124
|
slots.setAttribute("data-step-slots", String(i));
|
|
3956
4125
|
group.appendChild(slots);
|
|
3957
|
-
const trigger = document.createElement("button");
|
|
3958
|
-
trigger.type = "button";
|
|
3959
|
-
trigger.className = "lb-mix-match__add-product";
|
|
3960
|
-
trigger.setAttribute("data-step-trigger", String(i));
|
|
3961
|
-
trigger.textContent = "Add a product";
|
|
3962
|
-
group.appendChild(trigger);
|
|
3963
4126
|
groups.appendChild(group);
|
|
3964
4127
|
});
|
|
3965
4128
|
shell.products.replaceWith(groups);
|
|
@@ -3996,6 +4159,7 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
3996
4159
|
};
|
|
3997
4160
|
function updateAll() {
|
|
3998
4161
|
updateStepGroups(bodyDeps);
|
|
4162
|
+
updateDoor(bodyDeps);
|
|
3999
4163
|
updatePricing3(
|
|
4000
4164
|
bodyDeps,
|
|
4001
4165
|
{
|
|
@@ -4016,6 +4180,8 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
4016
4180
|
rulesMap,
|
|
4017
4181
|
showQtySelector: wc.mixMatchShowQuantitySelector !== false,
|
|
4018
4182
|
showTypeFilters: wc.mixMatchShowTypeFilters !== false,
|
|
4183
|
+
// Off by default: a stored config predating the key must not advance.
|
|
4184
|
+
autoAdvance: wc.multiStepAutoAdvance === true,
|
|
4019
4185
|
formatMoney,
|
|
4020
4186
|
dropdown: void 0,
|
|
4021
4187
|
portalTarget: null,
|
|
@@ -4042,10 +4208,14 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
|
|
|
4042
4208
|
},
|
|
4043
4209
|
canRemove: (item) => canRemovePick2(selections, item, rulesMap)
|
|
4044
4210
|
});
|
|
4045
|
-
|
|
4211
|
+
door.addEventListener("click", () => {
|
|
4212
|
+
if (wizard.isOpen()) return;
|
|
4213
|
+
wizard.open(parseInt(door.getAttribute("data-step-door") ?? "", 10) || 0);
|
|
4214
|
+
});
|
|
4215
|
+
shell.root.querySelectorAll("[data-step-row]").forEach((el2) => {
|
|
4046
4216
|
el2.addEventListener("click", () => {
|
|
4047
4217
|
if (wizard.isOpen()) return;
|
|
4048
|
-
wizard.open(parseInt(el2.getAttribute("data-step-
|
|
4218
|
+
wizard.open(parseInt(el2.getAttribute("data-step-row") ?? "", 10) || 0);
|
|
4049
4219
|
});
|
|
4050
4220
|
});
|
|
4051
4221
|
shell.cta.addEventListener("click", () => {
|
|
@@ -6239,12 +6409,19 @@ var BUNDLE_MULTI_STEP_CSS = `/**
|
|
|
6239
6409
|
* Canon: WIDGET-DESIGN.md (spacing scale, radius system, chip family).
|
|
6240
6410
|
*/
|
|
6241
6411
|
|
|
6242
|
-
/* \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
|
|
6412
|
+
/* \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
|
|
6413
|
+
One dashed door + one section per step. A step without picks shows a
|
|
6414
|
+
slim checklist row; a step with picks shows the heading + chosen
|
|
6415
|
+
cards. data-step-mode ("row" | "open") on the section picks the
|
|
6416
|
+
representation \u2014 both are in the markup, CSS hides the other, so the
|
|
6417
|
+
server-rendered untouched state IS the hydrated no-selection state.
|
|
6418
|
+
Spacing is per-pair rather than a flat gap: consecutive rows sit
|
|
6419
|
+
flush (hairline-separated), everything else breathes 16px. */
|
|
6243
6420
|
|
|
6244
6421
|
.lb-multi-step__groups {
|
|
6245
6422
|
display: flex;
|
|
6246
6423
|
flex-direction: column;
|
|
6247
|
-
gap:
|
|
6424
|
+
gap: 0;
|
|
6248
6425
|
}
|
|
6249
6426
|
|
|
6250
6427
|
.lb-multi-step__group {
|
|
@@ -6253,8 +6430,117 @@ var BUNDLE_MULTI_STEP_CSS = `/**
|
|
|
6253
6430
|
gap: 8px;
|
|
6254
6431
|
}
|
|
6255
6432
|
|
|
6433
|
+
.lb-multi-step__group + .lb-multi-step__group {
|
|
6434
|
+
margin-top: 16px;
|
|
6435
|
+
}
|
|
6436
|
+
|
|
6437
|
+
/* A run of empty-step rows reads as one checklist: flush, hairlines
|
|
6438
|
+
between (the first row of a run keeps no border). */
|
|
6439
|
+
.lb-multi-step__group[data-step-mode="row"] + .lb-multi-step__group[data-step-mode="row"] {
|
|
6440
|
+
margin-top: 0;
|
|
6441
|
+
}
|
|
6442
|
+
|
|
6443
|
+
.lb-multi-step__group[data-step-mode="row"]
|
|
6444
|
+
+ .lb-multi-step__group[data-step-mode="row"]
|
|
6445
|
+
.lb-multi-step__step-row {
|
|
6446
|
+
border-top: var(--lb-border-width) solid var(--lb-border);
|
|
6447
|
+
}
|
|
6448
|
+
|
|
6449
|
+
/* Mode switch: a row-mode step hides its open chrome and vice versa. */
|
|
6450
|
+
.lb-multi-step__group[data-step-mode="row"] .lb-multi-step__group-heading,
|
|
6451
|
+
.lb-multi-step__group[data-step-mode="row"] .lb-multi-step__group-slots {
|
|
6452
|
+
display: none;
|
|
6453
|
+
}
|
|
6454
|
+
|
|
6455
|
+
.lb-multi-step__group[data-step-mode="open"] .lb-multi-step__step-row {
|
|
6456
|
+
display: none;
|
|
6457
|
+
}
|
|
6458
|
+
|
|
6459
|
+
/* Checklist row \u2014 the empty step's whole representation, and a tap
|
|
6460
|
+
target that deep-links the wizard to that step. Quiet by design: the
|
|
6461
|
+
door above it is the primary action. */
|
|
6462
|
+
.lb-multi-step__step-row {
|
|
6463
|
+
display: flex;
|
|
6464
|
+
align-items: center;
|
|
6465
|
+
gap: 12px;
|
|
6466
|
+
width: 100%;
|
|
6467
|
+
min-height: 48px;
|
|
6468
|
+
padding: 10px 2px;
|
|
6469
|
+
background: none;
|
|
6470
|
+
border: none;
|
|
6471
|
+
font-family: inherit;
|
|
6472
|
+
text-align: left;
|
|
6473
|
+
cursor: pointer;
|
|
6474
|
+
box-sizing: border-box;
|
|
6475
|
+
transition: background-color 0.25s ease;
|
|
6476
|
+
}
|
|
6477
|
+
|
|
6478
|
+
.lb-multi-step__step-row:hover {
|
|
6479
|
+
background: color-mix(in srgb, var(--lb-text) 3%, transparent);
|
|
6480
|
+
}
|
|
6481
|
+
|
|
6482
|
+
.lb-multi-step__step-row:focus-visible {
|
|
6483
|
+
outline: 2px solid var(--lb-primary-color);
|
|
6484
|
+
outline-offset: -2px;
|
|
6485
|
+
border-radius: var(--lb-radius-sm);
|
|
6486
|
+
}
|
|
6487
|
+
|
|
6488
|
+
.lb-multi-step__step-row .lb-multi-step__group-count {
|
|
6489
|
+
margin-left: auto;
|
|
6490
|
+
}
|
|
6491
|
+
|
|
6492
|
+
/* Step number \u2014 quiet index, tabular so multi-digit lists align. */
|
|
6493
|
+
.lb-multi-step__step-ix {
|
|
6494
|
+
width: 18px;
|
|
6495
|
+
min-width: 18px;
|
|
6496
|
+
font-size: 12px;
|
|
6497
|
+
font-weight: 500;
|
|
6498
|
+
color: color-mix(in srgb, var(--lb-text) 45%, transparent);
|
|
6499
|
+
font-variant-numeric: tabular-nums;
|
|
6500
|
+
}
|
|
6501
|
+
|
|
6502
|
+
/* The door \u2014 the single wizard entry point, reusing the dashed
|
|
6503
|
+
add-product recipe with a two-line label. JS moves it directly above
|
|
6504
|
+
the first unsatisfied step and hides it once every step is met. The
|
|
6505
|
+
add-product recipe's own margin-top is for its mix & match position
|
|
6506
|
+
(below the slot list); here the pair rules own all spacing. */
|
|
6507
|
+
.lb-multi-step__door {
|
|
6508
|
+
margin-top: 0;
|
|
6509
|
+
}
|
|
6510
|
+
|
|
6511
|
+
.lb-multi-step__door + .lb-multi-step__group {
|
|
6512
|
+
margin-top: 12px;
|
|
6513
|
+
}
|
|
6514
|
+
|
|
6515
|
+
.lb-multi-step__door + .lb-multi-step__group[data-step-mode="row"] {
|
|
6516
|
+
margin-top: 4px;
|
|
6517
|
+
}
|
|
6518
|
+
|
|
6519
|
+
.lb-multi-step__group + .lb-multi-step__door {
|
|
6520
|
+
margin-top: 16px;
|
|
6521
|
+
}
|
|
6522
|
+
|
|
6523
|
+
/* A hidden door is parked as the container's first child (updateDoor), so
|
|
6524
|
+
the group after it is really the first visible element \u2014 no door gap. */
|
|
6525
|
+
.lb-multi-step__door--hidden:first-child + .lb-multi-step__group {
|
|
6526
|
+
margin-top: 0;
|
|
6527
|
+
}
|
|
6528
|
+
|
|
6529
|
+
.lb-multi-step__door-copy {
|
|
6530
|
+
display: flex;
|
|
6531
|
+
flex-direction: column;
|
|
6532
|
+
gap: 2px;
|
|
6533
|
+
}
|
|
6534
|
+
|
|
6535
|
+
.lb-multi-step__door-sub {
|
|
6536
|
+
font-size: 13px;
|
|
6537
|
+
font-weight: 400;
|
|
6538
|
+
line-height: 1.2;
|
|
6539
|
+
color: color-mix(in srgb, var(--lb-text) 55%, transparent);
|
|
6540
|
+
}
|
|
6541
|
+
|
|
6256
6542
|
/* Heading is a quiet, non-interactive row: step name left, live count
|
|
6257
|
-
chip right. The step's
|
|
6543
|
+
chip right. The step's chosen cards below are the edit targets. */
|
|
6258
6544
|
.lb-multi-step__group-heading {
|
|
6259
6545
|
display: flex;
|
|
6260
6546
|
align-items: center;
|