'use client';
import { useState, type ComponentProps } from 'react';
import { useTranslations } from 'next-intl';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { PencilSimple } from '@phosphor-icons/react';
import { sanitize } from '@/lib/sanitize';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { ProfileEditDialog } from '@/components/profile-edit-dialog';
import { useProfileEdit } from '@/components/profile-edit-provider';
const COLLAPSE_THRESHOLD = 300;
interface AboutSectionProps {
about: string;
isOwnProfile?: boolean;
}
/** Open links in new tab with safe rel attributes. */
function MarkdownLink(props: ComponentProps<'a'>) {
// eslint-disable-next-line jsx-a11y/anchor-has-content -- children are passed via spread props from react-markdown
return ;
}
export function AboutSection({ about, isOwnProfile }: AboutSectionProps) {
const t = useTranslations('profile');
const [expanded, setExpanded] = useState(false);
const [editing, setEditing] = useState(false);
const { profile } = useProfileEdit();
if (!about && !isOwnProfile) return null;
if (!about && isOwnProfile) {
return (
{t('addAbout')}
{editing && (
setEditing(false)}
/>
)}
);
}
// Strip any raw HTML from the source before markdown rendering
const cleaned = sanitize(about);
const isLong = cleaned.length > COLLAPSE_THRESHOLD;
return (
{cleaned}
{isOwnProfile && (
)}
{isLong && (
)}
{editing && (
setEditing(false)}
/>
)}
);
}