@elacity-js/ddrm-reader-ui
v0.2.4
Published
React library to render dDRM render-IR: channel client + RasterViewer/TextViewer/MeshViewer + <DdrmReader/>. React is a peer dependency.
Readme
@elacity-js/ddrm-reader-ui
The React client library for the dDRM reader. It opens the ECDH WebSocket channel, runs the wallet-signed handshake, requests an asset, and renders the returned render-IR with the right viewer. Pure JS/TS — no Rust/wasm renderer.
Workflow role
The receiving end of the pipeline. It dispatches on the IR kind tag (never the original mime), so it stays content-agnostic: a new decoder on the backend needs no client change.
wallet sign + ECDH handshake ──▶ asset-request ──▶ render-IR frames ──▶ IrViewer dispatches on kind
├─ raster-tile-set → RasterViewer (canvas pan/zoom)
├─ text-doc → TextViewer (sanitized HTML)
├─ mesh-set → MeshViewer (three.js)
└─ doc-file → pdf.js / epub.jsreact and react-dom are peer dependencies.
Install
pnpm add @elacity-js/ddrm-reader-ui react react-domDrop-in component
<DdrmReader/> handles the whole lifecycle — connecting, loading, error, and ready.
import { DdrmReader } from "@elacity-js/ddrm-reader-ui";
export function Viewer({ wallet }) {
return (
<DdrmReader
baseUrl="wss://reader.example.com"
wallet={wallet} // a WalletSigner: signs the handshake challenge
asset={{ contentId, kid /* ...AssetParams */ }}
/>
);
}Hook + your own UI
useDdrmReader exposes the state machine if you want to render it yourself:
import { useDdrmReader, RasterViewer, TextViewer, MeshViewer } from "@elacity-js/ddrm-reader-ui";
function Custom({ wallet, asset }) {
const state = useDdrmReader({ baseUrl: "wss://reader.example.com", wallet, asset });
if (state.status === "connecting" || state.status === "loading") return <Spinner />;
if (state.status === "error") return <p>{state.code}: {state.message}</p>;
switch (state.ir.kind) {
case "raster-tile-set": return <RasterViewer ir={state.ir} />;
case "text-doc": return <TextViewer ir={state.ir} />;
case "mesh-set": return <MeshViewer ir={state.ir} />;
case "doc-file": return /* pdf.js / epub.js */ null;
}
}Lower-level channel client
ChannelClient is the transport under the hook — connect(), request(asset), close() — injectable via the hook's client option for tests/playgrounds.
import { ChannelClient } from "@elacity-js/ddrm-reader-ui";
const client = new ChannelClient({ baseUrl: "wss://reader.example.com", wallet });
await client.connect();
const ir = await client.request({ contentId, kid });
client.close();