@manhphi1309/drawer 0.2.4 → 0.2.5
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/README.md +66 -0
- package/dist/index.cjs +105 -14
- package/dist/index.d.cts +17 -2
- package/dist/index.d.mts +17 -2
- package/dist/index.mjs +105 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ This package exports the following subcomponents:
|
|
|
16
16
|
- `DrawerFooter`
|
|
17
17
|
- `DrawerTitle`
|
|
18
18
|
- `DrawerDescription`
|
|
19
|
+
- `useDrawerPanel` (Hook)
|
|
19
20
|
|
|
20
21
|
## Dependencies
|
|
21
22
|
|
|
@@ -71,10 +72,66 @@ export default function App() {
|
|
|
71
72
|
}
|
|
72
73
|
```
|
|
73
74
|
|
|
75
|
+
## Multi-Step Wizard Example
|
|
76
|
+
|
|
77
|
+
The drawer has built-in support for a multi-step sliding wizard with lazy loading. You can control it manually from the parent, or let it manage its own state internally using the `useDrawerPanel` hook.
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import { Button } from "@manhphi1309/button"
|
|
81
|
+
import {
|
|
82
|
+
Drawer,
|
|
83
|
+
DrawerContent,
|
|
84
|
+
DrawerHeader,
|
|
85
|
+
DrawerTitle,
|
|
86
|
+
DrawerTrigger,
|
|
87
|
+
useDrawerPanel,
|
|
88
|
+
} from "@manhphi1309/drawer"
|
|
89
|
+
|
|
90
|
+
function PanelOne() {
|
|
91
|
+
const { nextPanel } = useDrawerPanel()
|
|
92
|
+
return (
|
|
93
|
+
<div className="p-4 flex flex-col gap-4 h-full">
|
|
94
|
+
<DrawerHeader className="px-0">
|
|
95
|
+
<DrawerTitle>Step 1</DrawerTitle>
|
|
96
|
+
</DrawerHeader>
|
|
97
|
+
<div className="mt-auto">
|
|
98
|
+
<Button onClick={nextPanel}>Next Step</Button>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function PanelTwo() {
|
|
105
|
+
const { prevPanel } = useDrawerPanel()
|
|
106
|
+
return (
|
|
107
|
+
<div className="p-4 flex flex-col gap-4 h-full">
|
|
108
|
+
<DrawerHeader className="px-0">
|
|
109
|
+
<DrawerTitle>Step 2</DrawerTitle>
|
|
110
|
+
</DrawerHeader>
|
|
111
|
+
<div className="mt-auto">
|
|
112
|
+
<Button variant="outline" onClick={prevPanel}>Go Back</Button>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default function WizardApp() {
|
|
119
|
+
return (
|
|
120
|
+
<Drawer>
|
|
121
|
+
<DrawerTrigger asChild>
|
|
122
|
+
<Button>Open Wizard</Button>
|
|
123
|
+
</DrawerTrigger>
|
|
124
|
+
<DrawerContent panels={[<PanelOne key="1" />, <PanelTwo key="2" />]} />
|
|
125
|
+
</Drawer>
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
74
130
|
## Props
|
|
75
131
|
|
|
76
132
|
The `Drawer` component natively wraps and accepts all props provided by the `vaul` library.
|
|
77
133
|
|
|
134
|
+
### Drawer
|
|
78
135
|
| Prop | Type | Description |
|
|
79
136
|
| :--- | :--- | :--- |
|
|
80
137
|
| `direction` | `"top" \| "bottom" \| "left" \| "right"` | Direction the drawer slides in from. |
|
|
@@ -82,4 +139,13 @@ The `Drawer` component natively wraps and accepts all props provided by the `vau
|
|
|
82
139
|
| `onOpenChange` | `(open: boolean) => void` | Callback when the open state changes. |
|
|
83
140
|
| `snapPoints` | `number[] \| string[]` | Array of numbers from 0 to 1 or string values representing heights to snap to. |
|
|
84
141
|
|
|
142
|
+
### DrawerContent (Wizard Mode)
|
|
143
|
+
If you pass the `panels` prop, `DrawerContent` transforms into a multi-step sliding wizard.
|
|
144
|
+
|
|
145
|
+
| Prop | Type | Description |
|
|
146
|
+
| :--- | :--- | :--- |
|
|
147
|
+
| `panels` | `React.ReactNode[]` | An array of panel components to render in the sliding track. |
|
|
148
|
+
| `activePanelIndex` | `number` | (Controlled mode) The index of the currently active panel. |
|
|
149
|
+
| `onPanelIndexChange` | `(index: number) => void` | (Controlled mode) Callback fired when a navigation hook triggers a slide. |
|
|
150
|
+
|
|
85
151
|
For a complete and advanced list of properties (like `fadeFromIndex`, `activeSnapPoint`, etc.), please refer to the official [Vaul documentation](https://github.com/emilkowalski/vaul).
|
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,13 @@ let _manhphi1309_hooks = require("@manhphi1309/hooks");
|
|
|
29
29
|
let _manhphi1309_utils = require("@manhphi1309/utils");
|
|
30
30
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
31
31
|
//#region index.tsx
|
|
32
|
+
const DrawerPanelContext = react.createContext(null);
|
|
33
|
+
const DrawerContext = react.createContext(null);
|
|
34
|
+
function useDrawerPanel() {
|
|
35
|
+
const context = react.useContext(DrawerPanelContext);
|
|
36
|
+
if (!context) throw new Error("useDrawerPanel must be used within a DrawerContent that has panels");
|
|
37
|
+
return context;
|
|
38
|
+
}
|
|
32
39
|
function Drawer({ ...props }) {
|
|
33
40
|
const [internalOpen, setInternalOpen] = react.useState(props.defaultOpen ?? false);
|
|
34
41
|
const isControlled = props.open !== void 0;
|
|
@@ -39,11 +46,17 @@ function Drawer({ ...props }) {
|
|
|
39
46
|
onOpenChange?.(newOpen);
|
|
40
47
|
}, [isControlled, onOpenChange]);
|
|
41
48
|
(0, _manhphi1309_hooks.useThemeColorAnimation)(open ?? false);
|
|
42
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DrawerContext.Provider, {
|
|
50
|
+
value: {
|
|
51
|
+
open: open ?? false,
|
|
52
|
+
onOpenChange: handleOpenChange
|
|
53
|
+
},
|
|
54
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(vaul.Drawer.Root, {
|
|
55
|
+
"data-slot": "drawer",
|
|
56
|
+
open,
|
|
57
|
+
onOpenChange: handleOpenChange,
|
|
58
|
+
...props
|
|
59
|
+
})
|
|
47
60
|
});
|
|
48
61
|
}
|
|
49
62
|
function DrawerTrigger({ ...props }) {
|
|
@@ -71,15 +84,92 @@ function DrawerOverlay({ className, ...props }) {
|
|
|
71
84
|
...props
|
|
72
85
|
});
|
|
73
86
|
}
|
|
74
|
-
function DrawerContent({ className, children, ...props }) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
function DrawerContent({ className, children, panels, activePanelIndex = 0, onPanelIndexChange, ...props }) {
|
|
88
|
+
const [internalIndex, setInternalIndex] = react.useState(0);
|
|
89
|
+
const drawerContext = react.useContext(DrawerContext);
|
|
90
|
+
const isControlled = activePanelIndex !== void 0 && onPanelIndexChange !== void 0;
|
|
91
|
+
const controlledIndex = isControlled ? activePanelIndex : internalIndex;
|
|
92
|
+
const [visitedPanels, setVisitedPanels] = react.useState(new Set([
|
|
93
|
+
controlledIndex,
|
|
94
|
+
controlledIndex + 1,
|
|
95
|
+
controlledIndex - 1
|
|
96
|
+
]));
|
|
97
|
+
react.useEffect(() => {
|
|
98
|
+
if (drawerContext && !drawerContext.open) {
|
|
99
|
+
const timer = setTimeout(() => {
|
|
100
|
+
setInternalIndex(0);
|
|
101
|
+
setVisitedPanels(new Set([
|
|
102
|
+
0,
|
|
103
|
+
1,
|
|
104
|
+
-1
|
|
105
|
+
]));
|
|
106
|
+
}, 500);
|
|
107
|
+
return () => clearTimeout(timer);
|
|
108
|
+
}
|
|
109
|
+
}, [drawerContext]);
|
|
110
|
+
if (!visitedPanels.has(controlledIndex)) setVisitedPanels((prev) => {
|
|
111
|
+
const newSet = new Set(prev);
|
|
112
|
+
newSet.add(controlledIndex);
|
|
113
|
+
newSet.add(controlledIndex + 1);
|
|
114
|
+
newSet.add(controlledIndex - 1);
|
|
115
|
+
return newSet;
|
|
116
|
+
});
|
|
117
|
+
const nextPanel = react.useCallback(() => {
|
|
118
|
+
if (!panels) return;
|
|
119
|
+
const newIndex = Math.min(controlledIndex + 1, panels.length - 1);
|
|
120
|
+
if (!isControlled) setInternalIndex(newIndex);
|
|
121
|
+
onPanelIndexChange?.(newIndex);
|
|
122
|
+
}, [
|
|
123
|
+
controlledIndex,
|
|
124
|
+
isControlled,
|
|
125
|
+
onPanelIndexChange,
|
|
126
|
+
panels
|
|
127
|
+
]);
|
|
128
|
+
const prevPanel = react.useCallback(() => {
|
|
129
|
+
const newIndex = Math.max(controlledIndex - 1, 0);
|
|
130
|
+
if (!isControlled) setInternalIndex(newIndex);
|
|
131
|
+
onPanelIndexChange?.(newIndex);
|
|
132
|
+
}, [
|
|
133
|
+
controlledIndex,
|
|
134
|
+
isControlled,
|
|
135
|
+
onPanelIndexChange
|
|
136
|
+
]);
|
|
137
|
+
const value = react.useMemo(() => ({
|
|
138
|
+
activePanelIndex: controlledIndex,
|
|
139
|
+
setActivePanelIndex: (index) => {
|
|
140
|
+
if (!isControlled) setInternalIndex(index);
|
|
141
|
+
onPanelIndexChange?.(index);
|
|
142
|
+
},
|
|
143
|
+
nextPanel,
|
|
144
|
+
prevPanel
|
|
145
|
+
}), [
|
|
146
|
+
controlledIndex,
|
|
147
|
+
isControlled,
|
|
148
|
+
nextPanel,
|
|
149
|
+
prevPanel,
|
|
150
|
+
onPanelIndexChange
|
|
151
|
+
]);
|
|
152
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DrawerPanelContext.Provider, {
|
|
153
|
+
value,
|
|
154
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DrawerPortal, {
|
|
155
|
+
"data-slot": "drawer-portal",
|
|
156
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DrawerOverlay, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(vaul.Drawer.Content, {
|
|
157
|
+
"data-slot": "drawer-content",
|
|
158
|
+
className: (0, _manhphi1309_utils.cn)("group/drawer-content fixed z-50 flex h-auto flex-col bg-popover text-sm text-popover-foreground data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[96dvh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[96dvh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm", className),
|
|
159
|
+
...props,
|
|
160
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mx-auto mt-4 hidden h-1 w-[40px] shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block" }), !panels ? children : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
161
|
+
className: "overflow-hidden",
|
|
162
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
163
|
+
style: { transform: `translateX(${controlledIndex * -100}%)` },
|
|
164
|
+
className: "flex h-full w-full flex-row transition-transform duration-300 ease-in-out",
|
|
165
|
+
children: panels.map((panel, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
166
|
+
className: "h-full w-full shrink-0",
|
|
167
|
+
children: visitedPanels.has(index) ? panel : null
|
|
168
|
+
}, index))
|
|
169
|
+
})
|
|
170
|
+
})]
|
|
171
|
+
})]
|
|
172
|
+
})
|
|
83
173
|
});
|
|
84
174
|
}
|
|
85
175
|
function DrawerHeader({ className, leftAction, rightAction, children, ...props }) {
|
|
@@ -138,3 +228,4 @@ exports.DrawerOverlay = DrawerOverlay;
|
|
|
138
228
|
exports.DrawerPortal = DrawerPortal;
|
|
139
229
|
exports.DrawerTitle = DrawerTitle;
|
|
140
230
|
exports.DrawerTrigger = DrawerTrigger;
|
|
231
|
+
exports.useDrawerPanel = useDrawerPanel;
|
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,13 @@ import * as React from "react";
|
|
|
2
2
|
import { Drawer as Drawer$1 } from "vaul";
|
|
3
3
|
|
|
4
4
|
//#region index.d.ts
|
|
5
|
+
type DrawerPanelContextValue = {
|
|
6
|
+
activePanelIndex: number;
|
|
7
|
+
setActivePanelIndex: (index: number) => void;
|
|
8
|
+
nextPanel: () => void;
|
|
9
|
+
prevPanel: () => void;
|
|
10
|
+
};
|
|
11
|
+
declare function useDrawerPanel(): DrawerPanelContextValue;
|
|
5
12
|
declare function Drawer({
|
|
6
13
|
...props
|
|
7
14
|
}: React.ComponentProps<typeof Drawer$1.Root>): React.JSX.Element;
|
|
@@ -18,11 +25,19 @@ declare function DrawerOverlay({
|
|
|
18
25
|
className,
|
|
19
26
|
...props
|
|
20
27
|
}: React.ComponentProps<typeof Drawer$1.Overlay>): React.JSX.Element;
|
|
28
|
+
interface DrawerContentProps extends React.ComponentProps<typeof Drawer$1.Content> {
|
|
29
|
+
panels?: React.ReactNode[];
|
|
30
|
+
activePanelIndex?: number;
|
|
31
|
+
onPanelIndexChange?: (index: number) => void;
|
|
32
|
+
}
|
|
21
33
|
declare function DrawerContent({
|
|
22
34
|
className,
|
|
23
35
|
children,
|
|
36
|
+
panels,
|
|
37
|
+
activePanelIndex,
|
|
38
|
+
onPanelIndexChange,
|
|
24
39
|
...props
|
|
25
|
-
}:
|
|
40
|
+
}: DrawerContentProps): React.JSX.Element;
|
|
26
41
|
declare function DrawerHeader({
|
|
27
42
|
className,
|
|
28
43
|
leftAction,
|
|
@@ -46,4 +61,4 @@ declare function DrawerDescription({
|
|
|
46
61
|
...props
|
|
47
62
|
}: React.ComponentProps<typeof Drawer$1.Description>): React.JSX.Element;
|
|
48
63
|
//#endregion
|
|
49
|
-
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger };
|
|
64
|
+
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, useDrawerPanel };
|
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,13 @@ import * as React from "react";
|
|
|
2
2
|
import { Drawer as Drawer$1 } from "vaul";
|
|
3
3
|
|
|
4
4
|
//#region index.d.ts
|
|
5
|
+
type DrawerPanelContextValue = {
|
|
6
|
+
activePanelIndex: number;
|
|
7
|
+
setActivePanelIndex: (index: number) => void;
|
|
8
|
+
nextPanel: () => void;
|
|
9
|
+
prevPanel: () => void;
|
|
10
|
+
};
|
|
11
|
+
declare function useDrawerPanel(): DrawerPanelContextValue;
|
|
5
12
|
declare function Drawer({
|
|
6
13
|
...props
|
|
7
14
|
}: React.ComponentProps<typeof Drawer$1.Root>): React.JSX.Element;
|
|
@@ -18,11 +25,19 @@ declare function DrawerOverlay({
|
|
|
18
25
|
className,
|
|
19
26
|
...props
|
|
20
27
|
}: React.ComponentProps<typeof Drawer$1.Overlay>): React.JSX.Element;
|
|
28
|
+
interface DrawerContentProps extends React.ComponentProps<typeof Drawer$1.Content> {
|
|
29
|
+
panels?: React.ReactNode[];
|
|
30
|
+
activePanelIndex?: number;
|
|
31
|
+
onPanelIndexChange?: (index: number) => void;
|
|
32
|
+
}
|
|
21
33
|
declare function DrawerContent({
|
|
22
34
|
className,
|
|
23
35
|
children,
|
|
36
|
+
panels,
|
|
37
|
+
activePanelIndex,
|
|
38
|
+
onPanelIndexChange,
|
|
24
39
|
...props
|
|
25
|
-
}:
|
|
40
|
+
}: DrawerContentProps): React.JSX.Element;
|
|
26
41
|
declare function DrawerHeader({
|
|
27
42
|
className,
|
|
28
43
|
leftAction,
|
|
@@ -46,4 +61,4 @@ declare function DrawerDescription({
|
|
|
46
61
|
...props
|
|
47
62
|
}: React.ComponentProps<typeof Drawer$1.Description>): React.JSX.Element;
|
|
48
63
|
//#endregion
|
|
49
|
-
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger };
|
|
64
|
+
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, useDrawerPanel };
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,13 @@ import { useThemeColorAnimation } from "@manhphi1309/hooks";
|
|
|
5
5
|
import { cn } from "@manhphi1309/utils";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region index.tsx
|
|
8
|
+
const DrawerPanelContext = React.createContext(null);
|
|
9
|
+
const DrawerContext = React.createContext(null);
|
|
10
|
+
function useDrawerPanel() {
|
|
11
|
+
const context = React.useContext(DrawerPanelContext);
|
|
12
|
+
if (!context) throw new Error("useDrawerPanel must be used within a DrawerContent that has panels");
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
8
15
|
function Drawer({ ...props }) {
|
|
9
16
|
const [internalOpen, setInternalOpen] = React.useState(props.defaultOpen ?? false);
|
|
10
17
|
const isControlled = props.open !== void 0;
|
|
@@ -15,11 +22,17 @@ function Drawer({ ...props }) {
|
|
|
15
22
|
onOpenChange?.(newOpen);
|
|
16
23
|
}, [isControlled, onOpenChange]);
|
|
17
24
|
useThemeColorAnimation(open ?? false);
|
|
18
|
-
return /* @__PURE__ */ jsx(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
return /* @__PURE__ */ jsx(DrawerContext.Provider, {
|
|
26
|
+
value: {
|
|
27
|
+
open: open ?? false,
|
|
28
|
+
onOpenChange: handleOpenChange
|
|
29
|
+
},
|
|
30
|
+
children: /* @__PURE__ */ jsx(Drawer$1.Root, {
|
|
31
|
+
"data-slot": "drawer",
|
|
32
|
+
open,
|
|
33
|
+
onOpenChange: handleOpenChange,
|
|
34
|
+
...props
|
|
35
|
+
})
|
|
23
36
|
});
|
|
24
37
|
}
|
|
25
38
|
function DrawerTrigger({ ...props }) {
|
|
@@ -47,15 +60,92 @@ function DrawerOverlay({ className, ...props }) {
|
|
|
47
60
|
...props
|
|
48
61
|
});
|
|
49
62
|
}
|
|
50
|
-
function DrawerContent({ className, children, ...props }) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
function DrawerContent({ className, children, panels, activePanelIndex = 0, onPanelIndexChange, ...props }) {
|
|
64
|
+
const [internalIndex, setInternalIndex] = React.useState(0);
|
|
65
|
+
const drawerContext = React.useContext(DrawerContext);
|
|
66
|
+
const isControlled = activePanelIndex !== void 0 && onPanelIndexChange !== void 0;
|
|
67
|
+
const controlledIndex = isControlled ? activePanelIndex : internalIndex;
|
|
68
|
+
const [visitedPanels, setVisitedPanels] = React.useState(new Set([
|
|
69
|
+
controlledIndex,
|
|
70
|
+
controlledIndex + 1,
|
|
71
|
+
controlledIndex - 1
|
|
72
|
+
]));
|
|
73
|
+
React.useEffect(() => {
|
|
74
|
+
if (drawerContext && !drawerContext.open) {
|
|
75
|
+
const timer = setTimeout(() => {
|
|
76
|
+
setInternalIndex(0);
|
|
77
|
+
setVisitedPanels(new Set([
|
|
78
|
+
0,
|
|
79
|
+
1,
|
|
80
|
+
-1
|
|
81
|
+
]));
|
|
82
|
+
}, 500);
|
|
83
|
+
return () => clearTimeout(timer);
|
|
84
|
+
}
|
|
85
|
+
}, [drawerContext]);
|
|
86
|
+
if (!visitedPanels.has(controlledIndex)) setVisitedPanels((prev) => {
|
|
87
|
+
const newSet = new Set(prev);
|
|
88
|
+
newSet.add(controlledIndex);
|
|
89
|
+
newSet.add(controlledIndex + 1);
|
|
90
|
+
newSet.add(controlledIndex - 1);
|
|
91
|
+
return newSet;
|
|
92
|
+
});
|
|
93
|
+
const nextPanel = React.useCallback(() => {
|
|
94
|
+
if (!panels) return;
|
|
95
|
+
const newIndex = Math.min(controlledIndex + 1, panels.length - 1);
|
|
96
|
+
if (!isControlled) setInternalIndex(newIndex);
|
|
97
|
+
onPanelIndexChange?.(newIndex);
|
|
98
|
+
}, [
|
|
99
|
+
controlledIndex,
|
|
100
|
+
isControlled,
|
|
101
|
+
onPanelIndexChange,
|
|
102
|
+
panels
|
|
103
|
+
]);
|
|
104
|
+
const prevPanel = React.useCallback(() => {
|
|
105
|
+
const newIndex = Math.max(controlledIndex - 1, 0);
|
|
106
|
+
if (!isControlled) setInternalIndex(newIndex);
|
|
107
|
+
onPanelIndexChange?.(newIndex);
|
|
108
|
+
}, [
|
|
109
|
+
controlledIndex,
|
|
110
|
+
isControlled,
|
|
111
|
+
onPanelIndexChange
|
|
112
|
+
]);
|
|
113
|
+
const value = React.useMemo(() => ({
|
|
114
|
+
activePanelIndex: controlledIndex,
|
|
115
|
+
setActivePanelIndex: (index) => {
|
|
116
|
+
if (!isControlled) setInternalIndex(index);
|
|
117
|
+
onPanelIndexChange?.(index);
|
|
118
|
+
},
|
|
119
|
+
nextPanel,
|
|
120
|
+
prevPanel
|
|
121
|
+
}), [
|
|
122
|
+
controlledIndex,
|
|
123
|
+
isControlled,
|
|
124
|
+
nextPanel,
|
|
125
|
+
prevPanel,
|
|
126
|
+
onPanelIndexChange
|
|
127
|
+
]);
|
|
128
|
+
return /* @__PURE__ */ jsx(DrawerPanelContext.Provider, {
|
|
129
|
+
value,
|
|
130
|
+
children: /* @__PURE__ */ jsxs(DrawerPortal, {
|
|
131
|
+
"data-slot": "drawer-portal",
|
|
132
|
+
children: [/* @__PURE__ */ jsx(DrawerOverlay, {}), /* @__PURE__ */ jsxs(Drawer$1.Content, {
|
|
133
|
+
"data-slot": "drawer-content",
|
|
134
|
+
className: cn("group/drawer-content fixed z-50 flex h-auto flex-col bg-popover text-sm text-popover-foreground data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[96dvh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[96dvh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm", className),
|
|
135
|
+
...props,
|
|
136
|
+
children: [/* @__PURE__ */ jsx("div", { className: "mx-auto mt-4 hidden h-1 w-[40px] shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block" }), !panels ? children : /* @__PURE__ */ jsx("div", {
|
|
137
|
+
className: "overflow-hidden",
|
|
138
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
139
|
+
style: { transform: `translateX(${controlledIndex * -100}%)` },
|
|
140
|
+
className: "flex h-full w-full flex-row transition-transform duration-300 ease-in-out",
|
|
141
|
+
children: panels.map((panel, index) => /* @__PURE__ */ jsx("div", {
|
|
142
|
+
className: "h-full w-full shrink-0",
|
|
143
|
+
children: visitedPanels.has(index) ? panel : null
|
|
144
|
+
}, index))
|
|
145
|
+
})
|
|
146
|
+
})]
|
|
147
|
+
})]
|
|
148
|
+
})
|
|
59
149
|
});
|
|
60
150
|
}
|
|
61
151
|
function DrawerHeader({ className, leftAction, rightAction, children, ...props }) {
|
|
@@ -104,4 +194,4 @@ function DrawerDescription({ className, ...props }) {
|
|
|
104
194
|
});
|
|
105
195
|
}
|
|
106
196
|
//#endregion
|
|
107
|
-
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger };
|
|
197
|
+
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, useDrawerPanel };
|