@rc-component/drawer 1.2.0 → 1.4.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,22 @@
1
- # rc-drawer
1
+ # @rc-component/drawer
2
+
3
+ [![NPM version][npm-image]][npm-url]
4
+ [![npm download][download-image]][download-url]
5
+ [![build status][github-actions-image]][github-actions-url]
6
+ [![codecov][codecov-image]][codecov-url]
7
+ [![dumi][dumi-image]][dumi-url]
8
+
9
+ [npm-image]: http://img.shields.io/npm/v/@rc-component/drawer.svg?style=flat-square
10
+ [npm-url]: http://npmjs.org/package/@rc-component/drawer
11
+ [dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
12
+ [dumi-url]: https://github.com/umijs/dumi
13
+ [github-actions-image]: https://github.com/react-component/drawer/actions/workflows/react-component-ci.yml/badge.svg
14
+ [github-actions-url]: https://github.com/react-component/drawer/actions/workflows/react-component-ci.yml
15
+ [download-image]: https://img.shields.io/npm/dm/@rc-component/drawer.svg?style=flat-square
16
+ [download-url]: https://npmjs.org/package/@rc-component/drawer
17
+ [codecov-image]: https://codecov.io/gh/react-component/drawer/branch/master/graph/badge.svg
18
+ [codecov-url]: https://codecov.io/gh/react-component/drawer
2
19
 
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]
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
13
20
 
14
21
  ## Example
15
22
 
@@ -18,7 +25,7 @@ https://drawer-react-component.vercel.app/
18
25
  ## Usage
19
26
 
