react-confirm 0.2.4 → 0.3.0-1

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,37 +1,38 @@
1
1
  # react-confirm
2
- Small library which makes your Dialog component callable.
2
+ react-confirm is a lightweight library that simplifies the implementation of confirmation dialogs in React applications by offering a Promise-based API that works seamlessly with async/await syntax, similar to `window.confirm`.
3
3
 
4
- This library does not provide any view component. Just adds a functionality to be callable like `window.confirm`.
4
+ One key feature of react-confirm is that it doesn't provide a specific view or component for the confirmation dialog, allowing you to easily customize the appearance of the dialog to match your application's design.
5
5
 
6
- In the [example](https://github.com/haradakunihiko/react-confirm/tree/master/example), [react-bootstrap](https://react-bootstrap.github.io/components.html#modals) and [material-ui](http://www.material-ui.com/#/components/dialog) are used with.
6
+ In the [example](https://github.com/haradakunihiko/react-confirm/tree/master/example), [react-bootstrap](https://react-bootstrap-v3.netlify.app/components/modal/) and [material-ui](http://www.material-ui.com/#/components/dialog) are used with.
7
7
 
8
8
  [![npm version](https://badge.fury.io/js/react-confirm.svg)](https://badge.fury.io/js/react-confirm)
9
9
 
10
10
  ## Motivation
11
- React is great. And I respect the concept to render the view reactively only by it's state. However, it easily becomes really complex to manage all states which are only needed just temporarily like confirmation dialog. The question is... Is it worth to manage them inside your app? I guess the answer is not always yes.
11
+ React is a powerful library that allows for reactive rendering based on component state. However, managing temporary states like confirmation dialogs can quickly become complex. The question is: is it worth implementing these states within your app? The answer is not always a clear yes.
12
12
 
13
13
  ## What you can do
14
- With this library,
15
- - You can open a dialog component by calling function and it will be rendered outside your application. The function returns promise so that you can define callbacks to handle the confirmation result.
16
- - You can pass arguments to the function and use them inside the dialog component.
17
- - You can get values from the component in the promise.
18
- - There is no limitation in the dialog. You can use input forms, multiple buttons, whatever you want (see demo site).
14
+ react-confirm library offers several benefits:
15
+
16
+ - You can open a dialog component by calling a function without appending it into your React tree. The function returns a promise, allowing you to handle confirmation results with callbacks.
17
+ - You can pass arguments to the function and use them inside the dialog component.
18
+ - You can retrieve values from the component in the promise.
19
+ - The library provides flexibility in designing the dialog. There is no limitation in the type of components you can use, whether it be input forms or multiple buttons. You can even check out the demo site to see examples of how to customize the dialog.
19
20
 
20
21
  ## Demo
21
22
  https://codesandbox.io/s/react-confirm-with-react-bootstrap-kjju1
22
23
 
23
24
  ## Versions
24
25
 
25
- - React 18+ users should use `react-confirm` version 0.2.x
26
+ - React 18+ users should use `react-confirm` version 0.2.x or 0.3.x
26
27
  - React <=17 users should stick to `react-confirm` version 0.1.x
27
28
 
28
29
  ## Usage
29
- 1. create your dialog component.
30
- 2. apply `confirmable` to your component (optional, but usually recommended).
31
- 3. create function with `createConfirmation` by passing your confirmable component.
32
- 4. call it!
30
+ 1. Create your dialog component.
31
+ 2. Apply `confirmable` HOC to your component (Optional. See `confirmable` implementation).
32
+ 3. Create a function using `createConfirmation` by passing your `confirmable` component.
33
+ 4. Call it!
33
34
 
34
- ### create confirmable component
35
+ ### Create your dialog component and Apply `confirmable` HOC to your component.
35
36
 
36
37
  ```js
37
38
  import React from 'react';
@@ -56,16 +57,9 @@ YourDialog.propTypes = {
56
57
 
57
58
  // confirmable HOC pass props `show`, `dismiss`, `cancel` and `proceed` to your component.
58
59
  export default confirmable(YourDialog);
59
-
60
- // or, use `confirmable` as decorator
61
- @confirmable
62
- class YourDialog extends React.Component {
63
- }
64
-
65
-
66
60
  ```
67
61
 
68
- ### create confirm function
62
+ ### Create a function using `createConfirmation`
69
63
  ```js
70
64
  import { createConfirmation } from 'react-confirm';
71
65
  import YourDialog from './YourDialog';
@@ -77,10 +71,9 @@ export const confirm = createConfirmation(YourDialog);
77
71
  export function confirmWrapper(confirmation, options = {}) {
78
72
  return confirm({ confirmation, options });
79
73
  }
80
-
81
74
  ```
82
75
 
83
- ### use it!
76
+ ### Call it!
84
77
  Now, you can show dialog just like window.confirm with async-await. The most common example is onclick handler for submit buttons.
85
78
 
86
79
  ```js
@@ -108,6 +101,45 @@ const handleOnClick2 = async () => {
108
101
 
109
102
  You can check more complex example in [codesandbox](https://codesandbox.io/s/react-confirm-with-react-bootstrap-kjju1)
110
103
 
104
+ ## Using with Context
105
+ By default, this library renders the confirmation dialog without appending the component to your app's React component tree. While this can be useful, it may cause issues if you need to consume context in your component. To overcome this problem, you can use the `MountPoint` component to include your confirmation dialog within your app's tree, enabling it to access context and other data from the app.
106
+
107
+ Create your own `createConfirmation` using `createConfirmationCreater` and `createReactTreeMounter`.
108
+
109
+ ```js
110
+ import { createConfirmationCreater, createReactTreeMounter, createMountPoint } from 'react-confirm';
111
+
112
+ const mounter = createReactTreeMounter();
113
+
114
+ export const createConfirmation = createConfirmationCreater(mounter);
115
+ export const MountPoint = createMountPoint(mounter);
116
+ ```
117
+
118
+ Put `MountPoint` into your React tree.
119
+ ```js
120
+ const YourRootComponent = () => {
121
+ return (
122
+ <YourContext.Provider>
123
+ <MountPoint />
124
+ <YourApp />
125
+ </YourContext.Provider>
126
+ )
127
+ }
128
+ ```
129
+
130
+ use your `createConfirmation` as usual.
131
+ ```js
132
+ export const confirm = createConfirmation(YourDialog);
133
+ ```
134
+
135
+ To render the confirmation dialog within the React component tree but in a different part of the DOM, you can pass a DOM element to the `createReactTreeMounter` function. This will use the `createPortal` method to render the confirmation dialog in the specified DOM element while keeping it within the React component tree.
136
+
137
+ ```js
138
+ const mounter = createReactTreeMounter(document.body);
139
+ ```
140
+
141
+ ### example
142
+ Context example with Chakra-ui in [codesandbox](https://codesandbox.io/s/react-confirm-with-chakra-ui-oidpf1)
111
143
 
112
144
  ## typescript
113
145
 
@@ -3,55 +3,54 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports["default"] = void 0;
7
-
8
- var _react = _interopRequireDefault(require("react"));
9
-
10
- var _client = require("react-dom/client");
11
-
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
-
14
- function _extends() { _extends = Object.assign || 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); }
15
-
16
- var createConfirmation = function createConfirmation(Component) {
17
- var unmountDelay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
18
- var mountingNode = arguments.length > 2 ? arguments[2] : undefined;
19
- return function (props) {
20
- var wrapper = (mountingNode || document.body).appendChild(document.createElement('div'));
21
- var root = (0, _client.createRoot)(wrapper);
22
- var promise = new Promise(function (resolve, reject) {
23
- try {
24
- root.render( /*#__PURE__*/_react["default"].createElement(Component, _extends({
25
- reject: reject,
26
- resolve: resolve,
27
- dispose: dispose
28
- }, props)));
29
- } catch (e) {
30
- console.error(e);
31
- throw e;
6
+ exports["default"] = exports.createConfirmationCreater = void 0;
7
+
8
+ var _domTree = require("./mounter/domTree");
9
+
10
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
11
+
12
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
13
+
14
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
15
+
16
+ var createConfirmationCreater = function createConfirmationCreater(mounter) {
17
+ return function (Component) {
18
+ var unmountDelay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
19
+ var mountingNode = arguments.length > 2 ? arguments[2] : undefined;
20
+ return function (props) {
21
+ var mountId;
22
+ var promise = new Promise(function (resolve, reject) {
23
+ try {
24
+ mountId = mounter.mount(Component, _objectSpread({
25
+ reject: reject,
26
+ resolve: resolve,
27
+ dispose: dispose
28
+ }, props), mountingNode);
29
+ } catch (e) {
30
+ console.error(e);
31
+ throw e;
32
+ }
33
+ });
34
+
35
+ function dispose() {
36
+ setTimeout(function () {
37
+ mounter.unmount(mountId);
38
+ }, unmountDelay);
32
39
  }
33
- });
34
40
 
35
- function dispose() {
36
- setTimeout(function () {
37
- root.unmount();
38
- setTimeout(function () {
39
- if (wrapper && wrapper.parentNode) {
40
- wrapper.parentNode.removeChild(wrapper);
41
- }
42
- });
43
- }, unmountDelay);
44
- }
45
-
46
- return promise.then(function (result) {
47
- dispose();
48
- return result;
49
- }, function (result) {
50
- dispose();
51
- return Promise.reject(result);
52
- });
41
+ return promise.then(function (result) {
42
+ dispose();
43
+ return result;
44
+ }, function (result) {
45
+ dispose();
46
+ return Promise.reject(result);
47
+ });
48
+ };
53
49
  };
54
50
  };
55
51
 
56
- var _default = createConfirmation;
52
+ exports.createConfirmationCreater = createConfirmationCreater;
53
+
54
+ var _default = createConfirmationCreater((0, _domTree.createDomTreeMounter)());
55
+
57
56
  exports["default"] = _default;
package/lib/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
 
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
+
3
5
  Object.defineProperty(exports, "__esModule", {
4
6
  value: true
5
7
  });
@@ -15,9 +17,41 @@ Object.defineProperty(exports, "createConfirmation", {
15
17
  return _createConfirmation["default"];
16
18
  }
17
19
  });
20
+ Object.defineProperty(exports, "createConfirmationCreater", {
21
+ enumerable: true,
22
+ get: function get() {
23
+ return _createConfirmation.createConfirmationCreater;
24
+ }
25
+ });
26
+ Object.defineProperty(exports, "createDomTreeMounter", {
27
+ enumerable: true,
28
+ get: function get() {
29
+ return _domTree.createDomTreeMounter;
30
+ }
31
+ });
32
+ Object.defineProperty(exports, "createMountPoint", {
33
+ enumerable: true,
34
+ get: function get() {
35
+ return _reactTree.createMountPoint;
36
+ }
37
+ });
38
+ Object.defineProperty(exports, "createReactTreeMounter", {
39
+ enumerable: true,
40
+ get: function get() {
41
+ return _reactTree.createReactTreeMounter;
42
+ }
43
+ });
18
44
 
19
45
  var _confirmable = _interopRequireDefault(require("./confirmable"));
20
46
 
21
- var _createConfirmation = _interopRequireDefault(require("./createConfirmation"));
47
+ var _createConfirmation = _interopRequireWildcard(require("./createConfirmation"));
48
+
49
+ var _domTree = require("./mounter/domTree");
50
+
51
+ var _reactTree = require("./mounter/reactTree");
52
+
53
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
54
+
55
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
22
56
 
23
57
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createDomTreeMounter = createDomTreeMounter;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _client = require("react-dom/client");
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
+
14
+ function createDomTreeMounter(defaultMountNode) {
15
+ var confirms = {};
16
+ var callbacks = {};
17
+
18
+ function mount(Component, props, mountNode) {
19
+ var key = Math.floor(Math.random() * (1 << 30)).toString(16);
20
+ var wrapper = (mountNode || defaultMountNode || document.body).appendChild(document.createElement('div'));
21
+ confirms[key] = wrapper;
22
+ var root = (0, _client.createRoot)(wrapper);
23
+ root.render( /*#__PURE__*/_react["default"].createElement(Component, props));
24
+ callbacks.mounted && callbacks.mounted();
25
+ return key;
26
+ }
27
+
28
+ function unmount(key) {
29
+ var wrapper = confirms[key];
30
+ delete confirms[key];
31
+
32
+ if (wrapper && wrapper.parentNode) {
33
+ wrapper.parentNode.removeChild(wrapper);
34
+ }
35
+ }
36
+
37
+ return {
38
+ mount: mount,
39
+ unmount: unmount,
40
+ options: {}
41
+ };
42
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.createMountPoint = createMountPoint;
9
+ exports.createReactTreeMounter = createReactTreeMounter;
10
+
11
+ var _react = _interopRequireWildcard(require("react"));
12
+
13
+ var _reactDom = require("react-dom");
14
+
15
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
+
17
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
+
19
+ function _extends() { _extends = Object.assign || 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); }
20
+
21
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
22
+
23
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
24
+
25
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
26
+
27
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
28
+
29
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
30
+
31
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
32
+
33
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
34
+
35
+ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
36
+
37
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
38
+
39
+ function createReactTreeMounter(mountNode) {
40
+ var confirms = {};
41
+ var callbacks = {};
42
+
43
+ function mount(Component, props) {
44
+ var key = Math.floor(Math.random() * (1 << 30)).toString(16);
45
+ confirms[key] = {
46
+ Component: Component,
47
+ props: props
48
+ };
49
+ callbacks.mounted && callbacks.mounted(confirms);
50
+ return key;
51
+ }
52
+
53
+ function unmount(key) {
54
+ delete confirms[key];
55
+ callbacks.mounted && callbacks.mounted(confirms);
56
+ }
57
+
58
+ function setMountedCallback(func) {
59
+ callbacks.mounted = func;
60
+ }
61
+
62
+ return {
63
+ mount: mount,
64
+ unmount: unmount,
65
+ options: {
66
+ setMountedCallback: setMountedCallback,
67
+ mountNode: mountNode
68
+ }
69
+ };
70
+ }
71
+
72
+ function createMountPoint(reactTreeMounter) {
73
+ return function () {
74
+ var _useState = (0, _react.useState)({}),
75
+ _useState2 = _slicedToArray(_useState, 2),
76
+ confirmComponents = _useState2[0],
77
+ setConfirmComponents = _useState2[1];
78
+
79
+ (0, _react.useEffect)(function () {
80
+ return reactTreeMounter.options.setMountedCallback(function (components) {
81
+ setConfirmComponents(_objectSpread({}, components));
82
+ });
83
+ }, []);
84
+
85
+ var element = /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, Object.keys(confirmComponents).map(function (key) {
86
+ var _confirmComponents$ke = confirmComponents[key],
87
+ Component = _confirmComponents$ke.Component,
88
+ props = _confirmComponents$ke.props;
89
+ return /*#__PURE__*/_react["default"].createElement(Component, _extends({
90
+ key: key
91
+ }, props));
92
+ }));
93
+
94
+ if (reactTreeMounter.options.mountNode) {
95
+ element = /*#__PURE__*/(0, _reactDom.createPortal)(element, reactTreeMounter.options.mountNode);
96
+ }
97
+
98
+ return element;
99
+ };
100
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-confirm",
3
- "version": "0.2.4",
3
+ "version": "0.3.0-1",
4
4
  "description": "Small library which makes your Dialog component callable",
5
5
  "main": "lib/index.js",
6
6
  "repository": {
@@ -1,21 +1,11 @@
1
- import React from 'react';
2
- import { createRoot } from 'react-dom/client';
1
+ import { createDomTreeMounter } from './mounter/domTree';
3
2
 
4
- const createConfirmation = (Component, unmountDelay = 1000, mountingNode) => {
3
+ export const createConfirmationCreater = (mounter) => (Component, unmountDelay = 1000, mountingNode) => {
5
4
  return (props) => {
6
- const wrapper = (mountingNode || document.body).appendChild(document.createElement('div'));
7
- const root = createRoot(wrapper);
8
-
5
+ let mountId;
9
6
  const promise = new Promise((resolve, reject) => {
10
7
  try {
11
- root.render(
12
- <Component
13
- reject={reject}
14
- resolve={resolve}
15
- dispose={dispose}
16
- {...props}
17
- />
18
- );
8
+ mountId = mounter.mount(Component, { reject, resolve, dispose, ...props}, mountingNode)
19
9
  } catch (e) {
20
10
  console.error(e);
21
11
  throw e;
@@ -24,12 +14,7 @@ const createConfirmation = (Component, unmountDelay = 1000, mountingNode) => {
24
14
 
25
15
  function dispose() {
26
16
  setTimeout(() => {
27
- root.unmount();
28
- setTimeout(() => {
29
- if (wrapper && wrapper.parentNode) {
30
- wrapper.parentNode.removeChild(wrapper);
31
- }
32
- });
17
+ mounter.unmount(mountId);
33
18
  }, unmountDelay);
34
19
  }
35
20
 
@@ -43,4 +28,4 @@ const createConfirmation = (Component, unmountDelay = 1000, mountingNode) => {
43
28
  }
44
29
  }
45
30
 
46
- export default createConfirmation;
31
+ export default createConfirmationCreater(createDomTreeMounter());
package/src/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import confirmable from './confirmable';
2
- import createConfirmation from './createConfirmation';
2
+ import createConfirmation, { createConfirmationCreater } from './createConfirmation';
3
+ import { createDomTreeMounter } from './mounter/domTree';
4
+ import { createReactTreeMounter, createMountPoint } from './mounter/reactTree';
3
5
 
4
- export { confirmable, createConfirmation };
6
+ export { confirmable, createConfirmation, createConfirmationCreater, createDomTreeMounter, createReactTreeMounter, createMountPoint };
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+
4
+ export function createDomTreeMounter(defaultMountNode) {
5
+ const confirms = {};
6
+ const callbacks = {};
7
+
8
+ function mount(Component, props, mountNode){
9
+ const key = Math.floor(Math.random() * (1 << 30)).toString(16);
10
+ const wrapper = (mountNode || defaultMountNode || document.body).appendChild(document.createElement('div'));
11
+ confirms[key] = wrapper;
12
+
13
+ const root = createRoot(wrapper);
14
+
15
+ root.render(
16
+ <Component
17
+ {...props}
18
+ />
19
+ );
20
+ callbacks.mounted && callbacks.mounted();
21
+ return key;
22
+ }
23
+
24
+ function unmount(key) {
25
+ const wrapper = confirms[key];
26
+ delete confirms[key];
27
+
28
+ if (wrapper && wrapper.parentNode) {
29
+ wrapper.parentNode.removeChild(wrapper);
30
+ }
31
+ }
32
+ return {
33
+ mount, unmount, options: {}
34
+ }
35
+ }
@@ -0,0 +1,55 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import { createPortal } from 'react-dom';
3
+
4
+ export function createReactTreeMounter(mountNode) {
5
+ const confirms = {};
6
+ const callbacks = {};
7
+
8
+ function mount(Component, props){
9
+ const key = Math.floor(Math.random() * (1 << 30)).toString(16);
10
+ confirms[key] = { Component, props};
11
+ callbacks.mounted && callbacks.mounted(confirms);
12
+ return key;
13
+ }
14
+ function unmount(key) {
15
+ delete confirms[key];
16
+ callbacks.mounted && callbacks.mounted(confirms);
17
+ }
18
+
19
+ function setMountedCallback(func) {
20
+ callbacks.mounted = func;
21
+ }
22
+
23
+ return {
24
+ mount, unmount,
25
+ options: {
26
+ setMountedCallback, mountNode
27
+ }
28
+ }
29
+ }
30
+
31
+ export function createMountPoint(reactTreeMounter) {
32
+ return () => {
33
+ const [confirmComponents, setConfirmComponents] = useState({});
34
+
35
+ useEffect(() => {
36
+ return reactTreeMounter.options.setMountedCallback((components) => {
37
+ setConfirmComponents({...components});
38
+ });
39
+ }, []);
40
+
41
+ let element = (
42
+ <>
43
+ {Object.keys(confirmComponents).map((key) => {
44
+ const { Component, props } = confirmComponents[key];
45
+ return <Component key={key} {...props} />
46
+ })}
47
+ </>
48
+ )
49
+ if (reactTreeMounter.options.mountNode) {
50
+ element = createPortal(element, reactTreeMounter.options.mountNode);
51
+ }
52
+
53
+ return element;
54
+ }
55
+ }