@reelkit/stories-core
v0.2.0
Published
Framework-agnostic stories state machine, timer, and utilities for ReelKit
Maintainers
Readme
@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/coreQuick Start
import {
createStoriesController,
getTapAction,
getSegments,
} from '@reelkit/stories-core';
const controller = createStoriesController({
groupCount: 5,
storyCounts: [3, 4, 2, 5, 3],
});
// Navigate stories
controller.nextStory();
controller.prevStory();
// Switch between users
controller.nextGroup();
controller.prevGroup();
// Read state via signals
console.log(controller.state.activeGroupIndex.value); // 0
console.log(controller.state.activeStoryIndex.value); // 1
// Tap zone detection
getTapAction(50, 400); // 'prev' (left 30%)
getTapAction(300, 400); // 'next' (right 70%)
// Progress bar segments
const segments = getSegments(5, 2, 0.6);
// [completed, completed, active(60%), upcoming, upcoming]Features
- Stories controller with story and group navigation and boundary detection
- Timer controller with
requestAnimationFrameprogress 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
| Config | Type | Default | Description |
| ---------------------- | ---------- | -------- | ------------------------- |
| 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
| Method / Property | Type | Description |
| ------------------------ | ----------------- | ----------------------------- |
| 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
| Event | Type | Description |
| --------------- | ---------------------------------- | ------------------------------------- |
| 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, // default: 0.3
): 'prev' | 'next';getSegments
function getSegments(
totalStories: number,
activeIndex: number,
timerProgress: number, // 0-1
): SegmentState[];getVisibleWindow
function getVisibleWindow(
totalStories: number,
activeIndex: number,
timerProgress: number,
containerWidth: number,
minSegmentWidth?: number, // default: 4
gap?: number,
): VisibleWindow;Types
type TapAction = 'prev' | 'next';
type SegmentStatus = 'completed' | 'active' | 'upcoming';
interface SegmentState {
status: SegmentStatus;
fillPercentage: number; // 0-100
}
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.
