Files
ERitors-Scribe-Desktop/components/ui/QSTextGeneratedPreview.tsx
natreex d4765e6576 Add foundational components and logic for migration, UI design, and input handling
- Introduced foundational UI components (`Badge`, `LockCard`, `SectionHeader`, `AvatarIcon`, etc.) for flexible layouts and consistent design.
- Added migration support with the `MigrationModal` component and backend integration for exporting/importing data between Electron and Tauri.
- Extended form components with `TextAreaInput`, `OrderInput`, `ToggleField`, and `ToolbarSelect` for improved input handling.
- Updated `ScribeShell` with migration popup logic to prompt users for data migration.
- Integrated `AlertStack` for better alert handling and notification management.
- Enhanced Rust/Tauri services with migration command implementations.
- Added translations and styles for new components.
2026-04-05 12:52:54 -04:00

99 lines
4.4 KiB
TypeScript

import React from 'react';
import {RefreshCw, Send, Square} from 'lucide-react';
import {useTranslations} from '@/lib/i18n';
import IconButton from '@/components/ui/IconButton';
import Button from '@/components/ui/Button';
import Modal from '@/components/ui/Modal';
interface QSTextGeneratedPreviewProps {
onClose: () => void;
onRefresh: () => void;
value: string;
onInsert: () => void;
isGenerating?: boolean;
onStop?: () => void;
}
export default function QSTextGeneratedPreview(
{
onClose,
onRefresh,
value,
onInsert,
isGenerating = false,
onStop,
}: QSTextGeneratedPreviewProps) {
const t = useTranslations();
const filteredValue: string = value.replace(/^starting\.{0,3}\s*/i, '').trim();
const hasRealContent: boolean = filteredValue.length > 0;
const headerActions: React.ReactNode = isGenerating && onStop ? (
<IconButton icon={Square} variant="danger" onClick={onStop}/>
) : (
<IconButton icon={RefreshCw} variant="ghost" onClick={onRefresh}/>
);
const footerContent: React.ReactNode = (
<Button variant="primary" onClick={onInsert} icon={Send}>
{t("qsTextPreview.insert")}
</Button>
);
return (
<Modal
title={t("qsTextPreview.title")}
onClose={onClose}
size="md"
actions={headerActions}
footer={footerContent}
enableOverflow={true}
>
<div className="font-['Lora']">
{isGenerating && !hasRealContent ? (
<div className="space-y-3 animate-pulse">
<div className="flex flex-wrap gap-2">
<span className="h-5 bg-primary/20 rounded px-4"></span>
<span className="h-5 bg-primary/15 rounded px-6"></span>
<span className="h-5 bg-primary/20 rounded px-3"></span>
<span className="h-5 bg-primary/10 rounded px-8"></span>
<span className="h-5 bg-primary/20 rounded px-5"></span>
<span className="h-5 bg-primary/15 rounded px-4"></span>
<span className="h-5 bg-primary/20 rounded px-7"></span>
</div>
<div className="flex flex-wrap gap-2">
<span className="h-5 bg-primary/15 rounded px-5"></span>
<span className="h-5 bg-primary/20 rounded px-3"></span>
<span className="h-5 bg-primary/10 rounded px-6"></span>
<span className="h-5 bg-primary/20 rounded px-4"></span>
<span className="h-5 bg-primary/15 rounded px-8"></span>
<span className="h-5 bg-primary/20 rounded px-3"></span>
</div>
<div className="flex flex-wrap gap-2">
<span className="h-5 bg-primary/20 rounded px-6"></span>
<span className="h-5 bg-primary/10 rounded px-4"></span>
<span className="h-5 bg-primary/20 rounded px-5"></span>
<span className="h-5 bg-primary/15 rounded px-7"></span>
<span className="h-5 bg-primary/20 rounded px-3"></span>
<span className="h-5 bg-primary/10 rounded px-5"></span>
<span className="h-5 bg-primary/20 rounded px-4"></span>
</div>
<div className="flex flex-wrap gap-2">
<span className="h-5 bg-primary/15 rounded px-4"></span>
<span className="h-5 bg-primary/20 rounded px-6"></span>
<span className="h-5 bg-primary/10 rounded px-3"></span>
<span className="h-5 bg-primary/20 rounded px-5"></span>
<span className="h-5 bg-primary/15 rounded px-7"></span>
</div>
</div>
) : (
<div className="text-text-primary text-justify leading-relaxed whitespace-pre-wrap fade-in-text">
{filteredValue}
</div>
)}
</div>
</Modal>
);
}