@rc-component/portal 2.0.0 → 2.1.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/es/Portal.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import * as React from 'react';
2
2
  export type ContainerType = Element | DocumentFragment;
3
3
  export type GetContainer = string | ContainerType | (() => ContainerType) | false;
4
+ export type EscCallback = ({ top, event, }: {
5
+ top: boolean;
6
+ event: KeyboardEvent;
7
+ }) => void;
4
8
  export interface PortalProps {
5
9
  /** Customize container element. Default will create a div in document.body when `open` */
6
10
  getContainer?: GetContainer;
@@ -11,6 +15,7 @@ export interface PortalProps {
11
15
  autoDestroy?: boolean;
12
16
  /** Lock screen scroll when open */
13
17
  autoLock?: boolean;
18
+ onEsc?: EscCallback;
14
19
  /** @private debug name. Do not use in prod */
15
20
  debug?: string;
16
21
  }
package/es/Portal.js CHANGED
@@ -7,6 +7,7 @@ import OrderContext from "./Context";
7
7
  import { inlineMock } from "./mock";
8
8
  import useDom from "./useDom";
9
9
  import useScrollLocker from "./useScrollLocker";
10
+ import useEscKeyDown from "./useEscKeyDown";
10
11
  const getPortalContainer = getContainer => {
11
12
  if (getContainer === false) {
12
13
  return false;
@@ -29,7 +30,8 @@ const Portal = /*#__PURE__*/React.forwardRef((props, ref) => {
29
30
  getContainer,
30
31
  debug,
31
32
  autoDestroy = true,
32
- children
33
+ children,
34
+ onEsc
33
35
  } = props;
34
36
  const [shouldRender, setShouldRender] = React.useState(open);
35
37
  const mergedRender = shouldRender || open;
@@ -60,6 +62,9 @@ const Portal = /*#__PURE__*/React.forwardRef((props, ref) => {
60
62
  // ========================= Locker ==========================
61
63
  useScrollLocker(autoLock && open && canUseDom() && (mergedContainer === defaultContainer || mergedContainer === document.body));
62
64
 
65
+ // ========================= Esc Keydown ==========================
66
+ useEscKeyDown(open, onEsc);
67
+
63
68
  // =========================== Ref ===========================
64
69
  let childRef = null;
65
70
  if (children && supportRef(children) && ref) {
@@ -0,0 +1,3 @@
1
+ import { type EscCallback } from './Portal';
2
+ export declare let stack: string[];
3
+ export default function useEscKeyDown(open: boolean, onEsc?: EscCallback): void;
@@ -0,0 +1,34 @@
1
+ import { useEffect, useMemo } from 'react';
2
+ import useId from "@rc-component/util/es/hooks/useId";
3
+ import { useEvent } from '@rc-component/util';
4
+ export let stack = []; // export for testing
5
+
6
+ export default function useEscKeyDown(open, onEsc) {
7
+ const id = useId();
8
+ const handleEscKeyDown = useEvent(event => {
9
+ if (event.key === 'Escape') {
10
+ const top = stack[stack.length - 1] === id;
11
+ onEsc?.({
12
+ top,
13
+ event
14
+ });
15
+ }
16
+ });
17
+ useMemo(() => {
18
+ if (open && !stack.includes(id)) {
19
+ stack.push(id);
20
+ } else if (!open) {
21
+ stack = stack.filter(item => item !== id);
22
+ }
23
+ }, [open, id]);
24
+ useEffect(() => {
25
+ if (!open) {
26
+ return;
27
+ }
28
+ window.addEventListener('keydown', handleEscKeyDown);
29
+ return () => {
30
+ stack = stack.filter(item => item !== id);
31
+ window.removeEventListener('keydown', handleEscKeyDown);
32
+ };
33
+ }, [open, id]);
34
+ }
package/lib/Portal.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import * as React from 'react';
2
2
  export type ContainerType = Element | DocumentFragment;
3
3
  export type GetContainer = string | ContainerType | (() => ContainerType) | false;
4
+ export type EscCallback = ({ top, event, }: {
5
+ top: boolean;
6
+ event: KeyboardEvent;
7
+ }) => void;
4
8
  export interface PortalProps {
5
9
  /** Customize container element. Default will create a div in document.body when `open` */
6
10
  getContainer?: GetContainer;
@@ -11,6 +15,7 @@ export interface PortalProps {
11
15
  autoDestroy?: boolean;
12
16
  /** Lock screen scroll when open */
13
17
  autoLock?: boolean;
18
+ onEsc?: EscCallback;
14
19
  /** @private debug name. Do not use in prod */
15
20
  debug?: string;
16
21
  }
package/lib/Portal.js CHANGED
@@ -13,6 +13,7 @@ var _Context = _interopRequireDefault(require("./Context"));
13
13
  var _mock = require("./mock");
14
14
  var _useDom = _interopRequireDefault(require("./useDom"));
15
15
  var _useScrollLocker = _interopRequireDefault(require("./useScrollLocker"));
16
+ var _useEscKeyDown = _interopRequireDefault(require("./useEscKeyDown"));
16
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); }
17
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; }
18
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -38,7 +39,8 @@ const Portal = /*#__PURE__*/React.forwardRef((props, ref) => {
38
39
  getContainer,
39
40
  debug,
40
41
  autoDestroy = true,
41
- children
42
+ children,
43
+ onEsc
42
44
  } = props;
43
45
  const [shouldRender, setShouldRender] = React.useState(open);
44
46
  const mergedRender = shouldRender || open;
@@ -69,6 +71,9 @@ const Portal = /*#__PURE__*/React.forwardRef((props, ref) => {
69
71
  // ========================= Locker ==========================
70
72
  (0, _useScrollLocker.default)(autoLock && open && (0, _canUseDom.default)() && (mergedContainer === defaultContainer || mergedContainer === document.body));
71
73
 
74
+ // ========================= Esc Keydown ==========================
75
+ (0, _useEscKeyDown.default)(open, onEsc);
76
+
72
77
  // =========================== Ref ===========================
73
78
  let childRef = null;
74
79
  if (children && (0, _ref.supportRef)(children) && ref) {
@@ -0,0 +1,3 @@
1
+ import { type EscCallback } from './Portal';
2
+ export declare let stack: string[];
3
+ export default function useEscKeyDown(open: boolean, onEsc?: EscCallback): void;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = useEscKeyDown;
7
+ exports.stack = void 0;
8
+ var _react = require("react");
9
+ var _useId = _interopRequireDefault(require("@rc-component/util/lib/hooks/useId"));
10
+ var _util = require("@rc-component/util");
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ let stack = exports.stack = []; // export for testing
13
+
14
+ function useEscKeyDown(open, onEsc) {
15
+ const id = (0, _useId.default)();
16
+ const handleEscKeyDown = (0, _util.useEvent)(event => {
17
+ if (event.key === 'Escape') {
18
+ const top = stack[stack.length - 1] === id;
19
+ onEsc?.({
20
+ top,
21
+ event
22
+ });
23
+ }
24
+ });
25
+ (0, _react.useMemo)(() => {
26
+ if (open && !stack.includes(id)) {
27
+ stack.push(id);
28
+ } else if (!open) {
29
+ exports.stack = stack = stack.filter(item => item !== id);
30
+ }
31
+ }, [open, id]);
32
+ (0, _react.useEffect)(() => {
33
+ if (!open) {
34
+ return;
35
+ }
36
+ window.addEventListener('keydown', handleEscKeyDown);
37
+ return () => {
38
+ exports.stack = stack = stack.filter(item => item !== id);
39
+ window.removeEventListener('keydown', handleEscKeyDown);
40
+ };
41
+ }, [open, id]);
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rc-component/portal",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "React Portal Component",
5
5
  "keywords": [
6
6
  "react",
@@ -45,20 +45,20 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@rc-component/util": "^1.2.1",
48
- "classnames": "^2.3.2"
48
+ "clsx": "^2.1.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@rc-component/father-plugin": "^2.0.2",
52
52
  "@rc-component/np": "^1.0.3",
53
- "@testing-library/jest-dom": "^5.16.4",
53
+ "@testing-library/jest-dom": "^6.9.0",
54
54
  "@testing-library/react": "^13.0.0",
55
55
  "@types/jest": "^26.0.20",
56
56
  "@types/node": "^20.9.0",
57
57
  "@types/react": "^18.0.0",
58
58
  "@types/react-dom": "^18.0.0",
59
- "@umijs/fabric": "^3.0.0",
59
+ "@umijs/fabric": "^4.0.0",
60
60
  "dumi": "^2.0.0",
61
- "eslint": "^7.18.0",
61
+ "eslint": "^8.0.0",
62
62
  "father": "^4.0.0",
63
63
  "gh-pages": "^6.1.1",
64
64
  "glob": "^10.0.0",