mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-05 17:30:50 +00:00
* feat(studio): timeline collision and placement model What: new pure module timelineCollision — zone-aware drop placement (clampTrackToZone, resolveZoneDropPlacement, resolveInsertRow, resolvePlacement, lane/overlap predicates) with its full test suite. Why: the no-overlap core of the NLE clip-drag engine; plain functions, no DOM, no React, no store writes. How: new files only; type-only imports from the existing playerStore. First runtime consumer arrives with the drag-engine PRs. Test plan: bunx vitest run timelineCollision.test.ts; tsc --noEmit; fallow audit clean (all exports test-consumed). * feat(studio): timeline magnetic snapping What: new pure module timelineSnapping — snap-target collection and pixel-threshold time snapping (collectTimelineSnapTargets, snapTimelineTime, snapMoveToTargets) with tests. Why: the magnet math for clip drags/trims, reviewable standalone. How: new files only; type-only playerStore imports; consumers land with the drag engine. Test plan: bunx vitest run timelineSnapping.test.ts; tsc --noEmit; fallow audit clean. * feat(studio): multi-clip drag preview math What: new pure module timelineMultiDragPreview — group-drag passenger offsets and clamped group deltas (isMultiDragActive, multiDragDeltaSeconds, multiDragPassengerOffsetPx, clampGroupMoveDelta) with tests. Why: the group-drag math, standalone and DOM-free. How: new files only; consumed later by TimelineLanes. Test plan: bunx vitest run timelineMultiDragPreview.test.ts; tsc --noEmit; fallow audit clean. * feat(studio): timeline z-stacking sync model What: new pure module timelineStackingSync — lane order ↔ z-index reconciliation (laneIsAbove, computeStackingPatches) with tests. Why: the single source of truth for how timeline lane order maps to canvas stacking; the ordering rules and tie-breaks live here. How: new files only; consumed later by timelineZones and the stacking-sync hook. Test plan: bunx vitest run timelineStackingSync.test.ts; tsc --noEmit; fallow audit clean. * feat(studio): timeline lane-zone model What: new pure module timelineZones — visual/audio track-zone classification (classifyZone) and normalizeToZones, which re-packs lanes into zone-consistent rows; tests cover the stacking/zones interaction. Why: completes the z-model started in the stacking-sync PR. How: new files; consumes isAudioTimelineElement (leaf-helpers PR) and computeStackingPatches (stacking-sync PR); type-only playerStore imports. Test plan: bunx vitest run timelineZones.test.ts; tsc --noEmit; fallow audit clean. * feat(studio): asset click policy and canvas nudge gate What: two small pure modules with tests — assetClickBehavior (click vs double-click policy for sidebar assets) and canvasNudgeGate (debounce gate for arrow-key canvas nudges). Why: policy dependencies of the upcoming asset card and nudge hook, reviewable as plain decision tables. How: new files only. Test plan: bunx vitest run on both test files; tsc --noEmit; fallow audit clean. --------- Co-authored-by: ukimsanov <ular.kimsanov@heygen.com>
32 lines
1.1 KiB
TypeScript
32 lines
1.1 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import { __resetForTests, acquireCanvasNudgeKeys, canvasNudgeKeysClaimed } from "./canvasNudgeGate";
|
|
|
|
describe("canvasNudgeGate", () => {
|
|
// The claim counter is module-level state; reset it so an unbalanced claim in one
|
|
// test can't leak into the next.
|
|
beforeEach(() => {
|
|
__resetForTests();
|
|
});
|
|
|
|
it("reports claimed while at least one claim is held", () => {
|
|
expect(canvasNudgeKeysClaimed()).toBe(false);
|
|
const releaseA = acquireCanvasNudgeKeys();
|
|
const releaseB = acquireCanvasNudgeKeys();
|
|
expect(canvasNudgeKeysClaimed()).toBe(true);
|
|
releaseA();
|
|
expect(canvasNudgeKeysClaimed()).toBe(true);
|
|
releaseB();
|
|
expect(canvasNudgeKeysClaimed()).toBe(false);
|
|
});
|
|
|
|
it("makes release idempotent so an effect re-run cannot underflow", () => {
|
|
const release = acquireCanvasNudgeKeys();
|
|
release();
|
|
release();
|
|
expect(canvasNudgeKeysClaimed()).toBe(false);
|
|
const releaseNext = acquireCanvasNudgeKeys();
|
|
expect(canvasNudgeKeysClaimed()).toBe(true);
|
|
releaseNext();
|
|
});
|
|
});
|