import * as React from 'react'; import { Col, ConfigProvider, Flex, Row, Tag, theme, Typography } from 'antd'; export interface SemanticPreviewProps { semantics: { name: string; desc: string; version?: string }[]; children: React.ReactElement; height?: number; } const SemanticPreview = (props: SemanticPreviewProps) => { const { semantics = [], children, height } = props; const { token } = theme.useToken(); // ======================= Semantic ======================= const getMarkClassName = React.useCallback( (semanticKey: string) => `semantic-mark-${semanticKey}`, [], ); const semanticClassNames = React.useMemo(() => { const classNames: Record = {}; semantics.forEach((semantic) => { classNames[semantic.name] = getMarkClassName(semantic.name); }); return classNames; }, [semantics]); const cloneNode = React.cloneElement(children, { classNames: semanticClassNames, }); // ======================== Hover ========================= const MARK_BORDER_SIZE = 2; const containerRef = React.useRef(null); const [positionMotion, setPositionMotion] = React.useState(false); const [hoverSemantic, setHoverSemantic] = React.useState(null); const [markPos, setMarkPos] = React.useState< [left: number, top: number, width: number, height: number] >([0, 0, 0, 0]); React.useEffect(() => { if (hoverSemantic) { const targetClassName = getMarkClassName(hoverSemantic); const targetElement = containerRef.current?.querySelector(`.${targetClassName}`); const containerRect = containerRef.current?.getBoundingClientRect(); const targetRect = targetElement?.getBoundingClientRect(); setMarkPos([ (targetRect?.left || 0) - (containerRect?.left || 0), (targetRect?.top || 0) - (containerRect?.top || 0), targetRect?.width || 0, targetRect?.height || 0, ]); setTimeout(() => { setPositionMotion(true); }, 10); } else { const timeout = setTimeout(() => { setPositionMotion(false); }, 500); return () => { clearTimeout(timeout); }; } }, [hoverSemantic]); // ======================== Render ======================== return (
{cloneNode}
    {semantics.map((semantic, index) => (
  • { setHoverSemantic(semantic.name); }} onMouseLeave={() => { setHoverSemantic(null); }} > {semantic.name} {semantic.version && {semantic.version}} {semantic.desc} {' '}
  • ))}
); }; export default SemanticPreview;