@reelkit/stories-core
Framework-agnostic stories state machine for ReelKit. Story and group navigation (tap to advance within a group, swipe to switch between users), auto-advance timer with pause/resume, tap zone detection, and segmented progress bar with sliding window for 50+ stories. ~1.7 kB gzip.
Installation
npm install @reelkit/stories-core @reelkit/core
Quick Start
import {
createStoriesController,
getTapAction,
getSegments,
} from '@reelkit/stories-core';
const controller = createStoriesController({
groupCount: 5,
storyCounts: [3, 4, 2, 5, 3],
});
controller.nextStory();
controller.prevStory();
controller.nextGroup();
controller.prevGroup();
console.log(controller.state.activeGroupIndex.value);
console.log(controller.state.activeStoryIndex.value);
getTapAction(50, 400);
getTapAction(300, 400);
const segments = getSegments(5, 2, 0.6);
Features
- Stories controller with story and group navigation and boundary detection
- Timer controller with
requestAnimationFrame progress and pause/resume
- Tap zone calculator (configurable left/right split ratio)
- Segmented progress bar with sliding window overflow
- Zero dependencies beyond
@reelkit/core
- Pure functions, fully tree-shakeable
API Reference
createStoriesController
groupCount | number | required | Number of story groups |
storyCounts | number[] | required | Stories per group |
initialGroupIndex | number | 0 | Starting group index |
initialStoryIndex | number | 0 | Starting story index |
defaultImageDuration | number | 5000 | Default auto-advance (ms) |
tapZoneSplit | number | 0.3 | Left zone ratio (0-1) |
StoriesController
state.activeGroupIndex | Signal<number> | Current group index |
state.activeStoryIndex | Signal<number> | Current story index |
state.isPaused | Signal<boolean> | Paused state |
nextStory() | void | Advance to next story |
prevStory() | void | Go to previous story |
nextGroup() | void | Switch to next user group |
prevGroup() | void | Switch to previous user group |
goToGroup(index) | void | Jump to specific group |
pause() | void | Pause timer and auto-advance |
resume() | void | Resume timer |
dispose() | void | Clean up subscriptions |
Events
onStoryChange | (groupIndex, storyIndex) => void | Fired after story navigation |
onGroupChange | (groupIndex) => void | Fired after group switch |
onStoryViewed | (groupIndex, storyIndex) => void | Fired when a story is viewed |
onComplete | () => void | Last story of last group finished |
onClose | () => void | Close requested (boundary navigation) |
getTapAction
function getTapAction(
tapX: number,
containerWidth: number,
splitRatio?: number,
): 'prev' | 'next';
getSegments
function getSegments(
totalStories: number,
activeIndex: number,
timerProgress: number,
): SegmentState[];
getVisibleWindow
function getVisibleWindow(
totalStories: number,
activeIndex: number,
timerProgress: number,
containerWidth: number,
minSegmentWidth?: number,
gap?: number,
): VisibleWindow;
Types
type TapAction = 'prev' | 'next';
type SegmentStatus = 'completed' | 'active' | 'upcoming';
interface SegmentState {
status: SegmentStatus;
fillPercentage: number;
}
interface VisibleWindow {
startIndex: number;
endIndex: number;
segments: SegmentState[];
}
Documentation
API reference and guides at reelkit.dev.
Support
If ReelKit saved you some time, a star on GitHub would mean a lot.

License
MIT