20
27
  ```js
21
- import Drawer from 'rc-drawer';
28
+ import Drawer from '@rc-component/drawer';
22
29
  import React from 'react';
23
30
  import ReactDom from 'react-dom';
24
31
 
@@ -31,7 +38,7 @@ ReactDom.render(
31
38
 
32
39
  ## Install
33
40
 
34
- [![rc-drawer](https://nodei.co/npm/rc-drawer.png)](https://npmjs.org/package/rc-drawer)
41
+ [![@rc-component/drawer](https://nodei.co/npm/@rc-component/drawer.png)](https://npmjs.org/package/@rc-component/drawer)
35
42
 
36
43
  ## Browser Support
37
44
 
@@ -45,7 +52,7 @@ ReactDom.render(
45
52
  | ------------------ | --------------------------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------- |
46
53
  | className | string | null | - |
47
54
  | 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 |
55
+ | styles | { mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties; } | `rc-drawer` | pass style to target area |
49
56
  | prefixCls | string | 'drawer' | prefix class |
50
57
  | width | string \| number | null | drawer content wrapper width, drawer level transition width |
51
58
  | height | string \| number | null | drawer content wrapper height, drawer level transition height |
package/assets/index.css CHANGED
@@ -18,6 +18,7 @@
18
18
  position: absolute;
19
19
  z-index: 1050;
20
20
  transition: transform 0.3s;
21
+ pointer-events: auto;
21
22
  }
22
23
  .rc-drawer-content-wrapper-hidden {
23
24
  display: none;
package/es/Drawer.d.ts CHANGED
@@ -7,7 +7,7 @@ export type Placement = 'left' | 'top' | 'right' | 'bottom';
7
7
  export interface DrawerProps extends Omit<DrawerPopupProps, 'prefixCls' | 'inline' | 'scrollLocker'>, DrawerPanelEvents, DrawerPanelAccessibility {
8
8
  prefixCls?: string;
9
9
  open?: boolean;
10
- onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
10
+ onClose?: (e: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => void;
11
11
  destroyOnHidden?: boolean;
12
12
  getContainer?: PortalProps['getContainer'];
13
13
  panelRef?: React.Ref<HTMLDivElement>;
@@ -27,12 +27,13 @@ export interface DrawerProps extends Omit<DrawerPopupProps, 'prefixCls' | 'inlin
27
27
  maxSize?: number;
28
28
  /** Default size for uncontrolled resizable drawer */
29
29
  defaultSize?: number | string;
30
- /** Resizable configuration - object with optional callbacks */
31
- resizable?: {
30
+ /** Resizable configuration - boolean to enable/disable or object with optional callbacks */
31
+ resizable?: boolean | {
32
32
  onResize?: (size: number) => void;
33
33
  onResizeStart?: () => void;
34
34
  onResizeEnd?: () => void;
35
35
  };
36
+ focusTriggerAfterClose?: boolean;
36
37
  }
37
38
  declare const Drawer: React.FC<DrawerProps>;
38
39
  export default Drawer;
package/es/Drawer.js CHANGED
@@ -27,8 +27,10 @@ const Drawer = props => {
27
27
  onClick,
28
28
  onKeyDown,
29
29
  onKeyUp,
30
+ onClose,
30
31
  resizable,
31
32
  defaultSize,
33
+ focusTriggerAfterClose,
32
34
  // Refs
33
35
  panelRef
34
36
  } = props;
@@ -59,7 +61,7 @@ const Drawer = props => {
59
61
  const internalAfterOpenChange = nextVisible => {
60
62
  setAnimatedVisible(nextVisible);
61
63
  afterOpenChange?.(nextVisible);
62
- if (!nextVisible && lastActiveRef.current && !popupRef.current?.contains(lastActiveRef.current)) {
64
+ if (!nextVisible && focusTriggerAfterClose !== false && lastActiveRef.current && !popupRef.current?.contains(lastActiveRef.current)) {
63
65
  lastActiveRef.current?.focus({
64
66
  preventScroll: true
65
67
  });
@@ -103,13 +105,23 @@ const Drawer = props => {
103
105
  resizable,
104
106
  ...eventHandlers
105
107
  };
108
+ const onEsc = ({
109
+ top,
110
+ event
111
+ }) => {
112
+ if (top && keyboard) {
113
+ event.stopPropagation();
114
+ onClose?.(event);
115
+ }
116
+ };
106
117
  return /*#__PURE__*/React.createElement(RefContext.Provider, {
107
118
  value: refContext
108
119
  }, /*#__PURE__*/React.createElement(Portal, {
109
120
  open: mergedOpen || forceRender || animatedVisible,
110
121
  autoDestroy: false,
111
122
  getContainer: getContainer,
112
- autoLock: mask && (mergedOpen || animatedVisible)
123
+ autoLock: mask && (mergedOpen || animatedVisible),
124
+ onEsc: onEsc
113
125
  }, /*#__PURE__*/React.createElement(DrawerPopup, drawerPopupProps)));
114
126
  };
115
127
  if (process.env.NODE_ENV !== 'production') {
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, {
@@ -12,8 +12,9 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
12
12
  inline?: boolean;
13
13
  push?: boolean | PushConfig;
14
14
  forceRender?: boolean;
15
- autoFocus?: boolean;
16
15
  keyboard?: boolean;
16
+ autoFocus?: boolean;
17
+ focusTrap?: boolean;
17
18
  rootClassName?: string;
18
19
  rootStyle?: React.CSSProperties;
19
20
  zIndex?: number;
@@ -41,7 +42,7 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
41
42
  drawerRender?: (node: React.ReactNode) => React.ReactNode;
42
43
  /** Default size for uncontrolled resizable drawer */
43
44
  defaultSize?: number | string;
44
- resizable?: {
45
+ resizable?: boolean | {
45
46
  onResize?: (size: number) => void;
46
47
  onResizeStart?: () => void;
47
48
  onResizeEnd?: () => void;
package/es/DrawerPopup.js CHANGED
@@ -1,7 +1,6 @@
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
- import KeyCode from "@rc-component/util/es/KeyCode";
5
4
  import pickAttrs from "@rc-component/util/es/pickAttrs";
6
5
  import * as React from 'react';
7
6
  import DrawerContext from "./context";
@@ -9,13 +8,7 @@ import DrawerPanel from "./DrawerPanel";
9
8
  import useDrag from "./hooks/useDrag";
10
9
  import { parseWidthHeight } from "./util";
11
10
  import { useEvent } from '@rc-component/util';
12
- const sentinelStyle = {
13
- width: 0,
14
- height: 0,
15
- overflow: 'hidden',
16
- outline: 'none',
17
- position: 'absolute'
18
- };
11
+ import useFocusable from "./hooks/useFocusable";
19
12
  const DrawerPopup = (props, ref) => {
20
13
  const {
21
14
  prefixCls,
@@ -24,8 +17,9 @@ const DrawerPopup = (props, ref) => {
24
17
  inline,
25
18
  push,
26
19
  forceRender,
20
+ // Focus
27
21
  autoFocus,
28
- keyboard,
22
+ focusTrap,
29
23
  // classNames
30
24
  classNames: drawerClassNames,
31
25
  // Root
@@ -65,53 +59,10 @@ const DrawerPopup = (props, ref) => {
65
59
 
66
60
  // ================================ Refs ================================
67
61
  const panelRef = React.useRef(null);
68
- const sentinelStartRef = React.useRef(null);
69
- const sentinelEndRef = React.useRef(null);
70
62
  React.useImperativeHandle(ref, () => panelRef.current);
71
- const onPanelKeyDown = event => {
72
- const {
73
- keyCode,
74
- shiftKey
75
- } = event;
76
- switch (keyCode) {
77
- // Tab active
78
- case KeyCode.TAB:
79
- {
80
- if (keyCode === KeyCode.TAB) {
81
- if (!shiftKey && document.activeElement === sentinelEndRef.current) {
82
- sentinelStartRef.current?.focus({
83
- preventScroll: true
84
- });
85
- } else if (shiftKey && document.activeElement === sentinelStartRef.current) {
86
- sentinelEndRef.current?.focus({
87
- preventScroll: true
88
- });
89
- }
90
- }
91
- break;
92
- }
93
-
94
- // Close
95
- case KeyCode.ESC:
96
- {
97
- if (onClose && keyboard) {
98
- event.stopPropagation();
99
- onClose(event);
100
- }
101
- break;
102
- }
103
- }
104
- };
105
63
 
106
- // ========================== Control ===========================
107
- // Auto Focus
108
- React.useEffect(() => {
109
- if (open && autoFocus) {
110
- panelRef.current?.focus({
111
- preventScroll: true
112
- });
113
- }
114
- }, [open]);
64
+ // ========================= Focusable ==========================
65
+ useFocusable(() => panelRef.current, open, autoFocus, focusTrap, mask);
115
66
 
116
67
  // ============================ Push ============================
117
68
  const [pushed, setPushed] = React.useState(false);
@@ -161,7 +112,7 @@ const DrawerPopup = (props, ref) => {
161
112
  className: motionMaskClassName,
162
113
  style: motionMaskStyle
163
114
  }, maskRef) => /*#__PURE__*/React.createElement("div", {
164
- className: classNames(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
115
+ className: clsx(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
165
116
  style: {
166
117
  ...motionMaskStyle,
167
118
  ...maskStyle,
@@ -214,9 +165,11 @@ const DrawerPopup = (props, ref) => {
214
165
 
215
166
  // =========================== Resize ===========================
216
167
  const wrapperRef = React.useRef(null);
168
+ const isResizable = !!resizable;
169
+ const resizeConfig = typeof resizable === 'object' && resizable || {};
217
170
  const onInternalResize = useEvent(size => {
218
171
  setCurrentSize(size);
219
- resizable?.onResize?.(size);
172
+ resizeConfig.onResize?.(size);
220
173
  });
221
174
  const {
222
175
  dragElementProps,
@@ -230,8 +183,8 @@ const DrawerPopup = (props, ref) => {
230
183
  containerRef: wrapperRef,
231
184
  currentSize: mergedSize,
232
185
  onResize: onInternalResize,
233
- onResizeStart: resizable?.onResizeStart,
234
- onResizeEnd: resizable?.onResizeEnd
186
+ onResizeStart: resizeConfig.onResizeStart,
187
+ onResizeEnd: resizeConfig.onResizeEnd
235
188
  });
236
189
 
237
190
  // =========================== Events ===========================
@@ -251,9 +204,7 @@ const DrawerPopup = (props, ref) => {
251
204
  }, motionProps, {
252
205
  visible: open,
253
206
  forceRender: forceRender,
254
- onVisibleChanged: nextVisible => {
255
- afterOpenChange?.(nextVisible);
256
- },
207
+ onVisibleChanged: afterOpenChange,
257
208
  removeOnLeave: false,
258
209
  leavedClassName: `${prefixCls}-content-wrapper-hidden`
259
210
  }), ({
@@ -264,7 +215,7 @@ const DrawerPopup = (props, ref) => {
264
215
  id: id,
265
216
  containerRef: motionRef,
266
217
  prefixCls: prefixCls,
267
- className: classNames(className, drawerClassNames?.section),
218
+ className: clsx(className, drawerClassNames?.section),
268
219
  style: {
269
220
  ...style,
270
221
  ...styles?.section
@@ -274,7 +225,7 @@ const DrawerPopup = (props, ref) => {
274
225
  }), eventHandlers), children);
275
226
  return /*#__PURE__*/React.createElement("div", _extends({
276
227
  ref: wrapperRef,
277
- className: classNames(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
228
+ className: clsx(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
278
229
  style: {
279
230
  ...motionStyle,
280
231
  ...wrapperStyle,
@@ -282,7 +233,7 @@ const DrawerPopup = (props, ref) => {
282
233
  }
283
234
  }, pickAttrs(props, {
284
235
  data: true
285
- })), resizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
236
+ })), isResizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
286
237
  });
287
238
 
288
239
  // >>>>> Container
@@ -295,27 +246,14 @@ const DrawerPopup = (props, ref) => {
295
246
  return /*#__PURE__*/React.createElement(DrawerContext.Provider, {
296
247
  value: mergedContext
297
248
  }, /*#__PURE__*/React.createElement("div", {
298
- className: classNames(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
249
+ className: clsx(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
299
250
  [`${prefixCls}-open`]: open,
300
251
  [`${prefixCls}-inline`]: inline
301
252
  }),
302
253
  style: containerStyle,
303
254
  tabIndex: -1,
304
- ref: panelRef,
305
- onKeyDown: onPanelKeyDown
306
- }, maskNode, /*#__PURE__*/React.createElement("div", {
307
- tabIndex: 0,
308
- ref: sentinelStartRef,
309
- style: sentinelStyle,
310
- "aria-hidden": "true",
311
- "data-sentinel": "start"
312
- }), panelNode, /*#__PURE__*/React.createElement("div", {
313
- tabIndex: 0,
314
- ref: sentinelEndRef,
315
- style: sentinelStyle,
316
- "aria-hidden": "true",
317
- "data-sentinel": "end"
318
- })));
255
+ ref: panelRef
256
+ }, maskNode, panelNode));
319
257
  };
320
258
  const RefDrawerPopup = /*#__PURE__*/React.forwardRef(DrawerPopup);
321
259
  if (process.env.NODE_ENV !== 'production') {
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import classNames from 'classnames';
2
+ import { clsx } from 'clsx';
3
3
  import { useEvent } from '@rc-component/util';
4
4
  export default function useDrag(options) {
5
5
  const {
@@ -82,7 +82,7 @@ export default function useDrag(options) {
82
82
  };
83
83
  }
84
84
  }, [isDragging, handleMouseMove, handleMouseUp]);
85
- const dragElementClassName = classNames(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
85
+ const dragElementClassName = clsx(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
86
86
  [`${prefixCls}-dragger-dragging`]: isDragging,
87
87
  [`${prefixCls}-dragger-horizontal`]: isHorizontal,
88
88
  [`${prefixCls}-dragger-vertical`]: !isHorizontal
@@ -0,0 +1 @@
1
+ export default function useFocusable(getContainer: () => HTMLElement, open: boolean, autoFocus?: boolean, focusTrap?: boolean, mask?: boolean): void;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useLockFocus } from "@rc-component/util/es/Dom/focus";
3
+ export default function useFocusable(getContainer, open, autoFocus, focusTrap, mask) {
4
+ const mergedFocusTrap = focusTrap ?? mask !== false;
5
+
6
+ // Focus lock
7
+ useLockFocus(open && mergedFocusTrap, getContainer);
8
+
9
+ // Auto Focus
10
+ React.useEffect(() => {
11
+ if (open && autoFocus === true) {
12
+ getContainer()?.focus({
13
+ preventScroll: true
14
+ });
15
+ }
16
+ }, [open]);
17
+ }
package/lib/Drawer.d.ts CHANGED
@@ -7,7 +7,7 @@ export type Placement = 'left' | 'top' | 'right' | 'bottom';
7
7
  export interface DrawerProps extends Omit<DrawerPopupProps, 'prefixCls' | 'inline' | 'scrollLocker'>, DrawerPanelEvents, DrawerPanelAccessibility {
8
8
  prefixCls?: string;
9
9
  open?: boolean;
10
- onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
10
+ onClose?: (e: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => void;
11
11
  destroyOnHidden?: boolean;
12
12
  getContainer?: PortalProps['getContainer'];
13
13
  panelRef?: React.Ref<HTMLDivElement>;
@@ -27,12 +27,13 @@ export interface DrawerProps extends Omit<DrawerPopupProps, 'prefixCls' | 'inlin
27
27
  maxSize?: number;
28
28
  /** Default size for uncontrolled resizable drawer */
29
29
  defaultSize?: number | string;
30
- /** Resizable configuration - object with optional callbacks */
31
- resizable?: {
30
+ /** Resizable configuration - boolean to enable/disable or object with optional callbacks */
31
+ resizable?: boolean | {
32
32
  onResize?: (size: number) => void;
33
33
  onResizeStart?: () => void;
34
34
  onResizeEnd?: () => void;
35
35
  };
36
+ focusTriggerAfterClose?: boolean;
36
37
  }
37
38
  declare const Drawer: React.FC<DrawerProps>;
38
39
  export default Drawer;
package/lib/Drawer.js CHANGED
@@ -36,8 +36,10 @@ const Drawer = props => {
36
36
  onClick,
37
37
  onKeyDown,
38
38
  onKeyUp,
39
+ onClose,
39
40
  resizable,
40
41
  defaultSize,
42
+ focusTriggerAfterClose,
41
43
  // Refs
42
44
  panelRef
43
45
  } = props;
@@ -68,7 +70,7 @@ const Drawer = props => {
68
70
  const internalAfterOpenChange = nextVisible => {
69
71
  setAnimatedVisible(nextVisible);
70
72
  afterOpenChange?.(nextVisible);
71
- if (!nextVisible && lastActiveRef.current && !popupRef.current?.contains(lastActiveRef.current)) {
73
+ if (!nextVisible && focusTriggerAfterClose !== false && lastActiveRef.current && !popupRef.current?.contains(lastActiveRef.current)) {
72
74
  lastActiveRef.current?.focus({
73
75
  preventScroll: true
74
76
  });
@@ -112,13 +114,23 @@ const Drawer = props => {
112
114
  resizable,
113
115
  ...eventHandlers
114
116
  };
117
+ const onEsc = ({
118
+ top,
119
+ event
120
+ }) => {
121
+ if (top && keyboard) {
122
+ event.stopPropagation();
123
+ onClose?.(event);
124
+ }
125
+ };
115
126
  return /*#__PURE__*/React.createElement(_context.RefContext.Provider, {
116
127
  value: refContext
117
128
  }, /*#__PURE__*/React.createElement(_portal.default, {
118
129
  open: mergedOpen || forceRender || animatedVisible,
119
130
  autoDestroy: false,
120
131
  getContainer: getContainer,
121
- autoLock: mask && (mergedOpen || animatedVisible)
132
+ autoLock: mask && (mergedOpen || animatedVisible),
133
+ onEsc: onEsc
122
134
  }, /*#__PURE__*/React.createElement(_DrawerPopup.default, drawerPopupProps)));
123
135
  };
124
136
  if (process.env.NODE_ENV !== 'production') {
@@ -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, {
@@ -12,8 +12,9 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
12
12
  inline?: boolean;
13
13
  push?: boolean | PushConfig;
14
14
  forceRender?: boolean;
15
- autoFocus?: boolean;
16
15
  keyboard?: boolean;
16
+ autoFocus?: boolean;
17
+ focusTrap?: boolean;
17
18
  rootClassName?: string;
18
19
  rootStyle?: React.CSSProperties;
19
20
  zIndex?: number;
@@ -41,7 +42,7 @@ export interface DrawerPopupProps extends DrawerPanelEvents, DrawerPanelAccessib
41
42
  drawerRender?: (node: React.ReactNode) => React.ReactNode;
42
43
  /** Default size for uncontrolled resizable drawer */
43
44
  defaultSize?: number | string;
44
- resizable?: {
45
+ resizable?: boolean | {
45
46
  onResize?: (size: number) => void;
46
47
  onResizeStart?: () => void;
47
48
  onResizeEnd?: () => void;
@@ -4,9 +4,8 @@ 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
- var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
10
9
  var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttrs"));
11
10
  var React = _interopRequireWildcard(require("react"));
12
11
  var _context = _interopRequireDefault(require("./context"));
@@ -14,17 +13,11 @@ var _DrawerPanel = _interopRequireDefault(require("./DrawerPanel"));
14
13
  var _useDrag = _interopRequireDefault(require("./hooks/useDrag"));
15
14
  var _util = require("./util");
16
15
  var _util2 = require("@rc-component/util");
16
+ var _useFocusable = _interopRequireDefault(require("./hooks/useFocusable"));
17
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); }
18
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; }
19
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
20
  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); }
21
- const sentinelStyle = {
22
- width: 0,
23
- height: 0,
24
- overflow: 'hidden',
25
- outline: 'none',
26
- position: 'absolute'
27
- };
28
21
  const DrawerPopup = (props, ref) => {
29
22
  const {
30
23
  prefixCls,
@@ -33,8 +26,9 @@ const DrawerPopup = (props, ref) => {
33
26
  inline,
34
27
  push,
35
28
  forceRender,
29
+ // Focus
36
30
  autoFocus,
37
- keyboard,
31
+ focusTrap,
38
32
  // classNames
39
33
  classNames: drawerClassNames,
40
34
  // Root
@@ -74,53 +68,10 @@ const DrawerPopup = (props, ref) => {
74
68
 
75
69
  // ================================ Refs ================================
76
70
  const panelRef = React.useRef(null);
77
- const sentinelStartRef = React.useRef(null);
78
- const sentinelEndRef = React.useRef(null);
79
71
  React.useImperativeHandle(ref, () => panelRef.current);
80
- const onPanelKeyDown = event => {
81
- const {
82
- keyCode,
83
- shiftKey
84
- } = event;
85
- switch (keyCode) {
86
- // Tab active
87
- case _KeyCode.default.TAB:
88
- {
89
- if (keyCode === _KeyCode.default.TAB) {
90
- if (!shiftKey && document.activeElement === sentinelEndRef.current) {
91
- sentinelStartRef.current?.focus({
92
- preventScroll: true
93
- });
94
- } else if (shiftKey && document.activeElement === sentinelStartRef.current) {
95
- sentinelEndRef.current?.focus({
96
- preventScroll: true
97
- });
98
- }
99
- }
100
- break;
101
- }
102
-
103
- // Close
104
- case _KeyCode.default.ESC:
105
- {
106
- if (onClose && keyboard) {
107
- event.stopPropagation();
108
- onClose(event);
109
- }
110
- break;
111
- }
112
- }
113
- };
114
72
 
115
- // ========================== Control ===========================
116
- // Auto Focus
117
- React.useEffect(() => {
118
- if (open && autoFocus) {
119
- panelRef.current?.focus({
120
- preventScroll: true
121
- });
122
- }
123
- }, [open]);
73
+ // ========================= Focusable ==========================
74
+ (0, _useFocusable.default)(() => panelRef.current, open, autoFocus, focusTrap, mask);
124
75
 
125
76
  // ============================ Push ============================
126
77
  const [pushed, setPushed] = React.useState(false);
@@ -170,7 +121,7 @@ const DrawerPopup = (props, ref) => {
170
121
  className: motionMaskClassName,
171
122
  style: motionMaskStyle
172
123
  }, maskRef) => /*#__PURE__*/React.createElement("div", {
173
- className: (0, _classnames.default)(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
124
+ className: (0, _clsx.clsx)(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName),
174
125
  style: {
175
126
  ...motionMaskStyle,
176
127
  ...maskStyle,
@@ -223,9 +174,11 @@ const DrawerPopup = (props, ref) => {
223
174
 
224
175
  // =========================== Resize ===========================
225
176
  const wrapperRef = React.useRef(null);
177
+ const isResizable = !!resizable;
178
+ const resizeConfig = typeof resizable === 'object' && resizable || {};
226
179
  const onInternalResize = (0, _util2.useEvent)(size => {
227
180
  setCurrentSize(size);
228
- resizable?.onResize?.(size);
181
+ resizeConfig.onResize?.(size);
229
182
  });
230
183
  const {
231
184
  dragElementProps,
@@ -239,8 +192,8 @@ const DrawerPopup = (props, ref) => {
239
192
  containerRef: wrapperRef,
240
193
  currentSize: mergedSize,
241
194
  onResize: onInternalResize,
242
- onResizeStart: resizable?.onResizeStart,
243
- onResizeEnd: resizable?.onResizeEnd
195
+ onResizeStart: resizeConfig.onResizeStart,
196
+ onResizeEnd: resizeConfig.onResizeEnd
244
197
  });
245
198
 
246
199
  // =========================== Events ===========================
@@ -260,9 +213,7 @@ const DrawerPopup = (props, ref) => {
260
213
  }, motionProps, {
261
214
  visible: open,
262
215
  forceRender: forceRender,
263
- onVisibleChanged: nextVisible => {
264
- afterOpenChange?.(nextVisible);
265
- },
216
+ onVisibleChanged: afterOpenChange,
266
217
  removeOnLeave: false,
267
218
  leavedClassName: `${prefixCls}-content-wrapper-hidden`
268
219
  }), ({
@@ -273,7 +224,7 @@ const DrawerPopup = (props, ref) => {
273
224
  id: id,
274
225
  containerRef: motionRef,
275
226
  prefixCls: prefixCls,
276
- className: (0, _classnames.default)(className, drawerClassNames?.section),
227
+ className: (0, _clsx.clsx)(className, drawerClassNames?.section),
277
228
  style: {
278
229
  ...style,
279
230
  ...styles?.section
@@ -283,7 +234,7 @@ const DrawerPopup = (props, ref) => {
283
234
  }), eventHandlers), children);
284
235
  return /*#__PURE__*/React.createElement("div", _extends({
285
236
  ref: wrapperRef,
286
- className: (0, _classnames.default)(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
237
+ className: (0, _clsx.clsx)(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName),
287
238
  style: {
288
239
  ...motionStyle,
289
240
  ...wrapperStyle,
@@ -291,7 +242,7 @@ const DrawerPopup = (props, ref) => {
291
242
  }
292
243
  }, (0, _pickAttrs.default)(props, {
293
244
  data: true
294
- })), resizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
245
+ })), isResizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content);
295
246
  });
296
247
 
297
248
  // >>>>> Container
@@ -304,27 +255,14 @@ const DrawerPopup = (props, ref) => {
304
255
  return /*#__PURE__*/React.createElement(_context.default.Provider, {
305
256
  value: mergedContext
306
257
  }, /*#__PURE__*/React.createElement("div", {
307
- className: (0, _classnames.default)(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
258
+ className: (0, _clsx.clsx)(prefixCls, `${prefixCls}-${placement}`, rootClassName, {
308
259
  [`${prefixCls}-open`]: open,
309
260
  [`${prefixCls}-inline`]: inline
310
261
  }),
311
262
  style: containerStyle,
312
263
  tabIndex: -1,
313
- ref: panelRef,
314
- onKeyDown: onPanelKeyDown
315
- }, maskNode, /*#__PURE__*/React.createElement("div", {
316
- tabIndex: 0,
317
- ref: sentinelStartRef,
318
- style: sentinelStyle,
319
- "aria-hidden": "true",
320
- "data-sentinel": "start"
321
- }), panelNode, /*#__PURE__*/React.createElement("div", {
322
- tabIndex: 0,
323
- ref: sentinelEndRef,
324
- style: sentinelStyle,
325
- "aria-hidden": "true",
326
- "data-sentinel": "end"
327
- })));
264
+ ref: panelRef
265
+ }, maskNode, panelNode));
328
266
  };
329
267
  const RefDrawerPopup = /*#__PURE__*/React.forwardRef(DrawerPopup);
330
268
  if (process.env.NODE_ENV !== 'production') {
@@ -5,9 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = useDrag;
7
7
  var React = _interopRequireWildcard(require("react"));
8
- var _classnames = _interopRequireDefault(require("classnames"));
8
+ var _clsx = require("clsx");
9
9
  var _util = require("@rc-component/util");
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
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); }
12
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; }
13
12
  function useDrag(options) {
@@ -91,7 +90,7 @@ function useDrag(options) {
91
90
  };
92
91
  }
93
92
  }, [isDragging, handleMouseMove, handleMouseUp]);
94
- const dragElementClassName = (0, _classnames.default)(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
93
+ const dragElementClassName = (0, _clsx.clsx)(`${prefixCls}-dragger`, `${prefixCls}-dragger-${direction}`, {
95
94
  [`${prefixCls}-dragger-dragging`]: isDragging,
96
95
  [`${prefixCls}-dragger-horizontal`]: isHorizontal,
97
96
  [`${prefixCls}-dragger-vertical`]: !isHorizontal
@@ -0,0 +1 @@
1
+ export default function useFocusable(getContainer: () => HTMLElement, open: boolean, autoFocus?: boolean, focusTrap?: boolean, mask?: boolean): void;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = useFocusable;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _focus = require("@rc-component/util/lib/Dom/focus");
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function useFocusable(getContainer, open, autoFocus, focusTrap, mask) {
11
+ const mergedFocusTrap = focusTrap ?? mask !== false;
12
+
13
+ // Focus lock
14
+ (0, _focus.useLockFocus)(open && mergedFocusTrap, getContainer);
15
+
16
+ // Auto Focus
17
+ _react.default.useEffect(() => {
18
+ if (open && autoFocus === true) {
19
+ getContainer()?.focus({
20
+ preventScroll: true
21
+ });
22
+ }
23
+ }, [open]);
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rc-component/drawer",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "drawer component for react",
5
5
  "keywords": [
6
6
  "react",
@@ -44,9 +44,9 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@rc-component/motion": "^1.1.4",
47
- "@rc-component/portal": "^2.0.0",
47
+ "@rc-component/portal": "^2.1.3",
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",
@@ -54,9 +54,8 @@
54
54
  "@rc-component/np": "^1.0.0",
55
55
  "@testing-library/jest-dom": "^6.2.0",
56
56
  "@testing-library/react": "^16.3.0",
57
- "@types/classnames": "^2.2.9",
58
57
  "@types/jest": "^29.5.11",
59
- "@types/node": "^24.3.0",
58
+ "@types/node": "^25.0.0",
60
59
  "@types/raf": "^3.4.0",
61
60
  "@types/react": "^19.0.0",
62
61
  "@types/react-dom": "^19.0.0",
@@ -64,7 +63,7 @@
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",
@@ -76,7 +75,7 @@
76
75
  "react": "^19.0.0",
77
76
  "react-dom": "^19.0.0",
78
77
  "stylelint": "^16.2.1",
79
- "stylelint-config-standard-less": "^3.0.1",
78
+ "stylelint-config-standard-less": "^4.0.0",
80
79
  "typescript": "^5.3.3"
81
80
  },
82
81
  "peerDependencies": {