> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heliosrender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sequencing

> Timeline sequencing utilities for orchestrating complex animations in Helios

Sequencing functions help you organize and coordinate multiple animations across your composition's timeline. These utilities make it easy to create complex choreography without manual frame calculations.

## sequence()

Calculates the local time and progress of a sequence relative to a start frame.

```typescript theme={null}
import { sequence } from '@helios-project/core';

const seq = sequence({
  frame: currentFrame,
  from: 30,
  durationInFrames: 60
});

if (seq.isActive) {
  const opacity = seq.progress;
}
```

### Parameters

**options** `SequenceOptions` *required*

Sequence configuration object

**properties**

**frame** `number` *required*

Current frame number from your composition

**from** `number` *required*

Starting frame for this sequence

**durationInFrames** `number`

Duration in frames. If undefined, sequence is active indefinitely after start.

### Returns

`SequenceResult` object with the following properties:

**localFrame** `number`

Frame number relative to the sequence start (frame - from)

**relativeFrame** `number`

Alias for localFrame, for clarity

**progress** `number`

Normalized progress from 0 to 1. Always 0 if no duration specified.

**isActive** `boolean`

True if the current frame is within the sequence's time range

### Examples

#### Basic sequence

```typescript theme={null}
import { sequence } from '@helios-project/core';

function SequencedElement({ frame }) {
  const seq = sequence({
    frame,
    from: 30,
    durationInFrames: 60
  });
  
  if (!seq.isActive) return null;
  
  return (
    <div style={{ opacity: seq.progress }}>
      Visible from frame 30-90
    </div>
  );
}
```

#### Using local frame

```typescript theme={null}
const seq = sequence({ frame, from: 30, durationInFrames: 90 });

if (seq.isActive) {
  // seq.localFrame goes from 0 to 89
  const x = interpolate(seq.localFrame, [0, 90], [0, 800]);
}
```

#### Infinite sequence

```typescript theme={null}
// Sequence starts at frame 60 and runs until end of composition
const seq = sequence({ frame, from: 60 });

if (seq.isActive) {
  // Active from frame 60 onward
}
```

## series()

Arranges items sequentially, automatically calculating start times based on each item's duration.

```typescript theme={null}
import { series } from '@helios-project/core';

const scenes = series([
  { id: 'intro', durationInFrames: 60 },
  { id: 'main', durationInFrames: 120 },
  { id: 'outro', durationInFrames: 60 }
]);

// scenes[0].from = 0
// scenes[1].from = 60
// scenes[2].from = 180
```

### Parameters

**items** `T[]` *required*

Array of items with `durationInFrames` and optional `offset` properties

**startFrame** `number` (default: 0)

Starting frame for the first item in the series

### Returns

`Array<T & { from: number }>` - Original items with `from` property added

### Examples

#### Sequential scenes

```typescript theme={null}
import { series, sequence } from '@helios-project/core';

const scenes = series([
  { name: 'Intro', durationInFrames: 90 },
  { name: 'Main', durationInFrames: 180 },
  { name: 'Credits', durationInFrames: 60 }
]);

function VideoComposition({ frame }) {
  return (
    <>
      {scenes.map((scene) => {
        const seq = sequence({
          frame,
          from: scene.from,
          durationInFrames: scene.durationInFrames
        });
        
        if (!seq.isActive) return null;
        
        return <Scene key={scene.name} name={scene.name} progress={seq.progress} />;
      })}
    </>
  );
}
```

#### With offsets

```typescript theme={null}
const scenes = series([
  { id: 'a', durationInFrames: 60 },
  { id: 'b', durationInFrames: 60, offset: -10 }, // Starts 10 frames before 'a' ends
  { id: 'c', durationInFrames: 60, offset: 20 }   // Starts 20 frames after 'b' ends
]);

// scenes[0].from = 0
// scenes[1].from = 50  (60 - 10)
// scenes[2].from = 130 (50 + 60 + 20)
```

#### Custom start frame

```typescript theme={null}
const delayedScenes = series(
  [
    { durationInFrames: 60 },
    { durationInFrames: 90 }
  ],
  30 // Start at frame 30
);

// delayedScenes[0].from = 30
// delayedScenes[1].from = 90
```

## stagger()

Staggers items at a fixed interval, useful for animating lists and grids.

```typescript theme={null}
import { stagger } from '@helios-project/core';

const items = stagger(
  ['Apple', 'Banana', 'Cherry'],
  10  // 10 frames between each
);

// items[0].from = 0
// items[1].from = 10
// items[2].from = 20
```

### Parameters

**items** `T[]` *required*

Array of items to stagger

**interval** `number` *required*

Number of frames between each item's start time

**startFrame** `number` (default: 0)

Frame to start the first item at

### Returns

`Array<T & { from: number }>` - Items with `from` property added

### Examples

#### Staggered list animation

