Hour meter input
An engine's or a generator's hour meter reading, typed as the meter shows it, with the hours run since the last reading and a question when it cannot be right.
On this page
Code
import { HourMeterInput } from "@bosunkit/components/hour-meter-input";
import { useState, type Dispatch, type ReactElement, type SetStateAction } from "react";
export const description: string =
"An engine log's hour meter, read yesterday at 1234.5 hr: today's reading says the hours run since, and one that " +
"gains more hours than have passed is questioned.";
export default function Showcase(): ReactElement {
const [hours, setHours]: [number | null, Dispatch<SetStateAction<number | null>>] = useState<number | null>(1324.5);
return (
<div style={{ width: "100%", maxWidth: 420 }}>
<HourMeterInput
label="Main engine hours"
previous={{ hours: 1234.5, at: "2026-10-10T12:00:00.000Z" }}
now={Date.parse("2026-10-11T12:00:00.000Z")}
value={hours}
onValueChange={setHours}
/>
</div>
);
}
An hour meter input holds a reading of an engine's or a generator's hour meter, the figure maintenance is due by. It reads the reading as the meter shows it: decimal hours with a point or a comma, 1234.5, or hours and minutes as a meter with a clock face shows them, 1234:30, with or without an hours symbol after it. It holds the reading to the tenth of an hour a meter's last figure shows, and writes it so, with hr after it.
Given the reading before it, previous, the field writes the hours run since under it: "5.5 hr since the last
reading on 10 October 2026". It questions a reading that cannot be right in an attention message. A reading below
the last one is questioned, since a meter does not run backwards. So is one that gains more hours than have passed
since the last reading's time. The reading is kept in both cases, because a new or reset meter starts again from zero,
and the crew may know why. Minutes past 59, or text the field cannot read, keep their text and name the problem,
and the field reports no reading until it is fixed, so a form never saves the one that stood before.
Examples
Empty
Code
import { HourMeterInput } from "@bosunkit/components/hour-meter-input";
import type { ReactElement } from "react";
export const description: string = "Empty, with no reading before it: the hint says what to write.";
export default function Empty(): ReactElement {
return <HourMeterInput label="Generator hours" hint="As the meter shows it, such as 812.4 or 812:25" />;
}
Hours since the last reading
Code
import { HourMeterInput } from "@bosunkit/components/hour-meter-input";
import type { ReactElement } from "react";
export const description: string = "With the reading before it: the hours run since that reading, under the field.";
export default function Since(): ReactElement {
return (
<HourMeterInput
label="Main engine hours"
previous={{ hours: 1234.5, at: "2026-10-10T12:00:00.000Z" }}
now={Date.parse("2026-10-11T12:00:00.000Z")}
defaultValue={1240}
/>
);
}
Backwards
Code
import { HourMeterInput } from "@bosunkit/components/hour-meter-input";
import type { ReactElement } from "react";
export const description: string =
"A reading below the last one is questioned, since a meter does not run backwards, but kept: a new meter starts " +
"again from zero.";
export default function Backwards(): ReactElement {
return (
<HourMeterInput
label="Main engine hours"
previous={{ hours: 1234.5, at: "2026-10-10T12:00:00.000Z" }}
now={Date.parse("2026-10-11T12:00:00.000Z")}
defaultValue={1224.5}
/>
);
}
Invalid
Code
import { HourMeterInput } from "@bosunkit/components/hour-meter-input";
import type { ReactElement } from "react";
export const description: string =
"Minutes past 59 or text the field cannot read keep their text and say why once the crew leave the field.";
export default function Invalid(): ReactElement {
return (
<HourMeterInput
label="Main engine hours"
defaultValue={1234.5}
error="Minutes run from 0 to 59. Check the minutes."
/>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | undefined | – | The field's name on the outline, translated by the caller; omit it inside a FormField. |
| value | number | null | undefined | – | The reading in hours, to the tenth, or null for none. |
| defaultValue | number | null | undefined | – | The reading it starts with when the caller does not hold value. |
| onValueChange | ((hours: number | null) => void) | undefined | – | Called with the reading when the crew type one and leave the field; null when they clear it. |
| previous | HourMeterReading | undefined | – | The reading before this one, for the hours run since and the checks against it: a reading below it, or more hours since it than have passed, is questioned. |
| now | number | undefined | – | The current time in epoch milliseconds, in place of the clock's, for the hours passed since the last reading. |
| hint | string | undefined | – | Text under the field while there is no reading before this one, translated by the caller. |
| error | string | undefined | – | The caller's own error, shown in place of the field's. |
| required | boolean | undefined | – | Whether the field must hold a reading. |
| disabled | boolean | undefined | – | Whether the field takes no input. |
| readOnly | boolean | undefined | – | Whether the field shows its reading without letting the crew change it. |
| id | string | undefined | – | The input's id, for a Label's htmlFor. |
| name | string | undefined | – | The form field name; the form receives the hours. |
| aria-label | string | undefined | – | Names the input when there is no label. |
| className | string | undefined | – | Classes added to the field's root. |
| testId | string | undefined | – | data-testid on the field. |
| ref | Ref<HTMLInputElement> | undefined | – | The input element. |
| motion | MotionProp | undefined | – | How the error line moves; off by default, as FormField's. |
Related
- Quantity input: a length, a volume or a speed in the crew's unit.
- Duration input: a length of time rather than a meter's running total.