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

@talarion/components

v0.1.0

Published

React components for Talarion prediction market UIs

Readme

@talarion/components

React components for Talarion prediction market UIs. Ships a self-contained MarketCard with CSS-variable theming — no Tailwind required.

Installation

pnpm add @talarion/components react

Quick Start

import { MarketCard, MarketGrid } from "@talarion/components";
import type { Market } from "@talarion/components";
import "@talarion/components/theme.css";

const markets: Market[] = [
  {
    id: "btc-100k",
    title: "Will BTC exceed $100K by end of 2026?",
    volume: 1_500_000,
    liquidity: 250_000,
    outcomes: [
      { label: "Yes", price: 0.65 },
      { label: "No", price: 0.35 },
    ],
  },
];

function App() {
  return (
    <MarketGrid expectedCount={markets.length}>
      {markets.map((m) => (
        <MarketCard
          key={m.id}
          market={m}
          onMarketClick={({ market }) => console.log("clicked", market.id)}
          onOutcomeClick={({ market, outcome }) =>
            console.log(`Trade ${outcome.label} on ${market.title}`)
          }
        />
      ))}
    </MarketGrid>
  );
}

Components

MarketCard

The primary component. Displays a market title, volume/liquidity/outcome stats, and Yes/No outcome buttons.

| Prop | Type | Description | |------|------|-------------| | market | Market | Market data to display | | disabled | boolean? | Disable card and buttons | | onMarketClick | (event: MarketClickEvent) => void | Card body clicked | | onOutcomeClick | (event: OutcomeClickEvent) => void | Outcome button clicked | | className | string? | Additional CSS class |

MarketGrid

Responsive grid container. Uses ResizeObserver to compute column count from available width.

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | ReactNode | — | Card elements | | minCardWidth | number? | 350 | Min card width (px) before columns collapse | | gap | number? | 16 | Gap between cards (px) | | expectedCount | number? | — | Limits max columns | | className | string? | — | Additional CSS class |

StatDisplay

Label + value stat pair with optional highlight color.

OutcomeButtons

Yes/No pill buttons with price in cents. Used internally by MarketCard but exported for standalone use.

MarketRulesModal

Full-screen overlay modal showing settlement rules and resolution date for a market. Closes on backdrop click or the close button.

| Prop | Type | Description | |------|------|-------------| | isOpen | boolean | Whether the modal is visible | | onClose | () => void | Called when the modal should close | | title | string | Market title shown in the header | | rules | string? | Settlement / description rules text | | expirationDate | string? | Expected resolution date (ISO string) |

TalarionLogo

Talarion "T" logo in a circular badge. White by default, clickable (links to talarion.tech).

| Prop | Type | Default | Description | |------|------|---------|-------------| | size | number? | 24 | Circle diameter in px | | clickable | boolean? | true | Render as link to talarion.tech | | className | string? | — | Additional CSS class |

Integrating MarketCard with MarketRulesModal

The modal is a separate component — wire it up via onMarketClick:

import { useState } from "react";
import { MarketCard, MarketRulesModal, MarketGrid } from "@talarion/components";
import type { Market, MarketClickEvent } from "@talarion/components";
import "@talarion/components/theme.css";

const markets: Market[] = [/* your markets */];

// Extend with rules data your app has available
const rulesMap: Record<string, { rules: string; expirationDate: string }> = {
  "btc-100k": {
    rules: "Resolves YES if BTC exceeds $100,000 on any major exchange before expiration.",
    expirationDate: "2026-12-31",
  },
};

function App() {
  const [selected, setSelected] = useState<Market | null>(null);

  return (
    <>
      <MarketGrid expectedCount={markets.length}>
        {markets.map((m) => (
          <MarketCard
            key={m.id}
            market={m}
            onMarketClick={({ market }) => setSelected(market)}
            onOutcomeClick={({ outcome }) => console.log(outcome.label)}
          />
        ))}
      </MarketGrid>

      {selected && (
        <MarketRulesModal
          isOpen={!!selected}
          onClose={() => setSelected(null)}
          title={selected.title}
          rules={rulesMap[selected.id]?.rules}
          expirationDate={rulesMap[selected.id]?.expirationDate}
        />
      )}
    </>
  );
}

Types

interface Market {
  id: string;
  title: string;
  volume: number | null;
  liquidity: number | null;
  outcomes: MarketOutcome[];
}

interface MarketOutcome {
  label: string;   // "Yes", "No", "Trump", etc.
  price: number;   // 0–1 decimal (0.65 = 65¢)
}

interface MarketClickEvent { market: Market }
interface OutcomeClickEvent { market: Market; outcome: MarketOutcome; outcomeIndex: number }

Theming

The default theme is dark. Override any --tlr-* CSS variable to customize:

:root {
  --tlr-card-bg: #ffffff;
  --tlr-card-bg-hover: #f5f5f5;
  --tlr-text-primary: #111111;
  --tlr-text-tertiary: #777777;
  --tlr-success-bg: #f4f7f4;
  --tlr-success-text: #4d6b4d;
  --tlr-danger-bg: #f8f4f4;
  --tlr-danger-text: #8a5555;
  /* ... see theme.css for all variables */
}

All components carry data-tlr attributes (data-tlr="card", data-tlr="grid") for targeted CSS overrides.

Available Variables

| Variable | Description | |----------|-------------| | --tlr-card-bg | Card background | | --tlr-card-bg-hover | Card hover background | | --tlr-card-border | Card border color | | --tlr-card-radius | Card border radius | | --tlr-card-padding | Card padding | | --tlr-card-shadow | Card box shadow | | --tlr-card-shadow-hover | Card hover shadow | | --tlr-text-primary | Primary text color | | --tlr-text-tertiary | Tertiary/label text color | | --tlr-success-bg | Yes button background | | --tlr-success-text | Yes button text | | --tlr-success-border | Yes button border | | --tlr-danger-bg | No button background | | --tlr-danger-text | No button text | | --tlr-danger-border | No button border | | --tlr-btn-radius | Button border radius | | --tlr-btn-min-width | Button minimum width | | --tlr-font-family | Font family | | --tlr-logo-color | Logo fill color |

Utilities

Exported for convenience:

  • formatVolume(usd: number)$1.50M, $150.0K, $500
  • formatLiquidity(usd: number)$1.50M, $150K, $500
  • convertPriceToCents(price: number)0.65"65.0"

Docs

Full Talarion documentation at docs.talarion.tech.

License

MIT