mirror of https://github.com/buster-so/buster.git
Add a loading indactor that is stylized
This commit is contained in:
parent
fbc0e94281
commit
8cd289ea59
|
@ -28,7 +28,6 @@ const editorVariants = cva(
|
||||||
true: 'ring-2 ring-ring ring-offset-2'
|
true: 'ring-2 ring-ring ring-offset-2'
|
||||||
},
|
},
|
||||||
variant: {
|
variant: {
|
||||||
ai: 'w-full px-0 text-base md:text-sm',
|
|
||||||
comment: cn('rounded-none border-none bg-transparent text-sm'),
|
comment: cn('rounded-none border-none bg-transparent text-sm'),
|
||||||
default: 'size-full px-16 pt-4 pb-72 text-base sm:px-[max(64px,calc(50%-350px))]',
|
default: 'size-full px-16 pt-4 pb-72 text-base sm:px-[max(64px,calc(50%-350px))]',
|
||||||
fullWidth: 'size-full px-16 pt-4 pb-72 text-base sm:px-24',
|
fullWidth: 'size-full px-16 pt-4 pb-72 text-base sm:px-24',
|
||||||
|
@ -41,7 +40,7 @@ const editorVariants = cva(
|
||||||
export type EditorProps = PlateContentProps & VariantProps<typeof editorVariants>;
|
export type EditorProps = PlateContentProps & VariantProps<typeof editorVariants>;
|
||||||
|
|
||||||
export const Editor = React.forwardRef<HTMLDivElement, EditorProps>(
|
export const Editor = React.forwardRef<HTMLDivElement, EditorProps>(
|
||||||
({ className, disabled, focused, variant, ...props }, ref) => {
|
({ className, disabled, focused, variant, children, ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<PlateContent
|
<PlateContent
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
|
@ -31,6 +31,7 @@ interface ReportEditorProps {
|
||||||
id?: string;
|
id?: string;
|
||||||
mode?: 'export' | 'default';
|
mode?: 'export' | 'default';
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
postEditorChildren?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IReportEditor = TPlateEditor<Value, AnyPluginConfig>;
|
export type IReportEditor = TPlateEditor<Value, AnyPluginConfig>;
|
||||||
|
@ -60,16 +61,14 @@ export const ReportEditor = React.memo(
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
isStreaming = false,
|
isStreaming = false,
|
||||||
children
|
children,
|
||||||
|
postEditorChildren
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
// Initialize the editor instance using the custom useEditor hook
|
// Initialize the editor instance using the custom useEditor hook
|
||||||
const isReady = useRef(false);
|
const isReady = useRef(false);
|
||||||
|
|
||||||
// readOnly = true;
|
|
||||||
// isStreaming = true;
|
|
||||||
|
|
||||||
const editor = useReportEditor({
|
const editor = useReportEditor({
|
||||||
isStreaming,
|
isStreaming,
|
||||||
mode,
|
mode,
|
||||||
|
@ -132,7 +131,7 @@ export const ReportEditor = React.memo(
|
||||||
variant={variant}
|
variant={variant}
|
||||||
readonly={readOnly}
|
readonly={readOnly}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={cn('editor-container overflow-auto', containerClassName)}>
|
className={cn('editor-container relative overflow-auto', containerClassName)}>
|
||||||
{children}
|
{children}
|
||||||
<ThemeWrapper id={id}>
|
<ThemeWrapper id={id}>
|
||||||
<Editor
|
<Editor
|
||||||
|
@ -142,12 +141,8 @@ export const ReportEditor = React.memo(
|
||||||
className={cn('editor', className)}
|
className={cn('editor', className)}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{isStreaming && (
|
|
||||||
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center gap-1.5 bg-background/80 backdrop-blur-sm px-3 py-2 rounded-md border border-border/50 shadow-sm">
|
|
||||||
<ShimmerText text="Generating content..." className="text-sm" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ThemeWrapper>
|
</ThemeWrapper>
|
||||||
|
{postEditorChildren}
|
||||||
</EditorContainer>
|
</EditorContainer>
|
||||||
</Plate>
|
</Plate>
|
||||||
);
|
);
|
||||||
|
|
|
@ -46,18 +46,11 @@ const EDITOR_THEME = { ...CSS_VARIABLES_THEME, ...THEME_RESET_STYLE };
|
||||||
|
|
||||||
export function ThemeWrapper({ children, className, defaultTheme, id }: ThemeWrapperProps) {
|
export function ThemeWrapper({ children, className, defaultTheme, id }: ThemeWrapperProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
<div
|
id={id}
|
||||||
id={id}
|
style={EDITOR_THEME}
|
||||||
style={EDITOR_THEME}
|
className={cn('themes-wrapper w-full bg-transparent antialiased', className)}>
|
||||||
className={cn(
|
{children}
|
||||||
'themes-wrapper h-full w-full overflow-visible bg-transparent antialiased',
|
</div>
|
||||||
className
|
|
||||||
)}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* <ThemesStyle /> */}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { queryKeys } from '@/api/query_keys';
|
||||||
|
import { ShimmerText } from '@/components/ui/typography/ShimmerText';
|
||||||
|
import { cn } from '@/lib/classMerge';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
export const GeneratingContent = ({
|
||||||
|
messageId,
|
||||||
|
className
|
||||||
|
}: {
|
||||||
|
messageId: string;
|
||||||
|
className?: string;
|
||||||
|
}) => {
|
||||||
|
const { data: text } = useQuery({
|
||||||
|
...queryKeys.chatsBlackBoxMessages(messageId),
|
||||||
|
notifyOnChangeProps: ['data'],
|
||||||
|
select: (data) => data
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn('right-0 bottom-0 left-0 -mt-68 flex items-center justify-center', className)}>
|
||||||
|
<div className="border-border item-center flex w-full justify-center rounded border px-8 py-1.5 shadow">
|
||||||
|
<ShimmerText text={text || 'Generating content...'} className="text-lg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -10,6 +10,8 @@ import { type IReportEditor } from '@/components/ui/report/ReportEditor';
|
||||||
import { ReportEditorSkeleton } from '@/components/ui/report/ReportEditorSkeleton';
|
import { ReportEditorSkeleton } from '@/components/ui/report/ReportEditorSkeleton';
|
||||||
import { useChatIndividualContextSelector } from '@/layouts/ChatLayout/ChatContext';
|
import { useChatIndividualContextSelector } from '@/layouts/ChatLayout/ChatContext';
|
||||||
import { useTrackAndUpdateReportChanges } from '@/api/buster-electric/reports/hooks';
|
import { useTrackAndUpdateReportChanges } from '@/api/buster-electric/reports/hooks';
|
||||||
|
import { ShimmerText } from '@/components/ui/typography/ShimmerText';
|
||||||
|
import { GeneratingContent } from './GeneratingContent';
|
||||||
|
|
||||||
export const ReportPageController: React.FC<{
|
export const ReportPageController: React.FC<{
|
||||||
reportId: string;
|
reportId: string;
|
||||||
|
@ -21,8 +23,10 @@ export const ReportPageController: React.FC<{
|
||||||
({ reportId, readOnly = false, className = '', onReady: onReadyProp, mode = 'default' }) => {
|
({ reportId, readOnly = false, className = '', onReady: onReadyProp, mode = 'default' }) => {
|
||||||
const { data: report } = useGetReport({ reportId, versionNumber: undefined });
|
const { data: report } = useGetReport({ reportId, versionNumber: undefined });
|
||||||
const isStreamingMessage = useChatIndividualContextSelector((x) => x.isStreamingMessage);
|
const isStreamingMessage = useChatIndividualContextSelector((x) => x.isStreamingMessage);
|
||||||
|
const messageId = useChatIndividualContextSelector((x) => x.currentMessageId);
|
||||||
|
|
||||||
const content = report?.content || '';
|
const content = report?.content || '';
|
||||||
|
const showGeneratingContent = messageId && isStreamingMessage;
|
||||||
const commonClassName = 'sm:px-[max(64px,calc(50%-350px))]';
|
const commonClassName = 'sm:px-[max(64px,calc(50%-350px))]';
|
||||||
|
|
||||||
const { mutate: updateReport } = useUpdateReport();
|
const { mutate: updateReport } = useUpdateReport();
|
||||||
|
@ -68,7 +72,12 @@ export const ReportPageController: React.FC<{
|
||||||
readOnly={readOnly || !report}
|
readOnly={readOnly || !report}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
onReady={onReadyProp}
|
onReady={onReadyProp}
|
||||||
isStreaming={isStreamingMessage}>
|
isStreaming={isStreamingMessage}
|
||||||
|
postEditorChildren={
|
||||||
|
showGeneratingContent ? (
|
||||||
|
<GeneratingContent messageId={messageId} className={commonClassName} />
|
||||||
|
) : null
|
||||||
|
}>
|
||||||
<ReportPageHeader
|
<ReportPageHeader
|
||||||
name={report?.name}
|
name={report?.name}
|
||||||
updatedAt={report?.updated_at}
|
updatedAt={report?.updated_at}
|
||||||
|
|
Loading…
Reference in New Issue