# Document Viewer

Reading pane with in-document search, citation anchors, original-PDF view, and export.

## Add it to an app

1. Open the app builder and find **Document Viewer** 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 `document_viewer`.

## Settings

| Setting | Accepted value | Required | Default | What it controls |
| --- | --- | --- | --- | --- |
| Provenance anchor (`anchor`) | object or null | No | null | Supports expression bindings. The active citation to land on (a grid's activeCitation via app state); null = none. The listed default is inserted when adding a new component. |
| Show close button (`closable`) | boolean | No | false | Supports expression bindings. The listed default is inserted when adding a new component. |
| Allow editing (needs versions capability) (`editable`) | boolean | No | false | Supports expression bindings. The listed default is inserted when adding a new component. |
| Export file name (`exportName`) | string | No | "" | Supports expression bindings. The listed default is inserted when adding a new component. |
| Document title (`fileName`) | string | No | "" | Supports expression bindings. The listed default is inserted when adding a new component. |
| Viewer height (CSS length) (`height`) | string | No | "32rem" | Supports expression bindings. The listed default is inserted when adding a new component. |
| Index record type (`indexRecordType`) | string | No | "search_index" | The listed default is inserted when adding a new component. |
| Search index data source id (`indexSource`) | string | No | "" | The listed default is inserted when adding a new component. |
| View mode (auto \| original \| text) (`mode`) | "auto" / "original" / "text" | No | "auto" | Supports expression bindings. Choose read to return query results or write to insert incoming records. The listed default is inserted when adding a new component. |
| Document object key (`objectKey`) | string | No | "" | Supports expression bindings. The listed default is inserted when adding a new component. |
| Detail visibility app-state key (literal) (`openKey`) | string | No | Not specified | Literal only; do not use an expression binding. |
| Refresh token (`refreshToken`) | string or null | No | Not specified | Supports expression bindings. A new non-empty value reloads the document from page 1. |
| Segment record type (blank = from index manifest) (`segmentRecordType`) | string | No | "" | The listed default is inserted when adding a new component. |
| Segments data source id (`segmentsSource`) | string | No | "" | The listed default is inserted when adding a new component. |
| Show find bar (`showSearch`) | boolean | No | true | Supports expression bindings. The listed default is inserted when adding a new component. |
| Detail width ('half' = even split; default 'third' = 2:1 — literal) (`split`) | "half" / "third" | No | Not specified | Literal only; do not use an expression binding. |

## Values available to bindings

| Value | Type | Initial value | Meaning |
| --- | --- | --- | --- |
| `activeMatch` | integer | 0 | Position of the active match. |
| `activeVersion` | integer or null | null | The version on display; null = current. |
| `anchorStatus` | "none" / "painted" / "approximate" / "page" / "document" / "unpaintable" | "none" | The landing the reader actually got for the anchor. |
| `editStatus` | "idle" / "editing" / "saving" / "conflict" / "error" | "idle" | The edit lifecycle. |
| `exportStatus` | "idle" / "exporting" / "done" / "empty" / "error" | "idle" | The last export's outcome (the host's verdict). |
| `lastSavedIngestId` | string or null | null | The last save's re-index correlation id (watch it like an upload's). |
| `lastSavedVersion` | integer or null | null | The last save's version. |
| `matchCount` | integer | 0 | Matches the index reports. |
| `matchCountExact` | boolean | true | The two counts agree. |
| `navigableMatches` | integer | 0 | Matches the reader can step through. |
| `segmentsLoaded` | integer | 0 | Segments loaded so far. |
| `segmentsTotal` | integer or null | null | Advisory segment total. |
| `status` | "idle" / "unavailable" / "loading" / "error" / "ready" / "empty" | "idle" | Read state of the document. |
| `terms` | list of string | [] | The search terms in play. |
| `value` | string | "" | The find query. |

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

## Events

- `onClose` — The close button was pressed.

- `onExport` — An export downloaded (after the host sink succeeded).

- `onMatchChange` — The active match moved.

- `onSearch` — The find query ran.

- `onVersionChange` — Another version was put on display.

- `onVersionSaved` — An edit was saved as a new version.

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: Document viewer.

- Escape clears the find query, else closes a closable viewer

## Example: Detail-pane reader with search

| Setting | Example value |
| --- | --- |
| `closable` | true |
| `indexSource` | "search" |
| `objectKey` | "{{ app.activeDocKey \|\| '' }}" |
| `openKey` | "viewerOpen" |
| `segmentsSource` | "segments" |

When `onClose` occurs, the example performs:

- `setStateValue` with {"key":"viewerOpen","value":false}

## Example: Citation target: lands anchors, editable, even split

| Setting | Example value |
| --- | --- |
| `anchor` | "{{ app.activeAnchor }}" |
| `editable` | true |
| `indexSource` | "search" |
| `objectKey` | "{{ app.activeAnchor ? app.activeAnchor.object_key : '' }}" |
| `segmentsSource` | "segments" |
| `split` | "half" |

## 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.
