npm package: @jamx-framework/ui
Description: JAMX Framework â€” UI Component Library
Author: Stiven-21
Latest version: 1.1.0

# @jamx-framework/ui

## Descripción

Biblioteca de componentes UI para JAMX Framework. Proporciona un conjunto de componentes básicos (layout, tipografía, interactivos, feedback) y tokens de diseño (colores, espaciado, tipografía) para construir interfaces de usuario de forma consistente y type-safe. Todos los componentes están diseñados para funcionar con el renderer SSR de JAMX y son completamente personalizables.

## Cómo funciona

La biblioteca implementa componentes funcionales que retornan elementos JSX usando el runtime de `@jamx-framework/renderer`. Cada componente acepta props tipadas y aplica estilos mediante tokens o estilos en línea. Los tokens proporcionan valores consistentes para colores, espaciado y tipografía que pueden ser personalizados.

## Componentes principales

### Layout

- **Box**: Contenedor genérico con padding, margin, display, etc.
- **Stack**: Contenedor con layout vertical/horizontal y gap
- **Grid**: Grid system con columnas y gap

### Typography

- **Text**: Texto con variantes (body, caption, etc.)
- **Heading**: Encabezados h1-h6 con tokens de tamaño

### Interactive

- **Button**: Botón con variantes (primary, secondary, etc.)
- **Link**: Enlace con estilos consistentes
- **Input**: Campo de texto con validación visual

### Feedback

- **Alert**: Mensajes de alerta (info, success, warning, error)
- **Badge**: Etiquetas y contadores

### Tokens

- **colors**: Paleta de colores (primario, neutros, semánticos)
- **spacing**: Espaciado (margins, paddings)
- **typography**: Tamaños, pesos, familias de fuente

## Uso básico

### Instalación

```bash
pnpm add @jamx-framework/ui
```

### Importar componentes

```typescript
import { Box, Stack, Heading, Text, Button, Alert } from "@jamx-framework/ui";
import { jsx } from "@jamx-framework/renderer";
```

### Ejemplo: Página simple

```typescript
// src/pages/index.page.tsx
import { jsx, type RenderContext } from "@jamx-framework/renderer";
import { Heading, Text, Button, Stack } from "@jamx-framework/ui";

export default {
  render(_ctx: RenderContext) {
    return jsx("div", {
      class: "container",
      children: [
        jsx(Heading, { level: 1, children: "Bienvenido a JAMX" }),
        jsx(Text, {
          variant: "body",
          children: "Esta es una aplicación de ejemplo",
        }),
        jsx(Stack, {
          direction: "row",
          gap: "16px",
          children: [
            jsx(Button, { variant: "primary", children: "Empezar" }),
            jsx(Button, { variant: "secondary", children: "Aprender más" }),
          ],
        }),
      ],
    });
  },
};
```

### Ejemplo: Formulario

```typescript
import { jsx } from "@jamx-framework/renderer";
import { Box, Stack, Input, Button, Alert } from "@jamx-framework/ui";

export default {
  render(ctx) {
    return jsx("form", {
      onSubmit: handleSubmit,
      children: [
        jsx(Input, {
          name: "email",
          type: "email",
          placeholder: "Correo electrónico",
          required: true,
        }),
        jsx(Input, {
          name: "password",
          type: "password",
          placeholder: "Contraseña",
          required: true,
        }),
        jsx(Button, {
          type: "submit",
          variant: "primary",
          children: "Iniciar sesión",
        }),
        jsx(Alert, { variant: "error", children: "Credenciales inválidas" }),
      ],
    });
  },
};
```

### Ejemplo: Card component

```typescript
import { jsx } from "@jamx-framework/renderer";
import { Box, Heading, Text, Button } from "@jamx-framework/ui";

function Card(props: { title: string; children: string }) {
  return jsx(Box, {
    as: "article",
    padding: "24px",
    style: { border: "1px solid #e5e7eb", borderRadius: "8px" },
    children: [
      jsx(Heading, { level: 2, children: props.title }),
      jsx(Text, { variant: "body", children: props.children }),
      jsx(Button, { variant: "primary", children: "Acción" }),
    ],
  });
}
```

