@elabs-ai/components-viewer
v6.1.0
Published
<!-- brand-ui:gen:readme:start --> <!-- Generated by scripts/gen-package-readmes.mjs — do not edit inside these markers. -->
Readme
@elabs-ai/components-viewer
FileViewer — any file (image, audio, video, text, code, JSON, CSV, markdown, PDF, docx, pptx, xlsx) via a pluggable adapter registry.
Part of brand-ui, a source-owned, token-driven React component system.
Published to the public npm registry under the @elabs-ai scope — it
installs like any other npm dependency, with no registry configuration and
no token required. See docs/CONSUMING.md.
Install
pnpm add @elabs-ai/components-tokens @elabs-ai/components-viewerSet up styling (do not skip)
Components are Tailwind v4 classes backed by semantic tokens. Two lines in your CSS entry, or everything renders unstyled — the single most common mistake:
@import "@elabs-ai/components-tokens/styles.css";
@source "../node_modules/@elabs-ai/components-viewer/dist";The @source line is required because Tailwind ignores node_modules. Add
one per brand-ui package you render. Then wrap your app once:
import { ThemeProvider } from "@elabs-ai/components-tokens";
<ThemeProvider defaultTheme="light">{children}</ThemeProvider>;What's in it
19 exported components — including ACTIVE_HIGHLIGHT_SELECTOR, DEFAULT_ZOOM, FileViewer, FileViewerContent, FileViewerEmpty.
Don't guess the API — ask the CLI:
pnpm add -D @elabs-ai/components-cli
pnpm exec brand-ui search <query> # find a component
pnpm exec brand-ui docs <Name> # its real props, from sourceUsing an AI coding agent?
For Claude Code, install the plugin from this repo's checkout:
/plugin marketplace add .
/plugin install brand-uibrand-ui docs <Name> returns intent, composition, state→token mappings and
anti-patterns — tell your agent to run it instead of guessing a prop. The CLI
also runs as an MCP server (brand-ui mcp).
Full guide
Tailwind and Next.js wiring, per-package extras, agent enablement and a
prompt for migrating an existing project: docs/CONSUMING.md.
License
MIT
Package detail
Renders a file — whatever it is, wherever it came from — themed and accessible.
import { FileViewer } from "@elabs-ai/components-viewer";
<div className="h-[600px]">
<FileViewer source={{ kind: "file", file }} />
</div>;The input is always a FileSource
One union from @elabs-ai/components-ui covers every way an app can
be holding a file — a user's File, an in-memory Blob or ArrayBuffer, a
string of content, or a remote URL. The url variant carries init, so a file
behind auth is reachable:
<FileViewer
source={{
kind: "url",
url: "https://files.internal/report.csv",
init: { headers: { Authorization: `Bearer ${token}` } },
}}
/>Formats come from adapters, and adapters are pluggable
Every format is an adapter in a registry: a small eager manifest (what it can open, what the toolbar should offer) plus a lazy loader. Nothing heavy is in the entry chunk, and an app that never opens a spreadsheet never downloads a spreadsheet parser.
Register your own — or override a built-in by registering a higher priority for the same id:
import { createRegistry, FileViewer } from "@elabs-ai/components-viewer";
const registry = createRegistry();
registry.register(myManifest, () => import("./my-adapter"));
<FileViewer source={source} registry={registry} />;Parsers are optional peers
Only install what you open. A format whose parser is absent renders a clear "can't open this here" state with a download action — never a module-resolution crash.
| Format | Peer to install |
| --------------- | --------------- |
| .csv / .tsv | papaparse |
Images, plain text and JSON need nothing — they use platform APIs.
Adapters emit data, not HTML
An adapter returns a model (rows, a tree, a page) that brand-ui components render, so the viewer's chrome is fully token-driven and re-themes with the rest of your app. Document content — a photo, a rendered page — renders as authored, because that is the file.
