@abhivarde/svelte-drawer 1.0.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +228 -526
- package/dist/components/Drawer.svelte +21 -10
- package/dist/components/Drawer.svelte.d.ts +3 -0
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,23 +7,25 @@ A drawer component for Svelte 5, inspired by [Vaul](https://github.com/emilkowal
|
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
10
|
+
- Smooth animations with gesture-driven dragging (mouse and touch)
|
|
11
|
+
- Support for multiple directions (bottom, top, left, right)
|
|
12
|
+
- Customizable animation duration and easing per drawer
|
|
13
|
+
- Snap points for iOS-like multi-height drawers
|
|
14
|
+
- Auto height for dynamic content (AI streaming, forms, lists)
|
|
15
|
+
- Backdrop blur on the overlay
|
|
16
|
+
- Portal rendering to escape z-index conflicts
|
|
17
|
+
- Prebuilt variants (default, sheet, dialog, minimal, sidebar)
|
|
18
|
+
- Drag handle with auto-adaptive orientation
|
|
19
|
+
- Optional header and footer components
|
|
20
|
+
- Nested drawer support
|
|
21
|
+
- Scrollable content areas
|
|
22
|
+
- Persistent state across page reloads
|
|
23
|
+
- Configurable dismiss threshold
|
|
24
|
+
- Keyboard shortcuts (Escape to close, Tab navigation)
|
|
25
|
+
- Focus management (auto-focus, focus trap, focus restoration)
|
|
26
|
+
- Fully accessible with keyboard navigation
|
|
27
|
+
- Full TypeScript support
|
|
28
|
+
- Works with Tailwind CSS
|
|
27
29
|
|
|
28
30
|
## Installation
|
|
29
31
|
|
|
@@ -33,435 +35,262 @@ npm install @abhivarde/svelte-drawer
|
|
|
33
35
|
|
|
34
36
|
## Usage
|
|
35
37
|
|
|
36
|
-
### Basic
|
|
38
|
+
### Basic
|
|
37
39
|
|
|
38
40
|
```svelte
|
|
39
41
|
<script>
|
|
40
|
-
|
|
42
|
+
import { Drawer, DrawerOverlay, DrawerContent, DrawerHandle } from '@abhivarde/svelte-drawer';
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
let open = $state(false);
|
|
43
45
|
</script>
|
|
44
46
|
|
|
45
|
-
<button onclick={() => open = true}>
|
|
46
|
-
Open Drawer
|
|
47
|
-
</button>
|
|
47
|
+
<button onclick={() => open = true}>Open Drawer</button>
|
|
48
48
|
|
|
49
49
|
<Drawer bind:open>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
51
|
+
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
52
|
+
<DrawerHandle class="mb-8" />
|
|
53
|
+
<h2>Drawer Content</h2>
|
|
54
|
+
<p>This is a drawer component.</p>
|
|
55
|
+
<button onclick={() => open = false}>Close</button>
|
|
56
|
+
</DrawerContent>
|
|
57
57
|
</Drawer>
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
###
|
|
61
|
-
|
|
62
|
-
Add a premium blur effect to the overlay background:
|
|
60
|
+
### Directions
|
|
63
61
|
|
|
64
62
|
```svelte
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
</script>
|
|
70
|
-
|
|
71
|
-
<Drawer bind:open>
|
|
72
|
-
<!-- Default medium blur -->
|
|
73
|
-
<DrawerOverlay blur class="fixed inset-0 bg-black/40" />
|
|
74
|
-
|
|
75
|
-
<!-- Or specify blur intensity -->
|
|
76
|
-
<!-- <DrawerOverlay blur="sm" class="fixed inset-0 bg-black/40" /> -->
|
|
77
|
-
<!-- <DrawerOverlay blur="lg" class="fixed inset-0 bg-black/40" /> -->
|
|
78
|
-
<!-- <DrawerOverlay blur="xl" class="fixed inset-0 bg-black/40" /> -->
|
|
79
|
-
|
|
80
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
81
|
-
<DrawerHandle class="mb-8" />
|
|
82
|
-
<h2>Blurred Backdrop</h2>
|
|
83
|
-
<p>Notice the premium blur effect behind this drawer.</p>
|
|
84
|
-
</DrawerContent>
|
|
85
|
-
</Drawer>
|
|
63
|
+
<Drawer bind:open direction="bottom">...</Drawer>
|
|
64
|
+
<Drawer bind:open direction="top">...</Drawer>
|
|
65
|
+
<Drawer bind:open direction="left">...</Drawer>
|
|
66
|
+
<Drawer bind:open direction="right">...</Drawer>
|
|
86
67
|
```
|
|
87
68
|
|
|
88
|
-
|
|
69
|
+
### Custom Animation
|
|
89
70
|
|
|
90
|
-
|
|
91
|
-
- `blur="sm"` - Small blur
|
|
92
|
-
- `blur="lg"` - Large blur
|
|
93
|
-
- `blur="xl"` - Extra large blur
|
|
94
|
-
- `blur="2xl"` - 2x extra large blur
|
|
95
|
-
- `blur="3xl"` - 3x extra large blur
|
|
96
|
-
|
|
97
|
-
### Side Drawer
|
|
71
|
+
Control the speed and easing of any drawer independently.
|
|
98
72
|
|
|
99
73
|
```svelte
|
|
100
74
|
<script>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
let open = $state(false);
|
|
75
|
+
import { cubicOut, bounceOut, linear } from 'svelte/easing';
|
|
104
76
|
</script>
|
|
105
77
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<DrawerHandle class="mb-4" />
|
|
110
|
-
<h2>Side Drawer</h2>
|
|
111
|
-
<button onclick={() => open = false}>Close</button>
|
|
112
|
-
</DrawerContent>
|
|
78
|
+
<!-- slower, softer -->
|
|
79
|
+
<Drawer bind:open animationDuration={400} animationEasing={cubicOut}>
|
|
80
|
+
...
|
|
113
81
|
</Drawer>
|
|
114
|
-
```
|
|
115
82
|
|
|
116
|
-
|
|
83
|
+
<!-- fast and snappy -->
|
|
84
|
+
<Drawer bind:open animationDuration={150} animationEasing={linear}>
|
|
85
|
+
...
|
|
86
|
+
</Drawer>
|
|
117
87
|
|
|
118
|
-
|
|
119
|
-
<
|
|
120
|
-
|
|
88
|
+
<!-- playful bounce -->
|
|
89
|
+
<Drawer bind:open animationDuration={500} animationEasing={bounceOut}>
|
|
90
|
+
...
|
|
91
|
+
</Drawer>
|
|
92
|
+
```
|
|
121
93
|
|
|
122
|
-
|
|
94
|
+
Any easing from `svelte/easing` works, or pass your own `(t: number) => number` function. Default is `220ms` with `expoOut`.
|
|
123
95
|
|
|
124
|
-
|
|
125
|
-
console.log('Drawer is now:', isOpen ? 'open' : 'closed');
|
|
126
|
-
open = isOpen;
|
|
127
|
-
}
|
|
128
|
-
</script>
|
|
96
|
+
### Side Drawer
|
|
129
97
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
98
|
+
```svelte
|
|
99
|
+
<Drawer bind:open direction="right">
|
|
100
|
+
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
101
|
+
<DrawerContent class="fixed right-0 top-0 bottom-0 w-80 bg-white p-4">
|
|
102
|
+
<DrawerHandle class="mb-4" />
|
|
103
|
+
<h2>Side Drawer</h2>
|
|
104
|
+
</DrawerContent>
|
|
136
105
|
</Drawer>
|
|
137
106
|
```
|
|
138
107
|
|
|
139
|
-
###
|
|
108
|
+
### Backdrop Blur
|
|
140
109
|
|
|
141
110
|
```svelte
|
|
142
|
-
<script>
|
|
143
|
-
import { Drawer, DrawerOverlay, DrawerContent } from '@abhivarde/svelte-drawer';
|
|
144
|
-
|
|
145
|
-
let open = $state(false);
|
|
146
|
-
</script>
|
|
147
|
-
|
|
148
|
-
<!-- Disable Escape key -->
|
|
149
|
-
<Drawer bind:open closeOnEscape={false}>
|
|
150
|
-
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
151
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
152
|
-
<h2>Cannot close with Escape</h2>
|
|
153
|
-
</DrawerContent>
|
|
154
|
-
</Drawer>
|
|
155
|
-
|
|
156
|
-
<!-- Disable focus trap -->
|
|
157
111
|
<Drawer bind:open>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
112
|
+
<DrawerOverlay blur="lg" class="fixed inset-0 bg-black/30" />
|
|
113
|
+
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
114
|
+
<DrawerHandle class="mb-8" />
|
|
115
|
+
<h2>Blurred Backdrop</h2>
|
|
116
|
+
</DrawerContent>
|
|
162
117
|
</Drawer>
|
|
163
118
|
```
|
|
164
119
|
|
|
165
|
-
|
|
120
|
+
Available intensities: `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`. Default is `md`.
|
|
166
121
|
|
|
167
|
-
|
|
122
|
+
### Snap Points
|
|
168
123
|
|
|
169
124
|
```svelte
|
|
170
125
|
<script>
|
|
171
|
-
import { Drawer, DrawerOverlay, DrawerContent, DrawerHandle } from '@abhivarde/svelte-drawer';
|
|
172
|
-
|
|
173
126
|
let open = $state(false);
|
|
127
|
+
let activeSnapPoint = $state(undefined);
|
|
174
128
|
</script>
|
|
175
129
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
</DrawerContent>
|
|
183
|
-
</Drawer>
|
|
184
|
-
|
|
185
|
-
<!-- harder to dismiss (long drag required) -->
|
|
186
|
-
<Drawer bind:open closeThreshold={0.5}>
|
|
130
|
+
<Drawer
|
|
131
|
+
bind:open
|
|
132
|
+
snapPoints={[0.25, 0.5, 0.9]}
|
|
133
|
+
bind:activeSnapPoint
|
|
134
|
+
onSnapPointChange={(point) => console.log('Snapped to:', point)}
|
|
135
|
+
>
|
|
187
136
|
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
188
137
|
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
189
138
|
<DrawerHandle class="mb-8" />
|
|
190
|
-
<p>
|
|
139
|
+
<p>Current: {activeSnapPoint ? `${(activeSnapPoint * 100).toFixed(0)}%` : 'loading'}</p>
|
|
140
|
+
<button onclick={() => activeSnapPoint = 0.5}>Jump to 50%</button>
|
|
191
141
|
</DrawerContent>
|
|
192
142
|
</Drawer>
|
|
193
143
|
```
|
|
194
144
|
|
|
195
|
-
|
|
145
|
+
Snap point values range from 0 to 1. The drawer snaps to the nearest point on release. Dragging past the lowest snap point dismisses it.
|
|
196
146
|
|
|
197
|
-
###
|
|
147
|
+
### Auto Height
|
|
148
|
+
|
|
149
|
+
Use `autoHeight` on `DrawerContent` when content changes height at runtime, such as AI streaming responses, multi-step forms, or dynamic lists.
|
|
198
150
|
|
|
199
151
|
```svelte
|
|
200
152
|
<script>
|
|
201
|
-
|
|
153
|
+
let open = $state(false);
|
|
154
|
+
let streaming = $state(false);
|
|
155
|
+
let text = $state('');
|
|
202
156
|
|
|
203
|
-
|
|
157
|
+
async function simulate() {
|
|
158
|
+
open = true;
|
|
159
|
+
streaming = true;
|
|
160
|
+
text = '';
|
|
161
|
+
const lines = [
|
|
162
|
+
'Sure! Here is what autoHeight does.',
|
|
163
|
+
'\n\nIt watches your content as it changes.',
|
|
164
|
+
'\n\nWhen content grows, the drawer follows automatically.',
|
|
165
|
+
'\n\nNo magic numbers. No hardcoded heights. Just works.',
|
|
166
|
+
];
|
|
167
|
+
for (const line of lines) {
|
|
168
|
+
await new Promise(r => setTimeout(r, 500));
|
|
169
|
+
text += line;
|
|
170
|
+
}
|
|
171
|
+
streaming = false;
|
|
172
|
+
}
|
|
204
173
|
</script>
|
|
205
174
|
|
|
206
|
-
|
|
207
|
-
<Drawer bind:open>
|
|
208
|
-
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
209
|
-
<DrawerVariants variant="sheet">
|
|
210
|
-
<div class="p-6">
|
|
211
|
-
<DrawerHandle class="mb-6" />
|
|
212
|
-
<h2>iOS-style Sheet</h2>
|
|
213
|
-
<p>Clean and modern bottom sheet design</p>
|
|
214
|
-
</div>
|
|
215
|
-
</DrawerVariants>
|
|
216
|
-
</Drawer>
|
|
175
|
+
<button onclick={simulate}>Ask AI</button>
|
|
217
176
|
|
|
218
|
-
<!-- Dialog variant (center modal) -->
|
|
219
177
|
<Drawer bind:open>
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
</
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
<h2>Sidebar Navigation</h2>
|
|
236
|
-
<p>Side navigation drawer</p>
|
|
237
|
-
</div>
|
|
238
|
-
</DrawerVariants>
|
|
178
|
+
<DrawerOverlay />
|
|
179
|
+
<DrawerContent
|
|
180
|
+
autoHeight
|
|
181
|
+
class="bg-gray-100 flex flex-col rounded-t-[10px] fixed bottom-0 left-0 right-0 outline-none"
|
|
182
|
+
>
|
|
183
|
+
<div class="p-4 bg-white rounded-t-[10px]">
|
|
184
|
+
<DrawerHandle class="mb-8" />
|
|
185
|
+
<p class="font-medium mb-2 text-gray-900">AI Response</p>
|
|
186
|
+
{#if text}
|
|
187
|
+
<p class="text-sm text-gray-600 leading-relaxed">
|
|
188
|
+
{text}{streaming ? '▌' : ''}
|
|
189
|
+
</p>
|
|
190
|
+
{/if}
|
|
191
|
+
</div>
|
|
192
|
+
</DrawerContent>
|
|
239
193
|
</Drawer>
|
|
240
194
|
```
|
|
241
195
|
|
|
242
|
-
###
|
|
243
|
-
|
|
244
|
-
```svelte
|
|
245
|
-
<script>
|
|
246
|
-
import { Drawer, DrawerOverlay, DrawerContent, DrawerHandle } from '@abhivarde/svelte-drawer';
|
|
247
|
-
|
|
248
|
-
let open = $state(false);
|
|
249
|
-
</script>
|
|
250
|
-
|
|
251
|
-
<Drawer bind:open>
|
|
252
|
-
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
253
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
254
|
-
<!-- Default gray handle -->
|
|
255
|
-
<DrawerHandle class="mb-8" />
|
|
196
|
+
### Close Threshold
|
|
256
197
|
|
|
257
|
-
|
|
258
|
-
<!-- <DrawerHandle class="bg-blue-500 mb-8" /> -->
|
|
198
|
+
Control how far the user must drag before the drawer dismisses.
|
|
259
199
|
|
|
260
|
-
|
|
261
|
-
|
|
200
|
+
```svelte
|
|
201
|
+
<!-- easier to dismiss -->
|
|
202
|
+
<Drawer bind:open closeThreshold={0.15}>...</Drawer>
|
|
262
203
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
</DrawerContent>
|
|
266
|
-
</Drawer>
|
|
204
|
+
<!-- harder to dismiss -->
|
|
205
|
+
<Drawer bind:open closeThreshold={0.5}>...</Drawer>
|
|
267
206
|
```
|
|
268
207
|
|
|
269
|
-
|
|
208
|
+
Values range from `0` to `1`. Default is `0.3`.
|
|
270
209
|
|
|
271
|
-
|
|
210
|
+
### Variants
|
|
272
211
|
|
|
273
212
|
```svelte
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
</
|
|
213
|
+
<!-- iOS-style sheet -->
|
|
214
|
+
<Drawer bind:open>
|
|
215
|
+
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
216
|
+
<DrawerVariants variant="sheet">
|
|
217
|
+
<DrawerHandle class="mb-6" />
|
|
218
|
+
<h2>Sheet</h2>
|
|
219
|
+
</DrawerVariants>
|
|
220
|
+
</Drawer>
|
|
280
221
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
>
|
|
287
|
-
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
288
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
289
|
-
<DrawerHandle class="mb-8" />
|
|
290
|
-
<h2>Drawer with Snap Points</h2>
|
|
291
|
-
<p>Drag to see snapping behavior at 25%, 50%, and 90%</p>
|
|
292
|
-
|
|
293
|
-
<!-- Programmatically change snap point -->
|
|
294
|
-
<button onclick={() => activeSnapPoint = 0.5}>Jump to 50%</button>
|
|
295
|
-
</DrawerContent>
|
|
222
|
+
<!-- sidebar -->
|
|
223
|
+
<Drawer bind:open direction="right">
|
|
224
|
+
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
225
|
+
<DrawerVariants variant="sidebar">
|
|
226
|
+
<h2>Sidebar</h2>
|
|
227
|
+
</DrawerVariants>
|
|
296
228
|
</Drawer>
|
|
297
229
|
```
|
|
298
230
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
- Snap point values range from 0 to 1 (e.g., `0.5` = 50% of screen height)
|
|
302
|
-
- The drawer automatically snaps to the nearest point when released
|
|
303
|
-
- Dragging beyond the lowest snap point dismisses the drawer
|
|
304
|
-
- Use `bind:activeSnapPoint` to programmatically control the current position
|
|
305
|
-
- Use `onSnapPointChange` callback to react to snap changes
|
|
231
|
+
Available: `default`, `sheet`, `dialog`, `minimal`, `sidebar`.
|
|
306
232
|
|
|
307
|
-
### Portal
|
|
233
|
+
### Portal
|
|
308
234
|
|
|
309
|
-
|
|
235
|
+
Renders the drawer at the end of `<body>` to avoid z-index and overflow conflicts.
|
|
310
236
|
|
|
311
237
|
```svelte
|
|
312
|
-
<script>
|
|
313
|
-
import { Drawer, DrawerOverlay, DrawerContent, DrawerHandle } from '@abhivarde/svelte-drawer';
|
|
314
|
-
|
|
315
|
-
let open = $state(false);
|
|
316
|
-
</script>
|
|
317
|
-
|
|
318
|
-
<!-- Enable portal (renders at end of body) -->
|
|
319
238
|
<Drawer bind:open portal={true}>
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
</DrawerContent>
|
|
326
|
-
</Drawer>
|
|
327
|
-
|
|
328
|
-
<!-- Custom portal container -->
|
|
329
|
-
<Drawer bind:open portal={true} portalContainer="#custom-portal">
|
|
330
|
-
<DrawerOverlay />
|
|
331
|
-
<DrawerContent>
|
|
332
|
-
<h2>Custom Portal</h2>
|
|
333
|
-
</DrawerContent>
|
|
239
|
+
<DrawerOverlay />
|
|
240
|
+
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-4">
|
|
241
|
+
<DrawerHandle class="mb-8" />
|
|
242
|
+
<h2>Portal Drawer</h2>
|
|
243
|
+
</DrawerContent>
|
|
334
244
|
</Drawer>
|
|
335
|
-
|
|
336
|
-
<div id="custom-portal"></div>
|
|
337
245
|
```
|
|
338
246
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
- Complex layouts with nested z-index contexts
|
|
342
|
-
- Third-party component libraries with fixed positioning
|
|
343
|
-
- Modals inside scrollable containers
|
|
344
|
-
- Preventing overflow: hidden conflicts
|
|
345
|
-
|
|
346
|
-
### Header & Footer Components
|
|
347
|
-
|
|
348
|
-
Optional pre-styled header and footer components for quick setup.
|
|
349
|
-
|
|
350
|
-
#### DrawerHeader
|
|
247
|
+
Custom container:
|
|
351
248
|
|
|
352
249
|
```svelte
|
|
353
|
-
<
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
let open = $state(false);
|
|
357
|
-
</script>
|
|
358
|
-
|
|
359
|
-
<!-- With title and description -->
|
|
360
|
-
<Drawer bind:open>
|
|
361
|
-
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
362
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg">
|
|
363
|
-
<DrawerHeader
|
|
364
|
-
title="Drawer Title"
|
|
365
|
-
description="Optional description text"
|
|
366
|
-
showCloseButton={true}
|
|
367
|
-
/>
|
|
368
|
-
<div class="p-4">
|
|
369
|
-
<p>Drawer content here</p>
|
|
370
|
-
</div>
|
|
371
|
-
</DrawerContent>
|
|
250
|
+
<Drawer bind:open portal={true} portalContainer="#my-portal">
|
|
251
|
+
...
|
|
372
252
|
</Drawer>
|
|
373
253
|
|
|
374
|
-
|
|
375
|
-
<Drawer bind:open>
|
|
376
|
-
<DrawerOverlay />
|
|
377
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg">
|
|
378
|
-
<DrawerHeader>
|
|
379
|
-
<div class="flex items-center gap-3">
|
|
380
|
-
<img src="/icon.png" alt="Icon" class="w-8 h-8" />
|
|
381
|
-
<div>
|
|
382
|
-
<h2 class="font-semibold">Custom Header</h2>
|
|
383
|
-
<p class="text-sm text-gray-600">Your custom content</p>
|
|
384
|
-
</div>
|
|
385
|
-
</div>
|
|
386
|
-
</DrawerHeader>
|
|
387
|
-
<div class="p-4">
|
|
388
|
-
<p>Drawer content</p>
|
|
389
|
-
</div>
|
|
390
|
-
</DrawerContent>
|
|
391
|
-
</Drawer>
|
|
254
|
+
<div id="my-portal"></div>
|
|
392
255
|
```
|
|
393
256
|
|
|
394
|
-
|
|
257
|
+
### Header and Footer
|
|
395
258
|
|
|
396
|
-
|
|
397
|
-
<script>
|
|
398
|
-
import { Drawer, DrawerOverlay, DrawerContent, DrawerFooter } from '@abhivarde/svelte-drawer';
|
|
399
|
-
|
|
400
|
-
let open = $state(false);
|
|
401
|
-
</script>
|
|
402
|
-
|
|
403
|
-
<!-- Simple footer with custom content -->
|
|
404
|
-
<Drawer bind:open>
|
|
405
|
-
<DrawerOverlay class="fixed inset-0 bg-black/40" />
|
|
406
|
-
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg flex flex-col">
|
|
407
|
-
<div class="p-4 flex-1">
|
|
408
|
-
<h2>Drawer Content</h2>
|
|
409
|
-
</div>
|
|
410
|
-
<DrawerFooter>
|
|
411
|
-
<button onclick={() => open = false} class="px-4 py-2 bg-gray-200 rounded">
|
|
412
|
-
Cancel
|
|
413
|
-
</button>
|
|
414
|
-
<button class="px-4 py-2 bg-black text-white rounded">
|
|
415
|
-
Confirm
|
|
416
|
-
</button>
|
|
417
|
-
</DrawerFooter>
|
|
418
|
-
</DrawerContent>
|
|
419
|
-
</Drawer>
|
|
259
|
+
Optional pre-styled components for quick layout setup.
|
|
420
260
|
|
|
421
|
-
|
|
261
|
+
```svelte
|
|
422
262
|
<Drawer bind:open>
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
</DrawerContent>
|
|
263
|
+
<DrawerOverlay />
|
|
264
|
+
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg flex flex-col h-[70vh]">
|
|
265
|
+
<DrawerHeader title="Settings" description="Manage your preferences" />
|
|
266
|
+
<div class="p-4 flex-1 overflow-y-auto">
|
|
267
|
+
<p>Content here</p>
|
|
268
|
+
</div>
|
|
269
|
+
<DrawerFooter>
|
|
270
|
+
<button onclick={() => open = false} class="px-4 py-2 bg-gray-200 rounded">Cancel</button>
|
|
271
|
+
<button class="px-4 py-2 bg-black text-white rounded">Save</button>
|
|
272
|
+
</DrawerFooter>
|
|
273
|
+
</DrawerContent>
|
|
435
274
|
</Drawer>
|
|
436
275
|
```
|
|
437
276
|
|
|
438
|
-
|
|
277
|
+
These are optional. You can use plain HTML instead.
|
|
439
278
|
|
|
440
279
|
### Persistent State
|
|
441
280
|
|
|
442
|
-
|
|
281
|
+
Saves and restores drawer state across page reloads.
|
|
443
282
|
|
|
444
283
|
```svelte
|
|
445
|
-
<
|
|
446
|
-
import { Drawer, DrawerOverlay, DrawerContent } from '@abhivarde/svelte-drawer';
|
|
447
|
-
|
|
448
|
-
let open = $state(false);
|
|
449
|
-
</script>
|
|
450
|
-
|
|
451
|
-
<Drawer
|
|
452
|
-
bind:open
|
|
453
|
-
persistState={true}
|
|
454
|
-
persistKey="main-drawer"
|
|
455
|
-
>
|
|
284
|
+
<Drawer bind:open persistState={true} persistKey="settings-drawer">
|
|
456
285
|
<DrawerOverlay />
|
|
457
|
-
<DrawerContent class="
|
|
458
|
-
<
|
|
459
|
-
<p>
|
|
286
|
+
<DrawerContent class="fixed bottom-0 left-0 right-0 bg-white rounded-t-lg p-6">
|
|
287
|
+
<DrawerHandle class="mb-8" />
|
|
288
|
+
<p>This drawer remembers if it was open.</p>
|
|
460
289
|
</DrawerContent>
|
|
461
290
|
</Drawer>
|
|
462
291
|
```
|
|
463
292
|
|
|
464
|
-
|
|
293
|
+
With snap points:
|
|
465
294
|
|
|
466
295
|
```svelte
|
|
467
296
|
<Drawer
|
|
@@ -472,228 +301,102 @@ Automatically save and restore drawer state across page reloads.
|
|
|
472
301
|
persistKey="snap-drawer"
|
|
473
302
|
persistSnapPoint={true}
|
|
474
303
|
>
|
|
475
|
-
|
|
476
|
-
<DrawerContent class="...">
|
|
477
|
-
<h2>Position is saved too!</h2>
|
|
478
|
-
<p>The snap point will be restored on reload.</p>
|
|
479
|
-
</DrawerContent>
|
|
304
|
+
...
|
|
480
305
|
</Drawer>
|
|
481
306
|
```
|
|
482
307
|
|
|
483
|
-
|
|
308
|
+
Clear saved state:
|
|
484
309
|
|
|
485
310
|
```svelte
|
|
486
311
|
<script>
|
|
487
312
|
import { clearDrawerState } from '@abhivarde/svelte-drawer';
|
|
488
|
-
|
|
489
|
-
function resetDrawer() {
|
|
490
|
-
clearDrawerState('main-drawer');
|
|
491
|
-
// Drawer will reset to default state on next load
|
|
492
|
-
}
|
|
493
|
-
</script>
|
|
494
|
-
|
|
495
|
-
<button onclick={resetDrawer}>Reset Drawer State</button>
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
### Auto Height (AI & Dynamic Content)
|
|
499
|
-
|
|
500
|
-
Use `autoHeight` on `DrawerContent` when your drawer content changes height at runtime like AI streaming responses, multi-step forms, search results, or dynamic lists.
|
|
501
|
-
|
|
502
|
-
```svelte
|
|
503
|
-
<script>
|
|
504
|
-
import {
|
|
505
|
-
Drawer,
|
|
506
|
-
DrawerOverlay,
|
|
507
|
-
DrawerContent,
|
|
508
|
-
DrawerHandle
|
|
509
|
-
} from '@abhivarde/svelte-drawer';
|
|
510
|
-
|
|
511
|
-
let open = $state(false);
|
|
512
|
-
let streaming = $state(false);
|
|
513
|
-
let text = $state('');
|
|
514
|
-
|
|
515
|
-
async function simulate() {
|
|
516
|
-
open = true;
|
|
517
|
-
streaming = true;
|
|
518
|
-
text = '';
|
|
519
|
-
|
|
520
|
-
const content =
|
|
521
|
-
'Sure! Here is what autoHeight does. It watches your content with a ResizeObserver. When content grows, the drawer follows automatically. No magic numbers, no hardcoded heights, it just works smoothly with streaming UI like AI chat apps.';
|
|
522
|
-
|
|
523
|
-
for (let i = 0; i < content.length; i++) {
|
|
524
|
-
text += content[i];
|
|
525
|
-
await new Promise(r => setTimeout(r, 18));
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
streaming = false;
|
|
529
|
-
}
|
|
530
313
|
</script>
|
|
531
314
|
|
|
532
|
-
<button onclick={
|
|
533
|
-
|
|
534
|
-
<Drawer bind:open>
|
|
535
|
-
<DrawerOverlay />
|
|
536
|
-
|
|
537
|
-
<DrawerContent
|
|
538
|
-
autoHeight
|
|
539
|
-
class="bg-gray-100 flex flex-col rounded-t-[10px] fixed bottom-0 left-0 right-0 outline-none"
|
|
540
|
-
>
|
|
541
|
-
<div class="p-4 bg-white rounded-t-[10px]">
|
|
542
|
-
<DrawerHandle class="mb-8" />
|
|
543
|
-
|
|
544
|
-
<p class="font-medium mb-2 text-gray-900">
|
|
545
|
-
AI Response
|
|
546
|
-
</p>
|
|
547
|
-
|
|
548
|
-
{#if text}
|
|
549
|
-
<p class="text-sm text-gray-600 leading-relaxed">
|
|
550
|
-
{text}{streaming ? '▌' : ''}
|
|
551
|
-
</p>
|
|
552
|
-
{/if}
|
|
553
|
-
</div>
|
|
554
|
-
</DrawerContent>
|
|
555
|
-
</Drawer>
|
|
315
|
+
<button onclick={() => clearDrawerState('settings-drawer')}>Reset</button>
|
|
556
316
|
```
|
|
557
317
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
- `height: auto` is applied to the drawer when `autoHeight` is true
|
|
561
|
-
- The drawer grows and shrinks naturally as content changes
|
|
562
|
-
- Perfect for AI streaming, dynamic lists, forms, and async content
|
|
563
|
-
- The slide animation remains smooth since it uses CSS transforms separately
|
|
564
|
-
- Fully compatible with snap points, portals, and existing props
|
|
565
|
-
- Zero impact on drawers that do not use `autoHeight` (opt-in, default `false`)
|
|
566
|
-
|
|
567
|
-
## Variants
|
|
318
|
+
### Keyboard Shortcuts
|
|
568
319
|
|
|
569
|
-
|
|
320
|
+
- `Escape` to close (disable with `closeOnEscape={false}`)
|
|
321
|
+
- `Tab` and `Shift+Tab` to navigate focusable elements
|
|
322
|
+
- `Enter` or `Space` on overlay to close
|
|
570
323
|
|
|
571
|
-
|
|
572
|
-
- `sheet` - iOS-style bottom sheet (white, rounded, 85vh height)
|
|
573
|
-
- `dialog` - Center modal dialog style
|
|
574
|
-
- `minimal` - Simple bottom drawer without extra styling
|
|
575
|
-
- `sidebar` - Side navigation drawer (full height)
|
|
324
|
+
### Focus Management
|
|
576
325
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
- **Escape** - Close the drawer (can be disabled with `closeOnEscape={false}`)
|
|
580
|
-
- **Tab / Shift+Tab** - Navigate between focusable elements inside the drawer
|
|
581
|
-
- **Enter / Space** (on overlay) - Close the drawer
|
|
326
|
+
The drawer auto-focuses the first focusable element when it opens, traps focus while open, and restores focus on close. Disable focus trapping with `trapFocus={false}` on `DrawerContent`.
|
|
582
327
|
|
|
583
328
|
## API Reference
|
|
584
329
|
|
|
585
330
|
### Drawer
|
|
586
331
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
### DrawerOverlay
|
|
606
|
-
|
|
607
|
-
Overlay component that appears behind the drawer.
|
|
608
|
-
|
|
609
|
-
**Props:**
|
|
610
|
-
|
|
611
|
-
- `class` (string, optional) - CSS classes for styling
|
|
612
|
-
- `blur` (boolean | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl', optional) - Enable backdrop blur effect
|
|
332
|
+
| Prop | Type | Default | Description |
|
|
333
|
+
| ------------------- | -------------------------------- | --------- | ---------------------------------- |
|
|
334
|
+
| `open` | `boolean` | `false` | Controls open state (bindable) |
|
|
335
|
+
| `onOpenChange` | `(open: boolean) => void` | | Callback when open state changes |
|
|
336
|
+
| `direction` | `bottom \| top \| left \| right` | `bottom` | Slide-in edge |
|
|
337
|
+
| `closeOnEscape` | `boolean` | `true` | Close on Escape key |
|
|
338
|
+
| `closeThreshold` | `number` | `0.3` | Drag distance to dismiss (0 to 1) |
|
|
339
|
+
| `animationDuration` | `number` | `220` | Animation duration in milliseconds |
|
|
340
|
+
| `animationEasing` | `(t: number) => number` | `expoOut` | Easing function for animations |
|
|
341
|
+
| `snapPoints` | `number[]` | | Snap positions between 0 and 1 |
|
|
342
|
+
| `activeSnapPoint` | `number` | | Current snap point (bindable) |
|
|
343
|
+
| `onSnapPointChange` | `(point: number) => void` | | Fires when snap point changes |
|
|
344
|
+
| `portal` | `boolean` | `false` | Render in a portal |
|
|
345
|
+
| `portalContainer` | `HTMLElement \| string` | | Custom portal target |
|
|
346
|
+
| `persistState` | `boolean` | `false` | Save state to localStorage |
|
|
347
|
+
| `persistKey` | `string` | `default` | Unique key for saved state |
|
|
348
|
+
| `persistSnapPoint` | `boolean` | `false` | Also save snap point position |
|
|
613
349
|
|
|
614
350
|
### DrawerContent
|
|
615
351
|
|
|
616
|
-
|
|
352
|
+
| Prop | Type | Default | Description |
|
|
353
|
+
| ------------ | --------- | ------- | ---------------------------- |
|
|
354
|
+
| `class` | `string` | | CSS classes |
|
|
355
|
+
| `trapFocus` | `boolean` | `true` | Trap keyboard focus inside |
|
|
356
|
+
| `autoHeight` | `boolean` | `false` | Resize to fit content height |
|
|
617
357
|
|
|
618
|
-
|
|
358
|
+
### DrawerOverlay
|
|
619
359
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
360
|
+
| Prop | Type | Default | Description |
|
|
361
|
+
| ------- | ----------------------------------------------- | ------- | ----------------------- |
|
|
362
|
+
| `class` | `string` | | CSS classes |
|
|
363
|
+
| `blur` | `boolean \| sm \| md \| lg \| xl \| 2xl \| 3xl` | | Backdrop blur intensity |
|
|
623
364
|
|
|
624
365
|
### DrawerHandle
|
|
625
366
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
- `class` (string, optional) - CSS classes for styling
|
|
631
|
-
|
|
632
|
-
**Features:**
|
|
633
|
-
|
|
634
|
-
- Automatically horizontal for `bottom`/`top` drawers (12px wide, 1.5px tall)
|
|
635
|
-
- Automatically vertical for `left`/`right` drawers (1.5px wide, 12px tall)
|
|
636
|
-
- Includes `data-drawer-drag` attribute for improved touch targeting
|
|
637
|
-
- Fully customizable with Tailwind classes
|
|
638
|
-
|
|
639
|
-
**Example:**
|
|
367
|
+
| Prop | Type | Default | Description |
|
|
368
|
+
| ------- | -------- | ------- | ----------- |
|
|
369
|
+
| `class` | `string` | | CSS classes |
|
|
640
370
|
|
|
641
|
-
|
|
642
|
-
<!-- Default gray handle -->
|
|
643
|
-
<DrawerHandle class="mb-8" />
|
|
644
|
-
|
|
645
|
-
<!-- Custom color -->
|
|
646
|
-
<DrawerHandle class="bg-blue-500 mb-8" />
|
|
647
|
-
|
|
648
|
-
<!-- Larger size -->
|
|
649
|
-
<DrawerHandle class="w-16 h-2 mb-8" />
|
|
650
|
-
```
|
|
371
|
+
Automatically horizontal for `bottom` and `top` drawers, vertical for `left` and `right`.
|
|
651
372
|
|
|
652
373
|
### DrawerVariants
|
|
653
374
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
- `class` (string, optional) - Additional CSS classes for styling
|
|
660
|
-
- `trapFocus` (boolean, optional, default: true) - Whether to trap focus inside drawer
|
|
375
|
+
| Prop | Type | Default | Description |
|
|
376
|
+
| ----------- | -------------------------------------------------- | --------- | -------------------------- |
|
|
377
|
+
| `variant` | `default \| sheet \| dialog \| minimal \| sidebar` | `default` | Preset style |
|
|
378
|
+
| `class` | `string` | | Additional CSS classes |
|
|
379
|
+
| `trapFocus` | `boolean` | `true` | Trap keyboard focus inside |
|
|
661
380
|
|
|
662
381
|
### DrawerHeader
|
|
663
382
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
- `onClose` (function, optional) - Custom close handler
|
|
672
|
-
- `class` (string, optional) - CSS classes for styling
|
|
673
|
-
|
|
674
|
-
**Features:**
|
|
675
|
-
|
|
676
|
-
- Automatic close button with drawer context
|
|
677
|
-
- Customizable via children render
|
|
678
|
-
- Border and padding included
|
|
383
|
+
| Prop | Type | Default | Description |
|
|
384
|
+
| ----------------- | ------------ | ------- | ----------------------- |
|
|
385
|
+
| `title` | `string` | | Header title |
|
|
386
|
+
| `description` | `string` | | Description below title |
|
|
387
|
+
| `showCloseButton` | `boolean` | `true` | Show close button |
|
|
388
|
+
| `onClose` | `() => void` | | Custom close handler |
|
|
389
|
+
| `class` | `string` | | CSS classes |
|
|
679
390
|
|
|
680
391
|
### DrawerFooter
|
|
681
392
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
- `class` (string, optional) - CSS classes for styling
|
|
687
|
-
|
|
688
|
-
**Features:**
|
|
689
|
-
|
|
690
|
-
- Automatic border and spacing
|
|
691
|
-
- Flexible content via children
|
|
692
|
-
- Works with mt-auto for bottom positioning
|
|
393
|
+
| Prop | Type | Default | Description |
|
|
394
|
+
| ------- | -------- | ------- | ----------- |
|
|
395
|
+
| `class` | `string` | | CSS classes |
|
|
693
396
|
|
|
694
397
|
## Demo
|
|
695
398
|
|
|
696
|
-
|
|
399
|
+
[drawer.abhivarde.in](https://drawer.abhivarde.in)
|
|
697
400
|
|
|
698
401
|
## Star History
|
|
699
402
|
|
|
@@ -701,8 +404,7 @@ Visit [drawer.abhivarde.in](https://drawer.abhivarde.in) to see live examples.
|
|
|
701
404
|
|
|
702
405
|
## License
|
|
703
406
|
|
|
704
|
-
|
|
705
|
-
See the [LICENSE](./LICENSE) file for details.
|
|
407
|
+
MIT. See [LICENSE](./LICENSE) for details.
|
|
706
408
|
|
|
707
409
|
## Credits
|
|
708
410
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { expoOut } from "svelte/easing";
|
|
4
4
|
import { setContext, onMount } from "svelte";
|
|
5
5
|
import DrawerPortal from "./DrawerPortal.svelte";
|
|
6
|
-
import { saveDrawerState, loadDrawerState } from "../utils/storage";
|
|
6
|
+
import { saveDrawerState, loadDrawerState } from "../utils/storage";
|
|
7
7
|
|
|
8
8
|
let {
|
|
9
9
|
open = $bindable(false),
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
persistKey = "default",
|
|
20
20
|
persistSnapPoint = false,
|
|
21
21
|
closeThreshold = 0.3,
|
|
22
|
+
animationDuration = 220,
|
|
23
|
+
animationEasing = expoOut,
|
|
22
24
|
children,
|
|
23
25
|
} = $props();
|
|
24
26
|
|
|
@@ -27,10 +29,7 @@
|
|
|
27
29
|
easing: expoOut,
|
|
28
30
|
});
|
|
29
31
|
|
|
30
|
-
let drawerPosition = new Tween(100
|
|
31
|
-
duration: 220,
|
|
32
|
-
easing: expoOut,
|
|
33
|
-
});
|
|
32
|
+
let drawerPosition = new Tween(100);
|
|
34
33
|
|
|
35
34
|
let previouslyFocusedElement: HTMLElement | null = null;
|
|
36
35
|
let visible = false;
|
|
@@ -85,7 +84,10 @@
|
|
|
85
84
|
previousSnapPoint !== activeSnapPoint
|
|
86
85
|
) {
|
|
87
86
|
const snapPos = (1 - activeSnapPoint) * 100;
|
|
88
|
-
drawerPosition.set(snapPos, {
|
|
87
|
+
drawerPosition.set(snapPos, {
|
|
88
|
+
duration: animationDuration,
|
|
89
|
+
easing: animationEasing,
|
|
90
|
+
});
|
|
89
91
|
}
|
|
90
92
|
previousSnapPoint = activeSnapPoint;
|
|
91
93
|
}
|
|
@@ -104,9 +106,15 @@
|
|
|
104
106
|
activeSnapPoint = snapPoints[snapPoints.length - 1];
|
|
105
107
|
}
|
|
106
108
|
const snapPos = (1 - activeSnapPoint) * 100;
|
|
107
|
-
drawerPosition.set(snapPos, {
|
|
109
|
+
drawerPosition.set(snapPos, {
|
|
110
|
+
duration: animationDuration,
|
|
111
|
+
easing: animationEasing,
|
|
112
|
+
});
|
|
108
113
|
} else {
|
|
109
|
-
drawerPosition.set(0
|
|
114
|
+
drawerPosition.set(0, {
|
|
115
|
+
duration: animationDuration,
|
|
116
|
+
easing: animationEasing,
|
|
117
|
+
});
|
|
110
118
|
}
|
|
111
119
|
} else if (visible) {
|
|
112
120
|
if (
|
|
@@ -119,7 +127,10 @@
|
|
|
119
127
|
}
|
|
120
128
|
|
|
121
129
|
overlayOpacity.set(0, { duration: 120 });
|
|
122
|
-
drawerPosition.set(100, {
|
|
130
|
+
drawerPosition.set(100, {
|
|
131
|
+
duration: animationDuration,
|
|
132
|
+
easing: animationEasing,
|
|
133
|
+
});
|
|
123
134
|
|
|
124
135
|
document.body.style.overflow = "";
|
|
125
136
|
|
|
@@ -131,7 +142,7 @@
|
|
|
131
142
|
setTimeout(() => {
|
|
132
143
|
visible = false;
|
|
133
144
|
previousSnapPoint = undefined;
|
|
134
|
-
},
|
|
145
|
+
}, animationDuration);
|
|
135
146
|
}
|
|
136
147
|
});
|
|
137
148
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { expoOut } from "svelte/easing";
|
|
1
2
|
declare const Drawer: import("svelte").Component<{
|
|
2
3
|
open?: boolean;
|
|
3
4
|
onOpenChange?: any;
|
|
@@ -12,6 +13,8 @@ declare const Drawer: import("svelte").Component<{
|
|
|
12
13
|
persistKey?: string;
|
|
13
14
|
persistSnapPoint?: boolean;
|
|
14
15
|
closeThreshold?: number;
|
|
16
|
+
animationDuration?: number;
|
|
17
|
+
animationEasing?: typeof expoOut;
|
|
15
18
|
children: any;
|
|
16
19
|
}, {}, "open" | "activeSnapPoint">;
|
|
17
20
|
type Drawer = ReturnType<typeof Drawer>;
|
package/dist/types.d.ts
CHANGED