Skip to content

Commit 023ac58

Browse files
committed
normalizeQuery: Parses query into a workable object
1 parent 43373e6 commit 023ac58

File tree

4 files changed

+85
-49
lines changed

4 files changed

+85
-49
lines changed

packages/atomic-layout-core/src/utils/styles/createMediaQuery/createMediaQuery.ts

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import {
44
BreakpointBehavior,
55
} from '../../../const/defaultOptions'
66
import transformNumeric from '../../math/transformNumeric'
7-
import normalizeQuery from '../../styles/normalizeQuery'
7+
import normalizeQuery, {
8+
NormalizedQueryParam,
9+
} from '../../styles/normalizeQuery'
810
import compose from '../../functions/compose'
911

10-
type MediaQueryPair = [string, Numeric]
11-
1212
/**
1313
* Determines whether a given media query param should be added
1414
* to the media query string based on a breakpoint's behavior.
1515
*/
1616
const shouldAppendProperty = (
17-
queryParam: string,
17+
queryParam: NormalizedQueryParam,
1818
behavior: BreakpointBehavior,
1919
): boolean => {
20-
const [prefix, splitPropName] = queryParam.split('-')
21-
const isDimensionalProp = ['height', 'width'].includes(splitPropName)
20+
const { prefix, name } = queryParam
21+
const isDimensionalProp = ['height', 'width'].includes(name)
2222

2323
if (!isDimensionalProp) {
2424
return true
@@ -31,31 +31,46 @@ const shouldAppendProperty = (
3131
}
3232

3333
const filterRelevantQueryParams = (behavior: BreakpointBehavior) => (
34-
queryList: MediaQueryPair[],
35-
): MediaQueryPair[] => {
36-
return queryList.filter(([queryParam]) =>
37-
shouldAppendProperty(queryParam, behavior),
34+
queryList: NormalizedQueryParam[],
35+
): NormalizedQueryParam[] => {
36+
return queryList.filter((normalizedQueryParam) =>
37+
shouldAppendProperty(normalizedQueryParam, behavior),
3838
)
3939
}
4040

4141
/**
4242
* Joins a given media query params list with the given transformer function.
4343
*/
44-
export const joinQueryList = (transformer: (pair: MediaQueryPair) => any) => (
45-
queryList: MediaQueryPair[],
44+
export const joinQueryList = (
45+
queryList: NormalizedQueryParam[],
46+
transformer: (pair: NormalizedQueryParam) => any,
4647
) => {
4748
return queryList.map(transformer).join(' and ')
4849
}
4950

50-
export default function createMediaQuery(
51+
export const createQueryList = (
5152
breakpoint: Breakpoint,
5253
behavior: BreakpointBehavior,
53-
): string {
54+
): NormalizedQueryParam[] => {
5455
return compose(
55-
joinQueryList(([dashedQueryProp, propValue]) => {
56-
return `(${dashedQueryProp}:${String(transformNumeric(propValue))})`
57-
}),
5856
filterRelevantQueryParams(behavior),
5957
normalizeQuery,
6058
)(breakpoint)
6159
}
60+
61+
export default function createMediaQuery(
62+
breakpoint: Breakpoint,
63+
behavior: BreakpointBehavior,
64+
): string {
65+
const queryList = createQueryList(breakpoint, behavior)
66+
67+
const mediaQueryString = joinQueryList(
68+
queryList,
69+
({ prefix, name, value }) => {
70+
const dashedQueryParamName = [prefix, name].filter(Boolean).join('-')
71+
return `(${dashedQueryParamName}:${String(transformNumeric(value))})`
72+
},
73+
)
74+
75+
return mediaQueryString
76+
}

packages/atomic-layout-core/src/utils/styles/normalizeQuery/normalizeQuery.spec.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,30 @@ import normalizeQuery from './normalizeQuery'
22

33
describe('normalizeQuery', () => {
44
describe('given a media query Object', () => {
5-
it('returns its [key, value] pairs', () => {
5+
it('returns its { prefix, name, value } data', () => {
66
expect(
77
normalizeQuery({
8+
height: 100,
89
minWidth: 120,
910
maxAspectRatio: '3/4',
1011
}),
11-
).toEqual([['min-width', 120], ['max-aspect-ratio', '3/4']])
12+
).toEqual([
13+
{
14+
prefix: undefined,
15+
name: 'height',
16+
value: 100,
17+
},
18+
{
19+
prefix: 'min',
20+
name: 'width',
21+
value: 120,
22+
},
23+
{
24+
prefix: 'max',
25+
name: 'aspectRatio',
26+
value: '3/4',
27+
},
28+
])
1229
})
1330
})
1431
})
Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
import { Numeric, Breakpoint } from '../../../const/defaultOptions'
22
import isset from '../../functions/isset'
3-
import toDashedString from '../../strings/toDashedString'
3+
import toLowerCaseFirst from '../../strings/toLowerCaseFirst'
4+
5+
export interface NormalizedQueryParam {
6+
prefix: string
7+
name: string
8+
value: Numeric
9+
}
410

511
/**
612
* Normalizes given media query object to a list of [propName, propValue].
7-
* @example
8-
* normalizeQuery({ minWidth: 120 })
9-
* // [['min-width', 120]]
1013
*/
1114
export default function normalizeQuery(
12-
queryProps: Breakpoint,
13-
): Array<[string, Numeric]> {
14-
return Object.entries<Numeric>(queryProps)
15-
.filter(([_, propValue]) => isset(propValue))
16-
.map<[string, Numeric]>(([propName, propValue]) => [
17-
toDashedString(propName),
18-
propValue,
19-
])
15+
breakpoint: Breakpoint,
16+
): NormalizedQueryParam[] {
17+
return Object.entries<Numeric>(breakpoint)
18+
.filter(([_, value]) => isset(value))
19+
.map(([propName, value]) => {
20+
const [_, prefix, restName] = propName.match(/(min|max)?(.+)/)
21+
const normalizedName = toLowerCaseFirst(restName)
22+
23+
return { prefix, name: normalizedName, value }
24+
})
2025
}

packages/atomic-layout/src/hooks/useMediaQuery.ts

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useState, useMemo, useLayoutEffect } from 'react'
22
import {
33
MediaQuery as MediaQueryParams,
4-
compose,
54
joinQueryList,
65
normalizeQuery,
76
transformNumeric,
@@ -11,24 +10,24 @@ import {
1110
* Creates a media querty string based on the given params.
1211
*/
1312
const createMediaQuery = (queryParams: MediaQueryParams): string => {
14-
return compose(
15-
joinQueryList(([paramName, paramValue]) => {
16-
/**
17-
* Transform values that begin with a number to prevent
18-
* transformations of "calc" expressions.
19-
* Transformation of numerics is necessary when a simple
20-
* number is used as a value (min-width: 750) is not valid.
21-
*
22-
* (min-width: 750) ==> (min-width: 750px)
23-
*/
24-
const resolvedParamValue = /^\d/.test(String(paramValue))
25-
? transformNumeric(paramValue)
26-
: paramValue
13+
const queryList = normalizeQuery(queryParams)
14+
const mediaQueryString = joinQueryList(queryList, ({ name, value }) => {
15+
/**
16+
* Transform values that begin with a number to prevent
17+
* transformations of "calc" expressions.
18+
* Transformation of numerics is necessary when a simple
19+
* number is used as a value (min-width: 750) is not valid.
20+
*
21+
* (min-width: 750) ==> (min-width: 750px)
22+
*/
23+
const resolvedParamValue = /^\d/.test(String(value))
24+
? transformNumeric(value)
25+
: value
2726

28-
return `(${paramName}:${resolvedParamValue})`
29-
}),
30-
normalizeQuery,
31-
)(queryParams)
27+
return `(${name}:${resolvedParamValue})`
28+
})
29+
30+
return mediaQueryString
3231
}
3332

3433
type UseMediaQuery = (

0 commit comments

Comments
 (0)