react-confirm 0.5.0-1 → 0.5.0-4

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
@@ -70,6 +70,23 @@ const handleDelete = async (): Promise<void> => {
70
70
  <button onClick={handleDelete}>Delete Item</button>
71
71
  ```
72
72
 
73
+ ## External Control
74
+
75
+ You can close pending confirmation dialogs from outside using the `proceed` function. This is useful when you need to close a dialog from a different part of your application.
76
+
77
+ ```typescript
78
+ import { proceed } from 'react-confirm';
79
+
80
+ const p = confirm({ message: 'Continue?' });
81
+
82
+ // Auto-close after 10 seconds
83
+ setTimeout(() => {
84
+ proceed(p, false);
85
+ }, 10000);
86
+
87
+ const result = await p;
88
+ ```
89
+
73
90
  ## Using with React Context
74
91
 
75
92
  If your dialog needs to access React Context (themes, authentication, etc.), use the context-aware approach:
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Control handle for a confirmation dialog
3
+ */
4
+ export type ConfirmationHandle<R> = {
5
+ resolve: (value: R) => void;
6
+ reject: (reason?: any) => void;
7
+ dispose: () => void;
8
+ settled?: boolean;
9
+ };
10
+ /**
11
+ * Register a Promise and its handle to the registry
12
+ */
13
+ export declare function register<R>(promise: Promise<R>, handle: ConfirmationHandle<R>): void;
14
+ /**
15
+ * Resolve a confirmation dialog and close it
16
+ * @param promise The Promise to resolve
17
+ * @param response The response value to resolve with
18
+ * @returns true if successful
19
+ */
20
+ export declare function proceed<R>(promise: Promise<R>, response: R): boolean;
21
+ /**
22
+ * Close a confirmation dialog without resolving or rejecting the Promise
23
+ * The Promise remains pending
24
+ * @param promise The Promise to dismiss
25
+ * @returns true if successful
26
+ */
27
+ export declare function dismiss<R>(promise: Promise<R>): boolean;
28
+ /**
29
+ * Reject a confirmation dialog and close it
30
+ * @param promise The Promise to reject
31
+ * @param reason The rejection reason
32
+ * @returns true if successful
33
+ */
34
+ export declare function cancel<R>(promise: Promise<R>, reason?: unknown): boolean;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ // Lightweight registry to control pending confirmations from outside
3
+ // Stores only control handles (resolve/reject/dispose), not UI state
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.register = register;
6
+ exports.proceed = proceed;
7
+ exports.dismiss = dismiss;
8
+ exports.cancel = cancel;
9
+ var active = new Map();
10
+ /**
11
+ * Register a Promise and its handle to the registry
12
+ */
13
+ function register(promise, handle) {
14
+ active.set(promise, handle);
15
+ // Auto cleanup after settlement
16
+ promise
17
+ .finally(function () {
18
+ var h = active.get(promise);
19
+ if (h)
20
+ h.settled = true;
21
+ active.delete(promise);
22
+ })
23
+ .catch(function () {
24
+ // Already handled by finally
25
+ });
26
+ }
27
+ /**
28
+ * Resolve a confirmation dialog and close it
29
+ * @param promise The Promise to resolve
30
+ * @param response The response value to resolve with
31
+ * @returns true if successful
32
+ */
33
+ function proceed(promise, response) {
34
+ var handle = active.get(promise);
35
+ if (!handle || handle.settled)
36
+ return false;
37
+ try {
38
+ handle.resolve(response);
39
+ }
40
+ finally {
41
+ try {
42
+ handle.dispose();
43
+ }
44
+ catch (_a) {
45
+ // Ignore
46
+ }
47
+ active.delete(promise);
48
+ }
49
+ return true;
50
+ }
51
+ /**
52
+ * Close a confirmation dialog without resolving or rejecting the Promise
53
+ * The Promise remains pending
54
+ * @param promise The Promise to dismiss
55
+ * @returns true if successful
56
+ */
57
+ function dismiss(promise) {
58
+ var handle = active.get(promise);
59
+ if (!handle || handle.settled)
60
+ return false;
61
+ try {
62
+ handle.dispose();
63
+ }
64
+ catch (_a) {
65
+ // Ignore
66
+ }
67
+ active.delete(promise);
68
+ return true;
69
+ }
70
+ /**
71
+ * Reject a confirmation dialog and close it
72
+ * @param promise The Promise to reject
73
+ * @param reason The rejection reason
74
+ * @returns true if successful
75
+ */
76
+ function cancel(promise, reason) {
77
+ var handle = active.get(promise);
78
+ if (!handle || handle.settled)
79
+ return false;
80
+ try {
81
+ handle.reject(reason);
82
+ }
83
+ finally {
84
+ try {
85
+ handle.dispose();
86
+ }
87
+ catch (_a) {
88
+ // Ignore
89
+ }
90
+ active.delete(promise);
91
+ }
92
+ return true;
93
+ }
@@ -13,12 +13,22 @@ var __assign = (this && this.__assign) || function () {
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.createConfirmationCreater = void 0;
15
15
  var domTree_1 = require("./mounter/domTree");
16
+ var controls_1 = require("./controls");
16
17
  var createConfirmationCreater = function (mounter) {
17
18
  return function (Component, unmountDelay, mountingNode) {
18
19
  if (unmountDelay === void 0) { unmountDelay = 1000; }
19
20
  return function (props) {
20
21
  var mountId;
21
- var promise = new Promise(function (resolve, reject) {
22
+ var resolveRef = function () { };
23
+ function dispose() {
24
+ setTimeout(function () {
25
+ mounter.unmount(mountId);
26
+ }, unmountDelay);
27
+ }
28
+ var rejectRef = function () { };
29
+ var inner = new Promise(function (resolve, reject) {
30
+ resolveRef = resolve;
31
+ rejectRef = reject;
22
32
  try {
23
33
  mountId = mounter.mount(Component, __assign({ reject: reject, resolve: resolve, dispose: dispose }, props), mountingNode);
24
34
  }
@@ -28,18 +38,16 @@ var createConfirmationCreater = function (mounter) {
28
38
  throw e;
29
39
  }
30
40
  });
31
- function dispose() {
32
- setTimeout(function () {
33
- mounter.unmount(mountId);
34
- }, unmountDelay);
35
- }
36
- return promise.then(function (result) {
41
+ var wrapped = inner.then(function (result) {
37
42
  dispose();
38
43
  return result;
39
- }, function (result) {
44
+ }, function (err) {
40
45
  dispose();
41
- return Promise.reject(result);
46
+ return Promise.reject(err);
42
47
  });
48
+ // Register to controls layer for external control
49
+ (0, controls_1.register)(wrapped, { resolve: resolveRef, reject: rejectRef, dispose: dispose });
50
+ return wrapped;
43
51
  };
44
52
  };
45
53
  };
package/dist/index.d.ts CHANGED
@@ -3,5 +3,6 @@ import createConfirmation, { createConfirmationCreater } from './createConfirmat
3
3
  import { createDomTreeMounter } from './mounter/domTree';
4
4
  import { createReactTreeMounter, createMountPoint } from './mounter/reactTree';
5
5
  import { createConfirmationContext, ContextAwareConfirmation } from './context';
6
+ import { proceed, dismiss, cancel } from './controls';
6
7
  export type { ConfirmDialogProps, ConfirmDialog, ConfirmableDialog, Mounter, TreeMounter, ConfirmationContext, } from './types';
7
- export { confirmable, createConfirmation, createConfirmationCreater, createDomTreeMounter, createReactTreeMounter, createMountPoint, createConfirmationContext, ContextAwareConfirmation };
8
+ export { confirmable, createConfirmation, createConfirmationCreater, createDomTreeMounter, createReactTreeMounter, createMountPoint, createConfirmationContext, ContextAwareConfirmation, proceed, dismiss, cancel, };
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.ContextAwareConfirmation = exports.createConfirmationContext = exports.createMountPoint = exports.createReactTreeMounter = exports.createDomTreeMounter = exports.createConfirmationCreater = exports.createConfirmation = exports.confirmable = void 0;
39
+ exports.cancel = exports.dismiss = exports.proceed = exports.ContextAwareConfirmation = exports.createConfirmationContext = exports.createMountPoint = exports.createReactTreeMounter = exports.createDomTreeMounter = exports.createConfirmationCreater = exports.createConfirmation = exports.confirmable = void 0;
40
40
  var confirmable_1 = __importDefault(require("./confirmable"));
41
41
  exports.confirmable = confirmable_1.default;
42
42
  var createConfirmation_1 = __importStar(require("./createConfirmation"));
@@ -50,3 +50,7 @@ Object.defineProperty(exports, "createMountPoint", { enumerable: true, get: func
50
50
  var context_1 = require("./context");
51
51
  Object.defineProperty(exports, "createConfirmationContext", { enumerable: true, get: function () { return context_1.createConfirmationContext; } });
52
52
  Object.defineProperty(exports, "ContextAwareConfirmation", { enumerable: true, get: function () { return context_1.ContextAwareConfirmation; } });
53
+ var controls_1 = require("./controls");
54
+ Object.defineProperty(exports, "proceed", { enumerable: true, get: function () { return controls_1.proceed; } });
55
+ Object.defineProperty(exports, "dismiss", { enumerable: true, get: function () { return controls_1.dismiss; } });
56
+ Object.defineProperty(exports, "cancel", { enumerable: true, get: function () { return controls_1.cancel; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-confirm",
3
- "version": "0.5.0-1",
3
+ "version": "0.5.0-4",
4
4
  "description": "A lightweight React library that simplifies confirmation dialogs with a Promise-based API — like window.confirm(), but fully customizable.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,103 @@
1
+ // Lightweight registry to control pending confirmations from outside
2
+ // Stores only control handles (resolve/reject/dispose), not UI state
3
+
4
+ /**
5
+ * Control handle for a confirmation dialog
6
+ */
7
+ export type ConfirmationHandle<R> = {
8
+ resolve: (value: R) => void;
9
+ reject: (reason?: any) => void;
10
+ dispose: () => void;
11
+ settled?: boolean;
12
+ };
13
+
14
+ const active = new Map<Promise<unknown>, ConfirmationHandle<unknown>>();
15
+
16
+ /**
17
+ * Register a Promise and its handle to the registry
18
+ */
19
+ export function register<R>(
20
+ promise: Promise<R>,
21
+ handle: ConfirmationHandle<R>
22
+ ): void {
23
+ active.set(promise, handle as ConfirmationHandle<unknown>);
24
+
25
+ // Auto cleanup after settlement
26
+ promise
27
+ .finally(() => {
28
+ const h = active.get(promise);
29
+ if (h) h.settled = true;
30
+ active.delete(promise);
31
+ })
32
+ .catch(() => {
33
+ // Already handled by finally
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Resolve a confirmation dialog and close it
39
+ * @param promise The Promise to resolve
40
+ * @param response The response value to resolve with
41
+ * @returns true if successful
42
+ */
43
+ export function proceed<R>(promise: Promise<R>, response: R): boolean {
44
+ const handle = active.get(promise) as ConfirmationHandle<R> | undefined;
45
+ if (!handle || handle.settled) return false;
46
+
47
+ try {
48
+ handle.resolve(response);
49
+ } finally {
50
+ try {
51
+ handle.dispose();
52
+ } catch {
53
+ // Ignore
54
+ }
55
+ active.delete(promise);
56
+ }
57
+
58
+ return true;
59
+ }
60
+
61
+ /**
62
+ * Close a confirmation dialog without resolving or rejecting the Promise
63
+ * The Promise remains pending
64
+ * @param promise The Promise to dismiss
65
+ * @returns true if successful
66
+ */
67
+ export function dismiss<R>(promise: Promise<R>): boolean {
68
+ const handle = active.get(promise) as ConfirmationHandle<R> | undefined;
69
+ if (!handle || handle.settled) return false;
70
+
71
+ try {
72
+ handle.dispose();
73
+ } catch {
74
+ // Ignore
75
+ }
76
+ active.delete(promise);
77
+
78
+ return true;
79
+ }
80
+
81
+ /**
82
+ * Reject a confirmation dialog and close it
83
+ * @param promise The Promise to reject
84
+ * @param reason The rejection reason
85
+ * @returns true if successful
86
+ */
87
+ export function cancel<R>(promise: Promise<R>, reason?: unknown): boolean {
88
+ const handle = active.get(promise) as ConfirmationHandle<R> | undefined;
89
+ if (!handle || handle.settled) return false;
90
+
91
+ try {
92
+ handle.reject(reason);
93
+ } finally {
94
+ try {
95
+ handle.dispose();
96
+ } catch {
97
+ // Ignore
98
+ }
99
+ active.delete(promise);
100
+ }
101
+
102
+ return true;
103
+ }
@@ -1,12 +1,25 @@
1
1
  import type React from 'react';
2
2
  import { createDomTreeMounter } from './mounter/domTree';
3
3
  import type { ConfirmableDialog, Mounter } from './types';
4
+ import { register } from './controls';
4
5
 
5
6
  export const createConfirmationCreater = (mounter: Mounter) =>
6
7
  <P, R>(Component: ConfirmableDialog<P, R>, unmountDelay: number = 1000, mountingNode?: HTMLElement) => {
7
8
  return (props: P): Promise<R> => {
8
9
  let mountId: string;
9
- const promise = new Promise<R>((resolve, reject) => {
10
+ let resolveRef: (value: R) => void = () => {};
11
+
12
+ function dispose() {
13
+ setTimeout(() => {
14
+ mounter.unmount(mountId);
15
+ }, unmountDelay);
16
+ }
17
+
18
+ let rejectRef: (reason?: any) => void = () => {};
19
+
20
+ const inner = new Promise<R>((resolve, reject) => {
21
+ resolveRef = resolve;
22
+ rejectRef = reject;
10
23
  try {
11
24
  mountId = mounter.mount(Component as React.ComponentType<any>, { reject, resolve, dispose, ...props }, mountingNode);
12
25
  } catch (e) {
@@ -16,22 +29,21 @@ export const createConfirmationCreater = (mounter: Mounter) =>
16
29
  }
17
30
  });
18
31
 
19
- function dispose() {
20
- setTimeout(() => {
21
- mounter.unmount(mountId);
22
- }, unmountDelay);
23
- }
24
-
25
- return promise.then(
32
+ const wrapped = inner.then(
26
33
  (result) => {
27
34
  dispose();
28
35
  return result;
29
36
  },
30
- (result) => {
37
+ (err) => {
31
38
  dispose();
32
- return Promise.reject(result);
39
+ return Promise.reject(err);
33
40
  }
34
41
  );
42
+
43
+ // Register to controls layer for external control
44
+ register(wrapped, { resolve: resolveRef, reject: rejectRef, dispose });
45
+
46
+ return wrapped;
35
47
  };
36
48
  };
37
49
 
package/src/index.ts CHANGED
@@ -2,10 +2,11 @@ import confirmable from './confirmable';
2
2
  import createConfirmation, { createConfirmationCreater } from './createConfirmation';
3
3
  import { createDomTreeMounter } from './mounter/domTree';
4
4
  import { createReactTreeMounter, createMountPoint } from './mounter/reactTree';
5
- import {
6
- createConfirmationContext,
5
+ import {
6
+ createConfirmationContext,
7
7
  ContextAwareConfirmation
8
8
  } from './context';
9
+ import { proceed, dismiss, cancel } from './controls';
9
10
 
10
11
  export type {
11
12
  ConfirmDialogProps,
@@ -16,13 +17,16 @@ export type {
16
17
  ConfirmationContext,
17
18
  } from './types';
18
19
 
19
- export {
20
- confirmable,
21
- createConfirmation,
22
- createConfirmationCreater,
23
- createDomTreeMounter,
24
- createReactTreeMounter,
20
+ export {
21
+ confirmable,
22
+ createConfirmation,
23
+ createConfirmationCreater,
24
+ createDomTreeMounter,
25
+ createReactTreeMounter,
25
26
  createMountPoint,
26
27
  createConfirmationContext,
27
- ContextAwareConfirmation
28
+ ContextAwareConfirmation,
29
+ proceed,
30
+ dismiss,
31
+ cancel,
28
32
  };
package/src/types.ts CHANGED
@@ -34,6 +34,7 @@ export type TreeMounter = {
34
34
  };
35
35
  } & Mounter;
36
36
 
37
+
37
38
  // Context-aware confirmation system
38
39
  export interface ConfirmationContext {
39
40
  /**