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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nipe-solutions/react-pull-to-refresh

v1.0.0

Published

Accessible, native-feeling pull-to-refresh for React.

Readme

React Pull to Refresh

Pull to refresh without owning your feed.

A small, accessible pull-to-refresh primitive with scroll arbitration, resistance, and an async refresh lifecycle.

Mobile pull-to-refresh depends on browser gesture ownership. See Browser Behavior.

npm install @nipe-solutions/react-pull-to-refresh
import { PullToRefresh } from '@nipe-solutions/react-pull-to-refresh'
import '@nipe-solutions/react-pull-to-refresh/core.css'

export function Inbox() {
  async function refresh() {
    await refetch()
  }

  return (
    <>
      <button type="button" onClick={() => void refresh()}>
        Refresh inbox
      </button>
      <PullToRefresh.Root onRefresh={refresh}>
        <PullToRefresh.Indicator>
          <Spinner />
        </PullToRefresh.Indicator>
        <PullToRefresh.Content>
          <Messages />
        </PullToRefresh.Content>
      </PullToRefresh.Root>
    </>
  )
}

Why this exists

Pull-to-refresh coordinates downward intent, the active scroll boundary, resistance, threshold hysteresis, exactly-once refresh commitment, and settling. It does not fetch data, own a cache, render a feed, or manage application errors.

API

| Root prop | Type | Default | Purpose | | --------------- | ---------------------------------- | -------- | ----------------------------------------------------------- | | onRefresh | function returning void or Promise | required | Runs the application-owned refresh. | | threshold | number | 72 | Visual pull distance required to arm. | | disabled | boolean | false | Cancels an uncommitted gesture without disabling scrolling. | | scrollContainer | HTMLElement, Window, or ref | auto | Overrides nearest scroll-surface detection. |

Root exposes data-state with idle, pending, pulling, armed, refreshing, settling, or disabled. Indicator positions consumer-owned visual content and is aria-hidden. Content provides a transform-isolated wrapper.

CSS

Import core.css for mechanics. theme.css is an optional neutral starting point; styles.css combines both.

@import '@nipe-solutions/react-pull-to-refresh/core.css';

Available root variables:

  • --ptr-distance: resisted visual distance in pixels
  • --ptr-progress: threshold progress clamped from 0 to 1
  • --ptr-overshoot: resisted distance beyond the threshold
  • --ptr-threshold: configured threshold

Scroll ownership

The root resolves an explicit owner or the nearest actually scrollable ancestor, then Window. It checks nested scrollers from the gesture origin and rechecks the boundary before claim. An explicit null ref stays unresolved until a subsequent gesture. Gestures starting below the top stay browser-owned for that stream.

Core CSS does not set root overflow or overscroll policy. Apply optional overscroll-behavior-y: contain to your actual scroller. Chromium page-level containment may help suppress native refresh; it is not a universal guarantee. Page-level custom Pull to Refresh on iOS Safari is not a guaranteed configuration. Safari may retain native browser Pull-to-Refresh ownership.

Accessibility

The gesture must not be the only refresh path. Pass the same application function to a normal button. Add a polite status announcement only when it benefits the product. The primitive adds no progress role, live region, keyboard gesture, or focus movement.

Browser notes

Directional-capable browsers use Pointer Events with pan-x pan-down pinch-zoom. Firefox/Safari use a session-scoped Touch Events compatibility adapter. Automated Chromium, Firefox, and WebKit tests cover mechanics, keyboard use, and axe rules. They do not verify physical iOS or Android behavior. No physical-device or human screen-reader session was performed for 1.0.0. Always provide an application refresh button as the accessible alternative.

See browser behavior, integrations, and real-device QA.

When not to use it

Prefer a refresh button when the app is desktop-only, content does not scroll, browser-native refresh is enough, or refresh requires explicit confirmation.

Development

npm install
npm run check
npm run test:e2e

Requires Node 24. React 18.3 and React 19 are peer-supported. Runtime dependencies are limited to React peers.

Current status: 1.0.0 stable. Automated checks do not replace the documented manual device and assistive-technology matrix.

Part of NIPE Open Source.

License

MIT