diff options
author | crupest <crupest@outlook.com> | 2021-06-15 18:25:17 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-15 18:25:17 +0800 |
commit | 4645761c2090aeaf8c26789155b342c048f44535 (patch) | |
tree | 1aab5ce94549f3f8b3fd1a31c84fb2dd8b6b2511 /FrontEnd/src/palette.ts | |
parent | 485ef185153890b7c6ac4ed9798a3f2db80c8845 (diff) | |
parent | b6afd5e8161126522bdfff876f5483fa97e94797 (diff) | |
download | timeline-4645761c2090aeaf8c26789155b342c048f44535.tar.gz timeline-4645761c2090aeaf8c26789155b342c048f44535.tar.bz2 timeline-4645761c2090aeaf8c26789155b342c048f44535.zip |
Merge pull request #620 from crupest/vite
Migrate to vite!
Diffstat (limited to 'FrontEnd/src/palette.ts')
-rw-r--r-- | FrontEnd/src/palette.ts | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/FrontEnd/src/palette.ts b/FrontEnd/src/palette.ts new file mode 100644 index 00000000..6385df66 --- /dev/null +++ b/FrontEnd/src/palette.ts @@ -0,0 +1,117 @@ +import Color from "color"; +import { BehaviorSubject, Observable } from "rxjs"; + +function lightenBy(color: Color, ratio: number): Color { + const lightness = color.lightness(); + return color.lightness(lightness + (100 - lightness) * ratio); +} + +function darkenBy(color: Color, ratio: number): Color { + const lightness = color.lightness(); + return color.lightness(lightness - lightness * ratio); +} + +export interface PaletteColor { + color: string; + inactive: string; + lighter: string; + darker: string; + [key: string]: string; +} + +const paletteColorList = [ + "primary", + "primary-enhance", + "secondary", + "text-primary", + "text-on-primary", + "danger", + "success", +] as const; + +export type PaletteColorType = typeof paletteColorList[number]; + +export type Palette = Record<PaletteColorType, PaletteColor>; + +export function generatePaletteColor(color: string): PaletteColor { + const c = Color(color); + return { + color: c.toString(), + inactive: (c.lightness() > 60 + ? darkenBy(c, 0.1) + : lightenBy(c, 0.2) + ).toString(), + lighter: lightenBy(c, 0.1).fade(0.1).toString(), + darker: darkenBy(c, 0.1).toString(), + }; +} + +export function generatePalette(options: { + primary: string; + primaryEnhance?: string; + secondary?: string; +}): Palette { + const { primary, primaryEnhance, secondary } = options; + const p = Color(primary); + const pe = + primaryEnhance == null + ? lightenBy(p, 0.3).saturate(0.3) + : Color(primaryEnhance); + const s = secondary == null ? p.rotate(90) : Color(secondary); + + return { + primary: generatePaletteColor(p.toString()), + "primary-enhance": generatePaletteColor(pe.toString()), + secondary: generatePaletteColor(s.toString()), + "text-primary": generatePaletteColor("#111111"), + "text-on-primary": generatePaletteColor( + p.lightness() > 60 ? "black" : "white" + ), + danger: generatePaletteColor("red"), + success: generatePaletteColor("green"), + }; +} + +export function generatePaletteCSS(palette: Palette): string { + const colors: [string, string][] = []; + for (const colorType of paletteColorList) { + const paletteColor = palette[colorType]; + for (const variant in paletteColor) { + let key = `--tl-${colorType}`; + if (variant !== "color") key += `-${variant}`; + key += "-color"; + colors.push([key, paletteColor[variant]]); + } + } + + return `:root {${colors + .map(([key, color]) => `${key} : ${color};`) + .join("")}}`; +} + +const paletteSubject: BehaviorSubject<Palette> = new BehaviorSubject<Palette>( + generatePalette({ primary: "#007bff" }) +); + +export const palette$: Observable<Palette> = paletteSubject.asObservable(); + +palette$.subscribe((palette) => { + const styleTagId = "timeline-palette-css"; + let styleTag = document.getElementById(styleTagId); + if (styleTag == null) { + styleTag = document.createElement("style"); + styleTag.id = styleTagId; + document.head.append(styleTag); + } + styleTag.innerHTML = generatePaletteCSS(palette); +}); + +export function setPalette(palette: Palette): () => void { + const old = paletteSubject.value; + + paletteSubject.next(palette); + + return () => { + paletteSubject.next(old); + }; +} |