1- import type { JSX } from "react" ;
1+ import { Children , isValidElement , type JSX } from "react" ;
22import * as ToastPrimitive from "@radix-ui/react-toast" ;
33import hotToast , {
44 resolveValue ,
@@ -343,6 +343,26 @@ const mapToVariant: Record<HotToast["type"], ToastVariant> = {
343343 custom : "warning" ,
344344} ;
345345
346+ const getTextContent = ( node : React . ReactNode ) : string => {
347+ if ( node === undefined || node === null || typeof node === "boolean" ) {
348+ return "" ;
349+ }
350+
351+ if ( typeof node === "string" || typeof node === "number" ) {
352+ return String ( node ) ;
353+ }
354+
355+ if ( Array . isArray ( node ) ) {
356+ return node . map ( getTextContent ) . join ( "" ) ;
357+ }
358+
359+ if ( isValidElement < { children ?: React . ReactNode } > ( node ) ) {
360+ return getTextContent ( node . props . children ) ;
361+ }
362+
363+ return Children . toArray ( node ) . map ( getTextContent ) . join ( "" ) ;
364+ } ;
365+
346366export const Toaster = ( ) => {
347367 const { toasts, handlers } = useToaster ( ) ;
348368 const { startPause, endPause } = handlers ;
@@ -352,6 +372,10 @@ export const Toaster = () => {
352372 { toasts . map ( ( toastData ) => {
353373 const toastVariant = mapToVariant [ toastData . type ] ;
354374 const children = resolveValue ( toastData . message , toastData ) ;
375+ const copyText =
376+ "copyText" in toastData && typeof toastData . copyText === "string"
377+ ? toastData . copyText
378+ : getTextContent ( children ) ;
355379
356380 return (
357381 < AnimatedToast
@@ -366,7 +390,7 @@ export const Toaster = () => {
366390 hotToast . remove ( toastData . id ) ;
367391 } }
368392 onCopy = { ( ) => {
369- navigator . clipboard . writeText ( children ?. toString ( ) ?? "" ) ;
393+ navigator . clipboard . writeText ( copyText ) ;
370394 } }
371395 icon = { toastData . icon }
372396 >
@@ -380,7 +404,9 @@ export const Toaster = () => {
380404 ) ;
381405} ;
382406
383- type Options = Pick < ToastOptions , "duration" | "id" | "icon" > ;
407+ type Options = Pick < ToastOptions , "duration" | "id" | "icon" > & {
408+ copyText ?: string ;
409+ } ;
384410
385411export const toast = {
386412 info : ( value : JSX . Element | string , options ?: Options ) =>
@@ -393,3 +419,7 @@ export const toast = {
393419 hotToast . success ( value , options ) ,
394420 dismiss : hotToast . dismiss ,
395421} ;
422+
423+ export const __testingToast__ = {
424+ getTextContent,
425+ } ;
0 commit comments