Skip to content

Instantly share code, notes, and snippets.

@EvanMarie
Created September 10, 2024 18:11
Show Gist options
  • Save EvanMarie/36e21139721b11e355251d08d1affb7a to your computer and use it in GitHub Desktop.
Save EvanMarie/36e21139721b11e355251d08d1affb7a to your computer and use it in GitHub Desktop.
export function ValidatedJSONNumberedInput({
initialValue,
onChange,
}: {
initialValue?: string;
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
}) {
// State to track textarea content and JSON validation errors
const [value, setValue] = useState(initialValue);
const [jsonError, setJsonError] = useState<string | null>(null);
// Update value state when initialValue changes
useEffect(() => {
setValue(initialValue || ""); // Set value when initialValue changes
}, [initialValue]);
// Function to calculate the line number from a given position in the string
const getLineNumber = (input: string, position: number): number => {
const normalizedInput = input.replace(/\r\n/g, "\n"); // Normalize line breaks
const lines = normalizedInput.substring(0, position).split("\n");
return lines.length; // Return the number of lines up to the error
};
// Function to validate the JSON input and identify the error line if parsing fails
const validateJSON = (input: string) => {
try {
JSON.parse(input); // Attempt to parse JSON
setJsonError(null); // Clear error if valid
} catch (error: any) {
const positionMatch = error.message.match(/position (\d+)/);
if (positionMatch) {
const position = parseInt(positionMatch[1], 10);
const lineNumber = getLineNumber(input, position); // Get line number of error
setJsonError(`Invalid JSON format at line ${lineNumber}`);
} else {
setJsonError("Invalid JSON format"); // General error message
}
}
};
// Handler function triggered when the content of the textarea changes
const handleTextAreaChange = (
event: React.ChangeEvent<HTMLTextAreaElement>
) => {
const inputValue = event.target.value;
setValue(inputValue); // Update value
validateJSON(inputValue); // Validate the input as JSON
if (onChange) {
onChange(event); // Call parent onChange handler
}
};
return (
<Center className="w-full">
{/* Use Flex to layout the content relatively */}
<FlexFull className="relative">
{jsonError && <JsonError jsonError={jsonError} />}{" "}
{/* Show error if present */}
<TextAreaNumberedLines
value={value} // Pass current value to textarea
onChange={handleTextAreaChange} // Trigger onChange event to validate JSON
/>
</FlexFull>
</Center>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment