@@ -151,55 +151,47 @@ export function DataTable<TData, TValue>({
151151 }
152152
153153 // Copy/Paste functionality
154- const handleCopy = React . useCallback ( ( e : React . ClipboardEvent ) => {
155- if ( ! enableCopyPaste ) return
156-
157- const selection = window . getSelection ( )
158- if ( selection && selection . toString ( ) ) {
159- // Let browser handle the copy
160- return
161- }
154+ const handleCopy = React . useCallback ( ( ) => {
155+ if ( ! enableCopyPaste || ! hasSelection ) return
162156
163- // Copy selected rows as TSV
164- if ( hasSelection ) {
165- e . preventDefault ( )
166- const headers = enhancedColumns
157+ const headers = enhancedColumns
158+ . filter ( col => col . id !== 'select' )
159+ . map ( col => typeof col . header === 'string' ? col . header : col . id )
160+ . join ( '\t' )
161+
162+ const rows = selectedRows . map ( row =>
163+ enhancedColumns
167164 . filter ( col => col . id !== 'select' )
168- . map ( col => typeof col . header === 'string' ? col . header : col . id )
165+ . map ( col => {
166+ const cell = row . getValue ( col . id as string )
167+ return cell !== null && cell !== undefined ? String ( cell ) : ''
168+ } )
169169 . join ( '\t' )
170-
171- const rows = selectedRows . map ( row =>
172- enhancedColumns
173- . filter ( col => col . id !== 'select' )
174- . map ( col => {
175- const cell = row . getValue ( col . id as string )
176- return cell !== null && cell !== undefined ? String ( cell ) : ''
177- } )
178- . join ( '\t' )
179- ) . join ( '\n' )
170+ ) . join ( '\n' )
180171
181- const tsv = headers + '\n' + rows
182- e . clipboardData . setData ( 'text/plain' , tsv )
183- }
184- } , [ enableCopyPaste , hasSelection , selectedRows , enhancedColumns ] )
185-
186- // Add keyboard shortcuts for copy
187- React . useEffect ( ( ) => {
188- if ( ! enableCopyPaste ) return
189-
190- const handleKeyDown = ( e : KeyboardEvent ) => {
191- if ( ( e . ctrlKey || e . metaKey ) && e . key === 'c' && hasSelection ) {
192- // Copy will be handled by the copy event
193- document . dispatchEvent ( new ClipboardEvent ( 'copy' , {
194- clipboardData : new DataTransfer ( ) ,
195- bubbles : true
196- } ) )
172+ const tsv = headers + '\n' + rows
173+
174+ // Use modern clipboard API with error handling
175+ if ( navigator . clipboard && navigator . clipboard . writeText ) {
176+ navigator . clipboard . writeText ( tsv ) . catch ( err => {
177+ console . error ( 'Failed to copy to clipboard:' , err )
178+ } )
179+ } else {
180+ // Fallback for older browsers
181+ const textArea = document . createElement ( 'textarea' )
182+ textArea . value = tsv
183+ textArea . style . position = 'fixed'
184+ textArea . style . left = '-999999px'
185+ document . body . appendChild ( textArea )
186+ textArea . select ( )
187+ try {
188+ document . execCommand ( 'copy' )
189+ } catch ( err ) {
190+ console . error ( 'Failed to copy to clipboard:' , err )
197191 }
192+ document . body . removeChild ( textArea )
198193 }
199-
200- document . addEventListener ( 'keydown' , handleKeyDown )
201- return ( ) => document . removeEventListener ( 'keydown' , handleKeyDown )
202- } , [ enableCopyPaste , hasSelection ] )
194+ } , [ enableCopyPaste , hasSelection , selectedRows , enhancedColumns ] )
203195
204196 const renderFilters = ( ) => {
205197 // If enableMultipleFilters is true and filterConfigs are provided
@@ -284,7 +276,7 @@ export function DataTable<TData, TValue>({
284276 }
285277
286278 return (
287- < div onCopy = { handleCopy } >
279+ < div >
288280 { /* Bulk actions toolbar */ }
289281 { enableRowSelection && hasSelection && (
290282 < div className = "flex items-center gap-2 p-2 mb-2 bg-blue-50 border border-blue-200 rounded-md" >
@@ -296,16 +288,7 @@ export function DataTable<TData, TValue>({
296288 < Button
297289 variant = "outline"
298290 size = "sm"
299- onClick = { ( ) => {
300- const event = new ClipboardEvent ( 'copy' , {
301- clipboardData : new DataTransfer ( ) ,
302- bubbles : true
303- } )
304- handleCopy ( event as any )
305- if ( event . clipboardData ) {
306- navigator . clipboard . writeText ( event . clipboardData . getData ( 'text/plain' ) )
307- }
308- } }
291+ onClick = { handleCopy }
309292 className = "h-8"
310293 >
311294 < Copy className = "w-4 h-4 mr-1" />
0 commit comments