@windrun-huaiin/third-ui 29.2.0 → 29.2.1

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 (25) hide show
  1. package/dist/main/alert-dialog/confirm-dialog.d.ts +2 -1
  2. package/dist/main/alert-dialog/confirm-dialog.js +2 -2
  3. package/dist/main/alert-dialog/confirm-dialog.mjs +2 -2
  4. package/dist/main/alert-dialog/dialog-loading-action.d.ts +2 -1
  5. package/dist/main/alert-dialog/dialog-loading-action.js +2 -2
  6. package/dist/main/alert-dialog/dialog-loading-action.mjs +2 -2
  7. package/dist/main/alert-dialog/high-priority-confirm-dialog.d.ts +2 -1
  8. package/dist/main/alert-dialog/high-priority-confirm-dialog.js +2 -2
  9. package/dist/main/alert-dialog/high-priority-confirm-dialog.mjs +2 -2
  10. package/dist/main/alert-dialog/info-dialog.d.ts +2 -1
  11. package/dist/main/alert-dialog/info-dialog.js +2 -2
  12. package/dist/main/alert-dialog/info-dialog.mjs +2 -2
  13. package/dist/main/alert-dialog/undoable-confirm-dialog.d.ts +2 -1
  14. package/dist/main/alert-dialog/undoable-confirm-dialog.js +2 -2
  15. package/dist/main/alert-dialog/undoable-confirm-dialog.mjs +2 -2
  16. package/dist/main/calendar/random-date-range-dialog.d.ts +5 -2
  17. package/dist/main/calendar/random-date-range-dialog.js +74 -70
  18. package/dist/main/calendar/random-date-range-dialog.mjs +76 -72
  19. package/package.json +3 -3
  20. package/src/main/alert-dialog/confirm-dialog.tsx +3 -1
  21. package/src/main/alert-dialog/dialog-loading-action.tsx +18 -3
  22. package/src/main/alert-dialog/high-priority-confirm-dialog.tsx +3 -1
  23. package/src/main/alert-dialog/info-dialog.tsx +3 -1
  24. package/src/main/alert-dialog/undoable-confirm-dialog.tsx +3 -1
  25. package/src/main/calendar/random-date-range-dialog.tsx +19 -7
@@ -12,8 +12,9 @@ interface ConfirmDialogProps {
12
12
  confirmText?: string;
13
13
  emphasis?: ConfirmDialogEmphasis;
14
14
  loadingActions?: readonly DialogLoadingAction[];
15
+ loadingFullPage?: boolean;
15
16
  onCancel?: DialogActionHandler;
16
17
  onConfirm?: DialogActionHandler;
17
18
  }
18
- export declare function ConfirmDialog({ open, onOpenChange, type, title, description, cancelText, confirmText, emphasis, loadingActions, onCancel, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function ConfirmDialog({ open, onOpenChange, type, title, description, cancelText, confirmText, emphasis, loadingActions, loadingFullPage, onCancel, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
19
20
  export {};
@@ -25,12 +25,12 @@ const confirmTypeClassMap = {
25
25
  Icon: icons.CircleAlertIcon,
26
26
  },
27
27
  };
28
- function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', loadingActions, onCancel, onConfirm, }) {
28
+ function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', loadingActions, loadingFullPage, onCancel, onConfirm, }) {
29
29
  const typeClass = confirmTypeClassMap[type];
30
30
  const Icon = typeClass.Icon;
31
31
  const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : dialogStyles.secondaryButtonClass;
32
32
  const confirmButtonClass = emphasis === 'cancel' ? dialogStyles.secondaryButtonClass : typeClass.action;
33
- const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
33
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
34
34
  const handleCancel = () => {
35
35
  void runDialogAction('cancel', onCancel);
36
36
  };
@@ -23,12 +23,12 @@ const confirmTypeClassMap = {
23
23
  Icon: CircleAlertIcon,
24
24
  },
25
25
  };
26
- function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', loadingActions, onCancel, onConfirm, }) {
26
+ function ConfirmDialog({ open, onOpenChange, type = 'normal', title, description, cancelText = 'Cancel', confirmText = 'Confirm', emphasis = 'confirm', loadingActions, loadingFullPage, onCancel, onConfirm, }) {
27
27
  const typeClass = confirmTypeClassMap[type];
28
28
  const Icon = typeClass.Icon;
29
29
  const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : secondaryButtonClass;
30
30
  const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : typeClass.action;
31
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
31
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
32
32
  const handleCancel = () => {
33
33
  void runDialogAction('cancel', onCancel);
34
34
  };
@@ -3,9 +3,10 @@ export type DialogLoadingAction = 'cancel' | 'confirm' | 'undo';
3
3
  export type DialogActionHandler = () => void | Promise<void>;
4
4
  interface UseDialogLoadingActionOptions {
5
5
  loadingActions?: readonly DialogLoadingAction[];
6
+ loadingFullPage?: boolean;
6
7
  onOpenChange: (open: boolean) => void;
7
8
  }
8
- export declare function useDialogLoadingAction({ loadingActions, onOpenChange, }: UseDialogLoadingActionOptions): {
9
+ export declare function useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange, }: UseDialogLoadingActionOptions): {
9
10
  dialogLoading: React.ReactPortal | null;
10
11
  runDialogAction: (action: DialogLoadingAction, handler?: DialogActionHandler) => Promise<void>;
11
12
  };
@@ -7,7 +7,7 @@ var React = require('react');
7
7
  var reactDom = require('react-dom');
8
8
  var loading = require('../loading.js');
9
9
 
10
- function useDialogLoadingAction({ loadingActions, onOpenChange, }) {
10
+ function useDialogLoadingAction({ loadingActions, loadingFullPage = false, onOpenChange, }) {
11
11
  const [mounted, setMounted] = React.useState(false);
12
12
  const [loading$1, setLoading] = React.useState(false);
13
13
  React.useEffect(() => {
@@ -31,7 +31,7 @@ function useDialogLoadingAction({ loadingActions, onOpenChange, }) {
31
31
  }
32
32
  }), [loadingActions, onOpenChange]);
33
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)
34
+ ? reactDom.createPortal(loadingFullPage ? (jsxRuntime.jsx("div", { className: "fixed inset-0 z-10000", children: jsxRuntime.jsx(loading.Loading, { className: "h-full w-full" }) })) : (jsxRuntime.jsx("div", { className: "pointer-events-none fixed inset-0 z-10000 flex items-center justify-center p-4", children: jsxRuntime.jsx("div", { className: "pointer-events-auto overflow-hidden rounded-[28px] bg-neutral-50/58 shadow-[0_18px_56px_rgba(15,23,42,0.14)] backdrop-blur-md dark:bg-neutral-900/58 dark:shadow-[0_18px_56px_rgba(0,0,0,0.34)]", children: jsxRuntime.jsx(loading.Loading, { compact: true, label: "Loading", className: "min-h-[250px] w-[min(22rem,calc(100vw-2rem))] bg-transparent", labelClassName: "text-foreground" }) }) })), document.body)
35
35
  : null;
36
36
  return {
37
37
  dialogLoading,
@@ -5,7 +5,7 @@ import React__default from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import { Loading } from '../loading.mjs';
7
7
 
8
- function useDialogLoadingAction({ loadingActions, onOpenChange, }) {
8
+ function useDialogLoadingAction({ loadingActions, loadingFullPage = false, onOpenChange, }) {
9
9
  const [mounted, setMounted] = React__default.useState(false);
10
10
  const [loading, setLoading] = React__default.useState(false);
11
11
  React__default.useEffect(() => {
@@ -29,7 +29,7 @@ function useDialogLoadingAction({ loadingActions, onOpenChange, }) {
29
29
  }
30
30
  }), [loadingActions, onOpenChange]);
31
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)
32
+ ? createPortal(loadingFullPage ? (jsx("div", { className: "fixed inset-0 z-10000", children: jsx(Loading, { className: "h-full w-full" }) })) : (jsx("div", { className: "pointer-events-none fixed inset-0 z-10000 flex items-center justify-center p-4", children: jsx("div", { className: "pointer-events-auto overflow-hidden rounded-[28px] bg-neutral-50/58 shadow-[0_18px_56px_rgba(15,23,42,0.14)] backdrop-blur-md dark:bg-neutral-900/58 dark:shadow-[0_18px_56px_rgba(0,0,0,0.34)]", children: jsx(Loading, { compact: true, label: "Loading", className: "min-h-[250px] w-[min(22rem,calc(100vw-2rem))] bg-transparent", labelClassName: "text-foreground" }) }) })), document.body)
33
33
  : null;
34
34
  return {
35
35
  dialogLoading,
@@ -10,6 +10,7 @@ interface HighPriorityConfirmDialogProps {
10
10
  confirmText?: string;
11
11
  cancelText?: string;
12
12
  loadingActions?: readonly DialogLoadingAction[];
13
+ loadingFullPage?: boolean;
13
14
  }
14
- export declare function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText, cancelText, loadingActions, }: HighPriorityConfirmDialogProps): import("react/jsx-runtime").JSX.Element | null;
15
+ export declare function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText, cancelText, loadingActions, loadingFullPage, }: HighPriorityConfirmDialogProps): import("react/jsx-runtime").JSX.Element | null;
15
16
  export {};
