@windrun-huaiin/third-ui 29.0.4 → 29.2.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.
Files changed (64) hide show
  1. package/dist/fuma/base/custom-header.js +6 -3
  2. package/dist/fuma/base/custom-header.mjs +6 -3
  3. package/dist/main/alert-dialog/confirm-dialog.d.ts +7 -3
  4. package/dist/main/alert-dialog/confirm-dialog.js +11 -6
  5. package/dist/main/alert-dialog/confirm-dialog.mjs +13 -8
  6. package/dist/main/alert-dialog/dialog-loading-action.d.ts +12 -0
  7. package/dist/main/alert-dialog/dialog-loading-action.js +42 -0
  8. package/dist/main/alert-dialog/dialog-loading-action.mjs +40 -0
  9. package/dist/main/alert-dialog/high-priority-confirm-dialog.d.ts +6 -3
  10. package/dist/main/alert-dialog/high-priority-confirm-dialog.js +13 -4
  11. package/dist/main/alert-dialog/high-priority-confirm-dialog.mjs +14 -5
  12. package/dist/main/alert-dialog/index.d.ts +1 -0
  13. package/dist/main/alert-dialog/info-dialog.d.ts +4 -2
  14. package/dist/main/alert-dialog/info-dialog.js +6 -5
  15. package/dist/main/alert-dialog/info-dialog.mjs +7 -6
  16. package/dist/main/alert-dialog/undoable-confirm-dialog.d.ts +8 -4
  17. package/dist/main/alert-dialog/undoable-confirm-dialog.js +23 -16
  18. package/dist/main/alert-dialog/undoable-confirm-dialog.mjs +24 -17
  19. package/dist/main/buttons/gradient-button.d.ts +3 -1
  20. package/dist/main/buttons/gradient-button.js +29 -3
  21. package/dist/main/buttons/gradient-button.mjs +29 -3
  22. package/dist/main/buttons/index.d.ts +1 -0
  23. package/dist/main/buttons/index.js +3 -0
  24. package/dist/main/buttons/index.mjs +1 -0
  25. package/dist/main/buttons/use-press-feedback.d.ts +18 -0
  26. package/dist/main/buttons/use-press-feedback.js +42 -0
  27. package/dist/main/buttons/use-press-feedback.mjs +39 -0
  28. package/dist/main/buttons/x-button.d.ts +3 -0
  29. package/dist/main/buttons/x-button.js +36 -6
  30. package/dist/main/buttons/x-button.mjs +36 -6
  31. package/dist/main/calendar/calendar-date-range-input.d.ts +17 -0
  32. package/dist/main/calendar/calendar-date-range-input.js +81 -0
  33. package/dist/main/calendar/calendar-date-range-input.mjs +79 -0
  34. package/dist/main/calendar/calendar-status-view.d.ts +23 -0
  35. package/dist/main/calendar/calendar-status-view.js +155 -0
  36. package/dist/main/calendar/calendar-status-view.mjs +153 -0
  37. package/dist/main/calendar/index.d.ts +3 -0
  38. package/dist/main/calendar/index.js +12 -0
  39. package/dist/main/calendar/index.mjs +4 -0
  40. package/dist/main/calendar/random-date-range-dialog.d.ts +15 -0
  41. package/dist/main/calendar/random-date-range-dialog.js +447 -0
  42. package/dist/main/calendar/random-date-range-dialog.mjs +445 -0
  43. package/dist/main/features.js +2 -2
  44. package/dist/main/features.mjs +1 -1
  45. package/dist/main/usage.js +2 -2
  46. package/dist/main/usage.mjs +1 -1
  47. package/package.json +9 -4
  48. package/src/fuma/base/custom-header.tsx +6 -3
  49. package/src/main/alert-dialog/confirm-dialog.tsx +59 -46
  50. package/src/main/alert-dialog/dialog-loading-action.tsx +63 -0
  51. package/src/main/alert-dialog/high-priority-confirm-dialog.tsx +67 -48
  52. package/src/main/alert-dialog/index.ts +1 -0
  53. package/src/main/alert-dialog/info-dialog.tsx +50 -44
  54. package/src/main/alert-dialog/undoable-confirm-dialog.tsx +96 -81
  55. package/src/main/buttons/gradient-button.tsx +36 -3
  56. package/src/main/buttons/index.ts +1 -0
  57. package/src/main/buttons/use-press-feedback.ts +58 -0
  58. package/src/main/buttons/x-button.tsx +53 -11
  59. package/src/main/calendar/calendar-date-range-input.tsx +173 -0
  60. package/src/main/calendar/calendar-status-view.tsx +365 -0
  61. package/src/main/calendar/index.ts +5 -0
  62. package/src/main/calendar/random-date-range-dialog.tsx +741 -0
  63. package/src/main/features.tsx +1 -1
  64. package/src/main/usage.tsx +1 -1
