@aleric.dev/ui 0.0.0-stage → 0.1.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.
Files changed (39) hide show
  1. package/README.md +120 -2
  2. package/bin/cli.cjs +145 -0
  3. package/dist/components/atoms/Badge.d.ts +9 -0
  4. package/dist/components/atoms/Button.d.ts +11 -0
  5. package/dist/components/atoms/Card.d.ts +5 -0
  6. package/dist/components/atoms/Input.d.ts +8 -0
  7. package/dist/components/atoms/Modal.d.ts +34 -0
  8. package/dist/components/atoms/Select.d.ts +34 -0
  9. package/dist/components/atoms/SocialIcons.d.ts +7 -0
  10. package/dist/components/atoms/Spinner.d.ts +6 -0
  11. package/dist/components/atoms/StatusToggle.d.ts +9 -0
  12. package/dist/components/atoms/Textarea.d.ts +6 -0
  13. package/dist/components/atoms/Toggle.d.ts +9 -0
  14. package/dist/components/atoms/index.d.ts +11 -0
  15. package/dist/components/index.d.ts +4 -0
  16. package/dist/components/molecules/ConfirmDialog.d.ts +13 -0
  17. package/dist/components/molecules/DatePicker.d.ts +14 -0
  18. package/dist/components/molecules/EmptyState.d.ts +10 -0
  19. package/dist/components/molecules/FormField.d.ts +10 -0
  20. package/dist/components/molecules/MarkdownRenderer.d.ts +7 -0
  21. package/dist/components/molecules/MetricStatCard.d.ts +10 -0
  22. package/dist/components/molecules/MetricStrip.d.ts +15 -0
  23. package/dist/components/molecules/SearchInput.d.ts +10 -0
  24. package/dist/components/molecules/StatusBadge.d.ts +13 -0
  25. package/dist/components/molecules/index.d.ts +9 -0
  26. package/dist/components/organisms/NotificationCenter.d.ts +22 -0
  27. package/dist/components/organisms/Sidebar.d.ts +37 -0
  28. package/dist/components/organisms/TopNav.d.ts +23 -0
  29. package/dist/components/organisms/index.d.ts +3 -0
  30. package/dist/components/templates/AppLayout.d.ts +8 -0
  31. package/dist/components/templates/StudioLayout.d.ts +8 -0
  32. package/dist/components/templates/index.d.ts +2 -0
  33. package/dist/favicon.svg +24 -0
  34. package/dist/index.cjs +206 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.js +6611 -0
  37. package/dist/ui.css +1 -0
  38. package/dist/utils/cn.d.ts +2 -0
  39. package/package.json +69 -4
