import { useState, useEffect, useRef, useEffectEvent } from 'react' import { Box, Button, Link, Typography } from '@mui/material' import type { WidgetNoteProps } from './types' import { styles } from './style' import ReactMarkdown, { type Components } from 'react-markdown' const DEFAULT_LABELS = { showMore: 'Show More', showLess: 'Show Less', } as const const DEFAULT_P = ({ children }: { children?: React.ReactNode }) => ( {children} ) const COMPONENTS: Components = { h1: DEFAULT_P, h2: DEFAULT_P, h3: DEFAULT_P, p: DEFAULT_P, a: ({ children, href, target = '_blank', rel = 'noopener noreferrer' }) => ( {children} ), img: () => null, ul: DEFAULT_P, ol: DEFAULT_P, li: DEFAULT_P, } /** * Displays text content with markdown support and automatic show more/less functionality for long content. Automatically detects content exceeding 3 lines and shows an expand/collapse button. * * @example * ```tsx * * {"**Important:** This data is from Q4 2024."} * * ``` */ export function WidgetNote({ children, labels = DEFAULT_LABELS, }: WidgetNoteProps) { const [isExpanded, setIsExpanded] = useState(false) const [shouldShowToggle, setShouldShowToggle] = useState(false) const contentRef = useRef(null) const checkOverflow = useEffectEvent(() => { if (contentRef.current) { // Check if content overflows 3 lines const isOverflowing = contentRef.current.scrollHeight > contentRef.current.clientHeight setShouldShowToggle(isOverflowing) } }) useEffect(() => { checkOverflow() }, [children]) useEffect(() => { const element = contentRef.current if (!element) return const resizeObserver = new ResizeObserver(() => { checkOverflow() }) resizeObserver.observe(element) return () => { resizeObserver.disconnect() } }, []) if (!children) { return null } const handleToggle = () => { setIsExpanded(!isExpanded) } const mergedLabels = { ...DEFAULT_LABELS, ...labels } return ( {children} {(shouldShowToggle || isExpanded) && ( )} ) }