- Merge the small modules into 12 files: shared, choreography,
navigation, scene/{types,graph,scene}, gesture/{definition,recognizer}.
- SceneGraph now owns the begin/update/commit/cancel history rules as
methods, with the step helpers as private methods.
- createOriginScene returns a markRaw'd Scene class; operation handles
are an OperationHandle class instead of inline object literals.
- GestureRecognizer gains static create()/policyFor() factories, absorbing
the separate policy module.
- Pure helpers used by classes (matchesStart, pointOf, stepSpring,
composeNodeStyle, nodeEffectLayers, shouldCommit, ...) are exported
consts so they can be tested directly.
- Add haptics tests showing where navigator.vibrate can be triggered.
Public exports, types, and behavior are unchanged; the differential
suites against main still pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Faarh2Ts6StJPcz2mRiHiR
53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
/** A rectangle measured in viewport CSS pixels. */
|
|
export interface OriginRect {
|
|
/** Distance from the viewport's top edge in CSS pixels. */
|
|
top: number;
|
|
/** Distance from the viewport's left edge in CSS pixels. */
|
|
left: number;
|
|
/** Rectangle width in CSS pixels. */
|
|
width: number;
|
|
/** Rectangle height in CSS pixels. */
|
|
height: number;
|
|
}
|
|
|
|
/** Clamp a value to the inclusive unit range `0..1`. */
|
|
export function clamp01(value: number): number {
|
|
return Math.max(0, Math.min(1, value));
|
|
}
|
|
|
|
/** Clamp a value to the inclusive range `min..max`. */
|
|
export function clamp(value: number, min: number, max: number): number {
|
|
return Math.max(min, Math.min(max, value));
|
|
}
|
|
|
|
/** Measure an element's viewport bounds as a plain, serializable rectangle. */
|
|
export function measureRect(element: Element): OriginRect {
|
|
const { top, left, width, height } = element.getBoundingClientRect();
|
|
return { top, left, width, height };
|
|
}
|
|
|
|
/** Bounds of the browser window, or a unit rectangle outside a browser. */
|
|
export function windowRect(): OriginRect {
|
|
const browser = typeof window !== "undefined";
|
|
return {
|
|
top: 0,
|
|
left: 0,
|
|
width: browser ? window.innerWidth : 1,
|
|
height: browser ? window.innerHeight : 1,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Whether animation should resolve immediately.
|
|
*
|
|
* True outside a browser, when `requestAnimationFrame` is unavailable, or when
|
|
* the user prefers reduced motion.
|
|
*/
|
|
export function prefersReducedMotion(): boolean {
|
|
return (
|
|
typeof window === "undefined" ||
|
|
!window.requestAnimationFrame ||
|
|
Boolean(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)
|
|
);
|
|
}
|