@rc-component/drawer 1.1.0 → 1.3.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 CHANGED
@@ -1,15 +1,13 @@
1
- # rc-drawer
1
+ # @rc-component/drawer
2
2
 
3
- [![NPM version][npm-image]][npm-url] [![dumi](https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square)](https://github.com/umijs/dumi) [![build status][github-actions-image]][github-actions-url] [![codecov](https://codecov.io/gh/react-component/drawer/branch/master/graph/badge.svg)](https://codecov.io/gh/react-component/drawer) [![node version][node-image]][node-url] [![npm download][download-image]][download-url]
3
+ [![NPM version][npm-image]][npm-url] [![dumi](https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square)](https://github.com/umijs/dumi) [![build status][github-actions-image]][github-actions-url] [![codecov](https://codecov.io/gh/react-component/drawer/branch/master/graph/badge.svg)](https://codecov.io/gh/react-component/drawer) [![npm download][download-image]][download-url]
4
4
 
5
- [npm-image]: http://img.shields.io/npm/v/rc-drawer.svg?style=flat-square
6
- [npm-url]: http://npmjs.org/package/rc-drawer
7
- [github-actions-image]: https://github.com/react-component/drawer/workflows/CI/badge.svg
8
- [github-actions-url]: https://github.com/react-component/drawer/actions
9
- [node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square
10
- [node-url]: http://nodejs.org/download/
11
- [download-image]: https://img.shields.io/npm/dm/rc-drawer.svg?style=flat-square
12
- [download-url]: https://npmjs.org/package/rc-drawer
5
+ [npm-image]: http://img.shields.io/npm/v/@rc-component/drawer.svg?style=flat-square
6
+ [npm-url]: http://npmjs.org/package/@rc-component/drawer
7
+ [github-actions-image]: https://github.com/react-component/drawer/actions/workflows/react-component-ci.yml/badge.svg
8
+ [github-actions-url]: https://github.com/react-component/drawer/actions/workflows/react-component-ci.yml
9
+ [download-image]: https://img.shields.io/npm/dm/@rc-component/drawer.svg?style=flat-square
10
+ [download-url]: https://npmjs.org/package/@rc-component/drawer
13
11
 
14
12
  ## Example
15
13
 
@@ -18,7 +16,7 @@ https://drawer-react-component.vercel.app/
18
16
  ## Usage
19
17
 
20
18
  ```js
21
- import Drawer from 'rc-drawer';
19
+ import Drawer from '@rc-component/drawer';
22
20
  import React from 'react';
23
21
  import ReactDom from 'react-dom';
24
22
 
@@ -31,7 +29,7 @@ ReactDom.render(
31
29
 
32
30
  ## Install
33
31
 
34
- [![rc-drawer](https://nodei.co/npm/rc-drawer.png)](https://npmjs.org/package/rc-drawer)
32
+ [![@rc-component/drawer](https://nodei.co/npm/@rc-component/drawer.png)](https://npmjs.org/package/@rc-component/drawer)
35
33
 
36
34
  ## Browser Support
37
35
 
@@ -45,10 +43,12 @@ ReactDom.render(
45
43
  | ------------------ | --------------------------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------- |
46
44
  | className | string | null | - |
47
45
  | classNames | { mask?: string; content?: string; wrapper?: string; } | - | pass className to target area |
48
- | styles | { mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties; } | - | pass style to target area |
46
+ | styles | { mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties; } | `rc-drawer` | pass style to target area |
49
47
  | prefixCls | string | 'drawer' | prefix class |
50
48
  | width | string \| number | null | drawer content wrapper width, drawer level transition width |
51
49
  | height | string \| number | null | drawer content wrapper height, drawer level transition height |
50
+ | defaultWidth | string \| number | null | default width for uncontrolled resizable drawer |
51
+ | defaultHeight | string \| number | null | default height for uncontrolled resizable drawer |
52
52
  | open | boolean | false | open or close menu |
53
53
  | defaultOpen | boolean | false | default open menu |
54
54
  | placement | string | `left` | `left` `top` `right` `bottom` |
@@ -64,6 +64,7 @@ ReactDom.render(
64
64
  | onClose | func | null | close click function |
65
65
  | keyboard | boolean | true | Whether support press esc to close |
66
66
  | autoFocus | boolean | true | Whether focusing on the drawer after it opened |
67
+ | resizable | { onResize?: (size: number) => void; onResizeStart?: () => void; onResizeEnd?: () => void; } | - | Resizable configuration with optional callbacks |
67
68
  | onMouseEnter | React.MouseEventHandler\<HTMLDivElement\> | - | Trigger when mouse enter drawer panel |
68
69
  | onMouseOver | React.MouseEventHandler\<HTMLDivElement\> | - | Trigger when mouse over drawer panel |
69
70
  | 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 - boolean to enable/disable or object with optional callbacks */
31
+ resizable?: boolean | {
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 = 378,
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/DrawerPanel.js CHANGED
@@ -1,5 +1,5 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
- import classNames from 'classnames';
2
+ import { clsx } from 'clsx';
3
3
  import * as React from 'react';
4
4
  import { RefContext } from "./context";
5
5
  import pickAttrs from "@rc-component/util/es/pickAttrs";
@@ -19,7 +19,7 @@ const DrawerPanel = props => {
19
19
  // =============================== Render ===============================
20
20
 
21
21
  return /*#__PURE__*/React.createElement("div", _extends({
22
- className: classNames(`${prefixCls}-section`, className),
22
+ className: clsx(`${prefixCls}-section`, className),
23
23
  role: "dialog",
24
24
  ref: mergedRef
25
25
  }, pickAttrs(props, {
@@ -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?: boolean | {
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
@@ -1,12 +1,14 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
- import classNames from 'classnames';
2
+ import { clsx } from 'clsx';
3
3
  import CSSMotion from '@rc-component/motion';
4
4
  import KeyCode from "@rc-component/util/es/KeyCode";
5
5
  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,15 +153,15 @@ const DrawerPopup = (props, ref) => {
147
153
  }, []);
148
154
 
149
155
  // ============================ Mask ============================
150
- const maskNode = mask && /*#__PURE__*/React.createElement(CSSMotion, _extends({
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
157
163
  }, maskRef) => /*#__PURE__*/React.createElement("div", {
158
- className: classNames(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
164
+ className: clsx(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
159
165
  style: {
160
166
  ...motionMaskStyle,
161
167
  ...maskStyle,
@@ -167,28 +173,70 @@ const DrawerPopup = (props, ref) => {
167
173
 
168
174
  // =========================== Panel ============================
169
175
  const motionProps = typeof motion === 'function' ? motion(placement) : motion;
170
- const wrapperStyle = {};
171
- if (pushed && pushDistance) {
172
- switch (placement) {
173
- case 'top':
174
- wrapperStyle.transform = `translateY(${pushDistance}px)`;
175
- break;
176
- case 'bottom':
177
- wrapperStyle.transform = `translateY(${-pushDistance}px)`;
178
- break;
179
- case 'left':
180
- wrapperStyle.transform = `translateX(${pushDistance}px)`;
181
- break;
182
- default:
183
- wrapperStyle.transform = `translateX(${-pushDistance}px)`;
184
- break;
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
- if (placement === 'left' || placement === 'right') {
188
- wrapperStyle.width = parseWidthHeight(width);
189
- } else {
190
- wrapperStyle.height = parseWidthHeight(height);
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 isResizable = !!resizable;
218
+ const resizeConfig = typeof resizable === 'object' && resizable || {};
219
+ const onInternalResize = useEvent(size => {
220
+ setCurrentSize(size);
221
+ resizeConfig.onResize?.(size);
222
+ });
223
+ const {
224
+ dragElementProps,
225
+ isDragging
226
+ } = useDrag({
227
+ prefixCls: `${prefixCls}-resizable`,
228
+ direction: placement,
229
+ className: drawerClassNames?.dragger,
230
+ style: styles?.dragger,
231
+ maxSize,
232
+ containerRef: wrapperRef,
233
+ currentSize: mergedSize,
234
+ onResize: onInternalResize,
235
+ onResizeStart: resizeConfig.onResizeStart,
236
+ onResizeEnd: resizeConfig.onResizeEnd
237
+ });
238
+
239
+ // =========================== Events ===========================
192
240
  const eventHandlers = {
193
241
  onMouseEnter,
194
242
  onMouseOver,
@@ -197,6 +245,9 @@ const DrawerPopup = (props, ref) => {
197
245
  onKeyDown,
198
246
  onKeyUp
199
247
  };
248
+
249
+ // =========================== Render ==========================
250
+ // >>>>> Panel
200
251
  const panelNode = /*#__PURE__*/React.createElement(CSSMotion, _extends({
201
252
  key: "panel"
202
253
  }, motionProps, {
@@ -215,7 +266,7 @@ const DrawerPopup = (props, ref) => {
215
266
  id: id,
216
267
  containerRef: motionRef,
217
268
  prefixCls: prefixCls,
218
- className: classNames(className, drawerClassNames?.section),
269
+ className: clsx(className, drawerClassNames?.section),
219
270
  style: {
220
271
  ...style,
221
272
  ...styles?.section
@@ -224,18 +275,19 @@ const DrawerPopup = (props, ref) => {
224
275
  aria: true
225
276
  }), eventHandlers), children);
226
277
  return /*#__PURE__*/React.createElement("div", _extends({
227
- className: classNames(`${prefixCls}-content-wrapper`, drawerClassNames?.wrapper, motionClassName),
278
+ ref: wrapperRef,
279
+ className: clsx(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
228
280
  style: {
229
- ...wrapperStyle,
230
281
  ...motionStyle,
282
+ ...wrapperStyle,
231
283
  ...styles?.wrapper
232
284
  }
233
285
  }, pickAttrs(props, {
234
286
  data: true
235
- })), drawerRender ? drawerRender(content) : content);
287
+ })), isResizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
236
288
  });
237
289
 
238
- // =========================== Render ===========================
290
+ // >>>>> Container
239
291
  const containerStyle = {
240
292
  ...rootStyle
241
293
  };
@@ -245,7 +297,7 @@ const DrawerPopup = (props, ref) => {
245
297
  return /*#__PURE__*/React.createElement(DrawerContext.Provider, {
246
298
  value: mergedContext
247
299
  }, /*#__PURE__*/React.createElement("div", {
248
- className: classNames(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
300
+ className: clsx(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
249
301
  [`${prefixCls}-open`]: open,
250
302
  [`${prefixCls}-inline`]: inline
251
303
  }),
@@ -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 { clsx } from 'clsx';
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 = clsx(`${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
@@ -1,4 +1,4 @@
1
1
  import Drawer from './Drawer';
2
- import type { DrawerProps } from './Drawer';
3
- export type { DrawerProps };
2
+ import type { DrawerProps, Placement } from './Drawer';
3
+ export type { DrawerProps, Placement };
4
4
  export default Drawer;
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' && String(Number(value)) === value) {
5
- warning(false, 'Invalid value type of `width` or `height` which should be number type instead.');
6
- return Number(value);
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 - boolean to enable/disable or object with optional callbacks */
31
+ resizable?: boolean | {
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 = 378,
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, {
@@ -4,14 +4,14 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _classnames = _interopRequireDefault(require("classnames"));
7
+ var _clsx = require("clsx");
8
8
  var React = _interopRequireWildcard(require("react"));
9
9
  var _context = require("./context");
10
10
  var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttrs"));
11
11
  var _ref = require("@rc-component/util/lib/ref");
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13
  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); }
13
14
  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; }
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
15
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
16
16
  const DrawerPanel = props => {
17
17
  const {
@@ -28,7 +28,7 @@ const DrawerPanel = props => {
28
28
  // =============================== Render ===============================
29
29
 
30
30
  return /*#__PURE__*/React.createElement("div", _extends({
31
- className: (0, _classnames.default)(`${prefixCls}-section`, className),
31
+ className: (0, _clsx.clsx)(`${prefixCls}-section`, className),
32
32
  role: "dialog",
33
33
  ref: mergedRef
34
34
  }, (0, _pickAttrs.default)(props, {
@@ -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?: boolean | {
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;
@@ -4,14 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _classnames = _interopRequireDefault(require("classnames"));
7
+ var _clsx = require("clsx");
8
8
  var _motion = _interopRequireDefault(require("@rc-component/motion"));
9
9
  var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
10
10
  var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttrs"));
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,15 +162,15 @@ const DrawerPopup = (props, ref) => {
156
162
  }, []);
157
163
 
158
164
  // ============================ Mask ============================
159
- const maskNode = mask && /*#__PURE__*/React.createElement(_motion.default, _extends({
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
166
172
  }, maskRef) => /*#__PURE__*/React.createElement("div", {
167
- className: (0, _classnames.default)(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
173
+ className: (0, _clsx.clsx)(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
168
174
  style: {
169
175
  ...motionMaskStyle,
170
176
  ...maskStyle,
@@ -176,28 +182,70 @@ const DrawerPopup = (props, ref) => {
176
182
 
177
183
  // =========================== Panel ============================
178
184
  const motionProps = typeof motion === 'function' ? motion(placement) : motion;
179
- const wrapperStyle = {};
180
- if (pushed && pushDistance) {
181
- switch (placement) {
182
- case 'top':
183
- wrapperStyle.transform = `translateY(${pushDistance}px)`;
184
- break;
185
- case 'bottom':
186
- wrapperStyle.transform = `translateY(${-pushDistance}px)`;
187
- break;
188
- case 'left':
189
- wrapperStyle.transform = `translateX(${pushDistance}px)`;
190
- break;
191
- default:
192
- wrapperStyle.transform = `translateX(${-pushDistance}px)`;
193
- break;
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
- if (placement === 'left' || placement === 'right') {
197
- wrapperStyle.width = (0, _util.parseWidthHeight)(width);
198
- } else {
199
- wrapperStyle.height = (0, _util.parseWidthHeight)(height);
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 isResizable = !!resizable;
227
+ const resizeConfig = typeof resizable === 'object' && resizable || {};
228
+ const onInternalResize = (0, _util2.useEvent)(size => {
229
+ setCurrentSize(size);
230
+ resizeConfig.onResize?.(size);
231
+ });
232
+ const {
233
+ dragElementProps,
234
+ isDragging
235
+ } = (0, _useDrag.default)({
236
+ prefixCls: `${prefixCls}-resizable`,
237
+ direction: placement,
238
+ className: drawerClassNames?.dragger,
239
+ style: styles?.dragger,
240
+ maxSize,
241
+ containerRef: wrapperRef,
242
+ currentSize: mergedSize,
243
+ onResize: onInternalResize,
244
+ onResizeStart: resizeConfig.onResizeStart,
245
+ onResizeEnd: resizeConfig.onResizeEnd
246
+ });
247
+
248
+ // =========================== Events ===========================
201
249
  const eventHandlers = {
202
250
  onMouseEnter,
203
251
  onMouseOver,
@@ -206,6 +254,9 @@ const DrawerPopup = (props, ref) => {
206
254
  onKeyDown,
207
255
  onKeyUp
208
256
  };
257
+
258
+ // =========================== Render ==========================
259
+ // >>>>> Panel
209
260
  const panelNode = /*#__PURE__*/React.createElement(_motion.default, _extends({
210
261
  key: "panel"
211
262
  }, motionProps, {
@@ -224,7 +275,7 @@ const DrawerPopup = (props, ref) => {
224
275
  id: id,
225
276
  containerRef: motionRef,
226
277
  prefixCls: prefixCls,
227
- className: (0, _classnames.default)(className, drawerClassNames?.section),
278
+ className: (0, _clsx.clsx)(className, drawerClassNames?.section),
228
279
  style: {
229
280
  ...style,
230
281
  ...styles?.section
@@ -233,18 +284,19 @@ const DrawerPopup = (props, ref) => {
233
284
  aria: true
234
285
  }), eventHandlers), children);
235
286
  return /*#__PURE__*/React.createElement("div", _extends({
236
- className: (0, _classnames.default)(`${prefixCls}-content-wrapper`, drawerClassNames?.wrapper, motionClassName),
287
+ ref: wrapperRef,
288
+ className: (0, _clsx.clsx)(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
237
289
  style: {
238
- ...wrapperStyle,
239
290
  ...motionStyle,
291
+ ...wrapperStyle,
240
292
  ...styles?.wrapper
241
293
  }
242
294
  }, (0, _pickAttrs.default)(props, {
243
295
  data: true
244
- })), drawerRender ? drawerRender(content) : content);
296
+ })), isResizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
245
297
  });
246
298
 
247
- // =========================== Render ===========================
299
+ // >>>>> Container
248
300
  const containerStyle = {
249
301
  ...rootStyle
250
302
  };
@@ -254,7 +306,7 @@ const DrawerPopup = (props, ref) => {
254
306
  return /*#__PURE__*/React.createElement(_context.default.Provider, {
255
307
  value: mergedContext
256
308
  }, /*#__PURE__*/React.createElement("div", {
257
- className: (0, _classnames.default)(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
309
+ className: (0, _clsx.clsx)(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
258
310
  [`${prefixCls}-open`]: open,
259
311
  [`${prefixCls}-inline`]: inline
260
312
  }),
@@ -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,106 @@
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 _clsx = require("clsx");
9
+ var _util = require("@rc-component/util");
10
+ 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); }
11
+ 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; }
12
+ function useDrag(options) {
13
+ const {
14
+ prefixCls,
15
+ direction,
16
+ className,
17
+ style,
18
+ maxSize,
19
+ containerRef,
20
+ currentSize,
21
+ onResize,
22
+ onResizeEnd,
23
+ onResizeStart
24
+ } = options;
25
+ const [isDragging, setIsDragging] = React.useState(false);
26
+ const [startPos, setStartPos] = React.useState(0);
27
+ const [startSize, setStartSize] = React.useState(0);
28
+ const isHorizontal = direction === 'left' || direction === 'right';
29
+ const handleMouseDown = (0, _util.useEvent)(e => {
30
+ e.preventDefault();
31
+ e.stopPropagation();
32
+ setIsDragging(true);
33
+ if (isHorizontal) {
34
+ setStartPos(e.clientX);
35
+ } else {
36
+ setStartPos(e.clientY);
37
+ }
38
+
39
+ // Use provided currentSize, or fallback to container size
40
+ let startSize;
41
+ if (typeof currentSize === 'number') {
42
+ startSize = currentSize;
43
+ } else if (containerRef?.current) {
44
+ const rect = containerRef.current.getBoundingClientRect();
45
+ startSize = isHorizontal ? rect.width : rect.height;
46
+ }
47
+ setStartSize(startSize);
48
+ onResizeStart?.(startSize);
49
+ });
50
+ const handleMouseMove = (0, _util.useEvent)(e => {
51
+ if (!isDragging) return;
52
+ const currentPos = isHorizontal ? e.clientX : e.clientY;
53
+ let delta = currentPos - startPos;
54
+
55
+ // Adjust delta direction based on placement
56
+ if (direction === 'right' || direction === 'bottom') {
57
+ delta = -delta;
58
+ }
59
+ let newSize = startSize + delta;
60
+
61
+ // Apply min/max size limits
62
+ if (newSize < 0) {
63
+ newSize = 0;
64
+ }
65
+ // Only apply maxSize if it's a valid positive number
66
+ if (maxSize && newSize > maxSize) {
67
+ newSize = maxSize;
68
+ }
69
+ onResize?.(newSize);
70
+ });
71
+ const handleMouseUp = React.useCallback(() => {
72
+ if (isDragging) {
73
+ setIsDragging(false);
74
+
75
+ // Get the final size after resize
76
+ if (containerRef?.current) {
77
+ const rect = containerRef.current.getBoundingClientRect();
78
+ const finalSize = isHorizontal ? rect.width : rect.height;
79
+ onResizeEnd?.(finalSize);
80
+ }
81
+ }
82
+ }, [isDragging, containerRef, onResizeEnd, isHorizontal]);
83
+ React.useEffect(() => {
84
+ if (isDragging) {
85
+ document.addEventListener('mousemove', handleMouseMove);
86
+ document.addEventListener('mouseup', handleMouseUp);
87
+ return () => {
88
+ document.removeEventListener('mousemove', handleMouseMove);
89
+ document.removeEventListener('mouseup', handleMouseUp);
90
+ };
91
+ }
92
+ }, [isDragging, handleMouseMove, handleMouseUp]);
93
+ const dragElementClassName = (0, _clsx.clsx)(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
94
+ [`${prefixCls}-dragger-dragging`]: isDragging,
95
+ [`${prefixCls}-dragger-horizontal`]: isHorizontal,
96
+ [`${prefixCls}-dragger-vertical`]: !isHorizontal
97
+ }, className);
98
+ return {
99
+ dragElementProps: {
100
+ className: dragElementClassName,
101
+ style,
102
+ onMouseDown: handleMouseDown
103
+ },
104
+ isDragging
105
+ };
106
+ }
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import Drawer from './Drawer';
2
- import type { DrawerProps } from './Drawer';
3
- export type { DrawerProps };
2
+ import type { DrawerProps, Placement } from './Drawer';
3
+ export type { DrawerProps, Placement };
4
4
  export default Drawer;
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' && String(Number(value)) === value) {
13
- (0, _warning.default)(false, 'Invalid value type of `width` or `height` which should be number type instead.');
14
- return Number(value);
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.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "drawer component for react",
5
5
  "keywords": [
6
6
  "react",
@@ -46,17 +46,16 @@
46
46
  "@rc-component/motion": "^1.1.4",
47
47
  "@rc-component/portal": "^2.0.0",
48
48
  "@rc-component/util": "^1.2.1",
49
- "classnames": "^2.2.6"
49
+ "clsx": "^2.1.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@ant-design/icons": "^5.3.0",
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": "^15.0.7",
57
- "@types/classnames": "^2.2.9",
56
+ "@testing-library/react": "^16.3.0",
58
57
  "@types/jest": "^29.5.11",
59
- "@types/node": "^22.15.18",
58
+ "@types/node": "^24.3.0",
60
59
  "@types/raf": "^3.4.0",
61
60
  "@types/react": "^19.0.0",
62
61
  "@types/react-dom": "^19.0.0",
@@ -64,13 +63,13 @@
64
63
  "antd": "^5.12.7",
65
64
  "dumi": "^2.2.0",
66
65
  "eslint": "^8.56.0",
67
- "eslint-plugin-jest": "^27.6.0",
66
+ "eslint-plugin-jest": "^29.0.1",
68
67
  "eslint-plugin-unicorn": "^51.0.1",
69
68
  "father": "^4.0.0",
70
69
  "glob": "^10.3.10",
71
70
  "husky": "^9.0.10",
72
71
  "less": "^4.2.0",
73
- "lint-staged": "^15.2.2",
72
+ "lint-staged": "^16.1.5",
74
73
  "prettier": "^3.0.0",
75
74
  "rc-test": "^7.0.9",
76
75
  "react": "^19.0.0",