@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.
Files changed (209) hide show
  1. package/dist/components/Autocomplete/index.js.map +1 -1
  2. package/dist/components/Autocomplete/types.d.ts +9 -10
  3. package/dist/components/Backdrop/index.js.map +1 -1
  4. package/dist/components/Checkbox/index.js +13 -9
  5. package/dist/components/Checkbox/index.js.map +1 -1
  6. package/dist/components/Checkbox/types.d.ts +5 -2
  7. package/dist/components/DatePickerModal/index.js +18 -11
  8. package/dist/components/DatePickerModal/index.js.map +1 -1
  9. package/dist/components/DatePickerModal/types.d.ts +12 -9
  10. package/dist/components/FileInput/types.d.ts +3 -4
  11. package/dist/components/Grid/index.js.map +1 -1
  12. package/dist/components/Image/types.d.ts +2 -5
  13. package/dist/components/InputBase/index.d.ts +2 -6
  14. package/dist/components/InputBase/index.js +9 -5
  15. package/dist/components/InputBase/index.js.map +1 -1
  16. package/dist/components/InputBase/types.d.ts +2 -0
  17. package/dist/components/InputBase/useInputBase.d.ts +24 -0
  18. package/dist/components/InputBase/useInputBase.js +46 -0
  19. package/dist/components/InputBase/useInputBase.js.map +1 -0
  20. package/dist/components/InputBase/useInputBasePartialStyles.d.ts +2 -0
  21. package/dist/components/InputBase/useInputBasePartialStyles.js +30 -0
  22. package/dist/components/InputBase/useInputBasePartialStyles.js.map +1 -0
  23. package/dist/components/InputBase/utils.js +16 -16
  24. package/dist/components/InputBase/utils.js.map +1 -1
  25. package/dist/components/List/index.js +1 -1
  26. package/dist/components/List/index.js.map +1 -1
  27. package/dist/components/Modal/index.js +4 -14
  28. package/dist/components/Modal/index.js.map +1 -1
  29. package/dist/components/NumberIncrement/index.js +21 -132
  30. package/dist/components/NumberIncrement/index.js.map +1 -1
  31. package/dist/components/NumberIncrement/types.d.ts +7 -5
  32. package/dist/components/NumberIncrement/useNumberIncrement.d.ts +55 -0
  33. package/dist/components/NumberIncrement/useNumberIncrement.js +107 -0
  34. package/dist/components/NumberIncrement/useNumberIncrement.js.map +1 -0
  35. package/dist/components/RadioInput/index.d.ts +1 -1
  36. package/dist/components/RadioInput/index.js +20 -41
  37. package/dist/components/RadioInput/index.js.map +1 -1
  38. package/dist/components/RadioInput/types.d.ts +11 -9
  39. package/dist/components/Scroll/index.js +25 -28
  40. package/dist/components/Scroll/index.js.map +1 -1
  41. package/dist/components/Scroll/types.d.ts +4 -4
  42. package/dist/components/Sections/index.js +1 -1
  43. package/dist/components/Sections/index.js.map +1 -1
  44. package/dist/components/SegmentedControl/index.js +6 -4
  45. package/dist/components/SegmentedControl/index.js.map +1 -1
  46. package/dist/components/SegmentedControl/types.d.ts +4 -3
  47. package/dist/components/Select/index.js +10 -6
  48. package/dist/components/Select/index.js.map +1 -1
  49. package/dist/components/Select/types.d.ts +19 -18
  50. package/dist/components/Slider/index.js +18 -57
  51. package/dist/components/Slider/index.js.map +1 -1
  52. package/dist/components/Slider/types.d.ts +7 -5
  53. package/dist/components/SortablePhotos/index.js +17 -18
  54. package/dist/components/SortablePhotos/index.js.map +1 -1
  55. package/dist/components/SortablePhotos/types.d.ts +5 -15
  56. package/dist/components/SortablePhotos/useSortablePhotos.d.ts +11 -8
  57. package/dist/components/SortablePhotos/useSortablePhotos.js +18 -11
  58. package/dist/components/SortablePhotos/useSortablePhotos.js.map +1 -1
  59. package/dist/components/Switch/index.js +13 -9
  60. package/dist/components/Switch/index.js.map +1 -1
  61. package/dist/components/Switch/types.d.ts +5 -2
  62. package/dist/components/TextInput/index.js +26 -70
  63. package/dist/components/TextInput/index.js.map +1 -1
  64. package/dist/components/TextInput/types.d.ts +8 -6
  65. package/dist/components/TextInput/useTextInput.d.ts +54 -0
  66. package/dist/components/TextInput/useTextInput.js +59 -0
  67. package/dist/components/TextInput/useTextInput.js.map +1 -0
  68. package/dist/components/Touchable/index.js +4 -3
  69. package/dist/components/Touchable/index.js.map +1 -1
  70. package/dist/components/View/index.d.ts +7 -12
  71. package/dist/components/View/index.js +9 -7
  72. package/dist/components/View/index.js.map +1 -1
  73. package/dist/components/View/types.d.ts +6 -6
  74. package/dist/components/components.d.ts +0 -2
  75. package/dist/components/components.js +0 -2
  76. package/dist/components/components.js.map +1 -1
  77. package/dist/hooks/index.d.ts +3 -2
  78. package/dist/hooks/index.js +3 -10
  79. package/dist/hooks/index.js.map +1 -1
  80. package/dist/hooks/useKeyboardController.d.ts +6 -0
  81. package/dist/hooks/useKeyboardController.js +19 -0
  82. package/dist/hooks/useKeyboardController.js.map +1 -0
  83. package/dist/hooks/useStatusBar.d.ts +6 -0
  84. package/dist/hooks/useStatusBar.js +15 -0
  85. package/dist/hooks/useStatusBar.js.map +1 -0
  86. package/dist/hooks/useStylesFor.d.ts +2 -0
  87. package/dist/hooks/useStylesFor.js +11 -0
  88. package/dist/hooks/useStylesFor.js.map +1 -0
  89. package/dist/index.d.ts +2 -1
  90. package/dist/index.js +2 -1
  91. package/dist/index.js.map +1 -1
  92. package/dist/modules/backgroundTimer.d.ts +3 -0
  93. package/dist/modules/backgroundTimer.js +31 -0
  94. package/dist/modules/backgroundTimer.js.map +1 -0
  95. package/dist/modules/index.d.ts +3 -0
  96. package/dist/modules/index.js +3 -0
  97. package/dist/modules/index.js.map +1 -0
  98. package/dist/modules/reactNavigation.d.ts +8 -21
  99. package/dist/modules/reactNavigation.js +38 -12
  100. package/dist/modules/reactNavigation.js.map +1 -1
  101. package/dist/modules/scroll.d.ts +18 -0
  102. package/dist/modules/scroll.js +57 -0
  103. package/dist/modules/scroll.js.map +1 -0
  104. package/dist/modules/types/textInputMask.d.ts +6 -2
  105. package/dist/utils/KeyboardAware/context.js +2 -6
  106. package/dist/utils/KeyboardAware/context.js.map +1 -1
  107. package/dist/utils/KeyboardAware/index.d.ts +0 -1
  108. package/dist/utils/KeyboardAware/index.js +0 -1
  109. package/dist/utils/KeyboardAware/index.js.map +1 -1
  110. package/dist/utils/ModalManager/context.js +2 -2
  111. package/dist/utils/ModalManager/context.js.map +1 -1
  112. package/dist/utils/hooks.js +4 -4
  113. package/dist/utils/hooks.js.map +1 -1
  114. package/dist/utils/locale.d.ts +1 -1
  115. package/dist/utils/locale.js +10 -5
  116. package/dist/utils/locale.js.map +1 -1
  117. package/dist/utils/theme.d.ts +1 -0
  118. package/dist/utils/theme.js +4 -2
  119. package/dist/utils/theme.js.map +1 -1
  120. package/package.json +31 -35
  121. package/package.json.bak +17 -20
  122. package/src/components/Autocomplete/index.tsx +2 -3
  123. package/src/components/Autocomplete/types.ts +9 -10
  124. package/src/components/Backdrop/index.tsx +0 -1
  125. package/src/components/Checkbox/index.tsx +23 -9
  126. package/src/components/Checkbox/types.ts +5 -2
  127. package/src/components/DatePickerModal/index.tsx +27 -18
  128. package/src/components/DatePickerModal/types.ts +12 -9
  129. package/src/components/FileInput/types.ts +3 -4
  130. package/src/components/Grid/index.tsx +3 -3
  131. package/src/components/Image/types.ts +3 -6
  132. package/src/components/InputBase/index.tsx +13 -7
  133. package/src/components/InputBase/types.ts +2 -0
  134. package/src/components/InputBase/useInputBase.ts +60 -0
  135. package/src/components/InputBase/useInputBasePartialStyles.ts +38 -0
  136. package/src/components/InputBase/utils.ts +17 -17
  137. package/src/components/List/index.tsx +0 -1
  138. package/src/components/Modal/index.tsx +4 -15
  139. package/src/components/NumberIncrement/index.tsx +52 -160
  140. package/src/components/NumberIncrement/types.ts +7 -5
  141. package/src/components/NumberIncrement/useNumberIncrement.ts +152 -0
  142. package/src/components/RadioInput/index.tsx +37 -53
  143. package/src/components/RadioInput/types.ts +11 -9
  144. package/src/components/Scroll/index.tsx +44 -45
  145. package/src/components/Scroll/types.ts +4 -4
  146. package/src/components/Sections/index.tsx +0 -1
  147. package/src/components/SegmentedControl/index.tsx +8 -6
  148. package/src/components/SegmentedControl/types.ts +4 -3
  149. package/src/components/Select/index.tsx +32 -24
  150. package/src/components/Select/types.ts +19 -18
  151. package/src/components/Slider/index.tsx +34 -66
  152. package/src/components/Slider/types.ts +7 -5
  153. package/src/components/SortablePhotos/index.tsx +31 -47
  154. package/src/components/SortablePhotos/types.ts +6 -15
  155. package/src/components/SortablePhotos/useSortablePhotos.ts +28 -22
  156. package/src/components/Switch/index.tsx +23 -9
  157. package/src/components/Switch/types.ts +5 -2
  158. package/src/components/TextInput/index.tsx +55 -89
  159. package/src/components/TextInput/types.ts +9 -7
  160. package/src/components/TextInput/useTextInput.ts +88 -0
  161. package/src/components/Touchable/index.tsx +5 -1
  162. package/src/components/View/index.tsx +19 -12
  163. package/src/components/View/types.ts +7 -6
  164. package/src/components/components.ts +0 -2
  165. package/src/hooks/index.ts +3 -13
  166. package/src/hooks/useKeyboardController.ts +28 -0
  167. package/src/hooks/useStatusBar.ts +21 -0
  168. package/src/hooks/useStylesFor.ts +13 -0
  169. package/src/index.ts +3 -1
  170. package/src/modules/backgroundTimer.ts +39 -0
  171. package/src/modules/index.ts +3 -0
  172. package/src/modules/reactNavigation.ts +64 -14
  173. package/src/modules/scroll.tsx +89 -0
  174. package/src/modules/types/textInputMask.ts +8 -4
  175. package/src/types/index.ts +1 -0
  176. package/src/utils/KeyboardAware/context.tsx +2 -6
  177. package/src/utils/KeyboardAware/index.ts +1 -1
  178. package/src/utils/ModalManager/context.tsx +2 -2
  179. package/src/utils/hooks.ts +4 -4
  180. package/src/utils/locale.ts +13 -5
  181. package/src/utils/theme.ts +6 -2
  182. package/dist/components/Navigation/Navigation.d.ts +0 -55
  183. package/dist/components/Navigation/Navigation.js +0 -41
  184. package/dist/components/Navigation/Navigation.js.map +0 -1
  185. package/dist/components/Navigation/constants.d.ts +0 -9
  186. package/dist/components/Navigation/constants.js +0 -9
  187. package/dist/components/Navigation/constants.js.map +0 -1
  188. package/dist/components/Navigation/index.d.ts +0 -3
  189. package/dist/components/Navigation/index.js +0 -4
  190. package/dist/components/Navigation/index.js.map +0 -1
  191. package/dist/components/Navigation/types.d.ts +0 -26
  192. package/dist/components/Navigation/types.js +0 -2
  193. package/dist/components/Navigation/types.js.map +0 -1
  194. package/dist/components/Navigation/utils.d.ts +0 -3
  195. package/dist/components/Navigation/utils.js +0 -34
  196. package/dist/components/Navigation/utils.js.map +0 -1
  197. package/dist/components/NumberIncrement/utils.d.ts +0 -5
  198. package/dist/components/NumberIncrement/utils.js +0 -23
  199. package/dist/components/NumberIncrement/utils.js.map +0 -1
  200. package/dist/utils/KeyboardAware/types.d.ts +0 -1
  201. package/dist/utils/KeyboardAware/types.js +0 -6
  202. package/dist/utils/KeyboardAware/types.js.map +0 -1
  203. package/src/components/Navigation/Navigation.tsx +0 -55
  204. package/src/components/Navigation/constants.ts +0 -24
  205. package/src/components/Navigation/index.tsx +0 -3
  206. package/src/components/Navigation/types.ts +0 -28
  207. package/src/components/Navigation/utils.tsx +0 -57
  208. package/src/components/NumberIncrement/utils.ts +0 -27
  209. package/src/utils/KeyboardAware/types.ts +0 -159
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import { TypeGuards } from '@codeleap/types'
3
3
  import { getRenderedComponent } from '@codeleap/utils'
