UNPKG

3.65 kBJavaScriptView Raw
1export function isUnitless(value) {
2 return String(parseFloat(value)).length === String(value).length;
3} // Ported from Compass
4// https://github.com/Compass/compass/blob/master/core/stylesheets/compass/typography/_units.scss
5// Emulate the sass function "unit"
6
7export function getUnit(input) {
8 return String(input).match(/[\d.\-+]*\s*(.*)/)[1] || '';
9} // Emulate the sass function "unitless"
10
11export function toUnitless(length) {
12 return parseFloat(length);
13} // Convert any CSS <length> or <percentage> value to any another.
14// From https://github.com/KyleAMathews/convert-css-length
15
16export function convertLength(baseFontSize) {
17 return (length, toUnit) => {
18 const fromUnit = getUnit(length); // Optimize for cases where `from` and `to` units are accidentally the same.
19
20 if (fromUnit === toUnit) {
21 return length;
22 } // Convert input length to pixels.
23
24
25 let pxLength = toUnitless(length);
26
27 if (fromUnit !== 'px') {
28 if (fromUnit === 'em') {
29 pxLength = toUnitless(length) * toUnitless(baseFontSize);
30 } else if (fromUnit === 'rem') {
31 pxLength = toUnitless(length) * toUnitless(baseFontSize);
32 return length;
33 }
34 } // Convert length in pixels to the output unit
35
36
37 let outputLength = pxLength;
38
39 if (toUnit !== 'px') {
40 if (toUnit === 'em') {
41 outputLength = pxLength / toUnitless(baseFontSize);
42 } else if (toUnit === 'rem') {
43 outputLength = pxLength / toUnitless(baseFontSize);
44 } else {
45 return length;
46 }
47 }
48
49 return parseFloat(outputLength.toFixed(5)) + toUnit;
50 };
51}
52export function alignProperty({
53 size,
54 grid
55}) {
56 const sizeBelow = size - size % grid;
57 const sizeAbove = sizeBelow + grid;
58 return size - sizeBelow < sizeAbove - size ? sizeBelow : sizeAbove;
59} // fontGrid finds a minimal grid (in rem) for the fontSize values so that the
60// lineHeight falls under a x pixels grid, 4px in the case of Material Design,
61// without changing the relative line height
62
63export function fontGrid({
64 lineHeight,
65 pixels,
66 htmlFontSize
67}) {
68 return pixels / (lineHeight * htmlFontSize);
69}
70/**
71 * generate a responsive version of a given CSS property
72 * @example
73 * responsiveProperty({
74 * cssProperty: 'fontSize',
75 * min: 15,
76 * max: 20,
77 * unit: 'px',
78 * breakpoints: [300, 600],
79 * })
80 *
81 * // this returns
82 *
83 * {
84 * fontSize: '15px',
85 * '@media (min-width:300px)': {
86 * fontSize: '17.5px',
87 * },
88 * '@media (min-width:600px)': {
89 * fontSize: '20px',
90 * },
91 * }
92 *
93 * @param {Object} params
94 * @param {string} params.cssProperty - The CSS property to be made responsive
95 * @param {number} params.min - The smallest value of the CSS property
96 * @param {number} params.max - The largest value of the CSS property
97 * @param {string} [params.unit] - The unit to be used for the CSS property
98 * @param {Array.number} [params.breakpoints] - An array of breakpoints
99 * @param {number} [params.alignStep] - Round scaled value to fall under this grid
100 * @returns {Object} responsive styles for {params.cssProperty}
101 */
102
103export function responsiveProperty({
104 cssProperty,
105 min,
106 max,
107 unit = 'rem',
108 breakpoints = [600, 960, 1280],
109 transform = null
110}) {
111 const output = {
112 [cssProperty]: `${min}${unit}`
113 };
114 const factor = (max - min) / breakpoints[breakpoints.length - 1];
115 breakpoints.forEach(breakpoint => {
116 let value = min + factor * breakpoint;
117
118 if (transform !== null) {
119 value = transform(value);
120 }
121
122 output[`@media (min-width:${breakpoint}px)`] = {
123 [cssProperty]: `${Math.round(value * 10000) / 10000}${unit}`
124 };
125 });
126 return output;
127}
\No newline at end of file