-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a set of CSS media query entropy sources
Squashed commit of the following: commit ee83891 Author: Surgie Finesse <finesserus@gmail.com> Date: Mon Jan 4 19:51:15 2021 +1000 Add sources: HDR, reduced motion commit 4a3b7b4 Author: Surgie Finesse <finesserus@gmail.com> Date: Mon Jan 4 13:15:34 2021 +1000 Add sources: contrast, forced colors, monochrome commit d8849ca Author: Surgie Finesse <finesserus@gmail.com> Date: Wed Dec 30 18:07:38 2020 +1000 Add the `invertedColors` source commit e0e95f7 Author: Surgie Finesse <finesserus@gmail.com> Date: Wed Dec 30 17:53:33 2020 +1000 Add the first CSS media source and tools to test CSS media sources
- Loading branch information
Showing
18 changed files
with
448 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import getColorGamut from './color_gamut' | ||
|
||
describe('Sources', () => { | ||
describe('colorGamut', () => { | ||
it('handles browser native value', () => { | ||
const colorGamut = getColorGamut() | ||
expect([undefined, 'srgb', 'p3', 'rec2020']).toContain(colorGamut) | ||
}) | ||
|
||
it('handles missing browser support', async () => { | ||
await withMockMatchMedia({ 'color-gamut': [undefined] }, true, () => expect(getColorGamut()).toBeUndefined()) | ||
}) | ||
|
||
it('handles various color gamuts', async () => { | ||
await withMockMatchMedia({ 'color-gamut': ['srgb'] }, true, () => expect(getColorGamut()).toBe('srgb')) | ||
await withMockMatchMedia({ 'color-gamut': ['srgb', 'p3'] }, true, () => expect(getColorGamut()).toBe('p3')) | ||
await withMockMatchMedia({ 'color-gamut': ['srgb', 'p3', 'rec2020'] }, true, () => | ||
expect(getColorGamut()).toBe('rec2020'), | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export type ColorGamut = 'srgb' | 'p3' | 'rec2020' | ||
|
||
/** | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/color-gamut | ||
*/ | ||
export default function getColorGamut(): ColorGamut | undefined { | ||
// rec2020 includes p3 and p3 includes srgb | ||
for (const gamut of ['rec2020', 'p3', 'srgb'] as const) { | ||
if (matchMedia(`(color-gamut: ${gamut})`).matches) { | ||
return gamut | ||
} | ||
} | ||
return undefined | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import getContrastPreference, { ContrastPreference } from './contrast' | ||
|
||
describe('Sources', () => { | ||
describe('contrast', () => { | ||
it('handles browser native value', () => { | ||
expect([ | ||
undefined, | ||
ContrastPreference.Less, | ||
ContrastPreference.None, | ||
ContrastPreference.More, | ||
ContrastPreference.ForcedColors, | ||
]).toContain(getContrastPreference()) | ||
}) | ||
|
||
it('handles various cases', async () => { | ||
await withMockMatchMedia({ 'prefers-contrast': [undefined] }, true, () => | ||
expect(getContrastPreference()).toBeUndefined(), | ||
) | ||
await withMockMatchMedia({ 'prefers-contrast': ['no-preference'] }, true, () => | ||
expect(getContrastPreference()).toBe(ContrastPreference.None), | ||
) | ||
await withMockMatchMedia({ 'prefers-contrast': ['high'] }, true, () => | ||
expect(getContrastPreference()).toBe(ContrastPreference.More), | ||
) | ||
await withMockMatchMedia({ 'prefers-contrast': ['more'] }, true, () => | ||
expect(getContrastPreference()).toBe(ContrastPreference.More), | ||
) | ||
await withMockMatchMedia({ 'prefers-contrast': ['low'] }, true, () => | ||
expect(getContrastPreference()).toBe(ContrastPreference.Less), | ||
) | ||
await withMockMatchMedia({ 'prefers-contrast': ['less'] }, true, () => | ||
expect(getContrastPreference()).toBe(ContrastPreference.Less), | ||
) | ||
await withMockMatchMedia({ 'prefers-contrast': ['forced'] }, true, () => | ||
expect(getContrastPreference()).toBe(ContrastPreference.ForcedColors), | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
export const enum ContrastPreference { | ||
Less = -1, | ||
None = 0, | ||
More = 1, | ||
// "Max" can be added in future | ||
ForcedColors = 10, | ||
} | ||
|
||
/** | ||
* @see https://www.w3.org/TR/mediaqueries-5/#prefers-contrast | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast | ||
*/ | ||
export default function getContrastPreference(): ContrastPreference | undefined { | ||
if (doesMatch('no-preference')) { | ||
return ContrastPreference.None | ||
} | ||
// The sources contradict on the keywords. Probably 'high' and 'low' will never be implemented. | ||
// Need to check it when all browsers implement the feature. | ||
if (doesMatch('high') || doesMatch('more')) { | ||
return ContrastPreference.More | ||
} | ||
if (doesMatch('low') || doesMatch('less')) { | ||
return ContrastPreference.Less | ||
} | ||
if (doesMatch('forced')) { | ||
return ContrastPreference.ForcedColors | ||
} | ||
return undefined | ||
} | ||
|
||
function doesMatch(value: string) { | ||
return matchMedia(`(prefers-contrast: ${value})`).matches | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import areColorsForced from './forced_colors' | ||
|
||
describe('Sources', () => { | ||
describe('forcedColors', () => { | ||
it('handles browser native value', () => { | ||
expect([undefined, true, false]).toContain(areColorsForced()) | ||
}) | ||
|
||
it('handles various cases', async () => { | ||
await withMockMatchMedia({ 'forced-colors': [undefined] }, true, () => expect(areColorsForced()).toBeUndefined()) | ||
await withMockMatchMedia({ 'forced-colors': ['none'] }, true, () => expect(areColorsForced()).toBeFalse()) | ||
await withMockMatchMedia({ 'forced-colors': ['active'] }, true, () => expect(areColorsForced()).toBeTrue()) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors | ||
*/ | ||
export default function areColorsForced(): boolean | undefined { | ||
if (doesMatch('active')) { | ||
return true | ||
} | ||
if (doesMatch('none')) { | ||
return false | ||
} | ||
return undefined | ||
} | ||
|
||
function doesMatch(value: string) { | ||
return matchMedia(`(forced-colors: ${value})`).matches | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import isHDR from './hdr' | ||
|
||
describe('Sources', () => { | ||
describe('hdr', () => { | ||
it('handles browser native value', () => { | ||
expect([undefined, true, false]).toContain(isHDR()) | ||
}) | ||
|
||
it('handles various cases', async () => { | ||
await withMockMatchMedia({ 'dynamic-range': [undefined] }, true, () => expect(isHDR()).toBeUndefined()) | ||
await withMockMatchMedia({ 'dynamic-range': ['high'] }, true, () => expect(isHDR()).toBeTrue()) | ||
await withMockMatchMedia({ 'dynamic-range': ['standard'] }, true, () => expect(isHDR()).toBeFalse()) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* @see https://www.w3.org/TR/mediaqueries-5/#dynamic-range | ||
*/ | ||
export default function isHDR(): boolean | undefined { | ||
if (doesMatch('high')) { | ||
return true | ||
} | ||
if (doesMatch('standard')) { | ||
return false | ||
} | ||
return undefined | ||
} | ||
|
||
function doesMatch(value: string) { | ||
return matchMedia(`(dynamic-range: ${value})`).matches | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import areColorsInverted from './inverted_colors' | ||
|
||
describe('Sources', () => { | ||
describe('invertedColors', () => { | ||
it('handles browser native value', () => { | ||
expect([undefined, true, false]).toContain(areColorsInverted()) | ||
}) | ||
|
||
it('handles various cases', async () => { | ||
await withMockMatchMedia({ 'inverted-colors': [undefined] }, true, () => | ||
expect(areColorsInverted()).toBeUndefined(), | ||
) | ||
await withMockMatchMedia({ 'inverted-colors': ['none'] }, true, () => expect(areColorsInverted()).toBeFalse()) | ||
await withMockMatchMedia({ 'inverted-colors': ['inverted'] }, true, () => expect(areColorsInverted()).toBeTrue()) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/inverted-colors | ||
*/ | ||
export default function areColorsInverted(): boolean | undefined { | ||
if (doesMatch('inverted')) { | ||
return true | ||
} | ||
if (doesMatch('none')) { | ||
return false | ||
} | ||
return undefined | ||
} | ||
|
||
function doesMatch(value: string) { | ||
return matchMedia(`(inverted-colors: ${value})`).matches | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import getMonochromeDepth from './monochrome' | ||
|
||
describe('Sources', () => { | ||
describe('monochrome', () => { | ||
it('handles browser native value', () => { | ||
expect(['undefined', 'number']).toContain(typeof getMonochromeDepth()) | ||
}) | ||
|
||
it('handles various cases', async () => { | ||
await withMockMatchMedia({ monochrome: [undefined] }, true, () => expect(getMonochromeDepth()).toBeUndefined()) | ||
await withMockMatchMedia({ monochrome: [0] }, true, () => expect(getMonochromeDepth()).toBe(0)) | ||
await withMockMatchMedia({ monochrome: [8] }, true, () => expect(getMonochromeDepth()).toBe(8)) | ||
await withMockMatchMedia({ monochrome: [10] }, true, () => expect(getMonochromeDepth()).toBe(10)) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const maxValueToCheck = 100 | ||
|
||
/** | ||
* If the display is monochrome (e.g. black&white), the value will be ≥0 and will mean the number of bits per pixel. | ||
* If the display is not monochrome, the returned value will be 0. | ||
* If the browser doesn't support this feature, the returned value will be undefined. | ||
* | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/monochrome | ||
*/ | ||
export default function getMonochromeDepth(): number | undefined { | ||
if (!matchMedia('(min-monochrome: 0)').matches) { | ||
// The media feature isn't supported by the browser | ||
return undefined | ||
} | ||
|
||
// A variation of binary search algorithm can be used here. | ||
// But since expected values are very small (≤10), there is no sense in adding the complexity. | ||
for (let i = 0; i <= maxValueToCheck; ++i) { | ||
if (matchMedia(`(max-monochrome: ${i})`).matches) { | ||
return i | ||
} | ||
} | ||
|
||
throw new Error('Too high value') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { withMockMatchMedia } from '../../tests/utils' | ||
import isMotionReduced from './reduced_motion' | ||
|
||
describe('Sources', () => { | ||
describe('reducedMotion', () => { | ||
it('handles browser native value', () => { | ||
expect([undefined, true, false]).toContain(isMotionReduced()) | ||
}) | ||
|
||
it('handles various cases', async () => { | ||
await withMockMatchMedia({ 'prefers-reduced-motion': [undefined] }, true, () => | ||
expect(isMotionReduced()).toBeUndefined(), | ||
) | ||
await withMockMatchMedia({ 'prefers-reduced-motion': ['no-preference'] }, true, () => | ||
expect(isMotionReduced()).toBeFalse(), | ||
) | ||
await withMockMatchMedia({ 'prefers-reduced-motion': ['reduce'] }, true, () => | ||
expect(isMotionReduced()).toBeTrue(), | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion | ||
*/ | ||
export default function isMotionReduced(): boolean | undefined { | ||
if (doesMatch('reduce')) { | ||
return true | ||
} | ||
if (doesMatch('no-preference')) { | ||
return false | ||
} | ||
return undefined | ||
} | ||
|
||
function doesMatch(value: string) { | ||
return matchMedia(`(prefers-reduced-motion: ${value})`).matches | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.