UNPKG

@mikezimm/fps-library-v2

Version:

Library of reusable typescript/javascript functions, interfaces and constants

68 lines 3.9 kB
/* 2026-04-30 Migrated from Drop-Zone | Entra */ import * as React from 'react'; import { useState } from 'react'; import { Icon } from '@fluentui/react/lib/Icon'; require('@mikezimm/fps-styles/dist/CopyCat.css'); export const CopyCat = ({ copyText, iconName = 'Copy', optionKey = '', hoverText, iconStyles, // iconStyles={{ root: { marginBottom: 4 } }} compStyles = {}, // compStyles={{ width: '220px'}} durationMs = 2000, confirmLabel, disabled = false, buttonLabel = '', joiner = '\n', onCopy, uniques = false, overlayIconName, // NEW overlayColor = '#7c3aed', // NEW (default purple) overlayScale = 0.5, // NEW overlayPosition = 'top-right', }) => { const [copied, setIsCopied] = useState(false); const handleClick = async (event) => { event.stopPropagation(); // prevents any parent click from happening if (disabled || !copyText) return; let useCopyText = copyText; if (uniques === true && Array.isArray(copyText)) { useCopyText = Array.from(new Set(copyText)); } // Determine if Ctrl (or Meta on Mac) is pressed const isCtrlPressed = event.ctrlKey || event.metaKey; // Decide what to copy const textToCopy = Array.isArray(useCopyText) ? isCtrlPressed ? JSON.stringify(useCopyText) // JS-style stringified array : useCopyText.join(joiner) // Multiline string : useCopyText; try { if (onCopy) { onCopy(event, textToCopy, optionKey); } else { await navigator.clipboard.writeText(textToCopy); } // Trigger copied state & animation for both cases setIsCopied(true); setTimeout(() => setIsCopied(false), durationMs); } catch (err) { console.warn('Copy failed:', err); } }; const positionStyles = { top: (overlayPosition === null || overlayPosition === void 0 ? void 0 : overlayPosition.includes('top')) ? 0 : undefined, bottom: (overlayPosition === null || overlayPosition === void 0 ? void 0 : overlayPosition.includes('bottom')) ? 0 : undefined, left: (overlayPosition === null || overlayPosition === void 0 ? void 0 : overlayPosition.includes('left')) ? 0 : undefined, right: (overlayPosition === null || overlayPosition === void 0 ? void 0 : overlayPosition.includes('right')) ? 0 : undefined, }; const className = [ 'copyCat-root', copyText ? 'clickable' : 'disabled', copied ? 'isCopied' : '' ].join(' '); return (React.createElement("span", { className: className, style: compStyles, onClick: copyText ? handleClick : undefined, title: `${hoverText} ${Array.isArray(copyText) ? 'CTRL-Click for JSON' : ''}` }, React.createElement("span", { className: "copyCat-icon-wrapper" }, React.createElement(Icon, { iconName: copied ? 'CheckMark' : iconName, styles: iconStyles, ariaLabel: copied ? 'Copied' : 'Copy to clipboard' }), overlayIconName && !copied && ( // only show overlay when not showing CheckMark React.createElement(Icon, { iconName: overlayIconName, className: "copyCat-overlay", style: { color: overlayColor, transform: `scale(${overlayScale})`, ...positionStyles, } }))), (buttonLabel || confirmLabel) && (React.createElement("span", { className: "copyCat-label-wrapper" }, React.createElement("span", { className: `copyCat-label default-label ${copied ? 'fade-out' : 'fade-in'}` }, buttonLabel), React.createElement("span", { className: `copyCat-label confirm-label ${copied ? 'fade-in' : 'fade-out'}` }, confirmLabel))))); }; //# sourceMappingURL=CopyCat.js.map