1 | const { decl } = require('postcss');
|
2 | const { percentage } = require('@typographist/utils');
|
3 | const {
|
4 | createMediaQuery,
|
5 | createFontSizeProp,
|
6 | createParentSelector,
|
7 | } = require('../elements');
|
8 | const { toKebabCase } = require('../lib/convertors');
|
9 |
|
10 | // renderStandardRoot :: (Object, Object) -> Void
|
11 | exports.renderStandardRoot = (atrule, breakpointsMap) => {
|
12 | if (atrule.params !== '') return;
|
13 |
|
14 | renderStandardRoot(atrule, breakpointsMap);
|
15 | };
|
16 |
|
17 | // renderStandardRoot :: (Object, Object) -> Void
|
18 | function renderStandardRoot(atrule, breakpointsMap) {
|
19 | const { initial, ...breaks } = breakpointsMap;
|
20 |
|
21 | addFontSizesForEachBreaks(atrule, breaks);
|
22 | addCssVariables(atrule, breaks);
|
23 | const fontSize = percentage(initial.root);
|
24 | atrule.replaceWith(createFontSizeProp(fontSize));
|
25 | }
|
26 |
|
27 | // addFontSizesForEachBreaks :: (Object, [Object]) -> Void
|
28 | function addFontSizesForEachBreaks(atrule, breaks) {
|
29 | Object.values(breaks)
|
30 | .reverse()
|
31 | .forEach(({ root, minWidth }) => {
|
32 | const fontSize = createFontSizeProp(percentage(root));
|
33 |
|
34 | atrule.parent.after(
|
35 | createMediaQuery(minWidth).append(
|
36 | createParentSelector(atrule.parent).append(fontSize),
|
37 | ),
|
38 | );
|
39 | });
|
40 | }
|
41 |
|
42 | // throwIsNotRootSelector :: Object -> Void
|
43 | exports.throwIsNotRootSelector = function(atrule) {
|
44 | if (!isValidRootSelector(atrule)) {
|
45 | throw atrule.error(
|
46 | `Use the '${atrule}' with the ':root' or 'html' selectors.`,
|
47 | );
|
48 | }
|
49 | };
|
50 |
|
51 | // isValidRootSelector :: Object -> Boolean
|
52 | function isValidRootSelector(atrule) {
|
53 | const { selector } = atrule.parent;
|
54 |
|
55 | return (atrule.parent && selector === ':root') || selector === 'html';
|
56 | }
|
57 |
|
58 | // FLUID ROOT ---------------------------------------------------------
|
59 | // renderFluidRoot :: (Object, Object) -> Void
|
60 | // exports.renderFluidRoot = function(atrule, breakpointsMap) {
|
61 | // if (atrule.params.length === 0) return;
|
62 |
|
63 | // throwInvalidParam(atrule);
|
64 | // fluidRoot(atrule, breakpointsMap);
|
65 | // };
|
66 |
|
67 | // throwInvalidParam :: Object -> Void
|
68 | // function throwInvalidParam(atrule) {
|
69 | // if (atrule.params !== '(fluid)') {
|
70 | // throw atrule.error(
|
71 | // `'${atrule.params}' is invalid value. Use '@root(fluid)'.`,
|
72 | // );
|
73 | // }
|
74 | // }
|
75 |
|
76 | // // defaultRoot :: (Object, Object) -> Void
|
77 | // function fluidRoot(atrule, breakpointsMap) {
|
78 | // const { initial: head, ...tail } = breakpointsMap;
|
79 |
|
80 | // addFluidFontForEachBreakpoints(atrule, tail);
|
81 | // addCssVariables(atrule, tail);
|
82 | // atrule.replaceWith(createFontSizeProp(percentage(head.root)));
|
83 | // }
|
84 |
|
85 | // // addFluidFontForEachBreakpoints :: (Object, [Object]) -> Void
|
86 | // function addFluidFontForEachBreakpoints(atrule, breakpointsMap) {
|
87 | // Object.values(breakpointsMap)
|
88 | // .reverse()
|
89 | // .forEach((b, index, arr) => {
|
90 | // const prevIndex = index - 1;
|
91 | // const currentElem = arr[index];
|
92 | // const prevElem = arr[prevIndex];
|
93 |
|
94 | // if (index === 0) {
|
95 | // atrule.parent.after(
|
96 | // createMediaQuery(b.minWidth).append(
|
97 | // createParentSelector(atrule.parent).append(
|
98 | // createFontSizeProp(percentage(b.root)),
|
99 | // ),
|
100 | // ),
|
101 | // );
|
102 | // }
|
103 |
|
104 | // if (index > 0 && arr[prevIndex]) {
|
105 | // atrule.parent.after(
|
106 | // createMediaQuery(currentElem.minWidth).append(
|
107 | // createParentSelector(atrule.parent).append(
|
108 | // createFontSizeProp(
|
109 | // createFluidFontSize({
|
110 | // minWidth: currentElem.minWidth,
|
111 | // maxWidth: prevElem.minWidth,
|
112 | // minFontSize: currentElem.root,
|
113 | // maxFontSize: prevElem.root,
|
114 | // fn: percentage,
|
115 | // }),
|
116 | // ),
|
117 | // ),
|
118 | // ),
|
119 | // );
|
120 | // }
|
121 | // });
|
122 | // }
|
123 |
|
124 | // UTILS
|
125 | // addCssVariables :: (Object, Object) -> [Object]
|
126 | function addCssVariables(atrule, breakpoints) {
|
127 | return Object.entries(breakpoints).map(([key, value]) =>
|
128 | atrule.before(cssVariable(key, value.minWidth)),
|
129 | );
|
130 | }
|
131 |
|
132 | // cssVariable :: (String, String) -> Object
|
133 | function cssVariable(name, value) {
|
134 | return decl({
|
135 | prop: `--${toKebabCase(name)}`,
|
136 | value,
|
137 | });
|
138 | }
|