From 59dc3f49ec700ccb29f966f9a593b31ab8f30e69 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Tue, 21 Nov 2023 23:25:14 +1100 Subject: [PATCH] Support em and rem min-width --- src/media-query.test.ts | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/media-query.test.ts b/src/media-query.test.ts index 7e663c8..e74452f 100644 --- a/src/media-query.test.ts +++ b/src/media-query.test.ts @@ -36,6 +36,7 @@ interface MatchMediaContext { mediaType: 'screen' | 'print'; viewportWidth: number; viewportHeight: number; + rootFontSizePx: number; primaryPointingDevice?: 'touchscreen' | 'mouse'; secondaryPointingDevice?: 'touchscreen' | 'mouse'; } @@ -82,10 +83,18 @@ class ParsedMinWidth { public readonly unit: 'px' | 'em' | 'rem' ) {} - matches(context: { viewportWidth: number }) { - if (this.unit !== 'px') throw Error('Only supports px for now.'); + private valueInPx(context: MatchMediaContext): number { + switch (this.unit) { + case 'px': + return this.value; + case 'rem': + case 'em': + return this.value * context.rootFontSizePx; + } + } - return this.value <= context.viewportWidth; + matches(context: MatchMediaContext) { + return this.valueInPx(context) <= context.viewportWidth; } static *Parser() { @@ -362,6 +371,7 @@ test('screen and (min-width: 480px)', () => { }); test('matchMedia()', () => { + const defaultRootFontSizePx = 16; const screenSized = ( viewportWidth: number, viewportHeight: number, @@ -372,12 +382,18 @@ test('matchMedia()', () => { mediaType: 'screen', viewportWidth, viewportHeight, + rootFontSizePx: defaultRootFontSizePx, primaryPointingDevice, secondaryPointingDevice, } as const); const printSized = (viewportWidth: number, viewportHeight: number) => - ({ mediaType: 'print', viewportWidth, viewportHeight } as const); + ({ + mediaType: 'print', + viewportWidth, + viewportHeight, + rootFontSizePx: defaultRootFontSizePx, + } as const); expect(matchMedia(screenSized(100, 100), 'screen').matches).toBe(true); expect(matchMedia(screenSized(100, 100), 'only screen').matches).toBe(true); @@ -403,6 +419,26 @@ test('matchMedia()', () => { true ); + expect(matchMedia(screenSized(479, 100), '(min-width: 30em)').matches).toBe( + false + ); + expect(matchMedia(screenSized(480, 100), '(min-width: 30em)').matches).toBe( + true + ); + expect(matchMedia(screenSized(481, 100), '(min-width: 30em)').matches).toBe( + true + ); + + expect(matchMedia(screenSized(479, 100), '(min-width: 30rem)').matches).toBe( + false + ); + expect(matchMedia(screenSized(480, 100), '(min-width: 30rem)').matches).toBe( + true + ); + expect(matchMedia(screenSized(481, 100), '(min-width: 30rem)').matches).toBe( + true + ); + expect( matchMedia(screenSized(200, 100), '(orientation: landscape)').matches ).toBe(true); @@ -522,13 +558,13 @@ test('matchMedia()', () => { ).toBe(true); expect( matchMedia( - screenSized(480, 100, "touchscreen"), + screenSized(480, 100, 'touchscreen'), 'only screen and (min-width: 480px) and (orientation: landscape) and (any-hover: hover)' ).matches ).toBe(false); expect( matchMedia( - screenSized(480, 100, "touchscreen", "mouse"), + screenSized(480, 100, 'touchscreen', 'mouse'), 'only screen and (min-width: 480px) and (orientation: landscape) and (any-hover: hover)' ).matches ).toBe(true);