This commit is contained in:
parent
824f038084
commit
3efb87bcd8
24 changed files with 14 additions and 19 deletions
173
app/validating-input-field.tsx
Normal file
173
app/validating-input-field.tsx
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
import React, {ChangeEventHandler, useState} from 'react';
|
||||
|
||||
export function ValidatingInputBigIntField({
|
||||
id,
|
||||
label,
|
||||
value = 0n,
|
||||
constraints = undefined,
|
||||
validatorFn = (value) => {
|
||||
return {valid: true, value: BigInt(value)};
|
||||
},
|
||||
disabled = false,
|
||||
onChange = () => {
|
||||
}
|
||||
}:
|
||||
{
|
||||
id: string;
|
||||
label: string;
|
||||
value?: bigint;
|
||||
constraints?: { min?: bigint; max?: bigint; };
|
||||
validatorFn: ValidatorFunction<string, bigint>;
|
||||
disabled: boolean;
|
||||
onChange: (v: bigint) => void;
|
||||
}) {
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
const value = e.target.value;
|
||||
const validation = validatorFn(value);
|
||||
if (!validation.valid) {
|
||||
setError(validation.message);
|
||||
} else {
|
||||
setError(undefined);
|
||||
}
|
||||
if (validation.value !== undefined) {
|
||||
onChange(validation.value);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={id}>{label}: </label>
|
||||
<input id={id}
|
||||
type={"number"}
|
||||
onChange={handleValueChange}
|
||||
value={value?.toString() || ""}
|
||||
min={constraints?.min?.toString()}
|
||||
max={constraints?.max?.toString()}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<span>{error}</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function ValidatingInputNumberField({
|
||||
id,
|
||||
label,
|
||||
value = 0,
|
||||
constraints = undefined,
|
||||
validatorFn = (value) => {
|
||||
return {valid: true, value: Number(value)};
|
||||
},
|
||||
disabled = false,
|
||||
onChange = () => {
|
||||
}
|
||||
}:
|
||||
{
|
||||
id: string;
|
||||
label: string;
|
||||
value?: number;
|
||||
constraints?: { min?: number; max?: number; };
|
||||
validatorFn: ValidatorFunction<string, number>;
|
||||
disabled: boolean;
|
||||
onChange: (v: number) => void;
|
||||
}) {
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
const value = e.target.value;
|
||||
const validation = validatorFn(value);
|
||||
if (!validation.valid) {
|
||||
setError(validation.message);
|
||||
} else {
|
||||
setError(undefined);
|
||||
}
|
||||
if (validation.value) {
|
||||
onChange(validation.value);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={id}>{label}: </label>
|
||||
<input id={id}
|
||||
type={"number"}
|
||||
onChange={handleValueChange}
|
||||
value={value || ""}
|
||||
min={constraints?.min}
|
||||
max={constraints?.max}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<span>{error}</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function ValidatingInputRegExpField({
|
||||
id,
|
||||
label,
|
||||
value = undefined,
|
||||
constraints = undefined,
|
||||
validatorFn = (value) => {
|
||||
if (constraints === undefined) {
|
||||
console.log("no constraints, returning VALID")
|
||||
return {valid: true, value};
|
||||
}
|
||||
const allValid = constraints
|
||||
.map(expr => expr.test(value))
|
||||
.reduce((prev, curr) => prev && curr)
|
||||
?? true;
|
||||
console.log("valid?", allValid);
|
||||
return {valid: allValid, value: allValid ? value : undefined};
|
||||
},
|
||||
disabled = false,
|
||||
onChange = () => {
|
||||
},
|
||||
placeholder = ""
|
||||
}:
|
||||
{
|
||||
id: string;
|
||||
label: string;
|
||||
value?: string;
|
||||
constraints?: RegExp[];
|
||||
validatorFn?: ValidatorFunction<string, string>;
|
||||
disabled: boolean;
|
||||
onChange: (v: string) => void;
|
||||
placeholder?: string;
|
||||
}) {
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
const value = e.target.value;
|
||||
const validation = validatorFn(value);
|
||||
if (!validation.valid) {
|
||||
setError(validation.message);
|
||||
} else {
|
||||
setError(undefined);
|
||||
}
|
||||
if (validation.value !== undefined) {
|
||||
console.log("setting value to:", validation.value);
|
||||
onChange(validation.value);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={id}>{label}: </label>
|
||||
<input id={id}
|
||||
type={"text"}
|
||||
placeholder={placeholder}
|
||||
onChange={handleValueChange}
|
||||
value={value?.toString() || ""}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<span>{error}</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export interface Validation<T> {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
value?: T;
|
||||
}
|
||||
|
||||
export type ValidatorFunction<I, T> = (v: I) => Validation<T>;
|
||||
Loading…
Add table
Add a link
Reference in a new issue