@planningcenter/sweetest-alert 1.7.0 → 1.9.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/README.md +59 -10
- package/dist/index.cjs +1 -1
- package/dist/index.js +94 -61
- package/dist/sweetest_alert.d.ts +47 -8
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -19,8 +19,8 @@ In your product’s main CSS file (ex. `app/assets/stylesheets/application.css`)
|
|
|
19
19
|
|
|
20
20
|
This package requires the following peer dependencies:
|
|
21
21
|
|
|
22
|
-
- `react` ^18.3.1
|
|
23
|
-
- `react-dom` ^18.3.1
|
|
22
|
+
- `react` ^18.3.1 || ^19.0.0
|
|
23
|
+
- `react-dom` ^18.3.1 || ^19.0.0
|
|
24
24
|
- `@planningcenter/tapestry` ^2.10.1 || ^3.0.0
|
|
25
25
|
- `@planningcenter/icons` ^15.29.1
|
|
26
26
|
|
|
@@ -95,6 +95,49 @@ if (isConfirmed) {
|
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
### Async Confirm
|
|
99
|
+
|
|
100
|
+
If `onConfirm` returns a promise (or other thenable), the dialog stays open with a loading confirm button and a disabled cancel button until it settles. Resolving closes the dialog and adds the resolved value as `value` on the result. Escape and `close()` do nothing while it's pending — `cleanup()` is the only way to force the dialog closed mid-flight.
|
|
101
|
+
|
|
102
|
+
```jsx
|
|
103
|
+
const { isConfirmed, value } = await SweetestAlert({
|
|
104
|
+
type: "warning",
|
|
105
|
+
title: "Save changes?",
|
|
106
|
+
content: "The dialog stays open, with a spinner, while the save is in flight.",
|
|
107
|
+
confirmButton: "Save",
|
|
108
|
+
onConfirm: async () => {
|
|
109
|
+
await saveChanges()
|
|
110
|
+
return { savedAt: new Date().toISOString() }
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
if (isConfirmed) {
|
|
115
|
+
console.log("saved", value)
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
If it rejects, the dialog's content is replaced with a generic error message and a single "Okay" button. Dismissing that button — the promise doesn't resolve on rejection itself — resolves `{ isConfirmed: false, isDismissed: true }`. **The returned promise never rejects**, so a failed confirm can't be mistaken for a success by a caller using `.then()`/`await` without a `try`/`catch`:
|
|
120
|
+
|
|
121
|
+
```jsx
|
|
122
|
+
SweetestAlert({
|
|
123
|
+
type: "danger",
|
|
124
|
+
title: "Delete this list?",
|
|
125
|
+
content: "This can't be undone.",
|
|
126
|
+
confirmButton: "Delete",
|
|
127
|
+
onConfirm: () => deleteList(),
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`isDismissed: true` now also covers a failed confirm, not just cancel/Escape — if you need to distinguish "the user backed out" from "the action failed," check `isConfirmed` first, since both cases share `isConfirmed: false`.
|
|
132
|
+
|
|
133
|
+
If you don't want the dialog to wait on the returned promise, don't return it:
|
|
134
|
+
|
|
135
|
+
```jsx
|
|
136
|
+
onConfirm: () => {
|
|
137
|
+
void saveChanges()
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
98
141
|
### Alert Types
|
|
99
142
|
|
|
100
143
|
The component supports five visual types:
|
|
@@ -166,20 +209,26 @@ SweetestAlert({
|
|
|
166
209
|
| `title` | **Required.** The main heading text displayed at the top of the modal. |
|
|
167
210
|
| `content` | **Required.** The body content. Accepts plain text or React components (`string \| React.ReactNode`). |
|
|
168
211
|
| `type` | The visual type of alert (`info`, `success`, `error`, `danger`, `warning`), affects icon and styling. Defaults to "warning". |
|
|
169
|
-
| `onConfirm` | Callback executed when confirm button is clicked.
|
|
170
|
-
| `onCancel` | Callback executed when cancel button is clicked.
|
|
212
|
+
| `onConfirm` | Callback executed when confirm button is clicked. If it returns a promise, the dialog stays open with a loading confirm button until it settles — see [Async Confirm](#async-confirm). |
|
|
213
|
+
| `onCancel` | Callback executed when cancel button is clicked. Not called when `onConfirm` rejects. |
|
|
171
214
|
| `confirmButton` | Custom text for the confirm button. Defaults to "Okay". |
|
|
172
215
|
| `hideCancel` | When `true`, hides the cancel button for simple notifications. Defaults to `false`. |
|
|
173
216
|
|
|
174
217
|
### Return Value
|
|
175
218
|
|
|
176
|
-
`SweetestAlert` returns a promise that resolves to `{ isConfirmed, isDismissed }` when the dialog is closed (via confirm, cancel, or
|
|
219
|
+
`SweetestAlert` returns a promise that resolves to `{ isConfirmed, isDismissed }` when the dialog is closed (via confirm, cancel, Escape, or dismissing the error state after a rejected `onConfirm`), plus:
|
|
220
|
+
|
|
221
|
+
| Property | Description |
|
|
222
|
+
| -------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
223
|
+
| `value` | The value `onConfirm`'s promise resolved with. Only present when `onConfirm` returned a promise and it resolved. |
|
|
224
|
+
|
|
225
|
+
The returned object is also merged with imperative controls:
|
|
177
226
|
|
|
178
|
-
| Property | Description
|
|
179
|
-
| --------- |
|
|
180
|
-
| `show` | Re-opens the dialog (calls the native `showModal()`).
|
|
181
|
-
| `close` | Closes the dialog (calls the native `close()`), resolving the promise with `isDismissed: true`. |
|
|
182
|
-
| `cleanup` | Unmounts the React root and removes the dialog from the DOM immediately.
|
|
227
|
+
| Property | Description |
|
|
228
|
+
| --------- | ------------------------------------------------------------------------------------------------------------ |
|
|
229
|
+
| `show` | Re-opens the dialog (calls the native `showModal()`). |
|
|
230
|
+
| `close` | Closes the dialog (calls the native `close()`), resolving the promise with `isDismissed: true`. Does nothing while `onConfirm` is pending. |
|
|
231
|
+
| `cleanup` | Unmounts the React root and removes the dialog from the DOM immediately, regardless of pending state. |
|
|
183
232
|
|
|
184
233
|
## Development
|
|
185
234
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require("react");let e=require("react-dom/client"),t=require("@planningcenter/tapestry"),n=require("react/jsx-runtime");var r=`M8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8M12.57,6.07l-1.14,-1.14l-4.43,4.44l-2.43,-2.44l-1.14,1.14l3.57,3.56z`,i=`M15.669,13.676c0.13528,0.2343 0.13541,0.52294 0.00036,0.75737c-0.13505,0.23443 -0.38481,0.37911 -0.65536,0.37963h-14.028c-0.27081,0.0001 -0.52105,-0.14447 -0.65623,-0.37913c-0.13518,-0.23466 -0.13471,-0.52366 0.00123,-0.75787l7.014,-12.115c0.13497,-0.23419 0.3847,-0.37849 0.655,-0.37849c0.2703,0 0.52003,0.14431 0.655,0.37849l7.014,12.115M8.757,11.028h-1.514v1.514h1.514zM8.757,6.485h-1.514v3.029h1.514z`,a=`M8.8,4h-1.6v1.6h1.6zM8.8,7.2h-1.6v4.8h1.6zM8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8`,o=`M11.395,10.262l-2.262,-2.262l2.262,-2.262l-1.132,-1.132l-2.262,2.262l-2.263,-2.262l-1.131,1.132l2.262,2.262l-2.262,2.262l1.131,1.132l2.263,-2.262l2.262,2.262zM13.659,2.343c3.12218,3.12514 3.12218,8.18886 0,11.314c-2.28834,2.28863 -5.73017,2.97305 -8.72,1.734c-2.99134,-1.23749 -4.94222,-4.15558 -4.94244,-7.39278c-0.00022,-3.2372 1.95027,-6.15555 4.94143,-7.39345c2.99117,-1.2379 6.43353,-0.55139 8.72101,1.73923
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require("react");let e=require("react-dom/client"),t=require("@planningcenter/tapestry"),n=require("react/jsx-runtime");var r=`M8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8M12.57,6.07l-1.14,-1.14l-4.43,4.44l-2.43,-2.44l-1.14,1.14l3.57,3.56z`,i=`M15.669,13.676c0.13528,0.2343 0.13541,0.52294 0.00036,0.75737c-0.13505,0.23443 -0.38481,0.37911 -0.65536,0.37963h-14.028c-0.27081,0.0001 -0.52105,-0.14447 -0.65623,-0.37913c-0.13518,-0.23466 -0.13471,-0.52366 0.00123,-0.75787l7.014,-12.115c0.13497,-0.23419 0.3847,-0.37849 0.655,-0.37849c0.2703,0 0.52003,0.14431 0.655,0.37849l7.014,12.115M8.757,11.028h-1.514v1.514h1.514zM8.757,6.485h-1.514v3.029h1.514z`,a=`M8.8,4h-1.6v1.6h1.6zM8.8,7.2h-1.6v4.8h1.6zM8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8`,o=`M11.395,10.262l-2.262,-2.262l2.262,-2.262l-1.132,-1.132l-2.262,2.262l-2.263,-2.262l-1.131,1.132l2.262,2.262l-2.262,2.262l1.131,1.132l2.263,-2.262l2.262,2.262zM13.659,2.343c3.12218,3.12514 3.12218,8.18886 0,11.314c-2.28834,2.28863 -5.73017,2.97305 -8.72,1.734c-2.99134,-1.23749 -4.94222,-4.15558 -4.94244,-7.39278c-0.00022,-3.2372 1.95027,-6.15555 4.94143,-7.39345c2.99117,-1.2379 6.43353,-0.55139 8.72101,1.73923`,s=`Uh oh!`,c=`Something went wrong, please try again. If the error continues, please contact support.`;function l(){let e;return{promise:new Promise(t=>{e=t}),resolve:e}}function u(e){return typeof(e!==null&&(typeof e==`object`||typeof e==`function`)?e.then:void 0)==`function`}function d({onCancel:d,onConfirm:f,confirmButton:p=`Okay`,content:m,hideCancel:h=!1,title:g,type:_=`warning`}){let v=document.createElement(`dialog`);v.className=`pco-sweetest-alert`,document.body.appendChild(v);let y=(0,e.createRoot)(v),b=!1,x=`idle`,{promise:S,resolve:C}=l(),w=()=>{b||(b=!0,x=`idle`,C({isConfirmed:!1,isDismissed:!0}),y.unmount(),v.remove())},T=e=>{b||(C({isConfirmed:!1,isDismissed:!0}),w(),e&&d?.())},E=async e=>{x=`pending`,M();let t;try{t=await e}catch{if(b)return;x=`error`,M();return}b||(C({isConfirmed:!0,isDismissed:!1,value:t}),w())},D=()=>{if(b||x!==`idle`)return;let e=f?.();if(!u(e)){C({isConfirmed:!0,isDismissed:!1}),w();return}E(e)},O=e=>{x===`pending`&&e.preventDefault()},k=()=>{b||x===`pending`||T(x!==`error`)},A=e=>{switch(e){case`success`:return r;case`error`:return o;case`info`:return a;case`danger`:case`warning`:return i}},j=()=>{let e=x===`error`,r=x===`pending`,i=e?`error`:_;return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(`svg`,{className:`pco-sweetest-alert__icon pco-sweetest-alert--${i}`,width:`48`,height:`48`,viewBox:`0 0 16 16`,"aria-hidden":`true`,children:(0,n.jsx)(`path`,{d:A(i)})}),(0,n.jsx)(`h2`,{className:`pco-sweetest-alert__title`,children:e?s:g}),(0,n.jsx)(`div`,{className:`pco-sweetest-alert__body`,children:e?(0,n.jsx)(`p`,{children:c}):typeof m==`string`?(0,n.jsx)(`p`,{children:m}):m}),(0,n.jsxs)(`div`,{className:`pco-sweetest-alert__actions`,children:[!e&&!h&&(0,n.jsx)(t.Button,{label:`Cancel`,kind:`ghost`,disabled:r,onClick:()=>T(!0)}),(0,n.jsx)(t.Button,{label:e?`Okay`:p,kind:!e&&_===`danger`?`delete`:`primary`,loading:r,onClick:e?()=>T(!1):D})]})]})},M=()=>y.render(j());return M(),v.showModal(),v.addEventListener(`cancel`,O),v.addEventListener(`close`,k),Object.assign(S,{show:()=>v.showModal(),close:()=>{x!==`pending`&&v.close()},cleanup:w})}exports.SweetestAlert=d;
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,8 @@ import { createRoot as e } from "react-dom/client";
|
|
|
3
3
|
import { Button as t } from "@planningcenter/tapestry";
|
|
4
4
|
import { Fragment as n, jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
5
5
|
//#region node_modules/@planningcenter/icons/paths/general.mjs
|
|
6
|
-
var a = "M8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8M12.57,6.07l-1.14,-1.14l-4.43,4.44l-2.43,-2.44l-1.14,1.14l3.57,3.56z", o = "M15.669,13.676c0.13528,0.2343 0.13541,0.52294 0.00036,0.75737c-0.13505,0.23443 -0.38481,0.37911 -0.65536,0.37963h-14.028c-0.27081,0.0001 -0.52105,-0.14447 -0.65623,-0.37913c-0.13518,-0.23466 -0.13471,-0.52366 0.00123,-0.75787l7.014,-12.115c0.13497,-0.23419 0.3847,-0.37849 0.655,-0.37849c0.2703,0 0.52003,0.14431 0.655,0.37849l7.014,12.115M8.757,11.028h-1.514v1.514h1.514zM8.757,6.485h-1.514v3.029h1.514z", s = "M8.8,4h-1.6v1.6h1.6zM8.8,7.2h-1.6v4.8h1.6zM8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8", c = "M11.395,10.262l-2.262,-2.262l2.262,-2.262l-1.132,-1.132l-2.262,2.262l-2.263,-2.262l-1.131,1.132l2.262,2.262l-2.262,2.262l1.131,1.132l2.263,-2.262l2.262,2.262zM13.659,2.343c3.12218,3.12514 3.12218,8.18886 0,11.314c-2.28834,2.28863 -5.73017,2.97305 -8.72,1.734c-2.99134,-1.23749 -4.94222,-4.15558 -4.94244,-7.39278c-0.00022,-3.2372 1.95027,-6.15555 4.94143,-7.39345c2.99117,-1.2379 6.43353,-0.55139 8.72101,1.73923";
|
|
7
|
-
|
|
8
|
-
//#region src/sweetest_alert.tsx
|
|
9
|
-
function l() {
|
|
6
|
+
var a = "M8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8M12.57,6.07l-1.14,-1.14l-4.43,4.44l-2.43,-2.44l-1.14,1.14l3.57,3.56z", o = "M15.669,13.676c0.13528,0.2343 0.13541,0.52294 0.00036,0.75737c-0.13505,0.23443 -0.38481,0.37911 -0.65536,0.37963h-14.028c-0.27081,0.0001 -0.52105,-0.14447 -0.65623,-0.37913c-0.13518,-0.23466 -0.13471,-0.52366 0.00123,-0.75787l7.014,-12.115c0.13497,-0.23419 0.3847,-0.37849 0.655,-0.37849c0.2703,0 0.52003,0.14431 0.655,0.37849l7.014,12.115M8.757,11.028h-1.514v1.514h1.514zM8.757,6.485h-1.514v3.029h1.514z", s = "M8.8,4h-1.6v1.6h1.6zM8.8,7.2h-1.6v4.8h1.6zM8,0c4.41828,0 8,3.58172 8,8c0,4.41828 -3.58172,8 -8,8c-4.41828,0 -8,-3.58172 -8,-8c0,-4.41828 3.58172,-8 8,-8", c = "M11.395,10.262l-2.262,-2.262l2.262,-2.262l-1.132,-1.132l-2.262,2.262l-2.263,-2.262l-1.131,1.132l2.262,2.262l-2.262,2.262l1.131,1.132l2.263,-2.262l2.262,2.262zM13.659,2.343c3.12218,3.12514 3.12218,8.18886 0,11.314c-2.28834,2.28863 -5.73017,2.97305 -8.72,1.734c-2.99134,-1.23749 -4.94222,-4.15558 -4.94244,-7.39278c-0.00022,-3.2372 1.95027,-6.15555 4.94143,-7.39345c2.99117,-1.2379 6.43353,-0.55139 8.72101,1.73923", l = "Uh oh!", u = "Something went wrong, please try again. If the error continues, please contact support.";
|
|
7
|
+
function d() {
|
|
10
8
|
let e;
|
|
11
9
|
return {
|
|
12
10
|
promise: new Promise((t) => {
|
|
@@ -15,67 +13,102 @@ function l() {
|
|
|
15
13
|
resolve: e
|
|
16
14
|
};
|
|
17
15
|
}
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
function f(e) {
|
|
17
|
+
return typeof (e !== null && (typeof e == "object" || typeof e == "function") ? e.then : void 0) == "function";
|
|
18
|
+
}
|
|
19
|
+
function p({ onCancel: p, onConfirm: m, confirmButton: h = "Okay", content: g, hideCancel: _ = !1, title: v, type: y = "warning" }) {
|
|
20
|
+
let b = document.createElement("dialog");
|
|
21
|
+
b.className = "pco-sweetest-alert", document.body.appendChild(b);
|
|
22
|
+
let x = e(b), S = !1, C = "idle", { promise: w, resolve: T } = d(), E = () => {
|
|
23
|
+
S || (S = !0, C = "idle", T({
|
|
23
24
|
isConfirmed: !1,
|
|
24
25
|
isDismissed: !0
|
|
25
|
-
}),
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
isConfirmed: !0,
|
|
29
|
-
isDismissed: !1
|
|
30
|
-
}), S(), d?.());
|
|
31
|
-
}, w = () => {
|
|
32
|
-
y || (x({
|
|
26
|
+
}), x.unmount(), b.remove());
|
|
27
|
+
}, D = (e) => {
|
|
28
|
+
S || (T({
|
|
33
29
|
isConfirmed: !1,
|
|
34
30
|
isDismissed: !0
|
|
35
|
-
}),
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
31
|
+
}), E(), e && p?.());
|
|
32
|
+
}, O = async (e) => {
|
|
33
|
+
C = "pending", P();
|
|
34
|
+
let t;
|
|
35
|
+
try {
|
|
36
|
+
t = await e;
|
|
37
|
+
} catch {
|
|
38
|
+
if (S) return;
|
|
39
|
+
C = "error", P();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
S || (T({
|
|
43
|
+
isConfirmed: !0,
|
|
44
|
+
isDismissed: !1,
|
|
45
|
+
value: t
|
|
46
|
+
}), E());
|
|
47
|
+
}, k = () => {
|
|
48
|
+
if (S || C !== "idle") return;
|
|
49
|
+
let e = m?.();
|
|
50
|
+
if (!f(e)) {
|
|
51
|
+
T({
|
|
52
|
+
isConfirmed: !0,
|
|
53
|
+
isDismissed: !1
|
|
54
|
+
}), E();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
O(e);
|
|
58
|
+
}, A = (e) => {
|
|
59
|
+
C === "pending" && e.preventDefault();
|
|
60
|
+
}, j = () => {
|
|
61
|
+
S || C === "pending" || D(C !== "error");
|
|
62
|
+
}, M = (e) => {
|
|
63
|
+
switch (e) {
|
|
64
|
+
case "success": return a;
|
|
65
|
+
case "error": return c;
|
|
66
|
+
case "info": return s;
|
|
67
|
+
case "danger":
|
|
68
|
+
case "warning": return o;
|
|
69
|
+
}
|
|
70
|
+
}, N = () => {
|
|
71
|
+
let e = C === "error", a = C === "pending", o = e ? "error" : y;
|
|
72
|
+
return /* @__PURE__ */ i(n, { children: [
|
|
73
|
+
/* @__PURE__ */ r("svg", {
|
|
74
|
+
className: `pco-sweetest-alert__icon pco-sweetest-alert--${o}`,
|
|
75
|
+
width: "48",
|
|
76
|
+
height: "48",
|
|
77
|
+
viewBox: "0 0 16 16",
|
|
78
|
+
"aria-hidden": "true",
|
|
79
|
+
children: /* @__PURE__ */ r("path", { d: M(o) })
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ r("h2", {
|
|
82
|
+
className: "pco-sweetest-alert__title",
|
|
83
|
+
children: e ? l : v
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ r("div", {
|
|
86
|
+
className: "pco-sweetest-alert__body",
|
|
87
|
+
children: e ? /* @__PURE__ */ r("p", { children: u }) : typeof g == "string" ? /* @__PURE__ */ r("p", { children: g }) : g
|
|
88
|
+
}),
|
|
89
|
+
/* @__PURE__ */ i("div", {
|
|
90
|
+
className: "pco-sweetest-alert__actions",
|
|
91
|
+
children: [!e && !_ && /* @__PURE__ */ r(t, {
|
|
92
|
+
label: "Cancel",
|
|
93
|
+
kind: "ghost",
|
|
94
|
+
disabled: a,
|
|
95
|
+
onClick: () => D(!0)
|
|
96
|
+
}), /* @__PURE__ */ r(t, {
|
|
97
|
+
label: e ? "Okay" : h,
|
|
98
|
+
kind: !e && y === "danger" ? "delete" : "primary",
|
|
99
|
+
loading: a,
|
|
100
|
+
onClick: e ? () => D(!1) : k
|
|
101
|
+
})]
|
|
102
|
+
})
|
|
103
|
+
] });
|
|
104
|
+
}, P = () => x.render(N());
|
|
105
|
+
return P(), b.showModal(), b.addEventListener("cancel", A), b.addEventListener("close", j), Object.assign(w, {
|
|
106
|
+
show: () => b.showModal(),
|
|
107
|
+
close: () => {
|
|
108
|
+
C !== "pending" && b.close();
|
|
109
|
+
},
|
|
110
|
+
cleanup: E
|
|
78
111
|
});
|
|
79
112
|
}
|
|
80
113
|
//#endregion
|
|
81
|
-
export {
|
|
114
|
+
export { p as SweetestAlert };
|
package/dist/sweetest_alert.d.ts
CHANGED
|
@@ -3,17 +3,55 @@ import React from "react";
|
|
|
3
3
|
type AlertTypes = "info" | "success" | "error" | "danger" | "warning";
|
|
4
4
|
/** Resolution value of the promise returned by {@link SweetestAlert}. */
|
|
5
5
|
type AlertResult = {
|
|
6
|
-
/** `true` when the user clicked the confirm button. */
|
|
6
|
+
/** `true` when the user clicked the confirm button (and `onConfirm`, if it returned a promise, resolved). */
|
|
7
7
|
isConfirmed: boolean;
|
|
8
|
-
/** `true` when the dialog was dismissed via cancel, Escape, `close()`,
|
|
8
|
+
/** `true` when the dialog was dismissed via cancel, Escape, `close()`, `cleanup()`, or a rejected `onConfirm`. */
|
|
9
9
|
isDismissed: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The value `onConfirm` resolved with, when `onConfirm` returned a promise
|
|
12
|
+
* (or other thenable). Omitted entirely — not `undefined` — when `onConfirm`
|
|
13
|
+
* didn't return one, so the result shape for existing callers is unchanged.
|
|
14
|
+
*/
|
|
15
|
+
value?: unknown;
|
|
10
16
|
};
|
|
11
17
|
/** Options for {@link SweetestAlert}. */
|
|
12
18
|
type AlertOptions = {
|
|
13
|
-
/** Callback executed when the cancel button is clicked, the dialog is dismissed via Escape, or `close()` is called. */
|
|
19
|
+
/** Callback executed when the cancel button is clicked, the dialog is dismissed via Escape, or `close()` is called. Not called when `onConfirm` rejects. */
|
|
14
20
|
onCancel?: () => void;
|
|
15
|
-
/**
|
|
16
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Callback executed when the confirm button is clicked.
|
|
23
|
+
*
|
|
24
|
+
* If it returns a promise (or other thenable), the dialog stays open with a
|
|
25
|
+
* loading confirm button and a disabled cancel button until it settles:
|
|
26
|
+
* - Resolves → the dialog closes and the returned promise resolves with
|
|
27
|
+
* `{ isConfirmed: true, isDismissed: false, value }`.
|
|
28
|
+
* - Rejects → the dialog stays open and its content is replaced with a
|
|
29
|
+
* generic error message and a single "Okay" button. Dismissing it
|
|
30
|
+
* resolves `{ isConfirmed: false, isDismissed: true }` — the returned
|
|
31
|
+
* promise never rejects, so a failed confirm can't be mistaken for a
|
|
32
|
+
* success by a caller using `.then()`/`await` without a `try`/`catch`.
|
|
33
|
+
*
|
|
34
|
+
* While pending, Escape and `close()` do nothing; `cleanup()` remains the
|
|
35
|
+
* only way to force the dialog closed.
|
|
36
|
+
*
|
|
37
|
+
* Only a rejected promise is treated as a failure — a synchronous throw is
|
|
38
|
+
* not caught, so it skips both the resolve and reject paths above. The
|
|
39
|
+
* dialog is left open and interactive (a user can still Cancel/Escape out
|
|
40
|
+
* of it), but the promise `SweetestAlert()` returned never settles, so an
|
|
41
|
+
* `await` on it hangs until then. Reject the returned promise instead of
|
|
42
|
+
* throwing.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const { isConfirmed, value } = await SweetestAlert({
|
|
47
|
+
* type: "danger",
|
|
48
|
+
* title: "Delete Item",
|
|
49
|
+
* content: "Are you sure you want to delete this item?",
|
|
50
|
+
* onConfirm: () => deleteItem(),
|
|
51
|
+
* })
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
onConfirm?: () => unknown;
|
|
17
55
|
/** Text for the confirm button. Defaults to `"Okay"`. */
|
|
18
56
|
confirmButton?: string;
|
|
19
57
|
/** Required. The body content explaining the alert. Accepts a string or React node. */
|
|
@@ -44,12 +82,13 @@ type AlertOptions = {
|
|
|
44
82
|
* ```
|
|
45
83
|
*
|
|
46
84
|
* @returns A promise that resolves to {@link AlertResult} when the dialog
|
|
47
|
-
* closes (confirm, cancel, or
|
|
85
|
+
* closes (confirm, cancel, Escape, or a rejected `onConfirm`), merged with:
|
|
48
86
|
* - `show()` — re-opens the dialog (calls the native `showModal()`)
|
|
49
87
|
* - `close()` — closes the dialog (calls the native `close()`), resolving
|
|
50
|
-
* the promise with `isDismissed: true` and invoking `onCancel` if provided
|
|
88
|
+
* the promise with `isDismissed: true` and invoking `onCancel` if provided.
|
|
89
|
+
* Does nothing while `onConfirm` is pending.
|
|
51
90
|
* - `cleanup()` — unmounts the React root and removes the dialog from the
|
|
52
|
-
* DOM immediately
|
|
91
|
+
* DOM immediately, regardless of pending state
|
|
53
92
|
*/
|
|
54
93
|
export declare function SweetestAlert({ onCancel, onConfirm, confirmButton, content, hideCancel, title, type, }: AlertOptions): Promise<AlertResult> & {
|
|
55
94
|
show: () => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/sweetest-alert",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "The sweetest alert ever",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "yarn@4.14.1+sha512.64df448055b2d37ba269d7db535a469b8da93f8ef1140c25fd7a83c00a8fbaacb214ca0e02553b92a2c54cef78bb67d0b4817fab02001df0e24fac0faccc3b42",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@planningcenter/icons": "^15.29.1",
|
|
45
45
|
"@planningcenter/tapestry": ">=2.10.1",
|
|
46
|
-
"react": "^18.3.1
|
|
47
|
-
"react-dom": "^18.3.1"
|
|
46
|
+
"react": "^18.3.1 || ^19.0.0",
|
|
47
|
+
"react-dom": "^18.3.1 || ^19.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@eslint/js": "^9.37.0",
|