dc78d8fea3
Componentes React reutilizables: card, dialog, tabs, select, alert, badge, button, input, label, skeleton, tooltip, progress_bar, page_header, form_field, settings_page, crud_page, analytics_page, dashboard_layout. Charts: area, bar, line, sparkline, kpi_card, chart_container. Hooks Wails: use_wails_query, use_wails_mutation, use_wails_stream, use_wails_event, use_animated_canvas. Funciones core: cn, format_compact, chart_colors, get_series_color, wails_cache, theme_config_to_colors. Tipos: chart_series, wails_ipc, theme_config, component_variants. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68 lines
1.6 KiB
TypeScript
68 lines
1.6 KiB
TypeScript
import * as React from 'react'
|
|
import { cn } from '../core/cn'
|
|
|
|
interface DashboardWidget {
|
|
id: string
|
|
title?: string
|
|
span?: 1 | 2 | 3 | 4
|
|
rowSpan?: 1 | 2
|
|
content: React.ReactNode
|
|
}
|
|
|
|
interface DashboardLayoutProps {
|
|
widgets: DashboardWidget[]
|
|
columns?: 1 | 2 | 3 | 4
|
|
gap?: 'sm' | 'md' | 'lg'
|
|
className?: string
|
|
}
|
|
|
|
const gapClasses = { sm: 'gap-2', md: 'gap-4', lg: 'gap-6' }
|
|
|
|
const spanClasses: Record<number, string> = {
|
|
1: 'col-span-1',
|
|
2: 'col-span-1 md:col-span-2',
|
|
3: 'col-span-1 md:col-span-2 lg:col-span-3',
|
|
4: 'col-span-1 md:col-span-2 lg:col-span-4',
|
|
}
|
|
|
|
const rowSpanClasses: Record<number, string> = {
|
|
1: 'row-span-1',
|
|
2: 'row-span-2',
|
|
}
|
|
|
|
export function dashboardLayout({
|
|
widgets,
|
|
columns = 4,
|
|
gap = 'md',
|
|
className,
|
|
}: DashboardLayoutProps): React.ReactElement {
|
|
const gridCols: Record<number, string> = {
|
|
1: 'grid-cols-1',
|
|
2: 'grid-cols-1 md:grid-cols-2',
|
|
3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
|
|
4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4',
|
|
}
|
|
|
|
return (
|
|
<div className={cn('grid', gridCols[columns], gapClasses[gap], className)}>
|
|
{widgets.map((widget) => (
|
|
<div
|
|
key={widget.id}
|
|
className={cn(
|
|
'rounded-xl border bg-card p-4 text-card-foreground shadow-sm',
|
|
spanClasses[widget.span || 1],
|
|
rowSpanClasses[widget.rowSpan || 1]
|
|
)}
|
|
>
|
|
{widget.title && (
|
|
<h3 className="mb-3 text-sm font-medium text-muted-foreground">{widget.title}</h3>
|
|
)}
|
|
{widget.content}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export type { DashboardWidget, DashboardLayoutProps }
|