/** * Inspired from fumadocs docsite * @from https://github.com/fuma-nama/fumadocs/blob/5723bbe58ef805a5421a780abf235a10b251be2f/apps/docs/app/docs/%5B...slug%5D/page.client.tsx#L11 * @license MIT */ import { useI18n } from '@rspress/core/runtime'; import { copyToClipboard, IconCopy, IconSuccess, SvgWrapper, } from '@rspress/core/theme'; import { useCallback, useRef, useState } from 'react'; import './index.scss'; import './LlmsCopyButton.scss'; import { useMdUrl } from './useMdUrl'; export interface LlmsCopyButtonProps extends React.ButtonHTMLAttributes { /** * Text by language, used with `useLang`. * @default en: 'Copy Markdown', zh: '\u590d\u5236 Markdown' */ textByLang?: Record; /** * Priority is higher than textByLang * @default '' */ text?: string; /** * Overrides the default click handler. * If provided, the default copy to clipboard functionality will not be executed. */ onClick?: React.MouseEventHandler; } const cache = new Map(); export function LlmsCopyButton(props: LlmsCopyButtonProps) { const { onClick, ...otherProps } = props; const t = useI18n(); const { pathname } = useMdUrl(); const [isLoading, setLoading] = useState(false); const [isFinished, setFinished] = useState(false); const timer = useRef(null); const handleClick = useCallback(async () => { setLoading(true); const url = pathname; try { const content: string = cache.get(url) ?? (await fetch(url).then(res => res.text())); cache.set(url, content); const isCopied = await copyToClipboard(content); if (!isCopied) { return; } setFinished(true); if (timer.current) { clearTimeout(timer.current); timer.current = null; } timer.current = window.setTimeout(() => { setFinished(false); timer.current = null; }, 500); } finally { setLoading(false); } }, [pathname]); if (!pathname) { return <>; } return ( ); }