This repository has no description
2.2 kB
82 lines
1'use client';
2
3import { RichText } from '@atproto/api';
4import Link from 'next/link';
5import { Anchor, AnchorProps, Text, TextProps } from '@mantine/core';
6import { getDomain } from '@/lib/utils/link';
7
8interface Props {
9 text: string;
10 linkProps?: Partial<AnchorProps>;
11 textProps?: Partial<TextProps>;
12}
13
14export default function RichTextRenderer({
15 text,
16 linkProps = {},
17 textProps = {},
18}: Props) {
19 const richText = new RichText({ text });
20 richText.detectFacetsWithoutResolution();
21
22 return (
23 <Text span {...textProps}>
24 {Array.from(richText.segments()).map((segment, i) => {
25 // Mentions
26 if (segment.isMention()) {
27 return (
28 <Anchor
29 key={`mention-${i}`}
30 href={`/profile/${segment.text.slice(1)}`}
31 c={linkProps.c || 'blue'}
32 fw={linkProps.fw || 500}
33 onClick={(e) => e.stopPropagation()}
34 {...linkProps}
35 >
36 {segment.text}
37 </Anchor>
38 );
39 }
40
41 // Links
42 if (segment.isLink() && segment.link?.uri) {
43 return (
44 <Anchor
45 key={`link-${i}`}
46 href={segment.link.uri}
47 c={linkProps.c || 'blue'}
48 fw={linkProps.fw || 500}
49 target="_blank"
50 onClick={(e) => e.stopPropagation()}
51 {...linkProps}
52 >
53 {getDomain(segment.link.uri)}
54 </Anchor>
55 );
56 }
57
58 // Hashtags
59 if (segment.isTag()) {
60 const encodedTag = encodeURIComponent(segment.tag?.tag || '');
61 return (
62 <Anchor
63 key={`tag-${i}`}
64 component={Link}
65 c={linkProps.c || 'blue'}
66 fw={linkProps.fw || 500}
67 href={`https://bsky.app/hashtag/${encodedTag}`}
68 target="_blank"
69 onClick={(e) => e.stopPropagation()}
70 {...linkProps}
71 >
72 {segment.text}
73 </Anchor>
74 );
75 }
76
77 // Plain text
78 return <span key={`text-${i}`}>{segment.text}</span>;
79 })}
80 </Text>
81 );
82}