@@ -137,11 +137,14 @@ function CustomNavbar(_a) {
137
137
  : '88rem';
138
138
  const minNavWidth = '15rem';
139
139
  const widthStyle = floating
140
- ? { width: `clamp(${minNavWidth}, 100vw, ${resolvedMaxWidth})` }
140
+ ? {
141
+ width: `min(calc(100vw - 1rem), ${resolvedMaxWidth})`,
142
+ maxWidth: resolvedMaxWidth,
143
+ }
141
144
  : { width: '100%', maxWidth: resolvedMaxWidth, minWidth: minNavWidth };
142
145
  const headerStyle = Object.assign(Object.assign(Object.assign({}, cssVars), widthStyle), style);
143
- return (jsxRuntime.jsx(navigationMenu.NavigationMenu, { value: value, onValueChange: setValue, asChild: true, children: jsxRuntime.jsxs("header", Object.assign({}, props, { style: headerStyle, className: utils.cn('rounded-2xl border px-4 py-1 transition-[background-color,box-shadow,transform] duration-300 backdrop-blur-xl shadow-lg shadow-black/5', floating
144
- ? 'fixed left-1/2 top-[--fd-banner-height] z-1001 -translate-x-1/2'
146
+ return (jsxRuntime.jsx(navigationMenu.NavigationMenu, { value: value, onValueChange: setValue, asChild: true, children: jsxRuntime.jsxs("header", Object.assign({}, props, { style: headerStyle, className: utils.cn('rounded-2xl border px-4 py-1 transition-[background-color,box-shadow] duration-300 backdrop-blur-xl shadow-lg shadow-black/5', floating
147
+ ? 'fixed inset-x-0 top-[--fd-banner-height] z-1001 mx-auto'
145
148
  : 'relative mx-auto w-full', 'border border-fd-border/60 bg-white/85 dark:border-white/20 dark:bg-neutral-900/75', value.length > 0 &&
146
149
  'max-lg:rounded-b-3xl border-fd-border/60 bg-white dark:border-white/20 dark:bg-neutral-900', className), children: [jsxRuntime.jsx(navigationMenu.NavigationMenuList, { className: "flex w-full items-center gap-4 px-1", style: { height: 'var(--fd-header-height)' }, asChild: true, children: jsxRuntime.jsx("nav", { children: props.children }) }), jsxRuntime.jsx(navigationMenu.NavigationMenuViewport, {})] })) }));
147
150
  }
@@ -135,11 +135,14 @@ function CustomNavbar(_a) {
135
135
  : '88rem';
136
136
  const minNavWidth = '15rem';
137
137
  const widthStyle = floating
138
- ? { width: `clamp(${minNavWidth}, 100vw, ${resolvedMaxWidth})` }
138
+ ? {
139
+ width: `min(calc(100vw - 1rem), ${resolvedMaxWidth})`,
140
+ maxWidth: resolvedMaxWidth,
141
+ }
139
142
  : { width: '100%', maxWidth: resolvedMaxWidth, minWidth: minNavWidth };
140
143
  const headerStyle = Object.assign(Object.assign(Object.assign({}, cssVars), widthStyle), style);
141
- return (jsx(NavigationMenu, { value: value, onValueChange: setValue, asChild: true, children: jsxs("header", Object.assign({}, props, { style: headerStyle, className: cn('rounded-2xl border px-4 py-1 transition-[background-color,box-shadow,transform] duration-300 backdrop-blur-xl shadow-lg shadow-black/5', floating
142
- ? 'fixed left-1/2 top-[--fd-banner-height] z-1001 -translate-x-1/2'
144
+ return (jsx(NavigationMenu, { value: value, onValueChange: setValue, asChild: true, children: jsxs("header", Object.assign({}, props, { style: headerStyle, className: cn('rounded-2xl border px-4 py-1 transition-[background-color,box-shadow] duration-300 backdrop-blur-xl shadow-lg shadow-black/5', floating
145
+ ? 'fixed inset-x-0 top-[--fd-banner-height] z-1001 mx-auto'
143
146
  : 'relative mx-auto w-full', 'border border-fd-border/60 bg-white/85 dark:border-white/20 dark:bg-neutral-900/75', value.length > 0 &&
144
147
  'max-lg:rounded-b-3xl border-fd-border/60 bg-white dark:border-white/20 dark:bg-neutral-900', className), children: [jsx(NavigationMenuList, { className: "flex w-full items-center gap-4 px-1", style: { height: 'var(--fd-header-height)' }, asChild: true, children: jsx("nav", { children: props.children }) }), jsx(NavigationMenuViewport, {})] })) }));
145
148
  }
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
+ import { DialogLoadingAction, DialogActionHandler } from './dialog-loading-action';
2
3
  export type ConfirmDialogType = 'normal' | 'danger';
4
+ export type ConfirmDialogEmphasis = 'confirm' | 'cancel';
3
5
  interface ConfirmDialogProps {
4
6
  open: boolean;
5
7
  onOpenChange: (open: boolean) => void;
@@ -8,8 +10,10 @@ interface ConfirmDialogProps {
8
10
  description: React.ReactNode;
9
11
  cancelText?: string;
10
12
  confirmText?: string;
11
- onCancel?: () => void;
12
- onConfirm?: () => void;
13
+ emphasis?: ConfirmDialogEmphasis;
14
+ loadingActions?: readonly DialogLoadingAction[];
15
+ onCancel?: DialogActionHandler;
16
+ onConfirm?: DialogActionHandler;
13
17
  }
14
- export declare function ConfirmDialog({ open, onOpenChange, type, title, description, cancelText, confirmText, onCancel, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
18
+ export declare function ConfirmDialog({ open, onOpenChange, type, title, description, cancelText, confirmText, emphasis, loadingActions, onCancel, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
15
19
  export {};
@@ -7,6 +7,7 @@ var lib = require('@windrun-huaiin/base-ui/lib');
7
7
  var ui = require('@windrun-huaiin/base-ui/ui');
8
8
  var utils = require('@windrun-huaiin/lib/utils');
9
9
  var dialogStyles = require('./dialog-styles.js');
10
+ var dialogLoadingAction = require('./dialog-loading-action.js');
10
11
 
11
12
  const confirmTypeClassMap = {
12
13
  normal: {
@@ -24,17 +25,21 @@ const confirmTypeClassMap = {
24
25
  Icon: icons.CircleAlertIcon,
25
26
  },
26
27
  };
27
- function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', onCancel, onConfirm, }) {
28
+ function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', loadingActions, onCancel, onConfirm, }) {
28
29
  const typeClass = confirmTypeClassMap[type];
29
30
  const Icon = typeClass.Icon;
31
+ const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : dialogStyles.secondaryButtonClass;
32
+ const confirmButtonClass = emphasis === 'cancel' ? dialogStyles.secondaryButtonClass : typeClass.action;
33
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
30
34
  const handleCancel = () => {
35
+ void runDialogAction('cancel', onCancel);
36
+ };
37
+ const handleClose = () => {
31
38
  onOpenChange(false);
32
- onCancel === null || onCancel === void 0 ? void 0 : onCancel();
33
39
  };
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: () => {
35
- onOpenChange(false);
36
- onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm();
37
- }, children: confirmText })] })] }) }));
40
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [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: () => {
41
+ void runDialogAction('confirm', onConfirm);
42
+ }, children: confirmText })] })] }) }), dialogLoading] }));
38
43
  }
