npm package: @siroi/react-portal
Description: A simple and intuitive React portal library for easy DOM mounting
Author: siroi
Latest version: 0.1.0-beta.2

# @siroi/react-portal

一个简单直观的React Portal库，用于简化DOM挂载操作。

## 特性

- 🎯 **极简API**：像使用普通组件一样使用Portal
- 🔄 **保持上下文**：自动透传React Context
- 🎨 **多种使用方式**：组件、Hook、HOC三种选择
- 📦 **轻量级**：只解决挂载问题，不做过度设计
- 🛡️ **类型安全**：完整的TypeScript支持
- 🌐 **SSR友好**：服务端渲染安全

## 安装

```bash
npm install @siroi/react-portal
# 或
yarn add @siroi/react-portal
# 或
pnpm add @siroi/react-portal
```

## 快速开始

### 1. Portal组件（推荐）

```tsx
import { Portal } from '@siroi/react-portal';

function App() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>
        打开Modal
      </button>
      
      {isOpen && (
        <Portal>
          <div className="modal">
            <h2>Modal标题</h2>
            <p>内容...</p>
            <button onClick={() => setIsOpen(false)}>
              关闭
            </button>
          </div>
        </Portal>
      )}
    </div>
  );
}
```

### 2. usePortal Hook

```tsx
import { usePortal } from '@siroi/react-portal';

function App() {
  const [isOpen, setIsOpen] = useState(false);
  const { portal } = usePortal();

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>
        打开Modal
      </button>
      
      {isOpen && portal(
        <div className="modal">
          <h2>Modal标题</h2>
          <p>内容...</p>
          <button onClick={() => setIsOpen(false)}>
            关闭
          </button>
        </div>
      )}
    </div>
  );
}
```

### 3. createPortal HOC

```tsx
import { createPortal } from '@siroi/react-portal';

function Modal({ children, onClose }) {
  return (
    <div className="modal">
      {children}
      <button onClick={onClose}>关闭</button>
    </div>
  );
}

const PortalModal = createPortal(Modal);

function App() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>
        打开Modal
      </button>
      
      {isOpen && (
        <PortalModal onClose={() => setIsOpen(false)}>
          <h2>Modal标题</h2>
          <p>内容...</p>
        </PortalModal>
      )}
    </div>
  );
}
```

## API 文档

### `<Portal />` 组件

| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `children` | `ReactNode` | - | Portal内容 |
| `to` | `HTMLElement` | `document.body` | 挂载目标元素 |
| `autoCleanup` | `boolean` | `true` | 是否自动清理 |
| `key` | `string \| null` | `null` | React key |

### `usePortal(options)` Hook

```tsx
const { portal, cleanup, target } = usePortal({
  to: document.body,      // 挂载目标
  autoCleanup: true,      // 自动清理
  key: null,              // React key
});
```

### `createPortal(Component, config)` HOC

```tsx
const PortalComponent = createPortal(Component, {
  to: document.body,      // 挂载目标
  autoCleanup: true,      // 自动清理
  key: null,              // React key
  displayName: 'PortalComponent', // 组件名称
});
```

## 高级用法

### 自定义挂载目标

```tsx
function App() {
  const [container, setContainer] = useState(null);
  const containerRef = useCallback((node) => {
    if (node) setContainer(node);
  }, []);

  return (
    <div>
      <div ref={containerRef} className="custom-container">
        自定义容器
      </div>
      
      <Portal to={container}>
        <div>渲染到自定义容器</div>
      </Portal>
    </div>
  );
}
```

### 批量创建Portal组件

```tsx
import { createPortalFactory } from '@siroi/react-portal';

// 创建工厂函数
const createBodyPortal = createPortalFactory({ to: document.body });

// 批量创建Portal组件
const PortalModal = createBodyPortal(Modal);
const PortalTooltip = createBodyPortal(Tooltip);
const PortalDropdown = createBodyPortal(Dropdown);
```

## 与原生createPortal对比

### 原生方式
```tsx
import { createPortal } from 'react-dom';

function Component() {
  return createPortal(
    <div>内容</div>,
    document.body,
    'portal-key'
  );
}
```

### @siroi/react-portal方式
```tsx
import { Portal } from '@siroi/react-portal';

function Component() {
  return (
    <Portal to={document.body} key="portal-key">
      <div>内容</div>
    </Portal>
  );
}
```

**优势：**
- 更符合React组件思维
- 自动处理SSR场景
- 更好的类型提示
- 支持多种使用模式

## 开发

### 构建
```bash
npm run build
```

### 开发模式
```bash
npm run dev
```

### 清理构建产物
```bash
npm run clean
```

## 技术细节

### 构建输出
这个包使用纯TypeScript编译，输出ES模块格式：
- `dist/index.js` - 编译后的JavaScript代码
- `dist/index.d.ts` - TypeScript类型定义

### 依赖关系
- **peerDependencies**: `react`, `react-dom`
- **devDependencies**: `typescript`, `@types/react`, `@types/react-dom`, `rimraf`

### 设计理念
1. **简单优先**：API设计直观易用
2. **零配置**：合理的默认值，开箱即用
3. **类型安全**：完整的TypeScript支持
4. **最小依赖**：只依赖React，不引入额外负担

## 许可证

MIT © siroi