11import type { PopoverNextProps } from '@blueprintjs/core' ;
22import { PopoverNext } from '@blueprintjs/core' ;
33import styled from '@emotion/styled' ;
4- import { yupResolver } from '@hookform/resolvers/yup' ;
5- import type { KeyboardEvent , MouseEvent , ReactNode } from 'react' ;
6- import { useState } from 'react' ;
7- import { useForm } from 'react-hook-form' ;
8- import * as Yup from 'yup' ;
9-
10- import { Input2Controller } from '../elements/Input2Controller.js' ;
11- import { NumberInput2Controller } from '../elements/NumberInput2Controller.js' ;
4+ import { revalidateLogic } from '@tanstack/react-form' ;
5+ import type { ReactNode } from 'react' ;
6+ import { useMemo , useState } from 'react' ;
7+ import { AppForm , coerceNumberInput , useForm } from 'react-science/ui' ;
8+ import { match } from 'ts-pattern' ;
9+ import { z } from 'zod' ;
1210
1311const StyledPopover = styled ( PopoverNext ) `
1412 .field-edition-popover {
@@ -21,33 +19,20 @@ type InputType = 'number' | 'text';
2119interface FieldProps {
2220 value : number | string ;
2321 inputType ?: InputType ;
24- onChange : ( value : any ) => void ;
22+ onChange : ( value : string ) => void ;
2523}
24+
2625interface FieldEditionsProps extends FieldProps {
2726 children : ReactNode ;
2827 PopoverProps ?: PopoverNextProps ;
2928}
30- const InputDimension = { height : 28 , width : 100 } ;
31-
32- const validationSchema = ( inputType : 'number' | 'text' ) =>
33- Yup . object ( {
34- value : ( inputType === 'number' ? Yup . number ( ) : Yup . string ( ) ) . required ( ) ,
35- } ) ;
36-
37- function stopPropagation ( e : MouseEvent ) {
38- e . stopPropagation ( ) ;
39- }
4029
4130export function FieldEdition ( props : FieldEditionsProps ) {
4231 const { value, inputType = 'text' , onChange, children, PopoverProps } = props ;
4332 const [ isOpen , setIsOpen ] = useState ( false ) ;
4433
45- function handleChange ( {
46- value : newValue ,
47- } : {
48- value : FieldEditionsProps [ 'value' ] ;
49- } ) {
50- onChange ( newValue ) ;
34+ function handleChange ( newValue : FieldEditionsProps [ 'value' ] ) {
35+ onChange ( String ( newValue ) ) ;
5136 setIsOpen ( false ) ;
5237 }
5338
@@ -67,49 +52,57 @@ export function FieldEdition(props: FieldEditionsProps) {
6752 ) ;
6853}
6954
55+ function validationSchema (
56+ inputType : InputType ,
57+ ) : z . ZodType < { value : string } | { value : number } , { value : string } > {
58+ return match ( inputType )
59+ . with ( 'number' , ( ) =>
60+ z . object ( {
61+ value : coerceNumberInput ( ) ,
62+ } ) ,
63+ )
64+ . with ( 'text' , ( ) =>
65+ z . object ( {
66+ value : z . string ( ) ,
67+ } ) ,
68+ )
69+ . exhaustive ( ) ;
70+ }
71+
7072function Field ( props : FieldProps ) {
7173 const { value, inputType = 'text' , onChange } = props ;
7274
73- const { control, handleSubmit } = useForm ( {
74- defaultValues : { value } ,
75- resolver : yupResolver ( validationSchema ( inputType ) ) ,
76- } ) ;
77-
78- function handleKeyDown ( event : KeyboardEvent < HTMLInputElement > ) {
79- if ( event . key === 'Enter' ) {
80- void handleSubmit ( onChange ) ( ) ;
81- }
82- }
75+ const validation = useMemo ( ( ) => {
76+ return validationSchema ( inputType ) . transform ( ( { value } ) => {
77+ return String ( value ) ;
78+ } ) ;
79+ } , [ inputType ] ) ;
8380
84- const style = {
85- height : `${ InputDimension . height } px` ,
86- outline : 'none' ,
87- } ;
88-
89- if ( inputType === 'number' ) {
90- return (
91- < NumberInput2Controller
92- name = "value"
93- control = { control }
94- style = { style }
95- onKeyDown = { handleKeyDown }
96- onClick = { stopPropagation }
97- onMouseDown = { stopPropagation }
98- autoFocus
99- buttonPosition = "none"
100- />
101- ) ;
102- }
81+ const form = useForm ( {
82+ validationLogic : revalidateLogic ( { mode : 'change' } ) ,
83+ defaultValues : {
84+ value,
85+ } ,
86+ validators : {
87+ onDynamic : validation ,
88+ } ,
89+ onSubmit : ( { value } ) => {
90+ const parsedValue = validation . parse ( value ) ;
91+ onChange ( parsedValue ) ;
92+ } ,
93+ } ) ;
10394
10495 return (
105- < Input2Controller
106- name = "value"
107- control = { control }
108- style = { style }
109- onKeyDown = { handleKeyDown }
110- onClick = { stopPropagation }
111- onMouseDown = { stopPropagation }
112- autoFocus
113- />
96+ < AppForm form = { form } >
97+ < form . AppField name = "value" >
98+ { ( field ) =>
99+ inputType === 'number' ? (
100+ < field . NumericInput autoFocus />
101+ ) : (
102+ < field . Input autoFocus />
103+ )
104+ }
105+ </ form . AppField >
106+ </ AppForm >
114107 ) ;
115108}
0 commit comments