Resolve merge conflict in DynamicJsonForm.tsx

Integrate JSON validation with copy JSON functionality:
- Maintain forwardRef structure for validation exposure
- Combine copy button with validation method
- Both features working together without conflicts
This commit is contained in:
Nandha Reddy 2025-07-09 23:38:39 +10:00
commit 20d9480aff
No known key found for this signature in database
GPG key ID: 09ED40FC0F563333

View file

@ -12,6 +12,8 @@ import JsonEditor from "./JsonEditor";
import { updateValueAtPath } from "@/utils/jsonUtils"; import { updateValueAtPath } from "@/utils/jsonUtils";
import { generateDefaultValue } from "@/utils/schemaUtils"; import { generateDefaultValue } from "@/utils/schemaUtils";
import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils"; import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils";
import { useToast } from "@/lib/hooks/useToast";
import { CheckCheck, Copy } from "lucide-react";
interface DynamicJsonFormProps { interface DynamicJsonFormProps {
schema: JsonSchemaType; schema: JsonSchemaType;
@ -67,6 +69,9 @@ const DynamicJsonForm = forwardRef<DynamicJsonFormRef, DynamicJsonFormProps>(
const isOnlyJSON = !isSimpleObject(schema); const isOnlyJSON = !isSimpleObject(schema);
const [isJsonMode, setIsJsonMode] = useState(isOnlyJSON); const [isJsonMode, setIsJsonMode] = useState(isOnlyJSON);
const [jsonError, setJsonError] = useState<string>(); const [jsonError, setJsonError] = useState<string>();
const [copiedJson, setCopiedJson] = useState<boolean>(false);
const { toast } = useToast();
// Store the raw JSON string to allow immediate feedback during typing // Store the raw JSON string to allow immediate feedback during typing
// while deferring parsing until the user stops typing // while deferring parsing until the user stops typing
const [rawJsonValue, setRawJsonValue] = useState<string>( const [rawJsonValue, setRawJsonValue] = useState<string>(
@ -160,6 +165,31 @@ const DynamicJsonForm = forwardRef<DynamicJsonFormRef, DynamicJsonFormProps>(
} }
}; };
const handleCopyJson = useCallback(async () => {
try {
await navigator.clipboard.writeText(
JSON.stringify(value, null, 2) ?? "[]",
);
setCopiedJson(true);
toast({
title: "JSON copied",
description:
"The JSON data has been successfully copied to your clipboard.",
});
setTimeout(() => {
setCopiedJson(false);
}, 2000);
} catch (error) {
toast({
title: "Error",
description: `Failed to copy JSON: ${error instanceof Error ? error.message : String(error)}`,
variant: "destructive",
});
}
}, [toast, value]);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
validateJson, validateJson,
})); }));
@ -432,14 +462,29 @@ const DynamicJsonForm = forwardRef<DynamicJsonFormRef, DynamicJsonFormProps>(
<div className="space-y-4"> <div className="space-y-4">
<div className="flex justify-end space-x-2"> <div className="flex justify-end space-x-2">
{isJsonMode && ( {isJsonMode && (
<Button <>
type="button" <Button
variant="outline" type="button"
size="sm" variant="outline"
onClick={formatJson} size="sm"
> onClick={handleCopyJson}
Format JSON >
</Button> {copiedJson ? (
<CheckCheck className="h-4 w-4 mr-2" />
) : (
<Copy className="h-4 w-4 mr-2" />
)}
Copy JSON
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={formatJson}
>
Format JSON
</Button>
</>
)} )}
{!isOnlyJSON && ( {!isOnlyJSON && (
<Button <Button