box-ui-elements-mlh
Version:
184 lines (152 loc) • 9.41 kB
JavaScript
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