@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
Markdown
# @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