import { useState } from "react"; import { cn } from "../../lib/utils"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; const REDACTED_TEXT_ALPHABET = "abcdefghjkmnpqrstuvwxyz23456789"; export function redactedPlaceholder(value: string): string { let state = 0x811c9dc5; for (let index = 0; index < value.length; index += 1) { state ^= value.charCodeAt(index); state = Math.imul(state, 0x01000193); } const nextChar = () => { state = Math.imul(state ^ (state >>> 13), 0x85ebca6b); state = Math.imul(state ^ (state >>> 16), 0xc2b2ae35); return REDACTED_TEXT_ALPHABET[Math.abs(state) % REDACTED_TEXT_ALPHABET.length] ?? "x"; }; return Array.from(value, (char) => { if (char === "@" || char === "." || char === "-" || char === "_") return char; return nextChar(); }).join(""); } export function RedactedSensitiveText(props: { readonly value: string | null | undefined; readonly ariaLabel: string; readonly revealTooltip: string; readonly hideTooltip: string; readonly className?: string; }) { const [revealed, setRevealed] = useState(false); const value = props.value?.trim(); const redacted = value ? redactedPlaceholder(value) : ""; if (!value) return null; return ( setRevealed((current) => !current)} aria-label={props.ariaLabel} > {revealed ? value : redacted} } /> {revealed ? props.hideTooltip : props.revealTooltip} ); }