Skip to content

Commit d6864b8

Browse files
committed
feat: add copy JSON value
1 parent eb5be0d commit d6864b8

File tree

1 file changed

+49
-8
lines changed

1 file changed

+49
-8
lines changed

client/src/components/DynamicJsonForm.tsx

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import JsonEditor from "./JsonEditor";
55
import { updateValueAtPath } from "@/utils/jsonUtils";
66
import { generateDefaultValue } from "@/utils/schemaUtils";
77
import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils";
8+
import { useToast } from "@/lib/hooks/useToast";
9+
import { CheckCheck, Copy } from "lucide-react";
810

911
interface DynamicJsonFormProps {
1012
schema: JsonSchemaType;
@@ -31,6 +33,9 @@ const DynamicJsonForm = ({
3133
const isOnlyJSON = !isSimpleObject(schema);
3234
const [isJsonMode, setIsJsonMode] = useState(isOnlyJSON);
3335
const [jsonError, setJsonError] = useState<string>();
36+
const [copiedJson, setCopiedJson] = useState<boolean>(false);
37+
const { toast } = useToast();
38+
3439
// Store the raw JSON string to allow immediate feedback during typing
3540
// while deferring parsing until the user stops typing
3641
const [rawJsonValue, setRawJsonValue] = useState<string>(
@@ -246,19 +251,55 @@ const DynamicJsonForm = ({
246251
}
247252
}, [shouldUseJsonMode, isJsonMode]);
248253

254+
const handleCopyJson = useCallback(() => {
255+
try {
256+
navigator.clipboard
257+
.writeText(JSON.stringify(value, null, 2) ?? "[]")
258+
.then(() => {
259+
setCopiedJson(true);
260+
261+
toast({
262+
title: "JSON copied",
263+
description:
264+
"The JSON data has been successfully copied to your clipboard.",
265+
});
266+
267+
setTimeout(() => {
268+
setCopiedJson(false);
269+
}, 2000);
270+
})
271+
.catch((error) => {
272+
reportError(error);
273+
});
274+
} catch (error) {
275+
reportError(error);
276+
}
277+
}, [toast, value]);
278+
249279
return (
250280
<div className="space-y-4">
251281
<div className="flex justify-end space-x-2">
252282
{isJsonMode && (
253-
<Button
254-
type="button"
255-
variant="outline"
256-
size="sm"
257-
onClick={formatJson}
258-
>
259-
Format JSON
260-
</Button>
283+
<>
284+
<Button variant="outline" size="sm" onClick={handleCopyJson}>
285+
{copiedJson ? (
286+
<CheckCheck className="h-4 w-4 mr-2" />
287+
) : (
288+
<Copy className="h-4 w-4 mr-2" />
289+
)}
290+
Copy JSON
291+
</Button>
292+
<Button
293+
type="button"
294+
variant="outline"
295+
size="sm"
296+
onClick={formatJson}
297+
>
298+
Format JSON
299+
</Button>
300+
</>
261301
)}
302+
262303
{!isOnlyJSON && (
263304
<Button variant="outline" size="sm" onClick={handleSwitchToFormMode}>
264305
{isJsonMode ? "Switch to Form" : "Switch to JSON"}

0 commit comments

Comments
 (0)