From a02686c2b26b849f277af878845890867ef660cf Mon Sep 17 00:00:00 2001 From: fluid-design-io <2216991777@qq.com> Date: Wed, 18 Oct 2023 01:11:07 -0500 Subject: [PATCH] feat: added react native paper codegen --- apps/web/app/code/generate-button.tsx | 2 +- apps/web/app/code/page.tsx | 1 - apps/web/app/page.tsx | 6 +- .../web/components/toolbar/shareable-link.tsx | 38 +++- apps/web/lib/code-gen/generate-rnp-tokens.ts | 162 ++++++++++++++++++ apps/web/lib/colorHelper.ts | 4 +- apps/web/lib/generateVariables.ts | 3 +- apps/web/next.config.js | 13 ++ apps/web/types/app.ts | 6 + 9 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 apps/web/lib/code-gen/generate-rnp-tokens.ts diff --git a/apps/web/app/code/generate-button.tsx b/apps/web/app/code/generate-button.tsx index ca64ba7..6cf7925 100644 --- a/apps/web/app/code/generate-button.tsx +++ b/apps/web/app/code/generate-button.tsx @@ -128,7 +128,7 @@ function CodeGenerateButton({ }} > {/* make it a span */} - {code.split("\n").map((line, index) => ( + {code?.split("\n").map((line, index) => ( { - navigator.clipboard.writeText(src); + navigator.clipboard.writeText(colors); setOpen(false); }; useEffect(() => { @@ -29,17 +33,39 @@ function ToolbarShareableLink() { .map((color) => colorHelper.toHex(color)) .join(","); search = encodeURIComponent(search); - const url = `${process.env.NEXT_PUBLIC_URL}/?colors=${search}`; - setSrc(url); + setColors(search); }, [!!open]); return ( - + +
+
+ + + Social preview setLoadingSocialPreview(false)} + width={288} + height={151} + /> +
+
- + diff --git a/apps/web/lib/code-gen/generate-rnp-tokens.ts b/apps/web/lib/code-gen/generate-rnp-tokens.ts new file mode 100644 index 0000000..91434ca --- /dev/null +++ b/apps/web/lib/code-gen/generate-rnp-tokens.ts @@ -0,0 +1,162 @@ +import { BaseColorTypes, ColorPalettes } from "@/types/app"; +import { colorStepMap } from "../colorStepMap"; +import { colorHelper } from "../colorHelper"; + +/* +{ + "colors": { + "primary": "rgb(120, 69, 172)", + "onPrimary": "rgb(255, 255, 255)", + "primaryContainer": "rgb(240, 219, 255)", + "onPrimaryContainer": "rgb(44, 0, 81)", + "secondary": "rgb(102, 90, 111)", + "onSecondary": "rgb(255, 255, 255)", + "secondaryContainer": "rgb(237, 221, 246)", + "onSecondaryContainer": "rgb(33, 24, 42)", + "tertiary": "rgb(128, 81, 88)", + "onTertiary": "rgb(255, 255, 255)", + "tertiaryContainer": "rgb(255, 217, 221)", + "onTertiaryContainer": "rgb(50, 16, 23)", + "error": "rgb(186, 26, 26)", + "onError": "rgb(255, 255, 255)", + "errorContainer": "rgb(255, 218, 214)", + "onErrorContainer": "rgb(65, 0, 2)", + "background": "rgb(255, 251, 255)", + "onBackground": "rgb(29, 27, 30)", + "surface": "rgb(255, 251, 255)", + "onSurface": "rgb(29, 27, 30)", + "surfaceVariant": "rgb(233, 223, 235)", + "onSurfaceVariant": "rgb(74, 69, 78)", + "outline": "rgb(124, 117, 126)", + "outlineVariant": "rgb(204, 196, 206)", + "shadow": "rgb(0, 0, 0)", + "scrim": "rgb(0, 0, 0)", + "inverseSurface": "rgb(50, 47, 51)", + "inverseOnSurface": "rgb(245, 239, 244)", + "inversePrimary": "rgb(220, 184, 255)", + "elevation": { + "level0": "transparent", + "level1": "rgb(248, 242, 251)", + "level2": "rgb(244, 236, 248)", + "level3": "rgb(240, 231, 246)", + "level4": "rgb(239, 229, 245)", + "level5": "rgb(236, 226, 243)" + }, + "surfaceDisabled": "rgba(29, 27, 30, 0.12)", + "onSurfaceDisabled": "rgba(29, 27, 30, 0.38)", + "backdrop": "rgba(51, 47, 55, 0.4)" + } +} +*/ +export const getColorRgb = ( + palette: ColorPalettes[T], + step: number, +): string => { + const color = palette.find((color) => color.step === colorStepMap[step]) + ?.color; + const { r, g, b } = colorHelper.toRgb(color); + return `rgb(${r},${g},${b})`; +}; + +const generateRNPTokens = (colorPalettes: ColorPalettes) => { + /** + * Helper function to get a color from a palette + * @param color + * @param step 0-10 + * @returns + */ + const g = (color: BaseColorTypes, step: number) => + getColorRgb(colorPalettes[color], step); + const lightTheme: Record = { + primary: g("primary", 6), + onPrimary: g("primary", 0), + primaryContainer: g("primary", 1), + onPrimaryContainer: g("primary", 9), + secondary: g("secondary", 6), + onSecondary: g("secondary", 0), + secondaryContainer: g("secondary", 1), + onSecondaryContainer: g("secondary", 9), + tertiary: g("accent", 6), + onTertiary: g("accent", 0), + tertiaryContainer: g("accent", 1), + onTertiaryContainer: g("accent", 9), + error: "rgb(186, 26, 26)", + onError: "rgb(255, 255, 255)", + errorContainer: "rgb(255, 218, 214)", + onErrorContainer: "rgb(65, 0, 2)", + background: g("gray", 0), + onBackground: g("gray", 10), + surface: g("gray", 0), + onSurface: g("gray", 10), + surfaceVariant: g("gray", 1), + onSurfaceVariant: g("gray", 9), + outline: g("gray", 2), + outlineVariant: g("accent", 3), + shadow: g("gray", 10), + scrim: g("gray", 10), + inverseSurface: g("gray", 9), + inverseOnSurface: g("gray", 1), + inversePrimary: g("primary", 6), + elevation: { + level0: "transparent", + level1: g("gray", 1), + level2: g("gray", 2), + level3: g("gray", 3), + level4: g("gray", 4), + level5: g("gray", 5), + }, + surfaceDisabled: "rgba(29, 27, 30, 0.12)", + onSurfaceDisabled: "rgba(29, 27, 30, 0.38)", + backdrop: "rgba(51, 47, 55, 0.4)", + }; + const darkTheme: Record = { + primary: g("primary", 6), + onPrimary: g("primary", 0), + primaryContainer: g("primary", 1), + onPrimaryContainer: g("primary", 9), + secondary: g("secondary", 6), + onSecondary: g("secondary", 0), + secondaryContainer: g("secondary", 1), + onSecondaryContainer: g("secondary", 9), + tertiary: g("accent", 6), + onTertiary: g("accent", 0), + tertiaryContainer: g("accent", 1), + onTertiaryContainer: g("accent", 9), + error: "rgb(186, 26, 26)", + onError: "rgb(255, 255, 255)", + errorContainer: "rgb(255, 218, 214)", + onErrorContainer: "rgb(65, 0, 2)", + background: g("gray", 10), + onBackground: g("gray", 0), + surface: g("gray", 10), + onSurface: g("gray", 0), + surfaceVariant: g("gray", 9), + onSurfaceVariant: g("gray", 1), + outline: g("gray", 8), + outlineVariant: g("accent", 3), + shadow: g("gray", 0), + scrim: g("gray", 0), + inverseSurface: g("gray", 1), + inverseOnSurface: g("gray", 9), + inversePrimary: g("primary", 6), + elevation: { + level0: "transparent", + level1: g("gray", 9), + level2: g("gray", 8), + level3: g("gray", 7), + level4: g("gray", 6), + level5: g("gray", 5), + }, + surfaceDisabled: "rgba(29, 27, 30, 0.12)", + onSurfaceDisabled: "rgba(29, 27, 30, 0.38)", + backdrop: "rgba(51, 47, 55, 0.4)", + }; + const tokens = { + light: lightTheme, + dark: darkTheme, + }; + + return `export const tokens = ${JSON.stringify(tokens, null, 2)}`; +}; + +export default generateRNPTokens; diff --git a/apps/web/lib/colorHelper.ts b/apps/web/lib/colorHelper.ts index cf7c585..f4cbc51 100644 --- a/apps/web/lib/colorHelper.ts +++ b/apps/web/lib/colorHelper.ts @@ -1,4 +1,4 @@ -import { BaseColors, ColorMode, RawColor } from "@/types/app"; +import { BaseColors, ColorMode, RGB, RawColor } from "@/types/app"; import tinycolor from "tinycolor2"; const toHex = (color: string | RawColor): string => @@ -7,6 +7,7 @@ const toRgba = (color: string | RawColor): string => tinycolor(color).toRgbString(); const toHsla = (color: string | RawColor): string => tinycolor(color).toHslString(); +const toRgb = (color: string | RawColor): RGB => tinycolor(color).toRgb(); const toColorMode = (color: any, mode: ColorMode): string => { if (!tinycolor(color).isValid) return "#000"; @@ -55,6 +56,7 @@ const colorStringToBaseColors = ( export const colorHelper = { toHex, toRgba, + toRgb, toHsla, toColorMode, toForeground, diff --git a/apps/web/lib/generateVariables.ts b/apps/web/lib/generateVariables.ts index 4b3771a..9435a8d 100644 --- a/apps/web/lib/generateVariables.ts +++ b/apps/web/lib/generateVariables.ts @@ -8,6 +8,7 @@ import { import { colorStepMap } from "./colorStepMap"; import { colorHelper } from "./colorHelper"; import generateFigmaUrlToken from "./code-gen/generate-figma-url-token"; +import generateRNPTokens from "./code-gen/generate-rnp-tokens"; export enum CodeGenerateType { CODEGEN = "codegen", @@ -163,7 +164,7 @@ export const generateCssVariables = async ({ case CodeButtonTitle.SHADCN: return generateShadcnCss(colorPalettes); case CodeButtonTitle.REACT_NATIVE_PAPER: - return ""; + return generateRNPTokens(colorPalettes); case CodeButtonTitle.FIGMA: return await generateFigmaUrlToken(baseColors); case CodeButtonTitle.WEBFLOW: diff --git a/apps/web/next.config.js b/apps/web/next.config.js index dd8da99..1b310c7 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -1,5 +1,18 @@ module.exports = { reactStrictMode: true, + images: { + remotePatterns: [ + { + protocol: 'http', + hostname: 'localhost', + }, + { + protocol: 'https', + hostname: 'fluid-colors.vercel.app', + pathname: '*', + }, + ] + }, transpilePackages: ["ui"], typescript: { ignoreBuildErrors: true diff --git a/apps/web/types/app.ts b/apps/web/types/app.ts index 8ea7f3c..e9c1793 100644 --- a/apps/web/types/app.ts +++ b/apps/web/types/app.ts @@ -11,6 +11,12 @@ export type RawColor = { a: number; }; +export type RGB = { + r: number; + g: number; + b: number; +}; + export type BaseColorTypes = "primary" | "secondary" | "accent" | "gray"; export type BaseColors = Record;