From e922adcfd3a92109625a717f8c07e8b3502c3fc5 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Feb 2026 22:58:41 +0000 Subject: [PATCH] Extract NumberInput component with nudge buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extracts the number input with -/+ nudge buttons from the main calculator into a reusable NumberInput component, and uses it for the Maxes page weight inputs (with ±5 step). https://claude.ai/code/session_01GRvYTjGFpp5DbYqZNtfkFP --- src/App.tsx | 85 +++++++++++---------------------------------- src/NumberInput.tsx | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 65 deletions(-) create mode 100644 src/NumberInput.tsx diff --git a/src/App.tsx b/src/App.tsx index c851379..ec559e5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,9 +7,9 @@ import { import { useDeferredValue, useMemo } from "react"; import { useMassStorage, Bar, Max, Plate } from "./plate-db"; import MassConfig from "./MassConfig"; -import { useAutoRepeat } from "./useAutoRepeat"; import { useWeightSet } from "./useWeightSet"; import { numbdfined } from "./utils"; +import { NumberInput } from "./NumberInput"; import { HiddenDeleteFieldset } from "./HiddenDeleteFieldset"; import BarView from "./BarView"; import { Link, Route, Routes } from "react-router"; @@ -139,19 +139,6 @@ function BarComputer({ const weightSet = useWeightSet(); const inWeightSet = target != null && weightSet.weights.includes(target); - const nudgeDown = useAutoRepeat(() => { - const nudge = activeBar?.sliderMinStep; - if (nudge == null) return; - const prev = Math.ceil((target ?? 0) / nudge) * nudge - nudge; - if (weightMin != null && prev >= weightMin) dispatchState({ target: prev }); - }); - const nudgeUp = useAutoRepeat(() => { - const nudge = activeBar?.sliderMinStep; - if (nudge == null) return; - const next = Math.floor((target ?? 0) / nudge) * nudge + nudge; - if (weightMax != null && next <= weightMax) dispatchState({ target: next }); - }); - return ( <> - dispatchState({ target: numbdfined(e.target.value) }) - } - aria-invalid={!validTarget} - /> - {activeBar?.sliderMinStep != null && ( - - )} - + dispatchState({ target: v })} + step={activeBar?.sliderMinStep} + min={weightMin} + max={weightMax} + style={{ flex: 1 }} + id="target-number" + placeholder="work weight" + onFocus={clear} + onKeyDown={onEnterBlur} + onBlur={scrollToTop} + aria-invalid={!validTarget} + /> {target != null && ( + )} + onChange(numbdfined(e.target.value))} + {...inputProps} + /> + {step != null && ( + + )} + + ); +}