@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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/Field.cjs +857 -0
  3. package/dist/cjs/Field.native.cjs +1018 -0
  4. package/dist/cjs/Field.native.js +1020 -0
  5. package/dist/cjs/Field.native.js.map +1 -0
  6. package/dist/cjs/FieldContext.cjs +86 -0
  7. package/dist/cjs/FieldContext.native.cjs +90 -0
  8. package/dist/cjs/FieldContext.native.js +92 -0
  9. package/dist/cjs/FieldContext.native.js.map +1 -0
  10. package/dist/cjs/index.cjs +21 -0
  11. package/dist/cjs/index.native.cjs +23 -0
  12. package/dist/cjs/index.native.js +25 -0
  13. package/dist/cjs/index.native.js.map +1 -0
  14. package/dist/cjs/types.cjs +17 -0
  15. package/dist/cjs/types.native.cjs +19 -0
  16. package/dist/cjs/types.native.js +21 -0
  17. package/dist/cjs/types.native.js.map +1 -0
  18. package/dist/cjs/validation.cjs +114 -0
  19. package/dist/cjs/validation.native.cjs +126 -0
  20. package/dist/cjs/validation.native.js +128 -0
  21. package/dist/cjs/validation.native.js.map +1 -0
  22. package/dist/esm/Field.mjs +824 -0
  23. package/dist/esm/Field.mjs.map +1 -0
  24. package/dist/esm/Field.native.js +983 -0
  25. package/dist/esm/Field.native.js.map +1 -0
  26. package/dist/esm/FieldContext.mjs +51 -0
  27. package/dist/esm/FieldContext.mjs.map +1 -0
  28. package/dist/esm/FieldContext.native.js +53 -0
  29. package/dist/esm/FieldContext.native.js.map +1 -0
  30. package/dist/esm/index.js +5 -0
  31. package/dist/esm/index.mjs +5 -0
  32. package/dist/esm/index.native.js +5 -0
  33. package/dist/esm/types.mjs +0 -0
  34. package/dist/esm/types.native.js +0 -0
  35. package/dist/esm/validation.mjs +86 -0
  36. package/dist/esm/validation.mjs.map +1 -0
  37. package/dist/esm/validation.native.js +96 -0
  38. package/dist/esm/validation.native.js.map +1 -0
  39. package/dist/jsx/Field.mjs +824 -0
  40. package/dist/jsx/Field.mjs.map +1 -0
  41. package/dist/jsx/Field.native.cjs +1018 -0
  42. package/dist/jsx/Field.native.js +1020 -0
  43. package/dist/jsx/Field.native.js.map +1 -0
  44. package/dist/jsx/FieldContext.mjs +51 -0
  45. package/dist/jsx/FieldContext.mjs.map +1 -0
  46. package/dist/jsx/FieldContext.native.cjs +90 -0
  47. package/dist/jsx/FieldContext.native.js +92 -0
  48. package/dist/jsx/FieldContext.native.js.map +1 -0
  49. package/dist/jsx/index.js +5 -0
  50. package/dist/jsx/index.mjs +5 -0
  51. package/dist/jsx/index.native.cjs +23 -0
  52. package/dist/jsx/index.native.js +25 -0
  53. package/dist/jsx/index.native.js.map +1 -0
  54. package/dist/jsx/types.mjs +0 -0
  55. package/dist/jsx/types.native.cjs +19 -0
  56. package/dist/jsx/types.native.js +21 -0
  57. package/dist/jsx/types.native.js.map +1 -0
  58. package/dist/jsx/validation.mjs +86 -0
  59. package/dist/jsx/validation.mjs.map +1 -0
  60. package/dist/jsx/validation.native.cjs +126 -0
  61. package/dist/jsx/validation.native.js +128 -0
  62. package/dist/jsx/validation.native.js.map +1 -0
  63. package/package.json +50 -5
  64. package/src/Field.tsx +1129 -0
  65. package/src/FieldContext.tsx +61 -0
  66. package/src/index.ts +3 -0
  67. package/src/types.ts +125 -0
  68. package/src/validation.ts +136 -0
  69. package/types/Field.d.ts +401 -0
  70. package/types/Field.d.ts.map +1 -0
  71. package/types/FieldContext.d.ts +11 -0
  72. package/types/FieldContext.d.ts.map +1 -0
  73. package/types/index.d.ts +4 -0
  74. package/types/index.d.ts.map +1 -0
  75. package/types/types.d.ts +112 -0
  76. package/types/types.d.ts.map +1 -0
  77. package/types/validation.d.ts +24 -0
  78. package/types/validation.d.ts.map +1 -0
  79. 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
@@ -0,0 +1,3 @@
1
+ export * from './Field'
2
+ export * from './FieldContext'
3
+ export * from './types'
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
+ }