diff --git a/web/src/lib/utils/layout-utils.spec.ts b/web/src/lib/utils/layout-utils.spec.ts new file mode 100644 index 0000000000..49c38c0d67 --- /dev/null +++ b/web/src/lib/utils/layout-utils.spec.ts @@ -0,0 +1,54 @@ +import { scaleToFit } from '$lib/utils/layout-utils'; + +describe('scaleToFit', () => { + const tests = [ + { + name: 'landscape image in square container', + dimensions: { width: 2000, height: 1000 }, + container: { width: 500, height: 500 }, + expected: { width: 500, height: 250 }, + }, + { + name: 'portrait image in square container', + dimensions: { width: 1000, height: 2000 }, + container: { width: 500, height: 500 }, + expected: { width: 250, height: 500 }, + }, + { + name: 'square image in square container', + dimensions: { width: 1000, height: 1000 }, + container: { width: 500, height: 500 }, + expected: { width: 500, height: 500 }, + }, + { + name: 'landscape image in landscape container', + dimensions: { width: 1600, height: 900 }, + container: { width: 800, height: 600 }, + expected: { width: 800, height: 450 }, + }, + { + name: 'portrait image in portrait container', + dimensions: { width: 900, height: 1600 }, + container: { width: 600, height: 800 }, + expected: { width: 450, height: 800 }, + }, + { + name: 'image matches container exactly', + dimensions: { width: 500, height: 300 }, + container: { width: 500, height: 300 }, + expected: { width: 500, height: 300 }, + }, + { + name: 'image smaller than container scales up', + dimensions: { width: 100, height: 50 }, + container: { width: 400, height: 400 }, + expected: { width: 400, height: 200 }, + }, + ]; + + for (const { name, dimensions, container, expected } of tests) { + it(`should handle ${name}`, () => { + expect(scaleToFit(dimensions, container)).toEqual(expected); + }); + } +}); diff --git a/web/src/lib/utils/layout-utils.ts b/web/src/lib/utils/layout-utils.ts index 3533851ddf..1864933a0b 100644 --- a/web/src/lib/utils/layout-utils.ts +++ b/web/src/lib/utils/layout-utils.ts @@ -129,3 +129,19 @@ export type CommonPosition = { width: number; height: number; }; + +// Scales dimensions to fit within a container (like object-fit: contain) +export const scaleToFit = ( + dimensions: { width: number; height: number }, + container: { width: number; height: number }, +) => { + const scaleX = container.width / dimensions.width; + const scaleY = container.height / dimensions.height; + + const scale = Math.min(scaleX, scaleY); + + return { + width: dimensions.width * scale, + height: dimensions.height * scale, + }; +};