diff --git a/app/static/mobile.css b/app/static/mobile.css index 62779a9..26f86ab 100644 --- a/app/static/mobile.css +++ b/app/static/mobile.css @@ -114,6 +114,44 @@ button.primary { gap: 8px; } +.stepper { + display: grid; + grid-template-columns: 48px minmax(64px, 1fr) 48px; + align-items: stretch; + min-height: 46px; + border: 1px solid #555; + border-radius: 7px; + overflow: hidden; + background: #303030; +} + +.stepper button { + min-height: 46px; + border: 0; + border-radius: 0; + background: #3a3a3a; + font-size: 22px; + line-height: 1; + padding: 0; +} + +.stepper button:first-child { + border-right: 1px solid #555; +} + +.stepper button:last-child { + border-left: 1px solid #555; +} + +.stepper output { + display: grid; + place-items: center; + min-width: 0; + padding: 0 8px; + color: #fff; + font-weight: 800; +} + .toggle-row { display: grid; grid-template-columns: 1fr 1fr; diff --git a/app/static/mobile.js b/app/static/mobile.js index 54596d7..a19dcd0 100644 --- a/app/static/mobile.js +++ b/app/static/mobile.js @@ -18,6 +18,12 @@ const fields = { message: document.getElementById("mobileMessage"), }; +const steppers = { + mobileCopies: { input: fields.copies, output: document.getElementById("mobileCopiesValue"), min: 1, max: 20, step: 1, suffix: "" }, + mobileFont: { input: fields.font, output: document.getElementById("mobileFontValue"), min: 2, max: 24, step: 0.5, suffix: " mm" }, + mobileMargin: { input: fields.margin, output: document.getElementById("mobileMarginValue"), min: 0, max: 20, step: 0.5, suffix: " mm" }, +}; + function estimateTextLengthMm(text, fontSize, margin, frame) { const lines = String(text || " ").split("\n"); const longest = lines.reduce((max, line) => Math.max(max, line.length), 0); @@ -25,6 +31,29 @@ function estimateTextLengthMm(text, fontSize, margin, frame) { return Math.min(300, Math.max(20, Math.ceil(textWidth + margin * 2 + (frame ? 4 : 0)))); } +function clamp(value, min, max) { + return Math.min(max, Math.max(min, value)); +} + +function formatStepperValue(value) { + return Number.isInteger(value) ? String(value) : value.toFixed(1).replace(".", ","); +} + +function syncStepper(id) { + const config = steppers[id]; + const value = Number(config.input.value); + config.output.textContent = `${formatStepperValue(value)}${config.suffix}`; +} + +function setStepperValue(id, value) { + const config = steppers[id]; + const rounded = Math.round(value / config.step) * config.step; + const next = clamp(rounded, config.min, config.max); + config.input.value = String(next); + syncStepper(id); + mobileDesign(); +} + function setMessage(text, type = "") { fields.message.textContent = text; fields.message.className = `message ${type}`; @@ -121,10 +150,20 @@ document.getElementById("mobileDetect").addEventListener("click", async () => { setMessage(`Band erkannt: ${payload.width} mm${bg}${text}`, "success"); }); -["text", "font", "margin", "frame", "bold", "align", "tape"].forEach((name) => { +["text", "frame", "bold", "align", "tape"].forEach((name) => { fields[name].addEventListener("input", () => { mobileDesign(); }); }); +document.querySelectorAll(".stepper").forEach((stepper) => { + const id = stepper.dataset.stepper; + stepper.querySelectorAll("button").forEach((button) => { + button.addEventListener("click", () => { + setStepperValue(id, Number(steppers[id].input.value) + Number(button.dataset.step)); + }); + }); + syncStepper(id); +}); + mobileDesign(); diff --git a/app/templates/mobile.html b/app/templates/mobile.html index a11ef85..350a96d 100644 --- a/app/templates/mobile.html +++ b/app/templates/mobile.html @@ -38,7 +38,12 @@