```typescript theme={null}
import { stagger, interpolate } from '@helios-project/core';

function StaggeredList({ items, frame }) {
  const staggeredItems = stagger(items, 8); // 8 frames delay between each
  
  return (
    <div>
      {staggeredItems.map((item, i) => {
        const opacity = interpolate(
          frame,
          [item.from, item.from + 20],
          [0, 1],
          { extrapolateRight: 'clamp' }
        );
        
        const y = interpolate(
          frame,
          [item.from, item.from + 20],
          [20, 0],
          { extrapolateRight: 'clamp' }
        );
        
        return (
          <div key={i} style={{ opacity, transform: `translateY(${y}px)` }}>
            {item}
          </div>
        );
      })}
    </div>
  );
}
```

#### Grid stagger

```typescript theme={null}
const grid = [
  ['A', 'B', 'C'],
  ['D', 'E', 'F'],
  ['G', 'H', 'I']
];

const flatGrid = grid.flat();
const staggeredGrid = stagger(flatGrid, 5, 30); // Start at frame 30
```

## shift()

Shifts the start times of all items by a fixed offset.

```typescript theme={null}
import { series, shift } from '@helios-project/core';

const scenes = series([
  { durationInFrames: 60 },
  { durationInFrames: 90 }
]);

const delayedScenes = shift(scenes, 30); // Delay everything by 30 frames
```

### Parameters

**items** `T[]` *required*

Array of items with a `from` property

**offset** `number` *required*

Number of frames to shift by (can be negative)

### Returns

`T[]` - Items with updated `from` values

### Examples

#### Delaying a sequence

```typescript theme={null}
const scenes = series([
  { durationInFrames: 60 },
  { durationInFrames: 90 }
]);

const delayed = shift(scenes, 60); // Start 60 frames later
```

#### Creating variations

```typescript theme={null}
const baseSequence = stagger(['A', 'B', 'C'], 10);

const earlyVersion = shift(baseSequence, -20);
const lateVersion = shift(baseSequence, 40);
```

## Common patterns

### Chapter-based composition

```typescript theme={null}
import { series, sequence } from '@helios-project/core';

const chapters = series([
  { title: 'Opening', durationInFrames: 90 },
  { title: 'Presentation', durationInFrames: 240 },
  { title: 'Demonstration', durationInFrames: 180 },
  { title: 'Conclusion', durationInFrames: 90 }
]);

function VideoComposition({ frame }) {
  return (
    <>
      {chapters.map((chapter) => {
        const seq = sequence({
          frame,
          from: chapter.from,
          durationInFrames: chapter.durationInFrames
        });
        
        return seq.isActive ? (
          <Chapter key={chapter.title} {...chapter} progress={seq.progress} />
        ) : null;
      })}
    </>
  );
}
```

### Overlapping transitions

```typescript theme={null}
const scenes = series([
  { id: 'a', durationInFrames: 90 },
  { id: 'b', durationInFrames: 90, offset: -15 }, // 15 frame overlap
  { id: 'c', durationInFrames: 90, offset: -15 }
]);

function Scene({ scene, frame }) {
  const seq = sequence({
    frame,
    from: scene.from,
    durationInFrames: scene.durationInFrames
  });
  
  // Fade in during first 15 frames, fade out during last 15 frames
  let opacity = 1;
  if (seq.localFrame < 15) {
    opacity = seq.localFrame / 15;
  } else if (seq.localFrame > scene.durationInFrames - 15) {
    opacity = (scene.durationInFrames - seq.localFrame) / 15;
  }
  
  return <div style={{ opacity }}>Scene content</div>;
}
```

### Multi-track timeline

```typescript theme={null}
const videoTrack = series([
  { type: 'clip', source: 'intro.mp4', durationInFrames: 120 },
  { type: 'clip', source: 'main.mp4', durationInFrames: 300 }
]);

const overlayTrack = stagger(
  ['Title', 'Subtitle', 'Call to action'],
  60,
  30 // Start at frame 30
);

function Timeline({ frame }) {
  return (
    <>
      <VideoLayer clips={videoTrack} frame={frame} />
      <OverlayLayer items={overlayTrack} frame={frame} />
    </>
  );
}
```

### Combining with animation helpers

```typescript theme={null}
import { series, sequence, interpolate, spring, Easing } from '@helios-project/core';

const elements = stagger(
  ['First', 'Second', 'Third', 'Fourth'],
  12
);

function AnimatedElements({ frame }) {
  return elements.map((item, i) => {
    const startFrame = item.from;
    
    // Use spring for natural entrance
    const scale = spring({
      frame: frame - startFrame,
      fps: 30,
      from: 0,
      to: 1,
      config: { stiffness: 150, damping: 12 }
    });
    
    // Use interpolate with easing for position
    const x = interpolate(
      frame,
      [startFrame, startFrame + 24],
      [-100, 0],
      { easing: Easing.cubic.out, extrapolateRight: 'clamp' }
    );
    
    const opacity = frame >= startFrame ? 1 : 0;
    
    return (
      <div
        key={i}
        style={{
          opacity,
          transform: `translateX(${x}px) scale(${scale})`
        }}
      >
        {item}
      </div>
    );
  });
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.