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

vue-waypoint

v5.1.0

Published

Trigger functions and events based on an element's position on screen — a tiny, dependency-free Vue 3 wrapper around IntersectionObserver.

Readme

vue-waypoint

Trigger functions and events based on an element's position on screen — a tiny, dependency-free Vue 3 wrapper around the native IntersectionObserver.

npm version npm downloads CI minzipped size license

Demo

Simple demo page — open your browser console and watch the events fire while scrolling up and down.

Features

  • Vue 3, written in TypeScript with shipped type declarations
  • Zero runtime dependencies — a thin wrapper over the native IntersectionObserver
  • ESM + CJS builds (tree-shakable) with correct exports
  • Flexible: custom tag, custom observer options, reactive active toggle
  • Optional CSS helper classes for quick, configuration-free animations
  • Slot support exposing the live waypoint state
  • useWaypoint composable for observing any template ref directly
  • SSR-safe

Install

npm i vue-waypoint

Usage

<script setup> (recommended)

<script setup lang="ts">
import { Waypoint, type WaypointState } from "vue-waypoint";

function onChange(state: WaypointState) {
  // state.going     -> "IN" | "OUT"
  // state.direction -> "UP" | "DOWN" | "LEFT" | "RIGHT"
  // state.el        -> the observed Element
  console.log(state.going, state.direction);
}
</script>

<template>
  <Waypoint @change="onChange">
    <!-- anything you want here -->
  </Waypoint>
</template>

Options API

<script lang="ts">
import { defineComponent } from "vue";
import { Waypoint, type WaypointState } from "vue-waypoint";

export default defineComponent({
  components: { Waypoint },
  setup() {
    const onChange = (state: WaypointState) => {
      console.log(state.going, state.direction);
    };
    return { onChange };
  },
});
</script>

<template>
  <Waypoint @change="onChange" />
</template>

Props

active

Reactively enable or disable the waypoint. The element is observed while active is true and unobserved when it flips to false.

  • Enable: <Waypoint :active="true" />
  • Disable: <Waypoint :active="false" />

options

A standard IntersectionObserverInit object, forwarded verbatim to the underlying observer.

const options: IntersectionObserverInit = {
  root: document,
  rootMargin: "0px 0px 0px 0px",
  threshold: [0.25, 0.75],
};

<Waypoint :options="options" />

tag

The rendered element tag. Defaults to div.

  • <Waypoint tag="div" /><div class="waypoint"></div>
  • <Waypoint tag="span" /><span class="waypoint"></span>
  • <Waypoint tag="p" /><p class="waypoint"></p>

disableCssHelpers

Disable the automatic CSS helper classes. Defaults to false.

  • With helpers (default): <Waypoint /><div class="waypoint going-in direction-down"></div>
  • Without helpers: <Waypoint :disable-css-helpers="true" /><div></div>

CSS helpers

Zero configuration, handy for simple CSS animations. The component toggles three families of classes:

  • waypoint — set as soon as the waypoint is ready
  • going-in / going-out — toggled as the element enters and leaves the viewport
  • direction-up / direction-down / direction-left / direction-right — toggled as the scroll direction changes

Examples:

  • waypoint going-in direction-up — visible, came from the bottom, scrolling up (natural scroll)
  • waypoint going-in direction-down — visible, came from the top, scrolling down
  • waypoint going-out direction-up — hidden, was scrolling up
  • waypoint going-out direction-down — hidden, was scrolling down

Events

change

Emitted every time the waypoint detects an intersection change.

interface WaypointState {
  el: Element | undefined;
  going: "IN" | "OUT" | undefined;
  direction: "UP" | "DOWN" | "LEFT" | "RIGHT" | undefined;
}
<template>
  <Waypoint @change="onChange" />
</template>

The same WaypointState is also exposed through the default slot:

<Waypoint #default="{ going, direction }">
  <span v-if="going">going-{{ going.toLowerCase() }}</span>
  <span v-if="direction">direction-{{ direction.toLowerCase() }}</span>
</Waypoint>

Composable

Prefer composing over a component? useWaypoint observes a template ref directly, with the same reactive active/options behavior as <Waypoint>:

<script setup lang="ts">
import { ref } from "vue";
import { useWaypoint } from "vue-waypoint";

const target = ref<Element | null>(null);
const { state } = useWaypoint(target, {
  active: true,
  observerOptions: { threshold: 0.5 },
});
</script>

<template>
  <div ref="target">{{ state?.going }}</div>
</template>

active and observerOptions accept a plain value or a Ref. The observer is created lazily (only once the target element and active are both truthy) and is disconnected automatically when the enclosing component scope is torn down. Outside a component scope, call the returned stop() yourself.

Development

npm i          # install
npm run dev    # run the demo app
npm run lint   # eslint (flat config)
npm run type-check
npm test       # vitest
npm run build  # type-check + library build (ESM + CJS + .d.ts)

Legacy: Vue 2 and Nuxt

The Vue 2 line lives on the vue2 branch. The 4.x/5.x releases target Vue 3 only.

License

MIT