@aleric.dev/ui 0.0.0-stage → 0.4.1
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/README.md +120 -2
- package/bin/cli.cjs +145 -0
- package/dist/components/atoms/Badge.d.ts +9 -0
- package/dist/components/atoms/Button.d.ts +11 -0
- package/dist/components/atoms/Card.d.ts +5 -0
- package/dist/components/atoms/Input.d.ts +8 -0
- package/dist/components/atoms/Modal.d.ts +34 -0
- package/dist/components/atoms/Select.d.ts +34 -0
- package/dist/components/atoms/SocialIcons.d.ts +7 -0
- package/dist/components/atoms/Spinner.d.ts +6 -0
- package/dist/components/atoms/StatusToggle.d.ts +9 -0
- package/dist/components/atoms/StepTimeline.d.ts +17 -0
- package/dist/components/atoms/Table.d.ts +13 -0
- package/dist/components/atoms/Tabs.d.ts +21 -0
- package/dist/components/atoms/Textarea.d.ts +6 -0
- package/dist/components/atoms/Toggle.d.ts +9 -0
- package/dist/components/atoms/index.d.ts +14 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/molecules/ConfirmDialog.d.ts +13 -0
- package/dist/components/molecules/DatePicker.d.ts +14 -0
- package/dist/components/molecules/EmptyState.d.ts +10 -0
- package/dist/components/molecules/FormField.d.ts +10 -0
- package/dist/components/molecules/MarkdownRenderer.d.ts +7 -0
- package/dist/components/molecules/MetricStatCard.d.ts +10 -0
- package/dist/components/molecules/MetricStrip.d.ts +15 -0
- package/dist/components/molecules/ModalSplitLayout.d.ts +44 -0
- package/dist/components/molecules/ModalStepLayout.d.ts +28 -0
- package/dist/components/molecules/SearchInput.d.ts +10 -0
- package/dist/components/molecules/StatusBadge.d.ts +13 -0
- package/dist/components/molecules/index.d.ts +11 -0
- package/dist/components/organisms/NotificationCenter.d.ts +22 -0
- package/dist/components/organisms/Sidebar.d.ts +41 -0
- package/dist/components/organisms/TopNav.d.ts +23 -0
- package/dist/components/organisms/index.d.ts +3 -0
- package/dist/components/templates/AppLayout.d.ts +8 -0
- package/dist/components/templates/StudioLayout.d.ts +8 -0
- package/dist/components/templates/index.d.ts +2 -0
- package/dist/favicon.svg +24 -0
- package/dist/index.cjs +211 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7251 -0
- package/dist/ui.css +1 -0
- package/dist/utils/cn.d.ts +2 -0
- package/package.json +71 -4
package/README.md
CHANGED
|
@@ -1,3 +1,121 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @aleric.dev/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Sistema de Diseño Atómico y Componentes UI Limpios para React 19 y Tailwind CSS**
|
|
4
|
+
|
|
5
|
+
`@aleric.dev/ui` es una biblioteca de componentes visuales desacoplados, 100% tipados con TypeScript y listos para construir dashboards modernos, paneles SaaS y aplicaciones multi-tenant sin dependencias de marcas propietarias.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📦 Instalación
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @aleric.dev/ui
|
|
13
|
+
# o con pnpm
|
|
14
|
+
pnpm add @aleric.dev/ui
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Importa la hoja de estilos en tu punto de entrada (`main.tsx` o `App.tsx`):
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import '@aleric.dev/ui/dist/styles.css';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🧩 Catálogo de Componentes
|
|
26
|
+
|
|
27
|
+
### 1. Átomos (`atoms`)
|
|
28
|
+
- **`Button`**: Variantes (`primary`, `secondary`, `outline`, `ghost`, `danger`), tamaños (`sm`, `md`, `lg`), estados de carga (`loading`) y slots para iconos.
|
|
29
|
+
- **`Badge`**: Variantes semánticas (`indigo`, `emerald`, `amber`, `rose`, `slate`), con soporte de indicador circular (`dot`).
|
|
30
|
+
- **`Card`**: Contenedores estructurados (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`) con soporte de hover.
|
|
31
|
+
- **`Input` / `Textarea`**: Entradas de formulario con estados de error, soporte monoespaciado y slots para iconos.
|
|
32
|
+
- **`Select`**: Dropdown estilizado para opciones tipadas.
|
|
33
|
+
- **`Toggle` / `StatusToggle`**: Interruptores accesibles para alternancia de estados de negocio.
|
|
34
|
+
- **`Modal`**: Diálogos accesibles con animación de entrada, backdrop y cierre con tecla Escape.
|
|
35
|
+
- **`Spinner`**: Indicador de carga animado.
|
|
36
|
+
- **`SocialIcon`**: Iconografía vectorial para redes y plataformas.
|
|
37
|
+
|
|
38
|
+
### 2. Moléculas (`molecules`)
|
|
39
|
+
- **`FormField`**: Wrapper de campo con etiqueta, indicador de requerido, textos de ayuda y manejo de errores.
|
|
40
|
+
- **`SearchInput`**: Input de búsqueda con icono de lupa y botón para limpiar texto.
|
|
41
|
+
- **`ConfirmDialog`**: Diálogo modal preconfigurado para confirmaciones o acciones críticas.
|
|
42
|
+
- **`EmptyState`**: Estado vacío elegante para listas y tablas con llamadas a la acción.
|
|
43
|
+
- **`MetricStatCard`**: Tarjetas de indicadores KPI con valores y tendencias de crecimiento.
|
|
44
|
+
- **`MetricStrip`**: Fila/rejilla responsive de métricas con separadores sutiles y acentos cromáticos.
|
|
45
|
+
- **`StatusBadge`**: Badge que mapea estados de ciclo de vida (`active`, `pending`, `ready`, `resolved`) con estilos consistentes.
|
|
46
|
+
- **`DatePicker`**: Selector de fechas con portal flotante y atajos rápidos (*"Hoy"*, *"Mañana"*, *"+1 Sem"*).
|
|
47
|
+
- **`MarkdownRenderer`**: Renderizador de texto enriquecido en markdown sanitizado.
|
|
48
|
+
|
|
49
|
+
### 3. Organismos (`organisms`)
|
|
50
|
+
- **`Sidebar`**: Barra de navegación lateral colapsable a iconos con tooltips emergentes, grupos jerárquicos (`NavGroup[]`), soporte responsive (drawer móvil con backdrop) y slots libres para logo de marca y pie de usuario.
|
|
51
|
+
- **`TopNav`**: Barra superior con navegación por migas de pan (`Breadcrumbs`), títulos dinámicos, botones de acción y switcher de tema.
|
|
52
|
+
- **`NotificationCenter`**: Centro de notificaciones desplegable con conteo de no leídas y filtrado de eventos.
|
|
53
|
+
|
|
54
|
+
### 4. Templates & Layouts (`templates`)
|
|
55
|
+
- **`AppLayout`**: Ensamblador maestro de pantalla completa que combina `Sidebar` + `TopNav` + área de contenido con scroll independiente y tema oscuro slate.
|
|
56
|
+
- **`StudioLayout`**: Layout de pantalla completa optimizado para editores y lienzos visuales.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 🚀 Ejemplo de Uso: Dashboard Multi-Tenant
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import React, { useState } from 'react';
|
|
64
|
+
import {
|
|
65
|
+
AppLayout,
|
|
66
|
+
Sidebar,
|
|
67
|
+
TopNav,
|
|
68
|
+
MetricStrip,
|
|
69
|
+
Card,
|
|
70
|
+
StatusBadge,
|
|
71
|
+
Button
|
|
72
|
+
} from '@aleric.dev/ui';
|
|
73
|
+
import { LayoutDashboard, Users, Activity } from 'lucide-react';
|
|
74
|
+
|
|
75
|
+
export function DashboardExample() {
|
|
76
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<AppLayout
|
|
80
|
+
sidebar={
|
|
81
|
+
<Sidebar
|
|
82
|
+
collapsed={collapsed}
|
|
83
|
+
onToggleCollapse={() => setCollapsed(!collapsed)}
|
|
84
|
+
brand={{
|
|
85
|
+
name: 'Acme Cloud',
|
|
86
|
+
logo: <div className="w-8 h-8 rounded-lg bg-indigo-600 text-white flex items-center justify-center font-bold">A</div>
|
|
87
|
+
}}
|
|
88
|
+
groups={[
|
|
89
|
+
{
|
|
90
|
+
label: 'General',
|
|
91
|
+
items: [
|
|
92
|
+
{ id: 'dash', label: 'Dashboard', icon: <LayoutDashboard className="w-4 h-4" />, active: true },
|
|
93
|
+
{ id: 'clients', label: 'Clientes', icon: <Users className="w-4 h-4" />, badge: 12 }
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]}
|
|
97
|
+
/>
|
|
98
|
+
}
|
|
99
|
+
topNav={<TopNav title="Panel Principal" />}
|
|
100
|
+
>
|
|
101
|
+
<div className="p-6 space-y-6">
|
|
102
|
+
<MetricStrip
|
|
103
|
+
items={[
|
|
104
|
+
{ label: 'MRR Activo', value: '$24,500', color: 'emerald' },
|
|
105
|
+
{ label: 'Usuarios Conectados', value: '1,280', color: 'indigo' }
|
|
106
|
+
]}
|
|
107
|
+
/>
|
|
108
|
+
<Card className="p-4">
|
|
109
|
+
<StatusBadge status="active" />
|
|
110
|
+
</Card>
|
|
111
|
+
</div>
|
|
112
|
+
</AppLayout>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 📄 Licencia
|
|
120
|
+
|
|
121
|
+
MIT © [Aleric Dev](https://aleric.dev)
|
package/bin/cli.cjs
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const REGISTRY = {
|
|
6
|
+
// 1. Átomos
|
|
7
|
+
'button': { file: 'atoms/Button.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
8
|
+
'badge': { file: 'atoms/Badge.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
9
|
+
'card': { file: 'atoms/Card.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
10
|
+
'input': { file: 'atoms/Input.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
11
|
+
'textarea': { file: 'atoms/Textarea.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
12
|
+
'select': { file: 'atoms/Select.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
13
|
+
'toggle': { file: 'atoms/Toggle.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
14
|
+
'status-toggle': { file: 'atoms/StatusToggle.tsx', deps: ['lucide-react'] },
|
|
15
|
+
'modal': { file: 'atoms/Modal.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
16
|
+
'spinner': { file: 'atoms/Spinner.tsx', deps: [] },
|
|
17
|
+
'social-icons': { file: 'atoms/SocialIcons.tsx', deps: [] },
|
|
18
|
+
|
|
19
|
+
// 2. Moléculas
|
|
20
|
+
'form-field': { file: 'molecules/FormField.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
21
|
+
'search-input': { file: 'molecules/SearchInput.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
22
|
+
'confirm-dialog': { file: 'molecules/ConfirmDialog.tsx', deps: ['lucide-react'], requires: ['modal', 'button'] },
|
|
23
|
+
'empty-state': { file: 'molecules/EmptyState.tsx', deps: ['clsx', 'tailwind-merge'], requires: ['button'] },
|
|
24
|
+
'metric-stat-card': { file: 'molecules/MetricStatCard.tsx', deps: ['clsx', 'tailwind-merge'], requires: ['card'] },
|
|
25
|
+
'metric-strip': { file: 'molecules/MetricStrip.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
26
|
+
'status-badge': { file: 'molecules/StatusBadge.tsx', deps: [], requires: ['badge'] },
|
|
27
|
+
'date-picker': { file: 'molecules/DatePicker.tsx', deps: ['lucide-react'] },
|
|
28
|
+
'markdown-renderer': { file: 'molecules/MarkdownRenderer.tsx', deps: ['marked'] },
|
|
29
|
+
|
|
30
|
+
// 3. Organismos
|
|
31
|
+
'sidebar': { file: 'organisms/Sidebar.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
32
|
+
'top-nav': { file: 'organisms/TopNav.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
33
|
+
'notification-center': { file: 'organisms/NotificationCenter.tsx', deps: ['clsx', 'tailwind-merge', 'lucide-react'] },
|
|
34
|
+
|
|
35
|
+
// 4. Templates
|
|
36
|
+
'app-layout': { file: 'templates/AppLayout.tsx', deps: ['clsx', 'tailwind-merge'] },
|
|
37
|
+
'studio-layout': { file: 'templates/StudioLayout.tsx', deps: ['clsx', 'tailwind-merge'] }
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const args = process.argv.slice(2);
|
|
41
|
+
const command = args[0];
|
|
42
|
+
|
|
43
|
+
console.log('\n💎 @aleric.dev/ui — Component Distribution CLI\n');
|
|
44
|
+
|
|
45
|
+
if (!command || command === '--help' || command === '-h') {
|
|
46
|
+
console.log('Uso:');
|
|
47
|
+
console.log(' npx @aleric.dev/ui init Inicializa el proyecto con la utilidad cn()');
|
|
48
|
+
console.log(' npx @aleric.dev/ui add <component> Añade un componente a src/components/ui/');
|
|
49
|
+
console.log(' npx @aleric.dev/ui list Lista todos los componentes disponibles\n');
|
|
50
|
+
console.log('Ejemplo:');
|
|
51
|
+
console.log(' npx @aleric.dev/ui add button');
|
|
52
|
+
console.log(' npx @aleric.dev/ui add sidebar');
|
|
53
|
+
console.log(' npx @aleric.dev/ui add metric-strip\n');
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (command === 'list') {
|
|
58
|
+
console.log('Componentes disponibles en el registro:');
|
|
59
|
+
console.log('---------------------------------------');
|
|
60
|
+
Object.keys(REGISTRY).forEach(name => {
|
|
61
|
+
const item = REGISTRY[name];
|
|
62
|
+
console.log(' • ' + name.padEnd(20) + '➔ src/components/' + item.file);
|
|
63
|
+
});
|
|
64
|
+
console.log('');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const targetCwd = process.cwd();
|
|
69
|
+
|
|
70
|
+
if (command === 'init') {
|
|
71
|
+
console.log('🚀 Inicializando configuración en ' + targetCwd);
|
|
72
|
+
|
|
73
|
+
// 1. Crear carpeta src/lib
|
|
74
|
+
const libDir = path.join(targetCwd, 'src', 'lib');
|
|
75
|
+
if (!fs.existsSync(libDir)) {
|
|
76
|
+
fs.mkdirSync(libDir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const utilsPath = path.join(libDir, 'utils.ts');
|
|
80
|
+
const utilsCode = 'import { clsx, type ClassValue } from "clsx";\nimport { twMerge } from "tailwind-merge";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n';
|
|
81
|
+
|
|
82
|
+
fs.writeFileSync(utilsPath, utilsCode, 'utf8');
|
|
83
|
+
console.log('✅ Creado: src/lib/utils.ts con la función cn()');
|
|
84
|
+
|
|
85
|
+
// 2. Crear directorio de componentes destino
|
|
86
|
+
const uiDir = path.join(targetCwd, 'src', 'components', 'ui');
|
|
87
|
+
if (!fs.existsSync(uiDir)) {
|
|
88
|
+
fs.mkdirSync(uiDir, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
console.log('✅ Directorio listo: src/components/ui/');
|
|
91
|
+
console.log('\n✨ Proyecto listo. Ahora añade componentes con: npx @aleric.dev/ui add <componente>\n');
|
|
92
|
+
process.exit(0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (command === 'add') {
|
|
96
|
+
const componentName = args[1]?.toLowerCase();
|
|
97
|
+
if (!componentName) {
|
|
98
|
+
console.error('❌ Debes especificar un componente. Ej: npx @aleric.dev/ui add button');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const meta = REGISTRY[componentName];
|
|
103
|
+
if (!meta) {
|
|
104
|
+
console.error('❌ El componente "' + componentName + '" no existe en el registro.');
|
|
105
|
+
console.log('Ejecuta "npx @aleric.dev/ui list" para ver la lista completa.');
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Leer el componente fuente desde el paquete @aleric.dev/ui
|
|
110
|
+
const sourcePath = path.resolve(__dirname, '..', 'src', 'components', meta.file);
|
|
111
|
+
if (!fs.existsSync(sourcePath)) {
|
|
112
|
+
console.error('❌ Archivo fuente no encontrado: ' + sourcePath);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let code = fs.readFileSync(sourcePath, 'utf8');
|
|
117
|
+
|
|
118
|
+
// Adaptar imports relativos a la convención estándar @/lib/utils o local
|
|
119
|
+
code = code.replace(/\.\.\/\.\.\/utils\/cn/g, '@/lib/utils');
|
|
120
|
+
code = code.replace(/\.\.\/utils\/cn/g, '@/lib/utils');
|
|
121
|
+
|
|
122
|
+
const destDir = path.join(targetCwd, 'src', 'components', 'ui');
|
|
123
|
+
if (!fs.existsSync(destDir)) {
|
|
124
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const destFile = path.basename(meta.file);
|
|
128
|
+
const destPath = path.join(destDir, destFile);
|
|
129
|
+
|
|
130
|
+
fs.writeFileSync(destPath, code, 'utf8');
|
|
131
|
+
console.log('✅ Componente instalado en: src/components/ui/' + destFile);
|
|
132
|
+
|
|
133
|
+
if (meta.deps && meta.deps.length > 0) {
|
|
134
|
+
console.log('📦 Asegúrate de tener instaladas las dependencias: ' + meta.deps.join(', '));
|
|
135
|
+
}
|
|
136
|
+
if (meta.requires && meta.requires.length > 0) {
|
|
137
|
+
console.log('🔗 Este componente utiliza otros átomos. Te recomendamos añadir también:');
|
|
138
|
+
meta.requires.forEach(req => console.log(' npx @aleric.dev/ui add ' + req));
|
|
139
|
+
}
|
|
140
|
+
console.log('');
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.error('❌ Comando no reconocido: ' + command);
|
|
145
|
+
process.exit(1);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type BadgeVariant = 'default' | 'primary' | 'emerald' | 'indigo' | 'amber' | 'rose' | 'slate' | 'outline';
|
|
3
|
+
export type BadgeSize = 'xs' | 'sm' | 'md';
|
|
4
|
+
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
5
|
+
variant?: BadgeVariant;
|
|
6
|
+
size?: BadgeSize;
|
|
7
|
+
dot?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const Badge: React.FC<BadgeProps>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'emerald' | 'amber' | 'danger' | 'ghost' | 'outline';
|
|
3
|
+
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
size?: ButtonSize;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
iconPosition?: 'left' | 'right';
|
|
9
|
+
loading?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const Button: React.FC<ButtonProps>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
3
|
+
error?: boolean;
|
|
4
|
+
mono?: boolean;
|
|
5
|
+
leftIcon?: React.ReactNode;
|
|
6
|
+
rightIcon?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl';
|
|
3
|
+
export interface ModalProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
size?: ModalSize;
|
|
8
|
+
className?: string;
|
|
9
|
+
closeOnBackdropClick?: boolean;
|
|
10
|
+
asForm?: boolean;
|
|
11
|
+
onSubmit?: (e: React.FormEvent) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const Modal: React.FC<ModalProps>;
|
|
14
|
+
export interface ModalHeaderProps {
|
|
15
|
+
title: React.ReactNode;
|
|
16
|
+
subtitle?: React.ReactNode;
|
|
17
|
+
icon?: React.ReactNode;
|
|
18
|
+
onClose?: () => void;
|
|
19
|
+
action?: React.ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const ModalHeader: React.FC<ModalHeaderProps>;
|
|
23
|
+
export interface ModalBodyProps {
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
className?: string;
|
|
26
|
+
noPadding?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare const ModalBody: React.FC<ModalBodyProps>;
|
|
29
|
+
export declare const ModalContent: React.FC<ModalBodyProps>;
|
|
30
|
+
export interface ModalFooterProps {
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare const ModalFooter: React.FC<ModalFooterProps>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface SelectOption {
|
|
3
|
+
value: string;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export type SelectChangeEvent = {
|
|
9
|
+
target: {
|
|
10
|
+
value: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export interface SelectProps {
|
|
15
|
+
value?: string;
|
|
16
|
+
defaultValue?: string;
|
|
17
|
+
onChange?: (e: SelectChangeEvent) => void;
|
|
18
|
+
onValueChange?: (value: string) => void;
|
|
19
|
+
options?: SelectOption[];
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
helperText?: string;
|
|
25
|
+
icon?: React.ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
buttonClassName?: string;
|
|
28
|
+
dropdownClassName?: string;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
name?: string;
|
|
31
|
+
id?: string;
|
|
32
|
+
size?: 'sm' | 'md';
|
|
33
|
+
}
|
|
34
|
+
export declare const Select: React.FC<SelectProps>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface SocialIconProps extends React.SVGAttributes<SVGSVGElement> {
|
|
3
|
+
name: 'github' | 'linkedin' | 'whatsapp' | 'x' | 'youtube';
|
|
4
|
+
size?: number;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const SocialIcon: React.FC<SocialIconProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type IdeaStatus = 'pending' | 'ready' | 'published';
|
|
3
|
+
export interface StatusToggleProps {
|
|
4
|
+
status: IdeaStatus;
|
|
5
|
+
onChange: (status: IdeaStatus) => void;
|
|
6
|
+
compact?: boolean;
|
|
7
|
+
fullWidth?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const StatusToggle: React.FC<StatusToggleProps>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface StepItem {
|
|
3
|
+
id: string | number;
|
|
4
|
+
number: number;
|
|
5
|
+
title: string;
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
badge?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface StepTimelineProps {
|
|
10
|
+
steps: StepItem[];
|
|
11
|
+
currentStep: number;
|
|
12
|
+
completedSteps?: number[];
|
|
13
|
+
onStepClick?: (stepNumber: number) => void;
|
|
14
|
+
allowStepBack?: boolean;
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const StepTimeline: React.FC<StepTimelineProps>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
|
|
3
|
+
containerClassName?: string;
|
|
4
|
+
wrapper?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const Table: React.ForwardRefExoticComponent<TableProps & React.RefAttributes<HTMLTableElement>>;
|
|
7
|
+
export declare const TableHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
|
|
8
|
+
export declare const TableBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
|
|
9
|
+
export declare const TableFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
|
|
10
|
+
export declare const TableRow: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableRowElement> & React.RefAttributes<HTMLTableRowElement>>;
|
|
11
|
+
export declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
|
|
12
|
+
export declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
|
|
13
|
+
export declare const TableCaption: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableCaptionElement> & React.RefAttributes<HTMLTableCaptionElement>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface TabItem<T extends string = string> {
|
|
3
|
+
id: T;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
badge?: React.ReactNode;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type TabsVariant = 'segmented' | 'underline' | 'pills';
|
|
10
|
+
export type TabsSize = 'sm' | 'md' | 'lg';
|
|
11
|
+
export interface TabsProps<T extends string = string> {
|
|
12
|
+
tabs: TabItem<T>[];
|
|
13
|
+
activeTab: T;
|
|
14
|
+
onChange: (tabId: T) => void;
|
|
15
|
+
variant?: TabsVariant;
|
|
16
|
+
size?: TabsSize;
|
|
17
|
+
fullWidth?: boolean;
|
|
18
|
+
className?: string;
|
|
19
|
+
tabClassName?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function Tabs<T extends string = string>({ tabs, activeTab, onChange, variant, size, fullWidth, className, tabClassName, }: TabsProps<T>): React.JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
3
|
+
error?: boolean;
|
|
4
|
+
mono?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './Button';
|
|
2
|
+
export * from './Badge';
|
|
3
|
+
export * from './Card';
|
|
4
|
+
export * from './Input';
|
|
5
|
+
export * from './Textarea';
|
|
6
|
+
export * from './Select';
|
|
7
|
+
export * from './Toggle';
|
|
8
|
+
export * from './StatusToggle';
|
|
9
|
+
export * from './Modal';
|
|
10
|
+
export * from './Spinner';
|
|
11
|
+
export * from './SocialIcons';
|
|
12
|
+
export * from './StepTimeline';
|
|
13
|
+
export * from './Table';
|
|
14
|
+
export * from './Tabs';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ConfirmDialogProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
onConfirm: () => void;
|
|
6
|
+
title: string;
|
|
7
|
+
message: string;
|
|
8
|
+
confirmText?: string;
|
|
9
|
+
cancelText?: string;
|
|
10
|
+
variant?: 'danger' | 'primary' | 'warning';
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const ConfirmDialog: React.FC<ConfirmDialogProps>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface DatePickerProps {
|
|
3
|
+
value: string;
|
|
4
|
+
onChange: (value: string) => void;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
minDate?: string;
|
|
7
|
+
maxDate?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
showShortcuts?: boolean;
|
|
11
|
+
align?: 'left' | 'right';
|
|
12
|
+
size?: 'sm' | 'md' | 'lg';
|
|
13
|
+
}
|
|
14
|
+
export declare const DatePicker: React.FC<DatePickerProps>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface EmptyStateProps {
|
|
3
|
+
icon?: React.ReactNode;
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
actionText?: string;
|
|
7
|
+
onAction?: () => void;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const EmptyState: React.FC<EmptyStateProps>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface MetricStatCardProps {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string | number;
|
|
5
|
+
subtitle?: string;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
iconColor?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const MetricStatCard: React.FC<MetricStatCardProps>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface MetricItem {
|
|
3
|
+
id?: string;
|
|
4
|
+
label: string;
|
|
5
|
+
value: string | number;
|
|
6
|
+
subtext?: React.ReactNode;
|
|
7
|
+
icon?: React.ElementType;
|
|
8
|
+
badge?: string;
|
|
9
|
+
color?: 'indigo' | 'emerald' | 'amber' | 'rose' | 'slate';
|
|
10
|
+
}
|
|
11
|
+
export interface MetricStripProps {
|
|
12
|
+
items: MetricItem[];
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const MetricStrip: React.FC<MetricStripProps>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ModalSplitRatio = '5/7' | '6/6' | '4/8' | '7/5';
|
|
3
|
+
export type ModalSplitMobileMode = 'tabs' | 'stack';
|
|
4
|
+
export interface ModalSplitLayoutProps {
|
|
5
|
+
/** Título de la columna izquierda (o Tab 1 en móvil) */
|
|
6
|
+
leftTitle: React.ReactNode;
|
|
7
|
+
/** Icono opcional para la columna izquierda */
|
|
8
|
+
leftIcon?: React.ReactNode;
|
|
9
|
+
/** Badge o conteo opcional para la columna izquierda */
|
|
10
|
+
leftBadge?: React.ReactNode;
|
|
11
|
+
/** Título de la columna derecha (o Tab 2 en móvil) */
|
|
12
|
+
rightTitle: React.ReactNode;
|
|
13
|
+
/** Icono opcional para la columna derecha */
|
|
14
|
+
rightIcon?: React.ReactNode;
|
|
15
|
+
/** Badge o conteo opcional para la columna derecha */
|
|
16
|
+
rightBadge?: React.ReactNode;
|
|
17
|
+
/** Relación de columnas en Desktop (>= 1024px) */
|
|
18
|
+
ratio?: ModalSplitRatio;
|
|
19
|
+
/** Comportamiento en Mobile (< 1024px): 'tabs' (pestañas segmentadas) o 'stack' (vertical fluido) */
|
|
20
|
+
mobileMode?: ModalSplitMobileMode;
|
|
21
|
+
/** Pestaña activa controlada */
|
|
22
|
+
activeTab?: 'left' | 'right';
|
|
23
|
+
/** Pestaña activa inicial si no es controlada */
|
|
24
|
+
defaultActiveTab?: 'left' | 'right';
|
|
25
|
+
/** Callback al cambiar de pestaña en móvil */
|
|
26
|
+
onTabChange?: (tab: 'left' | 'right') => void;
|
|
27
|
+
/** Contenido de la columna izquierda */
|
|
28
|
+
leftContent: React.ReactNode;
|
|
29
|
+
/** Pie o barra de botones anclada en la columna izquierda */
|
|
30
|
+
leftFooter?: React.ReactNode;
|
|
31
|
+
/** Clases adicionales para la columna izquierda */
|
|
32
|
+
leftClassName?: string;
|
|
33
|
+
/** Cabecera opcional para la columna derecha */
|
|
34
|
+
rightHeader?: React.ReactNode;
|
|
35
|
+
/** Contenido de la columna derecha */
|
|
36
|
+
rightContent: React.ReactNode;
|
|
37
|
+
/** Pie opcional para la columna derecha */
|
|
38
|
+
rightFooter?: React.ReactNode;
|
|
39
|
+
/** Clases adicionales para la columna derecha */
|
|
40
|
+
rightClassName?: string;
|
|
41
|
+
/** Clases adicionales para el contenedor raíz */
|
|
42
|
+
className?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare const ModalSplitLayout: React.FC<ModalSplitLayoutProps>;
|