@codeleap/mobile 2.3.0 → 2.3.2

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 (126) hide show
  1. package/dist/components/Button/index.d.ts +0 -1
  2. package/dist/components/Button/index.js +5 -12
  3. package/dist/components/Button/index.js.map +1 -1
  4. package/dist/components/List/styles.js +1 -1
  5. package/dist/components/List/styles.js.map +1 -1
  6. package/dist/components/Touchable/index.js +11 -9
  7. package/dist/components/Touchable/index.js.map +1 -1
  8. package/dist/utils/theme.d.ts +1 -0
  9. package/dist/utils/theme.js +7 -2
  10. package/dist/utils/theme.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/components/ActionIcon/index.tsx +32 -0
  13. package/src/components/ActionIcon/styles.ts +97 -0
  14. package/src/components/ActivityIndicator/index.tsx +50 -0
  15. package/src/components/ActivityIndicator/styles.ts +68 -0
  16. package/src/components/Animated.tsx +34 -0
  17. package/src/components/AutoComplete/index.tsx +163 -0
  18. package/src/components/AutoComplete/styles.ts +44 -0
  19. package/src/components/Backdrop/index.tsx +48 -0
  20. package/src/components/Backdrop/styles.ts +33 -0
  21. package/src/components/Button/index.tsx +154 -0
  22. package/src/components/Button/styles.ts +129 -0
  23. package/src/components/Calendar/index.tsx +65 -0
  24. package/src/components/Calendar/style.ts +35 -0
  25. package/src/components/Calendar/types.ts +102 -0
  26. package/src/components/Checkbox/index.tsx +91 -0
  27. package/src/components/Checkbox/styles.ts +81 -0
  28. package/src/components/ContentView/index.tsx +63 -0
  29. package/src/components/ContentView/styles.ts +24 -0
  30. package/src/components/Drawer/index.tsx +33 -0
  31. package/src/components/Drawer/styles.ts +43 -0
  32. package/src/components/EmptyPlaceholder/index.tsx +88 -0
  33. package/src/components/EmptyPlaceholder/styles.ts +58 -0
  34. package/src/components/FileInput/index.tsx +181 -0
  35. package/src/components/FileInput/styles.ts +15 -0
  36. package/src/components/Grid/index.tsx +117 -0
  37. package/src/components/Grid/styles.ts +11 -0
  38. package/src/components/Icon/index.tsx +69 -0
  39. package/src/components/Icon/styles.ts +57 -0
  40. package/src/components/Image/index.tsx +91 -0
  41. package/src/components/Image/styles.ts +20 -0
  42. package/src/components/ImageView/Spotlight.tsx +157 -0
  43. package/src/components/ImageView/component.tsx +38 -0
  44. package/src/components/ImageView/index.ts +2 -0
  45. package/src/components/InputLabel/index.tsx +38 -0
  46. package/src/components/InputLabel/styles.ts +19 -0
  47. package/src/components/List/PaginationIndicator.tsx +71 -0
  48. package/src/components/List/index.tsx +114 -0
  49. package/src/components/List/styles.ts +19 -0
  50. package/src/components/Modal/index.tsx +218 -0
  51. package/src/components/Modal/styles.ts +153 -0
  52. package/src/components/MultiSelect/index.tsx +138 -0
  53. package/src/components/MultiSelect/styles.ts +18 -0
  54. package/src/components/MultiSelect/types.ts +42 -0
  55. package/src/components/Navigation/Navigation.tsx +54 -0
  56. package/src/components/Navigation/constants.ts +8 -0
  57. package/src/components/Navigation/index.tsx +3 -0
  58. package/src/components/Navigation/types.ts +35 -0
  59. package/src/components/Navigation/utils.tsx +57 -0
  60. package/src/components/Pager/index.tsx +121 -0
  61. package/src/components/Pager/styles.ts +81 -0
  62. package/src/components/RadioInput/index.tsx +106 -0
  63. package/src/components/RadioInput/styles.ts +67 -0
  64. package/src/components/Scroll/index.tsx +124 -0
  65. package/src/components/Scroll/styles.ts +18 -0
  66. package/src/components/Sections/index.tsx +91 -0
  67. package/src/components/SegmentedControl/index.tsx +204 -0
  68. package/src/components/SegmentedControl/styles.ts +89 -0
  69. package/src/components/Select/index.tsx +167 -0
  70. package/src/components/Select/styles.ts +62 -0
  71. package/src/components/Select/types.ts +43 -0
  72. package/src/components/Slider/Mark.tsx +46 -0
  73. package/src/components/Slider/Thumb.tsx +29 -0
  74. package/src/components/Slider/index.tsx +130 -0
  75. package/src/components/Slider/styles.ts +76 -0
  76. package/src/components/Slider/types.ts +30 -0
  77. package/src/components/Switch/index.tsx +91 -0
  78. package/src/components/Switch/styles.ts +38 -0
  79. package/src/components/Text/index.tsx +97 -0
  80. package/src/components/Text/styles.ts +50 -0
  81. package/src/components/TextInput/index.tsx +319 -0
  82. package/src/components/TextInput/styles.ts +127 -0
  83. package/src/components/Touchable/index.tsx +174 -0
  84. package/src/components/Touchable/styles.ts +28 -0
  85. package/src/components/View/index.tsx +103 -0
  86. package/src/components/View/styles.ts +24 -0
  87. package/src/components/components.ts +42 -0
  88. package/src/components/defaultStyles.ts +62 -0
  89. package/src/components/legacy/Modal/index.tsx +163 -0
  90. package/src/components/legacy/Modal/styles.ts +125 -0
  91. package/src/components/legacy/Pager/index.tsx +242 -0
  92. package/src/components/legacy/Pager/styles.ts +51 -0
  93. package/src/components/legacy/index.ts +2 -0
  94. package/src/modules/documentPicker.ts +7 -0
  95. package/src/modules/fastImage.ts +2 -0
  96. package/src/modules/imageCropPicker.d.ts +497 -0
  97. package/src/modules/index.d.ts +682 -0
  98. package/src/modules/reactNavigation.ts +15 -0
  99. package/src/modules/textInputMask.ts +11 -0
  100. package/src/modules/types/documentPicker.d.ts +215 -0
  101. package/src/modules/types/fileTypes.ts +138 -0
  102. package/src/modules/types/textInputMask.ts +9 -0
  103. package/src/types/index.ts +1 -0
  104. package/src/types/utility.ts +9 -0
  105. package/src/utils/KeyboardAware/context.tsx +75 -0
  106. package/src/utils/KeyboardAware/index.ts +17 -0
  107. package/src/utils/KeyboardAware/keyboardHooks.ts +124 -0
  108. package/src/utils/KeyboardAware/lib/KeyboardAwareFlatList.ts +4 -0
  109. package/src/utils/KeyboardAware/lib/KeyboardAwareHOC.tsx +618 -0
  110. package/src/utils/KeyboardAware/lib/KeyboardAwareInterface.ts +13 -0
  111. package/src/utils/KeyboardAware/lib/KeyboardAwareScrollView.ts +6 -0
  112. package/src/utils/KeyboardAware/lib/KeyboardAwareSectionList.ts +6 -0
  113. package/src/utils/KeyboardAware/types.ts +159 -0
  114. package/src/utils/ModalManager/components.tsx +112 -0
  115. package/src/utils/ModalManager/context.tsx +260 -0
  116. package/src/utils/ModalManager/index.ts +16 -0
  117. package/src/utils/OSAlert.ts +180 -0
  118. package/src/utils/PermissionManager/context.tsx +302 -0
  119. package/src/utils/PermissionManager/index.ts +20 -0
  120. package/src/utils/PermissionManager/types.ts +24 -0
  121. package/src/utils/hooks.ts +163 -0
  122. package/src/utils/index.ts +11 -0
  123. package/src/utils/input.ts +51 -0
  124. package/src/utils/misc.ts +83 -0
  125. package/src/utils/notifications.ts +206 -0
  126. package/src/utils/theme.ts +58 -0
