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

ropav

v0.1.9

Published

Readme

Ropav

Minimal UI components for Vue Vapor.

Ropav components require Vapor mode. Use createVaporApp, or install Vue's Vapor interop plugin in a regular app.

import { createVaporApp } from 'vue';

createVaporApp(App).mount('#app');

or

import { createApp, vaporInteropPlugin } from 'vue';

createApp(App).use(vaporInteropPlugin).mount('#app');

Install

pnpm add ropav

Setup

import 'ropav/base.css';

Import the components you need:

import { Button } from 'ropav';

Headless state utilities are available from ropav/composables. See the public composables API for their controlled and uncontrolled state contracts.

Custom color contrast

autoContrast selects foreground colors for preset colors and opaque custom color literals. A translucent custom color depends on the surface behind the component, so its contrast cannot be determined from the color alone. Pass contrastColor explicitly whenever a custom background has alpha:

<Button color="rgba(255, 255, 255, 0.2)" contrast-color="var(--rp-color-white)" variant="solid">
  Continue
</Button>

In development, Ropav warns when auto contrast receives a translucent custom color without an explicit contrastColor. The production fallback remains var(--rp-color-white).

Progress and interactive ranges

Use Progress for read-only status and Slider when the user can change the value. A media seek control can draw buffered ranges below the played range, reveal its thumb during interaction, and preview the value under the pointer:

<Slider
  v-model="currentTime"
  :max="duration"
  thumb="interaction"
  :tooltip="{ anchor: 'pointer' }"
  :format-value="formatTime"
>
  <template #track-underlay="{ getPercent }">
    <span
      v-for="range in bufferedRanges"
      :key="range.start"
      class="buffered-range"
      :style="{
        left: `${getPercent(range.start)}%`,
        width: `${getPercent(range.end) - getPercent(range.start)}%`,
      }"
    />
  </template>
  <template #tooltip-content="{ formattedValue }">
    {{ formattedValue }}
  </template>
</Slider>

track-underlay and track-overlay are decorative layers below and above the selected range. Both receive the normalized slider state and a clamped getPercent(value) helper, so consumers can draw segments, markers, waveforms, or other track content without replacing slider behavior. Their coordinate space follows the thumb travel, so percentage positions stay aligned with the control. Set :thumb="false" to hide only the visual thumb while preserving the native input, hit area, and keyboard behavior. An object can combine visibility and geometry, for example :thumb="{ visibility: 'interaction', size: 20 }".

Icons

Ropav provides a compiler for unplugin-icons that emits each icon as a zero-VDOM Vue Vapor component.

Install unplugin-icons, a matching version of @vue/compiler-vapor, and the Iconify collection you want to use:

pnpm add -D unplugin-icons @vue/compiler-vapor @iconify-json/lucide

Pass vaporIconCompiler to unplugin-icons:

// vite.config.ts
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';
import Icons from 'unplugin-icons/vite';
import { vaporIconCompiler } from 'ropav/unplugin-icons';

export default defineConfig({
  plugins: [vue({ features: { vapor: true } }), Icons({ compiler: vaporIconCompiler() })],
});

Icons can then be imported on demand. Only imported icons are included in the application bundle.

<script setup lang="ts" vapor>
import IconSearch from '~icons/lucide/search';
</script>

<template>
  <IconSearch aria-hidden="true" />
</template>

Styling contract

Use typed classNames and styles, documented state attributes, and variables listed in the packaged styles manifest. DOM nesting, internal selectors and undocumented variables are private implementation details.

See the Public Styles API and public token table. Consumers can declare reset, ropav.tokens, ropav.components, app to establish their cascade layer order.

For headless floating content and custom overlay markup, see the public floating API.

Development

Contributors should follow the code architecture guide for module seams, dependency direction, and testing conventions. Run pnpm --workspace-root verify before submitting a change.