Skip to content

Commit

Permalink
feat(plugin): add themeColors
Browse files Browse the repository at this point in the history
  • Loading branch information
wzc520pyfm committed Mar 28, 2024
1 parent ed3d5fe commit 2a10973
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 0 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,36 @@ const mycolor2 = mycolor.extend(getLuminance)
mycolor2("yellow").getLuminance() // 0.9278
```

### themeColors

Generate color shades for themes.

```ts
import { mycolor } from 'ohcolor'
import { themeColors } from 'ohcolor/plugin'

const mycolor2 = mycolor.extend(themeColors)
mycolor2("yellow").themeColors()
```

Will generate the following shades:

```json
{
"100": "#FFFFE6",
"200": "#FFFFBF",
"300": "#FFFF99",
"400": "#FFFF4D",
"50": "#FFFFF2",
"500": "#FFFF00",
"600": "#E6E600",
"700": "#999900",
"800": "#737300",
"900": "#4D4D00",
"950": "#333300",
}
```

## Development

- Clone this repository
Expand Down
1 change: 1 addition & 0 deletions src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { inputHex } from "./inputHex";
export { outputHex } from "./outputHex";
export { inputNamed } from "./inputNamed";
export { getLuminance } from "./getLuminance";
export { themeColors } from "./themeColors";
47 changes: 47 additions & 0 deletions src/plugin/themeColors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { MyColorPlugin, MyColor, MyColorFn } from "../..";
import { withTint, withShade, parseColor, hexValue } from "./util";

interface OhColorClass extends MyColor {
themeColors: () => Record<string, string>;
}

interface OhColorFactory extends MyColorFn {
(...args: unknown[]): OhColorClass;
}

export const _variants = {
50: withTint(0.95),
100: withTint(0.9),
200: withTint(0.75),
300: withTint(0.6),
400: withTint(0.3),
500: (c: number[]) => c,
600: withShade(0.9),
700: withShade(0.6),
800: withShade(0.45),
900: withShade(0.3),
950: withShade(0.2),
};

/**
* Plugin: returns a number (float) representing the luminance of a color.
*/
export const themeColors: MyColorPlugin<OhColorFactory> = (_, c, cf) => {
const proto = c.prototype as OhColorClass;
const getRGB = proto.rgba;
proto.themeColors = function (variants = _variants) {
const [r,g,b] = getRGB.bind(this)();
const colors: Record<string, string> = {};
const components = parseColor(`${r},${g},${b}`);

for (const [name, fn] of Object.entries(variants)) {
colors[name] = hexValue(fn(components));
}

return colors;
};

return cf as OhColorFactory;
};

export default themeColors;
42 changes: 42 additions & 0 deletions src/plugin/themeColors/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export function parseColor(color = "") {
if (typeof color !== "string") {
throw new TypeError("Color should be string!");
}

const hexMatch = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(color);
if (hexMatch) {
return hexMatch.splice(1).map((c) => Number.parseInt(c, 16));
}

const hexMatchShort = /^#?([\da-f])([\da-f])([\da-f])$/i.exec(color);
if (hexMatchShort) {
return hexMatchShort.splice(1).map((c) => Number.parseInt(c + c, 16));
}

if (color.includes(",")) {
return color.split(",").map((p) => Number.parseInt(p));
}

throw new Error("Invalid color format! Use #ABC or #AABBCC or r,g,b");
}

export function hexValue(components: number[]) {
return (
"#" +
components.map((c) => `0${c.toString(16).toUpperCase()}`.slice(-2)).join("")
);
}

export function tint(components: number[], intensity: number) {
return components.map((c) => Math.round(c + (255 - c) * intensity));
}

export function shade(components: number[], intensity: number) {
return components.map((c) => Math.round(c * intensity));
}

export const withTint = (intensity: number) => (hex: number[]) =>
tint(hex, intensity);

export const withShade = (intensity: number) => (hex: number[]) =>
shade(hex, intensity);
27 changes: 27 additions & 0 deletions test/plugin/theme-colors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect, it, describe } from "vitest";
import { mycolor } from "../../src";
import { themeColors } from "../../src/plugin";

describe("mycolor plugin: themeColors", () => {
const fixture = {
hex: "#ABABAB",
theme: {
50: "#FBFBFB",
100: "#F7F7F7",
200: "#EAEAEA",
300: "#DDDDDD",
400: "#C4C4C4",
500: "#ABABAB",
600: "#9A9A9A",
700: "#676767",
800: "#4D4D4D",
900: "#333333",
950: "#222222",
},
};
it("input hex string, get theme", () => {
const mycolor2 = mycolor.extend(themeColors);

expect(mycolor2(fixture.hex).themeColors()).toMatchObject(fixture.theme);
});
});

0 comments on commit 2a10973

Please sign in to comment.