@baodev/mini-app-component 1.0.1 → 1.0.2
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/package.json +3 -4
- package/src/components/BottomSheet.tsx +45 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baodev/mini-app-component",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "WEBVIEW COMPONENT",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -26,12 +26,11 @@
|
|
|
26
26
|
"tailwindcss": "^3.4.19",
|
|
27
27
|
"tsup": "latest",
|
|
28
28
|
"typescript": "latest",
|
|
29
|
-
"vitest": "^4.1.7"
|
|
30
|
-
},
|
|
31
|
-
"dependencies": {
|
|
29
|
+
"vitest": "^4.1.7",
|
|
32
30
|
"@storybook/react": "^10.4.1",
|
|
33
31
|
"framer-motion": "^12.40.0"
|
|
34
32
|
},
|
|
33
|
+
"dependencies": {},
|
|
35
34
|
"scripts": {
|
|
36
35
|
"build": "tsup",
|
|
37
36
|
"storybook": "storybook dev -p 6006",
|
|
@@ -23,10 +23,9 @@ export function BottomSheet({
|
|
|
23
23
|
children,
|
|
24
24
|
snapPoints = "auto",
|
|
25
25
|
}: BottomSheetProps) {
|
|
26
|
-
// Điều khiển vùng vuốt bằng Framer Motion
|
|
27
26
|
const dragControls = useDragControls();
|
|
28
27
|
|
|
29
|
-
//
|
|
28
|
+
// Khóa cuộn trang khi mở Sheet
|
|
30
29
|
useEffect(() => {
|
|
31
30
|
document.body.style.overflow = isOpen ? "hidden" : "";
|
|
32
31
|
return () => {
|
|
@@ -40,61 +39,73 @@ export function BottomSheet({
|
|
|
40
39
|
<AnimatePresence>
|
|
41
40
|
{isOpen && (
|
|
42
41
|
<>
|
|
43
|
-
{/* Backdrop */}
|
|
42
|
+
{/* Backdrop với hiệu ứng làm mờ nhẹ nhàng */}
|
|
44
43
|
<motion.div
|
|
45
44
|
initial={{ opacity: 0 }}
|
|
46
45
|
animate={{ opacity: 1 }}
|
|
47
46
|
exit={{ opacity: 0 }}
|
|
48
|
-
transition={{ duration: 0.
|
|
49
|
-
className="fixed inset-0 bg-black/40 z-40 pointer-events-auto"
|
|
47
|
+
transition={{ duration: 0.25, ease: "linear" }}
|
|
48
|
+
className="fixed inset-0 bg-black/40 z-40 pointer-events-auto backdrop-blur-[1px]"
|
|
50
49
|
onClick={onClose}
|
|
51
50
|
/>
|
|
52
51
|
|
|
53
|
-
{/* Sheet */}
|
|
52
|
+
{/* Sheet Container */}
|
|
54
53
|
<motion.div
|
|
55
54
|
initial={{ y: "100%" }}
|
|
56
55
|
animate={{ y: 0 }}
|
|
57
56
|
exit={{ y: "100%" }}
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
// CHỈNH SỬA 1: Ép chạy bằng GPU chuyển động Tween mượt như iOS, bỏ Spring nặng nề
|
|
58
|
+
transition={{
|
|
59
|
+
type: "tween",
|
|
60
|
+
ease: [0.32, 0.94, 0.6, 1],
|
|
61
|
+
duration: 0.35,
|
|
62
|
+
}}
|
|
63
|
+
// LOGIC VUỐT TỐI ƯU
|
|
60
64
|
drag="y"
|
|
61
65
|
dragControls={dragControls}
|
|
62
|
-
dragListener={false}
|
|
63
|
-
dragConstraints={{ top: 0 }}
|
|
64
|
-
dragElastic={0.
|
|
66
|
+
dragListener={false}
|
|
67
|
+
dragConstraints={{ top: 0 }}
|
|
68
|
+
dragElastic={0.15} // Giảm độ nảy quá đà khi cố kéo lên
|
|
65
69
|
onDragEnd={(e, info) => {
|
|
66
|
-
// Vuốt xuống nhanh hoặc dài
|
|
67
|
-
if (info.offset.y >
|
|
70
|
+
// Vuốt xuống nhanh (velocity) hoặc kéo dài quá 80px là đóng luôn cho nhạy
|
|
71
|
+
if (info.offset.y > 80 || info.velocity.y > 400) {
|
|
68
72
|
onClose();
|
|
69
73
|
}
|
|
70
74
|
}}
|
|
71
|
-
//
|
|
75
|
+
// CHỈNH SỬA 2: Ép willChange tăng tốc đồ họa phần cứng phần cứng
|
|
76
|
+
style={{ willChange: "transform" }}
|
|
72
77
|
className={`fixed bottom-0 left-0 right-0 z-50 bg-white rounded-t-3xl shadow-2xl flex flex-col ${snapStyles[snapPoints]}`}
|
|
73
78
|
>
|
|
74
|
-
{/* Handle
|
|
79
|
+
{/* CHỈNH SỬA 3: Gom cả cụm Handle + Header thành vùng nhận sự kiện kéo để vuốt nhạy hơn */}
|
|
75
80
|
<div
|
|
76
|
-
onPointerDown={(e) => dragControls.start(e)}
|
|
77
|
-
className="
|
|
81
|
+
onPointerDown={(e) => dragControls.start(e)}
|
|
82
|
+
className="w-full flex flex-col flex-shrink-0 cursor-grab active:cursor-grabbing touch-none select-none"
|
|
78
83
|
>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{/* Header */}
|
|
83
|
-
{title && (
|
|
84
|
-
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-100 flex-shrink-0">
|
|
85
|
-
<h3 className="text-base font-semibold text-gray-900">
|
|
86
|
-
{title}
|
|
87
|
-
</h3>
|
|
88
|
-
<button
|
|
89
|
-
onClick={onClose}
|
|
90
|
-
className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 text-lg"
|
|
91
|
-
>
|
|
92
|
-
✕
|
|
93
|
-
</button>
|
|
84
|
+
{/* Handle bar */}
|
|
85
|
+
<div className="flex justify-center pt-3 pb-2">
|
|
86
|
+
<div className="w-10 h-1 bg-gray-300 rounded-full" />
|
|
94
87
|
</div>
|
|
95
|
-
)}
|
|
96
88
|
|
|
97
|
-
|
|
89
|
+
{/* Header nằm trong vùng kéo luôn */}
|
|
90
|
+
{title && (
|
|
91
|
+
<div className="flex items-center justify-between px-5 pb-3 border-b border-gray-100">
|
|
92
|
+
<h3 className="text-base font-semibold text-gray-900 pointer-events-none">
|
|
93
|
+
{title}
|
|
94
|
+
</h3>
|
|
95
|
+
<button
|
|
96
|
+
onClick={(e) => {
|
|
97
|
+
e.stopPropagation(); // Ngăn sự kiện kéo kích hoạt khi bấm nút X
|
|
98
|
+
onClose();
|
|
99
|
+
}}
|
|
100
|
+
className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 text-lg pointer-events-auto"
|
|
101
|
+
>
|
|
102
|
+
✕
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/* Content — Cuộn độc lập */}
|
|
98
109
|
<div
|
|
99
110
|
className="flex-1 overflow-y-auto overscroll-contain px-5 py-4"
|
|
100
111
|
style={{
|