135 lines
3.2 KiB
TypeScript
135 lines
3.2 KiB
TypeScript
/**
|
|
* useTransitionCreation Hook
|
|
*
|
|
* Encapsulates transition creation form state and actions.
|
|
* Used in the constructor to manage the "Create Transition" form.
|
|
*/
|
|
|
|
import { useState, useCallback, useEffect } from 'react';
|
|
import type { AssetOption } from '../types/constructor';
|
|
|
|
export interface TransitionCreationState {
|
|
/** Transition name */
|
|
name: string;
|
|
/** Video URL/storage key */
|
|
videoUrl: string;
|
|
/** Whether transition supports reverse playback */
|
|
supportsReverse: boolean;
|
|
/** Whether transition is being created */
|
|
isCreating: boolean;
|
|
}
|
|
|
|
export interface TransitionCreationActions {
|
|
/** Set transition name */
|
|
setName: (name: string) => void;
|
|
/** Set video URL */
|
|
setVideoUrl: (url: string) => void;
|
|
/** Set supports reverse flag */
|
|
setSupportsReverse: (value: boolean) => void;
|
|
/** Create the transition */
|
|
create: () => void;
|
|
/** Reset form to initial state */
|
|
reset: () => void;
|
|
}
|
|
|
|
export interface UseTransitionCreationOptions {
|
|
/** Available transition video options */
|
|
videoOptions: AssetOption[];
|
|
/** Callback to create transition */
|
|
onCreate: (params: {
|
|
name: string;
|
|
videoUrl: string;
|
|
supportsReverse: boolean;
|
|
durationSec?: number;
|
|
}) => Promise<void>;
|
|
/** Get duration of video URL */
|
|
getDuration?: (url: string) => number | undefined;
|
|
}
|
|
|
|
export interface UseTransitionCreationResult
|
|
extends TransitionCreationState,
|
|
TransitionCreationActions {}
|
|
|
|
/**
|
|
* Hook to manage transition creation form state.
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* const {
|
|
* name,
|
|
* videoUrl,
|
|
* supportsReverse,
|
|
* isCreating,
|
|
* setName,
|
|
* setVideoUrl,
|
|
* setSupportsReverse,
|
|
* create,
|
|
* } = useTransitionCreation({
|
|
* videoOptions: transitionVideoAssetOptions,
|
|
* onCreate: handleCreateTransition,
|
|
* getDuration,
|
|
* });
|
|
* ```
|
|
*/
|
|
export function useTransitionCreation({
|
|
videoOptions,
|
|
onCreate,
|
|
getDuration,
|
|
}: UseTransitionCreationOptions): UseTransitionCreationResult {
|
|
const [name, setName] = useState('');
|
|
const [videoUrl, setVideoUrl] = useState('');
|
|
const [supportsReverse, setSupportsReverse] = useState(true);
|
|
const [isCreating, setIsCreating] = useState(false);
|
|
|
|
// Auto-select first video option when available
|
|
useEffect(() => {
|
|
if (videoUrl) return;
|
|
if (!videoOptions.length) return;
|
|
setVideoUrl(videoOptions[0].value);
|
|
}, [videoUrl, videoOptions]);
|
|
|
|
const create = useCallback(async () => {
|
|
if (isCreating) return;
|
|
if (!videoUrl) return;
|
|
|
|
setIsCreating(true);
|
|
try {
|
|
const durationSec = getDuration?.(videoUrl);
|
|
await onCreate({
|
|
name,
|
|
videoUrl,
|
|
supportsReverse,
|
|
durationSec,
|
|
});
|
|
// Reset form on success
|
|
setName('');
|
|
setSupportsReverse(true);
|
|
} finally {
|
|
setIsCreating(false);
|
|
}
|
|
}, [isCreating, name, videoUrl, supportsReverse, getDuration, onCreate]);
|
|
|
|
const reset = useCallback(() => {
|
|
setName('');
|
|
setVideoUrl(videoOptions[0]?.value || '');
|
|
setSupportsReverse(true);
|
|
setIsCreating(false);
|
|
}, [videoOptions]);
|
|
|
|
return {
|
|
// State
|
|
name,
|
|
videoUrl,
|
|
supportsReverse,
|
|
isCreating,
|
|
// Actions
|
|
setName,
|
|
setVideoUrl,
|
|
setSupportsReverse,
|
|
create,
|
|
reset,
|
|
};
|
|
}
|
|
|
|
export default useTransitionCreation;
|