import type { PreviewAutomationResizeInput, PreviewViewportPresetId, PreviewViewportSetting,} from "@t3tools/contracts";import { PREVIEW_VIEWPORT_PRESET_IDS } from "@t3tools/contracts"; export interface PreviewViewportPreset { readonly id: PreviewViewportPresetId; readonly label: string; readonly category: "Desktop" | "Tablet" | "Phone"; readonly detail: string; readonly width: number; readonly height: number;} type PreviewViewportPresetDefinition = Omit<PreviewViewportPreset, "id">; // Keep this in Chrome DevTools' default-device order. Dimensions are CSS// viewport sizes from Chromium's EmulatedDevices.ts standard catalog.const PREVIEW_VIEWPORT_PRESET_DEFINITIONS = { "iphone-se": { label: "iPhone SE", category: "Phone", detail: "375 × 667", width: 375, height: 667, }, "iphone-xr": { label: "iPhone XR", category: "Phone", detail: "414 × 896", width: 414, height: 896, }, "iphone-12-pro": { label: "iPhone 12 Pro", category: "Phone", detail: "390 × 844", width: 390, height: 844, }, "iphone-14-pro-max": { label: "iPhone 14 Pro Max", category: "Phone", detail: "430 × 932", width: 430, height: 932, }, "pixel-7": { label: "Pixel 7", category: "Phone", detail: "412 × 915", width: 412, height: 915, }, "samsung-galaxy-s8-plus": { label: "Samsung Galaxy S8+", category: "Phone", detail: "360 × 740", width: 360, height: 740, }, "samsung-galaxy-s20-ultra": { label: "Samsung Galaxy S20 Ultra", category: "Phone", detail: "412 × 915", width: 412, height: 915, }, "ipad-mini": { label: "iPad Mini", category: "Tablet", detail: "768 × 1024", width: 768, height: 1024, }, "ipad-air": { label: "iPad Air", category: "Tablet", detail: "820 × 1180", width: 820, height: 1180, }, "ipad-pro": { label: "iPad Pro", category: "Tablet", detail: "1024 × 1366", width: 1024, height: 1366, }, "surface-pro-7": { label: "Surface Pro 7", category: "Tablet", detail: "912 × 1368", width: 912, height: 1368, }, "surface-duo": { label: "Surface Duo", category: "Phone", detail: "540 × 720", width: 540, height: 720, }, "galaxy-z-fold-5": { label: "Galaxy Z Fold 5", category: "Phone", detail: "344 × 882", width: 344, height: 882, }, "asus-zenbook-fold": { label: "Asus Zenbook Fold", category: "Tablet", detail: "853 × 1280", width: 853, height: 1280, }, "samsung-galaxy-a51-71": { label: "Samsung Galaxy A51/71", category: "Phone", detail: "412 × 914", width: 412, height: 914, }, "nest-hub": { label: "Nest Hub", category: "Tablet", detail: "1024 × 600", width: 1024, height: 600, }, "nest-hub-max": { label: "Nest Hub Max", category: "Tablet", detail: "1280 × 800", width: 1280, height: 800, },} as const satisfies Record<PreviewViewportPresetId, PreviewViewportPresetDefinition>; export const PREVIEW_VIEWPORT_PRESETS: ReadonlyArray<PreviewViewportPreset> = PREVIEW_VIEWPORT_PRESET_IDS.map((id) => ({ id, ...PREVIEW_VIEWPORT_PRESET_DEFINITIONS[id], })); export function resolvePreviewViewport( input: PreviewAutomationResizeInput,): PreviewViewportSetting { if (input.mode === "fill") return { _tag: "fill" }; if (input.mode === "preset" && input.preset !== undefined) { const preset = PREVIEW_VIEWPORT_PRESETS.find((candidate) => candidate.id === input.preset); if (!preset) throw new Error(`Unknown preview viewport preset: ${input.preset}`); const landscape = input.orientation === "landscape"; const portrait = input.orientation === "portrait"; const nativePortrait = preset.height >= preset.width; const shouldSwap = (landscape && nativePortrait) || (portrait && !nativePortrait); return { _tag: "preset", width: shouldSwap ? preset.height : preset.width, height: shouldSwap ? preset.width : preset.height, presetId: preset.id, }; } if (input.width === undefined || input.height === undefined) { throw new Error("Custom preview viewport requires width and height"); } return { _tag: "freeform", width: input.width, height: input.height, };}
import type {
PreviewAutomationResizeInput,
PreviewViewportPresetId,
PreviewViewportSetting,
} from "@t3tools/contracts";
import { PREVIEW_VIEWPORT_PRESET_IDS } from "@t3tools/contracts";
export interface PreviewViewportPreset {
readonly id: PreviewViewportPresetId;
readonly label: string;
readonly category: "Desktop" | "Tablet" | "Phone";
readonly detail: string;
readonly width: number;
readonly height: number;
}
type PreviewViewportPresetDefinition = Omit<PreviewViewportPreset, "id">;
// Keep this in Chrome DevTools' default-device order. Dimensions are CSS
// viewport sizes from Chromium's EmulatedDevices.ts standard catalog.
const PREVIEW_VIEWPORT_PRESET_DEFINITIONS = {
"iphone-se": {
label: "iPhone SE",
category: "Phone",
detail: "375 × 667",
width: 375,
height: 667,
},
"iphone-xr": {
label: "iPhone XR",
category: "Phone",
detail: "414 × 896",
width: 414,
height: 896,
},
"iphone-12-pro": {
label: "iPhone 12 Pro",
category: "Phone",
detail: "390 × 844",
width: 390,
height: 844,
},
"iphone-14-pro-max": {
label: "iPhone 14 Pro Max",
category: "Phone",
detail: "430 × 932",
width: 430,
height: 932,
},
"pixel-7": {
label: "Pixel 7",
category: "Phone",
detail: "412 × 915",
width: 412,
height: 915,
},
"samsung-galaxy-s8-plus": {
label: "Samsung Galaxy S8+",
category: "Phone",
detail: "360 × 740",
width: 360,
height: 740,
},
"samsung-galaxy-s20-ultra": {
label: "Samsung Galaxy S20 Ultra",
category: "Phone",
detail: "412 × 915",
width: 412,
height: 915,
},
"ipad-mini": {
label: "iPad Mini",
category: "Tablet",
detail: "768 × 1024",
width: 768,
height: 1024,
},
"ipad-air": {
label: "iPad Air",
category: "Tablet",
detail: "820 × 1180",
width: 820,
height: 1180,
},
"ipad-pro": {
label: "iPad Pro",
category: "Tablet",
detail: "1024 × 1366",
width: 1024,
height: 1366,
},
"surface-pro-7": {
label: "Surface Pro 7",
category: "Tablet",
detail: "912 × 1368",
width: 912,
height: 1368,
},
"surface-duo": {
label: "Surface Duo",
category: "Phone",
detail: "540 × 720",
width: 540,
height: 720,
},
"galaxy-z-fold-5": {
label: "Galaxy Z Fold 5",
category: "Phone",
detail: "344 × 882",
width: 344,
height: 882,
},
"asus-zenbook-fold": {
label: "Asus Zenbook Fold",
category: "Tablet",
detail: "853 × 1280",
width: 853,
height: 1280,
},
"samsung-galaxy-a51-71": {
label: "Samsung Galaxy A51/71",
category: "Phone",
detail: "412 × 914",
width: 412,
height: 914,
},
"nest-hub": {
label: "Nest Hub",
category: "Tablet",
detail: "1024 × 600",
width: 1024,
height: 600,
},
"nest-hub-max": {
label: "Nest Hub Max",
category: "Tablet",
detail: "1280 × 800",
width: 1280,
height: 800,
},
} as const satisfies Record<PreviewViewportPresetId, PreviewViewportPresetDefinition>;
export const PREVIEW_VIEWPORT_PRESETS: ReadonlyArray<PreviewViewportPreset> =
PREVIEW_VIEWPORT_PRESET_IDS.map((id) => ({
id,
...PREVIEW_VIEWPORT_PRESET_DEFINITIONS[id],
}));
export function resolvePreviewViewport(
input: PreviewAutomationResizeInput,
): PreviewViewportSetting {
if (input.mode === "fill") return { _tag: "fill" };
if (input.mode === "preset" && input.preset !== undefined) {
const preset = PREVIEW_VIEWPORT_PRESETS.find((candidate) => candidate.id === input.preset);
if (!preset) throw new Error(`Unknown preview viewport preset: ${input.preset}`);
const landscape = input.orientation === "landscape";
const portrait = input.orientation === "portrait";
const nativePortrait = preset.height >= preset.width;
const shouldSwap = (landscape && nativePortrait) || (portrait && !nativePortrait);
return {
_tag: "preset",
width: shouldSwap ? preset.height : preset.width,
height: shouldSwap ? preset.width : preset.height,
presetId: preset.id,
};
}
if (input.width === undefined || input.height === undefined) {
throw new Error("Custom preview viewport requires width and height");
}
return {
_tag: "freeform",
width: input.width,
height: input.height,
};
}