From 991a4c2516452ebc8fdbf5d4fd97b41084a17a7d Mon Sep 17 00:00:00 2001 From: Chai Date: Tue, 26 May 2026 12:22:27 -0400 Subject: [PATCH 1/4] Port Magic Rewrite to refactor --- .../components/LorebookFormFields.tsx | 151 +++++++++++++---- src/shared/components/ui/ExpandedTextarea.tsx | 115 +++++++++++-- .../components/ui/MagicRewritePanel.tsx | 158 ++++++++++++++++++ src/shared/hooks/use-magic-rewrite.ts | 116 +++++++++++++ 4 files changed, 494 insertions(+), 46 deletions(-) create mode 100644 src/shared/components/ui/MagicRewritePanel.tsx create mode 100644 src/shared/hooks/use-magic-rewrite.ts diff --git a/src/features/catalog/lorebooks/components/LorebookFormFields.tsx b/src/features/catalog/lorebooks/components/LorebookFormFields.tsx index bc3919113..4632d2ac9 100644 --- a/src/features/catalog/lorebooks/components/LorebookFormFields.tsx +++ b/src/features/catalog/lorebooks/components/LorebookFormFields.tsx @@ -4,10 +4,24 @@ // and LorebookEntryRow (the per-entry inline drawer). // Extracted from LorebookEditor.tsx so styling stays consistent. // ────────────────────────────────────────────── -import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent } from "react"; -import { FileText, Maximize2, ToggleLeft, ToggleRight, X } from "lucide-react"; +import { + useCallback, + useEffect, + useRef, + useState, + type KeyboardEvent as ReactKeyboardEvent, +} from "react"; +import { + FileText, + Maximize2, + Sparkles, + ToggleLeft, + ToggleRight, + X, +} from "lucide-react"; import { cn } from "../../../../shared/lib/utils"; import { HelpTooltip } from "../../../../shared/components/ui/HelpTooltip"; +import { MagicRewritePanel } from "../../../../shared/components/ui/MagicRewritePanel"; export function FieldGroup({ label, @@ -32,7 +46,13 @@ export function FieldGroup({ ); } -export function KeysEditor({ keys, onChange }: { keys: string[]; onChange: (keys: string[]) => void }) { +export function KeysEditor({ + keys, + onChange, +}: { + keys: string[]; + onChange: (keys: string[]) => void; +}) { const [input, setInput] = useState(""); const addKey = () => { @@ -123,7 +143,9 @@ export function NumberField({ }) { return (
- + void, ) { - if (event.key !== "Tab" || event.shiftKey || event.altKey || event.metaKey || event.ctrlKey) return; + if ( + event.key !== "Tab" || + event.shiftKey || + event.altKey || + event.metaKey || + event.ctrlKey + ) + return; event.preventDefault(); insertTabAtSelection(event.currentTarget, value, applyValue); } @@ -233,6 +262,8 @@ export function ExpandedContentModal({ placeholder?: string; }) { const [local, setLocal] = useState(value); + const [magicRewriteMode, setMagicRewriteMode] = useState(false); + const [magicRewriteResult, setMagicRewriteResult] = useState(""); const textareaRef = useRef(null); useEffect(() => { @@ -241,7 +272,7 @@ export function ExpandedContentModal({ useEffect(() => { const handler = (e: KeyboardEvent) => { - if (e.key === "Escape") { + if (e.key === "Escape" && !magicRewriteMode) { onChange(local); onCommit?.(); onClose(); @@ -249,7 +280,7 @@ export function ExpandedContentModal({ }; document.addEventListener("keydown", handler); return () => document.removeEventListener("keydown", handler); - }, [onClose, onChange, onCommit, local]); + }, [onClose, onChange, onCommit, local, magicRewriteMode]); const handleClose = () => { onChange(local); @@ -257,36 +288,100 @@ export function ExpandedContentModal({ onClose(); }; + const handleMagicRewriteBack = () => { + setMagicRewriteMode(false); + setMagicRewriteResult(""); + }; + + const handleMagicRewriteApply = () => { + if (!magicRewriteResult) return; + setLocal(magicRewriteResult); + setMagicRewriteMode(false); + setMagicRewriteResult(""); + window.setTimeout(() => textareaRef.current?.focus(), 100); + }; + + const handleMagicRewriteResultChange = useCallback((next: string) => { + setMagicRewriteResult(next); + }, []); + return (
-
-
+
+
-

{title}

- +

+ {magicRewriteMode ? "Magic Rewrite" : title} +

+
+ +
-