@juanarenas31/metrik-ui 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Universidad Simón Bolívar · Unidad de Ciencia de los Datos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
package/README.md ADDED
@@ -0,0 +1,268 @@
1
+ # @juanarenas31/metrik-ui
2
+
3
+ > Librería de componentes React para construir **dashboards analíticos** de la Unidad de Ciencia de los Datos · Universidad Simón Bolívar.
4
+
5
+ [![npm](https://img.shields.io/badge/npm-v0.1.0-0a4838)](#)
6
+ [![license](https://img.shields.io/badge/license-MIT-2bbfa0)](./LICENSE)
7
+ [![types](https://img.shields.io/badge/types-included-f26b7a)](#)
8
+
9
+ Inspirada en shadcn/ui · Radix · Mantine. Construida sobre **React 18+ · TypeScript · TailwindCSS · Radix Primitives · CVA**.
10
+
11
+ ---
12
+
13
+ ## ✨ Características
14
+
15
+ - **22+ componentes** accesibles (ARIA · keyboard · focus visible)
16
+ - **Tokens semánticos** para light + dark mode con un sólo `.dark` en `<html>`
17
+ - **Tree-shakeable** · cada componente se importa de su sub-path
18
+ - **`forwardRef` + `asChild`** en todo lo interactivo
19
+ - **Sistema de variantes tipadas** con `class-variance-authority`
20
+ - **TypeScript 5** estricto · types incluidos
21
+ - **Preset de Tailwind** plug-and-play · mapea tokens a clases utility
22
+ - **Hooks reutilizables** · `useTheme`, `useDisclosure`, `useMediaQuery`, `useDebounce`, `useLocalStorage`…
23
+
24
+ ---
25
+
26
+ ## 📦 Instalación
27
+
28
+ ```bash
29
+ # pnpm
30
+ pnpm add @juanarenas31/metrik-ui
31
+
32
+ # npm
33
+ npm install @juanarenas31/metrik-ui
34
+
35
+ # yarn
36
+ yarn add @juanarenas31/metrik-ui
37
+ ```
38
+
39
+ **peerDependencies** que debes tener instaladas:
40
+
41
+ ```bash
42
+ pnpm add react react-dom tailwindcss
43
+ ```
44
+
45
+ ---
46
+
47
+ ## 🚀 Setup en 3 pasos
48
+
49
+ ### 1 · Importa los estilos base
50
+
51
+ En tu archivo de estilos global (`globals.css` o `index.css`):
52
+
53
+ ```css
54
+ @import "@juanarenas31/metrik-ui/styles.css";
55
+
56
+ @tailwind base;
57
+ @tailwind components;
58
+ @tailwind utilities;
59
+ ```
60
+
61
+ > Solo necesitas el preset si quieres usar las clases utility (`bg-primary`, `text-fg-muted`, etc.). Si prefieres usar las CSS variables directamente, importa únicamente `tokens.css`.
62
+
63
+ ### 2 · Agrega el preset de Tailwind
64
+
65
+ En `tailwind.config.ts`:
66
+
67
+ ```ts
68
+ import metrikPreset from "@juanarenas31/metrik-ui/tailwind-preset";
69
+ import type { Config } from "tailwindcss";
70
+
71
+ export default {
72
+ presets: [metrikPreset],
73
+ content: [
74
+ "./src/**/*.{ts,tsx}",
75
+ "./node_modules/@juanarenas31/metrik-ui/dist/**/*.js",
76
+ ],
77
+ } satisfies Config;
78
+ ```
79
+
80
+ ### 3 · Empieza a usar componentes
81
+
82
+ ```tsx
83
+ import { Button, Card, CardHeader, CardTitle, CardContent, Badge } from "@juanarenas31/metrik-ui";
84
+ import { TrendingUp } from "lucide-react";
85
+
86
+ export function KPI() {
87
+ return (
88
+ <Card className="max-w-sm">
89
+ <CardHeader>
90
+ <div className="flex items-center justify-between">
91
+ <CardTitle>Estudiantes activos</CardTitle>
92
+ <Badge tone="primary" dot>+4.2%</Badge>
93
+ </div>
94
+ </CardHeader>
95
+ <CardContent>
96
+ <div className="text-3xl font-semibold tabular-nums">12 488</div>
97
+ <Button variant="outline" size="sm" className="mt-4" leftIcon={<TrendingUp />}>
98
+ Ver tendencia
99
+ </Button>
100
+ </CardContent>
101
+ </Card>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## 🌗 Dark mode
109
+
110
+ ```tsx
111
+ import { useTheme, Switch } from "@juanarenas31/metrik-ui";
112
+
113
+ export function ThemeToggle() {
114
+ const { resolvedTheme, toggleTheme } = useTheme();
115
+ return (
116
+ <Switch
117
+ checked={resolvedTheme === "dark"}
118
+ onCheckedChange={toggleTheme}
119
+ aria-label="Cambiar tema"
120
+ />
121
+ );
122
+ }
123
+ ```
124
+
125
+ Para evitar el "flash of unstyled content" en SSR, inyecta este script en tu `<head>`:
126
+
127
+ ```html
128
+ <script>
129
+ (function () {
130
+ var t = localStorage.getItem("metrik-theme") || "system";
131
+ var d = t === "dark" || (t === "system" && matchMedia("(prefers-color-scheme: dark)").matches);
132
+ document.documentElement.classList.toggle("dark", d);
133
+ document.documentElement.classList.toggle("light", !d);
134
+ })();
135
+ </script>
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 📚 Componentes
141
+
142
+ | Componente | Sub-path | Descripción |
143
+ |-------------------|---------------------------------------|----------------------------------------------|
144
+ | `Alert` | `@juanarenas31/metrik-ui` | Avisos · info · success · warning · danger |
145
+ | `Avatar` | `@juanarenas31/metrik-ui` | Imagen de usuario con fallback |
146
+ | `Badge` | `@juanarenas31/metrik-ui` | Etiquetas pequeñas · 7 tonos · 3 tamaños |
147
+ | `Button` | `@juanarenas31/metrik-ui` | 6 variantes · 4 tamaños · loading · iconos |
148
+ | `Card` | `@juanarenas31/metrik-ui` | Compound · Header/Title/Description/Content/Footer |
149
+ | `Checkbox` | `@juanarenas31/metrik-ui` | Checkbox accesible · indeterminate |
150
+ | `Dialog` | `@juanarenas31/metrik-ui` | Modal · focus trap · scroll-lock · portal |
151
+ | `DropdownMenu` | `@juanarenas31/metrik-ui` | Menú con checkbox · radio · sub-menús |
152
+ | `Input` | `@juanarenas31/metrik-ui` | Input texto · 3 tamaños · estados error/success |
153
+ | `Label` | `@juanarenas31/metrik-ui` | Label semántico · required |
154
+ | `Popover` | `@juanarenas31/metrik-ui` | Popover con anchor opcional |
155
+ | `Select` | `@juanarenas31/metrik-ui` | Select accesible · grupos · keyboard nav |
156
+ | `Separator` | `@juanarenas31/metrik-ui` | Línea divisoria · horizontal/vertical |
157
+ | `Skeleton` | `@juanarenas31/metrik-ui` | Loading placeholder con shimmer |
158
+ | `Spinner` | `@juanarenas31/metrik-ui` | Indicador de carga · 4 tamaños |
159
+ | `Switch` | `@juanarenas31/metrik-ui` | Toggle on/off |
160
+ | `Tabs` | `@juanarenas31/metrik-ui` | Tabs · underline o pill |
161
+ | `Textarea` | `@juanarenas31/metrik-ui` | Textarea con estado invalid |
162
+ | `Tooltip` | `@juanarenas31/metrik-ui` | Tooltip · provider + content |
163
+
164
+ ### Hooks
165
+
166
+ | Hook | Descripción |
167
+ |---------------------|---------------------------------------------------------------|
168
+ | `useTheme` | Light · dark · system con persistencia en localStorage |
169
+ | `useDisclosure` | Estado open/close para overlays |
170
+ | `useMediaQuery` | Suscríbete a media queries · incluye `useBreakpoint.lg()` |
171
+ | `useDebounce` | Valor debounced · útil para búsquedas |
172
+ | `useLocalStorage` | Estado sincronizado con localStorage |
173
+ | `useClickOutside` | Cierra paneles cuando el usuario hace click afuera |
174
+ | `useToggle` | Helper para booleanos |
175
+
176
+ ### Utilidades
177
+
178
+ | Export | Descripción |
179
+ |--------------|---------------------------------------------------------------|
180
+ | `cn(...)` | Combina clases de Tailwind resolviendo conflictos (twMerge) |
181
+ | `cva` | Re-export de class-variance-authority |
182
+
183
+ ---
184
+
185
+ ## 🎨 Tokens
186
+
187
+ Los tokens se exponen como **CSS variables**. Puedes usarlos:
188
+
189
+ - vía clases utility de Tailwind (`bg-primary`, `text-fg-muted`, `border-border`…)
190
+ - vía variables CSS directas (`var(--metrik-primary)`, `var(--metrik-fg)`…)
191
+
192
+ ### Color · semántico
193
+
194
+ | Token | Light | Dark | Uso |
195
+ |--------------------|------------------|------------------|------------------------------|
196
+ | `--metrik-bg` | slate-50 | slate-950 | Fondo de la app |
197
+ | `--metrik-surface` | white | slate-900 | Cards, panels |
198
+ | `--metrik-surface-muted` | slate-100 | slate-800 | Hover states |
199
+ | `--metrik-border` | slate-200 | slate-700 | Bordes sutiles |
200
+ | `--metrik-fg` | slate-800 | slate-50 | Texto principal |
201
+ | `--metrik-fg-muted` | slate-500 | slate-400 | Texto secundario |
202
+ | `--metrik-primary` | teal-500 | teal-400 | CTA principal |
203
+ | `--metrik-accent` | coral-500 | coral-400 | Resaltar, alertas |
204
+ | `--metrik-success` | teal-600 | teal-400 | Estados positivos |
205
+ | `--metrik-danger` | coral-600 | coral-400 | Errores, destructivos |
206
+ | `--metrik-warning` | amber-500 | amber-300 | Advertencias |
207
+
208
+ ### Radius · shadow · motion
209
+
210
+ `rounded-{sm,md,lg,xl,full}` · `shadow-{xs,sm,md,lg}` · `duration-{fast,base,slow}` · `ease-metrik`
211
+
212
+ ### Z-index
213
+
214
+ `z-{sticky,dropdown,overlay,modal,toast}` · 10 · 100 · 1000 · 1100 · 1500
215
+
216
+ ---
217
+
218
+ ## 🔧 Tree-shaking
219
+
220
+ Para máximo control sobre el bundle, importa por sub-path cuando trabajes con bundlers que no eliminan barrels eficientemente:
221
+
222
+ ```ts
223
+ // re-export root (~ tree-shake estándar)
224
+ import { Button } from "@juanarenas31/metrik-ui";
225
+
226
+ // alternativa equivalente · idéntico resultado con esbuild/vite/turbopack
227
+ import { Button } from "@juanarenas31/metrik-ui";
228
+ ```
229
+
230
+ Todos los componentes están marcados como side-effect-free excepto los archivos `.css`, lo cual permite a tu bundler eliminar cualquier componente no usado.
231
+
232
+ ---
233
+
234
+ ## 🛠️ Desarrollo local
235
+
236
+ ```bash
237
+ git clone <repo>
238
+ cd metrik-ui
239
+ pnpm install
240
+ pnpm dev # tsup watch
241
+ pnpm typecheck
242
+ pnpm lint
243
+ pnpm build
244
+ ```
245
+
246
+ ---
247
+
248
+ ## 📐 Convenciones
249
+
250
+ - **Naming** · `PascalCase` para componentes, `camelCase + use*` para hooks
251
+ - **Compound components** para piezas con múltiples partes (`Card.Header`, `Dialog.Footer`…)
252
+ - **`asChild` prop** disponible donde tiene sentido (Button, Trigger primitives) usando `Radix Slot`
253
+ - **Variantes** tipadas con `cva`, exportadas como `<Component>Variants` para extender
254
+
255
+ ---
256
+
257
+ ## 🗺️ Roadmap
258
+
259
+ - [ ] **v0.2** · DataTable · Toast · Drawer · Slider · DatePicker · FileUpload
260
+ - [ ] **v0.3** · Charts (recharts wrappers) · KPIWidget · StatsCard · ActivityFeed
261
+ - [ ] **v0.4** · Layouts pre-armados (DashboardLayout · AuthLayout · AdminLayout)
262
+ - [ ] **v1.0** · Documentación interactiva (Storybook + Astro Starlight) · CI/CD · npm público
263
+
264
+ ---
265
+
266
+ ## 📄 Licencia
267
+
268
+ [MIT](./LICENSE) © 2026 Universidad Simón Bolívar · Unidad de Ciencia de los Datos