@@ -20,6 +20,50 @@ export function useCopyCode() {
20
20
)
21
21
}
22
22
23
+ async function copyToClipboard ( text : string ) {
24
+ try {
25
+ return navigator . clipboard . writeText ( text )
26
+ } catch {
27
+ const element = document . createElement ( 'textarea' )
28
+ const previouslyFocusedElement = document . activeElement
29
+
30
+ element . value = text
31
+
32
+ // Prevent keyboard from showing on mobile
33
+ element . setAttribute ( 'readonly' , '' )
34
+
35
+ element . style . contain = 'strict'
36
+ element . style . position = 'absolute'
37
+ element . style . left = '-9999px'
38
+ element . style . fontSize = '12pt' // Prevent zooming on iOS
39
+
40
+ const selection = document . getSelection ( )
41
+ const originalRange = selection
42
+ ? selection . rangeCount > 0 && selection . getRangeAt ( 0 )
43
+ : null
44
+
45
+ document . body . appendChild ( element )
46
+ element . select ( )
47
+
48
+ // Explicit selection workaround for iOS
49
+ element . selectionStart = 0
50
+ element . selectionEnd = text . length
51
+
52
+ document . execCommand ( 'copy' )
53
+ document . body . removeChild ( element )
54
+
55
+ if ( originalRange ) {
56
+ selection ! . removeAllRanges ( ) // originalRange can't be truthy when selection is falsy
57
+ selection ! . addRange ( originalRange )
58
+ }
59
+
60
+ // Get the focus back on the previously focused element, if any
61
+ if ( previouslyFocusedElement ) {
62
+ ; ( previouslyFocusedElement as HTMLElement ) . focus ( )
63
+ }
64
+ }
65
+ }
66
+
23
67
function handleElement ( el : HTMLElement ) {
24
68
el . onclick = ( ) => {
25
69
const parent = el . parentElement
@@ -38,7 +82,7 @@ function handleElement(el: HTMLElement) {
38
82
text = text . replace ( / ^ * \$ / gm, '' )
39
83
}
40
84
41
- navigator . clipboard . writeText ( text ) . then ( ( ) => {
85
+ copyToClipboard ( text ) . then ( ( ) => {
42
86
el . classList . add ( 'copied' )
43
87
setTimeout ( ( ) => {
44
88
el . classList . remove ( 'copied' )
0 commit comments