39
44
 
40
45
  exports.ConfirmDialog = ConfirmDialog;
@@ -1,10 +1,11 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { CircleAlertIcon, CircleQuestionMarkIcon, XIcon } from '@windrun-huaiin/base-ui/icons';
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
+ import { useDialogLoadingAction } from './dialog-loading-action.mjs';
8
9
 
9
10
  const confirmTypeClassMap = {
10
11
  normal: {
@@ -22,17 +23,21 @@ const confirmTypeClassMap = {
22
23
  Icon: CircleAlertIcon,
23
24
  },
24
25
  };
25
- function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', onCancel, onConfirm, }) {
26
+ function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', loadingActions, onCancel, onConfirm, }) {
26
27
  const typeClass = confirmTypeClassMap[type];
27
28
  const Icon = typeClass.Icon;
29
+ const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : secondaryButtonClass;
30
+ const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : typeClass.action;
31
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
28
32
  const handleCancel = () => {
33
+ void runDialogAction('cancel', onCancel);
34
+ };
35
+ const handleClose = () => {
29
36
  onOpenChange(false);
30
- onCancel === null || onCancel === void 0 ? void 0 : onCancel();
31
37
  };
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: () => {
33
- onOpenChange(false);
34
- onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm();
35
- }, children: confirmText })] })] }) }));
38
+ return (jsxs(Fragment, { children: [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: () => {
39
+ void runDialogAction('confirm', onConfirm);
40
+ }, children: confirmText })] })] }) }), dialogLoading] }));
36
41
  }
