UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

271 lines (266 loc) 8.75 kB
"use strict"; 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