@tamagui/field 0.0.0-bootstrap.0 → 3.0.0-beta.643.1
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/LICENSE +21 -0
- package/dist/cjs/Field.cjs +857 -0
- package/dist/cjs/Field.native.cjs +1018 -0
- package/dist/cjs/Field.native.js +1020 -0
- package/dist/cjs/Field.native.js.map +1 -0
- package/dist/cjs/FieldContext.cjs +86 -0
- package/dist/cjs/FieldContext.native.cjs +90 -0
- package/dist/cjs/FieldContext.native.js +92 -0
- package/dist/cjs/FieldContext.native.js.map +1 -0
- package/dist/cjs/index.cjs +21 -0
- package/dist/cjs/index.native.cjs +23 -0
- package/dist/cjs/index.native.js +25 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/types.cjs +17 -0
- package/dist/cjs/types.native.cjs +19 -0
- package/dist/cjs/types.native.js +21 -0
- package/dist/cjs/types.native.js.map +1 -0
- package/dist/cjs/validation.cjs +114 -0
- package/dist/cjs/validation.native.cjs +126 -0
- package/dist/cjs/validation.native.js +128 -0
- package/dist/cjs/validation.native.js.map +1 -0
- package/dist/esm/Field.mjs +824 -0
- package/dist/esm/Field.mjs.map +1 -0
- package/dist/esm/Field.native.js +983 -0
- package/dist/esm/Field.native.js.map +1 -0
- package/dist/esm/FieldContext.mjs +51 -0
- package/dist/esm/FieldContext.mjs.map +1 -0
- package/dist/esm/FieldContext.native.js +53 -0
- package/dist/esm/FieldContext.native.js.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.mjs +5 -0
- package/dist/esm/index.native.js +5 -0
- package/dist/esm/types.mjs +0 -0
- package/dist/esm/types.native.js +0 -0
- package/dist/esm/validation.mjs +86 -0
- package/dist/esm/validation.mjs.map +1 -0
- package/dist/esm/validation.native.js +96 -0
- package/dist/esm/validation.native.js.map +1 -0
- package/dist/jsx/Field.mjs +824 -0
- package/dist/jsx/Field.mjs.map +1 -0
- package/dist/jsx/Field.native.cjs +1018 -0
- package/dist/jsx/Field.native.js +1020 -0
- package/dist/jsx/Field.native.js.map +1 -0
- package/dist/jsx/FieldContext.mjs +51 -0
- package/dist/jsx/FieldContext.mjs.map +1 -0
- package/dist/jsx/FieldContext.native.cjs +90 -0
- package/dist/jsx/FieldContext.native.js +92 -0
- package/dist/jsx/FieldContext.native.js.map +1 -0
- package/dist/jsx/index.js +5 -0
- package/dist/jsx/index.mjs +5 -0
- package/dist/jsx/index.native.cjs +23 -0
- package/dist/jsx/index.native.js +25 -0
- package/dist/jsx/index.native.js.map +1 -0
- package/dist/jsx/types.mjs +0 -0
- package/dist/jsx/types.native.cjs +19 -0
- package/dist/jsx/types.native.js +21 -0
- package/dist/jsx/types.native.js.map +1 -0
- package/dist/jsx/validation.mjs +86 -0
- package/dist/jsx/validation.mjs.map +1 -0
- package/dist/jsx/validation.native.cjs +126 -0
- package/dist/jsx/validation.native.js +128 -0
- package/dist/jsx/validation.native.js.map +1 -0
- package/package.json +50 -5
- package/src/Field.tsx +1129 -0
- package/src/FieldContext.tsx +61 -0
- package/src/index.ts +3 -0
- package/src/types.ts +125 -0
- package/src/validation.ts +136 -0
- package/types/Field.d.ts +401 -0
- package/types/Field.d.ts.map +1 -0
- package/types/FieldContext.d.ts +11 -0
- package/types/FieldContext.d.ts.map +1 -0
- package/types/index.d.ts +4 -0
- package/types/index.d.ts.map +1 -0
- package/types/types.d.ts +112 -0
- package/types/types.d.ts.map +1 -0
- package/types/validation.d.ts +24 -0
- package/types/validation.d.ts.map +1 -0
- package/README.md +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createStyledContext } from '@tamagui/core'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import type { FieldControlContextValue, FieldState, FieldStyleState } from './types'
|
|
4
|
+
import { createDefaultValidityState } from './validation'
|
|
5
|
+
|
|
6
|
+
const noop = () => {}
|
|
7
|
+
const unregister = () => {}
|
|
8
|
+
|
|
9
|
+
export const defaultFieldState: FieldState = {
|
|
10
|
+
name: undefined,
|
|
11
|
+
value: undefined,
|
|
12
|
+
error: '',
|
|
13
|
+
errors: [],
|
|
14
|
+
validity: createDefaultValidityState(),
|
|
15
|
+
valid: null,
|
|
16
|
+
touched: false,
|
|
17
|
+
dirty: false,
|
|
18
|
+
filled: false,
|
|
19
|
+
focused: false,
|
|
20
|
+
disabled: false,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const defaultFieldControl: FieldControlContextValue = {
|
|
24
|
+
name: undefined,
|
|
25
|
+
disabled: false,
|
|
26
|
+
ariaProps: {},
|
|
27
|
+
dataProps: {},
|
|
28
|
+
onFocus: noop,
|
|
29
|
+
onBlur: noop,
|
|
30
|
+
onChange: noop,
|
|
31
|
+
onDisabledChange: noop,
|
|
32
|
+
registerControl: () => unregister,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const FieldControlContext =
|
|
36
|
+
React.createContext<FieldControlContextValue>(defaultFieldControl)
|
|
37
|
+
|
|
38
|
+
export const FieldControlProvider = FieldControlContext.Provider
|
|
39
|
+
|
|
40
|
+
export function useFieldControl() {
|
|
41
|
+
return React.useContext(FieldControlContext)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const FieldStateContext = React.createContext<FieldState>(defaultFieldState)
|
|
45
|
+
|
|
46
|
+
export function useFieldState() {
|
|
47
|
+
return React.useContext(FieldStateContext)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const FieldStyledContext = createStyledContext<FieldStyleState>(
|
|
51
|
+
{
|
|
52
|
+
valid: false,
|
|
53
|
+
invalid: false,
|
|
54
|
+
touched: false,
|
|
55
|
+
dirty: false,
|
|
56
|
+
filled: false,
|
|
57
|
+
focused: false,
|
|
58
|
+
disabled: false,
|
|
59
|
+
},
|
|
60
|
+
'Field'
|
|
61
|
+
)
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { FormValidationMode, FormValues } from '@tamagui/form'
|
|
2
|
+
import type * as React from 'react'
|
|
3
|
+
|
|
4
|
+
export type FieldValidationResult = string | string[] | null
|
|
5
|
+
|
|
6
|
+
export type StandardSchemaIssue = {
|
|
7
|
+
message: string
|
|
8
|
+
path?: ReadonlyArray<PropertyKey | { key: PropertyKey }>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type StandardSchemaV1 = {
|
|
12
|
+
readonly '~standard': {
|
|
13
|
+
readonly version: 1
|
|
14
|
+
readonly vendor: string
|
|
15
|
+
readonly validate: (
|
|
16
|
+
value: unknown
|
|
17
|
+
) =>
|
|
18
|
+
| { value: unknown; issues?: undefined }
|
|
19
|
+
| { issues: ReadonlyArray<StandardSchemaIssue> }
|
|
20
|
+
| Promise<
|
|
21
|
+
| { value: unknown; issues?: undefined }
|
|
22
|
+
| { issues: ReadonlyArray<StandardSchemaIssue> }
|
|
23
|
+
>
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type FieldValidator =
|
|
28
|
+
| ((
|
|
29
|
+
value: unknown,
|
|
30
|
+
formValues: FormValues
|
|
31
|
+
) => FieldValidationResult | Promise<FieldValidationResult>)
|
|
32
|
+
| StandardSchemaV1
|
|
33
|
+
|
|
34
|
+
export type FieldValidityState = {
|
|
35
|
+
badInput: boolean
|
|
36
|
+
customError: boolean
|
|
37
|
+
patternMismatch: boolean
|
|
38
|
+
rangeOverflow: boolean
|
|
39
|
+
rangeUnderflow: boolean
|
|
40
|
+
stepMismatch: boolean
|
|
41
|
+
tooLong: boolean
|
|
42
|
+
tooShort: boolean
|
|
43
|
+
typeMismatch: boolean
|
|
44
|
+
valueMissing: boolean
|
|
45
|
+
valid: boolean | null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type FieldValidityData = {
|
|
49
|
+
state: FieldValidityState
|
|
50
|
+
error: string
|
|
51
|
+
errors: string[]
|
|
52
|
+
value: unknown
|
|
53
|
+
initialValue: unknown
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type FieldState = {
|
|
57
|
+
name?: string
|
|
58
|
+
value: unknown
|
|
59
|
+
error: string
|
|
60
|
+
errors: string[]
|
|
61
|
+
validity: FieldValidityState
|
|
62
|
+
valid: boolean | null
|
|
63
|
+
touched: boolean
|
|
64
|
+
dirty: boolean
|
|
65
|
+
filled: boolean
|
|
66
|
+
focused: boolean
|
|
67
|
+
disabled: boolean
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type FieldStyleState = {
|
|
71
|
+
valid: boolean
|
|
72
|
+
invalid: boolean
|
|
73
|
+
touched: boolean
|
|
74
|
+
dirty: boolean
|
|
75
|
+
filled: boolean
|
|
76
|
+
focused: boolean
|
|
77
|
+
disabled: boolean
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type FieldDataProps = {
|
|
81
|
+
'data-valid'?: ''
|
|
82
|
+
'data-invalid'?: ''
|
|
83
|
+
'data-touched'?: ''
|
|
84
|
+
'data-dirty'?: ''
|
|
85
|
+
'data-filled'?: ''
|
|
86
|
+
'data-focused'?: ''
|
|
87
|
+
'data-disabled'?: ''
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type FieldAriaProps = {
|
|
91
|
+
id?: string
|
|
92
|
+
'aria-labelledby'?: string
|
|
93
|
+
'aria-describedby'?: string
|
|
94
|
+
'aria-invalid'?: true
|
|
95
|
+
accessibilityLabel?: string
|
|
96
|
+
accessibilityHint?: string
|
|
97
|
+
accessibilityState?: {
|
|
98
|
+
disabled?: boolean
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type FieldControlRegistration = {
|
|
103
|
+
id?: string
|
|
104
|
+
name?: string
|
|
105
|
+
controlRef: React.RefObject<any>
|
|
106
|
+
inputRef?: React.RefObject<any>
|
|
107
|
+
getValue?: () => unknown
|
|
108
|
+
value?: unknown
|
|
109
|
+
disabled?: boolean
|
|
110
|
+
required?: boolean
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type FieldControlContextValue = {
|
|
114
|
+
name?: string
|
|
115
|
+
disabled: boolean
|
|
116
|
+
ariaProps: FieldAriaProps
|
|
117
|
+
dataProps: FieldDataProps
|
|
118
|
+
onFocus: () => void
|
|
119
|
+
onBlur: (value?: unknown) => void
|
|
120
|
+
onChange: (value: unknown) => void
|
|
121
|
+
onDisabledChange: (disabled: boolean) => void
|
|
122
|
+
registerControl: (registration: FieldControlRegistration) => () => void
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export type FieldValidationMode = FormValidationMode
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { FormValues } from '@tamagui/form'
|
|
2
|
+
import type {
|
|
3
|
+
FieldValidationMode,
|
|
4
|
+
FieldValidationResult,
|
|
5
|
+
FieldValidator,
|
|
6
|
+
FieldValidityState,
|
|
7
|
+
StandardSchemaIssue,
|
|
8
|
+
} from './types'
|
|
9
|
+
|
|
10
|
+
export function createDefaultValidityState(
|
|
11
|
+
valid: boolean | null = null
|
|
12
|
+
): FieldValidityState {
|
|
13
|
+
return {
|
|
14
|
+
badInput: false,
|
|
15
|
+
customError: false,
|
|
16
|
+
patternMismatch: false,
|
|
17
|
+
rangeOverflow: false,
|
|
18
|
+
rangeUnderflow: false,
|
|
19
|
+
stepMismatch: false,
|
|
20
|
+
tooLong: false,
|
|
21
|
+
tooShort: false,
|
|
22
|
+
typeMismatch: false,
|
|
23
|
+
valueMissing: false,
|
|
24
|
+
valid,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function normalizeNativeValidity(
|
|
29
|
+
state: FieldValidityState,
|
|
30
|
+
showValueMissing: boolean
|
|
31
|
+
) {
|
|
32
|
+
if (showValueMissing || !state.valueMissing) {
|
|
33
|
+
return { ...state }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const hasAnotherError = Object.entries(state).some(
|
|
37
|
+
([key, value]) => key !== 'valid' && key !== 'valueMissing' && value
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if (hasAnotherError) {
|
|
41
|
+
return { ...state }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
...state,
|
|
46
|
+
valueMissing: false,
|
|
47
|
+
valid: true,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isFilled(value: unknown) {
|
|
52
|
+
if (value === null || value === undefined || value === false) {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
if (typeof value === 'string' || Array.isArray(value)) {
|
|
56
|
+
return value.length > 0
|
|
57
|
+
}
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function shouldValidateOnChange(
|
|
62
|
+
mode: FieldValidationMode,
|
|
63
|
+
submitAttempted: boolean
|
|
64
|
+
) {
|
|
65
|
+
return mode === 'onChange' || (mode === 'onSubmit' && submitAttempted)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isPromiseLike<Value>(value: unknown): value is PromiseLike<Value> {
|
|
69
|
+
return Boolean(
|
|
70
|
+
value &&
|
|
71
|
+
(typeof value === 'object' || typeof value === 'function') &&
|
|
72
|
+
'then' in value &&
|
|
73
|
+
typeof value.then === 'function'
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function normalizeFunctionResult(result: FieldValidationResult) {
|
|
78
|
+
if (result === null || result === '') {
|
|
79
|
+
return []
|
|
80
|
+
}
|
|
81
|
+
return Array.isArray(result) ? result.filter(Boolean) : [result]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function normalizeSchemaResult(
|
|
85
|
+
result:
|
|
86
|
+
| { value: unknown; issues?: undefined }
|
|
87
|
+
| { issues: ReadonlyArray<StandardSchemaIssue> }
|
|
88
|
+
) {
|
|
89
|
+
return 'issues' in result && result.issues
|
|
90
|
+
? result.issues.map((issue) => issue.message).filter(Boolean)
|
|
91
|
+
: []
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function getValidationResult(
|
|
95
|
+
validator: FieldValidator,
|
|
96
|
+
value: unknown,
|
|
97
|
+
formValues: FormValues
|
|
98
|
+
): string[] | Promise<string[]> {
|
|
99
|
+
if ('~standard' in validator) {
|
|
100
|
+
const result = validator['~standard'].validate(value)
|
|
101
|
+
return isPromiseLike(result)
|
|
102
|
+
? Promise.resolve(result).then(normalizeSchemaResult)
|
|
103
|
+
: normalizeSchemaResult(result)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const result = validator(value, formValues)
|
|
107
|
+
return isPromiseLike(result)
|
|
108
|
+
? Promise.resolve(result).then(normalizeFunctionResult)
|
|
109
|
+
: normalizeFunctionResult(result)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function createValidationCommitter<Value>(commit: (value: Value) => void) {
|
|
113
|
+
let commitId = 0
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
invalidate() {
|
|
117
|
+
commitId += 1
|
|
118
|
+
},
|
|
119
|
+
run(value: Value | PromiseLike<Value>): Value | Promise<Value> {
|
|
120
|
+
commitId += 1
|
|
121
|
+
const nextCommitId = commitId
|
|
122
|
+
|
|
123
|
+
if (isPromiseLike<Value>(value)) {
|
|
124
|
+
return Promise.resolve(value).then((nextValue) => {
|
|
125
|
+
if (nextCommitId === commitId) {
|
|
126
|
+
commit(nextValue)
|
|
127
|
+
}
|
|
128
|
+
return nextValue
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
commit(value)
|
|
133
|
+
return value
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
}
|