Created
September 10, 2024 18:12
-
-
Save EvanMarie/316d967c93410df8027d507a0ec6a38f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function EditableJSONInput({ | |
JSONString, | |
scrollRef, | |
onChange, | |
}: { | |
JSONString: string; | |
scrollRef: React.RefObject<HTMLDivElement>; | |
onChange: (updatedJSON: any) => void; | |
}) { | |
const [jsonState, setJsonState] = useState(() => JSON.parse(JSONString)); | |
// Update jsonState on input change | |
const handleInputChange = (keyPath: string[], value: any) => { | |
const newState = { ...jsonState }; | |
let current = newState; | |
// Traverse the keyPath and set the new value | |
for (let i = 0; i < keyPath.length - 1; i++) { | |
current = current[keyPath[i]]; | |
} | |
current[keyPath[keyPath.length - 1]] = value; | |
setJsonState(newState); | |
onChange(newState); // Pass the updated JSON back to parent | |
}; | |
// Recursive rendering function for JSON values | |
const renderValue = (value: any, keyPath: string[] = [], isRoot = false) => { | |
if (Array.isArray(value)) { | |
return value.map((item, index) => ( | |
<VStackFull | |
key={index} | |
className={`pl-2vh ${ | |
isRoot | |
? "border-100-md p-[1.5vh] mb-[1vh] bg-col-950 insetShadow5xl" | |
: "" | |
}`} | |
> | |
{renderValue(item, [...keyPath, index.toString()])}{" "} | |
{/* Recursively render arrays */} | |
</VStackFull> | |
)); | |
} else if (typeof value === "object" && value !== null) { | |
return Object.keys(value).map((key) => ( | |
<VStackFull key={key} className="w-full h-full pl-2vh"> | |
<HStackFull gap="gap-[2vh]"> | |
<Text className="text-cyan-300 text-sm textShadow"> | |
<strong>{key}:</strong> | |
</Text> | |
<VStackFull className="w-full" align="items-start"> | |
{renderValue(value[key], [...keyPath, key])}{" "} | |
{/* Recursively render objects */} | |
</VStackFull> | |
</HStackFull> | |
</VStackFull> | |
)); | |
} else { | |
// For primitive types, render an input field | |
return ( | |
<input | |
type="text" | |
value={String(value)} | |
onChange={(e) => handleInputChange(keyPath, e.target.value)} // Update value on input | |
className="px-[1vh] py-[0.2vh] bg-transparent border-b-[0.1vh] rounded-none border-white/40 text-white text-sm w-full" | |
/> | |
); | |
} | |
}; | |
return ( | |
// Main container for JSON editing | |
<Transition | |
className="w-[98vw] md:w-[80vh] bg-col-800 insetShadow3xl h-[56vh] overflow-y-auto overflow-x-hidden p-[1vh]" | |
ref={scrollRef} | |
> | |
<VStackFull | |
className="w-full h-fit p-[1vh]" | |
gap="gap-0" | |
align="items-start" | |
> | |
{Object.keys(jsonState).map((key) => ( | |
<VStackFull key={key} className="w-full h-full"> | |
{/* Top-level JSON key */} | |
<Text className="text-[4vh] text-cyan-300 text-semibold textShadow"> | |
{key} | |
</Text> | |
<VStackFull className="w-full" align="items-start"> | |
{renderValue(jsonState[key], [key], true)}{" "} | |
{/* Recursively render JSON */} | |
</VStackFull> | |
</VStackFull> | |
))} | |
</VStackFull> | |
</Transition> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment