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

miku-charts

v0.0.9

Published

Librería de charts en React con arquitectura modular, temas configurables y tooltips extensibles. Diseñada para dashboards modernos con tipado estricto y componentes reutilizables.

Downloads

563

Readme

miku-charts

Librería de charts en React con arquitectura modular, temas configurables y tooltips extensibles. Diseñada para dashboards modernos con tipado estricto y componentes reutilizables.

Tabla De Contenidos

  1. Instalación
  2. Quick Start
  3. Conceptos Clave
  4. Modelo De Datos
  5. Props Comunes
  6. Labels Y Formato
  7. Tema Global
  8. Tooltips
  9. Paletas Y Colores
  10. Layout Y Responsividad
  11. Tailwind v4
  12. Charts Disponibles
  13. API Reference
  14. Ejemplos Por Chart
  15. Recetas
  16. FAQ
  17. Arquitectura Interna
  18. Playground
  19. Scripts
  20. Contribución
  21. Licencia

Instalación

pnpm add miku-charts
npm install miku-charts
yarn add miku-charts

Quick Start

import { BarChart, ChartProvider } from "miku-charts"

const data = [
  { label: "Ene", value: 120 },
  { label: "Feb", value: 90 },
  { label: "Mar", value: 160 }
]

export function Dashboard() {
  return (
    <ChartProvider>
      <BarChart data={data} height={320} />
    </ChartProvider>
  )
}

Requisitos

  • React 18+.
  • Un contenedor con ancho visible.
  • height o size definido en cada chart.

Conceptos Clave

  • El ancho siempre es 100% del contenedor.
  • El alto lo controla el usuario con height o size.
  • Los textos se controlan con LabelConfig.
  • La estética se controla con el ChartProvider.
  • Los tooltips se personalizan desde el tema o con plantillas.

Modelo De Datos

export type ChartDatum = {
  value: number
  label?: string
  color?: string
  meta?: Record<string, unknown>
}

Props Comunes

  • height define el alto del SVG en charts cartesianos (si no se pasa, toma el alto del contenedor).
  • size define el alto en charts polares (si no se pasa, toma el alto del contenedor).
  • margin controla espacio para ejes, labels y legend.
  • labels controla el texto sobre puntos, barras y segmentos.
  • xLabels y yLabels formatean labels del eje según el chart.
  • colors permite override de la paleta en charts por serie.
  • className permite usar Tailwind o clases utilitarias en el contenedor.

Labels Y Formato

LabelConfig controla visibilidad y formato para labels, valores y ejes.

type LabelConfig = {
  show?: boolean
  showLabel?: boolean
  showValue?: boolean
  formatter?: (value: number, label?: string) => string
  fontSize?: number
  rotate?: number | "auto"
  maxChars?: number
}

Ejemplo de labels globales:

<LineChart
  data={data}
  labels={{ show: true, showValue: true, showLabel: false, formatter: (v) => `${v}%` }}
  xLabels={{ show: true, maxChars: 6 }}
/>

Ejemplo con rotación automática:

<BarChart
  data={data}
  xLabels={{ show: true, rotate: "auto", maxChars: 10 }}
/>

Tema Global

import { ChartProvider } from "miku-charts"

const theme = {
  fontFamily: "'Inter', system-ui",
  textColor: "#e5e7eb",
  gridColor: "#ffffff22",
  axisColor: "#ffffff66",
  paletteName: "neon",
  palettes: {
    neon: ["#22d3ee", "#a78bfa", "#f472b6", "#facc15", "#4ade80"]
  },
  formatters: {
    value: (v: number) => `${v.toLocaleString()}`,
    axis: (v: number | string) => String(v),
    tooltip: (v: unknown) => String(v)
  }
}

<ChartProvider theme={theme}>
  {/* charts */}
</ChartProvider>

Tooltips

El tooltip se controla desde el tema con TooltipComponent. Plantillas incluidas:

  • ValueTooltip
  • LabelValueTooltip
  • DetailedTooltip
  • SeriesTooltip
  • CompactTooltip
  • StackedTooltip

