@contember/react-form 1.3.0-alpha.25 → 1.3.0-alpha.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/development/components/FormCheckbox.cjs +6 -6
- package/dist/development/components/FormCheckbox.cjs.map +1 -1
- package/dist/development/components/FormCheckbox.js +6 -6
- package/dist/development/components/FormCheckbox.js.map +1 -1
- package/dist/development/components/FormInput.cjs +4 -4
- package/dist/development/components/FormInput.cjs.map +1 -1
- package/dist/development/components/FormInput.js +4 -4
- package/dist/development/components/FormInput.js.map +1 -1
- package/dist/development/hooks/useFormInputValidationHandler.cjs +15 -8
- package/dist/development/hooks/useFormInputValidationHandler.cjs.map +1 -1
- package/dist/development/hooks/useFormInputValidationHandler.js +15 -8
- package/dist/development/hooks/useFormInputValidationHandler.js.map +1 -1
- package/dist/development/internal/useFormInputHandler.cjs +22 -25
- package/dist/development/internal/useFormInputHandler.cjs.map +1 -1
- package/dist/development/internal/useFormInputHandler.js +22 -25
- package/dist/development/internal/useFormInputHandler.js.map +1 -1
- package/dist/production/components/FormCheckbox.cjs +5 -5
- package/dist/production/components/FormCheckbox.cjs.map +1 -1
- package/dist/production/components/FormCheckbox.js +5 -5
- package/dist/production/components/FormCheckbox.js.map +1 -1
- package/dist/production/components/FormInput.cjs +2 -2
- package/dist/production/components/FormInput.cjs.map +1 -1
- package/dist/production/components/FormInput.js +2 -2
- package/dist/production/components/FormInput.js.map +1 -1
- package/dist/production/hooks/useFormInputValidationHandler.cjs +15 -8
- package/dist/production/hooks/useFormInputValidationHandler.cjs.map +1 -1
- package/dist/production/hooks/useFormInputValidationHandler.js +15 -8
- package/dist/production/hooks/useFormInputValidationHandler.js.map +1 -1
- package/dist/production/internal/useFormInputHandler.cjs +22 -25
- package/dist/production/internal/useFormInputHandler.cjs.map +1 -1
- package/dist/production/internal/useFormInputHandler.js +22 -25
- package/dist/production/internal/useFormInputHandler.js.map +1 -1
- package/dist/types/components/FormError.d.ts.map +1 -1
- package/dist/types/components/FormInput.d.ts +3 -0
- package/dist/types/components/FormInput.d.ts.map +1 -1
- package/dist/types/hooks/useFormInputValidationHandler.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/internal/useFormInputHandler.d.ts +2 -6
- package/dist/types/internal/useFormInputHandler.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/types/types/index.d.ts +7 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/package.json +8 -8
- package/src/components/FormCheckbox.tsx +5 -5
- package/src/components/FormInput.tsx +5 -2
- package/src/hooks/useFormInputValidationHandler.tsx +23 -8
- package/src/index.ts +1 -0
- package/src/internal/useFormInputHandler.ts +26 -31
- package/src/types/index.ts +7 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,MAAM,MAAM,gBAAgB,GAAG;IAC9B,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAA;IAClC,WAAW,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,CAAA;IACnC,iBAAiB,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;CAC/D,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/react-form",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "1.3.0-alpha.
|
|
4
|
+
"version": "1.3.0-alpha.27",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/production/index.js",
|
|
@@ -40,18 +40,18 @@
|
|
|
40
40
|
"directory": "packages/react-form"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@contember/react-binding": "1.3.0-alpha.
|
|
44
|
-
"@contember/react-utils": "1.3.0-alpha.
|
|
45
|
-
"@contember/utilities": "1.3.0-alpha.
|
|
43
|
+
"@contember/react-binding": "1.3.0-alpha.27",
|
|
44
|
+
"@contember/react-utils": "1.3.0-alpha.27",
|
|
45
|
+
"@contember/utilities": "1.3.0-alpha.27",
|
|
46
46
|
"@radix-ui/react-slot": "^1.0.2"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"react": "^
|
|
50
|
-
"react-dom": "^
|
|
49
|
+
"react": "^18 || ^19",
|
|
50
|
+
"react-dom": "^18 || ^19"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"react": "^18.
|
|
54
|
-
"react-dom": "^18.
|
|
53
|
+
"react": "^18.3.1",
|
|
54
|
+
"react-dom": "^18.3.1"
|
|
55
55
|
},
|
|
56
56
|
"stableVersion": "0.0.0"
|
|
57
57
|
}
|
|
@@ -28,15 +28,15 @@ export const FormCheckbox = Component<FormCheckboxProps>(({ field, isNonbearing,
|
|
|
28
28
|
if (!checkboxRef) {
|
|
29
29
|
return
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
if (value === null) {
|
|
33
|
-
checkboxRef.indeterminate = true
|
|
34
|
-
}
|
|
31
|
+
checkboxRef.indeterminate = value === null
|
|
35
32
|
}, [checkboxRef, ref, value])
|
|
36
33
|
|
|
37
34
|
return (
|
|
38
35
|
<SlotInput
|
|
39
|
-
ref={
|
|
36
|
+
ref={it => {
|
|
37
|
+
(ref as any).current = checkboxRef
|
|
38
|
+
setCheckboxRef(it)
|
|
39
|
+
}}
|
|
40
40
|
type="checkbox"
|
|
41
41
|
checked={accessor.value === true}
|
|
42
42
|
data-state={value === null ? 'indeterminate' : (value ? 'checked' : 'unchecked')}
|
|
@@ -6,6 +6,7 @@ import { dataAttribute } from '@contember/utilities'
|
|
|
6
6
|
import { useFormInputHandler } from '../internal/useFormInputHandler'
|
|
7
7
|
import { useFormError, useFormFieldId } from '../contexts'
|
|
8
8
|
import { useFormInputValidationHandler } from '../hooks/useFormInputValidationHandler'
|
|
9
|
+
import { FormInputHandler } from '../types'
|
|
9
10
|
|
|
10
11
|
type InputProps = React.JSX.IntrinsicElements['input']
|
|
11
12
|
const SlotInput = Slot as ComponentType<InputProps>
|
|
@@ -15,13 +16,15 @@ export interface FormInputProps {
|
|
|
15
16
|
isNonbearing?: boolean
|
|
16
17
|
defaultValue?: OptionallyVariableFieldValue
|
|
17
18
|
children: React.ReactElement
|
|
19
|
+
formatValue?: FormInputHandler['formatValue']
|
|
20
|
+
parseValue?: FormInputHandler['parseValue']
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
export const FormInput = Component<FormInputProps>(({ field, isNonbearing, defaultValue, ...props }) => {
|
|
23
|
+
export const FormInput = Component<FormInputProps>(({ field, isNonbearing, defaultValue, formatValue: formatValueIn, parseValue: parseValueIn, ...props }) => {
|
|
21
24
|
const id = useFormFieldId()
|
|
22
25
|
const accessor = useField(field)
|
|
23
26
|
const errors = useFormError() ?? accessor.errors?.errors ?? []
|
|
24
|
-
const { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor)
|
|
27
|
+
const { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor, { formatValue: formatValueIn, parseValue: parseValueIn })
|
|
25
28
|
const accessorGetter = accessor.getAccessor
|
|
26
29
|
const { ref, onFocus, onBlur } = useFormInputValidationHandler(accessor)
|
|
27
30
|
|
|
@@ -17,17 +17,32 @@ export const useFormInputValidationHandler = (field: FieldAccessor<any>) => {
|
|
|
17
17
|
if (!inputRef.current) {
|
|
18
18
|
return
|
|
19
19
|
}
|
|
20
|
+
|
|
20
21
|
const input = inputRef.current
|
|
21
22
|
const valid = input.validity?.valid
|
|
23
|
+
|
|
22
24
|
const message = valid ? undefined : input?.validationMessage
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const previousMessage = validationMessage.current
|
|
26
|
+
validationMessage.current = message
|
|
27
|
+
|
|
28
|
+
// if there is no message, we want to clear the error
|
|
29
|
+
if (!message) {
|
|
30
|
+
accessorGetter().clearErrors()
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
if (message === previousMessage) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
// if the input is not touched, we don't want to show the error message
|
|
37
|
+
if (!field.isTouched) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// if the input is not focused, we want to show the error message
|
|
42
|
+
// also, even the input is focused, we want to replace the previous message
|
|
43
|
+
if (!focus || !!previousMessage) {
|
|
44
|
+
accessorGetter().clearErrors()
|
|
45
|
+
accessorGetter().addError(message)
|
|
31
46
|
}
|
|
32
47
|
})
|
|
33
48
|
|
package/src/index.ts
CHANGED
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
import { FieldAccessor, SchemaColumn, SchemaKnownColumnType } from '@contember/react-binding'
|
|
2
|
-
import * as React from 'react'
|
|
3
2
|
import { useMemo } from 'react'
|
|
3
|
+
import { FormInputHandler } from '../types'
|
|
4
4
|
|
|
5
|
-
export const useFormInputHandler = (field: FieldAccessor) => {
|
|
5
|
+
export const useFormInputHandler = (field: FieldAccessor, { formatValue, parseValue }: Partial<FormInputHandler>): FormInputHandler => {
|
|
6
6
|
return useMemo(() => {
|
|
7
7
|
const schema = field.schema
|
|
8
8
|
const columnType = schema.type
|
|
9
|
-
const handlerFactory = ColumnTypeHandlerFactories[columnType as SchemaKnownColumnType]
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const handlerFactory = ColumnTypeHandlerFactories[columnType as SchemaKnownColumnType] ?? defaultHandlerFactory
|
|
10
|
+
const handler = handlerFactory(schema, field.getAccessor)
|
|
11
|
+
return {
|
|
12
|
+
defaultInputProps: handler.defaultInputProps,
|
|
13
|
+
formatValue: formatValue ?? handler.formatValue,
|
|
14
|
+
parseValue: parseValue ?? handler.parseValue,
|
|
12
15
|
}
|
|
13
|
-
|
|
14
|
-
}, [field.getAccessor, field.schema])
|
|
16
|
+
}, [field.getAccessor, field.schema, formatValue, parseValue])
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
type ColumnTypeHandlerFactory = (column: SchemaColumn, getAccessor: FieldAccessor.GetFieldAccessor) =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
type ColumnTypeHandlerFactory = (column: SchemaColumn, getAccessor: FieldAccessor.GetFieldAccessor) => FormInputHandler
|
|
20
|
+
|
|
21
|
+
const defaultHandlerFactory: ColumnTypeHandlerFactory = (schema, field) => ({
|
|
22
|
+
parseValue: (value: string) => {
|
|
23
|
+
if (value === '' && schema.nullable && field().valueOnServer === null) {
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
return value
|
|
27
|
+
},
|
|
28
|
+
formatValue: (value: string | null) => value ?? '',
|
|
29
|
+
})
|
|
22
30
|
|
|
23
|
-
const ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandlerFactory> = {
|
|
31
|
+
const ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandlerFactory | undefined> = {
|
|
32
|
+
String: defaultHandlerFactory,
|
|
24
33
|
Integer: () => ({
|
|
25
34
|
parseValue: (value: string) => {
|
|
26
35
|
if (value === '') {
|
|
@@ -51,15 +60,7 @@ const ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandle
|
|
|
51
60
|
type: 'number',
|
|
52
61
|
},
|
|
53
62
|
}),
|
|
54
|
-
|
|
55
|
-
parseValue: (value: string) => {
|
|
56
|
-
if (value === '' && schema.nullable && field().valueOnServer === null) {
|
|
57
|
-
return null
|
|
58
|
-
}
|
|
59
|
-
return value
|
|
60
|
-
},
|
|
61
|
-
formatValue: (value: string | null) => value ?? '',
|
|
62
|
-
}),
|
|
63
|
+
|
|
63
64
|
Date: () => ({
|
|
64
65
|
parseValue: (value: string) => {
|
|
65
66
|
if (value === '') {
|
|
@@ -93,15 +94,9 @@ const ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandle
|
|
|
93
94
|
type: 'datetime-local',
|
|
94
95
|
},
|
|
95
96
|
}),
|
|
96
|
-
Bool:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
Enum: () => {
|
|
100
|
-
throw new Error('Enum column type is not supported yet')
|
|
101
|
-
},
|
|
102
|
-
Uuid: () => {
|
|
103
|
-
throw new Error('UUID column type is not supported yet')
|
|
104
|
-
},
|
|
97
|
+
Bool: undefined,
|
|
98
|
+
Enum: undefined,
|
|
99
|
+
Uuid: undefined,
|
|
105
100
|
}
|
|
106
101
|
|
|
107
102
|
const toLocalDate = (date: Date) => {
|