@reallyland/really-elements
Version:
A collection of opinionated custom elements for the web
134 lines (133 loc) • 4.8 kB
JavaScript
import { __decorate } from "tslib";
import { css, html, LitElement } from 'lit';
import { property, query } from 'lit/decorators.js';
function toCopyNode(node, contentValue, noTextNode = false) {
let preNode = node;
if (noTextNode) {
preNode = document.createElement('pre');
preNode.textContent = contentValue;
preNode.style.position = 'absolute';
preNode.style.top = preNode.style.left = '200vh';
preNode.style.opacity = '0';
document.body.appendChild(preNode);
}
return { node: preNode, temporary: noTextNode };
}
export class ClipboardCopy extends LitElement {
constructor() {
super(...arguments);
this.forSlot = 'copy-for';
this.idSlot = 'copy-id';
this._idElement = null;
}
static { this.styles = [
css `
:host {
display: block;
}
* {
box-sizing: border-box;
}
`,
]; }
render() {
return html `<slot @slotchange="${this._assignSlotted}"></slot>`;
}
_assignSlotted() {
const slot = this._slot;
if (slot) {
const forSlot = this.forSlot;
const idSlot = this.idSlot;
const nodes = slot.assignedNodes();
const slotted = nodes.reduce((p, n) => {
if ((p.for && p.id) || n.nodeType !== Node.ELEMENT_NODE)
return p;
const isIdSlot = n.hasAttribute(idSlot);
const isForSlot = n.hasAttribute(forSlot);
const isIdSlotNull = p.id == null;
const isForSlotNull = p.for == null;
if (isIdSlot && isIdSlotNull) {
p.id = n;
}
else if (isForSlot && isForSlotNull) {
p.for = n;
}
else {
const forElement = isForSlotNull
? n.querySelector(`[${forSlot}]`)
: null;
const idElement = isIdSlotNull
? n.querySelector(`[${idSlot}]`)
: null;
if (forElement)
p.for = forElement;
if (idElement)
p.id = idElement;
}
return p;
}, { id: null, for: null });
const forSlotted = slotted.for;
if (forSlotted)
forSlotted.addEventListener('click', () => this._copyText());
this._idElement = slotted.id;
}
}
_copyText() {
let copySuccess = false;
let contentValue = '';
try {
const idElement = this._idElement;
if (idElement == null) {
throw new Error(`No element matches 'idSlot' is found`);
}
const isInputElement = idElement instanceof HTMLInputElement;
const isTextareaElement = idElement instanceof HTMLTextAreaElement;
const isAnchorElement = idElement instanceof HTMLAnchorElement;
contentValue =
(isInputElement || isTextareaElement
? idElement.value
: isAnchorElement
? idElement.href
: idElement.textContent) || '';
const nodeObj = toCopyNode(idElement, contentValue, isInputElement || isTextareaElement || isAnchorElement);
const copyNode = nodeObj.node;
const selection = getSelection();
const range = document.createRange();
selection?.removeAllRanges();
range.selectNodeContents(copyNode);
selection?.addRange(range);
copySuccess = document.execCommand('copy');
selection?.removeAllRanges();
if (nodeObj.temporary)
document.body.removeChild(copyNode);
if (!copySuccess)
throw new Error('Failed to copy');
}
catch (reason) {
this.dispatchEvent(new CustomEvent('copy-error', {
detail: { reason: reason },
bubbles: true,
composed: true,
}));
}
finally {
if (copySuccess) {
this.dispatchEvent(new CustomEvent('copy-success', {
detail: { value: contentValue },
bubbles: true,
composed: true,
}));
}
}
}
}
__decorate([
property({ type: String })
], ClipboardCopy.prototype, "forSlot", void 0);
__decorate([
property({ type: String })
], ClipboardCopy.prototype, "idSlot", void 0);
__decorate([
query('slot')
], ClipboardCopy.prototype, "_slot", void 0);
//# sourceMappingURL=clipboard-copy.js.map