1+ import { RefObject , useCallback , useRef } from "react" ;
2+ import { useSyncExternalStore } from "." ;
3+
4+ const askPermission = ( type : "clipboard-read" | "clipboard-write" ) => {
5+ return navigator . permissions . query ( {
6+ name : type as PermissionName
7+ } )
8+ . then ( permission => {
9+ if ( permission . state === "denied" ) {
10+ throw Error ( `Permission to ${ type . includes ( "read" ) ? "copy to" : "paste from" } Clipboard denied.` ) ;
11+ }
12+ } )
13+ . catch ( err => {
14+ throw err
15+ } ) ;
16+ }
17+ export const useClipboard = ( { useValue, target } : { useValue : boolean , target ?: RefObject < HTMLElement > | HTMLElement } ) => {
18+ const copy = useRef ( ( blob : Blob | Blob [ ] ) => (
19+ askPermission ( "clipboard-write" )
20+ . then ( ( ) => navigator . clipboard . write (
21+ Array . isArray ( blob )
22+ ? blob . map ( el => new ClipboardItem ( { [ el . type ] : el } ) )
23+ : [ new ClipboardItem ( { [ blob . type ] : blob } ) ]
24+ ) )
25+ . then ( ( ) => {
26+ const element = target
27+ ? ( target as RefObject < HTMLElement > ) . current
28+ ? ( target as RefObject < HTMLElement > ) . current
29+ : target as HTMLElement
30+ : document ;
31+ element ! . dispatchEvent ( new ClipboardEvent ( "copy" , {
32+ clipboardData : new DataTransfer ( )
33+ } ) )
34+ } )
35+ . catch ( err => {
36+ throw err ;
37+ } )
38+ ) ) ;
39+
40+ const copyText = useRef ( ( text : string ) => (
41+ askPermission ( "clipboard-write" )
42+ . then ( ( ) => navigator . clipboard . writeText ( text ) )
43+ . catch ( err => {
44+ throw err ;
45+ } )
46+ ) ) ;
47+
48+ const paste = useRef ( ( ) => (
49+ askPermission ( "clipboard-read" )
50+ . then ( ( ) => navigator . clipboard . read ( ) )
51+ . then ( items => {
52+ const promises = [ ] ;
53+ for ( const item of items ) {
54+ for ( let i = 0 , size = item . types . length ; i < size ; i ++ ) {
55+ promises . push ( item . getType ( item . types [ i ] ) ) ;
56+ }
57+ }
58+ return Promise . all ( promises ) ;
59+ } )
60+ . catch ( err => {
61+ throw err ;
62+ } )
63+ ) ) ;
64+
65+ const pasteText = useRef ( ( ) => (
66+ askPermission ( "clipboard-read" )
67+ . then ( ( ) => navigator . clipboard . readText ( ) )
68+ . catch ( err => {
69+ throw err ;
70+ } )
71+ ) ) ;
72+
73+ const value = useSyncExternalStore (
74+ useCallback ( notif => {
75+
76+ } , [ ] ) ,
77+ useCallback ( async ( ) => (
78+ askPermission ( "clipboard-read" )
79+ . then ( ( ) => pasteText . current )
80+ ) , [ ] )
81+ ) ;
82+
83+ if ( useValue ) {
84+ return [
85+ value ,
86+ copyText . current ,
87+ pasteText . current ,
88+ copy . current ,
89+ paste . current
90+ ]
91+ }
92+
93+ return [
94+ copyText . current ,
95+ pasteText . current ,
96+ copy . current ,
97+ paste . current
98+ ]
99+ }
0 commit comments