Skip to content

Commit

Permalink
feat: 新增dialog组件
Browse files Browse the repository at this point in the history
  • Loading branch information
yatessss committed Jan 9, 2024
1 parent 1789fa2 commit 956fbb5
Show file tree
Hide file tree
Showing 7 changed files with 449 additions and 1 deletion.
4 changes: 4 additions & 0 deletions example/src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
{
"title": "消息提醒",
"children": [
{
"title": "Dialog 对话框",
"key": "Dialog"
},
{
"title": "Loading 加载中",
"key": "Loading"
Expand Down
7 changes: 7 additions & 0 deletions src/components/Dialog/Dialog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:: BASE_DOC ::

## API
### Base Props

临时md,后期会自动生成

187 changes: 187 additions & 0 deletions src/components/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import React, { useCallback, useContext } from 'react';
import { StyleSheet } from 'react-native';
import { isArray, isString } from 'lodash';
import { View, Text, ScrollView } from '../Base';
import { Touchable } from '../Touchable';
import { Popup } from '../Popup';
import { ThemeContext } from '../../theme';
import { DialogProps, DialogStaticProps } from './types';

const styles = StyleSheet.create({
container: {
height: 'auto',
width: 320,
},
});

export const Dialog: React.FunctionComponent<DialogProps> & DialogStaticProps = (props) => {
const { style } = props;
const { theme } = useContext(ThemeContext);

const renderTitle = useCallback(() => {
const { title, titleStyle } = props;
if (isString(title)) {
return (
<Text className="text3b fontGray1 textCenter" style={[titleStyle]}>
{title}
</Text>
);
}
if (React.isValidElement(title)) {
return title;
}
return null;
}, [props]);

const renderContent = useCallback(() => {
const { content, contentStyle } = props;
let element = null;
if (isString(content)) {
element = (
<Text className="text3 textCenter" style={[contentStyle]}>
{content}
</Text>
);
} else if (isArray(content)) {
element = content?.map((item, index) => (
<Text key={index} className={`text3 textCenter ${index !== 0 ? 'mt8' : ''}`} style={[contentStyle]}>
{item}
</Text>
));
} else if (React.isValidElement(content)) {
element = content;
}
return element ? (
<ScrollView className="mt8 px4" style={{ maxHeight: 290 }}>
{element}
</ScrollView>
) : null;
}, [props]);

const renderButton = useCallback(() => {
const { buttons, buttonLayout } = props;
const classMap = {
default: 'text3 fontGray1',
primary: 'text3b brand7',
danger: 'text3b error6',
};
return (
<View className={`bt1 ${buttonLayout === 'vertical' ? 'flexCol' : 'flexRow'}`} style={{ minHeight: 56 }}>
{buttons?.map((item, index) => {
const textClass = classMap[item.theme || (buttons.length === 1 ? 'primary' : 'default')];
const viewClass = buttonLayout === 'vertical' ? 'bt1' : 'bl1';

return (
<Touchable
key={`button_${index}`}
mode="opacity"
onPress={() => {
if (item?.onPress) {
item?.onPress?.();
return;
}
Dialog.hide(Dialog.dialogId);
}}
style={buttonLayout === 'vertical' ? { width: '100%' } : { flex: 1 }}
>
<View className={`flexCenter py16 ${index !== 0 ? viewClass : ''}`}>
<Text className={`textCenter ${textClass}`} style={[item.style]}>
{item.text}
</Text>
</View>
</Touchable>
);
})}
</View>
);
}, [props]);

return (
<View style={[styles.container, { backgroundColor: theme.colors.bgContainer }, style]}>
<View className="py32 px24">
{renderTitle()}
{renderContent()}
</View>
{renderButton()}
</View>
);
};

Dialog.defaultProps = {
showOverlay: true,
buttons: [{ text: '知道了' }],
buttonLayout: 'horizontal',
closeOnOverlay: false,
};

Dialog.show = (config) => {
const mergedConfig = { ...Dialog.defaultProps, ...config };
Dialog.dialogId = Popup.show(<Dialog {...mergedConfig} />, {
wrapperStyle: {
borderRadius: 8,
height: 'auto',
width: 'auto',
overflow: 'hidden',
...mergedConfig.popupWrapperStyle,
},
closeOnOverlay: mergedConfig.closeOnOverlay,
showOverlay: mergedConfig.showOverlay,
});
return Dialog.dialogId;
};

Dialog.hide = (id) => {
return Popup.hide(id);
};

Dialog.confirm = (message, onConfirm, onCancel) => {
const isObj = typeof message === 'object';
const title = isObj ? message.title : '提示';
const content = isObj ? message.content : message;
const confirmText = isObj && message.confirm ? message.confirm : '确定';
const cancelText = isObj && message.cancel ? message.cancel : '取消';

const id = Dialog.show({
title,
content,
buttons: [
{
text: cancelText,
onPress: () => {
Dialog.hide(id).then(() => {
onCancel?.();
});
},
},
{
text: confirmText,
theme: 'primary',
onPress: () => {
Dialog.hide(id).then(() => {
onConfirm?.();
});
},
},
],
closeOnOverlay: true,
});
};

Dialog.alert = (message, onConfirm) => {
const id = Dialog.show({
title: null,
content: [message],
buttons: [
{
text: '确定',
theme: 'primary',
onPress: () => {
Dialog.hide(id).then(() => {
onConfirm?.();
});
},
},
],
closeOnOverlay: true,
});
};
177 changes: 177 additions & 0 deletions src/components/Dialog/_example/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/**
* title: Dialog 对话框
* description: 一种打断当前操作的模态视图,用于显示重要提示或请求用户进行重要操作
* spline: base
* isComponent: true
* toc: false
*/

import { View, Button, Dialog, Text } from 'tdesign-react-native/components';
import { Section, CodeSpace, H3 } from '@src/../example/src/components';

const Demo = () => (
<>
<Section>
<H3>1.基础</H3>
<CodeSpace>
<View className="gapY10">
<Button
content={'单行标题'}
onPress={() => {
Dialog.show({
title: '对话框标题',
});
}}
/>
<Button
content={'多行标题最大高度'}
onPress={() => {
Dialog.show({
title: '对话框标题告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内',
});
}}
/>
<Button
content={'带说明文本'}
onPress={() => {
Dialog.show({
title: '对话框标题',
content: '对话框标题告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内',
});
}}
/>
<Button
content={'最大高度说明文本'}
onPress={() => {
Dialog.show({
title: '对话框标题',
content:
'告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。',
});
}}
/>
</View>
</CodeSpace>
</Section>
<Section>
<H3>2.按钮及排列</H3>
<CodeSpace>
<View className="gapY10">
<Button
content={'双按钮'}
onPress={() => {
Dialog.show({
title: '对话框标题',
content: '告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。',
buttons: [{ text: '取消' }, { text: '确定' }],
});
}}
/>
<Button
content={'按钮配置主题'}
onPress={() => {
Dialog.show({
title: '对话框标题',
content: '告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。',
buttons: [
{ text: '取消', theme: 'primary' },
{ text: '确定', theme: 'danger' },
],
});
}}
/>
<Button
content={'按钮自定义样式'}
onPress={() => {
Dialog.show({
title: '对话框标题',
content: '告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。',
buttons: [
{ text: '取消', theme: 'primary' },
{
text: '自定义',
style: { color: 'green' },
},
],
});
}}
/>
<Button
content={'按钮竖向排列'}
onPress={() => {
Dialog.show({
title: '对话框标题',
content: '告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。',
buttons: [{ text: '取消' }, { text: '确定' }],
buttonLayout: 'vertical',
});
}}
/>
</View>
</CodeSpace>
</Section>
<Section>
<H3>3.自定义样式</H3>
<CodeSpace>
<View className="gapY10">
<Button
content={'自定义style控制'}
onPress={() => {
Dialog.show({
title: '对话框标题',
titleStyle: { color: 'green' },
content: '告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。',
contentStyle: { color: 'blue', fontSize: 14 },
buttons: [{ text: '取消' }, { text: '确定' }],
});
}}
/>
<Button
content={'自定义元素控制'}
onPress={() => {
Dialog.show({
title: <Text className="success6">对话框标题</Text>,
content: (
<View>
<Text className="brand7">告知当前状态、信息和解决方法,等内容。描述文案尽可能控制在三行内。</Text>
</View>
),
buttons: [{ text: '取消' }, { text: '确定' }],
});
}}
/>
</View>
</CodeSpace>
</Section>
<Section>
<H3>4.简易调用</H3>
<CodeSpace>
<View className="gapY10">
<Button
content={'confirm'}
onPress={() => {
Dialog.confirm(
'对话框标题',
() => {
console.log('onConfirm');
},
() => {
console.log('onCancel');
},
);
}}
/>
<Button
content={'alert'}
onPress={() => {
Dialog.alert('对话框标题', () => {
console.log('onConfirm');
});
}}
/>
</View>
</CodeSpace>
</Section>
</>
);
export default Demo;
2 changes: 2 additions & 0 deletions src/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Dialog';
export * from './types';
Loading

0 comments on commit 956fbb5

Please sign in to comment.