Compare commits
	
		
			2 commits
		
	
	
		
			9b52470f6b
			...
			79467e29f2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 79467e29f2 | |||
| 0dc5c28060 | 
					 3 changed files with 67 additions and 7 deletions
				
			
		|  | @ -10,6 +10,7 @@ import { | |||
| import styles from "./input-form.module.css"; | ||||
| import "./input-form.css"; | ||||
| import {State} from "@/app/state/state.ts"; | ||||
| import ValidatingInputBigIntField from "@/app/validating-input-bigint-field.tsx"; | ||||
| 
 | ||||
| export default function InputForm({state, dispatch}: { | ||||
|     state: State, | ||||
|  | @ -17,7 +18,7 @@ export default function InputForm({state, dispatch}: { | |||
| }) { | ||||
|     const [width, setWidth] = useState(10); | ||||
|     const [height, setHeight] = useState(10); | ||||
|     const [id, setId] = useState<number>(); | ||||
|     const [id, setId] = useState<bigint>(); | ||||
|     const [algorithm, setAlgorithm] = useState('wilson'); | ||||
| 
 | ||||
|     const handleSubmit = (e: FormEvent) => { | ||||
|  | @ -54,15 +55,14 @@ export default function InputForm({state, dispatch}: { | |||
|             value: numberValue | ||||
|         }; | ||||
|     }; | ||||
|     const validateIdInput: ValidatorFunction<string, number> = value => { | ||||
|     const validateIdInput: ValidatorFunction<string, bigint> = value => { | ||||
|         if ("" === value) { | ||||
|             return { | ||||
|                 valid: true | ||||
|             }; | ||||
|         } | ||||
|         const numberValue = Number(value); | ||||
|         // FIXME doesn't handle strings with characters correctly (e.g. "asdf" yields an empty value, due to "type=number").
 | ||||
|         if (isNaN(numberValue) || Math.floor(numberValue) !== numberValue) { | ||||
|         const numberValue = BigInt(value); | ||||
|         if (numberValue.toString() !== value.trim()) { | ||||
|             return { | ||||
|                 valid: false, | ||||
|                 message: "Must be empty or an integer" | ||||
|  | @ -96,7 +96,7 @@ export default function InputForm({state, dispatch}: { | |||
|                                             disabled={state.loading} | ||||
|                                             onChange={setHeight} | ||||
|                 /> | ||||
|                 <ValidatingInputNumberField id={"id"} | ||||
|                 <ValidatingInputBigIntField id={"id"} | ||||
|                                             label={"ID (optional)"} | ||||
|                                             value={id} | ||||
|                                             validatorFn={validateIdInput} | ||||
|  |  | |||
							
								
								
									
										60
									
								
								src/app/validating-input-bigint-field.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/app/validating-input-bigint-field.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| import React, {ChangeEventHandler, useState} from 'react'; | ||||
| 
 | ||||
| export default 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 interface Validation<T> { | ||||
|     valid: boolean; | ||||
|     message?: string; | ||||
|     value?: T; | ||||
| } | ||||
| 
 | ||||
| export type ValidatorFunction<I, T> = (v: I) => Validation<T>; | ||||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|   "compilerOptions": { | ||||
|     "target": "ES2017", | ||||
|     "target": "ES2020", | ||||
|     "lib": ["dom", "dom.iterable", "esnext"], | ||||
|     "allowJs": true, | ||||
|     "allowImportingTsExtensions": true, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue