# Input

> Atom — orn-ui

> ⚠️ Requires <UIProvider>: This component (like every orn-ui component) must render inside a <UIProvider> ancestor, or it throws at runtime. See https://orn-ui-docs.vercel.app/getting-started.md

> Runs on Expo SDK 54, 55, 56 and 57, and on bare React Native >=0.81 with react >=19.1. No native modules — works in Expo Go, no prebuild.

## Installation

Install just this component (copies the source into your project, no npm dependency)
```bash
npx orn-ui add input
```

Or install the whole package and import it
```tsx
pnpm add orn-ui
import { Input } from 'orn-ui/input';
```

Depends on: core (theme + icons)

## Variants

### 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={() => {}} />
```

## Full demo source

```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

| Name | Type | Default | Description |
|---|---|---|---|
| `label?` | `string` | — | — |
| `required?` | `boolean` | false | Shows an asterisk next to the label. Purely visual — it does not validate anything. |
| `error?` | `string` | — | — |
| `containerStyle?` | `StyleProp<ViewStyle>` | — | — |
| `style?` | `StyleProp<TextStyle>` | — | — |
| `leftIconName?` | `IconName` | — | — |
| `rightIconName?` | `IconName` | — | — |
| `onRightIconPress?` | `() => void` | — | — |
| `isPassword?` | `boolean` | false | — |
| `isLoading?` | `boolean` | false | — |
