Use jdf.js with React, Vue, Svelte
jdf.js ships as a custom element (<jdf>), so it works in every framework without a wrapper. The snippets below show the idiomatic way to use it in each.
Heads-up: import
@uurtech/jdf/style.css once at the app root. Without the stylesheet, the embed renders unstyled.
React
Use the custom element directly
// app.tsx
import "@uurtech/jdf";
import "@uurtech/jdf/style.css";
export default function Whitepaper() {
return <jdf src="/whitepaper.jdf" width="100%" height="800" />;
}
React 19+ supports custom elements natively. For React 18 add a JSX type augmentation:
// types.d.ts
declare namespace JSX {
interface IntrinsicElements {
jdf: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
src: string;
width?: string | number;
height?: string | number;
zoom?: string | number;
sidebar?: string;
"dark-mode"?: "auto" | "light" | "dark";
};
}
}
Programmatic with hooks
import { useEffect, useRef } from "react";
import { embed } from "@uurtech/jdf";
import "@uurtech/jdf/style.css";
export function JdfEmbed({ src }: { src: string }) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!ref.current) return;
let instance: any;
embed(ref.current, src, { sidebar: true }).then((v) => { instance = v; });
return () => instance?.destroy();
}, [src]);
return <div ref={ref} style={{ height: "80vh" }} />;
}
Vue 3
Custom elements work out of the box. Tell Vue's compiler that <jdf> is custom (silences the "unknown element" warning):
// vite.config.ts
import vue from "@vitejs/plugin-vue";
export default {
plugins: [vue({
template: { compilerOptions: { isCustomElement: (tag) => tag === "jdf" } }
})],
};
<template>
<jdf :src="docUrl" width="100%" height="800" sidebar="true" />
</template>
<script setup lang="ts">
import "@uurtech/jdf";
import "@uurtech/jdf/style.css";
const docUrl = "/whitepaper.jdf";
</script>
Svelte
Svelte handles custom elements natively. Just import the script once and use the tag:
<!-- App.svelte -->
<script>
import "@uurtech/jdf";
import "@uurtech/jdf/style.css";
let src = "/whitepaper.jdf";
</script>
<jdf {src} width="100%" height="800" />
<button on:click={() => src = "/other.jdf"}>Switch</button>
Next.js
Next 13+ App Router — wrap the embed in a client component:
// app/components/Jdf.tsx
"use client";
import "@uurtech/jdf";
import "@uurtech/jdf/style.css";
export default function Jdf({ src }: { src: string }) {
return <jdf src={src} width="100%" height="800" />;
}
Astro
---
import "@uurtech/jdf";
import "@uurtech/jdf/style.css";
const { src } = Astro.props;
---
<jdf src={src} width="100%" height="800"></jdf>
Vanilla / no framework
Easiest possible setup — just a script tag:
<link rel="stylesheet" href="https://unpkg.com/@uurtech/jdf/dist/jdfjs.css">
<script type="module" src="https://unpkg.com/@uurtech/jdf"></script>
<jdf src="/whitepaper.jdf"></jdf>