Skip to content

Commit

Permalink
feat: Modal add useModal(#1383)
Browse files Browse the repository at this point in the history
  • Loading branch information
1uokun committed Oct 7, 2024
1 parent 84f828d commit 0234e9c
Show file tree
Hide file tree
Showing 10 changed files with 516 additions and 123 deletions.
5 changes: 3 additions & 2 deletions components/modal/AlertContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { isValidElement } from 'react'
import { ScrollView, Text, TextStyle } from 'react-native'
import Modal from './Modal'
import { Action, CallbackOnBackHandler } from './PropsType'
import { Action, CallbackOnBackHandler, ModalPropsType } from './PropsType'

export interface AlertContainerProps {
export interface AlertContainerProps extends Pick<ModalPropsType, 'modalType'> {
title: React.ReactNode
content: React.ReactNode
actions: Action<TextStyle>[]
Expand Down Expand Up @@ -68,6 +68,7 @@ export default class AlertContainer extends React.Component<
title={title}
visible={this.state.visible}
footer={footer}
modalType={this.props.modalType}
onAnimationEnd={onAnimationEnd}
onRequestClose={this.onBackAndroid}
bodyStyle={{
Expand Down
122 changes: 56 additions & 66 deletions components/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,24 @@ import React from 'react'
import {
KeyboardAvoidingView,
Platform,
StyleProp,
Text,
TextStyle,
TouchableHighlight,
TouchableWithoutFeedback,
View,
ViewStyle,
} from 'react-native'
import { getComponentLocale } from '../_util/getLocale'
import { LocaleContext } from '../locale-provider'
import { WithTheme, WithThemeStyles } from '../style'
import { WithTheme } from '../style'
import RCModal from './ModalView'
import { CallbackOnBackHandler, ModalPropsType } from './PropsType'
import { ModalPropsType } from './PropsType'
import alert from './alert'
import zh_CN from './locale/zh_CN'
import operation from './operation'
import prompt from './prompt'
import modalStyles, { ModalStyle } from './style/index'
import modalStyles from './style/index'
import useModal from './useModal'

export interface ModalProps
extends ModalPropsType<TextStyle>,
WithThemeStyles<ModalStyle> {
style?: StyleProp<ViewStyle>
bodyStyle?: StyleProp<ViewStyle>
onRequestClose?: CallbackOnBackHandler
children?: React.ReactNode
}
export interface ModalProps extends ModalPropsType {}

class AntmModal extends React.Component<ModalProps, any> {
static defaultProps = {
Expand All @@ -48,6 +39,7 @@ class AntmModal extends React.Component<ModalProps, any> {
static alert: typeof alert
static operation: typeof operation
static prompt: typeof prompt
static useModal: typeof useModal

static contextType = LocaleContext

Expand All @@ -67,6 +59,7 @@ class AntmModal extends React.Component<ModalProps, any> {
bodyStyle,
onAnimationEnd,
onRequestClose,
modalType,
} = this.props

// tslint:disable-next-line:variable-name
Expand Down Expand Up @@ -158,31 +151,30 @@ class AntmModal extends React.Component<ModalProps, any> {
</View>
) : null
return (
<View style={styles.container}>
<RCModal
onClose={onClose}
animationType={animType}
wrapStyle={transparent ? styles.wrap : undefined}
style={styles.wrap}
visible={visible}
onAnimationEnd={onAnimationEnd}
onRequestClose={onRequestClose}
animateAppear={animateAppear}
maskClosable={maskClosable}>
<KeyboardAvoidingView
behavior="padding"
enabled={Platform.OS === 'ios'}>
<View style={[styles.innerContainer, style]}>
{title ? (
<Text style={[styles.header]}>{title}</Text>
) : null}
<View style={[styles.body, bodyStyle]}>{children}</View>
{footerDom}
{closableDom}
</View>
</KeyboardAvoidingView>
</RCModal>
</View>
<RCModal
modalType={modalType}
onClose={onClose}
animationType={animType}
wrapStyle={transparent ? styles.wrap : undefined}
style={styles.wrap}
visible={visible}
onAnimationEnd={onAnimationEnd}
onRequestClose={onRequestClose}
animateAppear={animateAppear}
maskClosable={maskClosable}>
<KeyboardAvoidingView
behavior="padding"
enabled={Platform.OS === 'ios'}>
<View style={[styles.innerContainer, style]}>
{title ? (
<Text style={[styles.header]}>{title}</Text>
) : null}
<View style={[styles.body, bodyStyle]}>{children}</View>
{footerDom}
{closableDom}
</View>
</KeyboardAvoidingView>
</RCModal>
)
}
if (popup) {
Expand All @@ -194,39 +186,37 @@ class AntmModal extends React.Component<ModalProps, any> {
animType = 'slide-down'
}
return (
<View style={styles.container}>
<RCModal
onClose={onClose}
animationType={animType}
// tslint:disable-next-line:jsx-no-multiline-js
style={[
styles.popupContainer,
(styles as any)[`popup${aType}`],
style,
]}
visible={visible}
onAnimationEnd={onAnimationEnd}
onRequestClose={onRequestClose}
animateAppear={animateAppear}
maskClosable={maskClosable}>
<View style={bodyStyle}>{children}</View>
</RCModal>
</View>
<RCModal
modalType={modalType}
onClose={onClose}
animationType={animType}
// tslint:disable-next-line:jsx-no-multiline-js
style={[
styles.popupContainer,
(styles as any)[`popup${aType}`],
style,
]}
visible={visible}
onAnimationEnd={onAnimationEnd}
onRequestClose={onRequestClose}
animateAppear={animateAppear}
maskClosable={maskClosable}>
<View style={bodyStyle}>{children}</View>
</RCModal>
)
}
if (animType === 'slide') {
animType = undefined
}
return (
<View style={styles.container}>
<RCModal
visible={visible}
animationType={animType}
onRequestClose={onRequestClose}
onClose={onClose}>
<View style={style}>{children}</View>
</RCModal>
</View>
<RCModal
modalType={modalType}
visible={visible}
animationType={animType}
onRequestClose={onRequestClose}
onClose={onClose}>
<View style={style}>{children}</View>
</RCModal>
)
}}
</WithTheme>
Expand Down
52 changes: 38 additions & 14 deletions components/modal/ModalView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import {
BackHandler,
Dimensions,
Easing,
Modal as NativeModal,
StyleProp,
StyleSheet,
TouchableWithoutFeedback,
View,
ViewStyle,
} from 'react-native'
import Portal from '../portal'
import { CallbackOnBackHandler } from './PropsType'
import { ModalPropsType } from './PropsType'

const styles = StyleSheet.create({
wrap: {
Expand All @@ -36,19 +37,23 @@ const styles = StyleSheet.create({

const screen = Dimensions.get('window')

export interface IModalPropTypes {
wrapStyle?: StyleProp<ViewStyle>
export interface IModalPropTypes
extends Pick<
ModalPropsType,
| 'animateAppear'
| 'children'
| 'maskClosable'
| 'modalType'
| 'onAnimationEnd'
| 'onClose'
| 'onRequestClose'
| 'visible'
> {
animationDuration?: number
animationType: 'none' | 'fade' | 'slide-up' | 'slide-down'
maskStyle?: StyleProp<ViewStyle>
style?: {}
children?: React.ReactNode
animationType: 'none' | 'fade' | 'slide-up' | 'slide-down'
animationDuration?: number
visible: boolean
maskClosable?: boolean
animateAppear?: boolean
onClose?: () => void // onDismiss
onAnimationEnd?: (visible: boolean) => void // onShow
onRequestClose?: CallbackOnBackHandler
wrapStyle?: StyleProp<ViewStyle>
}

export default class RCModal extends React.Component<IModalPropTypes, any> {
Expand All @@ -62,6 +67,7 @@ export default class RCModal extends React.Component<IModalPropTypes, any> {
maskClosable: true,
onClose() {},
onAnimationEnd(_visible: boolean) {},
modalType: 'portal',
} as IModalPropTypes

animMask: any
Expand Down Expand Up @@ -234,8 +240,26 @@ export default class RCModal extends React.Component<IModalPropTypes, any> {
},
}

let Modal = Portal as React.ElementType
switch (props.modalType) {
case 'modal':
Modal = (p) =>
React.createElement(NativeModal, {
visible: true,
transparent: true,
...p,
})
break
case 'view':
Modal = (p) =>
React.createElement(View, {
style: StyleSheet.absoluteFill,
...p,
})
}

return (
<Portal>
<Modal>
<View style={[styles.wrap, props.wrapStyle]}>
<TouchableWithoutFeedback onPress={this.onMaskClose}>
<Animated.View
Expand All @@ -252,7 +276,7 @@ export default class RCModal extends React.Component<IModalPropTypes, any> {
{this.props.children}
</Animated.View>
</View>
</Portal>
</Modal>
)
}
}
6 changes: 4 additions & 2 deletions components/modal/OperationContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React from 'react'
import { TextStyle } from 'react-native'
import { WithTheme } from '../style'
import Modal from './Modal'
import { Action, CallbackOnBackHandler } from './PropsType'
import { Action, CallbackOnBackHandler, ModalPropsType } from './PropsType'
import modalStyle from './style/index'

export interface OperationContainerProps {
export interface OperationContainerProps
extends Pick<ModalPropsType, 'modalType'> {
actions: Action<TextStyle>[]
onAnimationEnd?: (visible: boolean) => void
onBackHandler?: CallbackOnBackHandler
Expand Down Expand Up @@ -69,6 +70,7 @@ export default class OperationContainer extends React.Component<
transparent
maskClosable
visible={this.state.visible}
modalType={this.props.modalType}
onClose={this.onClose}
onAnimationEnd={onAnimationEnd}
onRequestClose={this.onBackAndroid}
Expand Down
11 changes: 9 additions & 2 deletions components/modal/PromptContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import { getComponentLocale } from '../_util/getLocale'
import { LocaleContext } from '../locale-provider'
import { WithTheme, WithThemeStyles } from '../style'
import Modal from './Modal'
import { CallbackOnBackHandler, CallbackOrActions } from './PropsType'
import {
CallbackOnBackHandler,
CallbackOrActions,
ModalPropsType,
} from './PropsType'
import zh_CN from './locale/zh_CN'
import promptStyles, { PromptStyle } from './style/prompt'

export interface PropmptContainerProps extends WithThemeStyles<PromptStyle> {
export interface PropmptContainerProps
extends WithThemeStyles<PromptStyle>,
Pick<ModalPropsType, 'modalType'> {
title: React.ReactNode
message?: React.ReactNode
type?: 'default' | 'login-password' | 'secure-text'
Expand Down Expand Up @@ -147,6 +153,7 @@ export default class PropmptContainer extends React.Component<
title={title}
visible={this.state.visible}
footer={footer}
modalType={this.props.modalType}
onAnimationEnd={onAnimationEnd}
onRequestClose={this.onBackAndroid}>
{message ? <Text style={styles.message}>{message}</Text> : null}
Expand Down
32 changes: 20 additions & 12 deletions components/modal/PropsType.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import React from 'react'
import { TextStyle } from 'react-native'
export interface ModalPropsType<T> {
title?: React.ReactNode
visible: boolean
maskClosable?: boolean
closable?: boolean
footer?: Action<T>[]
onClose?: () => void
transparent?: boolean
popup?: boolean
import { StyleProp, TextStyle, ViewStyle } from 'react-native'
import { ModalStyle } from './style/index'

export interface ModalPropsType {
animateAppear?: boolean
animated?: boolean
animationType?: 'none' | 'fade' | 'slide-up' | 'slide-down' | 'slide'
bodyStyle?: StyleProp<ViewStyle>
children?: React.ReactNode
closable?: boolean
footer?: Action<TextStyle>[]
locale?: object
animationType?: any
maskClosable?: boolean
modalType?: 'portal' | 'modal' | 'view'
onAnimationEnd?: (visible: boolean) => void
animateAppear?: boolean
onClose?: () => void
operation?: boolean
onRequestClose?: CallbackOnBackHandler
popup?: boolean
style?: StyleProp<ViewStyle>
styles?: Partial<ModalStyle>
title?: React.ReactNode
transparent?: boolean
visible: boolean
}

export interface Action<T = TextStyle> {
Expand Down
Loading

0 comments on commit 0234e9c

Please sign in to comment.