# Inline Editing

The CMS provides spreadsheet-style inline editing in Data Table mode, plus auto-generated create and edit forms in the record detail view. All editable fields are determined from your table's guard configuration.

## Spreadsheet Editing

In Data Table mode, every editable cell becomes an inline editor. Select a cell, start typing, and the value is saved automatically when you move to another cell or press Enter.

### Editable Fields

The CMS determines which fields are editable from the table's guards:

- **`guards.updatable`** fields are editable in existing records
- **`guards.createable`** fields are editable in new record forms
- **`guards.immutable`** fields are locked after creation (shown as disabled in edit mode)
- **`guards.protected`** fields can only be changed via actions (marked "Updated via actions only")

If a table has no explicit guard config, the CMS falls back to making all non-system columns editable (excluding `id`, audit fields, `organizationId`, and `deletedAt`).

## Cell Types

Each column type gets a specialized editor:

### Text

Standard text input. Type freely and press Enter or Tab to save.

### Number

Numeric input with step controls. Supports decimal values (step `0.01` for currency fields). The CMS detects money fields from column names containing `amount`, `total`, `price`, `cost`, `balance`, `rate`, etc.

### Boolean

A Yes/No dropdown. Click to toggle between the two values.

### FK Typeahead

Foreign key columns (ending in `Id`) get a typeahead dropdown with server-side search:

- **Debounced search** — Queries are debounced at 200ms to avoid flooding the API
- **Server-side filtering** — Sends `?search=query&pageSize=20` to the FK target table's list endpoint
- **Keyboard navigation** — Arrow keys to navigate options, Enter to select, Escape to close
- **Auto-loads initial options** — Opens with the first 20 records sorted by display column
- **Display labels** — Shows the target table's display column value (e.g., "John Smith" instead of `usr_abc123`)

The FK target table is derived by stripping the `Id` suffix from the column name. For example, `contactId` searches the `contact` table, and `accountCodeId` searches the `accountCode` table.

### Enum / Select

Columns with `validation.enum` render as a select dropdown with all allowed values.

## Display Labels

FK cells in the table view show human-readable names instead of raw IDs. The API enriches list responses with `_label` fields:

```
contactId: "cnt_abc123"     → displays "Acme Corporation"
projectId: "prj_xyz789"    → displays "Beach House Renovation"
```

The label comes from the referenced table's display column (auto-detected from `name`, `title`, `code`, etc.). This works in both Table mode and Data Table mode.

## Keyboard Shortcuts

| Shortcut | Action |
|----------|--------|
| Arrow keys | Navigate between cells |
| Tab | Move to next editable cell |
| Shift + Tab | Move to previous editable cell |
| Enter | Start editing / confirm edit and move down |
| Escape | Cancel current edit / deselect cell |
| Type any character | Start editing the selected cell |

### Navigation Flow

1. **Select** a cell by clicking or using arrow keys
2. **Edit** by pressing Enter, Tab, or just typing
3. **Save** by pressing Enter (moves down), Tab (moves right to next editable), or clicking elsewhere
4. **Cancel** by pressing Escape (reverts to previous value)

When you press Tab, the cursor skips non-editable cells and jumps to the next editable cell in the row. At the end of a row, it wraps to the first editable cell of the next row.

## Record Detail View

Clicking a row in Table mode navigates to the record detail view. Fields are automatically grouped by type:

| Group | Fields Included |
|-------|----------------|
| Identity | `name`, `code`, `status`, `title`, `companyName`, fields ending in `Type` or `Status` |
| Contact Info | `email`, `phone`, `mobile`, `website`, `address1`, `address2`, `city`, `state`, `zip`, `country` |
| Financial | Money fields, fields with `Percent`, `Rate`, `Markup`, `Discount`, `Currency`, `exchange` |
| References | All FK columns (ending in `Id`, excluding `id` and `organizationId`) |
| Settings | Boolean fields |
| Dates | Date/time fields |
| Audit | `createdAt`, `createdBy`, `modifiedAt`, `modifiedBy` |
| Other | Remaining ungrouped fields |

Each group is rendered as a card with the group label as a header. Fields display formatted values — dates are localized, money shows currency formatting, booleans render as Yes/No badges, enums use color-coded pills, and FK references are clickable links to the target record.

## Auto-Generated Forms

The CMS generates create and edit forms from the table's guard configuration:

### Create Form

Shows all fields listed in `guards.createable`. Required fields (notNull without a default) are marked with a red asterisk. Validation rules from the schema (min/max length, enum constraints, email format) are enforced client-side.

### Edit Form

Shows all fields listed in `guards.updatable`. Additionally:

- **Immutable fields** appear as disabled inputs with a lock icon
- **Protected fields** appear as disabled inputs with the note "Updated via actions only"
- **Validation** is applied on submit, with error messages shown per field

### Field Input Types

The auto-form selects the appropriate input control based on column type and validation:

| Detection | Input Type |
|-----------|-----------|
| `mode: "boolean"` | Checkbox |
| `validation.enum` present | Select dropdown |
| Column name matches date pattern | Date/time picker |
| Column name matches money pattern | Number input (step 0.01) |
| Column name matches URL pattern | URL input |
| `validation.email: true` | Email input |
| `type: "integer"` or `type: "real"` | Number input |
| Long text (description, notes) | Textarea |
| Default | Text input |

## Next Steps

- **[Table Views](/ui/admin/table-views)** — Browse mode and view projections
- **[Security](/ui/admin/security)** — How guards control editability
- **[Actions](/ui/admin/actions)** — Trigger actions from the detail view
