UNPKG

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