@codeleap/mobile 2.3.8 → 2.3.12

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 (116) hide show
  1. package/package.json +2 -3
  2. package/src/components/ActionIcon/index.tsx +32 -0
  3. package/src/components/ActionIcon/styles.ts +97 -0
  4. package/src/components/ActivityIndicator/index.tsx +50 -0
  5. package/src/components/ActivityIndicator/styles.ts +68 -0
  6. package/src/components/Animated.tsx +34 -0
  7. package/src/components/AutoComplete/index.tsx +163 -0
  8. package/src/components/AutoComplete/styles.ts +44 -0
  9. package/src/components/Backdrop/index.tsx +48 -0
  10. package/src/components/Backdrop/styles.ts +33 -0
  11. package/src/components/Button/index.tsx +155 -0
  12. package/src/components/Button/styles.ts +129 -0
  13. package/src/components/Calendar/index.tsx +65 -0
  14. package/src/components/Calendar/style.ts +35 -0
  15. package/src/components/Calendar/types.ts +102 -0
  16. package/src/components/Checkbox/index.tsx +91 -0
  17. package/src/components/Checkbox/styles.ts +81 -0
  18. package/src/components/ContentView/index.tsx +63 -0
  19. package/src/components/ContentView/styles.ts +24 -0
  20. package/src/components/Drawer/index.tsx +33 -0
  21. package/src/components/Drawer/styles.ts +43 -0
  22. package/src/components/EmptyPlaceholder/index.tsx +88 -0
  23. package/src/components/EmptyPlaceholder/styles.ts +58 -0
  24. package/src/components/FileInput/index.tsx +181 -0
  25. package/src/components/FileInput/styles.ts +15 -0
  26. package/src/components/Grid/index.tsx +117 -0
  27. package/src/components/Grid/styles.ts +11 -0
  28. package/src/components/Icon/index.tsx +69 -0
  29. package/src/components/Icon/styles.ts +57 -0
  30. package/src/components/Image/index.tsx +91 -0
  31. package/src/components/Image/styles.ts +20 -0
  32. package/src/components/ImageView/Spotlight.tsx +157 -0
  33. package/src/components/ImageView/component.tsx +38 -0
  34. package/src/components/ImageView/index.ts +2 -0
  35. package/src/components/InputLabel/index.tsx +38 -0
  36. package/src/components/InputLabel/styles.ts +19 -0
  37. package/src/components/List/PaginationIndicator.tsx +71 -0
  38. package/src/components/List/index.tsx +114 -0
  39. package/src/components/List/styles.ts +19 -0
  40. package/src/components/Modal/index.tsx +218 -0
  41. package/src/components/Modal/styles.ts +153 -0
  42. package/src/components/MultiSelect/index.tsx +138 -0
  43. package/src/components/MultiSelect/styles.ts +18 -0
  44. package/src/components/MultiSelect/types.ts +42 -0
  45. package/src/components/Navigation/Navigation.tsx +54 -0
  46. package/src/components/Navigation/constants.ts +8 -0
  47. package/src/components/Navigation/index.tsx +3 -0
  48. package/src/components/Navigation/types.ts +35 -0
  49. package/src/components/Navigation/utils.tsx +57 -0
  50. package/src/components/Pager/index.tsx +121 -0
  51. package/src/components/Pager/styles.ts +81 -0
  52. package/src/components/RadioInput/index.tsx +106 -0
  53. package/src/components/RadioInput/styles.ts +67 -0
  54. package/src/components/Scroll/index.tsx +124 -0
  55. package/src/components/Scroll/styles.ts +18 -0
  56. package/src/components/Sections/index.tsx +91 -0
  57. package/src/components/SegmentedControl/index.tsx +204 -0
  58. package/src/components/SegmentedControl/styles.ts +89 -0
  59. package/src/components/Select/index.tsx +167 -0
  60. package/src/components/Select/styles.ts +62 -0
  61. package/src/components/Select/types.ts +43 -0
  62. package/src/components/Slider/Mark.tsx +46 -0
  63. package/src/components/Slider/Thumb.tsx +29 -0
  64. package/src/components/Slider/index.tsx +130 -0
  65. package/src/components/Slider/styles.ts +76 -0
  66. package/src/components/Slider/types.ts +30 -0
  67. package/src/components/Switch/index.tsx +91 -0
  68. package/src/components/Switch/styles.ts +38 -0
  69. package/src/components/Text/index.tsx +124 -0
  70. package/src/components/Text/styles.ts +50 -0
  71. package/src/components/TextInput/index.tsx +319 -0
  72. package/src/components/TextInput/styles.ts +127 -0
  73. package/src/components/Touchable/index.tsx +174 -0
  74. package/src/components/Touchable/styles.ts +28 -0
  75. package/src/components/View/index.tsx +103 -0
  76. package/src/components/View/styles.ts +24 -0
  77. package/src/components/components.ts +42 -0
  78. package/src/components/defaultStyles.ts +62 -0
  79. package/src/components/legacy/Modal/index.tsx +163 -0
  80. package/src/components/legacy/Modal/styles.ts +125 -0
  81. package/src/components/legacy/Pager/index.tsx +242 -0
  82. package/src/components/legacy/Pager/styles.ts +51 -0
  83. package/src/components/legacy/index.ts +2 -0
  84. package/src/modules/documentPicker.ts +7 -0
  85. package/src/modules/fastImage.ts +2 -0
  86. package/src/modules/imageCropPicker.d.ts +497 -0
  87. package/src/modules/index.d.ts +682 -0
  88. package/src/modules/reactNavigation.ts +15 -0
  89. package/src/modules/textInputMask.ts +11 -0
  90. package/src/modules/types/documentPicker.d.ts +215 -0
  91. package/src/modules/types/fileTypes.ts +138 -0
  92. package/src/modules/types/textInputMask.ts +9 -0
  93. package/src/types/index.ts +1 -0
  94. package/src/types/utility.ts +9 -0
  95. package/src/utils/KeyboardAware/context.tsx +75 -0
  96. package/src/utils/KeyboardAware/index.ts +17 -0
  97. package/src/utils/KeyboardAware/keyboardHooks.ts +124 -0
  98. package/src/utils/KeyboardAware/lib/KeyboardAwareFlatList.ts +4 -0
  99. package/src/utils/KeyboardAware/lib/KeyboardAwareHOC.tsx +618 -0
  100. package/src/utils/KeyboardAware/lib/KeyboardAwareInterface.ts +13 -0
  101. package/src/utils/KeyboardAware/lib/KeyboardAwareScrollView.ts +6 -0
  102. package/src/utils/KeyboardAware/lib/KeyboardAwareSectionList.ts +6 -0
  103. package/src/utils/KeyboardAware/types.ts +159 -0
  104. package/src/utils/ModalManager/components.tsx +112 -0
  105. package/src/utils/ModalManager/context.tsx +260 -0
  106. package/src/utils/ModalManager/index.ts +16 -0
  107. package/src/utils/OSAlert.ts +180 -0
  108. package/src/utils/PermissionManager/context.tsx +302 -0
  109. package/src/utils/PermissionManager/index.ts +20 -0
  110. package/src/utils/PermissionManager/types.ts +24 -0
  111. package/src/utils/hooks.ts +163 -0
  112. package/src/utils/index.ts +11 -0
  113. package/src/utils/input.ts +51 -0
  114. package/src/utils/misc.ts +83 -0
  115. package/src/utils/notifications.ts +206 -0
  116. package/src/utils/theme.ts +58 -0
