Newer
Older
CrypticOreWallet / src / components / SmallCopyable.tsx
@BuildTools BuildTools on 9 Jun 2021 2 KB im gay
// Copyright (c) 2020-2021 Drew Lemmy
// This file is part of TenebraWeb 2 under AGPL-3.0.
// Full details: https://github.com/tmpim/TenebraWeb2/blob/master/LICENSE.txt
// -----------------------------------------------------------------------------
// This is based on the ant Typography copyable, but with some features removed,
// and without the overhead of the Typography Base component. The ResizeObserver
// in Typography seems to add a significant amount to render times when there
// are a lot of Text elements on the screen (for example, a table listing).
//
// This file is based off of the following source code from ant-design, which is
// licensed under the MIT license:
//
// https://github.com/ant-design/ant-design/blob/077443696ba0fb708f2af81f5eb665b908d8be66/components/typography/Base.tsx
//
// For the full terms of the MIT license used by ant-design, see:
// https://github.com/ant-design/ant-design/blob/master/LICENSE
// -----------------------------------------------------------------------------
import { useState, useEffect, useRef } from "react";
import classNames from "classnames";
import { Tooltip } from "antd";
import { CopyOutlined, CheckOutlined } from "@ant-design/icons";

import { useTranslation } from "react-i18next";

import { CopyConfig } from "./types";
import copy from "copy-to-clipboard";

import "./styles/SmallCopyable.less";

// Force 'text' to be set (don't traverse the children at all)
type Props = CopyConfig & {
  text: string;
  className?: string;
};

export function SmallCopyable({ text, onCopy, className }: Props): JSX.Element {
  const { t } = useTranslation();

  const [copied, setCopied] = useState(false);
  const copyId = useRef<number>();

  function onCopyClick(e: React.MouseEvent<HTMLDivElement>) {
    e.preventDefault();

    copy(text);

    // Display the 'Copied!' tooltip for 3 secs
    setCopied(true);
    onCopy?.();
    copyId.current = window.setTimeout(() => setCopied(false), 3000);
  }

  // Clear the timeout on unmount
  useEffect(() => () => window.clearTimeout(copyId.current), []);

  const title = copied ? t("copied") : t("copy");
  const classes = classNames(className, "ant-typography-copy", "small-copyable",
    copied && "ant-typography-copy-success");

  const btn = (
    <div
      role="button"
      onClick={onCopyClick}
      aria-label={title}
      className={classes}
    >
      {copied ? <CheckOutlined /> : <CopyOutlined />}
    </div>
  );

  return copied
    ? <Tooltip title={title}>{btn}</Tooltip>
    : btn;
}