css-drawer 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -2
- package/dist/index.d.cts +0 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/index.mjs.map +1 -1
- package/dist/observer-B-WjvsFU.cjs +1 -0
- package/dist/{observer-DIOx0VCj.mjs → observer-Cam7lP_h.mjs} +2 -1
- package/dist/{observer-DIOx0VCj.mjs.map → observer-Cam7lP_h.mjs.map} +1 -1
- package/dist/react.cjs +1 -2
- package/dist/react.d.cts +7 -7
- package/dist/react.d.cts.map +1 -1
- package/dist/react.d.mts +7 -7
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +1 -2
- package/dist/react.mjs.map +1 -1
- package/dist/{observer-CtfG4nrq.css → style.css} +88 -128
- package/package.json +6 -6
- package/dist/observer-QD6bSdOu.css +0 -334
- package/dist/observer-QD6bSdOu.css.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
require(
|
|
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=`
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});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
2
|
${i?`<div class="drawer-handle"></div>`:``}
|
|
4
3
|
<div class="drawer-content">${n}</div>
|
|
5
4
|
`,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
CHANGED
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";KAOY,aAAA,GAAgB,iBAAA;AAAA,KAEhB,SAAA,YAAqB,aAAA;AAAA,KAErB,eAAA;AAAA,UAEK,mBAAA;EAJgB;EAM/B,EAAA;EAJU;EAMV,OAAA;;EAEA,SAAA,GAAY,eAAA;EARa;EAUzB,MAAA;EARkC;EAUlC,SAAA;EAJ2B;EAM3B,mBAAA;AAAA;AAAA,UAGe,mBAAA;EATH;EAWZ,MAAA;EAPA;EASA,OAAA;EAPmB;EASnB,QAAA;AAAA;;;;iBAiBc,IAAA,CAAK,MAAA,EAAQ,SAAA;;;;iBAQb,KAAA,CAAM,MAAA,EAAQ,SAAA;AAR9B;;;AAAA,iBAgBgB,QAAA,CAAA;;AARhB;;iBAgBgB,MAAA,CAAO,MAAA,EAAQ,SAAA;;;AAR/B;iBAgBgB,OAAA,CAAA,GAAW,aAAA;;;;iBAOX,MAAA,CAAA,GAAU,aAAA;;;;iBAQV,MAAA,CAAO,OAAA,GAAS,mBAAA,GAA2B,aAAA;AAf3D;;;AAAA,iBA4CgB,KAAA,CAAM,MAAA,EAAQ,aAAA,GAAgB,aAAA;;AArC9C;;iBA6CgB,OAAA,CAAQ,MAAA,EAAQ,SAAA;;;AArChC;;;iBA+CgB,IAAA,CAAA;;;;;iBAgBA,SAAA,CACd,MAAA,EAAQ,SAAA,EACR,QAAA,EAAU,mBAAA;AApCZ;;;;AAAA,iBAqEgB,KAAA,CAAM,EAAA,UAAY,OAAA;EAAY,mBAAA;AAAA;EAAA;;;wBAM7B,UAAA;AAAA"}
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";KAOY,aAAA,GAAgB,iBAAA;AAAA,KAEhB,SAAA,YAAqB,aAAA;AAAA,KAErB,eAAA;AAAA,UAEK,mBAAA;EAJgB;EAM/B,EAAA;EAJU;EAMV,OAAA;;EAEA,SAAA,GAAY,eAAA;EARa;EAUzB,MAAA;EARkC;EAUlC,SAAA;EAJ2B;EAM3B,mBAAA;AAAA;AAAA,UAGe,mBAAA;EATH;EAWZ,MAAA;EAPA;EASA,OAAA;EAPmB;EASnB,QAAA;AAAA;;;;iBAiBc,IAAA,CAAK,MAAA,EAAQ,SAAA;;;;iBAQb,KAAA,CAAM,MAAA,EAAQ,SAAA;AAR9B;;;AAAA,iBAgBgB,QAAA,CAAA;;AARhB;;iBAgBgB,MAAA,CAAO,MAAA,EAAQ,SAAA;;;AAR/B;iBAgBgB,OAAA,CAAA,GAAW,aAAA;;;;iBAOX,MAAA,CAAA,GAAU,aAAA;;;;iBAQV,MAAA,CAAO,OAAA,GAAS,mBAAA,GAA2B,aAAA;AAf3D;;;AAAA,iBA4CgB,KAAA,CAAM,MAAA,EAAQ,aAAA,GAAgB,aAAA;;AArC9C;;iBA6CgB,OAAA,CAAQ,MAAA,EAAQ,SAAA;;;AArChC;;;iBA+CgB,IAAA,CAAA;;;;;iBAgBA,SAAA,CACd,MAAA,EAAQ,SAAA,EACR,QAAA,EAAU,mBAAA;AApCZ;;;;AAAA,iBAqEgB,KAAA,CAAM,EAAA,UAAY,OAAA;EAAY,mBAAA;AAAA;EAAA;;;wBAM7B,UAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./observer-
|
|
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=`
|
|
1
|
+
import{t as e}from"./observer-Cam7lP_h.mjs";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
2
|
${i?`<div class="drawer-handle"></div>`:``}
|
|
4
3
|
<div class="drawer-content">${n}</div>
|
|
5
4
|
`,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};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"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,EACjB,EAAE,WAAW,CAMjB,SAAgB,EAAM,EAAyB,CAClC,EAAQ,EACjB,EAAE,OAAO,CAMb,SAAgB,GAAiB,CACf,MAAM,KAAK,SAAS,iBAAgC,sBAAsB,CACnF,CAAC,SAAS,CAAC,QAAS,GAAM,EAAE,OAAO,CAAC,CAM7C,SAAgB,EAAO,EAA4B,CAEjD,OADW,EAAQ,EACV,EAAE,MAAQ,GAMrB,SAAgB,GAA2B,CACzC,OAAO,MAAM,KAAK,SAAS,iBAAgC,sBAAsB,CAAC,CAMpF,SAAgB,GAA+B,CAC7C,IAAM,EAAO,GAAS,CACtB,OAAO,EAAK,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,EACjB,EAAE,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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
+
import './style.css';
|
|
1
2
|
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}});
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import './style.css';
|
|
1
2
|
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-
|
|
3
|
+
//# sourceMappingURL=observer-Cam7lP_h.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer-
|
|
1
|
+
{"version":3,"file":"observer-Cam7lP_h.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,EAmBJ,IAhBqB,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,QAKE,CAAC,QAAQ,SAAS,KAAM,CAC9B,QAAS,GACT,WAAY,GACZ,gBAAiB,CAAC,OAAO,CAC1B,CAAC,CAIJ,GAAoB"}
|
package/dist/react.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
require(
|
|
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;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});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,5 +1,5 @@
|
|
|
1
|
-
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
-
import * as
|
|
1
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
+
import * as _$react from "react";
|
|
3
3
|
import { ComponentPropsWithoutRef, ReactNode, RefObject } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react.d.ts
|
|
@@ -21,7 +21,7 @@ interface RootProps {
|
|
|
21
21
|
declare function Root({
|
|
22
22
|
children,
|
|
23
23
|
direction
|
|
24
|
-
}: RootProps): react_jsx_runtime0.JSX.Element;
|
|
24
|
+
}: RootProps): _$react_jsx_runtime0.JSX.Element;
|
|
25
25
|
interface ContentProps extends Omit<ComponentPropsWithoutRef<'dialog'>, 'open'> {
|
|
26
26
|
/** Controlled open state */
|
|
27
27
|
open?: boolean;
|
|
@@ -35,10 +35,10 @@ interface TitleProps extends ComponentPropsWithoutRef<'h2'> {}
|
|
|
35
35
|
interface DescriptionProps extends ComponentPropsWithoutRef<'p'> {}
|
|
36
36
|
declare const Drawer: {
|
|
37
37
|
Root: typeof Root;
|
|
38
|
-
Content:
|
|
39
|
-
Handle:
|
|
40
|
-
Title:
|
|
41
|
-
Description:
|
|
38
|
+
Content: _$react.ForwardRefExoticComponent<ContentProps & _$react.RefAttributes<HTMLDialogElement>>;
|
|
39
|
+
Handle: _$react.ForwardRefExoticComponent<HandleProps & _$react.RefAttributes<HTMLDivElement>>;
|
|
40
|
+
Title: _$react.ForwardRefExoticComponent<TitleProps & _$react.RefAttributes<HTMLHeadingElement>>;
|
|
41
|
+
Description: _$react.ForwardRefExoticComponent<DescriptionProps & _$react.RefAttributes<HTMLParagraphElement>>;
|
|
42
42
|
};
|
|
43
43
|
//#endregion
|
|
44
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 };
|
package/dist/react.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.cts","names":[],"sources":["../src/react.tsx"],"
|
|
1
|
+
{"version":3,"file":"react.d.cts","names":[],"sources":["../src/react.tsx"],"mappings":";;;;;KAeK,SAAA;;;AAJgB;iBA8BL,YAAA,CAAA,GAAgB,iBAAA;;;;AAAhC;iBASgB,cAAA,CAAe,GAAA,EAAK,SAAA,CAAU,iBAAA;AAAA,UAqBpC,SAAA;EACR,QAAA,EAAU,SAAA;EA/BqC;EAiC/C,SAAA,GAAY,SAAA;AAAA;AAAA,iBAGL,IAAA,CAAA;EAAO,QAAA;EAAU;AAAA,GAAa,SAAA,GAAS,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAStC,YAAA,SAAqB,IAAA,CAAK,wBAAA;EApCA;EAsClC,IAAA;EAtC6B;EAwC7B,YAAA,IAAgB,IAAA;EAxCqD;EA0CrE,mBAAA;AAAA;AAAA,UAmDQ,WAAA,SAAoB,wBAAA;AAAA,UAapB,UAAA,SAAmB,wBAAA;AAAA,UAQnB,gBAAA,SAAyB,wBAAA;AAAA,cAQtB,MAAA"}
|
package/dist/react.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _$react from "react";
|
|
2
2
|
import { ComponentPropsWithoutRef, ReactNode, RefObject } from "react";
|
|
3
|
-
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
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';
|
|
@@ -21,7 +21,7 @@ interface RootProps {
|
|
|
21
21
|
declare function Root({
|
|
22
22
|
children,
|
|
23
23
|
direction
|
|
24
|
-
}: RootProps): react_jsx_runtime0.JSX.Element;
|
|
24
|
+
}: RootProps): _$react_jsx_runtime0.JSX.Element;
|
|
25
25
|
interface ContentProps extends Omit<ComponentPropsWithoutRef<'dialog'>, 'open'> {
|
|
26
26
|
/** Controlled open state */
|
|
27
27
|
open?: boolean;
|
|
@@ -35,10 +35,10 @@ interface TitleProps extends ComponentPropsWithoutRef<'h2'> {}
|
|
|
35
35
|
interface DescriptionProps extends ComponentPropsWithoutRef<'p'> {}
|
|
36
36
|
declare const Drawer: {
|
|
37
37
|
Root: typeof Root;
|
|
38
|
-
Content:
|
|
39
|
-
Handle:
|
|
40
|
-
Title:
|
|
41
|
-
Description:
|
|
38
|
+
Content: _$react.ForwardRefExoticComponent<ContentProps & _$react.RefAttributes<HTMLDialogElement>>;
|
|
39
|
+
Handle: _$react.ForwardRefExoticComponent<HandleProps & _$react.RefAttributes<HTMLDivElement>>;
|
|
40
|
+
Title: _$react.ForwardRefExoticComponent<TitleProps & _$react.RefAttributes<HTMLHeadingElement>>;
|
|
41
|
+
Description: _$react.ForwardRefExoticComponent<DescriptionProps & _$react.RefAttributes<HTMLParagraphElement>>;
|
|
42
42
|
};
|
|
43
43
|
//#endregion
|
|
44
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 };
|
package/dist/react.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.mts","names":[],"sources":["../src/react.tsx"],"
|
|
1
|
+
{"version":3,"file":"react.d.mts","names":[],"sources":["../src/react.tsx"],"mappings":";;;;;KAeK,SAAA;;;AAJgB;iBA8BL,YAAA,CAAA,GAAgB,iBAAA;;;;AAAhC;iBASgB,cAAA,CAAe,GAAA,EAAK,SAAA,CAAU,iBAAA;AAAA,UAqBpC,SAAA;EACR,QAAA,EAAU,SAAA;EA/BqC;EAiC/C,SAAA,GAAY,SAAA;AAAA;AAAA,iBAGL,IAAA,CAAA;EAAO,QAAA;EAAU;AAAA,GAAa,SAAA,GAAS,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAStC,YAAA,SAAqB,IAAA,CAAK,wBAAA;EApCA;EAsClC,IAAA;EAtC6B;EAwC7B,YAAA,IAAgB,IAAA;EAxCqD;EA0CrE,mBAAA;AAAA;AAAA,UAmDQ,WAAA,SAAoB,wBAAA;AAAA,UAapB,UAAA,SAAmB,wBAAA;AAAA,UAQnB,gBAAA,SAAyB,wBAAA;AAAA,cAQtB,MAAA"}
|
package/dist/react.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./observer-
|
|
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};
|
|
1
|
+
import{t as e}from"./observer-Cam7lP_h.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";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
2
|
//# 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 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,
|
|
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,SAAf,CAAwB,MAAO,CAAE,YAAW,CACzC,WACsB,CAAA,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,SAAD,CACE,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,WACM,CAAA,EAGd,CACD,EAAQ,YAAc,iBAKtB,MAAM,EAAS,GAAyC,CAAE,YAAW,GAAG,GAAS,IAC/E,EAAC,MAAD,CACO,MACL,UAAW,iBAAiB,GAAa,KAAK,MAAM,CACpD,cAAY,OACZ,GAAI,EACJ,CAAA,CACF,CACF,EAAO,YAAc,gBAKrB,MAAM,EAAQ,GAA4C,EAAO,IAC/D,EAAC,KAAD,CAAS,MAAK,GAAI,EAAS,CAAA,CAC3B,CACF,EAAM,YAAc,eAKpB,MAAM,EAAc,GAAoD,EAAO,IAC7E,EAAC,IAAD,CAAQ,MAAK,GAAI,EAAS,CAAA,CAC1B,CACF,EAAY,YAAc,qBAG1B,MAAa,EAAS,CACpB,OACA,UACA,SACA,QACA,cACD"}
|
|
@@ -1,94 +1,70 @@
|
|
|
1
|
-
/* CSS Drawer - Vaul-quality drawer with auto-nesting and directions */
|
|
2
|
-
|
|
3
1
|
:root {
|
|
4
|
-
/* Visual */
|
|
5
2
|
--drawer-bg: #fff;
|
|
6
3
|
--drawer-radius: 24px;
|
|
7
|
-
--drawer-backdrop:
|
|
4
|
+
--drawer-backdrop: #0006;
|
|
8
5
|
--drawer-backdrop-blur: 4px;
|
|
9
|
-
|
|
10
|
-
/* Sizing */
|
|
11
6
|
--drawer-max-height: 96dvh;
|
|
12
7
|
--drawer-modal-width: fit-content;
|
|
13
8
|
--drawer-modal-height: fit-content;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
--drawer-handle-bg: hsl(0 0% 80%);
|
|
17
|
-
--drawer-handle-bg-hover: hsl(0 0% 60%);
|
|
9
|
+
--drawer-handle-bg: #ccc;
|
|
10
|
+
--drawer-handle-bg-hover: #999;
|
|
18
11
|
--drawer-handle-width: 48px;
|
|
19
12
|
--drawer-handle-width-hover: 56px;
|
|
20
13
|
--drawer-handle-height: 5px;
|
|
21
|
-
--drawer-handle-padding-block: 1rem
|
|
14
|
+
--drawer-handle-padding-block: 1rem .5rem;
|
|
22
15
|
--drawer-handle-padding-inline: 0;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
--drawer-shadow-
|
|
26
|
-
--drawer-shadow-
|
|
27
|
-
--drawer-shadow-
|
|
28
|
-
--drawer-
|
|
29
|
-
--drawer-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
--drawer-duration: 0.5s;
|
|
33
|
-
--drawer-duration-close: 0.35s;
|
|
34
|
-
--drawer-ease: cubic-bezier(0.32, 0.72, 0, 1);
|
|
35
|
-
|
|
36
|
-
/* Nesting effects */
|
|
37
|
-
--drawer-nested-scale: 0.94;
|
|
16
|
+
--drawer-shadow-bottom: 0 -10px 60px #0000001f, 0 -4px 20px #00000014;
|
|
17
|
+
--drawer-shadow-top: 0 10px 60px #0000001f, 0 4px 20px #00000014;
|
|
18
|
+
--drawer-shadow-right: -10px 0 60px #0000001f, -4px 0 20px #00000014;
|
|
19
|
+
--drawer-shadow-left: 10px 0 60px #0000001f, 4px 0 20px #00000014;
|
|
20
|
+
--drawer-shadow-modal: 0 25px 50px -12px #00000040;
|
|
21
|
+
--drawer-duration: .5s;
|
|
22
|
+
--drawer-duration-close: .35s;
|
|
23
|
+
--drawer-ease: cubic-bezier(.32, .72, 0, 1);
|
|
24
|
+
--drawer-nested-scale: .94;
|
|
38
25
|
--drawer-nested-offset: 20px;
|
|
39
|
-
--drawer-nested-brightness:
|
|
40
|
-
--drawer-nested-backdrop:
|
|
26
|
+
--drawer-nested-brightness: .92;
|
|
27
|
+
--drawer-nested-backdrop: #00000026;
|
|
41
28
|
}
|
|
42
29
|
|
|
43
30
|
@media (prefers-color-scheme: dark) {
|
|
44
31
|
:root {
|
|
45
|
-
--drawer-bg:
|
|
46
|
-
--drawer-handle-bg:
|
|
47
|
-
--drawer-handle-bg-hover:
|
|
48
|
-
--drawer-shadow-bottom: 0 -10px 60px
|
|
49
|
-
--drawer-shadow-top: 0 10px 60px
|
|
50
|
-
--drawer-shadow-right: -10px 0 60px
|
|
51
|
-
--drawer-shadow-left: 10px 0 60px
|
|
52
|
-
--drawer-shadow-modal: 0 25px 50px -12px
|
|
32
|
+
--drawer-bg: #1f1f1f;
|
|
33
|
+
--drawer-handle-bg: #595959;
|
|
34
|
+
--drawer-handle-bg-hover: gray;
|
|
35
|
+
--drawer-shadow-bottom: 0 -10px 60px #0006, 0 -4px 20px #0000004d;
|
|
36
|
+
--drawer-shadow-top: 0 10px 60px #0006, 0 4px 20px #0000004d;
|
|
37
|
+
--drawer-shadow-right: -10px 0 60px #0006, -4px 0 20px #0000004d;
|
|
38
|
+
--drawer-shadow-left: 10px 0 60px #0006, 4px 0 20px #0000004d;
|
|
39
|
+
--drawer-shadow-modal: 0 25px 50px -12px #00000080;
|
|
53
40
|
}
|
|
54
41
|
}
|
|
55
42
|
|
|
56
|
-
/* Background scale effect */
|
|
57
43
|
body {
|
|
58
44
|
transition: scale var(--drawer-duration) var(--drawer-ease), border-radius var(--drawer-duration) var(--drawer-ease);
|
|
59
|
-
transform-origin:
|
|
45
|
+
transform-origin: top;
|
|
60
46
|
}
|
|
61
47
|
|
|
62
48
|
body:has(.drawer[open]) {
|
|
63
|
-
overflow: hidden;
|
|
64
49
|
scale: var(--drawer-nested-scale);
|
|
65
50
|
border-radius: var(--drawer-radius);
|
|
51
|
+
overflow: hidden;
|
|
66
52
|
}
|
|
67
53
|
|
|
68
|
-
/* Base drawer */
|
|
69
54
|
.drawer {
|
|
70
|
-
border: none;
|
|
71
|
-
padding: 0;
|
|
72
|
-
margin: 0;
|
|
73
|
-
max-width: 100%;
|
|
74
|
-
max-height: 100%;
|
|
75
|
-
position: fixed;
|
|
76
55
|
background: var(--drawer-bg);
|
|
77
|
-
overflow: hidden;
|
|
78
56
|
opacity: 0;
|
|
79
|
-
|
|
80
|
-
|
|
57
|
+
max-width: 100%;
|
|
58
|
+
max-height: 100%;
|
|
59
|
+
transition: display var(--drawer-duration-close) allow-discrete,
|
|
81
60
|
overlay var(--drawer-duration-close) allow-discrete,
|
|
82
61
|
translate var(--drawer-duration-close) var(--drawer-ease),
|
|
83
62
|
scale var(--drawer-duration-close) var(--drawer-ease),
|
|
84
63
|
filter var(--drawer-duration-close) ease,
|
|
85
64
|
opacity var(--drawer-duration-close) ease;
|
|
86
|
-
|
|
87
|
-
/* Default: bottom */
|
|
88
65
|
--_translate-closed: 0 100%;
|
|
89
66
|
--_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;
|
|
90
|
-
|
|
91
|
-
margin-inline: auto;
|
|
67
|
+
margin: 0;
|
|
92
68
|
width: var(--drawer-width, 100%);
|
|
93
69
|
max-width: var(--drawer-max-width, none);
|
|
94
70
|
height: var(--drawer-height, auto);
|
|
@@ -96,94 +72,97 @@ body:has(.drawer[open]) {
|
|
|
96
72
|
border-radius: var(--drawer-border-radius, var(--_border-radius));
|
|
97
73
|
box-shadow: var(--drawer-shadow-bottom);
|
|
98
74
|
translate: var(--_translate-closed);
|
|
75
|
+
border: none;
|
|
76
|
+
margin-inline: auto;
|
|
77
|
+
padding: 0;
|
|
78
|
+
position: fixed;
|
|
79
|
+
inset: auto 0 0;
|
|
80
|
+
overflow: hidden;
|
|
99
81
|
}
|
|
100
82
|
|
|
101
83
|
.drawer::backdrop {
|
|
102
84
|
background: var(--drawer-backdrop);
|
|
103
85
|
opacity: 0;
|
|
104
|
-
backdrop-filter: blur(var(--drawer-backdrop-blur));
|
|
105
86
|
-webkit-backdrop-filter: blur(var(--drawer-backdrop-blur));
|
|
106
|
-
transition:
|
|
107
|
-
display var(--drawer-duration-close) allow-discrete,
|
|
87
|
+
transition: display var(--drawer-duration-close) allow-discrete,
|
|
108
88
|
overlay var(--drawer-duration-close) allow-discrete,
|
|
109
89
|
opacity var(--drawer-duration-close) ease;
|
|
110
90
|
}
|
|
111
91
|
|
|
112
92
|
.drawer[open] {
|
|
113
93
|
opacity: 1;
|
|
114
|
-
|
|
115
|
-
transition:
|
|
116
|
-
display var(--drawer-duration) allow-discrete,
|
|
94
|
+
transition: display var(--drawer-duration) allow-discrete,
|
|
117
95
|
overlay var(--drawer-duration) allow-discrete,
|
|
118
96
|
translate var(--drawer-duration) var(--drawer-ease),
|
|
119
97
|
scale var(--drawer-duration) var(--drawer-ease),
|
|
120
98
|
filter var(--drawer-duration) ease,
|
|
121
|
-
opacity
|
|
99
|
+
opacity .15s ease;
|
|
100
|
+
translate: 0;
|
|
122
101
|
}
|
|
123
102
|
|
|
124
103
|
.drawer[open]::backdrop {
|
|
125
104
|
opacity: 1;
|
|
126
|
-
transition: display var(--drawer-duration) allow-discrete, overlay var(--drawer-duration) allow-discrete, opacity
|
|
105
|
+
transition: display var(--drawer-duration) allow-discrete, overlay var(--drawer-duration) allow-discrete, opacity .2s ease;
|
|
127
106
|
}
|
|
128
107
|
|
|
129
108
|
@starting-style {
|
|
130
|
-
.drawer[open] {
|
|
131
|
-
|
|
132
|
-
|
|
109
|
+
.drawer[open] {
|
|
110
|
+
opacity: 0;
|
|
111
|
+
translate: var(--_translate-closed);
|
|
112
|
+
}
|
|
133
113
|
|
|
134
|
-
|
|
114
|
+
.drawer[open]::backdrop {
|
|
115
|
+
opacity: 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
135
118
|
|
|
136
|
-
/* Right */
|
|
137
119
|
.drawer[data-direction="right"] {
|
|
138
120
|
--_translate-closed: 100% 0;
|
|
139
121
|
--_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);
|
|
140
|
-
inset: 0 0 0 auto;
|
|
141
|
-
margin: 0;
|
|
142
122
|
width: var(--drawer-width, 500px);
|
|
143
123
|
max-width: var(--drawer-max-width, 90%);
|
|
144
124
|
height: var(--drawer-height, 100dvh);
|
|
145
125
|
max-height: 100dvh;
|
|
146
126
|
box-shadow: var(--drawer-shadow-right);
|
|
127
|
+
margin: 0;
|
|
128
|
+
inset: 0 0 0 auto;
|
|
147
129
|
}
|
|
148
130
|
|
|
149
|
-
/* Left */
|
|
150
131
|
.drawer[data-direction="left"] {
|
|
151
132
|
--_translate-closed: -100% 0;
|
|
152
133
|
--_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;
|
|
153
|
-
inset: 0 auto 0 0;
|
|
154
|
-
margin: 0;
|
|
155
134
|
width: var(--drawer-width, 500px);
|
|
156
135
|
max-width: var(--drawer-max-width, 90%);
|
|
157
136
|
height: var(--drawer-height, 100dvh);
|
|
158
137
|
max-height: 100dvh;
|
|
159
138
|
box-shadow: var(--drawer-shadow-left);
|
|
139
|
+
margin: 0;
|
|
140
|
+
inset: 0 auto 0 0;
|
|
160
141
|
}
|
|
161
142
|
|
|
162
|
-
/* Top */
|
|
163
143
|
.drawer[data-direction="top"] {
|
|
164
144
|
--_translate-closed: 0 -100%;
|
|
165
145
|
--_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);
|
|
166
|
-
inset: 0 0 auto 0;
|
|
167
|
-
margin-inline: auto;
|
|
168
146
|
width: var(--drawer-width, 100%);
|
|
169
147
|
max-width: var(--drawer-max-width, none);
|
|
170
148
|
height: var(--drawer-height, auto);
|
|
171
149
|
max-height: var(--drawer-max-height, 96dvh);
|
|
172
150
|
box-shadow: var(--drawer-shadow-top);
|
|
151
|
+
margin-inline: auto;
|
|
152
|
+
inset: 0 0 auto;
|
|
173
153
|
}
|
|
174
154
|
|
|
175
|
-
/* Modal (centered) */
|
|
176
155
|
.drawer[data-direction="modal"] {
|
|
177
156
|
--_translate-closed: 0 0;
|
|
178
157
|
--_border-radius: var(--drawer-radius);
|
|
179
|
-
inset: 0;
|
|
180
|
-
margin: auto;
|
|
181
158
|
width: var(--drawer-modal-width, fit-content);
|
|
182
159
|
max-width: var(--drawer-max-width, 90%);
|
|
183
160
|
height: var(--drawer-modal-height, fit-content);
|
|
184
161
|
max-height: var(--drawer-max-height, 96dvh);
|
|
185
162
|
box-shadow: var(--drawer-shadow-modal);
|
|
186
163
|
scale: var(--drawer-nested-scale);
|
|
164
|
+
margin: auto;
|
|
165
|
+
inset: 0;
|
|
187
166
|
}
|
|
188
167
|
|
|
189
168
|
.drawer[data-direction="modal"][open] {
|
|
@@ -196,11 +175,7 @@ body:has(.drawer[open]) {
|
|
|
196
175
|
}
|
|
197
176
|
}
|
|
198
177
|
|
|
199
|
-
|
|
200
|
-
/* Uses sibling combinators to count open drawers */
|
|
201
|
-
|
|
202
|
-
/* 1+ open drawers after */
|
|
203
|
-
.drawer[open]:has(~ .drawer[open]) {
|
|
178
|
+
.drawer[open]:has( ~ .drawer[open]) {
|
|
204
179
|
scale: var(--drawer-nested-scale);
|
|
205
180
|
translate: 0 calc(-1 * var(--drawer-nested-offset));
|
|
206
181
|
border-radius: var(--drawer-radius);
|
|
@@ -208,125 +183,110 @@ body:has(.drawer[open]) {
|
|
|
208
183
|
pointer-events: none;
|
|
209
184
|
}
|
|
210
185
|
|
|
211
|
-
|
|
212
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open]) {
|
|
186
|
+
.drawer[open]:has( ~ .drawer[open] ~ .drawer[open]) {
|
|
213
187
|
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
214
188
|
translate: 0 calc(-2 * var(--drawer-nested-offset));
|
|
215
189
|
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
216
190
|
}
|
|
217
191
|
|
|
218
|
-
|
|
219
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
192
|
+
.drawer[open]:has( ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
220
193
|
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
221
194
|
translate: 0 calc(-3 * var(--drawer-nested-offset));
|
|
222
195
|
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
223
196
|
}
|
|
224
197
|
|
|
225
|
-
|
|
226
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
198
|
+
.drawer[open]:has( ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
227
199
|
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
228
200
|
translate: 0 calc(-4 * var(--drawer-nested-offset));
|
|
229
201
|
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
230
202
|
}
|
|
231
203
|
|
|
232
|
-
|
|
233
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
204
|
+
.drawer[open]:has( ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
234
205
|
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
235
206
|
translate: 0 calc(-5 * var(--drawer-nested-offset));
|
|
236
207
|
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
237
208
|
}
|
|
238
209
|
|
|
239
|
-
/* Lighter backdrop for stacked drawers */
|
|
240
210
|
.drawer[open] ~ .drawer[open]::backdrop {
|
|
241
211
|
background: var(--drawer-nested-backdrop);
|
|
242
212
|
backdrop-filter: none;
|
|
243
213
|
}
|
|
244
214
|
|
|
245
|
-
/* Handle */
|
|
246
215
|
.drawer-handle {
|
|
247
|
-
display: flex;
|
|
248
|
-
justify-content: center;
|
|
249
216
|
padding-block: var(--drawer-handle-padding-block);
|
|
250
217
|
padding-inline: var(--drawer-handle-padding-inline);
|
|
251
218
|
cursor: grab;
|
|
219
|
+
justify-content: center;
|
|
220
|
+
display: flex;
|
|
252
221
|
}
|
|
253
222
|
|
|
254
|
-
.drawer-handle
|
|
255
|
-
content:
|
|
223
|
+
.drawer-handle:before {
|
|
224
|
+
content: "";
|
|
256
225
|
width: var(--drawer-handle-width);
|
|
257
226
|
height: var(--drawer-handle-height);
|
|
258
227
|
background: var(--drawer-handle-bg);
|
|
228
|
+
transition: width .2s var(--drawer-ease), height .2s var(--drawer-ease), background .2s ease;
|
|
259
229
|
border-radius: 100px;
|
|
260
|
-
transition: width 0.2s var(--drawer-ease), height 0.2s var(--drawer-ease), background 0.2s ease;
|
|
261
230
|
}
|
|
262
231
|
|
|
263
|
-
.drawer-handle:hover
|
|
232
|
+
.drawer-handle:hover:before {
|
|
264
233
|
width: var(--drawer-handle-width-hover);
|
|
265
234
|
background: var(--drawer-handle-bg-hover);
|
|
266
235
|
}
|
|
267
236
|
|
|
268
|
-
|
|
269
|
-
.drawer[data-direction="left"] .drawer-handle,
|
|
270
|
-
.drawer[data-direction="right"] .drawer-handle {
|
|
271
|
-
flex-direction: column;
|
|
272
|
-
align-items: center;
|
|
273
|
-
justify-content: center;
|
|
237
|
+
.drawer[data-direction="left"] .drawer-handle, .drawer[data-direction="right"] .drawer-handle {
|
|
274
238
|
padding-block: var(--drawer-handle-padding-inline);
|
|
275
239
|
padding-inline: var(--drawer-handle-padding-block);
|
|
240
|
+
writing-mode: vertical-lr;
|
|
241
|
+
flex-direction: column;
|
|
242
|
+
justify-content: center;
|
|
243
|
+
align-items: center;
|
|
276
244
|
height: 100%;
|
|
277
245
|
position: absolute;
|
|
278
246
|
top: 0;
|
|
279
|
-
writing-mode: vertical-lr;
|
|
280
247
|
}
|
|
281
248
|
|
|
282
|
-
.drawer[data-direction="left"] .drawer-handle {
|
|
283
|
-
|
|
249
|
+
.drawer[data-direction="left"] .drawer-handle {
|
|
250
|
+
right: 0;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.drawer[data-direction="right"] .drawer-handle {
|
|
254
|
+
left: 0;
|
|
255
|
+
}
|
|
284
256
|
|
|
285
|
-
.drawer[data-direction="left"] .drawer-handle
|
|
286
|
-
.drawer[data-direction="right"] .drawer-handle::before {
|
|
257
|
+
.drawer[data-direction="left"] .drawer-handle:before, .drawer[data-direction="right"] .drawer-handle:before {
|
|
287
258
|
width: var(--drawer-handle-height);
|
|
288
259
|
height: var(--drawer-handle-width);
|
|
289
260
|
}
|
|
290
261
|
|
|
291
|
-
.drawer[data-direction="left"] .drawer-handle:hover
|
|
292
|
-
.drawer[data-direction="right"] .drawer-handle:hover::before {
|
|
262
|
+
.drawer[data-direction="left"] .drawer-handle:hover:before, .drawer[data-direction="right"] .drawer-handle:hover:before {
|
|
293
263
|
width: var(--drawer-handle-height);
|
|
294
264
|
height: var(--drawer-handle-width-hover);
|
|
295
265
|
}
|
|
296
266
|
|
|
297
|
-
/* Content - structural only, no opinionated padding */
|
|
298
267
|
.drawer-content {
|
|
299
|
-
overflow-x: hidden;
|
|
300
|
-
overflow-y: auto;
|
|
301
268
|
overscroll-behavior: contain;
|
|
302
269
|
flex: 1;
|
|
303
270
|
min-height: 0;
|
|
271
|
+
overflow: hidden auto;
|
|
304
272
|
}
|
|
305
273
|
|
|
306
|
-
|
|
307
|
-
.drawer[data-direction="left"] .drawer-content,
|
|
308
|
-
.drawer[data-direction="right"] .drawer-content {
|
|
274
|
+
.drawer[data-direction="left"] .drawer-content, .drawer[data-direction="right"] .drawer-content {
|
|
309
275
|
height: 100%;
|
|
310
276
|
}
|
|
311
277
|
|
|
312
|
-
/* Reduced motion */
|
|
313
278
|
@media (prefers-reduced-motion: reduce) {
|
|
314
|
-
*,
|
|
315
|
-
transition-duration:
|
|
279
|
+
*, :before, :after {
|
|
280
|
+
transition-duration: .01ms !important;
|
|
316
281
|
}
|
|
317
282
|
|
|
318
283
|
body:has(.drawer[open]) {
|
|
319
284
|
scale: 1;
|
|
320
285
|
}
|
|
321
286
|
|
|
322
|
-
.drawer[open]:has(~ .drawer[open]),
|
|
323
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open]),
|
|
324
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),
|
|
325
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),
|
|
326
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
327
|
-
scale: 1;
|
|
328
|
-
translate: 0 0;
|
|
287
|
+
.drawer[open]:has( ~ .drawer[open]), .drawer[open]:has( ~ .drawer[open] ~ .drawer[open]), .drawer[open]:has( ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]), .drawer[open]:has( ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]), .drawer[open]:has( ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
329
288
|
filter: none;
|
|
289
|
+
translate: 0;
|
|
290
|
+
scale: 1;
|
|
330
291
|
}
|
|
331
292
|
}
|
|
332
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "css-drawer",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Vaul-quality drawer component using native <dialog> and pure CSS animations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@
|
|
51
|
-
"@types/react": "^19.2.
|
|
50
|
+
"@tsdown/css": "^0.21.10",
|
|
51
|
+
"@types/react": "^19.2.14",
|
|
52
52
|
"@types/react-dom": "^19.2.3",
|
|
53
|
-
"react": "^19.2.
|
|
54
|
-
"tsdown": "^0.
|
|
55
|
-
"typescript": "^
|
|
53
|
+
"react": "^19.2.5",
|
|
54
|
+
"tsdown": "^0.21.10",
|
|
55
|
+
"typescript": "^6.0.3"
|
|
56
56
|
},
|
|
57
57
|
"keywords": [
|
|
58
58
|
"drawer",
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
/* CSS Drawer - Vaul-quality drawer with auto-nesting and directions */
|
|
2
|
-
|
|
3
|
-
:root {
|
|
4
|
-
/* Visual */
|
|
5
|
-
--drawer-bg: #fff;
|
|
6
|
-
--drawer-radius: 24px;
|
|
7
|
-
--drawer-backdrop: hsl(0 0% 0% / 0.4);
|
|
8
|
-
--drawer-backdrop-blur: 4px;
|
|
9
|
-
|
|
10
|
-
/* Sizing */
|
|
11
|
-
--drawer-max-height: 96dvh;
|
|
12
|
-
--drawer-modal-width: fit-content;
|
|
13
|
-
--drawer-modal-height: fit-content;
|
|
14
|
-
|
|
15
|
-
/* Handle */
|
|
16
|
-
--drawer-handle-bg: hsl(0 0% 80%);
|
|
17
|
-
--drawer-handle-bg-hover: hsl(0 0% 60%);
|
|
18
|
-
--drawer-handle-width: 48px;
|
|
19
|
-
--drawer-handle-width-hover: 56px;
|
|
20
|
-
--drawer-handle-height: 5px;
|
|
21
|
-
--drawer-handle-padding-block: 1rem 0.5rem;
|
|
22
|
-
--drawer-handle-padding-inline: 0;
|
|
23
|
-
|
|
24
|
-
/* Shadows */
|
|
25
|
-
--drawer-shadow-bottom: 0 -10px 60px hsl(0 0% 0% / 0.12), 0 -4px 20px hsl(0 0% 0% / 0.08);
|
|
26
|
-
--drawer-shadow-top: 0 10px 60px hsl(0 0% 0% / 0.12), 0 4px 20px hsl(0 0% 0% / 0.08);
|
|
27
|
-
--drawer-shadow-right: -10px 0 60px hsl(0 0% 0% / 0.12), -4px 0 20px hsl(0 0% 0% / 0.08);
|
|
28
|
-
--drawer-shadow-left: 10px 0 60px hsl(0 0% 0% / 0.12), 4px 0 20px hsl(0 0% 0% / 0.08);
|
|
29
|
-
--drawer-shadow-modal: 0 25px 50px -12px hsl(0 0% 0% / 0.25);
|
|
30
|
-
|
|
31
|
-
/* Animation */
|
|
32
|
-
--drawer-duration: 0.5s;
|
|
33
|
-
--drawer-duration-close: 0.35s;
|
|
34
|
-
--drawer-ease: cubic-bezier(0.32, 0.72, 0, 1);
|
|
35
|
-
|
|
36
|
-
/* Nesting effects */
|
|
37
|
-
--drawer-nested-scale: 0.94;
|
|
38
|
-
--drawer-nested-offset: 20px;
|
|
39
|
-
--drawer-nested-brightness: 0.92;
|
|
40
|
-
--drawer-nested-backdrop: hsl(0 0% 0% / 0.15);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
@media (prefers-color-scheme: dark) {
|
|
44
|
-
:root {
|
|
45
|
-
--drawer-bg: hsl(0 0% 12%);
|
|
46
|
-
--drawer-handle-bg: hsl(0 0% 35%);
|
|
47
|
-
--drawer-handle-bg-hover: hsl(0 0% 50%);
|
|
48
|
-
--drawer-shadow-bottom: 0 -10px 60px hsl(0 0% 0% / 0.4), 0 -4px 20px hsl(0 0% 0% / 0.3);
|
|
49
|
-
--drawer-shadow-top: 0 10px 60px hsl(0 0% 0% / 0.4), 0 4px 20px hsl(0 0% 0% / 0.3);
|
|
50
|
-
--drawer-shadow-right: -10px 0 60px hsl(0 0% 0% / 0.4), -4px 0 20px hsl(0 0% 0% / 0.3);
|
|
51
|
-
--drawer-shadow-left: 10px 0 60px hsl(0 0% 0% / 0.4), 4px 0 20px hsl(0 0% 0% / 0.3);
|
|
52
|
-
--drawer-shadow-modal: 0 25px 50px -12px hsl(0 0% 0% / 0.5);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* Background scale effect */
|
|
57
|
-
body {
|
|
58
|
-
transition: scale var(--drawer-duration) var(--drawer-ease), border-radius var(--drawer-duration) var(--drawer-ease);
|
|
59
|
-
transform-origin: center top;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
body:has(.drawer[open]) {
|
|
63
|
-
overflow: hidden;
|
|
64
|
-
scale: var(--drawer-nested-scale);
|
|
65
|
-
border-radius: var(--drawer-radius);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/* Base drawer */
|
|
69
|
-
.drawer {
|
|
70
|
-
border: none;
|
|
71
|
-
padding: 0;
|
|
72
|
-
margin: 0;
|
|
73
|
-
max-width: 100%;
|
|
74
|
-
max-height: 100%;
|
|
75
|
-
position: fixed;
|
|
76
|
-
background: var(--drawer-bg);
|
|
77
|
-
overflow: hidden;
|
|
78
|
-
opacity: 0;
|
|
79
|
-
transition:
|
|
80
|
-
display var(--drawer-duration-close) allow-discrete,
|
|
81
|
-
overlay var(--drawer-duration-close) allow-discrete,
|
|
82
|
-
translate var(--drawer-duration-close) var(--drawer-ease),
|
|
83
|
-
scale var(--drawer-duration-close) var(--drawer-ease),
|
|
84
|
-
filter var(--drawer-duration-close) ease,
|
|
85
|
-
opacity var(--drawer-duration-close) ease;
|
|
86
|
-
|
|
87
|
-
/* Default: bottom */
|
|
88
|
-
--_translate-closed: 0 100%;
|
|
89
|
-
--_border-radius: var(--drawer-radius) var(--drawer-radius) 0 0;
|
|
90
|
-
inset: auto 0 0 0;
|
|
91
|
-
margin-inline: auto;
|
|
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);
|
|
96
|
-
border-radius: var(--drawer-border-radius, var(--_border-radius));
|
|
97
|
-
box-shadow: var(--drawer-shadow-bottom);
|
|
98
|
-
translate: var(--_translate-closed);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.drawer::backdrop {
|
|
102
|
-
background: var(--drawer-backdrop);
|
|
103
|
-
opacity: 0;
|
|
104
|
-
backdrop-filter: blur(var(--drawer-backdrop-blur));
|
|
105
|
-
-webkit-backdrop-filter: blur(var(--drawer-backdrop-blur));
|
|
106
|
-
transition:
|
|
107
|
-
display var(--drawer-duration-close) allow-discrete,
|
|
108
|
-
overlay var(--drawer-duration-close) allow-discrete,
|
|
109
|
-
opacity var(--drawer-duration-close) ease;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.drawer[open] {
|
|
113
|
-
opacity: 1;
|
|
114
|
-
translate: 0 0;
|
|
115
|
-
transition:
|
|
116
|
-
display var(--drawer-duration) allow-discrete,
|
|
117
|
-
overlay var(--drawer-duration) allow-discrete,
|
|
118
|
-
translate var(--drawer-duration) var(--drawer-ease),
|
|
119
|
-
scale var(--drawer-duration) var(--drawer-ease),
|
|
120
|
-
filter var(--drawer-duration) ease,
|
|
121
|
-
opacity 0.15s ease;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.drawer[open]::backdrop {
|
|
125
|
-
opacity: 1;
|
|
126
|
-
transition: display var(--drawer-duration) allow-discrete, overlay var(--drawer-duration) allow-discrete, opacity 0.2s ease;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
@starting-style {
|
|
130
|
-
.drawer[open] { opacity: 0; translate: var(--_translate-closed); }
|
|
131
|
-
.drawer[open]::backdrop { opacity: 0; }
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/* ===== DIRECTIONS ===== */
|
|
135
|
-
|
|
136
|
-
/* Right */
|
|
137
|
-
.drawer[data-direction="right"] {
|
|
138
|
-
--_translate-closed: 100% 0;
|
|
139
|
-
--_border-radius: var(--drawer-radius) 0 0 var(--drawer-radius);
|
|
140
|
-
inset: 0 0 0 auto;
|
|
141
|
-
margin: 0;
|
|
142
|
-
width: var(--drawer-width, 500px);
|
|
143
|
-
max-width: var(--drawer-max-width, 90%);
|
|
144
|
-
height: var(--drawer-height, 100dvh);
|
|
145
|
-
max-height: 100dvh;
|
|
146
|
-
box-shadow: var(--drawer-shadow-right);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/* Left */
|
|
150
|
-
.drawer[data-direction="left"] {
|
|
151
|
-
--_translate-closed: -100% 0;
|
|
152
|
-
--_border-radius: 0 var(--drawer-radius) var(--drawer-radius) 0;
|
|
153
|
-
inset: 0 auto 0 0;
|
|
154
|
-
margin: 0;
|
|
155
|
-
width: var(--drawer-width, 500px);
|
|
156
|
-
max-width: var(--drawer-max-width, 90%);
|
|
157
|
-
height: var(--drawer-height, 100dvh);
|
|
158
|
-
max-height: 100dvh;
|
|
159
|
-
box-shadow: var(--drawer-shadow-left);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/* Top */
|
|
163
|
-
.drawer[data-direction="top"] {
|
|
164
|
-
--_translate-closed: 0 -100%;
|
|
165
|
-
--_border-radius: 0 0 var(--drawer-radius) var(--drawer-radius);
|
|
166
|
-
inset: 0 0 auto 0;
|
|
167
|
-
margin-inline: auto;
|
|
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);
|
|
172
|
-
box-shadow: var(--drawer-shadow-top);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/* Modal (centered) */
|
|
176
|
-
.drawer[data-direction="modal"] {
|
|
177
|
-
--_translate-closed: 0 0;
|
|
178
|
-
--_border-radius: var(--drawer-radius);
|
|
179
|
-
inset: 0;
|
|
180
|
-
margin: auto;
|
|
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);
|
|
185
|
-
box-shadow: var(--drawer-shadow-modal);
|
|
186
|
-
scale: var(--drawer-nested-scale);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.drawer[data-direction="modal"][open] {
|
|
190
|
-
scale: 1;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
@starting-style {
|
|
194
|
-
.drawer[data-direction="modal"][open] {
|
|
195
|
-
scale: var(--drawer-nested-scale);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/* ===== AUTO-NESTING (up to 5 levels) ===== */
|
|
200
|
-
/* Uses sibling combinators to count open drawers */
|
|
201
|
-
|
|
202
|
-
/* 1+ open drawers after */
|
|
203
|
-
.drawer[open]:has(~ .drawer[open]) {
|
|
204
|
-
scale: var(--drawer-nested-scale);
|
|
205
|
-
translate: 0 calc(-1 * var(--drawer-nested-offset));
|
|
206
|
-
border-radius: var(--drawer-radius);
|
|
207
|
-
filter: brightness(var(--drawer-nested-brightness));
|
|
208
|
-
pointer-events: none;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/* 2+ open drawers after */
|
|
212
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open]) {
|
|
213
|
-
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
214
|
-
translate: 0 calc(-2 * var(--drawer-nested-offset));
|
|
215
|
-
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/* 3+ open drawers after */
|
|
219
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
220
|
-
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
221
|
-
translate: 0 calc(-3 * var(--drawer-nested-offset));
|
|
222
|
-
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/* 4+ open drawers after */
|
|
226
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
227
|
-
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
228
|
-
translate: 0 calc(-4 * var(--drawer-nested-offset));
|
|
229
|
-
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/* 5+ open drawers after */
|
|
233
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
234
|
-
scale: calc(var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale) * var(--drawer-nested-scale));
|
|
235
|
-
translate: 0 calc(-5 * var(--drawer-nested-offset));
|
|
236
|
-
filter: brightness(calc(var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness) * var(--drawer-nested-brightness)));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/* Lighter backdrop for stacked drawers */
|
|
240
|
-
.drawer[open] ~ .drawer[open]::backdrop {
|
|
241
|
-
background: var(--drawer-nested-backdrop);
|
|
242
|
-
backdrop-filter: none;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/* Handle */
|
|
246
|
-
.drawer-handle {
|
|
247
|
-
display: flex;
|
|
248
|
-
justify-content: center;
|
|
249
|
-
padding-block: var(--drawer-handle-padding-block);
|
|
250
|
-
padding-inline: var(--drawer-handle-padding-inline);
|
|
251
|
-
cursor: grab;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
.drawer-handle::before {
|
|
255
|
-
content: '';
|
|
256
|
-
width: var(--drawer-handle-width);
|
|
257
|
-
height: var(--drawer-handle-height);
|
|
258
|
-
background: var(--drawer-handle-bg);
|
|
259
|
-
border-radius: 100px;
|
|
260
|
-
transition: width 0.2s var(--drawer-ease), height 0.2s var(--drawer-ease), background 0.2s ease;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.drawer-handle:hover::before {
|
|
264
|
-
width: var(--drawer-handle-width-hover);
|
|
265
|
-
background: var(--drawer-handle-bg-hover);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/* Vertical handle for left/right drawers */
|
|
269
|
-
.drawer[data-direction="left"] .drawer-handle,
|
|
270
|
-
.drawer[data-direction="right"] .drawer-handle {
|
|
271
|
-
flex-direction: column;
|
|
272
|
-
align-items: center;
|
|
273
|
-
justify-content: center;
|
|
274
|
-
padding-block: var(--drawer-handle-padding-inline);
|
|
275
|
-
padding-inline: var(--drawer-handle-padding-block);
|
|
276
|
-
height: 100%;
|
|
277
|
-
position: absolute;
|
|
278
|
-
top: 0;
|
|
279
|
-
writing-mode: vertical-lr;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
.drawer[data-direction="left"] .drawer-handle { right: 0; }
|
|
283
|
-
.drawer[data-direction="right"] .drawer-handle { left: 0; }
|
|
284
|
-
|
|
285
|
-
.drawer[data-direction="left"] .drawer-handle::before,
|
|
286
|
-
.drawer[data-direction="right"] .drawer-handle::before {
|
|
287
|
-
width: var(--drawer-handle-height);
|
|
288
|
-
height: var(--drawer-handle-width);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
.drawer[data-direction="left"] .drawer-handle:hover::before,
|
|
292
|
-
.drawer[data-direction="right"] .drawer-handle:hover::before {
|
|
293
|
-
width: var(--drawer-handle-height);
|
|
294
|
-
height: var(--drawer-handle-width-hover);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/* Content - structural only, no opinionated padding */
|
|
298
|
-
.drawer-content {
|
|
299
|
-
overflow-x: hidden;
|
|
300
|
-
overflow-y: auto;
|
|
301
|
-
overscroll-behavior: contain;
|
|
302
|
-
flex: 1;
|
|
303
|
-
min-height: 0;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/* Content sizing for directions */
|
|
307
|
-
.drawer[data-direction="left"] .drawer-content,
|
|
308
|
-
.drawer[data-direction="right"] .drawer-content {
|
|
309
|
-
height: 100%;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/* Reduced motion */
|
|
313
|
-
@media (prefers-reduced-motion: reduce) {
|
|
314
|
-
*, *::before, *::after {
|
|
315
|
-
transition-duration: 0.01ms !important;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
body:has(.drawer[open]) {
|
|
319
|
-
scale: 1;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.drawer[open]:has(~ .drawer[open]),
|
|
323
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open]),
|
|
324
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),
|
|
325
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]),
|
|
326
|
-
.drawer[open]:has(~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open] ~ .drawer[open]) {
|
|
327
|
-
scale: 1;
|
|
328
|
-
translate: 0 0;
|
|
329
|
-
filter: none;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
/*# sourceMappingURL=observer-QD6bSdOu.css.map*/
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|