mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-11-10 16:04:38 +00:00
86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
export const ASPECT_RATIOS = ['native', '16:9', '9:16', '1:1', '4:3', '4:5', '16:10', '10:16'] as const;
|
|
|
|
type PresetAspectRatio = typeof ASPECT_RATIOS[number];
|
|
type CustomAspectRatio = `${number}:${number}`;
|
|
|
|
export type AspectRatio = PresetAspectRatio | CustomAspectRatio;
|
|
|
|
const CUSTOM_ASPECT_RATIO_REGEX = /^(\d+):(\d+)$/;
|
|
|
|
export function isCustomAspectRatio(aspectRatio: string): aspectRatio is CustomAspectRatio {
|
|
if ((ASPECT_RATIOS as readonly string[]).includes(aspectRatio)) {
|
|
return false;
|
|
}
|
|
const match = aspectRatio.match(CUSTOM_ASPECT_RATIO_REGEX);
|
|
if (!match) {
|
|
return false;
|
|
}
|
|
const width = Number(match[1]);
|
|
const height = Number(match[2]);
|
|
return Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0;
|
|
}
|
|
|
|
function parseCustomAspectRatioValue(aspectRatio: string): number | null {
|
|
if (!isCustomAspectRatio(aspectRatio)) {
|
|
return null;
|
|
}
|
|
const [widthText, heightText] = aspectRatio.split(':');
|
|
const width = Number(widthText);
|
|
const height = Number(heightText);
|
|
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
return null;
|
|
}
|
|
return width / height;
|
|
}
|
|
|
|
/**
|
|
* Returns the numeric value of an aspect ratio.
|
|
* Uses exhaustive type checking to ensure all AspectRatio cases are handled.
|
|
* If TypeScript errors here, a new ratio was added to the type but not handled.
|
|
*/
|
|
export function getAspectRatioValue(aspectRatio: AspectRatio, nativeAspectRatio = 16 / 9): number {
|
|
switch (aspectRatio) {
|
|
case 'native': return nativeAspectRatio > 0 ? nativeAspectRatio : 16 / 9;
|
|
case '16:9': return 16 / 9;
|
|
case '9:16': return 9 / 16;
|
|
case '1:1': return 1;
|
|
case '4:3': return 4 / 3;
|
|
case '4:5': return 4 / 5;
|
|
case '16:10': return 16 / 10;
|
|
case '10:16': return 10 / 16;
|
|
default:
|
|
return parseCustomAspectRatioValue(aspectRatio) ?? 16 / 9;
|
|
}
|
|
}
|
|
|
|
export function getAspectRatioDimensions(
|
|
aspectRatio: AspectRatio,
|
|
baseWidth: number,
|
|
nativeAspectRatio?: number,
|
|
): { width: number; height: number } {
|
|
const ratio = getAspectRatioValue(aspectRatio, nativeAspectRatio);
|
|
return {
|
|
width: baseWidth,
|
|
height: baseWidth / ratio,
|
|
};
|
|
}
|
|
|
|
export function getAspectRatioLabel(aspectRatio: AspectRatio): string {
|
|
if (aspectRatio === 'native') {
|
|
return 'Native';
|
|
}
|
|
if (isCustomAspectRatio(aspectRatio)) {
|
|
return `Custom ${aspectRatio}`;
|
|
}
|
|
return aspectRatio;
|
|
}
|
|
|
|
|
|
export function formatAspectRatioForCSS(aspectRatio: AspectRatio, nativeAspectRatio = 16 / 9): string {
|
|
if (aspectRatio === 'native') {
|
|
return `${nativeAspectRatio > 0 ? nativeAspectRatio : 16 / 9}`;
|
|
}
|
|
return aspectRatio.replace(':', '/');
|
|
}
|
|
|