This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / webapp / features / connections / components / addConnectionDrawer / SourceCardPreview.tsx
2.4 kB 93 lines
1'use client'; 2 3import { 4 Anchor, 5 Card, 6 CloseButton, 7 Group, 8 Image, 9 Skeleton, 10 Stack, 11 Text, 12 Tooltip, 13} from '@mantine/core'; 14import { useQuery } from '@tanstack/react-query'; 15import { createSembleClient } from '@/services/client.apiClient'; 16import { getDomain } from '@/lib/utils/link'; 17 18function SourceCardPreviewSkeleton() { 19 return ( 20 <Card withBorder component="article" p={'xs'} radius={'lg'}> 21 <Group gap="xs" wrap="nowrap"> 22 <Skeleton width={45} height={45} radius={'md'} /> 23 <Stack gap={0} style={{ flex: 1 }}> 24 <Skeleton height={21.5} width="80%" radius="sm" /> 25 <Skeleton height={18.5} width="60%" radius="sm" mt={4} /> 26 </Stack> 27 </Group> 28 </Card> 29 ); 30} 31 32interface Props { 33 sourceUrl: string; 34 onRemove?: () => void; 35} 36 37export default function SourceCardPreview(props: Props) { 38 const { data, isLoading: isLoadingMetadata } = useQuery({ 39 queryKey: ['url metadata', props.sourceUrl], 40 queryFn: async () => { 41 const client = createSembleClient(); 42 return client.getUrlMetadata({ url: props.sourceUrl }); 43 }, 44 enabled: !!props.sourceUrl, 45 }); 46 47 if (isLoadingMetadata) { 48 return <SourceCardPreviewSkeleton />; 49 } 50 51 return ( 52 <Card withBorder component="article" p={'xs'} radius={'lg'}> 53 <Group gap="xs" wrap="nowrap"> 54 {data?.metadata?.imageUrl && ( 55 <Image 56 src={data.metadata.imageUrl} 57 alt={`${data.metadata.title} social preview image`} 58 radius={'md'} 59 w={45} 60 h={45} 61 style={{ flexShrink: 0 }} 62 /> 63 )} 64 <Stack gap={0} style={{ flex: 1, minWidth: 0 }}> 65 <Text fw={500} lineClamp={1} c={'bright'}> 66 {data?.metadata?.title || props.sourceUrl} 67 </Text> 68 <Tooltip label={props.sourceUrl}> 69 <Anchor 70 href={props.sourceUrl} 71 target="_blank" 72 c={'gray'} 73 fz={'sm'} 74 lineClamp={1} 75 w="fit-content" 76 onClick={(e) => e.stopPropagation()} 77 > 78 {getDomain(props.sourceUrl)} 79 </Anchor> 80 </Tooltip> 81 </Stack> 82 {props.onRemove && ( 83 <CloseButton 84 radius="xl" 85 size="md" 86 onClick={props.onRemove} 87 aria-label="Remove URL" 88 /> 89 )} 90 </Group> 91 </Card> 92 ); 93}