UNPKG

@codeworker.br/govbr-tw-react

Version:

Biblioteca de componentes React usando Tailwind CSS que implementa o Padrão Digital de Governo.

162 lines (161 loc) 7.68 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { jsx as _jsx } from "react/jsx-runtime"; import { cloneElement, isValidElement, useCallback, useEffect, useMemo, useRef, useState, } from "react"; import BASE_CLASSNAMES from "../../config/baseClassNames"; import { cn } from "../../libs/utils"; const copyWithFallback = (value) => __awaiter(void 0, void 0, void 0, function* () { if (typeof navigator !== "undefined" && navigator.clipboard && typeof navigator.clipboard.writeText === "function") { yield navigator.clipboard.writeText(value); return; } if (typeof document === "undefined") { throw new Error("Clipboard API is not available in this environment."); } const textarea = document.createElement("textarea"); textarea.value = value; textarea.setAttribute("readonly", ""); textarea.style.position = "fixed"; textarea.style.opacity = "0"; textarea.style.pointerEvents = "none"; textarea.style.top = "0"; textarea.style.left = "0"; document.body.appendChild(textarea); textarea.focus(); textarea.select(); const successful = document.execCommand("copy"); document.body.removeChild(textarea); if (!successful) { throw new Error("Unable to copy text to the clipboard."); } }); const composeEventHandlers = (theirHandler, ourHandler) => (event) => { theirHandler === null || theirHandler === void 0 ? void 0 : theirHandler(event); if (!event.defaultPrevented) { ourHandler(event); } }; const CopyAction = ({ targetRef, children, disabled = false, feedbackDuration = 2000, onCopy, onError, getText, className, }) => { var _a, _b, _c, _d, _e, _f, _g, _h; const [status, setStatus] = useState("idle"); const [error, setError] = useState(null); const resetTimerRef = useRef(); const clearResetTimer = useCallback(() => { if (resetTimerRef.current) { window.clearTimeout(resetTimerRef.current); resetTimerRef.current = undefined; } }, []); const reset = useCallback(() => { clearResetTimer(); setStatus("idle"); setError(null); }, [clearResetTimer]); useEffect(() => () => { clearResetTimer(); }, [clearResetTimer]); useEffect(() => { if (status === "idle" || feedbackDuration <= 0) { return; } resetTimerRef.current = window.setTimeout(() => { setStatus("idle"); setError(null); }, feedbackDuration); return () => { clearResetTimer(); }; }, [status, feedbackDuration, clearResetTimer]); const copy = useCallback(() => __awaiter(void 0, void 0, void 0, function* () { if (disabled) { return; } clearResetTimer(); try { const target = targetRef.current; if (!target) { throw new Error("CopyAction target element is not available."); } const resolvedText = (() => { var _a; if (getText) { const result = getText(target); if (typeof result !== "string") { throw new Error("CopyAction getText must return a string value."); } return result; } if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { return target.value; } const datasetValue = target.getAttribute("data-copy-value"); if (datasetValue !== null) { return datasetValue; } return (_a = target.textContent) !== null && _a !== void 0 ? _a : ""; })(); yield copyWithFallback(resolvedText); setStatus("success"); setError(null); onCopy === null || onCopy === void 0 ? void 0 : onCopy(resolvedText); } catch (cause) { const copyError = cause instanceof Error ? cause : new Error(typeof cause === "string" ? cause : "Failed to copy text value."); setStatus("error"); setError(copyError); onError === null || onError === void 0 ? void 0 : onError(copyError); throw copyError; } }), [clearResetTimer, disabled, getText, onCopy, onError, targetRef]); const target = (_a = targetRef.current) !== null && _a !== void 0 ? _a : null; const context = useMemo(() => ({ status, copied: status === "success", copy, reset, error, target, }), [status, copy, reset, error, target]); if (typeof children === "function") { return (_jsx("span", { className: cn((_b = BASE_CLASSNAMES.copyAction) === null || _b === void 0 ? void 0 : _b.root, className), "data-copy-status": status, "aria-live": "polite", children: children(context) })); } if (isValidElement(children)) { const child = children; const isButtonElement = typeof child.type === "string" && child.type.toLowerCase() === "button"; const mergedProps = { onClick: composeEventHandlers(child.props.onClick, (event) => { if (disabled || child.props.disabled) { event.preventDefault(); event.stopPropagation(); return; } void copy().catch(() => undefined); }), className: cn((_c = BASE_CLASSNAMES.copyAction) === null || _c === void 0 ? void 0 : _c.root, (_d = BASE_CLASSNAMES.copyAction) === null || _d === void 0 ? void 0 : _d.trigger, child.props.className, className), "data-copy-status": status, "aria-disabled": disabled || child.props.disabled ? true : undefined, }; if (isButtonElement) { mergedProps.type = (_e = child.props.type) !== null && _e !== void 0 ? _e : "button"; mergedProps.disabled = (_f = child.props.disabled) !== null && _f !== void 0 ? _f : disabled; } return cloneElement(child, mergedProps); } return (_jsx("button", { type: "button", className: cn("inline-flex items-center justify-center rounded-md border border-transparent bg-govbr-blue-warm-vivid-80 px-3 py-2 text-sm font-medium text-white transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-govbr-blue-warm-vivid-60 hover:bg-govbr-blue-warm-vivid-70 disabled:cursor-not-allowed disabled:opacity-70", (_g = BASE_CLASSNAMES.copyAction) === null || _g === void 0 ? void 0 : _g.root, (_h = BASE_CLASSNAMES.copyAction) === null || _h === void 0 ? void 0 : _h.trigger, className), onClick: () => { void copy().catch(() => undefined); }, "data-copy-status": status, disabled: disabled, children: children })); }; CopyAction.displayName = "CopyAction"; export { CopyAction };