# `hooks/use-timeline` _(no submodules)_ ## Purpose `useTimeline()` returns the provider's single `TimelineEngine` instance, the canonical owner of timeline state — tracks, clips, selection, loop region, master volume, undo/redo. The engine exposes its own typed event surface (`engine.on(event, listener)`); consumers who want to *subscribe* to engine events should pair this hook with `useSyncExternalStore` and pass `engine.on(...)` as the subscribe callback. The hook itself returns the engine handle and does not trigger re-renders on engine state changes. ## Features - Returns the `TimelineEngine` instance owned by the provider. - Stable identity across re-renders within a ready phase. - Throws `REACT_AUDIO.NO_PROVIDER` outside ``. - Throws `REACT_AUDIO.PROVIDER_PENDING` during async init. ## Usage: Basic ```tsx import { useTimeline } from "@suaveplan/react-audio"; function AddTrackButton() { const timeline = useTimeline(); return ( ); } ``` ## Usage: Advanced ```tsx import { useSyncExternalStore } from "react"; import { useTimeline } from "@suaveplan/react-audio"; function useTrackCount(): number { const timeline = useTimeline(); return useSyncExternalStore( (listener) => timeline.on("trackChange", listener as never), () => timeline.getState().tracks.length, () => timeline.getState().tracks.length ); } ``` ## API Reference - `useTimeline(): TimelineEngine` — see `@suaveplan/audio-timeline` for the full engine surface. ## Implementation Notes The hook deliberately stops short of re-rendering on every engine event. The `TimelineEngine` has a rich change surface and re-rendering on every state delta would be expensive at chain scale. Consumers choose which events they care about and pair the engine handle with `useSyncExternalStore` for narrow subscriptions, paying only for the re-renders they want. Mutator methods (`addTrack`, `updateTrack`, `removeTrack`, `setTempo`, `setMasterVolume`, …) are exposed directly on the engine handle — callers wrap them in their own callbacks when they need referential stability across renders. For per-track state prefer `useTrack(id)`, which already wraps `useSyncExternalStore` against the timeline's `trackChange` event so its subscription is narrow by construction.