diff --git a/web/src/components/http-code-block.tsx b/web/src/components/http-code-block.tsx index 6d35240..a6d4361 100644 --- a/web/src/components/http-code-block.tsx +++ b/web/src/components/http-code-block.tsx @@ -185,7 +185,7 @@ export function HttpPacketSyntax({ className={cn("grid min-w-0", lineClassName, lineNumbers && "grid-cols-[2.25rem_minmax(0,1fr)]")} > {lineNumbers ? ( - + {index + 1} ) : null} diff --git a/web/src/components/repeater/repeater-text-pane.tsx b/web/src/components/repeater/repeater-text-pane.tsx index 960353b..2ec5e78 100644 --- a/web/src/components/repeater/repeater-text-pane.tsx +++ b/web/src/components/repeater/repeater-text-pane.tsx @@ -10,6 +10,52 @@ import { HttpPacketSyntax } from "@/components/http-code-block"; import { Textarea } from "@/components/ui/textarea"; import { cn } from "@/lib/utils"; +function EditablePacket({ + id, + value, + onChange, + onScroll, +}: { + id: string; + value: string; + onChange: (value: string) => void; + onScroll: React.UIEventHandler; +}) { + const editor = React.useRef(null); + const lastValue = React.useRef(value); + + React.useEffect(() => { + if (!editor.current || lastValue.current === value) return; + if (editor.current.innerText !== value) { + editor.current.innerText = value; + } + lastValue.current = value; + }, [value]); + + return ( +
{ + const next = event.currentTarget.innerText.replace(/\r\n?/g, "\n"); + lastValue.current = next; + onChange(next); + }} + onScroll={onScroll} + className="h-full min-h-0 w-0 flex-1 overflow-auto whitespace-pre-wrap break-words rounded-none border-0 px-3 py-2 font-mono text-xs leading-5 outline-none md:text-xs" + > + +
+ ); +} + export function RepeaterTextPane({ id, label, @@ -64,7 +110,7 @@ export function RepeaterTextPane({ {toolbar} -
+
-