|
1 | 1 | import Layout from '@src/Layout' |
2 | | -import { BreakpointBehavior } from '@const/defaultOptions' |
3 | | -import propAliases from '@const/propAliases' |
| 2 | +import { BreakpointBehavior, Breakpoint } from '@const/defaultOptions' |
| 3 | +import propAliases, { PropAliasDeclaration } from '@const/propAliases' |
4 | 4 | import parsePropName, { Props } from '@utils/strings/parsePropName' |
5 | 5 | import isset from '@utils/functions/isset' |
6 | 6 | import createMediaQuery from '../createMediaQuery' |
@@ -28,37 +28,76 @@ const createStyleString = ( |
28 | 28 | : styleProps |
29 | 29 | } |
30 | 30 |
|
| 31 | +interface PropAliasGroup { |
| 32 | + propValue: string |
| 33 | + propAlias: PropAliasDeclaration |
| 34 | + records: Array<{ |
| 35 | + breakpoint: Breakpoint |
| 36 | + behavior: BreakpointBehavior |
| 37 | + }> |
| 38 | +} |
| 39 | + |
31 | 40 | /** |
32 | 41 | * Produces a CSS string based on the given component props. |
33 | 42 | * Takes only known prop aliases, ignores all the other props. |
34 | 43 | */ |
35 | 44 | export default function applyStyles(pristineProps: Props): string { |
36 | | - return Object.entries(pristineProps) |
37 | | - .reduce<string[]>((css, [pristinePropName, pristinePropValue]) => { |
38 | | - const { purePropName, breakpoint, behavior } = parsePropName( |
39 | | - pristinePropName, |
40 | | - ) |
41 | | - const propAlias = propAliases[purePropName] |
| 45 | + // First, split pritstine component's props into prop alias groups. |
| 46 | + // This allows to operate with each prop alias with all its records at once. |
| 47 | + const propAliasGroups = Object.entries(pristineProps) |
| 48 | + // Filter out props with "undefined" or "null" as a value. |
| 49 | + .filter(([_, propValue]) => isset(propValue)) |
| 50 | + .reduce<Record<string, PropAliasGroup>>( |
| 51 | + (groups, [pristinePropName, pristinePropValue]) => { |
| 52 | + const { purePropName, breakpoint, behavior } = parsePropName( |
| 53 | + pristinePropName, |
| 54 | + ) |
| 55 | + const propAlias = propAliases[purePropName] |
| 56 | + |
| 57 | + // Filter out props that are not in the known prop aliases. |
| 58 | + if (!propAlias) { |
| 59 | + return groups |
| 60 | + } |
| 61 | + |
| 62 | + const prevRecords = groups[purePropName] |
| 63 | + ? groups[purePropName].records |
| 64 | + : [] |
| 65 | + const nextRecords = prevRecords.concat({ |
| 66 | + breakpoint, |
| 67 | + behavior, |
| 68 | + }) |
| 69 | + const groupItem: PropAliasGroup = { |
| 70 | + propValue: pristinePropValue, |
| 71 | + propAlias, |
| 72 | + records: nextRecords, |
| 73 | + } |
42 | 74 |
|
43 | | - // Filter out props with "undefined" or "null" as a value. |
44 | | - // Filter out props that are not in the known prop aliases. |
45 | | - if (!isset(pristineProps[pristinePropName]) || !propAlias) { |
46 | | - return css |
47 | | - } |
| 75 | + return { |
| 76 | + ...groups, |
| 77 | + [purePropName]: groupItem, |
| 78 | + } |
| 79 | + }, |
| 80 | + {}, |
| 81 | + ) |
48 | 82 |
|
| 83 | + return Object.entries(propAliasGroups) |
| 84 | + .reduce<string[]>((css, [_, propAliasGroup]) => { |
| 85 | + const { propAlias, propValue, records } = propAliasGroup |
49 | 86 | const { props, transformValue } = propAlias |
50 | | - const propValue = transformValue |
51 | | - ? transformValue(pristinePropValue) |
52 | | - : pristinePropValue |
| 87 | + const transformedPropValue = transformValue |
| 88 | + ? transformValue(propValue) |
| 89 | + : propValue |
53 | 90 |
|
54 | | - const styleString = createStyleString( |
55 | | - props, |
56 | | - propValue, |
57 | | - breakpoint, |
58 | | - behavior, |
59 | | - ) |
| 91 | + const styles = records.map(({ breakpoint, behavior }) => { |
| 92 | + return createStyleString( |
| 93 | + props, |
| 94 | + transformedPropValue, |
| 95 | + breakpoint, |
| 96 | + behavior, |
| 97 | + ) |
| 98 | + }) |
60 | 99 |
|
61 | | - return css.concat(styleString) |
| 100 | + return css.concat(styles) |
62 | 101 | }, []) |
63 | 102 | .join(' ') |
64 | 103 | } |
0 commit comments