Skip to content

Commit a4c58de

Browse files
authored
feat: support classnames and styles (#378)
* feat: support classnames and styles * fix * Temporarily used in PurePanel, not used externally
1 parent a93f870 commit a4c58de

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

src/Image.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export interface ImagePreviewType
3535
getContainer?: GetContainer | false;
3636
mask?: React.ReactNode;
3737
maskClassName?: string;
38+
classNames?: Partial<Record<SemanticName, string>>;
39+
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
3840
icons?: PreviewProps['icons'];
3941
scaleStep?: number;
4042
movable?: boolean;
@@ -49,6 +51,8 @@ export interface ImagePreviewType
4951
) => React.ReactNode;
5052
}
5153

54+
export type SemanticName = 'root' | 'actions' | 'mask';
55+
5256
export interface ImageProps
5357
extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'placeholder' | 'onClick'> {
5458
// Original
@@ -92,7 +96,6 @@ const ImageInternal: CompoundedComponent<ImageProps> = props => {
9296
wrapperClassName,
9397
wrapperStyle,
9498
rootClassName,
95-
9699
...otherProps
97100
} = props;
98101

@@ -104,6 +107,8 @@ const ImageInternal: CompoundedComponent<ImageProps> = props => {
104107
getContainer: getPreviewContainer = undefined,
105108
mask: previewMask,
106109
maskClassName,
110+
classNames: imageClassNames,
111+
styles,
107112
movable,
108113
icons,
109114
scaleStep,
@@ -222,9 +227,10 @@ const ImageInternal: CompoundedComponent<ImageProps> = props => {
222227
{/* Preview Click Mask */}
223228
{previewMask && canPreview && (
224229
<div
225-
className={cn(`${prefixCls}-mask`, maskClassName)}
230+
className={cn(`${prefixCls}-mask`, maskClassName, imageClassNames?.mask)}
226231
style={{
227232
display: style?.display === 'none' ? 'none' : undefined,
233+
...styles?.mask,
228234
}}
229235
>
230236
{previewMask}
@@ -252,6 +258,8 @@ const ImageInternal: CompoundedComponent<ImageProps> = props => {
252258
imageRender={imageRender}
253259
imgCommonProps={imgCommonProps}
254260
toolbarRender={toolbarRender}
261+
classNames={imageClassNames}
262+
styles={styles}
255263
{...dialogProps}
256264
/>
257265
)}

src/Operations.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import CSSMotion from '@rc-component/motion';
44
import KeyCode from '@rc-component/util/lib/KeyCode';
55
import * as React from 'react';
66
import { useContext } from 'react';
7-
import type { ImgInfo } from './Image';
7+
import type { ImgInfo, SemanticName } from './Image';
88
import type { PreviewProps, ToolbarRenderInfoType } from './Preview';
99
import { PreviewGroupContext } from './context';
1010
import type { TransformType } from './hooks/useImageTransform';
11+
import classNames from 'classnames';
1112

1213
type OperationType =
1314
| 'prev'
@@ -61,6 +62,8 @@ interface OperationsProps
6162
) => React.ReactNode;
6263
zIndex?: number;
6364
image?: ImgInfo;
65+
classNames?: Partial<Record<SemanticName, string>>;
66+
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
6467
}
6568

6669
const Operations: React.FC<OperationsProps> = props => {
@@ -93,6 +96,8 @@ const Operations: React.FC<OperationsProps> = props => {
9396
toolbarRender,
9497
zIndex,
9598
image,
99+
classNames: imageClassNames,
100+
styles,
96101
} = props;
97102
const groupContext = useContext(PreviewGroupContext);
98103
const { rotateLeft, rotateRight, zoomIn, zoomOut, close, left, right, flipX, flipY } = icons;
@@ -195,7 +200,10 @@ const Operations: React.FC<OperationsProps> = props => {
195200
});
196201

197202
const toolbarNode = (
198-
<div className={`${prefixCls}-operations`}>
203+
<div
204+
className={classNames(`${prefixCls}-operations`, imageClassNames?.actions)}
205+
style={styles?.actions}
206+
>
199207
{flipYNode}
200208
{flipXNode}
201209
{rotateLeftNode}

src/Preview.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Dialog from '@rc-component/dialog';
33
import KeyCode from '@rc-component/util/lib/KeyCode';
44
import classnames from 'classnames';
55
import React, { useContext, useEffect, useRef, useState } from 'react';
6-
import type { ImgInfo } from './Image';
6+
import type { ImgInfo, SemanticName } from './Image';
77
import Operations from './Operations';
88
import { PreviewGroupContext } from './context';
99
import type { TransformAction, TransformType } from './hooks/useImageTransform';
@@ -41,7 +41,7 @@ export type ToolbarRenderInfoType = {
4141
image: ImgInfo;
4242
};
4343

44-
export interface PreviewProps extends Omit<IDialogPropTypes, 'onClose'> {
44+
export interface PreviewProps extends Omit<IDialogPropTypes, 'onClose' | 'styles' | 'classNames'> {
4545
imgCommonProps?: React.ImgHTMLAttributes<HTMLImageElement>;
4646
src?: string;
4747
alt?: string;
@@ -81,6 +81,11 @@ export interface PreviewProps extends Omit<IDialogPropTypes, 'onClose'> {
8181
info: ToolbarRenderInfoType,
8282
) => React.ReactNode;
8383
onChange?: (current, prev) => void;
84+
classNames?: Partial<Record<SemanticName, string>>;
85+
styles?: Partial<Record<SemanticName, React.CSSProperties>> & {
86+
/** Temporarily used in PurePanel, not used externally by antd */
87+
wrapper?: React.CSSProperties;
88+
};
8489
}
8590

8691
interface PreviewImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
@@ -133,6 +138,8 @@ const Preview: React.FC<PreviewProps> = props => {
133138
toolbarRender,
134139
onTransform,
135140
onChange,
141+
classNames: imageClassNames,
142+
styles,
136143
...restProps
137144
} = props;
138145

@@ -298,8 +305,14 @@ const Preview: React.FC<PreviewProps> = props => {
298305
visible={visible}
299306
classNames={{
300307
wrapper: wrapClassName,
308+
mask: imageClassNames?.mask,
301309
}}
302-
rootClassName={rootClassName}
310+
styles={{
311+
mask: styles?.mask,
312+
wrapper: styles?.wrapper,
313+
}}
314+
style={styles?.root}
315+
rootClassName={classnames(rootClassName, imageClassNames?.root)}
303316
getContainer={getContainer}
304317
{...restProps}
305318
afterClose={onAfterClose}
@@ -339,6 +352,8 @@ const Preview: React.FC<PreviewProps> = props => {
339352
onReset={onReset}
340353
zIndex={restProps.zIndex !== undefined ? restProps.zIndex + 1 : undefined}
341354
image={image}
355+
classNames={imageClassNames}
356+
styles={styles}
342357
/>
343358
</>
344359
);

tests/preview.test.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,4 +1030,36 @@ describe('Preview', () => {
10301030
expect(previewImg).not.toHaveAttribute('width');
10311031
expect(previewImg).not.toHaveAttribute('height');
10321032
});
1033+
it('support classnames and styles', () => {
1034+
const customClassnames = {
1035+
mask: 'custom-mask',
1036+
actions: 'custom-actions',
1037+
root: 'custom-root',
1038+
};
1039+
const customStyles = {
1040+
mask: { color: 'red' },
1041+
actions: { backgroundColor: 'blue' },
1042+
root: { border: '1px solid green' },
1043+
};
1044+
const { baseElement } = render(
1045+
<Image
1046+
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
1047+
preview={{
1048+
styles: customStyles,
1049+
classNames: customClassnames,
1050+
mask: 'Bamboo Is Light',
1051+
zIndex: 9999,
1052+
visible: true,
1053+
}}
1054+
/>,
1055+
);
1056+
const mask = document.querySelector('.rc-image-mask');
1057+
const actions = baseElement.querySelector('.rc-image-preview-operations');
1058+
expect(mask).toHaveClass(customClassnames.mask);
1059+
expect(mask).toHaveStyle(customStyles.mask);
1060+
expect(actions).toHaveClass(customClassnames.actions);
1061+
expect(actions).toHaveStyle(customStyles.actions);
1062+
expect(baseElement.querySelector('.rc-image-preview-root')).toHaveClass(customClassnames.root);
1063+
expect(baseElement.querySelector('.rc-image-preview')).toHaveStyle(customStyles.root);
1064+
});
10331065
});

0 commit comments

Comments
 (0)