4
4
  import { ActionIcon, ActionIconProps } from '../ActionIcon'
@@ -6,6 +6,9 @@ import { View } from '../View'
6
6
  import { useInputBaseStyles } from './styles'
7
7
  import { InputBaseProps } from './types'
8
8
  import { Text } from '../Text'
9
+ import RNAnimated, { FadeIn, FadeOut } from 'react-native-reanimated'
10
+ import { View as RNView } from 'react-native'
11
+ import { StyledComponentProps, StyledComponentWithProps } from '@codeleap/styles'
9
12
 
10
13
  export * from './styles'
11
14
  export * from './utils'
@@ -22,7 +25,7 @@ const KeyPassthrough = (props: React.PropsWithChildren<any>) => {
22
25
  return <>{props.children}</>
23
26
  }
24
27
 
25
- export const InputBase = (props: InputBaseProps) => {
28
+ export const InputBase = forwardRef<RNView, InputBaseProps>((props: InputBaseProps, ref) => {
26
29
  const {
27
30
  children,
28
31
  error = null,
@@ -82,24 +85,27 @@ export const InputBase = (props: InputBaseProps) => {
82
85
  {children}
83
86
  {_rightIcon}
84
87
  </InnerWrapperComponent>,
85
- error: hideErrorMessage ? null : (
86
- _error || <Text text={''} style={styles.errorStyle} />
87
- ),
88
88
  }
89
89
 
90
90
  return <WrapperComponent
91
91
  {...otherProps}
92
92
  {...wrapperProps}
93
93
  style={styles.wrapperStyle}
94
+ ref={ref}
94
95
  >
95
96
  {
96
97
  order.map((key) => <KeyPassthrough key={key}>
97
98
  {parts[key]}
98
99
  </KeyPassthrough>)
99
-
100
100
  }
101
+
102
+ {hideErrorMessage || !error ? null : (
103
+ <RNAnimated.View exiting={FadeOut.duration(100)} entering={FadeIn.duration(200)}>
104
+ {_error}
105
+ </RNAnimated.View>
106
+ )}
101
107
  </WrapperComponent>
102
- }
108
+ }) as StyledComponentWithProps<InputBaseProps>
103
109
 
104
110
  InputBase.elements = ['wrapper', 'innerWrapper', 'label', 'errorMessage', 'description', 'icon', 'leftIcon', 'rightIcon']
105
111
 
@@ -1,6 +1,7 @@
1
1
  import { PropsOf, StylesOf } from '@codeleap/types'
2
2
  import { InputBaseComposition } from './styles'
3
3
  import { ActionIcon } from '../ActionIcon'
4
+ import { View } from 'react-native'
4
5
 
5
6
  type ActionIconProps = PropsOf<typeof ActionIcon>
6
7
 
@@ -25,4 +26,5 @@ export type InputBaseProps = React.PropsWithChildren<{
25
26
  labelAsRow?: boolean
26
27
  hideErrorMessage?: boolean
27
28
  hasValue?: boolean
29
+ ref?: React.Ref<View>
28
30
  }>
@@ -0,0 +1,60 @@
1
+ import { useRef } from 'react'
2
+ import { View, TextInput, StatusBar } from 'react-native'
3
+ import { useWrappingScrollable } from '../../modules/scroll'
4
+ import { Field, IFieldRef, fields, useField } from '@codeleap/form'
5
+ import { AnyRecord } from '@codeleap/types'
6
+
7
+ export function useInputBase<V, T extends Field<V, any, any, unknown> = Field<V, any, any, unknown>>(
8
+ field: T,
9
+ defaultField: (options: AnyRecord) => T = fields.text as () => T,
10
+ customState: [V, (value: V) => void] | [] = [],
11
+ params: Partial<IFieldRef<V>> = {},
12
+ deps: any[] = []
13
+ ) {
14
+ const hasState = customState?.length === 2
15
+
16
+ const wrapperRef = useRef<View>()
17
+
18
+ const innerInputRef = useRef<TextInput>(null)
19
+
20
+ const scrollable = useWrappingScrollable()
21
+
22
+ const fieldHandle = useField<V, T>(field as T, [
23
+ {
24
+ blur() {
25
+ innerInputRef.current.blur()
26
+ },
27
+ focus() {
28
+ innerInputRef.current.focus()
29
+ },
30
+ getValue() {
31
+ return innerInputRef.current.state as V
32
+ },
33
+ scrollIntoView() {
34
+ return field.measurePosition(wrapperRef).then((measureResult) => {
35
+ field.scrollTo(scrollable, measureResult)
36
+ })
37
+ },
38
+ ...params,
39
+ },
40
+ deps
41
+ ] as unknown as Parameters<T['use']>, () => defaultField(hasState ? {
42
+ state: {
43
+ get: () => customState[0],
44
+ set: (val: V) => customState[1](val),
45
+ value: customState[0],
46
+ listen: () => {},
47
+ },
48
+ validate: () => ({ isValid: true })
49
+ } : {}))
50
+
51
+ const validation = fieldHandle.validation
52
+
53
+ return {
54
+ fieldHandle,
55
+ validation,
56
+ wrapperRef,
57
+ innerInputRef,
58
+ scrollable,
59
+ }
60
+ }
@@ -0,0 +1,38 @@
1
+ import { useMemo } from 'react'
2
+ import { TextStyle, ViewStyle } from 'react-native'
3
+
4
+ export function useInputBasePartialStyles<C extends string, S extends Record<string, boolean>>(
5
+ styles: Record<C, ViewStyle>,
6
+ styleKeys: Array<C | [C, boolean]>,
7
+ states: S,
8
+ ) {
9
+ return useMemo(() => {
10
+ return styleKeys.reduce((acc, value) => {
11
+ const [key, overrideWithDefault] = Array.isArray(value) ? value : [value, true]
12
+
13
+ const result = Object.entries(states).reduce((acc, [state, is]) => {
14
+ if (!is) return acc
15
+
16
+ const style = styles?.[`${key}:${state}` as C]
17
+
18
+ if (!style) return acc
19
+
20
+ return {
21
+ ...acc,
22
+ ...styles[`${key}:${state}` as C]
23
+ }
24
+ }, {})
25
+
26
+ if (overrideWithDefault && !!styles?.[key]) {
27
+ acc[key] = {
28
+ ...styles[key],
29
+ ...result,
30
+ }
31
+ } else {
32
+ acc[key] = result
33
+ }
34
+
35
+ return acc
36
+ }, {} as Record<C, ViewStyle & TextStyle>)
37
+ }, [states])
38
+ }
@@ -10,27 +10,27 @@ type InputBaseKey = keyof InputBaseProps
10
10
 
11
11
  type BaseProps = Omit<InputBaseProps, 'style'>
12
12
 
13
+ const varList:InputBaseKey[] = [
14
+ 'label',
15
+ 'style',
16
+ 'error',
17
+ 'innerWrapper',
18
+ 'leftIcon',
19
+ 'rightIcon',
20
+ 'description',
21
+ 'wrapper',
22
+ 'children',
23
+ 'innerWrapperProps',
24
+ 'wrapperProps',
25
+ 'disabled',
26
+ 'hideErrorMessage',
27
+ 'style',
28
+ ]
29
+
13
30
  export function selectInputBaseProps<T extends BaseProps>(props: T): {
14
31
  inputBaseProps: BaseProps
15
32
  others: OmitDiff<T, T>
16
33
  } {
17
- const varList:InputBaseKey[] = [
18
- 'label',
19
- 'style',
20
- 'error',
21
- 'innerWrapper',
22
- 'leftIcon',
23
- 'rightIcon',
24
- 'description',
25
- 'wrapper',
26
- 'children',
27
- 'innerWrapperProps',
28
- 'wrapperProps',
29
- 'disabled',
30
- 'hideErrorMessage',
31
- 'style',
32
- ]
33
-
34
34
  const copy = { ...props }
35
35
 
36
36
  const result = varList.reduce((acc, key) => {
@@ -22,7 +22,6 @@ export const List = forwardRef<FlatList, FlatListProps>((flatListProps, ref) =>
22
22
  const {
23
23
  style,
24
24
  onRefresh,
25
- component,
26
25
  refreshing,
27
26
  placeholder,
28
27
  refreshControlProps,
@@ -3,7 +3,7 @@ import { View } from '../View'
3
3
  import { Scroll } from '../Scroll'
4
4
  import { TypeGuards } from '@codeleap/types'
5
5
  import { Backdrop } from '../Backdrop'
6
- import { useAnimatedVariantStyles, useBackButton } from '../../utils/hooks'
6
+ import { useBackButton } from '../../utils/hooks'
7
7
  import { Text } from '../Text'
8
8
  import { Touchable } from '../Touchable'
9
9
  import { ActionIcon } from '../ActionIcon'
@@ -12,7 +12,7 @@ import { ModalHeaderProps, ModalProps } from './types'
12
12
  import { AnyRecord, AppIcon, useNestedStylesByKey, IJSX, StyledComponentProps, useTheme, AppTheme, Theme } from '@codeleap/styles'
13
13
  import { MobileStyleRegistry } from '../../Registry'
14
14
  import { useStylesFor } from '../../hooks'
15
- import { SlideInDown, SlideOutDown } from 'react-native-reanimated'
15
+ import { FadeIn, FadeOut } from 'react-native-reanimated'
16
16
 
17
17
  export * from './styles'
18
18
  export * from './types'
@@ -91,17 +91,6 @@ export const Modal = (modalProps: ModalProps) => {
91
91
 
92
92
  const buttonStyles = useNestedStylesByKey('closeButton', styles)
93
93
 
94
- const boxAnimationStyles = useAnimatedVariantStyles({
95
- updater: (states) => {
96
- 'worklet'
97
- return visible ? states['box:visible'] : states['box:hidden']
98
- },
99
- animatedProperties: ['box:hidden', 'box:visible'],
100
- variantStyles: styles,
101
- transition: styles['box:transition'],
102
- dependencies: [visible],
103
- })
104
-
105
94
  const ScrollComponent = scroll ? Scroll : View
106
95
  const scrollStyle = scroll ? styles?.scroll : styles?.innerWrapper
107
96
 
@@ -212,8 +201,8 @@ Modal.defaultProps = {
212
201
  dismissOnBackdrop: true,
213
202
  scroll: true,
214
203
  closeOnHardwareBackPress: true,
215
- boxEntering: SlideInDown.build(),
216
- boxExiting: SlideOutDown.build(),
204
+ boxEntering: FadeIn.duration(100).build(),
205
+ boxExiting: FadeOut.duration(100).build(),
217
206
  } as Partial<ModalProps>
218
207
 
219
208
  MobileStyleRegistry.registerComponent(Modal)
@@ -1,24 +1,22 @@
1
- import React, { useState, useRef } from 'react'
1
+ import React from 'react'
2
2
  import { TypeGuards } from '@codeleap/types'
3
- import { useValidate } from '@codeleap/form'
4
- import { forwardRef, useImperativeHandle } from 'react'
3
+ import { forwardRef } from 'react'
5
4
  import { InputBase, selectInputBaseProps } from '../InputBase'
6
5
  import { Text } from '../Text'
7
6
  import { MaskedTextInput } from '../../modules/textInputMask'
8
- import { TextInput as NativeTextInput, TextInputProps as NativeTextInputProps, NativeSyntheticEvent, TextInputFocusEventData } from 'react-native'
7
+ import { TextInput as NativeTextInput } from 'react-native'
9
8
  import { Touchable } from '../Touchable'
10
- import { useActionValidate } from './utils'
11
9
  import { NumberIncrementProps } from './types'
12
10
  import { AnyRecord, AppIcon, IJSX, StyledComponentProps, StyledComponentWithProps } from '@codeleap/styles'
13
11
  import { MobileStyleRegistry } from '../../Registry'
14
12
  import { useStylesFor } from '../../hooks'
15
13
  import CurrencyInput from 'react-native-currency-input'
14
+ import { useInputBasePartialStyles } from '../InputBase/useInputBasePartialStyles'
15
+ import { useNumberIncrement } from './useNumberIncrement'
16
16
 
17
17
  export * from './styles'
18
18
  export * from './types'
19
19
 
20
- const MAX_VALID_DIGITS = 1000000000000000 // maximum number of digits that the input supports to perform operations
21
-
22
20
  const defaultParseValue = (_value: string) => {
23
21
  const value = _value?.length > 0 ? _value : '0'
24
22
 
@@ -28,27 +26,24 @@ const defaultParseValue = (_value: string) => {
28
26
  }
29
27
 
30
28
  export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>((props, inputRef) => {
29
+ const allProps = {
30
+ ...NumberIncrement.defaultProps,
31
+ ...props,
32
+ }
33
+
31
34
  const {
32
35
  inputBaseProps,
33
36
  others,
34
- } = selectInputBaseProps({
35
- ...NumberIncrement.defaultProps,
36
- ...props,
37
- })
37
+ } = selectInputBaseProps(allProps)
38
38
 
39
39
  const {
40
40
  style,
41
- value,
42
41
  disabled,
43
- onChangeText,
44
42
  onChangeMask,
45
- max,
46
- min,
47
43
  step,
48
44
  editable,
49
- validate,
50
45
  onPress,
51
- _error,
46
+ forceError,
52
47
  masking,
53
48
  separator,
54
49
  prefix,
@@ -61,18 +56,30 @@ export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>
61
56
  mask,
62
57
  actionDebounce,
63
58
  precision,
59
+ field,
64
60
  ...textInputProps
65
61
  } = others
66
62
 
67
- const [isFocused, setIsFocused] = useState(false)
68
-
69
- const innerInputRef = useRef<NativeTextInput>(null)
70
-
71
- const actionValidation = useActionValidate(validate)
72
- const validation = useValidate(value, validate)
63
+ const styles = useStylesFor(NumberIncrement.styleRegistryName, style)
73
64
 
74
- const hasError = !validation.isValid || _error || !actionValidation?.isValid
75
- const errorMessage = validation.message || _error || actionValidation?.message
65
+ const {
66
+ fieldHandle,
67
+ validation,
68
+ min,
69
+ max,
70
+ innerInputRef,
71
+ wrapperRef,
72
+ isFocused,
73
+ hasValue,
74
+ hasError,
75
+ incrementDisabled,
76
+ decrementDisabled,
77
+ handleChangeInput,
78
+ handleChange,
79
+ handleMaskChange,
80
+ handleBlur,
81
+ handleFocus,
82
+ } = useNumberIncrement(allProps)
76
83
 
77
84
  const isFormatted = TypeGuards.isFunction(formatter)
78
85
 
@@ -84,130 +91,16 @@ export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>
84
91
 
85
92
  const InputElement: any = isMasked ? MaskedTextInput : isCurrency ? CurrencyInput : NativeTextInput
86
93
 
87
- const hasValue = TypeGuards.isString(value) ? value.length > 0 : !TypeGuards.isNil(value)
88
-
89
- // @ts-expect-error - React's ref type system is weird
90
- useImperativeHandle(inputRef, () => {
91
- return {
92
- ...innerInputRef.current,
93
- focus: () => {
94
- innerInputRef.current?.focus?.()
95
- },
96
- isTextInput: true,
97
- }
98
- }, [!!innerInputRef?.current?.focus])
99
-
100
- const incrementDisabled = React.useMemo(() => {
101
- if (TypeGuards.isNumber(max) && (Number(value) >= max)) {
102
- return true
94
+ const partialStyles = useInputBasePartialStyles(
95
+ styles,
96
+ [['input', false], 'placeholder', 'selection'],
97
+ {
98
+ disabled,
99
+ error: !!hasError,
100
+ focus: isFocused,
101
+ typed: hasValue,
103
102
  }
104
- return false
105
- }, [value])
106
-
107
- const decrementDisabled = React.useMemo(() => {
108
- if (TypeGuards.isNumber(min) && (Number(value) <= min)) {
109
- return true
110
- }
111
- return false
112
- }, [value])
113
-
114
- const styles = useStylesFor(NumberIncrement.styleRegistryName, style)
115
-
116
- const inputTextStyle = React.useMemo(() => ([
117
- styles.input,
118
- isFocused && styles['input:focus'],
119
- hasError && styles['input:error'],
120
- disabled && styles['input:disabled'],
121
- hasValue && styles['input:typed'],
122
- ]), [disabled, isFocused, hasError])
123
-
124
- const placeholderTextColor = [
125
- [disabled, styles['placeholder:disabled']],
126
- [hasError, styles['placeholder:error']],
127
- [isFocused, styles['placeholder:focus']],
128
- [hasValue, styles['placeholder:typed']],
129
- [true, styles.placeholder],
130
- // @ts-expect-error
131
- ].find(([x]) => x)?.[1]?.color
132
-
133
- const selectionColor = [
134
- [disabled, styles['selection:disabled']],
135
- [!validation.isValid, styles['selection:error']],
136
- [isFocused, styles['selection:focus']],
137
- [hasValue, styles['selection:typed']],
138
- [true, styles.selection],
139
- // @ts-expect-error
140
- ].find(([x]) => x)?.[1]?.color
141
-
142
- const onChange = (newValue: number) => {
143
- actionValidation.onAction(newValue)
144
- // @ts-ignore
145
- if (onChangeText) onChangeText?.(newValue)
146
- }
147
-
148
- const actionTimeoutRef = useRef(null)
149
-
150
- const clearActionTimeoutRef = React.useCallback(() => {
151
- if (actionTimeoutRef.current !== null) {
152
- clearTimeout(actionTimeoutRef.current)
153
- actionTimeoutRef.current = null
154
- }
155
- }, [actionTimeoutRef.current])
156
-
157
- const handleChange = React.useCallback((action: 'increment' | 'decrement') => {
158
- if (actionPressAutoFocus) setIsFocused(true)
159
- clearActionTimeoutRef()
160
-
161
- if (action === 'increment' && !incrementDisabled) {
162
- const newValue = Number(value) + step
163
- onChange(newValue)
164
- } else if (action === 'decrement' && !decrementDisabled) {
165
- const newValue = Number(value) - step
166
- onChange(newValue)
167
- }
168
-
169
- if (actionPressAutoFocus) {
170
- actionTimeoutRef.current = setTimeout(() => {
171
- setIsFocused(false)
172
- }, timeoutActionFocus)
173
- }
174
- }, [value])
175
-
176
- const handleBlur = React.useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
177
- if (TypeGuards.isNumber(max) && (Number(value) >= max)) {
178
- onChange(max)
179
- } else if (TypeGuards.isNumber(min) && (Number(value) <= min) || TypeGuards.isNil(value) || String(value)?.length <= 0) {
180
- onChange(min)
181
- }
182
-
183
- validation?.onInputBlurred()
184
- setIsFocused(false)
185
- props?.onBlur?.(e)
186
- }, [validation?.onInputBlurred, props?.onBlur, value])
187
-
188
- const handleFocus = React.useCallback((e?: NativeSyntheticEvent<TextInputFocusEventData>) => {
189
- validation?.onInputFocused()
190
- clearActionTimeoutRef()
191
- if (editable) setIsFocused(true)
192
- if (e) props?.onFocus?.(e)
193
- }, [validation?.onInputFocused, props?.onFocus])
194
-
195
- const handleChangeInput: NativeTextInputProps['onChangeText'] = (text) => {
196
- const value = parseValue(text)
197
-
198
- if (value >= MAX_VALID_DIGITS) {
199
- onChange(MAX_VALID_DIGITS)
200
- return MAX_VALID_DIGITS
201
- }
202
-
203
- onChange(value)
204
- return value
205
- }
206
-
207
- const handleMaskChange = (masked: string, unmasked: any) => {
208
- handleChangeInput?.(masked)
209
- if (onChangeMask) onChangeMask(masked, unmasked)
210
- }
103
+ )
211
104
 
212
105
  const maskingExtraProps = isMasked ? {
213
106
  type: TypeGuards.isNil(mask) ? 'money' : 'custom',
@@ -230,9 +123,9 @@ export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>
230
123
  } : {}
231
124
 
232
125
  const currencyExtraProps = isCurrency ? {
233
- value,
126
+ value: fieldHandle?.value,
234
127
  onChangeText: null,
235
- onChangeValue: onChange,
128
+ onChangeValue: fieldHandle.setValue,
236
129
  prefix: prefix,
237
130
  separator: separator ?? '.',
238
131
  suffix: suffix,
@@ -243,7 +136,7 @@ export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>
243
136
  } : {}
244
137
 
245
138
  const onPressInnerWrapper = () => {
246
- handleFocus()
139
+ handleFocus(null)
247
140
  if (editable) innerInputRef.current?.focus?.()
248
141
  if (onPress) onPress?.()
249
142
  }
@@ -251,7 +144,8 @@ export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>
251
144
  return (
252
145
  <InputBase
253
146
  {...inputBaseProps}
254
- error={hasError ? errorMessage : null}
147
+ ref={wrapperRef}
148
+ error={hasError ? validation.message || forceError : null}
255
149
  style={styles}
256
150
  rightIcon={TypeGuards.isComponentOrElement(inputBaseProps.rightIcon) ? inputBaseProps.rightIcon : {
257
151
  name: 'plus' as AppIcon,
@@ -284,22 +178,22 @@ export const NumberIncrement = forwardRef<NativeTextInput, NumberIncrementProps>
284
178
  textAlignVertical='center'
285
179
  allowFontScaling={false}
286
180
  editable={!disabled}
287
- placeholderTextColor={placeholderTextColor}
288
- value={isFormatted ? formatter(value) : String(value)}
289
- selectionColor={selectionColor}
181
+ placeholderTextColor={partialStyles?.placeholder?.color}
182
+ value={isFormatted ? formatter(fieldHandle?.value ?? min) : String(fieldHandle?.value ?? min)}
183
+ selectionColor={partialStyles?.selection?.color}
290
184
  onChangeText={handleChangeInput}
291
185
  {...textInputProps}
292
186
  onBlur={handleBlur}
293
187
  onFocus={handleFocus}
294
- style={inputTextStyle}
188
+ style={[styles.input, partialStyles.input]}
295
189
  ref={innerInputRef}
296
190
  {...maskingExtraProps}
297
191
  {...currencyExtraProps}
298
192
  />
299
193
  ) : (
300
194
  <Text
301
- text={isFormatted ? formatter(value) : String(value)}
302
- style={inputTextStyle}
195
+ text={isFormatted ? formatter(fieldHandle?.value) : String(fieldHandle?.value)}
196
+ style={[styles.input, partialStyles.input]}
303
197
  />
304
198
  )}
305
199
  </InputBase>
@@ -315,8 +209,6 @@ NumberIncrement.withVariantTypes = <S extends AnyRecord>(styles: S) => {
315
209
  }
316
210
 
317
211
  NumberIncrement.defaultProps = {
318
- max: MAX_VALID_DIGITS,
319
- min: 0,
320
212
  step: 1,
321
213
  editable: true,
322
214
  separator: null,
@@ -1,25 +1,24 @@
1
1
  import { AnyFunction } from '@codeleap/types'
2
- import { yup, FormTypes } from '@codeleap/form'
3
2
  import { NumberIncrementComposition } from './styles'
4
3
  import { TextInputMaskProps } from '../../modules/textInputMask'
5
4
  import { TextInputProps as RNTextInputProps } from 'react-native'
6
5
  import { InputBaseProps } from '../InputBase'
7
6
  import { StyledProp } from '@codeleap/styles'
7
+ import { TextInputProps } from '../TextInput'
8
+ import { NumberField } from '@codeleap/form'
8
9
 
9
- type Masking = FormTypes.TextField['masking']
10
+ type Masking = TextInputProps['masking']
10
11
  type MaskOptions = Masking['options']
11
12
 
12
13
  export type NumberIncrementProps =
13
14
  Omit<InputBaseProps, 'style'|'value'> &
14
15
  Omit<RNTextInputProps, 'style'|'value'> &
15
16
  {
16
- value: number | string
17
- validate?: FormTypes.ValidatorWithoutForm<string> | yup.SchemaOf<string>
18
17
  max?: number
19
18
  min?: number
20
19
  step?: number
21
20
  editable?: boolean
22
- _error?: string
21
+ forceError?: string
23
22
  placeholder?: string
24
23
  onChangeMask?: TextInputMaskProps['onChangeText']
25
24
  masking?: Exclude<Masking, 'mask' | 'format'>
@@ -36,4 +35,7 @@ export type NumberIncrementProps =
36
35
  actionDebounce?: number | null
37
36
  onPress?: AnyFunction
38
37
  style?: StyledProp<NumberIncrementComposition>
38
+ field?: NumberField<any>
39
+ value?: number
40
+ onValueChange?: (value: number) => void
39
41
  }