# File Upload

Drag-and-drop dropzone with a managed file list. Feeds documents into the app's workflows.

## Add it to an app

1. Open the app builder and find **File Upload** in the component palette.
2. Insert it into the intended region or container.
3. Set its properties in the inspector. Use a literal for a fixed value or a binding for a value supplied by the app.
4. Connect its events where the app should respond to a user gesture.
5. Preview with representative data and save after resolving validation problems.

The type name in the builder’s code view is `file_upload`.

## Settings

| Setting | Accepted value | Required | Default | What it controls |
| --- | --- | --- | --- | --- |
| Accepted types (e.g. .pdf,.txt,.png) (`accept`) | string | No | "" | Supports expression bindings. Comma-separated extensions/MIME types; '' accepts anything. The listed default is inserted when adding a new component. |
| Open first readable uploaded file (`autoSelectReadyFile`) | boolean | No | Not specified | Supports expression bindings. |
| File busy key (`busyKey`) | string | No | Not specified | Supports expression bindings. |
| Compact (sidebar) (`compact`) | boolean | No | Not specified | Supports expression bindings. Slimmer dropzone for the sidebar. |
| File error key (`errorKey`) | string | No | Not specified | Supports expression bindings. |
| Revision to replace (`expectedRevision`) | string | No | Not specified | Supports expression bindings. Managed mode: replace only this current revision. Omit to create a new document. |
| File id key (`fileIdKey`) | string | No | Not specified | Supports expression bindings. Row key of the file's id; '' uses the name. |
| File meta key (`fileMetaKey`) | string | No | Not specified | Supports expression bindings. Row key of the right-aligned meta column. |
| File name key (`fileNameKey`) | string | No | Not specified | Supports expression bindings. Row key of the display name ('name' when unset). |
| Files (`files`) | list of object | No | Not specified | Supports expression bindings. Bound file rows listed below the dropzone. |
| Highlighted file key (`highlightedFileKey`) | string | No | Not specified | Supports expression bindings. The row rendered selected — reflect selectedFileKey. |
| Label (`label`) | string | No | "Upload files" | Supports expression bindings. Shown above the dropzone; also its accessible name. The listed default is inserted when adding a new component. |
| Max files (`maxFiles`) | integer; minimum 1 | No | 1 | Supports expression bindings. Per hand-off cap; applies when multiple is on. The listed default is inserted when adding a new component. |
| Row menu items (`menuItems`) | list of object | No | Not specified | Supports expression bindings. |
| danger (`menuItems[].danger`) | boolean | No | Not specified | — |
| hideOnError (`menuItems[].hideOnError`) | boolean | No | Not specified | — |
| id (`menuItems[].id`) | string | Yes | Not specified | — |
| label (`menuItems[].label`) | string | Yes | Not specified | — |
| Allow multiple (`multiple`) | boolean | No | false | Supports expression bindings. The listed default is inserted when adding a new component. |
| Processing outcome (ingestId, status, error) (`processing`) | object | No | Not specified | Supports expression bindings. The latest watch outcome, applied only to its own batch. |
| Remove confirm text (`removeConfirmText`) | string | No | Not specified | Supports expression bindings. |
| Explicit document navigation revision (`selectionRevision`) | number | No | Not specified | Supports expression bindings. Changed by explicit navigation; stops a late automatic selection. |
| Storage mode (`storageMode`) | "ingest" / "managed" | No | Not specified | Supports expression bindings. Managed stores one immutable revision without starting an ingest workflow. |

### Layout controls

Additional host-rendered controls: `sectionTitle`. These control the surrounding component region rather than the record values.

## Values available to bindings

| Value | Type | Initial value | Meaning |
| --- | --- | --- | --- |
| `documentRevisions` | list of object | [] | Confirmed managed revisions: document_id, revision_id, object_key, content_sha256, size_bytes, media_type. |
| `errorMessage` | string | "" | Why the last upload failed, verbatim. |
| `fileNames` | list of string | [] | Names in the current hand-off. |
| `lastIngestId` | string | "" | The last successful batch's ingest correlation id (a mode:'watch' action's ingestId). |
| `menuAction` | object or null | null | The clicked row-menu action {id, fileKey, fileName, revision}. |
| `objectKeys` | list of string | [] | Object keys of the last upload. |
| `readyFile` | object or null | null | {fileKey, ingestId} of the first readable uploaded file (autoSelectReadyFile). |
| `removedFileKey` | string | "" | The object key just deleted through Remove. |
| `removedIngestId` | string | "" | The delete's re-index correlation id. |
| `resumeIngestId` | string | "" | The newest still-processing batch's id at mount (reload-resume). |
| `selectedFileKey` | string | "" | The clicked bound row's key. |
| `status` | "idle" / "uploading" / "uploaded" / "error" | "idle" | The current hand-off. |
| `uploaded` | integer | 0 | Files in the last upload. |

Refer to these values through `components.<component-id>.<value>` in a binding. Use the identifier assigned to this instance of File Upload, not the component type name.

## Events

- `onError` — The upload failed (errorMessage set).

- `onFileReady` — The first readable uploaded file is ready (readyFile set).

- `onFileRemoved` — A file was deleted through Remove.

- `onMenuAction` — A row-menu item was clicked (menuAction set).

- `onProcessingResumed` — A still-processing batch was found at mount.

- `onSelectFile` — A bound row was clicked (selectedFileKey set).

- `onUploaded` — The host sink accepted the upload.

Connect only the actions the app needs. An event can fetch results, run an enabled data source, set state, update another component, show a notification, or navigate where supported.

## Keyboard and accessible labels

Accessible label source: The dropzone is named by `label`, else 'Upload files'.

- Enter/Space on the dropzone opens the file picker.

Updates are announced through the component’s live status region.

## Example: Single document

| Setting | Example value |
| --- | --- |
| `accept` | ".pdf" |
| `label` | "Upload a contract" |
| `maxFiles` | 1 |
| `multiple` | false |

## Example: Sidebar documents list, watched to indexed

| Setting | Example value |
| --- | --- |
| `accept` | ".pdf,.txt,.md" |
| `compact` | true |
| `fileIdKey` | "object_key" |
| `fileNameKey` | "file_name" |
| `files` | "{{ dataSources.docs.data }}" |
| `highlightedFileKey` | "{{ app.activeDocKey }}" |
| `label` | "Drop documents" |
| `maxFiles` | 10 |
| `menuItems` | [{"hideOnError":true,"id":"reprocess","label":"Reprocess"}] |
| `multiple` | true |
| `sectionTitle` | "Documents" |

When `onUploaded` occurs, the example performs:

- `triggerDataSource` with {"dataSourceId":"docs","ingestId":"{{ components.Uploader.lastIngestId }}","mode":"watch"}

When `onSelectFile` occurs, the example performs:

- `setStateValue` with {"key":"activeDocKey","value":"{{ components.Uploader.selectedFileKey }}"}

## If it is empty or unavailable

Check the source binding, the selected item, and the app’s access. A hosted document, table, review, or storage component needs the corresponding app capability; an offline preview cannot supply live private data. A source running with no results is different from an invalid binding. Inspect the app’s workflow and data source before changing the presentation.
