analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
271 lines (266 loc) • 8.75 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/components/DownloadButton/DownloadButton.tsx
var DownloadButton_exports = {};
__export(DownloadButton_exports, {
default: () => DownloadButton_default
});
module.exports = __toCommonJS(DownloadButton_exports);
var import_react2 = require("react");
var import_phosphor_react = require("phosphor-react");
// src/components/IconButton/IconButton.tsx
var import_react = require("react");
// src/utils/utils.ts
var import_clsx = require("clsx");
var import_tailwind_merge = require("tailwind-merge");
function cn(...inputs) {
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
}
// src/components/IconButton/IconButton.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var IconButton = (0, import_react.forwardRef)(
({ icon, size = "md", active = false, className = "", disabled, ...props }, ref) => {
const baseClasses = [
"inline-flex",
"items-center",
"justify-center",
"rounded-lg",
"font-medium",
"bg-transparent",
"text-text-950",
"cursor-pointer",
"hover:bg-primary-600",
"hover:text-text",
"focus-visible:outline-none",
"focus-visible:ring-2",
"focus-visible:ring-offset-0",
"focus-visible:ring-indicator-info",
"disabled:opacity-50",
"disabled:cursor-not-allowed",
"disabled:pointer-events-none"
];
const sizeClasses = {
sm: ["w-6", "h-6", "text-sm"],
md: ["w-10", "h-10", "text-base"]
};
const activeClasses = active ? ["!bg-primary-50", "!text-primary-950", "hover:!bg-primary-100"] : [];
const allClasses = [
...baseClasses,
...sizeClasses[size],
...activeClasses
].join(" ");
const ariaLabel = props["aria-label"] ?? "Bot\xE3o de a\xE7\xE3o";
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
{
ref,
type: "button",
className: cn(allClasses, className),
disabled,
"aria-pressed": active,
"aria-label": ariaLabel,
...props,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center justify-center", children: icon })
}
);
}
);
IconButton.displayName = "IconButton";
var IconButton_default = IconButton;
// src/components/DownloadButton/DownloadButton.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var getMimeType = (url) => {
const extension = getFileExtension(url);
const mimeTypes = {
pdf: "application/pdf",
png: "image/png",
jpg: "image/jpeg",
jpeg: "image/jpeg",
mp3: "audio/mpeg",
mp4: "video/mp4",
vtt: "text/vtt"
};
return mimeTypes[extension] || "application/octet-stream";
};
var triggerDownload = async (url, filename) => {
try {
const response = await fetch(url, {
mode: "cors",
credentials: "same-origin"
});
if (!response.ok) {
throw new Error(
`Failed to fetch file: ${response.status} ${response.statusText}`
);
}
const blob = await response.blob();
const mimeType = getMimeType(url);
const typedBlob = new Blob([blob], { type: mimeType });
const blobUrl = URL.createObjectURL(typedBlob);
const link = document.createElement("a");
link.href = blobUrl;
link.download = filename;
link.rel = "noopener noreferrer";
document.body.appendChild(link);
link.click();
link.remove();
setTimeout(() => {
URL.revokeObjectURL(blobUrl);
}, 1e3);
} catch (error) {
console.warn("Fetch download failed, falling back to direct link:", error);
const link = document.createElement("a");
link.href = url;
link.download = filename;
link.rel = "noopener noreferrer";
link.target = "_blank";
document.body.appendChild(link);
link.click();
link.remove();
}
};
var getFileExtension = (url) => {
try {
const u = new URL(url, globalThis.location?.origin || "http://localhost");
url = u.pathname;
} catch {
}
const path = url.split(/[?#]/)[0];
const dot = path.lastIndexOf(".");
return dot > -1 ? path.slice(dot + 1).toLowerCase() : "file";
};
var generateFilename = (contentType, url, lessonTitle = "aula") => {
const sanitizedTitle = lessonTitle.toLowerCase().replaceAll(/[^a-z0-9\s]/g, "").replaceAll(/\s+/g, "-").substring(0, 50);
const extension = getFileExtension(url);
return `${sanitizedTitle}-${contentType}.${extension}`;
};
var DownloadButton = ({
content,
className,
onDownloadStart,
onDownloadComplete,
onDownloadError,
lessonTitle = "aula",
disabled = false
}) => {
const [isDownloading, setIsDownloading] = (0, import_react2.useState)(false);
const isValidUrl = (0, import_react2.useCallback)((url) => {
return Boolean(
url && url.trim() !== "" && url !== "undefined" && url !== "null"
);
}, []);
const getAvailableContent = (0, import_react2.useCallback)(() => {
const downloads = [];
if (isValidUrl(content.urlDoc)) {
downloads.push({
type: "documento",
url: content.urlDoc,
label: "Documento"
});
}
if (isValidUrl(content.urlInitialFrame)) {
downloads.push({
type: "quadro-inicial",
url: content.urlInitialFrame,
label: "Quadro Inicial"
});
}
if (isValidUrl(content.urlFinalFrame)) {
downloads.push({
type: "quadro-final",
url: content.urlFinalFrame,
label: "Quadro Final"
});
}
if (isValidUrl(content.urlPodcast)) {
downloads.push({
type: "podcast",
url: content.urlPodcast,
label: "Podcast"
});
}
if (isValidUrl(content.urlVideo)) {
downloads.push({ type: "video", url: content.urlVideo, label: "V\xEDdeo" });
}
return downloads;
}, [content, isValidUrl]);
const handleDownload = (0, import_react2.useCallback)(async () => {
if (disabled || isDownloading) return;
const availableContent = getAvailableContent();
if (availableContent.length === 0) {
return;
}
setIsDownloading(true);
try {
for (let i = 0; i < availableContent.length; i++) {
const item = availableContent[i];
try {
onDownloadStart?.(item.type);
const filename = generateFilename(item.type, item.url, lessonTitle);
await triggerDownload(item.url, filename);
onDownloadComplete?.(item.type);
if (i < availableContent.length - 1) {
await new Promise((resolve) => setTimeout(resolve, 200));
}
} catch (error) {
onDownloadError?.(
item.type,
error instanceof Error ? error : new Error(`Falha ao baixar ${item.label}`)
);
}
}
} finally {
setIsDownloading(false);
}
}, [
disabled,
isDownloading,
getAvailableContent,
lessonTitle,
onDownloadStart,
onDownloadComplete,
onDownloadError
]);
const hasContent = getAvailableContent().length > 0;
if (!hasContent) {
return null;
}
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: cn("flex items-center", className), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
IconButton_default,
{
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_phosphor_react.DownloadSimple, { size: 24 }),
onClick: handleDownload,
disabled: disabled || isDownloading,
"aria-label": (() => {
if (isDownloading) {
return "Baixando conte\xFAdo...";
}
const contentCount = getAvailableContent().length;
const suffix = contentCount > 1 ? "s" : "";
return `Baixar conte\xFAdo da aula (${contentCount} arquivo${suffix})`;
})(),
className: cn(
"!bg-transparent hover:!bg-black/10 transition-colors",
isDownloading && "opacity-60 cursor-not-allowed"
)
}
) });
};
var DownloadButton_default = DownloadButton;
//# sourceMappingURL=index.js.map