UNPKG

@retailmenot/anchor

Version:

A React UI Library by RetailMeNot

124 lines (120 loc) 4.83 kB
/* All of the logic here does NOT assume that the breakpoints in the RootTheme are specifically set as xs, sm, md, lg, xl. */ import { createContext } from 'react'; // Creates the context used by both Grid and Cell for enabling debug export const GridContext = createContext({ debug: false, }); export var FLOW; (function (FLOW) { FLOW["column"] = "column"; FLOW["row"] = "row"; })(FLOW || (FLOW = {})); export const debugColor = 'rgba(255, 0, 0, 0.4)'; /* Returns an array of objects sorted by their value, descending. Ex: const obj: { xs: 500: md: 800: sm: 650 }; sortBreakpoints(obj); // [{xs: 500}, {sm: 650}, {md: 800}] */ export function sortBreakpoints(unsortedBreakpoints) { return Object.keys(unsortedBreakpoints) .reduce((acc, next) => { acc.push({ [next]: unsortedBreakpoints[next] }); return acc; }, []) .sort((a, b) => Object.values(a)[0] - Object.values(b)[0]); } /* Returns the breakpoint key for the specified window's innerWidth. Ex: const innerWidth = 920; const sortedBreakpoints = [{ xs: 500, sm: 750, md: 1000 }]; getBreakpointKey(innerWidth, sortedBreakpoints); // sm */ export function getBreakpointKey(innerWidth, sortedBreakpoints) { const breakpoint = sortedBreakpoints // Get only breakpoints that are above the window's width .filter(bp => { return innerWidth >= Object.values(bp)[0]; }) // Sort those breakpoints, putting the largest breakpoint first .sort((a, b) => Object.values(b)[0] - Object.values(a)[0]) // Get the largest breakpoint from the array .shift(); // Gets the key based on the breakpoint (i.e. xs, sm, etc) return typeof breakpoint === 'object' ? Object.keys(breakpoint)[0] : ''; } /* Small helper object for the generateBreakpointCSS() function to render the correct CSS for each grid setting. */ const ops = { // If width is 0, don't show the cell. If middle is true, add in the middle CSS. width: (width, middle) => width > 0 ? `grid-column-end: span ${width}; display: block;` : 'display: none;', height: (height) => `grid-row-end: span ${height};`, left: (left) => `grid-column-start: ${left};`, top: (top) => `grid-row-start: ${top};`, }; /* Takes the gridSettings object and parses the data to generate sorted css breakpoints. It groups css properties based on the breakpoint size so that a single breakpoint declaration for 'xs' can have css for left, top, height & width if necessary. NOTE: This function uses older loop structures as they are tremendously more performant. */ export function generateBreakpointCSS(gridSettings, sortedBreakpoints) { const responsiveCSS = {}; const sortedResponsiveCSS = []; const generalSettings = {}; for (const gridSettingKey in gridSettings) { // forin requires an 'if' guard if (gridSettings[gridSettingKey]) { const gridSettingValue = gridSettings[gridSettingKey]; // Put non-responsive settings into the generalSettings object if (typeof gridSettingValue === 'number' || typeof gridSettingValue === 'undefined') { generalSettings[gridSettingKey] = gridSettingValue; } else if (typeof gridSettingValue === 'object') { for (const breakpointKey in gridSettingValue) { if (gridSettingValue[breakpointKey] >= 0) { // 0 is a valid value, no truthiness const responsiveValue = gridSettingValue[breakpointKey]; if (!responsiveCSS[breakpointKey]) { responsiveCSS[breakpointKey] = ''; } responsiveCSS[breakpointKey] += ops[gridSettingKey](responsiveValue); } } } } } // eslint-disable-next-line: prefer-for-of for (let i = 0; i < sortedBreakpoints.length; i++) { for (const breakpointKey in sortedBreakpoints[i]) { if (responsiveCSS[breakpointKey] !== undefined) { sortedResponsiveCSS.push({ [breakpointKey]: responsiveCSS[breakpointKey], }); } } } /* sortedResponsiveCSS is an array of breakpoint css associated to a breakpoint key, i.e. [ {xs: 'grid-column-end: span 2; display: block; grid-row-end: span 3;'}, {md: 'grid-column-end: span 10;'} ] generalSettings is the returned values which were not responsive objects, i.e. { left: 1, top: undefined, height: 1, width: 3 } */ return { sortedResponsiveCSS, generalSettings }; } //# sourceMappingURL=utils.js.map