Skip to content

feat(timeline-layers): add TimelineLayer CompositeLayer + example#517

Open
Copilot wants to merge 4 commits intomasterfrom
copilot/add-chrongl-timeline-layers
Open

feat(timeline-layers): add TimelineLayer CompositeLayer + example#517
Copilot wants to merge 4 commits intomasterfrom
copilot/add-chrongl-timeline-layers

Conversation

Copy link
Contributor

Copilot AI commented Feb 20, 2026

Extracts the timeline prototype from PR #379 into a proper reusable TimelineLayer in @deck.gl-community/timeline-layers, addressing Ib's feedback and the noodles.gl cross-project timeline discussion. The goal: a shared GPU-accelerated timeline primitive both noodles.gl and other deck.gl apps can mount directly.

Module: modules/timeline-layers/src/layers/timeline-layer/

  • timeline-types.tsTimelineClip, ClipWithSubtrack, TimelineTrack, TrackWithSubtracks, and all internal/callback info types
  • timeline-utils.tspositionToTime, timeToPosition, timeAxisFormatters (seconds, minutesSeconds, hoursMinutesSeconds, timestamp)
  • timeline-collision.ts — greedy subtrack assignment: overlapping clips automatically stack into subtracks
  • timeline-layout.tsSelectionStyle, TimelineLayout, DEFAULT_TIMELINE_LAYOUT
  • timeline-layer.tsTimelineLayer extends CompositeLayer: tracks, clips, axis, scrubber, hover/select state, zoom/pan API

All new exports re-exported from the module root.

Example: examples/timeline-layers/timeline-layer/

Per Ib's review comments on #379 — app is concise, scrubber/controls broken into separate components:

  • app.tsx — lean DeckGL + OrthographicView mount
  • demo-controls.tsx — sidebar panel (track count, duration, formatter, scrubber, zoom, advanced settings)
  • timeline-hooks.ts — interaction hooks: useWheelZoom, useContainerHandlers, useDeckGLHandlers, useCursorGetter
  • demo-utils.ts — random track/clip generator with 30% overlap probability to exercise collision detection

Tests: modules/timeline-layers/test/timeline-layer.spec.ts

47 unit tests across 7 suites covering all pure-function logic (no WebGL context required):

  • assignClipsToSubtracks — empty input, non-overlapping lanes, overlapping lanes, packing, sort-order independence, property preservation
  • calculateSubtrackCount — 1/2/3 subtrack scenarios
  • positionToTime — edges, midpoint, clamping, offset, non-zero startMs
  • timeToPosition — edges, midpoint, clamping, round-trip with positionToTime
  • timeAxisFormattersseconds, minutesSeconds (padding), hoursMinutesSeconds
  • generateTimelineTicks — count, first/last positions, formatter labels
  • TimelineLayer — static props, zoomToPoint (zoom in/out, max/min clamp, viewport callback range, boundary clamping)

Usage

import {TimelineLayer} from '@deck.gl-community/timeline-layers';

new TimelineLayer({
  data: tracks,           // TimelineTrack[]
  timelineStart: 0,
  timelineEnd: 60_000,
  currentTimeMs: 5_000,
  onClipClick: ({clip, track}) => console.log(clip.label),
  onViewportChange: (startMs, endMs) => setViewport({startMs, endMs}),
  onZoomChange: (zoom) => setZoom(zoom)
});

zoomToPoint(zoomFactor, mouseX, currentZoom) is exposed on the layer instance for wheel-zoom integration from the host app.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: charlieforward9 <62311337+charlieforward9@users.noreply.github.com>
Copilot AI changed the title [WIP] Add timeline layers module based on feedback feat(timeline-layers): add TimelineLayer CompositeLayer + example (chron.gl kickstarter) Feb 20, 2026
@charlieforward9 charlieforward9 marked this pull request as ready for review February 20, 2026 14:21
@charlieforward9
Copy link
Collaborator

@ibgreen I'd rather get a packaged example out now and incrementally split it up. Just put something on master and make it available for the community to help test out.

@copilot I want to call it time.gl or temp.gl - shorter. and make it released - finally - we want his branch off the existing work we did months ago. Keep the history

…ine-types, use in TrackWithSubtracks

Co-authored-by: charlieforward9 <62311337+charlieforward9@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

@ibgreen I'd rather get a packaged example out now and incrementally split it up. Just put something on master and make it available for the community to help test out.

@copilot I want to call it ...

Fixed the CI failure in e3c6113. The TS2345 error was because TrackWithSubtracks.clips was typed as TimelineClip[] (where subtrackIndex is optional), but _buildClipPolygon expected ClipWithSubtrack (where subtrackIndex is required after collision detection).

Fix: moved ClipWithSubtrack from timeline-collision.ts into timeline-types.ts, updated TrackWithSubtracks.clips: ClipWithSubtrack[], and explicitly typed the _buildClipPolygon parameter. All 263 tests pass, tsc --noEmit is clean.

On renaming to time.gl/temp.gl — that would mean a new package name (e.g. @deck.gl-community/time-layers or a standalone time.gl package). Happy to do that in a follow-up — want me to rename the module from timeline-layers to something shorter now, or land this first and rename separately?

@charlieforward9
Copy link
Collaborator

@copilot we need some tests for this layer

…tection, time utils

Co-authored-by: charlieforward9 <62311337+charlieforward9@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

@copilot we need some tests for this layer

Added modules/timeline-layers/test/timeline-layer.spec.ts in d2f4824 — 47 tests across 7 suites, all passing (310 total, 52 files):

  • assignClipsToSubtracks — empty input, non-overlapping on same lane, overlapping on separate lanes, packing 3 clips into 2 lanes, sort-order independence, property preservation
  • calculateSubtrackCount — returns 1 for empty/non-overlapping, 2 for pair overlap, 3 for triple overlap
  • positionToTime — left/right edges, midpoint, clamping (before/after range), non-zero offset, non-zero startMs
  • timeToPosition — left/right edges, midpoint, clamping, and a round-trip with positionToTime
  • timeAxisFormattersseconds (0ms, 1500ms, 5000ms), minutesSeconds (padding, 0ms, rollover), hoursMinutesSeconds (0ms, 1:01:01, padding)
  • generateTimelineTicks — correct count, first/last tick positions, formatter applied to labels
  • TimelineLayer — static props, zoomToPoint (zoom in/out, max/min clamp, viewport callback range, boundary clamping at left/right edges)

@charlieforward9 charlieforward9 changed the title feat(timeline-layers): add TimelineLayer CompositeLayer + example (chron.gl kickstarter) feat(timeline-layers): add TimelineLayer CompositeLayer + example\ Feb 20, 2026
@charlieforward9 charlieforward9 changed the title feat(timeline-layers): add TimelineLayer CompositeLayer + example\ feat(timeline-layers): add TimelineLayer CompositeLayer + example Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants