- add complete theme generation
This commit is contained in:
parent
4b94f300f2
commit
dbbbbf5997
@ -1,20 +1,33 @@
|
|||||||
import { countDecimals } from "Utils";
|
import { countDecimals } from "Utils";
|
||||||
import { fromString } from "css-color-converter";
|
import { fromString } from "css-color-converter";
|
||||||
|
|
||||||
|
export interface ColorsInput {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShadesOptions {
|
||||||
|
keys?: string[];
|
||||||
|
keyPrefix?: string;
|
||||||
|
keySuffix?: string;
|
||||||
|
opacities?: number[];
|
||||||
|
structure?: "flat" | "nested";
|
||||||
|
format?: "default" | "css-variable";
|
||||||
|
}
|
||||||
|
|
||||||
const DEFAULT_OPACITIES = [0.1, 0.25, 0.5, 0.75];
|
const DEFAULT_OPACITIES = [0.1, 0.25, 0.5, 0.75];
|
||||||
const DEFAULT_STRUCTURE = "flat";
|
const DEFAULT_STRUCTURE = "flat";
|
||||||
|
|
||||||
const formatColor = ({
|
const formatColor = ({
|
||||||
prefix,
|
key,
|
||||||
rgb,
|
rgb,
|
||||||
opacity,
|
opacity,
|
||||||
}: {
|
}: {
|
||||||
prefix?: string;
|
key?: string;
|
||||||
rgb: string;
|
rgb: string;
|
||||||
opacity?: number;
|
opacity?: number;
|
||||||
}) => {
|
}) => {
|
||||||
return {
|
return {
|
||||||
[`${prefix ? prefix + "-" : ""}${
|
[`${key ? key + "-" : ""}${
|
||||||
opacity !== undefined
|
opacity !== undefined
|
||||||
? countDecimals(opacity) === 1
|
? countDecimals(opacity) === 1
|
||||||
? (opacity + "").split(".")[1] + "0"
|
? (opacity + "").split(".")[1] + "0"
|
||||||
@ -24,16 +37,7 @@ const formatColor = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateShades = (
|
const generateShades = (colors: ColorsInput, options?: ShadesOptions) => {
|
||||||
colors: { [key: string]: string },
|
|
||||||
options?: {
|
|
||||||
keys?: string[];
|
|
||||||
keyPrefix?: string;
|
|
||||||
opacities?: number[];
|
|
||||||
structure?: "flat" | "nested";
|
|
||||||
format?: "default" | "css-variable";
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
const colorKeys = options?.keys
|
const colorKeys = options?.keys
|
||||||
? Object.keys(colors).filter((key) => options.keys?.includes(key))
|
? Object.keys(colors).filter((key) => options.keys?.includes(key))
|
||||||
: Object.keys(colors);
|
: Object.keys(colors);
|
||||||
@ -47,7 +51,7 @@ const generateShades = (
|
|||||||
const generatedColorShadesArr: object[] = [];
|
const generatedColorShadesArr: object[] = [];
|
||||||
|
|
||||||
colorKeys.forEach((_key) => {
|
colorKeys.forEach((_key) => {
|
||||||
const key = (options?.keyPrefix || "") + _key;
|
const key = (options?.keyPrefix || "") + _key + (options?.keySuffix || "");
|
||||||
const colorString = colors[_key];
|
const colorString = colors[_key];
|
||||||
|
|
||||||
const opacities = options?.opacities
|
const opacities = options?.opacities
|
||||||
@ -57,9 +61,7 @@ const generateShades = (
|
|||||||
if (structure === "flat") {
|
if (structure === "flat") {
|
||||||
opacities.forEach((opacity) => {
|
opacities.forEach((opacity) => {
|
||||||
const rgba = fromString(colorString).toRgbaArray();
|
const rgba = fromString(colorString).toRgbaArray();
|
||||||
generatedColorShadesArr.push(
|
generatedColorShadesArr.push(formatColor({ key, rgb: rgba, opacity }));
|
||||||
formatColor({ prefix: key, rgb: rgba, opacity })
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
generatedColorShadesArr.push({
|
generatedColorShadesArr.push({
|
||||||
|
74
src/Theme/index.test.ts
Normal file
74
src/Theme/index.test.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import {
|
||||||
|
generateThemeOverrideClass,
|
||||||
|
generateThemeRoot,
|
||||||
|
generateTheme,
|
||||||
|
ThemeInput,
|
||||||
|
} from ".";
|
||||||
|
|
||||||
|
const exampleProperties = {
|
||||||
|
"color-main-10": "black",
|
||||||
|
"color-main-50": "grey",
|
||||||
|
};
|
||||||
|
|
||||||
|
const exampleThemes: ThemeInput[] = [
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
colors: { "color-main": "black" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dark",
|
||||||
|
colors: { "color-main": "white", "color-secondary": "blue" },
|
||||||
|
},
|
||||||
|
{ name: "light", colors: { "color-secondary": "grey" } },
|
||||||
|
];
|
||||||
|
|
||||||
|
test("it generates css based on input properties", () => {
|
||||||
|
const themeClass = generateThemeOverrideClass({
|
||||||
|
properties: exampleProperties,
|
||||||
|
className: "dark-theme",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(themeClass).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("no input so it returns empty string", () => {
|
||||||
|
const themeClass = generateThemeOverrideClass({
|
||||||
|
properties: {},
|
||||||
|
className: "dark-theme",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(themeClass).toBeDefined();
|
||||||
|
expect(themeClass).toEqual("");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it generates the theme root", () => {
|
||||||
|
const themeRoot = generateThemeRoot({ properties: exampleProperties });
|
||||||
|
console.log(themeRoot);
|
||||||
|
expect(themeRoot).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it generates the complete theme with overrides", () => {
|
||||||
|
const theme = generateTheme({
|
||||||
|
themes: exampleThemes,
|
||||||
|
output: "CSS",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(theme);
|
||||||
|
|
||||||
|
expect(theme).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it generates the complete theme with overrides and color shades", () => {
|
||||||
|
const theme = generateTheme({
|
||||||
|
themes: exampleThemes,
|
||||||
|
output: "CSS",
|
||||||
|
generateColorShades: {
|
||||||
|
structure: "flat",
|
||||||
|
format: "css-variable",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(theme);
|
||||||
|
|
||||||
|
expect(theme).toBeDefined();
|
||||||
|
});
|
@ -1,3 +1,85 @@
|
|||||||
import * as Colors from "./Colors";
|
import * as Colors from "./Colors";
|
||||||
|
import { generateShades, ColorsInput, ShadesOptions } from "./Colors";
|
||||||
|
|
||||||
export default { Colors };
|
export interface ThemeInput {
|
||||||
|
name: string;
|
||||||
|
colors: ColorsInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateThemeOverrideClass = (input: {
|
||||||
|
properties: any;
|
||||||
|
className: string;
|
||||||
|
}) => {
|
||||||
|
const propKeys = Object.keys(input.properties);
|
||||||
|
|
||||||
|
if (propKeys.length > 0) {
|
||||||
|
return `
|
||||||
|
.${input.className} {${propKeys
|
||||||
|
.map((key) => `\t--${key}: ${input.properties[key]};`)
|
||||||
|
.join("\n")}}`;
|
||||||
|
} else return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateThemeRoot = (input: { properties: any }) => {
|
||||||
|
const propKeys = Object.keys(input.properties);
|
||||||
|
|
||||||
|
if (propKeys.length > 0) {
|
||||||
|
return `
|
||||||
|
:root {${propKeys
|
||||||
|
.map((key) => `\t--${key}: ${input.properties[key]};`)
|
||||||
|
.join("\n")}}`;
|
||||||
|
} else return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateTheme = (options: {
|
||||||
|
output?: "CSS";
|
||||||
|
themes: ThemeInput[];
|
||||||
|
generateColorShades?: boolean | ShadesOptions;
|
||||||
|
}) => {
|
||||||
|
if (
|
||||||
|
options.generateColorShades !== undefined &&
|
||||||
|
options.generateColorShades !== false
|
||||||
|
) {
|
||||||
|
options.themes = options.themes.map((theme) => {
|
||||||
|
theme.colors = {
|
||||||
|
...generateShades(
|
||||||
|
theme.colors,
|
||||||
|
typeof options.generateColorShades !== "boolean"
|
||||||
|
? options.generateColorShades
|
||||||
|
: undefined
|
||||||
|
),
|
||||||
|
...theme.colors,
|
||||||
|
};
|
||||||
|
|
||||||
|
return theme;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const themeRoot = generateThemeRoot({
|
||||||
|
properties: { ...options.themes[0].colors },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (options.themes.length > 1) {
|
||||||
|
const themeOverrides = options.themes
|
||||||
|
.slice(1)
|
||||||
|
.map((theme) => {
|
||||||
|
const overrideClass = generateThemeOverrideClass({
|
||||||
|
properties: { ...theme.colors },
|
||||||
|
className: theme.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
return overrideClass;
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
return themeRoot + themeOverrides;
|
||||||
|
} else return themeRoot;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { generateThemeOverrideClass, generateThemeRoot, generateTheme };
|
||||||
|
export default {
|
||||||
|
Colors,
|
||||||
|
generateThemeOverrideClass,
|
||||||
|
generateThemeRoot,
|
||||||
|
generateTheme,
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user