import { FontMetrics, precomputeValues } from "@capsizecss/core"; import { ThemeConfig } from "design-system/tools/createTheme"; import { PixelRatio, StyleProp, StyleSheet, TextStyle } from "react-native"; import { FontSizes, FontType, FontWeights } from "./types"; const capsize = (options: Parameters[0]) => { const values = precomputeValues(options); const fontSize = parseFloat(values.fontSize); const baselineTrimEm = parseFloat(values.baselineTrim); const capHeightTrimEm = parseFloat(values.capHeightTrim); const fontScale = PixelRatio.getFontScale(); return { fontSize, lineHeight: values.lineHeight !== "normal" ? parseFloat(values.lineHeight) : undefined, marginBottom: baselineTrimEm * fontSize * fontScale, marginTop: capHeightTrimEm * fontSize * fontScale, } as const; }; export const createTextSize = ({ fontMetrics, fontSize, lineHeight: leading, marginCorrection = 0, }: { fontMetrics: FontMetrics; fontSize: number; lineHeight: number | undefined; marginCorrection?: number; }) => { const sizes = capsize({ fontMetrics, fontSize, leading }); return { ...sizes, marginTop: PixelRatio.roundToNearestPixel(sizes.marginTop + marginCorrection), marginBottom: PixelRatio.roundToNearestPixel(sizes.marginBottom - marginCorrection), paddingVertical: marginCorrection, } as const; }; type GetFontStyles = { italic?: boolean; size: FontSizes; weight: FontWeights; type: FontType; config: ThemeConfig; style: StyleProp; }; export function getFontStyles({ weight, type, size, italic, config, style }: GetFontStyles) { const fontConfig = config.typography.fontConfig; const styles = StyleSheet.flatten(style); // @ts-ignore const fontFamily = italic ? fontConfig?.[type]?.[weight]?.italic : fontConfig?.[type]?.[weight]?.normal; const marginCorrection = fontConfig?.[type]?.[weight]?.marginCorrection; if (!fontFamily) { throw new Error(`${italic ? "italic" : ""} Font type "${type}" of weight "${weight} does not exist`); } // Adjust the top and bottom margins of the text blocks using Capsize const metrics = config.typography.fontMetrics[type]; if (metrics) { const Fontsizes = createTextSize({ fontMetrics: metrics, fontSize: styles?.fontSize ?? config.typography?.sizes?.[size].fontSize, lineHeight: styles?.lineHeight ?? config.typography?.sizes?.[size].lineHeight, marginCorrection, }); return { fontFamily, ...Fontsizes }; } const sizes = config.typography.sizes[size]; return { fontFamily, ...sizes }; } export function getTextDecoration({ underline, strikeThrough, }: { strikeThrough?: boolean; underline?: boolean; }) { let textDecorationLine = "none" as TextStyle["textDecorationLine"]; if (underline && strikeThrough) { textDecorationLine = "underline line-through"; } else if (underline) { textDecorationLine = "underline"; } else if (strikeThrough) { textDecorationLine = "line-through"; } return textDecorationLine; }