@codeleap/mobile 4.3.8 → 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 +22 -57
  51. package/dist/components/Slider/index.js.map +1 -1
  52. package/dist/components/Slider/types.d.ts +8 -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 +32 -36
  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 +35 -64
  152. package/src/components/Slider/types.ts +8 -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,18 +1,18 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import { View as RNView } from 'react-native'
3
- import { AnyRecord, IJSX, StyledComponentProps } from '@codeleap/styles'
3
+ import { AnyRecord, IJSX, StyledComponentProps, StyledComponentWithProps } from '@codeleap/styles'
4
4
  import { MobileStyleRegistry } from '../../Registry'
5
5
  import Animated from 'react-native-reanimated'
6
- import { ViewProps } from './types'
6
+ import { ViewAnimatedProps, ViewProps } from './types'
7
7
  import { useStylesFor } from '../../hooks'
8
+ import { useComponentTestId } from '@codeleap/hooks'
8
9
 
9
10
  export * from './types'
10
11
  export * from './styles'
11
12
 
12
- export const View = <T extends React.ComponentType = typeof RNView>(props: ViewProps<T>) => {
13
+ export const View = forwardRef<RNView, ViewProps>((props, ref) => {
13
14
  const {
14
15
  style,
15
- component: _Component = RNView,
16
16
  animated = false,
17
17
  animatedStyle,
18
18
  ...viewProps
@@ -20,15 +20,22 @@ export const View = <T extends React.ComponentType = typeof RNView>(props: ViewP
20
20
 
21
21
  const styles = useStylesFor(View.styleRegistryName, style)
22
22
 
23
- const Component: React.ComponentType<AnyRecord> = animated ? Animated.View : _Component
23
+ const testId = useComponentTestId(View, props, ['style', 'children', 'animated'])
24
+
25
+ const Component: React.ComponentType<AnyRecord> = animated ? Animated.View : RNView
24
26
 
25
27
  return (
26
- <Component {...viewProps} style={[styles.wrapper, animatedStyle]} />
28
+ <Component
29
+ testID={testId}
30
+ {...viewProps}
31
+ style={[styles.wrapper, animatedStyle]}
32
+ ref={ref}
33
+ />
27
34
  )
28
- }
35
+ }) as StyledComponentWithProps<ViewProps> & { Animated?: (props: ViewAnimatedProps) => JSX.Element }
29
36
 
30
- View.Animated = (props: ViewProps<typeof Animated.View>) => {
31
- return <View {...props} animated />
37
+ View.Animated = (props: ViewAnimatedProps) => {
38
+ return <View {...props} />
32
39
  }
33
40
 
34
41
  View.styleRegistryName = 'View'
@@ -36,7 +43,7 @@ View.elements = ['wrapper']
36
43
  View.rootElement = 'wrapper'
37
44
 
38
45
  View.withVariantTypes = <S extends AnyRecord>(styles: S) => {
39
- return View as (<T extends React.ComponentType = typeof RNView>(props: StyledComponentProps<ViewProps<T>, typeof styles>) => IJSX)
46
+ return View as (props: StyledComponentProps<ViewProps, typeof styles>) => IJSX
40
47
  }
41
48
 
42
- MobileStyleRegistry.registerComponent(View)
49
+ MobileStyleRegistry.registerComponent(View)
@@ -1,13 +1,14 @@
1
- import { PropsOf } from '@codeleap/types'
2
1
  import { StyledProp } from '@codeleap/styles'
3
- import { ImageStyle, TextStyle, View as RNView, ViewStyle } from 'react-native'
4
- import { AnimatedStyleProp } from 'react-native-reanimated'
2
+ import { ImageStyle, TextStyle, ViewProps as RNViewProps, ViewStyle } from 'react-native'
3
+ import Animated, { AnimatedStyleProp } from 'react-native-reanimated'
5
4
  import { ViewComposition } from './styles'
5
+ import { PropsOf } from '@codeleap/types'
6
6
 
7
- export type ViewProps<T extends React.ComponentType = typeof RNView> = {
8
- component?: T
7
+ export type ViewProps = Omit<RNViewProps, 'style'> & {
9
8
  style?: StyledProp<ViewComposition>
10
9
  animated?: boolean
11
10
  children?: React.ReactNode
12
11
  animatedStyle?: AnimatedStyleProp<ViewStyle | ImageStyle | TextStyle>
13
- } & PropsOf<T>
12
+ }
13
+
14
+ export type ViewAnimatedProps = ViewProps & Omit<PropsOf<typeof Animated.View>, 'style'>
@@ -12,7 +12,6 @@ export * from './Select'
12
12
  export * from './FileInput'
13
13
  export * from './Slider'
14
14
  export * from './SegmentedControl'
15
- export * from './Navigation'
16
15
  export * from './Scroll'
17
16
  export * from './List'
18
17
  export * from './ActivityIndicator'
@@ -20,7 +19,6 @@ export * from './Button'
20
19
  export * from './Modal'
21
20
  export * from './Calendar'
22
21
  export * from './ImageView'
23
- export * from './Navigation'
24
22
  export * from './Pager'
25
23
  export * from './EmptyPlaceholder'
26
24
  export * from './Backdrop'
@@ -1,13 +1,3 @@
1
- import { StyleProp, useStyleObserver } from '@codeleap/styles'
2
- import { useMemo } from 'react'
3
- import { MobileStyleRegistry } from '../Registry'
4
-
5
- export const useStylesFor = <T = unknown>(componentName: string, style: StyleProp<T, string>): T => {
6
- const styleObserver = useStyleObserver(style)
7
-
8
- const styles = useMemo(() => {
9
- return MobileStyleRegistry.current.styleFor(componentName, style)
10
- }, [styleObserver])
11
-
12
- return styles
13
- }
1
+ export * from './useStylesFor'
2
+ export * from './useStatusBar'
3
+ export * from './useKeyboardController'
@@ -0,0 +1,28 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { KeyboardEvents } from 'react-native-keyboard-controller'
3
+
4
+ type KeyboardControllerState = {
5
+ height: number
6
+ isVisible: boolean
7
+ }
8
+
9
+ export function useKeyboardController() {
10
+ const [keyboardState, setKeyboardState] = useState<KeyboardControllerState>({ isVisible: false, height: 0 })
11
+
12
+ useEffect(() => {
13
+ const show = KeyboardEvents.addListener('keyboardWillShow', event => {
14
+ setKeyboardState({ isVisible: true, height: event?.height })
15
+ })
16
+
17
+ const hide = KeyboardEvents.addListener('keyboardWillHide', event => {
18
+ setKeyboardState(prev => ({ isVisible: false, height: prev?.height }))
19
+ })
20
+
21
+ return () => {
22
+ show.remove()
23
+ hide.remove()
24
+ }
25
+ }, [])
26
+
27
+ return keyboardState
28
+ }
@@ -0,0 +1,21 @@
1
+ import { useIsFocused } from '@react-navigation/native'
2
+ import { useLayoutEffect } from '@codeleap/hooks'
3
+ import { StatusBar, StatusBarStyle } from 'react-native'
4
+
5
+ type UseStatusBarOptions = {
6
+ statusBarColor?: StatusBarStyle
7
+ }
8
+
9
+ export function useStatusBar({ statusBarColor }: UseStatusBarOptions) {
10
+ const focused = useIsFocused()
11
+
12
+ useLayoutEffect(() => {
13
+ if (!focused || !statusBarColor) return
14
+
15
+ const statusBarEntry = StatusBar.pushStackEntry({ barStyle: statusBarColor })
16
+
17
+ return () => {
18
+ StatusBar.popStackEntry(statusBarEntry)
19
+ }
20
+ }, [statusBarColor, focused])
21
+ }
@@ -0,0 +1,13 @@
1
+ import { StyleProp, useStyleObserver } from '@codeleap/styles'
2
+ import { useMemo } from 'react'
3
+ import { MobileStyleRegistry } from '../Registry'
4
+
5
+ export const useStylesFor = <T = unknown>(componentName: string, style?: StyleProp<T, string>): T => {
6
+ const styleObserver = useStyleObserver(style)
7
+
8
+ const styles = useMemo(() => {
9
+ return MobileStyleRegistry.current.styleFor(componentName, style)
10
+ }, [styleObserver])
11
+
12
+ return styles
13
+ }
package/src/index.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export * from './components/components'
2
- export { Linking } from 'react-native'
3
2
  export * from './utils'
4
3
  export * from './hooks'
4
+ export * from './modules'
5
+
6
+ export { Linking } from 'react-native'
5
7
  import uuid from 'react-native-uuid'
6
8
  import * as RNKeyboardAwareScrollView from './utils/KeyboardAware'
7
9
  export { uuid, RNKeyboardAwareScrollView }
@@ -0,0 +1,39 @@
1
+ import { AnyFunction } from '@codeleap/types'
2
+ import BackgroundTimer from '@boterop/react-native-background-timer'
3
+ import { uuid } from '..'
4
+
5
+ const throttleTimerId = {}
6
+
7
+ export function throttle(func:AnyFunction, ref?: string, delay = 200) {
8
+ if (!ref) {
9
+ ref = uuid.v4() as string
10
+ }
11
+ if (throttleTimerId[ref]) {
12
+ return
13
+ }
14
+ throttleTimerId[ref] = BackgroundTimer.setTimeout(function () {
15
+ func()
16
+ throttleTimerId[ref] = undefined
17
+ }, delay)
18
+
19
+ return ref
20
+ }
21
+
22
+ const debounceTimerId = {}
23
+
24
+ export function debounce(func:AnyFunction, ref?: string, delay = 200) {
25
+ if (!ref) {
26
+ ref = uuid.v4() as string
27
+ }
28
+
29
+ if (debounceTimerId[ref]) {
30
+ BackgroundTimer.clearTimeout(debounceTimerId[ref])
31
+ }
32
+
33
+ debounceTimerId[ref] = BackgroundTimer.setTimeout(function () {
34
+ func()
35
+ debounceTimerId[ref] = undefined
36
+ }, delay)
37
+
38
+ return ref
39
+ }
@@ -0,0 +1,3 @@
1
+ export * from './reactNavigation'
2
+ export * from './backgroundTimer'
3
+ export type { Scrollable } from './scroll'
@@ -1,14 +1,64 @@
1
- import React from 'react'
2
- export { createStackNavigator } from '@react-navigation/stack'
3
- export { createDrawerNavigator } from '@react-navigation/drawer'
4
- export { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
5
- import { NavigationContainerRefContext, NavigationContext } from '@react-navigation/core'
6
- export { useIsFocused } from '@react-navigation/native'
7
-
8
- export function useNavigationContext() {
9
- const root = React.useContext(NavigationContainerRefContext)
10
- const navigation = React.useContext(NavigationContext)
11
- if (!navigation && !root) return undefined
12
-
13
- return (navigation ?? root)
14
- }
1
+ import { AnyRecord } from '@codeleap/types'
2
+ import { deepMerge } from '@codeleap/utils'
3
+ import { createPathConfigForStaticNavigation } from '@react-navigation/native'
4
+
5
+ type TreeStack = Parameters<typeof createPathConfigForStaticNavigation>[0]
6
+
7
+ /**
8
+ * Extracts screen options from a static navigation tree, consolidating default, group,
9
+ * and individual screen options into a single object. Supports nested navigators.
10
+ */
11
+ export function staticNavigationExtractOptions(stack: TreeStack) {
12
+ const { config } = stack
13
+
14
+ // @ts-ignore
15
+ const defaultOptions = config.screenOptions
16
+
17
+ let result = {}
18
+
19
+ function extractScreens(screens: TreeStack['config'], groupKey: string | null, groupOptions: AnyRecord) {
20
+ let screenResults = {}
21
+
22
+ for (const screenKey in screens) {
23
+ const screen = screens[screenKey]
24
+
25
+ const key = groupKey ? `${groupKey}.${screenKey}` : screenKey
26
+
27
+ const isComponentInstance = typeof screen !== 'object'
28
+
29
+ const defaultScreenOptions = deepMerge(defaultOptions, groupOptions)
30
+
31
+ if (isComponentInstance) {
32
+ screenResults[key] = defaultScreenOptions
33
+ continue
34
+ }
35
+
36
+ const screenOptions = deepMerge(defaultScreenOptions, screen.options)
37
+
38
+ const isNavigationInstance = !!screen?.screen?.config?.screens
39
+
40
+ if (isNavigationInstance) {
41
+ screenResults = deepMerge(
42
+ screenResults,
43
+ extractScreens(screen?.screen?.config?.screens, null, screenOptions)
44
+ )
45
+ continue
46
+ }
47
+
48
+ screenResults[key] = screenOptions
49
+ }
50
+
51
+ return screenResults
52
+ }
53
+
54
+ for (const groupKey in config.groups) {
55
+ const group = config.groups[groupKey]
56
+
57
+ // @ts-ignore
58
+ const groupOptions = group.screenOptions
59
+
60
+ result = deepMerge(result, extractScreens(group.screens, null, groupOptions))
61
+ }
62
+
63
+ return result
64
+ }
@@ -0,0 +1,89 @@
1
+ import React, { MutableRefObject, useCallback, useContext, useImperativeHandle, useRef } from 'react'
2
+ import { NativeScrollEvent, NativeSyntheticEvent, ScrollView, ScrollViewProps } from "react-native"
3
+
4
+ const scrollProperties = [
5
+ 'scrollTo',
6
+ ] satisfies (keyof ScrollView)[]
7
+
8
+ type ScrollProperty = (typeof scrollProperties)[number]
9
+
10
+ type ScrollEvents = Pick<ScrollViewProps, 'onMomentumScrollEnd'>
11
+
12
+ export type Scrollable = Pick<ScrollView, ScrollProperty> & {
13
+ subscribe<T extends keyof ScrollEvents>(e: T, cb: ScrollEvents[T]): () => void
14
+ }
15
+
16
+ type ScrollRef = React.MutableRefObject<Scrollable>
17
+
18
+ type ScrollContextValue = {
19
+ ref: ScrollRef
20
+ }
21
+
22
+ const noOpScrollMethods = Object.fromEntries(
23
+ scrollProperties.map(p => [p, () => {
24
+ console.warn(`"${p}" was called from a ScrollProvider ref without a bound scrollable component. This does not cause errors but may impact user experience and indicate an unhandled edge case in calling code`)
25
+ }])
26
+ )
27
+
28
+ const noOpScrollable = {
29
+ ...noOpScrollMethods,
30
+ subscribe(e, cb){
31
+ return () => {}
32
+ }
33
+ } as Scrollable
34
+
35
+ const ScrollContext = React.createContext({} as ScrollContextValue)
36
+
37
+ export const useScrollPubSub = (ref: MutableRefObject<Omit<Scrollable,'subscribe'>>) => {
38
+ const listeners = useRef(new Map())
39
+
40
+ const augmentedRef = useRef<Scrollable>()
41
+
42
+ const emit = useCallback((event: keyof ScrollEvents, e: NativeSyntheticEvent<NativeScrollEvent>) => {
43
+ listeners.current.forEach((cb, key) => {
44
+ if(key.startsWith(`${event}-`)){
45
+ cb(e)
46
+ }
47
+ })
48
+ }, [])
49
+
50
+ useImperativeHandle(augmentedRef, () => ({
51
+ scrollTo(...args){
52
+ console.log(ref.current)
53
+ ref?.current.scrollTo(...args)
54
+ },
55
+ subscribe(e, cb){
56
+ const id = `${e}-${listeners.current.size}`
57
+
58
+ listeners.current.set(id, cb)
59
+
60
+ return () => {
61
+ listeners.current.delete(id)
62
+ }
63
+ }
64
+ }), [ref])
65
+
66
+ return {
67
+ ref: augmentedRef,
68
+ emit
69
+ }
70
+ }
71
+
72
+
73
+ export const ScrollProvider = React.forwardRef<Scrollable, React.PropsWithChildren>(({children}, ref) => {
74
+ return <ScrollContext.Provider value={{ ref: ref as ScrollRef }}>
75
+ {children}
76
+ </ScrollContext.Provider>
77
+ })
78
+
79
+ export function useWrappingScrollable(){
80
+ const ctx = useContext(ScrollContext)
81
+
82
+ if(!ctx){
83
+ return {
84
+ current: noOpScrollable
85
+ }
86
+ }
87
+
88
+ return ctx.ref
89
+ }
@@ -1,9 +1,13 @@
1
- import { FormTypes } from '@codeleap/form'
1
+ import { RNMaskedTextTypes } from '@codeleap/types'
2
2
  import { TextInputProps } from 'react-native'
3
3
 
4
4
  import { TextInputMaskProps as RNTextInputMaskProps } from 'react-native-masked-text'
5
5
 
6
- export type TextInputMaskProps =Omit<RNTextInputMaskProps, keyof TextInputProps > & {
7
- masking: FormTypes.TextField['masking']
8
- onChangeText: RNTextInputMaskProps['onChangeText']
6
+ type Mask = Partial<RNMaskedTextTypes.TextInputMaskProps> & {
7
+ saveFormatted?: boolean
8
+ }
9
+
10
+ export type TextInputMaskProps = Omit<RNTextInputMaskProps, keyof TextInputProps> & {
11
+ masking: Mask
12
+ onChangeText: RNTextInputMaskProps['onChangeText']
9
13
  }
@@ -1,5 +1,6 @@
1
1
  export * from './utility'
2
2
 
3
+
3
4
  export type ComponentWithDefaultProps<P = any> = ((props: P) => JSX.Element) & {
4
5
  defaultProps: Partial<P>
5
6
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { useSoftInputState } from 'react-native-avoid-softinput'
2
+ import { useKeyboardController } from '../../hooks'
3
3
 
4
4
  type TKeyboardCtx = {
5
5
  isVisible: boolean
@@ -17,9 +17,5 @@ export const KeyboardProvider = ({ children }) => {
17
17
  }
18
18
 
19
19
  export const useKeyboard = (): TKeyboardCtx => {
20
- const state = useSoftInputState()
21
- return {
22
- isVisible: state.isSoftInputShown,
23
- height: state.softInputHeight,
24
- }
20
+ return useKeyboardController()
25
21
  }
@@ -1,4 +1,4 @@
1
1
 
2
2
  export * from './keyboardHooks'
3
3
  export * from './context'
4
- export * from './types'
4
+
@@ -44,7 +44,7 @@ export function Provider({ children }) {
44
44
  const newVisible = typeof set === 'boolean' ? set : !visible
45
45
 
46
46
  setModals((current) => {
47
- const attached = newVisible ? [] : current[name].attachments.map(m => [m, { ...current[m], visible: false }])
47
+ const attached = newVisible ? [] : current[name]?.attachments?.map?.(m => [m, { ...current[m], visible: false }])
48
48
  return {
49
49
  ...current,
50
50
  [name]: {
@@ -52,7 +52,7 @@ export function Provider({ children }) {
52
52
  visible: newVisible,
53
53
  props,
54
54
  },
55
- ...Object.fromEntries(attached),
55
+ ...Object.fromEntries(attached ?? []),
56
56
  }
57
57
 
58
58
  })
@@ -4,9 +4,9 @@ import { TypeGuards } from '@codeleap/types'
4
4
  import { Animated, AppState, AppStateStatus, Platform, BackHandler, ViewStyle, ImageStyle, TextStyle, StyleSheet, StyleProp } from 'react-native'
5
5
  import { AnimatedStyleProp, Easing, EasingFn, useAnimatedStyle, withTiming } from 'react-native-reanimated'
6
6
  import { PressableRippleProps } from '../modules/PressableRipple/type'
7
- import { useSoftInputState } from 'react-native-avoid-softinput'
8
7
  import { useMemo } from 'react'
9
8
  import { mergeStyles } from '@codeleap/styles'
9
+ import { useKeyboardController } from '../hooks'
10
10
 
11
11
  export function useAnimateColor(value: string, opts?: Partial<Animated.TimingAnimationConfig>) {
12
12
  const iters = useRef(0)
@@ -307,7 +307,7 @@ export function useBackButton(cb: () => boolean|void, deps = []) {
307
307
  }
308
308
 
309
309
  export function useKeyboardPaddingStyle(styles: ViewStyle[], enabled = true) {
310
- const { isSoftInputShown, softInputHeight } = useSoftInputState()
310
+ const { isVisible, height } = useKeyboardController()
311
311
 
312
312
  const propStyle = useMemo(() => {
313
313
  return StyleSheet.flatten(styles)
@@ -315,7 +315,7 @@ export function useKeyboardPaddingStyle(styles: ViewStyle[], enabled = true) {
315
315
 
316
316
  const bottomPadding = propStyle && TypeGuards.isNumber(propStyle.paddingBottom) ? propStyle.paddingBottom : 0
317
317
 
318
- const totalPadding = softInputHeight + bottomPadding
318
+ const totalPadding = height + bottomPadding
319
319
 
320
- return isSoftInputShown && enabled ? mergeStyles([propStyle, { paddingBottom: totalPadding }]) : propStyle
320
+ return isVisible && enabled ? mergeStyles([propStyle, { paddingBottom: totalPadding }]) : propStyle
321
321
  }
@@ -1,7 +1,15 @@
1
- import { NativeModules, Platform } from 'react-native'
1
+ import { findBestLanguageTag, getLocales } from 'react-native-localize'
2
2
 
3
- export const getDeviceLocale = (): string => Platform.OS === 'ios'
4
- ? NativeModules.SettingsManager.settings.AppleLocale ||
5
- NativeModules.SettingsManager.settings.AppleLanguages[0]
6
- : NativeModules.I18nManager.localeIdentifier
3
+ export function getDeviceLocale(dictionary: Record<string, any>, defaultLocale: string) {
4
+ const deviceLocales = getLocales().map(locale => locale?.languageTag)
7
5
 
6
+ const dictionaryLocales = Object.keys(dictionary)
7
+
8
+ const possibleLocales = [...new Set([...dictionaryLocales, ...deviceLocales])]
9
+
10
+ const bestLocale = findBestLanguageTag(possibleLocales)
11
+
12
+ if (!bestLocale) return defaultLocale
13
+
14
+ return bestLocale?.languageTag
15
+ }
@@ -2,20 +2,24 @@ import { Platform, Dimensions, StyleSheet } from 'react-native'
2
2
  import DeviceInfo from 'react-native-device-info'
3
3
 
4
4
  type Options = {
5
+ statusBarHeight?: number
5
6
  getStatusBarHeight?: () => number
6
7
  getAndroidNavbarHeight?: () => number
7
8
  }
8
9
 
9
10
  export function getMobileThemeValues(initialWindowMetrics, options: Options = {}) {
11
+ const { statusBarHeight, getStatusBarHeight, getAndroidNavbarHeight } = options
12
+
10
13
  const screenDimensions = Dimensions.get('screen')
11
14
 
12
15
  const hasNotch = DeviceInfo.hasNotch()
13
16
  const hasIsland = DeviceInfo.hasDynamicIsland()
14
- const bottomNavHeight = Platform.OS === 'android' ? options?.getAndroidNavbarHeight?.() ?? 0 : 0
17
+ const bottomNavHeight = Platform.OS === 'android' ? getAndroidNavbarHeight?.() ?? 0 : 0
15
18
 
16
19
  const prefersConstantNavigationBar = bottomNavHeight > 0
17
20
 
18
- const safeAreaTop = Platform.OS === 'ios' ? (hasNotch ? 34 + (hasIsland ? 12 : 0) : 20) : (options?.getStatusBarHeight?.() || 0)
21
+ const currStatusBarHeight = typeof statusBarHeight === 'number' ? statusBarHeight : getStatusBarHeight?.() || 0
22
+ const safeAreaTop = Platform.OS === 'ios' ? (hasNotch ? 34 + (hasIsland ? 12 : 0) : 20) : currStatusBarHeight
19
23
 
20
24
  const safeAreaBottom = Platform.select({
21
25
  ios: hasNotch && !prefersConstantNavigationBar ? 20 : 0,
@@ -1,55 +0,0 @@
1
- import * as React from 'react';
2
- import { NavigationProps } from './types';
3
- export declare const Navigation: <T extends keyof {
4
- Drawer: {
5
- Navigator: React.ComponentType<Omit<any, "children" | "id" | "initialRouteName" | "screenListeners" | "screenOptions"> & import("@react-navigation/routers").DefaultRouterOptions<string> & {
6
- id?: string;
7
- children: React.ReactNode;
8
- screenListeners?: Partial<{
9
- [x: string]: import("@react-navigation/core").EventListenerCallback<any, string>;
10
- }> | ((props: {
11
- route: import("@react-navigation/core").RouteProp<any, string>;
12
- navigation: any;
13
- }) => Partial<{
14
- [x: string]: import("@react-navigation/core").EventListenerCallback<any, string>;
15
- }>);
16
- screenOptions?: any;
17
- }>;
18
- Group: React.ComponentType<import("@react-navigation/core").RouteGroupConfig<any, any>>;
19
- Screen: <RouteName extends string | number | symbol>(_: import("@react-navigation/core").RouteConfig<any, RouteName, any, any, any>) => null;
20
- };
21
- Stack: {
22
- Navigator: React.ComponentType<Omit<any, "children" | "id" | "initialRouteName" | "screenListeners" | "screenOptions"> & import("@react-navigation/routers").DefaultRouterOptions<string> & {
23
- id?: string;
24
- children: React.ReactNode;
25
- screenListeners?: Partial<{
26
- [x: string]: import("@react-navigation/core").EventListenerCallback<any, string>;
27
- }> | ((props: {
28
- route: import("@react-navigation/core").RouteProp<any, string>;
29
- navigation: any;
30
- }) => Partial<{
31
- [x: string]: import("@react-navigation/core").EventListenerCallback<any, string>;
32
- }>);
33
- screenOptions?: any;
34
- }>;
35
- Group: React.ComponentType<import("@react-navigation/core").RouteGroupConfig<any, any>>;
36
- Screen: <RouteName extends string | number | symbol>(_: import("@react-navigation/core").RouteConfig<any, RouteName, any, any, any>) => null;
37
- };
38
- Tab: {
39
- Navigator: React.ComponentType<Omit<any, "children" | "id" | "initialRouteName" | "screenListeners" | "screenOptions"> & import("@react-navigation/routers").DefaultRouterOptions<string> & {
40
- id?: string;
41
- children: React.ReactNode;
42
- screenListeners?: Partial<{
43
- [x: string]: import("@react-navigation/core").EventListenerCallback<any, string>;
44
- }> | ((props: {
45
- route: import("@react-navigation/core").RouteProp<any, string>;
46
- navigation: any;
47
- }) => Partial<{
48
- [x: string]: import("@react-navigation/core").EventListenerCallback<any, string>;
49
- }>);
50
- screenOptions?: any;
51
- }>;
52
- Group: React.ComponentType<import("@react-navigation/core").RouteGroupConfig<any, any>>;
53
- Screen: <RouteName extends string | number | symbol>(_: import("@react-navigation/core").RouteConfig<any, RouteName, any, any, any>) => null;
54
- };
55
- }>({ type, scenes, ...props }: NavigationProps<T>) => JSX.Element;
@@ -1,41 +0,0 @@
1
- // @ts-nocheck
2
- import * as React from 'react';
3
- import { TypeGuards, } from '@codeleap/types';
4
- import { Icon } from '../Icon';
5
- import { Navigators } from './constants';
6
- export const Navigation = ({ type, scenes, ...props }) => {
7
- const NavigationComponent = Navigators[type];
8
- // console.log('render Navigation', { type, scenes, props, defaultProps })
9
- return <NavigationComponent.Navigator {...props}>
10
- {Object.entries(scenes).map(([name, content], idx) => {
11
- const isFunction = TypeGuards.isFunction(content);
12
- let screenProps = {
13
- name,
14
- };
15
- if (isFunction) {
16
- screenProps.component = content;
17
- // console.log('Render NavigationScreen', { scenes, screenProps, content, isFunction }, 'PACKAGES')
18
- }
19
- else {
20
- screenProps.component = content?.component?.default || content?.component || content?.default;
21
- const nameParts = name.split('.');
22
- const title = content?.title || nameParts[nameParts.length - 1] || name.replace('.', '');
23
- screenProps = {
24
- ...screenProps,
25
- options: (optionProps) => ({
26
- title,
27
- tabBarIcon: (style) => <Icon name={content?.icon} style={style}/>,
28
- tabIcon: content?.icon,
29
- tabBarIconFocused: content?.iconFocused ? (style) => <Icon name={content?.iconFocused} style={style}/> : null,
30
- ...(TypeGuards.isFunction(content.options) ? content.options(optionProps) : content.options),
31
- }),
32
- };
33
- // console.log('Render NavigationScreen loop', { scenes, screenProps, content, title, isFunction, props }, 'PACKAGES')
34
- }
35
- return (
36
- // @ts-ignore
37
- <NavigationComponent.Screen key={idx} {...screenProps}/>);
38
- })}
39
- </NavigationComponent.Navigator>;
40
- };
41
- //# sourceMappingURL=Navigation.js.map