Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support reset action in toolbarRender #345

Merged
merged 6 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ type TransformAction =
onRotateRight: () => void;
onZoomOut: () => void;
onZoomIn: () => void;
onClose: () => void;
onReset: (type: 'flipX' | 'flipY' | 'rotate' | 'zoom') => void;
};
transform: {
x: number;
Expand Down
22 changes: 14 additions & 8 deletions docs/examples/toolbarRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,26 @@ export default function ToolbarRender() {
onZoomIn,
onZoomOut,
onClose,
onReset,
},
},
) => {
return (
<div
style={{ position: 'fixed', display: 'flex', bottom: 0, width: '100%', gap: 10 }}
style={{ position: 'fixed', display: 'flex', bottom: 100, width: '100%', gap: 10, justifyContent: 'center' }}
>
<div onClick={onFlipY}>flipY</div>
<div onClick={onFlipX}>flipX</div>
<div onClick={onRotateLeft}>rotateLeft</div>
<div onClick={onRotateRight}>rotateRight</div>
<div onClick={onZoomIn}>zoomIn</div>
<div onClick={onZoomOut}>zoomOut</div>
<div onClick={onClose}>close</div>
<button onClick={onFlipY}>flipY</button>
<button onClick={() => onReset("flipY")}>reset flipY</button>
<button onClick={onFlipX}>flipX</button>
<button onClick={() => onReset("flipX")}>reset flipX</button>
<button onClick={onRotateLeft}>rotateLeft</button>
<button onClick={onRotateRight}>rotateRight</button>
<button onClick={() => onReset("rotate")}>reset rotate</button>
<button onClick={onZoomIn}>zoomIn</button>
<button onClick={onZoomOut}>zoomOut</button>
<button onClick={() => onReset("zoom")}>reset zoom</button>
<button onClick={onClose}>close</button>

</div>
);
},
Expand Down
4 changes: 4 additions & 0 deletions src/Operations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface OperationsProps
onRotateLeft: () => void;
onFlipX: () => void;
onFlipY: () => void;
onReset: (type: "flipX" | "flipY" | "rotate" | "zoom") => void;
kiner-tang marked this conversation as resolved.
Show resolved Hide resolved
toolbarRender: (
originalNode: React.ReactElement,
info: ToolbarRenderInfoType | Omit<ToolbarRenderInfoType, 'current' | 'total'>,
Expand Down Expand Up @@ -73,6 +74,7 @@ const Operations: React.FC<OperationsProps> = props => {
onRotateLeft,
onFlipX,
onFlipY,
onReset,
toolbarRender,
zIndex,
image,
Expand Down Expand Up @@ -209,6 +211,8 @@ const Operations: React.FC<OperationsProps> = props => {
onRotateRight,
onZoomOut,
onZoomIn,
onReset,
onClose
},
transform,
...(groupContext ? { current, total: count } : {}),
Expand Down
26 changes: 24 additions & 2 deletions src/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import Dialog from 'rc-dialog';
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import KeyCode from 'rc-util/lib/KeyCode';
import React, { useContext, useEffect, useRef, useState } from 'react';
import type { ImgInfo } from './Image';
import Operations from './Operations';
import { PreviewGroupContext } from './context';
import type { TransformAction, TransformType } from './hooks/useImageTransform';
import useImageTransform from './hooks/useImageTransform';
import useMouseEvent from './hooks/useMouseEvent';
import useStatus from './hooks/useStatus';
import useTouchEvent from './hooks/useTouchEvent';
import type { ImgInfo } from './Image';
import Operations from './Operations';
import { BASE_SCALE_RATIO } from './previewConfig';

export type ToolbarRenderInfoType = {
Expand All @@ -30,6 +30,8 @@ export type ToolbarRenderInfoType = {
onRotateRight: () => void;
onZoomOut: () => void;
onZoomIn: () => void;
onClose: () => void;
onReset: (type: 'flipX' | 'flipY' | 'rotate' | 'zoom') => void;
};
transform: TransformType;
current: number;
Expand Down Expand Up @@ -184,6 +186,8 @@ const Preview: React.FC<PreviewProps> = props => {
dispatchZoomChange(BASE_SCALE_RATIO / (BASE_SCALE_RATIO + scaleStep), 'zoomOut');
};

// const onReset =
kiner-tang marked this conversation as resolved.
Show resolved Hide resolved

const onRotateRight = () => {
updateTransform({ rotate: rotate + 90 }, 'rotateRight');
};
Expand All @@ -200,6 +204,23 @@ const Preview: React.FC<PreviewProps> = props => {
updateTransform({ flipY: !transform.flipY }, 'flipY');
};

const onReset = (type: 'flipX' | 'flipY' | 'rotate' | 'zoom') => {
switch (type) {
case 'flipX':
resetTransform("flipX");
break;
case 'flipY':
resetTransform("flipY");
break;
case 'rotate':
resetTransform("rotateLeft");
break;
case 'zoom':
resetTransform("zoomIn");
break;
}
};

const onSwitchLeft = (event?: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
event?.preventDefault();
event?.stopPropagation();
Expand Down Expand Up @@ -337,6 +358,7 @@ const Preview: React.FC<PreviewProps> = props => {
onFlipX={onFlipX}
onFlipY={onFlipY}
onClose={onClose}
onReset={onReset}
zIndex={restProps.zIndex !== undefined ? restProps.zIndex + 1 : undefined}
image={image}
/>
Expand Down
99 changes: 95 additions & 4 deletions tests/preview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -792,12 +792,20 @@ describe('Preview', () => {
width={200}
height={200}
preview={{
toolbarRender: (_, { icons, image }) => {
toolbarRender: (_, { icons, image, actions }) => {
printImage(image);
return (
<>
{icons.flipYIcon}
{icons.flipXIcon}
<div id="flipY" onClick={() => actions.onFlipY()}>{icons.flipYIcon}</div>
<div id="resetFlipY" onClick={() => actions.onReset("flipY")}>reset FlipY</div>
<div id="flipX" onClick={() => actions.onFlipX()}>{icons.flipXIcon}</div>
<div id="resetFlipX" onClick={() => actions.onReset("flipX")}>reset FlipX</div>
<div id="zoomIn" onClick={() => actions.onZoomIn()}>{icons.zoomInIcon}</div>
<div id="zoomOut" onClick={() => actions.onZoomOut()}>{icons.zoomOutIcon}</div>
<div id="resetZoom" onClick={() => actions.onReset("zoom")}>reset zoom</div>
<div id="rotateLeft" onClick={() => actions.onRotateLeft()}>{icons.rotateLeftIcon}</div>
<div id="rotateRight" onClick={() => actions.onRotateRight()}>{icons.rotateRightIcon}</div>
<div id="resetRotate" onClick={() => actions.onReset("rotate")}>reset rotate</div>
</>
);
},
Expand All @@ -810,13 +818,96 @@ describe('Preview', () => {
jest.runAllTimers();
});

expect(document.querySelectorAll('.rc-image-preview-operations-operation')).toHaveLength(2);
expect(printImage).toHaveBeenCalledWith({
alt: 'alt',
height: 200,
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
width: 200,
});
// flipY
fireEvent.click(document.getElementById('flipY'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, -1, 1) rotate(0deg)',
});
// reset flipY
fireEvent.click(document.getElementById('resetFlipY'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});
// flipX
fireEvent.click(document.getElementById('flipX'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(-1, 1, 1) rotate(0deg)',
});
// reset flipX
fireEvent.click(document.getElementById('resetFlipX'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});
// zoomIn
fireEvent.click(document.getElementById('zoomIn'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(-206px, -142px, 0) scale3d(1.5, 1.5, 1) rotate(0deg)',
});
// zoomOut
fireEvent.click(document.getElementById('zoomOut'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});
// reset zoom
fireEvent.click(document.getElementById('zoomIn'));
act(() => {
jest.runAllTimers();
});
fireEvent.click(document.getElementById('resetZoom'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});
// rotateLeft
fireEvent.click(document.getElementById('rotateLeft'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(-90deg)',
});
// reset rotate
fireEvent.click(document.getElementById('resetRotate'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(0deg)',
});
// rotateRight
fireEvent.click(document.getElementById('rotateRight'));
act(() => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-image-preview-img')).toHaveStyle({
transform: 'translate3d(0px, 0px, 0) scale3d(1, 1, 1) rotate(90deg)',
});
});

it('onTransform should be triggered when transform change', () => {
Expand Down