@shopify/polaris
Version:
Shopify’s product component library
172 lines (171 loc) • 7.09 kB
JavaScript
import tokens from '@shopify/polaris-tokens';
import { colorToHsla, hslToString, hslToRgb } from '../color-transformers';
import { isLight } from '../color-validation';
import { constructColorName } from '../color-names';
import { createLightColor } from '../color-manipulation';
import { compose } from '../compose';
import { needsVariantList } from './config';
import colorAdjustmentsJson from './color-adjustments.json';
export function buildCustomProperties(themeConfig, globalTheming) {
return globalTheming
? buildColors(themeConfig)
: buildLegacyColors(themeConfig);
}
export function buildThemeContext(themeConfig, cssCustomProperties) {
const { logo } = themeConfig;
return {
logo,
// eslint-disable-next-line babel/camelcase
UNSTABLE_cssCustomProperties: toString(cssCustomProperties),
};
}
function toString(obj) {
if (obj) {
return Object.entries(obj)
.map((pair) => pair.join(':'))
.join(';');
}
else {
return undefined;
}
}
/* eslint-disable babel/camelcase */
// eslint-disable-next-line shopify/typescript/prefer-pascal-case-enums
export var UNSTABLE_Color;
(function (UNSTABLE_Color) {
UNSTABLE_Color["Surface"] = "#FAFAFA";
UNSTABLE_Color["DarkSurface"] = "#111213";
UNSTABLE_Color["OnSurface"] = "#1F2225";
UNSTABLE_Color["Interactive"] = "#0870D9";
UNSTABLE_Color["Neutral"] = "#EAEAEB";
UNSTABLE_Color["Branded"] = "#008060";
UNSTABLE_Color["Critical"] = "#E32727";
UNSTABLE_Color["Warning"] = "#FFC453";
UNSTABLE_Color["Highlight"] = "#59D0C2";
UNSTABLE_Color["Success"] = "#008060";
})(UNSTABLE_Color || (UNSTABLE_Color = {}));
export function buildColors(theme) {
const colors = Object.assign({ surface: UNSTABLE_Color.Surface, onSurface: UNSTABLE_Color.OnSurface, interactive: UNSTABLE_Color.Interactive, neutral: UNSTABLE_Color.Neutral, branded: UNSTABLE_Color.Branded, critical: UNSTABLE_Color.Critical, warning: UNSTABLE_Color.Warning, highlight: UNSTABLE_Color.Highlight, success: UNSTABLE_Color.Success }, theme.UNSTABLE_colors);
const surfaceColor = colorToHsla(colors.surface);
const lightSurface = isLight(hslToRgb(surfaceColor));
const colorAdjustments = {};
Object.assign(colorAdjustments, colorAdjustmentsJson);
const allColors = Object.entries(colorAdjustments).reduce((accumulator, [colorRole, colorAdjustment]) => {
if (colorAdjustment == null)
return accumulator;
const baseColor = colorToHsla(colors[colorAdjustment.baseColor]);
const { hue = baseColor.hue, saturation = baseColor.saturation, lightness = baseColor.lightness, alpha = baseColor.alpha, } = colorAdjustment[lightSurface ? 'light' : 'dark'];
return Object.assign({}, accumulator, { [colorRole]: hslToString({
hue,
saturation,
lightness,
alpha,
}) });
}, {});
return customPropertyTransformer(Object.assign({}, allColors, overrides()));
}
/* eslint-enable babel/camelcase */
function overrides() {
return {
overrideNone: 'none',
overrideTransparent: 'transparent',
overrideOne: '1',
overrideVisible: 'visible',
buttonFontWeight: '500',
nonNullContent: "''",
borderRadiusBase: rem('4px'),
borderRadiusWide: rem('8px'),
bannerDefaultBorder: buildBannerBorder('--p-divider-on-surface'),
bannerSuccessBorder: buildBannerBorder('--p-success-divider'),
bannerHighlightBorder: buildBannerBorder('--p-highlight-divider'),
bannerWarningBorder: buildBannerBorder('--p-warning-divider'),
bannerCriticalBorder: buildBannerBorder('--p-critical-divider'),
badgeMixBlendMode: 'luminosity',
borderSubdued: `${rem('1px')} solid var(--p-divider-subdued-on-surface)`,
textFieldSpinnerOffset: rem('2px'),
textFieldFocusRingOffset: rem('-4px'),
textFieldFocusRingBorderRadius: rem('7px'),
};
}
function customPropertyTransformer(properties) {
return Object.entries(properties).reduce((transformed, [key, value]) => (Object.assign({}, transformed, { [toCssCustomPropertySyntax(key)]: value })), {});
}
function toCssCustomPropertySyntax(camelCase) {
return `--p-${camelCase.replace(/([A-Z0-9])/g, '-$1').toLowerCase()}`;
}
function rem(px) {
const baseFontSize = 10;
return `${parseInt(px, 10) / baseFontSize}rem`;
}
function buildBannerBorder(cssVar) {
return `inset 0 ${rem('2px')} 0 0 var(${cssVar}), inset 0 0 0 ${rem('2px')} var(${cssVar})`;
}
function buildLegacyColors(theme) {
let colorPairs;
const colors = theme && theme.colors && theme.colors.topBar
? theme.colors.topBar
: { background: '#00848e', backgroundLighter: '#1d9ba4', color: '#f9fafb' };
const colorKey = 'topBar';
const colorKeys = Object.keys(colors);
if (colorKeys.length > 1) {
colorPairs = colorKeys.map((key) => {
return [constructColorName(colorKey, key), colors[key]];
});
}
else {
colorPairs = parseColors([colorKey, colors]);
}
return colorPairs.reduce((state, [key, value]) => (Object.assign({}, state, { [key]: value })), {});
}
export function needsVariant(name) {
return needsVariantList.indexOf(name) !== -1;
}
const lightenToString = compose(hslToString, createLightColor);
export function setTextColor(name, variant = 'dark') {
if (variant === 'light') {
return [name, tokens.colorInk];
}
return [name, tokens.colorWhite];
}
export function setTheme(color, baseName, key, variant) {
const colorPairs = [];
switch (variant) {
case 'light':
colorPairs.push(setTextColor(constructColorName(baseName, null, 'color'), 'light'));
colorPairs.push([
constructColorName(baseName, key, 'lighter'),
lightenToString(color, 7, -10),
]);
break;
case 'dark':
colorPairs.push(setTextColor(constructColorName(baseName, null, 'color'), 'dark'));
colorPairs.push([
constructColorName(baseName, key, 'lighter'),
lightenToString(color, 15, 15),
]);
break;
default:
}
return colorPairs;
}
function parseColors([baseName, colors]) {
const keys = Object.keys(colors);
const colorPairs = [];
for (let i = 0; i < keys.length; i++) {
colorPairs.push([constructColorName(baseName, keys[i]), colors[keys[i]]]);
if (needsVariant(baseName)) {
const hslColor = colorToHsla(colors[keys[i]]);
if (typeof hslColor === 'string') {
return colorPairs;
}
const rgbColor = hslToRgb(hslColor);
if (isLight(rgbColor)) {
colorPairs.push(...setTheme(hslColor, baseName, keys[i], 'light'));
}
else {
colorPairs.push(...setTheme(hslColor, baseName, keys[i], 'dark'));
}
}
}
return colorPairs;
}