Number
Manual numeric text entry with optional bounds, plus first-class integer, positive, and float constraints.
Number is for manual numeric text entry — there is no track or thumb. For
pointer-driven dragging, use Slider instead. min and
max are optional, so Number suits unbounded values (iteration counts,
durations) as well as bounded precise entry.
Try it
Usage
const iterations = pp.number({
label: "Iterations",
value: 10,
min: 1,
max: 100,
step: 1,
});Configuration
interface NumberConfig extends BaseControlConfig {
value: number;
min?: number;
max?: number;
step?: number;
/** Restrict to whole numbers. Defaults to false (fractional values allowed). */
integer?: boolean;
/**
* Restrict to positive values (> 0). Defaults to false. Composes with
* `integer` — set both for a positive integer.
*/
positive?: boolean;
format?: (value: number) => string;
parse?: (text: string) => number;
}
interface NumberControl extends ValueControl<number, NumberConfig> {}Integers, positives, and floats
integer and positive are independent, composable flags rather than a single
enum, so any combination is expressible:
// Whole numbers only, may be zero or negative.
const offset = pp.number({
label: "Offset",
value: 0,
integer: true,
});
// Any positive real number.
const gain = pp.number({
label: "Gain",
value: 1.5,
positive: true,
});
// Positive whole numbers only.
const particleCount = pp.number({
label: "Particles",
value: 1000,
integer: true,
positive: true,
});
// Unrestricted float — the default when neither flag is set.
const exposure = pp.number({
label: "Exposure",
value: 0.5,
});Constraint violations follow the same out-of-range pattern as Slider:
- Constructor and
configure()throw whenvalueviolatesinteger,positive,min, ormax. - User input is corrected on commit — rounded to the nearest integer when
integeris set, clamped above zero whenpositiveis set. set()throws for a value violating any constraint rather than silently correcting it.
Optional limits
Because bounds are optional, you can remove one by clearing it through
configure():
iterations.configure({ max: undefined }); // removes the upper boundCustom parsing
parse converts typed text into a number; format renders the number back into
display text. Together they let a field accept human-friendly input like 1.5s:
const duration = pp.number({
label: "Duration",
value: 500,
min: 0,
parse(text) {
const normalized = text.trim().toLowerCase();
if (normalized.endsWith("ms")) {
return Number.parseFloat(normalized);
}
if (normalized.endsWith("s")) {
return Number.parseFloat(normalized) * 1000;
}
return Number.parseFloat(normalized);
},
format(value) {
return `${value} ms`;
},
});Typing 1.5s stores 1500; the field then displays 1500 ms.
Parsing errors are non-destructive
When parsing fails, the error is surfaced without immediately discarding the last valid value — users can correct their input without losing state.