@@ -10,9 +10,9 @@ var dialogStyles = require('./dialog-styles.js');
10
10
  var lib = require('@windrun-huaiin/base-ui/lib');
11
11
  var dialogLoadingAction = require('./dialog-loading-action.js');
12
12
 
13
- function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", loadingActions, }) {
13
+ function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", loadingActions, loadingFullPage, }) {
14
14
  const [mounted, setMounted] = React.useState(false);
15
- const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
15
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
16
16
  React.useEffect(() => {
17
17
  // Ensure portal target exists and prevent hydration mismatch
18
18
  setTimeout(() => setMounted(true), 0);
@@ -8,9 +8,9 @@ import { dialogHeaderClass, highPriorityTitleClass, closeButtonClass, dialogDesc
8
8
  import { themeIconColor, themeBgColor, themeBorderColor } from '@windrun-huaiin/base-ui/lib';
9
9
  import { useDialogLoadingAction } from './dialog-loading-action.mjs';
10
10
 
11
- function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", loadingActions, }) {
11
+ function HighPriorityConfirmDialog({ open, onOpenChange, onCancel, onConfirm, title, description, confirmText = "Confirm", cancelText = "Cancel", loadingActions, loadingFullPage, }) {
12
12
  const [mounted, setMounted] = useState(false);
13
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
13
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
14
14
  useEffect(() => {
15
15
  // Ensure portal target exists and prevent hydration mismatch
16
16
  setTimeout(() => setMounted(true), 0);
@@ -9,7 +9,8 @@ interface InfoDialogProps {
9
9
  description: React.ReactNode;
10
10
  confirmText?: string;
11
11
  loadingActions?: readonly DialogLoadingAction[];
12
+ loadingFullPage?: boolean;
12
13
  onConfirm?: DialogActionHandler;
13
14
  }
14
- export declare function InfoDialog({ open, onOpenChange, type, title, description, confirmText, loadingActions, onConfirm, }: InfoDialogProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function InfoDialog({ open, onOpenChange, type, title, description, confirmText, loadingActions, loadingFullPage, onConfirm, }: InfoDialogProps): import("react/jsx-runtime").JSX.Element;
15
16
  export {};
@@ -38,11 +38,11 @@ const infoTypeClassMap = {
38
38
  Icon: icons.BadgeXIcon,
39
39
  },
40
40
  };
41
- function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', loadingActions, onConfirm, }) {
41
+ function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', loadingActions, loadingFullPage, onConfirm, }) {
42
42
  const typeClass = infoTypeClassMap[type];
43
43
  const Icon = typeClass.Icon;
44
44
  const handleClose = () => onOpenChange(false);
45
- const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
45
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
46
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
47
  void runDialogAction('confirm', onConfirm);
48
48
  }, children: confirmText }) })] }) }), dialogLoading] }));
@@ -36,11 +36,11 @@ const infoTypeClassMap = {
36
36
  Icon: BadgeXIcon,
37
37
  },
38
38
  };
39
- function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', loadingActions, onConfirm, }) {
39
+ function InfoDialog({ open, onOpenChange, type = 'info', title, description, confirmText = 'OK', loadingActions, loadingFullPage, onConfirm, }) {
40
40
  const typeClass = infoTypeClassMap[type];
41
41
  const Icon = typeClass.Icon;
42
42
  const handleClose = () => onOpenChange(false);
43
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
43
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
44
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
45
  void runDialogAction('confirm', onConfirm);
46
46
  }, children: confirmText }) })] }) }), dialogLoading] }));
@@ -14,8 +14,9 @@ export interface UndoableConfirmDialogProps {
14
14
  emphasis?: ConfirmDialogEmphasis;
15
15
  countdownSeconds?: number;
16
16
  loadingActions?: readonly DialogLoadingAction[];
17
+ loadingFullPage?: boolean;
17
18
  onCancel?: DialogActionHandler;
18
19
  onConfirm: DialogActionHandler;
19
20
  onUndo?: DialogActionHandler;
20
21
  }
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;
22
+ export declare function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText, confirmText, undoText, emphasis, countdownSeconds, loadingActions, loadingFullPage, onCancel, onConfirm, onUndo, }: UndoableConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -11,7 +11,7 @@ var utils = require('@windrun-huaiin/lib/utils');
11
11
  var dialogStyles = require('./dialog-styles.js');
12
12
  var dialogLoadingAction = require('./dialog-loading-action.js');
13
13
 
14
- function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, loadingActions, onCancel, onConfirm, onUndo, }) {
14
+ function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, loadingActions, loadingFullPage, onCancel, onConfirm, onUndo, }) {
15
15
  const safeCountdownSeconds = Math.max(1, Math.floor(countdownSeconds));
16
16
  const [pending, setPending] = React.useState(false);
17
17
  const [remainingSeconds, setRemainingSeconds] = React.useState(safeCountdownSeconds);
@@ -20,7 +20,7 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
20
20
  const intervalRef = React.useRef(null);
21
21
  const cancelButtonClass = emphasis === 'cancel' ? dialogStyles.dangerButtonClass : dialogStyles.secondaryButtonClass;
22
22
  const confirmButtonClass = emphasis === 'cancel' ? dialogStyles.secondaryButtonClass : dialogStyles.dangerButtonClass;
23
- const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, onOpenChange });
23
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
24
24
  const clearTimers = React.useCallback(() => {
25
25
  if (timeoutRef.current) {
26
26
  window.clearTimeout(timeoutRef.current);
@@ -9,7 +9,7 @@ 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
  import { useDialogLoadingAction } from './dialog-loading-action.mjs';
11
11
 
12
- function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, loadingActions, onCancel, onConfirm, onUndo, }) {
12
+ function UndoableConfirmDialog({ open, onOpenChange, title, description, pendingTitle, pendingDescription, cancelText = 'Cancel', confirmText = 'Delete', undoText = 'Undo', emphasis = 'confirm', countdownSeconds = 5, loadingActions, loadingFullPage, onCancel, onConfirm, onUndo, }) {
13
13
  const safeCountdownSeconds = Math.max(1, Math.floor(countdownSeconds));
14
14
  const [pending, setPending] = React__default.useState(false);
15
15
  const [remainingSeconds, setRemainingSeconds] = React__default.useState(safeCountdownSeconds);
@@ -18,7 +18,7 @@ function UndoableConfirmDialog({ open, onOpenChange, title, description, pending
18
18
  const intervalRef = React__default.useRef(null);
19
19
  const cancelButtonClass = emphasis === 'cancel' ? dangerButtonClass : secondaryButtonClass;
20
20
  const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : dangerButtonClass;
21
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
21
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
22
22
  const clearTimers = React__default.useCallback(() => {
23
23
  if (timeoutRef.current) {
24
24
  window.clearTimeout(timeoutRef.current);
@@ -1,3 +1,4 @@
1
+ import { DialogLoadingAction } from '../alert-dialog/dialog-loading-action';
1
2
  export type RandomCalendarRange = {
2
3
  startDate: string | null;
3
4
  endDate: string | null;
@@ -8,8 +9,10 @@ type RandomDateRangeDialogProps = {
8
9
  anchorDate: string;
9
10
  defaultRangeDays?: number;
10
11
  onOpenChange: (open: boolean) => void;
11
- onApply: (range: RandomCalendarRange) => void;
12
+ loadingActions?: readonly DialogLoadingAction[];
13
+ loadingFullPage?: boolean;
14
+ onApply: (range: RandomCalendarRange) => void | Promise<void>;
12
15
  onClear?: (range: RandomCalendarRange) => void;
13
16
  };
14
- export declare function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays, onOpenChange, onApply, onClear, }: RandomDateRangeDialogProps): import("react").ReactPortal | null;
17
+ export declare function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays, onOpenChange, loadingActions, loadingFullPage, onApply, onClear, }: RandomDateRangeDialogProps): import("react/jsx-runtime").JSX.Element;
15
18
  export {};
@@ -6,6 +6,7 @@ var React = require('react');
6
6
  var reactDom = require('react-dom');
7
7
  var icons = require('@windrun-huaiin/base-ui/icons');
8
8
  var utils = require('@windrun-huaiin/lib/utils');
9
+ var dialogLoadingAction = require('../alert-dialog/dialog-loading-action.js');
9
10
  var usePressFeedback = require('../buttons/use-press-feedback.js');
10
11
 
11
12
  const DEFAULT_RANGE_DAYS = 7;
@@ -118,7 +119,7 @@ function getMonthEnd(value) {
118
119
  const date = parseDateString(value);
119
120
  return formatDateString(new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0)));
120
121
  }
121
- function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEFAULT_RANGE_DAYS, onOpenChange, onApply, onClear, }) {
122
+ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEFAULT_RANGE_DAYS, onOpenChange, loadingActions, loadingFullPage, onApply, onClear, }) {
122
123
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
123
124
  const resolvedDefaultRangeDays = clampWindowDays(defaultRangeDays);
124
125
  const [draftRange, setDraftRange] = React.useState(value);
@@ -143,6 +144,7 @@ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEF
143
144
  const buildDraggedRangeRef = React.useRef(() => null);
144
145
  const previousBodyOverflowRef = React.useRef(null);
145
146
  const today = React.useMemo(() => getTodayString(), []);
147
+ const { dialogLoading, runDialogAction } = dialogLoadingAction.useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
146
148
  const baseReferenceDate = anchorDate || today;
147
149
  const previousOpenRef = React.useRef(false);
148
150
  const startRatio = getRatioByDate((_a = draftRange.startDate) !== null && _a !== void 0 ? _a : baseReferenceDate, trackBounds);
@@ -160,6 +162,9 @@ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEF
160
162
  .map((item) => formatMonthShort(item));
161
163
  return [...new Set(values)];
162
164
  }, [trackBounds.endDate, trackBounds.startDate]);