package/README.md CHANGED
@@ -1,3 +1,121 @@
1
- # Temporary Holding Version
1
+ # @aleric.dev/ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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' | '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,5 @@
1
+ import React from 'react';
2
+ export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
3
+ hover?: boolean;
4
+ }
5
+ export declare const Card: React.FC<CardProps>;
@@ -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,6 @@
1
+ import React from 'react';
2
+ export interface SpinnerProps {
3
+ size?: 'sm' | 'md' | 'lg';
4
+ className?: string;
5
+ }
6
+ export declare const Spinner: React.FC<SpinnerProps>;
@@ -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,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,9 @@
1
+ import React from 'react';
2
+ export interface ToggleProps {
3
+ checked: boolean;
4
+ onChange: (checked: boolean) => void;
5
+ disabled?: boolean;
6
+ size?: 'sm' | 'md';
7
+ className?: string;
8
+ }
9
+ export declare const Toggle: React.FC<ToggleProps>;
@@ -0,0 +1,11 @@
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';
@@ -0,0 +1,4 @@
1
+ export * from './atoms';
2
+ export * from './molecules';
3
+ export * from './organisms';
4
+ export * from './templates';
@@ -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 FormFieldProps {
3
+ label?: string;
4
+ error?: string;
5
+ helperText?: string;
6
+ required?: boolean;
7
+ className?: string;
8
+ children: React.ReactNode;
9
+ }
10
+ export declare const FormField: React.FC<FormFieldProps>;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export interface MarkdownRendererProps {
3
+ content: string;
4
+ articleTitle?: string;
5
+ className?: string;
6
+ }
7
+ export declare const MarkdownRenderer: React.FC<MarkdownRendererProps>;
@@ -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,10 @@
1
+ import React from 'react';
2
+ export interface SearchInputProps {
3
+ value: string;
4
+ onChange: (value: string) => void;
5
+ placeholder?: string;
6
+ className?: string;
7
+ onClear?: () => void;
8
+ autoFocus?: boolean;
9
+ }
10
+ export declare const SearchInput: React.FC<SearchInputProps>;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { BadgeVariant } from '../atoms/Badge';
3
+ export type GeneralStatus = 'pending' | 'ready' | 'published' | 'active' | 'inactive' | 'approved' | 'rejected' | 'open' | 'in_progress' | 'resolved' | 'closed';
4
+ export interface StatusBadgeProps {
5
+ status: GeneralStatus | string;
6
+ size?: 'xs' | 'sm' | 'md';
7
+ customConfig?: Record<string, {
8
+ label: string;
9
+ variant: BadgeVariant;
10
+ }>;
11
+ className?: string;
12
+ }
13
+ export declare const StatusBadge: React.FC<StatusBadgeProps>;
@@ -0,0 +1,9 @@
1
+ export * from './FormField';
2
+ export * from './SearchInput';
3
+ export * from './ConfirmDialog';
4
+ export * from './EmptyState';
5
+ export * from './MetricStatCard';
6
+ export * from './MetricStrip';
7
+ export * from './StatusBadge';
8
+ export * from './DatePicker';
9
+ export * from './MarkdownRenderer';
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ export interface NotificationItem {
3
+ id: string;
4
+ title: string;
5
+ description?: string;
6
+ timestamp?: string | Date;
7
+ read?: boolean;
8
+ type?: 'info' | 'success' | 'warning' | 'error';
9
+ tag?: string;
10
+ onAction?: () => void;
11
+ actionLabel?: string;
12
+ }
13
+ export interface NotificationCenterProps {
14
+ notifications: NotificationItem[];
15
+ unreadCount?: number;
16
+ onMarkAllAsRead?: () => void;
17
+ onNotificationClick?: (item: NotificationItem) => void;
18
+ emptyTitle?: string;
19
+ emptyDescription?: string;
20
+ className?: string;
21
+ }
22
+ export declare const NotificationCenter: React.FC<NotificationCenterProps>;
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ export interface NavItem {
3
+ id: string;
4
+ label: string;
5
+ icon: React.ReactNode;
6
+ active?: boolean;
7
+ badge?: string | number;
8
+ badgeVariant?: 'default' | 'success' | 'warning' | 'error';
9
+ href?: string;
10
+ onClick?: () => void;
11
+ }
12
+ export interface NavGroup {
13
+ id?: string;
14
+ label?: string;
15
+ items: NavItem[];
16
+ collapsible?: boolean;
17
+ defaultCollapsed?: boolean;
18
+ }
19
+ export interface SidebarBrand {
20
+ name?: string;
21
+ subtitle?: string;
22
+ logo?: React.ReactNode;
23
+ collapsedLogo?: React.ReactNode;
24
+ href?: string;
25
+ onClick?: () => void;
26
+ }
27
+ export interface SidebarProps {
28
+ brand?: SidebarBrand;
29
+ groups: NavGroup[];
30
+ footer?: React.ReactNode;
31
+ collapsed?: boolean;
32
+ onToggleCollapse?: () => void;
33
+ mobileOpen?: boolean;
34
+ onMobileClose?: () => void;
35
+ className?: string;
36
+ }
37
+ export declare const Sidebar: React.FC<SidebarProps>;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ export interface BreadcrumbItem {
3
+ label: string;
4
+ icon?: React.ReactNode;
5
+ href?: string;
6
+ onClick?: () => void;
7
+ color?: string;
8
+ }
9
+ export interface TopNavProps {
10
+ breadcrumbs?: BreadcrumbItem[];
11
+ title?: string;
12
+ subtitle?: string;
13
+ actions?: React.ReactNode;
14
+ userMenu?: React.ReactNode;
15
+ notificationSlot?: React.ReactNode;
16
+ themeToggle?: {
17
+ theme: 'dark' | 'light';
18
+ onToggle: () => void;
19
+ };
20
+ onMobileMenuToggle?: () => void;
21
+ className?: string;
22
+ }
23
+ export declare const TopNav: React.FC<TopNavProps>;
@@ -0,0 +1,3 @@
1
+ export * from './Sidebar';
2
+ export * from './TopNav';
3
+ export * from './NotificationCenter';