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

@samline/is-visible

v0.5.1

Published

Lightweight IntersectionObserver utility for visibility enter/leave callbacks.

Downloads

565

Readme

Element Visibility Observer

A lightweight TypeScript utility built on top of the Intersection Observer API that lets you execute callbacks when a DOM element enters or leaves the viewport.

It provides a small abstraction for common tasks like:

  • Scroll-triggered animations
  • Lazy loading content
  • Auto-playing or pausing media
  • Infinite scroll triggers
  • Analytics visibility tracking

The package ships a shared vanilla API plus framework-specific entrypoints for React, Vue and Svelte. It also includes a browser bundle for projects that load JavaScript directly in the page without a build step.

Table of Contents

  • Installation
  • Entry Points
  • Quick Start
  • Documentation Guides
  • Shared API Summary
  • Shared Options
  • Notes
  • License

Installation

Choose the installation method that matches your environment.

npm

npm install @samline/is-visible

pnpm

pnpm add @samline/is-visible

yarn

yarn add @samline/is-visible

bun

bun add @samline/is-visible

CDN / Browser

Use the browser bundle when your project loads scripts directly in the page and cannot compile npm modules.

This is useful in environments such as Shopify themes, WordPress templates, or plain HTML pages with no build step.

<script src="https://cdn.jsdelivr.net/npm/@samline/[email protected]/dist/browser/is-visible.global.js"></script>

Then use it from a normal script:

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const element = document.querySelector('[data-track-visibility]')

    if (!element) return

    window.IsVisible.observe(element, {
      inOut: true,
      visible: () => {
        console.log('Element entered the viewport')
        element.classList.add('is-visible')
      },
      notVisible: () => {
        console.log('Element left the viewport')
      }
    })
  })
</script>

After the CDN script loads, the browser build exposes window.isVisible(...) and window.IsVisible.observe(...).

Use one of the package manager commands above when your project has a build step. If you are working in Shopify, WordPress or any browser-only template without compilation, use the browser bundle described in docs/browser.md.

Entry Points

Choose the entrypoint that matches your stack so you only import the implementation you need.

| Use case | Import | Guide | | --------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------- | | Vanilla JS | import isVisible from '@samline/is-visible' | docs/vanilla.md | | Vanilla JS explicit subpath | import isVisible from '@samline/is-visible/vanilla' | docs/vanilla.md | | Browser / CDN | <script src=".../dist/browser/is-visible.global.js"></script> | docs/browser.md | | React | import { VisibilityObserver, useIsVisible } from '@samline/is-visible/react' | docs/react.md | | Vue | import { VisibilityObserver, useIsVisible } from '@samline/is-visible/vue' | docs/vue.md | | Svelte | import { createVisibilityAction, useIsVisible } from '@samline/is-visible/svelte' | docs/svelte.md |

No external runtime dependencies are required for the shared vanilla or browser bundle APIs. The package uses the native IntersectionObserver API.

Quick Start

import isVisible from '@samline/is-visible'

const disconnect = isVisible(targetElement, {
  visible: () => console.log('Element is visible'),
  notVisible: () => console.log('Element left the viewport'),
  inOut: true
})

disconnect()

For detailed setup and additional examples:

Documentation Guides

Vanilla

Use the shared DOM-oriented API with direct element references and callbacks.

Guide: docs/vanilla.md

Browser and CDN

Use the browser bundle when your project loads scripts directly in the page and cannot compile npm modules.

Guide: docs/browser.md

React

Use the React-native hook and component entrypoint instead of wiring the vanilla API manually inside effects.

Guide: docs/react.md

Vue

Use the Vue-native composable and component entrypoint instead of wiring the vanilla API manually in lifecycle hooks.

Guide: docs/vue.md

Svelte

Use the Svelte-native helper and action entrypoint instead of wiring the vanilla API manually in onMount blocks.

Guide: docs/svelte.md

Shared API Summary

The shared vanilla API has the following shape:

isVisible(element, options?)

Parameters

| Parameter | Type | Description | | --------- | ---------------- | ------------------------------- | | element | Element | DOM element to observe | | options | IsVisibleOptions | Optional observer configuration |

Returns

() => void

The returned cleanup function disconnects the observer.

Shared Options

| Property | Type | Default | Description | | ---------- | ------------------------ | -------- | ----------------------------------------------------------------- | | inOut | boolean | false | Enables detection when the element leaves the viewport | | visible | () => void | () => {} | Runs when the element enters the viewport | | notVisible | () => void | () => {} | Runs when the element leaves the viewport when inOut is enabled | | once | boolean | false | Stops observing after the first visible trigger | | options | IntersectionObserverInit | {} | Native IntersectionObserver configuration |

All framework-specific implementations map to these same visibility semantics, even if their return values differ by framework.

Notes

  • Requires IntersectionObserver support in the runtime environment
  • Supported by modern browsers
  • A polyfill may be required for older browsers

License

MIT