UNPKG

box-ui-elements-mlh

Version:
184 lines (152 loc) 9.41 kB
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /* eslint-disable no-restricted-syntax */ import Color from 'color'; import method from 'lodash/method'; import merge from 'lodash/merge'; import mapValues from 'lodash/mapValues'; import { THEME_VERY_DARK, THEME_DARK, THEME_MID_DARK, THEME_MIDTONE, THEME_MID_LIGHT, THEME_VERY_LIGHT } from '../constants'; import defaultTheme from '../styles/theme'; import * as vars from '../styles/variables'; // When converting from rgb/hsl to hex there is potential for // flattening of the color space, so we add an offset factor to account for it. var OFFSET_FACTOR = 0.05; export var MIN_CONTRAST = 4.5; // The yiq coefficients in the color library are incorrect // http://poynton.ca/notes/colour_and_gamma/ColorFAQ.html#RTFToC9 function getYiq(color) { var rgb = Color(color).rgb().color; return (rgb[0] * 2126 + rgb[1] * 7152 + rgb[2] * 722) / 10000; } function adjustLightness(color, amount) { var lightness = color.lightness(); return color.lightness(lightness + amount); } // Given a colorKey, output an accessible Box color palette function createTheme(colorKey) { var _colorMap; if (!colorKey) { throw new Error('Color key is undefined'); } var colorKeyObj = Color(colorKey); var colorKeyYiq = getYiq(colorKey); var colorKeyLightness = colorKeyObj.lightness(); var whiteTextContrast = colorKeyObj.contrast(Color(vars.white)); var blackTextContrast = colorKeyObj.contrast(Color(vars.black)); // Take the greater contrasting foreground color var foreground = whiteTextContrast > blackTextContrast ? vars.white : vars.black; var foregroundObj = Color(foreground); // vDark dark midDark midtone midLight vLight // |----|-----|-----------|----|----|-----------|----| // 0 4 20 118 128 168 235 255 var colorMap = (_colorMap = {}, _defineProperty(_colorMap, THEME_VERY_DARK, { yiqRange: [0, 4], modifiers: { active: 15, gradient: 10, hover: 10 } }), _defineProperty(_colorMap, THEME_DARK, { yiqRange: [4, 20], modifiers: { active: 8, gradient: 5, hover: 4 } }), _defineProperty(_colorMap, THEME_MID_DARK, { yiqRange: [20, 118], modifiers: { active: -8, gradient: -5, hover: 4 } }), _defineProperty(_colorMap, THEME_MIDTONE, { yiqRange: [118, 168], modifiers: { active: -7, activeInverse: 9, gradient: -7, hover: 7, hoverInverse: -4 } }), _defineProperty(_colorMap, THEME_MID_LIGHT, { yiqRange: [168, 235], modifiers: { active: 15, gradient: -10, hover: 10 } }), _defineProperty(_colorMap, THEME_VERY_LIGHT, { yiqRange: [235, 256], lightnessThreshold: 90, modifiers: { active: -8, gradient: -5, hover: -4 } }), _colorMap); // Filter down the color map to the object that's in the proper YIQ range var colorRange = Object.keys(colorMap).find(function (key) { return colorKeyYiq >= colorMap[key].yiqRange[0] && colorKeyYiq < colorMap[key].yiqRange[1] || colorMap[key].lightnessThreshold && colorKeyLightness >= colorMap[key].lightnessThreshold; }); var colorRangeConfig = _objectSpread({}, colorMap[colorRange || THEME_MIDTONE]); // Modify the primary colorKey with the associated modifiers from the filtered map var modifiedColors = {}; for (var _i = 0, _Object$entries = Object.entries(colorRangeConfig.modifiers); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), key = _Object$entries$_i[0], value = _Object$entries$_i[1]; // $FlowFixMe modifiedColors[key] = adjustLightness(colorKeyObj, value); } // If the color is too extreme on either end of the spectrum we need to change our rules. var exceedsLightThreshold = colorRange === THEME_VERY_LIGHT || colorRange === THEME_MID_LIGHT; var exceedsDarkThreshold = colorRange === THEME_VERY_DARK || colorRange === THEME_DARK; // Light or dark isn't sufficient for determining how the secondary or accent colors should // be calculated. In addition to that check, we will check the yiq value of the color to ensure // the colorKey is not on the edges of the spectrum. var hoverContrast = modifiedColors.hover.contrast(foregroundObj); // If contrast has reached 21, we have hit the end of the spectrum and want to invert. var hover = hoverContrast >= MIN_CONTRAST + OFFSET_FACTOR && hoverContrast !== 21 ? modifiedColors.hover : modifiedColors.hoverInverse || adjustLightness(colorKeyObj, -colorRangeConfig.modifiers.hover); var activeContrast = modifiedColors.active.contrast(foregroundObj); var active = activeContrast >= MIN_CONTRAST + OFFSET_FACTOR && activeContrast !== 21 ? modifiedColors.active : modifiedColors.activeInverse || adjustLightness(colorKeyObj, -colorRangeConfig.modifiers.active); var scrollShadowRgba = 'rgba(0, 0, 0, 0.12)'; if (exceedsLightThreshold) { scrollShadowRgba = 'rgba(0, 0, 0, 0.08)'; } else if (exceedsDarkThreshold) { scrollShadowRgba = 'rgba(0, 0, 0, 0.4)'; } // Converting color objects to hex for return value var colorKeyHex = colorKeyObj.hex(); var hoverHex = hover.hex(); var activeHex = active.hex(); var gradientHex = modifiedColors.gradient.hex(); var colorValues = { background: colorKeyHex, backgroundHover: hoverHex, backgroundActive: activeHex, backgroundGradient: gradientHex, foreground: foreground, border: exceedsLightThreshold ? vars.bdlGray10 : colorKeyHex, // Button specific overrides. If the primary color is greater than the lightness threshold // we will override the button styling to be a styling based on vars.bdlGray primary. buttonForeground: exceedsLightThreshold ? vars.white : foreground, buttonBackground: exceedsLightThreshold ? vars.bdlGray : colorKeyHex, buttonBackgroundHover: exceedsLightThreshold ? vars.bdlGray80 : hoverHex, buttonBackgroundActive: exceedsLightThreshold ? vars.bdlGray62 : activeHex, buttonBorder: exceedsLightThreshold ? vars.bdlGray : colorKeyHex, buttonBorderHover: exceedsLightThreshold ? vars.bdlGray80 : hoverHex, buttonBorderActive: exceedsLightThreshold ? vars.bdlGray62 : activeHex, // ProgressBar overrides progressBarBackground: exceedsLightThreshold ? vars.bdlGray50 : hoverHex, // Scroll effect overrides for scrollable themed elements scrollShadowRgba: scrollShadowRgba }; var dynamicTheme = { // To avoid a mixture of casing, we force all values to lower primary: _objectSpread(_objectSpread({}, mapValues(colorValues, method('toLowerCase'))), {}, { _debug: { colorRange: colorRange } }) }; return merge({}, defaultTheme, dynamicTheme); } export { createTheme }; //# sourceMappingURL=createTheme.js.map