{"_id":"@carlosmedina06/react-native-bottom-sheet","_rev":"2-2cda70cd0b2cf6521e009ece8123b069","name":"@carlosmedina06/react-native-bottom-sheet","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@carlosmedina06/react-native-bottom-sheet","version":"1.0.0","keywords":["react-native","bottom-sheet","draggable","reanimated","gesture-handler"],"license":"MIT","_id":"@carlosmedina06/react-native-bottom-sheet@1.0.0","maintainers":[{"name":"carlosmedina06","email":"carlosmedinadev0610@gmail.com"}],"homepage":"https://github.com/carlosmedina06/react-native-bottom-sheet#readme","bugs":{"url":"https://github.com/carlosmedina06/react-native-bottom-sheet/issues"},"dist":{"shasum":"f8db50a029ce5412d2b67855761c024e51728735","tarball":"https://registry.npmjs.org/@carlosmedina06/react-native-bottom-sheet/-/react-native-bottom-sheet-1.0.0.tgz","fileCount":26,"integrity":"sha512-kp56Ik0CkylGEqJmbGMC9ZGLC5BQm9l6hSUGQ0nrq06CQ8NaqsE4wulHXR+5aHiLON7qdUlKN2LDPF5OZrEjXg==","signatures":[{"sig":"MEUCIQDe7BkW7LHieHCy8afFIDWorRZQEI58V95X6Zic1ehgAgIgXaXNDkunPerGrSm/pQm3FSVNQr9g51PaOIQ5P4IKPR8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47887},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"e90b2256126deaaa518b6ddda8630e80e51b15bf","scripts":{"lint":"eslint \"src/**/*.{ts,tsx}\" --quiet","build":"tsc -p tsconfig.json","prepublishOnly":"npm run lint && npm run build"},"_npmUser":{"name":"carlosmedina06","email":"carlosmedinadev0610@gmail.com"},"repository":{"url":"git+https://github.com/carlosmedina06/react-native-bottom-sheet.git","type":"git"},"_npmVersion":"10.9.3","description":"Draggable bottom sheet for React Native with handle-only drag and fit-content mode","directories":{},"_nodeVersion":"22.18.0","_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","eslint":"^9.39.1","typescript":"~5.9.0","@types/react":"^18.0.0","react-native":">=0.70.0","typescript-eslint":"^8.50.1","eslint-config-expo":"~10.0.0","@types/react-native":"^0.72.0","eslint-plugin-react":"^7.37.5","eslint-plugin-import":"^2.32.0","eslint-config-prettier":"^10.1.8","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-prettier":"^5.5.4","react-native-reanimated":">=3.0.0","@typescript-eslint/parser":"^8.49.0","eslint-plugin-react-hooks":"^7.0.1","eslint-plugin-react-refresh":"^0.4.24","react-native-gesture-handler":">=2.0.0","react-native-safe-area-context":">=4.0.0","@typescript-eslint/eslint-plugin":"^8.49.0"},"peerDependencies":{"react":">=18.0.0","react-native":">=0.70.0","react-native-reanimated":">=3.0.0","react-native-gesture-handler":">=2.0.0","react-native-safe-area-context":">=4.0.0","react-native-keyboard-controller":">=1.0.0"},"peerDependenciesMeta":{"react-native-safe-area-context":{"optional":true},"react-native-keyboard-controller":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/react-native-bottom-sheet_1.0.0_1772398711521_0.3114334632807432","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@carlosmedina06/react-native-bottom-sheet","version":"1.0.1","description":"Draggable bottom sheet for React Native with handle-only drag and fit-content mode","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.json","lint":"eslint \"src/**/*.{ts,tsx}\" --quiet","test":"jest","test:watch":"jest --watch","prepublishOnly":"npm run lint && npm run build"},"peerDependencies":{"react":">=18.0.0","react-native":">=0.70.0","react-native-keyboard-controller":">=1.0.0","react-native-reanimated":">=3.0.0","react-native-gesture-handler":">=2.0.0","react-native-safe-area-context":">=4.0.0"},"peerDependenciesMeta":{"react-native-safe-area-context":{"optional":true},"react-native-keyboard-controller":{"optional":true}},"devDependencies":{"@testing-library/react-native":"^12.4.0","@types/jest":"^29.5.0","jest":"^29.7.0","react-test-renderer":"^18.0.0","ts-jest":"^29.2.0","@types/react":"^18.0.0","@types/react-native":"^0.72.0","react":"^18.0.0","react-native":">=0.70.0","react-native-gesture-handler":">=2.0.0","react-native-reanimated":">=3.0.0","react-native-safe-area-context":">=4.0.0","typescript":"~5.9.0","typescript-eslint":"^8.50.1","eslint":"^9.39.1","eslint-config-expo":"~10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-prettier":"^5.5.4","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^7.0.1","eslint-plugin-react-refresh":"^0.4.24","@typescript-eslint/eslint-plugin":"^8.49.0","@typescript-eslint/parser":"^8.49.0"},"keywords":["react-native","bottom-sheet","draggable","reanimated","gesture-handler"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/carlosmedina06/react-native-bottom-sheet.git"},"bugs":{"url":"https://github.com/carlosmedina06/react-native-bottom-sheet/issues"},"homepage":"https://github.com/carlosmedina06/react-native-bottom-sheet#readme","_id":"@carlosmedina06/react-native-bottom-sheet@1.0.1","gitHead":"8f69b2315ea6d1dfd5a81bb271a98dfb2e2c5d98","_nodeVersion":"22.18.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-IdTMc7I/UombJAf3kbuMPU6RP3LetAzAqvyYo3vOxS6dT/J/Qg/z3b76iaLwl0kuAUxAqm+4hoAyYLf4WQ1StA==","shasum":"c8b87cf850b5162e3d1657a79977fbf9d934889f","tarball":"https://registry.npmjs.org/@carlosmedina06/react-native-bottom-sheet/-/react-native-bottom-sheet-1.0.1.tgz","fileCount":27,"unpackedSize":52916,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCZTLAAcdsHTp1xzHalzUaYV+B2PaVmHNHZF3NbNnYrVgIhAL16YthE7JiAU1OIg7euoc51yz6Nhy7mG56oVy3otPk7"}]},"_npmUser":{"name":"carlosmedina06","email":"carlosmedinadev0610@gmail.com"},"directories":{},"maintainers":[{"name":"carlosmedina06","email":"carlosmedinadev0610@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-native-bottom-sheet_1.0.1_1772406737593_0.5117164473564388"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-01T20:58:31.402Z","modified":"2026-03-01T23:12:17.835Z","1.0.0":"2026-03-01T20:58:31.679Z","1.0.1":"2026-03-01T23:12:17.733Z"},"bugs":{"url":"https://github.com/carlosmedina06/react-native-bottom-sheet/issues"},"license":"MIT","homepage":"https://github.com/carlosmedina06/react-native-bottom-sheet#readme","keywords":["react-native","bottom-sheet","draggable","reanimated","gesture-handler"],"repository":{"type":"git","url":"git+https://github.com/carlosmedina06/react-native-bottom-sheet.git"},"description":"Draggable bottom sheet for React Native with handle-only drag and fit-content mode","maintainers":[{"name":"carlosmedina06","email":"carlosmedinadev0610@gmail.com"}],"readme":"# React Native Bottom Sheet\n\n[![npm](https://img.shields.io/badge/npm-@carlosmedina06/react--native--bottom--sheet-CB3837?style=flat-square&logo=npm)](https://www.npmjs.com/package/@carlosmedina06/react-native-bottom-sheet) [![license](https://img.shields.io/npm/l/@carlosmedina06/react-native-bottom-sheet?style=flat-square)](https://www.npmjs.com/package/@carlosmedina06/react-native-bottom-sheet) [![types included](https://img.shields.io/badge/types-included-blue?style=flat-square)](https://www.npmjs.com/package/@carlosmedina06/react-native-bottom-sheet) [![Runs with Expo](https://img.shields.io/badge/Runs%20with%20Expo-4630EB.svg?style=flat-square&logo=EXPO&labelColor=f3f3f3&logoColor=000)](https://expo.io/) [![downloads](https://img.shields.io/npm/dw/@carlosmedina06/react-native-bottom-sheet?style=flat-square)](https://www.npmjs.com/package/@carlosmedina06/react-native-bottom-sheet \"View package on npm\")\n\n[![react-native-reanimated](https://img.shields.io/badge/react--native--reanimated-%3E%3D3.0.0-9E2DD4?style=flat-square)](https://www.npmjs.com/package/react-native-reanimated) [![react-native-gesture-handler](https://img.shields.io/badge/react--native--gesture--handler-%3E%3D2.0.0-3DDC84?style=flat-square)](https://www.npmjs.com/package/react-native-gesture-handler) [![react-native-safe-area-context](https://img.shields.io/badge/react--native--safe--area--context-%3E%3D4.0.0-61DAFB?style=flat-square)](https://www.npmjs.com/package/react-native-safe-area-context) [![react-native-keyboard-controller](https://img.shields.io/badge/react--native--keyboard--controller-%3E%3D1.0.0-FF6B6B?style=flat-square)](https://www.npmjs.com/package/react-native-keyboard-controller)\n\n📱 A draggable bottom sheet for React Native with handle-only drag, fit-content mode, and lifecycle events.\n\n---\n\n## ✨ Features\n\n- 👆 Drag from the top handle only (pill)\n- 📐 `fitContent` to size the sheet to content height\n- 📜 Internal scroll when content exceeds `maxHeight`\n- ❌ Close via backdrop tap, Android back button, or drag\n- 🔄 Lifecycle events: `onOpenStart`, `onOpenEnd`, `onCloseStart`, `onCloseEnd`, `onDrag`\n- 📍 Optional snap points (e.g. `['25%', '50%', '90%']`)\n- ⌨️ Keyboard behavior: `padding`, `height`, or `none`\n- 🛡️ Optional `onCloseRequest` to confirm before closing (e.g. unsaved form)\n- 🎨 Customizable colors, handle, header, footer, and accessibility\n- 📘 Written in TypeScript\n- ⚡ Compatible with Reanimated v3\n- 📱 Compatible with Expo\n\n## 📦 Installation\n\n```bash\nyarn add @carlosmedina06/react-native-bottom-sheet@^1\n```\n\n### 📋 Dependencies\n\nThis library needs these dependencies to be installed in your project before you can use it:\n\n```bash\nyarn add react-native-reanimated react-native-gesture-handler\n```\n\n### 🟢 Using Expo?\n\n```bash\nnpx expo install react-native-reanimated react-native-gesture-handler\n```\n\n### ✅ Requirements\n\n| Type | Dependency | Version | Description |\n|------|-------------|---------|-------------|\n| **Required** | [React](https://www.npmjs.com/package/react) | `>=18.0.0` | Core UI library |\n| **Required** | [React Native](https://www.npmjs.com/package/react-native) | `>=0.70.0` | Mobile framework |\n| **Required** | [react-native-reanimated](https://www.npmjs.com/package/react-native-reanimated) | `>=3.0.0` | Animations & gestures |\n| **Required** | [react-native-gesture-handler](https://www.npmjs.com/package/react-native-gesture-handler) | `>=2.0.0` | Native gesture handling |\n| **Optional** | [react-native-safe-area-context](https://www.npmjs.com/package/react-native-safe-area-context) | `>=4.0.0` | Safe area insets (notch, home indicator) |\n| **Optional** | [react-native-keyboard-controller](https://www.npmjs.com/package/react-native-keyboard-controller) | `>=1.0.0` | Keyboard behavior (e.g. dismiss on sheet close) |\n\n> **ℹ️ OPTIONAL**\n>\n> These dependencies are **not required** for the bottom sheet to work. Install them only if you need the behavior they provide.\n>\n> **react-native-safe-area-context** (`>=4.0.0`) — Use it if you want the sheet to respect safe area insets (notch, home indicator). Follow their [installation instructions](https://github.com/th3rdwave/react-native-safe-area-context#installation).\n>\n> **react-native-keyboard-controller** (`>=1.0.0`) — Use it for improved keyboard handling (e.g. dismiss keyboard when closing the sheet by drag). Follow their [installation instructions](https://github.com/kirillzyusko/react-native-keyboard-controller#installation).\n\n> **ℹ️ INFO**\n>\n> **React Native Gesture Handler v2** needs extra steps to finalize its installation. Please follow their [installation instructions](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation).\n>\n> Please **make sure** to wrap your App with `GestureHandlerRootView` when you've upgraded to React Native Gesture Handler `^2`.\n>\n> **React Native Reanimated v3** needs extra steps to finalize its installation. Please follow their [installation instructions](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started).\n\n**Example — wrap your app with `GestureHandlerRootView`:**\n\n```tsx\nimport { GestureHandlerRootView } from 'react-native-gesture-handler'\n\nexport default function App() {\n  return (\n    <GestureHandlerRootView style={{ flex: 1 }}>\n      {/* Your app content */}\n    </GestureHandlerRootView>\n  )\n}\n```\n\n## 🚀 Usage\n\n```tsx\nimport { useState } from 'react'\nimport { Text, View } from 'react-native'\nimport BottomSheet from '@carlosmedina06/react-native-bottom-sheet'\n\nexport default function Example() {\n  const [open, setOpen] = useState(false)\n\n  return (\n    <BottomSheet\n      open={open}\n      onClose={() => setOpen(false)}\n      fitContent\n      minHeight=\"20%\"\n      maxHeight=\"90%\"\n      onOpenStart={() => console.log('open:start')}\n      onOpenEnd={() => console.log('open:end')}\n      onCloseStart={() => console.log('close:start')}\n      onCloseEnd={() => console.log('close:end')}\n      onDrag={(event) => {\n        // event.progress => 0..1\n      }}\n    >\n      <View>\n        <Text>Content</Text>\n      </View>\n    </BottomSheet>\n  )\n}\n```\n\n## 📚 API\n\n### 📤 Exports\n\n- `default` → `BottomSheet`\n- `type BottomSheetProps`\n- `type BottomSheetDragEvent`\n\n### ⚙️ Props\n\n| Prop | Type | Default | Description |\n|------|------|--------|-------------|\n| `open` | `boolean` | required | Controls sheet visibility |\n| `onClose` | `() => void` | required | Called when close is requested (backdrop, back, or drag) |\n| `onOpen` | `() => void` | `undefined` | Called when opening starts |\n| `onOpenStart` | `() => void` | `undefined` | Called when open transition starts |\n| `onOpenEnd` | `() => void` | `undefined` | Called when open animation ends |\n| `onCloseStart` | `() => void` | `undefined` | Called when close transition starts |\n| `onCloseEnd` | `() => void` | `undefined` | Called when close animation ends |\n| `onDrag` | `(event: BottomSheetDragEvent) => void` | `undefined` | Called on each drag update |\n| `children` | `ReactNode` | required | Sheet content |\n| `minHeight` | `number \\| string` | `220` | Min height (number or `%`) |\n| `maxHeight` | `number \\| string` | 95% of window | Max height (number or `%`) |\n| `fitContent` | `boolean` | `false` | Size to content up to `maxHeight` |\n| `keyboardBehavior` | `'padding' \\| 'height' \\| 'none'` | `'none'` | Keyboard offset behavior |\n| `enablePanDownToClose` | `boolean` | `true` | Allow close by dragging down |\n| `testID` | `string` | `undefined` | Test identifier |\n| `title` | `string \\| ReactNode` | `undefined` | Optional title below handle |\n| `accessibilityLabel` | `string` | `undefined` | A11y label for sheet container |\n| `accessibilityRole` | `AccessibilityRole` | `undefined` | A11y role (e.g. `'dialog'`) |\n| `handleAccessibilityLabel` | `string` | `'Drag to close'` | A11y label for handle |\n| `backdropColor` | `string` | `'rgba(0,0,0,0.4)'` | Backdrop color |\n| `handleColor` | `string` | `'#D1D5DB'` | Handle pill color |\n| `sheetBackgroundColor` | `string` | `'#fff'` | Sheet panel background |\n| `borderTopRadius` | `number` | `12` | Top corner radius |\n| `renderHandle` | `() => ReactNode` | `undefined` | Custom handle; default is pill |\n| `renderHeader` | `() => ReactNode` | `undefined` | Custom header above title |\n| `renderFooter` | `() => ReactNode` | `undefined` | Custom footer below content |\n| `onCloseRequest` | `() => boolean \\| Promise<boolean>` | `undefined` | Called before close; return `false` to prevent close |\n| `snapPoints` | `(number \\| string)[]` | `undefined` | Snap heights (e.g. `['30%', '60%', '100%']`); ignored if `fitContent` is true |\n\n### 📊 BottomSheetDragEvent\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `translateY` | `number` | Current Y translation of the sheet |\n| `height` | `number` | Current visible sheet height |\n| `progress` | `number` | Open progress 0..1 |\n\n## 💡 Examples\n\n**🎨 Custom colors and handle:**\n\n```tsx\n<BottomSheet\n  open={open}\n  onClose={() => setOpen(false)}\n  sheetBackgroundColor=\"#f5f5f5\"\n  handleColor=\"#6366f1\"\n  renderHandle={() => <MyCustomHandle />}\n>\n  {children}\n</BottomSheet>\n```\n\n**🛡️ Prevent close (onCloseRequest):**\n\n```tsx\n<BottomSheet\n  open={open}\n  onClose={() => setOpen(false)}\n  onCloseRequest={async () => {\n    if (hasUnsavedChanges) {\n      const ok = await Alert.alert('Discard changes?', '...', [...])\n      return ok\n    }\n    return true\n  }}\n>\n  {children}\n</BottomSheet>\n```\n\n**📍 Snap points (without fitContent):**\n\n```tsx\n<BottomSheet\n  open={open}\n  onClose={() => setOpen(false)}\n  snapPoints={['25%', '50%', '90%']}\n>\n  {children}\n</BottomSheet>\n```\n\n## 🔀 Event order\n\n- **Open:** `onOpenStart` → `onOpen` → `onOpenEnd`\n- **Close:** if `onCloseRequest` is set, it runs first; close only proceeds when it returns `true`. Then `onCloseStart` → `onCloseEnd`. Without `onCloseRequest`, close runs directly.\n- **Drag:** `onDrag` fires while dragging from the handle.\n\n## ⌨️ Keyboard (iOS)\n\nWith `keyboardBehavior` other than `'none'`:\n\n- **iOS:** The sheet background extends behind the keyboard; content translates up. Closing the sheet by drag also dismisses the keyboard with the close animation.\n- **Android:** The whole sheet moves up with the keyboard. Drag-to-close does not specially dismiss the keyboard.\n\n## 📖 Behavior\n\n- With `fitContent=true`, the sheet height follows content. `snapPoints` is ignored when `fitContent` is true.\n- With `snapPoints` (and no `fitContent`), the sheet snaps to the nearest point on release; if the nearest is the minimum and threshold/velocity is met, it closes.\n- When content is taller than `maxHeight`, internal scroll is enabled.\n- Dragging only works from the top handle (or custom `renderHandle`).\n- Close by gesture uses distance and/or velocity; `onCloseRequest` is respected before closing.\n- Colors and radii for sheet, handle, and backdrop are configurable via props.\n\n## 🤝 Contributing\n\nContributions are welcome. Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, workflow, and code expectations.\n\n## 📄 License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}