mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
Add 'scrollable' prop to Markdown component for better control over scrolling behavior (#964)
The scrollable prop controls if ScrollbarOverlay is added to the Markdown component.
This commit is contained in:
parent
f1fe401dbe
commit
28ca193c19
@ -7,6 +7,7 @@
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -17,6 +18,10 @@
|
||||
font-size: 14px;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
&.non-scrollable {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.heading {
|
||||
&:first-of-type {
|
||||
margin-top: 0 !important;
|
||||
|
@ -178,9 +178,19 @@ type MarkdownProps = {
|
||||
className?: string;
|
||||
onClickExecute?: (cmd: string) => void;
|
||||
resolveOpts?: MarkdownResolveOpts;
|
||||
scrollable?: boolean;
|
||||
};
|
||||
|
||||
const Markdown = ({ text, textAtom, showTocAtom, style, className, resolveOpts, onClickExecute }: MarkdownProps) => {
|
||||
const Markdown = ({
|
||||
text,
|
||||
textAtom,
|
||||
showTocAtom,
|
||||
style,
|
||||
className,
|
||||
resolveOpts,
|
||||
scrollable = true,
|
||||
onClickExecute,
|
||||
}: MarkdownProps) => {
|
||||
const textAtomValue = useAtomValueSafe(textAtom);
|
||||
const tocRef = useRef<TocItem[]>([]);
|
||||
const showToc = useAtomValueSafe(showTocAtom) ?? false;
|
||||
@ -240,8 +250,8 @@ const Markdown = ({ text, textAtom, showTocAtom, style, className, resolveOpts,
|
||||
|
||||
text = textAtomValue ?? text;
|
||||
|
||||
const ScrollableMarkdown = () => {
|
||||
return (
|
||||
<div className={clsx("markdown", className)} style={style}>
|
||||
<OverlayScrollbarsComponent
|
||||
ref={contentsOsRef}
|
||||
className="content"
|
||||
@ -274,6 +284,45 @@ const Markdown = ({ text, textAtom, showTocAtom, style, className, resolveOpts,
|
||||
{text}
|
||||
</ReactMarkdown>
|
||||
</OverlayScrollbarsComponent>
|
||||
);
|
||||
};
|
||||
|
||||
const NonScrollableMarkdown = () => {
|
||||
return (
|
||||
<div className="content non-scrollable">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, [RemarkFlexibleToc, { tocRef: tocRef.current }]]}
|
||||
rehypePlugins={[
|
||||
rehypeRaw,
|
||||
rehypeHighlight,
|
||||
() =>
|
||||
rehypeSanitize({
|
||||
...defaultSchema,
|
||||
attributes: {
|
||||
...defaultSchema.attributes,
|
||||
span: [
|
||||
...(defaultSchema.attributes?.span || []),
|
||||
// Allow all class names starting with `hljs-`.
|
||||
["className", /^hljs-./],
|
||||
// Alternatively, to allow only certain class names:
|
||||
// ['className', 'hljs-number', 'hljs-title', 'hljs-variable']
|
||||
],
|
||||
},
|
||||
tagNames: [...(defaultSchema.tagNames || []), "span"],
|
||||
}),
|
||||
() => rehypeSlug({ prefix: idPrefix }),
|
||||
]}
|
||||
components={markdownComponents}
|
||||
>
|
||||
{text}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx("markdown", className)} style={style}>
|
||||
{scrollable ? <ScrollableMarkdown /> : <NonScrollableMarkdown />}
|
||||
{toc && (
|
||||
<OverlayScrollbarsComponent className="toc" options={{ scrollbars: { autoHide: "leave" } }}>
|
||||
<div className="toc-inner">
|
||||
|
@ -14,7 +14,6 @@ import { atom, Atom, PrimitiveAtom, useAtomValue, useSetAtom, WritableAtom } fro
|
||||
import type { OverlayScrollbars } from "overlayscrollbars";
|
||||
import { OverlayScrollbarsComponent, OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
|
||||
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
||||
import tinycolor from "tinycolor2";
|
||||
import "./waveai.less";
|
||||
|
||||
interface ChatMessageType {
|
||||
@ -263,11 +262,8 @@ function makeWaveAiViewModel(blockId): WaveAiModel {
|
||||
|
||||
const ChatItem = ({ chatItem }: ChatItemProps) => {
|
||||
const { isAssistant, text, isError } = chatItem;
|
||||
const senderClassName = isAssistant ? "chat-msg-assistant" : "chat-msg-user";
|
||||
const msgClassName = `chat-msg ${senderClassName}`;
|
||||
const cssVar = "--panel-bg-color";
|
||||
const panelBgColor = getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim();
|
||||
const color = tinycolor(panelBgColor);
|
||||
|
||||
const renderError = (err: string): React.JSX.Element => <div className="chat-msg-error">{err}</div>;
|
||||
|
||||
@ -284,7 +280,7 @@ const ChatItem = ({ chatItem }: ChatItemProps) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-msg chat-msg-assistant">
|
||||
<Markdown text={text} />
|
||||
<Markdown text={text} scrollable={false} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
@ -299,7 +295,7 @@ const ChatItem = ({ chatItem }: ChatItemProps) => {
|
||||
return (
|
||||
<>
|
||||
<div className="chat-msg chat-msg-user">
|
||||
<Markdown className="msg-text" text={text} />
|
||||
<Markdown className="msg-text" text={text} scrollable={false} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user