@mikezimm/fps-library-v2
Version:
Library of reusable typescript/javascript functions, interfaces and constants
68 lines • 3.9 kB
JavaScript
/* 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