UNPKG

zarm

Version:

基于 React 的移动端UI库

505 lines (460 loc) 20.3 kB
# Modal 模态框 ## 基本用法 ```jsx import { useRef, useReducer } from 'react'; import { Modal, List, Button, Select } from 'zarm'; const initState = { normal: { visible: false, }, hasFooter: { visible: false, }, closable: { visible: false, }, onlyBody: { visible: false, }, animation: { visible: false, animationType: 'fade', }, customContainer: { visible: false, }, overlength: { visible: false, }, }; const reducer = (state, action) => { const { type, key, animationType } = action; switch (type) { case 'visible': return { ...state, [key]: { ...state[key], visible: !state[key].visible, }, }; case 'animation': return { ...state, [key]: { ...state[key], animationType, }, }; default: } }; const Demo = () => { const myRef = useRef(); const [state, dispatch] = useReducer(reducer, initState); const toggle = (key) => dispatch({ type: 'visible', key }); return ( <> <List> <List.Item title="普通" suffix={ <Button size="xs" onClick={() => toggle('normal')}> 开启 </Button> } /> <List.Item title="自定义底部" suffix={ <Button size="xs" onClick={() => toggle('hasFooter')}> 开启 </Button> } /> <List.Item title="遮罩层可关闭" suffix={ <Button size="xs" onClick={() => toggle('closable')}> 开启 </Button> } /> <List.Item title="无头部,无底部" suffix={ <Button size="xs" onClick={() => toggle('onlyBody')}> 开启 </Button> } /> <List.Item title="动画效果" suffix={ <Button size="xs" onClick={() => toggle('animation')}> 开启 </Button> } > <Select value={state.animation.animationType} dataSource={[ { value: 'fade', label: '淡出淡入效果' }, { value: 'zoom', label: '缩放效果' }, { value: 'rotate', label: '旋转效果' }, { value: 'door', label: '开关门效果' }, { value: 'flip', label: '翻转效果' }, { value: 'move-up', label: '向上移入效果' }, { value: 'move-down', label: '向下移入效果' }, { value: 'move-left', label: '向左移入效果' }, { value: 'move-right', label: '向右移入效果' }, { value: 'slide-up', label: '向上滑入效果' }, { value: 'slide-down', label: '向下滑入效果' }, { value: 'slide-left', label: '向左滑入效果' }, { value: 'slide-right', label: '向右滑入效果' }, ]} itemRender={(data) => data && `${data.label}(${data.value})`} displayRender={(selected) => selected.map((item) => item && item.label)} onConfirm={(selected) => { dispatch({ type: 'animation', key: 'animation', animationType: selected[0], }); }} /> </List.Item> <List.Item suffix={ <Button size="xs" onClick={() => toggle('customContainer')}> 开启 </Button> } > 挂载到指定 DOM 节点 </List.Item> <List.Item suffix={ <Button size="xs" onClick={() => toggle('overlength')}> 开启 </Button> } > 超长内容 </List.Item> </List> <div id="test-div" style={{ position: 'relative', zIndex: 1 }} ref={myRef} /> <Modal visible={state.normal.visible} title="标题" closable onClose={() => toggle('normal')}> 模态框内容 </Modal> <Modal title="标题" visible={state.hasFooter.visible} footer={ <Button block shape="rect" theme="primary" onClick={() => toggle('hasFooter')}> 确定 </Button> } > 模态框内容 </Modal> <Modal visible={state.closable.visible} title="标题" maskClosable onClose={() => toggle('closable')} > 点击遮罩层关闭 </Modal> <Modal visible={state.onlyBody.visible} maskClosable onClose={() => toggle('onlyBody')}> 无头部,无底部 </Modal> <Modal visible={state.animation.visible} animationType={state.animation.animationType} maskClosable onClose={() => toggle('animation')} > <div style={{ height: 100 }}> 当前使用的动画类型animationType:'{state.animation.animationType}' </div> </Modal> <Modal visible={state.customContainer.visible} maskClosable onClose={() => toggle('customContainer')} mountContainer={() => myRef.current} > 挂载到指定dom节点 </Modal> <Modal visible={state.overlength.visible} title="标题" closable onClose={() => toggle('overlength')} maskClosable > {Array.from(Array(100).fill(0)).map((_, index) => ( <div key={index}> 模态框内容 <br /> </div> ))} </Modal> </> ); }; ReactDOM.render(<Demo />, mountNode); ``` ## 带操作按钮 ```jsx import { useState } from 'react'; import { Modal, List, Button } from 'zarm'; const Demo = () => { const [visible, setVisible] = useState(false); const toggle = () => setVisible(!visible); return ( <> <List> <List.Item title="自定义操作按钮" suffix={ <Button size="xs" onClick={toggle}> 开启 </Button> } /> </List> <Modal visible={visible} title="标题" actions={[ { key: 'online', text: '在线阅读', theme: 'default', }, { key: 'download', text: '下载文件', theme: 'default', disabled: true, }, [ { key: 'cancel', text: '取消', }, { key: 'delete', text: '删除', bold: true, theme: 'danger', }, ], ]} onAction={async (action) => { switch (action.key) { case 'cancel': toggle(); break; default: // 模拟异步操作 await new Promise((resolve) => setTimeout(resolve, 3000)); toggle(); } console.log(action); }} > 模态框内容 </Modal> </> ); }; ReactDOM.render(<Demo />, mountNode); ``` ## 警告框 Alert ```jsx import { List, Button, Modal, Toast } from 'zarm'; const Demo = () => { return ( <List> <List.Item title="静态方法关闭" suffix={ <Button size="xs" onClick={() => { Modal.alert({ className: 'test', title: '警告框标题', content: '这里是警告框的内容部分', onConfirm: () => { console.log('点击确认'); }, }); }} > 开启 </Button> } /> <List.Item title="使用 Promise 关闭" suffix={ <Button size="xs" onClick={() => { Modal.alert({ title: '警告框标题', content: '这里是警告框的内容部分,点击关闭按钮,将触发 Promise 关闭警告框', onConfirm: async () => { await new Promise((resolve) => setTimeout(resolve, 3000)); Toast.show({ content: '提交成功' }); }, }); }} > 开启 </Button> } /> </List> ); }; ReactDOM.render(<Demo />, mountNode); ``` ## 确认框 Confirm ```jsx import { List, Button, Modal, Toast } from 'zarm'; const Demo = () => { return ( <List> <List.Item title="静态方法关闭" suffix={ <Button size="xs" onClick={() => { Modal.confirm({ title: '确认信息', content: '这里是确认框的内容部分', onCancel: () => { console.log('点击cancel'); }, onConfirm: () => { console.log('点击ok'); }, }); }} > 开启 </Button> } /> <List.Item title="使用 Promise 关闭" suffix={ <Button size="xs" onClick={() => { Modal.confirm({ title: '确定要删除吗?', content: '这里是确认框的内容部分,点击确定按钮,将触发 Promise 关闭确认框', onConfirm: async () => { await new Promise((resolve) => setTimeout(resolve, 3000)); Toast.show({ content: '提交成功' }); }, }); }} > 开启 </Button> } /> </List> ); }; ReactDOM.render(<Demo />, mountNode); ``` ## API | 属性 | 类型 | 默认值 | 说明 | | :---------------- | :------------------------------------------------------------------- | :------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | shape | string | 'radius' | 形状,可选值 `rect`、`radius` | | visible | boolean | false | 是否显示 | | animationType | string | 'fade' | 动画效果,可选值 `fade`, `door`, `flip`, `rotate`, `zoom`,`move-up`, `move-down`, `move-left`, `move-right`,`slide-up`, `slide-down`, `slide-left`, `slide-right` | | animationDuration | number | 200 | 动画执行时间(单位:毫秒) | | width | string &#124; number | '70%' | 宽度 | | mask | boolean | true | 是否展示遮罩层 | | maskType | string | 'normal' | 遮罩层的类型,可选值 `transparent`, `normal` | | maskClosable | boolean | false | 是否点击遮罩层时关闭,需要和 onCancel 一起使用 | | closable | boolean | false | 右上角是否显示关闭按钮,需要和 onCancel 一起使用 | | onClose | () => void | - | maskClosable 或 closable 为 true 时,点击遮罩或者右上角关闭按钮触发的函数 | | title | ReactNode | - | 标题 | | footer | ReactNode | - | 弹窗底部内容 | | actions | (ModalActionProps \| ModalActionProps[])[] | [] | 操作按钮配置 | | onAction | (action: ModalActionProps, index: number) => void \| Promise\<void\> | - | 点击操作按钮后触发的函数 | | destroy | boolean | true | 弹层关闭后是否移除节点 | | afterOpen | () => void | - | 模态框打开后的回调 | | afterClose | () => void | - | 模态框关闭后的回调 | | mountContainer | MountContainer | () => document.body | 指定 Modal 挂载的 HTML 节点 | ### ModalActionProps 操作按钮属性 | 属性 | 类型 | 默认值 | 说明 | | :------- | :--------- | :-------- | :---------------------------------------------- | | text | ReactNode | - | 按钮文字 | | theme | string | 'primary' | 按钮主题,可选值 `default`、`primary`、`danger` | | disabled | boolean | false | 按钮是否禁用 | | bold | boolean | false | 是否加粗 | | onClick | () => void | - | 按钮点击后触发的回调函数 | ## 指令式 API ```tsx // 显示警告框,点击“确定”按钮执行 onConfirm 方法,如需做更多操作,参考下方 Confirm 的例子 const alert = Modal.alert({ title: '警告框标题', content: '这里是警告框的内容部分', }); // 显示确认框,若关闭时需要 Promise,onConfirm、onCancel 均支持 Promise const confirm = Modal.confirm({ title: '确认框标题', content: '这里是确认框的内容部分,点击确定按钮,将触发 Promise 关闭确认框', onConfirm: () => { return fetch.get('xxx.api').then((res) => { if(res.code === 0) { return true; // 关闭弹窗 } else { return false; // 阻止弹窗关闭 } }).catch(...); } }); ``` | 属性 | 类型 | 默认值 | 说明 | | :---------- | :--------- | :---------------------------- | :------------------------------------------ | | title | ReactNode | - | 弹出框的标题 | | content | ReactNode | - | 弹出框的内容 | | cancelText | ReactNode | '取消' | 取消按钮的内容 | | confirmText | ReactNode | '确定' | 确定按钮的内容 | | onConfirm | () => void | - | 点击“确定”后的回调函数 | | onCancel | () => void | - | 点击“取消”后的回调函数 | ## CSS 变量 | 属性 | 默认值 | 说明 | | :------------------------- | :---------------------------------- | :------------------------- | | --background | 'rgb(242, 242, 242)' | 背景色 | | --border-radius | '14px' | 圆角大小 | | --shadow | '0 7px 21px var(--za-color-shadow)' | 阴影样式 | | --title-font-size | '17px' | 标题字体大小 | | --title-font-weight | 500 | 标题字体粗细 | | --title-text-color | 'var(--za-color-text)' | 标题字体颜色 | | --close-size | '20px' | 关闭图标字体大小 | | --close-color | '#ccc' | 关闭图标颜色 | | --close-active-color | '#999' | 关闭图标激活状态颜色 | | --body-font-size | '13px' | 内容字体大小 | | --body-text-color | 'var(--za-color-text)' | 内容字体颜色 | | --body-padding | '16px' | 内容内边距 | | --button-background | 'transparent' | 操作按钮背景 | | --button-height | '44px' | 操作按钮高度 | | --button-font-size | '17px' | 操作按钮字体大小 | | --button-font-weight | 500 | 操作按钮字体粗细 | | --button-text-color | 'var(--za-theme-primary)' | 操作按钮字体颜色 | | --button-active-background | 'var(--za-background-active)' | 操作按钮选中背景 | | --button-disabled-opacity | 'var(--za-opacity-disabled)' | 操作按钮禁用状态时的透明度 |