Ejemplo:

import { ChartProvider, SeriesTooltip } from "miku-charts"

<ChartProvider theme={{ TooltipComponent: SeriesTooltip }}>
  {/* charts */}
</ChartProvider>

Paletas Y Colores

  • paletteName selecciona una paleta definida en palettes.
  • palette puede definirse directamente para control fino.
  • color en cada dato puede sobreescribir la paleta.
<ChartProvider
  theme={{
    paletteName: "sunset",
    palettes: {
      sunset: ["#f97316", "#f59e0b", "#fbbf24", "#f472b6"]
    }
  }}
>
  <BarChart data={data} />
</ChartProvider>

Layout Y Responsividad

  • El ancho es 100% del contenedor.
  • El alto se toma de height/size o del alto del contenedor.
  • Usa margin para que labels y legend no se corten.
<StackedAreaChart
  data={data}
  keys={["A", "B", "C"]}
  height={360}
  margin={{ top: 72, right: 32, bottom: 48, left: 56 }}
/>

Ejemplo con alto definido por CSS:

<div style={{ height: 360 }}>
  <BarChart data={data} />
</div>

Tailwind CSS

Los charts exponen className en el contenedor para usar utilidades de Tailwind.

<BarChart
  data={data}
  height={320}
className="rounded-2xl border border-white/10 bg-white/5 p-4"
/>

Tailwind v4

Los colores base se leen desde CSS variables (--foreground, --border, --muted-foreground, --popover, --chart-1..12).
Si no usas shadcn, define esos tokens o sobrescribe el tema con ChartProvider.

Ejemplo mínimo de tokens:

:root {
  --foreground: #0f172a;
  --border: #e2e8f0;
  --muted-foreground: #64748b;
  --popover: #ffffff;
  --chart-1: #1f77b4;
  --chart-2: #ff7f0e;
  --chart-3: #2ca02c;
  --chart-4: #d62728;
  --chart-5: #9467bd;
}

Tailwind v4 + Vite (playground)

Si usas Vite, la guía oficial recomienda el plugin:

npm install tailwindcss @tailwindcss/vite
// vite.config.ts
import { defineConfig } from "vite"
import tailwindcss from "@tailwindcss/vite"

export default defineConfig({
  plugins: [tailwindcss()],
})
@import "tailwindcss";

En este repo el playground ya está configurado así.

Charts Disponibles

  • BarChart ChartDatum[]
  • HorizontalBarChart ChartDatum[]
  • StackedBarChart data: Record<string, number | string>[], keys: string[]
  • StackedBarChartHorizontal data: Record<string, number | string>[], keys: string[]
  • StackedAreaChart data: Record<string, number | string>[], keys: string[]
  • ClusteredBarChart data: Record<string, number | string>[], keys: string[]
  • ClusteredBarChartHorizontal data: Record<string, number | string>[], keys: string[]
  • LineChart ChartDatum[]
  • AreaChart ChartDatum[]
  • LineChartMultiple categories: string[], series: { label: string; values: number[] }[]
  • ScatterChart { x: number; y: number; label?: string }[]
  • ScatterChartMulticlass series: { label: string; points: { x: number; y: number; label?: string }[] }[]
  • PieChart ChartDatum[]
  • DonutChart ChartDatum[]
  • RadarChart ChartDatum[]
  • TreemapChart { label: string; value: number }[]
  • HeatmapChart { xLabels: string[]; yLabels: string[]; values: number[][] }
  • DivergingBarChart { label: string; value: number }[]
  • PyramidChart { label: string; left: number; right: number }[]
  • VennDiagram { label: string; value: number }[]

API Reference

ChartProvider

