@codeleap/mobile 2.3.0 → 2.3.1
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/List/styles.js +1 -1
- package/dist/components/List/styles.js.map +1 -1
- package/dist/utils/theme.d.ts +1 -0
- package/dist/utils/theme.js +7 -2
- package/dist/utils/theme.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ActionIcon/index.tsx +32 -0
- package/src/components/ActionIcon/styles.ts +97 -0
- package/src/components/ActivityIndicator/index.tsx +50 -0
- package/src/components/ActivityIndicator/styles.ts +68 -0
- package/src/components/Animated.tsx +34 -0
- package/src/components/AutoComplete/index.tsx +163 -0
- package/src/components/AutoComplete/styles.ts +44 -0
- package/src/components/Backdrop/index.tsx +48 -0
- package/src/components/Backdrop/styles.ts +33 -0
- package/src/components/Button/index.tsx +167 -0
- package/src/components/Button/styles.ts +129 -0
- package/src/components/Calendar/index.tsx +65 -0
- package/src/components/Calendar/style.ts +35 -0
- package/src/components/Calendar/types.ts +102 -0
- package/src/components/Checkbox/index.tsx +91 -0
- package/src/components/Checkbox/styles.ts +81 -0
- package/src/components/ContentView/index.tsx +63 -0
- package/src/components/ContentView/styles.ts +24 -0
- package/src/components/Drawer/index.tsx +33 -0
- package/src/components/Drawer/styles.ts +43 -0
- package/src/components/EmptyPlaceholder/index.tsx +88 -0
- package/src/components/EmptyPlaceholder/styles.ts +58 -0
- package/src/components/FileInput/index.tsx +181 -0
- package/src/components/FileInput/styles.ts +15 -0
- package/src/components/Grid/index.tsx +117 -0
- package/src/components/Grid/styles.ts +11 -0
- package/src/components/Icon/index.tsx +69 -0
- package/src/components/Icon/styles.ts +57 -0
- package/src/components/Image/index.tsx +91 -0
- package/src/components/Image/styles.ts +20 -0
- package/src/components/ImageView/Spotlight.tsx +157 -0
- package/src/components/ImageView/component.tsx +38 -0
- package/src/components/ImageView/index.ts +2 -0
- package/src/components/InputLabel/index.tsx +38 -0
- package/src/components/InputLabel/styles.ts +19 -0
- package/src/components/List/PaginationIndicator.tsx +71 -0
- package/src/components/List/index.tsx +114 -0
- package/src/components/List/styles.ts +19 -0
- package/src/components/Modal/index.tsx +218 -0
- package/src/components/Modal/styles.ts +153 -0
- package/src/components/MultiSelect/index.tsx +138 -0
- package/src/components/MultiSelect/styles.ts +18 -0
- package/src/components/MultiSelect/types.ts +42 -0
- package/src/components/Navigation/Navigation.tsx +54 -0
- package/src/components/Navigation/constants.ts +8 -0
- package/src/components/Navigation/index.tsx +3 -0
- package/src/components/Navigation/types.ts +35 -0
- package/src/components/Navigation/utils.tsx +57 -0
- package/src/components/Pager/index.tsx +121 -0
- package/src/components/Pager/styles.ts +81 -0
- package/src/components/RadioInput/index.tsx +106 -0
- package/src/components/RadioInput/styles.ts +67 -0
- package/src/components/Scroll/index.tsx +124 -0
- package/src/components/Scroll/styles.ts +18 -0
- package/src/components/Sections/index.tsx +91 -0
- package/src/components/SegmentedControl/index.tsx +204 -0
- package/src/components/SegmentedControl/styles.ts +89 -0
- package/src/components/Select/index.tsx +167 -0
- package/src/components/Select/styles.ts +62 -0
- package/src/components/Select/types.ts +43 -0
- package/src/components/Slider/Mark.tsx +46 -0
- package/src/components/Slider/Thumb.tsx +29 -0
- package/src/components/Slider/index.tsx +130 -0
- package/src/components/Slider/styles.ts +76 -0
- package/src/components/Slider/types.ts +30 -0
- package/src/components/Switch/index.tsx +91 -0
- package/src/components/Switch/styles.ts +38 -0
- package/src/components/Text/index.tsx +97 -0
- package/src/components/Text/styles.ts +50 -0
- package/src/components/TextInput/index.tsx +319 -0
- package/src/components/TextInput/styles.ts +127 -0
- package/src/components/Touchable/index.tsx +172 -0
- package/src/components/Touchable/styles.ts +28 -0
- package/src/components/View/index.tsx +103 -0
- package/src/components/View/styles.ts +24 -0
- package/src/components/components.ts +42 -0
- package/src/components/defaultStyles.ts +62 -0
- package/src/components/legacy/Modal/index.tsx +163 -0
- package/src/components/legacy/Modal/styles.ts +125 -0
- package/src/components/legacy/Pager/index.tsx +242 -0
- package/src/components/legacy/Pager/styles.ts +51 -0
- package/src/components/legacy/index.ts +2 -0
- package/src/modules/documentPicker.ts +7 -0
- package/src/modules/fastImage.ts +2 -0
- package/src/modules/imageCropPicker.d.ts +497 -0
- package/src/modules/index.d.ts +682 -0
- package/src/modules/reactNavigation.ts +15 -0
- package/src/modules/textInputMask.ts +11 -0
- package/src/modules/types/documentPicker.d.ts +215 -0
- package/src/modules/types/fileTypes.ts +138 -0
- package/src/modules/types/textInputMask.ts +9 -0
- package/src/types/index.ts +1 -0
- package/src/types/utility.ts +9 -0
- package/src/utils/KeyboardAware/context.tsx +75 -0
- package/src/utils/KeyboardAware/index.ts +17 -0
- package/src/utils/KeyboardAware/keyboardHooks.ts +124 -0
- package/src/utils/KeyboardAware/lib/KeyboardAwareFlatList.ts +4 -0
- package/src/utils/KeyboardAware/lib/KeyboardAwareHOC.tsx +618 -0
- package/src/utils/KeyboardAware/lib/KeyboardAwareInterface.ts +13 -0
- package/src/utils/KeyboardAware/lib/KeyboardAwareScrollView.ts +6 -0
- package/src/utils/KeyboardAware/lib/KeyboardAwareSectionList.ts +6 -0
- package/src/utils/KeyboardAware/types.ts +159 -0
- package/src/utils/ModalManager/components.tsx +112 -0
- package/src/utils/ModalManager/context.tsx +260 -0
- package/src/utils/ModalManager/index.ts +16 -0
- package/src/utils/OSAlert.ts +180 -0
- package/src/utils/PermissionManager/context.tsx +302 -0
- package/src/utils/PermissionManager/index.ts +20 -0
- package/src/utils/PermissionManager/types.ts +24 -0
- package/src/utils/hooks.ts +163 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/input.ts +51 -0
- package/src/utils/misc.ts +83 -0
- package/src/utils/notifications.ts +206 -0
- package/src/utils/theme.ts +58 -0
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React, { useContext, useState } from 'react'
|
|
2
|
+
import { deepEqual, onUpdate, ReactState, TypeGuards, usePrevious, useUnmount } from '@codeleap/common'
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import { ImageSource } from 'react-native-image-viewing/dist/@types'
|
|
5
|
+
import uuid from 'react-native-uuid'
|
|
6
|
+
import { ImageView } from './component'
|
|
7
|
+
import { ImageProps } from '../Image'
|
|
8
|
+
type TImage = {
|
|
9
|
+
source: ImageSource
|
|
10
|
+
created: number
|
|
11
|
+
id: string
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
type ImageList = Record<string, TImage>
|
|
15
|
+
|
|
16
|
+
type SpotlightState = ReactState<Record<string, ImageList>>
|
|
17
|
+
type IndexState = ReactState<Record<string, number>>
|
|
18
|
+
type TSpotlightCtx = {
|
|
19
|
+
spotlights: SpotlightState[0]
|
|
20
|
+
setSpotlights: SpotlightState[1]
|
|
21
|
+
indexes: IndexState[0]
|
|
22
|
+
setIndexes: IndexState[1]
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const SpotlightCtx = React.createContext({} as TSpotlightCtx)
|
|
27
|
+
|
|
28
|
+
export const SpotlightProvider:React.FC = ({ children }) => {
|
|
29
|
+
const [spotlights, setSpotlights] = useState<TSpotlightCtx['spotlights']>({})
|
|
30
|
+
const [indexes, setIndexes] = useState<TSpotlightCtx['indexes']>({})
|
|
31
|
+
const ctxValue:TSpotlightCtx = {
|
|
32
|
+
spotlights,
|
|
33
|
+
setSpotlights,
|
|
34
|
+
indexes,
|
|
35
|
+
setIndexes,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return <SpotlightCtx.Provider value={ctxValue}>
|
|
39
|
+
{children}
|
|
40
|
+
</SpotlightCtx.Provider>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function useSpotlight(name: string) {
|
|
44
|
+
const ctx = useContext(SpotlightCtx)
|
|
45
|
+
|
|
46
|
+
const imList =
|
|
47
|
+
Object.values(ctx.spotlights[name] || {})
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
images: imList,
|
|
51
|
+
currentIndex: ctx.indexes[name],
|
|
52
|
+
set(img: ImageSource, id?: string) {
|
|
53
|
+
const newId = id || uuid.v4() as string
|
|
54
|
+
ctx.setSpotlights((prev) => {
|
|
55
|
+
const images = { ...prev[name] }
|
|
56
|
+
|
|
57
|
+
if (id !== null) {
|
|
58
|
+
images[id] = {
|
|
59
|
+
...images[id],
|
|
60
|
+
source: img,
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
const now = Date.now()
|
|
64
|
+
|
|
65
|
+
images[newId] = {
|
|
66
|
+
created: now,
|
|
67
|
+
id: newId,
|
|
68
|
+
source: img,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
...prev,
|
|
74
|
+
[name]: images,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return newId
|
|
79
|
+
},
|
|
80
|
+
remove(id: string) {
|
|
81
|
+
ctx.setSpotlights((prev) => {
|
|
82
|
+
const images = { ...prev[name] }
|
|
83
|
+
delete images[id]
|
|
84
|
+
return {
|
|
85
|
+
...prev,
|
|
86
|
+
[name]: images,
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
},
|
|
90
|
+
open(id: string) {
|
|
91
|
+
const newIdx = imList.findIndex(x => x.id === id)
|
|
92
|
+
ctx.setIndexes((prev) => ({
|
|
93
|
+
...prev,
|
|
94
|
+
[name]: newIdx,
|
|
95
|
+
}))
|
|
96
|
+
},
|
|
97
|
+
close() {
|
|
98
|
+
|
|
99
|
+
ctx.setIndexes((prev) => ({
|
|
100
|
+
...prev,
|
|
101
|
+
[name]: undefined,
|
|
102
|
+
}))
|
|
103
|
+
},
|
|
104
|
+
clear() {
|
|
105
|
+
ctx.setIndexes((prev) => ({
|
|
106
|
+
...prev,
|
|
107
|
+
[name]: undefined,
|
|
108
|
+
}))
|
|
109
|
+
ctx.setSpotlights((prev) => {
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
...prev,
|
|
113
|
+
[name]: {},
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const useImageSpotlight = (name: string | null, src: ImageProps['source']) => {
|
|
121
|
+
const [id, setId] = useState(null)
|
|
122
|
+
const spotlight = useSpotlight(name)
|
|
123
|
+
const imSource = TypeGuards.isString(src) ? { uri: src } : src as TImage['source']
|
|
124
|
+
const prevSource = usePrevious(imSource)
|
|
125
|
+
|
|
126
|
+
onUpdate(() => {
|
|
127
|
+
if (!name) return
|
|
128
|
+
if (deepEqual(prevSource, imSource)) return
|
|
129
|
+
setId(spotlight.set(imSource, id))
|
|
130
|
+
}, [src, id])
|
|
131
|
+
|
|
132
|
+
useUnmount(() => {
|
|
133
|
+
if (!name) return
|
|
134
|
+
spotlight.remove(id)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
onImagePressed: () => {
|
|
139
|
+
spotlight.open(id)
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const Spotlight = ({ name }) => {
|
|
145
|
+
const spotlight = useSpotlight(name)
|
|
146
|
+
useUnmount(() => {
|
|
147
|
+
spotlight.clear()
|
|
148
|
+
})
|
|
149
|
+
return <ImageView
|
|
150
|
+
imageIndex={spotlight.currentIndex}
|
|
151
|
+
images={spotlight.images.map(x => x.source)}
|
|
152
|
+
keyExtractor={(_, index) => index.toString()}
|
|
153
|
+
onRequestClose={spotlight.close}
|
|
154
|
+
visible={typeof spotlight.currentIndex !== 'undefined'}
|
|
155
|
+
|
|
156
|
+
/>
|
|
157
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import { onUpdate, PropsOf } from '@codeleap/common'
|
|
4
|
+
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
import _ImageView from 'react-native-image-viewing'
|
|
7
|
+
import { StatusBar } from 'react-native'
|
|
8
|
+
import { View } from '../View'
|
|
9
|
+
import { Text } from '../Text'
|
|
10
|
+
|
|
11
|
+
type FooterComponentType = React.ComponentType<{
|
|
12
|
+
imageIndex: number
|
|
13
|
+
imagesLength: number
|
|
14
|
+
}>
|
|
15
|
+
|
|
16
|
+
const FooterComponent: FooterComponentType = ({ imageIndex, imagesLength }) => (
|
|
17
|
+
<View variants={['marginBottom:5', 'alignCenter']}>
|
|
18
|
+
<Text text={imageIndex + 1 + '/' + imagesLength}/>
|
|
19
|
+
</View>
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
export type ImageViewProps = PropsOf<typeof _ImageView>
|
|
23
|
+
|
|
24
|
+
export const ImageView: React.FC<ImageViewProps> = (props) => {
|
|
25
|
+
onUpdate(() => {
|
|
26
|
+
StatusBar.setHidden(props.visible)
|
|
27
|
+
// StatusBar.setBarStyle(`${props.visible ? 'light' : 'dark'}-content`)
|
|
28
|
+
}, [props.visible])
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<_ImageView
|
|
32
|
+
doubleTapToZoomEnabled={false}
|
|
33
|
+
FooterComponent={({ imageIndex }) => <FooterComponent imageIndex={imageIndex} imagesLength={props.images.length}/>}
|
|
34
|
+
presentationStyle={'overFullScreen'}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { ComponentVariants, FormTypes, useDefaultComponentStyle } from '@codeleap/common'
|
|
3
|
+
import { StylesOf } from '../../types'
|
|
4
|
+
import { View, ViewProps } from '../View'
|
|
5
|
+
import { InputLabelComposition, InputLabelStyles } from './styles'
|
|
6
|
+
import { Text } from '../Text'
|
|
7
|
+
import { StyleSheet } from 'react-native'
|
|
8
|
+
|
|
9
|
+
export type InputLabelProps = ViewProps & {
|
|
10
|
+
styles?: StylesOf<InputLabelComposition>
|
|
11
|
+
label?: FormTypes.Label
|
|
12
|
+
required?: boolean
|
|
13
|
+
} & ComponentVariants<typeof InputLabelStyles>
|
|
14
|
+
|
|
15
|
+
export * from './styles'
|
|
16
|
+
|
|
17
|
+
export const InputLabel:React.FC<InputLabelProps> = (props) => {
|
|
18
|
+
const { label, required = false, variants = [], styles = {}, style, ...viewProps } = props
|
|
19
|
+
const variantStyles = useDefaultComponentStyle<'u:InputLabel', typeof InputLabelStyles>('u:InputLabel', {
|
|
20
|
+
variants, styles, transform: StyleSheet.flatten,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
if (!label) return null
|
|
24
|
+
|
|
25
|
+
switch (typeof label) {
|
|
26
|
+
case 'string':
|
|
27
|
+
return <View {...viewProps} style={[variantStyles.wrapper, style]}>
|
|
28
|
+
<Text style={variantStyles.text} text={label} />
|
|
29
|
+
{required && <Text style={variantStyles.asterisk} text={' *'} />}
|
|
30
|
+
</View>
|
|
31
|
+
case 'object':
|
|
32
|
+
return <>
|
|
33
|
+
{label as React.ReactNode}
|
|
34
|
+
</>
|
|
35
|
+
default:
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { assignTextStyle, createDefaultVariantFactory } from '@codeleap/common'
|
|
2
|
+
|
|
3
|
+
export type InputLabelComposition = 'text' | 'wrapper' | 'asterisk'
|
|
4
|
+
|
|
5
|
+
const createInputLabelStyle = createDefaultVariantFactory<InputLabelComposition>()
|
|
6
|
+
|
|
7
|
+
export const InputLabelStyles = {
|
|
8
|
+
default: createInputLabelStyle((theme) => ({
|
|
9
|
+
asterisk: {
|
|
10
|
+
color: theme.colors.negative,
|
|
11
|
+
},
|
|
12
|
+
wrapper: {
|
|
13
|
+
...theme.presets.row,
|
|
14
|
+
},
|
|
15
|
+
text: {
|
|
16
|
+
...assignTextStyle('h5')(theme).text,
|
|
17
|
+
},
|
|
18
|
+
})),
|
|
19
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {
|
|
3
|
+
assignTextStyle,
|
|
4
|
+
ComponentVariants,
|
|
5
|
+
createDefaultVariantFactory,
|
|
6
|
+
getNestedStylesByKey,
|
|
7
|
+
includePresets,
|
|
8
|
+
TypeGuards,
|
|
9
|
+
useDefaultComponentStyle,
|
|
10
|
+
} from '@codeleap/common'
|
|
11
|
+
import { StyleSheet, ViewStyle } from 'react-native'
|
|
12
|
+
import { StylesOf } from '../../types'
|
|
13
|
+
import { ActivityIndicator, ActivityIndicatorComposition } from '../ActivityIndicator'
|
|
14
|
+
import { Text } from '../Text'
|
|
15
|
+
|
|
16
|
+
export type PaginationIndicatorComposition = 'text' | `loader${Capitalize<ActivityIndicatorComposition>}`
|
|
17
|
+
|
|
18
|
+
const createPaginationIndicatorStyle = createDefaultVariantFactory<PaginationIndicatorComposition>()
|
|
19
|
+
const presets = includePresets((style) => createPaginationIndicatorStyle(() => ({ loaderWrapper: style, text: style })))
|
|
20
|
+
export const PaginationIndicatorStyles = {
|
|
21
|
+
...presets,
|
|
22
|
+
default: createPaginationIndicatorStyle((theme) => {
|
|
23
|
+
return {
|
|
24
|
+
loaderWrapper: {
|
|
25
|
+
...theme.presets.center,
|
|
26
|
+
...theme.spacing.marginVertical(3),
|
|
27
|
+
},
|
|
28
|
+
text: {
|
|
29
|
+
...assignTextStyle('h4')(theme).text,
|
|
30
|
+
...theme.presets.textCenter,
|
|
31
|
+
...theme.spacing.marginVertical(3),
|
|
32
|
+
...theme.presets.fullWidth,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type PaginationIndicatorProps = {
|
|
39
|
+
isFetching?: boolean
|
|
40
|
+
noMoreItemsText: React.ReactChild
|
|
41
|
+
hasMore?: boolean
|
|
42
|
+
activityIndicator?: JSX.Element
|
|
43
|
+
styles?: StylesOf<PaginationIndicatorComposition>
|
|
44
|
+
style?: ViewStyle
|
|
45
|
+
} & ComponentVariants<typeof PaginationIndicatorStyles>
|
|
46
|
+
|
|
47
|
+
export const PaginationIndicator = (props: PaginationIndicatorProps) => {
|
|
48
|
+
const { hasMore, isFetching, noMoreItemsText, style, activityIndicator, styles = {}, variants = [] } = props
|
|
49
|
+
|
|
50
|
+
const variantStyles = useDefaultComponentStyle<
|
|
51
|
+
'u:PaginationIndicator',
|
|
52
|
+
typeof PaginationIndicatorStyles
|
|
53
|
+
>('u:PaginationIndicator', {
|
|
54
|
+
variants,
|
|
55
|
+
styles,
|
|
56
|
+
transform: StyleSheet.flatten,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const loaderStyles = getNestedStylesByKey('loader', variantStyles)
|
|
60
|
+
|
|
61
|
+
if (isFetching) {
|
|
62
|
+
return activityIndicator || <ActivityIndicator style={style} styles={loaderStyles}/>
|
|
63
|
+
}
|
|
64
|
+
if (!hasMore) {
|
|
65
|
+
if (TypeGuards.isString(noMoreItemsText) || TypeGuards.isNumber(noMoreItemsText)) {
|
|
66
|
+
return <Text style={[variantStyles.text, style]} text={noMoreItemsText.toString()}/>
|
|
67
|
+
}
|
|
68
|
+
return noMoreItemsText
|
|
69
|
+
}
|
|
70
|
+
return null
|
|
71
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { forwardRef } from 'react'
|
|
3
|
+
import {
|
|
4
|
+
|
|
5
|
+
useDefaultComponentStyle,
|
|
6
|
+
|
|
7
|
+
ComponentVariants,
|
|
8
|
+
useCallback,
|
|
9
|
+
} from '@codeleap/common'
|
|
10
|
+
|
|
11
|
+
import { RefreshControl, FlatList, FlatListProps as RNFlatListProps, ListRenderItemInfo, StyleSheet, RefreshControlProps } from 'react-native'
|
|
12
|
+
import { View, ViewProps } from '../View'
|
|
13
|
+
import { EmptyPlaceholder, EmptyPlaceholderProps } from '../EmptyPlaceholder'
|
|
14
|
+
import { ListComposition, ListStyles } from './styles'
|
|
15
|
+
import { StylesOf } from '../../types'
|
|
16
|
+
import { GetKeyboardAwarePropsOptions, useKeyboardAwareView } from '../../utils'
|
|
17
|
+
|
|
18
|
+
export type DataboundFlatListPropsTypes = 'data' | 'renderItem' | 'keyExtractor' | 'getItemLayout'
|
|
19
|
+
|
|
20
|
+
export type ReplaceFlatlistProps<P, T> = Omit<P, DataboundFlatListPropsTypes> & {
|
|
21
|
+
data: T[]
|
|
22
|
+
keyExtractor?: (item: T, index: number) => string
|
|
23
|
+
renderItem: (data: ListRenderItemInfo<T>) => React.ReactElement
|
|
24
|
+
onRefresh?: () => void
|
|
25
|
+
getItemLayout?: ((
|
|
26
|
+
data:T,
|
|
27
|
+
index: number,
|
|
28
|
+
) => { length: number; offset: number; index: number })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export * from './styles'
|
|
32
|
+
export * from './PaginationIndicator'
|
|
33
|
+
|
|
34
|
+
export type FlatListProps<
|
|
35
|
+
T = any[],
|
|
36
|
+
Data = T extends Array<infer D> ? D : never
|
|
37
|
+
> =RNFlatListProps<Data> &
|
|
38
|
+
Omit<ViewProps, 'variants'> & {
|
|
39
|
+
separators?: boolean
|
|
40
|
+
placeholder?: EmptyPlaceholderProps
|
|
41
|
+
keyboardAware?: GetKeyboardAwarePropsOptions
|
|
42
|
+
styles?: StylesOf<ListComposition>
|
|
43
|
+
refreshControlProps?: Partial<RefreshControlProps>
|
|
44
|
+
} & ComponentVariants<typeof ListStyles>
|
|
45
|
+
|
|
46
|
+
const ListCP = forwardRef<FlatList, FlatListProps>(
|
|
47
|
+
(flatListProps, ref) => {
|
|
48
|
+
const {
|
|
49
|
+
variants = [],
|
|
50
|
+
style,
|
|
51
|
+
styles = {},
|
|
52
|
+
onRefresh,
|
|
53
|
+
component,
|
|
54
|
+
refreshing,
|
|
55
|
+
placeholder,
|
|
56
|
+
keyboardAware,
|
|
57
|
+
refreshControlProps = {},
|
|
58
|
+
...props
|
|
59
|
+
} = flatListProps
|
|
60
|
+
|
|
61
|
+
const variantStyles = useDefaultComponentStyle<'u:List', typeof ListStyles>('u:List', {
|
|
62
|
+
variants,
|
|
63
|
+
styles,
|
|
64
|
+
transform: StyleSheet.flatten,
|
|
65
|
+
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const renderSeparator = useCallback(() => {
|
|
69
|
+
return (
|
|
70
|
+
<View style={variantStyles.separator}></View>
|
|
71
|
+
)
|
|
72
|
+
}, [])
|
|
73
|
+
|
|
74
|
+
const isEmpty = !props.data || !props.data.length
|
|
75
|
+
const separator = !isEmpty && props?.separators && renderSeparator
|
|
76
|
+
|
|
77
|
+
const Component:any = component || FlatList
|
|
78
|
+
const refreshStyles = StyleSheet.flatten([variantStyles.refreshControl, styles.refreshControl])
|
|
79
|
+
|
|
80
|
+
const _listProps = {
|
|
81
|
+
style: [variantStyles.wrapper, style],
|
|
82
|
+
contentContainerStyle: variantStyles.content,
|
|
83
|
+
ref: ref as unknown as FlatList,
|
|
84
|
+
ItemSeparatorComponent: separator,
|
|
85
|
+
refreshControl: !!onRefresh && (
|
|
86
|
+
<RefreshControl
|
|
87
|
+
refreshing={refreshing}
|
|
88
|
+
onRefresh={onRefresh}
|
|
89
|
+
tintColor={refreshStyles?.color}
|
|
90
|
+
colors={[refreshStyles?.color]}
|
|
91
|
+
{...refreshControlProps}
|
|
92
|
+
/>
|
|
93
|
+
),
|
|
94
|
+
ListEmptyComponent: <EmptyPlaceholder {...placeholder}/>,
|
|
95
|
+
...props,
|
|
96
|
+
}
|
|
97
|
+
const keyboard = useKeyboardAwareView()
|
|
98
|
+
const listProps = keyboard.getKeyboardAwareProps(_listProps, {
|
|
99
|
+
adapt: 'paddingBottom',
|
|
100
|
+
baseStyleProp: 'contentContainerStyle',
|
|
101
|
+
...keyboardAware,
|
|
102
|
+
})
|
|
103
|
+
return (
|
|
104
|
+
<Component
|
|
105
|
+
{...listProps}
|
|
106
|
+
/>
|
|
107
|
+
)
|
|
108
|
+
},
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
export type ListComponentType = <T extends any[] = any[]>(props: FlatListProps<T>) => React.ReactElement
|
|
112
|
+
|
|
113
|
+
export const List = ListCP as ListComponentType
|
|
114
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createDefaultVariantFactory } from '@codeleap/common'
|
|
2
|
+
import { ScrollComposition, ScrollStyles } from '../Scroll/styles'
|
|
3
|
+
|
|
4
|
+
export type ListComposition = ScrollComposition | 'separator'
|
|
5
|
+
|
|
6
|
+
const createListStyle = createDefaultVariantFactory<ListComposition>()
|
|
7
|
+
|
|
8
|
+
export const ListStyles = {
|
|
9
|
+
default: createListStyle((theme) => {
|
|
10
|
+
const defaultStyles = ScrollStyles.default(theme)
|
|
11
|
+
return {
|
|
12
|
+
...defaultStyles,
|
|
13
|
+
separator: {
|
|
14
|
+
width: '100%',
|
|
15
|
+
height: theme.spacing.value(1),
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
}),
|
|
19
|
+
}
|