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

ts-spin-wheel

v1.0.7

Published

A customizable spin wheel component for React with TypeScript, sound, easing, and modal support.

Readme

🎡 SpinWheel

A fully customizable and responsive React Spin Wheel Component built with TypeScript. Supports smooth animations, audio feedback, sector-based labeling, and a modal to show the winning result. Ideal for lucky draw or reward-based UIs.


✨ Features

  • 🎯 Customizable wheel sectors (colors, labels)
  • ⏱️ Smooth easing animation with custom duration
  • 🔊 Optional ticking sound on spin
  • 📦 Modal popup with custom content
  • 📐 Full TypeScript support
  • 💅 Easily styleable with Tailwind or custom CSS

📦 Installation

Using npm:

npm install ts-spin-wheel

Using yarn:

yarn add ts-spin-wheel

🔧 Usage

import React, { useRef } from 'react';
import SpinWheel, { SpinWheelHandle, Sector } from 'ts-spin-wheel';

const App = () => {
  const wheelRef = useRef<SpinWheelHandle>(null);

  const wheelData: Sector[] = [
    { label: '10% Off', color: '#C78970', text: '#fff' },
    { label: '20% Off', color: '#f87171', text: '#fff' },
    { label: '30% Off', color: '#60a5fa', text: '#fff' },
    { label: '40% Off', color: '#facc15', text: '#000' },
    { label: '50% Off', color: '#9acc15', text: '#000' },
  ];

  const triggerSpin = () => {
    if (wheelRef.current) {
      wheelRef.current.spin();
    }
  };

  const handleSpinEnd = (winner: Sector) => {
    console.log('Winner:', winner);
  };

  return (
    <div>
      <button onClick={triggerSpin}>
        Spin the Wheel!
      </button>

      <SpinWheel
        ref={wheelRef}
        sectors={wheelData}
        size={150}
        onSpinEnd={handleSpinEnd}
        spinButtonText="Spin"
        labelFontSize={12}
        spinButtonFontSize={10}
        spinButtonStyles={{
          boxShadow: '0 0 0 3px currentColor, 0 0px 15px 5px rgba(0, 0, 0, 0.6)',
          fontFamily: 'Lato, sans-serif',
          width: '30px',
          height: '30px',
          margin: '-15px',
        }}
        spinButtonArrowStyle={{
          top: '-9px',
          border: '8px solid transparent',
          borderBottomColor: '#fff',
        }}
        wheelBaseWidth="60%"
        wheelBaseBottom="4px"
        customModalContent={(winner, onClose) => (
          <div className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50">
            <div className="bg-yellow-100 p-8 rounded-xl shadow-xl text-center">
              <h1 className="text-2xl font-bold text-green-700">
                🌟 You got: {winner.label}
              </h1>
              <p className="mt-2">Enjoy your reward!</p>
              <button
                className="mt-4 px-4 py-2 bg-green-600 text-white rounded"
                onClick={onClose}
              >
                Close
              </button>
            </div>
          </div>
        )}
      />
    </div>
  );
};

export default App;

🧩 Props

| Prop | Type | Default | Description | |------------------------|----------------------------------------------------------------------|----------------------|--------------------------------------| | sectors | Sector[] | required | List of sectors to display | | size | number | 300 | Canvas size | | onSpinEnd | (winner: Sector) => void | () => {} | Callback after spinning stops | | spinButtonText | string \| (isSpinning: boolean, label: string) => string | "SPIN" | Text or function for button | | labelFontSize | number | 16 | Font size of sector labels | | spinButtonFontSize | number | 16 | Font size of spin button | | spinButtonStyles | React.CSSProperties | {} | Style object for spin button | | spinButtonArrowStyle | React.CSSProperties | {} | Style object for the arrow | | spinButtonClassName | string | "" | Additional class for spin button | | spinButtonArrowColor | string | "#fff" | Color of the arrow | | wheelBaseWidth | number \| string | "80%" | Width of the base image | | wheelBaseBottom | number \| string | "-45px" | Offset from bottom | | customModalContent | (winner: Sector, onClose: () => void) => React.ReactNode | undefined | Custom modal JSX | | enableSound | boolean | true | Enable spinning sound | | customSound | string | defaultTickingSound| URL to custom ticking sound | | spinDuration | number | 5000 | Duration of spin in milliseconds | | easingFunction | (t: number) => number | easeOutCubic | Custom easing function |


🎨 Styling

Use default Tailwind CSS classes or override with your own styles by targeting these classes:

  • .spin-button
  • .spin-arrow
  • .wheel-base-img
  • .win-modal

You can also override them using spinButtonClassName, spinButtonStyles, or custom CSS.


📁 Assets

Ensure the following assets are included in your project:

  • SpinBase.png – Decorative wheel base
  • spin-wheel-sound.mp3 – Optional default spin sound

📜 License

MIT License © Sivamaniyam