UNPKG

@cometchat/chat-uikit-react-native

Version:

Ready-to-use Chat UI Components for React Native

439 lines (404 loc) 18.4 kB
import { deepMerge } from "../shared/helper/helperFunctions"; import { DeepPartial } from "../shared/helper/types"; import { defaultColorDark, defaultSpacing } from "./default"; import { defaultColorLight } from "./default/color/light"; import { CometChatTheme } from "./type"; export enum Brightness { LIGHT = 0, DARK = 1, } enum Colors { BLACK = "#000000", WHITE = "#FFFFFF", } export class CometChatThemeHelper { /** * Returns a list of color blending percentages based on the brightness setting. * * @param brightness - The brightness mode to determine the blending percentages. * Use `Brightness.LIGHT` for light mode and `Brightness.DARK` for dark mode. * @returns An array of blending percentages. For light mode, it provides percentages closer to white; * for dark mode, it provides percentages closer to black. * * @example * ```typescript * const lightPercentages = getBlendColorsPercentage(Brightness.LIGHT); * console.log(lightPercentages); // Output: [0.96, 0.88, 0.77, 0.66, 0.55, 0.44, 0.33, 0.22, 0.11, 0.11] * ``` */ public static getBlendColorsPercentage(brightness: Brightness): { [key: number]: number } { return brightness === Brightness.LIGHT ? { 50: 0.96, 100: 0.88, 200: 0.77, 300: 0.66, 400: 0.55, 500: 0.44, 600: 0.33, 700: 0.22, 800: 0.11, 900: 0.11, } : { 50: 0.8, 100: 0.72, 200: 0.64, 300: 0.56, 400: 0.48, 500: 0.4, 600: 0.32, 700: 0.24, 800: 0.16, 900: 0.08, }; } /** * Converts a hexadecimal color code to its RGB components. * * @param hex - The color code in hexadecimal format (e.g., "#FF0000" for red). * @returns An object containing the red, green, and blue components of the color. * * @example * ```typescript * const rgb = hexToRgb("#FF0000"); * console.log(rgb); // Output: { r: 255, g: 0, b: 0 } * ``` */ private static hexToRgb(hex: string): { r: number; g: number; b: number } { let r = 0, g = 0, b = 0; // 3 digits if (hex.length === 4) { r = parseInt(hex[1] + hex[1], 16); g = parseInt(hex[2] + hex[2], 16); b = parseInt(hex[3] + hex[3], 16); } // 6 digits else if (hex.length === 7) { r = parseInt(hex[1] + hex[2], 16); g = parseInt(hex[3] + hex[4], 16); b = parseInt(hex[5] + hex[6], 16); } return { r, g, b }; } /** * Converts RGB color components to a hexadecimal color code. * * @param r - The red component of the color (0-255). * @param g - The green component of the color (0-255). * @param b - The blue component of the color (0-255). * @returns The color code in hexadecimal format. * * @example * ```typescript * const hex = rgbToHex(255, 0, 0); * console.log(hex); // Output: "#FF0000" * ``` */ private static rgbToHex(r: number, g: number, b: number): string { return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`; } /** * Blends two colors together based on a specified percentage. * * @param baseColor - The base color in hexadecimal format (e.g., "#FF0000" for red). * @param blendColor - The color to blend with the base color, also in hexadecimal format. * @param percentage - The percentage of the `blendColor` to blend with the `baseColor`. * It should be a value between 0 and 1, where 0 means only the `baseColor` is used and * 1 means only the `blendColor` is used. * @returns The resulting blended color in hexadecimal format. * * @example * ```typescript * const brightness: Brightness = Brightness.LIGHT; * const blendColorsPercentage = CometChatThemeHelper.getBlendColorsPercentage(brightness); * const blendedColor = CometChatThemeHelper.blendColors("#6852D6", "#FFFFFF", blendColorsPercentage[0]); * ``` */ private static blendColors(baseColor: string, blendColor: string, percentage: number): string { const { r: rBase, g: gBase, b: bBase } = this.hexToRgb(baseColor); const { r: rBlend, g: gBlend, b: bBlend } = this.hexToRgb(blendColor); const r = Math.round(rBase * (1 - percentage) + rBlend * percentage); const g = Math.round(gBase * (1 - percentage) + gBlend * percentage); const b = Math.round(bBase * (1 - percentage) + bBlend * percentage); return this.rgbToHex(r, g, b); } public static updateColors(color: Partial<CometChatTheme["color"]>, mode: Brightness) { if (mode == Brightness.LIGHT) { return CometChatThemeHelper.updateOtherColors( CometChatThemeHelper.updateExtendedColorsForLightTheme( color, CometChatThemeHelper.getBlendColorsPercentage(mode) ), defaultColorLight ); } return CometChatThemeHelper.updateOtherColors( CometChatThemeHelper.updateExtendedColorsForDarkTheme( color, CometChatThemeHelper.getBlendColorsPercentage(mode) ), defaultColorDark ); } private static updateOtherColors( color: Partial<CometChatTheme["color"]>, defaultColor: Partial<CometChatTheme["color"]> ) { color.neutral50 = color.neutral50 ?? defaultColor.neutral50; color.neutral100 = color.neutral100 ?? defaultColor.neutral100; color.neutral200 = color.neutral200 ?? defaultColor.neutral200; color.neutral300 = color.neutral300 ?? defaultColor.neutral300; color.neutral400 = color.neutral400 ?? defaultColor.neutral400; color.neutral500 = color.neutral500 ?? defaultColor.neutral500; color.neutral600 = color.neutral600 ?? defaultColor.neutral600; color.neutral700 = color.neutral700 ?? defaultColor.neutral700; color.neutral800 = color.neutral800 ?? defaultColor.neutral800; color.neutral900 = color.neutral900 ?? defaultColor.neutral900; color.staticBlack = color.staticBlack ?? defaultColor.staticBlack; color.staticWhite = color.staticWhite ?? defaultColor.staticWhite; color.info = color.info ?? defaultColor.info; color.warning = color.warning ?? defaultColor.warning; color.success = color.success ?? defaultColor.success; color.error = color.error ?? defaultColor.error; /***background colors***/ color.background1 = color.background1 === undefined ? color.neutral50 : color.background1; color.background2 = color.background2 === undefined ? color.neutral100 : color.background2; color.background3 = color.background3 === undefined ? color.neutral200 : color.background3; color.background4 = color.background4 === undefined ? color.neutral300 : color.background4; /***border colors***/ color.borderLight = color.borderLight === undefined ? color.neutral200 : color.borderLight; color.borderDefault = color.borderDefault === undefined ? color.neutral300 : color.borderDefault; color.borderDark = color.borderDark === undefined ? color.neutral400 : color.borderDark; color.borderHighlight = color.borderHighlight === undefined ? color.primary : color.borderHighlight; /***text colors***/ color.textPrimary = color.textPrimary === undefined ? color.neutral900 : color.textPrimary; color.textSecondary = color.textSecondary === undefined ? color.neutral600 : color.textSecondary; color.textTertiary = color.textTertiary === undefined ? color.neutral500 : color.textTertiary; color.textDisabled = color.textDisabled === undefined ? color.neutral400 : color.textDisabled; color.textWhite = color.textWhite === undefined ? color.neutral50 : color.textWhite; color.textHighlight = color.textHighlight === undefined ? color.primary : color.textHighlight; /***icon colors***/ color.iconPrimary = color.iconPrimary === undefined ? color.neutral900 : color.iconPrimary; color.iconSecondary = color.iconSecondary === undefined ? color.neutral500 : color.iconSecondary; color.iconTertiary = color.iconTertiary === undefined ? color.neutral400 : color.iconTertiary; color.iconWhite = color.iconWhite === undefined ? color.neutral50 : color.iconWhite; color.iconHighlight = color.iconHighlight === undefined ? color.primary : color.iconHighlight; /***button colors***/ color.primaryButtonBackground = color.primaryButtonBackground === undefined ? color.primary : color.primaryButtonBackground; color.primaryButtonIcon = color.primaryButtonIcon === undefined ? color.staticWhite : color.primaryButtonIcon; color.primaryButtonText = color.primaryButtonText === undefined ? color.staticWhite : color.primaryButtonText; color.secondaryButtonBackground = color.secondaryButtonBackground === undefined ? color.neutral900 : color.secondaryButtonBackground; color.secondaryButtonIcon = color.secondaryButtonIcon === undefined ? color.neutral900 : color.secondaryButtonIcon; color.secondaryButtonText = color.secondaryButtonText === undefined ? color.neutral900 : color.secondaryButtonText; /***other colors***/ color.linkBackground = color.linkBackground === undefined ? color.info : color.linkBackground; color.fabButtonBackground = color.fabButtonBackground === undefined ? color.primary : color.fabButtonBackground; color.fabButtonIcon = color.fabButtonIcon === undefined ? color.staticWhite : color.fabButtonIcon; color.whiteHover = color.whiteHover === undefined ? color.neutral100 : color.whiteHover; color.whitePressed = color.whitePressed === undefined ? color.neutral300 : color.whitePressed; /***send bubble colors***/ color.sendBubbleBackground = color.sendBubbleBackground === undefined ? color.primary : color.sendBubbleBackground; color.sendBubbleText = color.sendBubbleText === undefined ? color.staticWhite : color.sendBubbleText; color.sendBubbleTextHighlight = color.sendBubbleTextHighlight === undefined ? color.staticWhite : color.sendBubbleTextHighlight; color.sendBubbleLink = color.sendBubbleLink === undefined ? color.staticWhite : color.sendBubbleLink; color.sendBubbleTimestamp = color.sendBubbleTimestamp === undefined ? color.staticWhite : color.sendBubbleTimestamp; color.sendBubbleIcon = color.sendBubbleIcon === undefined ? color.staticWhite : color.sendBubbleIcon; /***receive bubble colors***/ color.receiveBubbleBackground = color.receiveBubbleBackground === undefined ? color.neutral300 : color.receiveBubbleBackground; color.receiveBubbleText = color.receiveBubbleText === undefined ? color.neutral900 : color.receiveBubbleText; color.receiveBubbleTextHighlight = color.receiveBubbleTextHighlight === undefined ? color.primary : color.receiveBubbleTextHighlight; color.receiveBubbleLink = color.receiveBubbleLink === undefined ? color.info : color.receiveBubbleLink; color.receiveBubbleTimestamp = color.receiveBubbleTimestamp === undefined ? color.neutral600 : color.receiveBubbleTimestamp; color.receiveBubbleIcon = color.receiveBubbleIcon === undefined ? color.primary : color.receiveBubbleIcon; return color; } private static updateExtendedColorsForLightTheme( color: Partial<CometChatTheme["color"]>, blendColorsPercentage: { [key: number]: number } ) { color.primary = color.primary ?? defaultColorLight.primary; color.extendedPrimary50 = color.extendedPrimary50 === undefined ? CometChatThemeHelper.blendColors( color.primary as string, Colors.WHITE, blendColorsPercentage[50] ) : color.extendedPrimary50; for (let i = 100; i < 900; i += 100) { // Ensure the blend percentage is defined in your blendColorsPercentage object const percentage = blendColorsPercentage[i] || 0; // Default to 0 if not defined color[`extendedPrimary${i}` as keyof typeof color] = color[`extendedPrimary${i}` as keyof typeof color] === undefined ? CometChatThemeHelper.blendColors(color.primary as string, Colors.WHITE, percentage) : color[`extendedPrimary${i}` as keyof typeof color]; color.extendedPrimary900 = color.extendedPrimary900 === undefined ? CometChatThemeHelper.blendColors( color.primary as string, Colors.BLACK, blendColorsPercentage[900] ) : color.extendedPrimary900; } return color; } private static updateExtendedColorsForDarkTheme( color: Partial<CometChatTheme["color"]>, blendColorsPercentage: { [key: number]: number } ) { color.primary = color.primary ?? defaultColorDark.primary; color.extendedPrimary50 = color.extendedPrimary50 === undefined ? CometChatThemeHelper.blendColors( color.primary as string, Colors.BLACK, blendColorsPercentage[50] ) : color.extendedPrimary50; for (let i = 100; i < 900; i += 100) { // Ensure the blend percentage is defined in your blendColorsPercentage object const percentage = blendColorsPercentage[i] || 0; // Default to 0 if not defined color[`extendedPrimary${i}` as keyof typeof color] = color[`extendedPrimary${i}` as keyof typeof color] === undefined ? CometChatThemeHelper.blendColors(color.primary as string, Colors.BLACK, percentage) : color[`extendedPrimary${i}` as keyof typeof color]; color.extendedPrimary900 = color.extendedPrimary900 === undefined ? CometChatThemeHelper.blendColors( color.primary as string, Colors.WHITE, blendColorsPercentage[900] ) : color.extendedPrimary900; } return color; } public static updateSpacing( spacing: DeepPartial<CometChatTheme["spacing"]> ): CometChatTheme["spacing"] { if (!spacing.spacing) { spacing.spacing = {} as any; } spacing.spacing!.s0 = spacing.spacing!.s0 !== undefined ? spacing.spacing?.s0 : defaultSpacing.spacing?.s0; spacing.spacing!.s1 = spacing.spacing!.s1 !== undefined ? spacing.spacing?.s1 : defaultSpacing.spacing?.s1; spacing.spacing!.s2 = spacing.spacing!.s2 !== undefined ? spacing.spacing?.s2 : defaultSpacing.spacing?.s2; spacing.spacing!.s3 = spacing.spacing!.s3 !== undefined ? spacing.spacing?.s3 : defaultSpacing.spacing?.s3; spacing.spacing!.s4 = spacing.spacing!.s4 !== undefined ? spacing.spacing?.s4 : defaultSpacing.spacing?.s4; spacing.spacing!.s5 = spacing.spacing!.s5 !== undefined ? spacing.spacing?.s5 : defaultSpacing.spacing?.s5; spacing.spacing!.s6 = spacing.spacing!.s6 !== undefined ? spacing.spacing?.s6 : defaultSpacing.spacing?.s6; spacing.spacing!.s7 = spacing.spacing!.s7 !== undefined ? spacing.spacing?.s7 : defaultSpacing.spacing?.s7; spacing.spacing!.s8 = spacing.spacing!.s8 !== undefined ? spacing.spacing?.s8 : defaultSpacing.spacing?.s8; spacing.spacing!.s9 = spacing.spacing!.s9 !== undefined ? spacing.spacing?.s9 : defaultSpacing.spacing?.s9; spacing.spacing!.s10 = spacing.spacing!.s10 !== undefined ? spacing.spacing?.s10 : defaultSpacing.spacing?.s10; spacing.spacing!.s11 = spacing.spacing!.s11 !== undefined ? spacing.spacing?.s11 : defaultSpacing.spacing?.s11; spacing.spacing!.s12 = spacing.spacing!.s12 !== undefined ? spacing.spacing?.s12 : defaultSpacing.spacing?.s12; spacing.spacing!.s13 = spacing.spacing!.s13 !== undefined ? spacing.spacing?.s13 : defaultSpacing.spacing?.s13; spacing.spacing!.s14 = spacing.spacing!.s14 !== undefined ? spacing.spacing?.s14 : defaultSpacing.spacing?.s14; spacing.spacing!.s15 = spacing.spacing!.s15 !== undefined ? spacing.spacing?.s15 : defaultSpacing.spacing?.s15; spacing.spacing!.s16 = spacing.spacing!.s16 !== undefined ? spacing.spacing?.s16 : defaultSpacing.spacing?.s16; spacing.spacing!.s17 = spacing.spacing!.s17 !== undefined ? spacing.spacing?.s17 : defaultSpacing.spacing?.s17; spacing.spacing!.s18 = spacing.spacing!.s18 !== undefined ? spacing.spacing?.s18 : defaultSpacing.spacing?.s18; spacing.spacing!.s19 = spacing.spacing!.s19 !== undefined ? spacing.spacing?.s19 : defaultSpacing.spacing?.s19; spacing.spacing!.s20 = spacing.spacing!.s20 !== undefined ? spacing.spacing?.s20 : defaultSpacing.spacing?.s20; spacing.spacing!.max = spacing.spacing!.max !== undefined ? spacing.spacing?.max : defaultSpacing.spacing?.max; if (!spacing.padding) { spacing.padding = {} as any; } if (!spacing.margin) { spacing.margin = {} as any; } if (!spacing.radius) { spacing.radius = {} as any; } /**padding**/ Object.keys(defaultSpacing.padding).forEach((key) => { const k = key as string; const paddingKey = k as keyof typeof spacing.padding; const spacingKey = k.replace("p", "s") as keyof typeof spacing.spacing; spacing.padding![paddingKey] = spacing.padding![paddingKey] === undefined ? spacing.spacing![spacingKey] : spacing.padding![paddingKey]; }); /**margin**/ Object.keys(defaultSpacing.margin).forEach((key) => { const k = key as string; const marginKey = k as keyof typeof spacing.margin; const spacingKey = k.replace("m", "s") as keyof typeof spacing.spacing; spacing.margin![marginKey] = ( spacing.margin?.[marginKey] === undefined ? spacing.spacing?.[spacingKey] : spacing.margin?.[marginKey] )!; }); /**radius**/ Object.keys(defaultSpacing.radius).forEach((key) => { const k = key as string; const radiusKey = k as keyof typeof spacing.radius; const spacingKey = k.replace("r", "s") as keyof typeof spacing.spacing; spacing.radius![radiusKey] = (spacing.radius?.[radiusKey] === undefined ? spacing.spacing?.[spacingKey] : spacing.radius?.[radiusKey])!; }); return spacing as CometChatTheme["spacing"]; } }