JDFJDF/ docs

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>