@@ -0,0 +1,181 @@
1
+ import React, { forwardRef, useImperativeHandle } from 'react'
2
+ import { DocumentPicker, ImageCropPicker } from '../../modules/documentPicker'
3
+ import {
4
+ MobileInputFile,
5
+ parseFilePathData,
6
+ useCodeleapContext,
7
+ MobileFile,
8
+ } from '@codeleap/common'
9
+ import { OSAlert } from '../../utils'
10
+ import { ImageOrVideo, Options } from 'react-native-image-crop-picker'
11
+ import { DocumentPickerOptions } from '../../modules/types/documentPicker'
12
+
13
+ export * from './styles'
14
+
15
+ export type FileInputRef = {
16
+ openFilePicker: (string?: 'camera' | 'library') => void
17
+ }
18
+
19
+ export type FileInputProps = {
20
+ mode: 'hidden' | 'button'
21
+ onFileSelect(files: MobileInputFile<ImageOrVideo>[]): void
22
+ options?: DocumentPickerOptions<any>
23
+
24
+ ref?: FileInputRef
25
+
26
+ type?: 'image' | 'anyFile'
27
+ alertProps?: Parameters<typeof OSAlert.ask>[0]
28
+ pickerOptions?: Partial<Options>
29
+ required?: boolean
30
+ onOpenCamera?: (resolve: (() => void)) => Promise<void>
31
+ onOpenFileSystem?: (resolve: (() => void)) => Promise<void>
32
+ onOpenGallery?: (resolve: (() => void)) => Promise<void>
33
+ onError?: (error: any) => void
34
+ }
35
+
36
+ const pickerDefaults = {
37
+ cropping: true,
38
+ }
39
+
40
+ function parsePickerData(data:ImageOrVideo):MobileInputFile<ImageOrVideo> {
41
+
42
+ const filePathData = parseFilePathData(data.path)
43
+ const d:MobileFile = {
44
+ ...data,
45
+ name: filePathData.name,
46
+ size: data.size,
47
+ type: data.mime,
48
+ uri: data.path,
49
+ fileCopyUri: data.path,
50
+ }
51
+
52
+ return {
53
+ file: d,
54
+ preview: data.path,
55
+ }
56
+ }
57
+
58
+ export const FileInput = forwardRef<
59
+ FileInputRef,
60
+ FileInputProps
61
+ >((fileInputProps, ref) => {
62
+ const {
63
+
64
+ onFileSelect,
65
+
66
+ options,
67
+ type = 'image',
68
+ alertProps,
69
+
70
+ pickerOptions,
71
+
72
+ onOpenCamera = null,
73
+ onOpenGallery = null,
74
+ onOpenFileSystem = null,
75
+ onError,
76
+ } = fileInputProps
77
+
78
+ const { logger } = useCodeleapContext()
79
+
80
+ async function openFileSystem() {
81
+ try {
82
+ let files = await DocumentPicker.pick(options)
83
+ if (!Array.isArray(files)) {
84
+ files = [files]
85
+ }
86
+
87
+ onFileSelect(files.map((file) => ({ preview: file.uri, file })))
88
+ } catch (err) {
89
+ handleError(err)
90
+ }
91
+ }
92
+
93
+ function handleError(err) {
94
+
95
+ logger.warn('File Input Error', err, 'FILE INPUT')
96
+ onError?.(err)
97
+
98
+ }
99
+
100
+ const mergedOptions = {
101
+ ...pickerDefaults,
102
+ ...pickerOptions,
103
+ } as Options
104
+
105
+ const handlePickerResolution = (data: ImageOrVideo | ImageOrVideo[]) => {
106
+ let imageArray:ImageOrVideo[] = []
107
+ if (!Array.isArray(data)) {
108
+ imageArray = [data]
109
+ } else {
110
+ imageArray = data
111
+ }
112
+ onFileSelect(imageArray.map(parsePickerData))
113
+ }
114
+ const onPress = (open?: 'camera' | 'library' | 'fs', options?: Options) => {
115
+ if (open == 'fs') {
116
+ openFileSystem()
117
+ } else {
118
+ const call = open === 'camera' ? 'openCamera' : 'openPicker'
119
+ ImageCropPicker[call]({ ...mergedOptions, ...(options || {}) }).then(handlePickerResolution)
120
+ }
121
+ }
122
+ const openFilePicker = async (imageSource = null) => {
123
+ if (type === 'image') {
124
+ if (imageSource === 'camera') {
125
+ onPress('camera')
126
+ } else if (imageSource === 'library') {
127
+ onPress('library')
128
+ } else {
129
+ OSAlert.ask({
130
+ title: 'Change Image',
131
+ body: 'Do you want to take a new picture or select an existing one?',
132
+ ...alertProps,
133
+ options: [
134
+ {
135
+ text: alertProps?.options?.[0]?.text || 'Camera',
136
+ onPress: () => {
137
+ if (onOpenCamera) {
138
+ onOpenCamera(() => onPress('camera'))
139
+ } else {
140
+ onPress('camera')
141
+ }
142
+ },
143
+ ...alertProps?.options[1],
144
+ },
145
+ {
146
+ text: 'Library',
147
+ onPress: () => {
148
+ if (onOpenGallery) {
149
+ onOpenGallery(() => onPress('library'))
150
+ } else {
151
+ onPress('library')
152
+ }
153
+ },
154
+ ...alertProps?.options[2],
155
+ },
156
+ {
157
+ text: 'Cancel',
158
+ style: 'cancel',
159
+ onPress: () => {},
160
+ ...alertProps?.options[0],
161
+ },
162
+ ],
163
+ })
164
+ }
165
+ } else {
166
+ if (onOpenFileSystem) {
167
+ onOpenFileSystem(() => onPress('fs'))
168
+ } else {
169
+
170
+ onPress('fs')
171
+ }
172
+ }
173
+
174
+ }
175
+
176
+ useImperativeHandle(ref, () => ({
177
+ openFilePicker,
178
+ }))
179
+
180
+ return null
181
+ })
@@ -0,0 +1,15 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+
3
+ export type FileInputComposition = 'label' | 'wrapper' | 'input'
4
+
5
+ const createFileInputStyle =
6
+ createDefaultVariantFactory<FileInputComposition>()
7
+
8
+ const presets = includePresets((styles) => createFileInputStyle(() => ({ wrapper: styles })),
9
+ )
10
+
11
+ export const FileInputStyles = {
12
+ ...presets,
13
+ default: createFileInputStyle((theme) => ({})),
14
+
15
+ }
@@ -0,0 +1,117 @@
1
+ import * as React from 'react'
2
+ import { forwardRef } from 'react'
3
+ import {
4
+ useDefaultComponentStyle,
5
+ ComponentVariants,
6
+ } from '@codeleap/common'
7
+
8
+ import { FlatGrid, FlatGridProps, GridRenderItemInfo } from 'react-native-super-grid'
9
+ import { RefreshControl, StyleSheet, RefreshControlProps } from 'react-native'
10
+ import { View, ViewProps } from '../View'
11
+ import { EmptyPlaceholder, EmptyPlaceholderProps } from '../EmptyPlaceholder'
12
+ import { GridComposition, GridStyles } from './styles'
13
+ import { StylesOf } from '../../types'
14
+ import { GetKeyboardAwarePropsOptions, useKeyboardAwareView } from '../../utils'
15
+
16
+ export type DataboundFlatGridPropsTypes = 'data' | 'renderItem' | 'keyExtractor' | 'getItemLayout'
17
+
18
+ export type ReplaceFlatGridProps<P, T> = Omit<P, DataboundFlatGridPropsTypes> & {
19
+ data: T[]
20
+ keyExtractor?: (item: T, index: number) => string
21
+ renderItem: (data: GridRenderItemInfo<T>) => React.ReactElement
22
+ onRefresh?: () => void
23
+ getItemLayout?: ((
24
+ data:T,
25
+ index: number,
26
+ ) => { length: number; offset: number; index: number })
27
+ }
28
+
29
+ export * from './styles'
30
+
31
+ export type GridProps<
32
+ T = any[],
33
+ Data = T extends Array<infer D> ? D : never
34
+ > =FlatGridProps<Data> &
35
+ Omit<ViewProps, 'variants'> & {
36
+ separators?: boolean
37
+ placeholder?: EmptyPlaceholderProps
38
+ keyboardAware?: GetKeyboardAwarePropsOptions
39
+ debugName?: string
40
+ styles?: StylesOf<GridComposition>
41
+ refreshControlProps?: Partial<RefreshControlProps>
42
+ } & ComponentVariants<typeof GridStyles>
43
+
44
+ const GridCP = forwardRef<FlatGrid, GridProps>(
45
+ (flatGridProps, ref) => {
46
+ const {
47
+ variants = [],
48
+ style,
49
+ styles = {},
50
+ onRefresh,
51
+ refreshing,
52
+ placeholder,
53
+ keyboardAware,
54
+ debugName,
55
+ refreshControlProps = {},
56
+ ...props
57
+ } = flatGridProps
58
+
59
+ const variantStyles = useDefaultComponentStyle<'u:Grid', typeof GridStyles>('u:Grid', {
60
+ variants,
61
+ styles,
62
+ transform: StyleSheet.flatten,
63
+
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
+ const refreshStyles = StyleSheet.flatten([variantStyles.refreshControl, styles.refreshControl])
77
+ const Component = FlatGrid
78
+
79
+ const _gridProps = {
80
+ style: [variantStyles.wrapper, style],
81
+ contentContainerStyle: variantStyles.content,
82
+ ref: ref as unknown as FlatGrid,
83
+ ItemSeparatorComponent: separator,
84
+ refreshControl:
85
+ !!onRefresh && (
86
+ <RefreshControl
87
+ refreshing={refreshing}
88
+ onRefresh={onRefresh}
89
+ tintColor={refreshStyles?.color}
90
+ colors={[refreshStyles?.color]}
91
+ {...refreshControlProps}
92
+ />
93
+ ),
94
+
95
+ ListEmptyComponent: <EmptyPlaceholder {...placeholder}/>,
96
+ ...props,
97
+ }
98
+ const keyboard = useKeyboardAwareView({
99
+ debugName,
100
+ })
101
+ const gridProps = keyboard.getKeyboardAwareProps(_gridProps, {
102
+ baseStyleProp: 'contentContainerStyle',
103
+ adapt: 'paddingBottom',
104
+ ...keyboardAware,
105
+ })
106
+ return (
107
+ <Component
108
+ {...gridProps}
109
+ />
110
+ )
111
+ },
112
+ )
113
+
114
+ export type GridComponentType = <T extends any[] = any[]>(props: FlatGridProps<T>) => React.ReactElement
115
+
116
+ export const Grid = GridCP as GridComponentType
117
+
@@ -0,0 +1,11 @@
1
+ import { createDefaultVariantFactory } from '@codeleap/common'
2
+ import { ListComposition, ListStyles } from '../List'
3
+
4
+ export type GridComposition = ListComposition
5
+
6
+ const createGridStyle = createDefaultVariantFactory<GridComposition>()
7
+
8
+ export const GridStyles = {
9
+ ...ListStyles,
10
+
11
+ }
@@ -0,0 +1,69 @@
1
+ import * as React from 'react'
2
+ import {
3
+ ComponentVariants,
4
+
5
+ useDefaultComponentStyle,
6
+ useCodeleapContext,
7
+ arePropsEqual,
8
+ IconPlaceholder,
9
+ onMount,
10
+ onUpdate,
11
+ } from '@codeleap/common'
12
+ import { StyleSheet } from 'react-native'
13
+ import { View } from '../View'
14
+ export * from './styles'
15
+
16
+ import {
17
+ IconStyles,
18
+ } from './styles'
19
+
20
+ export type IconProps = {
21
+ name: IconPlaceholder
22
+ style?: any
23
+ color?: string
24
+ variants?: ComponentVariants<typeof IconStyles>['variants']
25
+ renderEmptySpace?: boolean
26
+ size?: number
27
+ }
28
+
29
+ export const IconComponent: React.FC<IconProps> = ({ name, style, variants, renderEmptySpace, ...otherProps }) => {
30
+ const { Theme, logger } = useCodeleapContext()
31
+
32
+ const variantStyles = useDefaultComponentStyle<'u:Icon', typeof IconStyles>('u:Icon', {
33
+ variants,
34
+ transform: StyleSheet.flatten,
35
+ styles: {
36
+ icon: style,
37
+ },
38
+ rootElement: 'icon',
39
+ })
40
+ const Component = Theme?.icons?.[name]
41
+ onUpdate(() => {
42
+ if (!Component && !!name) {
43
+ logger.warn(
44
+ `Icon: No icon found in theme for name "${name}".`,
45
+ { props: { style, name, variants, variantStyles }},
46
+ 'Component',
47
+ )
48
+ }
49
+ }, [name])
50
+
51
+ if (!name) {
52
+ return renderEmptySpace ? <View style={variantStyles.icon}/> : null
53
+ }
54
+
55
+ if (!Component) {
56
+
57
+ return null
58
+ }
59
+ return <Component {...otherProps} style={variantStyles.icon} />
60
+ }
61
+
62
+ function areEqual(prevProps, nextProps) {
63
+ const check = ['name', 'style', 'variants', 'renderEmptySpace']
64
+ const res = arePropsEqual(prevProps, nextProps, { check })
65
+ return res
66
+ }
67
+
68
+ export const Icon = React.memo(IconComponent, areEqual)
69
+
@@ -0,0 +1,57 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+
3
+ export type IconComposition = 'icon'
4
+
5
+ const createIconStyle = createDefaultVariantFactory<IconComposition>()
6
+
7
+ const presets = includePresets((styles) => createIconStyle(() => ({ icon: styles })))
8
+
9
+ export const IconStyles = {
10
+ ...presets,
11
+ default: createIconStyle((theme) => ({
12
+ icon: {
13
+ color: theme.colors.icon,
14
+ },
15
+ })),
16
+ originalColor: createIconStyle(theme => ({
17
+ icon: {
18
+ color: 'auto',
19
+ },
20
+ })),
21
+ white: createIconStyle((theme) => ({
22
+ icon: {
23
+ color: theme.colors.white,
24
+ },
25
+ })),
26
+
27
+ primary: createIconStyle((theme) => ({
28
+ icon: {
29
+ color: theme.colors.primary,
30
+ },
31
+ })),
32
+ negative: createIconStyle((theme) => ({
33
+ icon: {
34
+ color: theme.colors.negative,
35
+ },
36
+ })),
37
+ positive: createIconStyle((theme) => ({
38
+ icon: {
39
+ color: theme.colors.positive,
40
+ },
41
+ })),
42
+ small: createIconStyle((theme) => ({
43
+ icon: {
44
+ ...theme.sized(1),
45
+ },
46
+ })),
47
+ medium: createIconStyle((theme) => ({
48
+ icon: {
49
+ ...theme.sized(2),
50
+ },
51
+ })),
52
+ large: createIconStyle((theme) => ({
53
+ icon: {
54
+ ...theme.sized(3),
55
+ },
56
+ })),
57
+ }
@@ -0,0 +1,91 @@
1
+ import * as React from 'react'
2
+ import {
3
+ ComponentVariants,
4
+
5
+ useDefaultComponentStyle,
6
+ arePropsEqual,
7
+ FormTypes,
8
+ TypeGuards,
9
+ } from '@codeleap/common'
10
+ import { ComponentPropsWithoutRef } from 'react'
11
+ import {
12
+ Image as NativeImage,
13
+ ImageStyle,
14
+ StyleProp,
15
+ StyleSheet,
16
+ TextStyle,
17
+ ViewStyle,
18
+ } from 'react-native'
19
+ import { FastImage } from '../../modules/fastImage'
20
+ import {
21
+ ImageStyles,
22
+ } from './styles'
23
+ import { useImageSpotlight } from '../ImageView/Spotlight'
24
+ import { Touchable } from '../Touchable'
25
+ import { isFile, toMultipartFile } from '../../utils'
26
+ export * from './styles'
27
+ type NativeImageProps = ComponentPropsWithoutRef<typeof NativeImage>
28
+ export type ImageProps = Omit<NativeImageProps, 'source' | 'style'> & {
29
+ variants?: ComponentVariants<typeof ImageStyles>['variants']
30
+ fast?: boolean
31
+ style?: StyleProp<ImageStyle | TextStyle | ViewStyle>
32
+ source:
33
+ | (NativeImageProps['source'] & {
34
+ priority?: keyof typeof FastImage.priority
35
+ })
36
+ | FormTypes.AnyFile
37
+ | string
38
+ | number
39
+ resizeMode?: keyof typeof FastImage.resizeMode
40
+ spotlight?: string
41
+ }
42
+
43
+ export const ImageComponent: React.FC<ImageProps> = (props) => {
44
+ const { variants, style, fast = true, spotlight = null, resizeMode = 'contain', source, ...imageProps } = props
45
+
46
+ const variantStyles = useDefaultComponentStyle<'u:Image', typeof ImageStyles>('u:Image', { variants })
47
+
48
+ const styles = StyleSheet.flatten([variantStyles.wrapper, style])
49
+ let imSource = source
50
+ if (isFile(imSource)) {
51
+ imSource = toMultipartFile(imSource)
52
+ } else if (TypeGuards.isString(source)) {
53
+ imSource = { uri: source }
54
+ }
55
+ const spotlightActions = useImageSpotlight(spotlight, props.source)
56
+ const Wrapper = !!spotlight ? Touchable : ({ children }) => <>{children}</>
57
+ const wrapperProps = {
58
+ onPress: spotlightActions.onImagePressed,
59
+ debugName: `Press spotlight image ${props.source}`,
60
+ style: [variantStyles.touchable],
61
+ android_ripple: null,
62
+ }
63
+ if (fast) {
64
+ return (
65
+ <Wrapper {...wrapperProps}>
66
+
67
+ <FastImage
68
+ style={styles}
69
+ // @ts-ignore
70
+ tintColor={styles?.tintColor}
71
+ source={imSource}
72
+ resizeMode={FastImage.resizeMode[resizeMode || 'contain']}
73
+ {...imageProps}
74
+ />
75
+ </Wrapper>
76
+ )
77
+ }
78
+ return <Wrapper {...wrapperProps}>
79
+ <NativeImage style={styles} resizeMode={resizeMode} source={imSource} {...(imageProps as any)} />
80
+
81
+ </Wrapper>
82
+ }
83
+
84
+ function areEqual(prevProps, nextProps) {
85
+ const check = ['source', 'style', 'variants', 'resizeMode', 'fast']
86
+ const res = arePropsEqual(prevProps, nextProps, { check })
87
+ return res
88
+ }
89
+
90
+ export const Image = React.memo(ImageComponent, areEqual)
91
+
@@ -0,0 +1,20 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+
3
+ export type ImageComposition = 'wrapper' | 'touchable'
4
+ const createImageStyle = createDefaultVariantFactory<ImageComposition>()
5
+
6
+ const presets = includePresets((styles) => createImageStyle(() => ({ wrapper: styles, touchable: styles })),
7
+ )
8
+
9
+ export const ImageStyles = {
10
+ ...presets,
11
+ default: createImageStyle(() => ({
12
+ wrapper: {},
13
+ })),
14
+
15
+ round: createImageStyle(() => ({
16
+ wrapper: {
17
+ borderRadius: 100,
18
+ },
19
+ })),
20
+ }