// #54 Phase 1 — single source of truth for transition presets. SHARED so
// server-side render-pipeline and client-side preview consume the SAME
// metadata; the Remotion presentation factory lives in the web layer
// (it imports from @remotion/transitions, a browser/render-time module),
// but the data model + family + default duration live here so server-side
// validation and any future ffmpeg xfade mapping stay in lockstep.
//
// Why a registry (not just an enum): the issue's core architectural risk
// is two engines drifting visually. A registry forces every consumer to
// add the same row when introducing a preset, so adding a preset to the
// schema without the matching renderer becomes a type error, not a silent
// "render-only" or "preview-only" orphan.
export const TRANSITION_PRESETS = [
    // ① dissolve
    "cross-dissolve",
    // ② wipe — directional + radial
    "wipe-left",
    "wipe-right",
    "wipe-up",
    "wipe-down",
    "clock-wipe",
    "iris",
    // ③ slide / push
    "push-left",
    "push-right",
    "push-up",
    "push-down",
    // ④ motion
    "flip",
    // ⑥ cut
    "hard-cut",
];
export const TRANSITION_PRESET_META = {
    "cross-dissolve": { family: "dissolve", ffmpegXfade: "fade", defaultDurationSec: 0.5 },
    "wipe-left": { family: "wipe", ffmpegXfade: "wipeleft", defaultDurationSec: 0.5 },
    "wipe-right": { family: "wipe", ffmpegXfade: "wiperight", defaultDurationSec: 0.5 },
    "wipe-up": { family: "wipe", ffmpegXfade: "wipeup", defaultDurationSec: 0.5 },
    "wipe-down": { family: "wipe", ffmpegXfade: "wipedown", defaultDurationSec: 0.5 },
    "clock-wipe": { family: "wipe", ffmpegXfade: "radial", defaultDurationSec: 0.7 },
    "iris": { family: "wipe", ffmpegXfade: "circleopen", defaultDurationSec: 0.7 },
    "push-left": { family: "slide", ffmpegXfade: "slideleft", defaultDurationSec: 0.5 },
    "push-right": { family: "slide", ffmpegXfade: "slideright", defaultDurationSec: 0.5 },
    "push-up": { family: "slide", ffmpegXfade: "slideup", defaultDurationSec: 0.5 },
    "push-down": { family: "slide", ffmpegXfade: "slidedown", defaultDurationSec: 0.5 },
    "flip": { family: "motion", ffmpegXfade: "", defaultDurationSec: 0.7 },
    "hard-cut": { family: "cut", ffmpegXfade: "", defaultDurationSec: 0.05 },
};
export function getPresetMeta(preset) {
    return TRANSITION_PRESET_META[preset];
}
// The transition durationSec schema bounds (src/shared/composition.ts
// TransitionSchema: z.number().min(0.05).max(5)). Mirrored here as the single
// source of truth for the clamp so the op layer never produces a value zod will
// reject on write. Keep these in lockstep with TransitionSchema's min/max.
export const TRANSITION_DURATION_MIN_SEC = 0.05;
export const TRANSITION_DURATION_MAX_SEC = 5;
/**
 * Clamp a desired transition duration to what the two adjacent clips can
 * physically afford ("handles"). A transition consumes durationSec from BOTH
 * adjacent clips; without this guard the renderer either panics or silently
 * produces a flicker. Returns the clamped duration in seconds, bounded to the
 * schema's [0.05, 5] range.
 *
 * `desiredSec` = the user's intent. `clipBeforeDur`, `clipAfterDur` = the
 * usable content duration of the clips on either side of the cut. The cap is
 * the lesser of the two halved (each clip contributes half the transition),
 * AND never exceeds the schema ceiling (so two very long adjacent clips can't
 * yield a dur > 5 that the write-path zod parse would then reject).
 */
export function clampHandleDuration(desiredSec, clipBeforeDur, clipAfterDur) {
    // Both halves contribute equally → each clip donates desiredSec/2. Cap so
    // neither donation exceeds half of its source duration.
    const maxHalf = Math.max(0, Math.min(clipBeforeDur, clipAfterDur) / 2);
    const cappedHalf = Math.min(desiredSec / 2, maxHalf);
    const out = cappedHalf * 2;
    // Bound to the schema's [min, max]: floor at 0.05 (never zero) and cap at the
    // schema max so an extreme desiredSec on very long clips can't produce a value
    // zod rejects on writeCompositionFor's parse.
    return Math.min(TRANSITION_DURATION_MAX_SEC, Math.max(TRANSITION_DURATION_MIN_SEC, out));
}
//# sourceMappingURL=transitions.js.map