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

@ramka/react

v0.0.1

Published

Unstyled, accessible image gallery primitives for React. ("ramka" — Polish for "frame".)

Readme

@ramka/react

Unstyled, accessible lightbox primitives for React — in the style of Radix UI and Base UI.

ramka — Polish for "frame".

Installation

npm install @ramka/react
# or
pnpm add @ramka/react
# or
yarn add @ramka/react

react and react-dom (>= 18) are peer dependencies, and they are the only dependencies: nothing else is installed, so nothing else can pull in a transitive tree, break under a version bump, or need auditing. CI runs the full suite, the typecheck and the build against React 18.3 as well as React 19, so the floor is a tested claim rather than an aspiration.

Usage

import * as Lightbox from '@ramka/react/lightbox';

The parts ship as a flat module and you name the namespace yourself, so your bundler can drop every part your gallery does not render. Importing a pre-built namespace out of a package defeats tree-shaking in esbuild-based bundlers (Vite dev, Remix), which is why @ramka/react itself exports no Lightbox object.

That only holds while the accesses stay statically visible, so reach for Lightbox.Root directly rather than pulling names off the namespace:

// Shakeable: esbuild rewrites each access into a direct reference.
<Lightbox.Root>…</Lightbox.Root>;

// Not shakeable: destructuring needs a real object, so every part is retained.
const { Root, Trigger } = Lightbox;

Spreading the namespace or passing it to a function costs the same. If you prefer bare local names, take them as named imports — import { Root, Trigger } from '@ramka/react/lightbox' — which shakes exactly like the namespace form.

Composition hooks (useLightboxContext, useLightboxItemContext, …) and shared types come from the package root:

import { useLightboxContext } from '@ramka/react';

Lightbox.* is a fullscreen modal image viewer composed of headless parts:

  • Lightbox.Trigger / Lightbox.Portal / Lightbox.Content / Lightbox.Backdrop — the modal shell with an optional View Transition morph from the trigger.
  • Lightbox.Slides / Lightbox.Slide — a swipeable, snapping carousel wired directly to the lightbox's active index. Snap alignment is built in; slide width (full-bleed, aspect cards, …) is consumer CSS.
  • Lightbox.Zoom, Lightbox.Caption, Lightbox.ThumbnailGroup, Lightbox.Previous / Lightbox.Next — zoom, captions, thumbnails, and navigation, plus built-in pull-to-dismiss.

Labels and localization

The library ships no user-facing copy: Lightbox.Close, Previous, Next, ZoomIn and ZoomOut render without an aria-label, so nothing English lands in your UI and there is no default wording to override. Give each control visible text or your own localized aria-label / aria-labelledby. In development a nameless control logs a warning, the same way Lightbox.Content does for a dialog with no accessible name.

<Lightbox.Close aria-label={t('gallery.close')}>
  <XIcon aria-hidden />
</Lightbox.Close>

Content Security Policy

Works under a strict style policy — style-src 'self'; style-src-attr 'none', no unsafe-inline and no nonce to configure. The library's own CSS (view-transition rules, morph keyframes, media fill) is delivered as constructed stylesheets, and element styling goes through CSSOM, so nothing ramka writes reaches the document as markup. Note that constructed stylesheets are adopted, so they cascade after your stylesheets; tune them through the documented --lightbox-* custom properties rather than by relying on source order.

Supply chain

Every version is published from a GitHub Actions workflow using npm trusted publishing, so the tarball carries a signed provenance attestation naming the commit and the run that built it. Nobody can publish @ramka/react from a laptop, with or without a stolen token:

npm audit signatures

A CycloneDX SBOM ships inside the package as sbom.cdx.json and is attached to each GitHub release. It records the zero installed dependencies, the peer dependencies your app supplies, and the Base UI code adapted into src/render/ — which a lockfile-reading scanner cannot see, because it was vendored precisely so it would not be a dependency. See THIRD-PARTY-NOTICES.md.

Docs: run the docs site and open /docs/lightbox (overview → composition → view transitions → gestures → API). Live demos live under /examples/lightbox/*.

API tables (props, data attributes, CSS variables) are generated from this package’s TypeScript + JSDoc — including the *DataAttributes / *CssVars enums. Usage code excerpts are extracted from typechecked sources under apps/docs/app/_content/lightbox/excerpts/sources/. After changing public APIs or excerpt sources, run pnpm docs:api and pnpm docs:excerpts from the repo root (CI fails if generated files are stale).

LLM-oriented copies of the docs (/llms.txt, /llms-full.txt, and a .md twin of each docs page) are generated from those same sources — pnpm docs:llms. The docs dev/build scripts regenerate them automatically.

License

Dual-licensed — choose the license that matches how you intend to use ramka.

GPL-3.0-only — free to use, modify and redistribute, including commercially; the GPL does not restrict commercial use. If your use of ramka creates a work that is subject to the GPL, the GPL's source-code and licensing requirements apply to that work when you distribute it.

Commercial license — if you are building proprietary software and do not want to rely on the GPL, you may purchase a commercial license instead. The commercial license is a separate license grant from the copyright holder and permits use under its own terms rather than the GPL.

Read more about the commercial license · Ramka License Agreement

Declare the license you are using on Lightbox.Root with license="gpl" or license="commercial". This is an honor-system declaration, not a license key, and is not validated remotely.

The GPLv3 text and licensing overview are in LICENSE, which ships inside this package. The commercial terms are in COMMERCIAL-LICENSE.md. The vendored Base UI code noted in THIRD-PARTY-NOTICES.md, also published at ramka.dev/license/notices, is MIT-licensed and remains subject to its own license terms.

Changes to each published version are recorded in CHANGELOG.md.