@get-asset/sdk

Document Viewer

Headless lookup for the source document behind an Invoice or a Bill — the uploaded file the record was raised from. A record carries at most one, so the compound answers a single question: does this record have a document, and can it be shown. It resolves the document with one bounded request, fetches a short-lived URL for the file, and exposes the processing status in the same vocabulary as Documents. A record with no document — or a lookup that fails — reads as NotFoundrather than an error, because the document pane is an enrichment of the details, never a gate on them. The file is always the record's own: files reach a record by being uploaded to Asset (see AssetDocuments), so there is no prop for rendering some other URL beside a bill or an invoice. AssetInvoices and AssetBills mount this behind their full views already.

Anatomy

Import the primitive and compose the parts you need.

<DocumentViewer.Root kind="invoice" objectId={invoice.id}>
{/* The details surface, laid out however the host likes */}
<DocumentViewer.Found>
{/* The record has a source document */}
<DocumentViewer.Status />
<DocumentViewer.Name />
<DocumentViewer.PreviewImage />
<DocumentViewer.PreviewPdf />
<DocumentViewer.PreviewPending>{/* file URL on the way */}</DocumentViewer.PreviewPending>
<DocumentViewer.IsImage>{/* zoom, or anything image-only */}</DocumentViewer.IsImage>
<DocumentViewer.OriginalLink>Open original</DocumentViewer.OriginalLink>
</DocumentViewer.Found>
<DocumentViewer.NotFound>
{/* The lookup answered: no document behind this record */}
</DocumentViewer.NotFound>
</DocumentViewer.Root>

Required scopes

The access token used by AssetProvider must include this scope for this primitive to fetch data successfully:

  • document:read

API reference

Root props

PropTypeDefaultDescription
kindrequired"invoice" | "bill"Which side of the ledger the record lives on. Picks whether the lookup filters documents by invoice_id or bill_id.
objectIdrequiredstringThe Invoice or Bill whose source document is being looked up.
childrenrequiredReactNodeCompound parts.

Parts

Container

Always rendered. Resolves the record's document and the URL its file renders from, and provides context.

PartDescription
DocumentViewer.RootOwns the document lookup (one request, filtered to the record) and the signed-URL fetch behind the preview, and provides context.

Gates

The two answers. Neither renders while the lookup is still in flight, so a host that mounts the pane inside Found adds it only once there is something to show.

PartDescription
DocumentViewer.FoundChildren render once a document is known to exist.
DocumentViewer.NotFoundChildren render once the lookup has answered none — including a lookup (or its signed-URL follow-up) that failed, which deliberately reads the same way.
DocumentViewer.PreviewPendingChildren render while a found document's file URL is still on the way — the slot for a placeholder on the page card.
DocumentViewer.IsImageChildren render when the file renders as an image — the slot for zoom or any other image-only control (a PDF's frame brings the browser viewer's own).

The document

Facts about the file. Each renders nothing until a document exists.

PartDescription
DocumentViewer.Status
asChild?, format?
The document's processing status. Renders the same display labels as the Documents list, and carries data-status with the display tone for the stylesheet's dot.
DocumentViewer.Name
asChild?
The original file name.
DocumentViewer.PreviewImage
asChild?
The file as an img, when the file is an image. Sets src on the child (asChild) or renders its own. Nothing renders until the URL is known.
DocumentViewer.PreviewPdf
asChild?
The file in an iframe, for everything an img can't take — PDFs render through the browser's own viewer. Same src contract as PreviewImage.
DocumentViewer.OriginalLink
asChild?
An anchor to the file itself, opening in its own tab. Renders nothing until the URL is known.