diff --git a/client/src/components/DynamicJsonForm.tsx b/client/src/components/DynamicJsonForm.tsx index 081a7d3be..4fbd45ca6 100644 --- a/client/src/components/DynamicJsonForm.tsx +++ b/client/src/components/DynamicJsonForm.tsx @@ -5,6 +5,8 @@ import JsonEditor from "./JsonEditor"; import { updateValueAtPath } from "@/utils/jsonUtils"; import { generateDefaultValue } from "@/utils/schemaUtils"; import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils"; +import { useToast } from "@/lib/hooks/useToast"; +import { CheckCheck, Copy } from "lucide-react"; interface DynamicJsonFormProps { schema: JsonSchemaType; @@ -60,6 +62,9 @@ const DynamicJsonForm = ({ const isOnlyJSON = !isSimpleObject(schema); const [isJsonMode, setIsJsonMode] = useState(isOnlyJSON); const [jsonError, setJsonError] = useState(); + const [copiedJson, setCopiedJson] = useState(false); + const { toast } = useToast(); + // Store the raw JSON string to allow immediate feedback during typing // while deferring parsing until the user stops typing const [rawJsonValue, setRawJsonValue] = useState( @@ -399,19 +404,64 @@ const DynamicJsonForm = ({ } }, [shouldUseJsonMode, isJsonMode]); + const handleCopyJson = useCallback(() => { + const copyToClipboard = 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", + }); + } + }; + + copyToClipboard(); + }, [toast, value]); + return (
{isJsonMode && ( - + <> + + + )} + {!isOnlyJSON && (