39948-vm/frontend/src/hooks/useAssetOptions.ts

120 lines
3.0 KiB
TypeScript

/**
* useAssetOptions Hook
*
* Derives memoized asset options for select dropdowns from project assets.
* This hook is used by ConstructorContext to provide pre-computed asset options.
*/
import { useMemo } from 'react';
import type {
ConstructorAsset as ProjectAsset,
AssetOption,
} from '../types/constructor';
import {
buildAssetOptions,
buildBackgroundImageOptions,
buildVideoAssetOptions,
buildAudioAssetOptions,
buildTransitionVideoOptions,
buildIconAssetOptions,
buildImageAssetOptions,
getAssetSourceValue,
} from '../lib/constructorHelpers';
export interface AssetOptionsResult {
/** All image assets (for galleries, carousels) */
image: AssetOption[];
/** Background image assets only */
backgroundImage: AssetOption[];
/** All video assets (except transitions) */
video: AssetOption[];
/** All audio assets */
audio: AssetOption[];
/** Transition video assets */
transitionVideo: AssetOption[];
/** Icon image assets */
icon: AssetOption[];
}
export interface UseAssetOptionsOptions {
/** Project assets to derive options from */
assets: ProjectAsset[];
}
/**
* Hook to derive memoized asset options from project assets.
*
* @example
* ```typescript
* const { image, video, audio, icon, transitionVideo } = useAssetOptions({
* assets: projectAssets,
* });
*
* <AssetSelect options={image} value={selectedImage} onChange={setImage} />
* ```
*/
export function useAssetOptions({
assets,
}: UseAssetOptionsOptions): AssetOptionsResult {
// All image assets
const imageOptions = useMemo(() => buildImageAssetOptions(assets), [assets]);
// Background image assets (filtered by type or naming convention)
const backgroundImageOptions = useMemo(
() => buildBackgroundImageOptions(assets),
[assets],
);
// Video assets (excluding transition videos)
const videoOptions = useMemo(
() =>
assets
.filter(
(asset) =>
asset.asset_type === 'video' &&
asset.type !== 'transition' &&
getAssetSourceValue(asset),
)
.map((asset) => ({
value: getAssetSourceValue(asset),
label: asset.name
? `${asset.name} · ${getAssetSourceValue(asset)}`
: getAssetSourceValue(asset),
})),
[assets],
);
// Audio assets
const audioOptions = useMemo(() => buildAudioAssetOptions(assets), [assets]);
// Transition video assets
const transitionVideoOptions = useMemo(
() => buildTransitionVideoOptions(assets),
[assets],
);
// Icon assets
const iconOptions = useMemo(() => buildIconAssetOptions(assets), [assets]);
return useMemo(
() => ({
image: imageOptions,
backgroundImage: backgroundImageOptions,
video: videoOptions,
audio: audioOptions,
transitionVideo: transitionVideoOptions,
icon: iconOptions,
}),
[
imageOptions,
backgroundImageOptions,
videoOptions,
audioOptions,
transitionVideoOptions,
iconOptions,
],
);
}
export default useAssetOptions;