diff --git a/.dumirc.ts b/.dumirc.ts
index 67ace038..7cae344c 100644
--- a/.dumirc.ts
+++ b/.dumirc.ts
@@ -1,12 +1,18 @@
import { defineConfig } from 'dumi';
import path from 'path';
+const basePath = process.env.GH_PAGES ? '/image/' : '/';
+const publicPath = basePath;
+
export default defineConfig({
alias: {
'@rc-component/image$': path.resolve('src'),
'@rc-component/image/es': path.resolve('src'),
},
favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'],
+ outputPath: 'docs-dist',
+ base: basePath,
+ publicPath,
themeConfig: {
name: 'Image',
logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4',
diff --git a/.fatherrc.ts b/.fatherrc.ts
new file mode 100644
index 00000000..96268ae1
--- /dev/null
+++ b/.fatherrc.ts
@@ -0,0 +1,5 @@
+import { defineConfig } from 'father';
+
+export default defineConfig({
+ plugins: ['@rc-component/father-plugin'],
+});
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 33b1999c..758659af 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,15 +1,2 @@
-# These are supported funding model platforms
-
-github: ant-design # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: # Replace with a single Patreon username
-open_collective: ant-design # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
-polar: # Replace with a single Polar username
-buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
-thanks_dev: # Replace with a single thanks.dev username
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+github: ant-design
+open_collective: ant-design
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 01619035..3b730ef9 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,26 +1,19 @@
version: 2
updates:
-- package-ecosystem: npm
- directory: "/"
- schedule:
- interval: daily
- time: "21:00"
- open-pull-requests-limit: 10
- ignore:
- - dependency-name: "@types/react-dom"
- versions:
- - 17.0.0
- - 17.0.1
- - 17.0.2
- - dependency-name: "@types/react"
- versions:
- - 17.0.0
- - 17.0.1
- - 17.0.2
- - 17.0.3
- - dependency-name: react
- versions:
- - 17.0.1
- - dependency-name: less
- versions:
- - 4.1.0
+ - package-ecosystem: npm
+ directory: '/'
+ schedule:
+ interval: weekly
+ day: monday
+ time: '21:00'
+ timezone: Asia/Shanghai
+ open-pull-requests-limit: 10
+
+ - package-ecosystem: github-actions
+ directory: '/'
+ schedule:
+ interval: weekly
+ day: monday
+ time: '21:00'
+ timezone: Asia/Shanghai
+ open-pull-requests-limit: 10
diff --git a/.github/workflows/react-component-ci.yml b/.github/workflows/react-component-ci.yml
index 5735e2d2..8d135ed5 100644
--- a/.github/workflows/react-component-ci.yml
+++ b/.github/workflows/react-component-ci.yml
@@ -1,6 +1,9 @@
name: ✅ test
on: [push, pull_request]
+permissions:
+ contents: read
jobs:
test:
- uses: react-component/rc-test/.github/workflows/test.yml@main
- secrets: inherit
\ No newline at end of file
+ uses: react-component/rc-test/.github/workflows/test-utoo.yml@main
+ secrets:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/react-doctor.yml b/.github/workflows/react-doctor.yml
new file mode 100644
index 00000000..097eb883
--- /dev/null
+++ b/.github/workflows/react-doctor.yml
@@ -0,0 +1,27 @@
+name: React Doctor
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
+ push:
+ branches: [master]
+
+permissions:
+ contents: read
+ pull-requests: write
+ issues: write
+ statuses: write
+
+concurrency:
+ group: react-doctor-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ react-doctor:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v7
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: millionco/react-doctor@0b4f4f4bd248a154e64eb508a48347f71154b3f3
diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml
new file mode 100644
index 00000000..4c2f17ed
--- /dev/null
+++ b/.github/workflows/surge-preview.yml
@@ -0,0 +1,54 @@
+name: Surge Preview
+
+on:
+ pull_request:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+ pull-requests: write
+ checks: write
+
+jobs:
+ preview:
+ runs-on: ubuntu-latest
+ concurrency:
+ group: surge-preview-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+ env:
+ PREVIEW: true
+ steps:
+ - uses: actions/checkout@v7
+ with:
+ persist-credentials: false
+ - name: Check Surge token
+ id: surge-token
+ env:
+ SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
+ run: |
+ if [ -n "$SURGE_TOKEN" ]; then
+ echo "enabled=true" >> "$GITHUB_OUTPUT"
+ else
+ echo "enabled=false" >> "$GITHUB_OUTPUT"
+ fi
+ - name: Build preview
+ if: ${{ steps.surge-token.outputs.enabled == 'true' }}
+ run: |
+ npm install
+ npm run build
+ - uses: afc163/surge-preview@bf90a5a86111f6311ca42f0a5a0f80fb0fb03cec
+ if: ${{ steps.surge-token.outputs.enabled == 'true' }}
+ env:
+ SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
+ with:
+ surge_token: ${{ env.SURGE_TOKEN }}
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ dist: docs-dist
+ failOnError: false
+ setCommitStatus: false
+ - name: Skip Surge preview
+ if: ${{ steps.surge-token.outputs.enabled != 'true' }}
+ run: echo "SURGE_TOKEN is not configured; skip Surge preview."
diff --git a/.gitignore b/.gitignore
index fe8ecdaf..cfa2eab2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ es/
# dumi
.dumi/tmp
.dumi/tmp-production
+docs-dist
bun.lockb
-.vscode
\ No newline at end of file
+.vscode
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 00000000..2312dc58
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+npx lint-staged
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000..c466d872
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,14 @@
+node_modules
+coverage
+docs-dist
+dist
+es
+lib
+.dumi/tmp
+.dumi/tmp-production
+.vercel
+package-lock.json
+pnpm-lock.yaml
+yarn.lock
+bun.lockb
+*.log
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..bd0a1f72
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019-present react-component
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 1874d079..2a2cde2f 100644
--- a/README.md
+++ b/README.md
@@ -1,148 +1,135 @@
-# rc-image
-
-React Image.
-
-
-[![NPM version][npm-image]][npm-url]
-[![npm download][download-image]][download-url]
-[![build status][github-actions-image]][github-actions-url]
-[![Codecov][codecov-image]][codecov-url]
-[![bundle size][bundlephobia-image]][bundlephobia-url]
-[![dumi][dumi-image]][dumi-url]
-
-[npm-image]: http://img.shields.io/npm/v/rc-image.svg?style=flat-square
-[npm-url]: http://npmjs.org/package/rc-image
-[github-actions-image]: https://github.com/react-component/image/actions/workflows/react-component-ci.yml/badge.svg
-[github-actions-url]: https://github.com/react-component/image/actions/workflows/react-component-ci.yml
-[codecov-image]: https://img.shields.io/codecov/c/gh/react-component/image?style=flat-square
-[codecov-url]: https://codecov.io/gh/react-component/image
-[download-image]: https://img.shields.io/npm/dm/rc-image.svg?style=flat-square
-[download-url]: https://npmjs.org/package/rc-image
-[bundlephobia-url]: https://bundlephobia.com/result?p=rc-image
-[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/rc-image
-[dumi-url]: https://github.com/umijs/dumi
-[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
-
-## Feature
-
-- [x] Placeholder
-- [x] Preview
-- [x] Rotate
-- [x] Zoom
-- [x] Flip
-- [x] Fallback
-- [x] Multiple Preview
-
-## install
-
-[](https://npmjs.org/package/rc-image)
+
+
@rc-component/image
+
Part of the Ant Design ecosystem.
+
🖼️ Image display, fallback, and preview tooling for React.
-## Usage
+
+
+
+
+
+
+
+
+
+
+English | 简体中文
+
+## Highlights
+
+- Supports placeholder, fallback, and preview.
+- Preview supports zoom, rotate, flip, drag, keyboard access, and custom actions.
+- `Image.PreviewGroup` supports grouped preview and custom preview items.
+- Ships compiled JavaScript, TypeScript definitions, and CSS assets.
+
+## Install
```bash
-npm install
-npm start
+npm install @rc-component/image
```
-```js
+## Usage
+
+```tsx | pure
import Image from '@rc-component/image';
+import '@rc-component/image/assets/index.css';
-export default () => (
-
-);
+export default function App() {
+ return (
+
+ );
+}
```
-## API
+## Preview Group
-| Name | Type | Default | Description |
-| --- | --- | --- | --- |
-| preview | boolean \| [PreviewType](#PreviewType) | true | Whether to show preview |
-| prefixCls | string | rc-image | Classname prefix |
-| placeholder | boolean \| ReactElement | - | if `true` will set default placeholder or use `ReactElement` set customize placeholder |
-| fallback | string | - | Load failed src |
-| previewPrefixCls | string | rc-image-preview | Preview classname prefix |
-| onError | (event: Event) => void | - | Load failed callback |
+```tsx | pure
+import Image from '@rc-component/image';
+import '@rc-component/image/assets/index.css';
+
+export default function App() {
+ return (
+
+
+
+
+ );
+}
+```
-### PreviewType
+## Examples
-| Name | Type | Default | Description |
-| --- | --- | --- | --- |
-| open | boolean | - | Whether the preview is open or not |
-| closeIcon | React.ReactNode | - | Custom close icon |
-| maskClosable | boolean | true | Whether to close preview on clicking mask |
-| src | string | - | Customize preview src |
-| movable | boolean | true | Enable drag |
-| scaleStep | number | 0.5 | The number to which the scale is increased or decreased |
-| minScale | number | 1 | Min scale |
-| maxScale | number | 50 | Max scale |
-| forceRender | boolean | - | Force render preview |
-| getContainer | string \| HTMLElement \| (() => HTMLElement) \| false | document.body | Return the mount node for preview |
-| imageRender | (originalNode: React.ReactElement, info: { transform: [TransformType](#TransformType) }) => React.ReactNode | - | Customize image |
-| actionsRender | (originalNode: React.ReactElement, info: Omit<[ToolbarRenderInfoType](#ToolbarRenderInfoType), 'current' \| 'total'>) => React.ReactNode | - | Customize toolbar |
-| onOpenChange | (open: boolean, prevVisible: boolean) => void | - | Callback when open is changed |
-| onTransform | { transform: [TransformType](#TransformType), action: [TransformAction](#TransformAction) } | - | Callback when transform is changed |
-
-## Image.PreviewGroup
-
-preview the merged src
-
-```js
-import Image from '@rc-component/image';
+Run the local dumi site:
-export default () => (
-
-
-
-
-);
+```bash
+npm install
+npm start
```
-### API
+Then open `http://localhost:8000`.
-| Name | Type | Default | Description |
+## API
+
+### Image
+
+| Property | Description | Type | Default |
| --- | --- | --- | --- |
-| preview | boolean \| [PreviewGroupType](#PreviewGroupType) | true | Whether to show preview,
current: If Preview the show img index, default 0 |
-| previewPrefixCls | string | rc-image-preview | Preview classname prefix |
-| icons | { [iconKey]?: ReactNode } | - | Icons in the top operation bar, iconKey: 'rotateLeft' \| 'rotateRight' \| 'zoomIn' \| 'zoomOut' \| 'close' \| 'left' \| 'right' |
-| fallback | string | - | Load failed src |
-| items | (string \| { src: string, alt: string, crossOrigin: string, ... })[] | - | preview group |
+| fallback | Image source used when loading fails | string | - |
+| placeholder | Placeholder before image loads | boolean \| `React.ReactElement` | - |
+| prefixCls | Component class name prefix | string | `rc-image` |
+| preview | Whether and how to show preview | boolean \| `PreviewConfig` | true |
+| previewPrefixCls | Preview class name prefix | string | `rc-image-preview` |
+| src | Image source | string | - |
+| onError | Callback when image loading fails | `(event: Event) => void` | - |
+
+Native image attributes are also supported.
-### PreviewGroupType
+### PreviewConfig
-| Name | Type | Default | Description |
+| Property | Description | Type | Default |
| --- | --- | --- | --- |
-| open | boolean | - | Whether the preview is open or not |
-| movable | boolean | true | Enable drag |
-| current | number | - | Current index |
-| closeIcon | React.ReactNode | - | Custom close icon |
-| maskClosable | boolean | true | Whether to close preview on clicking mask |
-| scaleStep | number | 0.5 | The number to which the scale is increased or decreased |
-| minScale | number | 1 | Min scale |
-| maxScale | number | 50 | Max scale |
-| forceRender | boolean | - | Force render preview |
-| getContainer | string \| HTMLElement \| (() => HTMLElement) \| false | document.body | Return the mount node for preview |
-| countRender | (current: number, total: number) => ReactNode | - | Customize count |
-| imageRender | (originalNode: React.ReactElement, info: { transform: [TransformType](#TransformType), current: number }) => React.ReactNode | - | Customize image |
-| actionsRender | (originalNode: React.ReactElement, info: [ToolbarRenderInfoType](#ToolbarRenderInfoType)) => React.ReactNode | - | Customize toolbar |
-| onOpenChange | (open: boolean, prevVisible: boolean, current: number) => void | - | Callback when open is changed |
-| onTransform | { transform: [TransformType](#TransformType), action: [TransformAction](#TransformAction) } | - | Callback when transform is changed |
+| actionsRender | Custom toolbar renderer | `(node: React.ReactElement, info: Omit) => React.ReactNode` | - |
+| closeIcon | Custom close icon | `React.ReactNode` | - |
+| cover | Custom preview cover | `React.ReactNode \| CoverConfig` | - |
+| countRender | Custom count renderer | `(current: number, total: number) => React.ReactNode` | - |
+| forceRender | Force render preview | boolean | false |
+| getContainer | Preview container | string \| HTMLElement \| `() => HTMLElement` \| false | `document.body` |
+| imageRender | Custom image renderer | `(node: React.ReactElement, info: { transform: TransformType; image: ImgInfo }) => React.ReactNode` | - |
+| maskClosable | Whether clicking mask closes preview | boolean | true |
+| maxScale | Max scale | number | 50 |
+| minScale | Min scale | number | 1 |
+| movable | Enable drag | boolean | true |
+| open | Controlled preview open state | boolean | - |
+| scaleStep | Scale step | number | 0.5 |
+| src | Custom preview image source | string | - |
+| onOpenChange | Callback when preview open state changes | `(open: boolean) => void` | - |
+| onTransform | Callback when transform changes | `(info: { transform: TransformType; action: TransformAction }) => void` | - |
+
+### Image.PreviewGroup
+
+| Property | Description | Type | Default |
+| --- | --- | --- | --- |
+| children | Image children | `React.ReactNode` | - |
+| classNames | Semantic preview popup class names | `{ popup?: Partial> }` | - |
+| fallback | Image source used when loading fails | string | - |
+| icons | Custom preview operation icons | `PreviewProps['icons']` | - |
+| items | Preview items | `(string \| ImageElementProps)[]` | - |
+| preview | Whether and how to show preview group | boolean \| `GroupPreviewConfig` | true |
+| previewPrefixCls | Preview class name prefix | string | `rc-image-preview` |
+| styles | Semantic preview popup styles | `{ popup?: Partial> }` | - |
### TransformType
-```typescript
-{
+```ts
+type TransformType = {
x: number;
y: number;
rotate: number;
scale: number;
flipX: boolean;
flipY: boolean;
-}
-```
+};
-### TransformAction
-
-```typescript
type TransformAction =
| 'flipY'
| 'flipX'
@@ -157,12 +144,20 @@ type TransformAction =
| 'doubleClick'
| 'move'
| 'dragRebound';
-```
-
-### ToolbarRenderInfoType
-```typescript
-{
+type Actions = {
+ onActive: (offset: number) => void;
+ onFlipY: () => void;
+ onFlipX: () => void;
+ onRotateLeft: () => void;
+ onRotateRight: () => void;
+ onZoomOut: () => void;
+ onZoomIn: () => void;
+ onClose: () => void;
+ onReset: () => void;
+};
+
+type ToolbarRenderInfoType = {
icons: {
prevIcon?: React.ReactNode;
nextIcon?: React.ReactNode;
@@ -173,52 +168,39 @@ type TransformAction =
zoomOutIcon: React.ReactNode;
zoomInIcon: React.ReactNode;
};
- actions: {
- onActive?: (offset: number) => void;
- onFlipY: () => void;
- onFlipX: () => void;
- onRotateLeft: () => void;
- onRotateRight: () => void;
- onZoomOut: () => void;
- onZoomIn: () => void;
- onClose: () => void;
- onReset: () => void;
- };
- transform: {
- x: number;
- y: number;
- rotate: number;
- scale: number;
- flipX: boolean;
- flipY: boolean;
- },
+ actions: Actions;
+ transform: TransformType;
current: number;
total: number;
-}
+ image: ImgInfo;
+};
```
-## Example
+## Development
-http://localhost:8003/examples/
+```bash
+npm install
+npm start
+```
-## Test Case
+The dumi site runs at `http://localhost:8000` by default.
-```
+```bash
npm test
+npm run tsc
+npm run lint
+npm run compile
+npm run build
```
-## Coverage
+## Release
-```
-npm run coverage
+```bash
+npm run prepublishOnly
```
-## License
+The release flow is handled by `@rc-component/np` through the `rc-np` command after the package build.
-rc-image is released under the MIT license.
-
-## 🤝 Contributing
+## License
-
-
-
+@rc-component/image is released under the [MIT](./LICENSE) license.
diff --git a/README.zh-CN.md b/README.zh-CN.md
new file mode 100644
index 00000000..e512d438
--- /dev/null
+++ b/README.zh-CN.md
@@ -0,0 +1,206 @@
+
+
@rc-component/image
+
Ant Design 生态的一部分。
+
🖼️ React 图片预览组件,支持预览组、缩放、旋转和自定义工具栏。
+
+
+
+
+
+
+
+
+
+
+
+English | 简体中文
+
+## 特性
+
+- 支持占位符、后备和预览。
+- 预览支持缩放、旋转、翻转、拖动、键盘访问和自定义操作。
+- `Image.PreviewGroup` 支持分组预览和自定义预览项。
+- 提供编译后的 JavaScript、TypeScript 类型定义和 CSS 资源。
+
+## 安装
+
+```bash
+npm install @rc-component/image
+```
+
+## 使用
+
+```tsx | pure
+import Image from '@rc-component/image';
+import '@rc-component/image/assets/index.css';
+
+export default function App() {
+ return (
+
+ );
+}
+```
+
+## Preview Group
+
+```tsx | pure
+import Image from '@rc-component/image';
+import '@rc-component/image/assets/index.css';
+
+export default function App() {
+ return (
+
+
+
+
+ );
+}
+```
+
+## 示例
+
+运行本地 dumi 站点:
+
+```bash
+npm install
+npm start
+```
+
+然后打开 `http://localhost:8000`。
+
+## API
+
+### Image
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| fallback | 加载失败时使用的图片源 | string | - |
+| placeholder | 图片加载前的占位内容 | boolean \| `React.ReactElement` | - |
+| prefixCls | 组件 className 前缀 | string | `rc-image` |
+| preview | 是否以及如何显示预览 | boolean \| `PreviewConfig` | true |
+| previewPrefixCls | 预览 className 前缀 | string | `rc-image-preview` |
+| src | 图片地址 | string | - |
+| onError | 图片加载失败时的回调 | `(event: Event) => void` | - |
+
+也支持原生图片属性。
+
+### PreviewConfig
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| actionsRender | 自定义工具栏渲染器 | `(node: React.ReactElement, info: Omit) => React.ReactNode` | - |
+| closeIcon | 自定义关闭图标 | `React.ReactNode` | - |
+| cover | 自定义预览封面 | `React.ReactNode \| CoverConfig` | - |
+| countRender | 自定义计数渲染器 | `(current: number, total: number) => React.ReactNode` | - |
+| forceRender | 强制渲染预览 | boolean | false |
+| getContainer | 预览容器 | string \| HTMLElement \| `() => HTMLElement` \| false | `document.body` |
+| imageRender | 自定义图像渲染器 | `(node: React.ReactElement, info: { transform: TransformType; image: ImgInfo }) => React.ReactNode` | - |
+| maskClosable | 单击蒙版是否关闭预览 | boolean | true |
+| maxScale | 最大缩放比例 | number | 50 |
+| minScale | 最小缩放比例 | number | 1 |
+| movable | 启用拖动 | boolean | true |
+| open | 受控预览打开状态 | boolean | - |
+| scaleStep | 缩放步长 | number | 0.5 |
+| src | 自定义预览图像源 | string | - |
+| onOpenChange | 预览打开状态变化时回调 | `(open: boolean) => void` | - |
+| onTransform | 变换变化时的回调 | `(info: { transform: TransformType; action: TransformAction }) => void` | - |
+
+### Image.PreviewGroup
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| children | 子元素 | `React.ReactNode` | - |
+| classNames | 语义预览弹层 className | `{ popup?: Partial> }` | - |
+| fallback | 加载失败时使用的图片源 | string | - |
+| icons | 自定义预览操作图标 | `PreviewProps['icons']` | - |
+| items | 预览项目 | `(string \| ImageElementProps)[]` | - |
+| preview | 是否以及如何显示预览 group | boolean \| `GroupPreviewConfig` | true |
+| previewPrefixCls | 预览 className 前缀 | string | `rc-image-preview` |
+| styles | 语义预览弹层样式 | `{ popup?: Partial> }` | - |
+
+### TransformType
+
+```ts
+type TransformType = {
+ x: number;
+ y: number;
+ rotate: number;
+ scale: number;
+ flipX: boolean;
+ flipY: boolean;
+};
+
+type TransformAction =
+ | 'flipY'
+ | 'flipX'
+ | 'rotateLeft'
+ | 'rotateRight'
+ | 'zoomIn'
+ | 'zoomOut'
+ | 'close'
+ | 'prev'
+ | 'next'
+ | 'wheel'
+ | 'doubleClick'
+ | 'move'
+ | 'dragRebound';
+
+type Actions = {
+ onActive: (offset: number) => void;
+ onFlipY: () => void;
+ onFlipX: () => void;
+ onRotateLeft: () => void;
+ onRotateRight: () => void;
+ onZoomOut: () => void;
+ onZoomIn: () => void;
+ onClose: () => void;
+ onReset: () => void;
+};
+
+type ToolbarRenderInfoType = {
+ icons: {
+ prevIcon?: React.ReactNode;
+ nextIcon?: React.ReactNode;
+ flipYIcon: React.ReactNode;
+ flipXIcon: React.ReactNode;
+ rotateLeftIcon: React.ReactNode;
+ rotateRightIcon: React.ReactNode;
+ zoomOutIcon: React.ReactNode;
+ zoomInIcon: React.ReactNode;
+ };
+ actions: Actions;
+ transform: TransformType;
+ current: number;
+ total: number;
+ image: ImgInfo;
+};
+```
+
+## 本地开发
+
+```bash
+npm install
+npm start
+```
+
+dumi 站点默认运行在 `http://localhost:8000`。
+
+```bash
+npm test
+npm run tsc
+npm run lint
+npm run compile
+npm run build
+```
+
+## 发布
+
+```bash
+npm run prepublishOnly
+```
+
+包构建完成后,发布流程由 `@rc-component/np` 通过 `rc-np` 命令处理。
+
+## 许可证
+
+@rc-component/image 基于 [MIT](./LICENSE) 许可证发布。
diff --git a/now.json b/now.json
deleted file mode 100644
index 4d507fa8..00000000
--- a/now.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "version": 2,
- "name": "rc-image",
- "builds": [
- {
- "src": "package.json",
- "use": "@now/static-build",
- "config": { "distDir": "dist" }
- }
- ],
- "routes": [{ "src": "/(.*)", "dest": "/dist/$1" }]
-}
diff --git a/package.json b/package.json
index 07a0c689..355d10cf 100644
--- a/package.json
+++ b/package.json
@@ -8,36 +8,38 @@
"react-image",
"image"
],
- "homepage": "http://github.com/react-component/image",
+ "homepage": "https://react-component.github.io/image",
"bugs": {
- "url": "http://github.com/react-component/image/issues"
+ "url": "https://github.com/react-component/image/issues"
},
"repository": {
"type": "git",
- "url": "git@github.com:react-component/image.git"
+ "url": "https://github.com/react-component/image.git"
},
"license": "MIT",
"main": "./lib/index",
"module": "./es/index",
- "types": "./lib/index.d.ts",
+ "types": "./es/index.d.ts",
"files": [
"assets/*.css",
"es",
"lib"
],
"scripts": {
+ "build": "npm run docs:build",
"compile": "father build && lessc assets/index.less assets/index.css",
"coverage": "rc-test --coverage",
"docs:build": "dumi build",
"docs:deploy": "gh-pages -d docs-dist",
"lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md",
- "now-build": "npm run docs:build",
"prepublishOnly": "npm run compile && rc-np",
- "prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
+ "prettier": "prettier --write --ignore-unknown .",
"start": "dumi dev",
"test": "rc-test",
"test:update": "rc-test -u",
- "tsc": "bunx tsc --noEmit"
+ "tsc": "tsc --noEmit",
+ "docs:build:gh-pages": "GH_PAGES=1 npm run docs:build",
+ "prepare": "husky"
},
"dependencies": {
"@rc-component/motion": "^1.0.0",
@@ -49,26 +51,36 @@
"@ant-design/icons": "^5.0.1",
"@rc-component/dialog": "^1.7.0",
"@rc-component/father-plugin": "^2.2.0",
- "@rc-component/np": "^1.0.0",
- "@testing-library/jest-dom": "^6.4.0",
- "@testing-library/react": "^15.0.6",
- "@types/jest": "^30.0.0",
- "@types/node": "^24.5.2",
- "@types/react": "^18.0.0",
- "@types/react-dom": "^18.0.0",
+ "prettier": "^3.9.0",
+ "@rc-component/np": "^1.0.4",
+ "@testing-library/jest-dom": "^6.9.1",
+ "@testing-library/react": "^15.0.7",
+ "@types/jest": "^29.5.14",
+ "@types/node": "^26.0.1",
+ "@types/react": "^18.3.31",
+ "@types/react-dom": "^18.3.7",
"@umijs/fabric": "^4.0.1",
- "dumi": "^2.1.4",
- "eslint": "^8.57.0",
- "father": "^4.0.0",
- "glob": "^11.0.3",
- "less": "^4.1.3",
- "rc-test": "^7.0.3",
- "react": "^18.0.0",
- "react-dom": "^18.0.0",
- "typescript": "^5.3.3"
+ "dumi": "^2.4.35",
+ "eslint": "^8.57.1",
+ "father": "^4.6.23",
+ "gh-pages": "^6.3.0",
+ "glob": "^13.0.6",
+ "less": "^4.6.7",
+ "rc-test": "^7.1.3",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "typescript": "^5.9.3",
+ "husky": "^9.1.7",
+ "lint-staged": "^16.4.0"
},
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "lint-staged": {
+ "*": "prettier --write --ignore-unknown"
}
}
diff --git a/tsconfig.json b/tsconfig.json
index cbdc6cdf..f17405ba 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -8,10 +8,29 @@
"skipLibCheck": true,
"esModuleInterop": true,
"paths": {
- "@/*": ["src/*"],
- "@@/*": [".dumi/tmp/*"],
- "@rc-component/image": ["src/index.ts"]
+ "@/*": [
+ "src/*"
+ ],
+ "@@/*": [
+ ".dumi/tmp/*"
+ ],
+ "@rc-component/image": [
+ "src/index.ts"
+ ]
},
- "types": ["@testing-library/jest-dom", "jest", "node"]
- }
+ "types": [
+ "@testing-library/jest-dom",
+ "jest",
+ "node"
+ ],
+ "ignoreDeprecations": "5.0"
+ },
+ "include": [
+ ".dumirc.ts",
+ ".fatherrc.ts",
+ "docs",
+ "src",
+ "tests",
+ "typings.d.ts"
+ ]
}
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 00000000..5f9139ef
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,6 @@
+{
+ "framework": "umijs",
+ "installCommand": "npm install",
+ "buildCommand": "npm run build",
+ "outputDirectory": "docs-dist"
+}