@rc-component/drawer 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/assets/index.css +231 -1
- package/es/Drawer.d.ts +20 -0
- package/es/Drawer.js +11 -1
- package/es/DrawerPopup.d.ts +11 -0
- package/es/DrawerPopup.js +78 -28
- package/es/hooks/useDrag.d.ts +23 -0
- package/es/hooks/useDrag.js +98 -0
- package/es/index.d.ts +2 -2
- package/es/inter.d.ts +2 -0
- package/es/util.js +9 -3
- package/lib/Drawer.d.ts +20 -0
- package/lib/Drawer.js +11 -1
- package/lib/DrawerPopup.d.ts +11 -0
- package/lib/DrawerPopup.js +78 -28
- package/lib/hooks/useDrag.d.ts +23 -0
- package/lib/hooks/useDrag.js +107 -0
- package/lib/index.d.ts +2 -2
- package/lib/inter.d.ts +2 -0
- package/lib/util.js +9 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -49,6 +49,8 @@ ReactDom.render(
|
|
|
49
49
|
| prefixCls | string | 'drawer' | prefix class |
|
|
50
50
|
| width | string \| number | null | drawer content wrapper width, drawer level transition width |
|
|
51
51
|
| height | string \| number | null | drawer content wrapper height, drawer level transition height |
|
|
52
|
+
| defaultWidth | string \| number | null | default width for uncontrolled resizable drawer |
|
|
53
|
+
| defaultHeight | string \| number | null | default height for uncontrolled resizable drawer |
|
|
52
54
|
| open | boolean | false | open or close menu |
|
|
53
55
|
| defaultOpen | boolean | false | default open menu |
|
|
54
56
|
| placement | string | `left` | `left` `top` `right` `bottom` |
|
|
@@ -64,6 +66,7 @@ ReactDom.render(
|
|
|
64
66
|
| onClose | func | null | close click function |
|
|
65
67
|
| keyboard | boolean | true | Whether support press esc to close |
|
|
66
68
|
| autoFocus | boolean | true | Whether focusing on the drawer after it opened |
|
|
69
|
+
| resizable | { onResize?: (size: number) => void; onResizeStart?: () => void; onResizeEnd?: () => void; } | - | Resizable configuration with optional callbacks |
|
|
67
70
|
| onMouseEnter | React.MouseEventHandler\<HTMLDivElement\> | - | Trigger when mouse enter drawer panel |
|
|
68
71
|
| onMouseOver | React.MouseEventHandler\<HTMLDivElement\> | - | Trigger when mouse over drawer panel |
|
|
69
72
|
| onMouseLeave | React.MouseEventHandler\<HTMLDivElement\> | - | Trigger when mouse leave drawer panel |
|
package/assets/index.css
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
.rc-drawer-content-wrapper {
|
|
18
18
|
position: absolute;
|
|
19
19
|
z-index: 1050;
|
|
20
|
-
overflow: hidden;
|
|
21
20
|
transition: transform 0.3s;
|
|
22
21
|
}
|
|
23
22
|
.rc-drawer-content-wrapper-hidden {
|
|
@@ -40,3 +39,234 @@
|
|
|
40
39
|
background: #fff;
|
|
41
40
|
pointer-events: auto;
|
|
42
41
|
}
|
|
42
|
+
.rc-drawer-resizable-dragger {
|
|
43
|
+
position: absolute;
|
|
44
|
+
z-index: 2;
|
|
45
|
+
pointer-events: auto;
|
|
46
|
+
}
|
|
47
|
+
.rc-drawer-resizable-dragger:hover {
|
|
48
|
+
background-color: #1890ff !important;
|
|
49
|
+
}
|
|
50
|
+
.rc-drawer-resizable-dragger-dragging {
|
|
51
|
+
background-color: #1890ff !important;
|
|
52
|
+
}
|
|
53
|
+
.rc-drawer-resizable-dragger-left {
|
|
54
|
+
top: 0;
|
|
55
|
+
bottom: 0;
|
|
56
|
+
right: -3px;
|
|
57
|
+
width: 6px;
|
|
58
|
+
cursor: ew-resize;
|
|
59
|
+
}
|
|
60
|
+
.rc-drawer-resizable-dragger-right {
|
|
61
|
+
top: 0;
|
|
62
|
+
bottom: 0;
|
|
63
|
+
left: -3px;
|
|
64
|
+
width: 6px;
|
|
65
|
+
cursor: ew-resize;
|
|
66
|
+
}
|
|
67
|
+
.rc-drawer-resizable-dragger-top {
|
|
68
|
+
left: 0;
|
|
69
|
+
right: 0;
|
|
70
|
+
bottom: -3px;
|
|
71
|
+
height: 6px;
|
|
72
|
+
cursor: ns-resize;
|
|
73
|
+
}
|
|
74
|
+
.rc-drawer-resizable-dragger-bottom {
|
|
75
|
+
left: 0;
|
|
76
|
+
right: 0;
|
|
77
|
+
top: -3px;
|
|
78
|
+
height: 6px;
|
|
79
|
+
cursor: ns-resize;
|
|
80
|
+
}
|
|
81
|
+
.rc-drawer {
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
z-index: 9999;
|
|
84
|
+
transition: width 0s ease 0.3s, height 0s ease 0.3s, transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
85
|
+
}
|
|
86
|
+
.rc-drawer > * {
|
|
87
|
+
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86), opacity 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86), box-shadow 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
88
|
+
}
|
|
89
|
+
.rc-drawer.rc-drawer-open {
|
|
90
|
+
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
91
|
+
}
|
|
92
|
+
.rc-drawer .rc-drawer-mask {
|
|
93
|
+
background: #000;
|
|
94
|
+
opacity: 0;
|
|
95
|
+
width: 100%;
|
|
96
|
+
height: 0;
|
|
97
|
+
position: absolute;
|
|
98
|
+
top: 0;
|
|
99
|
+
left: 0;
|
|
100
|
+
transition: opacity 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86), height 0s ease 0.3s;
|
|
101
|
+
}
|
|
102
|
+
.rc-drawer-content-wrapper {
|
|
103
|
+
position: absolute;
|
|
104
|
+
background: #fff;
|
|
105
|
+
}
|
|
106
|
+
.rc-drawer-content {
|
|
107
|
+
overflow: auto;
|
|
108
|
+
z-index: 1;
|
|
109
|
+
position: relative;
|
|
110
|
+
}
|
|
111
|
+
.rc-drawer-handle {
|
|
112
|
+
position: absolute;
|
|
113
|
+
top: 72px;
|
|
114
|
+
width: 41px;
|
|
115
|
+
height: 40px;
|
|
116
|
+
cursor: pointer;
|
|
117
|
+
z-index: 0;
|
|
118
|
+
text-align: center;
|
|
119
|
+
line-height: 40px;
|
|
120
|
+
font-size: 16px;
|
|
121
|
+
display: flex;
|
|
122
|
+
justify-content: center;
|
|
123
|
+
align-items: center;
|
|
124
|
+
background: #fff;
|
|
125
|
+
}
|
|
126
|
+
.rc-drawer-handle-icon {
|
|
127
|
+
width: 14px;
|
|
128
|
+
height: 2px;
|
|
129
|
+
background: #333;
|
|
130
|
+
position: relative;
|
|
131
|
+
transition: background 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
132
|
+
}
|
|
133
|
+
.rc-drawer-handle-icon::before,
|
|
134
|
+
.rc-drawer-handle-icon::after {
|
|
135
|
+
content: '';
|
|
136
|
+
display: block;
|
|
137
|
+
position: absolute;
|
|
138
|
+
background: #333;
|
|
139
|
+
width: 100%;
|
|
140
|
+
height: 2px;
|
|
141
|
+
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
142
|
+
}
|
|
143
|
+
.rc-drawer-handle-icon::before {
|
|
144
|
+
top: -5px;
|
|
145
|
+
}
|
|
146
|
+
.rc-drawer-handle-icon::after {
|
|
147
|
+
top: 5px;
|
|
148
|
+
}
|
|
149
|
+
.rc-drawer-left,
|
|
150
|
+
.rc-drawer-right {
|
|
151
|
+
width: 0%;
|
|
152
|
+
height: 100%;
|
|
153
|
+
}
|
|
154
|
+
.rc-drawer-left .rc-drawer-content-wrapper,
|
|
155
|
+
.rc-drawer-right .rc-drawer-content-wrapper,
|
|
156
|
+
.rc-drawer-left .rc-drawer-content,
|
|
157
|
+
.rc-drawer-right .rc-drawer-content {
|
|
158
|
+
height: 100%;
|
|
159
|
+
}
|
|
160
|
+
.rc-drawer-left.rc-drawer-open,
|
|
161
|
+
.rc-drawer-right.rc-drawer-open {
|
|
162
|
+
width: 100%;
|
|
163
|
+
}
|
|
164
|
+
.rc-drawer-left.rc-drawer-open.no-mask,
|
|
165
|
+
.rc-drawer-right.rc-drawer-open.no-mask {
|
|
166
|
+
width: 0%;
|
|
167
|
+
}
|
|
168
|
+
.rc-drawer-left {
|
|
169
|
+
top: 0;
|
|
170
|
+
left: 0;
|
|
171
|
+
}
|
|
172
|
+
.rc-drawer-left .rc-drawer-handle {
|
|
173
|
+
right: -40px;
|
|
174
|
+
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
|
|
175
|
+
border-radius: 0 4px 4px 0;
|
|
176
|
+
}
|
|
177
|
+
.rc-drawer-left.rc-drawer-open .rc-drawer-content-wrapper {
|
|
178
|
+
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
|
|
179
|
+
}
|
|
180
|
+
.rc-drawer-right {
|
|
181
|
+
top: 0;
|
|
182
|
+
right: 0;
|
|
183
|
+
}
|
|
184
|
+
.rc-drawer-right .rc-drawer-content-wrapper {
|
|
185
|
+
right: 0;
|
|
186
|
+
}
|
|
187
|
+
.rc-drawer-right .rc-drawer-handle {
|
|
188
|
+
left: -40px;
|
|
189
|
+
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
|
|
190
|
+
border-radius: 4px 0 0 4px;
|
|
191
|
+
}
|
|
192
|
+
.rc-drawer-right.rc-drawer-open .rc-drawer-content-wrapper {
|
|
193
|
+
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
|
|
194
|
+
}
|
|
195
|
+
.rc-drawer-right.rc-drawer-open.no-mask {
|
|
196
|
+
right: 1px;
|
|
197
|
+
transform: translateX(1px);
|
|
198
|
+
}
|
|
199
|
+
.rc-drawer-top,
|
|
200
|
+
.rc-drawer-bottom {
|
|
201
|
+
width: 100%;
|
|
202
|
+
height: 0%;
|
|
203
|
+
}
|
|
204
|
+
.rc-drawer-top .rc-drawer-content-wrapper,
|
|
205
|
+
.rc-drawer-bottom .rc-drawer-content-wrapper,
|
|
206
|
+
.rc-drawer-top .rc-drawer-content,
|
|
207
|
+
.rc-drawer-bottom .rc-drawer-content {
|
|
208
|
+
width: 100%;
|
|
209
|
+
}
|
|
210
|
+
.rc-drawer-top .rc-drawer-content,
|
|
211
|
+
.rc-drawer-bottom .rc-drawer-content {
|
|
212
|
+
height: 100%;
|
|
213
|
+
}
|
|
214
|
+
.rc-drawer-top.rc-drawer-open,
|
|
215
|
+
.rc-drawer-bottom.rc-drawer-open {
|
|
216
|
+
height: 100%;
|
|
217
|
+
}
|
|
218
|
+
.rc-drawer-top.rc-drawer-open.no-mask,
|
|
219
|
+
.rc-drawer-bottom.rc-drawer-open.no-mask {
|
|
220
|
+
height: 0%;
|
|
221
|
+
}
|
|
222
|
+
.rc-drawer-top .rc-drawer-handle,
|
|
223
|
+
.rc-drawer-bottom .rc-drawer-handle {
|
|
224
|
+
left: 50%;
|
|
225
|
+
margin-left: -20px;
|
|
226
|
+
}
|
|
227
|
+
.rc-drawer-top {
|
|
228
|
+
top: 0;
|
|
229
|
+
left: 0;
|
|
230
|
+
}
|
|
231
|
+
.rc-drawer-top .rc-drawer-handle {
|
|
232
|
+
top: auto;
|
|
233
|
+
bottom: -40px;
|
|
234
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
235
|
+
border-radius: 0 0 4px 4px;
|
|
236
|
+
}
|
|
237
|
+
.rc-drawer-top.rc-drawer-open .rc-drawer-content-wrapper {
|
|
238
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
239
|
+
}
|
|
240
|
+
.rc-drawer-bottom {
|
|
241
|
+
bottom: 0;
|
|
242
|
+
left: 0;
|
|
243
|
+
}
|
|
244
|
+
.rc-drawer-bottom .rc-drawer-content-wrapper {
|
|
245
|
+
bottom: 0;
|
|
246
|
+
}
|
|
247
|
+
.rc-drawer-bottom .rc-drawer-handle {
|
|
248
|
+
top: -40px;
|
|
249
|
+
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.15);
|
|
250
|
+
border-radius: 4px 4px 0 0;
|
|
251
|
+
}
|
|
252
|
+
.rc-drawer-bottom.rc-drawer-open .rc-drawer-content-wrapper {
|
|
253
|
+
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.15);
|
|
254
|
+
}
|
|
255
|
+
.rc-drawer-bottom.rc-drawer-open.no-mask {
|
|
256
|
+
bottom: 1px;
|
|
257
|
+
transform: translateY(1px);
|
|
258
|
+
}
|
|
259
|
+
.rc-drawer.rc-drawer-open .rc-drawer-mask {
|
|
260
|
+
opacity: 0.3;
|
|
261
|
+
height: 100%;
|
|
262
|
+
transition: opacity 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
263
|
+
}
|
|
264
|
+
.rc-drawer.rc-drawer-open .rc-drawer-handle-icon {
|
|
265
|
+
background: transparent;
|
|
266
|
+
}
|
|
267
|
+
.rc-drawer.rc-drawer-open .rc-drawer-handle-icon::before {
|
|
268
|
+
transform: translateY(5px) rotate(45deg);
|
|
269
|
+
}
|
|
270
|
+
.rc-drawer.rc-drawer-open .rc-drawer-handle-icon::after {
|
|
271
|
+
transform: translateY(-5px) rotate(-45deg);
|
|
272
|
+
}
|
package/es/Drawer.d.ts
CHANGED
|
@@ -13,6 +13,26 @@ export interface DrawerProps extends Omit<DrawerPopupProps, 'prefixCls' | 'inlin
|
|
|
13
13
|
panelRef?: React.Ref<HTMLDivElement>;
|
|
14
14
|
classNames?: DrawerClassNames;
|
|
15
15
|
styles?: DrawerStyles;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated Use `size` instead. Will be removed in next major version.
|
|
18
|
+
*/
|
|
19
|
+
width?: number | string;
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Use `size` instead. Will be removed in next major version.
|
|
22
|
+
*/
|
|
23
|
+
height?: number | string;
|
|
24
|
+
/** Size of the drawer (width for left/right placement, height for top/bottom placement) */
|
|
25
|
+
size?: number | string;
|
|
26
|
+
/** Maximum size of the drawer */
|
|
27
|
+
maxSize?: number;
|
|
28
|
+
/** Default size for uncontrolled resizable drawer */
|
|
29
|
+
defaultSize?: number | string;
|
|
30
|
+
/** Resizable configuration - object with optional callbacks */
|
|
31
|
+
resizable?: {
|
|
32
|
+
onResize?: (size: number) => void;
|
|
33
|
+
onResizeStart?: () => void;
|
|
34
|
+
onResizeEnd?: () => void;
|
|
35
|
+
};
|
|
16
36
|
}
|
|
17
37
|
declare const Drawer: React.FC<DrawerProps>;
|
|
18
38
|
export default Drawer;
|
package/es/Drawer.js
CHANGED
|
@@ -11,7 +11,10 @@ const Drawer = props => {
|
|
|
11
11
|
placement = 'right',
|
|
12
12
|
autoFocus = true,
|
|
13
13
|
keyboard = true,
|
|
14
|
-
width
|
|
14
|
+
width,
|
|
15
|
+
height,
|
|
16
|
+
size,
|
|
17
|
+
maxSize,
|
|
15
18
|
mask = true,
|
|
16
19
|
maskClosable = true,
|
|
17
20
|
getContainer,
|
|
@@ -24,6 +27,8 @@ const Drawer = props => {
|
|
|
24
27
|
onClick,
|
|
25
28
|
onKeyDown,
|
|
26
29
|
onKeyUp,
|
|
30
|
+
resizable,
|
|
31
|
+
defaultSize,
|
|
27
32
|
// Refs
|
|
28
33
|
panelRef
|
|
29
34
|
} = props;
|
|
@@ -86,11 +91,16 @@ const Drawer = props => {
|
|
|
86
91
|
autoFocus,
|
|
87
92
|
keyboard,
|
|
88
93
|
width,
|
|
94
|
+
height,
|
|
95
|
+
size,
|
|
96
|
+
maxSize,
|
|
97
|
+
defaultSize,
|
|
89
98
|
mask,
|
|
90
99
|
maskClosable,
|
|
91
100
|
inline: getContainer === false,
|
|
92
101
|
afterOpenChange: internalAfterOpenChange,
|
|
93
102
|
ref: popupRef,
|
|
103
|
+
resizable,
|
|
94
104
|
...eventHandlers
|
|
95
105
|
};
|
|
96
106
|
return /*#__PURE__*/React.createElement(RefContext.Provider, {
|
package/es/DrawerPopup.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
|
|
|
24
24
|
children?: React.ReactNode;
|
|
25
25
|
width?: number | string;
|
|
26
26
|
height?: number | string;
|
|
27
|
+
/** Size of the drawer (width for left/right placement, height for top/bottom placement) */
|
|
28
|
+
size?: number | string;
|
|
29
|
+
/** Maximum size of the drawer */
|
|
30
|
+
maxSize?: number;
|
|
27
31
|
mask?: boolean;
|
|
28
32
|
maskClosable?: boolean;
|
|
29
33
|
maskClassName?: string;
|
|
@@ -35,6 +39,13 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
|
|
|
35
39
|
classNames?: DrawerClassNames;
|
|
36
40
|
styles?: DrawerStyles;
|
|
37
41
|
drawerRender?: (node: React.ReactNode) => React.ReactNode;
|
|
42
|
+
/** Default size for uncontrolled resizable drawer */
|
|
43
|
+
defaultSize?: number | string;
|
|
44
|
+
resizable?: {
|
|
45
|
+
onResize?: (size: number) => void;
|
|
46
|
+
onResizeStart?: () => void;
|
|
47
|
+
onResizeEnd?: () => void;
|
|
48
|
+
};
|
|
38
49
|
}
|
|
39
50
|
declare const RefDrawerPopup: React.ForwardRefExoticComponent<DrawerPopupProps & React.RefAttributes<HTMLDivElement>>;
|
|
40
51
|
export default RefDrawerPopup;
|
package/es/DrawerPopup.js
CHANGED
|
@@ -6,7 +6,9 @@ import pickAttrs from "@rc-component/util/es/pickAttrs";
|
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import DrawerContext from "./context";
|
|
8
8
|
import DrawerPanel from "./DrawerPanel";
|
|
9
|
+
import useDrag from "./hooks/useDrag";
|
|
9
10
|
import { parseWidthHeight } from "./util";
|
|
11
|
+
import { useEvent } from '@rc-component/util';
|
|
10
12
|
const sentinelStyle = {
|
|
11
13
|
width: 0,
|
|
12
14
|
height: 0,
|
|
@@ -37,6 +39,8 @@ const DrawerPopup = (props, ref) => {
|
|
|
37
39
|
motion,
|
|
38
40
|
width,
|
|
39
41
|
height,
|
|
42
|
+
size,
|
|
43
|
+
maxSize,
|
|
40
44
|
children,
|
|
41
45
|
// Mask
|
|
42
46
|
mask,
|
|
@@ -54,7 +58,9 @@ const DrawerPopup = (props, ref) => {
|
|
|
54
58
|
onKeyDown,
|
|
55
59
|
onKeyUp,
|
|
56
60
|
styles,
|
|
57
|
-
drawerRender
|
|
61
|
+
drawerRender,
|
|
62
|
+
resizable,
|
|
63
|
+
defaultSize
|
|
58
64
|
} = props;
|
|
59
65
|
|
|
60
66
|
// ================================ Refs ================================
|
|
@@ -147,10 +153,10 @@ const DrawerPopup = (props, ref) => {
|
|
|
147
153
|
}, []);
|
|
148
154
|
|
|
149
155
|
// ============================ Mask ============================
|
|
150
|
-
const maskNode =
|
|
156
|
+
const maskNode = /*#__PURE__*/React.createElement(CSSMotion, _extends({
|
|
151
157
|
key: "mask"
|
|
152
158
|
}, maskMotion, {
|
|
153
|
-
visible: open
|
|
159
|
+
visible: mask && open
|
|
154
160
|
}), ({
|
|
155
161
|
className: motionMaskClassName,
|
|
156
162
|
style: motionMaskStyle
|
|
@@ -167,28 +173,68 @@ const DrawerPopup = (props, ref) => {
|
|
|
167
173
|
|
|
168
174
|
// =========================== Panel ============================
|
|
169
175
|
const motionProps = typeof motion === 'function' ? motion(placement) : motion;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
176
|
+
|
|
177
|
+
// ============================ Size ============================
|
|
178
|
+
const [currentSize, setCurrentSize] = React.useState();
|
|
179
|
+
const isHorizontal = placement === 'left' || placement === 'right';
|
|
180
|
+
|
|
181
|
+
// Aggregate size logic with backward compatibility using useMemo
|
|
182
|
+
const mergedSize = React.useMemo(() => {
|
|
183
|
+
const legacySize = isHorizontal ? width : height;
|
|
184
|
+
const nextMergedSize = size ?? legacySize ?? currentSize ?? defaultSize ?? (isHorizontal ? 378 : undefined);
|
|
185
|
+
return parseWidthHeight(nextMergedSize);
|
|
186
|
+
}, [size, width, height, defaultSize, isHorizontal, currentSize]);
|
|
187
|
+
|
|
188
|
+
// >>> Style
|
|
189
|
+
const wrapperStyle = React.useMemo(() => {
|
|
190
|
+
const nextWrapperStyle = {};
|
|
191
|
+
if (pushed && pushDistance) {
|
|
192
|
+
switch (placement) {
|
|
193
|
+
case 'top':
|
|
194
|
+
nextWrapperStyle.transform = `translateY(${pushDistance}px)`;
|
|
195
|
+
break;
|
|
196
|
+
case 'bottom':
|
|
197
|
+
nextWrapperStyle.transform = `translateY(${-pushDistance}px)`;
|
|
198
|
+
break;
|
|
199
|
+
case 'left':
|
|
200
|
+
nextWrapperStyle.transform = `translateX(${pushDistance}px)`;
|
|
201
|
+
break;
|
|
202
|
+
default:
|
|
203
|
+
nextWrapperStyle.transform = `translateX(${-pushDistance}px)`;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
185
206
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
if (isHorizontal) {
|
|
208
|
+
nextWrapperStyle.width = parseWidthHeight(mergedSize);
|
|
209
|
+
} else {
|
|
210
|
+
nextWrapperStyle.height = parseWidthHeight(mergedSize);
|
|
211
|
+
}
|
|
212
|
+
return nextWrapperStyle;
|
|
213
|
+
}, [pushed, pushDistance, placement, isHorizontal, mergedSize]);
|
|
214
|
+
|
|
215
|
+
// =========================== Resize ===========================
|
|
216
|
+
const wrapperRef = React.useRef(null);
|
|
217
|
+
const onInternalResize = useEvent(size => {
|
|
218
|
+
setCurrentSize(size);
|
|
219
|
+
resizable?.onResize?.(size);
|
|
220
|
+
});
|
|
221
|
+
const {
|
|
222
|
+
dragElementProps,
|
|
223
|
+
isDragging
|
|
224
|
+
} = useDrag({
|
|
225
|
+
prefixCls: `${prefixCls}-resizable`,
|
|
226
|
+
direction: placement,
|
|
227
|
+
className: drawerClassNames?.dragger,
|
|
228
|
+
style: styles?.dragger,
|
|
229
|
+
maxSize,
|
|
230
|
+
containerRef: wrapperRef,
|
|
231
|
+
currentSize: mergedSize,
|
|
232
|
+
onResize: onInternalResize,
|
|
233
|
+
onResizeStart: resizable?.onResizeStart,
|
|
234
|
+
onResizeEnd: resizable?.onResizeEnd
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// =========================== Events ===========================
|
|
192
238
|
const eventHandlers = {
|
|
193
239
|
onMouseEnter,
|
|
194
240
|
onMouseOver,
|
|
@@ -197,6 +243,9 @@ const DrawerPopup = (props, ref) => {
|
|
|
197
243
|
onKeyDown,
|
|
198
244
|
onKeyUp
|
|
199
245
|
};
|
|
246
|
+
|
|
247
|
+
// =========================== Render ==========================
|
|
248
|
+
// >>>>> Panel
|
|
200
249
|
const panelNode = /*#__PURE__*/React.createElement(CSSMotion, _extends({
|
|
201
250
|
key: "panel"
|
|
202
251
|
}, motionProps, {
|
|
@@ -224,18 +273,19 @@ const DrawerPopup = (props, ref) => {
|
|
|
224
273
|
aria: true
|
|
225
274
|
}), eventHandlers), children);
|
|
226
275
|
return /*#__PURE__*/React.createElement("div", _extends({
|
|
227
|
-
|
|
276
|
+
ref: wrapperRef,
|
|
277
|
+
className: classNames(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
|
|
228
278
|
style: {
|
|
229
|
-
...wrapperStyle,
|
|
230
279
|
...motionStyle,
|
|
280
|
+
...wrapperStyle,
|
|
231
281
|
...styles?.wrapper
|
|
232
282
|
}
|
|
233
283
|
}, pickAttrs(props, {
|
|
234
284
|
data: true
|
|
235
|
-
})), drawerRender ? drawerRender(content) : content);
|
|
285
|
+
})), resizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
|
|
236
286
|
});
|
|
237
287
|
|
|
238
|
-
//
|
|
288
|
+
// >>>>> Container
|
|
239
289
|
const containerStyle = {
|
|
240
290
|
...rootStyle
|
|
241
291
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Placement } from '../Drawer';
|
|
3
|
+
export interface UseDragOptions {
|
|
4
|
+
prefixCls: string;
|
|
5
|
+
direction: Placement;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
maxSize?: number;
|
|
9
|
+
containerRef?: React.RefObject<HTMLElement>;
|
|
10
|
+
currentSize?: number | string;
|
|
11
|
+
onResize?: (size: number) => void;
|
|
12
|
+
onResizeEnd?: (size: number) => void;
|
|
13
|
+
onResizeStart?: (size: number) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface UseDragReturn {
|
|
16
|
+
dragElementProps: {
|
|
17
|
+
className: string;
|
|
18
|
+
style: React.CSSProperties;
|
|
19
|
+
onMouseDown: (e: React.MouseEvent) => void;
|
|
20
|
+
};
|
|
21
|
+
isDragging: boolean;
|
|
22
|
+
}
|
|
23
|
+
export default function useDrag(options: UseDragOptions): UseDragReturn;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { useEvent } from '@rc-component/util';
|
|
4
|
+
export default function useDrag(options) {
|
|
5
|
+
const {
|
|
6
|
+
prefixCls,
|
|
7
|
+
direction,
|
|
8
|
+
className,
|
|
9
|
+
style,
|
|
10
|
+
maxSize,
|
|
11
|
+
containerRef,
|
|
12
|
+
currentSize,
|
|
13
|
+
onResize,
|
|
14
|
+
onResizeEnd,
|
|
15
|
+
onResizeStart
|
|
16
|
+
} = options;
|
|
17
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
18
|
+
const [startPos, setStartPos] = React.useState(0);
|
|
19
|
+
const [startSize, setStartSize] = React.useState(0);
|
|
20
|
+
const isHorizontal = direction === 'left' || direction === 'right';
|
|
21
|
+
const handleMouseDown = useEvent(e => {
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
e.stopPropagation();
|
|
24
|
+
setIsDragging(true);
|
|
25
|
+
if (isHorizontal) {
|
|
26
|
+
setStartPos(e.clientX);
|
|
27
|
+
} else {
|
|
28
|
+
setStartPos(e.clientY);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Use provided currentSize, or fallback to container size
|
|
32
|
+
let startSize;
|
|
33
|
+
if (typeof currentSize === 'number') {
|
|
34
|
+
startSize = currentSize;
|
|
35
|
+
} else if (containerRef?.current) {
|
|
36
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
37
|
+
startSize = isHorizontal ? rect.width : rect.height;
|
|
38
|
+
}
|
|
39
|
+
setStartSize(startSize);
|
|
40
|
+
onResizeStart?.(startSize);
|
|
41
|
+
});
|
|
42
|
+
const handleMouseMove = useEvent(e => {
|
|
43
|
+
if (!isDragging) return;
|
|
44
|
+
const currentPos = isHorizontal ? e.clientX : e.clientY;
|
|
45
|
+
let delta = currentPos - startPos;
|
|
46
|
+
|
|
47
|
+
// Adjust delta direction based on placement
|
|
48
|
+
if (direction === 'right' || direction === 'bottom') {
|
|
49
|
+
delta = -delta;
|
|
50
|
+
}
|
|
51
|
+
let newSize = startSize + delta;
|
|
52
|
+
|
|
53
|
+
// Apply min/max size limits
|
|
54
|
+
if (newSize < 0) {
|
|
55
|
+
newSize = 0;
|
|
56
|
+
}
|
|
57
|
+
// Only apply maxSize if it's a valid positive number
|
|
58
|
+
if (maxSize && newSize > maxSize) {
|
|
59
|
+
newSize = maxSize;
|
|
60
|
+
}
|
|
61
|
+
onResize?.(newSize);
|
|
62
|
+
});
|
|
63
|
+
const handleMouseUp = React.useCallback(() => {
|
|
64
|
+
if (isDragging) {
|
|
65
|
+
setIsDragging(false);
|
|
66
|
+
|
|
67
|
+
// Get the final size after resize
|
|
68
|
+
if (containerRef?.current) {
|
|
69
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
70
|
+
const finalSize = isHorizontal ? rect.width : rect.height;
|
|
71
|
+
onResizeEnd?.(finalSize);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}, [isDragging, containerRef, onResizeEnd, isHorizontal]);
|
|
75
|
+
React.useEffect(() => {
|
|
76
|
+
if (isDragging) {
|
|
77
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
78
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
79
|
+
return () => {
|
|
80
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
81
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}, [isDragging, handleMouseMove, handleMouseUp]);
|
|
85
|
+
const dragElementClassName = classNames(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
|
|
86
|
+
[`${prefixCls}-dragger-dragging`]: isDragging,
|
|
87
|
+
[`${prefixCls}-dragger-horizontal`]: isHorizontal,
|
|
88
|
+
[`${prefixCls}-dragger-vertical`]: !isHorizontal
|
|
89
|
+
}, className);
|
|
90
|
+
return {
|
|
91
|
+
dragElementProps: {
|
|
92
|
+
className: dragElementClassName,
|
|
93
|
+
style,
|
|
94
|
+
onMouseDown: handleMouseDown
|
|
95
|
+
},
|
|
96
|
+
isDragging
|
|
97
|
+
};
|
|
98
|
+
}
|
package/es/index.d.ts
CHANGED
package/es/inter.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ export interface DrawerClassNames {
|
|
|
3
3
|
mask?: string;
|
|
4
4
|
wrapper?: string;
|
|
5
5
|
section?: string;
|
|
6
|
+
dragger?: string;
|
|
6
7
|
}
|
|
7
8
|
export interface DrawerStyles {
|
|
8
9
|
mask?: React.CSSProperties;
|
|
9
10
|
wrapper?: React.CSSProperties;
|
|
10
11
|
section?: React.CSSProperties;
|
|
12
|
+
dragger?: React.CSSProperties;
|
|
11
13
|
}
|
package/es/util.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import warning from "@rc-component/util/es/warning";
|
|
2
2
|
import canUseDom from "@rc-component/util/es/Dom/canUseDom";
|
|
3
3
|
export function parseWidthHeight(value) {
|
|
4
|
-
if (typeof value === 'string'
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
if (typeof value === 'string') {
|
|
5
|
+
const num = Number(value.replace(/px$/i, ''));
|
|
6
|
+
const floatNum = parseFloat(value);
|
|
7
|
+
if (floatNum === num) {
|
|
8
|
+
warning(false, 'Invalid value type of `width` or `height` which should be number type instead.');
|
|
9
|
+
}
|
|
10
|
+
if (!Number.isNaN(num)) {
|
|
11
|
+
return num;
|
|
12
|
+
}
|
|
7
13
|
}
|
|
8
14
|
return value;
|
|
9
15
|
}
|
package/lib/Drawer.d.ts
CHANGED
|
@@ -13,6 +13,26 @@ export interface DrawerProps extends Omit<DrawerPopupProps, 'prefixCls' | 'inlin
|
|
|
13
13
|
panelRef?: React.Ref<HTMLDivElement>;
|
|
14
14
|
classNames?: DrawerClassNames;
|
|
15
15
|
styles?: DrawerStyles;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated Use `size` instead. Will be removed in next major version.
|
|
18
|
+
*/
|
|
19
|
+
width?: number | string;
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Use `size` instead. Will be removed in next major version.
|
|
22
|
+
*/
|
|
23
|
+
height?: number | string;
|
|
24
|
+
/** Size of the drawer (width for left/right placement, height for top/bottom placement) */
|
|
25
|
+
size?: number | string;
|
|
26
|
+
/** Maximum size of the drawer */
|
|
27
|
+
maxSize?: number;
|
|
28
|
+
/** Default size for uncontrolled resizable drawer */
|
|
29
|
+
defaultSize?: number | string;
|
|
30
|
+
/** Resizable configuration - object with optional callbacks */
|
|
31
|
+
resizable?: {
|
|
32
|
+
onResize?: (size: number) => void;
|
|
33
|
+
onResizeStart?: () => void;
|
|
34
|
+
onResizeEnd?: () => void;
|
|
35
|
+
};
|
|
16
36
|
}
|
|
17
37
|
declare const Drawer: React.FC<DrawerProps>;
|
|
18
38
|
export default Drawer;
|
package/lib/Drawer.js
CHANGED
|
@@ -20,7 +20,10 @@ const Drawer = props => {
|
|
|
20
20
|
placement = 'right',
|
|
21
21
|
autoFocus = true,
|
|
22
22
|
keyboard = true,
|
|
23
|
-
width
|
|
23
|
+
width,
|
|
24
|
+
height,
|
|
25
|
+
size,
|
|
26
|
+
maxSize,
|
|
24
27
|
mask = true,
|
|
25
28
|
maskClosable = true,
|
|
26
29
|
getContainer,
|
|
@@ -33,6 +36,8 @@ const Drawer = props => {
|
|
|
33
36
|
onClick,
|
|
34
37
|
onKeyDown,
|
|
35
38
|
onKeyUp,
|
|
39
|
+
resizable,
|
|
40
|
+
defaultSize,
|
|
36
41
|
// Refs
|
|
37
42
|
panelRef
|
|
38
43
|
} = props;
|
|
@@ -95,11 +100,16 @@ const Drawer = props => {
|
|
|
95
100
|
autoFocus,
|
|
96
101
|
keyboard,
|
|
97
102
|
width,
|
|
103
|
+
height,
|
|
104
|
+
size,
|
|
105
|
+
maxSize,
|
|
106
|
+
defaultSize,
|
|
98
107
|
mask,
|
|
99
108
|
maskClosable,
|
|
100
109
|
inline: getContainer === false,
|
|
101
110
|
afterOpenChange: internalAfterOpenChange,
|
|
102
111
|
ref: popupRef,
|
|
112
|
+
resizable,
|
|
103
113
|
...eventHandlers
|
|
104
114
|
};
|
|
105
115
|
return /*#__PURE__*/React.createElement(_context.RefContext.Provider, {
|
package/lib/DrawerPopup.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
|
|
|
24
24
|
children?: React.ReactNode;
|
|
25
25
|
width?: number | string;
|
|
26
26
|
height?: number | string;
|
|
27
|
+
/** Size of the drawer (width for left/right placement, height for top/bottom placement) */
|
|
28
|
+
size?: number | string;
|
|
29
|
+
/** Maximum size of the drawer */
|
|
30
|
+
maxSize?: number;
|
|
27
31
|
mask?: boolean;
|
|
28
32
|
maskClosable?: boolean;
|
|
29
33
|
maskClassName?: string;
|
|
@@ -35,6 +39,13 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
|
|
|
35
39
|
classNames?: DrawerClassNames;
|
|
36
40
|
styles?: DrawerStyles;
|
|
37
41
|
drawerRender?: (node: React.ReactNode) => React.ReactNode;
|
|
42
|
+
/** Default size for uncontrolled resizable drawer */
|
|
43
|
+
defaultSize?: number | string;
|
|
44
|
+
resizable?: {
|
|
45
|
+
onResize?: (size: number) => void;
|
|
46
|
+
onResizeStart?: () => void;
|
|
47
|
+
onResizeEnd?: () => void;
|
|
48
|
+
};
|
|
38
49
|
}
|
|
39
50
|
declare const RefDrawerPopup: React.ForwardRefExoticComponent<DrawerPopupProps & React.RefAttributes<HTMLDivElement>>;
|
|
40
51
|
export default RefDrawerPopup;
|
package/lib/DrawerPopup.js
CHANGED
|
@@ -11,7 +11,9 @@ var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttr
|
|
|
11
11
|
var React = _interopRequireWildcard(require("react"));
|
|
12
12
|
var _context = _interopRequireDefault(require("./context"));
|
|
13
13
|
var _DrawerPanel = _interopRequireDefault(require("./DrawerPanel"));
|
|
14
|
+
var _useDrag = _interopRequireDefault(require("./hooks/useDrag"));
|
|
14
15
|
var _util = require("./util");
|
|
16
|
+
var _util2 = require("@rc-component/util");
|
|
15
17
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
16
18
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
17
19
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -46,6 +48,8 @@ const DrawerPopup = (props, ref) => {
|
|
|
46
48
|
motion,
|
|
47
49
|
width,
|
|
48
50
|
height,
|
|
51
|
+
size,
|
|
52
|
+
maxSize,
|
|
49
53
|
children,
|
|
50
54
|
// Mask
|
|
51
55
|
mask,
|
|
@@ -63,7 +67,9 @@ const DrawerPopup = (props, ref) => {
|
|
|
63
67
|
onKeyDown,
|
|
64
68
|
onKeyUp,
|
|
65
69
|
styles,
|
|
66
|
-
drawerRender
|
|
70
|
+
drawerRender,
|
|
71
|
+
resizable,
|
|
72
|
+
defaultSize
|
|
67
73
|
} = props;
|
|
68
74
|
|
|
69
75
|
// ================================ Refs ================================
|
|
@@ -156,10 +162,10 @@ const DrawerPopup = (props, ref) => {
|
|
|
156
162
|
}, []);
|
|
157
163
|
|
|
158
164
|
// ============================ Mask ============================
|
|
159
|
-
const maskNode =
|
|
165
|
+
const maskNode = /*#__PURE__*/React.createElement(_motion.default, _extends({
|
|
160
166
|
key: "mask"
|
|
161
167
|
}, maskMotion, {
|
|
162
|
-
visible: open
|
|
168
|
+
visible: mask && open
|
|
163
169
|
}), ({
|
|
164
170
|
className: motionMaskClassName,
|
|
165
171
|
style: motionMaskStyle
|
|
@@ -176,28 +182,68 @@ const DrawerPopup = (props, ref) => {
|
|
|
176
182
|
|
|
177
183
|
// =========================== Panel ============================
|
|
178
184
|
const motionProps = typeof motion === 'function' ? motion(placement) : motion;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
|
|
186
|
+
// ============================ Size ============================
|
|
187
|
+
const [currentSize, setCurrentSize] = React.useState();
|
|
188
|
+
const isHorizontal = placement === 'left' || placement === 'right';
|
|
189
|
+
|
|
190
|
+
// Aggregate size logic with backward compatibility using useMemo
|
|
191
|
+
const mergedSize = React.useMemo(() => {
|
|
192
|
+
const legacySize = isHorizontal ? width : height;
|
|
193
|
+
const nextMergedSize = size ?? legacySize ?? currentSize ?? defaultSize ?? (isHorizontal ? 378 : undefined);
|
|
194
|
+
return (0, _util.parseWidthHeight)(nextMergedSize);
|
|
195
|
+
}, [size, width, height, defaultSize, isHorizontal, currentSize]);
|
|
196
|
+
|
|
197
|
+
// >>> Style
|
|
198
|
+
const wrapperStyle = React.useMemo(() => {
|
|
199
|
+
const nextWrapperStyle = {};
|
|
200
|
+
if (pushed && pushDistance) {
|
|
201
|
+
switch (placement) {
|
|
202
|
+
case 'top':
|
|
203
|
+
nextWrapperStyle.transform = `translateY(${pushDistance}px)`;
|
|
204
|
+
break;
|
|
205
|
+
case 'bottom':
|
|
206
|
+
nextWrapperStyle.transform = `translateY(${-pushDistance}px)`;
|
|
207
|
+
break;
|
|
208
|
+
case 'left':
|
|
209
|
+
nextWrapperStyle.transform = `translateX(${pushDistance}px)`;
|
|
210
|
+
break;
|
|
211
|
+
default:
|
|
212
|
+
nextWrapperStyle.transform = `translateX(${-pushDistance}px)`;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
194
215
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
216
|
+
if (isHorizontal) {
|
|
217
|
+
nextWrapperStyle.width = (0, _util.parseWidthHeight)(mergedSize);
|
|
218
|
+
} else {
|
|
219
|
+
nextWrapperStyle.height = (0, _util.parseWidthHeight)(mergedSize);
|
|
220
|
+
}
|
|
221
|
+
return nextWrapperStyle;
|
|
222
|
+
}, [pushed, pushDistance, placement, isHorizontal, mergedSize]);
|
|
223
|
+
|
|
224
|
+
// =========================== Resize ===========================
|
|
225
|
+
const wrapperRef = React.useRef(null);
|
|
226
|
+
const onInternalResize = (0, _util2.useEvent)(size => {
|
|
227
|
+
setCurrentSize(size);
|
|
228
|
+
resizable?.onResize?.(size);
|
|
229
|
+
});
|
|
230
|
+
const {
|
|
231
|
+
dragElementProps,
|
|
232
|
+
isDragging
|
|
233
|
+
} = (0, _useDrag.default)({
|
|
234
|
+
prefixCls: `${prefixCls}-resizable`,
|
|
235
|
+
direction: placement,
|
|
236
|
+
className: drawerClassNames?.dragger,
|
|
237
|
+
style: styles?.dragger,
|
|
238
|
+
maxSize,
|
|
239
|
+
containerRef: wrapperRef,
|
|
240
|
+
currentSize: mergedSize,
|
|
241
|
+
onResize: onInternalResize,
|
|
242
|
+
onResizeStart: resizable?.onResizeStart,
|
|
243
|
+
onResizeEnd: resizable?.onResizeEnd
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// =========================== Events ===========================
|
|
201
247
|
const eventHandlers = {
|
|
202
248
|
onMouseEnter,
|
|
203
249
|
onMouseOver,
|
|
@@ -206,6 +252,9 @@ const DrawerPopup = (props, ref) => {
|
|
|
206
252
|
onKeyDown,
|
|
207
253
|
onKeyUp
|
|
208
254
|
};
|
|
255
|
+
|
|
256
|
+
// =========================== Render ==========================
|
|
257
|
+
// >>>>> Panel
|
|
209
258
|
const panelNode = /*#__PURE__*/React.createElement(_motion.default, _extends({
|
|
210
259
|
key: "panel"
|
|
211
260
|
}, motionProps, {
|
|
@@ -233,18 +282,19 @@ const DrawerPopup = (props, ref) => {
|
|
|
233
282
|
aria: true
|
|
234
283
|
}), eventHandlers), children);
|
|
235
284
|
return /*#__PURE__*/React.createElement("div", _extends({
|
|
236
|
-
|
|
285
|
+
ref: wrapperRef,
|
|
286
|
+
className: (0, _classnames.default)(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
|
|
237
287
|
style: {
|
|
238
|
-
...wrapperStyle,
|
|
239
288
|
...motionStyle,
|
|
289
|
+
...wrapperStyle,
|
|
240
290
|
...styles?.wrapper
|
|
241
291
|
}
|
|
242
292
|
}, (0, _pickAttrs.default)(props, {
|
|
243
293
|
data: true
|
|
244
|
-
})), drawerRender ? drawerRender(content) : content);
|
|
294
|
+
})), resizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
|
|
245
295
|
});
|
|
246
296
|
|
|
247
|
-
//
|
|
297
|
+
// >>>>> Container
|
|
248
298
|
const containerStyle = {
|
|
249
299
|
...rootStyle
|
|
250
300
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Placement } from '../Drawer';
|
|
3
|
+
export interface UseDragOptions {
|
|
4
|
+
prefixCls: string;
|
|
5
|
+
direction: Placement;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
maxSize?: number;
|
|
9
|
+
containerRef?: React.RefObject<HTMLElement>;
|
|
10
|
+
currentSize?: number | string;
|
|
11
|
+
onResize?: (size: number) => void;
|
|
12
|
+
onResizeEnd?: (size: number) => void;
|
|
13
|
+
onResizeStart?: (size: number) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface UseDragReturn {
|
|
16
|
+
dragElementProps: {
|
|
17
|
+
className: string;
|
|
18
|
+
style: React.CSSProperties;
|
|
19
|
+
onMouseDown: (e: React.MouseEvent) => void;
|
|
20
|
+
};
|
|
21
|
+
isDragging: boolean;
|
|
22
|
+
}
|
|
23
|
+
export default function useDrag(options: UseDragOptions): UseDragReturn;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = useDrag;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
9
|
+
var _util = require("@rc-component/util");
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
|
+
function useDrag(options) {
|
|
14
|
+
const {
|
|
15
|
+
prefixCls,
|
|
16
|
+
direction,
|
|
17
|
+
className,
|
|
18
|
+
style,
|
|
19
|
+
maxSize,
|
|
20
|
+
containerRef,
|
|
21
|
+
currentSize,
|
|
22
|
+
onResize,
|
|
23
|
+
onResizeEnd,
|
|
24
|
+
onResizeStart
|
|
25
|
+
} = options;
|
|
26
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
27
|
+
const [startPos, setStartPos] = React.useState(0);
|
|
28
|
+
const [startSize, setStartSize] = React.useState(0);
|
|
29
|
+
const isHorizontal = direction === 'left' || direction === 'right';
|
|
30
|
+
const handleMouseDown = (0, _util.useEvent)(e => {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
setIsDragging(true);
|
|
34
|
+
if (isHorizontal) {
|
|
35
|
+
setStartPos(e.clientX);
|
|
36
|
+
} else {
|
|
37
|
+
setStartPos(e.clientY);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Use provided currentSize, or fallback to container size
|
|
41
|
+
let startSize;
|
|
42
|
+
if (typeof currentSize === 'number') {
|
|
43
|
+
startSize = currentSize;
|
|
44
|
+
} else if (containerRef?.current) {
|
|
45
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
46
|
+
startSize = isHorizontal ? rect.width : rect.height;
|
|
47
|
+
}
|
|
48
|
+
setStartSize(startSize);
|
|
49
|
+
onResizeStart?.(startSize);
|
|
50
|
+
});
|
|
51
|
+
const handleMouseMove = (0, _util.useEvent)(e => {
|
|
52
|
+
if (!isDragging) return;
|
|
53
|
+
const currentPos = isHorizontal ? e.clientX : e.clientY;
|
|
54
|
+
let delta = currentPos - startPos;
|
|
55
|
+
|
|
56
|
+
// Adjust delta direction based on placement
|
|
57
|
+
if (direction === 'right' || direction === 'bottom') {
|
|
58
|
+
delta = -delta;
|
|
59
|
+
}
|
|
60
|
+
let newSize = startSize + delta;
|
|
61
|
+
|
|
62
|
+
// Apply min/max size limits
|
|
63
|
+
if (newSize < 0) {
|
|
64
|
+
newSize = 0;
|
|
65
|
+
}
|
|
66
|
+
// Only apply maxSize if it's a valid positive number
|
|
67
|
+
if (maxSize && newSize > maxSize) {
|
|
68
|
+
newSize = maxSize;
|
|
69
|
+
}
|
|
70
|
+
onResize?.(newSize);
|
|
71
|
+
});
|
|
72
|
+
const handleMouseUp = React.useCallback(() => {
|
|
73
|
+
if (isDragging) {
|
|
74
|
+
setIsDragging(false);
|
|
75
|
+
|
|
76
|
+
// Get the final size after resize
|
|
77
|
+
if (containerRef?.current) {
|
|
78
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
79
|
+
const finalSize = isHorizontal ? rect.width : rect.height;
|
|
80
|
+
onResizeEnd?.(finalSize);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}, [isDragging, containerRef, onResizeEnd, isHorizontal]);
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
if (isDragging) {
|
|
86
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
87
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
88
|
+
return () => {
|
|
89
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
90
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}, [isDragging, handleMouseMove, handleMouseUp]);
|
|
94
|
+
const dragElementClassName = (0, _classnames.default)(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
|
|
95
|
+
[`${prefixCls}-dragger-dragging`]: isDragging,
|
|
96
|
+
[`${prefixCls}-dragger-horizontal`]: isHorizontal,
|
|
97
|
+
[`${prefixCls}-dragger-vertical`]: !isHorizontal
|
|
98
|
+
}, className);
|
|
99
|
+
return {
|
|
100
|
+
dragElementProps: {
|
|
101
|
+
className: dragElementClassName,
|
|
102
|
+
style,
|
|
103
|
+
onMouseDown: handleMouseDown
|
|
104
|
+
},
|
|
105
|
+
isDragging
|
|
106
|
+
};
|
|
107
|
+
}
|
package/lib/index.d.ts
CHANGED
package/lib/inter.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ export interface DrawerClassNames {
|
|
|
3
3
|
mask?: string;
|
|
4
4
|
wrapper?: string;
|
|
5
5
|
section?: string;
|
|
6
|
+
dragger?: string;
|
|
6
7
|
}
|
|
7
8
|
export interface DrawerStyles {
|
|
8
9
|
mask?: React.CSSProperties;
|
|
9
10
|
wrapper?: React.CSSProperties;
|
|
10
11
|
section?: React.CSSProperties;
|
|
12
|
+
dragger?: React.CSSProperties;
|
|
11
13
|
}
|
package/lib/util.js
CHANGED
|
@@ -9,9 +9,15 @@ var _warning = _interopRequireDefault(require("@rc-component/util/lib/warning"))
|
|
|
9
9
|
var _canUseDom = _interopRequireDefault(require("@rc-component/util/lib/Dom/canUseDom"));
|
|
10
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
11
|
function parseWidthHeight(value) {
|
|
12
|
-
if (typeof value === 'string'
|
|
13
|
-
(
|
|
14
|
-
|
|
12
|
+
if (typeof value === 'string') {
|
|
13
|
+
const num = Number(value.replace(/px$/i, ''));
|
|
14
|
+
const floatNum = parseFloat(value);
|
|
15
|
+
if (floatNum === num) {
|
|
16
|
+
(0, _warning.default)(false, 'Invalid value type of `width` or `height` which should be number type instead.');
|
|
17
|
+
}
|
|
18
|
+
if (!Number.isNaN(num)) {
|
|
19
|
+
return num;
|
|
20
|
+
}
|
|
15
21
|
}
|
|
16
22
|
return value;
|
|
17
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rc-component/drawer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "drawer component for react",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"@rc-component/father-plugin": "^2.0.2",
|
|
54
54
|
"@rc-component/np": "^1.0.0",
|
|
55
55
|
"@testing-library/jest-dom": "^6.2.0",
|
|
56
|
-
"@testing-library/react": "^
|
|
56
|
+
"@testing-library/react": "^16.3.0",
|
|
57
57
|
"@types/classnames": "^2.2.9",
|
|
58
58
|
"@types/jest": "^29.5.11",
|
|
59
|
-
"@types/node": "^
|
|
59
|
+
"@types/node": "^24.3.0",
|
|
60
60
|
"@types/raf": "^3.4.0",
|
|
61
61
|
"@types/react": "^19.0.0",
|
|
62
62
|
"@types/react-dom": "^19.0.0",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"glob": "^10.3.10",
|
|
71
71
|
"husky": "^9.0.10",
|
|
72
72
|
"less": "^4.2.0",
|
|
73
|
-
"lint-staged": "^
|
|
73
|
+
"lint-staged": "^16.1.5",
|
|
74
74
|
"prettier": "^3.0.0",
|
|
75
75
|
"rc-test": "^7.0.9",
|
|
76
76
|
"react": "^19.0.0",
|