mirror of https://github.com/docusealco/docuseal
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							153 lines
						
					
					
						
							3.2 KiB
						
					
					
				
			
		
		
	
	
							153 lines
						
					
					
						
							3.2 KiB
						
					
					
				| // Source: https://github.com/github/clipboard-copy-element
 | |
| // License: MIT
 | |
| export default class extends HTMLElement {
 | |
|   constructor () {
 | |
|     super()
 | |
|     this.addEventListener('click', clicked)
 | |
|     this.addEventListener('focus', focused)
 | |
|     this.addEventListener('blur', blurred)
 | |
|   }
 | |
| 
 | |
|   connectedCallback () {
 | |
|     if (!this.hasAttribute('tabindex')) {
 | |
|       this.setAttribute('tabindex', '0')
 | |
|     }
 | |
| 
 | |
|     if (!this.hasAttribute('role')) {
 | |
|       this.setAttribute('role', 'button')
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   get value () {
 | |
|     return this.getAttribute('value') || ''
 | |
|   }
 | |
| 
 | |
|   set value (text) {
 | |
|     this.setAttribute('value', text)
 | |
|   }
 | |
| }
 | |
| 
 | |
| function createNode (text) {
 | |
|   const node = document.createElement('pre')
 | |
|   node.style.width = '1px'
 | |
|   node.style.height = '1px'
 | |
|   node.style.position = 'fixed'
 | |
|   node.style.top = '5px'
 | |
|   node.textContent = text
 | |
|   return node
 | |
| }
 | |
| 
 | |
| function copyNode (node) {
 | |
|   if ('clipboard' in navigator) {
 | |
|     return navigator.clipboard.writeText(node.textContent || '')
 | |
|   }
 | |
| 
 | |
|   const selection = getSelection()
 | |
|   if (selection == null) {
 | |
|     return Promise.reject(new Error())
 | |
|   }
 | |
| 
 | |
|   selection.removeAllRanges()
 | |
| 
 | |
|   const range = document.createRange()
 | |
|   range.selectNodeContents(node)
 | |
|   selection.addRange(range)
 | |
| 
 | |
|   document.execCommand('copy')
 | |
|   selection.removeAllRanges()
 | |
|   return Promise.resolve()
 | |
| }
 | |
| 
 | |
| function copyText (text) {
 | |
|   if ('clipboard' in navigator) {
 | |
|     return navigator.clipboard.writeText(text)
 | |
|   }
 | |
| 
 | |
|   const body = document.body
 | |
|   if (!body) {
 | |
|     return Promise.reject(new Error())
 | |
|   }
 | |
| 
 | |
|   const node = createNode(text)
 | |
|   body.appendChild(node)
 | |
|   copyNode(node)
 | |
|   body.removeChild(node)
 | |
|   return Promise.resolve()
 | |
| }
 | |
| 
 | |
| function copyTarget (content) {
 | |
|   if (
 | |
|     content instanceof HTMLInputElement ||
 | |
|     content instanceof HTMLTextAreaElement
 | |
|   ) {
 | |
|     return copyText(content.value)
 | |
|   } else if (
 | |
|     content instanceof HTMLAnchorElement &&
 | |
|     content.hasAttribute('href')
 | |
|   ) {
 | |
|     return copyText(content.href)
 | |
|   } else {
 | |
|     return copyNode(content)
 | |
|   }
 | |
| }
 | |
| 
 | |
| async function copy (button) {
 | |
|   const id = button.getAttribute('for')
 | |
|   const text = button.getAttribute('value')
 | |
| 
 | |
|   function trigger () {
 | |
|     button.dispatchEvent(new CustomEvent('clipboard-copy', { bubbles: true }))
 | |
|   }
 | |
| 
 | |
|   function toggleActiveIcon () {
 | |
|     if (button.classList.contains('swap')) {
 | |
|       button.classList.toggle('swap-active')
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (text) {
 | |
|     await copyText(text)
 | |
|     trigger()
 | |
|     toggleActiveIcon()
 | |
|   } else if (id) {
 | |
|     const root = 'getRootNode' in Element.prototype ? button.getRootNode() : button.ownerDocument
 | |
| 
 | |
|     if (!(root instanceof Document || ('ShadowRoot' in window && root instanceof ShadowRoot))) return
 | |
| 
 | |
|     const node = root.getElementById(id)
 | |
| 
 | |
|     if (node) {
 | |
|       await copyTarget(node)
 | |
|       trigger()
 | |
|       toggleActiveIcon()
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function clicked (event) {
 | |
|   const button = event.currentTarget
 | |
| 
 | |
|   if (button instanceof HTMLElement) {
 | |
|     copy(button)
 | |
|   }
 | |
| }
 | |
| 
 | |
| function keydown (event) {
 | |
|   if (event.key === ' ' || event.key === 'Enter') {
 | |
|     const button = event.currentTarget
 | |
| 
 | |
|     if (button instanceof HTMLElement) {
 | |
|       event.preventDefault()
 | |
|       copy(button)
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function focused (event) {
 | |
|   event.currentTarget.addEventListener('keydown', keydown)
 | |
| }
 | |
| 
 | |
| function blurred (event) {
 | |
|   event.currentTarget.removeEventListener('keydown', keydown)
 | |
| }
 |