37
42
 
38
43
  export { ConfirmDialog };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export type DialogLoadingAction = 'cancel' | 'confirm' | 'undo';
3
+ export type DialogActionHandler = () => void | Promise<void>;
4
+ interface UseDialogLoadingActionOptions {
5
+ loadingActions?: readonly DialogLoadingAction[];
6
+ onOpenChange: (open: boolean) => void;
7
+ }
8
+ export declare function useDialogLoadingAction({ loadingActions, onOpenChange, }: UseDialogLoadingActionOptions): {
9
+ dialogLoading: React.ReactPortal | null;
10
+ runDialogAction: (action: DialogLoadingAction, handler?: DialogActionHandler) => Promise<void>;
11
+ };
12
+ export {};
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var tslib = require('tslib');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var React = require('react');
7
+ var reactDom = require('react-dom');
8
+ var loading = require('../loading.js');
9
+
10
+ function useDialogLoadingAction({ loadingActions, onOpenChange, }) {
11
+ const [mounted, setMounted] = React.useState(false);
12
+ const [loading$1, setLoading] = React.useState(false);
13
+ React.useEffect(() => {
14
+ setMounted(true);
15
+ }, []);
16
+ const runDialogAction = React.useCallback((action, handler) => tslib.__awaiter(this, void 0, void 0, function* () {
17
+ onOpenChange(false);
18
+ if (!handler) {
19
+ return;
20
+ }
21
+ if (!(loadingActions === null || loadingActions === void 0 ? void 0 : loadingActions.includes(action))) {
22
+ yield handler();
23
+ return;
24
+ }
25
+ setLoading(true);
26
+ try {
27
+ yield handler();
28
+ }
29
+ finally {
30
+ setLoading(false);
31
+ }
32
+ }), [loadingActions, onOpenChange]);
33
+ const dialogLoading = mounted && loading$1
34
+ ? reactDom.createPortal(jsxRuntime.jsx("div", { className: "fixed inset-0 z-10000", children: jsxRuntime.jsx(loading.Loading, { className: "h-full w-full" }) }), document.body)
35
+ : null;
36
+ return {
37
+ dialogLoading,
38
+ runDialogAction,
39
+ };
40
+ }
41
+
42
+ exports.useDialogLoadingAction = useDialogLoadingAction;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { __awaiter } from 'tslib';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import React__default from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { Loading } from '../loading.mjs';
7
+
8
+ function useDialogLoadingAction({ loadingActions, onOpenChange, }) {
9
+ const [mounted, setMounted] = React__default.useState(false);
10
+ const [loading, setLoading] = React__default.useState(false);
11
+ React__default.useEffect(() => {
12
+ setMounted(true);
13
+ }, []);
14
+ const runDialogAction = React__default.useCallback((action, handler) => __awaiter(this, void 0, void 0, function* () {
15
+ onOpenChange(false);
16
+ if (!handler) {
17
+ return;
18
+ }
19
+ if (!(loadingActions === null || loadingActions === void 0 ? void 0 : loadingActions.includes(action))) {
20
+ yield handler();
21
+ return;
22
+ }
23
+ setLoading(true);
24
+ try {
25
+ yield handler();
26
+ }
27
+ finally {
28
+ setLoading(false);
29
+ }
30
+ }), [loadingActions, onOpenChange]);
31
+ const dialogLoading = mounted && loading
32
+ ? createPortal(jsx("div", { className: "fixed inset-0 z-10000", children: jsx(Loading, { className: "h-full w-full" }) }), document.body)
33
+ : null;
34
+ return {
35
+ dialogLoading,
36
+ runDialogAction,
37
+ };
38
+ }
39
+
40
+ export { useDialogLoadingAction };
@@ -1,12 +1,15 @@
1
1
  import React from "react";
