@windrun-huaiin/third-ui 29.0.4 → 29.1.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.
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  export type ConfirmDialogType = 'normal' | 'danger';
3
+ export type ConfirmDialogEmphasis = 'confirm' | 'cancel';
3
4
  interface ConfirmDialogProps {
4
5
  open: boolean;
5
6
  onOpenChange: (open: boolean) => void;
@@ -8,8 +9,9 @@ interface ConfirmDialogProps {
8
9
  description: React.ReactNode;
9
10
  cancelText?: string;
10
11
  confirmText?: string;
12
+ emphasis?: ConfirmDialogEmphasis;
11
13
  onCancel?: () => void;
12
14
  onConfirm?: () => void;
13
15
  }
14
- export declare function ConfirmDialog({ open, onOpenChange, type, title, description, cancelText, confirmText, onCancel, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function ConfirmDialog({ open, onOpenChange, type, title, description, cancelText, confirmText, emphasis, onCancel, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
15
17
  export {};
@@ -24,14 +24,19 @@ const confirmTypeClassMap = {
24
24
  Icon: icons.CircleAlertIcon,
25
25
  },
26
26
  };
27
- function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', onCancel, onConfirm, }) {
27
+ function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', onCancel, onConfirm, }) {
28
28
  const typeClass = confirmTypeClassMap[type];
29
29
  const Icon = typeClass.Icon;
30
+ const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : dialogStyles.secondaryButtonClass;
31
+ const confirmButtonClass = emphasis === 'cancel' ? dialogStyles.secondaryButtonClass : typeClass.action;
30
32
  const handleCancel = () => {
31
33
  onOpenChange(false);
32
34
  onCancel === null || onCancel === void 0 ? void 0 : onCancel();
33
35
  };
34
- return (jsxRuntime.jsx(ui.AlertDialog, { open: open, onOpenChange: onOpenChange, children: jsxRuntime.jsxs(ui.AlertDialogContent, { className: utils.cn(dialogStyles.dialogContentClass, typeClass.content), overlayClassName: dialogStyles.dialogThemedOverlayClass, onOverlayClick: handleCancel, children: [jsxRuntime.jsxs("div", { className: dialogStyles.dialogHeaderClass, children: [jsxRuntime.jsx(ui.AlertDialogTitle, { asChild: true, children: jsxRuntime.jsxs("div", { className: dialogStyles.dialogTitleClass, children: [jsxRuntime.jsx("span", { className: utils.cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', typeClass.iconWrap), children: jsxRuntime.jsx(Icon, { className: utils.cn('size-5', typeClass.icon) }) }), jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title })] }) }), jsxRuntime.jsx("button", { type: "button", className: dialogStyles.closeButtonClass, onClick: handleCancel, "aria-label": "Close", children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }), jsxRuntime.jsx(ui.AlertDialogDescription, { className: dialogStyles.dialogDescriptionClass, children: description }), jsxRuntime.jsxs("div", { className: dialogStyles.dialogFooterClass, children: [jsxRuntime.jsx(ui.AlertDialogCancel, { className: dialogStyles.secondaryButtonClass, onClick: handleCancel, children: cancelText }), jsxRuntime.jsx(ui.AlertDialogAction, { className: typeClass.action, onClick: () => {
36
+ const handleClose = () => {
37
+ onOpenChange(false);
38
+ };
39
+ return (jsxRuntime.jsx(ui.AlertDialog, { open: open, onOpenChange: onOpenChange, children: jsxRuntime.jsxs(ui.AlertDialogContent, { className: utils.cn(dialogStyles.dialogContentClass, typeClass.content), overlayClassName: dialogStyles.dialogThemedOverlayClass, onOverlayClick: handleClose, children: [jsxRuntime.jsxs("div", { className: dialogStyles.dialogHeaderClass, children: [jsxRuntime.jsx(ui.AlertDialogTitle, { asChild: true, children: jsxRuntime.jsxs("div", { className: dialogStyles.dialogTitleClass, children: [jsxRuntime.jsx("span", { className: utils.cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', typeClass.iconWrap), children: jsxRuntime.jsx(Icon, { className: utils.cn('size-5', typeClass.icon) }) }), jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title })] }) }), jsxRuntime.jsx("button", { type: "button", className: dialogStyles.closeButtonClass, onClick: handleClose, "aria-label": "Close", children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }), jsxRuntime.jsx(ui.AlertDialogDescription, { className: dialogStyles.dialogDescriptionClass, children: description }), jsxRuntime.jsxs("div", { className: dialogStyles.dialogFooterClass, children: [jsxRuntime.jsx(ui.AlertDialogCancel, { className: cancelButtonClass, onClick: handleCancel, children: cancelText }), jsxRuntime.jsx(ui.AlertDialogAction, { className: confirmButtonClass, onClick: () => {
35
40
  onOpenChange(false);
36
41
  onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm();
37
42
  }, children: confirmText })] })] }) }));
@@ -4,7 +4,7 @@ import { CircleAlertIcon, CircleQuestionMarkIcon, XIcon } from '@windrun-huaiin/
4
4
  import { themeBgColor, themeIconColor } from '@windrun-huaiin/base-ui/lib';
5
5
  import { AlertDialog, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, AlertDialogCancel, AlertDialogAction } from '@windrun-huaiin/base-ui/ui';
6
6
  import { cn } from '@windrun-huaiin/lib/utils';
7
- import { dangerButtonClass, primaryButtonClass, dialogThemedOverlayClass, dialogHeaderClass, dialogTitleClass, closeButtonClass, dialogDescriptionClass, dialogFooterClass, secondaryButtonClass, dialogContentClass } from './dialog-styles.mjs';
7
+ import { dangerButtonClass, primaryButtonClass, secondaryButtonClass, dialogThemedOverlayClass, dialogHeaderClass, dialogTitleClass, closeButtonClass, dialogDescriptionClass, dialogFooterClass, dialogContentClass } from './dialog-styles.mjs';
8
8
 
9
9
  const confirmTypeClassMap = {
10
10
  normal: {
@@ -22,14 +22,19 @@ const confirmTypeClassMap = {
22
22
  Icon: CircleAlertIcon,
23
23
  },
24
24
  };
25
- function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', onCancel, onConfirm, }) {
25
+ function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', onCancel, onConfirm, }) {
26
26
  const typeClass = confirmTypeClassMap[type];
27
27
  const Icon = typeClass.Icon;
28
+ const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : secondaryButtonClass;
29
+ const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : typeClass.action;
28
30
  const handleCancel = () => {
29
31
  onOpenChange(false);
30
32
  onCancel === null || onCancel === void 0 ? void 0 : onCancel();
31
33
  };
32
- return (jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: jsxs(AlertDialogContent, { className: cn(dialogContentClass, typeClass.content), overlayClassName: dialogThemedOverlayClass, onOverlayClick: handleCancel, children: [jsxs("div", { className: dialogHeaderClass, children: [jsx(AlertDialogTitle, { asChild: true, children: jsxs("div", { className: dialogTitleClass, children: [jsx("span", { className: cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', typeClass.iconWrap), children: jsx(Icon, { className: cn('size-5', typeClass.icon) }) }), jsx("span", { className: "min-w-0 truncate", children: title })] }) }), jsx("button", { type: "button", className: closeButtonClass, onClick: handleCancel, "aria-label": "Close", children: jsx(XIcon, { className: "size-4" }) })] }), jsx(AlertDialogDescription, { className: dialogDescriptionClass, children: description }), jsxs("div", { className: dialogFooterClass, children: [jsx(AlertDialogCancel, { className: secondaryButtonClass, onClick: handleCancel, children: cancelText }), jsx(AlertDialogAction, { className: typeClass.action, onClick: () => {
34
+ const handleClose = () => {
35
+ onOpenChange(false);
36
+ };
37
+ return (jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: jsxs(AlertDialogContent, { className: cn(dialogContentClass, typeClass.content), overlayClassName: dialogThemedOverlayClass, onOverlayClick: handleClose, children: [jsxs("div", { className: dialogHeaderClass, children: [jsx(AlertDialogTitle, { asChild: true, children: jsxs("div", { className: dialogTitleClass, children: [jsx("span", { className: cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', typeClass.iconWrap), children: jsx(Icon, { className: cn('size-5', typeClass.icon) }) }), jsx("span", { className: "min-w-0 truncate", children: title })] }) }), jsx("button", { type: "button", className: closeButtonClass, onClick: handleClose, "aria-label": "Close", children: jsx(XIcon, { className: "size-4" }) })] }), jsx(AlertDialogDescription, { className: dialogDescriptionClass, children: description }), jsxs("div", { className: dialogFooterClass, children: [jsx(AlertDialogCancel, { className: cancelButtonClass, onClick: handleCancel, children: cancelText }), jsx(AlertDialogAction, { className: confirmButtonClass, onClick: () => {
33
38
  onOpenChange(false);
34
39
  onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm();
35
40
  }, children: confirmText })] })] }) }));
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  interface HighPriorityConfirmDialogProps {
3
3
  open: boolean;
4
+ onOpenChange: (open: boolean) => void;
4
5
  onCancel: () => void;
5
6
  onConfirm: () => void;
6
7
  title: string;
@@ -8,5 +9,5 @@ interface HighPriorityConfirmDialogProps {
8
9
  confirmText?: string;
9
10
  cancelText?: string;
10
11
  }
11
- export declare function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, description, confirmText, cancelText, }: HighPriorityConfirmDialogProps): React.ReactPortal | null;
12
+ export declare function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText, cancelText, }: HighPriorityConfirmDialogProps): React.ReactPortal | null;
12
13
  export {};
@@ -9,7 +9,7 @@ var utils = require('@windrun-huaiin/lib/utils');
9
9
  var dialogStyles = require('./dialog-styles.js');
10
10
  var lib = require('@windrun-huaiin/base-ui/lib');
11
11
 
12
- function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", }) {
12
+ function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", }) {
13
13
  const [mounted, setMounted] = React.useState(false);
14
14
  React.useEffect(() => {
15
15
  // Ensure portal target exists and prevent hydration mismatch
@@ -17,7 +17,10 @@ function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, descripti
17
17
  }, []);
18
18
  if (!open || !mounted)
19
19
  return null;
20
- return reactDom.createPortal(jsxRuntime.jsx("div", { className: "fixed inset-0 z-10000 flex items-center justify-center bg-black/60 backdrop-blur-sm animate-in fade-in duration-300", children: jsxRuntime.jsxs("div", { className: utils.cn(dialogStyles.highPrioritySurfaceClass, "scale-100"), role: "dialog", "aria-modal": "true", onClick: (e) => e.stopPropagation(), children: [jsxRuntime.jsxs("div", { className: dialogStyles.dialogHeaderClass, children: [jsxRuntime.jsxs("h3", { className: dialogStyles.highPriorityTitleClass, children: [jsxRuntime.jsx("span", { className: utils.cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', lib.themeBgColor, lib.themeBorderColor), children: jsxRuntime.jsx(icons.FAQSIcon, { className: utils.cn('size-5', lib.themeIconColor) }) }), jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title })] }), jsxRuntime.jsx("button", { type: "button", className: dialogStyles.closeButtonClass, onClick: onCancel, "aria-label": "Close", children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }), jsxRuntime.jsx("div", { className: dialogStyles.dialogDescriptionClass, children: description }), jsxRuntime.jsxs("div", { className: dialogStyles.dialogFooterClass, children: [jsxRuntime.jsx("button", { type: "button", onClick: onCancel, className: dialogStyles.secondaryButtonClass, children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: onConfirm, className: utils.cn(dialogStyles.primaryButtonClass, "hover:scale-105 active:scale-95"), children: confirmText })] })] }) }), document.body);
20
+ const handleClose = () => {
21
+ onOpenChange(false);
22
+ };
23
+ return reactDom.createPortal(jsxRuntime.jsx("div", { className: "fixed inset-0 z-10000 flex items-center justify-center bg-black/60 backdrop-blur-sm animate-in fade-in duration-300", children: jsxRuntime.jsxs("div", { className: utils.cn(dialogStyles.highPrioritySurfaceClass, "scale-100"), role: "dialog", "aria-modal": "true", onClick: (e) => e.stopPropagation(), children: [jsxRuntime.jsxs("div", { className: dialogStyles.dialogHeaderClass, children: [jsxRuntime.jsxs("h3", { className: dialogStyles.highPriorityTitleClass, children: [jsxRuntime.jsx("span", { className: utils.cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', lib.themeBgColor, lib.themeBorderColor), children: jsxRuntime.jsx(icons.FAQSIcon, { className: utils.cn('size-5', lib.themeIconColor) }) }), jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title })] }), jsxRuntime.jsx("button", { type: "button", className: dialogStyles.closeButtonClass, onClick: handleClose, "aria-label": "Close", children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }), jsxRuntime.jsx("div", { className: dialogStyles.dialogDescriptionClass, children: description }), jsxRuntime.jsxs("div", { className: dialogStyles.dialogFooterClass, children: [jsxRuntime.jsx("button", { type: "button", onClick: onCancel, className: dialogStyles.secondaryButtonClass, children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: onConfirm, className: utils.cn(dialogStyles.primaryButtonClass, "hover:scale-105 active:scale-95"), children: confirmText })] })] }) }), document.body);
21
24
  }
22
25
 
23
26
  exports.HighPriorityConfirmDialog = HighPriorityConfirmDialog;
@@ -7,7 +7,7 @@ import { cn } from '@windrun-huaiin/lib/utils';
7
7
  import { dialogHeaderClass, highPriorityTitleClass, closeButtonClass, dialogDescriptionClass, dialogFooterClass, secondaryButtonClass, primaryButtonClass, highPrioritySurfaceClass } from './dialog-styles.mjs';
8
8
  import { themeIconColor, themeBgColor, themeBorderColor } from '@windrun-huaiin/base-ui/lib';
9
9
 
10
- function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", }) {
10
+ function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", }) {
11
11
  const [mounted, setMounted] = useState(false);
12
12
  useEffect(() => {
13
13
  // Ensure portal target exists and prevent hydration mismatch
@@ -15,7 +15,10 @@ function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, descripti
15
15
  }, []);
16
16
  if (!open || !mounted)
17
17
  return null;
18
- return createPortal(jsx("div", { className: "fixed inset-0 z-10000 flex items-center justify-center bg-black/60 backdrop-blur-sm animate-in fade-in duration-300", children: jsxs("div", { className: cn(highPrioritySurfaceClass, "scale-100"), role: "dialog", "aria-modal": "true", onClick: (e) => e.stopPropagation(), children: [jsxs("div", { className: dialogHeaderClass, children: [jsxs("h3", { className: highPriorityTitleClass, children: [jsx("span", { className: cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', themeBgColor, themeBorderColor), children: jsx(FAQSIcon, { className: cn('size-5', themeIconColor) }) }), jsx("span", { className: "min-w-0 truncate", children: title })] }), jsx("button", { type: "button", className: closeButtonClass, onClick: onCancel, "aria-label": "Close", children: jsx(XIcon, { className: "size-4" }) })] }), jsx("div", { className: dialogDescriptionClass, children: description }), jsxs("div", { className: dialogFooterClass, children: [jsx("button", { type: "button", onClick: onCancel, className: secondaryButtonClass, children: cancelText }), jsx("button", { type: "button", onClick: onConfirm, className: cn(primaryButtonClass, "hover:scale-105 active:scale-95"), children: confirmText })] })] }) }), document.body);
18
+ const handleClose = () => {
19
+ onOpenChange(false);
20
+ };
21
+ return createPortal(jsx("div", { className: "fixed inset-0 z-10000 flex items-center justify-center bg-black/60 backdrop-blur-sm animate-in fade-in duration-300", children: jsxs("div", { className: cn(highPrioritySurfaceClass, "scale-100"), role: "dialog", "aria-modal": "true", onClick: (e) => e.stopPropagation(), children: [jsxs("div", { className: dialogHeaderClass, children: [jsxs("h3", { className: highPriorityTitleClass, children: [jsx("span", { className: cn('inline-flex size-9 shrink-0 items-center justify-center rounded-full ring-1', themeBgColor, themeBorderColor), children: jsx(FAQSIcon, { className: cn('size-5', themeIconColor) }) }), jsx("span", { className: "min-w-0 truncate", children: title })] }), jsx("button", { type: "button", className: closeButtonClass, onClick: handleClose, "aria-label": "Close", children: jsx(XIcon, { className: "size-4" }) })] }), jsx("div", { className: dialogDescriptionClass, children: description }), jsxs("div", { className: dialogFooterClass, children: [jsx("button", { type: "button", onClick: onCancel, className: secondaryButtonClass, children: cancelText }), jsx("button", { type: "button", onClick: onConfirm, className: cn(primaryButtonClass, "hover:scale-105 active:scale-95"), children: confirmText })] })] }) }), document.body);
19
22
  }
20
23
 
21
24
  export { HighPriorityConfirmDialog };
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { ConfirmDialogEmphasis } from './confirm-dialog';
2
3
  export interface UndoableConfirmDialogProps {
3
4
  open: boolean;
4
5
  onOpenChange: (open: boolean) => void;
@@ -9,9 +10,10 @@ export interface UndoableConfirmDialogProps {
9
10
  cancelText?: string;
10
11
  confirmText?: string;
11
12
  undoText?: string;
13
+ emphasis?: ConfirmDialogEmphasis;
12
14
  countdownSeconds?: number;
13
15
  onCancel?: () => void;
14
16
  onConfirm: () => void | Promise<void>;
15
17
  onUndo?: () => void;
16
18
  }
17
- export declare function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText, confirmText, undoText, countdownSeconds, onCancel, onConfirm, onUndo, }: UndoableConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText, confirmText, undoText, emphasis, countdownSeconds, onCancel, onConfirm, onUndo, }: UndoableConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -10,13 +10,15 @@ var ui = require('@windrun-huaiin/base-ui/ui');
10
10
  var utils = require('@windrun-huaiin/lib/utils');
11
11
  var dialogStyles = require('./dialog-styles.js');
12
12
 
13
- function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', countdownSeconds = 5, onCancel, onConfirm, onUndo, }) {
13
+ function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, onCancel, onConfirm, onUndo, }) {
14
14
  const safeCountdownSeconds = Math.max(1, Math.floor(countdownSeconds));
15
15
  const [pending, setPending] = React.useState(false);
16
16
  const [remainingSeconds, setRemainingSeconds] = React.useState(safeCountdownSeconds);
17
17
  const [confirming, setConfirming] = React.useState(false);
18
18
  const timeoutRef = React.useRef(null);
19
19
  const intervalRef = React.useRef(null);
20
+ const cancelButtonClass = emphasis === 'cancel' ? dialogStyles.dangerButtonClass : dialogStyles.secondaryButtonClass;
21
+ const confirmButtonClass = emphasis === 'cancel' ? dialogStyles.secondaryButtonClass : dialogStyles.dangerButtonClass;
20
22
  const clearTimers = React.useCallback(() => {
21
23
  if (timeoutRef.current) {
22
24
  window.clearTimeout(timeoutRef.current);
@@ -68,6 +70,10 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
68
70
  onOpenChange(false);
69
71
  onCancel === null || onCancel === void 0 ? void 0 : onCancel();
70
72
  };
73
+ const handleClose = React.useCallback(() => {
74
+ resetState();
75
+ onOpenChange(false);
76
+ }, [onOpenChange, resetState]);
71
77
  const handleUndo = () => {
72
78
  resetState();
73
79
  onOpenChange(false);
@@ -77,11 +83,11 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
77
83
  const displayDescription = pending ? pendingDescription !== null && pendingDescription !== void 0 ? pendingDescription : description : description;
78
84
  return (jsxRuntime.jsx(ui.AlertDialog, { open: open, onOpenChange: (nextOpen) => {
79
85
  if (!nextOpen) {
80
- handleCancel();
86
+ handleClose();
81
87
  return;
82
88
  }
83
89
  onOpenChange(nextOpen);
84
- }, children: jsxRuntime.jsxs(ui.AlertDialogContent, { className: utils.cn(dialogStyles.dialogContentClass, 'border-red-300 dark:border-red-700'), overlayClassName: dialogStyles.dialogThemedOverlayClass, onOverlayClick: pending ? undefined : handleCancel, children: [jsxRuntime.jsxs("div", { className: dialogStyles.dialogHeaderClass, children: [jsxRuntime.jsx(ui.AlertDialogTitle, { asChild: true, children: jsxRuntime.jsxs("div", { className: dialogStyles.dialogTitleClass, children: [jsxRuntime.jsx("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-full bg-red-100 text-red-600 ring-1 ring-red-200 dark:bg-red-950 dark:text-red-300 dark:ring-red-900", children: pending ? jsxRuntime.jsx(icons.Trash2Icon, { className: "size-5" }) : jsxRuntime.jsx(icons.CircleAlertIcon, { className: "size-5" }) }), jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: displayTitle })] }) }), jsxRuntime.jsx("button", { type: "button", className: dialogStyles.closeButtonClass, onClick: pending ? handleUndo : handleCancel, "aria-label": "Close", disabled: confirming, children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }), jsxRuntime.jsx(ui.AlertDialogDescription, { className: utils.cn(dialogStyles.dialogDescriptionClass, 'min-h-[44px]'), children: jsxRuntime.jsx("span", { children: displayDescription }) }), jsxRuntime.jsx("div", { className: "flex h-12 items-center justify-center py-1", children: jsxRuntime.jsxs("div", { className: "flex items-baseline justify-center gap-2", children: [jsxRuntime.jsx("span", { className: utils.cn('text-4xl font-black leading-none tabular-nums', pending && 'animate-bounce', lib.themeIconColor), children: pending ? remainingSeconds : safeCountdownSeconds }), jsxRuntime.jsx("span", { className: utils.cn('text-sm font-bold', lib.themeIconColor), children: "s" })] }) }), jsxRuntime.jsx("div", { className: utils.cn(dialogStyles.dialogFooterClass, 'min-h-[88px] sm:min-h-10 sm:items-center'), children: pending ? (jsxRuntime.jsxs("button", { type: "button", onClick: handleUndo, className: dialogStyles.secondaryButtonClass, disabled: confirming, children: [jsxRuntime.jsx(icons.Undo2Icon, { className: "mr-1.5 size-4" }), undoText] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: handleCancel, className: dialogStyles.secondaryButtonClass, children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: startCountdown, className: dialogStyles.dangerButtonClass, children: confirmText })] })) })] }) }));
90
+ }, children: jsxRuntime.jsxs(ui.AlertDialogContent, { className: utils.cn(dialogStyles.dialogContentClass, 'border-red-300 dark:border-red-700'), overlayClassName: dialogStyles.dialogThemedOverlayClass, onOverlayClick: pending ? undefined : handleClose, children: [jsxRuntime.jsxs("div", { className: dialogStyles.dialogHeaderClass, children: [jsxRuntime.jsx(ui.AlertDialogTitle, { asChild: true, children: jsxRuntime.jsxs("div", { className: dialogStyles.dialogTitleClass, children: [jsxRuntime.jsx("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-full bg-red-100 text-red-600 ring-1 ring-red-200 dark:bg-red-950 dark:text-red-300 dark:ring-red-900", children: pending ? jsxRuntime.jsx(icons.Trash2Icon, { className: "size-5" }) : jsxRuntime.jsx(icons.CircleAlertIcon, { className: "size-5" }) }), jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: displayTitle })] }) }), jsxRuntime.jsx("button", { type: "button", className: dialogStyles.closeButtonClass, onClick: handleClose, "aria-label": "Close", disabled: confirming, children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }), jsxRuntime.jsx(ui.AlertDialogDescription, { className: utils.cn(dialogStyles.dialogDescriptionClass, 'min-h-[44px]'), children: jsxRuntime.jsx("span", { children: displayDescription }) }), jsxRuntime.jsx("div", { className: "flex h-12 items-center justify-center py-1", children: jsxRuntime.jsxs("div", { className: "flex items-baseline justify-center gap-2", children: [jsxRuntime.jsx("span", { className: utils.cn('text-4xl font-black leading-none tabular-nums', pending && 'animate-bounce', lib.themeIconColor), children: pending ? remainingSeconds : safeCountdownSeconds }), jsxRuntime.jsx("span", { className: utils.cn('text-sm font-bold', lib.themeIconColor), children: "s" })] }) }), jsxRuntime.jsx("div", { className: utils.cn(dialogStyles.dialogFooterClass, 'min-h-[88px] sm:min-h-10 sm:items-center'), children: pending ? (jsxRuntime.jsxs("button", { type: "button", onClick: handleUndo, className: dialogStyles.secondaryButtonClass, disabled: confirming, children: [jsxRuntime.jsx(icons.Undo2Icon, { className: "mr-1.5 size-4" }), undoText] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: handleCancel, className: cancelButtonClass, children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: startCountdown, className: confirmButtonClass, children: confirmText })] })) })] }) }));
85
91
  }
86
92
 
87
93
  exports.UndoableConfirmDialog = UndoableConfirmDialog;
@@ -8,13 +8,15 @@ import { AlertDialog, AlertDialogContent, AlertDialogTitle, AlertDialogDescripti
8
8
  import { cn } from '@windrun-huaiin/lib/utils';
9
9
  import { dialogThemedOverlayClass, dialogHeaderClass, dialogTitleClass, closeButtonClass, dialogDescriptionClass, secondaryButtonClass, dangerButtonClass, dialogFooterClass, dialogContentClass } from './dialog-styles.mjs';
10
10
 
11
- function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', countdownSeconds = 5, onCancel, onConfirm, onUndo, }) {
11
+ function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, onCancel, onConfirm, onUndo, }) {
12
12
  const safeCountdownSeconds = Math.max(1, Math.floor(countdownSeconds));
13
13
  const [pending, setPending] = React__default.useState(false);
14
14
  const [remainingSeconds, setRemainingSeconds] = React__default.useState(safeCountdownSeconds);
15
15
  const [confirming, setConfirming] = React__default.useState(false);
16
16
  const timeoutRef = React__default.useRef(null);
17
17
  const intervalRef = React__default.useRef(null);
18
+ const cancelButtonClass = emphasis === 'cancel' ? dangerButtonClass : secondaryButtonClass;
19
+ const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : dangerButtonClass;
18
20
  const clearTimers = React__default.useCallback(() => {
19
21
  if (timeoutRef.current) {
20
22
  window.clearTimeout(timeoutRef.current);
@@ -66,6 +68,10 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
66
68
  onOpenChange(false);
67
69
  onCancel === null || onCancel === void 0 ? void 0 : onCancel();
68
70
  };
71
+ const handleClose = React__default.useCallback(() => {
72
+ resetState();
73
+ onOpenChange(false);
74
+ }, [onOpenChange, resetState]);
69
75
  const handleUndo = () => {
70
76
  resetState();
71
77
  onOpenChange(false);
@@ -75,11 +81,11 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
75
81
  const displayDescription = pending ? pendingDescription !== null && pendingDescription !== void 0 ? pendingDescription : description : description;
76
82
  return (jsx(AlertDialog, { open: open, onOpenChange: (nextOpen) => {
77
83
  if (!nextOpen) {
78
- handleCancel();
84
+ handleClose();
79
85
  return;
80
86
  }
81
87
  onOpenChange(nextOpen);
82
- }, children: jsxs(AlertDialogContent, { className: cn(dialogContentClass, 'border-red-300 dark:border-red-700'), overlayClassName: dialogThemedOverlayClass, onOverlayClick: pending ? undefined : handleCancel, children: [jsxs("div", { className: dialogHeaderClass, children: [jsx(AlertDialogTitle, { asChild: true, children: jsxs("div", { className: dialogTitleClass, children: [jsx("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-full bg-red-100 text-red-600 ring-1 ring-red-200 dark:bg-red-950 dark:text-red-300 dark:ring-red-900", children: pending ? jsx(Trash2Icon, { className: "size-5" }) : jsx(CircleAlertIcon, { className: "size-5" }) }), jsx("span", { className: "min-w-0 truncate", children: displayTitle })] }) }), jsx("button", { type: "button", className: closeButtonClass, onClick: pending ? handleUndo : handleCancel, "aria-label": "Close", disabled: confirming, children: jsx(XIcon, { className: "size-4" }) })] }), jsx(AlertDialogDescription, { className: cn(dialogDescriptionClass, 'min-h-[44px]'), children: jsx("span", { children: displayDescription }) }), jsx("div", { className: "flex h-12 items-center justify-center py-1", children: jsxs("div", { className: "flex items-baseline justify-center gap-2", children: [jsx("span", { className: cn('text-4xl font-black leading-none tabular-nums', pending && 'animate-bounce', themeIconColor), children: pending ? remainingSeconds : safeCountdownSeconds }), jsx("span", { className: cn('text-sm font-bold', themeIconColor), children: "s" })] }) }), jsx("div", { className: cn(dialogFooterClass, 'min-h-[88px] sm:min-h-10 sm:items-center'), children: pending ? (jsxs("button", { type: "button", onClick: handleUndo, className: secondaryButtonClass, disabled: confirming, children: [jsx(Undo2Icon, { className: "mr-1.5 size-4" }), undoText] })) : (jsxs(Fragment, { children: [jsx("button", { type: "button", onClick: handleCancel, className: secondaryButtonClass, children: cancelText }), jsx("button", { type: "button", onClick: startCountdown, className: dangerButtonClass, children: confirmText })] })) })] }) }));
88
+ }, children: jsxs(AlertDialogContent, { className: cn(dialogContentClass, 'border-red-300 dark:border-red-700'), overlayClassName: dialogThemedOverlayClass, onOverlayClick: pending ? undefined : handleClose, children: [jsxs("div", { className: dialogHeaderClass, children: [jsx(AlertDialogTitle, { asChild: true, children: jsxs("div", { className: dialogTitleClass, children: [jsx("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-full bg-red-100 text-red-600 ring-1 ring-red-200 dark:bg-red-950 dark:text-red-300 dark:ring-red-900", children: pending ? jsx(Trash2Icon, { className: "size-5" }) : jsx(CircleAlertIcon, { className: "size-5" }) }), jsx("span", { className: "min-w-0 truncate", children: displayTitle })] }) }), jsx("button", { type: "button", className: closeButtonClass, onClick: handleClose, "aria-label": "Close", disabled: confirming, children: jsx(XIcon, { className: "size-4" }) })] }), jsx(AlertDialogDescription, { className: cn(dialogDescriptionClass, 'min-h-[44px]'), children: jsx("span", { children: displayDescription }) }), jsx("div", { className: "flex h-12 items-center justify-center py-1", children: jsxs("div", { className: "flex items-baseline justify-center gap-2", children: [jsx("span", { className: cn('text-4xl font-black leading-none tabular-nums', pending && 'animate-bounce', themeIconColor), children: pending ? remainingSeconds : safeCountdownSeconds }), jsx("span", { className: cn('text-sm font-bold', themeIconColor), children: "s" })] }) }), jsx("div", { className: cn(dialogFooterClass, 'min-h-[88px] sm:min-h-10 sm:items-center'), children: pending ? (jsxs("button", { type: "button", onClick: handleUndo, className: secondaryButtonClass, disabled: confirming, children: [jsx(Undo2Icon, { className: "mr-1.5 size-4" }), undoText] })) : (jsxs(Fragment, { children: [jsx("button", { type: "button", onClick: handleCancel, className: cancelButtonClass, children: cancelText }), jsx("button", { type: "button", onClick: startCountdown, className: confirmButtonClass, children: confirmText })] })) })] }) }));
83
89
  }
84
90
 
85
91
  export { UndoableConfirmDialog };
@@ -3,7 +3,7 @@
3
3
  var tslib = require('tslib');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var server = require('next-intl/server');
6
- var server$1 = require('@windrun-huaiin/base-ui/components/server');
6
+ var shared = require('@windrun-huaiin/base-ui/components/shared');
7
7
  var lib = require('@windrun-huaiin/base-ui/lib');
8
8
  var utils = require('@windrun-huaiin/lib/utils');
9
9
  var richTextExpert = require('./rich-text-expert.js');
@@ -26,7 +26,7 @@ function Features(_a) {
26
26
  }))
27
27
  };
28
28
  return (jsxRuntime.jsxs("section", { id: "features", className: utils.cn(sectionLayout.responsiveSection, sectionClassName), children: [jsxRuntime.jsxs("h2", { className: "text-3xl md:text-4xl font-bold text-center mb-4", children: [data.title, " ", jsxRuntime.jsx("span", { className: lib.themeIconColor, children: data.eyesOn })] }), jsxRuntime.jsx("p", { className: "text-center text-gray-600 dark:text-gray-400 mb-12 text-base sm:text-lg mx-auto max-w-3xl", children: data.description }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-8 gap-y-12", children: data.items.map((feature) => {
29
- const Icon = server$1.getGlobalIcon(feature.iconKey);
29
+ const Icon = shared.getGlobalIcon(feature.iconKey);
30
30
  return (jsxRuntime.jsxs("div", { "data-feature-id": feature.id, className: utils.cn("bg-white dark:bg-gray-800/60 p-8 rounded-xl border border-gray-200 dark:border-gray-700 hover:border-current transition shadow-sm dark:shadow-none", lib.themeIconColor), children: [jsxRuntime.jsx("div", { className: "text-4xl mb-4 flex items-center justify-start", children: jsxRuntime.jsx(Icon, { className: "w-8 h-8" }) }), jsxRuntime.jsx("h3", { className: "text-xl font-semibold mb-3 text-gray-900 dark:text-gray-100", children: feature.title }), jsxRuntime.jsx("p", { className: "text-gray-700 dark:text-gray-300", children: feature.description })] }, feature.id));
31
31
  }) })] }));
32
32
  });
@@ -1,7 +1,7 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { getTranslations } from 'next-intl/server';
4
- import { getGlobalIcon } from '@windrun-huaiin/base-ui/components/server';
4
+ import { getGlobalIcon } from '@windrun-huaiin/base-ui/components/shared';
5
5
  import { themeIconColor } from '@windrun-huaiin/base-ui/lib';
6
6
  import { cn } from '@windrun-huaiin/lib/utils';
7
7
  import { richText } from './rich-text-expert.mjs';
@@ -4,7 +4,7 @@ var tslib = require('tslib');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var server = require('next-intl/server');
6
6
  var utils = require('@windrun-huaiin/lib/utils');
7
- var server$1 = require('@windrun-huaiin/base-ui/components/server');
7
+ var shared = require('@windrun-huaiin/base-ui/components/shared');
8
8
  var lib = require('@windrun-huaiin/base-ui/lib');
9
9
  var richTextExpert = require('./rich-text-expert.js');
10
10
  var sectionLayout = require('./section-layout.js');
@@ -27,7 +27,7 @@ function Usage(_a) {
27
27
  }))
28
28
  };
29
29
  return (jsxRuntime.jsxs("section", { id: "usage", className: utils.cn(sectionLayout.responsiveSection, sectionClassName), children: [jsxRuntime.jsxs("h2", { className: "text-3xl md:text-4xl font-bold text-center mb-4", children: [data.title, " ", jsxRuntime.jsx("span", { className: lib.themeIconColor, children: data.eyesOn })] }), jsxRuntime.jsx("p", { className: "text-center text-gray-600 dark:text-gray-400 mb-12 text-base sm:text-lg mx-auto max-w-3xl", children: data.description }), jsxRuntime.jsx("div", { className: "bg-gray-50 dark:bg-gray-800/60 border border-gray-200 dark:border-gray-700 rounded-2xl p-8 md:p-12 shadow-sm dark:shadow-none", children: jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-8 gap-y-12", children: data.steps.map((step) => {
30
- const Icon = server$1.getGlobalIcon(step.iconKey);
30
+ const Icon = shared.getGlobalIcon(step.iconKey);
31
31
  return (jsxRuntime.jsxs("div", { "data-usage-step": step.id, className: "flex items-start", children: [jsxRuntime.jsx("div", { className: "shrink-0 mr-4", children: jsxRuntime.jsx(Icon, { className: "w-8 h-8" }) }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("h3", { className: "text-xl font-semibold mb-3 text-gray-900 dark:text-gray-100 flex items-center", children: `${step.stepNumber}. ${step.title}` }), jsxRuntime.jsx("p", { className: "text-gray-700 dark:text-gray-300", children: step.description })] })] }, step.id));
32
32
  }) }) })] }));
33
33
  });
@@ -2,7 +2,7 @@ import { __awaiter } from 'tslib';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { getTranslations } from 'next-intl/server';
4
4
  import { cn } from '@windrun-huaiin/lib/utils';
5
- import { getGlobalIcon } from '@windrun-huaiin/base-ui/components/server';
5
+ import { getGlobalIcon } from '@windrun-huaiin/base-ui/components/shared';
6
6
  import { themeIconColor } from '@windrun-huaiin/base-ui/lib';
7
7
  import { richText } from './rich-text-expert.mjs';
8
8
  import { responsiveSection } from './section-layout.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windrun-huaiin/third-ui",
3
- "version": "29.0.4",
3
+ "version": "29.1.0",
4
4
  "description": "Third-party integrated UI components for windrun-huaiin projects",
5
5
  "exports": {
6
6
  "./clerk": {
@@ -227,7 +227,7 @@
227
227
  "tslib": "^2.8.1",
228
228
  "unified": "^11.0.5",
229
229
  "zod": "^4.3.6",
230
- "@windrun-huaiin/base-ui": "^29.0.1",
230
+ "@windrun-huaiin/base-ui": "^29.0.2",
231
231
  "@windrun-huaiin/contracts": "^29.0.0",
232
232
  "@windrun-huaiin/lib": "^29.0.0"
233
233
  },
@@ -26,6 +26,7 @@ import {
26
26
  } from './dialog-styles';
27
27
 
28
28
  export type ConfirmDialogType = 'normal' | 'danger';
29
+ export type ConfirmDialogEmphasis = 'confirm' | 'cancel';
29
30
 
30
31
  interface ConfirmDialogProps {
31
32
  open: boolean;
@@ -35,6 +36,7 @@ interface ConfirmDialogProps {
35
36
  description: React.ReactNode;
36
37
  cancelText?: string;
37
38
  confirmText?: string;
39
+ emphasis?: ConfirmDialogEmphasis;
38
40
  onCancel?: () => void;
39
41
  onConfirm?: () => void;
40
42
  }
@@ -70,23 +72,29 @@ export function ConfirmDialog({
70
72
  description,
71
73
  cancelText = 'Cancel',
72
74
  confirmText = 'Confirm',
75
+ emphasis = 'confirm',
73
76
  onCancel,
74
77
  onConfirm,
75
78
  }: ConfirmDialogProps) {
76
79
  const typeClass = confirmTypeClassMap[type];
77
80
  const Icon = typeClass.Icon;
81
+ const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : secondaryButtonClass;
82
+ const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : typeClass.action;
78
83
 
79
84
  const handleCancel = () => {
80
85
  onOpenChange(false);
81
86
  onCancel?.();
82
87
  };
88
+ const handleClose = () => {
89
+ onOpenChange(false);
90
+ };
83
91
 
84
92
  return (
85
93
  <AlertDialog open={open} onOpenChange={onOpenChange}>
86
94
  <AlertDialogContent
87
95
  className={cn(dialogContentClass, typeClass.content)}
88
96
  overlayClassName={dialogThemedOverlayClass}
89
- onOverlayClick={handleCancel}
97
+ onOverlayClick={handleClose}
90
98
  >
91
99
  <div className={dialogHeaderClass}>
92
100
  <AlertDialogTitle asChild>
@@ -100,7 +108,7 @@ export function ConfirmDialog({
100
108
  <button
101
109
  type="button"
102
110
  className={closeButtonClass}
103
- onClick={handleCancel}
111
+ onClick={handleClose}
104
112
  aria-label="Close"
105
113
  >
106
114
  <XIcon className="size-4" />
@@ -112,11 +120,11 @@ export function ConfirmDialog({
112
120
  </AlertDialogDescription>
113
121
 
114
122
  <div className={dialogFooterClass}>
115
- <AlertDialogCancel className={secondaryButtonClass} onClick={handleCancel}>
123
+ <AlertDialogCancel className={cancelButtonClass} onClick={handleCancel}>
116
124
  {cancelText}
117
125
  </AlertDialogCancel>
118
126
  <AlertDialogAction
119
- className={typeClass.action}
127
+ className={confirmButtonClass}
120
128
  onClick={() => {
121
129
  onOpenChange(false);
122
130
  onConfirm?.();
@@ -18,6 +18,7 @@ import { themeBgColor, themeBorderColor, themeIconColor } from "@windrun-huaiin/
18
18
 
19
19
  interface HighPriorityConfirmDialogProps {
20
20
  open: boolean;
21
+ onOpenChange: (open: boolean) => void;
21
22
  onCancel: () => void;
22
23
  onConfirm: () => void;
23
24
  title: string;
@@ -28,6 +29,7 @@ interface HighPriorityConfirmDialogProps {
28
29
 
29
30
  export function HighPriorityConfirmDialog({
30
31
  open,
32
+ onOpenChange,
31
33
  onCancel,
32
34
  onConfirm,
33
35
  title,
@@ -44,6 +46,10 @@ export function HighPriorityConfirmDialog({
44
46
 
45
47
  if (!open || !mounted) return null;
46
48
 
49
+ const handleClose = () => {
50
+ onOpenChange(false);
51
+ };
52
+
47
53
  return createPortal(
48
54
  <div className="fixed inset-0 z-10000 flex items-center justify-center bg-black/60 backdrop-blur-sm animate-in fade-in duration-300">
49
55
  <div
@@ -62,7 +68,7 @@ export function HighPriorityConfirmDialog({
62
68
  <button
63
69
  type="button"
64
70
  className={closeButtonClass}
65
- onClick={onCancel}
71
+ onClick={handleClose}
66
72
  aria-label="Close"
67
73
  >
68
74
  <XIcon className="size-4" />
@@ -21,6 +21,7 @@ import {
21
21
  dialogTitleClass,
22
22
  secondaryButtonClass,
23
23
  } from './dialog-styles';
24
+ import type { ConfirmDialogEmphasis } from './confirm-dialog';
24
25
 
25
26
  export interface UndoableConfirmDialogProps {
26
27
  open: boolean;
@@ -32,6 +33,7 @@ export interface UndoableConfirmDialogProps {
32
33
  cancelText?: string;
33
34
  confirmText?: string;
34
35
  undoText?: string;
36
+ emphasis?: ConfirmDialogEmphasis;
35
37
  countdownSeconds?: number;
36
38
  onCancel?: () => void;
37
39
  onConfirm: () => void | Promise<void>;
@@ -48,6 +50,7 @@ export function UndoableConfirmDialog({
48
50
  cancelText = 'Cancel',
49
51
  confirmText = 'Delete',
50
52
  undoText = 'Undo',
53
+ emphasis = 'confirm',
51
54
  countdownSeconds = 5,
52
55
  onCancel,
53
56
  onConfirm,
@@ -59,6 +62,8 @@ export function UndoableConfirmDialog({
59
62
  const [confirming, setConfirming] = React.useState(false);
60
63
  const timeoutRef = React.useRef<number | null>(null);
61
64
  const intervalRef = React.useRef<number | null>(null);
65
+ const cancelButtonClass = emphasis === 'cancel' ? dangerButtonClass : secondaryButtonClass;
66
+ const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : dangerButtonClass;
62
67
 
63
68
  const clearTimers = React.useCallback(() => {
64
69
  if (timeoutRef.current) {
@@ -121,6 +126,10 @@ export function UndoableConfirmDialog({
121
126
  onOpenChange(false);
122
127
  onCancel?.();
123
128
  };
129
+ const handleClose = React.useCallback(() => {
130
+ resetState();
131
+ onOpenChange(false);
132
+ }, [onOpenChange, resetState]);
124
133
 
125
134
  const handleUndo = () => {
126
135
  resetState();
@@ -133,7 +142,7 @@ export function UndoableConfirmDialog({
133
142
  return (
134
143
  <AlertDialog open={open} onOpenChange={(nextOpen) => {
135
144
  if (!nextOpen) {
136
- handleCancel();
145
+ handleClose();
137
146
  return;
138
147
  }
139
148
 
@@ -142,7 +151,7 @@ export function UndoableConfirmDialog({
142
151
  <AlertDialogContent
143
152
  className={cn(dialogContentClass, 'border-red-300 dark:border-red-700')}
144
153
  overlayClassName={dialogThemedOverlayClass}
145
- onOverlayClick={pending ? undefined : handleCancel}
154
+ onOverlayClick={pending ? undefined : handleClose}
146
155
  >
147
156
  <div className={dialogHeaderClass}>
148
157
  <AlertDialogTitle asChild>
@@ -156,7 +165,7 @@ export function UndoableConfirmDialog({
156
165
  <button
157
166
  type="button"
158
167
  className={closeButtonClass}
159
- onClick={pending ? handleUndo : handleCancel}
168
+ onClick={handleClose}
160
169
  aria-label="Close"
161
170
  disabled={confirming}
162
171
  >
@@ -195,14 +204,14 @@ export function UndoableConfirmDialog({
195
204
  <button
196
205
  type="button"
197
206
  onClick={handleCancel}
198
- className={secondaryButtonClass}
207
+ className={cancelButtonClass}
199
208
  >
200
209
  {cancelText}
201
210
  </button>
202
211
  <button
203
212
  type="button"
204
213
  onClick={startCountdown}
205
- className={dangerButtonClass}
214
+ className={confirmButtonClass}
206
215
  >
207
216
  {confirmText}
208
217
  </button>
@@ -1,5 +1,5 @@
1
1
  import { getTranslations } from 'next-intl/server';
2
- import { getGlobalIcon } from '@windrun-huaiin/base-ui/components/server';
2
+ import { getGlobalIcon } from '@windrun-huaiin/base-ui/components/shared';
3
3
  import type { globalLucideIcons } from '@windrun-huaiin/base-ui/icons';
4
4
  import { themeIconColor } from '@windrun-huaiin/base-ui/lib';
5
5
  import { cn } from '@windrun-huaiin/lib/utils';
@@ -1,6 +1,6 @@
1
1
  import { getTranslations } from 'next-intl/server';
2
2
  import { cn } from '@windrun-huaiin/lib/utils';
3
- import { globalLucideIcons as icons, getGlobalIcon } from '@windrun-huaiin/base-ui/components/server';
3
+ import { globalLucideIcons as icons, getGlobalIcon } from '@windrun-huaiin/base-ui/components/shared';
4
4
  import { themeIconColor } from '@windrun-huaiin/base-ui/lib';
5
5
  import { richText } from './rich-text-expert';
6
6
  import { responsiveSection } from './section-layout';