UNPKG

analytica-frontend-lib

Version:

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

251 lines (249 loc) 7.3 kB
// src/utils/utils.ts import { clsx } from "clsx"; import { twMerge } from "tailwind-merge"; function cn(...inputs) { return twMerge(clsx(inputs)); } // src/components/Text/Text.tsx import { jsx } from "react/jsx-runtime"; var Text = ({ children, size = "md", weight = "normal", color = "text-text-950", as, className = "", ...props }) => { let sizeClasses = ""; let weightClasses = ""; const sizeClassMap = { "2xs": "text-2xs", xs: "text-xs", sm: "text-sm", md: "text-md", lg: "text-lg", xl: "text-xl", "2xl": "text-2xl", "3xl": "text-3xl", "4xl": "text-4xl", "5xl": "text-5xl", "6xl": "text-6xl" }; sizeClasses = sizeClassMap[size] ?? sizeClassMap.md; const weightClassMap = { hairline: "font-hairline", light: "font-light", normal: "font-normal", medium: "font-medium", semibold: "font-semibold", bold: "font-bold", extrabold: "font-extrabold", black: "font-black" }; weightClasses = weightClassMap[weight] ?? weightClassMap.normal; const baseClasses = "font-primary"; const Component = as ?? "p"; return /* @__PURE__ */ jsx( Component, { className: cn(baseClasses, sizeClasses, weightClasses, color, className), ...props, children } ); }; var Text_default = Text; // src/components/ProgressCircle/ProgressCircle.tsx import { jsx as jsx2, jsxs } from "react/jsx-runtime"; var SIZE_CLASSES = { small: { container: "w-[90px] h-[90px]", // 90px circle from design specs strokeWidth: 4, // 4px stroke width - matches ProgressBar small (h-1) textSize: "2xl", // 24px for percentage (font-size: 24px) textWeight: "medium", // font-weight: 500 labelSize: "2xs", // Will be overridden with custom 8px in className labelWeight: "bold", // font-weight: 700 spacing: "gap-0", // Reduced gap between percentage and label for better spacing contentWidth: "max-w-[50px]" // Reduced width to fit text inside circle }, medium: { container: "w-[152px] h-[152px]", // 151.67px ≈ 152px circle from design specs strokeWidth: 8, // 8px stroke width - matches ProgressBar medium (h-2) textSize: "2xl", // 24px for percentage (font-size: 24px) textWeight: "medium", // font-weight: 500 labelSize: "xs", // 12px for status label (font-size: 12px) labelWeight: "medium", // font-weight: 500 (changed from bold) spacing: "gap-1", // 4px gap between percentage and label contentWidth: "max-w-[90px]" // Reduced width to fit text inside circle } }; var VARIANT_CLASSES = { blue: { background: "stroke-primary-100", // Light blue background (#BBDCF7) fill: "stroke-primary-700", // Blue for activity progress (#2271C4) textColor: "text-primary-700", // Blue text color (#2271C4) labelColor: "text-text-700" // Gray text for label (#525252) }, green: { background: "stroke-background-300", // Gray background (#D5D4D4 - matches design) fill: "stroke-success-200", // Green for performance (#84D3A2 - matches design) textColor: "text-text-800", // Dark gray text (#404040 - matches design) labelColor: "text-text-600" // Medium gray text for label (#737373 - matches design) } }; var ProgressCircle = ({ value, max = 100, size = "small", variant = "blue", label, showPercentage = true, className = "", labelClassName = "", percentageClassName = "" }) => { const safeValue = isNaN(value) ? 0 : value; const clampedValue = Math.max(0, Math.min(safeValue, max)); const percentage = max === 0 ? 0 : clampedValue / max * 100; const sizeClasses = SIZE_CLASSES[size]; const variantClasses = VARIANT_CLASSES[variant]; const radius = size === "small" ? 37 : 64; const circumference = 2 * Math.PI * radius; const strokeDashoffset = circumference - percentage / 100 * circumference; const center = size === "small" ? 45 : 76; const svgSize = size === "small" ? 90 : 152; return /* @__PURE__ */ jsxs( "div", { className: cn( "relative flex flex-col items-center justify-center", sizeClasses.container, "rounded-lg", className ), children: [ /* @__PURE__ */ jsxs( "svg", { className: "absolute inset-0 transform -rotate-90", width: svgSize, height: svgSize, viewBox: `0 0 ${svgSize} ${svgSize}`, "aria-hidden": "true", children: [ /* @__PURE__ */ jsx2( "circle", { cx: center, cy: center, r: radius, fill: "none", strokeWidth: sizeClasses.strokeWidth, className: cn(variantClasses.background, "rounded-lg") } ), /* @__PURE__ */ jsx2( "circle", { cx: center, cy: center, r: radius, fill: "none", strokeWidth: sizeClasses.strokeWidth, strokeLinecap: "round", strokeDasharray: circumference, strokeDashoffset, className: cn( variantClasses.fill, "transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg" ) } ) ] } ), /* @__PURE__ */ jsx2( "progress", { value: clampedValue, max, "aria-label": typeof label === "string" ? label : "Progress", className: "absolute opacity-0 w-0 h-0" } ), /* @__PURE__ */ jsxs( "div", { className: cn( "relative z-10 flex flex-col items-center justify-center", sizeClasses.spacing, sizeClasses.contentWidth ), children: [ showPercentage && /* @__PURE__ */ jsxs( Text_default, { size: sizeClasses.textSize, weight: sizeClasses.textWeight, className: cn( "text-center w-full", variantClasses.textColor, percentageClassName ), children: [ Math.round(percentage), "%" ] } ), label && /* @__PURE__ */ jsx2( Text_default, { as: "span", size: sizeClasses.labelSize, weight: sizeClasses.labelWeight, className: cn( variantClasses.labelColor, "text-center uppercase tracking-wide truncate w-full", labelClassName ), children: label } ) ] } ) ] } ); }; var ProgressCircle_default = ProgressCircle; export { ProgressCircle_default as default }; //# sourceMappingURL=index.mjs.map