Merge pull request #241 from hashicorp/copy-button-using-clipboardjs

Copy component using ClipboardJS
This commit is contained in:
Randall Morey authored and GitHub committed 2020-09-30 11:38:48 -04:00
commit 2209ccc82a
8 files changed
+141 -3

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
{{#if this.isClipboardLibrarySupported}}
<span
id={{this.id}}
aria-labelledby={{this.copyableButtonId}}
class="copyable"
{{did-insert this.register}}
{{will-destroy this.destroy}}
>
<span class="copyable-content">
{{yield}}
</span>
<Rose::Button
id={{this.copyableButtonId}}
class="copyable-button"
@style="ghost"
@iconOnly={{this.icon}}
>{{@text}}</Rose::Button>
</span>
{{else}}
{{yield}}
{{/if}}
+79
View File
@@ -0,0 +1,79 @@
import Component from '@glimmer/component';
import ClipboardJS from 'clipboard';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { generateComponentID } from 'rose/utilities/component-auto-id';
import { task, timeout } from 'ember-concurrency';
import { set } from '@ember/object';
import { bind } from '@ember/runloop';
export default class CopyableComponent extends Component {
// =attributes
id = generateComponentID();
copyableButtonId = `copyable-button-${this.id}`;
icon = 'copy-action';
@tracked text;
@tracked clipboard;
/**
* A Ember Concurrency-based task that updates copy icon to a success state
* and back after 1 second. This icon flash indicates success on
* copy to clipboard action.
*
* NOTE: tasks are sort of attributes and sort of methods, but they are not
* language-level constructs. Thus we annotate this task as if it
* is an attribute.
* @type {Task}
*/
@task(function * () {
set(this, 'icon', 'copy-success');
yield timeout(1000);
set(this, 'icon', 'copy-action');
}).drop() successIconTimer;
// =methods
/**
* Checks for ClipboardJS support.
* @return {boolean}
*/
get isClipboardLibrarySupported() {
return ClipboardJS.isSupported();
}
/**
* When copy to clipboard is successful, begin timer to show success icon.
*/
onCopySuccess(clipboardEvent) {
clipboardEvent.clearSelection();
this.successIconTimer.perform();
}
// =actions
/**
* Initialize ClipboardJS library and register for it's events.
*/
@action
register() {
if(!this.clipboard) {
this.clipboard = new ClipboardJS(`#${this.copyableButtonId}`, {
text: () => this.args.text,
});
this.clipboard.on('success', bind(this, this.onCopySuccess));
}
}
/**
* Destroy ClipboardJS library instance and cancel icon timer.
*/
@action
destroy() {
this.clipboard?.destroy();
this.successIconTimer.cancelAll();
}
}
+4
View File
@@ -80,3 +80,7 @@
}
}
}
.copyable .copyable-button {
padding: 0rem;
}
+8
View File
@@ -20,6 +20,14 @@ module.exports = function (defaults) {
},
});
// Only import when in development or test mode
if (app.env.match(/(development)|(test)/i)) {
app.import('node_modules/clipboard/dist/clipboard.js');
}
else {
app.import('node_modules/clipboard/dist/clipboard.min.js');
}
// Use `app.import` to add additional libraries to the generated
// output files.
//
+2
View File
@@ -29,6 +29,7 @@
"devDependencies": {
"@babel/core": "^7.9.6",
"@ember/optional-features": "^1.3.0",
"@ember/render-modifiers": "^1.0.2",
"@glimmer/component": "^1.0.0",
"@glimmer/tracking": "^1.0.0",
"api": "*",
@@ -36,6 +37,7 @@
"babel-eslint": "^10.0.3",
"babel-loader": "^8.1.0",
"broccoli-asset-rev": "^3.0.0",
"clipboard": "^2.0.6",
"doctoc": "^1.4.0",
"ember-a11y-testing": "^3.0.0",
"ember-auto-import": "^1.5.3",
@@ -0,0 +1,15 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | copyable', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<Copyable @text="Copy me">text</Copyable>`);
assert.ok(find('.copyable'));
assert.equal(find('.copyable-content').textContent.trim(), 'text');
assert.equal(find('.copyable-button').textContent.trim(), 'Copy me');
});
});
+1 -1
View File
@@ -27,4 +27,4 @@ add-members: Add Members
add-hosts: Add Hosts
set-password: Set Password
change-password: Change Password
edit-form: Edit Form
edit-form: Edit Form
+10 -2
View File
@@ -2543,6 +2543,14 @@
ember-cli-babel "^6.16.0"
ember-compatibility-helpers "^1.1.1"
"@ember/render-modifiers@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz#2e87c48db49d922ce4850d707215caaac60d8444"
integrity sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ==
dependencies:
ember-cli-babel "^7.10.0"
ember-modifier-manager-polyfill "^1.1.0"
"@ember/test-helpers@^1.7.0", "@ember/test-helpers@^1.7.1":
version "1.7.1"
resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.7.1.tgz#cc22a954b3b46856518f034bd492a74e0482389f"
@@ -7307,7 +7315,7 @@ cli-width@^2.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
clipboard@^2.0.0:
clipboard@^2.0.0, clipboard@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==
@@ -9601,7 +9609,7 @@ ember-maybe-import-regenerator@^0.1.5, ember-maybe-import-regenerator@^0.1.6:
ember-cli-babel "^6.0.0-beta.4"
regenerator-runtime "^0.9.5"
ember-modifier-manager-polyfill@^1.2.0:
ember-modifier-manager-polyfill@^1.1.0, ember-modifier-manager-polyfill@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda"
integrity sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA==