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

@ghr95223/decko

v1.5.2

Published

A Web Audio API-based deck manager for DJ applications

Readme

Decko

Decko is a deck management library for DJ applications using the Web Audio API and valtio for state management. This library provides basic features needed for DJ applications such as loading audio tracks, play/pause functionality, volume control, speed adjustment, and crossfader capabilities, all managed through a reactive state object.

Installation

You can install it using your preferred package manager:

npm install @ghr95223/decko
# or
yarn add @ghr95223/decko
# or
pnpm add @ghr95223/decko
# or
bun add @ghr95223/decko

Key Features

  • Management of two independent audio decks via a reactive state object.
  • Loading and play/pause control of audio tracks.
  • Volume and playback speed adjustment.
  • Transition between two decks via crossfader.
  • Track position seeking.
  • Reactive state management using valtio.

Decko State Management: deckoManager and useDeckoSnapshot

This document briefly explains how to change Decko's state using deckoManager and how to subscribe to those state changes in React components using the useDeckoSnapshot hook.

Core Concepts

  1. deckoState (Valtio Proxy): A central store containing all application state. It's created as a Valtio proxy object, allowing state changes to be tracked. (src/state.ts)
  2. deckoManager (Singleton Class): Encapsulates the Web Audio API logic and is responsible for directly modifying deckoState. For example, it performs tasks like playing/pausing tracks, adjusting volume, and updates the relevant state in deckoState. (src/DeckoManager.ts)
  3. useDeckoSnapshot (React Hook): Used within React components to subscribe to changes in specific parts of deckoState and retrieve their values. It's based on Valtio's useSnapshot and provides path-based access and type safety, supporting optimized re-renders. (src/useDeckoSnapshot.ts)

Modifying State (Using deckoManager)

To change the application state, call methods on the deckoManager instance. deckoManager is provided as a singleton instance, so you can reference and use the same instance from anywhere.

import { deckoManager, DECK_IDS } from '@ghr95223/decko'

// Example: Toggle play/pause for Deck 1
deckoManager.playPauseDeck(DECK_IDS.ID_1)

// Example: Set volume for Deck 2
deckoManager.setVolume(DECK_IDS.ID_2, 0.75)

// Example: Set the crossfader value
deckoManager.setCrossFade(0.3)

// Example: Load a track onto Deck 1 (Requires a Blob object)
async function loadAndPlay(trackBlob: Blob) {
  await deckoManager.loadTrack(DECK_IDS.ID_1, trackBlob)
  // Optionally play immediately after loading
  // deckoManager.playPauseDeck(DECK_IDS.ID_1);
}

// Example: Change the playback position of Deck 1 (in seconds)
deckoManager.seekDeck(DECK_IDS.ID_1, 30) // Seek to the 30-second mark

When you call a method on deckoManager, its internal logic runs, and the related state (e.g., isPlaying, volume, crossFade, uiPlaybackTime, etc.) is updated directly within the deckoState proxy object.

Subscribing to State Changes (Using useDeckoSnapshot)

To detect changes in deckoState within a React component and update the UI, use the useDeckoSnapshot hook. This hook returns the entire state object and automatically triggers re-renders when any part of the state changes that your component uses.

import React from 'react'
import { useDeckoSnapshot } from '@ghr95223/decko'
import { DECK_IDS } from '@ghr95223/decko'

function DeckStatus({
  deckId,
}: {
  deckId: typeof DECK_IDS.ID_1 | typeof DECK_IDS.ID_2
}) {
  // Get the entire state snapshot
  const snapshot = useDeckoSnapshot()

  // Access specific properties from the snapshot
  const isPlaying = snapshot.decks[deckId].isPlaying
  const playbackTime = snapshot.decks[deckId].uiPlaybackTime
  const duration = snapshot.decks[deckId].duration
  const volume = snapshot.decks[deckId].volume

  // Format function (example)
  const formatTime = (time: number) => {
    const minutes = Math.floor(time / 60)
    const seconds = Math.floor(time % 60)
      .toString()
      .padStart(2, '0')
    return `${minutes}:${seconds}`
  }

  return (
    <div>
      <h3>Deck {deckId} Status</h3>
      <p>Status: {isPlaying ? 'Playing' : 'Paused/Stopped'}</p>
      <p>
        Time: {formatTime(playbackTime)} / {formatTime(duration)}
      </p>
      <p>Volume: {Math.round(volume * 100)}%</p>
      {/* Add buttons here for play/pause, seek, volume control, etc., calling deckoManager */}
    </div>
  )
}

function CrossfaderControl() {
  // Get the entire state snapshot
  const snapshot = useDeckoSnapshot()

  // Access the crossFade value
  const crossFadeValue = snapshot.crossFade

  return (
    <div>
      <h4>Crossfader</h4>
      <input
        type="range"
        min="0"
        max="1"
        step="0.01"
        value={crossFadeValue}
        onChange={e => deckoManager.setCrossFade(parseFloat(e.target.value))} // Change state via deckoManager
      />
      <p>Value: {crossFadeValue.toFixed(2)}</p>
    </div>
  )
}

Summary

  • To change state, call methods on deckoManager.
  • To subscribe to state changes and reflect them in the UI within React components, use the useDeckoSnapshot hook.
  • deckoState serves as the central state store connecting these two.