feat: add copyToClipboard button

This commit is contained in:
Luca Tagliabue 2023-08-23 11:24:02 +02:00
parent 8e07c1d1d3
commit 25d7b5e8d4
4 changed files with 46 additions and 7 deletions

View File

@ -190,7 +190,7 @@ const App = () => (
Sort object keys with <code>sortObjectKeys</code> prop. Sort object keys with <code>sortObjectKeys</code> prop.
</p> </p>
<div> <div>
<JSONTree data={data} theme={theme} sortObjectKeys /> <JSONTree data={data} theme={theme} sortObjectKeys expandCollapseAll={{}}/>
</div> </div>
<p>Collapsed root node</p> <p>Collapsed root node</p>
<div> <div>

View File

@ -2,9 +2,11 @@ import {
faArrowDown, faArrowDown,
faArrowRight, faArrowRight,
faUndo, faUndo,
faCopy,
faCheck,
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { ReactNode } from 'react'; import React, { ReactNode, useState } from 'react';
import { ExpandCollapseAll } from '.'; import { ExpandCollapseAll } from '.';
import { useExpandCollapseAllContext } from './expandCollapseContext'; import { useExpandCollapseAllContext } from './expandCollapseContext';
import { StylingFunction } from 'react-base16-styling'; import { StylingFunction } from 'react-base16-styling';
@ -12,6 +14,7 @@ import { StylingFunction } from 'react-base16-styling';
interface Props { interface Props {
expandCollapseAll: ExpandCollapseAll; expandCollapseAll: ExpandCollapseAll;
styling: StylingFunction; styling: StylingFunction;
value: unknown;
} }
interface ExpandButtonProps { interface ExpandButtonProps {
@ -24,11 +27,17 @@ interface CollapseButtonProps {
collapseIcon?: ReactNode; collapseIcon?: ReactNode;
} }
interface CopyToClipboardButtonProps {
copyToClipboardIcon?: ReactNode;
copiedToClipboardIcon?: ReactNode;
value: unknown;
}
interface DefaultButtonProps { interface DefaultButtonProps {
defaultIcon?: ReactNode; defaultIcon?: ReactNode;
} }
function ExpandCollapseButtons({ expandCollapseAll, styling }: Props) { function ExpandCollapseButtons({ expandCollapseAll, styling, value }: Props) {
const { enableDefaultButton } = useExpandCollapseAllContext(); const { enableDefaultButton } = useExpandCollapseAllContext();
const expandableDefaultValue = expandCollapseAll?.defaultValue || 'expand'; const expandableDefaultValue = expandCollapseAll?.defaultValue || 'expand';
@ -39,6 +48,12 @@ function ExpandCollapseButtons({ expandCollapseAll, styling }: Props) {
<DefaultButton defaultIcon={expandCollapseAll?.defaultIcon} /> <DefaultButton defaultIcon={expandCollapseAll?.defaultIcon} />
)} )}
<CopyToClipboardButton
copyToClipboardIcon={expandCollapseAll?.copyToClipboardIcon}
copiedToClipboardIcon={expandCollapseAll?.copiedToClipboardIcon}
value={value}
/>
<ExpandButton <ExpandButton
expandableDefaultValue={expandableDefaultValue} expandableDefaultValue={expandableDefaultValue}
expandIcon={expandCollapseAll?.expandIcon} expandIcon={expandCollapseAll?.expandIcon}
@ -108,6 +123,26 @@ function CollapseButton({
return <></>; return <></>;
} }
function CopyToClipboardButton({copyToClipboardIcon, copiedToClipboardIcon, value}:CopyToClipboardButtonProps) {
const [isCopied, setIsCopied] = useState(false);
const handleOnCopyToClipboard = async () => {
await navigator.clipboard.writeText(JSON.stringify(value, null, 2));
setIsCopied(true)
}
if(isCopied){
return (<div role="presentation" onClick={handleOnCopyToClipboard}>
{copiedToClipboardIcon || <FontAwesomeIcon icon={faCheck} />}
</div>);
}
return (
<div role="presentation" onClick={handleOnCopyToClipboard}>
{copyToClipboardIcon || <FontAwesomeIcon icon={faCopy} />}
</div>)
}
function DefaultButton({ defaultIcon }: DefaultButtonProps) { function DefaultButton({ defaultIcon }: DefaultButtonProps) {
const { setExpandAllState, setEnableDefaultButton } = const { setExpandAllState, setEnableDefaultButton } =
useExpandCollapseAllContext(); useExpandCollapseAllContext();
@ -122,8 +157,6 @@ function DefaultButton({ defaultIcon }: DefaultButtonProps) {
{defaultIcon || <FontAwesomeIcon icon={faUndo} />} {defaultIcon || <FontAwesomeIcon icon={faUndo} />}
</div> </div>
); );
return <></>;
} }
export default ExpandCollapseButtons; export default ExpandCollapseButtons;

View File

@ -20,6 +20,7 @@ interface Props {
children: ReactNode; children: ReactNode;
expandCollapseAll?: ExpandCollapseAll; expandCollapseAll?: ExpandCollapseAll;
styling: StylingFunction; styling: StylingFunction;
value: unknown;
} }
const ExpandCollapseAllContext = createContext<Context>({} as Context); const ExpandCollapseAllContext = createContext<Context>({} as Context);
@ -28,11 +29,12 @@ function ExpandCollapseAllContextProvider({
expandCollapseAll, expandCollapseAll,
children, children,
styling, styling,
value,
}: Props) { }: Props) {
const [enableDefaultButton, setEnableDefaultButton] = useState(false); const [enableDefaultButton, setEnableDefaultButton] = useState(false);
const [expandAllState, setExpandAllState] = useState(); const [expandAllState, setExpandAllState] = useState();
const value = useMemo( const contextValue = useMemo(
() => ({ () => ({
enableDefaultButton, enableDefaultButton,
setEnableDefaultButton, setEnableDefaultButton,
@ -43,12 +45,13 @@ function ExpandCollapseAllContextProvider({
); );
return ( return (
<ExpandCollapseAllContext.Provider value={value}> <ExpandCollapseAllContext.Provider value={contextValue}>
{children} {children}
{expandCollapseAll && ( {expandCollapseAll && (
<ExpandCollapseButtons <ExpandCollapseButtons
expandCollapseAll={expandCollapseAll} expandCollapseAll={expandCollapseAll}
styling={styling} styling={styling}
value={value}
/> />
)} )}
</ExpandCollapseAllContext.Provider> </ExpandCollapseAllContext.Provider>

View File

@ -29,6 +29,8 @@ interface ExpandCollapseAll {
defaultValue?: 'expand' | 'collapse'; defaultValue?: 'expand' | 'collapse';
expandIcon?: ReactNode; expandIcon?: ReactNode;
collapseIcon?: ReactNode; collapseIcon?: ReactNode;
copyToClipboardIcon?: ReactNode;
copiedToClipboardIcon?: ReactNode;
defaultIcon?: ReactNode; defaultIcon?: ReactNode;
} }
@ -70,6 +72,7 @@ export function JSONTree({
<ExpandCollapseAllButtonsContext <ExpandCollapseAllButtonsContext
expandCollapseAll={expandCollapseAll} expandCollapseAll={expandCollapseAll}
styling={styling} styling={styling}
value={value}
> >
<JSONNode <JSONNode
keyPath={hideRoot ? [] : keyPath} keyPath={hideRoot ? [] : keyPath}