Skip to content

Instantly share code, notes, and snippets.

@EvanMarie
Created September 10, 2024 18:12
Show Gist options
  • Save EvanMarie/316d967c93410df8027d507a0ec6a38f to your computer and use it in GitHub Desktop.
Save EvanMarie/316d967c93410df8027d507a0ec6a38f to your computer and use it in GitHub Desktop.
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