@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,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 = <
|
|
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
|
|
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
|
|
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:
|
|
31
|
-
return <View {...props}
|
|
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 (
|
|
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,
|
|
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
|
|
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
|
-
}
|
|
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'
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
+
}
|
|
@@ -1,14 +1,64 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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 {
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import {
|
|
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
|
-
|
|
21
|
-
return {
|
|
22
|
-
isVisible: state.isSoftInputShown,
|
|
23
|
-
height: state.softInputHeight,
|
|
24
|
-
}
|
|
20
|
+
return useKeyboardController()
|
|
25
21
|
}
|
|
@@ -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]
|
|
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
|
})
|
package/src/utils/hooks.ts
CHANGED
|
@@ -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 {
|
|
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 =
|
|
318
|
+
const totalPadding = height + bottomPadding
|
|
319
319
|
|
|
320
|
-
return
|
|
320
|
+
return isVisible && enabled ? mergeStyles([propStyle, { paddingBottom: totalPadding }]) : propStyle
|
|
321
321
|
}
|
package/src/utils/locale.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { findBestLanguageTag, getLocales } from 'react-native-localize'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
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
|
+
}
|
package/src/utils/theme.ts
CHANGED
|
@@ -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' ?
|
|
17
|
+
const bottomNavHeight = Platform.OS === 'android' ? getAndroidNavbarHeight?.() ?? 0 : 0
|
|
15
18
|
|
|
16
19
|
const prefersConstantNavigationBar = bottomNavHeight > 0
|
|
17
20
|
|
|
18
|
-
const
|
|
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
|