@underverse-ui/underverse 0.2.29 → 0.2.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +100 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +108 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2539,6 +2539,8 @@ var Modal = ({
|
|
|
2539
2539
|
const [isMounted, setIsMounted] = React10.useState(false);
|
|
2540
2540
|
const [isVisible, setIsVisible] = React10.useState(false);
|
|
2541
2541
|
const [isAnimating, setIsAnimating] = React10.useState(true);
|
|
2542
|
+
const mouseDownTarget = React10.useRef(null);
|
|
2543
|
+
const modalContentRef = React10.useRef(null);
|
|
2542
2544
|
React10.useEffect(() => {
|
|
2543
2545
|
setIsMounted(true);
|
|
2544
2546
|
return () => setIsMounted(false);
|
|
@@ -2578,68 +2580,84 @@ var Modal = ({
|
|
|
2578
2580
|
document.body.style.overflow = "unset";
|
|
2579
2581
|
};
|
|
2580
2582
|
}, [isOpen]);
|
|
2581
|
-
const
|
|
2582
|
-
|
|
2583
|
+
const handleOverlayMouseDown = (event) => {
|
|
2584
|
+
mouseDownTarget.current = event.target;
|
|
2585
|
+
};
|
|
2586
|
+
const handleOverlayMouseUp = (event) => {
|
|
2587
|
+
const modalContent2 = modalContentRef.current;
|
|
2588
|
+
const mouseDownOutside = modalContent2 && !modalContent2.contains(mouseDownTarget.current);
|
|
2589
|
+
const mouseUpOutside = modalContent2 && !modalContent2.contains(event.target);
|
|
2590
|
+
if (closeOnOverlayClick && mouseDownOutside && mouseUpOutside) {
|
|
2583
2591
|
onClose();
|
|
2584
2592
|
}
|
|
2593
|
+
mouseDownTarget.current = null;
|
|
2585
2594
|
};
|
|
2586
2595
|
if (!isMounted || !isOpen && !isVisible) {
|
|
2587
2596
|
return null;
|
|
2588
2597
|
}
|
|
2589
2598
|
const maxWidthClass = width ? "max-w-none" : fullWidth ? "max-w-full" : sizeStyles3[size];
|
|
2590
|
-
const modalContent = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
"transition-all duration-200 ease-out",
|
|
2606
|
-
maxWidthClass,
|
|
2607
|
-
fullWidth && "mx-0",
|
|
2608
|
-
className
|
|
2599
|
+
const modalContent = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2600
|
+
"div",
|
|
2601
|
+
{
|
|
2602
|
+
className: cn("fixed inset-0 z-9999 flex items-center justify-center", overlayClassName),
|
|
2603
|
+
onMouseDown: handleOverlayMouseDown,
|
|
2604
|
+
onMouseUp: handleOverlayMouseUp,
|
|
2605
|
+
children: [
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2607
|
+
"div",
|
|
2608
|
+
{
|
|
2609
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out",
|
|
2610
|
+
style: {
|
|
2611
|
+
opacity: isOpen && !isAnimating ? 1 : 0
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2609
2614
|
),
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2616
|
+
"div",
|
|
2617
|
+
{
|
|
2618
|
+
ref: modalContentRef,
|
|
2619
|
+
className: cn(
|
|
2620
|
+
"relative w-full rounded-lg bg-card text-card-foreground shadow-xl",
|
|
2621
|
+
"transition-all duration-200 ease-out",
|
|
2622
|
+
maxWidthClass,
|
|
2623
|
+
fullWidth && "mx-0",
|
|
2624
|
+
className
|
|
2625
|
+
),
|
|
2626
|
+
style: {
|
|
2627
|
+
opacity: isOpen && !isAnimating ? 1 : 0,
|
|
2628
|
+
transform: isOpen && !isAnimating ? "scale(1)" : "scale(0.9)",
|
|
2629
|
+
// Thêm dòng này để tạo hiệu ứng nảy
|
|
2630
|
+
transition: "all 300ms cubic-bezier(0.34, 1.76, 0.64, 1)",
|
|
2631
|
+
width,
|
|
2632
|
+
height
|
|
2633
|
+
},
|
|
2634
|
+
onClick: (e) => e.stopPropagation(),
|
|
2635
|
+
children: [
|
|
2636
|
+
(title || description || showCloseButton) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start justify-between p-6 pb-0", children: [
|
|
2637
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-1.5", children: [
|
|
2638
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { className: "text-lg font-semibold leading-none tracking-tight", children: title }),
|
|
2639
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-muted-foreground", children: description })
|
|
2640
|
+
] }),
|
|
2641
|
+
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2642
|
+
"button",
|
|
2643
|
+
{
|
|
2644
|
+
onClick: onClose,
|
|
2645
|
+
className: cn(
|
|
2646
|
+
"rounded-sm opacity-70 ring-offset-background transition-opacity",
|
|
2647
|
+
"hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
2648
|
+
"disabled:pointer-events-none "
|
|
2649
|
+
),
|
|
2650
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.X, { className: "h-4 w-4 cursor-pointer" })
|
|
2651
|
+
}
|
|
2652
|
+
)
|
|
2653
|
+
] }),
|
|
2654
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn("p-6", noPadding && "p-0", contentClassName), children })
|
|
2655
|
+
]
|
|
2656
|
+
}
|
|
2657
|
+
)
|
|
2658
|
+
]
|
|
2659
|
+
}
|
|
2660
|
+
);
|
|
2643
2661
|
return typeof window !== "undefined" ? (0, import_react_dom.createPortal)(modalContent, document.body) : null;
|
|
2644
2662
|
};
|
|
2645
2663
|
var Modal_default = Modal;
|
|
@@ -2670,11 +2688,6 @@ var ToastProvider = ({ children, position = "top-right", maxToasts = 5 }) => {
|
|
|
2670
2688
|
const updated = [newToast, ...prev];
|
|
2671
2689
|
return updated.slice(0, maxToasts);
|
|
2672
2690
|
});
|
|
2673
|
-
if (toast.duration !== 0) {
|
|
2674
|
-
setTimeout(() => {
|
|
2675
|
-
removeToast(id);
|
|
2676
|
-
}, toast.duration || 5e3);
|
|
2677
|
-
}
|
|
2678
2691
|
},
|
|
2679
2692
|
[maxToasts, removeToast]
|
|
2680
2693
|
);
|
|
@@ -2695,33 +2708,31 @@ var ToastComponent = ({ toast, onRemove }) => {
|
|
|
2695
2708
|
const [isVisible, setIsVisible] = (0, import_react8.useState)(false);
|
|
2696
2709
|
const [progress, setProgress] = (0, import_react8.useState)(100);
|
|
2697
2710
|
const [paused, setPaused] = (0, import_react8.useState)(false);
|
|
2698
|
-
const [startTs] = (0, import_react8.useState)(() => Date.now());
|
|
2699
2711
|
const total = toast.duration && toast.duration > 0 ? toast.duration : 5e3;
|
|
2700
|
-
const
|
|
2712
|
+
const endTsRef = (0, import_react8.useRef)(Date.now() + total);
|
|
2713
|
+
const remainingRef = (0, import_react8.useRef)(total);
|
|
2714
|
+
const pausedRef = (0, import_react8.useRef)(false);
|
|
2715
|
+
const handleRemove = (0, import_react8.useCallback)(() => {
|
|
2716
|
+
setIsVisible(false);
|
|
2717
|
+
setTimeout(() => onRemove(toast.id), 150);
|
|
2718
|
+
}, [onRemove, toast.id]);
|
|
2701
2719
|
(0, import_react8.useEffect)(() => {
|
|
2702
2720
|
setIsVisible(true);
|
|
2703
2721
|
if (toast.duration === 0) return;
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
const remain = Math.max(
|
|
2709
|
-
|
|
2722
|
+
remainingRef.current = total;
|
|
2723
|
+
endTsRef.current = Date.now() + total;
|
|
2724
|
+
const intervalId = window.setInterval(() => {
|
|
2725
|
+
if (!pausedRef.current) {
|
|
2726
|
+
const remain = Math.max(endTsRef.current - Date.now(), 0);
|
|
2727
|
+
remainingRef.current = remain;
|
|
2710
2728
|
setProgress(remain / total * 100);
|
|
2711
2729
|
if (remain === 0) {
|
|
2712
2730
|
handleRemove();
|
|
2713
|
-
return;
|
|
2714
2731
|
}
|
|
2715
2732
|
}
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
return () => cancelAnimationFrame(raf);
|
|
2720
|
-
}, []);
|
|
2721
|
-
const handleRemove = () => {
|
|
2722
|
-
setIsVisible(false);
|
|
2723
|
-
setTimeout(() => onRemove(toast.id), 150);
|
|
2724
|
-
};
|
|
2733
|
+
}, 50);
|
|
2734
|
+
return () => window.clearInterval(intervalId);
|
|
2735
|
+
}, [handleRemove, toast.duration, total]);
|
|
2725
2736
|
const typeConfig = {
|
|
2726
2737
|
success: {
|
|
2727
2738
|
icon: import_lucide_react7.CheckCircle,
|
|
@@ -2757,8 +2768,18 @@ var ToastComponent = ({ toast, onRemove }) => {
|
|
|
2757
2768
|
),
|
|
2758
2769
|
role: "status",
|
|
2759
2770
|
"aria-live": toast.type === "error" ? "assertive" : "polite",
|
|
2760
|
-
onMouseEnter: () =>
|
|
2761
|
-
|
|
2771
|
+
onMouseEnter: () => {
|
|
2772
|
+
if (toast.duration === 0) return;
|
|
2773
|
+
pausedRef.current = true;
|
|
2774
|
+
remainingRef.current = Math.max(endTsRef.current - Date.now(), 0);
|
|
2775
|
+
setPaused(true);
|
|
2776
|
+
},
|
|
2777
|
+
onMouseLeave: () => {
|
|
2778
|
+
if (toast.duration === 0) return;
|
|
2779
|
+
pausedRef.current = false;
|
|
2780
|
+
endTsRef.current = Date.now() + remainingRef.current;
|
|
2781
|
+
setPaused(false);
|
|
2782
|
+
},
|
|
2762
2783
|
children: [
|
|
2763
2784
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-start gap-3 p-4", children: [
|
|
2764
2785
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, { className: cn("h-5 w-5 mt-0.5 shrink-0", config.iconClassName) }),
|