2
+ import { DialogLoadingAction, DialogActionHandler } from "./dialog-loading-action";
2
3
  interface HighPriorityConfirmDialogProps {
3
4
  open: boolean;
4
- onCancel: () => void;
5
- onConfirm: () => void;
5
+ onOpenChange: (open: boolean) => void;
6
+ onCancel: DialogActionHandler;
7
+ onConfirm: DialogActionHandler;
6
8
  title: string;
7
9
  description: React.ReactNode;
8
10
  confirmText?: string;
9
11
  cancelText?: string;
12
+ loadingActions?: readonly DialogLoadingAction[];
10
13
  }
11
- export declare function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, description, confirmText, cancelText, }: HighPriorityConfirmDialogProps): React.ReactPortal | null;
14
+ export declare function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText, cancelText, loadingActions, }: HighPriorityConfirmDialogProps): import("react/jsx-runtime").JSX.Element | null;
12
15
  export {};
@@ -8,16 +8,25 @@ var icons = require('@windrun-huaiin/base-ui/icons');
8
8
  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
+ var dialogLoadingAction = require('./dialog-loading-action.js');
11
12
 
12
- function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", }) {
13
+ function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", loadingActions, }) {
13
14
  const [mounted, setMounted] = React.useState(false);
15
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
14
16
  React.useEffect(() => {
15
17
  // Ensure portal target exists and prevent hydration mismatch
16
18
  setTimeout(() => setMounted(true), 0);
17
19
  }, []);
18
- if (!open || !mounted)
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
+ if (!mounted)
21
+ return dialogLoading;
22
+ const handleClose = () => {
23
+ onOpenChange(false);
24
+ };
25
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [open && 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: () => {
26
+ void runDialogAction('cancel', onCancel);
27
+ }, className: dialogStyles.secondaryButtonClass, children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
28
+ void runDialogAction('confirm', onConfirm);
29
+ }, className: utils.cn(dialogStyles.primaryButtonClass, "hover:scale-105 active:scale-95"), children: confirmText })] })] }) }), document.body), dialogLoading] }));
21
30
  }
