Skip to content

Commit 2173c3c

Browse files
shiqiWang0beier
andauthored
Feat v4 slide pane (#330)
* refactor: slidePane to refactor * fix: remove console in test file * fix: update slidePane snapshot * fix: fix ts in slidePane --------- Co-authored-by: beier <[email protected]>
1 parent 2ab03eb commit 2173c3c

File tree

9 files changed

+128
-134
lines changed

9 files changed

+128
-134
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"highlight.js": "^10.5.0",
111111
"lodash": "^4.17.21",
112112
"mxgraph": "^4.2.2",
113+
"rc-drawer": "~5.1.0",
113114
"rc-virtual-list": "^3.4.13",
114115
"showdown": "^1.9.0"
115116
},

pnpm-lock.yaml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/fullscreen/__tests__/index.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ describe('test Fullscreen', () => {
4141
};
4242
render(<Fullscreen iconStyle={iconStyle} />);
4343
const img = screen.getByRole('img');
44-
screen.debug(img);
4544
expect(img).toHaveStyle(`width: 12px; height: 12px; margin-right: 5px;`);
4645
});
4746
test('button fireEvent correct', () => {
Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,3 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`test SlidePane should render correct 1`] = `
4-
<div>
5-
<div
6-
class="dtc-slide-pane"
7-
style="top: 0px; color: red; background: rgb(255, 124, 18);"
8-
>
9-
<div
10-
class="dtc-slide-pane-content"
11-
data-testid="slidepane_container"
12-
style="display: block; height: 100%;"
13-
>
14-
<div>
15-
<h1>
16-
success
17-
</h1>
18-
</div>
19-
</div>
20-
<img
21-
alt=""
22-
class="dtc-slide-pane-icon"
23-
data-testid="slidepane_action"
24-
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAABwCAYAAAAE0LDPAAAAAXNSR0IArs4c6QAAAnlJREFUaEPtmk9IVHEQx78jufpw7ykouuEaBG6dEmrXOmRRt476VgvyEngKlNqQMu3PoSU7iCBq4CW2olNdRMRr7HasnnZb0y57WGODzUDjt/RIonbeyzfQYd51h/m8+c7395u3MOSs5Xexr4dKRLt5AhYJtbPRaNO7velo/4Bf6YhoB8B0R3vzNSLaNr8ECnBRRLTc0d583kBEAJU3J5o6HG0ZkgTs1OBATAxgqqghTIoCiPBeFABQSRggZFOxg/anC0ElYq9JlUglYhVgA9RFKhGrABugLlKJWAXYAHWRSsQqwAaoi1QiVgE2gHVRejKDUKgWQ1cvmj/XbMLfA3jA42dwVvPo7+tBd/xo8ICNzQLG7y3AskIYvz2IcEO9LwhbgcmWebGCpeUcEvEYBvrOBg8ol7cxOjaP4lYJqZEkIm2NniGeKjDZ3mQ/YPbJa7S1NiI1YntuuGeAgTx8lMHqx3XYvWdwOnHMUxW+AJufC7hzdwH1VggTt64gHLZYiC+Ayfb85QoWl3KIn+jEpeS54AHlb98xOjaHYrGEG8M2DkWaqkJ8V2CyZd86mJl7hdaWg7h5PVm14f8EMJD0zxM+ePkCuo4f+WsV/ycgm3MwMy8k0d4mp4ZtRIJusmvTxMlODNgB21T8oLlXRbK3B6cS3maDZxeJXnbudb315Wvl9AZ+XbsDpzseQ3/QA+fTRgET9wVHpvmqcNbWK6PSjEy/D9vkB+mnaLDq5D5b/L6x7+8iBbBNVolUItYDKpFKxCrABqiLVCJWATZAXaQSsQqwAeoilYhVgA1QFzESCS8wia9giS6Rma1B0TU40UU+sVVEoWXK6uugPwBjVkdxauLcgwAAAABJRU5ErkJggg=="
25-
/>
26-
</div>
27-
</div>
28-
`;
3+
exports[`test SlidePane snapshot match 1`] = `<DocumentFragment />`;
Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import SlidePane from '../index';
3-
import { render } from '@testing-library/react';
3+
import { fireEvent, render, screen } from '@testing-library/react';
44
import '@testing-library/jest-dom/extend-expect';
55

66
describe('test SlidePane ', () => {
@@ -13,24 +13,37 @@ describe('test SlidePane ', () => {
1313
visible: true,
1414
style: { color: 'red', background: '#FF7C12' },
1515
};
16+
test('snapshot match', () => {
17+
const { asFragment } = render(
18+
<SlidePane visible={expectValues.visible}>{expectValues.children}</SlidePane>
19+
);
20+
expect(asFragment()).toMatchSnapshot();
21+
});
1622
test('should render correct', () => {
17-
const { container, getByTestId } = render(
23+
render(
1824
<SlidePane visible={expectValues.visible} style={expectValues.style}>
1925
{expectValues.children}
2026
</SlidePane>
2127
);
22-
expect(container.firstChild).toHaveStyle(expectValues.style);
23-
const oDiv = getByTestId('slidepane_container');
24-
expect(oDiv).not.toBeNull();
25-
expect(oDiv).toBeVisible();
26-
expect(oDiv.innerHTML).toEqual('<div><h1>success</h1></div>');
27-
expect(container).toMatchSnapshot();
28+
const wrapper = document.getElementsByClassName('dtc-slide-pane');
29+
expect(wrapper?.[0]).toHaveStyle(expectValues.style);
30+
expect(screen.getByRole('heading')).toHaveTextContent('success');
2831
});
2932
test('should be invisible', () => {
30-
const { getByTestId } = render(
33+
const { container } = render(
3134
<SlidePane visible={false}>{expectValues.children}</SlidePane>
3235
);
33-
const oDiv = getByTestId('slidepane_container');
34-
expect(oDiv).not.toBeVisible();
36+
expect(container).not.toHaveClass();
37+
});
38+
test('should callback to be called', () => {
39+
const fn = jest.fn();
40+
const { getByRole } = render(
41+
<SlidePane visible onClose={fn}>
42+
{expectValues.children}
43+
</SlidePane>
44+
);
45+
const oImg = getByRole('img');
46+
fireEvent.click(oImg);
47+
expect(fn).toHaveBeenCalledTimes(1);
3548
});
3649
});

src/slidePane/demos/basic.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { useState } from 'react';
2+
import { SlidePane } from 'dt-react-component';
3+
import { Button, Slider } from 'antd';
4+
5+
export default () => {
6+
const [visible, setVisible] = useState(false);
7+
const [width, setWidth] = useState(80);
8+
9+
return (
10+
<>
11+
<Slider
12+
defaultValue={width}
13+
min={10}
14+
max={100}
15+
onChange={(value: number) => setWidth(value)}
16+
/>
17+
<span>width:{width}%</span>
18+
<Button style={{ margin: '10px' }} onClick={() => setVisible((v) => !v)}>
19+
click me
20+
</Button>
21+
<SlidePane
22+
visible={visible}
23+
style={{
24+
width: `${width}%`,
25+
minHeight: '600px',
26+
height: '100%',
27+
}}
28+
onClose={() => setVisible(false)}
29+
>
30+
<div>hello world</div>
31+
</SlidePane>
32+
</>
33+
);
34+
};

src/slidePane/index.md

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,19 @@ demo:
1010

1111
## 何时使用
1212

13-
从页面右侧弹出面板,展示相应内容
13+
从页面右侧弹出面板,展示相应内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到原任务。
14+
常用于: 查看详情, 预览较多内容的场景下。
1415

1516
## 示例
1617

17-
```jsx
18-
import React, { useState } from 'react';
19-
import { SlidePane } from 'dt-react-component';
20-
import { Button } from 'antd';
21-
22-
export default () => {
23-
const [visible, setVisible] = useState(false);
24-
const [width, setWidth] = useState(80);
25-
26-
return (
27-
<>
28-
width: {width}%
29-
<input
30-
type="range"
31-
value={width}
32-
min={10}
33-
max={100}
34-
onChange={(e) => setWidth(e.target.value)}
35-
/>
36-
<br />
37-
<Button style={{ marginBottom: '10px' }} onClick={() => setVisible((v) => !v)}>
38-
click me
39-
</Button>
40-
<SlidePane
41-
visible={visible}
42-
style={{
43-
right: '-20px',
44-
width: `${width}%`,
45-
minHeight: '600px',
46-
height: '100%',
47-
}}
48-
onClose={() => setVisible(false)}
49-
>
50-
<div>hello world</div>
51-
</SlidePane>
52-
</>
53-
);
54-
};
55-
```
18+
<code src="./demos/basic.tsx" title="基础使用"></code>
5619

5720
## API
5821

59-
| 参数 | 说明 | 类型 | 默认值 |
60-
| ------- | ------------------- | ---------- | ------ |
61-
| visible | SlidePanel 是否可见 | `boolean` | - |
62-
| onClose | 关闭回调 | `function` | - |
22+
| 参数 | 说明 | 类型 | 默认值 |
23+
| --------- | ---------------------- | --------------- | ------ |
24+
| visible | SlidePanel 是否可见 | `boolean` | - |
25+
| className | 右侧面板外层容器的类名 | `string` | - |
26+
| style | 右侧面板外层容器的样式 | `CSSProperties` | - |
27+
| bodyStyle | 右侧面板内部容器的样式 | `CSSProperties` | - |
28+
| onClose | 关闭回调 | `function` | - |

src/slidePane/index.tsx

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,65 @@
1-
import { assign } from 'lodash';
2-
import React from 'react';
1+
import React, { PropsWithChildren } from 'react';
32
import classNames from 'classnames';
3+
import { assign } from 'lodash';
4+
import RcDrawer from 'rc-drawer';
45
import './style.scss';
56

6-
export interface SlidePaneProps {
7-
children: React.ReactNode;
7+
export interface ISlidePaneProps {
88
visible: boolean;
9-
left?: string | number;
10-
width?: string | number;
119
className?: string;
1210
style?: React.CSSProperties;
13-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
14-
onClose?<HTMLSpanElement, MouseEvent>(): void;
15-
[propName: string]: any;
11+
bodyStyle?: React.CSSProperties;
12+
onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
1613
}
14+
const SlidePane = ({
15+
visible,
16+
className,
17+
style,
18+
bodyStyle,
19+
children,
20+
onClose,
21+
}: PropsWithChildren<ISlidePaneProps>) => {
22+
const slidePrefixCls = 'dtc-slide-pane';
23+
let rootStyle: React.CSSProperties = {
24+
top: 0,
25+
right: 0,
26+
transform: visible ? undefined : 'translate3d(150%, 0, 0)',
27+
};
28+
const classes = classNames(className);
1729

18-
class SlidePane extends React.Component<SlidePaneProps, any> {
19-
constructor(props: SlidePaneProps) {
20-
super(props);
30+
if (!visible) {
31+
rootStyle['pointerEvents'] = 'none';
2132
}
33+
if (style) rootStyle = assign(rootStyle, style);
2234

23-
render() {
24-
const { children, visible, style, className, onClose } = this.props;
25-
const slidePrefixCls = 'dtc-slide-pane';
26-
let myStyle: any = {
27-
top: 0,
28-
transform: visible ? undefined : 'translate3d(150%, 0, 0)',
29-
};
30-
const classes = classNames(slidePrefixCls, className);
31-
if (!visible) {
32-
myStyle['pointerEvents'] = 'none';
33-
}
34-
if (style) myStyle = assign(myStyle, style);
35-
35+
const renderButton = () => {
3636
return (
37-
<div className={classes} style={myStyle}>
38-
<div
39-
className={`${slidePrefixCls}-content`}
40-
data-testid="slidepane_container"
41-
style={{ display: visible ? 'block' : 'none', height: '100%' }}
42-
>
43-
{children}
44-
</div>
45-
<img
46-
className={`${slidePrefixCls}-icon`}
47-
data-testid="slidepane_action"
48-
onClick={onClose}
49-
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAABwCAYAAAAE0LDPAAAAAXNSR0IArs4c6QAAAnlJREFUaEPtmk9IVHEQx78jufpw7ykouuEaBG6dEmrXOmRRt476VgvyEngKlNqQMu3PoSU7iCBq4CW2olNdRMRr7HasnnZb0y57WGODzUDjt/RIonbeyzfQYd51h/m8+c7395u3MOSs5Xexr4dKRLt5AhYJtbPRaNO7velo/4Bf6YhoB8B0R3vzNSLaNr8ECnBRRLTc0d583kBEAJU3J5o6HG0ZkgTs1OBATAxgqqghTIoCiPBeFABQSRggZFOxg/anC0ElYq9JlUglYhVgA9RFKhGrABugLlKJWAXYAHWRSsQqwAaoi1QiVgE2gHVRejKDUKgWQ1cvmj/XbMLfA3jA42dwVvPo7+tBd/xo8ICNzQLG7y3AskIYvz2IcEO9LwhbgcmWebGCpeUcEvEYBvrOBg8ol7cxOjaP4lYJqZEkIm2NniGeKjDZ3mQ/YPbJa7S1NiI1YntuuGeAgTx8lMHqx3XYvWdwOnHMUxW+AJufC7hzdwH1VggTt64gHLZYiC+Ayfb85QoWl3KIn+jEpeS54AHlb98xOjaHYrGEG8M2DkWaqkJ8V2CyZd86mJl7hdaWg7h5PVm14f8EMJD0zxM+ePkCuo4f+WsV/ycgm3MwMy8k0d4mp4ZtRIJusmvTxMlODNgB21T8oLlXRbK3B6cS3maDZxeJXnbudb315Wvl9AZ+XbsDpzseQ3/QA+fTRgET9wVHpvmqcNbWK6PSjEy/D9vkB+mnaLDq5D5b/L6x7+8iBbBNVolUItYDKpFKxCrABqiLVCJWATZAXaQSsQqwAeoilYhVgA1QFzESCS8wia9giS6Rma1B0TU40UU+sVVEoWXK6uugPwBjVkdxauLcgwAAAABJRU5ErkJggg=="
50-
alt=""
51-
/>
52-
</div>
37+
<img
38+
className={`${slidePrefixCls}-icon`}
39+
onClick={onClose}
40+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAABwCAYAAAAE0LDPAAAAAXNSR0IArs4c6QAAAnlJREFUaEPtmk9IVHEQx78jufpw7ykouuEaBG6dEmrXOmRRt476VgvyEngKlNqQMu3PoSU7iCBq4CW2olNdRMRr7HasnnZb0y57WGODzUDjt/RIonbeyzfQYd51h/m8+c7395u3MOSs5Xexr4dKRLt5AhYJtbPRaNO7velo/4Bf6YhoB8B0R3vzNSLaNr8ECnBRRLTc0d583kBEAJU3J5o6HG0ZkgTs1OBATAxgqqghTIoCiPBeFABQSRggZFOxg/anC0ElYq9JlUglYhVgA9RFKhGrABugLlKJWAXYAHWRSsQqwAaoi1QiVgE2gHVRejKDUKgWQ1cvmj/XbMLfA3jA42dwVvPo7+tBd/xo8ICNzQLG7y3AskIYvz2IcEO9LwhbgcmWebGCpeUcEvEYBvrOBg8ol7cxOjaP4lYJqZEkIm2NniGeKjDZ3mQ/YPbJa7S1NiI1YntuuGeAgTx8lMHqx3XYvWdwOnHMUxW+AJufC7hzdwH1VggTt64gHLZYiC+Ayfb85QoWl3KIn+jEpeS54AHlb98xOjaHYrGEG8M2DkWaqkJ8V2CyZd86mJl7hdaWg7h5PVm14f8EMJD0zxM+ePkCuo4f+WsV/ycgm3MwMy8k0d4mp4ZtRIJusmvTxMlODNgB21T8oLlXRbK3B6cS3maDZxeJXnbudb315Wvl9AZ+XbsDpzseQ3/QA+fTRgET9wVHpvmqcNbWK6PSjEy/D9vkB+mnaLDq5D5b/L6x7+8iBbBNVolUItYDKpFKxCrABqiLVCJWATZAXaQSsQqwAeoilYhVgA1QFzESCS8wia9giS6Rma1B0TU40UU+sVVEoWXK6uugPwBjVkdxauLcgwAAAABJRU5ErkJggg=="
41+
alt="closeBtn"
42+
/>
5343
);
54-
}
55-
}
44+
};
45+
46+
return (
47+
<RcDrawer
48+
prefixCls={slidePrefixCls}
49+
rootClassName={classes}
50+
width="100%"
51+
onClose={onClose}
52+
open={visible}
53+
mask={false}
54+
rootStyle={rootStyle}
55+
placement="right"
56+
>
57+
{renderButton()}
58+
<div className={`${slidePrefixCls}-content`} style={bodyStyle}>
59+
{children}
60+
</div>
61+
</RcDrawer>
62+
);
63+
};
5664

5765
export default SlidePane;

src/slidePane/style.scss

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,18 @@ $prefix: "dtc-slide-pane";
22

33
.#{$prefix} {
44
background: #FFF;
5-
border-left: 1px solid #DDD;
6-
border-bottom: 1px solid #DDD;
7-
box-shadow: -2px 0 2px 0 rgba(0, 0, 0, 0.1);
8-
position: absolute;
5+
box-shadow: -10px 0 20px 0 rgba(61, 68, 110, 0.1);
96
display: inline-block;
7+
position: fixed;
108
transition: transform 0.3s ease-in;
119
z-index: 99;
12-
&.l-#{$prefix}--fixed {
13-
position: fixed;
14-
top: 0;
15-
right: 0;
10+
.#{$prefix}-content-wrapper {
11+
height: 100%;
1612
}
1713
.#{$prefix}-content {
1814
position: relative;
15+
height: 100%;
1916
}
20-
2117
.#{$prefix}-icon {
2218
width: 12px;
2319
height: 56px;

0 commit comments

Comments
 (0)