Skip to content

Commit

Permalink
feat(core): new Material You colors system. colorThemeCSSProperties
Browse files Browse the repository at this point in the history
… util now return object with `common`, `light` and `dark` vars
  • Loading branch information
nolimits4web committed Sep 20, 2022
1 parent 8759957 commit 9fb8b3a
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 25 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
@@ -1,4 +1,5 @@
const rules = {
'no-bitwise': 'off',
'no-param-reassign': [
'error',
{
Expand Down
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -79,6 +79,7 @@
"@babel/core": "^7.17.9",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@material/material-color-utilities": "^0.2.0",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^21.1.0",
"@rollup/plugin-node-resolve": "^13.2.1",
Expand Down
62 changes: 41 additions & 21 deletions src/core/components/app/app-class.js
Expand Up @@ -150,15 +150,29 @@ class Framework7 extends Framework7Class {
app.colorsStyleEl = document.createElement('style');
document.head.appendChild(app.colorsStyleEl);
}

const stringifyObject = (obj) => {
let res = '';
Object.keys(obj).forEach((key) => {
res += `${key}:${obj[key]};`;
});
return res;
};
const colorVars = app.utils.colorThemeCSSProperties(app.colors.primary);
let primary = '';
// primary
Object.keys(colorVars).forEach((key) => {
primary += `${key}: ${colorVars[key]};`;
});
primary = `:root {${primary};--swiper-theme-color:var(--f7-theme-color);}`;

const primary = [
`:root{`,
stringifyObject(colorVars.common),
stringifyObject(colorVars.light),
`--swiper-theme-color:var(--f7-theme-color);`,
`}`,
`.dark{`,
stringifyObject(colorVars.dark),
`}`,
].join('');

const restVars = {};

Object.keys(app.colors).forEach((colorName) => {
const colorValue = app.colors[colorName];
restVars[colorName] = app.utils.colorThemeCSSProperties(colorValue);
Expand All @@ -170,35 +184,41 @@ class Framework7 extends Framework7Class {
rest += ':root{';
Object.keys(app.colors).forEach((colorName) => {
rest += [
`--f7-color-${colorName}: ${restVars[colorName]['--f7-theme-color']};`,
`--f7-color-${colorName}-rgb: ${restVars[colorName]['--f7-theme-color-rgb']};`,
`--f7-color-${colorName}-shade: ${restVars[colorName]['--f7-theme-color-shade']};`,
`--f7-color-${colorName}-tint: ${restVars[colorName]['--f7-theme-color-tint']};`,
`--f7-color-${colorName}: ${restVars[colorName].common['--f7-theme-color']};`,
`--f7-color-${colorName}-rgb: ${restVars[colorName].common['--f7-theme-color-rgb']};`,
`--f7-color-${colorName}-shade: ${restVars[colorName].common['--f7-theme-color-shade']};`,
`--f7-color-${colorName}-tint: ${restVars[colorName].common['--f7-theme-color-tint']};`,
].join('');
});
rest += '}';

Object.keys(app.colors).forEach((colorName) => {
const { common, light, dark } = restVars[colorName];

rest += [
`.color-theme-${colorName} {`,
`--f7-theme-color : ${restVars[colorName]['--f7-theme-color']};`,
`--f7-theme-color-rgb : ${restVars[colorName]['--f7-theme-color-rgb']};`,
`--f7-theme-color-shade : ${restVars[colorName]['--f7-theme-color-shade']};`,
`--f7-theme-color-tint : ${restVars[colorName]['--f7-theme-color-tint']};`,
`--swiper-theme-color: ${restVars[colorName]['--f7-theme-color']};`,
stringifyObject(common),
stringifyObject(light),
`--swiper-theme-color: var(--f7-theme-color);`,
`}`,
`.color-theme-${colorName}.dark, .color-theme-${colorName} .dark, .dark .color-theme-${colorName} {${stringifyObject(
dark,
)}}`,
].join('');
});

Object.keys(app.colors).forEach((colorName) => {
const { common, light, dark } = restVars[colorName];

rest += [
`.color-${colorName} {`,
`--f7-theme-color : ${restVars[colorName]['--f7-theme-color']};`,
`--f7-theme-color-rgb : ${restVars[colorName]['--f7-theme-color-rgb']};`,
`--f7-theme-color-shade : ${restVars[colorName]['--f7-theme-color-shade']};`,
`--f7-theme-color-tint : ${restVars[colorName]['--f7-theme-color-tint']};`,
`--swiper-theme-color: ${restVars[colorName]['--f7-theme-color']};`,
stringifyObject(common),
stringifyObject(light),
`--swiper-theme-color: var(--f7-theme-color);`,
`}`,
`.color-${colorName}.dark, .color-${colorName} .dark, .dark .color-${colorName} {${stringifyObject(
dark,
)}}`,
`.text-color-${colorName} {`,
`--f7-theme-color-text-color: ${app.colors[colorName]};`,
`}`,
Expand All @@ -209,7 +229,7 @@ class Framework7 extends Framework7Class {
`--f7-theme-color-border-color: ${app.colors[colorName]};`,
`}`,
`.ripple-color-${colorName}, .ripple-${colorName} {`,
`--f7-theme-color-ripple-color: rgba(${restVars[colorName]['--f7-theme-color-rgb']}, 0.3);`,
`--f7-theme-color-ripple-color: var(--f7-theme-color-rgb);`,
`}`,
].join('');
});
Expand Down
108 changes: 108 additions & 0 deletions src/core/shared/material-colors.js
@@ -0,0 +1,108 @@
// eslint-disable-next-line
import { argbFromHex, hexFromArgb, themeFromSourceColor } from '@material/material-color-utilities';

/* eslint-disable */
// prettier-ignore
function toRGBA(d) {
const r = Math.round;
const l = d.length;
const rgba = {};
if (d.slice(0, 3).toLowerCase() === 'rgb') {
d = d.replace(' ', '').split(',');
rgba[0] = parseInt(d[0].slice(d[3].toLowerCase() === 'a' ? 5 : 4), 10);
rgba[1] = parseInt(d[1], 10);
rgba[2] = parseInt(d[2], 10);
rgba[3] = d[3] ? parseFloat(d[3]) : -1;
} else {
if (l < 6) d = parseInt(String(d[1]) + d[1] + d[2] + d[2] + d[3] + d[3] + (l > 4 ? String(d[4]) + d[4] : ''), 16);
else d = parseInt(d.slice(1), 16);
rgba[0] = (d >> 16) & 255;
rgba[1] = (d >> 8) & 255;
rgba[2] = d & 255;
rgba[3] = l === 9 || l === 5 ? r((((d >> 24) & 255) / 255) * 10000) / 10000 : -1;
}
return rgba;
}

// prettier-ignore
function blend(from, to, p = 0.5) {
const r = Math.round;
from = from.trim();
to = to.trim();
const b = p < 0;
p = b ? p * -1 : p;
const f = toRGBA(from);
const t = toRGBA(to);
if (to[0] === 'r') {
return 'rgb' + (to[3] === 'a' ? 'a(' : '(') +
r(((t[0] - f[0]) * p) + f[0]) + ',' +
r(((t[1] - f[1]) * p) + f[1]) + ',' +
r(((t[2] - f[2]) * p) + f[2]) + (
f[3] < 0 && t[3] < 0 ? '' : ',' + (
f[3] > -1 && t[3] > -1
? r((((t[3] - f[3]) * p) + f[3]) * 10000) / 10000
: t[3] < 0 ? f[3] : t[3]
)
) + ')';
}

return '#' + (0x100000000 + ((
f[3] > -1 && t[3] > -1
? r((((t[3] - f[3]) * p) + f[3]) * 255)
: t[3] > -1 ? r(t[3] * 255) : f[3] > -1 ? r(f[3] * 255) : 255
) * 0x1000000) +
(r(((t[0] - f[0]) * p) + f[0]) * 0x10000) +
(r(((t[1] - f[1]) * p) + f[1]) * 0x100) +
r(((t[2] - f[2]) * p) + f[2])
).toString(16).slice(f[3] > -1 || t[3] > -1 ? 1 : 3);
}
/* eslint-enable */

export const materialColors = (hexColor = '') => {
const theme = themeFromSourceColor(argbFromHex(`#${hexColor.replace('#', '')}`));
[0.05, 0.08, 0.11, 0.12, 0.14].forEach((amount, index) => {
theme.schemes.light.props[`surface${index + 1}`] = argbFromHex(
blend(
hexFromArgb(theme.schemes.light.props.surface),
hexFromArgb(theme.schemes.light.props.primary),
amount,
),
);
theme.schemes.dark.props[`surface${index + 1}`] = argbFromHex(
blend(
hexFromArgb(theme.schemes.dark.props.surface),
hexFromArgb(theme.schemes.dark.props.primary),
amount,
),
);
});

const name = (n) => {
return n
.split('')
.map((char) =>
char.toUpperCase() === char && char !== '-' && char !== '7'
? `-${char.toLowerCase()}`
: char,
)
.join('');
};

const shouldSkip = (prop) => {
const skip = ['tertiary', 'inverse', 'shadow', 'scrim', 'error', 'background'];
return skip.filter((v) => prop.toLowerCase().includes(v)).length > 0;
};

const light = {};
const dark = {};
Object.keys(theme.schemes.light.props).forEach((prop) => {
if (shouldSkip(prop)) return;
light[name(`--f7-md-${prop}`)] = hexFromArgb(theme.schemes.light.props[prop]);
});
Object.keys(theme.schemes.dark.props).forEach((prop) => {
if (shouldSkip(prop)) return;
dark[name(`--f7-md-${prop}`)] = hexFromArgb(theme.schemes.dark.props[prop]);
});

return { light, dark };
};
17 changes: 13 additions & 4 deletions src/core/shared/utils.js
@@ -1,4 +1,7 @@
import { getWindow } from 'ssr-window';
import { materialColors } from './material-colors.js';

export { materialColors } from './material-colors.js';

let uniqueNum = 0;
export function uniqueNumber() {
Expand Down Expand Up @@ -342,11 +345,17 @@ export function colorThemeCSSProperties(...args) {
const hslTint = [hsl[0], hsl[1], Math.max(0, hsl[2] + 0.08)];
const shade = colorRgbToHex(...colorHslToRgb(...hslShade));
const tint = colorRgbToHex(...colorHslToRgb(...hslTint));
const { light, dark } = materialColors(hex);

return {
'--f7-theme-color': hex,
'--f7-theme-color-rgb': rgb.join(', '),
'--f7-theme-color-shade': shade,
'--f7-theme-color-tint': tint,
common: {
'--f7-theme-color': hex,
'--f7-theme-color-rgb': rgb.join(', '),
'--f7-theme-color-shade': shade,
'--f7-theme-color-tint': tint,
},
light,
dark,
};
}

Expand Down

0 comments on commit 9fb8b3a

Please sign in to comment.