Skip to content

Commit

Permalink
feat(image-viewer): feat add defaultScale and closeOnEscKeydown (#2652)
Browse files Browse the repository at this point in the history
  • Loading branch information
HaixingOoO authored Dec 13, 2023
1 parent 14cef8a commit d5b3cc7
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/image-viewer/ImageViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const ImageViewer: React.FC<ImageViewerProps> = (originalProps) => {
closeOnOverlay={props.closeOnOverlay}
closeBtn={props.closeBtn}
showOverlay={props.showOverlay}
closeOnEscKeydown={props.closeOnEscKeydown}
onClose={close}
onOpen={open}
/>,
Expand Down
6 changes: 4 additions & 2 deletions src/image-viewer/ImageViewerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ interface ImageModalProps {
isMini: boolean;
draggable: boolean;
closeBtn: boolean | TNode;
closeOnEscKeydown?: boolean;
onIndexChange?: (index: number, context: { trigger: 'prev' | 'next' }) => void;
}

Expand All @@ -309,6 +310,7 @@ export const ImageModal: React.FC<ImageModalProps> = (props) => {
onClose,
visible,
title,
closeOnEscKeydown,
...resProps
} = props;
const { classPrefix } = useConfig();
Expand Down Expand Up @@ -357,10 +359,10 @@ export const ImageModal: React.FC<ImageModalProps> = (props) => {
case 'ArrowDown':
return onZoomOut();
case 'Escape':
return onClose?.({ trigger: 'esc', e: event });
return closeOnEscKeydown && onClose?.({ trigger: 'esc', e: event });
}
},
[next, onClose, prev, onZoom, onZoomOut],
[next, onClose, prev, onZoom, onZoomOut, closeOnEscKeydown],
);

useEffect(() => {
Expand Down
53 changes: 52 additions & 1 deletion src/image-viewer/__tests__/image-viewer.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { render, act, fireEvent, waitFor, vi, mockTimeout } from '@test/utils';
import { render, act, fireEvent, waitFor, vi, mockTimeout, mockDelay } from '@test/utils';
import userEvent from '@testing-library/user-event';

import { ImageViewer } from '../index';
Expand Down Expand Up @@ -175,4 +175,55 @@ describe('ImageViewerModal', () => {
});
expect(getByText('closeBtn')).toBeTruthy();
});

test('closeOnEscKeydown is false', async () => {
const user = userEvent.setup();
const BasicImageViewer = () => {
const trigger = ({ onOpen }) => <span onClick={onOpen}>{triggerText}</span>;
return <ImageViewer trigger={trigger} images={[imgUrl, imgUrl2]} closeOnEscKeydown={false} />;
};
const { getByText } = render(<BasicImageViewer />);

// 模拟鼠标点击
act(() => {
fireEvent.click(getByText(triggerText));
});
expect(document.querySelector('.t-image-viewer-preview-image')).toBeInTheDocument();

// 模拟键盘事件
await user.type(document.body, '{Escape}');
await mockDelay(300);
expect(document.querySelector('.t-image-viewer-preview-image')).toBeInTheDocument();
});

test('imageScale defaultScale', async () => {
const BasicImageViewer = () => {
const trigger = ({ onOpen }) => <span onClick={onOpen}>{triggerText}</span>;
return (
<ImageViewer
trigger={trigger}
images={[imgUrl, imgUrl2]}
imageScale={{
max: 2,
min: 0.5,
step: 0.5,
defaultScale: 2,
}}
/>
);
};
const { getByText } = render(<BasicImageViewer />);

// 模拟鼠标点击
act(() => {
fireEvent.click(getByText(triggerText));
});

await mockDelay();

expect(document.querySelector('.t-image-viewer__modal-image')).toBeInTheDocument();
expect(document.querySelector('.t-image-viewer__modal-image')).toHaveStyle({
transform: 'rotateZ(0deg) scale(2)',
});
});
});
1 change: 1 addition & 0 deletions src/image-viewer/defaultProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TdImageViewerProps } from './type';

