@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
JavaScript
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 };