npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-navigation-popover

v1.1.1

Published

A <Popover /> component for react-native

Downloads

5

Readme

react-native-popover-view

npm version npm version npm licence

This allows the popover view from react-native-popover-view to be used with React Navigation, just like the Stack Navigator, Drawer Navigator, and others.

It works by modifying the stack navigator to show the child views in a popover if desired, which is great for making your app adaptable to tablets, where full-screen views in a stack can be a bit much.

See the documentation for react-native-popover-view for details on how the Popover component itself works.

This project is not officially affiliated with React Navigation, but integrates well and borrows code from react-navigation-stack. Thanks to all the guys at React Navigation for all the work they do.

Table of Contents

Demo App

You can play around with the various features using the Expo test app. Source Code: react-native-popover-view-test-app

Installation

npm i react-navigation-popover

or

yarn add react-navigation-popover

Usage with React Navigation

Support

  • react-navigation-popover v1.1.x supports react-navigation v3.0.0 and forwards
  • react-navigation-popover v1.0.x supports react-navigation v2.12.0 to v2.14.2
  • For older versions of react-navigation, instead install react-native-popover-view v1.0.5 or ealier, and use the documentation at that repository for the corresponding tag

If react-navigation changes in a future versions and breaks compatibility with this library, please open an issue.

Basic Setup

1) Change createStackNavigator to createPopoverStackNavigator

createPopoverStackNavigator is a drop-in replacement for react-navigation's createStackNavigator. It assumes the first view in your routeConfigMap is the base view, and every other view should be shown in a Popover when the showInPopover prop is true (see step #2). You can pass a few (optional) per-screen options through your routeConfigMap or globally through your stackConfig:

Option | Type | Default | Description ----------- | ----------------- | ---------------------- | -------------- placement | PLACEMENT_OPTIONS | PLACEMENT_OPTIONS.AUTO | Passed through to Popover. contentContainerStyle | number | {width: 380} | The style for the internal view that wraps the Popover. showInModal | boolean | true | Passed through to Popover. If you want to stack multiple Popover's, only the bottom one can be shown in a Modal on iOS. showBackground | boolean | true | Passed through to Popover arrowStyle | object | {} | Passed through to Popover popoverStyle | object | {} | Passed through to Popover animationConfig | object | | Passed through to Popover verticalOffset | number | 0 | Passed through to Popover

Note: If you pass a value through the stackConfig, and pass the same option for an individual screen, the value passed for the screen overrides.

Example:

import createPopoverStackNavigator from 'react-navigation-popover';

let stack = createPopoverStackNavigator({
  BaseView: {
    screen: BaseView,
    navigationOptions: {
      title: 'BaseView',
      ...otherOptions
    }
  },
  ModalView: {
    screen: ModalView,
    navigationOptions: {
      title: 'ModalView',
      ...otherOptions // You'll probably want to pass in your header style's here
    },
    popoverOptions: {
      placement: Popover.PLACEMENT_OPTIONS.BOTTOM,
      showBackground: true // Remember: this overrides the global popoverOptions passed in below
    }
  }
}, 
{
  mode: 'modal',
  popoverOptions: {
    showBackground: false,
    contentContainerStyle: {
      width: 500,
      ...otherStyles // These can be any styles you'd normally apply to a view
    }
  }
});

2) Define when Popover should be shown

By default, views will be shown in a Popover view on tablets, and normally on phones. To override this behavior, you can pass the showInPopover option in the screenProps to the class returned by createPopoverStackNavigator:

let Stack = createPopoverStackNavigator(...);
...
  render() {
    let smallScreen = this.props.width < 500;
    return <Stack screenProps={{ showInPopover: !smallScreen }} />;
  }

This sort of width-based test is needed if your app can be launched in split-screen mode on tablets, because the default value is always true on tablets regardless of the actual display width of your app.

3) (Optional) Set Popover Source

There are several ways to make sure the Popover shows from the button that triggered it:

I. (Recommended) Register Refs for Views

You can register the button as the source of the Popover for a particular route. Check out this example:

We first register the ref for a view:

<TouchableHighlight ref={ref => createPopoverStackNavigator.registerRefForView(ref, 'View1')} {...otherProps} />

Then, if View1 is a route name in a createPopoverStackNavigator...

import View1 from './views/View1';
...
let stack = createPopoverStackNavigator({
  View1: {
    screen: View1,
    navigationOptions: navOptions
  }
}, options);

When we navigate to the view, the Popover will originate from the associated TouchableHighlight:

this.props.navigation.navigate('View1', params);

You can register any type of view, not only a TouchableHighlight, and the Popover will point to the outside of the bounds of that view.

Note: The map is stored statically, so you cannot register two views with the same name, even if they are in different createPopoverStackNavigator's.

II. Send showFromView

If you need even more fine-grained control, such as wanting to open the same child but have it originate from different views at different times, you can pass the showFromView param in your navigate call:

