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-page-controller

v3.1.0

Published

horizontal, swipeable panes built for react

Downloads

87

Readme

react-page-controller

npm package Follow on Twitter

React-page-controller is a react library for providing views that can be swiped left or right. It was originally built for use in Sancho UI and is inspired by the iOS library of the same name.

Features

  • Built with react-gesture-responder to enable better control over gesture delegation. This means that you can embed gesture based controls within this gesture view (or embed multiple gesture views within eachother) and delegate between them.
  • Configurable. Configure the animation spring, enable mouse support, use child render callbacks, etc.
  • Optional lazy loading.

Install

Install react-page-controller and its peer dependency react-gesture-responder using yarn or npm.

yarn add react-page-controller react-gesture-responder

Basic usage

The gesture view should be provided with a collection of children, each representing a panel. By default, each child will be wrapped in an element wiith the recommended props. If you'd rather render the element yourself, provide a render callback for each child instead.

import Pager from "react-page-controller";

function TabContent() {
  const [index, setIndex] = React.useState(0);
  return (
    <Pager value={index} onRequestChange={i => setIndex(i)}>
      <div>First panel</div>
      <div>Second panel</div>
      <div>Third panel</div>
      {(props, active, load) => <div {...props}>fourth panel</div>}
    </Pager>
  );
}

API

| Name | Type | Default Value | Description | | -------------------- | ----------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------- | | value* | number | { index: number, immediate: boolean } | | The current index to show | | onRequestChange* | (value: number) => void; | | A callback for handling index changes | | lazyLoad | boolean | false | Lazy load pane contents | | enableMouse | boolean | false | By default mouse gestures are not enabled | | enableGestures | boolean | true | By default gestures are enabled | | animationConfig | SpringConfig | { tension: 190, friction: 20, mass: 0.4 } | A react-spring config for animations | | onTerminationRequest | (state) => boolean; | | Optionally prevent parent views from claiming the pan-responder. Useful for embedded gesture views | | onMoveShouldSet | (state, e, suggested) => boolean; | | Optionally override the default onMoveShouldSet behaviour. Useful for embedding multiple gesture views. | | enableScrollLock | boolean | true | Lock all page scrolling when making swiping gestures. This is generally the desired behaviour. |

Imperative API

You can use the imperative API to manually focus the active panel, which is something you'll likely want to do for accessibility reasons.

function TabContent() {
  const [index, setIndex] = React.useState(0);
  const ref = React.useRef();

  function focusCurrentIndex() {
    ref.current.focus();
  }

  return (
    <Pager ref={ref} value={index} onRequestChange={i => setIndex(i)}>
      <div>First panel</div>
      <div>Second panel</div>
      <div>Third panel</div>
    </Pager>
  );
}

Embedding Views

Each Pager exposes the react-gesture-responder onTerminationRequest function which allows you to negotiate between gesture views competing for the responder. Typically, you'll want the child view to prevent the parent from claiming the responder.

<Pager>
  <div>Left parent pane</div>
  <Pager onTerminationRequest={() => false}>
    <div>child pane</div>
    <div>another child</div>
  </Pager>
</Pager>

The logic can become more sophisticated. In the gif at the top of the readme, our parent claims the responder (and prevents the child from stealing it) when showing the first child pane and moving left. The code will look something like this:

const [childIndex, setChildIndex] = React.useState(0);
const [parentIndex, setParentIndex] = React.useState(0);

function onMoveShouldSet(state, e, suggested) {
  if (suggested) {
    if (parentIndex === 0 || (state.delta[0] > 0 && childIndex === 0)) {
      return true;
    }
  }

  return false;
}

function onTerminationRequest(state) {
  if (state.delta[0] > 0 && childIndex === 0) {
    return false;
  }

  return true;
}

<Pager
  onMoveShouldSet={onMoveShouldSet}
  onTerminationRequest={onTerminationRequest}
  value={parentIndex}
  onRequestChange={i => setParentIndex(i)}
>
  <div>Left parent pane</div>
  <Pager value={childIndex} onRequestChange={i => setChildIndex(i)}>
    <div>child pane</div>
    <div>another child</div>
  </Pager>
</Pager>;