Skip to content

Commit

Permalink
feat: add support to arrays of breakpoints with string values
Browse files Browse the repository at this point in the history
Supports all valid CSS units.
```javascript
const stringBreakpoints = ['576px', '768px', '992px', '1200px']
```
  • Loading branch information
thebiltheory committed Apr 30, 2020
1 parent c54e8ec commit 4c4f1c3
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 3 deletions.
8 changes: 8 additions & 0 deletions example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import useBreakpoints from 'usebreakpoints'
const App = () => {
const breakpoints = [576, 768, 992, 1200]

const stringBreakpoints = ['576px', '768px', '992px', '1200px']

const [value, breakpoint] = useBreakpoints([1, 2, 3, 4], breakpoints)

const [componentId] = useBreakpoints(
['sad', 'neutral', 'happy', 'rocket'],
breakpoints
)

const [mood] = useBreakpoints(
['sad', 'neutral', 'happy', 'rocket'],
stringBreakpoints
)

const list = {
sad: (
<span role='img' aria-label='sad'>
Expand Down Expand Up @@ -64,6 +71,7 @@ const App = () => {
useBreakpoints
</h1>
<h3>{breakpoint}px</h3>
I'm in a {mood} mood
<div
style={{
fontSize: 'clamp(5em, 5em + 8vw, 10em)',
Expand Down
14 changes: 14 additions & 0 deletions src/utils/__tests__/isValidUnit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import '../../lib/__test__/useBreakpoints.mock'
import isValidUnit from '../isValidUnit'

describe('Validates breakpoint strings with units', () => {
it('Should throw an error if an invalid CSS unit is provided', () => {
expect(() => isValidUnit('1000pxx')).toThrowError(
`"pxx" is not a valid CSS unit.`
)
})

it('Should return true if a valid CSS is provided', () => {
expect(() => isValidUnit('1000px')).toBeTruthy()
})
})
34 changes: 34 additions & 0 deletions src/utils/__tests__/makeMediaQueryList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import '../../lib/__test__/useBreakpoints.mock'
import makeMediaQueryList from '../makeMediaQueryList'

describe('Generates media query listeners', () => {
const providedBreakPointsAreNumbers = [
window.matchMedia('(min-width: 300px) and (max-width: 500px)'),
window.matchMedia('(min-width: 500px) and (max-width: 800px)'),
window.matchMedia('(min-width: 800px) and (max-width: 1200px)'),
window.matchMedia('(min-width: 1200px) ')
]

const providedBreakPointsAreStrings = [
window.matchMedia('(min-width: 300em) and (max-width: 500px)'),
window.matchMedia('(min-width: 500px) and (max-width: 800cm)'),
window.matchMedia('(min-width: 800cm) and (max-width: 1200rem)'),
window.matchMedia('(min-width: 1200rem) ')
]

it('Should create an array of mediaQueries with an array of type numbers', () => {
const expected = JSON.stringify(makeMediaQueryList([300, 500, 800, 1200]))
const received = JSON.stringify(providedBreakPointsAreNumbers)

expect(expected).toEqual(received)
})

it('Should create an array of mediaQueries with an array of type strings', () => {
const expected = JSON.stringify(
makeMediaQueryList(['300em', '500px', '800cm', '1200rem'])
)
const received = JSON.stringify(providedBreakPointsAreStrings)

expect(expected).toEqual(received)
})
})
28 changes: 28 additions & 0 deletions src/utils/isValidUnit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const units: string[] = [
'cm',
'mm',
'in',
'px',
'pt',
'pc',
'em',
'ex',
'ch',
'rem',
'vw',
'vh',
'vmin',
'vmax',
'%'
]
export default function isValidUnit(breakpoint: string) {
const unit: string[] = breakpoint.match(/(\D+)/g) || ['']

if (!units.includes(unit[0])) {
throw new Error(
`"${breakpoint.match(/[^0-9]+/g)}" is not a valid CSS unit.`
)
}

return true
}
17 changes: 14 additions & 3 deletions src/utils/makeMediaQueryList.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { isBrowser } from './isBrowser'
import isValidUnit from './isValidUnit'

export default function makeMediaQueryList(breakpoints: number[]) {
return breakpoints.map((breakpoint: number, index: number) => {
type TBreakpoint = number | string

export default function makeMediaQueryList(breakpoints: TBreakpoint[]) {
return breakpoints.map((breakpoint: TBreakpoint, index: number) => {
const maxWidth = breakpoints[index + 1]

if (!isBrowser) return

if (typeof breakpoint === 'string' && isValidUnit(breakpoint)) {
return window.matchMedia(
`(min-width: ${breakpoint}) ${
maxWidth ? `and (max-width: ${maxWidth})` : ''
}`
)
}

return window.matchMedia(
`(min-width: ${breakpoint}px) ${
maxWidth ? `and (max-width: ${maxWidth - 1}px)` : ''
maxWidth ? `and (max-width: ${maxWidth}px)` : ''
}`
)
})
Expand Down

0 comments on commit 4c4f1c3

Please sign in to comment.