promise-portal 1.0.4 → 1.0.6

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
@@ -15,6 +15,10 @@ npm install promise-portal -D
15
15
  yarn add promise-portal --D
16
16
  ```
17
17
 
18
+ ## Online Demo
19
+
20
+ [Demo on codesandbox](https://codesandbox.io/p/github/tjyuanpeng/promise-portal)
21
+
18
22
  ## Relative Resourece
19
23
 
20
24
  - [react protal](https://reactjs.org/docs/portals.html)
@@ -75,6 +79,7 @@ const onClick = async () => {
75
79
 
76
80
  ```ts
77
81
  // ./main.ts
82
+ import { createApp } from 'vue'
78
83
  import { createPromisePortal } from 'promise-portal'
79
84
 
80
85
  const app = createApp(App)
@@ -114,11 +119,19 @@ const onClick = async () => {
114
119
 
115
120
  - createPromisePortal
116
121
 
117
- create promise-portal instance
122
+ create promise-portal instance, set to vue instance
118
123
 
119
124
  ```ts
120
125
  const instance = createPromisePortal()
121
- app.use(instance) // vue instance
126
+ app.use(instance)
127
+ ```
128
+
129
+ you can set default config to instance
130
+
131
+ ```ts
132
+ const instance = createPromisePortal({
133
+ unmountDelay: 100,
134
+ })
122
135
  ```
123
136
 
124
137
  - getActiveInstance
@@ -142,11 +155,12 @@ const onClick = async () => {
142
155
  a vue composition api, use in portal component to get context of portal
143
156
 
144
157
  ```ts
145
- const { resolve, reject, el, vNode } = usePortalContext()
158
+ const { resolve, reject, el, vNode, setUnmountDelay } = usePortalContext()
146
159
  // resolve: promise resolve handler
147
160
  // reject: promise reject handler
148
161
  // el: portal base element, injecting to body element
149
162
  // vNode: portal base vue vnode
163
+ // setUnmountDelay: set unmount delay to this portal
150
164
  ```
151
165
 
152
166
  you can use typescript generic types
@@ -223,6 +237,28 @@ const onClick = async () => {
223
237
  })
224
238
  ```
225
239
 
240
+ - detectPromisePortalInstance
241
+
242
+ Check if the instance has been properly destroyed
243
+
244
+ ```ts
245
+ // main.ts
246
+ if (import.meta.env.DEV) {
247
+ detectPromisePortalInstance()
248
+ }
249
+ ```
250
+
251
+ You can pass in other values to customize it.
252
+
253
+ ```ts
254
+ // default value
255
+ detectPromisePortalInstance({
256
+ style = 'position:fixed;top:0;right:0;text-align:right;line-height:1.3;color:red;z-index:9999;',
257
+ text = `Detected that the promise-portal instance has not been properly destroyed<br>
258
+ Please make sure to call resolve/reject to release the instance correctly.`,
259
+ })
260
+ ```
261
+
226
262
  ## Link
227
263
 
228
264
  - [@filez/portal](https://github.com/lenovo-filez/portal)
package/dist/index.cjs CHANGED
@@ -22,6 +22,7 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  createPromisePortal: () => createPromisePortal,
24
24
  definePortal: () => definePortal,
25
+ detectPromisePortalInstance: () => detectPromisePortalInstance,
25
26
  getActiveInstance: () => getActiveInstance,
26
27
  setActiveInstance: () => setActiveInstance,
27
28
  usePortalContext: () => usePortalContext
@@ -32,8 +33,9 @@ var promisePortalSymbol = process.env.NODE_ENV !== "production" ? Symbol("promis
32
33
  var activeInstance;
33
34
  var getActiveInstance = () => activeInstance;
34
35
  var setActiveInstance = (instance) => activeInstance = instance;
35
- var createPromisePortal = () => {
36
+ var createPromisePortal = (defaultOptions = {}) => {
36
37
  const instance = {
38
+ defaultOptions,
37
39
  app: void 0,
38
40
  map: /* @__PURE__ */ new WeakMap(),
39
41
  install(app) {
@@ -59,18 +61,23 @@ var usePortalContext = () => {
59
61
  }
60
62
  return data;
61
63
  };
62
- var definePortal = (component, { instance, unmountDelay = 0 } = {}) => {
64
+ var definePortal = (component, { instance, unmountDelay } = {}) => {
63
65
  const _instance = instance || (0, import_vue.getCurrentInstance)() && (0, import_vue.inject)(promisePortalSymbol) || activeInstance;
64
66
  if (!_instance) {
65
67
  throw new Error("[promise-portal]: no instance found. Do you forget install promise-portal?");
66
68
  }
67
69
  return (props, children) => {
68
70
  let el = document.createElement("div");
71
+ el.setAttribute("data-promise-portal-container", "");
69
72
  document.body.appendChild(el);
73
+ let _delay = unmountDelay || _instance.defaultOptions?.unmountDelay;
74
+ const setUnmountDelay = (delay) => {
75
+ _delay = delay;
76
+ };
70
77
  let vNode;
71
78
  const p = new Promise((resolve, reject) => {
72
79
  vNode = (0, import_vue.createVNode)(component, props, children);
73
- _instance.map.set(vNode, { resolve, reject, el, vNode });
80
+ _instance.map.set(vNode, { resolve, reject, el, vNode, setUnmountDelay });
74
81
  vNode.appContext = _instance.app._context;
75
82
  (0, import_vue.render)(vNode, el);
76
83
  });
@@ -82,15 +89,36 @@ var definePortal = (component, { instance, unmountDelay = 0 } = {}) => {
82
89
  }
83
90
  el = null;
84
91
  vNode = null;
85
- }, unmountDelay);
92
+ }, _delay);
86
93
  });
87
94
  return p;
88
95
  };
89
96
  };
97
+ var detectPromisePortalInstance = (config = {}) => {
98
+ const {
99
+ style = "position:fixed;top:0;right:0;text-align:right;line-height:1.3;color:red;z-index:9999;",
100
+ text = `Detected that the promise-portal instance has not been properly destroyed<br>Please make sure to call resolve/reject to release the instance correctly.`
101
+ } = config;
102
+ const nodes = document.querySelectorAll("[data-promise-portal-container]");
103
+ if (nodes.length > 0) {
104
+ let el = document.querySelector("[data-promise-portal-detector]");
105
+ if (!el) {
106
+ el = document.createElement("div");
107
+ el.setAttribute("data-promise-portal-detector", "");
108
+ el.setAttribute("style", style);
109
+ el.innerHTML = text;
110
+ document.body.appendChild(el);
111
+ }
112
+ } else {
113
+ document.querySelector("[data-promise-portal-detector]")?.remove();
114
+ }
115
+ setTimeout(() => detectPromisePortalInstance(config), 200);
116
+ };
90
117
  // Annotate the CommonJS export names for ESM import in node:
91
118
  0 && (module.exports = {
92
119
  createPromisePortal,
93
120
  definePortal,
121
+ detectPromisePortalInstance,
94
122
  getActiveInstance,
95
123
  setActiveInstance,
96
124
  usePortalContext
package/dist/index.d.ts CHANGED
@@ -5,8 +5,12 @@ interface PortalContext<R> {
5
5
  reject: (reason?: any) => void;
6
6
  el: HTMLDivElement;
7
7
  vNode: VNode;
8
+ setUnmountDelay: (unmountDelay: number) => void;
8
9
  }
9
10
  interface PromisePortal<R = any> {
11
+ defaultOptions: {
12
+ unmountDelay?: number;
13
+ };
10
14
  app: App;
11
15
  map: WeakMap<VNode, PortalContext<R>>;
12
16
  install: (app: App) => void;
@@ -17,8 +21,13 @@ interface PortalOptions<R> {
17
21
  }
18
22
  declare const getActiveInstance: () => PromisePortal<any>;
19
23
  declare const setActiveInstance: (instance: PromisePortal) => PromisePortal<any>;
20
- declare const createPromisePortal: () => PromisePortal<any>;
24
+ declare const createPromisePortal: (defaultOptions?: {}) => PromisePortal<any>;
21
25
  declare const usePortalContext: <TOutput = any>() => PortalContext<TOutput>;
22
26
  declare const definePortal: <TOutput = any, TProps = any>(component: Component, { instance, unmountDelay }?: PortalOptions<TOutput>) => (props?: TProps | undefined, children?: unknown) => Promise<TOutput>;
27
+ interface DetectPromisePortalInstanceConfig {
28
+ style?: string;
29
+ text?: string;
30
+ }
31
+ declare const detectPromisePortalInstance: (config?: DetectPromisePortalInstanceConfig) => void;
23
32
 
24
- export { PortalContext, PortalOptions, PromisePortal, createPromisePortal, definePortal, getActiveInstance, setActiveInstance, usePortalContext };
33
+ export { DetectPromisePortalInstanceConfig, PortalContext, PortalOptions, PromisePortal, createPromisePortal, definePortal, detectPromisePortalInstance, getActiveInstance, setActiveInstance, usePortalContext };
package/dist/index.js CHANGED
@@ -4,8 +4,9 @@ var promisePortalSymbol = process.env.NODE_ENV !== "production" ? Symbol("promis
4
4
  var activeInstance;
5
5
  var getActiveInstance = () => activeInstance;
6
6
  var setActiveInstance = (instance) => activeInstance = instance;
7
- var createPromisePortal = () => {
7
+ var createPromisePortal = (defaultOptions = {}) => {
8
8
  const instance = {
9
+ defaultOptions,
9
10
  app: void 0,
10
11
  map: /* @__PURE__ */ new WeakMap(),
11
12
  install(app) {
@@ -31,18 +32,23 @@ var usePortalContext = () => {
31
32
  }
32
33
  return data;
33
34
  };
34
- var definePortal = (component, { instance, unmountDelay = 0 } = {}) => {
35
+ var definePortal = (component, { instance, unmountDelay } = {}) => {
35
36
  const _instance = instance || getCurrentInstance() && inject(promisePortalSymbol) || activeInstance;
36
37
  if (!_instance) {
37
38
  throw new Error("[promise-portal]: no instance found. Do you forget install promise-portal?");
38
39
  }
39
40
  return (props, children) => {
40
41
  let el = document.createElement("div");
42
+ el.setAttribute("data-promise-portal-container", "");
41
43
  document.body.appendChild(el);
44
+ let _delay = unmountDelay || _instance.defaultOptions?.unmountDelay;
45
+ const setUnmountDelay = (delay) => {
46
+ _delay = delay;
47
+ };
42
48
  let vNode;
43
49
  const p = new Promise((resolve, reject) => {
44
50
  vNode = createVNode(component, props, children);
45
- _instance.map.set(vNode, { resolve, reject, el, vNode });
51
+ _instance.map.set(vNode, { resolve, reject, el, vNode, setUnmountDelay });
46
52
  vNode.appContext = _instance.app._context;
47
53
  render(vNode, el);
48
54
  });
@@ -54,14 +60,35 @@ var definePortal = (component, { instance, unmountDelay = 0 } = {}) => {
54
60
  }
55
61
  el = null;
56
62
  vNode = null;
57
- }, unmountDelay);
63
+ }, _delay);
58
64
  });
59
65
  return p;
60
66
  };
61
67
  };
68
+ var detectPromisePortalInstance = (config = {}) => {
69
+ const {
70
+ style = "position:fixed;top:0;right:0;text-align:right;line-height:1.3;color:red;z-index:9999;",
71
+ text = `Detected that the promise-portal instance has not been properly destroyed<br>Please make sure to call resolve/reject to release the instance correctly.`
72
+ } = config;
73
+ const nodes = document.querySelectorAll("[data-promise-portal-container]");
74
+ if (nodes.length > 0) {
75
+ let el = document.querySelector("[data-promise-portal-detector]");
76
+ if (!el) {
77
+ el = document.createElement("div");
78
+ el.setAttribute("data-promise-portal-detector", "");
79
+ el.setAttribute("style", style);
80
+ el.innerHTML = text;
81
+ document.body.appendChild(el);
82
+ }
83
+ } else {
84
+ document.querySelector("[data-promise-portal-detector]")?.remove();
85
+ }
86
+ setTimeout(() => detectPromisePortalInstance(config), 200);
87
+ };
62
88
  export {
63
89
  createPromisePortal,
64
90
  definePortal,
91
+ detectPromisePortalInstance,
65
92
  getActiveInstance,
66
93
  setActiveInstance,
67
94
  usePortalContext
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promise-portal",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "let you use react portal in vue, and with promise",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",