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

@core-tecnologias-empresariales/core-ui

v0.2.0

Published

Sistema visual transversal (design tokens, 11 temas oficiales, componentes) del ecosistema Core Tecnología Empresarial.

Readme

@core-tecnologias-empresariales/core-ui

Sistema visual transversal del ecosistema Core Tecnología Empresarial. Todos los productos (CorePyme, Core Tributario, Core Contador) consumen esta capa — no crean sistemas visuales paralelos.

Entradas del paquete

import { THEMES, applyTheme } from "@core-tecnologias-empresariales/core-ui";            // tokens/temas, sin React
import { Sheet, VerificationCodeInput } from "@core-tecnologias-empresariales/core-ui/components"; // capa React
import { tailwindPreset } from "@core-tecnologias-empresariales/core-ui/tailwind-preset";

Están separadas a propósito: un tailwind.config o un proceso backend importa los temas sin arrastrar React.

Los 11 temas oficiales

LIGHT: light-1 … light-6     DARK: dark-1 … dark-5

Transcritos literalmente del CLAUDE.md §8 — 110 valores de color, verificados por tests. Default: light-4 / dark-1.

Histórico: las versiones previas del documento maestro enumeraban un light-7 con paleta idéntica a light-5. Se resolvió como duplicación accidental y se eliminó del catálogo (decisión del 2026-08-29, registrada en CLAUDE.md). Un test impide que dos temas vuelvan a compartir paleta.

Uso

/* Una vez, en el entry CSS de la app */
@import "@core-tecnologias-empresariales/core-ui/styles/tokens.css";
import { applyTheme, THEME_IDS, defaultThemeFor } from "@core-tecnologias-empresariales/core-ui";

applyTheme(document.documentElement, "dark-1");   // cambia el tema, sin tocar componentes
defaultThemeFor("dark");                           // "dark-1"
THEME_IDS;                                         // para poblar un selector de temas

Cambiar de tema es escribir data-theme en el elemento raíz. Nunca requiere modificar un componente (CLAUDE.md §8). Sin data-theme, la hoja respeta prefers-color-scheme del sistema.

Tailwind

// tailwind.config.js del producto
import { tailwindPreset } from "@core-tecnologias-empresariales/core-ui/tailwind-preset";
export default { presets: [tailwindPreset], content: [...] };