165
+ const handleApply = React.useCallback(() => {
166
+ return onApply(draftRange);
167
+ }, [draftRange, onApply]);
163
168
  React.useEffect(() => {
164
169
  if (open && !previousOpenRef.current) {
165
170
  const nextRange = {
@@ -372,76 +377,75 @@ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEF
372
377
  };
373
378
  }, [open]);
374
379
  if (!open) {
375
- return null;
380
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: dialogLoading });
376
381
  }
377
- return reactDom.createPortal(jsxRuntime.jsx("div", { className: "fixed inset-0 z-120 flex select-none items-center justify-center bg-slate-950/60 px-3 py-6 backdrop-blur-sm", children: jsxRuntime.jsx("div", { className: "w-full max-w-2xl overflow-hidden rounded-3xl border border-black/10 bg-white shadow-2xl dark:border-white/10 dark:bg-slate-950", children: jsxRuntime.jsxs("div", { className: "space-y-5 p-4", children: [jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center px-16 text-center", children: [jsxRuntime.jsx("div", { ref: resultLabelRef, className: "select-none text-base font-semibold text-slate-900 dark:text-white", children: getRangeLabel(draftRange) }), jsxRuntime.jsxs("div", { className: "absolute right-0 top-1/2 flex -translate-y-1/2 items-center gap-2", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => onOpenChange(false), className: DIALOG_ICON_BUTTON_CLASS_NAME, "aria-label": "Cancel", children: jsxRuntime.jsx(icons.XIcon, { className: "h-4 w-4" }) }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
378
- onApply(draftRange);
379
- onOpenChange(false);
380
- }, disabled: !draftRange.startDate || !draftRange.endDate, className: utils.cn(DIALOG_ICON_BUTTON_CLASS_NAME, 'text-slate-700 dark:text-slate-100', 'disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-black/10 disabled:hover:bg-white disabled:hover:text-slate-700 dark:disabled:hover:border-white/10 dark:disabled:hover:bg-slate-950 dark:disabled:hover:text-slate-100'), "aria-label": "Apply", children: jsxRuntime.jsx(icons.CheckCheckIcon, { className: "h-4 w-4" }) })] })] }), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
381
- flashNavButtonPress('prevYear');
382
- shiftReferenceDateByYears(-1);
383
- }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevYear'
384
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
385
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevYear'), { "aria-label": "Previous year", title: "Previous year", children: jsxRuntime.jsx(icons.ChevronsLeftIcon, { className: "h-4 w-4" }) })), jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
386
- flashNavButtonPress('prevMonth');
387
- shiftReferenceDateByMonths(-1);
388
- }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevMonth'
389
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
390
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevMonth'), { "aria-label": "Previous month", title: "Previous month", children: jsxRuntime.jsx(icons.ChevronLeftIcon, { className: "h-4 w-4" }) }))] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => {
391
- const nextRange = {
392
- startDate: baseReferenceDate,
393
- endDate: addDays(baseReferenceDate, resolvedDefaultRangeDays - 1),
394
- };
395
- setReferenceDate(baseReferenceDate);
396
- setTrackBounds(buildTrackRange(baseReferenceDate, resolvedDefaultRangeDays));
397
- setWindowDays(resolvedDefaultRangeDays);
398
- setDraftRange(nextRange);
399
- onClear === null || onClear === void 0 ? void 0 : onClear(nextRange);
400
- }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "Current Day" }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
401
- const nextRange = {
402
- startDate: getMonthStart(referenceDate),
403
- endDate: addDays(getMonthStart(referenceDate), MAX_RANGE_DAYS - 1),
404
- };
405
- const clampedEndDate = compareDateStrings(nextRange.endDate, getMonthEnd(referenceDate)) > 0
406
- ? getMonthEnd(referenceDate)
407
- : nextRange.endDate;
408
- const normalizedRange = {
409
- startDate: nextRange.startDate,
410
- endDate: clampedEndDate,
411
- };
412
- setDraftRange(normalizedRange);
413
- setWindowDays(getInclusiveDayCount(normalizedRange));
414
- setTrackBounds(buildTrackRange(normalizedRange.startDate, getInclusiveDayCount(normalizedRange)));
415
- }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "This Month" })] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
416
- flashNavButtonPress('nextMonth');
417
- shiftReferenceDateByMonths(1);
418
- }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextMonth'
419
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
420
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextMonth'), { "aria-label": "Next month", title: "Next month", children: jsxRuntime.jsx(icons.ChevronRightIcon, { className: "h-4 w-4" }) })), jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
421
- flashNavButtonPress('nextYear');
422
- shiftReferenceDateByYears(1);
423
- }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextYear'
424
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
425
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextYear'), { "aria-label": "Next year", title: "Next year", children: jsxRuntime.jsx(icons.ChevronsRightIcon, { className: "h-4 w-4" }) }))] })] }), jsxRuntime.jsxs("div", { className: "relative h-24", children: [jsxRuntime.jsxs("div", { className: "absolute inset-x-0 top-0 grid grid-cols-[3.5rem_minmax(0,1fr)_3.5rem] items-center gap-2 text-sm font-semibold text-slate-500 dark:text-slate-400", children: [jsxRuntime.jsxs("span", { className: "relative block select-none text-center", children: [(_g = monthLabels[0]) !== null && _g !== void 0 ? _g : formatMonthShort((_h = trackBounds.startDate) !== null && _h !== void 0 ? _h : baseReferenceDate), jsxRuntime.jsx("span", { className: "pointer-events-none absolute left-1/2 top-7 h-2.5 w-2.5 -translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsxRuntime.jsx("span", { className: "pointer-events-none absolute left-1/2 top-[1.95rem] h-9 w-0.5 -translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] }), jsxRuntime.jsx("div", { className: "flex min-w-0 items-center justify-center gap-1", children: [
426
- { label: '+7', days: 7 },
427
- { label: '+10', days: 10 },
428
- { label: '+15', days: 15 },
429
- { label: '+30', days: 30 },
430
- ].map((item) => (jsxRuntime.jsx("button", { type: "button", onClick: () => applyQuickRange(item.days), className: DIALOG_PILL_BUTTON_COMPACT_CLASS_NAME, children: item.label }, item.label))) }), jsxRuntime.jsxs("span", { className: "relative block select-none text-center", children: [(_j = monthLabels[1]) !== null && _j !== void 0 ? _j : formatMonthShort((_k = trackBounds.endDate) !== null && _k !== void 0 ? _k : baseReferenceDate), jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-1/2 top-7 h-2.5 w-2.5 translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-1/2 top-[1.95rem] h-9 w-0.5 translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] })] }), jsxRuntime.jsx("div", { className: "absolute inset-x-0 top-[3.35rem] h-10 touch-none", onDoubleClick: (event) => {
431
- event.stopPropagation();
432
- resetReferenceFromClientX(event.clientX);
433
- }, children: jsxRuntime.jsxs("div", { ref: trackRef, className: "absolute inset-x-0 top-1/2 h-3 -translate-y-1/2 rounded-full bg-slate-400/30 dark:bg-slate-500/25", children: [jsxRuntime.jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0 top-1/2 grid h-8 -translate-y-1/2 items-center", style: { gridTemplateColumns: `repeat(${trackTickCount}, minmax(0, 1fr))` }, children: Array.from({ length: trackTickCount }, (_, index) => {
434
- return (jsxRuntime.jsx("span", { className: "flex justify-center", children: jsxRuntime.jsx("span", { className: utils.cn('rounded-full bg-slate-400/55 dark:bg-slate-500/55', 'h-3 w-px') }) }, index));
435
- }) }), jsxRuntime.jsx("div", { ref: selectionRef, className: "absolute top-1/2 z-10 h-4 touch-none -translate-y-1/2 overflow-visible rounded-md border border-sky-500 bg-white dark:border-sky-300 dark:bg-slate-950", style: { left: `${leftPercent}%`, width: `${widthPercent}%` }, onPointerDown: (event) => {
436
- event.stopPropagation();
437
- beginDrag('window', event.pointerId, event.clientX);
438
- }, children: jsxRuntime.jsx("div", { ref: selectionDaysRef, className: "pointer-events-none absolute inset-0 z-30 flex select-none items-center justify-center text-xs font-semibold text-sky-700 dark:text-sky-100", children: `${getInclusiveDayCount(draftRange)}D` }) }), jsxRuntime.jsx("button", { ref: startHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${startHandlePercent}%` }, onPointerDown: (event) => {
439
- event.stopPropagation();
440
- beginDrag('start', event.pointerId);
441
- }, "aria-label": "Adjust start date" }), jsxRuntime.jsx("button", { ref: endHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${endHandlePercent}%` }, onPointerDown: (event) => {
442
- event.stopPropagation();
443
- beginDrag('end', event.pointerId);
444
- }, "aria-label": "Adjust end date" })] }) })] })] })] }) }) }), document.body);
382
+ return reactDom.createPortal(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "fixed inset-0 z-120 flex select-none items-center justify-center bg-slate-950/60 px-3 py-6 backdrop-blur-sm", children: jsxRuntime.jsx("div", { className: "w-full max-w-2xl overflow-hidden rounded-3xl border border-black/10 bg-white shadow-2xl dark:border-white/10 dark:bg-slate-950", children: jsxRuntime.jsxs("div", { className: "space-y-5 p-4", children: [jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center px-16 text-center", children: [jsxRuntime.jsx("div", { ref: resultLabelRef, className: "select-none text-base font-semibold text-slate-900 dark:text-white", children: getRangeLabel(draftRange) }), jsxRuntime.jsxs("div", { className: "absolute right-0 top-1/2 flex -translate-y-1/2 items-center gap-2", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => onOpenChange(false), className: DIALOG_ICON_BUTTON_CLASS_NAME, "aria-label": "Cancel", children: jsxRuntime.jsx(icons.XIcon, { className: "h-4 w-4" }) }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
383
+ void runDialogAction('confirm', handleApply);
384
+ }, disabled: !draftRange.startDate || !draftRange.endDate, className: utils.cn(DIALOG_ICON_BUTTON_CLASS_NAME, 'text-slate-700 dark:text-slate-100', 'disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-black/10 disabled:hover:bg-white disabled:hover:text-slate-700 dark:disabled:hover:border-white/10 dark:disabled:hover:bg-slate-950 dark:disabled:hover:text-slate-100'), "aria-label": "Apply", children: jsxRuntime.jsx(icons.CheckCheckIcon, { className: "h-4 w-4" }) })] })] }), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
385
+ flashNavButtonPress('prevYear');
386
+ shiftReferenceDateByYears(-1);
387
+ }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevYear'
388
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
389
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevYear'), { "aria-label": "Previous year", title: "Previous year", children: jsxRuntime.jsx(icons.ChevronsLeftIcon, { className: "h-4 w-4" }) })), jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
390
+ flashNavButtonPress('prevMonth');
391
+ shiftReferenceDateByMonths(-1);
392
+ }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevMonth'
393
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
394
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevMonth'), { "aria-label": "Previous month", title: "Previous month", children: jsxRuntime.jsx(icons.ChevronLeftIcon, { className: "h-4 w-4" }) }))] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => {
395
+ const nextRange = {
396
+ startDate: baseReferenceDate,
397
+ endDate: addDays(baseReferenceDate, resolvedDefaultRangeDays - 1),
398
+ };
399
+ setReferenceDate(baseReferenceDate);
400
+ setTrackBounds(buildTrackRange(baseReferenceDate, resolvedDefaultRangeDays));
401
+ setWindowDays(resolvedDefaultRangeDays);
402
+ setDraftRange(nextRange);
403
+ onClear === null || onClear === void 0 ? void 0 : onClear(nextRange);
404
+ }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "Current Day" }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
405
+ const nextRange = {
406
+ startDate: getMonthStart(referenceDate),
407
+ endDate: addDays(getMonthStart(referenceDate), MAX_RANGE_DAYS - 1),
408
+ };
409
+ const clampedEndDate = compareDateStrings(nextRange.endDate, getMonthEnd(referenceDate)) > 0
410
+ ? getMonthEnd(referenceDate)
411
+ : nextRange.endDate;
412
+ const normalizedRange = {
413
+ startDate: nextRange.startDate,
414
+ endDate: clampedEndDate,
415
+ };
416
+ setDraftRange(normalizedRange);
417
+ setWindowDays(getInclusiveDayCount(normalizedRange));
418
+ setTrackBounds(buildTrackRange(normalizedRange.startDate, getInclusiveDayCount(normalizedRange)));
419
+ }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "This Month" })] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
420
+ flashNavButtonPress('nextMonth');
421
+ shiftReferenceDateByMonths(1);
422
+ }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextMonth'
423
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
424
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextMonth'), { "aria-label": "Next month", title: "Next month", children: jsxRuntime.jsx(icons.ChevronRightIcon, { className: "h-4 w-4" }) })), jsxRuntime.jsx("button", Object.assign({ type: "button", onClick: () => {
425
+ flashNavButtonPress('nextYear');
426
+ shiftReferenceDateByYears(1);
427
+ }, className: utils.cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextYear'
428
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
429
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextYear'), { "aria-label": "Next year", title: "Next year", children: jsxRuntime.jsx(icons.ChevronsRightIcon, { className: "h-4 w-4" }) }))] })] }), jsxRuntime.jsxs("div", { className: "relative h-24", children: [jsxRuntime.jsxs("div", { className: "absolute inset-x-0 top-0 grid grid-cols-[3.5rem_minmax(0,1fr)_3.5rem] items-center gap-2 text-sm font-semibold text-slate-500 dark:text-slate-400", children: [jsxRuntime.jsxs("span", { className: "relative block select-none text-center", children: [(_g = monthLabels[0]) !== null && _g !== void 0 ? _g : formatMonthShort((_h = trackBounds.startDate) !== null && _h !== void 0 ? _h : baseReferenceDate), jsxRuntime.jsx("span", { className: "pointer-events-none absolute left-1/2 top-7 h-2.5 w-2.5 -translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsxRuntime.jsx("span", { className: "pointer-events-none absolute left-1/2 top-[1.95rem] h-9 w-0.5 -translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] }), jsxRuntime.jsx("div", { className: "flex min-w-0 items-center justify-center gap-1", children: [
430
+ { label: '+7', days: 7 },
431
+ { label: '+10', days: 10 },
432
+ { label: '+15', days: 15 },
433
+ { label: '+30', days: 30 },
434
+ ].map((item) => (jsxRuntime.jsx("button", { type: "button", onClick: () => applyQuickRange(item.days), className: DIALOG_PILL_BUTTON_COMPACT_CLASS_NAME, children: item.label }, item.label))) }), jsxRuntime.jsxs("span", { className: "relative block select-none text-center", children: [(_j = monthLabels[1]) !== null && _j !== void 0 ? _j : formatMonthShort((_k = trackBounds.endDate) !== null && _k !== void 0 ? _k : baseReferenceDate), jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-1/2 top-7 h-2.5 w-2.5 translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-1/2 top-[1.95rem] h-9 w-0.5 translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] })] }), jsxRuntime.jsx("div", { className: "absolute inset-x-0 top-[3.35rem] h-10 touch-none", onDoubleClick: (event) => {
435
+ event.stopPropagation();
436
+ resetReferenceFromClientX(event.clientX);
437
+ }, children: jsxRuntime.jsxs("div", { ref: trackRef, className: "absolute inset-x-0 top-1/2 h-3 -translate-y-1/2 rounded-full bg-slate-400/30 dark:bg-slate-500/25", children: [jsxRuntime.jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0 top-1/2 grid h-8 -translate-y-1/2 items-center", style: { gridTemplateColumns: `repeat(${trackTickCount}, minmax(0, 1fr))` }, children: Array.from({ length: trackTickCount }, (_, index) => {
438
+ return (jsxRuntime.jsx("span", { className: "flex justify-center", children: jsxRuntime.jsx("span", { className: utils.cn('rounded-full bg-slate-400/55 dark:bg-slate-500/55', 'h-3 w-px') }) }, index));
439
+ }) }), jsxRuntime.jsx("div", { ref: selectionRef, className: "absolute top-1/2 z-10 h-4 touch-none -translate-y-1/2 overflow-visible rounded-md border border-sky-500 bg-white dark:border-sky-300 dark:bg-slate-950", style: { left: `${leftPercent}%`, width: `${widthPercent}%` }, onPointerDown: (event) => {
440
+ event.stopPropagation();
441
+ beginDrag('window', event.pointerId, event.clientX);
442
+ }, children: jsxRuntime.jsx("div", { ref: selectionDaysRef, className: "pointer-events-none absolute inset-0 z-30 flex select-none items-center justify-center text-xs font-semibold text-sky-700 dark:text-sky-100", children: `${getInclusiveDayCount(draftRange)}D` }) }), jsxRuntime.jsx("button", { ref: startHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${startHandlePercent}%` }, onPointerDown: (event) => {
443
+ event.stopPropagation();
444
+ beginDrag('start', event.pointerId);
445
+ }, "aria-label": "Adjust start date" }), jsxRuntime.jsx("button", { ref: endHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${endHandlePercent}%` }, onPointerDown: (event) => {
446
+ event.stopPropagation();
447
+ beginDrag('end', event.pointerId);
448
+ }, "aria-label": "Adjust end date" })] }) })] })] })] }) }) }), dialogLoading] }), document.body);
445
449
  }
