From 7250d321bdb5183fc7d3bef531c3e698e645d454 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 15 Feb 2026 22:03:03 -0600 Subject: [PATCH 1/5] working --- apps/roam/src/components/FuzzySelectInput.tsx | 22 ++++++++++++++----- apps/roam/src/components/ModifyNodeDialog.tsx | 10 ++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/roam/src/components/FuzzySelectInput.tsx b/apps/roam/src/components/FuzzySelectInput.tsx index 16acdca1a..d4ac3422a 100644 --- a/apps/roam/src/components/FuzzySelectInput.tsx +++ b/apps/roam/src/components/FuzzySelectInput.tsx @@ -1,4 +1,10 @@ -import React, { useState, useCallback, useMemo, useRef, useEffect } from "react"; +import React, { + useState, + useCallback, + useMemo, + useRef, + useEffect, +} from "react"; import { Button, TextArea, @@ -16,7 +22,6 @@ type FuzzySelectInputProps = { setValue: (q: T) => void; onLockedChange?: (isLocked: boolean) => void; mode: "create" | "edit"; - initialUid: string; options?: T[]; placeholder?: string; autoFocus?: boolean; @@ -28,7 +33,6 @@ const FuzzySelectInput = ({ setValue, onLockedChange, mode, - initialUid, options = [], placeholder = "Enter value", autoFocus, @@ -52,7 +56,7 @@ const FuzzySelectInput = ({ const handleSelect = useCallback( (item: T) => { - if (mode === "create" && item.uid && item.uid !== initialUid) { + if (mode === "create" && item.uid) { setIsLocked(true); setQuery(item.text); setValue(item); @@ -65,7 +69,7 @@ const FuzzySelectInput = ({ requestAnimationFrame(() => inputRef.current?.focus()); } }, - [mode, initialUid, setValue, onLockedChange], + [mode, setValue, onLockedChange], ); const handleClear = useCallback(() => { @@ -105,6 +109,12 @@ const FuzzySelectInput = ({ } }, [query, mode, isLocked, setValue]); + useEffect(() => { + if (typeof initialIsLocked === "boolean") { + setIsLocked(initialIsLocked); + } + }, [initialIsLocked]); + useEffect(() => { if (isFocused && filteredItems.length > 0 && query) { setIsOpen(true); @@ -223,4 +233,4 @@ const FuzzySelectInput = ({ ); }; -export default FuzzySelectInput; \ No newline at end of file +export default FuzzySelectInput; diff --git a/apps/roam/src/components/ModifyNodeDialog.tsx b/apps/roam/src/components/ModifyNodeDialog.tsx index ebd84e473..b92ab8c7c 100644 --- a/apps/roam/src/components/ModifyNodeDialog.tsx +++ b/apps/roam/src/components/ModifyNodeDialog.tsx @@ -84,12 +84,8 @@ const ModifyNodeDialog = ({ [content.uid, initialValue.uid, mode], ); const isReferencedNodeLocked = useMemo( - () => - Boolean( - referencedNodeValue.uid && - referencedNodeValue.uid !== initialReferencedNode?.uid, - ), - [referencedNodeValue.uid, initialReferencedNode?.uid], + () => Boolean(referencedNodeValue.uid), + [referencedNodeValue.uid], ); const [options, setOptions] = useState<{ @@ -537,7 +533,6 @@ const ModifyNodeDialog = ({ : `Enter a ${selectedNodeType.text.toLowerCase()} ...` } mode={mode} - initialUid={content.uid} autoFocus /> @@ -552,7 +547,6 @@ const ModifyNodeDialog = ({ options={options.referencedNode} placeholder={loading ? "..." : "Select a referenced node"} mode={"create"} - initialUid={referencedNodeValue.uid} initialIsLocked={isReferencedNodeLocked} autoFocus={false} /> From 99b07549f298e4e6441fed11017698753cc3c44a Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 15 Feb 2026 22:05:48 -0600 Subject: [PATCH 2/5] refactor --- apps/roam/src/components/FuzzySelectInput.tsx | 33 +++++-------------- apps/roam/src/components/ModifyNodeDialog.tsx | 1 - 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/apps/roam/src/components/FuzzySelectInput.tsx b/apps/roam/src/components/FuzzySelectInput.tsx index d4ac3422a..9bf4ee295 100644 --- a/apps/roam/src/components/FuzzySelectInput.tsx +++ b/apps/roam/src/components/FuzzySelectInput.tsx @@ -20,29 +20,25 @@ import { Result } from "~/utils/types"; type FuzzySelectInputProps = { value?: T; setValue: (q: T) => void; - onLockedChange?: (isLocked: boolean) => void; mode: "create" | "edit"; options?: T[]; placeholder?: string; autoFocus?: boolean; - initialIsLocked?: boolean; }; const FuzzySelectInput = ({ value, setValue, - onLockedChange, mode, options = [], placeholder = "Enter value", autoFocus, - initialIsLocked, }: FuzzySelectInputProps) => { - const [isLocked, setIsLocked] = useState(initialIsLocked || false); const [query, setQuery] = useState(() => value?.text || ""); const [isOpen, setIsOpen] = useState(false); const [activeIndex, setActiveIndex] = useState(0); const [isFocused, setIsFocused] = useState(false); + const isLocked = mode === "create" && Boolean(value?.uid); const menuRef = useRef(null); const inputRef = useRef(null); @@ -56,28 +52,21 @@ const FuzzySelectInput = ({ const handleSelect = useCallback( (item: T) => { - if (mode === "create" && item.uid) { - setIsLocked(true); - setQuery(item.text); - setValue(item); - setIsOpen(false); - onLockedChange?.(true); - } else { - setQuery(item.text); - setValue(item); - setIsOpen(false); + setQuery(item.text); + setValue(item); + setIsOpen(false); + + if (!(mode === "create" && item.uid)) { requestAnimationFrame(() => inputRef.current?.focus()); } }, - [mode, setValue, onLockedChange], + [mode, setValue], ); const handleClear = useCallback(() => { - setIsLocked(false); setQuery(""); setValue({ ...value, text: "", uid: "" } as T); - onLockedChange?.(false); - }, [value, setValue, onLockedChange]); + }, [value, setValue]); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { @@ -109,12 +98,6 @@ const FuzzySelectInput = ({ } }, [query, mode, isLocked, setValue]); - useEffect(() => { - if (typeof initialIsLocked === "boolean") { - setIsLocked(initialIsLocked); - } - }, [initialIsLocked]); - useEffect(() => { if (isFocused && filteredItems.length > 0 && query) { setIsOpen(true); diff --git a/apps/roam/src/components/ModifyNodeDialog.tsx b/apps/roam/src/components/ModifyNodeDialog.tsx index b92ab8c7c..2578f70b3 100644 --- a/apps/roam/src/components/ModifyNodeDialog.tsx +++ b/apps/roam/src/components/ModifyNodeDialog.tsx @@ -547,7 +547,6 @@ const ModifyNodeDialog = ({ options={options.referencedNode} placeholder={loading ? "..." : "Select a referenced node"} mode={"create"} - initialIsLocked={isReferencedNodeLocked} autoFocus={false} /> From c6b53e0e7b72f25e747c1eccec7c010226fffbc0 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 15 Feb 2026 23:06:42 -0600 Subject: [PATCH 3/5] fix bug when changing input types --- apps/roam/src/components/FuzzySelectInput.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/roam/src/components/FuzzySelectInput.tsx b/apps/roam/src/components/FuzzySelectInput.tsx index 9bf4ee295..cf89fc4a1 100644 --- a/apps/roam/src/components/FuzzySelectInput.tsx +++ b/apps/roam/src/components/FuzzySelectInput.tsx @@ -68,6 +68,16 @@ const FuzzySelectInput = ({ setValue({ ...value, text: "", uid: "" } as T); }, [value, setValue]); + const handleInputChange = useCallback( + (text: string) => { + setQuery(text); + if (mode === "create" && !isLocked) { + setValue({ text, uid: "" } as T); + } + }, + [mode, isLocked, setValue], + ); + const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "ArrowDown") { @@ -93,10 +103,9 @@ const FuzzySelectInput = ({ ); useEffect(() => { - if (mode === "create" && !isLocked) { - setValue({ text: query, uid: "" } as T); - } - }, [query, mode, isLocked, setValue]); + if (isLocked) return; + setQuery(value?.text ?? ""); + }, [isLocked, value?.text]); useEffect(() => { if (isFocused && filteredItems.length > 0 && query) { @@ -199,7 +208,7 @@ const FuzzySelectInput = ({ inputRef={inputRef} className="w-full" value={query} - onChange={(e) => setQuery(e.target.value)} + onChange={(e) => handleInputChange(e.target.value)} onKeyDown={handleKeyDown} autoFocus={autoFocus} placeholder={placeholder} From 37b1ff3027f2c1cbc5574ddf3acae22e3c6bf260 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Tue, 17 Feb 2026 18:44:06 -0600 Subject: [PATCH 4/5] re-add isLocked as prop --- apps/roam/src/components/FuzzySelectInput.tsx | 4 +++- apps/roam/src/components/ModifyNodeDialog.tsx | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/roam/src/components/FuzzySelectInput.tsx b/apps/roam/src/components/FuzzySelectInput.tsx index cf89fc4a1..d124526b3 100644 --- a/apps/roam/src/components/FuzzySelectInput.tsx +++ b/apps/roam/src/components/FuzzySelectInput.tsx @@ -24,6 +24,7 @@ type FuzzySelectInputProps = { options?: T[]; placeholder?: string; autoFocus?: boolean; + isLocked?: boolean; }; const FuzzySelectInput = ({ @@ -33,12 +34,13 @@ const FuzzySelectInput = ({ options = [], placeholder = "Enter value", autoFocus, + isLocked: isLockedProp, }: FuzzySelectInputProps) => { const [query, setQuery] = useState(() => value?.text || ""); const [isOpen, setIsOpen] = useState(false); const [activeIndex, setActiveIndex] = useState(0); const [isFocused, setIsFocused] = useState(false); - const isLocked = mode === "create" && Boolean(value?.uid); + const isLocked = isLockedProp ?? (mode === "create" && Boolean(value?.uid)); const menuRef = useRef(null); const inputRef = useRef(null); diff --git a/apps/roam/src/components/ModifyNodeDialog.tsx b/apps/roam/src/components/ModifyNodeDialog.tsx index 2578f70b3..c36ff9071 100644 --- a/apps/roam/src/components/ModifyNodeDialog.tsx +++ b/apps/roam/src/components/ModifyNodeDialog.tsx @@ -533,6 +533,7 @@ const ModifyNodeDialog = ({ : `Enter a ${selectedNodeType.text.toLowerCase()} ...` } mode={mode} + isLocked={isContentLocked} autoFocus /> @@ -547,6 +548,7 @@ const ModifyNodeDialog = ({ options={options.referencedNode} placeholder={loading ? "..." : "Select a referenced node"} mode={"create"} + isLocked={isReferencedNodeLocked} autoFocus={false} /> From c636d242b81442afbf77f55ff6857b47a9bdce1f Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Tue, 17 Feb 2026 18:51:31 -0600 Subject: [PATCH 5/5] make isLocked required --- apps/roam/src/components/FuzzySelectInput.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/roam/src/components/FuzzySelectInput.tsx b/apps/roam/src/components/FuzzySelectInput.tsx index d124526b3..e685811b8 100644 --- a/apps/roam/src/components/FuzzySelectInput.tsx +++ b/apps/roam/src/components/FuzzySelectInput.tsx @@ -24,7 +24,7 @@ type FuzzySelectInputProps = { options?: T[]; placeholder?: string; autoFocus?: boolean; - isLocked?: boolean; + isLocked: boolean; }; const FuzzySelectInput = ({ @@ -34,13 +34,12 @@ const FuzzySelectInput = ({ options = [], placeholder = "Enter value", autoFocus, - isLocked: isLockedProp, + isLocked, }: FuzzySelectInputProps) => { const [query, setQuery] = useState(() => value?.text || ""); const [isOpen, setIsOpen] = useState(false); const [activeIndex, setActiveIndex] = useState(0); const [isFocused, setIsFocused] = useState(false); - const isLocked = isLockedProp ?? (mode === "create" && Boolean(value?.uid)); const menuRef = useRef(null); const inputRef = useRef(null);