| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- "use client";
- import { useEffect, useState } from "react";
- export default function JsonInput({
- value,
- onChange,
- className = "",
- ...props
- }: {
- value: string;
- onChange: (v: string) => void;
- className?: string;
- [key: string]: any;
- }) {
- const [error, setError] = useState<string | null>(null);
- useEffect(() => {
- // Auto-format valid JSON on mount or when value changes externally
- if (value.trim() !== "") {
- try {
- const parsed = JSON.parse(value);
- const formatted = JSON.stringify(parsed, null, 2);
- if (formatted !== value) {
- onChange(formatted);
- }
- setError(null);
- } catch (err: any) {
- setError(err.message);
- }
- }
- }, [value, onChange]);
- function handleInput(e: React.ChangeEvent<HTMLTextAreaElement>) {
- const val = e.target.value;
- try {
- if (val.trim() !== "") {
- JSON.parse(val);
- }
- setError(null);
- onChange(val);
- } catch (err: any) {
- setError(err.message);
- onChange(val);
- }
- }
- function handleFormat() {
- try {
- const formatted = JSON.stringify(JSON.parse(value), null, 2);
- setError(null);
- onChange(formatted);
- } catch (err: any) {
- setError("Invalid JSON");
- }
- }
- return (
- <div className={className}>
- <textarea
- className="block w-full rounded-md border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 font-mono text-xs min-h-[200px] bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100"
- value={value}
- onChange={handleInput}
- spellCheck={false}
- rows={10}
- {...props}
- />
- <div className="flex items-center gap-2 mt-1">
- <button
- type="button"
- className="inline-flex items-center rounded-md bg-indigo-600 px-3 py-1 text-xs font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
- onClick={handleFormat}
- >
- Format JSON
- </button>
- {error && (
- <span className="ml-2 text-xs text-red-500 font-medium">{error}</span>
- )}
- </div>
- </div>
- );
- }
|