import { useMemo } from "react"; import { Markdown, type CustomRenderers, type NodeStyleOverrides, type PartialMarkdownTheme, } from "react-native-nitro-markdown"; import { Linking, ScrollView, Text as NativeText, View } from "react-native"; import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; import { useThemeColor } from "../../lib/useThemeColor"; import { hasNativeSelectableMarkdownText, SelectableMarkdownText, type NativeMarkdownTextStyle, } from "../../native/SelectableMarkdownText"; interface MarkdownPreviewStyles { readonly theme: PartialMarkdownTheme; readonly styles: NodeStyleOverrides; readonly renderers: CustomRenderers; readonly nativeTextStyle: NativeMarkdownTextStyle; } function useMarkdownPreviewStyles(): MarkdownPreviewStyles { const body = String(useThemeColor("--color-md-body")); const strong = String(useThemeColor("--color-md-strong")); const link = String(useThemeColor("--color-md-link")); const blockquoteBorder = String(useThemeColor("--color-md-blockquote-border")); const blockquoteBackground = String(useThemeColor("--color-md-blockquote-bg")); const codeBackground = String(useThemeColor("--color-md-code-bg")); const codeText = String(useThemeColor("--color-md-code-text")); const horizontalRule = String(useThemeColor("--color-md-hr")); return useMemo(() => { const renderers: CustomRenderers = { link: ({ href, children }) => ( { if (href) { void Linking.openURL(href); } }} style={{ color: link, fontFamily: "DMSans_500Medium", textDecorationLine: "none", }} > {children} ), }; return { theme: { colors: { text: body, heading: strong, link, blockquote: blockquoteBorder, border: horizontalRule, surfaceLight: blockquoteBackground, accent: link, tableBorder: horizontalRule, tableHeader: blockquoteBackground, tableHeaderText: strong, code: codeText, codeBackground, }, }, styles: { text: { color: body, fontFamily: "DMSans_400Regular", ...MOBILE_TYPOGRAPHY.body, }, heading: { color: strong, fontFamily: "DMSans_700Bold", }, strong: { color: strong, fontFamily: "DMSans_700Bold", }, link: { color: link, fontFamily: "DMSans_500Medium", }, blockquote: { backgroundColor: blockquoteBackground, borderLeftColor: blockquoteBorder, borderLeftWidth: 3, paddingLeft: 12, }, code: { backgroundColor: codeBackground, color: codeText, fontFamily: "ui-monospace", }, codeBlock: { backgroundColor: codeBackground, borderRadius: 12, color: codeText, fontFamily: "ui-monospace", padding: 12, }, hr: { backgroundColor: horizontalRule, }, }, renderers, nativeTextStyle: { color: body, strongColor: strong, mutedColor: body, linkColor: link, inlineCodeColor: codeText, codeColor: codeText, codeBackgroundColor: codeBackground, codeBlockBackgroundColor: codeBackground, fileTextColor: codeText, skillTextColor: codeText, quoteMarkerColor: blockquoteBorder, dividerColor: horizontalRule, ...MOBILE_TYPOGRAPHY.body, fontFamily: "DMSans_400Regular", headingFontFamily: "DMSans_700Bold", boldFontFamily: "DMSans_700Bold", }, }; }, [ blockquoteBackground, blockquoteBorder, body, codeBackground, codeText, horizontalRule, link, strong, ]); } export function FileMarkdownPreview(props: { readonly markdown: string }) { const styles = useMarkdownPreviewStyles(); return ( {hasNativeSelectableMarkdownText() ? ( ) : ( {props.markdown} )} ); }