### Usar tokens

```typescript
import { colors, spacing, typography } from "@jamx-framework/ui";

// Colores
const primaryColor = colors.primary[500]; // #3b82f6
const successColor = colors.success[500]; // #22c55e

// Espaciado
const padding = spacing[4]; // 16px
const margin = spacing[8]; // 32px

// Tipografía
const fontSize = typography.fontSizes.lg; // 18px
const fontWeight = typography.fontWeights.semibold; // 600
```

## API Reference

### Componentes

#### Box

```typescript
interface BoxProps extends BaseProps {
  as?: string; // elemento HTML (default: 'div')
  padding?: string; // padding (ej: '16px', 'spacing[4]')
  margin?: string; // margin
  display?: "block" | "flex" | "grid" | "inline" | "inline-block" | "none";
  width?: string; // ancho (ej: '100%', '300px')
  height?: string; // alto
}
```

Contenedor genérico. Renderiza cualquier elemento HTML con estilos aplicados.

**Ejemplo:**

```typescript
jsx(Box, {
  as: "section",
  padding: spacing[6],
  display: "flex",
  children: "Contenido",
});
```

#### Stack

```typescript
interface StackProps extends BaseProps {
  direction?: "row" | "column"; // dirección del layout
  gap?: string; // espacio entre hijos
  align?: "start" | "center" | "end" | "stretch";
  justify?: "start" | "center" | "end" | "between" | "around";
  wrap?: boolean; // permitir wrap (solo row)
}
```

Contenedor con layout flex y gap automático.

**Ejemplo:**

```typescript
jsx(Stack, {
  direction: "row",
  gap: spacing[4],
  align: "center",
  children: [item1, item2, item3],
});
```

#### Grid

```typescript
interface GridProps extends BaseProps {
  columns?: number | string; // número de columnas o 'auto-fit'
  gap?: string; // espacio entre celdas
}
```

Grid system basado en CSS Grid.

**Ejemplo:**

```typescript
jsx(Grid, {
  columns: 3,
  gap: spacing[4],
  children: [item1, item2, item3, item4, item5, item6],
});
```

#### Text

```typescript
interface TextProps extends BaseProps {
  variant?: "body" | "caption" | "label" | "helper";
  size?: "sm" | "md" | "lg"; // override de tamaño
  weight?: "normal" | "medium" | "semibold" | "bold";
  color?: string; // color personalizado
}
```

Componente de texto con variantes predefinidas.

**Ejemplo:**

```typescript
jsx(Text, { variant: "body", children: "Texto normal" });
jsx(Text, { variant: "caption", children: "Texto pequeño" });
```

#### Heading

```typescript
interface HeadingProps extends BaseProps {
  level: 1 | 2 | 3 | 4 | 5 | 6; // nivel del encabezado (h1-h6)
  size?: "sm" | "md" | "lg" | "xl" | "2xl" | "3xl"; // override
  weight?: "normal" | "medium" | "semibold" | "bold";
}
```

Encabezados con jerarquía semántica.

**Ejemplo:**

```typescript
jsx(Heading, { level: 1, children: "Título principal" });
jsx(Heading, { level: 2, size: "lg", children: "Subtítulo" });
```

#### Button

```typescript
interface ButtonProps extends BaseProps {
  variant?: "primary" | "secondary" | "ghost" | "danger";
  size?: "sm" | "md" | "lg";
  type?: "button" | "submit" | "reset";
  disabled?: boolean;
  loading?: boolean; // mostrar spinner
  fullWidth?: boolean; // ancho 100%
}
```

Botón con estilos consistentes.

**Ejemplo:**

```typescript
jsx(Button, {
  variant: "primary",
  size: "md",
  onClick: handleClick,
  children: "Guardar",
});
```

#### Link

```typescript
interface LinkProps extends BaseProps {
  href: string;
  external?: boolean; // abrir en nueva pestaña
  underline?: boolean; // subrayado
}
```

Enlace con estilos de link.

**Ejemplo:**

```typescript
jsx(Link, {
  href: "/about",
  children: "Acerca de",
});

jsx(Link, {
  href: "https://example.com",
  external: true,
  children: "Ejemplo externo",
});
```

#### Input

```typescript
interface InputProps extends BaseProps {
  type?: "text" | "email" | "password" | "number" | "tel" | "url";
  name?: string;
  placeholder?: string;
  value?: string;
  defaultValue?: string;
  disabled?: boolean;
  required?: boolean;
  error?: boolean; // estado de error
  helperText?: string; // texto de ayuda
}
```

Campo de texto con validación visual.

**Ejemplo:**

```typescript
jsx(Input, {
  name: "email",
  type: "email",
  placeholder: "Correo electrónico",
  required: true,
  error: !isValid,
  helperText: isValid ? "" : "Correo inválido",
});
```

#### Alert

```typescript
interface AlertProps extends BaseProps {
  variant?: "info" | "success" | "warning" | "error";
  title?: string; // título opcional
  dismissible?: boolean; // mostrar botón cerrar
  onDismiss?: () => void;
}
```

Mensaje de alerta con variantes semánticas.

**Ejemplo:**

```typescript
jsx(Alert, {
  variant: "success",
  title: "Éxito",
  children: "Operación completada",
});
```

#### Badge

```typescript
interface BadgeProps extends BaseProps {
  variant?: "default" | "primary" | "success" | "warning" | "error";
  size?: "sm" | "md" | "lg";
  count?: number; // para contadores
  dot?: boolean; // punto de notificación
}
```

Etiqueta o contador.

**Ejemplo:**

```typescript
jsx(Badge, { variant: "primary", children: "Nuevo" });
jsx(Badge, { count: 5, children: "Notificaciones" });
```

### Tokens

#### colors

```typescript
export const colors = {
  // Paleta primaria (configurable)
  primary: {
    50: "#eff6ff",
    100: "#dbeafe",
    200: "#bfdbfe",
    300: "#93c5fd",
    400: "#60a5fa",
    500: "#3b82f6", // primario por defecto
    600: "#2563eb",
    700: "#1d4ed8",
    800: "#1e40af",
    900: "#1e3a8a",
  },

  // Colores semánticos
  success: {
    /* ... */
  },
  warning: {
    /* ... */
  },
  error: {
    /* ... */
  },
  info: {
    /* ... */
  },

  // Escala de grises
  gray: {
    50: "#f9fafb",
    100: "#f3f4f6",
    200: "#e5e7eb",
    300: "#d1d5db",
    400: "#9ca3af",
    500: "#6b7280",
    600: "#4b5563",
    700: "#374151",
    800: "#1f2937",
    900: "#111827",
  },
};
```

#### spacing

```typescript
export const spacing = {
  0: "0px",
  1: "4px",
  2: "8px",
  3: "12px",
  4: "16px",
  5: "20px",
  6: "24px",
  8: "32px",
  10: "40px",
  12: "48px",
  16: "64px",
  24: "96px",
  32: "128px",
};
```

#### typography

```typescript
export const typography = {
  fontSizes: {
    xs: "12px",
    sm: "14px",
    md: "16px",
    lg: "18px",
    xl: "20px",
    "2xl": "24px",
    "3xl": "30px",
    "4xl": "36px",
    "5xl": "48px",
    "6xl": "60px",
  },

  fontWeights: {
    normal: 400,
    medium: 500,
    semibold: 600,
    bold: 700,
  },

  lineHeights: {
    tight: 1.25,
    normal: 1.5,
    relaxed: 1.75,
  },

  fontFamilies: {
    sans: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
    mono: 'ui-monospace, SFMono-Regular, "SF Mono", monospace',
  },
};
```

### Utilidades

#### cx

```typescript
function cx(...classNames: (string | undefined | null | false)[]): string;
```

Combina classNames, filtrando falsy values.

**Ejemplo:**

```typescript
const className = cx("base-class", condition && "conditional", customClass);
```

#### sp

```typescript
function sp(token: SpacingToken): string;
```

Helper para obtener valores de spacing.

**Ejemplo:**

```typescript
import { sp } from "@jamx-framework/ui";

jsx(Box, { padding: sp(4) }); // '16px'
```

### Tipos

#### BaseProps

```typescript
interface BaseProps {
  class?: string; // clase CSS adicional
  className?: string; // alias de class
  style?: Record<string, string>; // estilos en línea
  testId?: string; // para testing (data-testid)
  id?: string; // ID HTML
  [key: string]: unknown; // otras props pasan al elemento
}
```

Props base que todos los componentes aceptan.

#### ColorVariant

```typescript
type ColorVariant =
  | "primary"
  | "secondary"
  | "success"
  | "warning"
  | "error"
  | "info";
```

#### Size

```typescript
type Size = "sm" | "md" | "lg" | "xl";
```

## Personalización

### Override de tokens

Puedes crear tus propios tokens:

```typescript
// theme.ts
import { createTheme } from "@jamx-framework/ui";

export const myTheme = createTheme({
  colors: {
    primary: {
      500: "#ff5722", // naranja personalizado
    },
  },
  spacing: {
    4: "20px", // spacing personalizado
  },
  typography: {
    fontSizes: {
      lg: "20px",
    },
  },
});
```

### Estilos personalizados

Todos los componentes aceptan `style` y `className`:

```typescript
jsx(Button, {
  variant: "primary",
  style: { borderRadius: "9999px" },
  className: "my-custom-button",
  children: "Botón",
});
```

### CSS Modules

Puedes usar CSS modules con los componentes:

```typescript
import styles from "./MyComponent.module.css";

jsx(Box, {
  class: styles.container,
  children: jsx(Button, { class: styles.button, children: "Click" }),
});
```

## Ejemplos completos

### Layout con Stack y Grid

```typescript
import { jsx } from "@jamx-framework/renderer";
import { Box, Stack, Grid, Heading, Text, Card } from "@jamx-framework/ui";

export default {
  render(ctx) {
    return jsx(Box, {
      as: "main",
      padding: spacing[6],
      children: [
        jsx(Heading, { level: 1, children: "Dashboard" }),

        // Grid de cards
        jsx(Grid, {
          columns: { sm: 1, md: 2, lg: 3 },
          gap: spacing[4],
          children: [
            jsx(Card, { title: "Ventas", children: "$12,345" }),
            jsx(Card, { title: "Usuarios", children: "1,234" }),
            jsx(Card, { title: "Pedidos", children: "567" }),
          ],
        }),

        // Stack vertical
        jsx(Stack, {
          direction: "column",
          gap: spacing[4],
          children: [
            jsx(Heading, { level: 2, children: "Actividad reciente" }),
            jsx(Text, { variant: "body", children: "No hay actividad" }),
          ],
        }),
      ],
    });
  },
};
```

### Formulario con validación

```typescript
import { jsx, useState } from "@jamx-framework/renderer";
import { Box, Stack, Input, Button, Alert } from "@jamx-framework/ui";

export default {
  async render(ctx) {
    return jsx(Box, {
      as: "form",
      onSubmit: handleSubmit,
      children: [
        jsx(Input, {
          name: "email",
          type: "email",
          placeholder: "Correo electrónico",
          value: email,
          onChange: (e: React.ChangeEvent<HTMLInputElement>) =>
            setEmail(e.target.value),
          error: !!error,
          helperText: error,
        }),
        jsx(Button, {
          type: "submit",
          variant: "primary",
          disabled: !email,
          children: "Enviar",
        }),
      ],
    });
  },
};
```

### Componente Card reutilizable

