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

courthive-components

v3.14.1

Published

Components for competitions projects

Readme

courthive-components

Vanilla JavaScript UI components for tennis tournament management and competition displays.

Storybook npm version License: MIT

Overview

This library provides a comprehensive set of UI components for building tournament management applications. Components are framework-agnostic (vanilla JavaScript) and designed to work seamlessly with the Competition Factory engine.

Used by:

  • TMX (Tournament Management eXperience) - Production tournament management application
  • Competition Factory Documentation - Interactive examples and demonstrations

Installation

pnpm add courthive-components

(External consumers may also use npm install courthive-components or yarn add courthive-components. Inside the CourtHive monorepo, pnpm is the only supported manager.)

Quick Start

import { renderMatchUp, scoringModal, compositions } from 'courthive-components';

// Render a match display
const matchUpElement = renderMatchUp({
  matchUp: myMatchUpData,
  composition: compositions.Australian
});
document.getElementById('container').appendChild(matchUpElement);

// Open scoring modal
scoringModal({
  matchUp: myMatchUpData,
  callback: (outcome) => {
    console.log('Score submitted:', outcome);
  }
});

Components

Display Components

renderMatchUp

Display a single match with scores, participants, and status indicators.

import { renderMatchUp, compositions } from 'courthive-components';

const element = renderMatchUp({
  matchUp: matchUpData,
  composition: compositions.Wimbledon,
  isLucky: false
});

renderStructure

Display a complete draw structure (bracket, round robin, etc.).

import { renderStructure } from 'courthive-components';

const element = renderStructure({
  structure: drawStructure,
  config: { showSeeds: true }
});

renderRound

Display a single round of matches within a structure.

import { renderRound } from 'courthive-components';

const element = renderRound({
  round: roundData,
  roundNumber: 1
});

renderParticipant

Display participant information (name, rating, country, etc.).

import { renderParticipant } from 'courthive-components';

const element = renderParticipant({
  participant: participantData,
  showRating: true
});

renderRoundHeader

Display round headers for draw structures.

import { renderRoundHeader } from 'courthive-components';

const element = renderRoundHeader({
  roundName: 'Quarterfinals',
  roundNumber: 3
});

renderContainer

Wrapper component for draw containers with scrolling and layout.

Input Components

renderParticipantInput

Autocomplete input for participant selection.

import { renderParticipantInput } from 'courthive-components';

const input = renderParticipantInput({
  participants: participantsList,
  onSelect: (participant) => console.log('Selected:', participant)
});

Modal Components

cModal

Base modal system with flexible configuration.

import { cModal } from 'courthive-components';

cModal.open({
  title: 'Confirm Action',
  content: 'Are you sure?',
  buttons: [
    { label: 'Cancel', close: true },
    { label: 'Confirm', onClick: handleConfirm, close: true }
  ]
});

scoringModal

Interactive score entry with multiple input approaches.

import { scoringModal, setScoringConfig } from 'courthive-components';

// Configure scoring behavior
setScoringConfig({
  scoringApproach: 'dynamicSets', // 'dynamicSets' | 'freeScore' | 'dialPad'
  smartComplements: true,
  composition: 'Australian'
});

// Open scoring modal
scoringModal({
  matchUp: matchUpData,
  callback: (outcome) => {
    // outcome: { isValid, sets, winningSide, matchUpStatus }
  }
});

Scoring Approaches:

  • dynamicSets - Set-by-set entry with real-time validation
  • freeScore - Flexible text-based entry (e.g., "6-4 6-3")
  • dialPad - Touch-friendly numeric keypad

getMatchUpFormatModal

Interactive modal for selecting/editing match formats.

import { getMatchUpFormatModal } from 'courthive-components';

getMatchUpFormatModal({
  existingMatchUpFormat: 'SET3-S:6/TB7',
  callback: (newFormat) => {
    console.log('Format:', newFormat);
  }
});

Form Components

renderForm

Render dynamic forms from configuration.

import { renderForm } from 'courthive-components';

const inputs = renderForm(container, [
  { field: 'name', label: 'Name', type: 'text' },
  { field: 'age', label: 'Age', type: 'number' }
]);

renderField

Render individual form fields.

renderButtons

Render button groups with consistent styling.

renderMenu

Render dropdown/context menus.

validator

Form validation utilities.

UI Components

drawer

Slide-out drawer component for side panels.

import { drawer, initDrawer } from 'courthive-components';

initDrawer(); // Initialize once

drawer.open({
  title: 'Details',
  content: myContent,
  side: 'right' // 'left' | 'right'
});

tipster

Tooltip/popover system using Tippy.js.

import { tipster } from 'courthive-components';

tipster({
  target: buttonElement,
  content: 'Click to edit',
  placement: 'top'
});

Compositions

Pre-configured visual themes matching Grand Slam tournaments:

import { compositions } from 'courthive-components';

// Available compositions:
compositions.Australian; // Australian Open colors
compositions.French; // Roland Garros colors
compositions.Wimbledon; // Wimbledon colors
compositions.US; // US Open colors

Constants

MATCH_FORMATS

Pre-defined match format codes.

import { MATCH_FORMATS } from 'courthive-components';

console.log(MATCH_FORMATS.BEST_OF_3_TB7);
// 'SET3-S:6/TB7'

Utilities

courthiveComponentsVersion

Get the current package version.

import { courthiveComponentsVersion } from 'courthive-components';

console.log(courthiveComponentsVersion());

Documentation

📚 Interactive Documentation: Storybook

The Storybook includes:

  • Live component demos
  • Interactive examples
  • Configuration options
  • Usage patterns
  • Integration guides

Styling

Import the bundled CSS:

import 'courthive-components/dist/courthive-components.css';

TypeScript Support

The package includes TypeScript definitions:

import { renderMatchUp, ScoringModalParams, ScoreOutcome } from 'courthive-components';

const params: ScoringModalParams = {
  matchUp: myMatchUp,
  callback: (outcome: ScoreOutcome) => {
    if (outcome.isValid) {
      console.log('Winner:', outcome.winningSide);
    }
  }
};

Integration with Competition Factory

Components are designed to work with TODS (Tennis Open Data Standards) data structures from tods-competition-factory:

import { tournamentEngine } from 'tods-competition-factory';
import { renderMatchUp, scoringModal } from 'courthive-components';

// Get match data from factory
const { matchUp } = tournamentEngine.findMatchUp({ matchUpId });

// Render with components
const display = renderMatchUp({ matchUp });

// Score with modal
scoringModal({
  matchUp,
  callback: (outcome) => {
    // Update tournament using factory
    tournamentEngine.setMatchUpStatus({
      matchUpId,
      outcome: {
        score: { sets: outcome.sets },
        winningSide: outcome.winningSide,
        matchUpStatus: outcome.matchUpStatus
      }
    });
  }
});

Development

# Install dependencies
pnpm install

# Start Storybook
pnpm storybook

# Build library
pnpm build

# Run tests
pnpm test

# Build Storybook for deployment
pnpm build-storybook

Contributing

Contributions are welcome! This library is actively used in production tournament management applications.

Guidelines

  • Maintain framework-agnostic vanilla JavaScript
  • Follow existing component patterns
  • Add Storybook stories for new components
  • Include TypeScript types
  • Test with Competition Factory integration

License

MIT © Charles Allen

Links