446
450
 
447
451
  exports.RandomDateRangeDialog = RandomDateRangeDialog;
@@ -1,9 +1,10 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
2
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
+ import { useState, useRef, useMemo, useCallback, useEffect } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { XIcon, CheckCheckIcon, ChevronsLeftIcon, ChevronLeftIcon, ChevronRightIcon, ChevronsRightIcon } from '@windrun-huaiin/base-ui/icons';
6
6
  import { cn } from '@windrun-huaiin/lib/utils';
7
+ import { useDialogLoadingAction } from '../alert-dialog/dialog-loading-action.mjs';
7
8
  import { usePressFeedback } from '../buttons/use-press-feedback.mjs';
8
9
 
9
10
  const DEFAULT_RANGE_DAYS = 7;
@@ -116,7 +117,7 @@ function getMonthEnd(value) {
116
117
  const date = parseDateString(value);
117
118
  return formatDateString(new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0)));
118
119
  }
119
- function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEFAULT_RANGE_DAYS, onOpenChange, onApply, onClear, }) {
120
+ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEFAULT_RANGE_DAYS, onOpenChange, loadingActions, loadingFullPage, onApply, onClear, }) {
120
121
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
121
122
  const resolvedDefaultRangeDays = clampWindowDays(defaultRangeDays);
122
123
  const [draftRange, setDraftRange] = useState(value);
@@ -141,6 +142,7 @@ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEF
141
142
  const buildDraggedRangeRef = useRef(() => null);
142
143
  const previousBodyOverflowRef = useRef(null);
143
144
  const today = useMemo(() => getTodayString(), []);
145
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
144
146
  const baseReferenceDate = anchorDate || today;
145
147
  const previousOpenRef = useRef(false);
146
148
  const startRatio = getRatioByDate((_a = draftRange.startDate) !== null && _a !== void 0 ? _a : baseReferenceDate, trackBounds);
@@ -158,6 +160,9 @@ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEF
158
160
  .map((item) => formatMonthShort(item));
159
161
  return [...new Set(values)];
160
162
  }, [trackBounds.endDate, trackBounds.startDate]);
