presentation/components/clipboard.component.ts

presentation/components/clipboard.component.ts is a file in Bane's Lab Site. 39 lines of code and 5 definitions.

import { CHECK_ICON, CLIPBOARD_ICON, CROSS_ICON, ICON_BASE_CLASS } from "#configuration/icons/element.icons";
import { COPIED_CLASS, COPY_FEEDBACK_MS } from "#configuration/constants/clipboard.constants";
import { COPY_REFUSED } from "#configuration/strings/report.strings";
import { COPY_TITLE } from "#configuration/strings/clipboard.strings";
import { createElement } from "#core/factories/element.factory";
import { reportFailure } from "#core/reporters/failure.reporter";

const iconClass = function iconClass(icon: string): string {
    return `${ICON_BASE_CLASS} ${icon}`;
};

const flash = function flash(button: HTMLButtonElement, icon: HTMLElement, result: string): void {
    icon.className = iconClass(result);
    button.classList.toggle(COPIED_CLASS, result === CHECK_ICON);
    setTimeout(() => {
        icon.className = iconClass(CLIPBOARD_ICON);
        button.classList.remove(COPIED_CLASS);
    }, COPY_FEEDBACK_MS);
};

export const createCopyButton = function createCopyButton(
    text: () => string,
    className: string,
    title: string = COPY_TITLE,
): HTMLButtonElement {
    const icon = createElement("i", { className: iconClass(CLIPBOARD_ICON) });
    const button = createElement("button", { attributes: { title, type: "button" }, children: [icon], className });
    button.addEventListener("click", (event) => {
        event.preventDefault();
        event.stopPropagation();
        navigator.clipboard
            .writeText(text())
            .then(() => {
                flash(button, icon, CHECK_ICON);
            })
            .catch((error: unknown) => {
                reportFailure(COPY_REFUSED, error);
                flash(button, icon, CROSS_ICON);
            });
    });
    return button;
};