```typescript
import { jsx } from "@jamx-framework/renderer";
import { Box, Stack, Heading, Text, Button } from "@jamx-framework/ui";

interface CardProps {
  title: string;
  description: string;
  actionLabel?: string;
  onAction?: () => void;
}

function Card({ title, description, actionLabel, onAction }: CardProps) {
  return jsx(Box, {
    as: "article",
    padding: spacing[6],
    style: {
      border: `1px solid ${colors.gray[200]}`,
      borderRadius: "8px",
      boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
    },
    children: [
      jsx(Heading, { level: 3, children: title }),
      jsx(Text, {
        variant: "body",
        style: { marginTop: spacing[3] },
        children: description,
      }),
      actionLabel &&
        jsx(Button, {
          variant: "primary",
          onClick: onAction,
          style: { marginTop: spacing[4] },
          children: actionLabel,
        }),
    ],
  });
}
```

### Alertas con dismiss

```typescript
import { jsx, useState } from "@jamx-framework/renderer";
import { Alert, Button, Stack } from "@jamx-framework/ui";

export default {
  render(ctx) {
    const [showSuccess, setShowSuccess] = useState(true);

    return jsx(Stack, {
      direction: "column",
      gap: spacing[3],
      children: [
        showSuccess &&
          jsx(Alert, {
            variant: "success",
            title: "Éxito",
            dismissible: true,
            onDismiss: () => setShowSuccess(false),
            children: "Cambios guardados correctamente",
          }),

        jsx(Button, {
          variant: "primary",
          onClick: () => setShowSuccess(true),
          children: "Mostrar alerta",
        }),
      ],
    });
  },
};
```

### Badge con contador

```typescript
import { jsx } from "@jamx-framework/renderer";
import { Badge, Button, Stack } from "@jamx-framework/ui";

export default {
  render(ctx) {
    return jsx(Stack, {
      direction: "row",
      gap: spacing[4],
      children: [
        jsx(Button, { variant: "primary", children: "Inbox" }),
        jsx(Badge, { count: 5, children: "Notificaciones" }),
        jsx(Badge, { variant: "success", children: "Activo" }),
        jsx(Badge, { variant: "error", children: "Error" }),
      ],
    });
  },
};
```

## Diseño y tokens

### Sistema de diseño

La biblioteca sigue un sistema de diseño basado en tokens:

- **Colores**: Escala de 50-900 + colores semánticos (success, warning, error, info)
- **Espaciado**: Escala de 0-32 (0px a 128px)
- **Tipografía**: Tamaños xs-6xl, pesos normal/semibold/bold, line-heights

### Customización global

Para cambiar el tema global, puedes:

1. **Modificar los archivos de tokens** (si tienes acceso al código fuente)
2. **Usar CSS variables** y sobreescribir en tu hoja de estilos:

```css
:root {
  --color-primary-500: #ff5722;
  --spacing-4: 20px;
  --font-size-lg: 20px;
}
```

3. **Crear un wrapper de componentes** con tus estilos por defecto:

```typescript
function MyButton(props: ButtonProps) {
  return jsx(Button, {
    ...props,
    style: { borderRadius: "9999px", ...props.style },
  });
}
```

## Testing

### Tests unitarios

```typescript
import { describe, it, expect } from "vitest";
import { render } from "@jamx-framework/testing";
import { Button, Alert } from "@jamx-framework/ui";

describe("Button", () => {
  it("should render with primary variant", () => {
    const html = render(jsx(Button, { variant: "primary", children: "Click" }));
    expect(html).toContain('class="btn btn-primary"');
  });

  it("should be disabled when disabled prop", () => {
    const html = render(jsx(Button, { disabled: true, children: "Click" }));
    expect(html).toContain("disabled");
  });
});
```

### Tests de integración

```typescript
import { createTestServer } from "@jamx-framework/testing";
import { Button } from "@jamx-framework/ui";

// Testear que los componentes se renderizan correctamente en el servidor
```

## Accesibilidad

Los componentes están diseñados con accesibilidad en mente:

- **Box**: Usa `as` para cambiar elemento semántico (section, article, etc.)
- **Button**: Usa `<button>` nativo con type correcto
- **Link**: Usa `<a>` con href
- **Input**: Usa `<input>` con label implícito (placeholder) o explícito
- **Heading**: Jerarquía h1-h6 semántica
- **Alert**: Usa `role="alert"` automáticamente

