@@ -45,6 +45,17 @@ export function parseValueFromNodes(nodes: NodeListOf<ChildNode>): string[][] {
4545 return result ;
4646}
4747
48+ export function parseValueFromText ( text : string ) : string | string [ ] [ ] {
49+ const rows = text
50+ . trim ( )
51+ . split ( '\n' )
52+ . map ( row => row . split ( '\t' ) ) ;
53+ if ( rows . length === 1 && rows [ 0 ] . length === 1 ) {
54+ return rows [ 0 ] [ 0 ] ;
55+ }
56+ return rows ;
57+ }
58+
4859export function parseValueFromElement (
4960 element : HTMLElement
5061) : string | string [ ] [ ] | null {
@@ -104,21 +115,35 @@ class PasteKeyHandler extends KeyHandler {
104115 'clip-path: "inset(50%)"; height: 1px; width: 1px; margin: -1px; overflow: hidden; padding 0; position: absolute;'
105116 ) ;
106117
107- const listener = ( ) : void => {
108- dummyInput . removeEventListener ( 'input' , listener ) ;
118+ const cleanup = ( ) : void => {
119+ dummyInput . removeEventListener ( 'paste' , pasteListener ) ;
120+ dummyInput . removeEventListener ( 'input' , inputListener ) ;
109121 dummyInput . remove ( ) ;
110-
111122 grid . focus ( ) ;
112- const value = parseValueFromElement ( dummyInput ) ;
123+ } ;
124+
125+ let plainText = '' ;
126+
127+ // Capture text/plain from the clipboard during the paste event.
128+ // HTML element parsing is used as a fallback if text/plain is unavailable.
129+ const pasteListener = ( e : Event ) : void => {
130+ const clipboardEvent = e as ClipboardEvent ;
131+ plainText =
132+ clipboardEvent . clipboardData ?. getData ( 'text/plain' ) ?? '' ;
133+ } ;
134+
135+ const inputListener = ( ) : void => {
136+ cleanup ( ) ;
137+ const value =
138+ ( plainText . length > 0 ? parseValueFromText ( plainText ) : null ) ??
139+ parseValueFromElement ( dummyInput ) ;
113140 if ( value != null ) {
114141 grid . pasteValue ( value ) ;
115142 }
116143 } ;
117144
118- // Listen for the `input` event, when there's a change to the HTML
119- // We could also listen to the `paste` event to get the clipboard data, but that's just text data
120- // By listening to `input`, we can get a table that's already parsed in HTML, which is easier to consume
121- dummyInput . addEventListener ( 'input' , listener ) ;
145+ dummyInput . addEventListener ( 'paste' , pasteListener ) ;
146+ dummyInput . addEventListener ( 'input' , inputListener ) ;
122147
123148 // Focus the element so it receives the paste event
124149 dummyInput . focus ( ) ;
0 commit comments