163
+ const handleApply = useCallback(() => {
164
+ return onApply(draftRange);
165
+ }, [draftRange, onApply]);
161
166
  useEffect(() => {
162
167
  if (open && !previousOpenRef.current) {
163
168
  const nextRange = {
@@ -370,76 +375,75 @@ function RandomDateRangeDialog({ open, value, anchorDate, defaultRangeDays = DEF
370
375
  };
371
376
  }, [open]);
372
377
  if (!open) {
373
- return null;
378
+ return jsx(Fragment, { children: dialogLoading });
374
379
  }
375
- return createPortal(jsx("div", { className: "fixed inset-0 z-120 flex select-none items-center justify-center bg-slate-950/60 px-3 py-6 backdrop-blur-sm", children: jsx("div", { className: "w-full max-w-2xl overflow-hidden rounded-3xl border border-black/10 bg-white shadow-2xl dark:border-white/10 dark:bg-slate-950", children: jsxs("div", { className: "space-y-5 p-4", children: [jsxs("div", { className: "relative flex items-center justify-center px-16 text-center", children: [jsx("div", { ref: resultLabelRef, className: "select-none text-base font-semibold text-slate-900 dark:text-white", children: getRangeLabel(draftRange) }), jsxs("div", { className: "absolute right-0 top-1/2 flex -translate-y-1/2 items-center gap-2", children: [jsx("button", { type: "button", onClick: () => onOpenChange(false), className: DIALOG_ICON_BUTTON_CLASS_NAME, "aria-label": "Cancel", children: jsx(XIcon, { className: "h-4 w-4" }) }), jsx("button", { type: "button", onClick: () => {
376
- onApply(draftRange);
377
- onOpenChange(false);
378
- }, disabled: !draftRange.startDate || !draftRange.endDate, className: cn(DIALOG_ICON_BUTTON_CLASS_NAME, 'text-slate-700 dark:text-slate-100', 'disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-black/10 disabled:hover:bg-white disabled:hover:text-slate-700 dark:disabled:hover:border-white/10 dark:disabled:hover:bg-slate-950 dark:disabled:hover:text-slate-100'), "aria-label": "Apply", children: jsx(CheckCheckIcon, { className: "h-4 w-4" }) })] })] }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsxs("div", { className: "flex items-center gap-1", children: [jsx("button", Object.assign({ type: "button", onClick: () => {
379
- flashNavButtonPress('prevYear');
380
- shiftReferenceDateByYears(-1);
381
- }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevYear'
382
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
383
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevYear'), { "aria-label": "Previous year", title: "Previous year", children: jsx(ChevronsLeftIcon, { className: "h-4 w-4" }) })), jsx("button", Object.assign({ type: "button", onClick: () => {
384
- flashNavButtonPress('prevMonth');
385
- shiftReferenceDateByMonths(-1);
386
- }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevMonth'
387
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
388
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevMonth'), { "aria-label": "Previous month", title: "Previous month", children: jsx(ChevronLeftIcon, { className: "h-4 w-4" }) }))] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx("button", { type: "button", onClick: () => {
389
- const nextRange = {
390
- startDate: baseReferenceDate,
391
- endDate: addDays(baseReferenceDate, resolvedDefaultRangeDays - 1),
392
- };
393
- setReferenceDate(baseReferenceDate);
394
- setTrackBounds(buildTrackRange(baseReferenceDate, resolvedDefaultRangeDays));
395
- setWindowDays(resolvedDefaultRangeDays);
396
- setDraftRange(nextRange);
397
- onClear === null || onClear === void 0 ? void 0 : onClear(nextRange);
398
- }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "Current Day" }), jsx("button", { type: "button", onClick: () => {
399
- const nextRange = {
400
- startDate: getMonthStart(referenceDate),
401
- endDate: addDays(getMonthStart(referenceDate), MAX_RANGE_DAYS - 1),
402
- };
403
- const clampedEndDate = compareDateStrings(nextRange.endDate, getMonthEnd(referenceDate)) > 0
404
- ? getMonthEnd(referenceDate)
405
- : nextRange.endDate;
406
- const normalizedRange = {
407
- startDate: nextRange.startDate,
408
- endDate: clampedEndDate,
409
- };
410
- setDraftRange(normalizedRange);
411
- setWindowDays(getInclusiveDayCount(normalizedRange));
412
- setTrackBounds(buildTrackRange(normalizedRange.startDate, getInclusiveDayCount(normalizedRange)));
413
- }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "This Month" })] }), jsxs("div", { className: "flex items-center gap-1", children: [jsx("button", Object.assign({ type: "button", onClick: () => {
414
- flashNavButtonPress('nextMonth');
415
- shiftReferenceDateByMonths(1);
416
- }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextMonth'
417
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
418
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextMonth'), { "aria-label": "Next month", title: "Next month", children: jsx(ChevronRightIcon, { className: "h-4 w-4" }) })), jsx("button", Object.assign({ type: "button", onClick: () => {
419
- flashNavButtonPress('nextYear');
420
- shiftReferenceDateByYears(1);
421
- }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextYear'
422
- ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
423
- : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextYear'), { "aria-label": "Next year", title: "Next year", children: jsx(ChevronsRightIcon, { className: "h-4 w-4" }) }))] })] }), jsxs("div", { className: "relative h-24", children: [jsxs("div", { className: "absolute inset-x-0 top-0 grid grid-cols-[3.5rem_minmax(0,1fr)_3.5rem] items-center gap-2 text-sm font-semibold text-slate-500 dark:text-slate-400", children: [jsxs("span", { className: "relative block select-none text-center", children: [(_g = monthLabels[0]) !== null && _g !== void 0 ? _g : formatMonthShort((_h = trackBounds.startDate) !== null && _h !== void 0 ? _h : baseReferenceDate), jsx("span", { className: "pointer-events-none absolute left-1/2 top-7 h-2.5 w-2.5 -translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsx("span", { className: "pointer-events-none absolute left-1/2 top-[1.95rem] h-9 w-0.5 -translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] }), jsx("div", { className: "flex min-w-0 items-center justify-center gap-1", children: [
424
- { label: '+7', days: 7 },
425
- { label: '+10', days: 10 },
426
- { label: '+15', days: 15 },
427
- { label: '+30', days: 30 },
428
- ].map((item) => (jsx("button", { type: "button", onClick: () => applyQuickRange(item.days), className: DIALOG_PILL_BUTTON_COMPACT_CLASS_NAME, children: item.label }, item.label))) }), jsxs("span", { className: "relative block select-none text-center", children: [(_j = monthLabels[1]) !== null && _j !== void 0 ? _j : formatMonthShort((_k = trackBounds.endDate) !== null && _k !== void 0 ? _k : baseReferenceDate), jsx("span", { className: "pointer-events-none absolute right-1/2 top-7 h-2.5 w-2.5 translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsx("span", { className: "pointer-events-none absolute right-1/2 top-[1.95rem] h-9 w-0.5 translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] })] }), jsx("div", { className: "absolute inset-x-0 top-[3.35rem] h-10 touch-none", onDoubleClick: (event) => {
429
- event.stopPropagation();
430
- resetReferenceFromClientX(event.clientX);
431
- }, children: jsxs("div", { ref: trackRef, className: "absolute inset-x-0 top-1/2 h-3 -translate-y-1/2 rounded-full bg-slate-400/30 dark:bg-slate-500/25", children: [jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0 top-1/2 grid h-8 -translate-y-1/2 items-center", style: { gridTemplateColumns: `repeat(${trackTickCount}, minmax(0, 1fr))` }, children: Array.from({ length: trackTickCount }, (_, index) => {
432
- return (jsx("span", { className: "flex justify-center", children: jsx("span", { className: cn('rounded-full bg-slate-400/55 dark:bg-slate-500/55', 'h-3 w-px') }) }, index));
433
- }) }), jsx("div", { ref: selectionRef, className: "absolute top-1/2 z-10 h-4 touch-none -translate-y-1/2 overflow-visible rounded-md border border-sky-500 bg-white dark:border-sky-300 dark:bg-slate-950", style: { left: `${leftPercent}%`, width: `${widthPercent}%` }, onPointerDown: (event) => {
434
- event.stopPropagation();
435
- beginDrag('window', event.pointerId, event.clientX);
436
- }, children: jsx("div", { ref: selectionDaysRef, className: "pointer-events-none absolute inset-0 z-30 flex select-none items-center justify-center text-xs font-semibold text-sky-700 dark:text-sky-100", children: `${getInclusiveDayCount(draftRange)}D` }) }), jsx("button", { ref: startHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${startHandlePercent}%` }, onPointerDown: (event) => {
437
- event.stopPropagation();
438
- beginDrag('start', event.pointerId);
439
- }, "aria-label": "Adjust start date" }), jsx("button", { ref: endHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${endHandlePercent}%` }, onPointerDown: (event) => {
440
- event.stopPropagation();
441
- beginDrag('end', event.pointerId);
442
- }, "aria-label": "Adjust end date" })] }) })] })] })] }) }) }), document.body);
380
+ return createPortal(jsxs(Fragment, { children: [jsx("div", { className: "fixed inset-0 z-120 flex select-none items-center justify-center bg-slate-950/60 px-3 py-6 backdrop-blur-sm", children: jsx("div", { className: "w-full max-w-2xl overflow-hidden rounded-3xl border border-black/10 bg-white shadow-2xl dark:border-white/10 dark:bg-slate-950", children: jsxs("div", { className: "space-y-5 p-4", children: [jsxs("div", { className: "relative flex items-center justify-center px-16 text-center", children: [jsx("div", { ref: resultLabelRef, className: "select-none text-base font-semibold text-slate-900 dark:text-white", children: getRangeLabel(draftRange) }), jsxs("div", { className: "absolute right-0 top-1/2 flex -translate-y-1/2 items-center gap-2", children: [jsx("button", { type: "button", onClick: () => onOpenChange(false), className: DIALOG_ICON_BUTTON_CLASS_NAME, "aria-label": "Cancel", children: jsx(XIcon, { className: "h-4 w-4" }) }), jsx("button", { type: "button", onClick: () => {
381
+ void runDialogAction('confirm', handleApply);
382
+ }, disabled: !draftRange.startDate || !draftRange.endDate, className: cn(DIALOG_ICON_BUTTON_CLASS_NAME, 'text-slate-700 dark:text-slate-100', 'disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-black/10 disabled:hover:bg-white disabled:hover:text-slate-700 dark:disabled:hover:border-white/10 dark:disabled:hover:bg-slate-950 dark:disabled:hover:text-slate-100'), "aria-label": "Apply", children: jsx(CheckCheckIcon, { className: "h-4 w-4" }) })] })] }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsxs("div", { className: "flex items-center gap-1", children: [jsx("button", Object.assign({ type: "button", onClick: () => {
383
+ flashNavButtonPress('prevYear');
384
+ shiftReferenceDateByYears(-1);
385
+ }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevYear'
386
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
387
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevYear'), { "aria-label": "Previous year", title: "Previous year", children: jsx(ChevronsLeftIcon, { className: "h-4 w-4" }) })), jsx("button", Object.assign({ type: "button", onClick: () => {
388
+ flashNavButtonPress('prevMonth');
389
+ shiftReferenceDateByMonths(-1);
390
+ }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'prevMonth'
391
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
392
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('prevMonth'), { "aria-label": "Previous month", title: "Previous month", children: jsx(ChevronLeftIcon, { className: "h-4 w-4" }) }))] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx("button", { type: "button", onClick: () => {
393
+ const nextRange = {
394
+ startDate: baseReferenceDate,
395
+ endDate: addDays(baseReferenceDate, resolvedDefaultRangeDays - 1),
396
+ };
397
+ setReferenceDate(baseReferenceDate);
398
+ setTrackBounds(buildTrackRange(baseReferenceDate, resolvedDefaultRangeDays));
399
+ setWindowDays(resolvedDefaultRangeDays);
400
+ setDraftRange(nextRange);
401
+ onClear === null || onClear === void 0 ? void 0 : onClear(nextRange);
402
+ }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "Current Day" }), jsx("button", { type: "button", onClick: () => {
403
+ const nextRange = {
404
+ startDate: getMonthStart(referenceDate),
405
+ endDate: addDays(getMonthStart(referenceDate), MAX_RANGE_DAYS - 1),
406
+ };
407
+ const clampedEndDate = compareDateStrings(nextRange.endDate, getMonthEnd(referenceDate)) > 0
408
+ ? getMonthEnd(referenceDate)
409
+ : nextRange.endDate;
410
+ const normalizedRange = {
411
+ startDate: nextRange.startDate,
412
+ endDate: clampedEndDate,
413
+ };
414
+ setDraftRange(normalizedRange);
415
+ setWindowDays(getInclusiveDayCount(normalizedRange));
416
+ setTrackBounds(buildTrackRange(normalizedRange.startDate, getInclusiveDayCount(normalizedRange)));
417
+ }, className: DIALOG_PILL_BUTTON_CLASS_NAME, children: "This Month" })] }), jsxs("div", { className: "flex items-center gap-1", children: [jsx("button", Object.assign({ type: "button", onClick: () => {
418
+ flashNavButtonPress('nextMonth');
419
+ shiftReferenceDateByMonths(1);
420
+ }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextMonth'
421
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
422
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextMonth'), { "aria-label": "Next month", title: "Next month", children: jsx(ChevronRightIcon, { className: "h-4 w-4" }) })), jsx("button", Object.assign({ type: "button", onClick: () => {
423
+ flashNavButtonPress('nextYear');
424
+ shiftReferenceDateByYears(1);
425
+ }, className: cn(DIALOG_NAV_BUTTON_CLASS_NAME, pressedNavButton === 'nextYear'
426
+ ? DIALOG_NAV_BUTTON_PRESSED_CLASS_NAME
427
+ : DIALOG_NAV_BUTTON_REST_CLASS_NAME) }, getNavButtonPressProps('nextYear'), { "aria-label": "Next year", title: "Next year", children: jsx(ChevronsRightIcon, { className: "h-4 w-4" }) }))] })] }), jsxs("div", { className: "relative h-24", children: [jsxs("div", { className: "absolute inset-x-0 top-0 grid grid-cols-[3.5rem_minmax(0,1fr)_3.5rem] items-center gap-2 text-sm font-semibold text-slate-500 dark:text-slate-400", children: [jsxs("span", { className: "relative block select-none text-center", children: [(_g = monthLabels[0]) !== null && _g !== void 0 ? _g : formatMonthShort((_h = trackBounds.startDate) !== null && _h !== void 0 ? _h : baseReferenceDate), jsx("span", { className: "pointer-events-none absolute left-1/2 top-7 h-2.5 w-2.5 -translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsx("span", { className: "pointer-events-none absolute left-1/2 top-[1.95rem] h-9 w-0.5 -translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] }), jsx("div", { className: "flex min-w-0 items-center justify-center gap-1", children: [
428
+ { label: '+7', days: 7 },
429
+ { label: '+10', days: 10 },
430
+ { label: '+15', days: 15 },
431
+ { label: '+30', days: 30 },
432
+ ].map((item) => (jsx("button", { type: "button", onClick: () => applyQuickRange(item.days), className: DIALOG_PILL_BUTTON_COMPACT_CLASS_NAME, children: item.label }, item.label))) }), jsxs("span", { className: "relative block select-none text-center", children: [(_j = monthLabels[1]) !== null && _j !== void 0 ? _j : formatMonthShort((_k = trackBounds.endDate) !== null && _k !== void 0 ? _k : baseReferenceDate), jsx("span", { className: "pointer-events-none absolute right-1/2 top-7 h-2.5 w-2.5 translate-x-1/2 rounded-full bg-slate-400 dark:bg-slate-500" }), jsx("span", { className: "pointer-events-none absolute right-1/2 top-[1.95rem] h-9 w-0.5 translate-x-1/2 bg-slate-400 dark:bg-slate-500" })] })] }), jsx("div", { className: "absolute inset-x-0 top-[3.35rem] h-10 touch-none", onDoubleClick: (event) => {
433
+ event.stopPropagation();
434
+ resetReferenceFromClientX(event.clientX);
435
+ }, children: jsxs("div", { ref: trackRef, className: "absolute inset-x-0 top-1/2 h-3 -translate-y-1/2 rounded-full bg-slate-400/30 dark:bg-slate-500/25", children: [jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0 top-1/2 grid h-8 -translate-y-1/2 items-center", style: { gridTemplateColumns: `repeat(${trackTickCount}, minmax(0, 1fr))` }, children: Array.from({ length: trackTickCount }, (_, index) => {
436
+ return (jsx("span", { className: "flex justify-center", children: jsx("span", { className: cn('rounded-full bg-slate-400/55 dark:bg-slate-500/55', 'h-3 w-px') }) }, index));
437
+ }) }), jsx("div", { ref: selectionRef, className: "absolute top-1/2 z-10 h-4 touch-none -translate-y-1/2 overflow-visible rounded-md border border-sky-500 bg-white dark:border-sky-300 dark:bg-slate-950", style: { left: `${leftPercent}%`, width: `${widthPercent}%` }, onPointerDown: (event) => {
438
+ event.stopPropagation();
439
+ beginDrag('window', event.pointerId, event.clientX);
440
+ }, children: jsx("div", { ref: selectionDaysRef, className: "pointer-events-none absolute inset-0 z-30 flex select-none items-center justify-center text-xs font-semibold text-sky-700 dark:text-sky-100", children: `${getInclusiveDayCount(draftRange)}D` }) }), jsx("button", { ref: startHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${startHandlePercent}%` }, onPointerDown: (event) => {
441
+ event.stopPropagation();
442
+ beginDrag('start', event.pointerId);
443
+ }, "aria-label": "Adjust start date" }), jsx("button", { ref: endHandleRef, type: "button", className: "absolute top-1/2 z-20 h-6 w-6 touch-none -translate-x-1/2 -translate-y-1/2 rounded-full border border-sky-500 bg-white shadow-sm dark:border-sky-300 dark:bg-slate-950", style: { left: `${endHandlePercent}%` }, onPointerDown: (event) => {
444
+ event.stopPropagation();
445
+ beginDrag('end', event.pointerId);
446
+ }, "aria-label": "Adjust end date" })] }) })] })] })] }) }) }), dialogLoading] }), document.body);
443
447
  }
444
448
 
445
449
  export { RandomDateRangeDialog };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windrun-huaiin/third-ui",
3
- "version": "29.2.0",
3
+ "version": "29.2.1",
4
4
  "description": "Third-party integrated UI components for windrun-huaiin projects",
5
5
  "exports": {
6
6
  "./clerk": {
@@ -233,8 +233,8 @@
233
233
  "unified": "^11.0.5",
234
234
  "zod": "^4.3.6",
235
235
  "@windrun-huaiin/base-ui": "^29.0.2",
236
- "@windrun-huaiin/lib": "^29.0.0",
237
- "@windrun-huaiin/contracts": "^29.0.0"
236
+ "@windrun-huaiin/contracts": "^29.0.0",
237
+ "@windrun-huaiin/lib": "^29.0.0"
238
238
  },
239
239
  "peerDependencies": {
240
240
  "clsx": "^2.1.1",
@@ -39,6 +39,7 @@ interface ConfirmDialogProps {
39
39
  confirmText?: string;
40
40
  emphasis?: ConfirmDialogEmphasis;
41
41
  loadingActions?: readonly DialogLoadingAction[];
42
+ loadingFullPage?: boolean;
42
43
  onCancel?: DialogActionHandler;
43
44
  onConfirm?: DialogActionHandler;
44
45
  }
@@ -76,6 +77,7 @@ export function ConfirmDialog({
76
77
  confirmText = 'Confirm',
77
78
  emphasis = 'confirm',
78
79
  loadingActions,
80
+ loadingFullPage,
79
81
  onCancel,
80
82
  onConfirm,
81
83
  }: ConfirmDialogProps) {
@@ -83,7 +85,7 @@ export function ConfirmDialog({
83
85
  const Icon = typeClass.Icon;
84
86
  const cancelButtonClass = emphasis === 'cancel' ? typeClass.action : secondaryButtonClass;
85
87
  const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : typeClass.action;
86
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
88
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
87
89
 
88
90
  const handleCancel = () => {
89
91
  void runDialogAction('cancel', onCancel);
@@ -9,11 +9,13 @@ export type DialogActionHandler = () => void | Promise<void>;
9
9
 
10
10
  interface UseDialogLoadingActionOptions {
11
11
  loadingActions?: readonly DialogLoadingAction[];
12
+ loadingFullPage?: boolean;
12
13
  onOpenChange: (open: boolean) => void;
13
14
  }
14
15
 
15
16
  export function useDialogLoadingAction({
16
17
  loadingActions,
18
+ loadingFullPage = false,
17
19
  onOpenChange,
18
20
  }: UseDialogLoadingActionOptions) {
19
21
  const [mounted, setMounted] = React.useState(false);
@@ -49,9 +51,22 @@ export function useDialogLoadingAction({
49
51
 
50
52
  const dialogLoading = mounted && loading
51
53
  ? createPortal(
52
- <div className="fixed inset-0 z-10000">
53
- <Loading className="h-full w-full" />
54
- </div>,
54
+ loadingFullPage ? (
55
+ <div className="fixed inset-0 z-10000">
56
+ <Loading className="h-full w-full" />
57
+ </div>
58
+ ) : (
59
+ <div className="pointer-events-none fixed inset-0 z-10000 flex items-center justify-center p-4">
60
+ <div className="pointer-events-auto overflow-hidden rounded-[28px] bg-neutral-50/58 shadow-[0_18px_56px_rgba(15,23,42,0.14)] backdrop-blur-md dark:bg-neutral-900/58 dark:shadow-[0_18px_56px_rgba(0,0,0,0.34)]">
61
+ <Loading
62
+ compact
63
+ label="Loading"
64
+ className="min-h-[250px] w-[min(22rem,calc(100vw-2rem))] bg-transparent"
65
+ labelClassName="text-foreground"
66
+ />
67
+ </div>
68
+ </div>
69
+ ),
55
70
  document.body
56
71
  )
57
72
  : null;
@@ -27,6 +27,7 @@ interface HighPriorityConfirmDialogProps {
27
27
  confirmText?: string;
28
28
  cancelText?: string;
29
29
  loadingActions?: readonly DialogLoadingAction[];
30
+ loadingFullPage?: boolean;
30
31
  }
31
32
 
32
33
  export function HighPriorityConfirmDialog({
@@ -39,9 +40,10 @@ export function HighPriorityConfirmDialog({
39
40
  confirmText = "Confirm",
40
41
  cancelText = "Cancel",
41
42
  loadingActions,
43
+ loadingFullPage,
42
44
  }: HighPriorityConfirmDialogProps) {
43
45
  const [mounted, setMounted] = useState(false);
44
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
46
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
45
47
 
46
48
  useEffect(() => {
47
49
  // Ensure portal target exists and prevent hydration mismatch
@@ -38,6 +38,7 @@ interface InfoDialogProps {
38
38
  description: React.ReactNode;
39
39
  confirmText?: string;
40
40
  loadingActions?: readonly DialogLoadingAction[];
41
+ loadingFullPage?: boolean;
41
42
  onConfirm?: DialogActionHandler;
42
43
  }
43
44
 
@@ -86,12 +87,13 @@ export function InfoDialog({
86
87
  description,
87
88
  confirmText = 'OK',
88
89
  loadingActions,
90
+ loadingFullPage,
89
91
  onConfirm,
90
92
  }: InfoDialogProps) {
91
93
  const typeClass = infoTypeClassMap[type];
92
94
  const Icon = typeClass.Icon;
93
95
  const handleClose = () => onOpenChange(false);
94
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
96
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
95
97
 
96
98
  return (
97
99
  <>
@@ -37,6 +37,7 @@ export interface UndoableConfirmDialogProps {
37
37
  emphasis?: ConfirmDialogEmphasis;
38
38
  countdownSeconds?: number;
39
39
  loadingActions?: readonly DialogLoadingAction[];
40
+ loadingFullPage?: boolean;
40
41
  onCancel?: DialogActionHandler;
41
42
  onConfirm: DialogActionHandler;
42
43
  onUndo?: DialogActionHandler;
@@ -55,6 +56,7 @@ export function UndoableConfirmDialog({
55
56
  emphasis = 'confirm',
56
57
  countdownSeconds = 5,
57
58
  loadingActions,
59
+ loadingFullPage,
58
60
  onCancel,
59
61
  onConfirm,
60
62
  onUndo,
@@ -67,7 +69,7 @@ export function UndoableConfirmDialog({
67
69
  const intervalRef = React.useRef<number | null>(null);
68
70
  const cancelButtonClass = emphasis === 'cancel' ? dangerButtonClass : secondaryButtonClass;
69
71
  const confirmButtonClass = emphasis === 'cancel' ? secondaryButtonClass : dangerButtonClass;
70
- const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, onOpenChange });
72
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
71
73
 
72
74
  const clearTimers = React.useCallback(() => {
73
75
  if (timeoutRef.current) {
@@ -11,6 +11,7 @@ import {
11
11
  XIcon,
12
12
  } from '@windrun-huaiin/base-ui/icons';
13
13
  import { cn } from '@windrun-huaiin/lib/utils';
14
+ import { DialogLoadingAction, DialogActionHandler, useDialogLoadingAction } from '../alert-dialog/dialog-loading-action';
14
15
  import { usePressFeedback } from '../buttons/use-press-feedback';
15
16
 
16
17
  export type RandomCalendarRange = {
@@ -24,7 +25,9 @@ type RandomDateRangeDialogProps = {
24
25
  anchorDate: string;
25
26
  defaultRangeDays?: number;
26
27
  onOpenChange: (open: boolean) => void;
27
- onApply: (range: RandomCalendarRange) => void;
28
+ loadingActions?: readonly DialogLoadingAction[];
29
+ loadingFullPage?: boolean;
30
+ onApply: (range: RandomCalendarRange) => void | Promise<void>;
28
31
  onClear?: (range: RandomCalendarRange) => void;
29
32
  };
30
33
 
@@ -180,6 +183,8 @@ export function RandomDateRangeDialog({
180
183
  anchorDate,
181
184
  defaultRangeDays = DEFAULT_RANGE_DAYS,
182
185
  onOpenChange,
186
+ loadingActions,
187
+ loadingFullPage,
183
188
  onApply,
184
189
  onClear,
185
190
  }: RandomDateRangeDialogProps) {
@@ -210,6 +215,7 @@ export function RandomDateRangeDialog({
210
215
  const buildDraggedRangeRef = useRef<(clientX: number) => RandomCalendarRange | null>(() => null);
211
216
  const previousBodyOverflowRef = useRef<string | null>(null);
212
217
  const today = useMemo(() => getTodayString(), []);
218
+ const { dialogLoading, runDialogAction } = useDialogLoadingAction({ loadingActions, loadingFullPage, onOpenChange });
213
219
  const baseReferenceDate = anchorDate || today;
214
220
  const previousOpenRef = useRef(false);
215
221
  const startRatio = getRatioByDate(draftRange.startDate ?? baseReferenceDate, trackBounds);
@@ -229,6 +235,10 @@ export function RandomDateRangeDialog({
229
235
  return [...new Set(values)];
230
236
  }, [trackBounds.endDate, trackBounds.startDate]);
231
237
 
238
+ const handleApply = useCallback<DialogActionHandler>(() => {
239
+ return onApply(draftRange);
240
+ }, [draftRange, onApply]);
241
+
232
242
  useEffect(() => {
233
243
  if (open && !previousOpenRef.current) {
234
244
  const nextRange = {
@@ -472,12 +482,13 @@ export function RandomDateRangeDialog({
472
482
  }, [open]);
473
483
 
474
484
  if (!open) {
475
- return null;
485
+ return <>{dialogLoading}</>;
476
486
  }
477
487
 
478
488
  return createPortal(
479
- <div className="fixed inset-0 z-120 flex select-none items-center justify-center bg-slate-950/60 px-3 py-6 backdrop-blur-sm">
480
- <div className="w-full max-w-2xl overflow-hidden rounded-3xl border border-black/10 bg-white shadow-2xl dark:border-white/10 dark:bg-slate-950">
489
+ <>
490
+ <div className="fixed inset-0 z-120 flex select-none items-center justify-center bg-slate-950/60 px-3 py-6 backdrop-blur-sm">
491
+ <div className="w-full max-w-2xl overflow-hidden rounded-3xl border border-black/10 bg-white shadow-2xl dark:border-white/10 dark:bg-slate-950">
481
492
  <div className="space-y-5 p-4">
482
493
  <div className="relative flex items-center justify-center px-16 text-center">
483
494
  <div ref={resultLabelRef} className="select-none text-base font-semibold text-slate-900 dark:text-white">{getRangeLabel(draftRange)}</div>
@@ -493,8 +504,7 @@ export function RandomDateRangeDialog({
493
504
  <button
494
505
  type="button"
495
506
  onClick={() => {
496
- onApply(draftRange);
497
- onOpenChange(false);
507
+ void runDialogAction('confirm', handleApply);
498
508
  }}
499
509
  disabled={!draftRange.startDate || !draftRange.endDate}
500
510
  className={cn(
@@ -734,8 +744,10 @@ export function RandomDateRangeDialog({
734
744
 
735
745
  </div>
736
746
  </div>
747
+ </div>
737
748
  </div>
738
- </div>,
749
+ {dialogLoading}
750
+ </>,
739
751
  document.body
740
752
  );
741
753
  }