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

hazehash-vue

v0.1.1

Published

Vue 3 component and composable for HazeHash image placeholders

Readme

HazeHash Vue

HazeHash Vue

Vue 3 component and composable for HazeHash placeholders: <PlaceholderImage> reserves the space with the right aspect ratio, draws the blurred preview into a canvas and fades the real image in over it. On the server it renders only the average colour and the aspect ratio, so hydration cannot mismatch.

Part of the hazehash monorepo. Core package and Nuxt module: hazehash, hazehash-nuxt.


Features

  • One component for the image and its placeholder — <PlaceholderImage> takes a hash and a src, and renders the preview, the image and the fade between them
  • Hydration cannot mismatch — on the server only background-color (the average colour) and aspect-ratio are emitted; the canvas is added after mount
  • A canvas preview that fades into the real image — the blurred frame is drawn into an aria-hidden <canvas>, and the <img> fades in over it on load; an image that was already cached is detected through img.complete and appears at once
  • Aspect ratio from your data or from the hash — width and height, when both are set, define the ratio, and otherwise it comes from the hash
  • Respects reduced motion — prefers-reduced-motion: reduce turns the fade off
  • An invalid hash never throws — a flat background remains and one console.warn is printed for the whole page
  • A composable for your own markup — usePlaceholder() returns the canvas ref, the background colour, the aspect ratio and a client flag for a hash that can be a value, a ref or a getter

When you'd reach for this

You already have hashes, or can make them ahead of time, and want Vue to show them without writing the canvas and fade logic yourself.

  • An image grid or a catalogue — Every card gets a blurred frame of the right proportions at once, so the page does not jump when the photos arrive.
  • A server-rendered Vue app — The markup the server sends and the first client render are identical, so there is no hydration warning, and no <ClientOnly> wrapper is needed.
  • A custom card that needs the placeholder's colour or ratio — usePlaceholder() hands you the pieces, and you keep full control of the markup.

Installation

npm install hazehash hazehash-vue

Requires Vue ^3.3.0 and Node.js 20+. hazehash is a peer dependency.

The component only draws hashes. Create them ahead of time with the command line that comes with hazehash:

npm install --save-dev sharp   # lets the command read images
npx hazehash encode ./public/images -f json -o hashes.json

Quick start

<script setup lang="ts">
import { PlaceholderImage } from 'hazehash-vue';
</script>

<template>
  <PlaceholderImage
    hash="Ed7UwRWKKv5znm6a7sC1tziHDNpMuCikxrYpIg"
    src="/photo.jpg"
    alt="Mountain lake"
    :width="1280"
    :height="959"
  />
</template>

More examples

Hashes from your data

<script setup lang="ts">
import { PlaceholderImage } from 'hazehash-vue';

defineProps<{
  photos: { url: string; hash: string; width: number; height: number; title: string }[];
}>();
</script>

<template>
  <PlaceholderImage
    v-for="photo in photos"
    :key="photo.url"
    :src="photo.url"
    :hash="photo.hash"
    :width="photo.width"
    :height="photo.height"
    :alt="photo.title"
  />
</template>

Props

| Prop | Type | Default | Meaning | | -------- | ------------------ | ----------- | ------------------------------------------------------------------ | | hash | string | undefined | the HazeHash of the image; without it only the <img> renders | | src | string | undefined | the URL of the real image; without it only the placeholder renders | | alt | string | '' | the alt text of the image | | width | number \| string | undefined | intrinsic width; with height it defines the aspect ratio | | height | number \| string | undefined | intrinsic height | | size | number | 32 | long side of the decoded preview in pixels (4–128) | | fade | number | 300 | fade-in of the real image in milliseconds; 0 for no transition |

The root <div> takes class and style like any block, and has no emits and no slots.

Styling

<PlaceholderImage class="avatar" :hash="hash" :src="url" :width="64" :height="64" alt="" />
.avatar {
  width: 64px;
  border-radius: 50%;
}

The height comes from the aspect ratio, and rounded corners work because the root clips its content.

usePlaceholder() for your own markup

<script setup lang="ts">
import { usePlaceholder } from 'hazehash-vue';

const props = defineProps<{ hash: string }>();
const { canvas, backgroundColor, aspectRatio } = usePlaceholder(() => props.hash, { size: 64 });
</script>

<template>
  <div :style="{ backgroundColor, aspectRatio }">
    <canvas ref="canvas" aria-hidden="true" />
  </div>
</template>

usePlaceholder(hash, { size }) returns canvas (a template ref), mounted, average, aspectRatio and backgroundColor. On the server only average, aspectRatio and backgroundColor have values, and the canvas is drawn after mount.


Documentation & links


License

MIT


💖 Support the project

Open source takes time and effort. If this library saves you time or brings value, consider supporting further development.

Thank you for being part of this journey. ❤️