# InputToolBar (Mobile)

A **UI-only** horizontal toolbar for text-input UIs on mobile (e.g. chat, composer, search). Built with gluestack-ui and NativeWind. All data and behavior come from props; the component does not know about modes, methods, or app logic.

## Layout

When `inputConfig` or `children` is provided:

- **First row**: Optional `topContent`, then built-in TextInput (if `inputConfig` is set) or `children`.
- **Second row**: Left section (`leftItems` + optional `templateButton`) and right section (`rightItems` + optional `micSendButton`).

When neither is provided, a single toolbar row is rendered. Parent passes `leftItems` and `rightItems` with full config (e.g. `active`, `onClick`, `enabled`) and optional helpers `getDefaultLeftItems` / `getDefaultRightItems`.

## Installation

The component is part of `@admin-layout/gluestack-ui-mobile`:

```ts
import { InputToolBar, getDefaultLeftItems, getDefaultRightItems } from '@admin-layout/gluestack-ui-mobile';
```

## Props

All data and behavior are passed from the parent. No internal mode or method logic.

| Prop                          | Type                                        | Description                                                                                                                                                                                  |
| ----------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `className`                   | `string`                                    | Optional class for the toolbar container (merged with `classNames.container`).                                                                                                               |
| `classNames`                  | `InputToolBarClassNames`                    | Optional class overrides per section for theme (light/dark) or custom styling.                                                                                                               |
| `inputConfig`                 | `InputConfig \| null`                       | When set, a built-in TextInput is rendered; pass value, onChange, etc.                                                                                                                       |
| `topContent`                  | `ReactNode`                                 | Rendered above the input when `inputConfig` is set.                                                                                                                                          |
| `leftItems`                   | `ToolbarItemConfig<LeftToolbarItemId>[]`    | Left section items (active, onClick, etc. from parent).                                                                                                                                      |
| `rightItems`                  | `ToolbarItemConfig<RightToolbarItemId>[]`   | Right section items (onClick, etc. from parent).                                                                                                                                             |
| `templateButton`              | `TemplateButtonConfig \| null`              | Optional "+ Template (count)" pill; data from parent.                                                                                                                                        |
| `leftCustomRender`            | `ReactNode`                                 | Custom left content (overrides `leftItems`).                                                                                                                                                 |
| `rightCustomRender`           | `ReactNode`                                 | Custom right content (overrides `rightItems` and `micSendButton`).                                                                                                                           |
| `micSendButton`               | `MicSendButtonConfig \| null`               | Rightmost button (Stop/Send/Mic); all data and handlers from parent.                                                                                                                         |
| `projectSettingsModalOpen`    | `boolean`                                   | When true, the project settings modal (from `projectSettingsModalRender`) is shown. Set by parent when projectSettings is clicked.                                                           |
| `onProjectSettingsModalClose` | `() => void`                                | Called when the project settings modal should close (overlay/close button).                                                                                                                  |
| `projectSettingsModalRender`  | `(props: { onClose }) => ReactNode \| null` | Renders the project settings modal content (e.g. Configuration / Other Settings / Secret). Parent passes config and onChange so values update via parent (same pattern as ModelConfigPanel). |
| `children`                    | `ReactNode`                                 | Optional middle content when not using `inputConfig`.                                                                                                                                        |
| `onContainerClick`            | `(e) => void`                               | Called when the container is clicked (e.g. to focus input).                                                                                                                                  |

## Theme and class overrides

Default styles use gluestack-ui tokens (`$primary500`, `$background100`, `$outline200`, etc.) so the toolbar works in both **light and dark** themes. Buttons and the template pill use borders and backgrounds that stay visible in either mode.

To override from outside, pass **`classNames`**:

```ts
interface InputToolBarClassNames {
    container?: string; // root section
    leftGroup?: string; // left section wrapper
    templatePill?: string; // "+ Template (N)" button
    templatePillSelected?: string; // selected/suggested pill
    leftButtonActive?: string; // left mode button – active
    leftButtonInactive?: string; // left mode button – inactive
    rightButton?: string; // right toolbar button – default
    rightButtonActive?: string; // right toolbar button – active
    rightButtonDisabled?: string; // right toolbar button – disabled
    micSendButton?: string; // primary mic/send button
}
```

## Types

### ToolbarItemConfig

```ts
interface ToolbarItemConfig<TId> {
    id: TId;
    label: string;
    icon?: ReactNode;
    enabled?: boolean; // default true; when false, the item is not rendered and takes no space
    disabled?: boolean;
    loading?: boolean;
    active?: boolean; // dark/primary style when true
    onClick?: () => void;
    customButton?: ReactNode; // use instead of icon when provided
}
```

### LeftToolbarItemId

`'search' | 'zap' | 'lightbulb' | 'template'`

### RightToolbarItemId

`'projectSettings' | 'tag' | 'chip' | 'camera' | 'image' | 'attach' | 'mic'`

- **projectSettings** – Project settings (gear icon). **Disabled by default.** Enable with `getDefaultRightItems({ projectSettings: { enabled: true, onClick: () => setProjectSettingsModalOpen(true) } })`.
- **tag** – Enhance prompt with AI
- **chip** – Configure chat model
- **camera** – Capture image / screenshot
- **image** – Insert image / picture
- **attach** – Attach file (paperclip)
- **mic** – Mic (or replaced by micSendButton)

### InputConfig (React Native)

```ts
interface InputConfig {
    value: string;
    onChange: (e: NativeSyntheticEvent<TextInputChangeEventData>) => void;
    placeholder?: string;
    disabled?: boolean;
    onKeyDown?: (e: any) => void;
    onPaste?: (e: any) => void;
    id?: string;
    name?: string;
    inputRef?: React.RefObject<any>;
}
```

> **Note:** Unlike the web version, `onChange` receives a React Native event. Use `e.nativeEvent.text` to get the value.

### MicSendButtonConfig

```ts
interface MicSendButtonConfig {
    hasContent: boolean;
    onSend: () => void;
    onMic: () => void;
    disabled?: boolean;
    isLoading?: boolean; // when true, show Stop icon and call onStop
    onStop?: () => void;
}
```

### Template visibility (build mode)

The template button should only be visible when the user is in **build mode** (lightbulb/workflow). The parent controls this by passing `templateButton` only when `activeMode === 'workflow'`:

```tsx
templateButton={
    activeMode === 'workflow'
        ? { label: '+ Template', count: templates.length, onClick: openTemplateModal }
        : null
}
```

### TemplateButtonConfig

```ts
interface TemplateButtonConfig {
    label: string; // e.g. "+ Template" when no selection
    count?: number; // e.g. (1)
    selectedLabel?: string | null; // when set, show selected template pill (name + remove + change)
    onClick?: () => void; // open modal; also "change" when selected
    onClearTemplate?: () => void; // when selected, called on remove (X)
    disabled?: boolean;
}
```

### Template selection modal

When you pass **`templateModalConfig`**, InputToolBar renders a built-in modal with search, category filters, and a grid of template items. Each item needs: `id`, `label`, optional `description`, optional `category` (`TemplateModalItem`). Pass **`templateModalRender`** to use your own custom modal UI.

## Helpers

- **`getDefaultLeftItems(overrides?)`** – Returns default left items (search, zap, lightbulb). Override per id: `label`, `enabled`, `active`, `onClick`, `icon`, `customButton`.
- **`getDefaultRightItems(overrides?)`** – Returns default right items (tag, chip, camera, image, attach, mic). Override per id (e.g. `image: { enabled: false }` or `image: { onClick: handleInsertImage }`).

When using `micSendButton`, the parent typically omits `mic` from `rightItems` (e.g. `mic: { enabled: false }` in overrides) so the mic/send button is the rightmost action.

## Examples

### Basic usage with input

```tsx
import { InputToolBar, getDefaultLeftItems, getDefaultRightItems } from '@admin-layout/gluestack-ui-mobile';

const [value, setValue] = useState('');
const textareaRef = useRef<any>(null);

const leftItems = getDefaultLeftItems({
    search: { active: activeMode === 'chat', onClick: () => setMode('chat') },
    zap: { active: activeMode === 'deep-search', onClick: () => setMode('deep-search') },
    lightbulb: { active: activeMode === 'workflow', onClick: () => setMode('workflow') },
});

const rightItems = getDefaultRightItems({
    tag: { enabled: false },
    chip: { enabled: false },
    camera: { onClick: handleCaptureImage },
    attach: { onClick: handleAttachFile },
});

<InputToolBar
    inputConfig={{
        value,
        onChange: (e) => setValue(e.nativeEvent.text),
        placeholder: 'Ask anything...',
        disabled: isLoading,
        inputRef: textareaRef,
    }}
    topContent={<>… panels / banners …</>}
    leftItems={leftItems}
    rightItems={rightItems}
    templateButton={{
        label: '+ Template',
        count: templates.length,
        onClick: openTemplateModal,
    }}
    micSendButton={{
        hasContent: value.trim().length > 0,
        onSend: handleSend,
        onMic: handleMic,
        disabled,
        isLoading,
        onStop,
    }}
    onContainerClick={() => textareaRef.current?.focus()}
/>;
```

### Custom left/right content

```tsx
<InputToolBar leftCustomRender={<YourLeftButtons />} rightCustomRender={<YourRightButtons />}>
    <TextInput placeholder="Message" />
</InputToolBar>
```

## Mic / Send behavior

When `micSendButton` is provided:

- **Empty input** (`hasContent === false`): rightmost button shows the **Mic** icon and calls `onMic` on click.
- **Input has text** (`hasContent === true`): rightmost button shows the **Send** (arrow) icon and calls `onSend` on click.

The button uses the primary style in both states. Any item with `id === 'mic'` in `rightItems` is not rendered when `micSendButton` is set.

## Platform notes

- Built with **@gluestack-ui/themed** (Box, HStack, VStack, Text, Pressable, etc.)
- Uses **React Native** TextInput, Modal, ScrollView, Pressable
- Icons from **@expo/vector-icons** (Ionicons)
- Supports **NativeWind** for Tailwind styling where needed (e.g. `className` on RN Text)