type ChartTheme = {
  barColor: string
  textColor: string
  gridColor: string
  axisColor: string
  fontFamily: string
  palette: string[]
  palettes: Record<string, string[]>
  paletteName?: string
  fontSizes: {
    axis: number
    label: number
    legend: number
    tooltip: number
  }
  formatters?: {
    value?: (value: number, label?: string) => string
    label?: (label?: string) => string
    axis?: (value: number | string) => string
    tooltip?: (value: unknown, datum?: any) => string
  }
  TooltipComponent: React.ComponentType
}

Ejemplo de uso:

<ChartProvider theme={{ paletteName: "miku" }}>
  <BarChart data={data} height={320} />
</ChartProvider>

BarChart / LineChart / AreaChart

type Props = {
  data: ChartDatum[]
  height?: number
  labels?: LabelConfig
  xLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

HorizontalBarChart

type Props = {
  data: ChartDatum[]
  height?: number
  labels?: LabelConfig
  yLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

StackedBarChart / StackedBarChartHorizontal / StackedAreaChart

type Props = {
  data: Record<string, number | string>[]
  keys: string[]
  colors?: string[]
  height?: number
  labels?: StackedLabelConfig
  xLabels?: LabelConfig
  yLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

StackedLabelConfig

type StackedLabelConfig = LabelConfig & {
  showTotals?: boolean
  totalFormatter?: (total: number, label?: string) => string
  segmentFormatter?: (value: number, info: { label?: string; series: string; total: number; index: number }) => string
}

ClusteredBarChart / ClusteredBarChartHorizontal

type Props = {
  data: Record<string, number | string>[]
  keys: string[]
  colors?: string[]
  height?: number
  labels?: LabelConfig
  xLabels?: LabelConfig
  yLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

LineChartMultiple

type Props = {
  categories: string[]
  series: { label: string; values: number[]; color?: string }[]
  height?: number
  labels?: LabelConfig
  xLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

ScatterChart

type Props = {
  data: { x: number; y: number; label?: string }[]
  height?: number
  labels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

ScatterChartMulticlass

type Props = {
  series: { label: string; points: { x: number; y: number; label?: string }[]; color?: string }[]
  height?: number
  labels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

PieChart / DonutChart / RadarChart

type Props = {
  data: ChartDatum[]
  size?: number
  labels?: LabelConfig
}

TreemapChart

type Props = {
  data: { label: string; value: number; color?: string }[]
  height?: number
  labels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

HeatmapChart

type Props = {
  data: { xLabels: string[]; yLabels: string[]; values: number[][] }
  height?: number
  labels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

DivergingBarChart

type Props = {
  data: { label: string; value: number; color?: string }[]
  height?: number
  labels?: LabelConfig
  yLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

PyramidChart

type Props = {
  data: { label: string; left: number; right: number }[]
  height?: number
  labels?: LabelConfig
  yLabels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

VennDiagram

type Props = {
  sets: { label: string; value: number; color?: string }[]
  height?: number
  labels?: LabelConfig
  margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
}

Ejemplos Por Chart

BarChart

<BarChart
  data={[
    { label: "Alpha", value: 40 },
    { label: "Beta", value: 55 },
    { label: "Gamma", value: 28 }
  ]}
  height={300}
  labels={{ show: true, showValue: true, showLabel: false }}
/>

HorizontalBarChart

<HorizontalBarChart
  data={[
    { label: "A", value: 32 },
    { label: "B", value: 18 },
    { label: "C", value: 44 }
  ]}
  height={260}
  labels={{ show: true }}
/>

StackedBarChart

<StackedBarChart
  data={[
    { label: "Q1", A: 30, B: 20, C: 12 },
    { label: "Q2", A: 28, B: 26, C: 16 },
    { label: "Q3", A: 45, B: 22, C: 18 }
  ]}
  keys={["A", "B", "C"]}
  height={320}
  labels={{ show: true, showTotals: true }}
/>

StackedBarChartHorizontal

<StackedBarChartHorizontal
  data={[
    { label: "Norte", A: 20, B: 14, C: 10 },
    { label: "Sur", A: 18, B: 20, C: 12 }
  ]}
  keys={["A", "B", "C"]}
  height={260}
  labels={{ show: true }}
/>

StackedAreaChart

<StackedAreaChart
  data={[
    { label: "Ene", A: 20, B: 15, C: 10 },
    { label: "Feb", A: 28, B: 18, C: 12 },
    { label: "Mar", A: 32, B: 24, C: 18 }
  ]}
  keys={["A", "B", "C"]}
  height={320}
/>

ClusteredBarChart

<ClusteredBarChart
  data={[
    { label: "2023", A: 30, B: 22, C: 18 },
    { label: "2024", A: 40, B: 28, C: 20 }
  ]}
  keys={["A", "B", "C"]}
  height={300}
  labels={{ show: true }}
/>

ClusteredBarChartHorizontal

<ClusteredBarChartHorizontal
  data={[
    { label: "Team A", A: 12, B: 18, C: 10 },
    { label: "Team B", A: 16, B: 22, C: 14 }
  ]}
  keys={["A", "B", "C"]}
  height={260}
/>

LineChart

<LineChart
  data={[
    { label: "Ene", value: 120 },
    { label: "Feb", value: 90 },
    { label: "Mar", value: 160 }
  ]}
  height={300}
  labels={{ show: true }}
/>

AreaChart

<AreaChart
  data={[
    { label: "Ene", value: 120 },
    { label: "Feb", value: 90 },
    { label: "Mar", value: 160 }
  ]}
  height={300}
/>

LineChartMultiple

<LineChartMultiple
  categories={["Jan", "Feb", "Mar", "Apr"]}
  series={[
    { label: "Ventas", values: [12, 18, 15, 22] },
    { label: "Gasto", values: [8, 14, 10, 12] }
  ]}
  height={320}
/>

ScatterChart

<ScatterChart
  data={[
    { x: 10, y: 40, label: "P1" },
    { x: 20, y: 25, label: "P2" },
    { x: 30, y: 50, label: "P3" }
  ]}
  height={280}
/>

ScatterChartMulticlass

<ScatterChartMulticlass
  series={[
    { label: "Grupo A", points: [{ x: 10, y: 30 }, { x: 20, y: 18 }] },
    { label: "Grupo B", points: [{ x: 12, y: 40 }, { x: 24, y: 32 }] }
  ]}
  height={280}
/>

PieChart

<PieChart
  data={[
    { label: "Web", value: 40 },
    { label: "Mobile", value: 35 },
    { label: "Retail", value: 25 }
  ]}
  size={300}
  labels={{ show: true }}
/>

DonutChart

<DonutChart
  data={[
    { label: "Free", value: 70 },
    { label: "Pro", value: 20 },
    { label: "Enterprise", value: 10 }
  ]}
  size={300}
  labels={{ show: true }}
/>

RadarChart

<RadarChart
  data={[
    { label: "Speed", value: 80 },
    { label: "Control", value: 60 },
    { label: "Quality", value: 90 }
  ]}
  size={320}
  labels={{ show: true }}
/>

TreemapChart

<TreemapChart
  data={[
    { label: "Product A", value: 120 },
    { label: "Product B", value: 80 },
    { label: "Product C", value: 60 }
  ]}
  height={240}
  labels={{ show: true }}
/>

HeatmapChart

<HeatmapChart
  data={{
    xLabels: ["Mon", "Tue", "Wed", "Thu"],
    yLabels: ["AM", "PM"],
    values: [
      [12, 18, 22, 15],
      [8, 14, 19, 11]
    ]
  }}
  height={220}
  labels={{ show: true }}
/>

DivergingBarChart

<DivergingBarChart
  data={[
    { label: "North", value: 40 },
    { label: "South", value: -25 },
    { label: "East", value: 18 },
    { label: "West", value: -30 }
  ]}
  height={280}
  labels={{ show: true }}
/>

PyramidChart

<PyramidChart
  data={[
    { label: "18-25", left: 20, right: 22 },
    { label: "26-35", left: 30, right: 28 },
    { label: "36-45", left: 25, right: 20 }
  ]}
  height={300}
  labels={{ show: true }}
/>

VennDiagram

<VennDiagram
  sets={[
    { label: "A", value: 60 },
    { label: "B", value: 40 },
    { label: "C", value: 30 }
  ]}
  height={260}
  labels={{ show: true }}
/>

Recetas

Dashboard con múltiples charts

export function Dashboard() {
  return (
    <ChartProvider>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(2, minmax(0, 1fr))", gap: 24 }}>
        <BarChart data={sales} height={280} />
        <LineChart data={visits} height={280} />
        <DonutChart data={channels} size={280} />
        <ScatterChart data={quality} height={280} />
      </div>
    </ChartProvider>
  )
}

Comparación antes/después con Diverging

<DivergingBarChart
  data={[
    { label: "Producto A", value: 12 },
    { label: "Producto B", value: -8 },
    { label: "Producto C", value: 20 },
    { label: "Producto D", value: -5 }
  ]}
  labels={{ show: true }}
/>

Piramide Poblacional

<PyramidChart
  data={[
    { label: "18-25", left: 12, right: 14 },
    { label: "26-35", left: 22, right: 20 },
    { label: "36-45", left: 18, right: 16 }
  ]}
  labels={{ show: true }}
  yLabels={{ show: true }}
/>

Series múltiples con color custom

<LineChartMultiple
  categories={["Q1", "Q2", "Q3", "Q4"]}
  series={[
    { label: "North", values: [12, 18, 15, 20], color: "#60a5fa" },
    { label: "South", values: [10, 14, 12, 16], color: "#f472b6" }
  ]}
  labels={{ show: true }}
/>

Stacked con totales y formato

<StackedBarChart
  data={data}
  keys={["A", "B", "C"]}
  labels={{
    show: true,
    showTotals: true,
    totalFormatter: (total) => `Total ${total}`,
    segmentFormatter: (value, info) => `${info.series}: ${value}`
  }}
/>

FAQ

No se ve el chart

  • Asegúrate de envolver con ChartProvider.
  • Verifica que el contenedor tenga ancho visible.
  • Define height/size o un alto explícito en el contenedor.

Labels se cortan

  • Aumenta margin.
  • Reduce fontSize o maxChars.
  • Usa rotate: "auto" en xLabels.

El tooltip no aparece

  • Revisa que el chart esté dentro de ChartProvider.
  • Verifica que no haya un contenedor con overflow: hidden tapando el portal.

Tailwind v4 no aplica estilos

  • Verifica que estés importando @import "tailwindcss"; en tu CSS.
  • Asegúrate de tener el plugin @tailwindcss/vite si usas Vite.
  • Define los tokens CSS (--foreground, --border, --chart-1..12) o usa ChartProvider con theme.

Errores de imports en CSS

  • tw-animate-css: instala tw-animate-css o elimina el import.
  • shadcn/tailwind.css: no es un paquete npm. Usa tus propios tokens o copia los de shadcn en un CSS local.

Arquitectura Interna

  • ChartRoot maneja escalas, layout, grid, ejes y leyendas en charts cartesianos.
  • PolarChartRoot se usa en charts radiales como pie, donut y radar.
  • ChartCanvasRoot permite layouts customizados sin ejes ni grid por defecto.
  • ChartContext distribuye scales, innerWidth/Height, tooltip, legend y datos.
  • Primitivos desacoplados: bars, lines, dots, grids, labels, tooltips.

Playground

pnpm install
pnpm run dev

Scripts

  • pnpm run dev ejecuta la lib y el playground en paralelo
  • pnpm run dev:lib build en watch
  • pnpm run dev:playground playground con Vite
  • pnpm run build build de la librería
  • pnpm run test vitest

Contribución

  • pnpm run build y pnpm run test antes de abrir PR.
  • Mantén el tipado estricto activo en tsconfig.json.

Licencia

Pendiente.