@@ -0,0 +1,57 @@
1
+ import React from 'react'
2
+ import { Navigation } from './Navigation'
3
+
4
+ export function createAppNavigation(Scenes:any) {
5
+
6
+ const AllScenes = Object.entries<any>(Scenes).reduce((allScenes, [moduleName, content]) => {
7
+
8
+ const subScenes = []
9
+
10
+ for (const [name, sceneContent] of Object.entries(content.scenes)) {
11
+ subScenes.push(
12
+ [`${moduleName}.${name}`, sceneContent],
13
+ )
14
+ }
15
+
16
+ return [
17
+ ...allScenes,
18
+ ...subScenes,
19
+ ]
20
+ }, [])
21
+
22
+ const AppScenes = Object.fromEntries(AllScenes)
23
+
24
+ const SCENES_RESULT = Object.fromEntries(
25
+ Object.entries<any>(Scenes)
26
+ .map(([S, { _ig_scenes, exclude, type, navigationProps, ...otherProps }]) => {
27
+ let filterScenes = null
28
+
29
+ if (exclude) {
30
+ filterScenes = Object.fromEntries(
31
+ AllScenes.filter(([path]) => !exclude.some(param => path.startsWith(param))),
32
+ )
33
+ }
34
+
35
+ const Component = () => <Navigation
36
+ type={type || 'Stack'}
37
+ scenes={filterScenes || AppScenes}
38
+ screenOptions={{
39
+ headerShown: false,
40
+ ...navigationProps?.screenOptions,
41
+ }}
42
+ {...navigationProps}
43
+ />
44
+ // console.log('SCENES_RESULT create', { _ig_scenes, exclude, type, navigationProps, otherProps })
45
+
46
+ return [S, {
47
+ ...otherProps,
48
+ component: Component,
49
+ }]
50
+ }),
51
+ )
52
+
53
+ // console.log('SCENES_RESULT', SCENES_RESULT)
54
+
55
+ return SCENES_RESULT
56
+ }
57
+
@@ -0,0 +1,121 @@
1
+ import {
2
+ ComponentVariants,
3
+ useDefaultComponentStyle,
4
+ } from '@codeleap/common'
5
+ import React, {
6
+ ReactNode,
7
+ } from 'react'
8
+ import { StyleSheet } from 'react-native'
9
+ import { StylesOf } from '../../types/utility'
10
+ import { View } from '../View'
11
+ import { PagerStyles, PagerComposition } from './styles'
12
+ export * from './styles'
13
+
14
+ export type PageProps = {
15
+ isLast: boolean
16
+ isFirst: boolean
17
+ isActive: boolean
18
+ isNext: boolean
19
+ page: number
20
+ index: number
21
+ isPrevious: boolean
22
+ }
23
+
24
+ export type PagerProps = {
25
+ variants?: ComponentVariants<typeof PagerStyles>['variants']
26
+ styles?: StylesOf<PagerComposition>
27
+ children?: (((pageData: PageProps) => ReactNode) | ReactNode)[]
28
+ page?: number
29
+ style?: any
30
+ setPage?: (page: number) => void
31
+ returnEarly?: boolean
32
+ renderPageWrapper?:React.FC<PageProps>
33
+ pageWrapperProps?: any
34
+ }
35
+
36
+ export const Pager:React.FC<PagerProps> = (pagerProps) => {
37
+ const {
38
+
39
+ styles,
40
+ variants,
41
+ page,
42
+ style = {},
43
+ returnEarly = true,
44
+ renderPageWrapper,
45
+ pageWrapperProps = {},
46
+ children,
47
+ } = pagerProps
48
+
49
+ let variantStyles = useDefaultComponentStyle<'u:Pager', typeof PagerStyles>(
50
+ 'u:Pager',
51
+ {
52
+ styles,
53
+ transform: StyleSheet.flatten,
54
+ variants,
55
+ },
56
+ )
57
+ const nChildren = React.Children.count(children)
58
+
59
+ const lastPage = nChildren - 1
60
+
61
+ const childArr = React.Children.toArray(children)
62
+
63
+ const WrapperComponent = renderPageWrapper || View
64
+
65
+ // Reamimated seems to glitch if this is not done
66
+ variantStyles = JSON.parse(JSON.stringify(variantStyles))
67
+
68
+ return (
69
+ <View style={[variantStyles.wrapper, style]} >
70
+ {
71
+ childArr.map((child:PagerProps['children'][number], index) => {
72
+ const isActive = index === page
73
+ const isLast = index === lastPage
74
+ const isFirst = index === 0
75
+ const isNext = index === page + 1
76
+ const isPrevious = index === page - 1
77
+ const shouldRender = isActive || isNext || isPrevious
78
+
79
+ if (!shouldRender && returnEarly) return null
80
+ let pos = 0
81
+
82
+ if (isActive) {
83
+ pos = 1
84
+ } else if (index > page) {
85
+ pos = 2
86
+ } else {
87
+ pos = 0
88
+ }
89
+
90
+ const pageProps = {
91
+ isLast,
92
+ isActive,
93
+ isFirst,
94
+ isNext,
95
+ isPrevious,
96
+ index,
97
+ page,
98
+ }
99
+
100
+ const content = typeof child === 'function' ? child(pageProps) : child
101
+
102
+ const wrapperProps = {
103
+ key: index,
104
+ style: variantStyles.page,
105
+ animated: true,
106
+ transition: variantStyles['page:transition'],
107
+ animate: [variantStyles['page:previous'], variantStyles['page:current'], variantStyles['page:next']][pos],
108
+ ...pageWrapperProps,
109
+ }
110
+
111
+ return (
112
+ <WrapperComponent {...wrapperProps}>
113
+ {content}
114
+ </WrapperComponent>
115
+ )
116
+
117
+ })
118
+ }
119
+ </View>
120
+ )
121
+ }
@@ -0,0 +1,81 @@
1
+ import {
2
+ createDefaultVariantFactory,
3
+ includePresets,
4
+ } from '@codeleap/common'
5
+ import { Easing } from 'react-native'
6
+
7
+ export type PagerComposition =
8
+ | 'page'
9
+ | 'page:transition'
10
+ | 'page:previous'
11
+ | 'page:next'
12
+ | 'page:current'
13
+ | 'wrapper'
14
+
15
+ const createPagerStyle = createDefaultVariantFactory<PagerComposition>()
16
+
17
+ const presets = includePresets((style) => createPagerStyle(() => ({ wrapper: style })),
18
+ )
19
+ export const defaultPagerTransition = {
20
+ type: 'timing',
21
+ duration: 300,
22
+ easing: Easing.linear,
23
+ }
24
+
25
+ export function pagerAnimation(height, width, translate = 'X', transition = defaultPagerTransition) {
26
+ const translateProp = `translate${translate}`
27
+
28
+ const translateVal = translate === 'X' ? width : height
29
+
30
+ return {
31
+ wrapper: {
32
+ height,
33
+ width,
34
+ overflow: 'hidden',
35
+ },
36
+ 'page:transition': {
37
+ [translateProp]: transition,
38
+ },
39
+ 'page:next': {
40
+ [translateProp]: translateVal,
41
+
42
+ },
43
+ 'page:current': {
44
+ [translateProp]: 0,
45
+ },
46
+ 'page:previous': {
47
+ [translateProp]: -translateVal,
48
+ },
49
+ }
50
+ }
51
+
52
+ export const PagerStyles = {
53
+ ...presets,
54
+ default: createPagerStyle((theme) => {
55
+ const width = theme.values.width
56
+ const height = theme.values.window.height * 0.8
57
+ return {
58
+ ...pagerAnimation(height, width, 'X'),
59
+ page: {
60
+ width: '100%',
61
+ height: '100%',
62
+ position: 'absolute',
63
+ left: 0,
64
+ right: 0,
65
+ bottom: 0,
66
+ top: 0,
67
+ },
68
+ }
69
+ }),
70
+ horizontal: createPagerStyle((theme) => {
71
+
72
+ const width = theme.values.width
73
+ const height = theme.values.window.height * 0.8
74
+ return pagerAnimation(height, width, 'X')
75
+ }),
76
+ vertical: createPagerStyle((theme) => {
77
+ const height = theme.values.window.height * 0.8
78
+ const width = theme.values.width
79
+ return pagerAnimation(height, width, 'Y')
80
+ }),
81
+ }
@@ -0,0 +1,106 @@
1
+ import * as React from 'react'
2
+ import { ReactNode, ComponentPropsWithoutRef } from 'react'
3
+
4
+ import { Text } from '../Text'
5
+ import { Touchable } from '../Touchable'
6
+ import {
7
+ ComponentVariants,
8
+ getNestedStylesByKey,
9
+ StylesOf,
10
+ useDefaultComponentStyle,
11
+ } from '@codeleap/common'
12
+ import { View } from '../View'
13
+ import { RadioInputComposition, RadioInputStyles } from './styles'
14
+ import { InputLabel } from '../InputLabel'
15
+
16
+ export * from './styles'
17
+
18
+ type RadioItem<T extends unknown = any> = {
19
+ value: T
20
+ label: ReactNode
21
+ }
22
+
23
+ const getRadioStyle = (props) => useDefaultComponentStyle<'u:RadioInput', typeof RadioInputStyles>('u:RadioInput', props)
24
+
25
+ export type RadioButtonProps = Omit<
26
+ ComponentPropsWithoutRef<typeof Touchable>,
27
+ 'style'
28
+ > & {
29
+ item: RadioItem
30
+ select: () => void
31
+ style: StylesOf<RadioInputComposition>
32
+ checked: boolean
33
+ defaultValue?: number
34
+ }
35
+
36
+ export type RadioGroupProps<T> = {
37
+ options: RadioItem<T>[]
38
+ value: T
39
+ onValueChange(value: T): void
40
+ required?: boolean
41
+ label: ReactNode
42
+ styles?: StylesOf<RadioInputComposition>
43
+ } & ComponentVariants<typeof RadioInputStyles>
44
+
45
+ export const RadioButton: React.FC<RadioButtonProps> = ({
46
+ item,
47
+ select,
48
+ style,
49
+ checked,
50
+ ...props
51
+ }) => {
52
+ return (
53
+ <Touchable onPress={select} style={style.itemWrapper} debugName={'Change radioButton value'} styles={{
54
+ feedback: style.buttonFeedback,
55
+ }}>
56
+ <View style={[style.button, checked && style['button:checked']]}>
57
+ <View
58
+ style={[style.buttonMark, checked && style['buttonMark:checked']]}
59
+ />
60
+ </View>
61
+ {typeof item.label === 'string' ? (
62
+ <Text text={item.label} style={style.text} />
63
+ ) : (
64
+ item.label
65
+ )}
66
+ </Touchable>
67
+ )
68
+ }
69
+
70
+ export const RadioGroup = <T extends unknown>(
71
+ radioGroupProps: RadioGroupProps<T>,
72
+ ) => {
73
+ const {
74
+ options,
75
+ value,
76
+ onValueChange,
77
+ label,
78
+ responsiveVariants,
79
+ required = false,
80
+ variants,
81
+ styles,
82
+ } = radioGroupProps
83
+
84
+ const radioStyle = getRadioStyle({
85
+ responsiveVariants,
86
+ variants,
87
+ styles,
88
+ })
89
+ return (
90
+ <View style={radioStyle.wrapper}>
91
+ <InputLabel required={required} label={label} styles={getNestedStylesByKey('label', radioStyle)}/>
92
+ <View style={radioStyle.list}>
93
+ {options?.map((item, idx) => (
94
+ <RadioButton
95
+ debugName={'RadioButton'}
96
+ item={item}
97
+ key={idx}
98
+ style={radioStyle}
99
+ checked={value === item.value}
100
+ select={() => onValueChange(item.value)}
101
+ />
102
+ ))}
103
+ </View>
104
+ </View>
105
+ )
106
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ createDefaultVariantFactory, includePresets,
3
+ } from '@codeleap/common'
4
+ import { InputLabelComposition } from '../InputLabel'
5
+ type RadioParts = 'button' | 'itemWrapper' | 'text' | 'buttonMark' | 'buttonFeedback'
6
+
7
+ type RadioGroupParts = `label${Capitalize<InputLabelComposition>}` | 'wrapper' | 'list'
8
+
9
+ export type RadioInputComposition =
10
+ | `${RadioParts}:checked`
11
+ | RadioParts
12
+ | RadioGroupParts
13
+
14
+ const createRadioStyle =
15
+ createDefaultVariantFactory<RadioInputComposition>()
16
+
17
+ const presets = includePresets(style => createRadioStyle(() => ({ wrapper: style })))
18
+
19
+ export const RadioInputStyles = {
20
+ ...presets,
21
+ default: createRadioStyle((theme) => {
22
+
23
+ const itemHeight = theme.typography.baseFontSize * 1.2
24
+ const markHeight = itemHeight / 2
25
+ const translateX = -(markHeight / 2)
26
+ const translateY = -(markHeight / 2)
27
+ return {
28
+ itemWrapper: {
29
+ ...theme.presets.row,
30
+ ...theme.spacing.marginVertical(1.3),
31
+ },
32
+ button: {
33
+ height: itemHeight,
34
+ width: itemHeight,
35
+ ...theme.border.primary(1),
36
+ borderRadius: theme.borderRadius.large,
37
+
38
+ position: 'relative',
39
+ ...theme.spacing.marginRight(1),
40
+ },
41
+ buttonFeedback: { type: 'opacity', value: 0.5 },
42
+ buttonMark: {
43
+ backgroundColor: theme.colors.primary,
44
+ position: 'absolute',
45
+ left: '50%',
46
+ top: '50%',
47
+ height: markHeight,
48
+ width: markHeight,
49
+
50
+ transform: [{ translateX }, { translateY }],
51
+ borderRadius: theme.borderRadius.large,
52
+ opacity: 0,
53
+ },
54
+ 'buttonMark:checked': {
55
+ opacity: 1,
56
+ },
57
+ }
58
+ }),
59
+ square: createRadioStyle(() => ({
60
+ buttonMark: {
61
+ borderRadius: 0,
62
+ },
63
+ button: {
64
+ borderRadius: 0,
65
+ },
66
+ })),
67
+ }
@@ -0,0 +1,124 @@
1
+ import * as React from 'react'
2
+ import { forwardRef, useState } from 'react'
3
+ import {
4
+ deepEqual,
5
+ onUpdate,
6
+ useDefaultComponentStyle,
7
+ usePrevious,
8
+ } from '@codeleap/common'
9
+
10
+ import { RefreshControl, RefreshControlProps, ScrollView, StyleSheet } from 'react-native'
11
+ import { ViewProps } from '../View'
12
+ import { KeyboardAwareScrollViewTypes } from '../../modules'
13
+ import { StylesOf } from '../../types'
14
+ import { ScrollComposition, ScrollStyles } from './styles'
15
+ import { GetKeyboardAwarePropsOptions, useKeyboardAwareView } from '../../utils'
16
+ import { ScrollView as MotiScrollView } from 'moti'
17
+ // import { KeyboardAwareScrollView } from '../../utils'
18
+
19
+ type KeyboardAwareScrollViewProps = KeyboardAwareScrollViewTypes.KeyboardAwareScrollViewProps
20
+
21
+ export type ScrollProps = KeyboardAwareScrollViewProps &
22
+ ViewProps & {
23
+ onRefresh?: () => void
24
+ refreshTimeout?: number
25
+ changeData?: any
26
+ keyboardAware?: GetKeyboardAwarePropsOptions
27
+ refreshing?: boolean
28
+ styles?: StylesOf<ScrollComposition>
29
+ refreshControlProps?: Partial<RefreshControlProps>
30
+ debugName?: string
31
+ }
32
+
33
+ export const Scroll = forwardRef<ScrollView, ScrollProps>(
34
+ (scrollProps, ref) => {
35
+ const {
36
+ variants = [],
37
+ style,
38
+ refreshTimeout = 3000,
39
+ children,
40
+ changeData,
41
+ styles = {},
42
+ refreshControlProps = {},
43
+ contentContainerStyle,
44
+ keyboardAware,
45
+ debugName = '',
46
+ animated = true,
47
+ ...props
48
+ } = scrollProps
49
+ const hasRefresh = !!props.onRefresh
50
+ const [refreshingState, setRefreshing] = useState(false)
51
+ const refreshingDisplay = props.refreshing !== undefined ? props.refreshing : refreshingState
52
+
53
+ const timer = React.useRef(null)
54
+ const previousData = usePrevious(changeData)
55
+
56
+ const onRefresh = () => {
57
+ if (timer.current) {
58
+ clearTimeout(timer.current)
59
+ }
60
+
61
+ setRefreshing(true)
62
+
63
+ props.onRefresh()
64
+
65
+ timer.current = setTimeout(() => {
66
+ setRefreshing(false)
67
+ }, refreshTimeout)
68
+ }
69
+ onUpdate(() => {
70
+ if (refreshingDisplay && !deepEqual(previousData, changeData)) {
71
+ setRefreshing(false)
72
+ if (timer.current) {
73
+ clearTimeout(timer.current)
74
+ }
75
+ }
76
+ }, [refreshingDisplay, changeData])
77
+
78
+ const variantStyles = useDefaultComponentStyle<'u:Scroll', typeof ScrollStyles>('u:Scroll', {
79
+ variants,
80
+ styles,
81
+ transform: StyleSheet.flatten,
82
+ rootElement: 'content',
83
+ })
84
+
85
+ const refreshStyles = StyleSheet.flatten([variantStyles.refreshControl, styles.refreshControl])
86
+ const _scrollProps = {
87
+ style: [variantStyles.wrapper, style],
88
+ contentContainerStyle: [variantStyles.content, contentContainerStyle],
89
+ ref: ref as unknown as ScrollView,
90
+ refreshControl: hasRefresh && (
91
+ <RefreshControl
92
+ refreshing={refreshingDisplay}
93
+ onRefresh={onRefresh}
94
+ tintColor={refreshStyles?.color}
95
+ colors={[refreshStyles?.color]}
96
+ {...refreshControlProps}
97
+ />
98
+ ),
99
+ ...props,
100
+ }
101
+ const keyboard = useKeyboardAwareView({
102
+ debugName,
103
+ })
104
+
105
+ const rootProps = keyboard.getKeyboardAwareProps(_scrollProps, {
106
+ adapt: 'marginBottom',
107
+ baseStyleProp: 'style',
108
+ animated,
109
+ ...keyboardAware,
110
+
111
+ })
112
+ const Component = animated ? MotiScrollView : ScrollView
113
+
114
+ return (
115
+ <Component
116
+ {...rootProps}
117
+
118
+ >
119
+ {children}
120
+ </Component>
121
+ )
122
+ },
123
+ )
124
+ export * from './styles'
@@ -0,0 +1,18 @@
1
+ import { createDefaultVariantFactory } from '@codeleap/common'
2
+
3
+ export type ScrollComposition = 'wrapper' |'content' | 'refreshControl'
4
+
5
+ const createScrollStyle = createDefaultVariantFactory<ScrollComposition>()
6
+
7
+ export const ScrollStyles = {
8
+ default: createScrollStyle((theme) => {
9
+ return {
10
+ wrapper: {
11
+ ...theme.presets.fullHeight,
12
+ },
13
+ refreshControl: {
14
+ color: theme.colors.primary,
15
+ },
16
+ }
17
+ }),
18
+ }
@@ -0,0 +1,91 @@
1
+ import * as React from 'react'
2
+ import { forwardRef, useState } from 'react'
3
+ import {
4
+ deepEqual,
5
+ onUpdate,
6
+ useDefaultComponentStyle,
7
+ usePrevious,
8
+ useCodeleapContext,
9
+ } from '@codeleap/common'
10
+
11
+ import { RefreshControl, SectionList } from 'react-native'
12
+ import { View, ViewProps } from '../View'
13
+ import { KeyboardAwareScrollViewTypes } from '../../modules'
14
+ import { KeyboardAwareSectionList } from '../../utils'
15
+
16
+ export type SectionListProps = KeyboardAwareScrollViewTypes.KeyboardAwareSectionListProps<any> &
17
+ ViewProps & {
18
+ onRefresh?: () => void
19
+ refreshTimeout?: number
20
+ changeData?: any
21
+ separators?: boolean
22
+ }
23
+
24
+ export const Sections = forwardRef<SectionList, SectionListProps>(
25
+ (flatListProps, ref) => {
26
+ const {
27
+ variants = [],
28
+ style,
29
+ refreshTimeout = 3000,
30
+ changeData,
31
+ ...props
32
+ } = flatListProps
33
+ const hasRefresh = !!props.onRefresh
34
+ const [refreshing, setRefreshing] = useState(false)
35
+
36
+ const timer = React.useRef(null)
37
+ const previousData = usePrevious(changeData)
38
+
39
+ const onRefresh = () => {
40
+ if (timer.current) {
41
+ clearTimeout(timer.current)
42
+ }
43
+
44
+ setRefreshing(true)
45
+
46
+ props.onRefresh()
47
+
48
+ timer.current = setTimeout(() => {
49
+ setRefreshing(false)
50
+ }, refreshTimeout)
51
+ }
52
+ onUpdate(() => {
53
+ if (refreshing && !deepEqual(previousData, changeData)) {
54
+ setRefreshing(false)
55
+ if (timer.current) {
56
+ clearTimeout(timer.current)
57
+ }
58
+ }
59
+ }, [refreshing, changeData])
60
+ const { Theme } = useCodeleapContext()
61
+
62
+ const variantStyles = useDefaultComponentStyle('View', {
63
+ variants,
64
+ })
65
+
66
+ const renderSeparator = () => {
67
+ return (
68
+ <View variants={['separator']}></View>
69
+ )
70
+ }
71
+
72
+ const separatorProp = props.separators
73
+ const isEmpty = !props.data || !props.data.length
74
+ const separator = !isEmpty && separatorProp == true && renderSeparator
75
+
76
+ return (
77
+ <KeyboardAwareSectionList
78
+ style={[Theme.presets.full, style]}
79
+ contentContainerStyle={[variantStyles.wrapper]}
80
+ ref={ref as unknown as SectionList}
81
+ ItemSeparatorComponent={separator}
82
+ {...props}
83
+ refreshControl={
84
+ hasRefresh && (
85
+ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
86
+ )
87
+ }
88
+ />
89
+ )
90
+ },
91
+ )