React

Use @editframe/react for TypeScript-typed compositions with React component syntax.

Install

npm install @editframe/react

Components

All elements are available as React components:

import { Timegroup, Video, Audio, Image, Text, Captions, Surface, Waveform } from "@editframe/react";

React props use camelCase where the HTML attribute uses a hyphen or has a different name:

HTML attributeReact prop
sourceinsourceIn
sourceoutsourceOut
trimstarttrimStart
trimendtrimEnd
mutemuted
fft-sizefftSize
bar-spacingbarSpacing
line-widthlineWidth
target (waveform)for
captions-srcsrc
captions-scriptcaptionsScript

All other attributes have the same name in both HTML and React.

Basic example

import { Timegroup, Text } from "@editframe/react";

export default function Composition() {
  return (
    <Timegroup
      duration="5s"
      className="w-[1920px] h-[1080px] bg-black flex items-center justify-center"
    >
      <Text className="text-white text-8xl font-bold">Hello from React</Text>
    </Timegroup>
  );
}

Sequence with video and text

import { Timegroup, Video, Text } from "@editframe/react";

export default function Composition() {
  return (
    <Timegroup mode="sequence" className="w-[1920px] h-[1080px] bg-black">
      <Timegroup mode="fixed" duration="5s" className="absolute w-full h-full">
        <Video
          src="https://assets.editframe.com/bg.mp4"
          sourceIn="2s"
          sourceOut="7s"
          className="size-full"
          style={{ objectFit: "cover" }}
        />
        <Text className="absolute inset-0 flex items-center justify-center text-white text-7xl font-bold">
          Scene One
        </Text>
      </Timegroup>
      <Timegroup mode="fixed" duration="8s" className="absolute w-full h-full">
        <Video
          src="https://assets.editframe.com/bars-n-tone.mp4"
          className="size-full"
          style={{ objectFit: "cover" }}
        />
      </Timegroup>
    </Timegroup>
  );
}

useTimingInfo

useTimingInfo() returns the current playback time for a Timegroup. Use it for time-reactive animations.

import { Timegroup, Text, useTimingInfo } from "@editframe/react";

function AnimatedHeadline() {
  const { ownCurrentTimeMs, durationMs, percentComplete, ref } = useTimingInfo();

  return (
    <Timegroup
      ref={ref}
      duration="3s"
      className="w-[1920px] h-[1080px] bg-black flex items-center justify-center"
    >
      <Text
        className="text-white text-8xl font-bold"
        style={{ opacity: percentComplete }}
      >
        Fades In
      </Text>
    </Timegroup>
  );
}

The hook creates a ref internally and returns it. Pass it to the <Timegroup> you want to observe:

FieldTypeDescription
refRefObject<EFTimegroup>Pass to <Timegroup ref={ref}>
ownCurrentTimeMsnumberms since this group's start
durationMsnumberTotal duration in ms
percentCompletenumber0–1 progress

Data-driven compositions

import { Timegroup, Text } from "@editframe/react";

const slides = [
  { text: "Slide One", bg: "bg-indigo-900" },
  { text: "Slide Two", bg: "bg-purple-900" },
  { text: "Slide Three", bg: "bg-rose-900" },
];

export default function Composition() {
  return (
    <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
      {slides.map((slide) => (
        <Timegroup
          key={slide.text}
          duration="3s"
          className={`w-full h-full flex items-center justify-center ${slide.bg}`}
        >
          <Text className="text-white text-7xl font-bold">{slide.text}</Text>
        </Timegroup>
      ))}
    </Timegroup>
  );
}
Compositions render in a headless browser — SSR concerns (hydration, window access) don't apply.