@codeleap/mobile 1.0.1 → 1.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/Animated.d.ts +103 -0
- package/dist/components/{Checkbox.js → Animated.js} +22 -28
- package/dist/components/Animated.js.map +1 -0
- package/dist/components/Button.d.ts +2 -8
- package/dist/components/Button.js +2 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/ContentView.d.ts +10 -0
- package/dist/components/ContentView.js +49 -0
- package/dist/components/ContentView.js.map +1 -0
- package/dist/components/FileInput.d.ts +19 -2
- package/dist/components/FileInput.js +89 -4
- package/dist/components/FileInput.js.map +1 -1
- package/dist/components/Image.d.ts +2 -2
- package/dist/components/Image.js.map +1 -1
- package/dist/components/Modal/index.d.ts +24 -0
- package/dist/components/Modal/index.js +116 -0
- package/dist/components/Modal/index.js.map +1 -0
- package/dist/components/Modal/styles.d.ts +62 -0
- package/dist/components/Modal/styles.js +62 -0
- package/dist/components/Modal/styles.js.map +1 -0
- package/dist/components/Overlay.d.ts +16 -0
- package/dist/components/Overlay.js +68 -0
- package/dist/components/Overlay.js.map +1 -0
- package/dist/components/Scroll.d.ts +1 -95
- package/dist/components/TextInput.js +1 -1
- package/dist/components/TextInput.js.map +1 -1
- package/dist/components/Touchable.d.ts +8 -14
- package/dist/components/Touchable.js +10 -12
- package/dist/components/Touchable.js.map +1 -1
- package/dist/components/View.d.ts +12 -10
- package/dist/components/View.js +2 -4
- package/dist/components/View.js.map +1 -1
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.js +5 -0
- package/dist/components/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/cropPicker.d.ts +1 -0
- package/dist/modules/cropPicker.js +10 -0
- package/dist/modules/cropPicker.js.map +1 -0
- package/dist/modules/documentPicker.d.ts +1 -0
- package/dist/modules/documentPicker.js +10 -0
- package/dist/modules/documentPicker.js.map +1 -0
- package/package.json +4 -2
- package/src/components/Animated.tsx +31 -0
- package/src/components/Button.tsx +2 -1
- package/src/components/ContentView.tsx +52 -0
- package/src/components/FileInput.tsx +67 -4
- package/src/components/Image.tsx +3 -3
- package/src/components/Modal/index.tsx +143 -0
- package/src/components/Modal/styles.ts +122 -0
- package/src/components/Overlay.tsx +72 -0
- package/src/components/TextInput.tsx +1 -1
- package/src/components/Touchable.tsx +20 -23
- package/src/components/View.tsx +5 -15
- package/src/components/index.ts +7 -0
- package/src/index.ts +2 -1
- package/src/modules/documentPicker.ts +2 -0
- package/dist/components/Checkbox.d.ts +0 -12
- package/dist/components/Checkbox.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -13,8 +13,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.OSAlert = void 0;
|
|
16
|
+
exports.posed = exports.OSAlert = void 0;
|
|
17
17
|
__exportStar(require("./components"), exports);
|
|
18
18
|
var OSAlert_1 = require("./utils/OSAlert");
|
|
19
19
|
Object.defineProperty(exports, "OSAlert", { enumerable: true, get: function () { return __importDefault(OSAlert_1).default; } });
|
|
20
|
+
var react_native_pose_1 = require("react-native-pose");
|
|
21
|
+
Object.defineProperty(exports, "posed", { enumerable: true, get: function () { return __importDefault(react_native_pose_1).default; } });
|
|
20
22
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA4B;AAC5B,2CAAmD;AAA3C,mHAAA,OAAO,OAAW"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA4B;AAC5B,2CAAmD;AAA3C,mHAAA,OAAO,OAAW;AAC1B,uDAAkD;AAA1C,2HAAA,OAAO,OAAS"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as ImagePicker } from 'react-native-image-crop-picker';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ImagePicker = void 0;
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
var react_native_image_crop_picker_1 = require("react-native-image-crop-picker");
|
|
9
|
+
Object.defineProperty(exports, "ImagePicker", { enumerable: true, get: function () { return __importDefault(react_native_image_crop_picker_1).default; } });
|
|
10
|
+
//# sourceMappingURL=cropPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cropPicker.js","sourceRoot":"","sources":["../../src/modules/cropPicker.ts"],"names":[],"mappings":";;;;;;AAAA,aAAa;AACb,iFAAqE;AAA7D,8IAAA,OAAO,OAAe"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DocumentPicker } from 'react-native-document-picker';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DocumentPicker = void 0;
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
var react_native_document_picker_1 = require("react-native-document-picker");
|
|
9
|
+
Object.defineProperty(exports, "DocumentPicker", { enumerable: true, get: function () { return __importDefault(react_native_document_picker_1).default; } });
|
|
10
|
+
//# sourceMappingURL=documentPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentPicker.js","sourceRoot":"","sources":["../../src/modules/documentPicker.ts"],"names":[],"mappings":";;;;;;AAAA,cAAc;AACd,6EAAsE;AAA9D,+IAAA,OAAO,OAAkB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeleap/mobile",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"repository": "git@github.com:codeleap-uk/codeleap-lib.git",
|
|
6
6
|
"author": "Paulo Henrique De Souza <paulosouza300272@gmail.com>",
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@miblanchard/react-native-slider": "^2.1.0",
|
|
31
|
-
"react-native-
|
|
31
|
+
"react-native-animatable": "^1.3.3",
|
|
32
|
+
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
|
33
|
+
"react-native-pose": "^0.9.1"
|
|
32
34
|
}
|
|
33
35
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { onUpdate } from '@codeleap/common'
|
|
2
|
+
import React, { useRef } from 'react'
|
|
3
|
+
|
|
4
|
+
import posed from 'react-native-pose'
|
|
5
|
+
import {Touchable} from './Touchable'
|
|
6
|
+
import {View} from './View'
|
|
7
|
+
const Components = {
|
|
8
|
+
Touchable,
|
|
9
|
+
View
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const PosedComponents = Object.fromEntries(Object.entries(Components).map(([key,Render]) => [key, posed(Render)]))
|
|
14
|
+
|
|
15
|
+
type AnimatedComponents = typeof Components
|
|
16
|
+
type CP = keyof AnimatedComponents
|
|
17
|
+
|
|
18
|
+
type AnimatedProps<T extends CP, CFG = Record<string,any>> = {
|
|
19
|
+
component: T
|
|
20
|
+
config: CFG
|
|
21
|
+
pose: keyof CFG
|
|
22
|
+
initialPose?: keyof CFG
|
|
23
|
+
} & Omit<Parameters<AnimatedComponents[T]>[0],'component'>
|
|
24
|
+
|
|
25
|
+
export const Animated = <T extends CP, CFG = any>({config,component, ...props}:AnimatedProps<T, CFG>) => {
|
|
26
|
+
|
|
27
|
+
const Component = useRef(PosedComponents[component](config)).current
|
|
28
|
+
|
|
29
|
+
return <Component {...props} />
|
|
30
|
+
}
|
|
31
|
+
|
|
@@ -54,7 +54,8 @@ export const Button = forwardRef<TouchableOpacity, ButtonProps>( (buttonProps,re
|
|
|
54
54
|
>
|
|
55
55
|
{loading && <ActivityIndicator style={[variantStyles.loader, styles.loader]} />}
|
|
56
56
|
{!loading && <Icon name={icon} style={StyleSheet.flatten([variantStyles.icon, styles.icon, variantStyles.leftIcon, styles.leftIcon])}/>}
|
|
57
|
-
{
|
|
57
|
+
{text ? <Text text={text} style={[variantStyles.text, styles.text]}/> : null}
|
|
58
|
+
{children}
|
|
58
59
|
<Icon name={rightIcon} style={StyleSheet.flatten([variantStyles.icon, styles.icon, variantStyles.rightIcon, styles.rightIcon])}/>
|
|
59
60
|
</Touchable>
|
|
60
61
|
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { ComponentVariants, ContentViewStyles, useComponentStyle, ViewComposition } from '@codeleap/common'
|
|
3
|
+
import { ViewProps, View } from './View'
|
|
4
|
+
import { Text } from './Text'
|
|
5
|
+
import { StylesOf } from '../types/utility'
|
|
6
|
+
import { ActivityIndicator } from './ActivityIndicator'
|
|
7
|
+
|
|
8
|
+
export type ContentViewProps = Omit<ViewProps, 'variants' | 'responsiveVariants'> & {
|
|
9
|
+
placeholderMsg: string
|
|
10
|
+
loading?: boolean
|
|
11
|
+
styles?: StylesOf<ViewComposition>
|
|
12
|
+
} & ComponentVariants<typeof ContentViewStyles>
|
|
13
|
+
|
|
14
|
+
const WrapContent = ({ children, ...props }) => <View {...props}>{children}</View>
|
|
15
|
+
|
|
16
|
+
export const ContentView: React.FC<ContentViewProps> = (rawProps) => {
|
|
17
|
+
const {
|
|
18
|
+
children,
|
|
19
|
+
placeholderMsg,
|
|
20
|
+
loading,
|
|
21
|
+
variants,
|
|
22
|
+
styles,
|
|
23
|
+
...props
|
|
24
|
+
} = rawProps
|
|
25
|
+
|
|
26
|
+
const variantStyle = useComponentStyle('ContentView', {
|
|
27
|
+
variants,
|
|
28
|
+
styles,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
if (loading) {
|
|
32
|
+
return (
|
|
33
|
+
<WrapContent {...props} style={variantStyle.wrapper}>
|
|
34
|
+
<ActivityIndicator styles={{wrapper: variantStyle.loader}}/>
|
|
35
|
+
</WrapContent>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
const hasChildren = Object.keys(children || {}).length > 0
|
|
39
|
+
if (hasChildren) {
|
|
40
|
+
return (
|
|
41
|
+
<WrapContent {...props} style={variantStyle.wrapper}>
|
|
42
|
+
{children}
|
|
43
|
+
</WrapContent>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<WrapContent {...props} style={styles}>
|
|
49
|
+
<Text text={placeholderMsg} />
|
|
50
|
+
</WrapContent>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -1,6 +1,69 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import React, { forwardRef, useImperativeHandle, useRef } from 'react'
|
|
2
|
+
import { DocumentPicker } from '../modules/documentPicker'
|
|
3
|
+
import { ComponentVariants, FileInputComposition, FileInputStyles, IconPlaceholder, MobileInputFile, useComponentStyle, useStyle} from '@codeleap/common'
|
|
4
|
+
import { StylesOf } from '../types/utility'
|
|
5
|
+
import { Button, ButtonProps } from './Button'
|
|
6
|
+
import { View } from './View'
|
|
7
|
+
import { InputLabel } from './TextInput'
|
|
3
8
|
|
|
4
|
-
export
|
|
5
|
-
|
|
9
|
+
export type FileInputRef = {
|
|
10
|
+
openFilePicker: () => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type FileInputProps = {
|
|
14
|
+
label?: string;
|
|
15
|
+
iconName?: IconPlaceholder
|
|
16
|
+
styles?: StylesOf<FileInputComposition>;
|
|
17
|
+
mode: 'hidden' | 'button'
|
|
18
|
+
variants?: ComponentVariants<typeof FileInputStyles>['variants']
|
|
19
|
+
onFileSelect(files:MobileInputFile[]): void
|
|
20
|
+
options?: DocumentPicker.DocumentPickerOptions
|
|
21
|
+
buttonProps?: ButtonProps
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const FileInput: React.FC<FileInputProps> = forwardRef<FileInputRef, FileInputProps>((fileInputProps,ref) => {
|
|
25
|
+
const {mode = 'hidden', onFileSelect, iconName, styles, label, variants, options, buttonProps} = fileInputProps
|
|
26
|
+
|
|
27
|
+
const [file, setFile] = React.useState(null)
|
|
28
|
+
|
|
29
|
+
const {logger} = useStyle()
|
|
30
|
+
|
|
31
|
+
const openFilePicker = async () => {
|
|
32
|
+
try {
|
|
33
|
+
let files = await DocumentPicker.pick(options)
|
|
34
|
+
if(!Array.isArray(files)){
|
|
35
|
+
files = [files]
|
|
36
|
+
}
|
|
37
|
+
setFile(files)
|
|
38
|
+
onFileSelect(files.map((file) => ({preview: file, file})))
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (DocumentPicker.isCancel(err)) {
|
|
41
|
+
logger.log('User cancelled the picker.', null, 'Component')
|
|
42
|
+
} else {
|
|
43
|
+
throw err
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const variantStyles = useComponentStyle('FileInput', {
|
|
49
|
+
styles,
|
|
50
|
+
variants,
|
|
51
|
+
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
useImperativeHandle(ref, () => ({
|
|
56
|
+
openFilePicker
|
|
57
|
+
}))
|
|
58
|
+
|
|
59
|
+
const filenames = file ? file.map((f) => f.name) : ''
|
|
60
|
+
if(mode === 'button'){
|
|
61
|
+
return (<View style={variantStyles.wrapper}>
|
|
62
|
+
<InputLabel label={label} style={variantStyles.label}/>
|
|
63
|
+
<Button onPress={() => openFilePicker()} text={filenames } icon={ iconName || 'fileInputButton' as IconPlaceholder} variants={filenames ? '' : 'icon' } {...buttonProps}/>
|
|
64
|
+
</View>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null
|
|
6
69
|
})
|
package/src/components/Image.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import { ComponentVariants, ImageStyles, useComponentStyle } from "@codeleap/common"
|
|
2
|
+
import { ComponentVariants, ImageStyles, MobileInputFile, useComponentStyle } from "@codeleap/common"
|
|
3
3
|
import { ComponentPropsWithoutRef } from "react"
|
|
4
4
|
import { Image as NativeImage } from 'react-native'
|
|
5
5
|
import {FastImage} from '../modules/fastImage'
|
|
@@ -10,7 +10,7 @@ export type ImageProps = Omit<NativeImageProps, 'source'> & {
|
|
|
10
10
|
fast?: boolean
|
|
11
11
|
source: NativeImageProps['source'] & {
|
|
12
12
|
priority?: keyof typeof FastImage.priority
|
|
13
|
-
}
|
|
13
|
+
} | MobileInputFile | string
|
|
14
14
|
resizeMode?: keyof typeof FastImage.resizeMode
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -38,6 +38,6 @@ export const Image:React.FC<ImageProps> = (props) => {
|
|
|
38
38
|
}
|
|
39
39
|
return <NativeImage
|
|
40
40
|
style={styles}
|
|
41
|
-
{...imageProps}
|
|
41
|
+
{...(imageProps as any)}
|
|
42
42
|
/>
|
|
43
43
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
ViewProps,
|
|
5
|
+
AnimatedView
|
|
6
|
+
} from '../View'
|
|
7
|
+
import { Button, ButtonProps } from '../Button'
|
|
8
|
+
import { Scroll } from '../Scroll'
|
|
9
|
+
import { capitalize, ComponentVariants, IconPlaceholder, onUpdate, useComponentStyle, useStyle } from '@codeleap/common'
|
|
10
|
+
import { MobileModalComposition, MobileModalStyles, MobileModalParts } from './styles'
|
|
11
|
+
import { StyleSheet } from 'react-native'
|
|
12
|
+
import { StylesOf } from '../../types/utility'
|
|
13
|
+
|
|
14
|
+
import { Touchable } from '../Touchable'
|
|
15
|
+
import { Text } from '../Text'
|
|
16
|
+
import { Animated } from '../Animated'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export * from './styles'
|
|
20
|
+
|
|
21
|
+
export type ModalProps = Omit<ViewProps, 'variants'|'styles'> & {
|
|
22
|
+
variants?: ComponentVariants<typeof MobileModalStyles>['variants']
|
|
23
|
+
styles?: StylesOf<MobileModalComposition>
|
|
24
|
+
dismissOnBackdrop?: boolean
|
|
25
|
+
buttonProps?: ButtonProps
|
|
26
|
+
accessible?:boolean
|
|
27
|
+
showClose?: boolean
|
|
28
|
+
closable?: boolean
|
|
29
|
+
footer?: React.ReactNode
|
|
30
|
+
title?: React.ReactNode;
|
|
31
|
+
debugName?: string
|
|
32
|
+
closeIconName?: IconPlaceholder
|
|
33
|
+
visible: boolean
|
|
34
|
+
toggle: () => void
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const Modal:React.FC<ModalProps> = (modalProps) => {
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
variants = [],
|
|
41
|
+
styles = { },
|
|
42
|
+
style,
|
|
43
|
+
visible,
|
|
44
|
+
showClose,
|
|
45
|
+
closable = true,
|
|
46
|
+
title,
|
|
47
|
+
footer,
|
|
48
|
+
children,
|
|
49
|
+
toggle,
|
|
50
|
+
dismissOnBackdrop = true,
|
|
51
|
+
closeIconName = 'close',
|
|
52
|
+
debugName,
|
|
53
|
+
...props
|
|
54
|
+
} = modalProps
|
|
55
|
+
|
|
56
|
+
const variantStyles = useComponentStyle('Modal', {
|
|
57
|
+
variants: variants as any,
|
|
58
|
+
transform: StyleSheet.flatten,
|
|
59
|
+
styles
|
|
60
|
+
}) as ModalProps['styles']
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
function getStyles(key:MobileModalParts){
|
|
64
|
+
const s = [
|
|
65
|
+
variantStyles[key],
|
|
66
|
+
styles[key],
|
|
67
|
+
visible ? variantStyles[key + ':visible'] : {},
|
|
68
|
+
visible ? styles[key + ':visible'] : {},
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
return s
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const buttonStyles = React.useMemo(() => {
|
|
75
|
+
const buttonEntries = {}
|
|
76
|
+
|
|
77
|
+
for(const [key,style] of Object.entries(variantStyles)){
|
|
78
|
+
if(key.startsWith('closeButton')){
|
|
79
|
+
buttonEntries[capitalize(key.replace('closeButton', ''), true)] = style
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return buttonEntries
|
|
83
|
+
}, [variantStyles])
|
|
84
|
+
|
|
85
|
+
const boxAnimation = {
|
|
86
|
+
hidden : {
|
|
87
|
+
...variantStyles['box:pose'],
|
|
88
|
+
...styles['box:pose'],
|
|
89
|
+
},
|
|
90
|
+
visible : {
|
|
91
|
+
...variantStyles['box:pose:visible'],
|
|
92
|
+
...styles['box:pose:visible'],
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
|
|
98
|
+
<View style={getStyles('wrapper')} pointerEvents={visible ? 'auto' : 'none'} >
|
|
99
|
+
<AnimatedView style={getStyles('overlay')} transition={'opacity'}/>
|
|
100
|
+
<Scroll style={getStyles('innerWrapper')} contentContainerStyle={getStyles('innerWrapperScroll')}>
|
|
101
|
+
{
|
|
102
|
+
dismissOnBackdrop &&
|
|
103
|
+
<Touchable
|
|
104
|
+
debugName={`${debugName} modal backdrop`}
|
|
105
|
+
activeOpacity={1}
|
|
106
|
+
onPress={() => toggle()}
|
|
107
|
+
style={getStyles('touchableBackdrop')}
|
|
108
|
+
|
|
109
|
+
/>
|
|
110
|
+
}
|
|
111
|
+
<Animated component='View' config={boxAnimation} pose={visible ? 'visible' : 'hidden'} style={getStyles('box')}>
|
|
112
|
+
{
|
|
113
|
+
(title || showClose) &&
|
|
114
|
+
|
|
115
|
+
<View style={getStyles('header')}>
|
|
116
|
+
|
|
117
|
+
{typeof title === 'string' ? <Text text={title} style={getStyles('title')}/> : title}
|
|
118
|
+
|
|
119
|
+
{
|
|
120
|
+
(showClose && closable) &&
|
|
121
|
+
<Button debugName={`${debugName} modal close button`} icon={closeIconName as IconPlaceholder} variants={['icon']} onPress={toggle} styles={buttonStyles}/>
|
|
122
|
+
}
|
|
123
|
+
</View>
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
<View style={getStyles('body')}>
|
|
127
|
+
{children}
|
|
128
|
+
</View>
|
|
129
|
+
{
|
|
130
|
+
footer && <View style={getStyles('footer')}>
|
|
131
|
+
{footer}
|
|
132
|
+
</View>
|
|
133
|
+
}
|
|
134
|
+
</Animated>
|
|
135
|
+
|
|
136
|
+
</Scroll>
|
|
137
|
+
</View>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
export default Modal
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ButtonComposition, createDefaultVariantFactory, includePresets, ModalComposition, ModalStyles } from '@codeleap/common'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const backgroundTransition = {
|
|
5
|
+
duration: 200,
|
|
6
|
+
ease: 'easeOut',
|
|
7
|
+
useNativeDriver: false,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const modalTransition = {
|
|
11
|
+
duration: 150,
|
|
12
|
+
ease: 'easeOut',
|
|
13
|
+
useNativeDriver: false,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
export type MobileModalParts =
|
|
18
|
+
| 'wrapper'
|
|
19
|
+
| 'overlay'
|
|
20
|
+
| 'innerWrapper'
|
|
21
|
+
| 'innerWrapperScroll'
|
|
22
|
+
| 'box'
|
|
23
|
+
| 'footer'
|
|
24
|
+
| 'body'
|
|
25
|
+
| 'header'
|
|
26
|
+
| 'touchableBackdrop'
|
|
27
|
+
| 'box:pose'
|
|
28
|
+
|
|
29
|
+
| 'title'
|
|
30
|
+
| `closeButton${Capitalize<ButtonComposition>}`
|
|
31
|
+
|
|
32
|
+
export type MobileModalComposition = MobileModalParts | `${MobileModalParts}:visible`
|
|
33
|
+
|
|
34
|
+
const createModalStyle = createDefaultVariantFactory<MobileModalComposition>()
|
|
35
|
+
|
|
36
|
+
const presets = includePresets((style ) => createModalStyle(() => ({wrapper: style})))
|
|
37
|
+
|
|
38
|
+
const defaultModalStyles = ModalStyles
|
|
39
|
+
|
|
40
|
+
export const MobileModalStyles = {
|
|
41
|
+
...presets,
|
|
42
|
+
...defaultModalStyles,
|
|
43
|
+
default: createModalStyle((Theme) => {
|
|
44
|
+
|
|
45
|
+
const fullSize = {
|
|
46
|
+
...Theme.presets.whole,
|
|
47
|
+
position: 'absolute',
|
|
48
|
+
width: Theme?.values?.width,
|
|
49
|
+
height: Theme?.values?.height,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
wrapper: {
|
|
54
|
+
zIndex:1,
|
|
55
|
+
|
|
56
|
+
...fullSize
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
overlay: {
|
|
60
|
+
opacity: 0,
|
|
61
|
+
zIndex: 2,
|
|
62
|
+
|
|
63
|
+
backgroundColor: Theme.colors.black,
|
|
64
|
+
...fullSize
|
|
65
|
+
},
|
|
66
|
+
"overlay:visible": {
|
|
67
|
+
opacity: 0.5
|
|
68
|
+
},
|
|
69
|
+
innerWrapper: {
|
|
70
|
+
|
|
71
|
+
zIndex: 3,
|
|
72
|
+
},
|
|
73
|
+
innerWrapperScroll: {
|
|
74
|
+
display: 'flex',
|
|
75
|
+
alignItems: 'center',
|
|
76
|
+
...Theme.presets.justifyCenter,
|
|
77
|
+
minHeight: Theme.values.height,
|
|
78
|
+
zIndex: 3
|
|
79
|
+
},
|
|
80
|
+
box: {
|
|
81
|
+
width: '80%',
|
|
82
|
+
backgroundColor: Theme.colors.white,
|
|
83
|
+
zIndex: 10,
|
|
84
|
+
borderRadius: Theme.borderRadius.medium,
|
|
85
|
+
...Theme.spacing.padding(1)
|
|
86
|
+
|
|
87
|
+
},
|
|
88
|
+
touchableBackdrop: {
|
|
89
|
+
...fullSize,
|
|
90
|
+
|
|
91
|
+
zIndex:5
|
|
92
|
+
},
|
|
93
|
+
"box:pose": {
|
|
94
|
+
opacity: 0,
|
|
95
|
+
scale: 0.8,
|
|
96
|
+
y: Theme.values.height * 0.15,
|
|
97
|
+
transition: modalTransition,
|
|
98
|
+
},
|
|
99
|
+
"box:pose:visible": {
|
|
100
|
+
y: 0,
|
|
101
|
+
opacity: 1,
|
|
102
|
+
scale: 1,
|
|
103
|
+
transition: modalTransition,
|
|
104
|
+
},
|
|
105
|
+
header: {
|
|
106
|
+
flexDirection: 'row',
|
|
107
|
+
...Theme.presets.justifySpaceBetween,
|
|
108
|
+
...Theme.presets.alignCenter
|
|
109
|
+
},
|
|
110
|
+
closeButtonWrapper: {
|
|
111
|
+
alignSelf: 'center',
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}),
|
|
119
|
+
popup: createModalStyle((Theme) => ({
|
|
120
|
+
|
|
121
|
+
}))
|
|
122
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import * as Animatable from 'react-native-animatable'
|
|
3
|
+
import { ComponentVariants, IconPlaceholder, OverlayComposition, OverlayStyles, useComponentStyle } from "@codeleap/common"
|
|
4
|
+
import { ReactNode } from "react"
|
|
5
|
+
import { InputLabel } from "./TextInput"
|
|
6
|
+
import { Button } from './Button'
|
|
7
|
+
|
|
8
|
+
import { View } from "./View"
|
|
9
|
+
import { StylesOf } from "../types/utility"
|
|
10
|
+
import { StyleSheet, ViewProps } from "react-native"
|
|
11
|
+
import { AnimatedTouchable } from '.'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export type OverlayProps = ViewProps & {
|
|
15
|
+
title?: ReactNode
|
|
16
|
+
visible?: boolean
|
|
17
|
+
showClose?: boolean
|
|
18
|
+
variants?: ComponentVariants<typeof OverlayStyles>
|
|
19
|
+
styles?: StylesOf<OverlayComposition>
|
|
20
|
+
style?: any
|
|
21
|
+
onPress?:() => void
|
|
22
|
+
} & React.ComponentPropsWithoutRef<typeof AnimatedTouchable>
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export const Overlay:React.FC<OverlayProps> = (overlayProps) => {
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
showClose,
|
|
29
|
+
title,
|
|
30
|
+
children,
|
|
31
|
+
visible,
|
|
32
|
+
styles,
|
|
33
|
+
style,
|
|
34
|
+
variants,
|
|
35
|
+
...props
|
|
36
|
+
} = overlayProps
|
|
37
|
+
|
|
38
|
+
const variantStyles = useComponentStyle('Overlay', {
|
|
39
|
+
styles,
|
|
40
|
+
transform: StyleSheet.flatten,
|
|
41
|
+
variants: variants as any
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const touchableStyle = [
|
|
45
|
+
variantStyles.wrapper,
|
|
46
|
+
styles.wrapper,
|
|
47
|
+
visible && variantStyles['wrapper:visible'],
|
|
48
|
+
visible && styles['wrapper:visible']
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
return <AnimatedTouchable
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
transition={'opacity'}
|
|
55
|
+
style={touchableStyle}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
<View>
|
|
59
|
+
|
|
60
|
+
{ (title || showClose) && (
|
|
61
|
+
<View style={variantStyles.header}>
|
|
62
|
+
<InputLabel style={variantStyles.title} label={title}/>
|
|
63
|
+
{
|
|
64
|
+
showClose && <Button variants={['icon']} icon={'close' as IconPlaceholder} style={variantStyles.closeButton}/>
|
|
65
|
+
}
|
|
66
|
+
</View>
|
|
67
|
+
)}
|
|
68
|
+
|
|
69
|
+
</View>
|
|
70
|
+
</AnimatedTouchable>
|
|
71
|
+
|
|
72
|
+
}
|