analytica-frontend-lib 1.0.36 → 1.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Progress circle size variants
6
+ */
7
+ type ProgressCircleSize = 'small' | 'medium';
8
+ /**
9
+ * Progress circle color variants
10
+ */
11
+ type ProgressCircleVariant = 'blue' | 'green';
12
+ /**
13
+ * ProgressCircle component props interface
14
+ */
15
+ type ProgressCircleProps = {
16
+ /** Progress value between 0 and 100 */
17
+ value: number;
18
+ /** Maximum value (defaults to 100) */
19
+ max?: number;
20
+ /** Size variant of the progress circle */
21
+ size?: ProgressCircleSize;
22
+ /** Color variant of the progress circle */
23
+ variant?: ProgressCircleVariant;
24
+ /** Optional label to display below percentage */
25
+ label?: ReactNode;
26
+ /** Show percentage text */
27
+ showPercentage?: boolean;
28
+ /** Additional CSS classes */
29
+ className?: string;
30
+ /** Label CSS classes */
31
+ labelClassName?: string;
32
+ /** Percentage text CSS classes */
33
+ percentageClassName?: string;
34
+ };
35
+ /**
36
+ * ProgressCircle component for Analytica Ensino platforms
37
+ *
38
+ * A circular progress indicator with size and color variants designed for tracking
39
+ * activity progress (blue) and performance metrics (green).
40
+ * Uses the Analytica Ensino Design System colors from styles.css with automatic
41
+ * light/dark mode support. Includes Text component integration for consistent typography.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // Basic progress circle
46
+ * <ProgressCircle value={65} />
47
+ *
48
+ * // Activity progress (blue)
49
+ * <ProgressCircle variant="blue" value={45} label="CONCLUÍDO" showPercentage />
50
+ *
51
+ * // Performance metrics (green)
52
+ * <ProgressCircle variant="green" size="medium" value={85} label="MÉDIA" />
53
+ *
54
+ * // Small size with custom max value
55
+ * <ProgressCircle size="small" value={3} max={5} showPercentage />
56
+ * ```
57
+ */
58
+ declare const ProgressCircle: ({ value, max, size, variant, label, showPercentage, className, labelClassName, percentageClassName, }: ProgressCircleProps) => react_jsx_runtime.JSX.Element;
59
+
60
+ export { type ProgressCircleProps, ProgressCircle as default };
@@ -0,0 +1,60 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Progress circle size variants
6
+ */
7
+ type ProgressCircleSize = 'small' | 'medium';
8
+ /**
9
+ * Progress circle color variants
10
+ */
11
+ type ProgressCircleVariant = 'blue' | 'green';
12
+ /**
13
+ * ProgressCircle component props interface
14
+ */
15
+ type ProgressCircleProps = {
16
+ /** Progress value between 0 and 100 */
17
+ value: number;
18
+ /** Maximum value (defaults to 100) */
19
+ max?: number;
20
+ /** Size variant of the progress circle */
21
+ size?: ProgressCircleSize;
22
+ /** Color variant of the progress circle */
23
+ variant?: ProgressCircleVariant;
24
+ /** Optional label to display below percentage */
25
+ label?: ReactNode;
26
+ /** Show percentage text */
27
+ showPercentage?: boolean;
28
+ /** Additional CSS classes */
29
+ className?: string;
30
+ /** Label CSS classes */
31
+ labelClassName?: string;
32
+ /** Percentage text CSS classes */
33
+ percentageClassName?: string;
34
+ };
35
+ /**
36
+ * ProgressCircle component for Analytica Ensino platforms
37
+ *
38
+ * A circular progress indicator with size and color variants designed for tracking
39
+ * activity progress (blue) and performance metrics (green).
40
+ * Uses the Analytica Ensino Design System colors from styles.css with automatic
41
+ * light/dark mode support. Includes Text component integration for consistent typography.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // Basic progress circle
46
+ * <ProgressCircle value={65} />
47
+ *
48
+ * // Activity progress (blue)
49
+ * <ProgressCircle variant="blue" value={45} label="CONCLUÍDO" showPercentage />
50
+ *
51
+ * // Performance metrics (green)
52
+ * <ProgressCircle variant="green" size="medium" value={85} label="MÉDIA" />
53
+ *
54
+ * // Small size with custom max value
55
+ * <ProgressCircle size="small" value={3} max={5} showPercentage />
56
+ * ```
57
+ */
58
+ declare const ProgressCircle: ({ value, max, size, variant, label, showPercentage, className, labelClassName, percentageClassName, }: ProgressCircleProps) => react_jsx_runtime.JSX.Element;
59
+
60
+ export { type ProgressCircleProps, ProgressCircle as default };
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/components/ProgressCircle/ProgressCircle.tsx
22
+ var ProgressCircle_exports = {};
23
+ __export(ProgressCircle_exports, {
24
+ default: () => ProgressCircle_default
25
+ });
26
+ module.exports = __toCommonJS(ProgressCircle_exports);
27
+
28
+ // src/components/Text/Text.tsx
29
+ var import_jsx_runtime = require("react/jsx-runtime");
30
+ var Text = ({
31
+ children,
32
+ size = "md",
33
+ weight = "normal",
34
+ color = "text-text-950",
35
+ as,
36
+ className = "",
37
+ ...props
38
+ }) => {
39
+ let sizeClasses = "";
40
+ let weightClasses = "";
41
+ const sizeClassMap = {
42
+ "2xs": "text-2xs",
43
+ xs: "text-xs",
44
+ sm: "text-sm",
45
+ md: "text-md",
46
+ lg: "text-lg",
47
+ xl: "text-xl",
48
+ "2xl": "text-2xl",
49
+ "3xl": "text-3xl",
50
+ "4xl": "text-4xl",
51
+ "5xl": "text-5xl",
52
+ "6xl": "text-6xl"
53
+ };
54
+ sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;
55
+ const weightClassMap = {
56
+ hairline: "font-hairline",
57
+ light: "font-light",
58
+ normal: "font-normal",
59
+ medium: "font-medium",
60
+ semibold: "font-semibold",
61
+ bold: "font-bold",
62
+ extrabold: "font-extrabold",
63
+ black: "font-black"
64
+ };
65
+ weightClasses = weightClassMap[weight] ?? weightClassMap.normal;
66
+ const baseClasses = "font-primary";
67
+ const Component = as ?? "p";
68
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
69
+ Component,
70
+ {
71
+ className: `${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`,
72
+ ...props,
73
+ children
74
+ }
75
+ );
76
+ };
77
+ var Text_default = Text;
78
+
79
+ // src/components/ProgressCircle/ProgressCircle.tsx
80
+ var import_jsx_runtime2 = require("react/jsx-runtime");
81
+ var SIZE_CLASSES = {
82
+ small: {
83
+ container: "w-[90px] h-[90px]",
84
+ // 90px circle from design specs
85
+ strokeWidth: 4,
86
+ // 4px stroke width - matches ProgressBar small (h-1)
87
+ textSize: "2xl",
88
+ // 24px for percentage (font-size: 24px)
89
+ textWeight: "medium",
90
+ // font-weight: 500
91
+ labelSize: "2xs",
92
+ // 10px for status label (closest to 8px design spec)
93
+ labelWeight: "bold",
94
+ // font-weight: 700
95
+ spacing: "gap-1"
96
+ // 4px gap between percentage and label
97
+ },
98
+ medium: {
99
+ container: "w-[152px] h-[152px]",
100
+ // 151.67px ≈ 152px circle from design specs
101
+ strokeWidth: 8,
102
+ // 8px stroke width - matches ProgressBar medium (h-2)
103
+ textSize: "2xl",
104
+ // 24px for percentage (font-size: 24px)
105
+ textWeight: "medium",
106
+ // font-weight: 500
107
+ labelSize: "xs",
108
+ // 12px for status label (font-size: 12px)
109
+ labelWeight: "medium",
110
+ // font-weight: 500 (changed from bold)
111
+ spacing: "gap-1"
112
+ // 4px gap between percentage and label
113
+ }
114
+ };
115
+ var VARIANT_CLASSES = {
116
+ blue: {
117
+ background: "stroke-primary-100",
118
+ // Light blue background (#BBDCF7)
119
+ fill: "stroke-primary-700",
120
+ // Blue for activity progress (#2271C4)
121
+ textColor: "text-primary-700",
122
+ // Blue text color (#2271C4)
123
+ labelColor: "text-text-700"
124
+ // Gray text for label (#525252)
125
+ },
126
+ green: {
127
+ background: "stroke-background-300",
128
+ // Gray background (#D5D4D4 - matches design)
129
+ fill: "stroke-success-200",
130
+ // Green for performance (#84D3A2 - matches design)
131
+ textColor: "text-text-800",
132
+ // Dark gray text (#404040 - matches design)
133
+ labelColor: "text-text-600"
134
+ // Medium gray text for label (#737373 - matches design)
135
+ }
136
+ };
137
+ var ProgressCircle = ({
138
+ value,
139
+ max = 100,
140
+ size = "small",
141
+ variant = "blue",
142
+ label,
143
+ showPercentage = true,
144
+ className = "",
145
+ labelClassName = "",
146
+ percentageClassName = ""
147
+ }) => {
148
+ const safeValue = isNaN(value) ? 0 : value;
149
+ const clampedValue = Math.max(0, Math.min(safeValue, max));
150
+ const percentage = max === 0 ? 0 : clampedValue / max * 100;
151
+ const sizeClasses = SIZE_CLASSES[size];
152
+ const variantClasses = VARIANT_CLASSES[variant];
153
+ const radius = size === "small" ? 37 : 64;
154
+ const circumference = 2 * Math.PI * radius;
155
+ const strokeDashoffset = circumference - percentage / 100 * circumference;
156
+ const center = size === "small" ? 45 : 76;
157
+ const svgSize = size === "small" ? 90 : 152;
158
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
159
+ "div",
160
+ {
161
+ className: `relative flex flex-col items-center justify-center ${sizeClasses.container} rounded-lg ${className}`,
162
+ children: [
163
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
164
+ "svg",
165
+ {
166
+ className: "absolute inset-0 transform -rotate-90",
167
+ width: svgSize,
168
+ height: svgSize,
169
+ viewBox: `0 0 ${svgSize} ${svgSize}`,
170
+ "aria-hidden": "true",
171
+ children: [
172
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
173
+ "circle",
174
+ {
175
+ cx: center,
176
+ cy: center,
177
+ r: radius,
178
+ fill: "none",
179
+ strokeWidth: sizeClasses.strokeWidth,
180
+ className: `${variantClasses.background} rounded-lg`
181
+ }
182
+ ),
183
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
184
+ "circle",
185
+ {
186
+ cx: center,
187
+ cy: center,
188
+ r: radius,
189
+ fill: "none",
190
+ strokeWidth: sizeClasses.strokeWidth,
191
+ strokeLinecap: "round",
192
+ strokeDasharray: circumference,
193
+ strokeDashoffset,
194
+ className: `${variantClasses.fill} transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg`
195
+ }
196
+ )
197
+ ]
198
+ }
199
+ ),
200
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
201
+ "progress",
202
+ {
203
+ value: clampedValue,
204
+ max,
205
+ "aria-label": typeof label === "string" ? label : "Progress",
206
+ className: "absolute opacity-0 w-0 h-0"
207
+ }
208
+ ),
209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
210
+ "div",
211
+ {
212
+ className: `relative z-10 flex flex-col items-center justify-center ${sizeClasses.spacing}`,
213
+ children: [
214
+ showPercentage && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
215
+ Text_default,
216
+ {
217
+ size: sizeClasses.textSize,
218
+ weight: sizeClasses.textWeight,
219
+ className: `text-center ${variantClasses.textColor} ${percentageClassName}`,
220
+ children: [
221
+ Math.round(percentage),
222
+ "%"
223
+ ]
224
+ }
225
+ ),
226
+ label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
227
+ Text_default,
228
+ {
229
+ as: "span",
230
+ size: sizeClasses.labelSize,
231
+ weight: sizeClasses.labelWeight,
232
+ className: `${variantClasses.labelColor} text-center uppercase tracking-wide ${labelClassName}`,
233
+ children: label
234
+ }
235
+ )
236
+ ]
237
+ }
238
+ )
239
+ ]
240
+ }
241
+ );
242
+ };
243
+ var ProgressCircle_default = ProgressCircle;
244
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/ProgressCircle/ProgressCircle.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["'use client';\n\nimport { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress circle size variants\n */\ntype ProgressCircleSize = 'small' | 'medium';\n\n/**\n * Progress circle color variants\n */\ntype ProgressCircleVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'w-[90px] h-[90px]', // 90px circle from design specs\n strokeWidth: 4, // 4px stroke width - matches ProgressBar small (h-1)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: '2xs' as const, // 10px for status label (closest to 8px design spec)\n labelWeight: 'bold', // font-weight: 700\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n medium: {\n container: 'w-[152px] h-[152px]', // 151.67px ≈ 152px circle from design specs\n strokeWidth: 8, // 8px stroke width - matches ProgressBar medium (h-2)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: 'xs' as const, // 12px for status label (font-size: 12px)\n labelWeight: 'medium', // font-weight: 500 (changed from bold)\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'stroke-primary-100', // Light blue background (#BBDCF7)\n fill: 'stroke-primary-700', // Blue for activity progress (#2271C4)\n textColor: 'text-primary-700', // Blue text color (#2271C4)\n labelColor: 'text-text-700', // Gray text for label (#525252)\n },\n green: {\n background: 'stroke-background-300', // Gray background (#D5D4D4 - matches design)\n fill: 'stroke-success-200', // Green for performance (#84D3A2 - matches design)\n textColor: 'text-text-800', // Dark gray text (#404040 - matches design)\n labelColor: 'text-text-600', // Medium gray text for label (#737373 - matches design)\n },\n} as const;\n\n/**\n * ProgressCircle component props interface\n */\nexport type ProgressCircleProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress circle */\n size?: ProgressCircleSize;\n /** Color variant of the progress circle */\n variant?: ProgressCircleVariant;\n /** Optional label to display below percentage */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressCircle component for Analytica Ensino platforms\n *\n * A circular progress indicator with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\n * Uses the Analytica Ensino Design System colors from styles.css with automatic\n * light/dark mode support. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic progress circle\n * <ProgressCircle value={65} />\n *\n * // Activity progress (blue)\n * <ProgressCircle variant=\"blue\" value={45} label=\"CONCLUÍDO\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressCircle variant=\"green\" size=\"medium\" value={85} label=\"MÉDIA\" />\n *\n * // Small size with custom max value\n * <ProgressCircle size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressCircle = ({\n value,\n max = 100,\n size = 'small',\n variant = 'blue',\n label,\n showPercentage = true,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressCircleProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Calculate SVG dimensions and stroke properties\n const radius = size === 'small' ? 37 : 64; // Radius calculation based on container size\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (percentage / 100) * circumference;\n const center = size === 'small' ? 45 : 76; // Center point of SVG\n const svgSize = size === 'small' ? 90 : 152; // SVG viewBox size\n\n return (\n <div\n className={`relative flex flex-col items-center justify-center ${sizeClasses.container} rounded-lg ${className}`}\n >\n {/* Progress circle SVG */}\n <svg\n className=\"absolute inset-0 transform -rotate-90\"\n width={svgSize}\n height={svgSize}\n viewBox={`0 0 ${svgSize} ${svgSize}`}\n aria-hidden=\"true\"\n >\n {/* Background circle */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n className={`${variantClasses.background} rounded-lg`}\n />\n {/* Progress circle - SVG stroke properties require style for animation */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={strokeDashoffset}\n className={`${variantClasses.fill} transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg`}\n />\n </svg>\n\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute opacity-0 w-0 h-0\"\n />\n\n {/* Content overlay - centered content */}\n <div\n className={`relative z-10 flex flex-col items-center justify-center ${sizeClasses.spacing}`}\n >\n {/* Percentage text */}\n {showPercentage && (\n <Text\n size={sizeClasses.textSize}\n weight={sizeClasses.textWeight}\n className={`text-center ${variantClasses.textColor} ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* Label text */}\n {label && (\n <Text\n as=\"span\"\n size={sizeClasses.labelSize}\n weight={sizeClasses.labelWeight}\n className={`${variantClasses.labelColor} text-center uppercase tracking-wide ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n </div>\n );\n};\n\nexport default ProgressCircle;\n","import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';\n\n/**\n * Base text component props\n */\ntype BaseTextProps = {\n /** Content to be displayed */\n children?: ReactNode;\n /** Text size variant */\n size?:\n | '2xs'\n | 'xs'\n | 'sm'\n | 'md'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | '4xl'\n | '5xl'\n | '6xl';\n /** Font weight variant */\n weight?:\n | 'hairline'\n | 'light'\n | 'normal'\n | 'medium'\n | 'semibold'\n | 'bold'\n | 'extrabold'\n | 'black';\n /** Color variant - white for light backgrounds, black for dark backgrounds */\n color?: string;\n /** Additional CSS classes to apply */\n className?: string;\n};\n\n/**\n * Polymorphic text component props that ensures type safety based on the 'as' prop\n */\ntype TextProps<T extends ElementType = 'p'> = BaseTextProps & {\n /** HTML tag to render */\n as?: T;\n} & Omit<ComponentPropsWithoutRef<T>, keyof BaseTextProps>;\n\n/**\n * Text component for Analytica Ensino platforms\n *\n * A flexible polymorphic text component with multiple sizes, weights, and colors.\n * Automatically adapts to dark and light themes with full type safety.\n * Fully compatible with Next.js 15 and React 19.\n *\n * @param children - The content to display\n * @param size - The text size variant (2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl)\n * @param weight - The font weight variant (hairline, light, normal, medium, semibold, bold, extrabold, black)\n * @param color - The color variant - adapts to theme\n * @param as - The HTML tag to render - determines allowed attributes via TypeScript\n * @param className - Additional CSS classes\n * @param props - HTML attributes valid for the chosen tag only\n * @returns A styled text element with type-safe attributes\n *\n * @example\n * ```tsx\n * <Text size=\"lg\" weight=\"bold\" color=\"text-info-800\">\n * This is a large, bold text\n * </Text>\n *\n * <Text as=\"a\" href=\"/link\" target=\"_blank\">\n * Link with type-safe anchor attributes\n * </Text>\n *\n * <Text as=\"button\" onClick={handleClick} disabled>\n * Button with type-safe button attributes\n * </Text>\n * ```\n */\nconst Text = <T extends ElementType = 'p'>({\n children,\n size = 'md',\n weight = 'normal',\n color = 'text-text-950',\n as,\n className = '',\n ...props\n}: TextProps<T>) => {\n let sizeClasses = '';\n let weightClasses = '';\n\n // Text size classes mapping\n const sizeClassMap = {\n '2xs': 'text-2xs',\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-md',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n '5xl': 'text-5xl',\n '6xl': 'text-6xl',\n } as const;\n\n sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;\n\n // Font weight classes mapping\n const weightClassMap = {\n hairline: 'font-hairline',\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n black: 'font-black',\n } as const;\n\n weightClasses = weightClassMap[weight] ?? weightClassMap.normal;\n\n const baseClasses = 'font-primary';\n const Component = as ?? ('p' as ElementType);\n\n return (\n <Component\n className={`${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC2HI;AA/CJ,IAAM,OAAO,CAA8B;AAAA,EACzC;AAAA,EACA,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR;AAAA,EACA,YAAY;AAAA,EACZ,GAAG;AACL,MAAoB;AAClB,MAAI,cAAc;AAClB,MAAI,gBAAgB;AAGpB,QAAM,eAAe;AAAA,IACnB,OAAO;AAAA,IACP,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAEA,gBAAc,aAAa,IAAI,KAAK,aAAa;AAGjD,QAAM,iBAAiB;AAAA,IACrB,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,MAAM;AAAA,IACN,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AAEA,kBAAgB,eAAe,MAAM,KAAK,eAAe;AAEzD,QAAM,cAAc;AACpB,QAAM,YAAY,MAAO;AAEzB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,WAAW,IAAI,WAAW,IAAI,aAAa,IAAI,KAAK,IAAI,SAAS;AAAA,MAC9E,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;ADIT,IAAAA,sBAAA;AAtHN,IAAM,eAAe;AAAA,EACnB,OAAO;AAAA,IACL,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,UAAU;AAAA;AAAA,IACV,YAAY;AAAA;AAAA,IACZ,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,SAAS;AAAA;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,UAAU;AAAA;AAAA,IACV,YAAY;AAAA;AAAA,IACZ,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,SAAS;AAAA;AAAA,EACX;AACF;AAKA,IAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,IACJ,YAAY;AAAA;AAAA,IACZ,MAAM;AAAA;AAAA,IACN,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,YAAY;AAAA;AAAA,IACZ,MAAM;AAAA;AAAA,IACN,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,EACd;AACF;AAiDA,IAAM,iBAAiB,CAAC;AAAA,EACtB;AAAA,EACA,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,sBAAsB;AACxB,MAA2B;AAEzB,QAAM,YAAY,MAAM,KAAK,IAAI,IAAI;AACrC,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,GAAG,CAAC;AACzD,QAAM,aAAa,QAAQ,IAAI,IAAK,eAAe,MAAO;AAG1D,QAAM,cAAc,aAAa,IAAI;AACrC,QAAM,iBAAiB,gBAAgB,OAAO;AAG9C,QAAM,SAAS,SAAS,UAAU,KAAK;AACvC,QAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,QAAM,mBAAmB,gBAAiB,aAAa,MAAO;AAC9D,QAAM,SAAS,SAAS,UAAU,KAAK;AACvC,QAAM,UAAU,SAAS,UAAU,KAAK;AAExC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,sDAAsD,YAAY,SAAS,eAAe,SAAS;AAAA,MAG9G;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,SAAS,OAAO,OAAO,IAAI,OAAO;AAAA,YAClC,eAAY;AAAA,YAGZ;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,IAAI;AAAA,kBACJ,IAAI;AAAA,kBACJ,GAAG;AAAA,kBACH,MAAK;AAAA,kBACL,aAAa,YAAY;AAAA,kBACzB,WAAW,GAAG,eAAe,UAAU;AAAA;AAAA,cACzC;AAAA,cAEA;AAAA,gBAAC;AAAA;AAAA,kBACC,IAAI;AAAA,kBACJ,IAAI;AAAA,kBACJ,GAAG;AAAA,kBACH,MAAK;AAAA,kBACL,aAAa,YAAY;AAAA,kBACzB,eAAc;AAAA,kBACd,iBAAiB;AAAA,kBACjB;AAAA,kBACA,WAAW,GAAG,eAAe,IAAI;AAAA;AAAA,cACnC;AAAA;AAAA;AAAA,QACF;AAAA,QAGA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP;AAAA,YACA,cAAY,OAAO,UAAU,WAAW,QAAQ;AAAA,YAChD,WAAU;AAAA;AAAA,QACZ;AAAA,QAGA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,2DAA2D,YAAY,OAAO;AAAA,YAGxF;AAAA,gCACC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAM,YAAY;AAAA,kBAClB,QAAQ,YAAY;AAAA,kBACpB,WAAW,eAAe,eAAe,SAAS,IAAI,mBAAmB;AAAA,kBAExE;AAAA,yBAAK,MAAM,UAAU;AAAA,oBAAE;AAAA;AAAA;AAAA,cAC1B;AAAA,cAID,SACC;AAAA,gBAAC;AAAA;AAAA,kBACC,IAAG;AAAA,kBACH,MAAM,YAAY;AAAA,kBAClB,QAAQ,YAAY;AAAA,kBACpB,WAAW,GAAG,eAAe,UAAU,wCAAwC,cAAc;AAAA,kBAE5F;AAAA;AAAA,cACH;AAAA;AAAA;AAAA,QAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,yBAAQ;","names":["import_jsx_runtime"]}
@@ -0,0 +1,222 @@
1
+ "use client";
2
+
3
+ // src/components/Text/Text.tsx
4
+ import { jsx } from "react/jsx-runtime";
5
+ var Text = ({
6
+ children,
7
+ size = "md",
8
+ weight = "normal",
9
+ color = "text-text-950",
10
+ as,
11
+ className = "",
12
+ ...props
13
+ }) => {
14
+ let sizeClasses = "";
15
+ let weightClasses = "";
16
+ const sizeClassMap = {
17
+ "2xs": "text-2xs",
18
+ xs: "text-xs",
19
+ sm: "text-sm",
20
+ md: "text-md",
21
+ lg: "text-lg",
22
+ xl: "text-xl",
23
+ "2xl": "text-2xl",
24
+ "3xl": "text-3xl",
25
+ "4xl": "text-4xl",
26
+ "5xl": "text-5xl",
27
+ "6xl": "text-6xl"
28
+ };
29
+ sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;
30
+ const weightClassMap = {
31
+ hairline: "font-hairline",
32
+ light: "font-light",
33
+ normal: "font-normal",
34
+ medium: "font-medium",
35
+ semibold: "font-semibold",
36
+ bold: "font-bold",
37
+ extrabold: "font-extrabold",
38
+ black: "font-black"
39
+ };
40
+ weightClasses = weightClassMap[weight] ?? weightClassMap.normal;
41
+ const baseClasses = "font-primary";
42
+ const Component = as ?? "p";
43
+ return /* @__PURE__ */ jsx(
44
+ Component,
45
+ {
46
+ className: `${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`,
47
+ ...props,
48
+ children
49
+ }
50
+ );
51
+ };
52
+ var Text_default = Text;
53
+
54
+ // src/components/ProgressCircle/ProgressCircle.tsx
55
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
56
+ var SIZE_CLASSES = {
57
+ small: {
58
+ container: "w-[90px] h-[90px]",
59
+ // 90px circle from design specs
60
+ strokeWidth: 4,
61
+ // 4px stroke width - matches ProgressBar small (h-1)
62
+ textSize: "2xl",
63
+ // 24px for percentage (font-size: 24px)
64
+ textWeight: "medium",
65
+ // font-weight: 500
66
+ labelSize: "2xs",
67
+ // 10px for status label (closest to 8px design spec)
68
+ labelWeight: "bold",
69
+ // font-weight: 700
70
+ spacing: "gap-1"
71
+ // 4px gap between percentage and label
72
+ },
73
+ medium: {
74
+ container: "w-[152px] h-[152px]",
75
+ // 151.67px ≈ 152px circle from design specs
76
+ strokeWidth: 8,
77
+ // 8px stroke width - matches ProgressBar medium (h-2)
78
+ textSize: "2xl",
79
+ // 24px for percentage (font-size: 24px)
80
+ textWeight: "medium",
81
+ // font-weight: 500
82
+ labelSize: "xs",
83
+ // 12px for status label (font-size: 12px)
84
+ labelWeight: "medium",
85
+ // font-weight: 500 (changed from bold)
86
+ spacing: "gap-1"
87
+ // 4px gap between percentage and label
88
+ }
89
+ };
90
+ var VARIANT_CLASSES = {
91
+ blue: {
92
+ background: "stroke-primary-100",
93
+ // Light blue background (#BBDCF7)
94
+ fill: "stroke-primary-700",
95
+ // Blue for activity progress (#2271C4)
96
+ textColor: "text-primary-700",
97
+ // Blue text color (#2271C4)
98
+ labelColor: "text-text-700"
99
+ // Gray text for label (#525252)
100
+ },
101
+ green: {
102
+ background: "stroke-background-300",
103
+ // Gray background (#D5D4D4 - matches design)
104
+ fill: "stroke-success-200",
105
+ // Green for performance (#84D3A2 - matches design)
106
+ textColor: "text-text-800",
107
+ // Dark gray text (#404040 - matches design)
108
+ labelColor: "text-text-600"
109
+ // Medium gray text for label (#737373 - matches design)
110
+ }
111
+ };
112
+ var ProgressCircle = ({
113
+ value,
114
+ max = 100,
115
+ size = "small",
116
+ variant = "blue",
117
+ label,
118
+ showPercentage = true,
119
+ className = "",
120
+ labelClassName = "",
121
+ percentageClassName = ""
122
+ }) => {
123
+ const safeValue = isNaN(value) ? 0 : value;
124
+ const clampedValue = Math.max(0, Math.min(safeValue, max));
125
+ const percentage = max === 0 ? 0 : clampedValue / max * 100;
126
+ const sizeClasses = SIZE_CLASSES[size];
127
+ const variantClasses = VARIANT_CLASSES[variant];
128
+ const radius = size === "small" ? 37 : 64;
129
+ const circumference = 2 * Math.PI * radius;
130
+ const strokeDashoffset = circumference - percentage / 100 * circumference;
131
+ const center = size === "small" ? 45 : 76;
132
+ const svgSize = size === "small" ? 90 : 152;
133
+ return /* @__PURE__ */ jsxs(
134
+ "div",
135
+ {
136
+ className: `relative flex flex-col items-center justify-center ${sizeClasses.container} rounded-lg ${className}`,
137
+ children: [
138
+ /* @__PURE__ */ jsxs(
139
+ "svg",
140
+ {
141
+ className: "absolute inset-0 transform -rotate-90",
142
+ width: svgSize,
143
+ height: svgSize,
144
+ viewBox: `0 0 ${svgSize} ${svgSize}`,
145
+ "aria-hidden": "true",
146
+ children: [
147
+ /* @__PURE__ */ jsx2(
148
+ "circle",
149
+ {
150
+ cx: center,
151
+ cy: center,
152
+ r: radius,
153
+ fill: "none",
154
+ strokeWidth: sizeClasses.strokeWidth,
155
+ className: `${variantClasses.background} rounded-lg`
156
+ }
157
+ ),
158
+ /* @__PURE__ */ jsx2(
159
+ "circle",
160
+ {
161
+ cx: center,
162
+ cy: center,
163
+ r: radius,
164
+ fill: "none",
165
+ strokeWidth: sizeClasses.strokeWidth,
166
+ strokeLinecap: "round",
167
+ strokeDasharray: circumference,
168
+ strokeDashoffset,
169
+ className: `${variantClasses.fill} transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg`
170
+ }
171
+ )
172
+ ]
173
+ }
174
+ ),
175
+ /* @__PURE__ */ jsx2(
176
+ "progress",
177
+ {
178
+ value: clampedValue,
179
+ max,
180
+ "aria-label": typeof label === "string" ? label : "Progress",
181
+ className: "absolute opacity-0 w-0 h-0"
182
+ }
183
+ ),
184
+ /* @__PURE__ */ jsxs(
185
+ "div",
186
+ {
187
+ className: `relative z-10 flex flex-col items-center justify-center ${sizeClasses.spacing}`,
188
+ children: [
189
+ showPercentage && /* @__PURE__ */ jsxs(
190
+ Text_default,
191
+ {
192
+ size: sizeClasses.textSize,
193
+ weight: sizeClasses.textWeight,
194
+ className: `text-center ${variantClasses.textColor} ${percentageClassName}`,
195
+ children: [
196
+ Math.round(percentage),
197
+ "%"
198
+ ]
199
+ }
200
+ ),
201
+ label && /* @__PURE__ */ jsx2(
202
+ Text_default,
203
+ {
204
+ as: "span",
205
+ size: sizeClasses.labelSize,
206
+ weight: sizeClasses.labelWeight,
207
+ className: `${variantClasses.labelColor} text-center uppercase tracking-wide ${labelClassName}`,
208
+ children: label
209
+ }
210
+ )
211
+ ]
212
+ }
213
+ )
214
+ ]
215
+ }
216
+ );
217
+ };
218
+ var ProgressCircle_default = ProgressCircle;
219
+ export {
220
+ ProgressCircle_default as default
221
+ };
222
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Text/Text.tsx","../../src/components/ProgressCircle/ProgressCircle.tsx"],"sourcesContent":["import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';\n\n/**\n * Base text component props\n */\ntype BaseTextProps = {\n /** Content to be displayed */\n children?: ReactNode;\n /** Text size variant */\n size?:\n | '2xs'\n | 'xs'\n | 'sm'\n | 'md'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | '4xl'\n | '5xl'\n | '6xl';\n /** Font weight variant */\n weight?:\n | 'hairline'\n | 'light'\n | 'normal'\n | 'medium'\n | 'semibold'\n | 'bold'\n | 'extrabold'\n | 'black';\n /** Color variant - white for light backgrounds, black for dark backgrounds */\n color?: string;\n /** Additional CSS classes to apply */\n className?: string;\n};\n\n/**\n * Polymorphic text component props that ensures type safety based on the 'as' prop\n */\ntype TextProps<T extends ElementType = 'p'> = BaseTextProps & {\n /** HTML tag to render */\n as?: T;\n} & Omit<ComponentPropsWithoutRef<T>, keyof BaseTextProps>;\n\n/**\n * Text component for Analytica Ensino platforms\n *\n * A flexible polymorphic text component with multiple sizes, weights, and colors.\n * Automatically adapts to dark and light themes with full type safety.\n * Fully compatible with Next.js 15 and React 19.\n *\n * @param children - The content to display\n * @param size - The text size variant (2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl)\n * @param weight - The font weight variant (hairline, light, normal, medium, semibold, bold, extrabold, black)\n * @param color - The color variant - adapts to theme\n * @param as - The HTML tag to render - determines allowed attributes via TypeScript\n * @param className - Additional CSS classes\n * @param props - HTML attributes valid for the chosen tag only\n * @returns A styled text element with type-safe attributes\n *\n * @example\n * ```tsx\n * <Text size=\"lg\" weight=\"bold\" color=\"text-info-800\">\n * This is a large, bold text\n * </Text>\n *\n * <Text as=\"a\" href=\"/link\" target=\"_blank\">\n * Link with type-safe anchor attributes\n * </Text>\n *\n * <Text as=\"button\" onClick={handleClick} disabled>\n * Button with type-safe button attributes\n * </Text>\n * ```\n */\nconst Text = <T extends ElementType = 'p'>({\n children,\n size = 'md',\n weight = 'normal',\n color = 'text-text-950',\n as,\n className = '',\n ...props\n}: TextProps<T>) => {\n let sizeClasses = '';\n let weightClasses = '';\n\n // Text size classes mapping\n const sizeClassMap = {\n '2xs': 'text-2xs',\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-md',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n '5xl': 'text-5xl',\n '6xl': 'text-6xl',\n } as const;\n\n sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;\n\n // Font weight classes mapping\n const weightClassMap = {\n hairline: 'font-hairline',\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n black: 'font-black',\n } as const;\n\n weightClasses = weightClassMap[weight] ?? weightClassMap.normal;\n\n const baseClasses = 'font-primary';\n const Component = as ?? ('p' as ElementType);\n\n return (\n <Component\n className={`${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n","'use client';\n\nimport { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress circle size variants\n */\ntype ProgressCircleSize = 'small' | 'medium';\n\n/**\n * Progress circle color variants\n */\ntype ProgressCircleVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'w-[90px] h-[90px]', // 90px circle from design specs\n strokeWidth: 4, // 4px stroke width - matches ProgressBar small (h-1)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: '2xs' as const, // 10px for status label (closest to 8px design spec)\n labelWeight: 'bold', // font-weight: 700\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n medium: {\n container: 'w-[152px] h-[152px]', // 151.67px ≈ 152px circle from design specs\n strokeWidth: 8, // 8px stroke width - matches ProgressBar medium (h-2)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: 'xs' as const, // 12px for status label (font-size: 12px)\n labelWeight: 'medium', // font-weight: 500 (changed from bold)\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'stroke-primary-100', // Light blue background (#BBDCF7)\n fill: 'stroke-primary-700', // Blue for activity progress (#2271C4)\n textColor: 'text-primary-700', // Blue text color (#2271C4)\n labelColor: 'text-text-700', // Gray text for label (#525252)\n },\n green: {\n background: 'stroke-background-300', // Gray background (#D5D4D4 - matches design)\n fill: 'stroke-success-200', // Green for performance (#84D3A2 - matches design)\n textColor: 'text-text-800', // Dark gray text (#404040 - matches design)\n labelColor: 'text-text-600', // Medium gray text for label (#737373 - matches design)\n },\n} as const;\n\n/**\n * ProgressCircle component props interface\n */\nexport type ProgressCircleProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress circle */\n size?: ProgressCircleSize;\n /** Color variant of the progress circle */\n variant?: ProgressCircleVariant;\n /** Optional label to display below percentage */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressCircle component for Analytica Ensino platforms\n *\n * A circular progress indicator with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\n * Uses the Analytica Ensino Design System colors from styles.css with automatic\n * light/dark mode support. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic progress circle\n * <ProgressCircle value={65} />\n *\n * // Activity progress (blue)\n * <ProgressCircle variant=\"blue\" value={45} label=\"CONCLUÍDO\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressCircle variant=\"green\" size=\"medium\" value={85} label=\"MÉDIA\" />\n *\n * // Small size with custom max value\n * <ProgressCircle size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressCircle = ({\n value,\n max = 100,\n size = 'small',\n variant = 'blue',\n label,\n showPercentage = true,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressCircleProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Calculate SVG dimensions and stroke properties\n const radius = size === 'small' ? 37 : 64; // Radius calculation based on container size\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (percentage / 100) * circumference;\n const center = size === 'small' ? 45 : 76; // Center point of SVG\n const svgSize = size === 'small' ? 90 : 152; // SVG viewBox size\n\n return (\n <div\n className={`relative flex flex-col items-center justify-center ${sizeClasses.container} rounded-lg ${className}`}\n >\n {/* Progress circle SVG */}\n <svg\n className=\"absolute inset-0 transform -rotate-90\"\n width={svgSize}\n height={svgSize}\n viewBox={`0 0 ${svgSize} ${svgSize}`}\n aria-hidden=\"true\"\n >\n {/* Background circle */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n className={`${variantClasses.background} rounded-lg`}\n />\n {/* Progress circle - SVG stroke properties require style for animation */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={strokeDashoffset}\n className={`${variantClasses.fill} transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg`}\n />\n </svg>\n\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute opacity-0 w-0 h-0\"\n />\n\n {/* Content overlay - centered content */}\n <div\n className={`relative z-10 flex flex-col items-center justify-center ${sizeClasses.spacing}`}\n >\n {/* Percentage text */}\n {showPercentage && (\n <Text\n size={sizeClasses.textSize}\n weight={sizeClasses.textWeight}\n className={`text-center ${variantClasses.textColor} ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* Label text */}\n {label && (\n <Text\n as=\"span\"\n size={sizeClasses.labelSize}\n weight={sizeClasses.labelWeight}\n className={`${variantClasses.labelColor} text-center uppercase tracking-wide ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n </div>\n );\n};\n\nexport default ProgressCircle;\n"],"mappings":"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","names":["jsx"]}