mirror of
https://github.com/datahub-project/datahub.git
synced 2025-10-05 14:06:40 +00:00
168 lines
4.7 KiB
TypeScript
168 lines
4.7 KiB
TypeScript
import React, { useCallback, useState } from 'react';
|
|
import styled from 'styled-components';
|
|
|
|
import { Editor } from '@app/entityV2/shared/tabs/Documentation/components/editor/Editor';
|
|
import { Button, Tooltip } from '@src/alchemy-components';
|
|
|
|
const LINE_HEIGHT = 1.5;
|
|
|
|
const ShowMoreWrapper = styled.div`
|
|
align-items: start;
|
|
justify-content: center;
|
|
display: flex;
|
|
flex-direction: column;
|
|
`;
|
|
|
|
const MarkdownContainer = styled.div<{ lineLimit?: number | null }>`
|
|
max-width: 100%;
|
|
position: relative;
|
|
flex: 1;
|
|
${(props) =>
|
|
props.lineLimit &&
|
|
props.lineLimit <= 1 &&
|
|
`
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
`}
|
|
`;
|
|
|
|
const CustomButton = styled(Button)`
|
|
padding: 8px 0px;
|
|
`;
|
|
|
|
const MarkdownViewContainer = styled.div<{ scrollableY: boolean }>`
|
|
display: block;
|
|
overflow-wrap: break-word;
|
|
word-wrap: break-word;
|
|
overflow-x: hidden;
|
|
overflow-y: ${(props) => (props.scrollableY ? 'auto' : 'hidden')};
|
|
flex: 1;
|
|
`;
|
|
|
|
const CompactEditor = styled(Editor)<{ limit: number | null; customStyle?: React.CSSProperties }>`
|
|
.remirror-theme {
|
|
max-width: 100%;
|
|
}
|
|
.remirror-editor.ProseMirror {
|
|
${({ limit }) => limit && `max-height: ${limit * LINE_HEIGHT}em;`}
|
|
h1 {
|
|
font-size: 1.4em;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 1.3em;
|
|
}
|
|
|
|
h3 {
|
|
font-size: 1.2em;
|
|
}
|
|
|
|
h4 {
|
|
font-size: 1.1em;
|
|
}
|
|
|
|
h5,
|
|
h6 {
|
|
font-size: 1em;
|
|
}
|
|
|
|
p {
|
|
${(props) => props?.customStyle?.fontSize && `font-size: ${props?.customStyle?.fontSize}`};
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
padding: 0;
|
|
}
|
|
`;
|
|
|
|
const FixedLineHeightEditor = styled(CompactEditor)<{ customStyle?: React.CSSProperties }>`
|
|
.remirror-editor.ProseMirror {
|
|
* {
|
|
line-height: ${LINE_HEIGHT};
|
|
font-size: 1em !important;
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
p {
|
|
font-size: ${(props) => (props?.customStyle?.fontSize ? props?.customStyle?.fontSize : '1em')} !important;
|
|
}
|
|
}
|
|
`;
|
|
|
|
const MoreIndicator = styled.span`
|
|
break-word: normal;
|
|
`;
|
|
|
|
export type Props = {
|
|
content: string;
|
|
lineLimit?: number | null;
|
|
fixedLineHeight?: boolean;
|
|
customStyle?: React.CSSProperties;
|
|
scrollableY?: boolean; // Whether the viewer is vertically scrollable.
|
|
handleShowMore?: () => void;
|
|
hideShowMore?: boolean;
|
|
};
|
|
|
|
export default function CompactMarkdownViewer({
|
|
content,
|
|
lineLimit = 4,
|
|
fixedLineHeight = false,
|
|
customStyle = {},
|
|
scrollableY = true,
|
|
handleShowMore,
|
|
hideShowMore,
|
|
}: Props) {
|
|
const [isShowingMore, setIsShowingMore] = useState(false);
|
|
const [isTruncated, setIsTruncated] = useState(false);
|
|
|
|
const measuredRef = useCallback((node: HTMLDivElement | null) => {
|
|
if (node !== null) {
|
|
const resizeObserver = new ResizeObserver(() => {
|
|
setIsTruncated(node.scrollHeight > node.clientHeight + 1);
|
|
});
|
|
resizeObserver.observe(node);
|
|
}
|
|
}, []);
|
|
|
|
const StyledEditor = fixedLineHeight ? FixedLineHeightEditor : CompactEditor;
|
|
|
|
return (
|
|
<MarkdownContainer lineLimit={lineLimit}>
|
|
<MarkdownViewContainer scrollableY={scrollableY} ref={measuredRef}>
|
|
<StyledEditor
|
|
customStyle={customStyle}
|
|
limit={isShowingMore ? null : lineLimit}
|
|
content={content}
|
|
readOnly
|
|
/>
|
|
</MarkdownViewContainer>
|
|
{hideShowMore && isTruncated && (
|
|
<Tooltip title={content}>
|
|
<MoreIndicator>...</MoreIndicator>
|
|
</Tooltip>
|
|
)}
|
|
|
|
{!hideShowMore &&
|
|
(isShowingMore || isTruncated) && ( // "show more" when isTruncated, "show less" when isShowingMore
|
|
<ShowMoreWrapper>
|
|
<CustomButton
|
|
variant="text"
|
|
size={lineLimit && lineLimit <= 1 ? 'sm' : undefined}
|
|
onClick={(e) => {
|
|
if (handleShowMore) {
|
|
handleShowMore();
|
|
} else {
|
|
setIsShowingMore(!isShowingMore);
|
|
}
|
|
e.stopPropagation();
|
|
}}
|
|
>
|
|
{isShowingMore ? 'show less' : 'show more'}
|
|
</CustomButton>
|
|
</ShowMoreWrapper>
|
|
)}
|
|
</MarkdownContainer>
|
|
);
|
|
}
|