22
31
 
23
32
  exports.HighPriorityConfirmDialog = HighPriorityConfirmDialog;
@@ -1,21 +1,30 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { useState, useEffect } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { FAQSIcon, XIcon } from '@windrun-huaiin/base-ui/icons';
6
6
  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
+ import { useDialogLoadingAction } from './dialog-loading-action.mjs';
9
10
 
10
- function HighPriorityConfirmDialog({ open, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", }) {
11
+ function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", loadingActions, }) {
11
12
  const [mounted, setMounted] = useState(false);
13
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
12
14
  useEffect(() => {
13
15
  // Ensure portal target exists and prevent hydration mismatch
14
16
  setTimeout(() => setMounted(true), 0);
15
17
  }, []);
16
- if (!open || !mounted)
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
+ if (!mounted)
19
+ return dialogLoading;
20
+ const handleClose = () => {
21
+ onOpenChange(false);
22
+ };
23
+ return (jsxs(Fragment, { children: [open && 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: () => {
24
+ void runDialogAction('cancel', onCancel);
25
+ }, className: secondaryButtonClass, children: cancelText }), jsx("button", { type: "button", onClick: () => {
26
+ void runDialogAction('confirm', onConfirm);
27
+ }, className: cn(primaryButtonClass, "hover:scale-105 active:scale-95"), children: confirmText })] })] }) }), document.body), dialogLoading] }));
19
28
  }
20
29
 
21
30
  export { HighPriorityConfirmDialog };
@@ -3,3 +3,4 @@ export * from './confirm-dialog';
3
3
  export * from './high-priority-confirm-dialog';
4
4
  export * from './info-dialog';
5
5
  export * from './undoable-confirm-dialog';
6
+ export type { DialogLoadingAction } from './dialog-loading-action';
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { DialogLoadingAction, DialogActionHandler } from './dialog-loading-action';
2
3
  export type InfoDialogType = 'info' | 'warn' | 'success' | 'error';
3
4
  interface InfoDialogProps {
4
5
  open: boolean;
@@ -7,7 +8,8 @@ interface InfoDialogProps {
7
8
  title: React.ReactNode;
8
9
  description: React.ReactNode;
9
10
  confirmText?: string;
10
- onConfirm?: () => void;
11
+ loadingActions?: readonly DialogLoadingAction[];
12
+ onConfirm?: DialogActionHandler;
11
13
  }
12
- export declare function InfoDialog({ open, onOpenChange, type, title, description, confirmText, onConfirm, }: InfoDialogProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function InfoDialog({ open, onOpenChange, type, title, description, confirmText, loadingActions, onConfirm, }: InfoDialogProps): import("react/jsx-runtime").JSX.Element;
13
15
  export {};
@@ -6,6 +6,7 @@ var icons = require('@windrun-huaiin/base-ui/icons');
6
6
  var ui = require('@windrun-huaiin/base-ui/ui');
7
7
  var utils = require('@windrun-huaiin/lib/utils');
8
8
  var dialogStyles = require('./dialog-styles.js');
9
+ var dialogLoadingAction = require('./dialog-loading-action.js');
9
10
 
10
11
  const infoTypeClassMap = {
11
12
  info: {
@@ -37,14 +38,14 @@ const infoTypeClassMap = {
37
38
  Icon: icons.BadgeXIcon,
38
39
  },
39
40
  };
40
- function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', onConfirm, }) {
41
+ function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', loadingActions, onConfirm, }) {
41
42
  const typeClass = infoTypeClassMap[type];
42
43
  const Icon = typeClass.Icon;
43
44
  const handleClose = () => onOpenChange(false);
44
- 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.jsx("div", { className: dialogStyles.dialogFooterClass, children: jsxRuntime.jsx(ui.AlertDialogAction, { className: utils.cn('inline-flex min-h-10 items-center justify-center rounded-full px-5 py-2 text-sm font-bold transition focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-60', typeClass.action), onClick: () => {
45
- onOpenChange(false);
46
- onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm();
47
- }, children: confirmText }) })] }) }));
45
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
46
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [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.jsx("div", { className: dialogStyles.dialogFooterClass, children: jsxRuntime.jsx(ui.AlertDialogAction, { className: utils.cn('inline-flex min-h-10 items-center justify-center rounded-full px-5 py-2 text-sm font-bold transition focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-60', typeClass.action), onClick: () => {
47
+ void runDialogAction('confirm', onConfirm);
48
+ }, children: confirmText }) })] }) }), dialogLoading] }));
48
49
  }
