├── .gitignore ├── CODEOWNERS ├── src ├── index.ts ├── clipboard-copy-element-define.ts ├── clipboard.ts └── clipboard-copy-element.ts ├── tsconfig.json ├── .github └── workflows │ ├── nodejs.yml │ └── publish.yml ├── web-test-runner.config.js ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .eslintrc.json ├── LICENSE ├── README.md ├── package.json ├── examples └── index.html ├── test └── test.js └── custom-elements.json /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @github/primer-reviewers 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import {ClipboardCopyElement} from './clipboard-copy-element.js' 2 | 3 | export {ClipboardCopyElement} 4 | export default ClipboardCopyElement 5 | 6 | export * from './clipboard-copy-element-define.js' 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es2020", 4 | "target": "es2017", 5 | "strict": true, 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "outDir": "dist", 9 | "lib": ["dom", "dom.iterable", "es2020"], 10 | "removeComments": true 11 | }, 12 | "files": ["src/index.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: push 4 | permissions: 5 | contents: read 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Use Node.js 18.x 12 | uses: actions/setup-node@v1 13 | with: 14 | node-version: 18.x 15 | - name: npm install, build, and test 16 | run: | 17 | npm install 18 | npm run build --if-present 19 | npm test 20 | env: 21 | CI: true 22 | -------------------------------------------------------------------------------- /web-test-runner.config.js: -------------------------------------------------------------------------------- 1 | import {esbuildPlugin} from '@web/dev-server-esbuild' 2 | import {playwrightLauncher} from '@web/test-runner-playwright' 3 | const getBrowser = product => 4 | playwrightLauncher({ 5 | product, 6 | createBrowserContext: ({browser}) => { 7 | return browser.newContext({permissions: ['clipboard-read']}) 8 | }, 9 | }) 10 | 11 | export default { 12 | files: ['test/*'], 13 | nodeResolve: true, 14 | plugins: [esbuildPlugin({ts: true, target: 'es2020'})], 15 | browsers: [getBrowser('chromium')], 16 | testFramework: { 17 | config: { 18 | timeout: 1000, 19 | }, 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | publish-npm: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 18 18 | registry-url: https://registry.npmjs.org/ 19 | cache: npm 20 | - run: npm ci 21 | - run: npm test 22 | - run: npm version ${TAG_NAME} --git-tag-version=false 23 | env: 24 | TAG_NAME: ${{ github.event.release.tag_name }} 25 | - run: npm whoami; npm --ignore-scripts publish 26 | env: 27 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 28 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.222.0/containers/javascript-node/.devcontainer/base.Dockerfile 2 | 3 | # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster 4 | ARG VARIANT="16" 5 | FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} 6 | 7 | # [Optional] Uncomment this section to install additional OS packages. 8 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 9 | # && apt-get -y install --no-install-recommends 10 | 11 | # [Optional] Uncomment if you want to install an additional version of node using nvm 12 | # ARG EXTRA_NODE_VERSION=10 13 | # RUN su node -c "source/usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" 14 | 15 | # [Optional] Uncomment if you want to install more global node modules 16 | # RUN su node -c "npm install -g " 17 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": [ 4 | "plugin:github/browser", 5 | "plugin:github/recommended", 6 | "plugin:github/typescript", 7 | "plugin:custom-elements/recommended" 8 | ], 9 | "rules": { 10 | "custom-elements/tag-name-matches-class": [ 11 | "error", 12 | { 13 | "suffix": "Element" 14 | } 15 | ], 16 | "custom-elements/define-tag-after-class-definition": "off", 17 | "custom-elements/no-method-prefixed-with-on": "off", 18 | "custom-elements/expose-class-on-global": "off", 19 | "import/extensions": ["error", "always"], 20 | "import/no-unresolved": "off" 21 | }, 22 | "overrides": [ 23 | { 24 | "files": "src/*-define.ts", 25 | "rules": { 26 | "@typescript-eslint/no-namespace": "off" 27 | } 28 | }, 29 | { 30 | "files": "test/**/*.js", 31 | "rules": { 32 | "github/unescaped-html-literal": "off", 33 | "github/no-inner-html": "off", 34 | "i18n-text/no-en": "off" 35 | }, 36 | "env": { 37 | "mocha": true 38 | } 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /src/clipboard-copy-element-define.ts: -------------------------------------------------------------------------------- 1 | import {ClipboardCopyElement} from './clipboard-copy-element.js' 2 | 3 | const root = (typeof globalThis !== 'undefined' ? globalThis : window) as typeof window 4 | try { 5 | root.ClipboardCopyElement = ClipboardCopyElement.define() 6 | } catch (e: unknown) { 7 | if ( 8 | !(root.DOMException && e instanceof DOMException && e.name === 'NotSupportedError') && 9 | !(e instanceof ReferenceError) 10 | ) { 11 | throw e 12 | } 13 | } 14 | 15 | type JSXBase = JSX.IntrinsicElements extends {span: unknown} 16 | ? JSX.IntrinsicElements 17 | : Record> 18 | declare global { 19 | interface Window { 20 | ClipboardCopyElement: typeof ClipboardCopyElement 21 | } 22 | interface HTMLElementTagNameMap { 23 | 'clipboard-copy': ClipboardCopyElement 24 | } 25 | namespace JSX { 26 | interface IntrinsicElements { 27 | ['clipboard-copy']: JSXBase['span'] & Partial> 28 | } 29 | } 30 | } 31 | 32 | export default ClipboardCopyElement 33 | export * from './clipboard-copy-element.js' 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 GitHub, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.222.0/containers/javascript-node 3 | { 4 | "name": "Node.js", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | // Update 'VARIANT' to pick a Node version: 16, 14, 12. 8 | // Append -bullseye or -buster to pin to an OS version. 9 | // Use -bullseye variants on local arm64/Apple Silicon. 10 | "args": { "VARIANT": "16" } 11 | }, 12 | 13 | // Set *default* container specific settings.json values on container create. 14 | "settings": {}, 15 | 16 | // Add the IDs of extensions you want installed when the container is created. 17 | "extensions": [ 18 | "dbaeumer.vscode-eslint" 19 | ], 20 | 21 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 22 | // "forwardPorts": [], 23 | 24 | // Use 'postCreateCommand' to run commands after the container is created. 25 | // "postCreateCommand": "yarn install", 26 | 27 | // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 28 | "remoteUser": "node", 29 | "features": { 30 | "git": "latest" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/clipboard.ts: -------------------------------------------------------------------------------- 1 | function createNode(text: string): Element { 2 | const node = document.createElement('pre') 3 | node.style.width = '1px' 4 | node.style.height = '1px' 5 | node.style.position = 'fixed' 6 | node.style.top = '5px' 7 | node.textContent = text 8 | return node 9 | } 10 | 11 | export function copyNode(node: Element): Promise { 12 | if ('clipboard' in navigator) { 13 | return navigator.clipboard.writeText(node.textContent || '') 14 | } 15 | 16 | const selection = getSelection() 17 | if (selection == null) { 18 | return Promise.reject(new Error()) 19 | } 20 | 21 | selection.removeAllRanges() 22 | 23 | const range = document.createRange() 24 | range.selectNodeContents(node) 25 | selection.addRange(range) 26 | 27 | document.execCommand('copy') 28 | selection.removeAllRanges() 29 | return Promise.resolve() 30 | } 31 | 32 | export function copyText(text: string): Promise { 33 | if ('clipboard' in navigator) { 34 | return navigator.clipboard.writeText(text) 35 | } 36 | 37 | const body = document.body 38 | if (!body) { 39 | return Promise.reject(new Error()) 40 | } 41 | 42 | const node = createNode(text) 43 | body.appendChild(node) 44 | copyNode(node) 45 | body.removeChild(node) 46 | return Promise.resolve() 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # <clipboard-copy> element 2 | 3 | Copy element text content or input values to the clipboard. 4 | 5 | ## Installation 6 | 7 | ``` 8 | $ npm install --save @github/clipboard-copy-element 9 | ``` 10 | 11 | ## Usage 12 | 13 | ### Script 14 | 15 | Import as ES modules: 16 | 17 | ```js 18 | import '@github/clipboard-copy-element' 19 | ``` 20 | 21 | With a script tag: 22 | 23 | ```html 24 | 6 | 7 | 35 | 46 | 47 | 48 |
49 |

Demo

50 |
51 |
52 |

Copy from value attribute:

53 | 54 | Copy 55 | 56 | 57 |
58 |
59 | 60 |
61 |

Copy from an element specified by the for attribute:

62 |
@hubot copied from <div>
63 | 64 | Copy 65 | 66 | 67 |
68 |
69 | 70 |
71 |
75 | 76 | Copy 77 | 78 | 79 |
80 |
81 | 82 |
83 | 87 |
88 | 89 | 90 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | import {assert} from '@open-wc/testing' 2 | import {ClipboardCopyElement} from '../src/index.ts' 3 | 4 | describe('clipboard-copy element', function () { 5 | describe('element creation', function () { 6 | it('creates from document.createElement', function () { 7 | const el = document.createElement('clipboard-copy') 8 | assert.equal('CLIPBOARD-COPY', el.nodeName) 9 | assert(el instanceof ClipboardCopyElement) 10 | assert(el instanceof window.ClipboardCopyElement) 11 | }) 12 | 13 | it('creates from constructor', function () { 14 | const el = new window.ClipboardCopyElement() 15 | assert.equal('CLIPBOARD-COPY', el.nodeName) 16 | }) 17 | }) 18 | 19 | describe('clicking the button', function () { 20 | beforeEach(function () { 21 | const container = document.createElement('div') 22 | container.innerHTML = ` 23 | 24 | Copy 25 | ` 26 | document.body.append(container) 27 | }) 28 | 29 | afterEach(function () { 30 | document.body.innerHTML = '' 31 | }) 32 | 33 | it('retains focus on the button', function () { 34 | const button = document.querySelector('clipboard-copy') 35 | button.focus() 36 | assert.equal(document.activeElement, button) 37 | button.click() 38 | assert.equal(document.activeElement, button) 39 | }) 40 | }) 41 | 42 | describe('target element', function () { 43 | const nativeClipboard = navigator.clipboard 44 | let whenCopied 45 | 46 | beforeEach(function () { 47 | const container = document.createElement('div') 48 | container.innerHTML = ` 49 | 50 | Copy 51 | ` 52 | document.body.append(container) 53 | 54 | let copiedText = null 55 | defineClipboard({ 56 | writeText(text) { 57 | copiedText = text 58 | return Promise.resolve() 59 | }, 60 | readText() { 61 | return Promise.resolve(copiedText) 62 | }, 63 | }) 64 | 65 | whenCopied = new Promise(resolve => { 66 | document.addEventListener('clipboard-copy', () => resolve(copiedText), { 67 | once: true, 68 | }) 69 | }) 70 | }) 71 | 72 | afterEach(function () { 73 | document.body.innerHTML = '' 74 | defineClipboard(nativeClipboard) 75 | }) 76 | 77 | it('node', async function () { 78 | const target = document.createElement('div') 79 | target.innerHTML = 'Hello world!' 80 | target.id = 'copy-target' 81 | document.body.append(target) 82 | 83 | const button = document.querySelector('clipboard-copy') 84 | button.click() 85 | 86 | const text = await whenCopied 87 | assert.equal(text, 'Hello world!') 88 | }) 89 | 90 | it('hidden input', async function () { 91 | const target = document.createElement('input') 92 | target.type = 'hidden' 93 | target.value = 'Hello world!' 94 | target.id = 'copy-target' 95 | document.body.append(target) 96 | 97 | const button = document.querySelector('clipboard-copy') 98 | button.click() 99 | 100 | const text = await whenCopied 101 | assert.equal(text, 'Hello world!') 102 | }) 103 | 104 | it('input field', async function () { 105 | const target = document.createElement('input') 106 | target.value = 'Hello world!' 107 | target.id = 'copy-target' 108 | document.body.append(target) 109 | 110 | const button = document.querySelector('clipboard-copy') 111 | button.click() 112 | 113 | const text = await whenCopied 114 | assert.equal(text, 'Hello world!') 115 | }) 116 | 117 | it('textarea', async function () { 118 | const target = document.createElement('textarea') 119 | target.value = 'Hello world!' 120 | target.id = 'copy-target' 121 | document.body.append(target) 122 | 123 | const button = document.querySelector('clipboard-copy') 124 | button.click() 125 | 126 | const text = await whenCopied 127 | assert.equal(text, 'Hello world!') 128 | }) 129 | 130 | it('a[href]', async function () { 131 | const target = document.createElement('a') 132 | target.href = '/hello#world' 133 | target.textContent = 'I am a link' 134 | target.id = 'copy-target' 135 | document.body.append(target) 136 | 137 | const button = document.querySelector('clipboard-copy') 138 | button.click() 139 | 140 | const text = await whenCopied 141 | assert.equal(text, `${location.origin}/hello#world`) 142 | }) 143 | 144 | it('a[id]', async function () { 145 | const target = document.createElement('a') 146 | target.textContent = 'I am a link' 147 | target.id = 'copy-target' 148 | document.body.append(target) 149 | 150 | const button = document.querySelector('clipboard-copy') 151 | button.click() 152 | 153 | const text = await whenCopied 154 | assert.equal(text, 'I am a link') 155 | }) 156 | 157 | it('does not copy when disabled', async function () { 158 | const target = document.createElement('div') 159 | target.innerHTML = 'Hello world!' 160 | target.id = 'copy-target' 161 | document.body.append(target) 162 | 163 | const button = document.querySelector('clipboard-copy') 164 | button.setAttribute('aria-disabled', 'true') 165 | 166 | let fired = false 167 | document.addEventListener( 168 | 'clipboard-copy', 169 | () => { 170 | fired = true 171 | }, 172 | {once: true}, 173 | ) 174 | 175 | button.click() 176 | 177 | await new Promise(setTimeout) 178 | assert.equal(fired, false) 179 | assert.equal(null, await navigator.clipboard.readText()) 180 | }) 181 | }) 182 | 183 | describe('shadow DOM context', function () { 184 | const nativeClipboard = navigator.clipboard 185 | let whenCopied 186 | beforeEach(function () { 187 | const container = document.createElement('div') 188 | container.id = 'shadow' 189 | const elementInDocument = document.createElement('div') 190 | elementInDocument.id = 'copy-target' 191 | elementInDocument.textContent = 'Target in Document' 192 | const shadowRoot = container.attachShadow({mode: 'open'}) 193 | shadowRoot.innerHTML = ` 194 | 195 | Copy 196 | 197 |
Target in shadowRoot
` 198 | document.body.append(container) 199 | document.body.append(elementInDocument) 200 | container.click() 201 | 202 | let copiedText = null 203 | defineClipboard({ 204 | writeText(text) { 205 | copiedText = text 206 | return Promise.resolve() 207 | }, 208 | }) 209 | 210 | whenCopied = new Promise(resolve => { 211 | shadowRoot.addEventListener('clipboard-copy', () => resolve(copiedText), {once: true}) 212 | }) 213 | }) 214 | 215 | afterEach(function () { 216 | document.body.innerHTML = '' 217 | defineClipboard(nativeClipboard) 218 | }) 219 | 220 | it('copies from within its shadow root', async function () { 221 | const shadow = document.querySelector('#shadow') 222 | shadow.shadowRoot.querySelector('clipboard-copy').click() 223 | 224 | const text = await whenCopied 225 | assert.equal(text, 'Target in shadowRoot') 226 | }) 227 | }) 228 | }) 229 | 230 | function defineClipboard(customClipboard) { 231 | Object.defineProperty(navigator, 'clipboard', { 232 | enumerable: false, 233 | configurable: true, 234 | get() { 235 | return customClipboard 236 | }, 237 | }) 238 | } 239 | -------------------------------------------------------------------------------- /custom-elements.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": "1.0.0", 3 | "readme": "", 4 | "modules": [ 5 | { 6 | "kind": "javascript-module", 7 | "path": "dist/bundle.js", 8 | "declarations": [ 9 | { 10 | "kind": "variable", 11 | "name": "ClipboardCopyElement", 12 | "default": "class extends HTMLElement {\n static define(tag = \"clipboard-copy\", registry = customElements) {\n registry.define(tag, this);\n return this;\n }\n constructor() {\n super();\n this.addEventListener(\"click\", clicked);\n this.addEventListener(\"focus\", focused);\n this.addEventListener(\"blur\", blurred);\n }\n connectedCallback() {\n if (!this.hasAttribute(\"tabindex\")) {\n this.setAttribute(\"tabindex\", \"0\");\n }\n if (!this.hasAttribute(\"role\")) {\n this.setAttribute(\"role\", \"button\");\n }\n }\n get value() {\n return this.getAttribute(\"value\") || \"\";\n }\n set value(text) {\n this.setAttribute(\"value\", text);\n }\n}" 13 | }, 14 | { 15 | "kind": "variable", 16 | "name": "dist_default", 17 | "default": "ClipboardCopyElement" 18 | } 19 | ], 20 | "exports": [ 21 | { 22 | "kind": "js", 23 | "name": "ClipboardCopyElement", 24 | "declaration": { 25 | "name": "ClipboardCopyElement", 26 | "module": "dist/bundle.js" 27 | } 28 | }, 29 | { 30 | "kind": "js", 31 | "name": "default", 32 | "declaration": { 33 | "name": "dist_default", 34 | "module": "dist/bundle.js" 35 | } 36 | } 37 | ] 38 | }, 39 | { 40 | "kind": "javascript-module", 41 | "path": "dist/clipboard-copy-element-define.js", 42 | "declarations": [], 43 | "exports": [ 44 | { 45 | "kind": "js", 46 | "name": "default", 47 | "declaration": { 48 | "name": "ClipboardCopyElement", 49 | "module": "dist/clipboard-copy-element-define.js" 50 | } 51 | }, 52 | { 53 | "kind": "js", 54 | "name": "*", 55 | "declaration": { 56 | "name": "*", 57 | "package": "./clipboard-copy-element.js" 58 | } 59 | } 60 | ] 61 | }, 62 | { 63 | "kind": "javascript-module", 64 | "path": "dist/clipboard-copy-element.js", 65 | "declarations": [ 66 | { 67 | "kind": "class", 68 | "description": "", 69 | "name": "ClipboardCopyElement", 70 | "members": [ 71 | { 72 | "kind": "method", 73 | "name": "define", 74 | "static": true, 75 | "parameters": [ 76 | { 77 | "name": "tag", 78 | "default": "'clipboard-copy'" 79 | }, 80 | { 81 | "name": "registry", 82 | "default": "customElements" 83 | } 84 | ] 85 | }, 86 | { 87 | "kind": "field", 88 | "name": "value" 89 | } 90 | ], 91 | "superclass": { 92 | "name": "HTMLElement" 93 | }, 94 | "customElement": true 95 | } 96 | ], 97 | "exports": [ 98 | { 99 | "kind": "js", 100 | "name": "ClipboardCopyElement", 101 | "declaration": { 102 | "name": "ClipboardCopyElement", 103 | "module": "dist/clipboard-copy-element.js" 104 | } 105 | } 106 | ] 107 | }, 108 | { 109 | "kind": "javascript-module", 110 | "path": "dist/clipboard.js", 111 | "declarations": [ 112 | { 113 | "kind": "function", 114 | "name": "copyNode", 115 | "parameters": [ 116 | { 117 | "name": "node" 118 | } 119 | ] 120 | }, 121 | { 122 | "kind": "function", 123 | "name": "copyText", 124 | "parameters": [ 125 | { 126 | "name": "text" 127 | } 128 | ] 129 | } 130 | ], 131 | "exports": [ 132 | { 133 | "kind": "js", 134 | "name": "copyNode", 135 | "declaration": { 136 | "name": "copyNode", 137 | "module": "dist/clipboard.js" 138 | } 139 | }, 140 | { 141 | "kind": "js", 142 | "name": "copyText", 143 | "declaration": { 144 | "name": "copyText", 145 | "module": "dist/clipboard.js" 146 | } 147 | } 148 | ] 149 | }, 150 | { 151 | "kind": "javascript-module", 152 | "path": "dist/index.js", 153 | "declarations": [], 154 | "exports": [ 155 | { 156 | "kind": "js", 157 | "name": "ClipboardCopyElement", 158 | "declaration": { 159 | "name": "ClipboardCopyElement", 160 | "module": "dist/index.js" 161 | } 162 | }, 163 | { 164 | "kind": "js", 165 | "name": "default", 166 | "declaration": { 167 | "name": "ClipboardCopyElement", 168 | "module": "dist/index.js" 169 | } 170 | }, 171 | { 172 | "kind": "js", 173 | "name": "*", 174 | "declaration": { 175 | "name": "*", 176 | "package": "./clipboard-copy-element-define.js" 177 | } 178 | } 179 | ] 180 | }, 181 | { 182 | "kind": "javascript-module", 183 | "path": "src/clipboard-copy-element-define.ts", 184 | "declarations": [], 185 | "exports": [ 186 | { 187 | "kind": "js", 188 | "name": "default", 189 | "declaration": { 190 | "name": "ClipboardCopyElement", 191 | "module": "src/clipboard-copy-element-define.ts" 192 | } 193 | }, 194 | { 195 | "kind": "js", 196 | "name": "*", 197 | "declaration": { 198 | "name": "*", 199 | "package": "./clipboard-copy-element.js" 200 | } 201 | } 202 | ] 203 | }, 204 | { 205 | "kind": "javascript-module", 206 | "path": "src/clipboard-copy-element.ts", 207 | "declarations": [ 208 | { 209 | "kind": "class", 210 | "description": "", 211 | "name": "ClipboardCopyElement", 212 | "members": [ 213 | { 214 | "kind": "method", 215 | "name": "define", 216 | "static": true, 217 | "parameters": [ 218 | { 219 | "name": "tag", 220 | "default": "'clipboard-copy'" 221 | }, 222 | { 223 | "name": "registry", 224 | "default": "customElements" 225 | } 226 | ] 227 | }, 228 | { 229 | "kind": "field", 230 | "name": "value", 231 | "type": { 232 | "text": "string" 233 | } 234 | } 235 | ], 236 | "superclass": { 237 | "name": "HTMLElement" 238 | }, 239 | "customElement": true 240 | } 241 | ], 242 | "exports": [ 243 | { 244 | "kind": "js", 245 | "name": "ClipboardCopyElement", 246 | "declaration": { 247 | "name": "ClipboardCopyElement", 248 | "module": "src/clipboard-copy-element.ts" 249 | } 250 | } 251 | ] 252 | }, 253 | { 254 | "kind": "javascript-module", 255 | "path": "src/clipboard.ts", 256 | "declarations": [ 257 | { 258 | "kind": "function", 259 | "name": "copyNode", 260 | "return": { 261 | "type": { 262 | "text": "Promise" 263 | } 264 | }, 265 | "parameters": [ 266 | { 267 | "name": "node", 268 | "type": { 269 | "text": "Element" 270 | } 271 | } 272 | ] 273 | }, 274 | { 275 | "kind": "function", 276 | "name": "copyText", 277 | "return": { 278 | "type": { 279 | "text": "Promise" 280 | } 281 | }, 282 | "parameters": [ 283 | { 284 | "name": "text", 285 | "type": { 286 | "text": "string" 287 | } 288 | } 289 | ] 290 | } 291 | ], 292 | "exports": [ 293 | { 294 | "kind": "js", 295 | "name": "copyNode", 296 | "declaration": { 297 | "name": "copyNode", 298 | "module": "src/clipboard.ts" 299 | } 300 | }, 301 | { 302 | "kind": "js", 303 | "name": "copyText", 304 | "declaration": { 305 | "name": "copyText", 306 | "module": "src/clipboard.ts" 307 | } 308 | } 309 | ] 310 | }, 311 | { 312 | "kind": "javascript-module", 313 | "path": "src/index.ts", 314 | "declarations": [], 315 | "exports": [ 316 | { 317 | "kind": "js", 318 | "name": "ClipboardCopyElement", 319 | "declaration": { 320 | "name": "ClipboardCopyElement", 321 | "module": "src/index.ts" 322 | } 323 | }, 324 | { 325 | "kind": "js", 326 | "name": "default", 327 | "declaration": { 328 | "name": "ClipboardCopyElement", 329 | "module": "src/index.ts" 330 | } 331 | }, 332 | { 333 | "kind": "js", 334 | "name": "*", 335 | "declaration": { 336 | "name": "*", 337 | "package": "./clipboard-copy-element-define.js" 338 | } 339 | } 340 | ] 341 | }, 342 | { 343 | "kind": "javascript-module", 344 | "path": "test/test.js", 345 | "declarations": [], 346 | "exports": [] 347 | } 348 | ] 349 | } 350 | --------------------------------------------------------------------------------