Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: rn modal.prompt, ref #1011 #1089

Merged
merged 2 commits into from
Apr 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions components/modal/PromptContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/* tslint:disable:jsx-no-multiline-js */
import React from 'react';
import { View, Text, TextInput } from 'react-native';
import Modal from './Modal';
import promptStyles from './style/prompt';

export type ButtonType = {
text: string;
onPress?: () => void;
style?: any;
};

export interface PropmptContainerProps {
title: string;
type?: 'default' | 'login-password' | 'secure-text';
message?: string | null;
defaultValue?: string;
actions: Array<ButtonType>;
onAnimationEnd?: (visible: boolean) => void;
styles?: any;
};

export default class PropmptContainer extends React.Component<PropmptContainerProps, any> {
static defaultProps = {
type: 'default',
defaultValue: '',
styles: promptStyles,
};

constructor(props) {
super(props);
this.state = {
visible: true,
text: props.defaultValue,
password: props.type === 'secure-text' ? props.defaultValue : '',
};
}

onClose() {
this.setState({
visible: false,
});
}

onChangeText(type, value) {
this.setState({
[type]: value,
});
}

render() {
const { title, onAnimationEnd, message, type, actions, styles } = this.props;
const { text, password } = this.state;
const getArgs = function(func) {
if (type === 'login-password') {
return func.apply(this, [text, password]);
} else if (type === 'secure-text') {
return func.apply(this, [password]);
}
return func.apply(this, [text]);
};
let callbacks;
if (typeof actions === 'function') {
callbacks = [
{ text: '取消', style: 'cancel' },
{ text: '确定', onPress: () => getArgs(actions as Function) },
];
} else {
callbacks = actions.map(item => {
return {
text: item.text,
onPress: () => {
if (item.onPress) {
return getArgs(item.onPress);
}
},
style: item.style || {},
};
});
}

const footer = callbacks.map((button) => {
const orginPress = button.onPress || function () {};
button.onPress = () => {
const res = orginPress();
if (res && (res as any).then) {
(res as any).then(() => {
this.onClose();
});
} else {
this.onClose();
}
};
return button;
});

const firstStyle = [styles.inputWrapper];
const lastStyle = [styles.inputWrapper];

if (type === 'login-password') {
firstStyle.push(styles.inputFirst);
lastStyle.push(styles.inputLast);
} else if ( type === 'secure-text') {
lastStyle.push(styles.inputFirst);
lastStyle.push(styles.inputLast);
} else {
firstStyle.push(styles.inputFirst);
firstStyle.push(styles.inputLast);
}

return (
<Modal
transparent
title={title}
visible={this.state.visible}
onClose={() => this.onClose}
footer={footer}
onAnimationEnd={onAnimationEnd}
>
<View>
{ message && message.length && <Text style={styles.message}>{message}</Text> }
<View style={styles.inputGroup}>
{ type !== 'secure-text' && (
<View style={firstStyle}>
<TextInput
autoFocus
onChangeText={(value) => { this.onChangeText('text', value); }}
value={this.state.text}
style={styles.input}
/>
</View>
)
}
{
(type === 'secure-text' || type === 'login-password') && (
<View style={lastStyle}>
<TextInput
autoFocus
secureTextEntry
onChangeText={(value) => { this.onChangeText('password', value); }}
value={this.state.password}
style={styles.input}
/>
</View>
)
}
</View>
</View>
</Modal>
);
}
}
162 changes: 162 additions & 0 deletions components/modal/__tests__/__snapshots__/demo.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,168 @@ exports[`renders ./components/modal/demo/basic.tsx correctly 1`] = `
</Text>
</View>
</View>
<View
style={
Array [
Object {
"height": 9,
},
undefined,
]
}
/>
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
hitSlop={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
Object {
"backgroundColor": "transparent",
},
Array [
Object {
"alignItems": "center",
"borderRadius": 5,
"borderWidth": 1,
"justifyContent": "center",
},
Object {
"height": 42,
"paddingLeft": 15,
"paddingRight": 15,
},
Object {
"backgroundColor": "#fff",
"borderColor": "#ddd",
},
false,
false,
false,
undefined,
],
]
}
testID={undefined}
>
<View
style={
Object {
"flexDirection": "row",
}
}
>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
style={
Array [
Object {
"fontSize": 18,
},
Object {
"color": "#000",
},
false,
false,
]
}
>
显示 Modal.propmt (login-password)
</Text>
</View>
</View>
<View
style={
Array [
Object {
"height": 9,
},
undefined,
]
}
/>
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
hitSlop={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
Object {
"backgroundColor": "transparent",
},
Array [
Object {
"alignItems": "center",
"borderRadius": 5,
"borderWidth": 1,
"justifyContent": "center",
},
Object {
"height": 42,
"paddingLeft": 15,
"paddingRight": 15,
},
Object {
"backgroundColor": "#fff",
"borderColor": "#ddd",
},
false,
false,
false,
undefined,
],
]
}
testID={undefined}
>
<View
style={
Object {
"flexDirection": "row",
}
}
>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
style={
Array [
Object {
"fontSize": 18,
},
Object {
"color": "#000",
},
false,
false,
]
}
>
显示 Modal.propmt (secure-text)
</Text>
</View>
</View>
</View>
<View
style={
Expand Down
23 changes: 23 additions & 0 deletions components/modal/demo/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ export default class BasicModalExample extends React.Component<any, any> {
]);
}

onButtonClick3 = () => {
Modal.prompt(
'登录',
'输入用户名和密码',
(login, password) => console.log(`login: ${login}, password: ${password}`),
'login-password',
);
}

onButtonClick4 = () => {
Modal.prompt(
'输入密码',
'这是密码message,可以不要',
password => console.log(`password: ${password}`),
'secure-text',
'defaultValue'
);
}

render() {
const footerButtons = [
{ text: 'Cancel', onPress: () => console.log('cancel') },
Expand All @@ -69,6 +88,10 @@ export default class BasicModalExample extends React.Component<any, any> {
<Button onClick={this.onButtonClick}>显示 Modal.alert</Button>
<WhiteSpace />
<Button onClick={this.onButtonClick2}>显示 Modal.opertation</Button>
<WhiteSpace />
<Button onClick={this.onButtonClick3}>显示 Modal.propmt (login-password)</Button>
<WhiteSpace />
<Button onClick={this.onButtonClick4}>显示 Modal.propmt (secure-text)</Button>
</WingBlank>
<Modal
transparent={false}
Expand Down
6 changes: 2 additions & 4 deletions components/modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import Modal from './Modal';
import alert from './alert';
import propmt from './prompt';
import operation from './operation';

(Modal as any).alert = alert;
(Modal as any).operation = operation;

(Modal as any).prompt = () => {
console.warn('Modal.prompt is on the road, use react native "AlertIOS" temporarily');
};
(Modal as any).prompt = propmt;

export default Modal;
2 changes: 0 additions & 2 deletions components/modal/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ subtitle: 对话框

### Modal.prompt(title, message, callbackOrActions, type?, defaultValue?)

适用平台:WEB

属性 | 说明 | 类型 | 默认值
----|-----|------|------
| title | 标题 | String 或 React.Element | 无 |
Expand Down
Loading