Stories Core
The engine behind @reelkit/react-stories-player. Pure TypeScript, no framework deps. Use it to build stories players for Angular, Vue, or vanilla JS.
Installation
Stories Controller
createStoriesController(config, events?) manages navigation across groups and stories. Tracks pause/resume state, remembers the last viewed story per group, and fires callbacks on each transition.
Config (StoriesControllerConfig)
| Property | Type | Default | Description |
|---|---|---|---|
| groupCount | number | required | Total number of story groups |
| storyCounts | number[] | required | Number of stories in each group |
| initialGroupIndex | number | 0 | Initial group index |
| initialStoryIndex | number | 0 | Initial story index within the group |
| defaultImageDuration | number | 5000 | Default auto-advance duration for image stories in ms |
Events (StoriesControllerEvents)
| Event | Type | Description |
|---|---|---|
| onStoryChange | (groupIndex, storyIndex) => void | Fired when the active story changes |
| onGroupChange | (groupIndex) => void | Fired when the active group changes |
| onStoryViewed | (groupIndex, storyIndex) => void | Fired when a story becomes visible |
| onStoryComplete | (groupIndex, storyIndex) => void | Fired when a story's timer completes (before advancing) |
| onComplete | () => void | Fired when the last story of the last group finishes |
| onClose | () => void | Fired when the overlay should close |
State (reactive signals)
| Signal | Type | Description |
|---|---|---|
| state.activeGroupIndex | Signal<number> | Currently active group index |
| state.activeStoryIndex | Signal<number> | Currently active story index within the group |
| state.isPaused | Signal<boolean> | Whether auto-advance is paused |
Methods
| Method | Type | Description |
|---|---|---|
| nextStory() | () => void | Advance within group; crosses boundary to next group |
| prevStory() | () => void | Go back within group; crosses boundary to prev group |
| nextGroup() | () => void | Switch to next group, resuming at last viewed story |
| prevGroup() | () => void | Switch to previous group, resuming at last viewed story |
| goToGroup(index) | (number) => void | Jump to a specific group by index |
| pause() | () => void | Pause auto-advance |
| resume() | () => void | Resume auto-advance |
| onStoryTimerComplete() | () => void | Called when the timer finishes; fires onStoryComplete then advances |
| getLastStoryIndex(groupIndex) | (number) => number | Last viewed story index for a group (0 if never visited) |
| dispose() | () => void | Clean up resources |
Example
Timer Controller
createTimerController(config) drives auto-advance with a requestAnimationFrame loop. The progress signal (0 to 1) feeds the progress bar. Pause and resume preserve the exact position.
Config (TimerControllerConfig)
| Property | Type | Default | Description |
|---|---|---|---|
| duration | number | required | Default duration in milliseconds |
| onComplete | () => void | undefined | Called when the timer reaches 100% |
State
| Signal | Type | Description |
|---|---|---|
| progress | Signal<number> | Progress signal (0 to 1) |
| isRunning | Signal<boolean> | Whether the timer is currently running |
Methods
| Method | Type | Description |
|---|---|---|
| start(duration?) | (number?) => void | Start (or restart) the timer with an optional duration override |
| pause() | () => void | Freeze progress at the current position |
| resume() | () => void | Continue from the frozen position |
| reset() | () => void | Reset progress to 0 and stop |
| dispose() | () => void | Clean up resources |
Example
Canvas Progress Renderer
createCanvasProgressRenderer(config?) draws segmented progress bars on a canvas. Scales for Retina displays, measures its container via ResizeObserver, and uses a sliding window when segments don't fit.
Config (CanvasProgressRendererConfig)
| Property | Type | Default | Description |
|---|---|---|---|
| gap | number | 2 | Gap in pixels between segments |
| barHeight | number | 2 | Bar height in pixels |
| minSegmentWidth | number | 8 | Minimum segment width before the sliding window kicks in |
| bgColor | string | 'rgba(255,255,255,0.3)' | Background color of unfilled segments |
| fillColor | string | '#ffffff' | Fill color of completed/active segments |
Methods
| Member | Type | Description |
|---|---|---|
| attach(canvas) | (HTMLCanvasElement) => void | Attach to a canvas element; starts ResizeObserver on parent |
| draw(totalStories, activeIndex, progress) | (number, number, number) => void | Draw the progress bar for the given state |
| width | number (readonly) | Current measured width in CSS pixels |
| dispose() | () => void | Clean up ResizeObserver and internal state |
Example
Utility Functions
Pure functions for tap zone detection and progress bar math.
| Function | Type | Description |
|---|---|---|
| getTapAction(tapX, containerWidth, splitRatio?) | (number, number, number?) => 'prev' | 'next' | Determines whether a tap triggers 'prev' or 'next' based on position. Default splitRatio is 0.3. |
| getSegments(totalStories, activeIndex, progress) | (number, number, number) => SegmentState[] | Computes status and fill percentage of each segment in a progress bar |
| getVisibleWindow(totalStories, activeIndex, progress, containerWidth, minSegmentWidth?, gap?) | (number, number, number, number, number?, number?) => VisibleWindow | Computes the visible sliding window of segments when total count exceeds container capacity |
Types
All type definitions exported from @reelkit/stories-core.