@planningcenter/sweetest-alert 1.3.0 → 1.6.3

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
@@ -29,7 +29,7 @@ This package requires the following peer dependencies:
29
29
  ### Basic Example
30
30
 
31
31
  ```jsx
32
- import { SweetestAlert } from '@planningcenter/sweetest-alert'
32
+ import { SweetestAlert } from "@planningcenter/sweetest-alert"
33
33
 
34
34
  // Simple notification
35
35
  SweetestAlert({
@@ -46,10 +46,55 @@ SweetestAlert({
46
46
  title: "Delete Item",
47
47
  content: "Are you sure you want to delete this item?",
48
48
  onConfirm: () => console.log("Confirmed"),
49
- onCancel: () => console.log("Cancelled")
49
+ onCancel: () => console.log("Cancelled"),
50
50
  })
51
51
  ```
52
52
 
53
+ ### Promise-based Usage
54
+
55
+ `SweetestAlert` also returns a promise that resolves to `{ isConfirmed, isDismissed }`, so you can use `.then()`/`await` instead of (or alongside) `onConfirm`/`onCancel`:
56
+
57
+ ```jsx
58
+ const { isConfirmed } = await SweetestAlert({
59
+ type: "danger",
60
+ title: "Delete Item",
61
+ content: "Are you sure you want to delete this item?",
62
+ })
63
+
64
+ if (isConfirmed) {
65
+ deleteItem()
66
+ }
67
+ ```
68
+
69
+ Or chain `.then()` when you can’t (or don’t want to) use `await`:
70
+
71
+ ```jsx
72
+ SweetestAlert({
73
+ title: "Discard changes?",
74
+ content: "You have unsaved changes that will be lost.",
75
+ confirmButton: "Discard",
76
+ }).then(({ isConfirmed }) => {
77
+ if (isConfirmed) {
78
+ discardChanges()
79
+ }
80
+ })
81
+ ```
82
+
83
+ `isDismissed` is handy when you want to react to a cancel or Escape too, not just a confirm:
84
+
85
+ ```jsx
86
+ const { isConfirmed, isDismissed } = await SweetestAlert({
87
+ title: "Leave without saving?",
88
+ content: "Your draft will be lost if you leave now.",
89
+ })
90
+
91
+ if (isConfirmed) {
92
+ navigateAway()
93
+ } else if (isDismissed) {
94
+ trackEvent("leave_prompt_dismissed")
95
+ }
96
+ ```
97
+
53
98
  ### Alert Types
54
99
 
55
100
  The component supports five visual types:
@@ -59,28 +104,28 @@ The component supports five visual types:
59
104
  SweetestAlert({
60
105
  type: "info",
61
106
  title: "Information",
62
- content: "This is an informational message."
107
+ content: "This is an informational message.",
63
108
  })
64
109
 
65
110
  // Success alert
66
111
  SweetestAlert({
67
112
  type: "success",
68
113
  title: "Success!",
69
- content: "Operation completed successfully."
114
+ content: "Operation completed successfully.",
70
115
  })
71
116
 
72
117
  // Warning alert (default)
73
118
  SweetestAlert({
74
119
  type: "warning",
75
120
  title: "Warning",
76
- content: "Please proceed with caution."
121
+ content: "Please proceed with caution.",
77
122
  })
78
123
 
79
124
  // Error alert
80
125
  SweetestAlert({
81
126
  type: "error",
82
127
  title: "Error",
83
- content: "Something went wrong."
128
+ content: "Something went wrong.",
84
129
  })
85
130
 
86
131
  // Danger alert (for destructive actions)
@@ -88,7 +133,7 @@ SweetestAlert({
88
133
  type: "danger",
89
134
  title: "Delete Account",
90
135
  content: "This action cannot be undone.",
91
- confirmButton: "Delete"
136
+ confirmButton: "Delete",
92
137
  })
93
138
  ```
94
139
 
@@ -108,7 +153,7 @@ SweetestAlert({
108
153
  <li>Formatted text</li>
109
154
  </ul>
110
155
  </>
111
- )
156
+ ),
112
157
  })
113
158
  ```
