Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/react-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ jobs:
fetch-depth: 0
persist-credentials: false
- uses: millionco/react-doctor@0b4f4f4bd248a154e64eb508a48347f71154b3f3
with:
version: 0.7.4
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Native image attributes are also supported.
| open | Controlled preview open state | boolean | - |
| scaleStep | Scale step | number | 0.5 |
| src | Custom preview image source | string | - |
| wheel | Enable mouse wheel zoom | boolean | true |
| onOpenChange | Callback when preview open state changes | `(open: boolean) => void` | - |
| onTransform | Callback when transform changes | `(info: { transform: TransformType; action: TransformAction }) => void` | - |

Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ npm start
| open | 受控预览打开状态 | boolean | - |
| scaleStep | 缩放步长 | number | 0.5 |
| src | 自定义预览图像源 | string | - |
| wheel | 启用鼠标滚轮缩放 | boolean | true |
| onOpenChange | 预览打开状态变化时回调 | `(open: boolean) => void` | - |
| onTransform | 变换变化时的回调 | `(info: { transform: TransformType; action: TransformAction }) => void` | - |

Expand Down
5 changes: 5 additions & 0 deletions src/Preview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ export interface InternalPreviewConfig {
minScale?: number;
maxScale?: number;

/** Whether to enable mouse wheel zoom. Default is true. */
wheel?: boolean;

// Display
motionName?: string;
open?: boolean;
Expand Down Expand Up @@ -196,6 +199,7 @@ const Preview: React.FC<PreviewProps> = props => {
styles = {},
mousePosition,
zIndex,
wheel = true,
focusTrap = true,
} = props;

Expand Down Expand Up @@ -223,6 +227,7 @@ const Preview: React.FC<PreviewProps> = props => {
transform,
updateTransform,
dispatchZoomChange,
wheel,
);
const { isTouching, onTouchStart, onTouchMove, onTouchEnd } = useTouchEvent(
imgRef,
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useMouseEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function useMouseEvent(
transform: TransformType,
updateTransform: UpdateTransformFunc,
dispatchZoomChange: DispatchZoomChangeFunc,
wheel: boolean = true,
) {
const { rotate, scale, x, y } = transform;

Expand Down Expand Up @@ -83,7 +84,7 @@ export default function useMouseEvent(
};

const onWheel = (event: React.WheelEvent<HTMLImageElement>) => {
if (!open || event.deltaY == 0) return;
if (!open || !wheel || event.deltaY == 0) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use strict equality === instead of loose equality == for comparing event.deltaY with 0. This is a standard TypeScript best practice to avoid type coercion and ensure type safety.

Suggested change
if (!open || !wheel || event.deltaY == 0) return;
if (!open || !wheel || event.deltaY === 0) return;

// Scale ratio depends on the deltaY size
const scaleRatio = Math.abs(event.deltaY / 100);
// Limit the maximum scale ratio
Expand Down
73 changes: 73 additions & 0 deletions tests/preview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,79 @@ describe('Preview', () => {
});
});

it('should zoom with wheel when wheel is explicitly true', () => {
const { container } = render(
<Image
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
preview={{
open: true,
wheel: true,
}}
/>,
);
fireEvent.click(container.querySelector('.rc-image'));
act(() => {
jest.runAllTimers();
});

expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});

// Wheel zoom should work when wheel is true
fireEvent.wheel(document.querySelector('.rc-image-preview-img'), {
deltaY: -50,
});

act(() => {
jest.runAllTimers();
});

// Scale should change to 1.25
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1.25, 1.25, 1) rotate(0deg)',
});
});

it('should not zoom with wheel when wheel is false', () => {
const { container } = render(
<Image
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
preview={{
open: true,
wheel: false,
}}
/>,
);

expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});

// Wheel zoom should not work when wheel is false
fireEvent.wheel(document.querySelector('.rc-image-preview-img'), {
deltaY: -50,
});

act(() => {
jest.runAllTimers();
});

// Scale should remain 1
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});

// But zoom in button should still work
fireEvent.click(document.querySelectorAll('.rc-image-preview-actions-action')[5]);
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(-256px, -192px, 0) scale3d(1.5, 1.5, 1) rotate(0deg)',
});
});

it('scaleStep = 1', () => {
const { container } = render(
<Image
Expand Down
Loading