css-drawer 0.2.1 → 0.3.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 +75 -4
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/observer-B-WjvsFU.cjs +1 -0
- package/dist/{drawer-C21nwiwE.css → observer-CtfG4nrq.css} +20 -19
- package/dist/observer-DIOx0VCj.mjs +2 -0
- package/dist/observer-DIOx0VCj.mjs.map +1 -0
- package/dist/{drawer-CXCJQa45.css → observer-QD6bSdOu.css} +21 -20
- package/dist/observer-QD6bSdOu.css.map +1 -0
- package/dist/react.cjs +2 -2
- package/dist/react.d.cts +11 -2
- package/dist/react.d.cts.map +1 -1
- package/dist/react.d.mts +11 -2
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +2 -2
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
- package/src/drawer.css +20 -19
- package/dist/drawer-BWZh2Fyp.cjs +0 -0
- package/dist/drawer-CXCJQa45.css.map +0 -1
- package/dist/drawer-CiHZcyXE.mjs +0 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A near drop-in replacement for [Vaul](https://vaul.emilkowal.ski) using native `
|
|
|
8
8
|
|
|
9
9
|
| Feature | Vaul | CSS Drawer |
|
|
10
10
|
|---------|------|------------|
|
|
11
|
-
| Bundle size | ~12KB | **
|
|
11
|
+
| Bundle size | ~12KB | **~2KB** JS + 10.8KB CSS (gzip: ~3KB total) |
|
|
12
12
|
| Animation engine | JavaScript | Pure CSS |
|
|
13
13
|
| Nesting | Manual setup | Automatic (CSS `:has()`) |
|
|
14
14
|
| Accessibility | Built-in | Automatic (native `<dialog>` + `inert`) |
|
|
@@ -89,6 +89,7 @@ Then use the native dialog API in your component:
|
|
|
89
89
|
|
|
90
90
|
```typescript
|
|
91
91
|
import { Component } from '@angular/core';
|
|
92
|
+
import { getTop, closeAll } from 'css-drawer';
|
|
92
93
|
|
|
93
94
|
@Component({
|
|
94
95
|
selector: 'app-example',
|
|
@@ -96,6 +97,9 @@ import { Component } from '@angular/core';
|
|
|
96
97
|
<button (click)="openDrawer(drawer)">Open</button>
|
|
97
98
|
|
|
98
99
|
<dialog #drawer class="drawer" data-direction="modal">
|
|
100
|
+
@if (isTopDrawer(drawer)) {
|
|
101
|
+
<div class="top-badge">Top Drawer</div>
|
|
102
|
+
}
|
|
99
103
|
<div class="drawer-content">
|
|
100
104
|
<h2>Title</h2>
|
|
101
105
|
<button (click)="closeDrawer(drawer)">Close</button>
|
|
@@ -111,9 +115,19 @@ export class ExampleComponent {
|
|
|
111
115
|
closeDrawer(dialog: HTMLDialogElement) {
|
|
112
116
|
dialog.close();
|
|
113
117
|
}
|
|
118
|
+
|
|
119
|
+
isTopDrawer(dialog: HTMLDialogElement): boolean {
|
|
120
|
+
return getTop() === dialog;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
closeAllDrawers() {
|
|
124
|
+
closeAll();
|
|
125
|
+
}
|
|
114
126
|
}
|
|
115
127
|
```
|
|
116
128
|
|
|
129
|
+
> **Note:** Angular's change detection runs after template-bound events like `(click)`, so `isTopDrawer()` re-evaluates automatically. For zoneless Angular or programmatic updates outside template events, use signals.
|
|
130
|
+
|
|
117
131
|
---
|
|
118
132
|
|
|
119
133
|
## React API
|
|
@@ -223,6 +237,50 @@ Semantic description for accessibility.
|
|
|
223
237
|
|------|------|---------|-------------|
|
|
224
238
|
| `...props` | `HTMLAttributes<HTMLParagraphElement>` | - | All native p props |
|
|
225
239
|
|
|
240
|
+
### useIsTopDrawer(ref)
|
|
241
|
+
|
|
242
|
+
Hook to check if a drawer is the topmost open drawer. Useful for conditionally rendering content (like notifications) only in the top drawer.
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
import { useRef } from 'react'
|
|
246
|
+
import { Drawer, useIsTopDrawer } from 'css-drawer/react'
|
|
247
|
+
|
|
248
|
+
function MyDrawer() {
|
|
249
|
+
const ref = useRef<HTMLDialogElement>(null)
|
|
250
|
+
const isTop = useIsTopDrawer(ref)
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<Drawer.Root>
|
|
254
|
+
<Drawer.Content ref={ref}>
|
|
255
|
+
{isTop && <div className="notification">You have new messages</div>}
|
|
256
|
+
{/* drawer content */}
|
|
257
|
+
</Drawer.Content>
|
|
258
|
+
</Drawer.Root>
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
| Param | Type | Description |
|
|
264
|
+
|-------|------|-------------|
|
|
265
|
+
| `ref` | `RefObject<HTMLDialogElement \| null>` | Ref to the drawer dialog element |
|
|
266
|
+
|
|
267
|
+
**Returns:** `boolean` - `true` if this drawer is currently the topmost open drawer
|
|
268
|
+
|
|
269
|
+
The hook automatically updates when any drawer opens or closes.
|
|
270
|
+
|
|
271
|
+
### getTopDrawer()
|
|
272
|
+
|
|
273
|
+
Utility function to get the topmost open drawer element. Useful for imperative access.
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { getTopDrawer } from 'css-drawer/react'
|
|
277
|
+
|
|
278
|
+
const topDrawer = getTopDrawer()
|
|
279
|
+
topDrawer?.close()
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Returns:** `HTMLDialogElement | null`
|
|
283
|
+
|
|
226
284
|
---
|
|
227
285
|
|
|
228
286
|
## Vanilla JS API
|
|
@@ -230,7 +288,7 @@ Semantic description for accessibility.
|
|
|
230
288
|
### Installation
|
|
231
289
|
|
|
232
290
|
```ts
|
|
233
|
-
import { open, close, closeAll } from 'css-drawer'
|
|
291
|
+
import { open, close, closeAll, getTop, subscribe } from 'css-drawer'
|
|
234
292
|
// Styles are auto-injected
|
|
235
293
|
```
|
|
236
294
|
|
|
@@ -613,8 +671,16 @@ Override any of these CSS custom properties to customize the drawer:
|
|
|
613
671
|
|
|
614
672
|
| Variable | Default | Description |
|
|
615
673
|
|----------|---------|-------------|
|
|
616
|
-
| `--drawer-
|
|
617
|
-
| `--drawer-
|
|
674
|
+
| `--drawer-width` | direction-based | Drawer width (100% for bottom/top, 500px for left/right) |
|
|
675
|
+
| `--drawer-height` | direction-based | Drawer height (auto for bottom/top, 100dvh for left/right) |
|
|
676
|
+
| `--drawer-max-width` | direction-based | Maximum width (none for bottom/top, 90% for left/right/modal) |
|
|
677
|
+
| `--drawer-max-height` | `96dvh` | Maximum height (bottom/top/modal only) |
|
|
678
|
+
| `--drawer-modal-width` | `fit-content` | Modal width |
|
|
679
|
+
| `--drawer-modal-height` | `fit-content` | Modal height |
|
|
680
|
+
|
|
681
|
+
> **Note:** `--drawer-width`, `--drawer-height`, and `--drawer-max-width` are not defined globally—each direction uses sensible fallbacks. Set these per-instance to override.
|
|
682
|
+
|
|
683
|
+
> **Fullscreen modal:** Set `--drawer-modal-width`, `--drawer-modal-height`, `--drawer-max-width`, and `--drawer-max-height` to `100%`.
|
|
618
684
|
|
|
619
685
|
#### Handle
|
|
620
686
|
|
|
@@ -810,6 +876,8 @@ Full TypeScript support included.
|
|
|
810
876
|
// React
|
|
811
877
|
import {
|
|
812
878
|
Drawer,
|
|
879
|
+
useIsTopDrawer,
|
|
880
|
+
getTopDrawer,
|
|
813
881
|
type DrawerRootProps,
|
|
814
882
|
type DrawerContentProps,
|
|
815
883
|
type DrawerDirection
|
|
@@ -819,6 +887,9 @@ import {
|
|
|
819
887
|
import {
|
|
820
888
|
open,
|
|
821
889
|
close,
|
|
890
|
+
getTop,
|
|
891
|
+
closeAll,
|
|
892
|
+
subscribe,
|
|
822
893
|
create,
|
|
823
894
|
type DrawerElement,
|
|
824
895
|
type DrawerRef,
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require('./
|
|
2
|
-
|
|
1
|
+
require('./observer-CtfG4nrq.css');
|
|
2
|
+
const e=require(`./observer-B-WjvsFU.cjs`);function t(e){return e?typeof e==`string`?document.getElementById(e):e:null}function n(e){t(e)?.showModal()}function r(e){t(e)?.close()}function i(){Array.from(document.querySelectorAll(`dialog.drawer[open]`)).reverse().forEach(e=>e.close())}function a(e){return t(e)?.open??!1}function o(){return Array.from(document.querySelectorAll(`dialog.drawer[open]`))}function s(){let e=o();return e[e.length-1]??null}function c(e={}){let{id:t,content:n=``,direction:r,handle:i=!0,className:a=``,closeOnOutsideClick:o=!0}=e,s=document.createElement(`dialog`);return s.className=`drawer ${a}`.trim(),t&&(s.id=t),r&&(s.dataset.direction=r),o||(s.dataset.closeOnOutsideClick=`false`),s.innerHTML=`
|
|
3
3
|
${i?`<div class="drawer-handle"></div>`:``}
|
|
4
4
|
<div class="drawer-content">${n}</div>
|
|
5
|
-
`,s.addEventListener(`click`,e=>{e.target===s&&s.dataset.closeOnOutsideClick!==`false`&&s.close()}),s}function
|
|
5
|
+
`,s.addEventListener(`click`,e=>{e.target===s&&s.dataset.closeOnOutsideClick!==`false`&&s.close()}),s}function l(e){return document.body.appendChild(e),e}function u(e){t(e)?.remove()}function d(){let e=e=>{let t=e.target;t.matches(`dialog.drawer`)&&t.dataset.closeOnOutsideClick!==`false`&&t.close()};return document.addEventListener(`click`,e),()=>document.removeEventListener(`click`,e)}function f(n,r){let i=t(n);if(!i)return()=>{};let{onOpen:a,onClose:o,onCancel:s}=r,c=()=>o?.(),l=()=>s?.(),u=e=>{e.detail?.target===i&&i.open&&a?.()};return i.addEventListener(`close`,c),i.addEventListener(`cancel`,l),window.addEventListener(e.t,u),()=>{i.removeEventListener(`close`,c),i.removeEventListener(`cancel`,l),window.removeEventListener(e.t,u)}}function p(e,t){let n=t?.closeOnOutsideClick??!0;return{id:e,className:`drawer`,"data-close-on-outside-click":n?void 0:`false`,onClick:e=>{n&&e.target===e.currentTarget&&e.currentTarget.close()}}}exports.close=r,exports.closeAll=i,exports.create=c,exports.getOpen=o,exports.getTop=s,exports.init=d,exports.isOpen=a,exports.mount=l,exports.open=n,exports.props=p,exports.subscribe=f,exports.unmount=u;
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AA4BiB,KArBL,aAAA,GAAgB,iBAqBQ;AAuBpB,KA1CJ,SAAA,GA0CiB,MAAA,GA1CI,aA0CK,GAAA,IAAA,GAAA,SAAA;AAQtB,KAhDJ,eAAA,GAgDkB,QAAS,GAAA,KAAA,GAAA,MAAA,GAAA,OAAA,GAAA,OAAA;AAQvB,UAtDC,mBAAA,CAsDO;EAQR;EAQA,EAAA,CAAA,EAAA,MAAO;EAOP;EAQA,OAAA,CAAA,EAAM,MAAA;EA6BN;EAQA,SAAA,CAAO,EApHT,eAoHkB;EAUhB;EAgBA,MAAA,CAAA,EAAA,OAAS;EAmCT;;;;;UAxKC,mBAAA;;;;;;;;;;;iBAuBD,IAAA,SAAa;;;;iBAQb,KAAA,SAAc;;;;iBAQd,QAAA,CAAA;;;;iBAQA,MAAA,SAAe;;;;iBAQf,OAAA,CAAA,GAAW;;;;iBAOX,MAAA,CAAA,GAAU;;;;iBAQV,MAAA,WAAgB,sBAA2B;;;;iBA6B3C,KAAA,SAAc,gBAAgB;;;;iBAQ9B,OAAA,SAAgB;;;;;;iBAUhB,IAAA,CAAA;;;;;iBAgBA,SAAA,SACN,qBACE;;;;;iBAiCI,KAAA;;;;;;wBAMC"}
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AA4BiB,KArBL,aAAA,GAAgB,iBAqBQ;AAuBpB,KA1CJ,SAAA,GA0CiB,MAAA,GA1CI,aA0CK,GAAA,IAAA,GAAA,SAAA;AAQtB,KAhDJ,eAAA,GAgDkB,QAAS,GAAA,KAAA,GAAA,MAAA,GAAA,OAAA,GAAA,OAAA;AAQvB,UAtDC,mBAAA,CAsDO;EAQR;EAQA,EAAA,CAAA,EAAA,MAAO;EAOP;EAQA,OAAA,CAAA,EAAM,MAAA;EA6BN;EAQA,SAAA,CAAO,EApHT,eAoHkB;EAUhB;EAgBA,MAAA,CAAA,EAAA,OAAS;EAmCT;;;;;UAxKC,mBAAA;;;;;;;;;;;iBAuBD,IAAA,SAAa;;;;iBAQb,KAAA,SAAc;;;;iBAQd,QAAA,CAAA;;;;iBAQA,MAAA,SAAe;;;;iBAQf,OAAA,CAAA,GAAW;;;;iBAOX,MAAA,CAAA,GAAU;;;;iBAQV,MAAA,WAAgB,sBAA2B;;;;iBA6B3C,KAAA,SAAc,gBAAgB;;;;iBAQ9B,OAAA,SAAgB;;;;;;iBAUhB,IAAA,CAAA;;;;;iBAgBA,SAAA,SACN,qBACE;;;;;iBAiCI,KAAA;;;;;;wBAMC"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import"./
|
|
2
|
-
|
|
1
|
+
import{t as e}from"./observer-DIOx0VCj.mjs";import './observer-QD6bSdOu.css';
|
|
2
|
+
function t(e){return e?typeof e==`string`?document.getElementById(e):e:null}function n(e){t(e)?.showModal()}function r(e){t(e)?.close()}function i(){Array.from(document.querySelectorAll(`dialog.drawer[open]`)).reverse().forEach(e=>e.close())}function a(e){return t(e)?.open??!1}function o(){return Array.from(document.querySelectorAll(`dialog.drawer[open]`))}function s(){let e=o();return e[e.length-1]??null}function c(e={}){let{id:t,content:n=``,direction:r,handle:i=!0,className:a=``,closeOnOutsideClick:o=!0}=e,s=document.createElement(`dialog`);return s.className=`drawer ${a}`.trim(),t&&(s.id=t),r&&(s.dataset.direction=r),o||(s.dataset.closeOnOutsideClick=`false`),s.innerHTML=`
|
|
3
3
|
${i?`<div class="drawer-handle"></div>`:``}
|
|
4
4
|
<div class="drawer-content">${n}</div>
|
|
5
|
-
`,s.addEventListener(`click`,e=>{e.target===s&&s.dataset.closeOnOutsideClick!==`false`&&s.close()}),s}function
|
|
5
|
+
`,s.addEventListener(`click`,e=>{e.target===s&&s.dataset.closeOnOutsideClick!==`false`&&s.close()}),s}function l(e){return document.body.appendChild(e),e}function u(e){t(e)?.remove()}function d(){let e=e=>{let t=e.target;t.matches(`dialog.drawer`)&&t.dataset.closeOnOutsideClick!==`false`&&t.close()};return document.addEventListener(`click`,e),()=>document.removeEventListener(`click`,e)}function f(n,r){let i=t(n);if(!i)return()=>{};let{onOpen:a,onClose:o,onCancel:s}=r,c=()=>o?.(),l=()=>s?.(),u=e=>{e.detail?.target===i&&i.open&&a?.()};return i.addEventListener(`close`,c),i.addEventListener(`cancel`,l),window.addEventListener(e,u),()=>{i.removeEventListener(`close`,c),i.removeEventListener(`cancel`,l),window.removeEventListener(e,u)}}function p(e,t){let n=t?.closeOnOutsideClick??!0;return{id:e,className:`drawer`,"data-close-on-outside-click":n?void 0:`false`,onClick:e=>{n&&e.target===e.currentTarget&&e.currentTarget.close()}}}export{r as close,i as closeAll,c as create,o as getOpen,s as getTop,d as init,a as isOpen,l as mount,n as open,p as props,f as subscribe,u as unmount};
|
|
6
6
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["open"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * CSS Drawer - Headless drawer component\n * Works with any framework: React, Vue, Svelte, vanilla JS\n */\nimport './drawer.css'\
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["open"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * CSS Drawer - Headless drawer component\n * Works with any framework: React, Vue, Svelte, vanilla JS\n */\nimport './drawer.css'\nimport { DRAWER_STATE_CHANGE } from './observer'\n\nexport type DrawerElement = HTMLDialogElement\n\nexport type DrawerRef = string | DrawerElement | null | undefined\n\nexport type DrawerDirection = 'bottom' | 'top' | 'left' | 'right' | 'modal'\n\nexport interface CreateDrawerOptions {\n /** Drawer ID */\n id?: string\n /** HTML content for the drawer */\n content?: string\n /** Direction the drawer opens from (default: 'bottom') */\n direction?: DrawerDirection\n /** Include drag handle (default: true) */\n handle?: boolean\n /** Additional CSS classes */\n className?: string\n /** Close when clicking outside (default: true) */\n closeOnOutsideClick?: boolean\n}\n\nexport interface DrawerEventHandlers {\n /** Called when drawer opens */\n onOpen?: () => void\n /** Called when drawer closes */\n onClose?: () => void\n /** Called when drawer is cancelled (backdrop click or Escape) */\n onCancel?: () => void\n}\n\n/**\n * Resolve a drawer reference to an element\n */\nfunction resolve(drawer: DrawerRef): DrawerElement | null {\n if (!drawer) return null\n if (typeof drawer === 'string') {\n return document.getElementById(drawer) as DrawerElement | null\n }\n return drawer\n}\n\n/**\n * Open a drawer by ID or element reference\n */\nexport function open(drawer: DrawerRef): void {\n const el = resolve(drawer)\n el?.showModal()\n}\n\n/**\n * Close a drawer by ID or element reference\n */\nexport function close(drawer: DrawerRef): void {\n const el = resolve(drawer)\n el?.close()\n}\n\n/**\n * Close all open drawers (in reverse DOM order for proper animation)\n */\nexport function closeAll(): void {\n const drawers = Array.from(document.querySelectorAll<DrawerElement>('dialog.drawer[open]'))\n drawers.reverse().forEach((d) => d.close())\n}\n\n/**\n * Check if a drawer is open\n */\nexport function isOpen(drawer: DrawerRef): boolean {\n const el = resolve(drawer)\n return el?.open ?? false\n}\n\n/**\n * Get all open drawers\n */\nexport function getOpen(): DrawerElement[] {\n return Array.from(document.querySelectorAll<DrawerElement>('dialog.drawer[open]'))\n}\n\n/**\n * Get the topmost open drawer\n */\nexport function getTop(): DrawerElement | null {\n const open = getOpen()\n return open[open.length - 1] ?? null\n}\n\n/**\n * Create a drawer element programmatically\n */\nexport function create(options: CreateDrawerOptions = {}): DrawerElement {\n const { id, content = '', direction, handle = true, className = '', closeOnOutsideClick = true } = options\n\n const dialog = document.createElement('dialog') as DrawerElement\n dialog.className = `drawer ${className}`.trim()\n if (id) dialog.id = id\n if (direction) dialog.dataset.direction = direction\n if (!closeOnOutsideClick) {\n dialog.dataset.closeOnOutsideClick = 'false'\n }\n\n dialog.innerHTML = `\n ${handle ? '<div class=\"drawer-handle\"></div>' : ''}\n <div class=\"drawer-content\">${content}</div>\n `\n\n // Backdrop click to close (respects data attribute)\n dialog.addEventListener('click', (e) => {\n if (e.target === dialog && dialog.dataset.closeOnOutsideClick !== 'false') {\n dialog.close()\n }\n })\n\n return dialog\n}\n\n/**\n * Mount a drawer to the DOM (appends to body)\n */\nexport function mount(drawer: DrawerElement): DrawerElement {\n document.body.appendChild(drawer)\n return drawer\n}\n\n/**\n * Unmount a drawer from the DOM\n */\nexport function unmount(drawer: DrawerRef): void {\n const el = resolve(drawer)\n el?.remove()\n}\n\n/**\n * Initialize global backdrop-click-to-close behavior\n * Alternative to adding onclick to each drawer\n * Respects data-close-on-outside-click=\"false\" attribute\n */\nexport function init(): () => void {\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n if (target.matches('dialog.drawer') && (target as DrawerElement).dataset.closeOnOutsideClick !== 'false') {\n ;(target as DrawerElement).close()\n }\n }\n\n document.addEventListener('click', handler)\n return () => document.removeEventListener('click', handler)\n}\n\n/**\n * Subscribe to drawer events\n * @returns Cleanup function\n */\nexport function subscribe(\n drawer: DrawerRef,\n handlers: DrawerEventHandlers\n): () => void {\n const el = resolve(drawer)\n if (!el) return () => {}\n\n const { onOpen, onClose, onCancel } = handlers\n\n const handleClose = () => onClose?.()\n const handleCancel = () => onCancel?.()\n\n // Listen to shared drawer state change event (no per-subscription observer)\n const handleStateChange = (e: Event) => {\n const detail = (e as CustomEvent).detail\n if (detail?.target === el && el.open) {\n onOpen?.()\n }\n }\n\n el.addEventListener('close', handleClose)\n el.addEventListener('cancel', handleCancel)\n window.addEventListener(DRAWER_STATE_CHANGE, handleStateChange)\n\n return () => {\n el.removeEventListener('close', handleClose)\n el.removeEventListener('cancel', handleCancel)\n window.removeEventListener(DRAWER_STATE_CHANGE, handleStateChange)\n }\n}\n\n/**\n * React-friendly hook helper - returns props to spread on dialog\n * Usage: <dialog {...drawer.props('my-drawer')} />\n */\nexport function props(id: string, options?: { closeOnOutsideClick?: boolean }) {\n const closeOnOutsideClick = options?.closeOnOutsideClick ?? true\n return {\n id,\n className: 'drawer',\n 'data-close-on-outside-click': closeOnOutsideClick ? undefined : 'false',\n onClick: (e: MouseEvent) => {\n if (closeOnOutsideClick && e.target === e.currentTarget) {\n ;(e.currentTarget as DrawerElement).close()\n }\n },\n } as const\n}\n\n"],"mappings":"4CAwCA,SAAS,EAAQ,EAAyC,CAKxD,OAJK,EACD,OAAO,GAAW,SACb,SAAS,eAAe,EAAO,CAEjC,EAJa,KAUtB,SAAgB,EAAK,EAAyB,CACjC,EAAQ,EAAO,EACtB,WAAW,CAMjB,SAAgB,EAAM,EAAyB,CAClC,EAAQ,EAAO,EACtB,OAAO,CAMb,SAAgB,GAAiB,CACf,MAAM,KAAK,SAAS,iBAAgC,sBAAsB,CAAC,CACnF,SAAS,CAAC,QAAS,GAAM,EAAE,OAAO,CAAC,CAM7C,SAAgB,EAAO,EAA4B,CAEjD,OADW,EAAQ,EAAO,EACf,MAAQ,GAMrB,SAAgB,GAA2B,CACzC,OAAO,MAAM,KAAK,SAAS,iBAAgC,sBAAsB,CAAC,CAMpF,SAAgB,GAA+B,CAC7C,IAAMA,EAAO,GAAS,CACtB,OAAOA,EAAKA,EAAK,OAAS,IAAM,KAMlC,SAAgB,EAAO,EAA+B,EAAE,CAAiB,CACvE,GAAM,CAAE,KAAI,UAAU,GAAI,YAAW,SAAS,GAAM,YAAY,GAAI,sBAAsB,IAAS,EAE7F,EAAS,SAAS,cAAc,SAAS,CAoB/C,MAnBA,GAAO,UAAY,UAAU,IAAY,MAAM,CAC3C,IAAI,EAAO,GAAK,GAChB,IAAW,EAAO,QAAQ,UAAY,GACrC,IACH,EAAO,QAAQ,oBAAsB,SAGvC,EAAO,UAAY;MACf,EAAS,oCAAsC,GAAG;kCACtB,EAAQ;IAIxC,EAAO,iBAAiB,QAAU,GAAM,CAClC,EAAE,SAAW,GAAU,EAAO,QAAQ,sBAAwB,SAChE,EAAO,OAAO,EAEhB,CAEK,EAMT,SAAgB,EAAM,EAAsC,CAE1D,OADA,SAAS,KAAK,YAAY,EAAO,CAC1B,EAMT,SAAgB,EAAQ,EAAyB,CACpC,EAAQ,EAAO,EACtB,QAAQ,CAQd,SAAgB,GAAmB,CACjC,IAAM,EAAW,GAAkB,CACjC,IAAM,EAAS,EAAE,OACb,EAAO,QAAQ,gBAAgB,EAAK,EAAyB,QAAQ,sBAAwB,SAC7F,EAAyB,OAAO,EAKtC,OADA,SAAS,iBAAiB,QAAS,EAAQ,KAC9B,SAAS,oBAAoB,QAAS,EAAQ,CAO7D,SAAgB,EACd,EACA,EACY,CACZ,IAAM,EAAK,EAAQ,EAAO,CAC1B,GAAI,CAAC,EAAI,UAAa,GAEtB,GAAM,CAAE,SAAQ,UAAS,YAAa,EAEhC,MAAoB,KAAW,CAC/B,MAAqB,KAAY,CAGjC,EAAqB,GAAa,CACtB,EAAkB,QACtB,SAAW,GAAM,EAAG,MAC9B,KAAU,EAQd,OAJA,EAAG,iBAAiB,QAAS,EAAY,CACzC,EAAG,iBAAiB,SAAU,EAAa,CAC3C,OAAO,iBAAiB,EAAqB,EAAkB,KAElD,CACX,EAAG,oBAAoB,QAAS,EAAY,CAC5C,EAAG,oBAAoB,SAAU,EAAa,CAC9C,OAAO,oBAAoB,EAAqB,EAAkB,EAQtE,SAAgB,EAAM,EAAY,EAA6C,CAC7E,IAAM,EAAsB,GAAS,qBAAuB,GAC5D,MAAO,CACL,KACA,UAAW,SACX,8BAA+B,EAAsB,IAAA,GAAY,QACjE,QAAU,GAAkB,CACtB,GAAuB,EAAE,SAAW,EAAE,eACtC,EAAE,cAAgC,OAAO,EAGhD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=`drawer:statechange`;let t=!1;function n(){if(typeof window>`u`||t)return;t=!0;let n=()=>{let e=Array.from(document.querySelectorAll(`dialog.drawer[open]`));e.forEach((t,n)=>{n===e.length-1?t.removeAttribute(`inert`):t.setAttribute(`inert`,``)})};new MutationObserver(t=>{for(let r of t)if(r.type===`attributes`&&r.attributeName===`open`&&r.target.classList.contains(`drawer`)){n(),window.dispatchEvent(new CustomEvent(e,{detail:{target:r.target}}));break}}).observe(document.body,{subtree:!0,attributes:!0,attributeFilter:[`open`]})}n(),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return e}});
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
--drawer-backdrop-blur: 4px;
|
|
9
9
|
|
|
10
10
|
/* Sizing */
|
|
11
|
-
--drawer-max-width: 500px;
|
|
12
11
|
--drawer-max-height: 96dvh;
|
|
12
|
+
--drawer-modal-width: fit-content;
|
|
13
|
+
--drawer-modal-height: fit-content;
|
|
13
14
|
|
|
14
15
|
/* Handle */
|
|
15
16
|
--drawer-handle-bg: hsl(0 0% 80%);
|
|
@@ -88,10 +89,10 @@ body:has(.drawer[open]) {
|
|
|
88
89
|
--_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;
|
|
89
90
|
inset: auto 0 0 0;
|
|
90
91
|
margin-inline: auto;
|
|
91
|
-
width: 100
|
|
92
|
-
max-width: var(--drawer-max-width);
|
|
93
|
-
height: auto;
|
|
94
|
-
max-height: var(--drawer-max-height);
|
|
92
|
+
width: var(--drawer-width, 100%);
|
|
93
|
+
max-width: var(--drawer-max-width, none);
|
|
94
|
+
height: var(--drawer-height, auto);
|
|
95
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
95
96
|
border-radius: var(--drawer-border-radius, var(--_border-radius));
|
|
96
97
|
box-shadow: var(--drawer-shadow-bottom);
|
|
97
98
|
translate: var(--_translate-closed);
|
|
@@ -138,9 +139,9 @@ body:has(.drawer[open]) {
|
|
|
138
139
|
--_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);
|
|
139
140
|
inset: 0 0 0 auto;
|
|
140
141
|
margin: 0;
|
|
141
|
-
width:
|
|
142
|
-
max-width: var(--drawer-max-width);
|
|
143
|
-
height: 100dvh;
|
|
142
|
+
width: var(--drawer-width, 500px);
|
|
143
|
+
max-width: var(--drawer-max-width, 90%);
|
|
144
|
+
height: var(--drawer-height, 100dvh);
|
|
144
145
|
max-height: 100dvh;
|
|
145
146
|
box-shadow: var(--drawer-shadow-right);
|
|
146
147
|
}
|
|
@@ -151,9 +152,9 @@ body:has(.drawer[open]) {
|
|
|
151
152
|
--_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;
|
|
152
153
|
inset: 0 auto 0 0;
|
|
153
154
|
margin: 0;
|
|
154
|
-
width:
|
|
155
|
-
max-width: var(--drawer-max-width);
|
|
156
|
-
height: 100dvh;
|
|
155
|
+
width: var(--drawer-width, 500px);
|
|
156
|
+
max-width: var(--drawer-max-width, 90%);
|
|
157
|
+
height: var(--drawer-height, 100dvh);
|
|
157
158
|
max-height: 100dvh;
|
|
158
159
|
box-shadow: var(--drawer-shadow-left);
|
|
159
160
|
}
|
|
@@ -164,10 +165,10 @@ body:has(.drawer[open]) {
|
|
|
164
165
|
--_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);
|
|
165
166
|
inset: 0 0 auto 0;
|
|
166
167
|
margin-inline: auto;
|
|
167
|
-
width: 100
|
|
168
|
-
max-width: var(--drawer-max-width);
|
|
169
|
-
height: auto;
|
|
170
|
-
max-height: var(--drawer-max-height);
|
|
168
|
+
width: var(--drawer-width, 100%);
|
|
169
|
+
max-width: var(--drawer-max-width, none);
|
|
170
|
+
height: var(--drawer-height, auto);
|
|
171
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
171
172
|
box-shadow: var(--drawer-shadow-top);
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -177,10 +178,10 @@ body:has(.drawer[open]) {
|
|
|
177
178
|
--_border-radius: var(--drawer-radius);
|
|
178
179
|
inset: 0;
|
|
179
180
|
margin: auto;
|
|
180
|
-
width: fit-content;
|
|
181
|
-
max-width: var(--drawer-max-width);
|
|
182
|
-
height: fit-content;
|
|
183
|
-
max-height: var(--drawer-max-height);
|
|
181
|
+
width: var(--drawer-modal-width, fit-content);
|
|
182
|
+
max-width: var(--drawer-max-width, 90%);
|
|
183
|
+
height: var(--drawer-modal-height, fit-content);
|
|
184
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
184
185
|
box-shadow: var(--drawer-shadow-modal);
|
|
185
186
|
scale: var(--drawer-nested-scale);
|
|
186
187
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=`drawer:statechange`;let t=!1;function n(){if(typeof window>`u`||t)return;t=!0;let n=()=>{let e=Array.from(document.querySelectorAll(`dialog.drawer[open]`));e.forEach((t,n)=>{n===e.length-1?t.removeAttribute(`inert`):t.setAttribute(`inert`,``)})};new MutationObserver(t=>{for(let r of t)if(r.type===`attributes`&&r.attributeName===`open`&&r.target.classList.contains(`drawer`)){n(),window.dispatchEvent(new CustomEvent(e,{detail:{target:r.target}}));break}}).observe(document.body,{subtree:!0,attributes:!0,attributeFilter:[`open`]})}n();export{e as t};
|
|
2
|
+
//# sourceMappingURL=observer-DIOx0VCj.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer-DIOx0VCj.mjs","names":[],"sources":["../src/observer.ts"],"sourcesContent":["/**\n * Shared drawer state observer\n * Single MutationObserver that dispatches events for all drawer state changes\n */\n\nexport const DRAWER_STATE_CHANGE = 'drawer:statechange'\n\nlet initialized = false\n\nexport function initDrawerObserver(): void {\n if (typeof window === 'undefined' || initialized) return\n initialized = true\n\n const updateInertState = () => {\n const openDrawers = Array.from(\n document.querySelectorAll<HTMLDialogElement>('dialog.drawer[open]')\n )\n openDrawers.forEach((drawer, index) => {\n if (index === openDrawers.length - 1) {\n drawer.removeAttribute('inert')\n } else {\n drawer.setAttribute('inert', '')\n }\n })\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'open' &&\n (mutation.target as HTMLElement).classList.contains('drawer')\n ) {\n updateInertState()\n window.dispatchEvent(new CustomEvent(DRAWER_STATE_CHANGE, {\n detail: { target: mutation.target }\n }))\n break\n }\n }\n })\n\n observer.observe(document.body, {\n subtree: true,\n attributes: true,\n attributeFilter: ['open'],\n })\n}\n\n// Auto-initialize on import\ninitDrawerObserver()\n"],"mappings":"AAKA,MAAa,EAAsB,qBAEnC,IAAI,EAAc,GAElB,SAAgB,GAA2B,CACzC,GAAI,OAAO,OAAW,KAAe,EAAa,OAClD,EAAc,GAEd,IAAM,MAAyB,CAC7B,IAAM,EAAc,MAAM,KACxB,SAAS,iBAAoC,sBAAsB,CACpE,CACD,EAAY,SAAS,EAAQ,IAAU,CACjC,IAAU,EAAY,OAAS,EACjC,EAAO,gBAAgB,QAAQ,CAE/B,EAAO,aAAa,QAAS,GAAG,EAElC,EAGa,IAAI,iBAAkB,GAAc,CACnD,IAAK,IAAM,KAAY,EACrB,GACE,EAAS,OAAS,cAClB,EAAS,gBAAkB,QAC1B,EAAS,OAAuB,UAAU,SAAS,SAAS,CAC7D,CACA,GAAkB,CAClB,OAAO,cAAc,IAAI,YAAY,EAAqB,CACxD,OAAQ,CAAE,OAAQ,EAAS,OAAQ,CACpC,CAAC,CAAC,CACH,QAGJ,CAEO,QAAQ,SAAS,KAAM,CAC9B,QAAS,GACT,WAAY,GACZ,gBAAiB,CAAC,OAAO,CAC1B,CAAC,CAIJ,GAAoB"}
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
--drawer-backdrop-blur: 4px;
|
|
9
9
|
|
|
10
10
|
/* Sizing */
|
|
11
|
-
--drawer-max-width: 500px;
|
|
12
11
|
--drawer-max-height: 96dvh;
|
|
12
|
+
--drawer-modal-width: fit-content;
|
|
13
|
+
--drawer-modal-height: fit-content;
|
|
13
14
|
|
|
14
15
|
/* Handle */
|
|
15
16
|
--drawer-handle-bg: hsl(0 0% 80%);
|
|
@@ -88,10 +89,10 @@ body:has(.drawer[open]) {
|
|
|
88
89
|
--_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;
|
|
89
90
|
inset: auto 0 0 0;
|
|
90
91
|
margin-inline: auto;
|
|
91
|
-
width: 100
|
|
92
|
-
max-width: var(--drawer-max-width);
|
|
93
|
-
height: auto;
|
|
94
|
-
max-height: var(--drawer-max-height);
|
|
92
|
+
width: var(--drawer-width, 100%);
|
|
93
|
+
max-width: var(--drawer-max-width, none);
|
|
94
|
+
height: var(--drawer-height, auto);
|
|
95
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
95
96
|
border-radius: var(--drawer-border-radius, var(--_border-radius));
|
|
96
97
|
box-shadow: var(--drawer-shadow-bottom);
|
|
97
98
|
translate: var(--_translate-closed);
|
|
@@ -138,9 +139,9 @@ body:has(.drawer[open]) {
|
|
|
138
139
|
--_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);
|
|
139
140
|
inset: 0 0 0 auto;
|
|
140
141
|
margin: 0;
|
|
141
|
-
width:
|
|
142
|
-
max-width: var(--drawer-max-width);
|
|
143
|
-
height: 100dvh;
|
|
142
|
+
width: var(--drawer-width, 500px);
|
|
143
|
+
max-width: var(--drawer-max-width, 90%);
|
|
144
|
+
height: var(--drawer-height, 100dvh);
|
|
144
145
|
max-height: 100dvh;
|
|
145
146
|
box-shadow: var(--drawer-shadow-right);
|
|
146
147
|
}
|
|
@@ -151,9 +152,9 @@ body:has(.drawer[open]) {
|
|
|
151
152
|
--_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;
|
|
152
153
|
inset: 0 auto 0 0;
|
|
153
154
|
margin: 0;
|
|
154
|
-
width:
|
|
155
|
-
max-width: var(--drawer-max-width);
|
|
156
|
-
height: 100dvh;
|
|
155
|
+
width: var(--drawer-width, 500px);
|
|
156
|
+
max-width: var(--drawer-max-width, 90%);
|
|
157
|
+
height: var(--drawer-height, 100dvh);
|
|
157
158
|
max-height: 100dvh;
|
|
158
159
|
box-shadow: var(--drawer-shadow-left);
|
|
159
160
|
}
|
|
@@ -164,10 +165,10 @@ body:has(.drawer[open]) {
|
|
|
164
165
|
--_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);
|
|
165
166
|
inset: 0 0 auto 0;
|
|
166
167
|
margin-inline: auto;
|
|
167
|
-
width: 100
|
|
168
|
-
max-width: var(--drawer-max-width);
|
|
169
|
-
height: auto;
|
|
170
|
-
max-height: var(--drawer-max-height);
|
|
168
|
+
width: var(--drawer-width, 100%);
|
|
169
|
+
max-width: var(--drawer-max-width, none);
|
|
170
|
+
height: var(--drawer-height, auto);
|
|
171
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
171
172
|
box-shadow: var(--drawer-shadow-top);
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -177,10 +178,10 @@ body:has(.drawer[open]) {
|
|
|
177
178
|
--_border-radius: var(--drawer-radius);
|
|
178
179
|
inset: 0;
|
|
179
180
|
margin: auto;
|
|
180
|
-
width: fit-content;
|
|
181
|
-
max-width: var(--drawer-max-width);
|
|
182
|
-
height: fit-content;
|
|
183
|
-
max-height: var(--drawer-max-height);
|
|
181
|
+
width: var(--drawer-modal-width, fit-content);
|
|
182
|
+
max-width: var(--drawer-max-width, 90%);
|
|
183
|
+
height: var(--drawer-modal-height, fit-content);
|
|
184
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
184
185
|
box-shadow: var(--drawer-shadow-modal);
|
|
185
186
|
scale: var(--drawer-nested-scale);
|
|
186
187
|
}
|
|
@@ -330,4 +331,4 @@ body:has(.drawer[open]) {
|
|
|
330
331
|
}
|
|
331
332
|
|
|
332
333
|
|
|
333
|
-
/*# sourceMappingURL=
|
|
334
|
+
/*# sourceMappingURL=observer-QD6bSdOu.css.map*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer-QD6bSdOu.css","names":[],"sources":["../src/drawer.css"],"sourcesContent":["/* CSS Drawer - Vaul-quality drawer with auto-nesting and directions */\n\n:root {\n /* Visual */\n --drawer-bg: #fff;\n --drawer-radius: 24px;\n --drawer-backdrop: hsl(0 0% 0% / 0.4);\n --drawer-backdrop-blur: 4px;\n\n /* Sizing */\n --drawer-max-height: 96dvh;\n --drawer-modal-width: fit-content;\n --drawer-modal-height: fit-content;\n\n /* Handle */\n --drawer-handle-bg: hsl(0 0% 80%);\n --drawer-handle-bg-hover: hsl(0 0% 60%);\n --drawer-handle-width: 48px;\n --drawer-handle-width-hover: 56px;\n --drawer-handle-height: 5px;\n --drawer-handle-padding-block: 1rem 0.5rem;\n --drawer-handle-padding-inline: 0;\n\n /* Shadows */\n --drawer-shadow-bottom: 0 -10px 60px hsl(0 0% 0% / 0.12), 0 -4px 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-top: 0 10px 60px hsl(0 0% 0% / 0.12), 0 4px 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-right: -10px 0 60px hsl(0 0% 0% / 0.12), -4px 0 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-left: 10px 0 60px hsl(0 0% 0% / 0.12), 4px 0 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-modal: 0 25px 50px -12px hsl(0 0% 0% / 0.25);\n\n /* Animation */\n --drawer-duration: 0.5s;\n --drawer-duration-close: 0.35s;\n --drawer-ease: cubic-bezier(0.32, 0.72, 0, 1);\n\n /* Nesting effects */\n --drawer-nested-scale: 0.94;\n --drawer-nested-offset: 20px;\n --drawer-nested-brightness: 0.92;\n --drawer-nested-backdrop: hsl(0 0% 0% / 0.15);\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n --drawer-bg: hsl(0 0% 12%);\n --drawer-handle-bg: hsl(0 0% 35%);\n --drawer-handle-bg-hover: hsl(0 0% 50%);\n --drawer-shadow-bottom: 0 -10px 60px hsl(0 0% 0% / 0.4), 0 -4px 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-top: 0 10px 60px hsl(0 0% 0% / 0.4), 0 4px 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-right: -10px 0 60px hsl(0 0% 0% / 0.4), -4px 0 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-left: 10px 0 60px hsl(0 0% 0% / 0.4), 4px 0 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-modal: 0 25px 50px -12px hsl(0 0% 0% / 0.5);\n }\n}\n\n/* Background scale effect */\nbody {\n transition: scale var(--drawer-duration) var(--drawer-ease), border-radius var(--drawer-duration) var(--drawer-ease);\n transform-origin: center top;\n}\n\nbody:has(.drawer[open]) {\n overflow: hidden;\n scale: var(--drawer-nested-scale);\n border-radius: var(--drawer-radius);\n}\n\n/* Base drawer */\n.drawer {\n border: none;\n padding: 0;\n margin: 0;\n max-width: 100%;\n max-height: 100%;\n position: fixed;\n background: var(--drawer-bg);\n overflow: hidden;\n opacity: 0;\n transition:\n display var(--drawer-duration-close) allow-discrete,\n overlay var(--drawer-duration-close) allow-discrete,\n translate var(--drawer-duration-close) var(--drawer-ease),\n scale var(--drawer-duration-close) var(--drawer-ease),\n filter var(--drawer-duration-close) ease,\n opacity var(--drawer-duration-close) ease;\n\n /* Default: bottom */\n --_translate-closed: 0 100%;\n --_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;\n inset: auto 0 0 0;\n margin-inline: auto;\n width: var(--drawer-width, 100%);\n max-width: var(--drawer-max-width, none);\n height: var(--drawer-height, auto);\n max-height: var(--drawer-max-height, 96dvh);\n border-radius: var(--drawer-border-radius, var(--_border-radius));\n box-shadow: var(--drawer-shadow-bottom);\n translate: var(--_translate-closed);\n}\n\n.drawer::backdrop {\n background: var(--drawer-backdrop);\n opacity: 0;\n backdrop-filter: blur(var(--drawer-backdrop-blur));\n -webkit-backdrop-filter: blur(var(--drawer-backdrop-blur));\n transition:\n display var(--drawer-duration-close) allow-discrete,\n overlay var(--drawer-duration-close) allow-discrete,\n opacity var(--drawer-duration-close) ease;\n}\n\n.drawer[open] {\n opacity: 1;\n translate: 0 0;\n transition:\n display var(--drawer-duration) allow-discrete,\n overlay var(--drawer-duration) allow-discrete,\n translate var(--drawer-duration) var(--drawer-ease),\n scale var(--drawer-duration) var(--drawer-ease),\n filter var(--drawer-duration) ease,\n opacity 0.15s ease;\n}\n\n.drawer[open]::backdrop {\n opacity: 1;\n transition: display var(--drawer-duration) allow-discrete, overlay var(--drawer-duration) allow-discrete, opacity 0.2s ease;\n}\n\n@starting-style {\n .drawer[open] { opacity: 0; translate: var(--_translate-closed); }\n .drawer[open]::backdrop { opacity: 0; }\n}\n\n/* ===== DIRECTIONS ===== */\n\n/* Right */\n.drawer[data-direction=\"right\"] {\n --_translate-closed: 100% 0;\n --_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);\n inset: 0 0 0 auto;\n margin: 0;\n width: var(--drawer-width, 500px);\n max-width: var(--drawer-max-width, 90%);\n height: var(--drawer-height, 100dvh);\n max-height: 100dvh;\n box-shadow: var(--drawer-shadow-right);\n}\n\n/* Left */\n.drawer[data-direction=\"left\"] {\n --_translate-closed: -100% 0;\n --_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;\n inset: 0 auto 0 0;\n margin: 0;\n width: var(--drawer-width, 500px);\n max-width: var(--drawer-max-width, 90%);\n height: var(--drawer-height, 100dvh);\n max-height: 100dvh;\n box-shadow: var(--drawer-shadow-left);\n}\n\n/* Top */\n.drawer[data-direction=\"top\"] {\n --_translate-closed: 0 -100%;\n --_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);\n inset: 0 0 auto 0;\n margin-inline: auto;\n width: var(--drawer-width, 100%);\n max-width: var(--drawer-max-width, none);\n height: var(--drawer-height, auto);\n max-height: var(--drawer-max-height, 96dvh);\n box-shadow: var(--drawer-shadow-top);\n}\n\n/* Modal (centered) */\n.drawer[data-direction=\"modal\"] {\n --_translate-closed: 0 0;\n --_border-radius: var(--drawer-radius);\n inset: 0;\n margin: auto;\n width: var(--drawer-modal-width, fit-content);\n max-width: var(--drawer-max-width, 90%);\n height: var(--drawer-modal-height, fit-content);\n max-height: var(--drawer-max-height, 96dvh);\n box-shadow: var(--drawer-shadow-modal);\n scale: var(--drawer-nested-scale);\n}\n\n.drawer[data-direction=\"modal\"][open] {\n scale: 1;\n}\n\n@starting-style {\n .drawer[data-direction=\"modal\"][open] {\n scale: var(--drawer-nested-scale);\n }\n}\n\n/* ===== AUTO-NESTING (up to 5 levels) ===== */\n/* Uses sibling combinators to count open drawers */\n\n/* 1+ open drawers after */\n.drawer[open]:has(~ .drawer[open]) {\n scale: var(--drawer-nested-scale);\n translate: 0 calc(-1 * var(--drawer-nested-offset));\n border-radius: var(--drawer-radius);\n filter: brightness(var(--drawer-nested-brightness));\n pointer-events: none;\n}\n\n/* 2+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-2 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* 3+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-3 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* 4+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-4 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* 5+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-5 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* Lighter backdrop for stacked drawers */\n.drawer[open] ~ .drawer[open]::backdrop {\n background: var(--drawer-nested-backdrop);\n backdrop-filter: none;\n}\n\n/* Handle */\n.drawer-handle {\n display: flex;\n justify-content: center;\n padding-block: var(--drawer-handle-padding-block);\n padding-inline: var(--drawer-handle-padding-inline);\n cursor: grab;\n}\n\n.drawer-handle::before {\n content: '';\n width: var(--drawer-handle-width);\n height: var(--drawer-handle-height);\n background: var(--drawer-handle-bg);\n border-radius: 100px;\n transition: width 0.2s var(--drawer-ease), height 0.2s var(--drawer-ease), background 0.2s ease;\n}\n\n.drawer-handle:hover::before {\n width: var(--drawer-handle-width-hover);\n background: var(--drawer-handle-bg-hover);\n}\n\n/* Vertical handle for left/right drawers */\n.drawer[data-direction=\"left\"] .drawer-handle,\n.drawer[data-direction=\"right\"] .drawer-handle {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding-block: var(--drawer-handle-padding-inline);\n padding-inline: var(--drawer-handle-padding-block);\n height: 100%;\n position: absolute;\n top: 0;\n writing-mode: vertical-lr;\n}\n\n.drawer[data-direction=\"left\"] .drawer-handle { right: 0; }\n.drawer[data-direction=\"right\"] .drawer-handle { left: 0; }\n\n.drawer[data-direction=\"left\"] .drawer-handle::before,\n.drawer[data-direction=\"right\"] .drawer-handle::before {\n width: var(--drawer-handle-height);\n height: var(--drawer-handle-width);\n}\n\n.drawer[data-direction=\"left\"] .drawer-handle:hover::before,\n.drawer[data-direction=\"right\"] .drawer-handle:hover::before {\n width: var(--drawer-handle-height);\n height: var(--drawer-handle-width-hover);\n}\n\n/* Content - structural only, no opinionated padding */\n.drawer-content {\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n min-height: 0;\n}\n\n/* Content sizing for directions */\n.drawer[data-direction=\"left\"] .drawer-content,\n.drawer[data-direction=\"right\"] .drawer-content {\n height: 100%;\n}\n\n/* Reduced motion */\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n transition-duration: 0.01ms !important;\n }\n\n body:has(.drawer[open]) {\n scale: 1;\n }\n\n .drawer[open]:has(~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: 1;\n translate: 0 0;\n filter: none;\n }\n}\n"],"mappings":"AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/react.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(
|
|
2
|
-
|
|
1
|
+
require('./observer-CtfG4nrq.css');
|
|
2
|
+
const e=require(`./observer-B-WjvsFU.cjs`);let t=require(`react`),n=require(`react/jsx-runtime`);const r=(0,t.createContext)({direction:void 0});function i(){return(0,t.useContext)(r)}function a(){return typeof window>`u`?[]:Array.from(document.querySelectorAll(`dialog.drawer[open]`))}function o(){let e=a();return e[e.length-1]??null}function s(n){let[r,i]=(0,t.useState)(!1);return(0,t.useEffect)(()=>{let t=()=>{let e=o();i(n.current!==null&&n.current===e)};return t(),window.addEventListener(e.t,t),()=>window.removeEventListener(e.t,t)},[n]),r}function c({children:e,direction:t}){return(0,n.jsx)(r.Provider,{value:{direction:t},children:e})}const l=(0,t.forwardRef)(({children:e,className:r,open:a,onOpenChange:o,closeOnOutsideClick:s=!0,...c},l)=>{let{direction:u}=i(),d=(0,t.useRef)(null),f=l||d;return(0,t.useEffect)(()=>{let e=f.current;e&&(a&&!e.open?(e.showModal(),o?.(!0)):a===!1&&e.open&&e.close())},[a]),(0,n.jsx)(`dialog`,{ref:f,className:`drawer ${r??``}`.trim(),"data-direction":u,onClose:e=>{e.target===e.currentTarget&&(c.onClose?.(e),o?.(!1))},onClick:e=>{c.onClick?.(e),s&&e.target===e.currentTarget&&e.currentTarget.close()},...c,children:e})});l.displayName=`Drawer.Content`;const u=(0,t.forwardRef)(({className:e,...t},r)=>(0,n.jsx)(`div`,{ref:r,className:`drawer-handle ${e??``}`.trim(),"aria-hidden":`true`,...t}));u.displayName=`Drawer.Handle`;const d=(0,t.forwardRef)((e,t)=>(0,n.jsx)(`h2`,{ref:t,...e}));d.displayName=`Drawer.Title`;const f=(0,t.forwardRef)((e,t)=>(0,n.jsx)(`p`,{ref:t,...e}));f.displayName=`Drawer.Description`;const p={Root:c,Content:l,Handle:u,Title:d,Description:f};exports.Drawer=p,exports.getTopDrawer=o,exports.useIsTopDrawer=s;
|
package/dist/react.d.cts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
2
|
import * as react0 from "react";
|
|
3
|
-
import { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
3
|
+
import { ComponentPropsWithoutRef, ReactNode, RefObject } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react.d.ts
|
|
6
6
|
type Direction = 'bottom' | 'top' | 'left' | 'right' | 'modal';
|
|
7
|
+
/**
|
|
8
|
+
* Get the topmost open drawer
|
|
9
|
+
*/
|
|
10
|
+
declare function getTopDrawer(): HTMLDialogElement | null;
|
|
11
|
+
/**
|
|
12
|
+
* Hook to check if a drawer is the topmost open drawer
|
|
13
|
+
* Useful for conditionally rendering content only in the top drawer
|
|
14
|
+
*/
|
|
15
|
+
declare function useIsTopDrawer(ref: RefObject<HTMLDialogElement | null>): boolean;
|
|
7
16
|
interface RootProps {
|
|
8
17
|
children: ReactNode;
|
|
9
18
|
/** Direction the drawer opens from */
|
|
@@ -32,5 +41,5 @@ declare const Drawer: {
|
|
|
32
41
|
Description: react0.ForwardRefExoticComponent<DescriptionProps & react0.RefAttributes<HTMLParagraphElement>>;
|
|
33
42
|
};
|
|
34
43
|
//#endregion
|
|
35
|
-
export { Drawer, type ContentProps as DrawerContentProps, type DescriptionProps as DrawerDescriptionProps, type Direction as DrawerDirection, type HandleProps as DrawerHandleProps, type RootProps as DrawerRootProps, type TitleProps as DrawerTitleProps };
|
|
44
|
+
export { Drawer, type ContentProps as DrawerContentProps, type DescriptionProps as DrawerDescriptionProps, type Direction as DrawerDirection, type HandleProps as DrawerHandleProps, type RootProps as DrawerRootProps, type TitleProps as DrawerTitleProps, getTopDrawer, useIsTopDrawer };
|
|
36
45
|
//# sourceMappingURL=react.d.cts.map
|
package/dist/react.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.cts","names":[],"sources":["../src/react.tsx"],"sourcesContent":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"react.d.cts","names":[],"sources":["../src/react.tsx"],"sourcesContent":[],"mappings":";;;;;KAeK,SAAA;;;AAJgB;AA8BL,iBAAA,YAAA,CAAA,CAAgB,EAAA,iBAAiB,GAAA,IAAA;AASjD;AAkBC;AAMsB;;AAGG,iBA3BV,cAAA,CA2BU,GAAA,EA3BU,SA2BV,CA3BoB,iBA2BpB,GAAA,IAAA,CAAA,CAAA,EAAA,OAAA;UANhB,SAAA,CAM6B;EAAS,QAAA,EALpC,SAKoC;EAAA;EAStC,SAAA,CAAA,EAZI,SAYS;AAAY;AAyDmB,iBAlE7C,IAAA,CA+EY;EAAA,QAAQ;EAAA;AAAwB,CAAxB,EA/EU,SA+Ec,CAAA,EA/EL,kBAAA,CAAA,GAAA,CAAA,OA+EK;AAAA,UAtE3C,YAAA,SAAqB,IA8EI,CA9EC,wBA8EuB,CAAA,QAAA,CAAA,EAAA,MAAA,CAAA,CAAA;EAQ9C;;;;;;;UA7BH,WAAA,SAAoB;UAapB,UAAA,SAAmB;UAQnB,gBAAA,SAAyB;cAQtB"}
|
package/dist/react.d.mts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import * as react0 from "react";
|
|
2
|
-
import { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
+
import { ComponentPropsWithoutRef, ReactNode, RefObject } from "react";
|
|
3
3
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
4
|
|
|
5
5
|
//#region src/react.d.ts
|
|
6
6
|
type Direction = 'bottom' | 'top' | 'left' | 'right' | 'modal';
|
|
7
|
+
/**
|
|
8
|
+
* Get the topmost open drawer
|
|
9
|
+
*/
|
|
10
|
+
declare function getTopDrawer(): HTMLDialogElement | null;
|
|
11
|
+
/**
|
|
12
|
+
* Hook to check if a drawer is the topmost open drawer
|
|
13
|
+
* Useful for conditionally rendering content only in the top drawer
|
|
14
|
+
*/
|
|
15
|
+
declare function useIsTopDrawer(ref: RefObject<HTMLDialogElement | null>): boolean;
|
|
7
16
|
interface RootProps {
|
|
8
17
|
children: ReactNode;
|
|
9
18
|
/** Direction the drawer opens from */
|
|
@@ -32,5 +41,5 @@ declare const Drawer: {
|
|
|
32
41
|
Description: react0.ForwardRefExoticComponent<DescriptionProps & react0.RefAttributes<HTMLParagraphElement>>;
|
|
33
42
|
};
|
|
34
43
|
//#endregion
|
|
35
|
-
export { Drawer, type ContentProps as DrawerContentProps, type DescriptionProps as DrawerDescriptionProps, type Direction as DrawerDirection, type HandleProps as DrawerHandleProps, type RootProps as DrawerRootProps, type TitleProps as DrawerTitleProps };
|
|
44
|
+
export { Drawer, type ContentProps as DrawerContentProps, type DescriptionProps as DrawerDescriptionProps, type Direction as DrawerDirection, type HandleProps as DrawerHandleProps, type RootProps as DrawerRootProps, type TitleProps as DrawerTitleProps, getTopDrawer, useIsTopDrawer };
|
|
36
45
|
//# sourceMappingURL=react.d.mts.map
|
package/dist/react.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.mts","names":[],"sources":["../src/react.tsx"],"sourcesContent":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"react.d.mts","names":[],"sources":["../src/react.tsx"],"sourcesContent":[],"mappings":";;;;;KAeK,SAAA;;;AAJgB;AA8BL,iBAAA,YAAA,CAAA,CAAgB,EAAA,iBAAiB,GAAA,IAAA;AASjD;AAkBC;AAMsB;;AAGG,iBA3BV,cAAA,CA2BU,GAAA,EA3BU,SA2BV,CA3BoB,iBA2BpB,GAAA,IAAA,CAAA,CAAA,EAAA,OAAA;UANhB,SAAA,CAM6B;EAAS,QAAA,EALpC,SAKoC;EAAA;EAStC,SAAA,CAAA,EAZI,SAYS;AAAY;AAyDmB,iBAlE7C,IAAA,CA+EY;EAAA,QAAQ;EAAA;AAAwB,CAAxB,EA/EU,SA+Ec,CAAA,EA/EL,kBAAA,CAAA,GAAA,CAAA,OA+EK;AAAA,UAtE3C,YAAA,SAAqB,IA8EI,CA9EC,wBA8EuB,CAAA,QAAA,CAAA,EAAA,MAAA,CAAA,CAAA;EAQ9C;;;;;;;UA7BH,WAAA,SAAoB;UAapB,UAAA,SAAmB;UAQnB,gBAAA,SAAyB;cAQtB"}
|
package/dist/react.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import"./
|
|
2
|
-
|
|
1
|
+
import{t as e}from"./observer-DIOx0VCj.mjs";import{createContext as t,forwardRef as n,useContext as r,useEffect as i,useRef as a,useState as o}from"react";import{jsx as s}from"react/jsx-runtime";import './observer-QD6bSdOu.css';
|
|
2
|
+
const c=t({direction:void 0});function l(){return r(c)}function u(){return typeof window>`u`?[]:Array.from(document.querySelectorAll(`dialog.drawer[open]`))}function d(){let e=u();return e[e.length-1]??null}function f(t){let[n,r]=o(!1);return i(()=>{let n=()=>{let e=d();r(t.current!==null&&t.current===e)};return n(),window.addEventListener(e,n),()=>window.removeEventListener(e,n)},[t]),n}function p({children:e,direction:t}){return s(c.Provider,{value:{direction:t},children:e})}const m=n(({children:e,className:t,open:n,onOpenChange:r,closeOnOutsideClick:o=!0,...c},u)=>{let{direction:d}=l(),f=a(null),p=u||f;return i(()=>{let e=p.current;e&&(n&&!e.open?(e.showModal(),r?.(!0)):n===!1&&e.open&&e.close())},[n]),s(`dialog`,{ref:p,className:`drawer ${t??``}`.trim(),"data-direction":d,onClose:e=>{e.target===e.currentTarget&&(c.onClose?.(e),r?.(!1))},onClick:e=>{c.onClick?.(e),o&&e.target===e.currentTarget&&e.currentTarget.close()},...c,children:e})});m.displayName=`Drawer.Content`;const h=n(({className:e,...t},n)=>s(`div`,{ref:n,className:`drawer-handle ${e??``}`.trim(),"aria-hidden":`true`,...t}));h.displayName=`Drawer.Handle`;const g=n((e,t)=>s(`h2`,{ref:t,...e}));g.displayName=`Drawer.Title`;const _=n((e,t)=>s(`p`,{ref:t,...e}));_.displayName=`Drawer.Description`;const v={Root:p,Content:m,Handle:h,Title:g,Description:_};export{v as Drawer,d as getTopDrawer,f as useIsTopDrawer};
|
|
3
3
|
//# sourceMappingURL=react.mjs.map
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.mjs","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n forwardRef,\n useEffect,\n useRef,\n type ReactNode,\n type ComponentPropsWithoutRef,\n} from 'react'\nimport './drawer.css'\n\n/* =====
|
|
1
|
+
{"version":3,"file":"react.mjs","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n forwardRef,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n type ComponentPropsWithoutRef,\n type RefObject,\n} from 'react'\nimport './drawer.css'\nimport { DRAWER_STATE_CHANGE } from './observer'\n\n/* ===== Types ===== */\ntype Direction = 'bottom' | 'top' | 'left' | 'right' | 'modal'\n\ninterface DrawerContextValue {\n direction?: Direction\n}\n\n/* ===== Context ===== */\nconst DrawerContext = createContext<DrawerContextValue>({ direction: undefined })\n\nfunction useDrawerContext() {\n return useContext(DrawerContext)\n}\n\n/* ===== Utilities ===== */\n\n/**\n * Get all open drawers\n */\nfunction getOpenDrawers(): HTMLDialogElement[] {\n if (typeof window === 'undefined') return []\n return Array.from(document.querySelectorAll<HTMLDialogElement>('dialog.drawer[open]'))\n}\n\n/**\n * Get the topmost open drawer\n */\nexport function getTopDrawer(): HTMLDialogElement | null {\n const open = getOpenDrawers()\n return open[open.length - 1] ?? null\n}\n\n/**\n * Hook to check if a drawer is the topmost open drawer\n * Useful for conditionally rendering content only in the top drawer\n */\nexport function useIsTopDrawer(ref: RefObject<HTMLDialogElement | null>): boolean {\n const [isTop, setIsTop] = useState(false)\n\n useEffect(() => {\n const checkIsTop = () => {\n const topDrawer = getTopDrawer()\n setIsTop(ref.current !== null && ref.current === topDrawer)\n }\n\n // Initial check\n checkIsTop()\n\n // Listen to shared drawer state change event (single observer, not N observers)\n window.addEventListener(DRAWER_STATE_CHANGE, checkIsTop)\n return () => window.removeEventListener(DRAWER_STATE_CHANGE, checkIsTop)\n }, [ref])\n\n return isTop\n}\n\n/* ===== Root ===== */\ninterface RootProps {\n children: ReactNode\n /** Direction the drawer opens from */\n direction?: Direction\n}\n\nfunction Root({ children, direction }: RootProps) {\n return (\n <DrawerContext.Provider value={{ direction }}>\n {children}\n </DrawerContext.Provider>\n )\n}\n\n/* ===== Content ===== */\ninterface ContentProps extends Omit<ComponentPropsWithoutRef<'dialog'>, 'open'> {\n /** Controlled open state */\n open?: boolean\n /** Called when open state changes */\n onOpenChange?: (open: boolean) => void\n /** Close when clicking outside the drawer (default: true) */\n closeOnOutsideClick?: boolean\n}\n\nconst Content = forwardRef<HTMLDialogElement, ContentProps>(\n ({ children, className, open, onOpenChange, closeOnOutsideClick = true, ...props }, ref) => {\n const { direction } = useDrawerContext()\n const internalRef = useRef<HTMLDialogElement>(null)\n const dialogRef = (ref as React.RefObject<HTMLDialogElement>) || internalRef\n\n useEffect(() => {\n const dialog = dialogRef.current\n if (!dialog) return\n\n if (open && !dialog.open) {\n dialog.showModal()\n onOpenChange?.(true)\n } else if (open === false && dialog.open) {\n dialog.close()\n }\n }, [open])\n\n return (\n <dialog\n ref={dialogRef}\n className={`drawer ${className ?? ''}`.trim()}\n data-direction={direction}\n onClose={(e) => {\n // Only handle close event if it originated from THIS dialog\n // This prevents nested dialogs from triggering parent dialog closes\n if (e.target !== e.currentTarget) return\n\n props.onClose?.(e)\n onOpenChange?.(false)\n }}\n onClick={(e) => {\n props.onClick?.(e)\n // Backdrop click - only if clicking the dialog element itself\n if (closeOnOutsideClick && e.target === e.currentTarget) {\n e.currentTarget.close()\n }\n }}\n {...props}\n >\n {children}\n </dialog>\n )\n }\n)\nContent.displayName = 'Drawer.Content'\n\n/* ===== Handle ===== */\ninterface HandleProps extends ComponentPropsWithoutRef<'div'> {}\n\nconst Handle = forwardRef<HTMLDivElement, HandleProps>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={`drawer-handle ${className ?? ''}`.trim()}\n aria-hidden=\"true\"\n {...props}\n />\n))\nHandle.displayName = 'Drawer.Handle'\n\n/* ===== Title ===== */\ninterface TitleProps extends ComponentPropsWithoutRef<'h2'> {}\n\nconst Title = forwardRef<HTMLHeadingElement, TitleProps>((props, ref) => (\n <h2 ref={ref} {...props} />\n))\nTitle.displayName = 'Drawer.Title'\n\n/* ===== Description ===== */\ninterface DescriptionProps extends ComponentPropsWithoutRef<'p'> {}\n\nconst Description = forwardRef<HTMLParagraphElement, DescriptionProps>((props, ref) => (\n <p ref={ref} {...props} />\n))\nDescription.displayName = 'Drawer.Description'\n\n/* ===== Namespace Export ===== */\nexport const Drawer = {\n Root,\n Content,\n Handle,\n Title,\n Description,\n}\n\nexport type {\n RootProps as DrawerRootProps,\n ContentProps as DrawerContentProps,\n HandleProps as DrawerHandleProps,\n TitleProps as DrawerTitleProps,\n DescriptionProps as DrawerDescriptionProps,\n Direction as DrawerDirection,\n}\n"],"mappings":"mMAsBA,MAAM,EAAgB,EAAkC,CAAE,UAAW,IAAA,GAAW,CAAC,CAEjF,SAAS,GAAmB,CAC1B,OAAO,EAAW,EAAc,CAQlC,SAAS,GAAsC,CAE7C,OADI,OAAO,OAAW,IAAoB,EAAE,CACrC,MAAM,KAAK,SAAS,iBAAoC,sBAAsB,CAAC,CAMxF,SAAgB,GAAyC,CACvD,IAAM,EAAO,GAAgB,CAC7B,OAAO,EAAK,EAAK,OAAS,IAAM,KAOlC,SAAgB,EAAe,EAAmD,CAChF,GAAM,CAAC,EAAO,GAAY,EAAS,GAAM,CAgBzC,OAdA,MAAgB,CACd,IAAM,MAAmB,CACvB,IAAM,EAAY,GAAc,CAChC,EAAS,EAAI,UAAY,MAAQ,EAAI,UAAY,EAAU,EAQ7D,OAJA,GAAY,CAGZ,OAAO,iBAAiB,EAAqB,EAAW,KAC3C,OAAO,oBAAoB,EAAqB,EAAW,EACvE,CAAC,EAAI,CAAC,CAEF,EAUT,SAAS,EAAK,CAAE,WAAU,aAAwB,CAChD,OACE,EAAC,EAAc,SAAA,CAAS,MAAO,CAAE,YAAW,CACzC,YACsB,CAc7B,MAAM,EAAU,GACb,CAAE,WAAU,YAAW,OAAM,eAAc,sBAAsB,GAAM,GAAG,GAAS,IAAQ,CAC1F,GAAM,CAAE,aAAc,GAAkB,CAClC,EAAc,EAA0B,KAAK,CAC7C,EAAa,GAA8C,EAcjE,OAZA,MAAgB,CACd,IAAM,EAAS,EAAU,QACpB,IAED,GAAQ,CAAC,EAAO,MAClB,EAAO,WAAW,CAClB,IAAe,GAAK,EACX,IAAS,IAAS,EAAO,MAClC,EAAO,OAAO,GAEf,CAAC,EAAK,CAAC,CAGR,EAAC,SAAA,CACC,IAAK,EACL,UAAW,UAAU,GAAa,KAAK,MAAM,CAC7C,iBAAgB,EAChB,QAAU,GAAM,CAGV,EAAE,SAAW,EAAE,gBAEnB,EAAM,UAAU,EAAE,CAClB,IAAe,GAAM,GAEvB,QAAU,GAAM,CACd,EAAM,UAAU,EAAE,CAEd,GAAuB,EAAE,SAAW,EAAE,eACxC,EAAE,cAAc,OAAO,EAG3B,GAAI,EAEH,YACM,EAGd,CACD,EAAQ,YAAc,iBAKtB,MAAM,EAAS,GAAyC,CAAE,YAAW,GAAG,GAAS,IAC/E,EAAC,MAAA,CACM,MACL,UAAW,iBAAiB,GAAa,KAAK,MAAM,CACpD,cAAY,OACZ,GAAI,GACJ,CACF,CACF,EAAO,YAAc,gBAKrB,MAAM,EAAQ,GAA4C,EAAO,IAC/D,EAAC,KAAA,CAAQ,MAAK,GAAI,GAAS,CAC3B,CACF,EAAM,YAAc,eAKpB,MAAM,EAAc,GAAoD,EAAO,IAC7E,EAAC,IAAA,CAAO,MAAK,GAAI,GAAS,CAC1B,CACF,EAAY,YAAc,qBAG1B,MAAa,EAAS,CACpB,OACA,UACA,SACA,QACA,cACD"}
|
package/package.json
CHANGED
package/src/drawer.css
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
--drawer-backdrop-blur: 4px;
|
|
9
9
|
|
|
10
10
|
/* Sizing */
|
|
11
|
-
--drawer-max-width: 500px;
|
|
12
11
|
--drawer-max-height: 96dvh;
|
|
12
|
+
--drawer-modal-width: fit-content;
|
|
13
|
+
--drawer-modal-height: fit-content;
|
|
13
14
|
|
|
14
15
|
/* Handle */
|
|
15
16
|
--drawer-handle-bg: hsl(0 0% 80%);
|
|
@@ -88,10 +89,10 @@ body:has(.drawer[open]) {
|
|
|
88
89
|
--_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;
|
|
89
90
|
inset: auto 0 0 0;
|
|
90
91
|
margin-inline: auto;
|
|
91
|
-
width: 100
|
|
92
|
-
max-width: var(--drawer-max-width);
|
|
93
|
-
height: auto;
|
|
94
|
-
max-height: var(--drawer-max-height);
|
|
92
|
+
width: var(--drawer-width, 100%);
|
|
93
|
+
max-width: var(--drawer-max-width, none);
|
|
94
|
+
height: var(--drawer-height, auto);
|
|
95
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
95
96
|
border-radius: var(--drawer-border-radius, var(--_border-radius));
|
|
96
97
|
box-shadow: var(--drawer-shadow-bottom);
|
|
97
98
|
translate: var(--_translate-closed);
|
|
@@ -138,9 +139,9 @@ body:has(.drawer[open]) {
|
|
|
138
139
|
--_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);
|
|
139
140
|
inset: 0 0 0 auto;
|
|
140
141
|
margin: 0;
|
|
141
|
-
width:
|
|
142
|
-
max-width: var(--drawer-max-width);
|
|
143
|
-
height: 100dvh;
|
|
142
|
+
width: var(--drawer-width, 500px);
|
|
143
|
+
max-width: var(--drawer-max-width, 90%);
|
|
144
|
+
height: var(--drawer-height, 100dvh);
|
|
144
145
|
max-height: 100dvh;
|
|
145
146
|
box-shadow: var(--drawer-shadow-right);
|
|
146
147
|
}
|
|
@@ -151,9 +152,9 @@ body:has(.drawer[open]) {
|
|
|
151
152
|
--_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;
|
|
152
153
|
inset: 0 auto 0 0;
|
|
153
154
|
margin: 0;
|
|
154
|
-
width:
|
|
155
|
-
max-width: var(--drawer-max-width);
|
|
156
|
-
height: 100dvh;
|
|
155
|
+
width: var(--drawer-width, 500px);
|
|
156
|
+
max-width: var(--drawer-max-width, 90%);
|
|
157
|
+
height: var(--drawer-height, 100dvh);
|
|
157
158
|
max-height: 100dvh;
|
|
158
159
|
box-shadow: var(--drawer-shadow-left);
|
|
159
160
|
}
|
|
@@ -164,10 +165,10 @@ body:has(.drawer[open]) {
|
|
|
164
165
|
--_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);
|
|
165
166
|
inset: 0 0 auto 0;
|
|
166
167
|
margin-inline: auto;
|
|
167
|
-
width: 100
|
|
168
|
-
max-width: var(--drawer-max-width);
|
|
169
|
-
height: auto;
|
|
170
|
-
max-height: var(--drawer-max-height);
|
|
168
|
+
width: var(--drawer-width, 100%);
|
|
169
|
+
max-width: var(--drawer-max-width, none);
|
|
170
|
+
height: var(--drawer-height, auto);
|
|
171
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
171
172
|
box-shadow: var(--drawer-shadow-top);
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -177,10 +178,10 @@ body:has(.drawer[open]) {
|
|
|
177
178
|
--_border-radius: var(--drawer-radius);
|
|
178
179
|
inset: 0;
|
|
179
180
|
margin: auto;
|
|
180
|
-
width: fit-content;
|
|
181
|
-
max-width: var(--drawer-max-width);
|
|
182
|
-
height: fit-content;
|
|
183
|
-
max-height: var(--drawer-max-height);
|
|
181
|
+
width: var(--drawer-modal-width, fit-content);
|
|
182
|
+
max-width: var(--drawer-max-width, 90%);
|
|
183
|
+
height: var(--drawer-modal-height, fit-content);
|
|
184
|
+
max-height: var(--drawer-max-height, 96dvh);
|
|
184
185
|
box-shadow: var(--drawer-shadow-modal);
|
|
185
186
|
scale: var(--drawer-nested-scale);
|
|
186
187
|
}
|
package/dist/drawer-BWZh2Fyp.cjs
DELETED
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drawer-CXCJQa45.css","names":[],"sources":["../src/drawer.css"],"sourcesContent":["/* CSS Drawer - Vaul-quality drawer with auto-nesting and directions */\n\n:root {\n /* Visual */\n --drawer-bg: #fff;\n --drawer-radius: 24px;\n --drawer-backdrop: hsl(0 0% 0% / 0.4);\n --drawer-backdrop-blur: 4px;\n\n /* Sizing */\n --drawer-max-width: 500px;\n --drawer-max-height: 96dvh;\n\n /* Handle */\n --drawer-handle-bg: hsl(0 0% 80%);\n --drawer-handle-bg-hover: hsl(0 0% 60%);\n --drawer-handle-width: 48px;\n --drawer-handle-width-hover: 56px;\n --drawer-handle-height: 5px;\n --drawer-handle-padding-block: 1rem 0.5rem;\n --drawer-handle-padding-inline: 0;\n\n /* Shadows */\n --drawer-shadow-bottom: 0 -10px 60px hsl(0 0% 0% / 0.12), 0 -4px 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-top: 0 10px 60px hsl(0 0% 0% / 0.12), 0 4px 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-right: -10px 0 60px hsl(0 0% 0% / 0.12), -4px 0 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-left: 10px 0 60px hsl(0 0% 0% / 0.12), 4px 0 20px hsl(0 0% 0% / 0.08);\n --drawer-shadow-modal: 0 25px 50px -12px hsl(0 0% 0% / 0.25);\n\n /* Animation */\n --drawer-duration: 0.5s;\n --drawer-duration-close: 0.35s;\n --drawer-ease: cubic-bezier(0.32, 0.72, 0, 1);\n\n /* Nesting effects */\n --drawer-nested-scale: 0.94;\n --drawer-nested-offset: 20px;\n --drawer-nested-brightness: 0.92;\n --drawer-nested-backdrop: hsl(0 0% 0% / 0.15);\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n --drawer-bg: hsl(0 0% 12%);\n --drawer-handle-bg: hsl(0 0% 35%);\n --drawer-handle-bg-hover: hsl(0 0% 50%);\n --drawer-shadow-bottom: 0 -10px 60px hsl(0 0% 0% / 0.4), 0 -4px 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-top: 0 10px 60px hsl(0 0% 0% / 0.4), 0 4px 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-right: -10px 0 60px hsl(0 0% 0% / 0.4), -4px 0 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-left: 10px 0 60px hsl(0 0% 0% / 0.4), 4px 0 20px hsl(0 0% 0% / 0.3);\n --drawer-shadow-modal: 0 25px 50px -12px hsl(0 0% 0% / 0.5);\n }\n}\n\n/* Background scale effect */\nbody {\n transition: scale var(--drawer-duration) var(--drawer-ease), border-radius var(--drawer-duration) var(--drawer-ease);\n transform-origin: center top;\n}\n\nbody:has(.drawer[open]) {\n overflow: hidden;\n scale: var(--drawer-nested-scale);\n border-radius: var(--drawer-radius);\n}\n\n/* Base drawer */\n.drawer {\n border: none;\n padding: 0;\n margin: 0;\n max-width: 100%;\n max-height: 100%;\n position: fixed;\n background: var(--drawer-bg);\n overflow: hidden;\n opacity: 0;\n transition:\n display var(--drawer-duration-close) allow-discrete,\n overlay var(--drawer-duration-close) allow-discrete,\n translate var(--drawer-duration-close) var(--drawer-ease),\n scale var(--drawer-duration-close) var(--drawer-ease),\n filter var(--drawer-duration-close) ease,\n opacity var(--drawer-duration-close) ease;\n\n /* Default: bottom */\n --_translate-closed: 0 100%;\n --_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;\n inset: auto 0 0 0;\n margin-inline: auto;\n width: 100%;\n max-width: var(--drawer-max-width);\n height: auto;\n max-height: var(--drawer-max-height);\n border-radius: var(--drawer-border-radius, var(--_border-radius));\n box-shadow: var(--drawer-shadow-bottom);\n translate: var(--_translate-closed);\n}\n\n.drawer::backdrop {\n background: var(--drawer-backdrop);\n opacity: 0;\n backdrop-filter: blur(var(--drawer-backdrop-blur));\n -webkit-backdrop-filter: blur(var(--drawer-backdrop-blur));\n transition:\n display var(--drawer-duration-close) allow-discrete,\n overlay var(--drawer-duration-close) allow-discrete,\n opacity var(--drawer-duration-close) ease;\n}\n\n.drawer[open] {\n opacity: 1;\n translate: 0 0;\n transition:\n display var(--drawer-duration) allow-discrete,\n overlay var(--drawer-duration) allow-discrete,\n translate var(--drawer-duration) var(--drawer-ease),\n scale var(--drawer-duration) var(--drawer-ease),\n filter var(--drawer-duration) ease,\n opacity 0.15s ease;\n}\n\n.drawer[open]::backdrop {\n opacity: 1;\n transition: display var(--drawer-duration) allow-discrete, overlay var(--drawer-duration) allow-discrete, opacity 0.2s ease;\n}\n\n@starting-style {\n .drawer[open] { opacity: 0; translate: var(--_translate-closed); }\n .drawer[open]::backdrop { opacity: 0; }\n}\n\n/* ===== DIRECTIONS ===== */\n\n/* Right */\n.drawer[data-direction=\"right\"] {\n --_translate-closed: 100% 0;\n --_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);\n inset: 0 0 0 auto;\n margin: 0;\n width: 100%;\n max-width: var(--drawer-max-width);\n height: 100dvh;\n max-height: 100dvh;\n box-shadow: var(--drawer-shadow-right);\n}\n\n/* Left */\n.drawer[data-direction=\"left\"] {\n --_translate-closed: -100% 0;\n --_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;\n inset: 0 auto 0 0;\n margin: 0;\n width: 100%;\n max-width: var(--drawer-max-width);\n height: 100dvh;\n max-height: 100dvh;\n box-shadow: var(--drawer-shadow-left);\n}\n\n/* Top */\n.drawer[data-direction=\"top\"] {\n --_translate-closed: 0 -100%;\n --_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);\n inset: 0 0 auto 0;\n margin-inline: auto;\n width: 100%;\n max-width: var(--drawer-max-width);\n height: auto;\n max-height: var(--drawer-max-height);\n box-shadow: var(--drawer-shadow-top);\n}\n\n/* Modal (centered) */\n.drawer[data-direction=\"modal\"] {\n --_translate-closed: 0 0;\n --_border-radius: var(--drawer-radius);\n inset: 0;\n margin: auto;\n width: fit-content;\n max-width: var(--drawer-max-width);\n height: fit-content;\n max-height: var(--drawer-max-height);\n box-shadow: var(--drawer-shadow-modal);\n scale: var(--drawer-nested-scale);\n}\n\n.drawer[data-direction=\"modal\"][open] {\n scale: 1;\n}\n\n@starting-style {\n .drawer[data-direction=\"modal\"][open] {\n scale: var(--drawer-nested-scale);\n }\n}\n\n/* ===== AUTO-NESTING (up to 5 levels) ===== */\n/* Uses sibling combinators to count open drawers */\n\n/* 1+ open drawers after */\n.drawer[open]:has(~ .drawer[open]) {\n scale: var(--drawer-nested-scale);\n translate: 0 calc(-1 * var(--drawer-nested-offset));\n border-radius: var(--drawer-radius);\n filter: brightness(var(--drawer-nested-brightness));\n pointer-events: none;\n}\n\n/* 2+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-2 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* 3+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-3 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* 4+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-4 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* 5+ open drawers after */\n.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));\n translate: 0 calc(-5 * var(--drawer-nested-offset));\n filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));\n}\n\n/* Lighter backdrop for stacked drawers */\n.drawer[open] ~ .drawer[open]::backdrop {\n background: var(--drawer-nested-backdrop);\n backdrop-filter: none;\n}\n\n/* Handle */\n.drawer-handle {\n display: flex;\n justify-content: center;\n padding-block: var(--drawer-handle-padding-block);\n padding-inline: var(--drawer-handle-padding-inline);\n cursor: grab;\n}\n\n.drawer-handle::before {\n content: '';\n width: var(--drawer-handle-width);\n height: var(--drawer-handle-height);\n background: var(--drawer-handle-bg);\n border-radius: 100px;\n transition: width 0.2s var(--drawer-ease), height 0.2s var(--drawer-ease), background 0.2s ease;\n}\n\n.drawer-handle:hover::before {\n width: var(--drawer-handle-width-hover);\n background: var(--drawer-handle-bg-hover);\n}\n\n/* Vertical handle for left/right drawers */\n.drawer[data-direction=\"left\"] .drawer-handle,\n.drawer[data-direction=\"right\"] .drawer-handle {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding-block: var(--drawer-handle-padding-inline);\n padding-inline: var(--drawer-handle-padding-block);\n height: 100%;\n position: absolute;\n top: 0;\n writing-mode: vertical-lr;\n}\n\n.drawer[data-direction=\"left\"] .drawer-handle { right: 0; }\n.drawer[data-direction=\"right\"] .drawer-handle { left: 0; }\n\n.drawer[data-direction=\"left\"] .drawer-handle::before,\n.drawer[data-direction=\"right\"] .drawer-handle::before {\n width: var(--drawer-handle-height);\n height: var(--drawer-handle-width);\n}\n\n.drawer[data-direction=\"left\"] .drawer-handle:hover::before,\n.drawer[data-direction=\"right\"] .drawer-handle:hover::before {\n width: var(--drawer-handle-height);\n height: var(--drawer-handle-width-hover);\n}\n\n/* Content - structural only, no opinionated padding */\n.drawer-content {\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n min-height: 0;\n}\n\n/* Content sizing for directions */\n.drawer[data-direction=\"left\"] .drawer-content,\n.drawer[data-direction=\"right\"] .drawer-content {\n height: 100%;\n}\n\n/* Reduced motion */\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n transition-duration: 0.01ms !important;\n }\n\n body:has(.drawer[open]) {\n scale: 1;\n }\n\n .drawer[open]:has(~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),\n .drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {\n scale: 1;\n translate: 0 0;\n filter: none;\n }\n}\n"],"mappings":"AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/drawer-CiHZcyXE.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export{};
|