Skip to content

Commit

Permalink
feat: add copy button to code highlighter
Browse files Browse the repository at this point in the history
Closes #1441

Update src/components/JSONViewer/index.tsx

Co-authored-by: Moshe Immerman <[email protected]>

Update src/components/JSONViewer/index.tsx

Co-authored-by: Moshe Immerman <[email protected]>

fix: use GoCopy instead of facopy icon
  • Loading branch information
mainawycliffe committed Oct 26, 2023
1 parent 73d4e60 commit d2fb93f
Showing 1 changed file with 54 additions and 32 deletions.
86 changes: 54 additions & 32 deletions src/components/JSONViewer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ComponentProps, useMemo } from "react";
import Highlight, { defaultProps, Language } from "prism-react-renderer";
import Highlight, { Language, defaultProps } from "prism-react-renderer";
import vsLight from "prism-react-renderer/themes/vsLight";
import { ComponentProps, useMemo } from "react";
import { GoCopy } from "react-icons/go";
import { parse, stringify } from "yaml";
import { Button } from "../Button";
import { useCopyToClipboard } from "../Hooks/useCopyToClipboard";

type RenderProps = Parameters<
ComponentProps<typeof Highlight>["children"]
Expand Down Expand Up @@ -34,7 +37,7 @@ function JSONViewerLine({
>
{showLineNo && (
<span
className="text-gray-400 text-xs px-1 select-none"
className="text-gray-400 text-xs pr-2 select-none"
style={{ display: "table-cell" }}
>
{idx + 1}
Expand Down Expand Up @@ -63,6 +66,7 @@ type JSONViewerProps = {
*
**/
convertToYaml?: boolean;
hideCopyButton?: boolean;
};

export function JSONViewer({
Expand All @@ -71,7 +75,8 @@ export function JSONViewer({
showLineNo,
selections,
onClick = () => {},
convertToYaml = false
convertToYaml = false,
hideCopyButton = false
}: JSONViewerProps) {
// convert JSON object to YAML string
const codeForHighlight = useMemo(() => {
Expand All @@ -92,6 +97,8 @@ export function JSONViewer({
return code;
}, [code, convertToYaml, format]);

const copyFn = useCopyToClipboard();

const formatDerived = useMemo(() => {
if (format !== "json") {
return format;
Expand All @@ -103,34 +110,49 @@ export function JSONViewer({
}, [convertToYaml, format]);

return (
<Highlight
{...defaultProps}
code={codeForHighlight}
theme={vsLight}
language={formatDerived}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={`${className} text-sm`} style={style}>
{tokens.map((line, i) => {
const { style, ...props } = getLineProps({ line, key: i });
return (
<JSONViewerLine
{...props}
style={{
...style,
display: showLineNo ? "table-row" : "block",
backgroundColor: selections && selections[i] ? "#cfe3ff" : ""
}}
onClick={onClick}
getTokenProps={getTokenProps}
showLineNo={showLineNo}
idx={i}
line={line}
/>
);
})}
</pre>
<div className="flex flex-col relative">
<Highlight
{...defaultProps}
code={codeForHighlight}
theme={vsLight}
language={formatDerived}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={`${className} text-sm`} style={style}>
{tokens.map((line, i) => {
const { style, ...props } = getLineProps({ line, key: i });
return (
<JSONViewerLine
{...props}
style={{
...style,
display: showLineNo ? "table-row" : "block",
backgroundColor:
selections && selections[i] ? "#cfe3ff" : ""
}}
onClick={onClick}
getTokenProps={getTokenProps}
showLineNo={showLineNo}
idx={i}
line={line}
/>
);
})}
</pre>
)}
</Highlight>
{!hideCopyButton && (
<Button
icon={<GoCopy />}
title="Copy to clipboard"
className={
"bg-white z-[99999999999999999] absolute right-4 text-black"
}
onClick={async () => {
await copyFn(codeForHighlight);
}}
/>
)}
</Highlight>
</div>
);
}

0 comments on commit d2fb93f

Please sign in to comment.