# react-native-safe-popover

> A faithful JS-only imitation of UIKit's UIPopoverPresentationController, which respects the safe area, to React Native.

Latest version **1.1.0** (published 2021-04-19) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-native-safe-popover
pnpm add react-native-safe-popover
yarn add react-native-safe-popover
bun add react-native-safe-popover
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.0 |
| Published | 2021-04-19 |
| First published | 2020-04-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 263.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 16 |
| Author | Jamie Birch |
| Maintainers | shirakaba |
| Keywords | react-native, ios, android |

## Links

- npm: https://www.npmjs.com/package/react-native-safe-popover
- Repository: https://github.com/shirakaba/react-native-safe-popover
- Homepage: https://github.com/shirakaba/react-native-safe-popover#readme
- Issues: https://github.com/shirakaba/react-native-safe-popover/issues
- npm.io page: https://npm.io/package/react-native-safe-popover

## Alternatives

- [@sindresorhus/slugify](https://npm.io/package/@sindresorhus/slugify.md) — 3.7M weekly downloads
- [solid-js](https://npm.io/package/solid-js.md) — 2.7M weekly downloads
- [expo-glass-effect](https://npm.io/package/expo-glass-effect.md) — 2.5M weekly downloads
- [nanoassert](https://npm.io/package/nanoassert.md) — 780.8K weekly downloads
- [@ffmpeg/ffmpeg](https://npm.io/package/@ffmpeg/ffmpeg.md) — 529.5K weekly downloads

## Recent versions

- 1.1.0 (latest) — 2021-04-19
- 1.0.1 — 2021-04-19
- 0.2.0 — 2020-04-16
- 0.1.2 — 2020-04-13
- 0.1.1 — 2020-04-13
- 0.1.0 — 2020-04-13

## README

# react-native-safe-popover

A faithful JS-only imitation of UIKit's UIPopoverPresentationController, which respects the safe area, to React Native.

## Installation

```sh
npm install react-native-safe-popover
# or
yarn add react-native-safe-popover
```

## Appearance

<table>
    <tbody>
        <tr>
            <td align="center" valign="middle">
                <img width="200px" src="/github/bottom.png"/>
            </td>
            <td align="center" valign="middle">
                <img width="200px" src="/github/right.png"/>
            </td>
            <td align="center" valign="middle">
                <img width="200px" src="/github/top-left.png"/>
            </td>
        </tr>
        <tr>
            <td align="center" valign="middle">
                Bottom (fits)
            </td>
            <td align="center" valign="middle">
                Right (fits)
            </td>
            <td align="center" valign="middle">
                Top-left (respects 10px margins)
            </td>
        </tr>
    </tbody>
</table>

## Usage

* As this is an imitation of [UIPopoverPresentationController](https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller), the APIs are generally modelled on those of it.
* SafePopover is nested within a full-screen modal, and so will have access to the entire screen area regardless of where you place it into the view hierarchy.
* When SafePopover appears, it appears over a backdrop, which by default is `rgba(0,0,0,0.25)` (as configured by the `backdropColor` prop), but you could make it totally transparent if preferred.
* It supports the props exposed in `src/Popover.tsx` by the interface `PopoverProps`; read those for full details on how you can configure SafePopover.
* You can specify the preferred size for the popover content via the `preferredWidth` and `preferredHeight` props. You can think of these as equivalent to `maxWidth` and `maxHeight` in CSS.
* Given a source rectangle to "pop" out of, it calculates the optimal position to place the popover content, and thus also the orientation for the arrow.
* Through the `permittedArrowDirections` prop, you can specify your order of preference for the orientation of the arrow, and thus the placement of the popover content. You can force the content to always be placed above the rectangle by specifying `permittedArrowDirections={[PopoverArrowDirection.down]}`.
* If no position satisfies the constraints, it fills all available space and omits the arrow entirely (I think - I haven't bothered testing it). I think this could only realistically occur by setting silly arrow sizes.
* **Does it work in both portrait and landscape orientations?** Yes. Note that the width and height of the popover content do always mean width and height – they don't swap between orientations. So if your popover content is tall and thin in portrait mode, it'll be tall and thin on landscape mode too – not short and wide.
* **Does it handle rotation?** Sometimes, sometimes not. At least on iOS, it partially depends on whether you're using a simulator or a real device. I found that this is a limitation of `react-native-safe-area-context` – it doesn't provide the edge insets soon enough for us to apply them.
* **How do you show it?** Toggle its `modalVisible` property to `true`.
* **How do you dismiss it?** Toggle its `modalVisible` property to `false`. SafePopover exposes an `onBackdropPress` prop in case you want to toggle its `modalVisible` property to `false` upon the user pressing the backdrop.

```tsx
import SafePopover from "react-native-safe-popover";

export function Example(targetRect: { x: number, y: number, height: number, width: number }) {
    const [popupVisible, setPopupVisible] = React.useState(false);
    const { x, y, height, width } = targetRect;

    function onBackdropPress(): void {
        setPopupVisible(false);
    }

    return (
        <SafePopover
            animationType={"fade"}
            sourceRectHeight={height}
            sourceRectWidth={width}
            sourceRectX={x}
            sourceRectY={y}
            modalVisible={popupVisible}
            onBackdropPress={onBackdropPress}
            canOverlapSourceViewRect={false}
        >
            <Text style={{ padding: 8 }}>I'm the content of this popover!</Text>
        </SafePopover>
    );
}
```

## License

MIT

---
_Source: https://npm.io/package/react-native-safe-popover · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
