@rc-component/portal 2.0.1 → 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 +5 -0
- package/es/Portal.js +6 -1
- package/es/useEscKeyDown.d.ts +3 -0
- package/es/useEscKeyDown.js +34 -0
- package/lib/Portal.d.ts +5 -0
- package/lib/Portal.js +6 -1
- package/lib/useEscKeyDown.d.ts +3 -0
- package/lib/useEscKeyDown.js +42 -0
- package/package.json +4 -4
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,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,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
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "React Portal Component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -50,15 +50,15 @@
|
|
|
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": "^
|
|
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": "^
|
|
59
|
+
"@umijs/fabric": "^4.0.0",
|
|
60
60
|
"dumi": "^2.0.0",
|
|
61
|
-
"eslint": "^
|
|
61
|
+
"eslint": "^8.0.0",
|
|
62
62
|
"father": "^4.0.0",
|
|
63
63
|
"gh-pages": "^6.1.1",
|
|
64
64
|
"glob": "^10.0.0",
|