* [packages][m]: mv @flowershow/core package here * [packages/core][xs]: rename to @portaljs/core * [package.json][xs]: setup npm workspaces * [packages/core][xs]:replace deprecated rollup executor * [core/package.json][s]: fix mermaid versions * [core/tsconfig][xs]: rm extends * [core/jest.config][xs]: rm coverageDirectory * [core/package.json][xs]: install core-js * [packages.json][s]:use same version for all nrwl packages * [core/.eslintrc][xs]: adjust ignorePatterns * [core/project.json][xs]: rm publish targets * [packages][m]: mv @flowershow/remark-wiki-link here * [packages][m]: mv @flowershow/remark-wiki-link here * [packages][m]: mv @flowershow/remark-embed here * [remark-callouts/project.json][xs]: adjst test pattern * [package.json][s]: install missing deps * [remark-callouts][xs]: adjst fields in package.json * [remark-callouts][s]: rm pubish targets and adjst build executor * [remark-embed/jest.config][xs]: rm unknown option coverageDirectory * [remark-embed][xs]: rm publish targets * [remark-embed][s]: rename to @portaljs/remark-embed * [remark-wiki-link/eslintrc][xs]:adjst ignorePatterns * [package.json][xs]: install missing deps * [remark-wiki-link/test][xs]:specify format - also temporarily force any type on htmlExtension * [remark-wiki-link/README][xs]: replace @flowershow with @portaljs * [remark-wiki-link][xs]:rm old changelog * [remark-wiki-link][xs]: adjst package.json * [remark-wiki-link/project.json][xs]: rm publish targets * [core][s]: rm old changelog * [core/README][xs]:correct scope name * [remark-callouts/README][xs]: add @portaljs to pckg name * [remark-embed/README][xs]: add @portaljs to pckg name * [package-lock.json][xs]: refresh after rebasing on main
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { useRef, useState } from "react";
|
|
|
|
interface Props extends React.PropsWithChildren {
|
|
className?: string;
|
|
}
|
|
|
|
export const Pre: React.FC<Props> = ({ children, ...props }) => {
|
|
const ref = useRef<any>(); // TODO type
|
|
const [hovered, setHovered] = useState(false);
|
|
const [copied, setCopied] = useState(false);
|
|
|
|
const onEnter = () => {
|
|
setHovered(true);
|
|
};
|
|
const onExit = () => {
|
|
setHovered(false);
|
|
setCopied(false);
|
|
};
|
|
const onCopy = () => {
|
|
setCopied(true);
|
|
navigator.clipboard.writeText(ref.current.textContent);
|
|
setTimeout(() => {
|
|
setCopied(false);
|
|
}, 2000);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
onMouseEnter={onEnter}
|
|
onMouseLeave={onExit}
|
|
className="relative"
|
|
>
|
|
{hovered && (
|
|
<button
|
|
aria-label="Copy code"
|
|
type="button"
|
|
className={`absolute right-2 top-2 h-6 w-6 rounded border bg-gray-700 p-1 ease-in-out duration-100 ${
|
|
copied
|
|
? "border-green-400 focus:border-green-400 focus:outline-none"
|
|
: "border-slate-300"
|
|
}`}
|
|
onClick={onCopy}
|
|
>
|
|
<svg
|
|
aria-hidden="true"
|
|
viewBox="-2 -2 20 20"
|
|
fill="currentColor"
|
|
className={copied ? "text-green-400" : "text-slate-300"}
|
|
>
|
|
{copied ? (
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"
|
|
/>
|
|
) : (
|
|
<>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z"
|
|
/>
|
|
</>
|
|
)}
|
|
</svg>
|
|
</button>
|
|
)}
|
|
<pre>{children}</pre>
|
|
</div>
|
|
);
|
|
};
|