@grafana/ui
Version:
Grafana Components Library
1 lines • 7.1 kB
Source Map (JSON)
{"version":3,"file":"ClipboardButton.mjs","sources":["../../../../src/components/ClipboardButton/ClipboardButton.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { useCallback, useRef, useState, useEffect } from 'react';\nimport * as React from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { t } from '@grafana/i18n';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { Button, ButtonProps } from '../Button/Button';\nimport { Icon } from '../Icon/Icon';\nimport { InlineToast } from '../InlineToast/InlineToast';\n\nexport type Props = ButtonProps & {\n /** A function that returns text to be copied */\n getText(): string;\n /** Callback when the text has been successfully copied */\n onClipboardCopy?(copiedText: string): void;\n /** Callback when there was an error copying the text */\n onClipboardError?(copiedText: string, error: unknown): void;\n};\n\nconst SHOW_SUCCESS_DURATION = 2 * 1000;\n\n/**\n * A control for allowing the user to copy text to their clipboard. Uses native APIs on modern browsers, falling back to the old `document.execCommand('copy')` API on other browsers. The text to be copied should be provided via `getText` prop.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/inputs-clipboardbutton--docs\n */\nexport function ClipboardButton({\n onClipboardCopy,\n onClipboardError,\n children,\n getText,\n icon,\n variant,\n ...buttonProps\n}: Props) {\n const styles = useStyles2(getStyles);\n const [showCopySuccess, setShowCopySuccess] = useState(false);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout>;\n\n if (showCopySuccess) {\n timeoutId = setTimeout(() => {\n setShowCopySuccess(false);\n }, SHOW_SUCCESS_DURATION);\n }\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [showCopySuccess]);\n\n const buttonRef = useRef<null | HTMLButtonElement>(null);\n const copyTextCallback = useCallback(async () => {\n const textToCopy = getText();\n\n try {\n await copyText(textToCopy, buttonRef);\n setShowCopySuccess(true);\n onClipboardCopy?.(textToCopy);\n } catch (e) {\n onClipboardError?.(textToCopy, e);\n }\n }, [getText, onClipboardCopy, onClipboardError]);\n\n const copiedText = t('clipboard-button.inline-toast.success', 'Copied');\n return (\n <>\n {showCopySuccess && (\n <InlineToast placement=\"top\" referenceElement={buttonRef.current}>\n {copiedText}\n </InlineToast>\n )}\n\n <Button\n onClick={copyTextCallback}\n icon={icon}\n variant={showCopySuccess ? 'success' : variant}\n {...buttonProps}\n className={cx(styles.button, showCopySuccess && styles.successButton, buttonProps.className)}\n ref={buttonRef}\n >\n {children}\n\n {showCopySuccess && (\n <div className={styles.successOverlay}>\n <Icon name=\"check\" />\n </div>\n )}\n </Button>\n </>\n );\n}\n\nconst copyText = async (text: string, buttonRef: React.MutableRefObject<HTMLButtonElement | null>) => {\n if (navigator.clipboard && window.isSecureContext) {\n return navigator.clipboard.writeText(text);\n } else {\n // Use a fallback method for browsers/contexts that don't support the Clipboard API.\n // See https://web.dev/async-clipboard/#feature-detection.\n // Use textarea so the user can copy multi-line content.\n const textarea = document.createElement('textarea');\n // Normally we'd append this to the body. However if we're inside a focus manager\n // from react-aria, we can't focus anything outside of the managed area.\n // Instead, let's append it to the button. Then we're guaranteed to be able to focus + copy.\n buttonRef.current?.appendChild(textarea);\n textarea.value = text;\n textarea.focus();\n textarea.select();\n document.execCommand('copy');\n textarea.remove();\n }\n};\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n button: css({\n position: 'relative',\n }),\n successButton: css({\n '> *': css({\n visibility: 'hidden',\n }),\n }),\n successOverlay: css({\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n left: 0,\n visibility: 'visible', // re-visible the overlay\n }),\n };\n};\n"],"names":[],"mappings":";;;;;;;;;;AAqBA,MAAM,wBAAwB,CAAA,GAAI,GAAA;AAO3B,SAAS,eAAA,CAAgB;AAAA,EAC9B,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAU;AACR,EAAA,MAAM,MAAA,GAAS,WAAW,SAAS,CAAA;AACnC,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5D,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA;AAEJ,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,SAAA,GAAY,WAAW,MAAM;AAC3B,QAAA,kBAAA,CAAmB,KAAK,CAAA;AAAA,MAC1B,GAAG,qBAAqB,CAAA;AAAA,IAC1B;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,aAAa,SAAS,CAAA;AAAA,IAC/B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,eAAe,CAAC,CAAA;AAEpB,EAAA,MAAM,SAAA,GAAY,OAAiC,IAAI,CAAA;AACvD,EAAA,MAAM,gBAAA,GAAmB,YAAY,YAAY;AAC/C,IAAA,MAAM,aAAa,OAAA,EAAQ;AAE3B,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,CAAS,YAAY,SAAS,CAAA;AACpC,MAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,MAAA,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,CAAkB,UAAA,CAAA;AAAA,IACpB,SAAS,CAAA,EAAG;AACV,MAAA,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAmB,UAAA,EAAY,CAAA,CAAA;AAAA,IACjC;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,eAAA,EAAiB,gBAAgB,CAAC,CAAA;AAE/C,EAAA,MAAM,UAAA,GAAa,CAAA,CAAE,uCAAA,EAAyC,QAAQ,CAAA;AACtE,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,eAAA,wBACE,WAAA,EAAA,EAAY,SAAA,EAAU,OAAM,gBAAA,EAAkB,SAAA,CAAU,SACtD,QAAA,EAAA,UAAA,EACH,CAAA;AAAA,oBAGF,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,gBAAA;AAAA,QACT,IAAA;AAAA,QACA,OAAA,EAAS,kBAAkB,SAAA,GAAY,OAAA;AAAA,QACtC,GAAG,WAAA;AAAA,QACJ,SAAA,EAAW,GAAG,MAAA,CAAO,MAAA,EAAQ,mBAAmB,MAAA,CAAO,aAAA,EAAe,YAAY,SAAS,CAAA;AAAA,QAC3F,GAAA,EAAK,SAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,UAAA,QAAA;AAAA,UAEA,eAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,gBACrB,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,CAAA,EACrB;AAAA;AAAA;AAAA;AAEJ,GAAA,EACF,CAAA;AAEJ;AAEA,MAAM,QAAA,GAAW,OAAO,IAAA,EAAc,SAAA,KAAgE;AAhGtG,EAAA,IAAA,EAAA;AAiGE,EAAA,IAAI,SAAA,CAAU,SAAA,IAAa,MAAA,CAAO,eAAA,EAAiB;AACjD,IAAA,OAAO,SAAA,CAAU,SAAA,CAAU,SAAA,CAAU,IAAI,CAAA;AAAA,EAC3C,CAAA,MAAO;AAIL,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAIlD,IAAA,CAAA,EAAA,GAAA,SAAA,CAAU,OAAA,KAAV,mBAAmB,WAAA,CAAY,QAAA,CAAA;AAC/B,IAAA,QAAA,CAAS,KAAA,GAAQ,IAAA;AACjB,IAAA,QAAA,CAAS,KAAA,EAAM;AACf,IAAA,QAAA,CAAS,MAAA,EAAO;AAChB,IAAA,QAAA,CAAS,YAAY,MAAM,CAAA;AAC3B,IAAA,QAAA,CAAS,MAAA,EAAO;AAAA,EAClB;AACF,CAAA;AAEA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAyB;AAC1C,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,CAAI;AAAA,MACV,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,IACD,eAAe,GAAA,CAAI;AAAA,MACjB,OAAO,GAAA,CAAI;AAAA,QACT,UAAA,EAAY;AAAA,OACb;AAAA,KACF,CAAA;AAAA,IACD,gBAAgB,GAAA,CAAI;AAAA,MAClB,QAAA,EAAU,UAAA;AAAA,MACV,GAAA,EAAK,CAAA;AAAA,MACL,MAAA,EAAQ,CAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,IAAA,EAAM,CAAA;AAAA,MACN,UAAA,EAAY;AAAA;AAAA,KACb;AAAA,GACH;AACF,CAAA;;;;"}