Las clases quedan mapeadas a los tokens: bg-bg-200, text-text-100, text-primary, shadow-md, rounded-lg, z-drawer, font-mono. Un producto que escribe bg-[#123456] está violando la regla contra hardcoding (§8) — el preset existe para que no haga falta.

Tokens disponibles

| Grupo | Tokens | |---|---| | Paleta | --primary-100/200/300, --accent-100/200, --text-100/200, --bg-100/200/300 | | Semánticos | --color-success/warning/danger/info | | Estado | --color-border/muted/hover/active/focus/selected/disabled (derivados del tema) | | Tipografía | --font-sans (IBM Plex Sans), --font-mono (IBM Plex Mono) | | Escalas | --space-*, --radius-*, --shadow-*, --z-*, --breakpoint-*, --motion-* |

Los semánticos se definen una vez por modo (light/dark) en lugar de 4 × 12 temas: menos superficie, mismo resultado accesible. Los de estado se derivan del tema, así que nunca hay que hardcodearlos por producto.

Tipografía

El paquete define el stack (--font-sans / --font-mono) pero no empaqueta los archivos de fuente — cargarlos es decisión del producto (next/font, self-host o CDN), y evita arrastrar ~2MB de woff2 a todos los consumidores. Regla de uso: IBM Plex Sans para toda la interfaz, IBM Plex Mono solo para RUT, folios, IDs, códigos, JSON y logs.

Decisiones tomadas

  • Drawer: shadcn/ui Sheet sobre @radix-ui/react-dialog — CLAUDE.md §15 manda preferir shadcn/Radix. Google Analytics es la referencia de UX (§14), no de librería: se replica su comportamiento (panel lateral, scrim, header con cierre, cuerpo scrolleable, acciones abajo) sin traer Material, que rompería Tailwind y Lucide (§12).
  • Sin vaul — el bottom-sheet con gesto de arrastre es patrón móvil/consumer; el Sheet de Radix ya cubre móvil a ancho completo. Se agrega solo si la experiencia móvil lo pide.
  • Los temas se generan desde datos tipados, no se escriben a mano: src/themes.ts es la única fuente de verdad y alimenta tanto styles/tokens.css como el selector de temas.

Componentes (v0.2)

Sheet — panel lateral

El patrón principal de interacción del ecosistema, sobre @radix-ui/react-dialog (que aporta focus trap, cierre con Esc, scroll lock y ARIA sin código propio).

<Sheet>
  <SheetTrigger>Nuevo usuario</SheetTrigger>
  <SheetContent side="right">
    <SheetHeader>
      <SheetTitle>Nuevo usuario</SheetTitle>
      <SheetDescription>Completa los datos.</SheetDescription>
    </SheetHeader>
    <SheetBody>{/* formulario */}</SheetBody>
    <SheetFooter>
      <SheetClose>Cancelar</SheetClose>
      <button type="submit">Guardar</button>
    </SheetFooter>
  </SheetContent>
</Sheet>

Estructura Header / Body / Footer obligatoria: el cuerpo scrollea y el footer nunca se va de la vista. Ancho contenido en desktop (420px), full-width bajo sm. side acepta right (default), left, top, bottom.

Cuándo NO usarlo: procesos de múltiples etapas, navegación interna compleja o pantallas de trabajo completas — ahí va una página dedicada.

VerificationCodeInput — código de verificación

Para recuperación de contraseña y MFA. Placeholder de guiones y presentación monoespaciada según el documento maestro.

<VerificationCodeInput
  length={6}
  value={code}
  onChange={setCode}
  onComplete={(code) => verificar(code)}
  error={codigoInvalido}
/>

Implementado como un solo input monoespaciado, no como N casillas: el pegado del código, la navegación con teclado, el borrado y el autocompletado del SMS (autoComplete="one-time-code") los resuelve el input nativo. Las casillas segmentadas exigirían ~100 líneas de manejo de refs y foco para el mismo resultado visible.

No lleva maxLength: ese atributo cuenta caracteres crudos y truncaba un pegado con separadores ("48-39 20""48-39 ") antes de poder extraer los dígitos. El recorte se hace después de limpiar.

Resto de primitivos

Button (variants primary/secondary/ghost/danger/outline, loading, asChild para renderizar como <a>), Input, Textarea, Label (con required), Card/CardHeader/CardTitle/CardDescription/CardContent/CardFooter, Badge, Alert (con ícono propio por variante — el color nunca es el único indicador, CLAUDE.md §26), Skeleton, EmptyState, ErrorState, Tabs, Tooltip, Avatar, Dialog (confirmaciones/acciones destructivas, distinto de Sheet), DropdownMenu, Checkbox, RadioGroup, Switch, Progress (nativo, sin dependencia), Popover, Select.

Badge/Alert no usan fondos translúcidos (bg-danger/15): los tokens de color son hex planos y no soportan el modificador de opacidad de Tailwind sin convertirlos a rgb()+<alpha-value>. Usan fondo neutro + texto en el color semántico.

Aún no incluido

Toast, Combobox, DatePicker, DataTable, Form (wrapper RHF+Zod), Pagination, y los empresariales RutInput/CurrencyInput/PercentageInput/PhoneInput. Se agregan cuando core-dashboard/core-shell (o un producto) tengan un consumidor real que dicte su forma — no de manera especulativa.

Tests lentos bajo jsdom (conocido, no bloqueante)

Los tests de Tooltip, DropdownMenu, Select, Popover tardan más que el default de vitest: el detector de animaciones de Radix Presence (getAnimations()/animationend) no tiene equivalente real en jsdom y cae a un fallback lento (15-100s por test en este entorno). Se resolvió con dos técnicas, documentadas inline en cada archivo:

  • Controlar open directamente en vez de simular el toggle con click/hover, cuando el test no necesita verificar la transición en sí.
  • Timeout explícito por test cuando sí hace falta una interacción real (userEvent.click).

En corridas de la suite completa que superan ~10-15 min continuos, el canal RPC interno de vitest (worker↔main thread) puede caerse por agotamiento de recursos del sandbox (Timeout calling "onTaskUpdate"), típicamente durante el test de click de dropdown-menu.test.tsx — no es un fallo de aserción ni un bug del componente (su lógica es idéntica a la de Sheet/Dialog, verificados). Si aparece, correr ese archivo solo.

Desarrollo

pnpm build   # compila TS y regenera styles/tokens.css
pnpm test

styles/tokens.css es generado — no editarlo a mano; cambiar src/themes.ts o src/tokens.ts y rebuildear.