### Ejemplo accesible

```typescript
jsx(Box, { as: "main" }, [
  jsx(Heading, { level: 1 }, "Título principal"),
  jsx(Input, {
    name: "email",
    type: "email",
    placeholder: "Correo electrónico",
    "aria-label": "Correo electrónico",
    required: true,
  }),
  jsx(Button, { type: "submit" }, "Enviar"),
]);
```

## Limitaciones

### Sin CSS framework integrado

- No incluye Tailwind, CSS Modules, o styled-components
- Los estilos son en línea o className manual
- Se recomienda usar con un sistema de estilos externo

### Componentes básicos

- Solo incluye componentes fundamentales
- No tiene componentes complejos (tables, modals, dropdowns, etc.)
- Para componentes avanzados, extender o usar otra biblioteca

### Sin JavaScript interactivo

- Los componentes son estáticos (no tienen estado interno)
- Para interactividad, usar hooks de JAMX o estado externo

### Renderer dependency

- Depende de `@jamx-framework/renderer`
- No funciona con React, Vue, etc.

## Buenas prácticas

### 1. Usar tokens en lugar de valores hardcodeados

```typescript
// ✅ Bien
jsx(Box, { padding: spacing[4] });

// ❌ No
jsx(Box, { padding: "16px" });
```

### 2. Componer componentes

```typescript
// ✅ Bien: crear componentes compuestos
function UserCard({ user }) {
  return jsx(Box, {
    as: "article",
    children: [
      jsx(Heading, { level: 3, children: user.name }),
      jsx(Text, { variant: "body", children: user.email }),
      jsx(Button, { variant: "primary", children: "Ver perfil" }),
    ],
  });
}

// ❌ No: repetir estructura
```

### 3. Usar variantes semánticas

```typescript
// ✅ Bien: usar variantes apropiadas
jsx(Alert, { variant: "error", children: "Error crítico" });
jsx(Button, { variant: "primary", children: "Guardar" });

// ❌ No: inventar variantes
jsx(Alert, { variant: "red", children: "Error" });
```

### 4. Proporcionar fallbacks

```typescript
// ✅ Bien: manejar datos undefined
jsx(Text, { variant: "body", children: user?.name ?? "Anónimo" });

// ❌ No: asumir datos
jsx(Text, { variant: "body", children: user.name });
```

### 5. Testear con testId

```typescript
jsx(Button, {
  testId: "login-submit",
  children: "Iniciar sesión",
});

// En tests
const button = screen.getByTestId("login-submit");
expect(button).toBeInTheDocument();
```

## Integración con otros paquetes

### Con `@jamx-framework/renderer`

```typescript
import { jsx } from "@jamx-framework/renderer";
import { Box, Text } from "@jamx-framework/ui";

const page = {
  render(ctx) {
    return jsx(Box, {
      padding: "16px",
      children: [jsx(Text, { children: "Hello" })],
    });
  },
};
```

### Con `@jamx-framework/server`

```typescript
import { JamxServer } from "@jamx-framework/server";
import { Box, Heading } from "@jamx-framework/ui";

const server = await JamxServer.create();

server.use(async (req, res) => {
  const html = render(
    jsx(Box, {}, jsx(Heading, { level: 1, children: "Hello" })),
  );
  res.send(html);
});
```

### Con `@jamx-framework/testing`

```typescript
import { render } from "@jamx-framework/testing";
import { Button } from "@jamx-framework/ui";

test("renders button", () => {
  const html = render(jsx(Button, { children: "Click" }));
  expect(html).toContain("Click");
});
```

## Roadmap futuro

- [ ] Componentes adicionales: Select, Checkbox, Radio, Modal, Dropdown, Table
- [ ] Soporte para dark mode con tokens de color
- [ ] Animaciones y transiciones
- [ ] Accesibilidad mejorada (ARIA, focus management)
- [ ] Internacionalización (i18n) integrada
- [ ] Soporte para CSS-in-JS (emotion, styled-components)
- [ ] Componentes de formulario completos (Form, Field, FieldGroup)
- [ ] Data display: List, Card, Avatar, AvatarGroup
- [ ] Navigation: Tabs, Breadcrumb, Pagination
- [ ] Layout: Divider, Spacer, Container