49
50
 
50
51
  exports.InfoDialog = InfoDialog;
@@ -1,9 +1,10 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { BadgeXIcon, BadgeCheckIcon, BadgeAlertIcon, BadgeInfoIcon, XIcon } from '@windrun-huaiin/base-ui/icons';
4
4
  import { AlertDialog, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, AlertDialogAction } from '@windrun-huaiin/base-ui/ui';
5
5
  import { cn } from '@windrun-huaiin/lib/utils';
6
6
  import { dialogThemedOverlayClass, dialogHeaderClass, dialogTitleClass, closeButtonClass, dialogDescriptionClass, dialogFooterClass, dialogContentClass } from './dialog-styles.mjs';
7
+ import { useDialogLoadingAction } from './dialog-loading-action.mjs';
7
8
 
8
9
  const infoTypeClassMap = {
9
10
  info: {
@@ -35,14 +36,14 @@ const infoTypeClassMap = {
35
36
  Icon: BadgeXIcon,
36
37
  },
37
38
  };
38
- function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', onConfirm, }) {
39
+ function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', loadingActions, onConfirm, }) {
39
40
  const typeClass = infoTypeClassMap[type];
40
41
  const Icon = typeClass.Icon;
41
42
  const handleClose = () => onOpenChange(false);
42
- 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 }), jsx("div", { className: dialogFooterClass, children: jsx(AlertDialogAction, { className: cn('inline-flex min-h-10 items-center justify-center rounded-full px-5 py-2 text-sm font-bold transition focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-60', typeClass.action), onClick: () => {
43
- onOpenChange(false);
44
- onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm();
45
- }, children: confirmText }) })] }) }));
43
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
44
+ return (jsxs(Fragment, { children: [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 }), jsx("div", { className: dialogFooterClass, children: jsx(AlertDialogAction, { className: cn('inline-flex min-h-10 items-center justify-center rounded-full px-5 py-2 text-sm font-bold transition focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-60', typeClass.action), onClick: () => {
45
+ void runDialogAction('confirm', onConfirm);
46
+ }, children: confirmText }) })] }) }), dialogLoading] }));
46
47
  }
47
48
 
48
49
  export { InfoDialog };
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ import type { ConfirmDialogEmphasis } from './confirm-dialog';
3
+ import { DialogLoadingAction, DialogActionHandler } from './dialog-loading-action';
2
4
  export interface UndoableConfirmDialogProps {
3
5
  open: boolean;
4
6
  onOpenChange: (open: boolean) => void;
@@ -9,9 +11,11 @@ export interface UndoableConfirmDialogProps {
9
11
  cancelText?: string;
10
12
  confirmText?: string;
11
13
  undoText?: string;
14
+ emphasis?: ConfirmDialogEmphasis;
12
15
  countdownSeconds?: number;
13
- onCancel?: () => void;
14
- onConfirm: () => void | Promise<void>;
15
- onUndo?: () => void;
16
+ loadingActions?: readonly DialogLoadingAction[];
17
+ onCancel?: DialogActionHandler;
18
+ onConfirm: DialogActionHandler;
19
+ onUndo?: DialogActionHandler;
16
20
  }
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;
21
+ export declare function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText, confirmText, undoText, emphasis, countdownSeconds, loadingActions, onCancel, onConfirm, onUndo, }: UndoableConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -9,14 +9,18 @@ var lib = require('@windrun-huaiin/base-ui/lib');
9
9
  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
