Extract NumberStepControl
This commit is contained in:
parent
f980d4d86d
commit
13fe0ee852
4 changed files with 134 additions and 83 deletions
74
frontend/src/components/basics/NumberStepControl.tsx
Normal file
74
frontend/src/components/basics/NumberStepControl.tsx
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import {Minus, Plus} from "lucide-react";
|
||||
import {defaultIconSize} from "./SvgIcon.tsx";
|
||||
|
||||
type NumberStepControlProps = {
|
||||
/** Current numeric value */
|
||||
value: number;
|
||||
/** Callback when value changes */
|
||||
onChange: (newValue: number) => void;
|
||||
/** Optional: minimum allowed value */
|
||||
min?: number;
|
||||
/** Optional: maximum allowed value */
|
||||
max?: number;
|
||||
/** Optional: step increment (default = 1) */
|
||||
step?: number;
|
||||
/** Optional: additional Tailwind classes */
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A compact number input with +/– buttons.
|
||||
* Removes native browser spinners and supports min/max limits.
|
||||
*/
|
||||
export function NumberStepControl({
|
||||
value,
|
||||
onChange,
|
||||
min = Number.NEGATIVE_INFINITY,
|
||||
max = Number.POSITIVE_INFINITY,
|
||||
step = 1,
|
||||
className = "",
|
||||
}: NumberStepControlProps) {
|
||||
const handleDecrease = () => {
|
||||
const newValue = Math.max(value - step, min);
|
||||
onChange(newValue);
|
||||
};
|
||||
|
||||
const handleIncrease = () => {
|
||||
const newValue = Math.min(value + step, max);
|
||||
onChange(newValue);
|
||||
};
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const num = Number(e.target.value);
|
||||
if (!isNaN(num)) onChange(Math.min(Math.max(num, min), max));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`flex items-center gap-2 ${className}`}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleDecrease}
|
||||
className="circular-container primary-button-bg"
|
||||
>
|
||||
<Minus size={defaultIconSize}/>
|
||||
</button>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
value={value}
|
||||
onChange={handleInputChange}
|
||||
className="w-16 text-center input-field"
|
||||
/>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleIncrease}
|
||||
className="circular-container primary-button-bg"
|
||||
>
|
||||
<Plus size={defaultIconSize}/>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue