@ttt-productions/ui-core 0.11.4 → 0.11.5
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/dist/react/components/consequence-dialog.d.ts +68 -0
- package/dist/react/components/consequence-dialog.d.ts.map +1 -0
- package/dist/react/components/consequence-dialog.js +80 -0
- package/dist/react/components/consequence-dialog.js.map +1 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/package.json +3 -3
- package/src/react/components/consequence-dialog.tsx +276 -0
- package/src/react/index.ts +3 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inline required-reason config. The caller OWNS the reason value/onChange (draft state lives at
|
|
3
|
+
* the call site). Any `minLength`/`maxLength` the caller supplies MUST come from a caller-owned
|
|
4
|
+
* constant — this component declares no business numbers and no copy; it only derives the gate + the
|
|
5
|
+
* Textarea `maxLength` from the values it is handed.
|
|
6
|
+
*/
|
|
7
|
+
export interface ConsequenceDialogReason {
|
|
8
|
+
required?: boolean;
|
|
9
|
+
minLength?: number;
|
|
10
|
+
maxLength?: number;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
label?: React.ReactNode;
|
|
13
|
+
value: string;
|
|
14
|
+
onChange: (value: string) => void;
|
|
15
|
+
rows?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The exact-match typed-confirmation gate. `phrase` is business copy owned by the CALLER; the
|
|
19
|
+
* component only compares the typed value against it.
|
|
20
|
+
*/
|
|
21
|
+
export interface ConsequenceDialogTypedConfirmation {
|
|
22
|
+
phrase: string;
|
|
23
|
+
label?: React.ReactNode;
|
|
24
|
+
}
|
|
25
|
+
export interface ConsequenceDialogProps {
|
|
26
|
+
/** Uncontrolled open model: the element that opens the dialog (rendered `asChild`). */
|
|
27
|
+
trigger?: React.ReactNode;
|
|
28
|
+
/** Controlled open model. Provide with `onOpenChange`. */
|
|
29
|
+
open?: boolean;
|
|
30
|
+
onOpenChange?: (open: boolean) => void;
|
|
31
|
+
/** Heading — a string or node so callers can interpolate amounts / names. */
|
|
32
|
+
title: React.ReactNode;
|
|
33
|
+
/** SLOT 1 — what happens right now (e.g. "initiates a Stripe refund of $X now"). */
|
|
34
|
+
immediateEffect?: React.ReactNode;
|
|
35
|
+
/** SLOT 2 — what settles later, out of band (webhook / worker / async confirmation). */
|
|
36
|
+
delayedEffect?: React.ReactNode;
|
|
37
|
+
/** SLOT 3 — whether/how this can be undone or superseded. */
|
|
38
|
+
reversibility?: React.ReactNode;
|
|
39
|
+
/** Inline required-reason field. Optional. */
|
|
40
|
+
reason?: ConsequenceDialogReason;
|
|
41
|
+
/** Exact-phrase typed-confirmation gate. Optional. */
|
|
42
|
+
typedConfirmation?: ConsequenceDialogTypedConfirmation;
|
|
43
|
+
confirmLabel: React.ReactNode;
|
|
44
|
+
cancelLabel?: React.ReactNode;
|
|
45
|
+
/** `true` styles the confirm button with `bg-destructive`. */
|
|
46
|
+
destructive?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Runs on confirm. May be async — while it is pending the dialog STAYS OPEN, both buttons disable,
|
|
49
|
+
* and a `Loader2` spins in the confirm button. Closes on resolve. If it rejects the dialog
|
|
50
|
+
* stays open so the caller's own surface (error toast, TOTP step-up) can show and the operator can
|
|
51
|
+
* retry or cancel. This component takes no Sentry/monitoring dependency — every error path
|
|
52
|
+
* belongs to the caller's `onConfirm`.
|
|
53
|
+
*/
|
|
54
|
+
onConfirm: () => void | Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A reusable confirm-before-a-consequential-action dialog. Three optional, consistently-styled
|
|
58
|
+
* consequence slots (immediate / afterward / reversibility), an optional inline required-reason field,
|
|
59
|
+
* and an optional exact-phrase typed-confirmation gate. Composes the ui-core AlertDialog primitives
|
|
60
|
+
* (Radix) — it never re-implements them. Supports BOTH a `trigger` (uncontrolled) and `open` /
|
|
61
|
+
* `onOpenChange` (controlled).
|
|
62
|
+
*
|
|
63
|
+
* Pending model: the confirm button is a plain `Button` (NOT `AlertDialogAction`), so Radix does not
|
|
64
|
+
* auto-close on click; open state is managed here so the dialog stays open with a visible spinner
|
|
65
|
+
* until `onConfirm` resolves.
|
|
66
|
+
*/
|
|
67
|
+
export declare function ConsequenceDialog({ trigger, open, onOpenChange, title, immediateEffect, delayedEffect, reversibility, reason, typedConfirmation, confirmLabel, cancelLabel, destructive, onConfirm, }: ConsequenceDialogProps): import("react").JSX.Element;
|
|
68
|
+
//# sourceMappingURL=consequence-dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consequence-dialog.d.ts","sourceRoot":"","sources":["../../../src/react/components/consequence-dialog.tsx"],"names":[],"mappings":"AAkBA;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,kCAAkC;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,uFAAuF;IACvF,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvC,6EAA6E;IAC7E,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IAEvB,oFAAoF;IACpF,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,wFAAwF;IACxF,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,6DAA6D;IAC7D,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEhC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,kCAAkC,CAAC;IAEvD,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AA0BD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,MAAM,EACN,iBAAiB,EACjB,YAAY,EACZ,WAAsB,EACtB,WAAmB,EACnB,SAAS,GACV,EAAE,sBAAsB,+BAiJxB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useId, useState } from 'react';
|
|
4
|
+
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, } from './alert-dialog.js';
|
|
5
|
+
import { Button } from './button.js';
|
|
6
|
+
import { Textarea } from './textarea.js';
|
|
7
|
+
import { Input } from './input.js';
|
|
8
|
+
import { Label } from './label.js';
|
|
9
|
+
import { Loader2, Zap, Clock, RotateCcw } from 'lucide-react';
|
|
10
|
+
const SLOT_ICON_CLASS = 'icon-xs mt-0.5 shrink-0 text-muted-foreground';
|
|
11
|
+
function ConsequenceRow({ icon: Icon, label, children, }) {
|
|
12
|
+
return (_jsxs("span", { className: "flex items-start gap-2", children: [_jsx(Icon, { className: SLOT_ICON_CLASS, "aria-hidden": "true" }), _jsxs("span", { className: "stack-1 min-w-0", children: [_jsx("span", { className: "text-caption font-medium uppercase tracking-wide text-muted-foreground", children: label }), _jsx("span", { className: "text-small text-foreground", children: children })] })] }));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A reusable confirm-before-a-consequential-action dialog. Three optional, consistently-styled
|
|
16
|
+
* consequence slots (immediate / afterward / reversibility), an optional inline required-reason field,
|
|
17
|
+
* and an optional exact-phrase typed-confirmation gate. Composes the ui-core AlertDialog primitives
|
|
18
|
+
* (Radix) — it never re-implements them. Supports BOTH a `trigger` (uncontrolled) and `open` /
|
|
19
|
+
* `onOpenChange` (controlled).
|
|
20
|
+
*
|
|
21
|
+
* Pending model: the confirm button is a plain `Button` (NOT `AlertDialogAction`), so Radix does not
|
|
22
|
+
* auto-close on click; open state is managed here so the dialog stays open with a visible spinner
|
|
23
|
+
* until `onConfirm` resolves.
|
|
24
|
+
*/
|
|
25
|
+
export function ConsequenceDialog({ trigger, open, onOpenChange, title, immediateEffect, delayedEffect, reversibility, reason, typedConfirmation, confirmLabel, cancelLabel = 'Cancel', destructive = false, onConfirm, }) {
|
|
26
|
+
const isControlled = open !== undefined;
|
|
27
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
28
|
+
const [typedValue, setTypedValue] = useState('');
|
|
29
|
+
const [pending, setPending] = useState(false);
|
|
30
|
+
const actualOpen = isControlled ? open : internalOpen;
|
|
31
|
+
const reasonId = useId();
|
|
32
|
+
const typedId = useId();
|
|
33
|
+
const setOpenState = useCallback((next) => {
|
|
34
|
+
if (isControlled)
|
|
35
|
+
onOpenChange?.(next);
|
|
36
|
+
else
|
|
37
|
+
setInternalOpen(next);
|
|
38
|
+
}, [isControlled, onOpenChange]);
|
|
39
|
+
// Never allow an open-state change (Escape, cancel, controlled parent) to fight the pending action.
|
|
40
|
+
const handleOpenChange = useCallback((next) => {
|
|
41
|
+
if (pending)
|
|
42
|
+
return;
|
|
43
|
+
setTypedValue(''); // reset the typed gate on every open/close
|
|
44
|
+
setOpenState(next);
|
|
45
|
+
}, [pending, setOpenState]);
|
|
46
|
+
const handleConfirm = useCallback(async () => {
|
|
47
|
+
if (pending)
|
|
48
|
+
return;
|
|
49
|
+
setPending(true);
|
|
50
|
+
try {
|
|
51
|
+
await onConfirm();
|
|
52
|
+
setTypedValue('');
|
|
53
|
+
setOpenState(false);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Keep the dialog open — the caller's onConfirm surfaced the error (toast / step-up). The
|
|
57
|
+
// operator can retry or cancel. Never rethrow, never monitor here.
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
setPending(false);
|
|
61
|
+
}
|
|
62
|
+
}, [pending, onConfirm, setOpenState]);
|
|
63
|
+
const reasonTrimmedLength = reason ? reason.value.trim().length : 0;
|
|
64
|
+
const reasonProvided = reasonTrimmedLength > 0;
|
|
65
|
+
const reasonOk = !reason
|
|
66
|
+
? true
|
|
67
|
+
: reason.required && !reasonProvided
|
|
68
|
+
? false
|
|
69
|
+
: !reasonProvided
|
|
70
|
+
? true // optional + empty is fine
|
|
71
|
+
: (reason.minLength === undefined || reasonTrimmedLength >= reason.minLength) &&
|
|
72
|
+
(reason.maxLength === undefined || reason.value.length <= reason.maxLength);
|
|
73
|
+
const typedOk = !typedConfirmation ? true : typedValue === typedConfirmation.phrase;
|
|
74
|
+
const confirmDisabled = pending || !reasonOk || !typedOk;
|
|
75
|
+
return (_jsxs(AlertDialog, { open: actualOpen, onOpenChange: handleOpenChange, children: [trigger ? _jsx(AlertDialogTrigger, { asChild: true, children: trigger }) : null, _jsxs(AlertDialogContent, { onEscapeKeyDown: (e) => {
|
|
76
|
+
if (pending)
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
}, children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: title }), _jsx(AlertDialogDescription, { asChild: true, children: _jsxs("span", { className: "stack-3", children: [immediateEffect ? (_jsx(ConsequenceRow, { icon: Zap, label: "Immediately", children: immediateEffect })) : null, delayedEffect ? (_jsx(ConsequenceRow, { icon: Clock, label: "Afterward", children: delayedEffect })) : null, reversibility ? (_jsx(ConsequenceRow, { icon: RotateCcw, label: "Reversibility", children: reversibility })) : null] }) })] }), reason ? (_jsxs("div", { className: "stack-2", children: [_jsx(Label, { htmlFor: reasonId, children: reason.label ?? 'Reason' }), _jsx(Textarea, { id: reasonId, value: reason.value, onChange: (e) => reason.onChange(e.target.value), placeholder: reason.placeholder, maxLength: reason.maxLength, rows: reason.rows ?? 3, disabled: pending })] })) : null, typedConfirmation ? (_jsxs("div", { className: "stack-2", children: [_jsx(Label, { htmlFor: typedId, children: typedConfirmation.label ?? (_jsxs(_Fragment, { children: ["Type ", _jsx("span", { className: "font-mono", children: typedConfirmation.phrase }), " to confirm"] })) }), _jsx(Input, { id: typedId, value: typedValue, onChange: (e) => setTypedValue(e.target.value), placeholder: typedConfirmation.phrase, disabled: pending, autoComplete: "off" })] })) : null, _jsxs(AlertDialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => handleOpenChange(false), disabled: pending, children: cancelLabel }), _jsxs(Button, { variant: destructive ? 'destructive' : 'default', onClick: handleConfirm, disabled: confirmDisabled, "aria-busy": pending, children: [pending ? _jsx(Loader2, { className: "mr-2 spinner-xs", "aria-hidden": "true" }) : null, confirmLabel] })] })] })] }));
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=consequence-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consequence-dialog.js","sourceRoot":"","sources":["../../../src/react/components/consequence-dialog.tsx"],"names":[],"mappings":"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"}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export { Sheet, SheetPortal, SheetOverlay, SheetTrigger, SheetClose, SheetConten
|
|
|
38
38
|
export { Collapsible, CollapsibleTrigger, CollapsibleContent } from "./components/collapsible.js";
|
|
39
39
|
export type { SearchDropdownProps } from "./components/search-dropdown.js";
|
|
40
40
|
export { SearchDropdown } from "./components/search-dropdown.js";
|
|
41
|
+
export type { ConsequenceDialogProps, ConsequenceDialogReason, ConsequenceDialogTypedConfirmation } from "./components/consequence-dialog.js";
|
|
42
|
+
export { ConsequenceDialog } from "./components/consequence-dialog.js";
|
|
41
43
|
export type { MaxWidthOption, ScreenAdaptiveViewProps } from "./components/layout/screen-adaptive-view.js";
|
|
42
44
|
export { ScreenAdaptiveView } from "./components/layout/screen-adaptive-view.js";
|
|
43
45
|
export { useMediaQuery } from "./hooks/use-media-query.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
package/dist/react/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableC
|
|
|
33
33
|
export { Sheet, SheetPortal, SheetOverlay, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from "./components/sheet.js";
|
|
34
34
|
export { Collapsible, CollapsibleTrigger, CollapsibleContent } from "./components/collapsible.js";
|
|
35
35
|
export { SearchDropdown } from "./components/search-dropdown.js";
|
|
36
|
+
export { ConsequenceDialog } from "./components/consequence-dialog.js";
|
|
36
37
|
export { ScreenAdaptiveView } from "./components/layout/screen-adaptive-view.js";
|
|
37
38
|
export { useMediaQuery } from "./hooks/use-media-query.js";
|
|
38
39
|
// Shared building blocks
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/ui-core",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.5",
|
|
4
4
|
"description": "Shared UI components for TTT Productions projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"react-dom": ">=19.0.0",
|
|
50
50
|
"react-hook-form": ">=7.0.0",
|
|
51
51
|
"@hookform/resolvers": ">=3.0.0",
|
|
52
|
-
"@ttt-productions/firebase-helpers": "^0.12.
|
|
52
|
+
"@ttt-productions/firebase-helpers": "^0.12.1"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"react": {
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"typescript": "^5.8.3",
|
|
100
100
|
"react-hook-form": "^7.69.0",
|
|
101
101
|
"@hookform/resolvers": "^5.2.2",
|
|
102
|
-
"@ttt-productions/firebase-helpers": "^0.12.
|
|
102
|
+
"@ttt-productions/firebase-helpers": "^0.12.1"
|
|
103
103
|
},
|
|
104
104
|
"author": "DJ (TTT Productions)",
|
|
105
105
|
"license": "MIT"
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useId, useState } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
AlertDialog,
|
|
6
|
+
AlertDialogTrigger,
|
|
7
|
+
AlertDialogContent,
|
|
8
|
+
AlertDialogHeader,
|
|
9
|
+
AlertDialogFooter,
|
|
10
|
+
AlertDialogTitle,
|
|
11
|
+
AlertDialogDescription,
|
|
12
|
+
} from './alert-dialog.js';
|
|
13
|
+
import { Button } from './button.js';
|
|
14
|
+
import { Textarea } from './textarea.js';
|
|
15
|
+
import { Input } from './input.js';
|
|
16
|
+
import { Label } from './label.js';
|
|
17
|
+
import { Loader2, Zap, Clock, RotateCcw } from 'lucide-react';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The inline required-reason config. The caller OWNS the reason value/onChange (draft state lives at
|
|
21
|
+
* the call site). Any `minLength`/`maxLength` the caller supplies MUST come from a caller-owned
|
|
22
|
+
* constant — this component declares no business numbers and no copy; it only derives the gate + the
|
|
23
|
+
* Textarea `maxLength` from the values it is handed.
|
|
24
|
+
*/
|
|
25
|
+
export interface ConsequenceDialogReason {
|
|
26
|
+
required?: boolean;
|
|
27
|
+
minLength?: number;
|
|
28
|
+
maxLength?: number;
|
|
29
|
+
placeholder?: string;
|
|
30
|
+
label?: React.ReactNode;
|
|
31
|
+
value: string;
|
|
32
|
+
onChange: (value: string) => void;
|
|
33
|
+
rows?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The exact-match typed-confirmation gate. `phrase` is business copy owned by the CALLER; the
|
|
38
|
+
* component only compares the typed value against it.
|
|
39
|
+
*/
|
|
40
|
+
export interface ConsequenceDialogTypedConfirmation {
|
|
41
|
+
phrase: string;
|
|
42
|
+
label?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ConsequenceDialogProps {
|
|
46
|
+
/** Uncontrolled open model: the element that opens the dialog (rendered `asChild`). */
|
|
47
|
+
trigger?: React.ReactNode;
|
|
48
|
+
/** Controlled open model. Provide with `onOpenChange`. */
|
|
49
|
+
open?: boolean;
|
|
50
|
+
onOpenChange?: (open: boolean) => void;
|
|
51
|
+
|
|
52
|
+
/** Heading — a string or node so callers can interpolate amounts / names. */
|
|
53
|
+
title: React.ReactNode;
|
|
54
|
+
|
|
55
|
+
/** SLOT 1 — what happens right now (e.g. "initiates a Stripe refund of $X now"). */
|
|
56
|
+
immediateEffect?: React.ReactNode;
|
|
57
|
+
/** SLOT 2 — what settles later, out of band (webhook / worker / async confirmation). */
|
|
58
|
+
delayedEffect?: React.ReactNode;
|
|
59
|
+
/** SLOT 3 — whether/how this can be undone or superseded. */
|
|
60
|
+
reversibility?: React.ReactNode;
|
|
61
|
+
|
|
62
|
+
/** Inline required-reason field. Optional. */
|
|
63
|
+
reason?: ConsequenceDialogReason;
|
|
64
|
+
/** Exact-phrase typed-confirmation gate. Optional. */
|
|
65
|
+
typedConfirmation?: ConsequenceDialogTypedConfirmation;
|
|
66
|
+
|
|
67
|
+
confirmLabel: React.ReactNode;
|
|
68
|
+
cancelLabel?: React.ReactNode;
|
|
69
|
+
/** `true` styles the confirm button with `bg-destructive`. */
|
|
70
|
+
destructive?: boolean;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Runs on confirm. May be async — while it is pending the dialog STAYS OPEN, both buttons disable,
|
|
74
|
+
* and a `Loader2` spins in the confirm button. Closes on resolve. If it rejects the dialog
|
|
75
|
+
* stays open so the caller's own surface (error toast, TOTP step-up) can show and the operator can
|
|
76
|
+
* retry or cancel. This component takes no Sentry/monitoring dependency — every error path
|
|
77
|
+
* belongs to the caller's `onConfirm`.
|
|
78
|
+
*/
|
|
79
|
+
onConfirm: () => void | Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const SLOT_ICON_CLASS = 'icon-xs mt-0.5 shrink-0 text-muted-foreground';
|
|
83
|
+
|
|
84
|
+
function ConsequenceRow({
|
|
85
|
+
icon: Icon,
|
|
86
|
+
label,
|
|
87
|
+
children,
|
|
88
|
+
}: {
|
|
89
|
+
icon: typeof Zap;
|
|
90
|
+
label: string;
|
|
91
|
+
children: React.ReactNode;
|
|
92
|
+
}) {
|
|
93
|
+
return (
|
|
94
|
+
<span className="flex items-start gap-2">
|
|
95
|
+
<Icon className={SLOT_ICON_CLASS} aria-hidden="true" />
|
|
96
|
+
<span className="stack-1 min-w-0">
|
|
97
|
+
<span className="text-caption font-medium uppercase tracking-wide text-muted-foreground">
|
|
98
|
+
{label}
|
|
99
|
+
</span>
|
|
100
|
+
<span className="text-small text-foreground">{children}</span>
|
|
101
|
+
</span>
|
|
102
|
+
</span>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A reusable confirm-before-a-consequential-action dialog. Three optional, consistently-styled
|
|
108
|
+
* consequence slots (immediate / afterward / reversibility), an optional inline required-reason field,
|
|
109
|
+
* and an optional exact-phrase typed-confirmation gate. Composes the ui-core AlertDialog primitives
|
|
110
|
+
* (Radix) — it never re-implements them. Supports BOTH a `trigger` (uncontrolled) and `open` /
|
|
111
|
+
* `onOpenChange` (controlled).
|
|
112
|
+
*
|
|
113
|
+
* Pending model: the confirm button is a plain `Button` (NOT `AlertDialogAction`), so Radix does not
|
|
114
|
+
* auto-close on click; open state is managed here so the dialog stays open with a visible spinner
|
|
115
|
+
* until `onConfirm` resolves.
|
|
116
|
+
*/
|
|
117
|
+
export function ConsequenceDialog({
|
|
118
|
+
trigger,
|
|
119
|
+
open,
|
|
120
|
+
onOpenChange,
|
|
121
|
+
title,
|
|
122
|
+
immediateEffect,
|
|
123
|
+
delayedEffect,
|
|
124
|
+
reversibility,
|
|
125
|
+
reason,
|
|
126
|
+
typedConfirmation,
|
|
127
|
+
confirmLabel,
|
|
128
|
+
cancelLabel = 'Cancel',
|
|
129
|
+
destructive = false,
|
|
130
|
+
onConfirm,
|
|
131
|
+
}: ConsequenceDialogProps) {
|
|
132
|
+
const isControlled = open !== undefined;
|
|
133
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
134
|
+
const [typedValue, setTypedValue] = useState('');
|
|
135
|
+
const [pending, setPending] = useState(false);
|
|
136
|
+
|
|
137
|
+
const actualOpen = isControlled ? open : internalOpen;
|
|
138
|
+
|
|
139
|
+
const reasonId = useId();
|
|
140
|
+
const typedId = useId();
|
|
141
|
+
|
|
142
|
+
const setOpenState = useCallback(
|
|
143
|
+
(next: boolean) => {
|
|
144
|
+
if (isControlled) onOpenChange?.(next);
|
|
145
|
+
else setInternalOpen(next);
|
|
146
|
+
},
|
|
147
|
+
[isControlled, onOpenChange],
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Never allow an open-state change (Escape, cancel, controlled parent) to fight the pending action.
|
|
151
|
+
const handleOpenChange = useCallback(
|
|
152
|
+
(next: boolean) => {
|
|
153
|
+
if (pending) return;
|
|
154
|
+
setTypedValue(''); // reset the typed gate on every open/close
|
|
155
|
+
setOpenState(next);
|
|
156
|
+
},
|
|
157
|
+
[pending, setOpenState],
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const handleConfirm = useCallback(async () => {
|
|
161
|
+
if (pending) return;
|
|
162
|
+
setPending(true);
|
|
163
|
+
try {
|
|
164
|
+
await onConfirm();
|
|
165
|
+
setTypedValue('');
|
|
166
|
+
setOpenState(false);
|
|
167
|
+
} catch {
|
|
168
|
+
// Keep the dialog open — the caller's onConfirm surfaced the error (toast / step-up). The
|
|
169
|
+
// operator can retry or cancel. Never rethrow, never monitor here.
|
|
170
|
+
} finally {
|
|
171
|
+
setPending(false);
|
|
172
|
+
}
|
|
173
|
+
}, [pending, onConfirm, setOpenState]);
|
|
174
|
+
|
|
175
|
+
const reasonTrimmedLength = reason ? reason.value.trim().length : 0;
|
|
176
|
+
const reasonProvided = reasonTrimmedLength > 0;
|
|
177
|
+
const reasonOk = !reason
|
|
178
|
+
? true
|
|
179
|
+
: reason.required && !reasonProvided
|
|
180
|
+
? false
|
|
181
|
+
: !reasonProvided
|
|
182
|
+
? true // optional + empty is fine
|
|
183
|
+
: (reason.minLength === undefined || reasonTrimmedLength >= reason.minLength) &&
|
|
184
|
+
(reason.maxLength === undefined || reason.value.length <= reason.maxLength);
|
|
185
|
+
|
|
186
|
+
const typedOk = !typedConfirmation ? true : typedValue === typedConfirmation.phrase;
|
|
187
|
+
const confirmDisabled = pending || !reasonOk || !typedOk;
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<AlertDialog open={actualOpen} onOpenChange={handleOpenChange}>
|
|
191
|
+
{trigger ? <AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger> : null}
|
|
192
|
+
<AlertDialogContent
|
|
193
|
+
onEscapeKeyDown={(e) => {
|
|
194
|
+
if (pending) e.preventDefault();
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
197
|
+
<AlertDialogHeader>
|
|
198
|
+
<AlertDialogTitle>{title}</AlertDialogTitle>
|
|
199
|
+
<AlertDialogDescription asChild>
|
|
200
|
+
<span className="stack-3">
|
|
201
|
+
{immediateEffect ? (
|
|
202
|
+
<ConsequenceRow icon={Zap} label="Immediately">
|
|
203
|
+
{immediateEffect}
|
|
204
|
+
</ConsequenceRow>
|
|
205
|
+
) : null}
|
|
206
|
+
{delayedEffect ? (
|
|
207
|
+
<ConsequenceRow icon={Clock} label="Afterward">
|
|
208
|
+
{delayedEffect}
|
|
209
|
+
</ConsequenceRow>
|
|
210
|
+
) : null}
|
|
211
|
+
{reversibility ? (
|
|
212
|
+
<ConsequenceRow icon={RotateCcw} label="Reversibility">
|
|
213
|
+
{reversibility}
|
|
214
|
+
</ConsequenceRow>
|
|
215
|
+
) : null}
|
|
216
|
+
</span>
|
|
217
|
+
</AlertDialogDescription>
|
|
218
|
+
</AlertDialogHeader>
|
|
219
|
+
|
|
220
|
+
{reason ? (
|
|
221
|
+
<div className="stack-2">
|
|
222
|
+
<Label htmlFor={reasonId}>{reason.label ?? 'Reason'}</Label>
|
|
223
|
+
<Textarea
|
|
224
|
+
id={reasonId}
|
|
225
|
+
value={reason.value}
|
|
226
|
+
onChange={(e) => reason.onChange(e.target.value)}
|
|
227
|
+
placeholder={reason.placeholder}
|
|
228
|
+
maxLength={reason.maxLength}
|
|
229
|
+
rows={reason.rows ?? 3}
|
|
230
|
+
disabled={pending}
|
|
231
|
+
/>
|
|
232
|
+
</div>
|
|
233
|
+
) : null}
|
|
234
|
+
|
|
235
|
+
{typedConfirmation ? (
|
|
236
|
+
<div className="stack-2">
|
|
237
|
+
<Label htmlFor={typedId}>
|
|
238
|
+
{typedConfirmation.label ?? (
|
|
239
|
+
<>
|
|
240
|
+
Type <span className="font-mono">{typedConfirmation.phrase}</span> to confirm
|
|
241
|
+
</>
|
|
242
|
+
)}
|
|
243
|
+
</Label>
|
|
244
|
+
<Input
|
|
245
|
+
id={typedId}
|
|
246
|
+
value={typedValue}
|
|
247
|
+
onChange={(e) => setTypedValue(e.target.value)}
|
|
248
|
+
placeholder={typedConfirmation.phrase}
|
|
249
|
+
disabled={pending}
|
|
250
|
+
autoComplete="off"
|
|
251
|
+
/>
|
|
252
|
+
</div>
|
|
253
|
+
) : null}
|
|
254
|
+
|
|
255
|
+
<AlertDialogFooter>
|
|
256
|
+
<Button
|
|
257
|
+
variant="outline"
|
|
258
|
+
onClick={() => handleOpenChange(false)}
|
|
259
|
+
disabled={pending}
|
|
260
|
+
>
|
|
261
|
+
{cancelLabel}
|
|
262
|
+
</Button>
|
|
263
|
+
<Button
|
|
264
|
+
variant={destructive ? 'destructive' : 'default'}
|
|
265
|
+
onClick={handleConfirm}
|
|
266
|
+
disabled={confirmDisabled}
|
|
267
|
+
aria-busy={pending}
|
|
268
|
+
>
|
|
269
|
+
{pending ? <Loader2 className="mr-2 spinner-xs" aria-hidden="true" /> : null}
|
|
270
|
+
{confirmLabel}
|
|
271
|
+
</Button>
|
|
272
|
+
</AlertDialogFooter>
|
|
273
|
+
</AlertDialogContent>
|
|
274
|
+
</AlertDialog>
|
|
275
|
+
);
|
|
276
|
+
}
|
package/src/react/index.ts
CHANGED
|
@@ -41,6 +41,9 @@ export { Collapsible, CollapsibleTrigger, CollapsibleContent } from "./component
|
|
|
41
41
|
export type { SearchDropdownProps } from "./components/search-dropdown.js";
|
|
42
42
|
export { SearchDropdown } from "./components/search-dropdown.js";
|
|
43
43
|
|
|
44
|
+
export type { ConsequenceDialogProps, ConsequenceDialogReason, ConsequenceDialogTypedConfirmation } from "./components/consequence-dialog.js";
|
|
45
|
+
export { ConsequenceDialog } from "./components/consequence-dialog.js";
|
|
46
|
+
|
|
44
47
|
export type { MaxWidthOption, ScreenAdaptiveViewProps } from "./components/layout/screen-adaptive-view.js";
|
|
45
48
|
export { ScreenAdaptiveView } from "./components/layout/screen-adaptive-view.js";
|
|
46
49
|
|