adds CopyToClipboard

This commit is contained in:
James
2020-05-29 16:04:16 -04:00
parent fd3b34b2eb
commit fab2ef16fa
7 changed files with 170 additions and 7 deletions

View File

@@ -0,0 +1,62 @@
import React, { useEffect, useState, useRef } from 'react';
import PropTypes from 'prop-types';
import Copy from '../../icons/Copy';
import Tooltip from '../Tooltip';
import './index.scss';
const baseClass = 'copy-to-clipboard';
const CopyToClipboard = ({ value }) => {
const ref = useRef(null);
const [copied, setCopied] = useState(false);
const [hovered, setHovered] = useState(false);
useEffect(() => {
if (copied && !hovered) {
setTimeout(() => {
setCopied(false);
}, 1500);
}
}, [copied, hovered]);
return (
<button
onMouseEnter={() => {
setHovered(true);
setCopied(false);
}}
onMouseLeave={() => {
setHovered(false);
setCopied(false);
}}
type="button"
className={baseClass}
onClick={() => {
if (ref && ref.current) {
ref.current.select();
ref.current.setSelectionRange(0, value.length + 1);
document.execCommand('copy');
setCopied(true);
}
}}
>
<Copy />
<Tooltip>
{copied && 'Copied'}
{!copied && 'Copy'}
</Tooltip>
<textarea
value={value}
ref={ref}
/>
</button>
);
};
CopyToClipboard.propTypes = {
value: PropTypes.string.isRequired,
};
export default CopyToClipboard;

View File

@@ -0,0 +1,35 @@
@import '../../../scss/styles.scss';
.copy-to-clipboard {
@extend %btn-reset;
position: relative;
cursor: pointer;
vertical-align: middle;
textarea {
position: absolute;
opacity: 0;
z-index: -1;
height: 0px;
width: 0px;
}
.tooltip {
pointer-events: none;
opacity: 0;
visibility: hidden;
}
&:focus,
&:active {
outline: none;
}
&:hover {
.tooltip {
opacity: 1;
visibility: visible;
}
}
}

View File

@@ -6,7 +6,7 @@
z-index: 2;
top: 0;
left: 50%;
transform: translateX(-50%);
transform: translate3d(-50%, -120%, 0);
padding: 0 base(.4);
color: white;
line-height: $baseline;

View File

@@ -0,0 +1,27 @@
import React from 'react';
import './index.scss';
const Copy = () => {
return (
<svg
className="icon icon--copy"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 25 25"
>
<rect
x="6.5"
y="10"
width="8"
height="8"
className="stroke"
/>
<path
d="M10 9.98438V6.5H18V14.5H14"
className="stroke"
/>
</svg>
);
};
export default Copy;

View File

@@ -0,0 +1,12 @@
@import '../../../scss/styles';
.icon--copy {
height: $baseline;
width: $baseline;
.stroke {
fill: none;
stroke: $color-dark-gray;
stroke-width: $style-stroke-width-s;
}
}

View File

@@ -8,6 +8,7 @@ import Form from '../../../forms/Form';
import PreviewButton from '../../../elements/PreviewButton';
import FormSubmit from '../../../forms/Submit';
import RenderFields from '../../../forms/RenderFields';
import CopyToClipboard from '../../../elements/CopyToClipboard';
import * as fieldTypes from '../../../forms/field-types';
import './index.scss';
@@ -34,6 +35,8 @@ const DefaultEditView = (props) => {
preview,
} = collection;
const apiURL = `${serverURL}${api}/${slug}/${id}`;
return (
<div className={baseClass}>
<Form
@@ -86,6 +89,22 @@ const DefaultEditView = (props) => {
<PreviewButton generatePreviewURL={preview} />
<FormSubmit>Save</FormSubmit>
</div>
{isEditing && (
<div className={`${baseClass}__api-url`}>
<span className={`${baseClass}__label`}>
API URL
{' '}
<CopyToClipboard value={apiURL} />
</span>
<a
href={apiURL}
target="_blank"
rel="noopener noreferrer"
>
{apiURL}
</a>
</div>
)}
<div className={`${baseClass}__sidebar-fields`}>
<RenderFields
filter={field => field.position === 'sidebar'}

View File

@@ -8,10 +8,6 @@
align-items: flex-start;
}
&__main {
// max-width: base(20);
}
&__header {
h1 {
word-break: break-all;
@@ -44,7 +40,8 @@
&__document-actions,
&__meta,
&__sidebar-fields {
&__sidebar-fields,
&__api-url {
padding-left: base(1.5);
}
@@ -77,6 +74,16 @@
}
}
&__api-url {
margin-bottom: base(1.5);
a {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
}
&__sidebar-fields {
margin-bottom: base(1.5);
}
@@ -120,7 +127,8 @@
&__document-actions,
&__meta,
&__sidebar-fields {
&__sidebar-fields,
&__api-url {
padding-left: $baseline;
}