UNPKG

@nnnb/prompt

Version:

A factory method that supports various modal components in function call. Support asynchronous collection and function call.

399 lines (329 loc) 8.37 kB
# @nnnb/prompt 一个用于 React 应用中 各种组件的灵活弹层管理解决方案。 ## 特性 - 🚀 简单易用的弹窗系统,支持 Modal、Drawer 等弹层组件 - 🎯 支持全局和局部上下文渲染 - ⚡ 高效的弹层管理,自动清理资源 - 🛠️ 使用 TypeScript 实现类型安全 - 🔄 可复用的弹层组件,支持自定义配置 - 📊 支持异步获取弹层组件的返回值 ## 安装 ```bash npm install @nnnb/prompt # 或 yarn add @nnnb/prompt ``` ## 使用方法 ### 基础用法 ```typescript import { createPrompt } from '@nnnb/prompt'; import { Modal } from 'antd'; // 创建一个带默认配置的 Modal 提示框 const ModalPrompt = createPrompt(Modal, { centered: true, destroyOnClose: true }); // 使用 Modal 提示框 const showModal = async () => { const result = await ModalPrompt({ props:{ title: '示例弹窗', content: '这是一个弹窗内容' } }); console.log(result); }; ``` ## 使用案例 ### 1. 简单使用 创建并显示一个 Modal,支持自定义组件和获取返回值: ```typescript import React from 'react'; import { createPrompt } from '@nnnb/prompt'; import { Button, Input, Modal } from 'antd'; // 创建一个 Modal 提示框 const ModalPrompt = createPrompt(Modal, { centered: true, destroyOnClose: true }); // 自定义表单组件 const FormA = ({ A, B }) => { return ( <div> <div> A: <Input defaultValue={A} /> </div> <div> B: <Input defaultValue={B} /> </div> </div> ); }; const Form = () => { const createModal = async () => { const res = await ModalPrompt({ component: FormA, props: { title: 'Modal', onOk: (e) => { console.log('onOk', e); return { a: 'a' }; }, onCancel: () => { console.log('onCancel'); } }, data: { A: 'AAAA', B: 'BBBB' } }); console.log(res); // 获取返回值 }; return ( <div> <Button onClick={() => createModal()}>创建 Modal</Button> </div> ); }; ``` ### 2. 使用 Ant Design 的全局配置 在 ConfigProvider 中使用弹层,继承全局主题配置: ```typescript import React from 'react'; import { LayerContextProvider, createPrompt } from '@nnnb/prompt'; import { Button, ConfigProvider, Input, Modal } from 'antd'; const ModalPrompt = createPrompt(Modal, { centered: true, destroyOnClose: true }); // 自定义表单组件 const FormA = ({ A, B }) => { return ( <div> <div> A: <Input defaultValue={A} /> </div> <div> B: <Input defaultValue={B} /> </div> </div> ); }; const Form = () => { const createModal = () => { ModalPrompt({ component: FormA, props: { title: 'Modal' }, data: { A: 'AAAA', B: 'BBBB' } }); }; return ( <div> <Button onClick={() => createModal()}>创建 Modal</Button> </div> ); }; // 在应用中使用 function App() { const [open, setOpen] = React.useState(false); return ( <ConfigProvider theme={{ token: { colorPrimary: '#006603', borderRadius: 6 }, components: { Button: { colorPrimary: '#00B96B' } } }} > <div> <Button onClick={() => setOpen(!open)}>显示</Button> <div>{open && <LayerContextProvider />}</div> </div> <Form /> </ConfigProvider> ); } ``` ### 3. 自定义渲染位置 使用 `usePrompt` 钩子获取 holder 来控制弹层渲染位置: ```typescript import React from 'react'; import { usePrompt } from '@nnnb/prompt'; import { Button, ConfigProvider, Drawer, Input, Modal } from 'antd'; // 自定义表单组件 const FormA = ({ A, B }) => { return ( <div> <div> A: <Input defaultValue={A} /> </div> <div> B: <Input defaultValue={B} /> </div> </div> ); }; const Form = ({ ModalPrompt }) => { const createModal = () => { ModalPrompt({ component: FormA, props: { title: 'Modal' }, data: { A: 'AAAA', B: 'BBBB' } }); }; return ( <div> <Button type="primary" onClick={() => createModal()}>创建 Modal</Button> </div> ); }; function App() { // 获取 Modal 的 holder 和 prompt 函数 const [holder, prompt] = usePrompt(Modal); // 获取 Drawer 的 holder 和 prompt 函数 const [holder2, prompt2] = usePrompt(Drawer); return ( <div> {/* Modal 将在这里渲染 */} {holder} <ConfigProvider theme={{ token: { colorPrimary: '#006603', borderRadius: 6 } }} > {/* Drawer 将在这里渲染,会继承 ConfigProvider 的样式 */} {holder2} <Form ModalPrompt={prompt} /> <Form ModalPrompt={prompt2} /> </ConfigProvider> </div> ); } ``` ### 4. 高级用法 - 异步获取子组件返回值 通过 `ref` 和 `useImperativeHandle` 实现异步获取子组件值: ```typescript import React, { ForwardRefRenderFunction, useImperativeHandle } from 'react'; import { PromptModalRef, usePrompt } from '@nnnb/prompt'; import { Button, Input, Modal } from 'antd'; // 延迟函数,模拟异步操作 const delay = (time: number) => new Promise((resolve) => setTimeout(resolve, time)); // 自定义表单组件,通过 ref 暴露方法 const FormA: ForwardRefRenderFunction<PromptModalRef, any> = ({ A, B }, ref) => { useImperativeHandle(ref, () => ({ // 定义 onOk 方法,将在点击确定按钮时调用 onOk: async () => { await delay(2000); // 模拟异步操作,比如数据验证或提交 return 'a'; // 返回值将作为 ModalPrompt 的结果 } })); return ( <div> <div> A: <Input defaultValue={A} /> </div> <div> B: <Input defaultValue={B} /> </div> </div> ); }; const Form = ({ ModalPrompt }) => { const createModal = async () => { // 等待弹窗操作完成,获取返回值 const val = await ModalPrompt({ component: FormA, props: { title: 'Modal', onOk: (e) => { console.log('Form', e); } }, data: { A: 'AAAA', B: 'BBBB' } }); console.log(val); // 输出 'a' }; return ( <div> <Button type="primary" onClick={() => createModal()}>创建 Modal</Button> </div> ); }; function App() { const [holder, prompt] = usePrompt(Modal); return ( <div> {holder} <Form ModalPrompt={prompt} /> </div> ); } ``` ## API 文档 ### createPrompt ```typescript createPrompt<ComponentProps extends PromptBaseModalProps, ReturnType = any>( Component: ComponentType<ComponentProps>, defaultConfig?: Partial<ComponentProps> ) => PromptFunction ``` 创建一个新的提示框函数,可以指定组件和默认配置。 ### usePrompt ```typescript usePrompt<P>( Component: ComponentType<P>, defaultConfig?: Partial<P> ): [ReactNode, PromptFunction] ``` 返回一个元组,包含渲染占位符和提示函数。 ### LayerContextProvider ```typescript <LayerContextProvider /> ``` 全局上下文提供者,用于在特定位置渲染弹层组件。 ### PromptModalRef 接口 ```typescript interface PromptModalRef { onOk?: () => Promise<any> | any; onCancel?: () => void; } ``` 用于在自定义组件中通过 ref 暴露方法。 ## 类型定义 ```typescript interface PromptBaseModalProps { open?: boolean; confirmLoading?: boolean; onOk?: (e: any) => void | Promise<any>; onCancel?: (e: any) => void; children?: ReactNode; } ``` ## 贡献指南 欢迎提交 Pull Request 来帮助改进这个项目! ## 许可证 MIT