@codeleap/mobile 4.3.9 → 5.0.0
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/components/Autocomplete/index.js.map +1 -1
- package/dist/components/Autocomplete/types.d.ts +9 -10
- package/dist/components/Backdrop/index.js.map +1 -1
- package/dist/components/Checkbox/index.js +13 -9
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Checkbox/types.d.ts +5 -2
- package/dist/components/DatePickerModal/index.js +18 -11
- package/dist/components/DatePickerModal/index.js.map +1 -1
- package/dist/components/DatePickerModal/types.d.ts +12 -9
- package/dist/components/FileInput/types.d.ts +3 -4
- package/dist/components/Grid/index.js.map +1 -1
- package/dist/components/Image/types.d.ts +2 -5
- package/dist/components/InputBase/index.d.ts +2 -6
- package/dist/components/InputBase/index.js +9 -5
- package/dist/components/InputBase/index.js.map +1 -1
- package/dist/components/InputBase/types.d.ts +2 -0
- package/dist/components/InputBase/useInputBase.d.ts +24 -0
- package/dist/components/InputBase/useInputBase.js +46 -0
- package/dist/components/InputBase/useInputBase.js.map +1 -0
- package/dist/components/InputBase/useInputBasePartialStyles.d.ts +2 -0
- package/dist/components/InputBase/useInputBasePartialStyles.js +30 -0
- package/dist/components/InputBase/useInputBasePartialStyles.js.map +1 -0
- package/dist/components/InputBase/utils.js +16 -16
- package/dist/components/InputBase/utils.js.map +1 -1
- package/dist/components/List/index.js +1 -1
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Modal/index.js +4 -14
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/NumberIncrement/index.js +21 -132
- package/dist/components/NumberIncrement/index.js.map +1 -1
- package/dist/components/NumberIncrement/types.d.ts +7 -5
- package/dist/components/NumberIncrement/useNumberIncrement.d.ts +55 -0
- package/dist/components/NumberIncrement/useNumberIncrement.js +107 -0
- package/dist/components/NumberIncrement/useNumberIncrement.js.map +1 -0
- package/dist/components/RadioInput/index.d.ts +1 -1
- package/dist/components/RadioInput/index.js +20 -41
- package/dist/components/RadioInput/index.js.map +1 -1
- package/dist/components/RadioInput/types.d.ts +11 -9
- package/dist/components/Scroll/index.js +25 -28
- package/dist/components/Scroll/index.js.map +1 -1
- package/dist/components/Scroll/types.d.ts +4 -4
- package/dist/components/Sections/index.js +1 -1
- package/dist/components/Sections/index.js.map +1 -1
- package/dist/components/SegmentedControl/index.js +6 -4
- package/dist/components/SegmentedControl/index.js.map +1 -1
- package/dist/components/SegmentedControl/types.d.ts +4 -3
- package/dist/components/Select/index.js +10 -6
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/Select/types.d.ts +19 -18
- package/dist/components/Slider/index.js +18 -57
- package/dist/components/Slider/index.js.map +1 -1
- package/dist/components/Slider/types.d.ts +7 -5
- package/dist/components/SortablePhotos/index.js +17 -18
- package/dist/components/SortablePhotos/index.js.map +1 -1
- package/dist/components/SortablePhotos/types.d.ts +5 -15
- package/dist/components/SortablePhotos/useSortablePhotos.d.ts +11 -8
- package/dist/components/SortablePhotos/useSortablePhotos.js +18 -11
- package/dist/components/SortablePhotos/useSortablePhotos.js.map +1 -1
- package/dist/components/Switch/index.js +13 -9
- package/dist/components/Switch/index.js.map +1 -1
- package/dist/components/Switch/types.d.ts +5 -2
- package/dist/components/TextInput/index.js +26 -70
- package/dist/components/TextInput/index.js.map +1 -1
- package/dist/components/TextInput/types.d.ts +8 -6
- package/dist/components/TextInput/useTextInput.d.ts +54 -0
- package/dist/components/TextInput/useTextInput.js +59 -0
- package/dist/components/TextInput/useTextInput.js.map +1 -0
- package/dist/components/Touchable/index.js +4 -3
- package/dist/components/Touchable/index.js.map +1 -1
- package/dist/components/View/index.d.ts +7 -12
- package/dist/components/View/index.js +9 -7
- package/dist/components/View/index.js.map +1 -1
- package/dist/components/View/types.d.ts +6 -6
- package/dist/components/components.d.ts +0 -2
- package/dist/components/components.js +0 -2
- package/dist/components/components.js.map +1 -1
- package/dist/hooks/index.d.ts +3 -2
- package/dist/hooks/index.js +3 -10
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useKeyboardController.d.ts +6 -0
- package/dist/hooks/useKeyboardController.js +19 -0
- package/dist/hooks/useKeyboardController.js.map +1 -0
- package/dist/hooks/useStatusBar.d.ts +6 -0
- package/dist/hooks/useStatusBar.js +15 -0
- package/dist/hooks/useStatusBar.js.map +1 -0
- package/dist/hooks/useStylesFor.d.ts +2 -0
- package/dist/hooks/useStylesFor.js +11 -0
- package/dist/hooks/useStylesFor.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/backgroundTimer.d.ts +3 -0
- package/dist/modules/backgroundTimer.js +31 -0
- package/dist/modules/backgroundTimer.js.map +1 -0
- package/dist/modules/index.d.ts +3 -0
- package/dist/modules/index.js +3 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/reactNavigation.d.ts +8 -21
- package/dist/modules/reactNavigation.js +38 -12
- package/dist/modules/reactNavigation.js.map +1 -1
- package/dist/modules/scroll.d.ts +18 -0
- package/dist/modules/scroll.js +57 -0
- package/dist/modules/scroll.js.map +1 -0
- package/dist/modules/types/textInputMask.d.ts +6 -2
- package/dist/utils/KeyboardAware/context.js +2 -6
- package/dist/utils/KeyboardAware/context.js.map +1 -1
- package/dist/utils/KeyboardAware/index.d.ts +0 -1
- package/dist/utils/KeyboardAware/index.js +0 -1
- package/dist/utils/KeyboardAware/index.js.map +1 -1
- package/dist/utils/ModalManager/context.js +2 -2
- package/dist/utils/ModalManager/context.js.map +1 -1
- package/dist/utils/hooks.js +4 -4
- package/dist/utils/hooks.js.map +1 -1
- package/dist/utils/locale.d.ts +1 -1
- package/dist/utils/locale.js +10 -5
- package/dist/utils/locale.js.map +1 -1
- package/dist/utils/theme.d.ts +1 -0
- package/dist/utils/theme.js +4 -2
- package/dist/utils/theme.js.map +1 -1
- package/package.json +31 -35
- package/package.json.bak +17 -20
- package/src/components/Autocomplete/index.tsx +2 -3
- package/src/components/Autocomplete/types.ts +9 -10
- package/src/components/Backdrop/index.tsx +0 -1
- package/src/components/Checkbox/index.tsx +23 -9
- package/src/components/Checkbox/types.ts +5 -2
- package/src/components/DatePickerModal/index.tsx +27 -18
- package/src/components/DatePickerModal/types.ts +12 -9
- package/src/components/FileInput/types.ts +3 -4
- package/src/components/Grid/index.tsx +3 -3
- package/src/components/Image/types.ts +3 -6
- package/src/components/InputBase/index.tsx +13 -7
- package/src/components/InputBase/types.ts +2 -0
- package/src/components/InputBase/useInputBase.ts +60 -0
- package/src/components/InputBase/useInputBasePartialStyles.ts +38 -0
- package/src/components/InputBase/utils.ts +17 -17
- package/src/components/List/index.tsx +0 -1
- package/src/components/Modal/index.tsx +4 -15
- package/src/components/NumberIncrement/index.tsx +52 -160
- package/src/components/NumberIncrement/types.ts +7 -5
- package/src/components/NumberIncrement/useNumberIncrement.ts +152 -0
- package/src/components/RadioInput/index.tsx +37 -53
- package/src/components/RadioInput/types.ts +11 -9
- package/src/components/Scroll/index.tsx +44 -45
- package/src/components/Scroll/types.ts +4 -4
- package/src/components/Sections/index.tsx +0 -1
- package/src/components/SegmentedControl/index.tsx +8 -6
- package/src/components/SegmentedControl/types.ts +4 -3
- package/src/components/Select/index.tsx +32 -24
- package/src/components/Select/types.ts +19 -18
- package/src/components/Slider/index.tsx +34 -66
- package/src/components/Slider/types.ts +7 -5
- package/src/components/SortablePhotos/index.tsx +31 -47
- package/src/components/SortablePhotos/types.ts +6 -15
- package/src/components/SortablePhotos/useSortablePhotos.ts +28 -22
- package/src/components/Switch/index.tsx +23 -9
- package/src/components/Switch/types.ts +5 -2
- package/src/components/TextInput/index.tsx +55 -89
- package/src/components/TextInput/types.ts +9 -7
- package/src/components/TextInput/useTextInput.ts +88 -0
- package/src/components/Touchable/index.tsx +5 -1
- package/src/components/View/index.tsx +19 -12
- package/src/components/View/types.ts +7 -6
- package/src/components/components.ts +0 -2
- package/src/hooks/index.ts +3 -13
- package/src/hooks/useKeyboardController.ts +28 -0
- package/src/hooks/useStatusBar.ts +21 -0
- package/src/hooks/useStylesFor.ts +13 -0
- package/src/index.ts +3 -1
- package/src/modules/backgroundTimer.ts +39 -0
- package/src/modules/index.ts +3 -0
- package/src/modules/reactNavigation.ts +64 -14
- package/src/modules/scroll.tsx +89 -0
- package/src/modules/types/textInputMask.ts +8 -4
- package/src/types/index.ts +1 -0
- package/src/utils/KeyboardAware/context.tsx +2 -6
- package/src/utils/KeyboardAware/index.ts +1 -1
- package/src/utils/ModalManager/context.tsx +2 -2
- package/src/utils/hooks.ts +4 -4
- package/src/utils/locale.ts +13 -5
- package/src/utils/theme.ts +6 -2
- package/dist/components/Navigation/Navigation.d.ts +0 -55
- package/dist/components/Navigation/Navigation.js +0 -41
- package/dist/components/Navigation/Navigation.js.map +0 -1
- package/dist/components/Navigation/constants.d.ts +0 -9
- package/dist/components/Navigation/constants.js +0 -9
- package/dist/components/Navigation/constants.js.map +0 -1
- package/dist/components/Navigation/index.d.ts +0 -3
- package/dist/components/Navigation/index.js +0 -4
- package/dist/components/Navigation/index.js.map +0 -1
- package/dist/components/Navigation/types.d.ts +0 -26
- package/dist/components/Navigation/types.js +0 -2
- package/dist/components/Navigation/types.js.map +0 -1
- package/dist/components/Navigation/utils.d.ts +0 -3
- package/dist/components/Navigation/utils.js +0 -34
- package/dist/components/Navigation/utils.js.map +0 -1
- package/dist/components/NumberIncrement/utils.d.ts +0 -5
- package/dist/components/NumberIncrement/utils.js +0 -23
- package/dist/components/NumberIncrement/utils.js.map +0 -1
- package/dist/utils/KeyboardAware/types.d.ts +0 -1
- package/dist/utils/KeyboardAware/types.js +0 -6
- package/dist/utils/KeyboardAware/types.js.map +0 -1
- package/src/components/Navigation/Navigation.tsx +0 -55
- package/src/components/Navigation/constants.ts +0 -24
- package/src/components/Navigation/index.tsx +0 -3
- package/src/components/Navigation/types.ts +0 -28
- package/src/components/Navigation/utils.tsx +0 -57
- package/src/components/NumberIncrement/utils.ts +0 -27
- package/src/utils/KeyboardAware/types.ts +0 -159
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CreateOSAlert } from '@codeleap/modals'
|
|
2
2
|
import { useEffect, useMemo, useState } from '@codeleap/hooks'
|
|
3
3
|
import { FileInputImageSource, useFileInput } from '../FileInput'
|
|
4
|
-
import { SortablePhoto, SortablePhotosProps } from './types'
|
|
4
|
+
import { SortablePhoto, SortablePhotosProps, WithId } from './types'
|
|
5
5
|
|
|
6
6
|
const SortableAlert = CreateOSAlert()
|
|
7
7
|
|
|
@@ -22,9 +22,9 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
22
22
|
|
|
23
23
|
const input = useFileInput()
|
|
24
24
|
|
|
25
|
-
const [data, setData] = useState<T[]>([])
|
|
25
|
+
const [data, setData] = useState<WithId<T>[]>([])
|
|
26
26
|
|
|
27
|
-
const onChange = (photos: T[]) => {
|
|
27
|
+
const onChange = (photos: WithId<T>[]) => {
|
|
28
28
|
const { newPhotos, sortedPhotos } = sortPhotos(photos)
|
|
29
29
|
|
|
30
30
|
setData(sortedPhotos)
|
|
@@ -37,14 +37,14 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
37
37
|
const length = Math.abs(numPhotos - currentLength)
|
|
38
38
|
const fillPhotos = Array(length).fill({ filename: null, file: null }) as T[]
|
|
39
39
|
|
|
40
|
-
const newPhotos = currentPhotos.concat(fillPhotos)
|
|
40
|
+
const newPhotos = currentPhotos.concat(fillPhotos).map((photo, idx) => ({ ...photo, key: idx + '-photo' }))
|
|
41
41
|
|
|
42
42
|
setData(newPhotos)
|
|
43
|
-
onChangePhotos(currentPhotos)
|
|
43
|
+
onChangePhotos(assignOrder(currentPhotos))
|
|
44
44
|
}
|
|
45
45
|
}, [loading])
|
|
46
46
|
|
|
47
|
-
const { emptyIndexes, numberPhotosMissing } = useMemo(() => {
|
|
47
|
+
const { emptyIndexes, numberPhotosMissing, enabledDragDrop } = useMemo(() => {
|
|
48
48
|
const copyPhotos = [...data]
|
|
49
49
|
|
|
50
50
|
const emptyIndexes = copyPhotos.reduce((indexes, photo, index) => {
|
|
@@ -56,28 +56,32 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
56
56
|
|
|
57
57
|
const numberPhotosMissing = emptyIndexes?.length
|
|
58
58
|
|
|
59
|
+
const enabledDragDrop = numberPhotosMissing < numPhotos - 1
|
|
60
|
+
|
|
59
61
|
return {
|
|
60
62
|
emptyIndexes,
|
|
61
63
|
numberPhotosMissing,
|
|
64
|
+
enabledDragDrop,
|
|
62
65
|
}
|
|
63
66
|
}, [JSON.stringify(data)])
|
|
64
67
|
|
|
65
|
-
const
|
|
68
|
+
const assignOrder = (photos: WithId<T>[] | T[]) => {
|
|
69
|
+
return photos.map((photo, idx) => ({ ...photo, order: idx }))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const sortPhotos = (_unorderedPhotos: WithId<T>[]) => {
|
|
66
73
|
const unorderedPhotos = [..._unorderedPhotos]
|
|
67
74
|
|
|
68
|
-
const
|
|
69
|
-
([newPhotos, emptyPhotos], photo) => {
|
|
70
|
-
!!photo?.filename ? newPhotos.push(photo) : emptyPhotos.push(photo)
|
|
71
|
-
return [newPhotos, emptyPhotos]
|
|
72
|
-
},
|
|
73
|
-
[[], []] as [T[], T[]]
|
|
74
|
-
)
|
|
75
|
+
const newPhotos = unorderedPhotos.filter(photo => !!photo?.filename)
|
|
75
76
|
|
|
76
|
-
const sortedPhotos
|
|
77
|
+
const sortedPhotos = unorderedPhotos.map((photo, index) => ({
|
|
78
|
+
...(newPhotos[index] ?? { file: null, filename: null } as T),
|
|
79
|
+
key: photo?.key
|
|
80
|
+
}))
|
|
77
81
|
|
|
78
82
|
return {
|
|
79
83
|
sortedPhotos,
|
|
80
|
-
newPhotos,
|
|
84
|
+
newPhotos: assignOrder(newPhotos),
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
|
|
@@ -111,7 +115,7 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
111
115
|
...newPhotos[order],
|
|
112
116
|
filename,
|
|
113
117
|
file: uri,
|
|
114
|
-
} as T
|
|
118
|
+
} as WithId<T>
|
|
115
119
|
}
|
|
116
120
|
} else {
|
|
117
121
|
const file = files?.[0]
|
|
@@ -122,7 +126,7 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
122
126
|
...newPhotos[order],
|
|
123
127
|
filename,
|
|
124
128
|
file: uri,
|
|
125
|
-
} as T
|
|
129
|
+
} as WithId<T>
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
onChange(newPhotos)
|
|
@@ -135,12 +139,12 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
135
139
|
...newPhotos[order],
|
|
136
140
|
filename: null,
|
|
137
141
|
file: null,
|
|
138
|
-
} as T
|
|
142
|
+
} as WithId<T>
|
|
139
143
|
|
|
140
144
|
onChange(newPhotos)
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
const handlePressPhoto = (
|
|
147
|
+
const handlePressPhoto = (photo: T, order: number) => {
|
|
144
148
|
SortableAlert.custom({
|
|
145
149
|
title: modalTitle,
|
|
146
150
|
body: modalBody,
|
|
@@ -150,13 +154,14 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
150
154
|
!!photo?.filename && { text: modalDeleteText, onPress: () => handleDeletePhoto(photo, order) },
|
|
151
155
|
],
|
|
152
156
|
// @ts-expect-error
|
|
157
|
+
closable: true,
|
|
153
158
|
isRow: false,
|
|
154
159
|
})
|
|
155
160
|
|
|
156
|
-
onPressPhoto?.(
|
|
161
|
+
onPressPhoto?.(data, photo, order)
|
|
157
162
|
}
|
|
158
163
|
|
|
159
|
-
const onChangePhotosOrder = (newData: T[]) => {
|
|
164
|
+
const onChangePhotosOrder = (newData: WithId<T>[]) => {
|
|
160
165
|
onChange(newData)
|
|
161
166
|
}
|
|
162
167
|
|
|
@@ -170,5 +175,6 @@ export const useSortablePhotos = <T extends SortablePhoto>(props: SortablePhotos
|
|
|
170
175
|
onChangePhotosOrder,
|
|
171
176
|
emptyIndexes,
|
|
172
177
|
data,
|
|
178
|
+
enabledDragDrop,
|
|
173
179
|
}
|
|
174
180
|
}
|
|
@@ -7,6 +7,8 @@ import { SwitchProps } from './types'
|
|
|
7
7
|
import { AnyRecord, IJSX, StyledComponentProps } from '@codeleap/styles'
|
|
8
8
|
import { MobileStyleRegistry } from '../../Registry'
|
|
9
9
|
import { useStylesFor } from '../../hooks'
|
|
10
|
+
import { useInputBase } from '../InputBase/useInputBase'
|
|
11
|
+
import { fields } from '@codeleap/form'
|
|
10
12
|
|
|
11
13
|
export * from './styles'
|
|
12
14
|
export * from './types'
|
|
@@ -24,15 +26,23 @@ export const Switch = (props: SwitchProps) => {
|
|
|
24
26
|
|
|
25
27
|
const {
|
|
26
28
|
style,
|
|
27
|
-
value,
|
|
28
29
|
disabled,
|
|
29
30
|
debugName,
|
|
30
|
-
onValueChange,
|
|
31
31
|
switchOnLeft,
|
|
32
|
+
field,
|
|
33
|
+
forceError,
|
|
34
|
+
value,
|
|
35
|
+
onValueChange,
|
|
32
36
|
} = others
|
|
33
37
|
|
|
34
38
|
const styles = useStylesFor(Switch.styleRegistryName, style)
|
|
35
39
|
|
|
40
|
+
const {
|
|
41
|
+
fieldHandle,
|
|
42
|
+
validation,
|
|
43
|
+
wrapperRef,
|
|
44
|
+
} = useInputBase<boolean>(field, fields.boolean, [value, onValueChange])
|
|
45
|
+
|
|
36
46
|
const trackAnimation = useAnimatedVariantStyles({
|
|
37
47
|
variantStyles: styles,
|
|
38
48
|
animatedProperties: ['track:off', 'track:disabled', 'track:on', 'track:disabled-on', 'track:disabled-off'],
|
|
@@ -41,16 +51,16 @@ export const Switch = (props: SwitchProps) => {
|
|
|
41
51
|
'worklet'
|
|
42
52
|
let disabledStyle = {}
|
|
43
53
|
if (disabled) {
|
|
44
|
-
disabledStyle = value ? styles['track:disabled-on'] : styles['track:disabled-off']
|
|
54
|
+
disabledStyle = fieldHandle?.value ? styles['track:disabled-on'] : styles['track:disabled-off']
|
|
45
55
|
}
|
|
46
|
-
const style = value ? styles['track:on'] : styles['track:off']
|
|
56
|
+
const style = fieldHandle?.value ? styles['track:on'] : styles['track:off']
|
|
47
57
|
|
|
48
58
|
return {
|
|
49
59
|
...style,
|
|
50
60
|
...disabledStyle,
|
|
51
61
|
}
|
|
52
62
|
},
|
|
53
|
-
dependencies: [value, disabled],
|
|
63
|
+
dependencies: [fieldHandle?.value, disabled],
|
|
54
64
|
})
|
|
55
65
|
|
|
56
66
|
const thumbAnimation = useAnimatedVariantStyles({
|
|
@@ -61,29 +71,33 @@ export const Switch = (props: SwitchProps) => {
|
|
|
61
71
|
'worklet'
|
|
62
72
|
let disabledStyle = {}
|
|
63
73
|
if (disabled) {
|
|
64
|
-
disabledStyle = value ? styles['thumb:disabled-on'] : styles['thumb:disabled-off']
|
|
74
|
+
disabledStyle = fieldHandle?.value ? styles['thumb:disabled-on'] : styles['thumb:disabled-off']
|
|
65
75
|
}
|
|
66
|
-
const style = value ? styles['thumb:on'] : styles['thumb:off']
|
|
76
|
+
const style = fieldHandle?.value ? styles['thumb:on'] : styles['thumb:off']
|
|
67
77
|
return {
|
|
68
78
|
...style,
|
|
69
79
|
...disabledStyle,
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
},
|
|
73
|
-
dependencies: [value, disabled],
|
|
83
|
+
dependencies: [fieldHandle?.value, disabled],
|
|
74
84
|
})
|
|
75
85
|
|
|
76
86
|
// @ts-expect-error
|
|
77
87
|
const _switchOnLeft = switchOnLeft ?? styles?.__props?.switchOnLeft
|
|
78
88
|
|
|
89
|
+
const hasError = validation.showError || forceError
|
|
90
|
+
|
|
79
91
|
return <InputBase
|
|
80
92
|
{...inputBaseProps}
|
|
93
|
+
ref={wrapperRef}
|
|
81
94
|
debugName={debugName}
|
|
82
95
|
wrapper={Touchable}
|
|
96
|
+
error={hasError ? validation.message || forceError : null}
|
|
83
97
|
style={styles}
|
|
84
98
|
wrapperProps={{
|
|
85
99
|
onPress: () => {
|
|
86
|
-
|
|
100
|
+
fieldHandle.setValue(!fieldHandle?.value)
|
|
87
101
|
},
|
|
88
102
|
disabled,
|
|
89
103
|
rippleDisabled: true,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { StyledProp } from '@codeleap/styles'
|
|
2
2
|
import { InputBaseProps } from '../InputBase'
|
|
3
3
|
import { SwitchComposition } from './styles'
|
|
4
|
+
import { BooleanField } from '@codeleap/form'
|
|
4
5
|
|
|
5
6
|
export type SwitchProps =
|
|
6
7
|
Omit<InputBaseProps, 'style'> &
|
|
7
8
|
{
|
|
8
|
-
|
|
9
|
-
onValueChange: (value: boolean) => void
|
|
9
|
+
field?: BooleanField<any>
|
|
10
10
|
style?: StyledProp<SwitchComposition>
|
|
11
11
|
switchOnLeft?: boolean
|
|
12
|
+
forceError?: boolean
|
|
13
|
+
value?: boolean
|
|
14
|
+
onValueChange?: (value: boolean) => void
|
|
12
15
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { useValidate } from '@codeleap/form'
|
|
3
|
-
import { useBooleanToggle } from '@codeleap/hooks'
|
|
1
|
+
import React from 'react'
|
|
4
2
|
import { TypeGuards } from '@codeleap/types'
|
|
5
|
-
import { forwardRef
|
|
6
|
-
import { TextInput as NativeTextInput
|
|
3
|
+
import { forwardRef } from 'react'
|
|
4
|
+
import { TextInput as NativeTextInput } from 'react-native'
|
|
7
5
|
import { InputBase, selectInputBaseProps } from '../InputBase'
|
|
8
6
|
import { Touchable } from '../Touchable'
|
|
9
7
|
import { MaskedTextInput } from '../../modules/textInputMask'
|
|
@@ -11,31 +9,29 @@ import { AnyRecord, AppIcon, IJSX, StyledComponentProps, StyledComponentWithProp
|
|
|
11
9
|
import { TextInputProps } from './types'
|
|
12
10
|
import { MobileStyleRegistry } from '../../Registry'
|
|
13
11
|
import { useStylesFor } from '../../hooks'
|
|
12
|
+
import { useTextInput } from './useTextInput'
|
|
13
|
+
import { useInputBasePartialStyles } from '../InputBase/useInputBasePartialStyles'
|
|
14
14
|
|
|
15
15
|
export * from './styles'
|
|
16
16
|
export * from './types'
|
|
17
17
|
|
|
18
18
|
export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inputRef) => {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const allProps = {
|
|
20
|
+
...TextInput.defaultProps,
|
|
21
|
+
...props,
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
const {
|
|
25
25
|
inputBaseProps,
|
|
26
26
|
others,
|
|
27
|
-
} = selectInputBaseProps(
|
|
28
|
-
...TextInput.defaultProps,
|
|
29
|
-
...props,
|
|
30
|
-
})
|
|
27
|
+
} = selectInputBaseProps(allProps)
|
|
31
28
|
|
|
32
29
|
const {
|
|
33
|
-
value,
|
|
34
|
-
validate,
|
|
35
30
|
debugName,
|
|
36
31
|
visibilityToggle,
|
|
37
32
|
masking,
|
|
38
|
-
|
|
33
|
+
secure,
|
|
34
|
+
field,
|
|
39
35
|
onChangeMask,
|
|
40
36
|
onPress,
|
|
41
37
|
visibleIcon,
|
|
@@ -43,70 +39,42 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
|
|
|
43
39
|
style,
|
|
44
40
|
autoAdjustSelection,
|
|
45
41
|
selectionStart,
|
|
46
|
-
|
|
42
|
+
forceError,
|
|
43
|
+
onChangeText,
|
|
44
|
+
multiline,
|
|
47
45
|
...textInputProps
|
|
48
46
|
} = others
|
|
49
47
|
|
|
50
|
-
const [secureTextEntry, toggleSecureTextEntry] = useBooleanToggle(true)
|
|
51
|
-
|
|
52
|
-
const isMasked = !!masking
|
|
53
|
-
|
|
54
|
-
const InputElement = isMasked ? MaskedTextInput : NativeTextInput
|
|
55
|
-
|
|
56
48
|
const styles = useStylesFor(TextInput.styleRegistryName, style)
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
const {
|
|
51
|
+
fieldHandle,
|
|
52
|
+
validation,
|
|
53
|
+
innerInputRef,
|
|
54
|
+
wrapperRef,
|
|
55
|
+
isFocused,
|
|
56
|
+
secureTextEntry,
|
|
57
|
+
currentSelection,
|
|
58
|
+
hasMultipleLines,
|
|
59
|
+
hasValue,
|
|
60
|
+
hasError,
|
|
61
|
+
toggleSecureTextEntry,
|
|
62
|
+
handleMaskChange,
|
|
63
|
+
handleBlur,
|
|
64
|
+
handleFocus,
|
|
65
|
+
} = useTextInput(allProps)
|
|
66
|
+
|
|
67
|
+
const InputElement = masking ? MaskedTextInput : NativeTextInput
|
|
68
68
|
|
|
69
69
|
const isPressable = TypeGuards.isFunction(onPress)
|
|
70
70
|
|
|
71
|
-
const validation = useValidate(value, validate)
|
|
72
|
-
|
|
73
|
-
const handleBlur = React.useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
74
|
-
validation.onInputBlurred()
|
|
75
|
-
setIsFocused(false)
|
|
76
|
-
if (autoAdjustSelection) setCurrentSelection({ start: selectionStart })
|
|
77
|
-
props.onBlur?.(e)
|
|
78
|
-
}, [validation.onInputBlurred, props.onBlur])
|
|
79
|
-
|
|
80
|
-
const handleFocus = React.useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
81
|
-
validation.onInputFocused()
|
|
82
|
-
setIsFocused(true)
|
|
83
|
-
if (autoAdjustSelection) setCurrentSelection(null)
|
|
84
|
-
props.onFocus?.(e)
|
|
85
|
-
}, [validation.onInputFocused, props.onFocus])
|
|
86
|
-
|
|
87
|
-
const handleMaskChange = (masked, unmasked) => {
|
|
88
|
-
if (textInputProps.onChangeText) textInputProps.onChangeText(masking?.saveFormatted ? masked : masked)
|
|
89
|
-
if (onChangeMask) onChangeMask(masked, unmasked)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const isMultiline = textInputProps.multiline
|
|
93
71
|
const isDisabled = !!inputBaseProps.disabled
|
|
94
72
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// @ts-expect-error
|
|
101
|
-
].find(([x]) => x)?.[1]?.color
|
|
102
|
-
|
|
103
|
-
const selectionColor = [
|
|
104
|
-
[isDisabled, styles['selection:disabled']],
|
|
105
|
-
[!validation.isValid, styles['selection:error']],
|
|
106
|
-
[isFocused, styles['selection:focus']],
|
|
107
|
-
[true, styles?.selection],
|
|
108
|
-
// @ts-expect-error
|
|
109
|
-
].find(([x]) => x)?.[1]?.color
|
|
73
|
+
const partialStyles = useInputBasePartialStyles(styles, ['placeholder', 'selection'], {
|
|
74
|
+
disabled: isDisabled,
|
|
75
|
+
error: !!hasError,
|
|
76
|
+
focus: isFocused,
|
|
77
|
+
})
|
|
110
78
|
|
|
111
79
|
const visibilityToggleProps = visibilityToggle ? {
|
|
112
80
|
onPress: toggleSecureTextEntry,
|
|
@@ -116,36 +84,33 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
|
|
|
116
84
|
|
|
117
85
|
const rightIcon = inputBaseProps?.rightIcon ?? visibilityToggleProps
|
|
118
86
|
|
|
119
|
-
const maskingExtraProps =
|
|
87
|
+
const maskingExtraProps = masking ? {
|
|
120
88
|
onChangeText: handleMaskChange,
|
|
121
89
|
ref: null,
|
|
122
90
|
refInput: (inputRef) => {
|
|
123
|
-
if (!!inputRef)
|
|
124
|
-
innerInputRef.current = inputRef
|
|
125
|
-
}
|
|
91
|
+
if (!!inputRef) innerInputRef.current = inputRef
|
|
126
92
|
},
|
|
127
93
|
...masking,
|
|
128
|
-
} : {
|
|
94
|
+
} : {
|
|
95
|
+
onChangeText: fieldHandle.setValue
|
|
96
|
+
}
|
|
129
97
|
|
|
130
98
|
const buttonModeProps = isPressable ? {
|
|
131
99
|
editable: false,
|
|
132
100
|
caretHidden: true,
|
|
133
101
|
} : {}
|
|
134
102
|
|
|
135
|
-
const hasMultipleLines = isMultiline && value?.includes('\n')
|
|
136
|
-
|
|
137
|
-
const hasValue = value?.length > 0
|
|
138
|
-
|
|
139
103
|
return <InputBase
|
|
140
104
|
{...inputBaseProps}
|
|
105
|
+
ref={wrapperRef}
|
|
141
106
|
innerWrapper={isPressable ? Touchable : undefined}
|
|
142
107
|
debugName={debugName}
|
|
143
|
-
error={
|
|
108
|
+
error={hasError ? validation.message || forceError : null}
|
|
144
109
|
style={{
|
|
145
110
|
...styles,
|
|
146
111
|
innerWrapper: [
|
|
147
112
|
styles?.innerWrapper,
|
|
148
|
-
|
|
113
|
+
multiline && styles['innerWrapper:multiline'],
|
|
149
114
|
hasMultipleLines && styles['innerWrapper:hasMultipleLines'],
|
|
150
115
|
],
|
|
151
116
|
}}
|
|
@@ -164,23 +129,23 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
|
|
|
164
129
|
editable={!isPressable && !isDisabled}
|
|
165
130
|
{...buttonModeProps}
|
|
166
131
|
selection={autoAdjustSelection ? currentSelection : undefined}
|
|
167
|
-
placeholderTextColor={
|
|
168
|
-
value={value}
|
|
169
|
-
selectionColor={
|
|
170
|
-
secureTextEntry={
|
|
171
|
-
textAlignVertical={
|
|
132
|
+
placeholderTextColor={partialStyles?.placeholder?.color}
|
|
133
|
+
value={fieldHandle?.value}
|
|
134
|
+
selectionColor={partialStyles?.selection?.color}
|
|
135
|
+
secureTextEntry={secure && secureTextEntry}
|
|
136
|
+
textAlignVertical={multiline ? 'top' : undefined}
|
|
137
|
+
multiline={multiline}
|
|
172
138
|
{...textInputProps}
|
|
173
139
|
onBlur={handleBlur}
|
|
174
140
|
onFocus={handleFocus}
|
|
175
141
|
style={[
|
|
176
142
|
styles?.input,
|
|
177
|
-
|
|
143
|
+
multiline && styles['input:multiline'],
|
|
178
144
|
isFocused && styles['input:focused'],
|
|
179
|
-
|
|
145
|
+
hasError && styles['input:error'],
|
|
180
146
|
isDisabled && styles['input:disabled'],
|
|
181
147
|
hasMultipleLines && styles['input:hasMultipleLines'],
|
|
182
148
|
hasValue && styles['input:typed'],
|
|
183
|
-
|
|
184
149
|
]}
|
|
185
150
|
ref={innerInputRef}
|
|
186
151
|
pointerEvents={isPressable ? 'none' : undefined}
|
|
@@ -203,6 +168,7 @@ TextInput.defaultProps = {
|
|
|
203
168
|
visibilityToggle: false,
|
|
204
169
|
autoAdjustSelection: false,
|
|
205
170
|
selectionStart: 0,
|
|
171
|
+
secure: false,
|
|
206
172
|
} as Partial<TextInputProps>
|
|
207
173
|
|
|
208
174
|
MobileStyleRegistry.registerComponent(TextInput)
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { InputBaseProps } from '../InputBase'
|
|
2
2
|
import { TextInputProps as RNTextInputProps, TextInput as RNTextInput } from 'react-native'
|
|
3
3
|
import { AnyFunction } from '@codeleap/types'
|
|
4
|
-
import { FormTypes, yup } from '@codeleap/form'
|
|
5
4
|
import { AppIcon, StyledProp } from '@codeleap/styles'
|
|
6
5
|
import { TextInputMaskProps } from '../../modules/textInputMask'
|
|
7
6
|
import { TextInputComposition } from './styles'
|
|
7
|
+
import { Field } from '@codeleap/form'
|
|
8
8
|
|
|
9
9
|
export type TextInputProps =
|
|
10
|
-
Omit<InputBaseProps, 'style'> &
|
|
10
|
+
Omit<InputBaseProps, 'style' | 'ref'> &
|
|
11
11
|
Omit<RNTextInputProps, 'style'> &
|
|
12
12
|
{
|
|
13
|
-
|
|
14
|
-
validate?: FormTypes.ValidatorFunctionWithoutForm | yup.SchemaOf<string>
|
|
13
|
+
secure?: boolean
|
|
15
14
|
debugName: string
|
|
16
15
|
autoAdjustSelection?: boolean
|
|
17
16
|
selectionStart?: number
|
|
18
17
|
visibilityToggle?: boolean
|
|
19
|
-
masking?: FormTypes.TextField['masking']
|
|
20
18
|
onChangeMask?: TextInputMaskProps['onChangeText']
|
|
19
|
+
masking?: TextInputMaskProps['masking']
|
|
21
20
|
visibleIcon?: AppIcon
|
|
22
21
|
hiddenIcon?: AppIcon
|
|
23
|
-
|
|
22
|
+
forceError?: string
|
|
24
23
|
onPress?: AnyFunction
|
|
25
24
|
style?: StyledProp<TextInputComposition>
|
|
26
25
|
ref?: React.Ref<RNTextInput>
|
|
27
|
-
|
|
26
|
+
field?: Field<string, any, any>
|
|
27
|
+
value?: string
|
|
28
|
+
onValueChange?: (value: string) => void
|
|
29
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react'
|
|
2
|
+
import { TextInputProps } from './types'
|
|
3
|
+
import { NativeSyntheticEvent, TextInputFocusEventData } from 'react-native/types'
|
|
4
|
+
import { useInputBase } from '../InputBase/useInputBase'
|
|
5
|
+
import { fields } from '@codeleap/form'
|
|
6
|
+
|
|
7
|
+
export function useTextInput(props: Partial<TextInputProps>) {
|
|
8
|
+
const {
|
|
9
|
+
onFocus,
|
|
10
|
+
onBlur,
|
|
11
|
+
secure,
|
|
12
|
+
field,
|
|
13
|
+
autoAdjustSelection,
|
|
14
|
+
selectionStart,
|
|
15
|
+
masking,
|
|
16
|
+
onChangeMask,
|
|
17
|
+
multiline,
|
|
18
|
+
forceError,
|
|
19
|
+
value,
|
|
20
|
+
onValueChange,
|
|
21
|
+
} = props
|
|
22
|
+
|
|
23
|
+
const [isFocused, setIsFocused] = useState(false)
|
|
24
|
+
|
|
25
|
+
const [currentSelection, setCurrentSelection] = useState({ start: 0 })
|
|
26
|
+
|
|
27
|
+
const [secureTextEntry, setSecureTextEntry] = useState(secure)
|
|
28
|
+
|
|
29
|
+
const toggleSecureTextEntry = () => setSecureTextEntry(s => !s)
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
fieldHandle,
|
|
33
|
+
validation,
|
|
34
|
+
innerInputRef,
|
|
35
|
+
wrapperRef,
|
|
36
|
+
} = useInputBase<string>(field, fields.text, [value, onValueChange], {
|
|
37
|
+
revealValue() {
|
|
38
|
+
setSecureTextEntry(false)
|
|
39
|
+
},
|
|
40
|
+
hideValue() {
|
|
41
|
+
setSecureTextEntry(true)
|
|
42
|
+
},
|
|
43
|
+
toggleValueVisibility() {
|
|
44
|
+
toggleSecureTextEntry()
|
|
45
|
+
},
|
|
46
|
+
}, [setSecureTextEntry])
|
|
47
|
+
|
|
48
|
+
const handleBlur = useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
49
|
+
validation.onInputBlurred()
|
|
50
|
+
setIsFocused(false)
|
|
51
|
+
if (autoAdjustSelection) setCurrentSelection({ start: selectionStart })
|
|
52
|
+
onBlur?.(e)
|
|
53
|
+
}, [validation.onInputBlurred, onBlur])
|
|
54
|
+
|
|
55
|
+
const handleFocus = useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
56
|
+
setIsFocused(true)
|
|
57
|
+
if (autoAdjustSelection) setCurrentSelection(null)
|
|
58
|
+
onFocus?.(e)
|
|
59
|
+
}, [onFocus])
|
|
60
|
+
|
|
61
|
+
const handleMaskChange = useCallback((masked, unmasked) => {
|
|
62
|
+
fieldHandle.setValue(masking?.saveFormatted ? masked : masked)
|
|
63
|
+
if (onChangeMask) onChangeMask(masked, unmasked)
|
|
64
|
+
}, [masking?.saveFormatted, onChangeMask])
|
|
65
|
+
|
|
66
|
+
const hasMultipleLines = multiline && fieldHandle?.value?.includes('\n')
|
|
67
|
+
|
|
68
|
+
const hasValue = fieldHandle?.value?.length > 0
|
|
69
|
+
|
|
70
|
+
const hasError = validation.showError || forceError
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
isFocused,
|
|
74
|
+
currentSelection,
|
|
75
|
+
secureTextEntry,
|
|
76
|
+
handleBlur,
|
|
77
|
+
handleFocus,
|
|
78
|
+
handleMaskChange,
|
|
79
|
+
fieldHandle,
|
|
80
|
+
validation,
|
|
81
|
+
innerInputRef,
|
|
82
|
+
wrapperRef,
|
|
83
|
+
toggleSecureTextEntry,
|
|
84
|
+
hasMultipleLines,
|
|
85
|
+
hasValue,
|
|
86
|
+
hasError,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import { TypeGuards } from '@codeleap/types'
|
|
3
|
-
import { onMount } from '@codeleap/hooks'
|
|
3
|
+
import { onMount, useComponentTestId } from '@codeleap/hooks'
|
|
4
4
|
import { useGlobalContext } from '@codeleap/hooks'
|
|
5
5
|
import { Pressable, StyleSheet, View as RNView, Insets, Platform } from 'react-native'
|
|
6
6
|
import { View } from '../View'
|
|
@@ -51,6 +51,8 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
|
|
|
51
51
|
|
|
52
52
|
const { logger } = useGlobalContext()
|
|
53
53
|
|
|
54
|
+
const testId = useComponentTestId(Touchable, touchableProps, ['style', 'children', 'debounce'])
|
|
55
|
+
|
|
54
56
|
const press = () => {
|
|
55
57
|
if (!onPress) return
|
|
56
58
|
|
|
@@ -187,6 +189,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
|
|
|
187
189
|
{!disableRipple ? (
|
|
188
190
|
<PressableRipple
|
|
189
191
|
onPress={press}
|
|
192
|
+
testID={testId}
|
|
190
193
|
{...props}
|
|
191
194
|
style={[pressableStyle, styles?.pressable]}
|
|
192
195
|
rippleFades={false}
|
|
@@ -207,6 +210,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
|
|
|
207
210
|
getFeedbackStyle(pressed),
|
|
208
211
|
styles?.pressable,
|
|
209
212
|
])}
|
|
213
|
+
testID={testId}
|
|
210
214
|
{...props}
|
|
211
215
|
ref={ref}
|
|
212
216
|
>
|