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 🙏

© 2025 – Pkg Stats / Ryan Hefner

vue-roulette

v0.1.5

Published

Vue 3 roulette component

Readme

Vue Roulette

Reusable Vue 3 component that renders an animated casino wheel on <canvas>.

Demo

A live demo is available at: https://vue-roulette.ablondel.com/

Installation

npm install vue-roulette

Then import the component (or the RouletteItem type) from the package.

Quick start

<script setup lang="ts">
import { ref } from "vue";
import VueRoulette, { type RouletteItem } from "vue-roulette";

const items = ref<RouletteItem[]>([
  { label: "10", value: 10 },
  { label: "25", value: 25 },
  { label: "50", value: 50 },
]);

const selection = ref<RouletteItem | null>(null);
const rouletteRef = ref<InstanceType<typeof VueRoulette> | null>(null);

const onSelect = (item: RouletteItem) => {
  selection.value = item;
};

const spin = () => rouletteRef.value?.spin();
</script>

<template>
  <VueRoulette ref="rouletteRef" :items="items" :useColor="false" @select="onSelect" />
  <button @click="spin">Spin</button>
  <p v-if="selection">Winner: {{ selection.label }}</p>
</template>

Props

| Prop | Type | Default | Description | | ----------------- | ----------------------- | -------------------- | -------------------------------------------------------------------- | | items | RouletteItem[] | required | Segments to draw. | | size | number | 400 | Canvas width/height. | | spinDuration | number | 4000 | Total animation duration (ms). | | easingFunction | (t: number) => number | t => 1 - (1 - t)^4 | Acceleration/deceleration curve. | | useColor | boolean | false | Uses each item's color when true. | | initialVelocity | number | 2000 | Degrees per second applied on launch to set the number of rotations. | | initialAngle | number | 0 | Starting angle. | | enableTickSound | boolean | false | Plays a click sound on every segment crossing. | | pointerOptions | PointerOptions | {} | Customization options for the pointer (see below). | | pointerPosition | string | 'top' | Position of the pointer: 'top', 'right', 'bottom', or 'left'.| | centerHoleRatio | number | 0.28 | Size ratio of the center hole relative to the wheel radius (0-1). | | spinOnClick | boolean | false | Enables spinning the wheel by clicking on it. | | tickSoundVolume | number | 0.15 | Volume of the tick sound (0-1). Only applies when enableTickSound is true. | | borderWidth | number | 4 | Width of the wheel border in pixels. | | borderColor | string | '#ffffff' | Color of the wheel border. |

RouletteItem interface

interface RouletteItem {
  label: string;
  value: unknown;
  color?: string;
}

PointerOptions interface

interface PointerOptions {
  visible?: boolean; // Show or hide the pointer (default: true)
  color?: string;    // Pointer color (default: '#ffffff')
  width?: number;    // Pointer width in pixels (default: 26)
  length?: number;   // Pointer length in pixels (default: 38)
}

Emitted events

| Event | Payload | When | | -------------- | -------------- | -------------------------------------------- | | spin-start | void | A spin begins. | | spin-end | void | Animation ends (wheel stops). | | select | RouletteItem | Item located at the pointer after stopping. | | update:angle | number | Current angle (0-360) emitted on each frame. |

Exposed methods

Reference the component via ref, then use defineExpose:

  • spin(): void — starts a spin toward a randomly chosen item.
  • stop(): void — requests a smooth stop toward the currently targeted item.
  • reset(): void — cancels the animation and resets the angle to initialAngle.
  • getCurrentItem(): RouletteItem | null — returns the item under the pointer.

Color logic

  • useColor = true: every item uses item.color (a built-in palette is used as a fallback when missing).
  • useColor = false: automatic red/black alternation. If the item count is odd, a green "0" slice is inserted at position 0 before applying the alternation.

Text color: The label text color is automatically adjusted based on the background color luminance. Dark backgrounds display white text, while light backgrounds display black text for optimal readability.

Local demo

npm install
npm run dev

The root page loads Example.vue, which showcases props, events, and exposed methods (spin, stop, reset).

Build & publish

npm run build:lib
  • dist/vue-roulette.js: ES module.
  • dist/vue-roulette.umd.cjs: UMD build.
  • dist/index.d.ts: TypeScript declarations.

Then publish to npm (after logging in):

npm publish --access public