{"_id":"@alexapvl/drwr","name":"@alexapvl/drwr","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@alexapvl/drwr","version":"0.1.0","description":"A zero-dependency, framework-agnostic bottom sheet / drawer component","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./style.css":"./dist/style.css"},"sideEffects":["**/*.css"],"keywords":["drawer","sheet","bottom-sheet","modal","mobile","gesture","drag","spring","a11y"],"author":"","license":"MIT","devDependencies":{"tsup":"^8.0.0","typescript":"^5.4.0","vite":"^6.0.0"},"scripts":{"build":"tsup","dev":"vite demo","typecheck":"tsc --noEmit"},"_id":"@alexapvl/drwr@0.1.0","_integrity":"sha512-n9VhCHz/8eD9uc9GEeRr+7ntbN/zKy1Yb0XZ6HT0DQx5orSWcVYiji3sNLZjo8+Zx9jhtzUK3aAbeKFqY7FK+Q==","_resolved":"/private/var/folders/d_/46cq7fw53_v5z03x7_ft8hv80000gn/T/eef97286b7acea091e9f3410ae952616/alexapvl-drwr-0.1.0.tgz","_from":"file:alexapvl-drwr-0.1.0.tgz","_nodeVersion":"25.4.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-n9VhCHz/8eD9uc9GEeRr+7ntbN/zKy1Yb0XZ6HT0DQx5orSWcVYiji3sNLZjo8+Zx9jhtzUK3aAbeKFqY7FK+Q==","shasum":"e454d99f15b11deee18cc76e66ded87b81d3f102","tarball":"https://registry.npmjs.org/@alexapvl/drwr/-/drwr-0.1.0.tgz","fileCount":10,"unpackedSize":157463,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCQV8B/ldq4aAL0b08qmz4aDVMAVf/DeeOetMAv++rUnAIhANwNoCd57Gc3Zpwb2tgrQVNmKEVB1UdwK46SVGgD+m5z"}]},"_npmUser":{"name":"alexapvl","email":"alex.robite@gmail.com"},"directories":{},"maintainers":[{"name":"alexapvl","email":"alex.robite@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/drwr_0.1.0_1779124784179_0.18184982620248613"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-18T17:19:44.082Z","0.1.0":"2026-05-18T17:19:44.327Z","modified":"2026-05-18T17:19:44.506Z"},"maintainers":[{"name":"alexapvl","email":"alex.robite@gmail.com"}],"description":"A zero-dependency, framework-agnostic bottom sheet / drawer component","keywords":["drawer","sheet","bottom-sheet","modal","mobile","gesture","drag","spring","a11y"],"license":"MIT","readme":"# drwr\n\nA zero-dependency, framework-agnostic bottom sheet / drawer component. Vanilla JS + CSS. Works in any project.\n\n## Install\n\n```bash\nnpm install drwr\n```\n\n## Usage\n\n```js\nimport { Sheet } from \"drwr\";\nimport \"drwr/style.css\";\n\nconst sheet = new Sheet(document.getElementById(\"my-sheet\"), {\n  snapPoints: [0, 0.5, 1],\n  defaultSnap: 0,\n  overlay: true,\n  dragHandle: true,\n});\n\nsheet.open();       // open to highest snap\nsheet.open(0.5);    // open to specific snap\nsheet.snapTo(0.5);\nsheet.close();\nsheet.refresh();    // re-measure after dynamic content change\nsheet.destroy();\n```\n\n## Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `snapPoints` | `number[]` | `[0, 1]` | Normalized snap points from 0 to 1 (0 = closed, 1 = max height). Sanitized on input. |\n| `defaultSnap` | `number` | `0` | Initial snap point. Non-zero values open with full state (scroll lock, focus trap, etc). |\n| `overlay` | `boolean` | `true` | Show backdrop overlay |\n| `dragHandle` | `boolean` | `true` | Render a drag handle bar |\n| `damping` | `number` | `30` | Spring damping coefficient |\n| `stiffness` | `number` | `200` | Spring stiffness coefficient |\n| `closeThreshold` | `number` | `0.2` | Fraction of lowest snap below which the sheet closes on release |\n| `topPadding` | `number` | `40` | Space left above the sheet at max height, in px |\n| `width` | `number` | `60` (desktop) / `100` (mobile) | Width as % of viewport |\n| `align` | `\"center\" \\| \"left\" \\| \"right\"` | `\"center\"` | Horizontal alignment |\n| `sidePadding` | `number` | `0` | Minimum side padding in px |\n| `maxWidth` | `number` | `0` | Max width in px (0 = no max) |\n| `dragMode` | `\"handle\" \\| \"sheet\" \\| \"none\"` | `\"sheet\"` | Which part initiates drag |\n| `ariaLabel` | `string` | `\"Sheet\"` | Accessible label for the dialog |\n| `ariaLabelledBy` | `string` | — | ID of labelling element (overrides `ariaLabel`) |\n| `closeOnEscape` | `boolean` | `true` | Close on Escape key |\n| `closeOnOverlayClick` | `boolean` | `true` | Close on overlay click |\n| `trapFocus` | `boolean` | `true` | Trap focus inside the sheet |\n| `modal` | `boolean` | `true` | Set `aria-modal` |\n| `reducedMotion` | `boolean` | `true` | Skip spring animation when user prefers reduced motion |\n| `onOpen` | `() => void` | — | Called when sheet opens |\n| `onClose` | `() => void` | — | Called when sheet closes |\n| `onSnap` | `(point: number) => void` | — | Called when sheet snaps to a point |\n\n## Methods\n\n| Method | Description |\n|--------|-------------|\n| `open(point?)` | Open to the given snap (or highest). |\n| `close()` | Close the sheet. |\n| `snapTo(point)` | Animate to a specific snap point. |\n| `refresh()` | Re-measure content height after dynamic changes. |\n| `setSnapPoints(points)` | Replace snap points (sanitized). |\n| `setLayout({ width?, align?, sidePadding? })` | Update layout at runtime. |\n| `setOptions(opts)` | Merge partial options at runtime. |\n| `destroy()` | Tear down the sheet and restore DOM. |\n\n## Theming\n\nAll visual tokens are exposed as CSS custom properties:\n\n```css\n:root {\n  --drwr-bg: #fff;\n  --drwr-radius: 16px;\n  --drwr-handle-width: 32px;\n  --drwr-handle-height: 4px;\n  --drwr-handle-color: rgba(0, 0, 0, 0.25);\n  --drwr-overlay-color: rgba(0, 0, 0, 0.4);\n  --drwr-shadow: 0 -1px 0 rgba(0, 0, 0, 0.04), 0 -8px 32px rgba(0, 0, 0, 0.12), 0 -24px 60px rgba(0, 0, 0, 0.06);\n  --drwr-border: 1px solid rgba(0, 0, 0, 0.06);\n  --drwr-z-index: 9999;\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-7a481ad9341339b77a31c0b2b0fd1f71"}