@inputkit/react
v0.2.0
Published
React hooks for formatted inputs: payment cards, TOTP/OTP codes, and custom formatted fields.
Maintainers
Readme
@inputkit/react
React hooks for formatted inputs. Payment cards, TOTP codes, or anything
that needs formatting and validation. Prop getters spread directly onto
<input> or shadcn <Input>.
Payment card inputs
import { usePaymentInputs } from "@inputkit/react";
function PaymentForm() {
const {
getCardNumberProps,
getExpiryDateProps,
getCVCProps,
meta,
} = usePaymentInputs();
return (
<form onSubmit={() => submit(meta.values)}>
<input {...getCardNumberProps()} />
<input {...getExpiryDateProps()} />
<input {...getCVCProps()} />
{meta.cardType && <span>{meta.cardType.displayName}</span>}
{meta.error && <span>{meta.error}</span>}
</form>
);
}TOTP / OTP codes
import { useSegmentedInput } from "@inputkit/react";
function OTPInput() {
const { getInputProps, slots } = useSegmentedInput({
maxLength: 6,
onComplete: (code) => verify(code),
});
return (
<div style={{ position: "relative" }}>
<input {...getInputProps()} />
<div style={{ display: "flex", gap: 8 }}>
{slots.map((slot, i) => (
<div key={i}>{slot.char || (slot.hasFakeCaret ? "|" : "")}</div>
))}
</div>
</div>
);
}Custom formatted input
import { useFormattedInput } from "@inputkit/react";
import { formatCardNumber, stripNonDigits } from "@inputkit/core";
function CardInput() {
const { getInputProps, meta } = useFormattedInput({
format: (v) => formatCardNumber(v),
parse: stripNonDigits,
accept: /\d/,
maxLength: 16,
});
return (
<>
<input {...getInputProps({ placeholder: "Card number" })} />
{meta.isComplete && <span>Card type: {meta.rawValue}</span>}
</>
);
}Controlled mode
Every hook supports controlled values for integration with form libraries:
const [card, setCard] = useState("");
const { getCardNumberProps } = usePaymentInputs({
cardNumber: card,
onChangeCardNumber: setCard,
});