export const imageViewerDefaultProps: TdImageViewerProps = {
closeBtn: true,
closeOnEscKeydown: true,
draggable: undefined,
images: [],
defaultIndex: 0,
Expand Down
12 changes: 11 additions & 1 deletion src/image-viewer/hooks/useImageScale.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { ImageScale } from '../type';

const useImageScale = (imageScale) => {
const useImageScale = (imageScale: ImageScale) => {
const result: ImageScale = {
...imageScale,
max: 2,
min: 0.5,
step: 0.5,
};
if (imageScale?.min !== undefined) result.min = imageScale.min;
if (imageScale?.max !== undefined) result.max = imageScale.max;
if (imageScale?.step !== undefined) result.step = imageScale.step;
// defaultScale 不能超出本身设置的最大和最小值
if (imageScale?.defaultScale !== undefined) {
if (imageScale.defaultScale > result.max) {
result.defaultScale = result.max;
}
if (imageScale.defaultScale < result.min) {
result.defaultScale = result.min;
}
}
return result;
};

Expand Down
7 changes: 4 additions & 3 deletions src/image-viewer/hooks/useScale.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// 缩放控制
import { useCallback, useState } from 'react';
import { ImageScale } from '../type';

const useScale = (imageScale) => {
const [scale, setScale] = useState(1);
const useScale = (imageScale: ImageScale) => {
const [scale, setScale] = useState(() => imageScale.defaultScale ?? 1);
const onZoom = useCallback(() => {
setScale((scale) => {
const newScale = scale + imageScale.step;
Expand All @@ -21,7 +22,7 @@ const useScale = (imageScale) => {
});
}, [imageScale]);

const onResetScale = useCallback(() => setScale(1), []);
const onResetScale = useCallback(() => setScale(imageScale.defaultScale ?? 1), [imageScale]);

return {
scale,
Expand Down
7 changes: 4 additions & 3 deletions src/image-viewer/image-viewer.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ name | type | default | description | required
className | String | - | 类名 | N
style | Object | - | 样式,Typescript:`React.CSSProperties` | N
closeBtn | TNode | true | Typescript:`boolean \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
closeOnEscKeydown | Boolean | true | trigger image viewer close event on `ESC` keydown | N
closeOnOverlay | Boolean | - | \- | N
draggable | Boolean | undefined | \- | N
imageScale | Object | - | Typescript:`ImageScale` `interface ImageScale { max: number; min: number; step: number }`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
imageScale | Object | - | Typescript:`ImageScale` `interface ImageScale { max: number; min: number; step: number; defaultScale?: number; }`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
images | Array | [] | Typescript:`Array<string \| File \| ImageInfo>` `interface ImageInfo { mainImage: string \| File; thumbnail?: string \| File; download?: boolean }`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
index | Number | 0 | \- | N
defaultIndex | Number | 0 | uncontrolled property | N
Expand All @@ -20,8 +21,8 @@ showOverlay | Boolean | undefined | \- | N
title | TNode | - | preview title。Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
trigger | TNode | - | trigger element。Typescript:`TNode \| TNode<{ open: () => void }>`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
viewerScale | Object | - | Typescript:`ImageViewerScale` `interface ImageViewerScale { minWidth: number; minHeight: number }`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
visible | Boolean | false | \- | N
defaultVisible | Boolean | false | uncontrolled property | N
visible | Boolean | false | hide or show image viewer | N
defaultVisible | Boolean | false | hide or show image viewer。uncontrolled property | N
zIndex | Number | - | \- | N
onClose | Function | | Typescript:`(context: { trigger: 'close-btn' \| 'overlay' \| 'esc'; e: MouseEvent \| KeyboardEvent }) => void`<br/> | N
onIndexChange | Function | | Typescript:`(index: number, context: { trigger: 'prev' \| 'next' \| 'current' }) => void`<br/> | N
3 changes: 2 additions & 1 deletion src/image-viewer/image-viewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
className | String | - | 类名 | N
style | Object | - | 样式,TS 类型:`React.CSSProperties` | N
closeBtn | TNode | true | 是否展示关闭按钮,值为 `true` 显示默认关闭按钮;值为 `false` 则不显示关闭按钮;也可以完全自定义关闭按钮。TS 类型:`boolean \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
closeOnEscKeydown | Boolean | true | 按下 ESC 时是否触发图片预览器关闭事件 | N
closeOnOverlay | Boolean | - | 是否在点击遮罩层时,触发预览关闭 | N
draggable | Boolean | undefined | 是否允许拖拽调整位置。`mode=modal` 时,默认不允许拖拽;`mode=modeless` 时,默认允许拖拽 | N
imageScale | Object | - | 图片缩放相关配置。`imageScale.max` 缩放的最大比例;`imageScale.min` 缩放的最小比例;`imageScale.step` 缩放的步长速度。TS 类型:`ImageScale` `interface ImageScale { max: number; min: number; step: number }`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
imageScale | Object | - | 图片缩放相关配置。`imageScale.max` 缩放的最大比例;`imageScale.min` 缩放的最小比例;`imageScale.step` 缩放的步长速度; `imageScale.defaultScale` 默认的缩放比例。TS 类型:`ImageScale` `interface ImageScale { max: number; min: number; step: number; defaultScale?: number; }`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
images | Array | [] | 图片数组。`mainImage` 表示主图,必传;`thumbnail` 表示缩略图,如果不存在,则使用主图显示;`download` 是否允许下载图片,默认允许下载。示例: `['img_url_1', 'img_url_2']``[{ thumbnail: 'small_image_url', mainImage: 'big_image_url', download: false }]`。TS 类型:`Array<string \| File \| ImageInfo>` `interface ImageInfo { mainImage: string \| File; thumbnail?: string \| File; download?: boolean }`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/image-viewer/type.ts) | N
index | Number | 0 | 当前预览图片所在的下标 | N
defaultIndex | Number | 0 | 当前预览图片所在的下标。非受控属性 | N
Expand Down
8 changes: 7 additions & 1 deletion src/image-viewer/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export interface TdImageViewerProps {
* @default true
*/
closeBtn?: TNode;
/**
* 按下 ESC 时是否触发图片预览器关闭事件
* @default true
*/
closeOnEscKeydown?: boolean;
/**
* 是否在点击遮罩层时,触发预览关闭
*/
Expand All @@ -22,7 +27,7 @@ export interface TdImageViewerProps {
*/
draggable?: boolean;
/**
* 图片缩放相关配置。`imageScale.max` 缩放的最大比例;`imageScale.min` 缩放的最小比例;`imageScale.step` 缩放的步长速度
* 图片缩放相关配置。`imageScale.max` 缩放的最大比例;`imageScale.min` 缩放的最小比例;`imageScale.step` 缩放的步长速度; `imageScale.defaultScale` 默认的缩放比例
*/
imageScale?: ImageScale;
/**
Expand Down Expand Up @@ -94,6 +99,7 @@ export interface ImageScale {
max: number;
min: number;
step: number;
defaultScale?: number;
}

export interface ImageInfo {
Expand Down

0 comments on commit d5b3cc7

Please sign in to comment.