Files
hyperframes/packages/studio/src/components/editor/KeyframeDiamond.tsx
T
Miguel Ángel a468550f82 feat(studio): keyframe system — parser, runtime, timeline UI, design panel, gesture recording (#1311)
* feat(studio): runtime hooks — global time compiler + keyframe runtime

Add the runtime bridge layer: global time compilation (tween % → clip %),
soft reload after mutations, runtime keyframe preview, and keyframe
commit helper.

* feat(studio): runtime hooks — global time compiler + keyframe runtime

Add the runtime bridge layer: global time compilation (tween % → clip %),
soft reload after mutations, runtime keyframe preview, and keyframe
commit helper.

* feat(studio): keyframe cache + commit hooks

Add hooks for keyframe cache population (tween → clip-relative %),
mutation dispatch, keyframe snapping, and audio beat detection.

* feat(studio): timeline UI — dopesheet diamonds + keyboard nav

Add dopesheet strip with diamond keyframe indicators, timeline property
rows, keyboard navigation (J/Shift+J/Delete/K), and feature gate
(STUDIO_KEYFRAMES_ENABLED defaults to false).

* feat(studio): design panel — arc controls + ease curve + stagger

Add arc path controls (curviness slider, auto-rotate), motion path SVG
overlay, ease curve visualization, stagger controls, and expanded
animation card. Includes border-radius editor dependency from #1217.

* feat(studio): gesture recording core

Add gesture recording engine with RAF sampling, modifier key property
mapping (Shift→rotationXY, Alt→rotation, Cmd→opacity),
Ramer-Douglas-Peucker simplification, and ghost trail SVG overlay.

* fix(studio): keyframe drag + recording bug bash

21 fixes: capture GSAP base at drag start, translate:none before
gsap.set, skip reapplyPathOffsets for GSAP elements, clamp recording
seek, _auto flag for 100% keyframes, overlay flash fix, block edits
during recording.

* feat(studio): keyframe integration wiring + docs

Wire App.tsx recording orchestration, TimelineToolbar K/R buttons,
PropertyPanel per-property diamonds, shortcuts panel, toast
notifications, and keyframes guide documentation. All gated on
STUDIO_KEYFRAMES_ENABLED (default false).
2026-06-09 18:30:23 -04:00

65 lines
1.5 KiB
TypeScript

import { memo } from "react";
export type DiamondState = "active" | "inactive" | "ghost";
interface KeyframeDiamondProps {
state: DiamondState;
onClick: () => void;
title?: string;
size?: number;
isHold?: boolean;
}
// fallow-ignore-next-line complexity
export const KeyframeDiamond = memo(function KeyframeDiamond({
state,
onClick,
title,
size = 10,
isHold = false,
}: KeyframeDiamondProps) {
const isFilled = state === "active";
const opacity = state === "ghost" ? 0.25 : state === "inactive" ? 0.6 : 1;
const color = state === "active" ? "#3CE6AC" : "#a3a3a3";
return (
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onClick();
}}
className="flex-shrink-0 p-0.5 transition-opacity hover:opacity-100"
style={{ color, opacity }}
title={title}
>
<svg width={size} height={size} viewBox="0 0 10 10">
{isHold ? (
<rect
x="2"
y="2"
width="6"
height="6"
rx="0.5"
fill={isFilled ? "currentColor" : "none"}
stroke="currentColor"
strokeWidth="1.2"
/>
) : (
<rect
x="5"
y="0.7"
width="6"
height="6"
rx="1"
transform="rotate(45 5 0.7)"
fill={isFilled ? "currentColor" : "none"}
stroke="currentColor"
strokeWidth="1.2"
/>
)}
</svg>
</button>
);
});