# Input

> Atom — orn-ui

> ⚠️ Requiere <UIProvider>: Este componente (como todos los de orn-ui) debe renderizarse dentro de un ancestro <UIProvider>, o lanza un error en runtime. See https://orn-ui-docs.vercel.app/getting-started.md

> Corre en Expo SDK 54, 55, 56 y 57, y en React Native puro >=0.81 con react >=19.1. Sin módulos nativos — funciona en Expo Go, sin prebuild.

## Instalación

Instala solo este componente (copia el código fuente a tu proyecto, sin dependencia npm)
```bash
npx orn-ui add input
```

O instala el paquete completo e impórtalo
```tsx
pnpm add orn-ui
import { Input } from 'orn-ui/input';
```

Depende de: core (theme + icons)

## Variantes

### Default

```tsx
<Input label="Email" required placeholder="you@example.com" value={email} onChangeText={setEmail} leftIconName="info" />
```

### Password

```tsx
<Input label="Password" isPassword value={password} onChangeText={setPassword} />
```

### Clearable

```tsx
<Input
  label="Search"
  value={search}
  onChangeText={setSearch}
  leftIconName="search"
  rightIconName={search.length > 0 ? 'close' : undefined}
  onRightIconPress={() => setSearch('')}
/>
```

### Error

```tsx
<Input label="Email" error="This field is required" value="" onChangeText={() => {}} />
```

### Loading

```tsx
<Input label="Checking availability" isLoading value="" onChangeText={() => {}} />
```

### Read-only

```tsx
<Input label="Read-only" value="Cannot be edited" editable={false} onChangeText={() => {}} />
```

## Código completo del demo

```tsx
const variants: VariantDef[] = [
  {
    label: 'Default',
    content: (
      <Input label="Email" required placeholder="you@example.com" value={email} onChangeText={setEmail} leftIconName="info" />
    ),
  },
  { label: 'Password', content: <Input label="Password" isPassword value={password} onChangeText={setPassword} /> },
  {
    label: 'Clearable',
    content: (
      <Input
        label="Search"
        value={search}
        onChangeText={setSearch}
        leftIconName="search"
        rightIconName={search.length > 0 ? 'close' : undefined}
        onRightIconPress={() => setSearch('')}
      />
    ),
  },
  { label: 'Error', content: <Input label="Email" error="This field is required" value="" onChangeText={() => {}} /> },
  { label: 'Loading', content: <Input label="Checking availability" isLoading value="" onChangeText={() => {}} /> },
  { label: 'Read-only', content: <Input label="Read-only" value="Cannot be edited" editable={false} onChangeText={() => {}} /> },
];
return <VariantList variants={variants} />;
```

## Props

| Nombre | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `label?` | `string` | — | — |
| `required?` | `boolean` | false | Muestra un asterisco junto al label. Puramente visual, no valida nada. |
| `error?` | `string` | — | — |
| `containerStyle?` | `StyleProp<ViewStyle>` | — | — |
| `style?` | `StyleProp<TextStyle>` | — | — |
| `leftIconName?` | `IconName` | — | — |
| `rightIconName?` | `IconName` | — | — |
| `onRightIconPress?` | `() => void` | — | — |
| `isPassword?` | `boolean` | false | — |
| `isLoading?` | `boolean` | false | — |
