@react-kino/core
v0.4.0
Published
Framework-agnostic scroll engine powering react-kino
Readme
Do you need this package?
Probably not directly. @react-kino/core is the low-level scroll math (progress calculation, easing, duration parsing, pinning checks) that react-kino wraps with React components and hooks. If you're building with React, install react-kino instead -- it re-exports the types from this package (EasingName, EasingFn, ProgressData) so you rarely need to depend on @react-kino/core yourself.
Install this package directly only if you're integrating the scroll engine into a non-React app, or building bindings for another framework.
npm install @react-kino/coreWhat's included
ScrollTracker-- subscribes towindowscroll/resize events, batches updates viarequestAnimationFrame, and emits{ scrollY, viewportHeight, scrollHeight, progress }to subscribers. Resize bursts (window drags, mobile browser URL-bar show/hide) are debounced and coalesced into a single rAF-scheduled emission so viewport-dependent values stay in sync.ProgressValue-- a tiny, React-free "motion value". Holds a single number, notifies subscribers imperatively on change (get()/set(n)/on(fn)), and skips redundant notifications when the value is unchanged. This is the backbone of react-kino's ref-based rendering engine: components subscribe and write to the DOM directly, bypassing React's render cycle on the scroll hot path.calcElementProgress(offsets, info)-- computes element-relative scroll progress (0-1) from Motion-style offset pairs like["start end", "end start"], mapping an element's viewport entry/exit without pinning. Pure and unit-tested; helpersedgeToFraction,parseOffsetEntry, andresolveOffsetScrollYare also exported.calcSceneProgress(scrollY, offsetTop, duration)-- computes a pinned scene's progress (0-1) from raw scroll position.parseDuration(duration, viewportHeight)-- parses a CSS-like duration string ("200vh","1500px") into pixels. Warns in development (not production) and falls back to0if the input can't be parsed.isSceneActive(scrollY, offsetTop, duration)-- returns whether a scene is currently within its scroll range.clamp(value, min, max)/lerp(a, b, t)-- small numeric helpers used throughout the engine.- Easing presets --
linear,easeIn,easeOut,easeInOut,easeInCubic,easeOutCubic,easeInOutCubic,easeInQuart,easeOutQuart,easeInOutQuart, plus anEASINGSlookup keyed by the typedEasingNameunion ("linear" | "ease-in" | "ease-out" | "ease-in-out" | "ease-in-cubic" | "ease-out-cubic" | "ease-in-out-cubic" | "ease-in-quart" | "ease-out-quart" | "ease-in-out-quart"). - Types --
EasingFn,EasingName,SceneConfig,ProgressData,ScrollSubscriber,ProgressListener,OffsetEdge,OffsetEntry,ElementOffsetInfo.
import { ProgressValue, calcElementProgress } from "@react-kino/core";
// A motion value you can write to without re-rendering anything.
const progress = new ProgressValue(0);
const unsubscribe = progress.on((p) => {
element.style.setProperty("--kino-progress", String(p));
});
progress.set(0.5); // notifies subscribers; set(0.5) again is a no-op
// Element-relative progress (0 as it enters, 1 once it has fully passed).
const p = calcElementProgress(["start end", "end start"], {
elementTop: 1200, // rect.top + scrollY
elementHeight: 480,
viewportHeight: 800,
scrollY: 900,
});import {
ScrollTracker,
calcSceneProgress,
parseDuration,
} from "@react-kino/core";
const tracker = new ScrollTracker();
const unsubscribe = tracker.subscribe(({ scrollY, viewportHeight }) => {
const durationPx = parseDuration("300vh", viewportHeight);
const progress = calcSceneProgress(scrollY, /* offsetTop */ 0, durationPx);
console.log(progress); // 0 -> 1
});
tracker.start();
// later: unsubscribe(); tracker.stop();Design goals
- Zero dependencies -- pure TypeScript, runs anywhere (browser, edge runtimes) with no Node.js assumptions.
- Framework-agnostic -- no React (or any UI framework) in this package;
react-kinois the React binding. - Tiny -- import only the engine utilities you need.
- Type-safe -- ships full
.d.tsdeclarations and source maps.
License
MIT
Portable story documents
The separate @react-kino/core/document entry exports version 1 types, validateStory, parseStory, serializeStory, inspectStory, and sampleTrack. These pure APIs work without React or a DOM. Browser scroll tracking remains in the main entry.
Support independent maintenance
Support this project. Contributions support maintenance, documentation and development across Tourlight, Kino, Clickmap and Redact. Every feature remains MIT licensed.
