Data Interfaces
A deep-dive into TimelineRow, TimelineAction, and TimelineEffect — the three core types that power the timeline editor.
The React Timeline Editor is built around three core data types exported from @keplar-404/react-timeline-editor.
TimelineRow
A Row (or Track) is the vertical lane in your timeline. Each row contains an ordered list of action blocks.
export interface TimelineRow {
/** Row unique ID */
id: string;
/** List of actions contained in this row */
actions: TimelineAction[];
/** Custom CSS class for styling the row */
classNames?: string[];
/** Whether the row is in a "selected" state */
selected?: boolean;
/** Flexible row height (overrides rowHeight prop) */
flexy?: boolean;
}TimelineAction
An Action is a time-bounded block sitting inside a TimelineRow. It is the fundamental unit of the timeline.
export interface TimelineAction {
/** Action unique ID */
id: string;
/** Start time of the action in seconds */
start: number;
/** End time of the action in seconds */
end: number;
/** ID of the effect that defines this action's behavior */
effectId: string;
/** If false, the action cannot be dragged horizontally. Defaults to true. */
movable?: boolean;
/** If false, the action cannot be resized. Defaults to true. */
flexible?: boolean;
/** Optional minimum start position (clamps dragging). */
minStart?: number;
/** Optional maximum end position (clamps dragging). */
maxEnd?: number;
/** Inline CSS styles for the action block */
style?: React.CSSProperties;
/** Additional CSS class name for the action block */
className?: string;
/** Custom data payload — attach any extra metadata here */
data?: any;
}You can extend TimelineAction with your own TypeScript interface to add typed custom data:
export interface MyAudioAction extends TimelineAction {
data: {
src: string;
volume: number;
};
}TimelineEffect
An Effect is the mapping between an action's effectId and the logic that runs during playback. Effects live in a flat Record<string, TimelineEffect> and are passed to the <Timeline /> via the effects prop.
export interface TimelineEffect {
/** Effect ID (must match the effectId in your TimelineAction) */
id: string;
/** Human-readable name */
name: string;
/** Engine source callbacks — define what happens during playback */
source?: TimeLineEffectSource;
}TimeLineEffectSource Callbacks
The source property contains lifecycle callbacks that the engine fires during playback:
export interface TimeLineEffectSource {
/** Called when playback starts while cursor is already inside this action */
start?: (params: EffectSourceParams) => void;
/** Called when the playhead enters this action's time range */
enter?: (params: EffectSourceParams) => void;
/** Called every animation frame while inside this action's range */
update?: (params: EffectSourceParams) => void;
/** Called when the playhead leaves this action's time range */
leave?: (params: EffectSourceParams) => void;
/** Called when playback is paused while inside this action */
stop?: (params: EffectSourceParams) => void;
}Engine Callback Lifecycle
| Callback | Fires when... | Typical use |
|---|---|---|
start | Playback begins while cursor is already within the action range | Resume audio at correct offset |
enter | Playhead crosses into the action from outside | Start sound / show animation |
update | Every tick while inside the action | Advance animation frame |
leave | Playhead crosses out of the action | Stop audio / hide animation |
stop | Playback is paused inside the action | Pause audio |
A Full Example Setup
import { TimelineRow, TimelineEffect } from "@keplar-404/react-timeline-editor";
import { TimelineEngine } from "@keplar-404/timeline-engine";
// ── Effect definitions ──────────────────────────────────────────────────────
const mockEffect: Record<string, TimelineEffect> = {
audio: {
id: "audio",
name: "Play Audio",
source: {
enter: ({ action, time }) => {
console.log(`Playing audio for action ${action.id} at t=${time}`);
},
leave: ({ action }) => {
console.log(`Stopping audio for action ${action.id}`);
},
},
},
video: {
id: "video",
name: "Play Video",
},
};
// ── Timeline data ──────────────────────────────────────────────────────────
const editorData: TimelineRow[] = [
{
id: "audio-track",
actions: [
{
id: "audio-clip-1",
start: 0,
end: 10,
effectId: "audio",
data: { src: "/audio/bg.mp3", name: "Background Music" },
},
],
},
{
id: "video-track",
actions: [
{
id: "video-clip-1",
start: 2,
end: 8,
effectId: "video",
movable: true,
flexible: true,
minStart: 0,
maxEnd: 20,
},
],
},
];