import type { MediaTime } from "@/wasm"; import type { ParamValue } from "@/params"; export const ANIMATION_PROPERTY_PATHS = [ "transform.positionX", "transform.positionY", "transform.scaleX", "transform.scaleY", "transform.rotate", "opacity", "volume", "color", "background.color", "background.paddingX", "background.paddingY", "background.offsetX", "background.offsetY", "background.cornerRadius", ] as const; export type AnimationPropertyPath = (typeof ANIMATION_PROPERTY_PATHS)[number]; export type GraphicParamPath = `params.${string}`; export type EffectParamPath = `effects.${string}.params.${string}`; export type AnimationPath = string; export const ANIMATION_PROPERTY_GROUPS = { "transform.scale": ["transform.scaleX", "transform.scaleY"], } as const satisfies Record>; export type AnimationPropertyGroup = keyof typeof ANIMATION_PROPERTY_GROUPS; export type DiscreteValue = boolean | string; export interface NumericSpec { min?: number; max?: number; step?: number; } export type AnimationColorPropertyPath = Extract< AnimationPropertyPath, "color" | "background.color" >; export type AnimationNumericPropertyPath = Exclude< AnimationPropertyPath, AnimationColorPropertyPath >; export type ContinuousKeyframeInterpolation = "linear" | "hold" | "bezier"; export type DiscreteKeyframeInterpolation = "hold"; export type AnimationInterpolation = | ContinuousKeyframeInterpolation | DiscreteKeyframeInterpolation; export type ScalarSegmentType = "step" | "linear" | "bezier"; export type TangentMode = "auto" | "aligned" | "broken" | "flat"; export type ChannelExtrapolationMode = "hold" | "linear"; export interface CurveHandle { dt: MediaTime; dv: number; } interface BaseAnimationKeyframe { id: string; time: MediaTime; // relative to element start time value: TValue; } export interface ScalarAnimationKey extends BaseAnimationKeyframe { leftHandle?: CurveHandle; rightHandle?: CurveHandle; segmentToNext: ScalarSegmentType; tangentMode: TangentMode; } export type DiscreteAnimationKey = BaseAnimationKeyframe; export type Keyframe = TValue extends number ? ScalarAnimationKey : TValue extends DiscreteValue ? DiscreteAnimationKey : never; export interface ScalarChannel { keys: ScalarAnimationKey[]; extrapolation?: { before: ChannelExtrapolationMode; after: ChannelExtrapolationMode; }; } export interface DiscreteChannel { keys: DiscreteAnimationKey[]; } export type Channel = TValue extends number ? ScalarChannel : TValue extends DiscreteValue ? DiscreteChannel : never; export type ScalarAnimationChannel = Channel; export type DiscreteAnimationChannel = Channel; export type AnimationChannel = Channel; export type CompositeChannelData = Record; export type ChannelData = AnimationChannel | CompositeChannelData; export interface ElementAnimations { [propertyPath: AnimationPath]: ChannelData | undefined; } export type NormalizedCubicBezier = [number, number, number, number]; export interface ScalarGraphChannelTarget { propertyPath: AnimationPath; componentKey: string; } export interface ScalarGraphChannel extends ScalarGraphChannelTarget { channel: ScalarAnimationChannel; } export interface ScalarGraphKeyframeRef extends ScalarGraphChannelTarget { keyframeId: string; } export interface ScalarGraphKeyframeContext extends ScalarGraphChannel { keyframe: ScalarAnimationKey; keyframeIndex: number; previousKey: ScalarAnimationKey | null; nextKey: ScalarAnimationKey | null; } export interface ScalarCurveKeyframePatch { leftHandle?: CurveHandle | null; rightHandle?: CurveHandle | null; segmentToNext?: ScalarSegmentType; tangentMode?: TangentMode; } export interface ElementKeyframe { propertyPath: AnimationPath; id: string; time: MediaTime; value: ParamValue; interpolation: AnimationInterpolation; } export interface SelectedKeyframeRef { trackId: string; elementId: string; propertyPath: AnimationPath; keyframeId: string; }