this.props.navigation.navigate('View1', {showFromView: this.storedView});

where this.storedView is a ref of a component (obtained through a ref callback).

III. Use a Custum Rect

See "Show Popover from custom rect" in the Advanced Usage section below.

Full Example

import React, { Component } from 'react';
import createPopoverStackNavigator from 'react-navigation-popover';
import { MoreHeaderView, ExtraInfoView, MoreOptionView } from './myOtherViews';
import { Colors } from './Colors';
import DeviceInfo from 'react-native-device-info';

class MoreView extends Component {
  render() {
    return (
      <View style={styles.viewStyle}>
        <MoreHeaderView />
        <View>
          <TouchableHighlight
            style={styles.buttonStyle} 
            ref={touchable => createPopoverStackNavigator.registerRefForView(touchable, 'About')} 
            onPress={() => this.props.navigation.navigate('About')}>
            <Text>About the App</Text>
          </TouchableHighlight>
          <TouchableHighlight
            style={styles.buttonStyle} 
            ref={touchable => createPopoverStackNavigator.registerRefForView(touchable, 'Settings')} 
            onPress={() => this.props.navigation.navigate('Settings')}>
            <Text>Content Settings</Text>
          </TouchableHighlight>
          <TouchableHighlight
            style={styles.buttonStyle} 
            ref={touchable => createPopoverStackNavigator.registerRefForView(touchable, 'Account')} 
            onPress={() => this.props.navigation.navigate('Account')}>
            <Text>Account Details</Text>
          </TouchableHighlight>
        </View>
        <ExtraInfoView />
      </View>
    )
  }
}

let MoreStack = createPopoverStackNavigator({
  MoreView: {
    screen: MoreView,
    navigationOptions: {title: 'More'}
  },
  About: {
    screen: AboutView,
    navigationOptions: {title: 'About', ...styles.headerStyle}
  },
  Settings: {
    screen: SettingsView,
    navigationOptions: {title: 'Settings', ...styles.headerStyle}
  },
  Account: {
    screen: AccountView,
    navigationOptions: {title: 'About', ...styles.headerStyle}
  },
}, {
  headerMode: 'screen'
});

export default class MoreStackWrapper extends Component {
  state = { width: DeviceInfo.getInitialWidth() }
  render() {
    return (
      <View
        style={styles.fullScreenViewStyle} 
        onLayout={evt => this.setState({width: evt.nativeEvent.layout.width})}>
        <MoreStack screenProps={{ showInPopover: DeviceInfo.isTablet() && this.state.width > 500 }} />
      </View>
    );
  }
}

let styles = {
  buttonStyle: {
    width: 100,
    height: 40,
    marginBottom: 50
  },
  viewStyle: {
    alignItems: 'center'
  },
  headerStyle: {
    headerStyle: {
      backgroundColor: Colors.backgroundColor
    },
    headerTintColor: Colors.tintColor,
    headerTitleStyle: {
      color: Colors.headerTextColor
    }
  },
  fullScreenViewStyle: {
    position: 'absolute',
    left: 0,
    right: 0,
    top: 0,
    bottom: 0
  }
}

Advanced Usage

Custumize Display Area used by Popovers

By default, Popover's will query RN's SafeAreaView to get the allowed display area on the device, and then add a 10pt padding around all the edges, and set this as the display area. If you want to inject a custum display area to a specific popover, you can do so either through the createPopoverStackNavigator's RouteConfigs or through params in the navigate call:

let Stack = createPopoverStackNavigator({
  View1: {
    screen: 'View1',
    popoverOptions: {
      displayArea: new Rect(0, 0, 50, 50)
    },
    ...otherOptions
  },
  ...otherViews
}, options);

OR

this.props.navigation.navigate('View1', {displayArea: new Rect(0, 0, 50,50)});

Show Popover from custom rect

There may be situations in which you want to show a Popover with a custom fromRect, not tied to any view. Instead of using createPopoverStackNavigator.registerRefForView, you can pass in a custom fromRect as params to the navigate() call. For example:

import { Rect } from 'react-navigation-popover';
...
  this.props.navigation.navigate('NextView', {fromRect: new Rect(10, 10, 40, 20), ...otherParams});

If the rect uses variables that could change when the display area changes, you should instead use calculateRect, and pass in a function that will return the rect. For example, if your popover originates from a button that is always centered, regardless of screen size, you could use the following:

import { Rect } from 'react-navigation-popover';
...
  this.props.navigation.navigate('NextView', {calculateRect: () => new Rect(this.state.width/2 - 20, 50, 40, 20), ...otherParams});

Now, if your app is put into split-screen mode while the popover is still showing, calculateRect will be called again, and the popover will shift to point to the new rect.

Contributing

Pull requests are welcome; if you find that you are having to bend over backwards to make this work for you, feel free to open an issue or PR! Of course, try to keep the same coding style if possible and I'll try to get back to you as soon as I can.


MIT Licensed