|
| 1 | +"use client"; |
| 2 | + |
| 3 | +import { forwardRef, useState, type ComponentProps, type ReactNode } from "react"; |
| 4 | +import { twMerge } from "tailwind-merge"; |
| 5 | +import { mergeDeep } from "../../helpers/merge-deep"; |
| 6 | +import { getTheme } from "../../theme-store"; |
| 7 | +import type { DeepPartial } from "../../types"; |
| 8 | +import { Tooltip } from "../Tooltip"; |
| 9 | +import { ClipboardWithIcon } from "./ClipboardWithIcon"; |
| 10 | +import type { FlowbiteClipboardWithIconTheme } from "./ClipboardWithIcon"; |
| 11 | +import { ClipboardWithIconText } from "./ClipboardWithIconText"; |
| 12 | +import type { FlowbiteClipboardWithIconTextTheme } from "./ClipboardWithIconText"; |
| 13 | +import { copyToClipboard } from "./helpers"; |
| 14 | + |
| 15 | +export interface FlowbiteClipboardTheme { |
| 16 | + button: { |
| 17 | + base: string; |
| 18 | + label: string; |
| 19 | + }; |
| 20 | + withIcon: FlowbiteClipboardWithIconTheme; |
| 21 | + withIconText: FlowbiteClipboardWithIconTextTheme; |
| 22 | +} |
| 23 | + |
| 24 | +export interface ClipboardProps extends ComponentProps<"button"> { |
| 25 | + valueToCopy: string; |
| 26 | + label?: ReactNode; |
| 27 | + theme?: DeepPartial<FlowbiteClipboardTheme>; |
| 28 | +} |
| 29 | + |
| 30 | +const ClipboardComponent = forwardRef<HTMLButtonElement, ClipboardProps>( |
| 31 | + ({ className, valueToCopy, label, theme: customTheme = {}, ...rest }, ref) => { |
| 32 | + const [isJustCopied, setIsJustCopied] = useState(false); |
| 33 | + |
| 34 | + const theme = mergeDeep(getTheme().clipboard.button, customTheme); |
| 35 | + |
| 36 | + return ( |
| 37 | + <Tooltip content={isJustCopied ? "Copied" : "Copy to clipboard"} className="[&_*]:cursor-pointer"> |
| 38 | + <button |
| 39 | + className={twMerge(theme.base, className)} |
| 40 | + onClick={() => copyToClipboard(valueToCopy, setIsJustCopied)} |
| 41 | + {...rest} |
| 42 | + ref={ref} |
| 43 | + > |
| 44 | + <span className={theme.label}>{label}</span> |
| 45 | + </button> |
| 46 | + </Tooltip> |
| 47 | + ); |
| 48 | + }, |
| 49 | +); |
| 50 | + |
| 51 | +ClipboardComponent.displayName = "Clipboard"; |
| 52 | +ClipboardWithIcon.displayName = "Clipboard.WithIcon"; |
| 53 | +ClipboardWithIconText.displayName = "Clipboard.WithIconText"; |
| 54 | + |
| 55 | +export const Clipboard = Object.assign(ClipboardComponent, { |
| 56 | + WithIcon: ClipboardWithIcon, |
| 57 | + WithIconText: ClipboardWithIconText, |
| 58 | +}); |
0 commit comments