mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-25 19:15:18 +02:00
feat: implement input handling improvements in MemoryContent and TeamMemoryManager components, including click outside to close functionality
This commit is contained in:
parent
8c9440998a
commit
27cd032d28
2 changed files with 67 additions and 13 deletions
|
|
@ -34,6 +34,7 @@ export function MemoryContent() {
|
||||||
const [editing, setEditing] = useState(false);
|
const [editing, setEditing] = useState(false);
|
||||||
const [showInput, setShowInput] = useState(false);
|
const [showInput, setShowInput] = useState(false);
|
||||||
const textareaRef = useRef<HTMLInputElement>(null);
|
const textareaRef = useRef<HTMLInputElement>(null);
|
||||||
|
const inputContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const fetchMemory = useCallback(async () => {
|
const fetchMemory = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -51,6 +52,26 @@ export function MemoryContent() {
|
||||||
fetchMemory();
|
fetchMemory();
|
||||||
}, [fetchMemory]);
|
}, [fetchMemory]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showInput) return;
|
||||||
|
|
||||||
|
const handlePointerDownOutside = (event: MouseEvent | TouchEvent) => {
|
||||||
|
const target = event.target;
|
||||||
|
if (!(target instanceof Node)) return;
|
||||||
|
if (inputContainerRef.current?.contains(target)) return;
|
||||||
|
|
||||||
|
setShowInput(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", handlePointerDownOutside);
|
||||||
|
document.addEventListener("touchstart", handlePointerDownOutside, { passive: true });
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("mousedown", handlePointerDownOutside);
|
||||||
|
document.removeEventListener("touchstart", handlePointerDownOutside);
|
||||||
|
};
|
||||||
|
}, [showInput]);
|
||||||
|
|
||||||
const handleClear = async () => {
|
const handleClear = async () => {
|
||||||
try {
|
try {
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
|
|
@ -122,9 +143,6 @@ export function MemoryContent() {
|
||||||
if (e.key === "Enter" && !e.shiftKey) {
|
if (e.key === "Enter" && !e.shiftKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleEdit();
|
handleEdit();
|
||||||
} else if (e.key === "Escape") {
|
|
||||||
setShowInput(false);
|
|
||||||
setEditQuery("");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -183,7 +201,10 @@ export function MemoryContent() {
|
||||||
|
|
||||||
{showInput ? (
|
{showInput ? (
|
||||||
<div className="absolute bottom-3 inset-x-3 z-10">
|
<div className="absolute bottom-3 inset-x-3 z-10">
|
||||||
<div className="relative flex items-center gap-2 rounded-full border bg-muted/60 backdrop-blur-sm px-4 py-2 shadow-sm">
|
<div
|
||||||
|
ref={inputContainerRef}
|
||||||
|
className="relative flex h-[54px] items-center gap-2 rounded-[9999px] border bg-muted/60 backdrop-blur-sm pl-4 pr-1 shadow-sm"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
ref={textareaRef}
|
ref={textareaRef}
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -200,9 +221,15 @@ export function MemoryContent() {
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={handleEdit}
|
onClick={handleEdit}
|
||||||
disabled={editing || !editQuery.trim()}
|
disabled={editing || !editQuery.trim()}
|
||||||
className="h-9 w-9 shrink-0 rounded-full"
|
className={`h-11 w-11 shrink-0 rounded-full ${
|
||||||
|
editing ? "" : "bg-muted-foreground/15 hover:bg-muted-foreground/20"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{editing ? <Spinner size="sm" /> : <ArrowUp className="!h-5 !w-5" />}
|
{editing ? (
|
||||||
|
<Spinner size="sm" />
|
||||||
|
) : (
|
||||||
|
<ArrowUp className="!h-5 !w-5 text-foreground" strokeWidth={2.25} />
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { ArrowUp, ChevronDown, ClipboardCopy, Download, Info, Pen } from "lucide-react";
|
import { ArrowUp, ChevronDown, ClipboardCopy, Download, Info, Pen } from "lucide-react";
|
||||||
import { useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { updateSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms";
|
import { updateSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms";
|
||||||
|
|
@ -48,9 +48,30 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
|
||||||
const [editing, setEditing] = useState(false);
|
const [editing, setEditing] = useState(false);
|
||||||
const [showInput, setShowInput] = useState(false);
|
const [showInput, setShowInput] = useState(false);
|
||||||
const textareaRef = useRef<HTMLInputElement>(null);
|
const textareaRef = useRef<HTMLInputElement>(null);
|
||||||
|
const inputContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const memory = searchSpace?.shared_memory_md || "";
|
const memory = searchSpace?.shared_memory_md || "";
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showInput) return;
|
||||||
|
|
||||||
|
const handlePointerDownOutside = (event: MouseEvent | TouchEvent) => {
|
||||||
|
const target = event.target;
|
||||||
|
if (!(target instanceof Node)) return;
|
||||||
|
if (inputContainerRef.current?.contains(target)) return;
|
||||||
|
|
||||||
|
setShowInput(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", handlePointerDownOutside);
|
||||||
|
document.addEventListener("touchstart", handlePointerDownOutside, { passive: true });
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("mousedown", handlePointerDownOutside);
|
||||||
|
document.removeEventListener("touchstart", handlePointerDownOutside);
|
||||||
|
};
|
||||||
|
}, [showInput]);
|
||||||
|
|
||||||
const handleClear = async () => {
|
const handleClear = async () => {
|
||||||
try {
|
try {
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
|
|
@ -126,9 +147,6 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
|
||||||
if (e.key === "Enter" && !e.shiftKey) {
|
if (e.key === "Enter" && !e.shiftKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleEdit();
|
handleEdit();
|
||||||
} else if (e.key === "Escape") {
|
|
||||||
setShowInput(false);
|
|
||||||
setEditQuery("");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -189,7 +207,10 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
|
||||||
|
|
||||||
{showInput ? (
|
{showInput ? (
|
||||||
<div className="absolute bottom-3 inset-x-3 z-10">
|
<div className="absolute bottom-3 inset-x-3 z-10">
|
||||||
<div className="relative flex items-center gap-2 rounded-full border bg-muted/60 backdrop-blur-sm px-4 py-2 shadow-sm">
|
<div
|
||||||
|
ref={inputContainerRef}
|
||||||
|
className="relative flex h-[54px] items-center gap-2 rounded-[9999px] border bg-muted/60 backdrop-blur-sm pl-4 pr-1 shadow-sm"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
ref={textareaRef}
|
ref={textareaRef}
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -206,9 +227,15 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={handleEdit}
|
onClick={handleEdit}
|
||||||
disabled={editing || !editQuery.trim()}
|
disabled={editing || !editQuery.trim()}
|
||||||
className="h-9 w-9 shrink-0 rounded-full"
|
className={`h-11 w-11 shrink-0 rounded-full ${
|
||||||
|
editing ? "" : "bg-muted-foreground/15 hover:bg-muted-foreground/20"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{editing ? <Spinner size="sm" /> : <ArrowUp className="!h-5 !w-5" />}
|
{editing ? (
|
||||||
|
<Spinner size="sm" />
|
||||||
|
) : (
|
||||||
|
<ArrowUp className="!h-5 !w-5 text-foreground" strokeWidth={2.25} />
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue