From 8dd60430ed97b39b2bff1c61de0ffb24bd12e804 Mon Sep 17 00:00:00 2001 From: fluid-design-io <2216991777@qq.com> Date: Wed, 18 Oct 2023 00:02:11 -0500 Subject: [PATCH] fix: core code updates --- apps/web/lib/colorHelper.ts | 21 +++- apps/web/lib/generateVariables.ts | 174 +++++++++++++++++++++++++++++ apps/web/lib/getServerColors.ts | 34 ++++++ apps/web/lib/updateCssVariables.ts | 9 +- 4 files changed, 233 insertions(+), 5 deletions(-) create mode 100644 apps/web/lib/generateVariables.ts create mode 100644 apps/web/lib/getServerColors.ts diff --git a/apps/web/lib/colorHelper.ts b/apps/web/lib/colorHelper.ts index d30c88a..cf7c585 100644 --- a/apps/web/lib/colorHelper.ts +++ b/apps/web/lib/colorHelper.ts @@ -1,4 +1,4 @@ -import { ColorMode, RawColor } from "@/types/app"; +import { BaseColors, ColorMode, RawColor } from "@/types/app"; import tinycolor from "tinycolor2"; const toHex = (color: string | RawColor): string => @@ -35,10 +35,29 @@ const toForeground = (color: string | RawColor): string => { } }; +const toRaw = (color: string): RawColor => { + const { h, s, l, a } = tinycolor(color).toHsl(); + return { h, s, l, a }; +}; + +const colorStringToBaseColors = ( + colorString: string, +): Omit => { + const colors = colorString.split(","); + const baseColors = { + primary: colorHelper.toRaw(colors[0]), + secondary: colorHelper.toRaw(colors[1]), + accent: colorHelper.toRaw(colors[2]), + }; + return baseColors; +}; + export const colorHelper = { toHex, toRgba, toHsla, toColorMode, toForeground, + toRaw, + colorStringToBaseColors, }; diff --git a/apps/web/lib/generateVariables.ts b/apps/web/lib/generateVariables.ts new file mode 100644 index 0000000..4b3771a --- /dev/null +++ b/apps/web/lib/generateVariables.ts @@ -0,0 +1,174 @@ +import { + AppCSSVariables, + BaseColorTypes, + BaseColors, + ColorMode, + ColorPalettes, +} from "@/types/app"; +import { colorStepMap } from "./colorStepMap"; +import { colorHelper } from "./colorHelper"; +import generateFigmaUrlToken from "./code-gen/generate-figma-url-token"; + +export enum CodeGenerateType { + CODEGEN = "codegen", + PLUGIN = "plugin", +} +export enum CodeButtonTitle { + RAW = "Raw", + TAILWINDCSS = "Tailwind CSS", + SHADCN = "shadcn/ui", + REACT_NATIVE_PAPER = "React Native Paper", + WEBFLOW = "Webflow", + FIGMA = "Figma", +} + +export const getColorHsl = ( + palette: ColorPalettes[T], + step: number, +): string => { + const { h, s, l } = palette.find((color) => color.step === colorStepMap[step]) + ?.raw; + const hRounded = Math.round(h * 100) / 100; + const sRounded = Math.round(s * 100); + const lRounded = Math.round(l * 100); + return `${hRounded} ${sRounded}% ${lRounded}%`; +}; + +const generateShadcnCss = (colorPalettes: ColorPalettes) => { + const g = (color: BaseColorTypes, step: number) => + getColorHsl(colorPalettes[color], step); + const darkTheme: Record = { + "--background": g("gray", 10), + "--foreground": g("gray", 0), + "--card": g("gray", 10), + "--card-foreground": g("gray", 0), + "--popover": g("gray", 10), + "--popover-foreground": g("gray", 0), + "--primary": g("primary", 4), + "--primary-foreground": g("primary", 9), + "--secondary": g("secondary", 9), + "--secondary-foreground": g("secondary", 1), + "--muted": g("gray", 9), + "--muted-foreground": g("gray", 4), + "--accent": g("accent", 8), + "--accent-foreground": g("accent", 1), + "--border": g("gray", 8), + "--input": g("gray", 8), + "--ring": g("gray", 0), + "--background-accent": g("gray", 9), + }; + + const lightTheme: Record = { + "--background": g("gray", 0), + "--foreground": g("gray", 10), + "--card": g("gray", 0), + "--card-foreground": g("gray", 10), + "--popover": g("gray", 0), + "--popover-foreground": g("gray", 10), + "--primary": g("primary", 6), + "--primary-foreground": g("primary", 1), + "--secondary": g("secondary", 2), + "--secondary-foreground": g("secondary", 9), + "--muted": g("gray", 1), + "--muted-foreground": g("gray", 7), + "--accent": g("accent", 2), + "--accent-foreground": g("accent", 9), + "--border": g("gray", 2), + "--input": g("gray", 2), + "--ring": g("gray", 10), + "--background-accent": g("gray", 1), + }; + + const cssText = `:root { +${Object.entries(lightTheme) + .map(([variableName, value]) => `\t${variableName}: ${value};`) + .join("\n")} +} +.dark { +${Object.entries(darkTheme) + .map(([variableName, value]) => `\t${variableName}: ${value};`) + .join("\n")} +}`; + return cssText; +}; + +const generateRawCss = (colorPalettes: ColorPalettes) => { + // using tailwindcss naming convention, e.g. --gray-100 + // total 4 base colors, 11 steps each + const g = (color: BaseColorTypes, step: number) => + getColorHsl(colorPalettes[color], step); + const tailwindCss: Record = [ + "gray", + "primary", + "secondary", + "accent", + ].reduce((acc, color) => { + for (let i = 0; i < 11; i++) { + acc[`\t--${color}-${colorStepMap[i]}`] = g(color as BaseColorTypes, i); + } + return acc; + }, {}); + const cssText = `:root{ +${Object.entries(tailwindCss) + .map(([variableName, value]) => `${variableName}: ${value};`) + .join("\n")} +}`; + return cssText; +}; + +const generateTailwindCss = (colorPalettes: ColorPalettes) => { + const text = Object.entries(colorPalettes) + .map(([colorName, colorPalette]) => { + let paletteSection = `\t\t${colorName}: {\n`; + colorPalette.forEach((color) => { + paletteSection += `\t\t\t${color.step}: '${colorHelper.toColorMode( + color.raw, + ColorMode.HEX, + )}',\n`; + }); + paletteSection += "\t\t},\n"; + return paletteSection; + }) + .join(""); + + return ` +/* tailwind.config.js */ + +module.exports = { + // ... + theme: { + extend: { + colors: { +${text} }, + }, + }, +}; +`; +}; + +export const generateCssVariables = async ({ + title, + colorPalettes, + baseColors, +}: { + title: CodeButtonTitle; + colorPalettes: ColorPalettes; + baseColors: Omit; +}) => { + switch (title) { + case CodeButtonTitle.RAW: + return generateRawCss(colorPalettes); + case CodeButtonTitle.TAILWINDCSS: + return generateTailwindCss(colorPalettes); + case CodeButtonTitle.SHADCN: + return generateShadcnCss(colorPalettes); + case CodeButtonTitle.REACT_NATIVE_PAPER: + return ""; + case CodeButtonTitle.FIGMA: + return await generateFigmaUrlToken(baseColors); + case CodeButtonTitle.WEBFLOW: + return ""; + default: + return ""; + } +}; diff --git a/apps/web/lib/getServerColors.ts b/apps/web/lib/getServerColors.ts new file mode 100644 index 0000000..6edfc15 --- /dev/null +++ b/apps/web/lib/getServerColors.ts @@ -0,0 +1,34 @@ +import { cookies } from "next/headers"; +import { generateBaseColors } from "./generateBaseColors"; +import { generateColorPalette } from "./colorCalculator"; +import { BaseColorTypes, ColorMode } from "@/types/app"; +import { colorHelper } from "./colorHelper"; + +export const getServerColors = async () => { + const newBaseColors = generateBaseColors(); + const cookieStore = cookies(); + const mode = cookieStore.get("colorMode"); + // short-hand + const [primaryPalette, secondaryPalette, accentPalette, grayPalette] = [ + "primary", + "secondary", + "accent", + "gray", + ].map((color) => + generateColorPalette({ + color: color === "gray" ? newBaseColors.primary : newBaseColors[color], + type: color as BaseColorTypes, + colorMode: mode ? (mode.value as ColorMode) : ColorMode.HEX, + }), + ); + return { + baseColors: newBaseColors, + colorPalettes: { + primary: primaryPalette, + secondary: secondaryPalette, + accent: accentPalette, + gray: grayPalette, + }, + colorMode: mode ? (mode.value as ColorMode) : ColorMode.HEX, + }; +}; diff --git a/apps/web/lib/updateCssVariables.ts b/apps/web/lib/updateCssVariables.ts index ab62fc7..3eef5db 100644 --- a/apps/web/lib/updateCssVariables.ts +++ b/apps/web/lib/updateCssVariables.ts @@ -1,9 +1,10 @@ import { BaseColors, ColorPalettes } from "@/types/app"; import { - CSSType, + CodeButtonTitle, + CodeGenerateType, generateCssVariables, getColorHsl, -} from "./generateCssVariables"; +} from "./generateVariables"; export async function updateCSSVariables( colorPalettes: ColorPalettes, @@ -21,7 +22,7 @@ export async function updateCSSVariables( // Build the CSS text const cssText = ` ${await generateCssVariables({ - type: CSSType.SHADCN, + title: CodeButtonTitle.SHADCN, colorPalettes, baseColors, })} @@ -41,7 +42,7 @@ export async function updateCSSVariables( } /* Custom constant variables */ ${await generateCssVariables({ - type: CSSType.RAW, + title: CodeButtonTitle.RAW, colorPalettes, baseColors, })}