markdown update

This commit is contained in:
Nate Kelley 2025-03-10 12:30:26 -06:00
parent 9819ea57fa
commit 5d211e8848
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 69 additions and 64 deletions

View File

@ -1,5 +1,9 @@
import type { Meta, StoryObj } from '@storybook/react';
import { AppMarkdown } from './AppMarkdown';
import { Button } from '@/components/ui/buttons';
import { useState } from 'react';
import { Checkbox } from '../../checkbox';
import { Switch } from '../../switch/Switch';
const meta: Meta<typeof AppMarkdown> = {
title: 'UI/Typography/AppMarkdown',
@ -215,9 +219,42 @@ export const WithCustomClass: Story = {
}
};
export const WithLoader: Story = {
args: {
markdown: '# Loading Example\n\nThis example shows the loader state.',
showLoader: true
}
const randomMarkdownContent = [
'# New Section\n\nThis is a new section with some content.',
'## Subheading\n\nHere is a paragraph with **bold** and *italic* text.',
'### Smaller Heading\n\n- List item 1\n- List item 2\n- List item 3',
'#### Tiny Heading\n\n> This is a blockquote with some important information.',
'##### Micro Heading\n\n1. Numbered item 1\n2. Numbered item 2',
'###### Nano Heading\n\n`code example` and more text here.',
'## Table Example\n\n| Header 1 | Header 2 |\n|----------|----------|\n| Cell 1 | Cell 2 |',
'### Mixed Content\n\nHere is some text with [a link](https://example.com) and `inline code`.'
];
const InteractiveMarkdown = () => {
const [markdown, setMarkdown] = useState(
'# Interactive Markdown\n\nClick the button to add more content!'
);
const [stripFormatting, setStripFormatting] = useState(false);
const addRandomContent = () => {
const randomContent =
randomMarkdownContent[Math.floor(Math.random() * randomMarkdownContent.length)];
setMarkdown((prev) => `${prev}\n\n${randomContent}`);
};
return (
<div className="space-y-4">
<Button onClick={addRandomContent}>Add Random Content</Button>
<div className="flex items-center gap-2">
<span>Strip Formatting</span>
<Switch checked={stripFormatting} onCheckedChange={setStripFormatting}></Switch>
</div>
<AppMarkdown markdown={markdown} showLoader stripFormatting={stripFormatting} />
</div>
);
};
export const WithLoader: Story = {
render: () => <InteractiveMarkdown />
};

View File

@ -1,44 +1,13 @@
import React from 'react';
import { ExtraProps } from 'react-markdown';
import { AppCodeBlock } from '../AppCodeBlock/AppCodeBlock';
import { TextDotLoader } from '@/components/ui/loaders';
import { cva } from 'class-variance-authority';
type Element = any; //TODO fix this after migration
export const commonStreamingCheck = (
endLine?: number,
startLine?: number,
lastTrackedLine?: number
): boolean => {
const isLineNumber = typeof endLine === 'number' && typeof lastTrackedLine === 'number';
return isLineNumber && endLine === lastTrackedLine && startLine === lastTrackedLine;
};
import { cn } from '@/lib/classMerge';
export interface ExtraPropsExtra extends ExtraProps {
numberOfLineMarkdown: number;
}
export const CommonPulseLoader: React.FC<{
showLoader: boolean;
numberOfLineMarkdown: number;
node?: Element;
}> = ({ showLoader, numberOfLineMarkdown, node }) => {
const showStreamingLoader =
node &&
showLoader &&
commonStreamingCheck(
node?.position?.end.line,
node?.position?.start.line,
numberOfLineMarkdown
);
if (showStreamingLoader) {
return <TextDotLoader />;
}
return null;
};
export const CustomCode: React.FC<
{
children?: React.ReactNode;
@ -68,12 +37,11 @@ export const CustomParagraph: React.FC<
markdown: string;
showLoader: boolean;
} & ExtraPropsExtra
> = ({ children, markdown, ...rest }) => {
> = ({ children, markdown, showLoader, ...rest }) => {
if (Array.isArray(children)) {
return (
<p className="leading-1.3">
<p className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>
{children}
<CommonPulseLoader {...rest} />
</p>
);
}
@ -85,10 +53,7 @@ export const CustomParagraph: React.FC<
}
return (
<p className="leading-1.3">
{children}
<CommonPulseLoader {...rest} />
</p>
<p className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>{children}</p>
);
};
@ -105,6 +70,7 @@ const headingVariants = cva('leading-1.3 my-2', {
}
}
});
export const CustomHeading: React.FC<
{
level: 1 | 2 | 3 | 4 | 5 | 6;
@ -114,13 +80,15 @@ export const CustomHeading: React.FC<
numberOfLineMarkdown: number;
stripFormatting?: boolean;
} & ExtraPropsExtra
> = ({ level, children, markdown, stripFormatting = false, ...rest }) => {
> = ({ level, children, markdown, stripFormatting = false, showLoader, ...rest }) => {
const HeadingTag = `h${level}` as any;
console.log('heading', HeadingTag, level, children);
return (
<HeadingTag className={headingVariants({ level: stripFormatting ? 'base' : level })}>
<HeadingTag
className={cn(
headingVariants({ level: stripFormatting ? 'base' : level }),
showLoader && 'animate-in fade-in duration-700'
)}>
{children}
<CommonPulseLoader {...rest} />
</HeadingTag>
);
};
@ -132,12 +100,11 @@ export const CustomList: React.FC<
markdown: string;
showLoader: boolean;
} & ExtraPropsExtra
> = ({ ordered, children, markdown, ...rest }) => {
> = ({ ordered, children, markdown, showLoader, ...rest }) => {
const ListTag = ordered ? 'ol' : 'ul';
return (
<ListTag className="leading-1.3">
<ListTag className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>
{children}
<CommonPulseLoader {...rest} />
</ListTag>
);
};
@ -148,11 +115,10 @@ export const CustomListItem: React.FC<
markdown: string;
showLoader: boolean;
} & ExtraPropsExtra
> = ({ children, markdown, ...rest }) => {
> = ({ children, markdown, showLoader, ...rest }) => {
return (
<li className="leading-1.3">
<li className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>
{children}
<CommonPulseLoader {...rest} />
</li>
);
};
@ -163,11 +129,10 @@ export const CustomBlockquote: React.FC<
markdown: string;
showLoader: boolean;
} & ExtraPropsExtra
> = ({ children, markdown, ...rest }) => {
> = ({ children, markdown, showLoader, ...rest }) => {
return (
<blockquote className="leading-1.3">
<blockquote className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>
{children}
<CommonPulseLoader {...rest} />
</blockquote>
);
};
@ -178,11 +143,10 @@ export const CustomTable: React.FC<
markdown: string;
showLoader: boolean;
} & ExtraPropsExtra
> = ({ children, markdown, ...rest }) => {
> = ({ children, markdown, showLoader, ...rest }) => {
return (
<table className="leading-1.3">
<table className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>
{children}
<CommonPulseLoader {...rest} />
</table>
);
};
@ -193,6 +157,10 @@ export const CustomSpan: React.FC<
markdown: string;
showLoader: boolean;
} & ExtraPropsExtra
> = ({ children, markdown, ...rest }) => {
return <span className="leading-1.3">{children}</span>;
> = ({ children, markdown, showLoader, ...rest }) => {
return (
<span className={cn('leading-1.3', showLoader && 'animate-in fade-in duration-700')}>
{children}
</span>
);
};

View File

@ -1,8 +1,8 @@
import React from 'react';
import { StreamingMessage_Text } from '@/components/ui/streaming/StreamingMessage_Text';
import { ReasoningMessageProps } from '../ReasoningMessageSelector';
import { type BusterChatMessageReasoning_text } from '@/api/asset_interfaces/chat';
import { useMessageIndividual } from '@/context/Chats';
import { AppMarkdown } from '@/components/ui/typography/AppMarkdown';
export const ReasoningMessage_Text: React.FC<ReasoningMessageProps> = React.memo(
({ reasoningMessageId, messageId, isCompletedStream }) => {
@ -11,7 +11,7 @@ export const ReasoningMessage_Text: React.FC<ReasoningMessageProps> = React.memo
(x) => (x?.reasoning_messages[reasoningMessageId] as BusterChatMessageReasoning_text)?.message
)!;
return <StreamingMessage_Text isCompletedStream={isCompletedStream} message={message ?? ''} />;
return <AppMarkdown markdown={message} showLoader={!isCompletedStream} />;
}
);