114
159
 
@@ -116,15 +161,25 @@ SweetestAlert({
116
161
 
117
162
  ### Parameters
118
163
 
119
- | Parameter | Type | Required | Default | Description |
120
- |-----------|------|----------|---------|-------------|
121
- | `title` | `string` | Yes | - | The main heading text displayed at the top of the modal |
122
- | `content` | `string \| React.ReactNode` | Yes | - | The body content. Accepts plain text or React components |
123
- | `type` | `"info" \| "success" \| "error" \| "danger" \| "warning"` | No | `"warning"` | The visual type of alert, affects icon and styling |
124
- | `onConfirm` | `() => void` | No | - | Callback executed when confirm button is clicked |
125
- | `onCancel` | `() => void` | No | - | Callback executed when cancel button is clicked |
126
- | `confirmButton` | `string` | No | `"Okay"` | Custom text for the confirm button |
127
- | `hideCancel` | `boolean` | No | `false` | When true, hides the cancel button for simple notifications |
164
+ | Parameter | Description |
165
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------------- |
166
+ | `title` | **Required.** The main heading text displayed at the top of the modal. |
167
+ | `content` | **Required.** The body content. Accepts plain text or React components (`string \| React.ReactNode`). |
168
+ | `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. |
171
+ | `confirmButton` | Custom text for the confirm button. Defaults to "Okay". |
172
+ | `hideCancel` | When `true`, hides the cancel button for simple notifications. Defaults to `false`. |
173
+
174
+ ### Return Value
175
+
176
+ `SweetestAlert` returns a promise that resolves to `{ isConfirmed, isDismissed }` when the dialog is closed (via confirm, cancel, or Escape), plus:
177
+
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. |
128
183
 
129
184
  ## Development
130
185
 
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),v=require("react-dom"),h=require("@planningcenter/tapestry");var o={},_;function C(){if(_)return o;_=1;var n=v;if(process.env.NODE_ENV==="production")o.createRoot=n.createRoot,o.hydrateRoot=n.hydrateRoot;else{var c=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;o.createRoot=function(l,r){c.usingClientEntryPoint=!0;try{return n.createRoot(l,r)}finally{c.usingClientEntryPoint=!1}},o.hydrateRoot=function(l,r,s){c.usingClientEntryPoint=!0;try{return n.hydrateRoot(l,r,s)}finally{c.usingClientEntryPoint=!1}}}return o}var f=C();const p="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",w="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",E="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",R="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";function x({onCancel:n,onConfirm:c,confirmButton:l="Okay",content:r,hideCancel:s=!1,title:y,type:a="warning"}){const t=document.createElement("dialog");t.className="pco-sweetest-alert",document.body.appendChild(t);const d=f.createRoot(t),i=()=>{d.unmount(),document.body.removeChild(t)},g=()=>{i(),c?.()},u=()=>{i(),n?.()},m=()=>{switch(a){case"success":return p;case"error":return R;case"info":return E;case"danger":case"warning":return w}};return d.render(e.jsxs(e.Fragment,{children:[e.jsx("svg",{className:`pco-sweetest-alert__icon pco-sweetest-alert--${a}`,width:"48",height:"48",viewBox:"0 0 16 16","aria-hidden":"true",children:e.jsx("path",{d:m()})}),e.jsx("h2",{className:"pco-sweetest-alert__title",children:y}),e.jsx("div",{className:"pco-sweetest-alert__body",children:typeof r=="string"?e.jsx("p",{children:r}):r}),e.jsxs("div",{className:"pco-sweetest-alert__actions",children:[!s&&e.jsx(h.Button,{label:"Cancel",kind:"ghost",onClick:u}),e.jsx(h.Button,{label:l,kind:a==="danger"?"delete":"primary",onClick:g})]})]})),t.showModal(),t.addEventListener("close",u),{show:()=>t.showModal(),close:()=>t.close(),cleanup:i}}exports.SweetestAlert=x;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);require("react");let t=require("@planningcenter/tapestry"),n=require("react/jsx-runtime");var r=e((e=>{var t=require("react-dom");if(process.env.NODE_ENV===`production`)e.createRoot=t.createRoot,e.hydrateRoot=t.hydrateRoot;else{var n=t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;e.createRoot=function(e,r){n.usingClientEntryPoint=!0;try{return t.createRoot(e,r)}finally{n.usingClientEntryPoint=!1}},e.hydrateRoot=function(e,r,i){n.usingClientEntryPoint=!0;try{return t.hydrateRoot(e,r,i)}finally{n.usingClientEntryPoint=!1}}}}))(),i=`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`,a=`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`,o=`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`,s=`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`;function c(){let e;return{promise:new Promise(t=>{e=t}),resolve:e}}function l({onCancel:e,onConfirm:l,confirmButton:u=`Okay`,content:d,hideCancel:f=!1,title:p,type:m=`warning`}){let h=document.createElement(`dialog`);h.className=`pco-sweetest-alert`,document.body.appendChild(h);let g=(0,r.createRoot)(h),_=!1,{promise:v,resolve:y}=c(),b=()=>{_||(_=!0,y({isConfirmed:!1,isDismissed:!0}),g.unmount(),document.body.removeChild(h))},x=()=>{_||(y({isConfirmed:!0,isDismissed:!1}),b(),l?.())},S=()=>{_||(y({isConfirmed:!1,isDismissed:!0}),b(),e?.())};return g.render((0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(`svg`,{className:`pco-sweetest-alert__icon pco-sweetest-alert--${m}`,width:`48`,height:`48`,viewBox:`0 0 16 16`,"aria-hidden":`true`,children:(0,n.jsx)(`path`,{d:(()=>{switch(m){case`success`:return i;case`error`:return s;case`info`:return o;case`danger`:case`warning`:return a}})()})}),(0,n.jsx)(`h2`,{className:`pco-sweetest-alert__title`,children:p}),(0,n.jsx)(`div`,{className:`pco-sweetest-alert__body`,children:typeof d==`string`?(0,n.jsx)(`p`,{children:d}):d}),(0,n.jsxs)(`div`,{className:`pco-sweetest-alert__actions`,children:[!f&&(0,n.jsx)(t.Button,{label:`Cancel`,kind:`ghost`,onClick:S}),(0,n.jsx)(t.Button,{label:u,kind:m===`danger`?`delete`:`primary`,onClick:x})]})]})),h.showModal(),h.addEventListener(`close`,S),Object.assign(v,{show:()=>h.showModal(),close:()=>h.close(),cleanup:b})}exports.SweetestAlert=l;
package/dist/index.js CHANGED
@@ -1,108 +1,104 @@
1
- import { jsxs as u, Fragment as g, jsx as n } from "react/jsx-runtime";
2
- import v from "react-dom";
3
- import { Button as m } from "@planningcenter/tapestry";
4
- var o = {}, _;
5
- function y() {
6
- if (_) return o;
7
- _ = 1;
8
- var t = v;
9
- if (process.env.NODE_ENV === "production")
10
- o.createRoot = t.createRoot, o.hydrateRoot = t.hydrateRoot;
11
- else {
12
- var c = t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
13
- o.createRoot = function(l, r) {
14
- c.usingClientEntryPoint = !0;
15
- try {
16
- return t.createRoot(l, r);
17
- } finally {
18
- c.usingClientEntryPoint = !1;
19
- }
20
- }, o.hydrateRoot = function(l, r, a) {
21
- c.usingClientEntryPoint = !0;
22
- try {
23
- return t.hydrateRoot(l, r, a);
24
- } finally {
25
- c.usingClientEntryPoint = !1;
26
- }
27
- };
28
- }
29
- return o;
1
+ import "react";
2
+ import { Button as e } from "@planningcenter/tapestry";
3
+ import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
4
+ //#region \0rolldown/runtime.js
5
+ var i = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), a = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
6
+ if (typeof require < "u") return require.apply(this, arguments);
7
+ throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
8
+ }), o = (/* @__PURE__ */ i(((e) => {
9
+ var t = a("react-dom");
10
+ if (process.env.NODE_ENV === "production") e.createRoot = t.createRoot, e.hydrateRoot = t.hydrateRoot;
11
+ else {
12
+ var n = t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
13
+ e.createRoot = function(e, r) {
14
+ n.usingClientEntryPoint = !0;
15
+ try {
16
+ return t.createRoot(e, r);
17
+ } finally {
18
+ n.usingClientEntryPoint = !1;
19
+ }
20
+ }, e.hydrateRoot = function(e, r, i) {
21
+ n.usingClientEntryPoint = !0;
22
+ try {
23
+ return t.hydrateRoot(e, r, i);
24
+ } finally {
25
+ n.usingClientEntryPoint = !1;
26
+ }
27
+ };
28
+ }
29
+ })))(), s = "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", c = "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", l = "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", u = "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";
30
+ //#endregion
31
+ //#region src/sweetest_alert.tsx
32
+ function d() {
33
+ let e;
34
+ return {
35
+ promise: new Promise((t) => {
36
+ e = t;
37
+ }),
38
+ resolve: e
39
+ };
30
40
  }
31
- var w = y();
32
- const E = "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", R = "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", M = "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", N = "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";
33
- function O({
34
- // Optional: Callback function executed when cancel button is clicked
35
- onCancel: t,
36
- // Optional: Callback function executed when confirm button is clicked
37
- onConfirm: c,
38
- // Optional: Text for the confirm button. Defaults to "Okay".
39
- confirmButton: l = "Okay",
40
- // Required: The body content explaining the alert.
41
- // Accepts a React fragment or a string of text.
42
- content: r,
43
- // Optional: When true, hides the cancel button for simple notifications.
44
- // Defaults to "false".
45
- hideCancel: a = !1,
46
- // Required: The main heading text displayed at the top of the modal
47
- title: f,
48
- // Optional: The visual type of alert, affects icon and styling.
49
- // Values can be "info", "success", "error", "danger", or "warning" (default).
50
- type: s = "warning"
51
- }) {
52
- const e = document.createElement("dialog");
53
- e.className = "pco-sweetest-alert", document.body.appendChild(e);
54
- const d = w.createRoot(e), i = () => {
55
- d.unmount(), document.body.removeChild(e);
56
- }, p = () => {
57
- i(), c?.();
58
- }, h = () => {
59
- i(), t?.();
60
- }, C = () => {
61
- switch (s) {
62
- case "success":
63
- return E;
64
- case "error":
65
- return N;
66
- case "info":
67
- return M;
68
- case "danger":
69
- case "warning":
70
- return R;
71
- }
72
- };
73
- return d.render(
74
- /* @__PURE__ */ u(g, { children: [
75
- /* @__PURE__ */ n(
76
- "svg",
77
- {
78
- className: `pco-sweetest-alert__icon pco-sweetest-alert--${s}`,
79
- width: "48",
80
- height: "48",
81
- viewBox: "0 0 16 16",
82
- "aria-hidden": "true",
83
- children: /* @__PURE__ */ n("path", { d: C() })
84
- }
85
- ),
86
- /* @__PURE__ */ n("h2", { className: "pco-sweetest-alert__title", children: f }),
87
- /* @__PURE__ */ n("div", { className: "pco-sweetest-alert__body", children: typeof r == "string" ? /* @__PURE__ */ n("p", { children: r }) : r }),
88
- /* @__PURE__ */ u("div", { className: "pco-sweetest-alert__actions", children: [
89
- !a && /* @__PURE__ */ n(m, { label: "Cancel", kind: "ghost", onClick: h }),
90
- /* @__PURE__ */ n(
91
- m,
92
- {
93
- label: l,
94
- kind: s === "danger" ? "delete" : "primary",
95
- onClick: p
96
- }
97
- )
98
- ] })
99
- ] })
100
- ), e.showModal(), e.addEventListener("close", h), {
101
- show: () => e.showModal(),
102
- close: () => e.close(),
103
- cleanup: i
104
- };
41
+ function f({ onCancel: i, onConfirm: a, confirmButton: f = "Okay", content: p, hideCancel: m = !1, title: h, type: g = "warning" }) {
42
+ let _ = document.createElement("dialog");
43
+ _.className = "pco-sweetest-alert", document.body.appendChild(_);
44
+ let v = (0, o.createRoot)(_), y = !1, { promise: b, resolve: x } = d(), S = () => {
45
+ y || (y = !0, x({
46
+ isConfirmed: !1,
47
+ isDismissed: !0
48
+ }), v.unmount(), document.body.removeChild(_));
49
+ }, C = () => {
50
+ y || (x({
51
+ isConfirmed: !0,
52
+ isDismissed: !1
53
+ }), S(), a?.());
54
+ }, w = () => {
55
+ y || (x({
56
+ isConfirmed: !1,
57
+ isDismissed: !0
58
+ }), S(), i?.());
59
+ };
60
+ return v.render(/* @__PURE__ */ r(t, { children: [
61
+ /* @__PURE__ */ n("svg", {
62
+ className: `pco-sweetest-alert__icon pco-sweetest-alert--${g}`,
63
+ width: "48",
64
+ height: "48",
65
+ viewBox: "0 0 16 16",
66
+ "aria-hidden": "true",
67
+ children: /* @__PURE__ */ n("path", { d: (() => {
68
+ switch (g) {
69
+ case "success": return s;
70
+ case "error": return u;
71
+ case "info": return l;
72
+ case "danger":
73
+ case "warning": return c;
74
+ }
75
+ })() })
76
+ }),
77
+ /* @__PURE__ */ n("h2", {
78
+ className: "pco-sweetest-alert__title",
79
+ children: h
80
+ }),
81
+ /* @__PURE__ */ n("div", {
82
+ className: "pco-sweetest-alert__body",
83
+ children: typeof p == "string" ? /* @__PURE__ */ n("p", { children: p }) : p
84
+ }),
85
+ /* @__PURE__ */ r("div", {
86
+ className: "pco-sweetest-alert__actions",
87
+ children: [!m && /* @__PURE__ */ n(e, {
88
+ label: "Cancel",
89
+ kind: "ghost",
90
+ onClick: w
91
+ }), /* @__PURE__ */ n(e, {
92
+ label: f,
93
+ kind: g === "danger" ? "delete" : "primary",
94
+ onClick: C
95
+ })]
96
+ })
97
+ ] })), _.showModal(), _.addEventListener("close", w), Object.assign(b, {
98
+ show: () => _.showModal(),
99
+ close: () => _.close(),
100
+ cleanup: S
101
+ });
105
102
  }
106
- export {
107
- O as SweetestAlert
108
- };
103
+ //#endregion
104
+ export { f as SweetestAlert };
@@ -1,14 +1,57 @@
1
1
  import React from "react";
2
+ /** Visual type of alert; affects icon and border/hover color. */
2
3
  type AlertTypes = "info" | "success" | "error" | "danger" | "warning";
3
- export declare function SweetestAlert({ onCancel, onConfirm, confirmButton, content, hideCancel, title, type, }: {
4
+ /** Resolution value of the promise returned by {@link SweetestAlert}. */
5
+ type AlertResult = {
6
+ /** `true` when the user clicked the confirm button. */
7
+ isConfirmed: boolean;
8
+ /** `true` when the dialog was dismissed via cancel, Escape, `close()`, or `cleanup()`. */
9
+ isDismissed: boolean;
10
+ };
11
+ /** Options for {@link SweetestAlert}. */
12
+ type AlertOptions = {
13
+ /** Callback executed when the cancel button is clicked, the dialog is dismissed via Escape, or `close()` is called. */
4
14
  onCancel?: () => void;
15
+ /** Callback executed when the confirm button is clicked. */
5
16
  onConfirm?: () => void;
17
+ /** Text for the confirm button. Defaults to `"Okay"`. */
6
18
  confirmButton?: string;
19
+ /** Required. The body content explaining the alert. Accepts a string or React node. */
7
20
  content: string | React.ReactNode;
21
+ /** When `true`, hides the cancel button for simple notifications. Defaults to `false`. */
8
22
  hideCancel?: boolean;
23
+ /** Required. The main heading text displayed at the top of the modal. */
9
24
  title: string;
25
+ /** Visual type of alert; affects icon and styling. Defaults to `"warning"`. */
10
26
  type?: AlertTypes;
11
- }): {
27
+ };
28
+ /**
29
+ * Shows a modal alert/confirmation dialog using a native `<dialog>` element.
30
+ *
31
+ * Creates the dialog, mounts a React root into it, and appends it to
32
+ * `document.body`. Not a traditional React component — call it directly
33
+ * from anywhere, including outside a React render tree.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * const { isConfirmed } = await SweetestAlert({
38
+ * type: "danger",
39
+ * title: "Delete Item",
40
+ * content: "Are you sure you want to delete this item?",
41
+ * })
42
+ *
43
+ * if (isConfirmed) deleteItem()
44
+ * ```
45
+ *
46
+ * @returns A promise that resolves to {@link AlertResult} when the dialog
47
+ * closes (confirm, cancel, or Escape), merged with:
48
+ * - `show()` — re-opens the dialog (calls the native `showModal()`)
49
+ * - `close()` — closes the dialog (calls the native `close()`), resolving
50
+ * the promise with `isDismissed: true` and invoking `onCancel` if provided
51
+ * - `cleanup()` — unmounts the React root and removes the dialog from the
52
+ * DOM immediately
53
+ */
54
+ export declare function SweetestAlert({ onCancel, onConfirm, confirmButton, content, hideCancel, title, type, }: AlertOptions): Promise<AlertResult> & {
12
55
  show: () => void;
13
56
  close: () => void;
14
57
  cleanup: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/sweetest-alert",
3
- "version": "1.3.0",
3
+ "version": "1.6.3",
4
4
  "description": "The sweetest alert ever",
5
5
  "type": "module",
6
6
  "packageManager": "yarn@4.14.1+sha512.64df448055b2d37ba269d7db535a469b8da93f8ef1140c25fd7a83c00a8fbaacb214ca0e02553b92a2c54cef78bb67d0b4817fab02001df0e24fac0faccc3b42",
@@ -35,6 +35,7 @@
35
35
  "build:docs": "vite build --config vite.config.docs.ts",
36
36
  "preview": "vite preview --config vite.config.docs.ts",
37
37
  "test": "vitest",
38
+ "typecheck": "tsc --noEmit",
38
39
  "lint:js": "eslint .",
39
40
  "lint:css": "stylelint \"**/*.css\"",
40
41
  "prepublishOnly": "yarn build:lib"
@@ -56,11 +57,13 @@
56
57
  "@types/prismjs": "^1.26.5",
57
58
  "@types/react": "^18.3.12",
58
59
  "@types/react-dom": "^18.3.1",
59
- "@vitejs/plugin-react": "^5.0.4",
60
+ "@vitejs/plugin-react": "^6.0.2",
60
61
  "eslint": "^9.37.0",
62
+ "eslint-config-prettier": "^10.1.8",
61
63
  "eslint-plugin-react": "^7.37.5",
62
64
  "eslint-plugin-react-hooks": "^7.0.0",
63
- "jsdom": "^27.0.0",
65
+ "happy-dom": "^20.10.6",
66
+ "prettier": "^3.8.3",
64
67
  "prismjs": "^1.30.0",
65
68
  "react": "^18.3.1",
66
69
  "react-dom": "^18.3.1",
@@ -68,7 +71,7 @@
68
71
  "stylelint": "^16.25.0",
69
72
  "typescript": "^5.9.3",
70
73
  "typescript-eslint": "^8.46.1",
71
- "vite": "^7.1.11",
72
- "vitest": "^4.1.0"
74
+ "vite": "^8.0.16",
75
+ "vitest": "4.1.8"
73
76
  }
74
77
  }