+ var dialogLoadingAction = require('./dialog-loading-action.js');
12
13
 
13
- function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', countdownSeconds = 5, onCancel, onConfirm, onUndo, }) {
14
+ function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, loadingActions, onCancel, onConfirm, onUndo, }) {
14
15
  const safeCountdownSeconds = Math.max(1, Math.floor(countdownSeconds));
15
16
  const [pending, setPending] = React.useState(false);
16
17
  const [remainingSeconds, setRemainingSeconds] = React.useState(safeCountdownSeconds);
17
18
  const [confirming, setConfirming] = React.useState(false);
18
19
  const timeoutRef = React.useRef(null);
19
20
  const intervalRef = React.useRef(null);
21
+ const cancelButtonClass = emphasis === 'cancel' ? dialogStyles.dangerButtonClass : dialogStyles.secondaryButtonClass;
22
+ const confirmButtonClass = emphasis === 'cancel' ? dialogStyles.secondaryButtonClass : dialogStyles.dangerButtonClass;
23
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
20
24
  const clearTimers = React.useCallback(() => {
21
25
  if (timeoutRef.current) {
22
26
  window.clearTimeout(timeoutRef.current);
@@ -45,13 +49,12 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
45
49
  clearTimers();
46
50
  setConfirming(true);
47
51
  try {
48
- yield onConfirm();
49
- onOpenChange(false);
52
+ yield runDialogAction('confirm', onConfirm);
50
53
  }
51
54
  finally {
52
55
  setConfirming(false);
53
56
  }
54
- }), [clearTimers, onConfirm, onOpenChange]);
57
+ }), [clearTimers, onConfirm, runDialogAction]);
55
58
  const startCountdown = () => {
56
59
  clearTimers();
57
60
  setPending(true);
@@ -65,23 +68,27 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
65
68
  };
66
69
  const handleCancel = () => {
67
70
  resetState();
68
- onOpenChange(false);
69
- onCancel === null || onCancel === void 0 ? void 0 : onCancel();
71
+ void runDialogAction('cancel', onCancel);
70
72
  };
71
- const handleUndo = () => {
73
+ const handleClose = React.useCallback(() => {
72
74
  resetState();
73
75
  onOpenChange(false);
74
- onUndo === null || onUndo === void 0 ? void 0 : onUndo();
75
- };
76
+ }, [onOpenChange, resetState]);
77
+ const handleUndo = () => tslib.__awaiter(this, void 0, void 0, function* () {
78
+ resetState();
79
+ yield runDialogAction('undo', onUndo);
80
+ });
76
81
  const displayTitle = pending ? pendingTitle !== null && pendingTitle !== void 0 ? pendingTitle : title : title;
77
82
  const displayDescription = pending ? pendingDescription !== null && pendingDescription !== void 0 ? pendingDescription : description : description;
78
- return (jsxRuntime.jsx(ui.AlertDialog, { open: open, onOpenChange: (nextOpen) => {
79
- if (!nextOpen) {
80
- handleCancel();
81
- return;
82
- }
83
- 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 })] })) })] }) }));
83
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ui.AlertDialog, { open: open, onOpenChange: (nextOpen) => {
84
+ if (!nextOpen) {
85
+ handleClose();
86
+ return;
87
+ }
88
+ onOpenChange(nextOpen);
89
+ }, 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: () => {
90
+ void handleUndo();
91
+ }, 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 })] })) })] }) }), dialogLoading] }));
85
92
  }
86
93
 
87
94
  exports.UndoableConfirmDialog = UndoableConfirmDialog;