@contember/react-form 1.3.0-alpha.14
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 +68 -0
- package/dist/development/components/FormCheckbox.cjs.map +1 -0
- package/dist/development/components/FormCheckbox.js +52 -0
- package/dist/development/components/FormCheckbox.js.map +1 -0
- package/dist/development/components/FormError.cjs +22 -0
- package/dist/development/components/FormError.cjs.map +1 -0
- package/dist/development/components/FormError.js +22 -0
- package/dist/development/components/FormError.js.map +1 -0
- package/dist/development/components/FormFieldScope.cjs +15 -0
- package/dist/development/components/FormFieldScope.cjs.map +1 -0
- package/dist/development/components/FormFieldScope.js +15 -0
- package/dist/development/components/FormFieldScope.js.map +1 -0
- package/dist/development/components/FormHasManyRelationScope.cjs +15 -0
- package/dist/development/components/FormHasManyRelationScope.cjs.map +1 -0
- package/dist/development/components/FormHasManyRelationScope.js +15 -0
- package/dist/development/components/FormHasManyRelationScope.js.map +1 -0
- package/dist/development/components/FormHasOneRelationScope.cjs +15 -0
- package/dist/development/components/FormHasOneRelationScope.cjs.map +1 -0
- package/dist/development/components/FormHasOneRelationScope.js +15 -0
- package/dist/development/components/FormHasOneRelationScope.js.map +1 -0
- package/dist/development/components/FormInput.cjs +40 -0
- package/dist/development/components/FormInput.cjs.map +1 -0
- package/dist/development/components/FormInput.js +40 -0
- package/dist/development/components/FormInput.js.map +1 -0
- package/dist/development/components/FormLabel.cjs +24 -0
- package/dist/development/components/FormLabel.cjs.map +1 -0
- package/dist/development/components/FormLabel.js +24 -0
- package/dist/development/components/FormLabel.js.map +1 -0
- package/dist/development/components/FormRadioInput.cjs +39 -0
- package/dist/development/components/FormRadioInput.cjs.map +1 -0
- package/dist/development/components/FormRadioInput.js +39 -0
- package/dist/development/components/FormRadioInput.js.map +1 -0
- package/dist/development/contexts.cjs +14 -0
- package/dist/development/contexts.cjs.map +1 -0
- package/dist/development/contexts.js +14 -0
- package/dist/development/contexts.js.map +1 -0
- package/dist/development/hooks/useFormInputValidationHandler.cjs +64 -0
- package/dist/development/hooks/useFormInputValidationHandler.cjs.map +1 -0
- package/dist/development/hooks/useFormInputValidationHandler.js +48 -0
- package/dist/development/hooks/useFormInputValidationHandler.js.map +1 -0
- package/dist/development/index.cjs +26 -0
- package/dist/development/index.cjs.map +1 -0
- package/dist/development/index.js +26 -0
- package/dist/development/index.js.map +1 -0
- package/dist/development/internal/useFormInputHandler.cjs +98 -0
- package/dist/development/internal/useFormInputHandler.cjs.map +1 -0
- package/dist/development/internal/useFormInputHandler.js +98 -0
- package/dist/development/internal/useFormInputHandler.js.map +1 -0
- package/dist/production/components/FormCheckbox.cjs +68 -0
- package/dist/production/components/FormCheckbox.cjs.map +1 -0
- package/dist/production/components/FormCheckbox.js +52 -0
- package/dist/production/components/FormCheckbox.js.map +1 -0
- package/dist/production/components/FormError.cjs +22 -0
- package/dist/production/components/FormError.cjs.map +1 -0
- package/dist/production/components/FormError.js +22 -0
- package/dist/production/components/FormError.js.map +1 -0
- package/dist/production/components/FormFieldScope.cjs +15 -0
- package/dist/production/components/FormFieldScope.cjs.map +1 -0
- package/dist/production/components/FormFieldScope.js +15 -0
- package/dist/production/components/FormFieldScope.js.map +1 -0
- package/dist/production/components/FormHasManyRelationScope.cjs +15 -0
- package/dist/production/components/FormHasManyRelationScope.cjs.map +1 -0
- package/dist/production/components/FormHasManyRelationScope.js +15 -0
- package/dist/production/components/FormHasManyRelationScope.js.map +1 -0
- package/dist/production/components/FormHasOneRelationScope.cjs +15 -0
- package/dist/production/components/FormHasOneRelationScope.cjs.map +1 -0
- package/dist/production/components/FormHasOneRelationScope.js +15 -0
- package/dist/production/components/FormHasOneRelationScope.js.map +1 -0
- package/dist/production/components/FormInput.cjs +40 -0
- package/dist/production/components/FormInput.cjs.map +1 -0
- package/dist/production/components/FormInput.js +40 -0
- package/dist/production/components/FormInput.js.map +1 -0
- package/dist/production/components/FormLabel.cjs +24 -0
- package/dist/production/components/FormLabel.cjs.map +1 -0
- package/dist/production/components/FormLabel.js +24 -0
- package/dist/production/components/FormLabel.js.map +1 -0
- package/dist/production/components/FormRadioInput.cjs +39 -0
- package/dist/production/components/FormRadioInput.cjs.map +1 -0
- package/dist/production/components/FormRadioInput.js +39 -0
- package/dist/production/components/FormRadioInput.js.map +1 -0
- package/dist/production/contexts.cjs +14 -0
- package/dist/production/contexts.cjs.map +1 -0
- package/dist/production/contexts.js +14 -0
- package/dist/production/contexts.js.map +1 -0
- package/dist/production/hooks/useFormInputValidationHandler.cjs +64 -0
- package/dist/production/hooks/useFormInputValidationHandler.cjs.map +1 -0
- package/dist/production/hooks/useFormInputValidationHandler.js +48 -0
- package/dist/production/hooks/useFormInputValidationHandler.js.map +1 -0
- package/dist/production/index.cjs +26 -0
- package/dist/production/index.cjs.map +1 -0
- package/dist/production/index.js +26 -0
- package/dist/production/index.js.map +1 -0
- package/dist/production/internal/useFormInputHandler.cjs +98 -0
- package/dist/production/internal/useFormInputHandler.cjs.map +1 -0
- package/dist/production/internal/useFormInputHandler.js +98 -0
- package/dist/production/internal/useFormInputHandler.js.map +1 -0
- package/dist/types/components/FormCheckbox.d.ts +11 -0
- package/dist/types/components/FormCheckbox.d.ts.map +1 -0
- package/dist/types/components/FormError.d.ts +7 -0
- package/dist/types/components/FormError.d.ts.map +1 -0
- package/dist/types/components/FormFieldScope.d.ts +8 -0
- package/dist/types/components/FormFieldScope.d.ts.map +1 -0
- package/dist/types/components/FormHasManyRelationScope.d.ts +8 -0
- package/dist/types/components/FormHasManyRelationScope.d.ts.map +1 -0
- package/dist/types/components/FormHasOneRelationScope.d.ts +8 -0
- package/dist/types/components/FormHasOneRelationScope.d.ts.map +1 -0
- package/dist/types/components/FormInput.d.ts +10 -0
- package/dist/types/components/FormInput.d.ts.map +1 -0
- package/dist/types/components/FormLabel.d.ts +5 -0
- package/dist/types/components/FormLabel.d.ts.map +1 -0
- package/dist/types/components/FormRadioInput.d.ts +11 -0
- package/dist/types/components/FormRadioInput.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +9 -0
- package/dist/types/components/index.d.ts.map +1 -0
- package/dist/types/contexts.d.ts +8 -0
- package/dist/types/contexts.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useFormInputValidationHandler.d.ts +8 -0
- package/dist/types/hooks/useFormInputValidationHandler.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/internal/useFormInputHandler.d.ts +8 -0
- package/dist/types/internal/useFormInputHandler.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +57 -0
- package/src/components/FormCheckbox.tsx +58 -0
- package/src/components/FormError.tsx +22 -0
- package/src/components/FormFieldScope.tsx +24 -0
- package/src/components/FormHasManyRelationScope.tsx +24 -0
- package/src/components/FormHasOneRelationScope.tsx +24 -0
- package/src/components/FormInput.tsx +46 -0
- package/src/components/FormLabel.tsx +22 -0
- package/src/components/FormRadioInput.tsx +45 -0
- package/src/components/index.ts +8 -0
- package/src/contexts.ts +12 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useFormInputValidationHandler.tsx +47 -0
- package/src/index.ts +3 -0
- package/src/internal/useFormInputHandler.ts +104 -0
- package/src/tsconfig.json +11 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './FormError'
|
|
2
|
+
export * from './FormCheckbox'
|
|
3
|
+
export * from './FormFieldScope'
|
|
4
|
+
export * from './FormHasOneRelationScope'
|
|
5
|
+
export * from './FormHasManyRelationScope'
|
|
6
|
+
export * from './FormInput'
|
|
7
|
+
export * from './FormLabel'
|
|
8
|
+
export * from './FormRadioInput'
|
package/src/contexts.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createContext } from '@contember/react-utils'
|
|
2
|
+
import { ErrorAccessor } from '@contember/react-binding'
|
|
3
|
+
|
|
4
|
+
const FormFieldIdContext_ = createContext<string | undefined>('FormFieldIdContext', undefined)
|
|
5
|
+
/** @internal */
|
|
6
|
+
export const FormFieldIdContext = FormFieldIdContext_[0]
|
|
7
|
+
export const useFormFieldId = FormFieldIdContext_[1]
|
|
8
|
+
|
|
9
|
+
const FormErrorContext_ = createContext<ErrorAccessor.Error[] | undefined>('FormErrorContext', undefined)
|
|
10
|
+
/** @internal */
|
|
11
|
+
export const FormErrorContext = FormErrorContext_[0]
|
|
12
|
+
export const useFormError = FormErrorContext_[1]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useFormInputValidationHandler'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { useCallback, useEffect, useRef } from 'react'
|
|
3
|
+
import { FieldAccessor, useEntityBeforePersist } from '@contember/react-binding'
|
|
4
|
+
|
|
5
|
+
export const useFormInputValidationHandler = (field: FieldAccessor<any>) => {
|
|
6
|
+
const accessorGetter = field.getAccessor
|
|
7
|
+
const validationMessage = useRef<string>()
|
|
8
|
+
const [focus, setFocus] = React.useState(false)
|
|
9
|
+
const inputRef = React.useRef<HTMLInputElement>(null)
|
|
10
|
+
useEntityBeforePersist(useCallback(() => {
|
|
11
|
+
if (validationMessage.current) {
|
|
12
|
+
accessorGetter().addError(validationMessage.current)
|
|
13
|
+
}
|
|
14
|
+
}, [accessorGetter]))
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (!inputRef.current) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
const input = inputRef.current
|
|
21
|
+
const valid = input.validity?.valid
|
|
22
|
+
const message = valid ? undefined : input?.validationMessage
|
|
23
|
+
if (message !== validationMessage.current) {
|
|
24
|
+
validationMessage.current = message
|
|
25
|
+
if (!message || !focus) {
|
|
26
|
+
accessorGetter().clearErrors()
|
|
27
|
+
}
|
|
28
|
+
if (!focus && message) {
|
|
29
|
+
accessorGetter().addError(message)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
ref: inputRef,
|
|
36
|
+
onFocus: useCallback(() => {
|
|
37
|
+
setFocus(true)
|
|
38
|
+
}, []),
|
|
39
|
+
onBlur: useCallback(() => {
|
|
40
|
+
setFocus(false)
|
|
41
|
+
accessorGetter().clearErrors()
|
|
42
|
+
if (validationMessage.current) {
|
|
43
|
+
accessorGetter().addError(validationMessage.current)
|
|
44
|
+
}
|
|
45
|
+
}, [accessorGetter]),
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { FieldAccessor, SchemaColumn, SchemaKnownColumnType } from '@contember/react-binding'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { useMemo } from 'react'
|
|
4
|
+
|
|
5
|
+
export const useFormInputHandler = (field: FieldAccessor) => {
|
|
6
|
+
return useMemo(() => {
|
|
7
|
+
const schema = field.schema
|
|
8
|
+
const columnType = schema.type
|
|
9
|
+
const handlerFactory = ColumnTypeHandlerFactories[columnType as SchemaKnownColumnType]
|
|
10
|
+
if (!handlerFactory) {
|
|
11
|
+
throw new Error(`Column type ${columnType} is not supported yet`)
|
|
12
|
+
}
|
|
13
|
+
return handlerFactory(schema, field.getAccessor)
|
|
14
|
+
}, [field.getAccessor, field.schema])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type ColumnTypeHandlerFactory = (column: SchemaColumn, getAccessor: FieldAccessor.GetFieldAccessor) => {
|
|
18
|
+
parseValue: (value: string) => any
|
|
19
|
+
formatValue: (value: any) => string
|
|
20
|
+
defaultInputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandlerFactory> = {
|
|
24
|
+
Integer: () => ({
|
|
25
|
+
parseValue: (value: string) => {
|
|
26
|
+
if (value === '') {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
const parsed = parseInt(value, 10)
|
|
30
|
+
return isNaN(parsed) ? null : parsed
|
|
31
|
+
},
|
|
32
|
+
formatValue: (value: number | null) => {
|
|
33
|
+
return value === null ? '' : value.toString(10)
|
|
34
|
+
},
|
|
35
|
+
defaultInputProps: {
|
|
36
|
+
type: 'number',
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
Double: () => ({
|
|
40
|
+
parseValue: (value: string) => {
|
|
41
|
+
if (value === '') {
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
const parsed = parseFloat(value)
|
|
45
|
+
return isNaN(parsed) ? null : parsed
|
|
46
|
+
},
|
|
47
|
+
formatValue: (value: number | null) => {
|
|
48
|
+
return value === null ? '' : value.toString(10)
|
|
49
|
+
},
|
|
50
|
+
defaultInputProps: {
|
|
51
|
+
type: 'number',
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
String: (schema, field) => ({
|
|
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
|
+
Date: () => ({
|
|
64
|
+
parseValue: (value: string) => {
|
|
65
|
+
if (value === '') {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
const parsed = Date.parse(value)
|
|
69
|
+
return isNaN(parsed) ? null : new Date(parsed)
|
|
70
|
+
},
|
|
71
|
+
formatValue: (value: string | null) => {
|
|
72
|
+
const parsed = value ? Date.parse(value) : null
|
|
73
|
+
return !parsed || isNaN(parsed) ? '' : new Date(parsed).toISOString().split('T')[0]
|
|
74
|
+
},
|
|
75
|
+
defaultInputProps: {
|
|
76
|
+
type: 'date',
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
DateTime: () => ({
|
|
80
|
+
parseValue: (value: string) => {
|
|
81
|
+
if (value === '') {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
const parsed = Date.parse(value)
|
|
85
|
+
return isNaN(parsed) ? null : new Date(parsed)
|
|
86
|
+
},
|
|
87
|
+
formatValue: (value: string | null) => {
|
|
88
|
+
const parsed = value ? Date.parse(value) : null
|
|
89
|
+
return !parsed || isNaN(parsed) ? '' : new Date(parsed).toISOString().substring(0, 16)
|
|
90
|
+
},
|
|
91
|
+
defaultInputProps: {
|
|
92
|
+
type: 'datetime-local',
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
Bool: () => {
|
|
96
|
+
throw new Error('Boolean column type is not supported yet')
|
|
97
|
+
},
|
|
98
|
+
Enum: () => {
|
|
99
|
+
throw new Error('Enum column type is not supported yet')
|
|
100
|
+
},
|
|
101
|
+
Uuid: () => {
|
|
102
|
+
throw new Error('UUID column type is not supported yet')
|
|
103
|
+
},
|
|
104
|
+
}
|