## Contribución

Para añadir un nuevo componente:

1. Crear archivo en `src/components/<category>/<ComponentName>.ts`
2. Definir interface de props que extienda `BaseProps`
3. Implementar componente como función que retorna `JamxElement`
4. Exportar desde `src/index.ts`
5. Añadir tests en `tests/unit/components/`
6. Documentar en este README

## Archivos importantes

- `src/index.ts` - Punto de entrada
- `src/components/` - Componentes organizados por categoría
- `src/tokens/` - Tokens de diseño
- `src/types.ts` - Tipos compartidos
- `tests/unit/components/` - Tests de componentes

## Dependencias

- `@jamx-framework/renderer` - Para jsx y tipos
- `@types/node` - Tipos de Node.js
- `vitest` - Testing

## Scripts del paquete

- `pnpm build` - Compila TypeScript
- `pnpm dev` - Watch mode
- `pnpm test` - Tests unitarios
- `pnpm test:watch` - Tests en watch
- `pnpm type-check` - Verificar tipos
- `pnpm clean` - Limpiar build

## Ejemplo completo de aplicación

```typescript
// src/pages/dashboard.page.tsx
import { jsx } from "@jamx-framework/renderer";
import {
  Box,
  Stack,
  Grid,
  Heading,
  Text,
  Button,
  Alert,
  Badge,
  Input,
} from "@jamx-framework/ui";
import { colors, spacing, typography } from "@jamx-framework/ui";

export default {
  render(ctx) {
    return jsx(Box, { as: "div", padding: spacing[6] }, [
      // Header
      jsx(Stack, {
        direction: "row",
        justify: "between",
        align: "center",
        style: { marginBottom: spacing[8] },
        children: [
          jsx(Heading, { level: 1, children: "Dashboard" }),
          jsx(Button, { variant: "primary", children: "Nuevo" }),
        ],
      }),

      // Stats grid
      jsx(Grid, {
        columns: { sm: 1, md: 2, lg: 4 },
        gap: spacing[4],
        children: [
          jsx(Box, {
            as: "div",
            padding: spacing[4],
            style: { background: colors.gray[50] },
            children: [
              jsx(Text, { variant: "caption", children: "Usuarios" }),
              jsx(Heading, { level: 2, children: "1,234" }),
            ],
          }),
          jsx(Box, {
            as: "div",
            padding: spacing[4],
            style: { background: colors.gray[50] },
            children: [
              jsx(Text, { variant: "caption", children: "Ingresos" }),
              jsx(Heading, { level: 2, children: "$12,345" }),
            ],
          }),
        ],
      }),

      // Alert
      jsx(Alert, {
        variant: "info",
        title: "Bienvenido",
        children: "Esta es tu dashboard personal",
      }),

      // Search
      jsx(Input, {
        placeholder: "Buscar...",
        style: { maxWidth: "300px" },
      }),
    ]);
  },
};
```

<!-- ## Comparación con otras bibliotecas

| Característica | JAMX UI | Material-UI | Chakra UI | Tailwind CSS |
| -------------- | ------- | ----------- | --------- | ------------ |
| Framework      | JAMX    | React       | React     | Agnostico    |
| Componentes    | Básicos | Completo    | Completo  | Ninguno      |
| Tokens         | Sí      | Sí          | Sí        | No           |
| SSR            | Sí      | Sí          | Sí        | Sí           |
| TypeScript     | Nativo  | Nativo      | Nativo    | No           |
| Tamaño         | Pequeño | Grande      | Medio     | Variable     | -->

## Conclusión

`@jamx-framework/ui` proporciona un conjunto minimalista pero poderoso de componentes y tokens para construir interfaces de usuario en JAMX. Su diseño modular y type-safe lo hace ideal para aplicaciones que necesitan consistencia visual sin el overhead de bibliotecas grandes.