analytica-frontend-lib 1.4.62 → 1.4.63

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/utils.ts","../../src/components/Text/Text.tsx","../../src/components/Button/Button.tsx","../../src/components/ActivityCardQuestionBanks/ActivityCardQuestionBanks.tsx","../../src/index.ts","../../src/components/Badge/Badge.tsx","../../src/components/HtmlMathRenderer/KatexMath.tsx","../../src/components/HtmlMathRenderer/HtmlMathRenderer.tsx","../../src/components/MarkdownMathRenderer/MarkdownMathRenderer.tsx","../../src/components/HtmlMathRenderer/utils.ts","../../src/components/CheckBox/CheckBox.tsx","../../src/components/CheckBox/CheckboxList.tsx","../../src/components/Radio/Radio.tsx","../../src/components/IconRender/IconRender.tsx","../../src/assets/icons/subjects/ChatPT.tsx","../../src/assets/icons/subjects/ChatEN.tsx","../../src/assets/icons/subjects/ChatES.tsx","../../src/assets/icons/subjects/BookOpenText.tsx","../../src/assets/icons/subjects/Microscope.tsx","../../src/assets/icons/subjects/HeadCircuit.tsx","../../src/components/Alternative/Alternative.tsx","../../src/utils/questionRenderer/alternative/index.tsx","../../src/components/MultipleChoice/MultipleChoice.tsx","../../src/utils/questionRenderer/multipleChoice/index.tsx","../../src/components/Quiz/QuizContent.tsx","../../src/components/Quiz/Quiz.utils.ts","../../src/utils/stringUtils.ts","../../src/components/Select/Select.tsx","../../src/utils/questionRenderer/trueOrFalse/index.tsx","../../src/utils/questionRenderer/components/index.tsx","../../src/utils/questionRenderer/dissertative/index.tsx","../../src/utils/questionRenderer/fill/index.tsx","../../src/utils/questionRenderer/image/index.tsx","../../src/utils/questionRenderer/connectDots/index.tsx","../../src/utils/questionRenderer/index.tsx","../../src/types/questionTypes.ts","../../src/components/FillInBlanks/FillInBlanks.tsx","../../src/utils/parseContent.ts","../../src/components/ConnectDots/ConnectDots.tsx"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport { syncDropdownState } from './dropdown';\nexport {\n getSelectedIdsFromCategories,\n toggleArrayItem,\n toggleSingleValue,\n areFiltersEqual,\n} from './activityFilters';\nexport {\n mapQuestionTypeToEnum,\n mapQuestionTypeToEnumRequired,\n} from './questionTypeUtils';\nexport {\n getStatusBadgeConfig,\n formatTimeSpent,\n formatQuestionNumbers,\n formatDateToBrazilian,\n} from './activityDetailsUtils';\n\n/**\n * Format a number as a rounded percentage string\n * @param value - Number to format (0-100)\n * @returns Formatted string with % suffix (e.g., \"72%\")\n */\nexport function formatPercentageRounded(value: number): string {\n return `${Math.round(value)}%`;\n}\n\nexport { formatScore } from './formatScore';\n\n/**\n * Convert hex color to rgba with opacity for background\n * @param hex - Hex color (e.g., \"#4B0082\")\n * @param opacity - Opacity value (0-1)\n * @returns rgba string\n */\nexport function hexToRgba(hex: string, opacity: number): string {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n if (!result) return `rgba(107, 114, 128, ${opacity})`; // fallback gray\n const r = Number.parseInt(result[1], 16);\n const g = Number.parseInt(result[2], 16);\n const b = Number.parseInt(result[3], 16);\n return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n}\n\n/**\n * Maps Tailwind bg-* class to CSS variable\n * @param bgClass - Tailwind background class (e.g., \"bg-error-600\")\n * @returns CSS variable string (e.g., \"var(--color-error-600)\")\n */\nexport function bgClassToCssVar(bgClass: string): string {\n return `var(--color-${bgClass.replace('bg-', '')})`;\n}\n\n/**\n * Converts polar coordinates to Cartesian for SVG arc path calculations.\n * Angles are in degrees, with 0° at the top (12 o'clock position).\n * @param cx - Center X coordinate\n * @param cy - Center Y coordinate\n * @param r - Radius\n * @param angleDeg - Angle in degrees\n * @returns Cartesian coordinates { x, y }\n */\nexport function polarToCartesian(\n cx: number,\n cy: number,\n r: number,\n angleDeg: number\n): { x: number; y: number } {\n const rad = ((angleDeg - 90) * Math.PI) / 180;\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };\n}\n\n/**\n * Generates an SVG filled arc (pie slice) path string.\n * @param cx - Center X coordinate\n * @param cy - Center Y coordinate\n * @param r - Radius\n * @param startAngle - Start angle in degrees\n * @param endAngle - End angle in degrees\n * @returns SVG path string for the arc\n */\nexport function describeArc(\n cx: number,\n cy: number,\n r: number,\n startAngle: number,\n endAngle: number\n): string {\n const span = endAngle - startAngle;\n\n // For full circle (or near-full), use two arcs to avoid SVG arc degeneracy\n if (span >= 359.99) {\n const midAngle = startAngle + 180;\n const s = polarToCartesian(cx, cy, r, startAngle);\n const m = polarToCartesian(cx, cy, r, midAngle);\n return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 1 1 ${m.x} ${m.y} A ${r} ${r} 0 1 1 ${s.x} ${s.y} Z`;\n }\n\n const s = polarToCartesian(cx, cy, r, endAngle);\n const e = polarToCartesian(cx, cy, r, startAngle);\n const largeArc = span > 180 ? 1 : 0;\n return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 ${largeArc} 0 ${e.x} ${e.y} Z`;\n}\n\n/**\n * Retorna a cor hexadecimal com opacidade 0.3 (4d) se não estiver em dark mode.\n * Se estiver em dark mode, retorna a cor original.\n *\n * @param hexColor - Cor hexadecimal (ex: \"#0066b8\" ou \"0066b8\")\n * @param isDark - booleano indicando se está em dark mode\n * @returns string - cor hexadecimal com opacidade se necessário\n */\nexport function getSubjectColorWithOpacity(\n hexColor: string | undefined,\n isDark: boolean\n): string | undefined {\n if (!hexColor) return undefined;\n // Remove o '#' se existir\n let color = hexColor.replace(/^#/, '').toLowerCase();\n\n if (isDark) {\n // Se está em dark mode, sempre remove opacidade se existir\n if (color.length === 8) {\n color = color.slice(0, 6);\n }\n return `#${color}`;\n } else {\n // Se não está em dark mode (light mode)\n let resultColor: string;\n if (color.length === 6) {\n // Adiciona opacidade 0.3 (4D) para cores de 6 dígitos\n resultColor = `#${color}4d`;\n } else if (color.length === 8) {\n // Já tem opacidade, retorna como está\n resultColor = `#${color}`;\n } else {\n // Para outros tamanhos (3, 4, 5 dígitos), retorna como está\n resultColor = `#${color}`;\n }\n return resultColor;\n }\n}\n","import { ComponentPropsWithRef, ElementType, ReactNode } from 'react';\nimport { cn } from '../../utils/utils';\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<ComponentPropsWithRef<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 *\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: string;\n let weightClasses: string;\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={cn(baseClasses, sizeClasses, weightClasses, color, className)}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n","import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n primary:\n 'bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed',\n secondary:\n 'bg-text-950 text-text border border-text-800 hover:bg-text-800 hover:border-text-950 focus-visible:outline-none focus-visible:bg-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-text-700 active:border-text-700 disabled:bg-text-500 disabled:border-text-500 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n outline: {\n primary:\n 'bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n secondary:\n 'bg-transparent text-text-950 border border-text-800 hover:bg-background-50 hover:text-text-700 hover:border-text-700 focus-visible:border-0 focus-visible:outline-none focus-visible:text-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-text-700 active:border-text-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n link: {\n primary:\n 'bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n secondary:\n 'bg-transparent text-text-950 hover:text-text-800 focus-visible:outline-none focus-visible:text-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-text-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'text-xs px-3.5 py-2',\n small: 'text-sm px-4 py-2.5',\n medium: 'text-md px-5 py-2.5',\n large: 'text-lg px-6 py-3',\n 'extra-large': 'text-lg px-7 py-3.5',\n} as const;\n\n/**\n * Button component props interface\n */\ntype ButtonProps = {\n /** Content to be displayed inside the button */\n children: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Size of the button */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the button. Use 'raw' for no default styling */\n variant?: 'solid' | 'outline' | 'link' | 'raw';\n /** Action type of the button */\n action?: 'primary' | 'secondary' | 'positive' | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Button component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the button\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, secondary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard button HTML attributes\n * @returns A styled button element\n *\n * @example\n * ```tsx\n * <Button variant=\"solid\" action=\"primary\" size=\"medium\" onClick={() => console.log('clicked')}>\n * Click me\n * </Button>\n * ```\n */\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'primary',\n className = '',\n disabled,\n type = 'button',\n ...props\n },\n ref\n ) => {\n // Raw variant: no default styling, only className\n if (variant === 'raw') {\n return (\n <button\n ref={ref}\n className={className}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && (\n <span className=\"mr-2 flex items-center\">{iconLeft}</span>\n )}\n {children}\n {iconRight && (\n <span className=\"ml-2 flex items-center\">{iconRight}</span>\n )}\n </button>\n );\n }\n\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_ACTION_CLASSES[variant][action];\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-full cursor-pointer font-medium';\n\n return (\n <button\n ref={ref}\n className={cn(baseClasses, variantClasses, sizeClasses, className)}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && <span className=\"mr-2 flex items-center\">{iconLeft}</span>}\n {children}\n {iconRight && (\n <span className=\"ml-2 flex items-center\">{iconRight}</span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport default Button;\n","import {\n Button,\n getSubjectColorWithOpacity,\n IconRender,\n Text,\n} from '../../index';\nimport { Plus } from 'phosphor-react';\nimport { QUESTION_TYPE } from '../Quiz/useQuizStore';\nimport { prependLetterToHtml } from '../Quiz/Quiz.utils';\nimport {\n renderFromMap,\n type QuestionRendererMap,\n} from '../../utils/questionRenderer/index';\nimport { AlternativesList, type Alternative } from '../Alternative/Alternative';\nimport { OptionStatus } from '../../enums/Options';\nimport { MultipleChoiceList } from '../MultipleChoice/MultipleChoice';\nimport { FillInBlanks } from '../FillInBlanks/FillInBlanks';\nimport { ConnectDots } from '../ConnectDots/ConnectDots';\nimport { useMemo } from 'react';\nimport { questionTypeLabels } from '../../types/questionTypes';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\n\ninterface QuestionOption {\n id: string;\n option: string;\n isCorrect?: boolean;\n correctValue?: string | null;\n}\n\ninterface QuestionData {\n options: QuestionOption[];\n correctOptionIds?: string[];\n}\n\ninterface ActivityCardQuestionBanksProps {\n question?: QuestionData;\n questionType?: QUESTION_TYPE;\n iconName?: string;\n subjectColor?: string;\n isDark?: boolean;\n onAddToActivity?: () => void;\n content?: string;\n bank?: string;\n year?: string;\n statement?: string;\n additionalContent?: string | null;\n /** Enable exam mode - changes text labels from 'atividade' to 'prova' */\n enableExamMode?: boolean;\n}\n\nexport const ActivityCardQuestionBanks = ({\n question,\n questionType,\n iconName = 'BookOpen',\n subjectColor = '#000000',\n isDark = false,\n onAddToActivity,\n content,\n bank,\n year,\n statement,\n additionalContent,\n enableExamMode = false,\n}: ActivityCardQuestionBanksProps = {}) => {\n // Transform question options into Alternative format for teacher view\n const alternatives = useMemo(() => {\n if (!question?.options || questionType !== QUESTION_TYPE.ALTERNATIVA)\n return [];\n\n const correctOptionIds = question.correctOptionIds || [];\n\n return question.options.map((option) => {\n // Check isCorrect from option, fallback to correctOptionIds\n const isCorrect =\n option.isCorrect ?? correctOptionIds.includes(option.id);\n return {\n value: option.id,\n label: option.option,\n status: isCorrect ? OptionStatus.CORRECT : undefined,\n disabled: !isCorrect,\n } satisfies Alternative;\n });\n }, [question, questionType]);\n\n const correctOptionId = useMemo(() => {\n if (!question?.correctOptionIds || question.correctOptionIds.length === 0) {\n return undefined;\n }\n return question.correctOptionIds[0];\n }, [question]);\n\n // Transform question options into MultipleChoice format for teacher view\n const multipleChoices = useMemo(() => {\n if (!question?.options || questionType !== QUESTION_TYPE.MULTIPLA_ESCOLHA)\n return [];\n\n const correctOptionIds = question.correctOptionIds || [];\n\n return question.options.map((option) => {\n // Check isCorrect from option, fallback to correctOptionIds\n const isCorrect =\n option.isCorrect ?? correctOptionIds.includes(option.id);\n return {\n value: option.id,\n label: option.option,\n status: isCorrect ? OptionStatus.CORRECT : undefined,\n disabled: !isCorrect,\n };\n });\n }, [question, questionType]);\n\n const correctOptionIds = useMemo(() => {\n return question?.correctOptionIds || [];\n }, [question]);\n\n // Helper function to get letter by index\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n // Render functions for each question type\n const renderAlternative = () => {\n if (!question || alternatives.length === 0) return null;\n return (\n <div className=\"mt-4\">\n <AlternativesList\n alternatives={alternatives}\n mode=\"readonly\"\n layout=\"compact\"\n selectedValue={correctOptionId}\n name=\"teacher-question-view\"\n />\n </div>\n );\n };\n\n const renderMultipleChoice = () => {\n if (!question || multipleChoices.length === 0) return null;\n return (\n <div className=\"mt-4\">\n <MultipleChoiceList\n choices={multipleChoices}\n mode=\"readonly\"\n selectedValues={correctOptionIds}\n name=\"teacher-question-view-multiple\"\n />\n </div>\n );\n };\n\n const renderDissertative = () => {\n return (\n <div className=\"mt-4 px-2 py-4\">\n <Text size=\"sm\" className=\"text-text-600 italic\">\n Resposta do aluno\n </Text>\n </div>\n );\n };\n\n const renderTrueOrFalse = () => {\n if (!question || question.options.length === 0) return null;\n return (\n <div className=\"mt-4\">\n <div className=\"flex flex-col gap-3.5\">\n {question.options.map((option, index) => {\n // For VERDADEIRO_FALSO, use isCorrect from option\n const isCorrect =\n option.isCorrect ?? correctOptionIds.includes(option.id);\n const correctAnswer = isCorrect ? 'Verdadeiro' : 'Falso';\n const letter = getLetterByIndex(index);\n const contentWithLetter = prependLetterToHtml(\n letter,\n option.option\n );\n\n return (\n <section key={option.id} className=\"flex flex-col gap-2\">\n <div className=\"flex flex-row justify-between items-start gap-2 p-2 rounded-md border border-border-200\">\n <HtmlMathRenderer\n content={contentWithLetter}\n className=\"text-text-900 text-sm flex-1\"\n />\n\n <Text\n size=\"sm\"\n className=\"text-text-700 shrink-0 whitespace-nowrap\"\n >\n Resposta correta: {correctAnswer}\n </Text>\n </div>\n </section>\n );\n })}\n </div>\n </div>\n );\n };\n\n // Transform options for ConnectDots component\n const connectDotsOptions = useMemo(() => {\n if (!question?.options || questionType !== QUESTION_TYPE.RELACIONAR)\n return [];\n return question.options\n .filter((opt) => opt.correctValue)\n .map((opt) => ({\n id: opt.id,\n option: opt.option,\n correctValue: opt.correctValue as string,\n }));\n }, [question?.options, questionType]);\n\n const renderConnectDots = () => {\n if (connectDotsOptions.length === 0) return null;\n\n return (\n <ConnectDots\n options={connectDotsOptions}\n mode=\"readonly\"\n className=\"mt-4\"\n />\n );\n };\n\n // Transform options for FillInBlanks component\n const fillInBlanksOptions = useMemo(() => {\n if (!question?.options) return [];\n return question.options.map((opt) => ({\n id: opt.id,\n option: opt.option,\n }));\n }, [question?.options]);\n\n const renderFill = () => {\n // For PREENCHER_LACUNAS, additionalContent contains the fill-in text with placeholders\n if (!additionalContent || fillInBlanksOptions.length === 0) return null;\n\n return (\n <FillInBlanks\n content={additionalContent}\n options={fillInBlanksOptions}\n mode=\"readonly\"\n className=\"mt-4\"\n />\n );\n };\n\n // Parse image coordinates from options for IMAGEM questions\n const imageCoordinates = useMemo(() => {\n if (\n questionType !== QUESTION_TYPE.IMAGEM ||\n !question?.options?.[0]?.option\n )\n return null;\n\n try {\n const coords = JSON.parse(question.options[0].option);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n return { x: coords.x, y: coords.y };\n }\n } catch {\n // Invalid JSON, return null\n }\n return null;\n }, [question?.options, questionType]);\n\n const renderImage = () => {\n if (!additionalContent) return null;\n return (\n <div className=\"mt-4 relative inline-block\">\n <img\n src={additionalContent}\n alt=\"Imagem da questão\"\n className=\"max-w-full h-auto rounded-md border border-border-200\"\n />\n {imageCoordinates && (\n <div\n className=\"absolute w-5 h-5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-success-500 border-2 border-white shadow-md\"\n style={{\n left: `${imageCoordinates.x}%`,\n top: `${imageCoordinates.y}%`,\n }}\n />\n )}\n </div>\n );\n };\n\n // Map question types to render functions\n const questionRenderers: QuestionRendererMap = {\n [QUESTION_TYPE.ALTERNATIVA]: renderAlternative,\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: renderMultipleChoice,\n [QUESTION_TYPE.DISSERTATIVA]: renderDissertative,\n [QUESTION_TYPE.VERDADEIRO_FALSO]: renderTrueOrFalse,\n [QUESTION_TYPE.RELACIONAR]: renderConnectDots,\n [QUESTION_TYPE.PREENCHER_LACUNAS]: renderFill,\n [QUESTION_TYPE.IMAGEM]: renderImage,\n };\n\n return (\n <div className=\"w-full flex flex-col gap-2 px-4 py-6\">\n <section className=\"flex flex-row gap-2 text-text-650\">\n <div className=\"py-1 px-2 flex flex-row items-center gap-1\">\n <span\n className=\"size-4 rounded-sm flex items-center justify-center shrink-0 text-text-950\"\n style={{\n backgroundColor: getSubjectColorWithOpacity(subjectColor, isDark),\n }}\n >\n <IconRender iconName={iconName} size={14} color=\"currentColor\" />\n </span>\n <Text size=\"sm\">{content || 'Assunto não informado'}</Text>\n </div>\n\n <div className=\"py-1 px-2 flex flex-row items-center gap-1\">\n <Text size=\"sm\" className=\"\">\n {questionType\n ? questionTypeLabels[questionType]\n : 'Tipo de questão'}\n </Text>\n </div>\n\n {(bank || year) && (\n <div className=\"py-1 px-2 flex flex-row items-center gap-1\">\n <Text size=\"sm\">{[bank, year].filter(Boolean).join(' - ')}</Text>\n </div>\n )}\n </section>\n\n <section className=\"flex flex-col gap-1\">\n {statement ? (\n <HtmlMathRenderer\n content={statement}\n className=\"text-text-950 text-md font-medium\"\n />\n ) : (\n <Text size=\"md\" weight=\"medium\" className=\"text-text-950 text-md\">\n Enunciado não informado\n </Text>\n )}\n\n {renderFromMap(questionRenderers, questionType)}\n </section>\n\n <section>\n <Button\n size=\"small\"\n variant=\"outline\"\n iconLeft={<Plus />}\n className=\"w-full\"\n onClick={() => {\n if (onAddToActivity) {\n onAddToActivity();\n }\n }}\n >\n {enableExamMode ? 'Adicionar à prova' : 'Adicionar à atividade'}\n </Button>\n </section>\n </div>\n );\n};\n","// Complete bundle index - includes all components\n// Individual imports still recommended for better tree-shaking\n\n// CSS import\nimport './styles.css';\n\n// Layout Components\nexport { PageContainer } from './components/PageContainer/PageContainer';\nexport type { PageContainerProps } from './components/PageContainer/PageContainer';\n\n// Basic Components\nexport { default as Text } from './components/Text/Text';\nexport { default as Button } from './components/Button/Button';\nexport { default as Badge } from './components/Badge/Badge';\nexport { default as Alert } from './components/Alert/Alert';\nexport { default as LatexRenderer } from './components/LatexRenderer/LatexRenderer';\nexport type { LatexRendererProps } from './components/LatexRenderer/LatexRenderer';\nexport {\n HtmlMathRenderer,\n processHtmlWithMath,\n sanitizeHtmlForDisplay,\n cleanLatex,\n containsMath,\n stripHtml,\n looksLikeLatex,\n isLikelyMarkdown,\n} from './components/HtmlMathRenderer';\nexport type {\n HtmlMathRendererProps,\n MathPart,\n} from './components/HtmlMathRenderer';\nexport {\n MarkdownMathRenderer,\n protectCurrencyInlineMath,\n reflowDisplayMath,\n} from './components/MarkdownMathRenderer';\nexport type { MarkdownMathRendererProps } from './components/MarkdownMathRenderer';\nexport { default as IconButton } from './components/IconButton/IconButton';\nexport { Tooltip } from './components/Tooltip/Tooltip';\nexport type { TooltipProps } from './components/Tooltip/Tooltip';\nexport { TruncatedText } from './components/TruncatedText/TruncatedText';\nexport type {\n TruncatedTextProps,\n TruncatedTextSize,\n TruncatedTextWeight,\n TruncatedTextTooltipPosition,\n} from './components/TruncatedText/TruncatedText';\nexport { default as IconRoundedButton } from './components/IconRoundedButton/IconRoundedButton';\nexport { default as NavButton } from './components/NavButton/NavButton';\nexport { default as SelectionButton } from './components/SelectionButton/SelectionButton';\nexport { default as CheckBox } from './components/CheckBox/CheckBox';\nexport { default as ToggleSwitch } from './components/ToggleSwitch/ToggleSwitch';\nexport type { ToggleSwitchProps } from './components/ToggleSwitch/ToggleSwitch';\nexport { default as ImageUpload } from './components/ImageUpload/ImageUpload';\nexport type { ImageUploadProps } from './components/ImageUpload/ImageUpload';\nexport { default as FileDropzone } from './components/FileDropzone/FileDropzone';\nexport type {\n FileDropzoneProps,\n FileType,\n} from './components/FileDropzone/FileDropzone';\nexport {\n default as CheckboxList,\n CheckboxListItem,\n} from './components/CheckBox/CheckboxList';\n\n// CheckboxGroup Component\nexport {\n CheckboxGroup,\n type CategoryConfig,\n type Item,\n} from './components/CheckBoxGroup/CheckBoxGroup';\nexport { AlertsManager } from './components/AlertManager/AlertsManager';\nexport { useAlertFormStore } from './components/AlertManager/useAlertForm';\nexport { AlertsManagerView } from './components/AlertManagerView/AlertsManagerView';\nexport type {\n AlertViewData,\n RecipientStatus,\n} from './components/AlertManagerView/AlertsManagerView';\nexport type {\n AlertsConfig,\n AlertData,\n RecipientItem,\n} from './components/AlertManager/types';\nexport { AppHeader } from './components/AppHeader/AppHeader';\nexport type {\n AppHeaderProps,\n AppHeaderUser,\n AppHeaderSessionInfo,\n AppHeaderNotifications,\n} from './components/AppHeader/AppHeader';\nexport { AppLayout } from './components/AppLayout/AppLayout';\nexport type {\n AppLayoutProps,\n AppLayoutMenuItem,\n} from './components/AppLayout/AppLayout';\nexport {\n default as Radio,\n RadioGroup,\n RadioGroupItem,\n} from './components/Radio/Radio';\nexport { default as TextArea } from './components/TextArea/TextArea';\nexport { default as Toast } from './components/Toast/Toast';\nexport { default as Toaster } from './components/Toast/utils/Toaster';\nexport { default as Divider } from './components/Divider/Divider';\nexport { default as useToastStore } from './components/Toast/utils/ToastStore';\nexport { default as Input } from './components/Input/Input';\nexport { default as ColorPicker } from './components/ColorPicker/ColorPicker';\nexport type { ColorPickerProps } from './components/ColorPicker/ColorPicker';\nexport { default as Search } from './components/Search/Search';\nexport { default as Chips } from './components/Chips/Chips';\nexport { default as ProgressBar } from './components/ProgressBar/ProgressBar';\nexport { default as ProgressCircle } from './components/ProgressCircle/ProgressCircle';\nexport { default as Stepper } from './components/Stepper/Stepper';\nexport { default as Calendar } from './components/Calendar/Calendar';\nexport { DateTimeInput } from './components/DateTimeInput';\nexport type { DateTimeInputProps } from './components/DateTimeInput';\nexport { default as Modal } from './components/Modal/Modal';\nexport { default as CorrectActivityModal } from './components/CorrectActivityModal/CorrectActivityModal';\nexport type { CorrectActivityModalProps } from './components/CorrectActivityModal/CorrectActivityModal';\nexport {\n QUESTION_STATUS as CORRECTION_QUESTION_STATUS,\n getQuestionStatusBadgeConfig,\n convertApiResponseToCorrectionData,\n} from './utils/studentActivityCorrection';\nexport type {\n QuestionStatus as CorrectionQuestionStatus,\n StudentQuestion,\n StudentActivityCorrectionData,\n QuestionsAnswersByStudentResponse,\n} from './utils/studentActivityCorrection';\n\n// FileAttachment Component\nexport { default as FileAttachment } from './components/FileAttachment/FileAttachment';\nexport {\n generateFileId,\n formatFileSize,\n} from './components/FileAttachment/FileAttachment';\nexport type {\n FileAttachmentProps,\n AttachedFile,\n} from './components/FileAttachment/FileAttachment';\n\nexport { AlertDialog } from './components/AlertDialog/AlertDialog';\nexport { default as LoadingModal } from './components/LoadingModal/loadingModal';\nexport { default as ProgressModal } from './components/ProgressModal/ProgressModal';\nexport type { ProgressModalProps } from './components/ProgressModal/ProgressModal';\nexport { default as ScoreCircle } from './components/ScoreCircle/ScoreCircle';\nexport type {\n ScoreCircleProps,\n ScoreCircleVariant,\n} from './components/ScoreCircle/ScoreCircle';\nexport { default as ImagePreviewCard } from './components/ImagePreviewCard/ImagePreviewCard';\nexport type { ImagePreviewCardProps } from './components/ImagePreviewCard/ImagePreviewCard';\nexport { default as NotificationCard } from './components/NotificationCard/NotificationCard';\nexport { default as CalendarCard } from './components/CalendarCard/CalendarCard';\nexport type { CalendarCardProps } from './components/CalendarCard/CalendarCard';\nexport { ThemeToggle } from './components/ThemeToggle/ThemeToggle';\n\n// Choropleth Map Component\nexport { default as ChoroplethMap } from './components/ChoroplethMap/ChoroplethMap';\nexport type {\n ChoroplethMapProps,\n RegionData,\n MapBounds,\n LegendItem,\n ColorClass,\n} from './components/ChoroplethMap/ChoroplethMap.types';\n\n// Map Data Hook\nexport { createUseMapData } from './hooks/useMapData';\nexport type { UseMapDataReturn } from './hooks/useMapData';\nexport { REPORT_PERIOD, REPORT_MODAL_VARIANT } from './types/common';\nexport type {\n MapFilters as MapDataFilters,\n MapDataRegion,\n MapDataApiResponse,\n MapDataBounds,\n} from './types/mapData';\n\n// Export notification card types\nexport type {\n NotificationItem,\n NotificationGroup,\n} from './components/NotificationCard/NotificationCard';\n\n// Subject Components\nexport {\n SubjectInfo,\n getSubjectInfo,\n getSubjectIcon,\n getSubjectColorClass,\n getSubjectName,\n} from './components/SubjectInfo/SubjectInfo';\nexport type {\n SubjectData,\n IconProps as SubjectIconProps,\n} from './components/SubjectInfo/SubjectInfo';\n\n// Notification Store\nexport {\n createNotificationStore,\n formatTimeAgo,\n} from './store/notificationStore';\nexport { createUseNotificationStore } from './hooks/useNotificationStore';\nexport {\n createUseNotifications,\n createNotificationsHook,\n} from './hooks/useNotifications';\nexport { NotificationEntityType } from './types/notifications';\nexport { questionTypeLabels } from './types/questionTypes';\nexport type {\n Notification,\n NotificationType,\n BackendNotification,\n BackendNotificationsResponse,\n NotificationsResponse,\n FetchNotificationsParams,\n NotificationApiClient,\n} from './types/notifications';\nexport type {\n NotificationState,\n NotificationActions,\n NotificationStore,\n} from './store/notificationStore';\n\n// Activity Filters Data Hook (consolidated hook for all filter data)\nexport {\n createUseActivityFiltersData,\n createActivityFiltersDataHook,\n} from './hooks/useActivityFiltersData';\nexport type {\n UseActivityFiltersDataReturn,\n UseActivityFiltersDataOptions,\n} from './hooks/useActivityFiltersData';\n\n// Questions List Hook\nexport {\n createUseQuestionsList,\n createQuestionsListHook,\n} from './hooks/useQuestionsList';\nexport { CreateActivity } from './components/ActivityCreate/ActivityCreate';\nexport {\n ActivityType,\n ActivityStatus,\n} from './components/ActivityCreate/ActivityCreate';\nexport type {\n ActivityData,\n BackendFiltersFormat,\n ActivityDraftResponse,\n ActivityPreFiltersInput,\n ActivityCreatePayload,\n ActivityCreateResponse,\n School,\n SchoolYear,\n Class,\n Student,\n} from './components/ActivityCreate/ActivityCreate';\n\n// RecommendedLessonCreate Component\nexport { RecommendedLessonCreate } from './components/RecommendedLessonCreate';\nexport type {\n LessonBackendFiltersFormat,\n RecommendedLessonDraftResponse,\n RecommendedLessonData,\n RecommendedLessonPreFiltersInput,\n RecommendedLessonCreatePayload,\n RecommendedLessonCreateResponse,\n} from './components/RecommendedLessonCreate';\nexport type { UseQuestionsListReturn } from './hooks/useQuestionsList';\nexport type {\n Question as QuestionActivity,\n Pagination,\n QuestionsFilterBody,\n QuestionOptionActivity,\n KnowledgeMatrixItemActivity,\n QuestionBankYearActivity,\n PaginationActivity,\n QuestionsListResponseActivity,\n} from './types/questions';\nexport { DIFFICULTY_LEVEL_ENUM, QUESTION_STATUS_ENUM } from './types/questions';\n\n// API Types\nexport type { BaseApiClient } from './types/api';\n\n// Theme Store\nexport { useThemeStore } from './store/themeStore';\nexport type { ThemeStore, ThemeState, ThemeActions } from './store/themeStore';\n\n// Storage Keys\nexport { KEYS, FEATURE_FLAGS_KEYS } from './utils/keys';\n\n// DropdownMenu Components\nexport {\n default as DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n ProfileMenuTrigger,\n ProfileMenuFooter,\n ProfileMenuHeader,\n ProfileMenuInfo,\n ProfileMenuSection,\n MenuLabel,\n DropdownMenuSeparator,\n ProfileToggleTheme,\n} from './components/DropdownMenu/DropdownMenu';\n\nexport {\n default as Table,\n TableHeader,\n TableBody,\n TableRow,\n TableHead,\n TableCell,\n TableFooter,\n TableCaption,\n TablePagination,\n useTableSort,\n} from './components/Table/Table';\nexport type {\n UseTableSortOptions,\n SortDirection,\n} from './components/Table/Table';\n\n// Filter Components\nexport { FilterModal, useTableFilter } from './components/Filter';\nexport type {\n FilterModalProps,\n FilterConfig,\n UseTableFilterOptions,\n UseTableFilterReturn,\n} from './components/Filter';\n\n// SimulatedFilters Components\nexport {\n SimulatedFiltersModal,\n StudentsFilterSection,\n useUserAccessData as useSimulatedUserAccessData,\n useStudentsFilter as useSimulatedStudentsFilter,\n} from './components/SimulatedFilters';\nexport type {\n SimulatedFilters,\n SimulatedFiltersModalProps,\n SchoolItem as SimulatedSchoolItem,\n SchoolYearItem as SimulatedSchoolYearItem,\n ClassItem as SimulatedClassItem,\n StudentFilterItem,\n StudentGroup,\n UserAccessDataApiResponse as SimulatedUserAccessDataApiResponse,\n StudentsFilterApiResponse as SimulatedStudentsFilterApiResponse,\n StudentsFilterParams,\n UseUserAccessDataState,\n UseUserAccessDataReturn,\n UseStudentsFilterState,\n UseStudentsFilterReturn,\n StudentsFilterSectionProps,\n} from './components/SimulatedFilters';\n\n// GeneralOverviewSection Component\nexport {\n GeneralOverviewSection,\n useGeneralOverview,\n} from './components/GeneralOverviewSection';\nexport type {\n AreaKnowledgePerformance,\n EssayPerformance,\n GeneralOverviewData,\n SubjectItem as GeneralOverviewSubjectItem,\n GeneralOverviewParams,\n GeneralOverviewApiResponse,\n UseGeneralOverviewState,\n UseGeneralOverviewReturn,\n GeneralOverviewSectionProps,\n GeneralOverviewLabels,\n} from './components/GeneralOverviewSection';\n\n// AreaKnowledgeSelector Component\nexport {\n AreaKnowledgeSelector,\n ESSAY_AREA_ID,\n} from './components/AreaKnowledgeSelector';\nexport type { AreaKnowledgeSelectorProps } from './components/AreaKnowledgeSelector';\n\n// SimulatedSubjectMenu Component\nexport {\n SimulatedSubjectMenu,\n useSimulatedSubjects,\n} from './components/SimulatedSubjectMenu';\nexport type {\n SimulatedSubjectItem,\n SimulatedSubjectsApiResponse,\n UseSimulatedSubjectsState,\n UseSimulatedSubjectsReturn,\n SimulatedSubjectMenuProps,\n} from './components/SimulatedSubjectMenu';\n\n// SimulatedStudentRanking Component\nexport {\n SimulatedStudentRanking,\n SimulatedRankingCard,\n} from './components/SimulatedStudentRanking';\nexport type {\n RankingVariant,\n SimulatedStudentRankingItem,\n SimulatedStudentRankingProps,\n SimulatedRankingCardProps,\n} from './components/SimulatedStudentRanking';\n\n// PerformanceDistributionChart Component\nexport { PerformanceDistributionChart } from './components/PerformanceDistributionChart';\nexport type {\n SimulatedPerformanceCounters,\n SliceData,\n PerformanceDistributionChartProps,\n} from './components/PerformanceDistributionChart';\n\n// SimulatedStudentDetailsModal Component\nexport {\n SimulatedStudentDetailsModal,\n useSimulatedStudentDetails,\n isStudentSubjectsData,\n isStudentContentsData,\n simulationTypeToActivityFilters,\n SIMULATED_PERFORMANCE_TAG_CONFIG,\n PERFORMANCE_TAG_TO_BADGE_ACTION,\n PerformanceBadgeAction,\n ReportSimulationType,\n} from './components/SimulatedStudentDetailsModal';\nexport type {\n SimulatedPerformanceTag,\n SimulatedPerformanceTagConfig,\n SimulationType,\n StudentDetailsInfo,\n SubjectPerformanceItem,\n StudentContentPerformanceItem,\n StudentSubjectsData,\n StudentContentsData,\n StudentDetailsData,\n ActivityFilters as SimulatedActivityFilters,\n StudentDetailsParams,\n StudentDetailsApiResponse,\n UseSimulatedStudentDetailsState,\n UseSimulatedStudentDetailsReturn,\n SimulatedStudentDetailsModalProps,\n} from './components/SimulatedStudentDetailsModal';\n\n// SimulatedContentsPerformance Hook\nexport { useSimulatedContents } from './components/SimulatedContentsPerformance';\nexport type {\n SimulatedContentItem,\n ContentsPerformanceData,\n SimulatedContentsParams,\n ContentsPerformanceApiResponse,\n UseSimulatedContentsState,\n UseSimulatedContentsReturn,\n} from './components/SimulatedContentsPerformance';\n\n// SimulatedContentDetailsModal Component\nexport {\n SimulatedContentDetailsModal,\n useSimulatedContentDetails,\n} from './components/SimulatedContentDetailsModal';\nexport type {\n ContentDetailsInfo,\n ContentPerformanceCounters,\n ContentStudentItem,\n ContentStudentsPaginated,\n ContentDetailsData,\n ContentDetailsParams,\n ContentDetailsApiResponse,\n UseSimulatedContentDetailsState,\n UseSimulatedContentDetailsReturn,\n SimulatedContentDetailsModalProps,\n} from './components/SimulatedContentDetailsModal';\n\n// EssayCompetencies Components\nexport {\n EssayCompetenciesTable,\n EssayCompetenceDetailsModal,\n useEssayCompetenciesOverview,\n useEssayCompetenceDetails,\n} from './components/EssayCompetencies';\nexport type {\n EssayCompetencyOverviewItem,\n EssayCompetenciesOverviewData,\n EssayCompetenciesOverviewParams,\n EssayCompetenciesOverviewApiResponse,\n EssayCompetenceInfo,\n EssayCompetenceCounters,\n EssayCompetenceStudentItem,\n EssayCompetenceStudentsPaginated,\n EssayCompetenceDetailsData,\n EssayCompetenceDetailsParams,\n EssayCompetenceDetailsApiResponse,\n UseEssayCompetenciesOverviewState,\n UseEssayCompetenciesOverviewReturn,\n UseEssayCompetenceDetailsState,\n UseEssayCompetenceDetailsReturn,\n EssayCompetenciesTableProps,\n EssayCompetenceDetailsModalProps,\n} from './components/EssayCompetencies';\n\n// SimulatedStudentsOverview Hook\nexport { useSimulatedOverview } from './components/SimulatedStudentsOverview';\nexport type {\n SimulatedStudentItem,\n SimulatedStudentsPaginated,\n SimulatedOverviewData,\n SimulatedOverviewParams,\n SimulatedOverviewApiResponse,\n UseSimulatedOverviewState,\n UseSimulatedOverviewReturn,\n} from './components/SimulatedStudentsOverview';\n\n// EssayStudentDetailsModal Component\nexport {\n EssayStudentDetailsModal,\n useEssayStudentDetails,\n} from './components/EssayStudentDetailsModal';\nexport type {\n EssayCompetencyPerformance,\n EssayStudentInfo,\n EssayStudentDetailsData,\n EssayStudentDetailsParams,\n EssayStudentDetailsApiResponse,\n UseEssayStudentDetailsState,\n UseEssayStudentDetailsReturn,\n EssayStudentDetailsLabels,\n EssayStudentDetailsModalProps,\n} from './components/EssayStudentDetailsModal';\n\n// ActivityFilters Component\nexport {\n ActivityFilters,\n ActivityFiltersPopover,\n} from './components/ActivityFilters/ActivityFilters';\nexport type {\n ActivityFiltersProps,\n ActivityFiltersPopoverProps,\n} from './components/ActivityFilters/ActivityFilters';\nexport type {\n ActivityFiltersData,\n Bank,\n BankYear,\n KnowledgeArea,\n KnowledgeItem,\n KnowledgeStructureState,\n} from './types/activityFilters';\n\nexport type { TablePaginationProps } from './components/Table/Table';\n\n// TableProvider Component\nexport { TableProvider } from './components/TableProvider';\nexport type {\n ColumnConfig,\n TableParams,\n PaginationConfig,\n TableProviderProps,\n EmptyStateConfig,\n} from './components/TableProvider';\n\n// Select Components\nexport {\n default as Select,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectItem,\n} from './components/Select/Select';\n\n// SearchSelect Component (Select with search functionality)\nexport { default as SearchSelect } from './components/SearchSelect/SearchSelect';\nexport type {\n SearchSelectProps,\n SearchSelectOption,\n SearchSelectPagination,\n} from './components/SearchSelect/SearchSelect';\n\n// TypeSelector Component (Activity/Exam type switcher)\nexport {\n TypeSelector,\n default as TypeSelectorDefault,\n} from './components/TypeSelector';\nexport type { TypeSelectorProps } from './components/TypeSelector';\nexport {\n type ActivityCategory,\n type ActiveTab,\n type TypeLabels,\n type TypeRoutes,\n type TypeConfig,\n ATIVIDADE_LABELS,\n PROVA_LABELS,\n DEFAULT_STATUS_OPTIONS,\n getTabPath,\n getTabFromPath,\n createActivityCategoryConfig,\n} from './components/TypeSelector';\n\n// Menu Components\nexport {\n default as Menu,\n MenuItem,\n MenuOverflow,\n MenuContent,\n} from './components/Menu/Menu';\n\n// PeriodSelector Component\nexport {\n PeriodSelector,\n Period,\n PERIOD_OPTIONS,\n} from './components/PeriodSelector';\nexport type {\n PeriodTab,\n PeriodValue,\n PeriodSelectorProps,\n} from './components/PeriodSelector';\n\n// Card Components\nexport {\n CardActivitiesResults,\n CardPerformance,\n CardProgress,\n CardQuestions,\n CardResults,\n CardSimulado,\n CardStatus,\n CardTopic,\n CardTest,\n CardSimulationHistory,\n CardAudio,\n CardEssayHistory,\n EssayStatus,\n EssayReviewStatus,\n} from './components/Card/Card';\nexport type {\n EssayHistoryItem,\n EssayHistoryData,\n} from './components/Card/Card';\nexport { StatisticsCard } from './components/StatisticsCard/StatisticsCard';\nexport {\n StudentRanking,\n RankingCard,\n} from './components/StudentRanking/StudentRanking';\nexport type {\n StudentRankingProps,\n StudentRankingItem,\n StudentRankingVariant,\n RankingCardProps,\n} from './components/StudentRanking/StudentRanking';\nexport { QuestionsData } from './components/QuestionsData/QuestionsData';\nexport type {\n QuestionsDataProps,\n QuestionsDataItem,\n} from './components/QuestionsData/QuestionsData';\n\n// Skeleton Components\nexport {\n Skeleton,\n SkeletonText,\n SkeletonCircle,\n SkeletonRectangle,\n SkeletonRounded,\n SkeletonCard,\n SkeletonList,\n SkeletonTable,\n} from './components/Skeleton/Skeleton';\n\n// Media Components\nexport { default as NotFound } from './components/NotFound/NotFound';\nexport { default as RestrictedAccess } from './components/RestrictedAccess/RestrictedAccess';\nexport type { RestrictedAccessProps } from './components/RestrictedAccess/RestrictedAccess';\nexport { default as TokenValidation } from './components/TokenValidation/TokenValidation';\nexport type { TokenValidationProps } from './components/TokenValidation/TokenValidation';\nexport { default as NoSearchResult } from './components/NoSearchResult/NoSearchResult';\nexport type { NoSearchResultProps } from './components/NoSearchResult/NoSearchResult';\nexport { default as EmptyState } from './components/EmptyState/EmptyState';\nexport type { EmptyStateProps } from './components/EmptyState/EmptyState';\nexport { default as VideoPlayer } from './components/VideoPlayer/VideoPlayer';\nexport { default as Whiteboard } from './components/Whiteboard/Whiteboard';\nexport { default as DownloadButton } from './components/DownloadButton/DownloadButton';\n\n// RichEditor - WYSIWYG editor with LaTeX support (requires @tiptap/* dependencies)\nexport { RichEditor } from './components/RichEditor/RichEditor';\nexport { FormulaDialog } from './components/RichEditor/components/FormulaDialog';\nexport { MathNode } from './components/RichEditor/components/MathNode';\nexport {\n processLatexInHtml,\n unprocessLatexInHtml,\n} from './components/RichEditor/components/utils';\nexport type {\n DownloadContent,\n DownloadButtonProps,\n} from './components/DownloadButton/DownloadButton';\n\n// Auth Components\nexport type { AuthContextType } from './components/Auth/Auth';\nexport {\n AuthProvider,\n ProtectedRoute,\n PublicRoute,\n withAuth,\n useAuth,\n useAuthGuard,\n useRouteAuth,\n getRootDomain,\n} from './components/Auth/Auth';\nexport { useTokenInUrl } from './components/Auth/useTokenInUrl';\nexport {\n CardAccordation,\n AccordionGroup,\n} from './components/Accordation/index';\nexport {\n AlternativesList,\n HeaderAlternative,\n} from './components/Alternative/Alternative';\nexport { createZustandAuthAdapter } from './components/Auth/zustandAuthAdapter';\nexport { useUrlAuthentication } from './components/Auth/useUrlAuthentication';\nexport { useApiConfig } from './components/Auth/useApiConfig';\n\n// Quiz Components\nexport { QuizVariant } from './components/Quiz/Quiz.types';\nexport {\n QuizTitle,\n Quiz,\n QuizHeader,\n QuizContent,\n QuizQuestionList,\n QuizFooter,\n} from './components/Quiz/Quiz';\nexport {\n getStatusBadge,\n QuizImageQuestion,\n QuizAlternative,\n QuizMultipleChoice,\n QuizDissertative,\n QuizTrueOrFalse,\n QuizConnectDots,\n} from './components/Quiz/QuizContent';\nexport {\n QuizHeaderResult,\n QuizListResult,\n QuizResultHeaderTitle,\n QuizResultTitle,\n QuizResultPerformance,\n QuizListResultByMateria,\n} from './components/Quiz/QuizResult';\nexport { TeacherFeedbackSection } from './components/Quiz/TeacherFeedbackSection';\nexport type { TeacherFeedbackSectionProps } from './components/Quiz/TeacherFeedbackSection';\nexport { useQuizStore } from './components/Quiz/useQuizStore';\nexport { formatExamInfo } from './components/Quiz/Quiz.utils';\n\n// Quiz Types and Enums\nexport {\n QUESTION_DIFFICULTY,\n QUESTION_TYPE,\n QUESTION_STATUS,\n ANSWER_STATUS,\n SUBTYPE_ENUM,\n QUIZ_TYPE,\n} from './components/Quiz/useQuizStore';\nexport { TrueFalseEnum } from './enums/Quiz';\nexport { SubjectEnum } from './enums/SubjectEnum';\nexport type {\n QuestionResult,\n Question,\n UserAnswerItem,\n QuizState,\n QuizInterface,\n DraftAnswerItem,\n SaveDraftPayload,\n DraftApiClient,\n} from './components/Quiz/useQuizStore';\n\n// Multiple Choice and Icon Components\nexport { MultipleChoiceList } from './components/MultipleChoice/MultipleChoice';\nexport { FillInBlanks } from './components/FillInBlanks/FillInBlanks';\nexport type {\n FillInBlanksProps,\n FillInBlanksOption,\n} from './components/FillInBlanks/FillInBlanks';\nexport { ConnectDots } from './components/ConnectDots/ConnectDots';\nexport type {\n ConnectDotsProps,\n ConnectDotsOption,\n} from './components/ConnectDots/ConnectDots';\nexport { default as IconRender } from './components/IconRender/IconRender';\n\n// Hooks\nexport { useMobile, getDeviceType } from './hooks/useMobile';\nexport type { DeviceType } from './hooks/useMobile';\nexport { useTheme } from './hooks/useTheme';\nexport type { ThemeMode } from './hooks/useTheme';\nexport { useBrandingLogo } from './hooks/useBrandingLogo';\nexport type {\n BrandingLogoVariant,\n UseBrandingLogoOptions,\n} from './hooks/useBrandingLogo';\nexport { BrandingLogo } from './components/BrandingLogo/BrandingLogo';\nexport type { BrandingLogoProps } from './components/BrandingLogo/BrandingLogo';\nexport { UserIcon } from './components/UserIcon/UserIcon';\nexport type { UserIconProps } from './components/UserIcon/UserIcon';\nexport { useDraftAutoSave } from './hooks/useDraftAutoSave';\nexport type {\n ApiClient as DraftApiClientAdapter,\n UseDraftAutoSaveOptions,\n} from './hooks/useDraftAutoSave';\nexport { useCep } from './hooks/useCep';\nexport type { CepData } from './hooks/useCep';\n\n// BreadcrumbMenu Components\nexport { BreadcrumbMenu } from './components/BreadcrumbMenu/BreadcrumbMenu';\nexport type { BreadcrumbMenuProps } from './components/BreadcrumbMenu/BreadcrumbMenu';\nexport { useBreadcrumbBuilder } from './components/BreadcrumbMenu/useBreadcrumbBuilder';\nexport type {\n BreadcrumbBuilderConfig,\n BreadcrumbLevel,\n BreadcrumbLevelWithData,\n BreadcrumbLevelStatic,\n} from './components/BreadcrumbMenu/useBreadcrumbBuilder';\nexport { useUrlParams } from './components/BreadcrumbMenu/useUrlParams';\nexport type { UrlParamsConfig } from './components/BreadcrumbMenu/useUrlParams';\nexport { useBreadcrumb } from './components/BreadcrumbMenu/breadcrumbStore';\nexport type { BreadcrumbItem } from './components/BreadcrumbMenu/breadcrumbStore';\n// Auth Hooks\nexport { useAppInitialization } from './hooks/useAppInitialization';\nexport { useAppContent } from './hooks/useAppContent';\nexport { useInstitutionId, useInstitution } from './hooks/useInstitution';\nexport type { InstitutionData } from './hooks/useInstitution';\nexport { useAuthStore } from './store/authStore';\nexport { useAppStore } from './store/appStore';\nexport { useQuestionFiltersStore } from './store/questionFiltersStore';\nexport type { QuestionFiltersState } from './store/questionFiltersStore';\nexport { useLessonFiltersStore } from './store/lessonFiltersStore';\nexport type { LessonFiltersState } from './store/lessonFiltersStore';\nexport { useModulesStore } from './store/modulesStore';\nexport type { ModulesState, ModulesConfig } from './store/modulesStore';\nexport { useModules } from './hooks/useModules';\nexport type { UseModulesReturn } from './hooks/useModules';\nexport { ModuleProtectedRoute } from './components/ModuleProtectedRoute';\nexport type { ModuleProtectedRouteProps } from './components/ModuleProtectedRoute';\nexport type {\n AuthState,\n SessionInfo,\n AuthTokens,\n User,\n UserProfile,\n} from './store/authStore';\nexport { ActivityCardQuestionBanks } from './components/ActivityCardQuestionBanks/ActivityCardQuestionBanks';\nexport { ActivityCardQuestionPreview } from './components/ActivityCardQuestionPreview/ActivityCardQuestionPreview';\nexport { ActivityListQuestions } from './components/ActivityListQuestions/ActivityListQuestions';\nexport type { ActivityListQuestionsProps } from './components/ActivityListQuestions/ActivityListQuestions';\nexport type {\n ActivityCardQuestionPreviewProps,\n MatchingPairPreview,\n} from './components/ActivityCardQuestionPreview/ActivityCardQuestionPreview';\nexport { ActivityPreview } from './components/ActivityPreview/ActivityPreview';\nexport type {\n ActivityPreviewProps,\n PreviewQuestion,\n} from './components/ActivityPreview/ActivityPreview';\n\nexport { LessonPreview } from './components/LessonPreview/LessonPreview';\nexport type {\n LessonPreviewProps,\n PreviewLesson,\n} from './components/LessonPreview/LessonPreview';\n\nexport {\n QuestionsPdfGenerator,\n QuestionsPdfContent,\n useQuestionsPdfPrint,\n} from './components/QuestionsPdfGenerator';\nexport type { QuestionsPdfGeneratorProps } from './components/QuestionsPdfGenerator';\n// Utils\nexport {\n cn,\n getSubjectColorWithOpacity,\n syncDropdownState,\n getSelectedIdsFromCategories,\n toggleArrayItem,\n toggleSingleValue,\n formatScore,\n formatPercentageRounded,\n} from './utils/utils';\nexport { convertActivityFiltersToQuestionsFilter } from './utils/questionFiltersConverter';\nexport {\n MASK_TYPE,\n applyInputMask,\n formatCep,\n formatCnpj,\n formatCpf,\n formatDocument,\n formatPhone,\n maskCepInput,\n maskCnpjInput,\n maskCpfInput,\n maskPhoneInput,\n} from './utils/brazilianFormatters';\nexport { BR_STATES_FULL, UF_LIST } from './utils/brazilianStates';\nexport type { UF } from './utils/brazilianStates';\nexport { default as MaskedInput } from './components/MaskedInput/MaskedInput';\nexport type { MaskedInputProps } from './components/MaskedInput/MaskedInput';\nexport { default as HierarchicalCheckboxGroup } from './components/HierarchicalCheckboxGroup/HierarchicalCheckboxGroup';\nexport type {\n HierarchicalCheckboxGroupItem,\n HierarchicalCheckboxGroupProps,\n HierarchicalCheckboxItem,\n HierarchicalCheckboxItemsLayout,\n} from './components/HierarchicalCheckboxGroup/HierarchicalCheckboxGroup';\nexport {\n mapQuestionTypeToEnum,\n mapQuestionTypeToEnumRequired,\n} from './utils/questionTypeUtils';\n// Activity Details Types\nexport {\n STUDENT_ACTIVITY_STATUS,\n ACTIVITY_AVAILABILITY,\n studentActivityStatusSchema,\n} from './types/activityDetails';\n\n// Lesson Availability Types\nexport { LESSON_AVAILABILITY } from './types/lessonAvailability';\nexport type {\n LessonAvailability,\n LessonAvailabilityResult,\n} from './types/lessonAvailability';\n\n// Lesson Availability Utils\nexport {\n checkLessonAvailability,\n isLessonNotYetAvailable,\n isLessonExpired,\n} from './utils/lessonAvailabilityUtils';\n\n// Activity Details Utils\nexport {\n getStatusBadgeConfig,\n formatTimeSpent,\n formatQuestionNumbers,\n formatDateToBrazilian,\n} from './utils/utils';\nexport type {\n StudentActivityStatus,\n ActivityAvailability,\n ActivityStudentData,\n Pagination as ActivityDetailsPagination,\n GeneralStats,\n QuestionStats,\n ActivityMetadata,\n ActivityDetailsData,\n ActivityDetailsQueryParams,\n ActivityStudentTableItem,\n StatusBadgeConfig,\n} from './types/activityDetails';\n\n// Activity Details Component\nexport { ActivityDetails } from './components/ActivityDetails/ActivityDetails';\nexport type { ActivityDetailsProps } from './components/ActivityDetails/ActivityDetails';\nexport { useActivityDetails } from './hooks/useActivityDetails';\nexport type { UseActivityDetailsReturn } from './hooks/useActivityDetails';\n\n// Support Components\nexport {\n Support,\n TicketModal,\n getCategoryIcon,\n supportSchema,\n} from './components/Support';\nexport type {\n SupportProps,\n TicketModalProps,\n SupportFormData,\n} from './components/Support';\n\n// Support Types\nexport {\n SupportStatus,\n SupportCategory,\n getStatusBadgeAction,\n getStatusText,\n getCategoryText,\n mapApiStatusToInternal,\n mapInternalStatusToApi,\n SupportType,\n} from './types/support';\nexport type {\n TicketStatus,\n ProblemType,\n TabType,\n SupportResponse,\n SupportTicket,\n CreateSupportTicketRequest,\n CreateSupportTicketResponse,\n SupportTicketAPI,\n SupportPagination,\n GetSupportTicketsResponse,\n SupportAnswerAPI,\n GetSupportAnswersResponse,\n SubmitSupportAnswerRequest,\n SubmitSupportAnswerResponse,\n SupportApiClient,\n SupportFeatureFlags,\n} from './types/support';\n\n// Zendesk Widget Component\nexport { ZendeskWidget } from './components/ZendeskWidget';\nexport type { ZendeskWidgetProps } from './components/ZendeskWidget';\n\n// Support Feature Flag Hook\nexport { useSupportFeatureFlag } from './hooks/useSupportFeatureFlag';\nexport type {\n UseSupportFeatureFlagConfig,\n UseSupportFeatureFlagReturn,\n} from './hooks/useSupportFeatureFlag';\n\n// SendActivityModal Component\nexport { SendActivityModal } from './components/SendActivityModal';\nexport { useSendActivityModal } from './components/SendActivityModal';\nexport type {\n SendActivityModalProps,\n SendActivityFormData,\n ActivitySubtype,\n StepErrors,\n StepState,\n StepConfig,\n SendActivityModalInitialData,\n} from './components/SendActivityModal';\nexport {\n validateActivityStep,\n validateRecipientStep,\n validateDeadlineStep,\n validateStep,\n isStepValid,\n isFormValid,\n ERROR_MESSAGES,\n} from './components/SendActivityModal';\n\n// ChooseActivityModelModal Component\nexport { ChooseActivityModelModal } from './components/ChooseActivityModelModal';\nexport type { ChooseActivityModelModalProps } from './components/ChooseActivityModelModal';\n\n// SaveActivityModelModal Component\nexport { SaveActivityModelModal } from './components/SaveActivityModelModal';\nexport type { SaveActivityModelModalProps } from './components/SaveActivityModelModal';\n\n// SendLessonModal Component\nexport { SendLessonModal } from './components/SendLessonModal';\nexport { useSendLessonModal } from './components/SendLessonModal';\nexport type {\n SendLessonModalProps,\n SendLessonFormData,\n StepErrors as SendLessonStepErrors,\n StepState as SendLessonStepState,\n StepConfig as SendLessonStepConfig,\n} from './components/SendLessonModal';\n\n// Recommended Lessons / RecommendedClass History Component\nexport {\n RecommendedLessonsHistory,\n RecommendedClassPageTab,\n} from './components/RecommendedLessonsHistory';\nexport type { RecommendedLessonsHistoryProps } from './components/RecommendedLessonsHistory';\n\n// Recommended Lesson Details Component\nexport {\n RecommendedLessonDetails,\n StudentPerformanceModal,\n} from './components/RecommendedLessonDetails';\nexport type {\n RecommendedLessonDetailsProps,\n StudentPerformanceModalProps,\n StudentPerformanceData,\n StudentPerformanceLabels,\n LessonProgress,\n LessonQuestion,\n QuestionAlternative,\n LessonDetailsLabels,\n DisplayStudent,\n} from './components/RecommendedLessonDetails';\n\n// Recommended Lessons Hook Factory\nexport {\n createUseRecommendedLessonsHistory,\n createRecommendedLessonsHistoryHook,\n determineRecommendedClassStatus,\n transformRecommendedClassToTableItem,\n handleRecommendedClassFetchError,\n recommendedClassHistoryApiResponseSchema,\n} from './hooks/useRecommendedLessons';\nexport type {\n UseRecommendedLessonsHistoryState,\n UseRecommendedLessonsHistoryReturn,\n} from './hooks/useRecommendedLessons';\n\n// Recommended Lessons Page Hook Factory\nexport {\n createUseRecommendedLessonsPage,\n createRecommendedLessonsPageHook,\n} from './hooks/useRecommendedLessonsPage';\nexport type {\n UseRecommendedLessonsPageConfig,\n UseRecommendedLessonsPageReturn,\n RecommendedLessonsApiClient,\n RecommendedLessonsUserData,\n RecommendedLessonsPagePaths,\n RecommendedLessonsPageEndpoints,\n RecommendedLessonsPageTexts,\n UserInstitution as RecommendedLessonsUserInstitution,\n SubTeacherTopicClass as RecommendedLessonsSubTeacherTopicClass,\n} from './hooks/useRecommendedLessonsPage';\n\n// Recommended Lesson Details Hook Factory\nexport {\n createUseRecommendedLessonDetails,\n createRecommendedLessonDetailsHook,\n handleLessonDetailsFetchError,\n recommendedClassApiResponseSchema,\n recommendedClassDetailsApiResponseSchema,\n historyApiResponseSchema,\n} from './hooks/useRecommendedLessonDetails';\nexport type {\n UseRecommendedLessonDetailsState,\n UseRecommendedLessonDetailsReturn,\n LessonDetailsApiClient,\n} from './hooks/useRecommendedLessonDetails';\n\n// Recommended Lessons Types\nexport {\n RecommendedClassApiStatus,\n RecommendedClassDisplayStatus,\n RecommendedClassBadgeActionType,\n getRecommendedClassStatusBadgeAction,\n RECOMMENDED_CLASS_FILTER_STATUS_OPTIONS,\n RECOMMENDED_CLASS_STATUS_OPTIONS,\n StudentLessonStatus,\n getStudentStatusBadgeAction,\n isDeadlinePassed,\n deriveStudentStatus,\n formatDaysToComplete,\n RecommendedClassDraftType,\n RECOMMENDED_CLASS_ACTIVITY_STATUS,\n} from './types/recommendedLessons';\nexport type {\n RecommendedClassSubject,\n RecommendedClassCreator,\n RecommendedClassStats,\n RecommendedClassBreakdown,\n RecommendedClassData,\n RecommendedClassHistoryItem,\n RecommendedClassTableItem,\n RecommendedClassHistoryApiResponse,\n RecommendedClassHistoryFilters,\n RecommendedClassHistoryPagination,\n RecommendedClassFilterOption,\n RecommendedClassUserFilterData,\n // Lesson Details API Types\n RecommendedClassDetailStudent,\n RecommendedClassDetailAggregated,\n RecommendedClassDetailContentPerformanceItem,\n RecommendedClassDetailContentPerformance,\n RecommendedClassDetailsData,\n RecommendedClassDetailsApiResponse,\n RecommendedClassLessonSubject,\n RecommendedClassLesson,\n RecommendedClassLessonProgress,\n RecommendedClassLessonsItem,\n RecommendedClassMetadata,\n RecommendedClassApiResponse,\n LessonDetailsData,\n // RecommendedClass Models Types\n RecommendedClassModelResponse,\n RecommendedClassModelTableItem,\n RecommendedClassModelsApiResponse,\n RecommendedClassModelFilters,\n RecommendedClassModelPagination,\n // RecommendedClass Activity Types\n RecommendedClassActivityStatus,\n RecommendedClassActivity,\n RecommendedClassSupUsersActivities,\n RecommendedClassActivities,\n} from './types/recommendedLessons';\n\n// RecommendedClass Models Hook Factory\nexport {\n createUseRecommendedClassModels,\n createRecommendedClassModelsHook,\n transformRecommendedClassModelToTableItem,\n handleRecommendedClassModelFetchError,\n recommendedClassModelsApiResponseSchema,\n DEFAULT_RECOMMENDED_CLASS_MODELS_PAGINATION,\n} from './hooks/useRecommendedClassModels';\nexport type {\n UseRecommendedClassModelsState,\n UseRecommendedClassModelsReturn,\n} from './hooks/useRecommendedClassModels';\n\n// RecommendedClass Drafts Hook Factory\nexport {\n createUseRecommendedClassDrafts,\n createRecommendedClassDraftsHook,\n handleRecommendedClassDraftFetchError,\n DEFAULT_RECOMMENDED_CLASS_DRAFTS_PAGINATION,\n} from './hooks/useRecommendedClassDrafts';\nexport type {\n UseRecommendedClassDraftsState,\n UseRecommendedClassDraftsReturn,\n} from './hooks/useRecommendedClassDrafts';\n\n// RecommendedClass Drafts Tab Component\nexport { RecommendedClassDraftsTab } from './components/RecommendedLessonsHistory/tabs/DraftsTab';\nexport type { RecommendedClassDraftsTabProps } from './components/RecommendedLessonsHistory/tabs/DraftsTab';\n\n// Activities History Component\nexport { ActivitiesHistory } from './components/ActivitiesHistory';\nexport type { ActivitiesHistoryProps } from './components/ActivitiesHistory';\n\n// Activity Page Layout Component\nexport {\n ActivityPageLayout,\n ActivityTab,\n} from './components/ActivityPageLayout';\nexport type { ActivityPageLayoutProps } from './components/ActivityPageLayout';\n\n// Unified History Page Component\nexport { UnifiedHistoryPage } from './components/UnifiedHistoryPage';\nexport type {\n UnifiedHistoryPageProps,\n UserData as UnifiedHistoryPageUserData,\n ApiFilterOptions as UnifiedHistoryPageApiFilterOptions,\n} from './components/UnifiedHistoryPage';\n\n// Unified Draft Model Page Component\nexport { UnifiedDraftModelPage } from './components/UnifiedDraftModelPage';\nexport type {\n UnifiedDraftModelPageProps,\n UserData as UnifiedDraftModelPageUserData,\n} from './components/UnifiedDraftModelPage';\n\n// Activities History Hook Factory\nexport {\n createUseActivitiesHistory,\n createActivitiesHistoryHook,\n transformActivityToTableItem,\n extractActivityFilterOptions,\n DEFAULT_ACTIVITIES_PAGINATION,\n DEFAULT_ACTIVITY_FILTER_OPTIONS,\n} from './hooks/useActivitiesHistory';\nexport type {\n UseActivitiesHistoryOptions,\n UseActivitiesHistoryState,\n UseActivitiesHistoryReturn,\n ActivityApiFilterOptions,\n} from './hooks/useActivitiesHistory';\n\n// Activity Drafts Hook Factory\nexport {\n createUseActivityDrafts,\n createActivityDraftsHook,\n transformDraftToTableItem as transformActivityDraftToTableItem,\n DEFAULT_DRAFTS_PAGINATION,\n} from './hooks/useActivityDrafts';\nexport type {\n UseActivityDraftsOptions,\n UseActivityDraftsState,\n UseActivityDraftsReturn,\n} from './hooks/useActivityDrafts';\n\n// Activity Models Hook Factory\nexport {\n createUseActivityModels,\n createActivityModelsHook,\n transformModelToTableItem,\n DEFAULT_MODELS_PAGINATION,\n} from './hooks/useActivityModels';\n\n// Activity Draft Model Page Hook (shared logic for drafts/models pages)\nexport { useActivityDraftModelPage } from './hooks/useActivityDraftModelPage';\nexport type {\n UseActivityDraftModelPageOptions,\n UseActivityDraftModelPageReturn,\n} from './hooks/useActivityDraftModelPage';\nexport type {\n UseActivityModelsOptions,\n UseActivityModelsState,\n UseActivityModelsReturn,\n} from './hooks/useActivityModels';\n\n// Students Highlight Hook Factory\nexport {\n createUseStudentsHighlight,\n createStudentsHighlightHook,\n calculatePerformancePercentage,\n transformStudentHighlightItem,\n handleStudentsHighlightFetchError,\n studentsHighlightApiResponseSchema,\n PERIOD_TABS,\n} from './hooks/useStudentsHighlight';\nexport type {\n StudentsHighlightPeriod,\n StudentsHighlightType,\n TrendDirection,\n StudentsHighlightFilters,\n StudentHighlightApiItem,\n StudentsHighlightApiResponse,\n StudentHighlightItem,\n UseStudentsHighlightState,\n UseStudentsHighlightReturn,\n} from './hooks/useStudentsHighlight';\n\n// Questions Data Hook Factory\nexport {\n createUseQuestionsData,\n createQuestionsDataHook,\n transformQuestionsData,\n handleQuestionsDataFetchError,\n questionsDataApiResponseSchema,\n} from './hooks/useQuestionsData';\nexport type {\n QuestionsDataPeriod,\n QuestionsDataTrendDirection,\n QuestionsDataFilters,\n QuestionsDataTrend,\n QuestionsDataApiData,\n QuestionsDataApiResponse,\n QuestionsDataHookResult,\n UseQuestionsDataState,\n UseQuestionsDataReturn,\n} from './hooks/useQuestionsData';\n\n// Activities History Types\nexport {\n ActivityApiStatus,\n ActivityDisplayStatus,\n ActivityBadgeActionType,\n ActivityDraftType,\n getActivityStatusBadgeAction,\n mapActivityStatusToDisplay,\n ACTIVITY_FILTER_STATUS_OPTIONS,\n} from './types/activitiesHistory';\nexport type {\n ActivityHistoryResponse,\n ActivityTableItem,\n ActivityPagination,\n ActivitiesHistoryApiResponse,\n ActivityHistoryFilters,\n ActivityDraftFilters,\n ActivityModelResponse,\n ActivityModelTableItem,\n ActivityModelsApiResponse,\n ActivityModelFilters,\n ActivityFilterOption,\n ActivityUserFilterData,\n} from './types/activitiesHistory';\n\n// Subject Mappers\nexport {\n mapSubjectNameToEnum,\n mapSubjectEnumToName,\n} from './utils/subjectMappers';\n\n// Subject Cell Renderer\nexport { renderSubjectCell } from './utils/renderSubjectCell';\nexport { renderTextCell } from './utils/renderTextCell';\n\n// Filter Helpers (robust version with deduplication)\nexport {\n getSchoolOptionsFromUserData,\n getSubjectOptionsFromUserData,\n getSchoolYearOptionsFromUserData,\n getClassOptionsFromUserData,\n buildUserFilterData,\n mergeFilterOptions,\n} from './utils/filterHelpers';\nexport type {\n UserInstitutionData,\n SubTeacherTopicClassData,\n UserFilterSourceData,\n} from './utils/filterHelpers';\n\n// Draft Model Filter Helpers\nexport { createDraftsModelsFiltersConfig } from './utils/draftModelFilterHelpers';\n\n// Pagination Types\nexport type { PaginationData } from './types/pagination';\n\n// Chat Hooks\nexport { useChat, createUseChat, WS_STATES } from './hooks/useChat';\nexport type { UseChatOptions, UseChatReturn } from './hooks/useChat';\nexport { useChatRooms, createUseChatRooms } from './hooks/useChatRooms';\nexport type {\n UseChatRoomsOptions,\n UseChatRoomsReturn,\n} from './hooks/useChatRooms';\n\n// Chat Types\nexport { CHAT_MESSAGE_TYPES, PROFILE_ROLES } from './types/chat';\nexport type {\n ChatMessageType,\n ChatUser,\n AvailableUsers,\n ChatRoom,\n ChatRoomWithDetails,\n ChatMessage,\n ChatParticipant,\n WSUserInfo,\n WSClientMessageType,\n WSServerMessageType,\n WSClientMessage,\n WSServerMessage,\n ChatApiClient,\n AvailableUsersResponse,\n CreateRoomResponse,\n GetRoomsResponse,\n GetRoomDetailsResponse,\n} from './types/chat';\n\n// Chat Component\nexport { Chat, ChatLoading } from './components/Chat';\nexport type { ChatProps } from './components/Chat';\n\n// Chat Utils\nexport {\n getChatWsUrl,\n getChatUserInfo,\n isChatUserInfoValid,\n} from './utils/chatUtils';\nexport type { ChatUserInfo } from './utils/chatUtils';\n\n// Chatbot Hook\nexport { createUseChatbot } from './hooks/useChatbot';\nexport type { UseChatbotReturn } from './hooks/useChatbot';\n\n// Chatbot Types\nexport { CHATBOT_MESSAGE_ROLES } from './types/chatbot';\nexport type {\n ChatbotRole,\n ChatbotMessage as ChatbotMessageData,\n ChatbotConversation,\n ChatbotCurrentContext,\n SendChatbotMessagePayload,\n SendChatbotMessageResult,\n ChatbotUser,\n ChatbotApiClient,\n} from './types/chatbot';\n\n// Chatbot Components\nexport {\n Chatbot,\n ChatbotFab,\n ChatbotPanel,\n ChatbotMessageList,\n ChatbotMessage,\n ChatbotInput,\n ChatbotTypingIndicator,\n ChatbotConversationList,\n ChatbotContentRenderer,\n} from './components/Chatbot';\nexport type {\n ChatbotProps,\n ChatbotFabProps,\n ChatbotPanelProps,\n ChatbotMessageListProps,\n ChatbotMessageProps,\n ChatbotInputProps,\n ChatbotTypingIndicatorProps,\n ChatbotConversationListProps,\n ChatbotContentRendererProps,\n} from './components/Chatbot';\n\n// Accessibility Widget\nexport {\n AccessibilityWidget,\n AccessibilityFab,\n AccessibilityPanel,\n LibrasFab,\n VLibrasLoader,\n ReadingAid,\n ColorBlindFilters,\n TTSController,\n WebSpeechProvider,\n} from './components/AccessibilityWidget';\nexport type {\n AccessibilityWidgetProps,\n AccessibilityFabProps,\n AccessibilityFabPosition,\n AccessibilityFabVerticalAlign,\n AccessibilityPanelProps,\n LibrasFabProps,\n TTSProvider,\n TTSVoice,\n TTSSpeakOptions,\n TTSProviderEvents,\n} from './components/AccessibilityWidget';\n\n// Accessibility Store + Hook\nexport {\n useAccessibilityStore,\n DEFAULT_ACCESSIBILITY_PREFERENCES,\n ColorBlindMode,\n getColorBlindClass,\n getColorBlindFilterId,\n} from './store/accessibilityStore';\nexport type {\n AccessibilityStore,\n AccessibilityState,\n AccessibilityActions,\n AccessibilityPreferences,\n ContrastMode,\n SaturationMode,\n FontSizeLevel,\n SpacingLevel,\n ReadingAid as ReadingAidMode,\n TTSMode,\n TTSStatus,\n} from './store/accessibilityStore';\nexport { useA11yPreferences } from './hooks/useA11yPreferences';\nexport { useA11yKeyboardShortcut } from './hooks/useA11yKeyboardShortcut';\nexport { useTTS } from './hooks/useTTS';\nexport type { UseTTSReturn } from './hooks/useTTS';\n\n// Forum Component\nexport { Forum } from './components/Forum/Forum';\nexport type { ForumProps } from './components/Forum/Forum';\n\n// Forum Hook\nexport { createUseForum } from './hooks/useForum';\nexport type { UseForumReturn } from './hooks/useForum';\n\n// Forum Types\nexport type {\n ForumPostBase,\n ForumTopic,\n ForumReply,\n ForumPagination,\n ForumTopicsResponse,\n ForumTopicDetailResponse,\n ForumApiClient,\n} from './types/forum';\n\n// General Activity Types (calendar, activity list)\nexport {\n ActivityStatus as GeneralActivityStatus,\n ActivityFilter,\n CalendarActivityStatus,\n} from './types/activities';\nexport type {\n Activity,\n CalendarActivity,\n ActivityResponse,\n CalendarActivitiesResponse,\n} from './types/activities';\n\n// Send Activity Hook\nexport { useSendActivity } from './hooks/useSendActivity';\nexport type {\n UseSendActivityConfig,\n UseSendActivityReturn,\n SendActivityCategoriesData,\n CreateActivityPayload,\n StudentPayload,\n ActivityModelItem,\n RecipientItem as SendActivityRecipientItem,\n} from './types/sendActivity';\n\n// Performance Types and Utils\nexport {\n PERFORMANCE_TAG_CONFIG,\n getPerformanceTag,\n getPerformanceTagConfig,\n} from './types/performance';\nexport { PerformanceTag } from './types/performance';\nexport type { PerformanceTagConfig, TimeInterval } from './types/performance';\n\n// Student Performance Details Modal\nexport { StudentPerformanceDetailsModal } from './components/StudentPerformanceDetailsModal';\nexport type {\n StudentPerformanceDetailsModalProps,\n StudentPerformanceDetailsData,\n StudentPerformanceDetailsLabels,\n ActivityProgress,\n} from './components/StudentPerformanceDetailsModal';\n\n// Student Lesson Progress Modal\nexport { StudentLessonProgressModal } from './components/StudentLessonProgressModal';\nexport type {\n StudentLessonProgressModalProps,\n StudentLessonProgressData,\n StudentLessonProgressLabels,\n TopicProgressItem,\n SubtopicProgressItem,\n ContentProgressItem,\n LessonProgressStatus,\n} from './components/StudentLessonProgressModal';\nexport { DEFAULT_LESSON_PROGRESS_LABELS } from './components/StudentLessonProgressModal';\n\n// TimeChart Components\nexport {\n TimeChart,\n TIME_CHART_CATEGORY_KEY,\n STUDENT_CATEGORIES,\n DEFAULT_CATEGORIES,\n calculateHourTicks,\n bgClassToCssVar,\n} from './components/TimeChart/TimeChart';\nexport type {\n TimeChartProps,\n TimeChartData,\n TimeChartCategory,\n TimeChartDayData,\n TimeChartRequest,\n TimeChartStudentPeriodItem,\n TimeChartStudentItemBreakdown,\n TimeChartStudentData,\n TimeChartDefaultPeriodItem,\n TimeChartDefaultItemBreakdown,\n TimeChartDefaultData,\n TimeChartResponse,\n} from './components/TimeChart/TimeChart';\n\n// TimeReport Components\nexport {\n TimeReport,\n TimeCard,\n formatHoursToTime,\n getTrendDirection,\n formatVariation,\n} from './components/TimeReport/TimeReport';\nexport type {\n TimeReportProps,\n TimeCardProps,\n TimeReportTab,\n TimeCardData,\n TimeCardTrend,\n TimeReportPeriod,\n TimeReportRequest,\n TimeMetric,\n TimeReportData,\n TimeReportResponse,\n} from './components/TimeReport/TimeReport';\n\n// PerformanceReport Components\nexport {\n PerformanceReport,\n PerformanceCard,\n} from './components/PerformanceReport/PerformanceReport';\nexport type {\n PerformanceReportProps,\n PerformanceCardProps,\n PerformanceReportTab,\n PerformanceCardData,\n PerformanceReportPeriod,\n PerformanceReportRequest,\n PerformanceStudentData,\n PerformanceDefaultData,\n PerformanceReportResponse,\n} from './components/PerformanceReport/PerformanceReport';\n\n// PerformanceQuestionsData Components\nexport {\n PerformanceQuestionsData,\n PerformanceQuestionsVariant,\n} from './components/PerformanceQuestionsData/PerformanceQuestionsData';\nexport type {\n PerformanceQuestionsDataProps,\n QuestionsVariantData,\n ContentVariantData,\n PerformanceFilterOption,\n PerformanceFilterConfig,\n PerformanceQuestionsPeriod,\n PerformanceQuestionsRequest,\n PerformanceQuestionsStudentResponse,\n PerformanceQuestionsDefaultResponse,\n} from './components/PerformanceQuestionsData/PerformanceQuestionsData';\n\n// PerformanceRanking Components\nexport { PerformanceRanking } from './components/PerformanceRanking/PerformanceRanking';\nexport type {\n PerformanceRankingProps,\n PerformanceRankingItem,\n PerformanceRankingData,\n GroupedBy,\n} from './components/PerformanceRanking/PerformanceRanking';\n\n// PerformanceReportModal Components\nexport {\n PerformanceReportModal,\n PerformanceReportModalVariant,\n} from './components/PerformanceReportModal/PerformanceReportModal';\nexport type {\n PerformanceReportModalProps,\n UserPerformanceRequest,\n UserPerformanceQuestionStats,\n UserPerformanceMaterialStats,\n UserPerformanceLesson,\n UserPerformanceStudentData,\n UserPerformanceProfessionalData,\n} from './components/PerformanceReportModal/PerformanceReportModal';\n\n// AccessReportModal Components\nexport {\n AccessReportModal,\n AccessReportModalVariant,\n} from './components/AccessReportModal/AccessReportModal';\nexport type {\n AccessReportModalProps,\n AccessReportStudentData,\n AccessReportProfessionalData,\n AccessReportTimePercentage,\n AccessReportUser,\n AccessReportByPlatform,\n} from './components/AccessReportModal/AccessReportModal';\n\n// DownloadModal Components\nexport { default as DownloadModal } from './components/DownloadModal/DownloadModal';\nexport { DOWNLOAD_FORMAT } from './enums/DownloadFormat';\nexport { FILTER_CATEGORY, FILTER_GROUP } from './enums/FilterEnums';\nexport type {\n DownloadModalProps,\n DownloadFormat,\n} from './components/DownloadModal/DownloadModal';\n\n// PrintableUsersTable Component\nexport { default as PrintableUsersTable } from './components/PrintableUsersTable/PrintableUsersTable';\nexport type { PrintableUsersTableProps } from './components/PrintableUsersTable/PrintableUsersTable';\n\n// Report Export Utils\nexport { downloadExcel } from './utils/exportExcel';\nexport { printAsPdf } from './utils/exportPdf';\n\n// Report Export Types\nexport type { ExcelCell, SheetConfig } from './utils/exportExcel';\n\n// SimulatedPerformance Component\nexport {\n useSimulatedPerformance,\n SimulatedPerformanceView,\n SCORE_TYPE_OPTIONS,\n SimulatedViewTab,\n} from './components/SimulatedPerformance';\nexport type {\n UseSimulatedPerformanceOptions,\n UseSimulatedPerformanceReturn,\n SimulatedPerformanceViewProps,\n} from './components/SimulatedPerformance';\n\n// ComparatorChart Components\nexport {\n // Base chart components\n Legend as ComparatorLegend,\n PercentageScale,\n ChartArea,\n BarChartRow,\n // Content components\n KnowledgeAreasContent,\n CurricularComponentsContent,\n CompetenciesContent,\n NationalAverageCard,\n NationalAveragesContent,\n // UI components\n ComparatorEmptyState,\n ComparatorLoadingState,\n ComparatorSelectTypeStep,\n ComparatorSelectItemsStep,\n ComparatorTabContent,\n // Main view\n ComparatorView,\n} from './components/ComparatorChart';\nexport type {\n LegendProps as ComparatorLegendProps,\n LegendItem as ComparatorLegendItem,\n ChartAreaProps,\n BarChartRowProps,\n BarChartValue,\n KnowledgeAreasContentProps,\n CurricularComponentsContentProps,\n CompetenciesContentProps,\n NationalAverageCardProps,\n NationalAveragesContentProps,\n ComparatorEmptyStateProps,\n ComparatorSelectTypeStepProps,\n ComparatorSelectItemsStepProps,\n ComparatorTabContentProps,\n ComparatorViewProps,\n} from './components/ComparatorChart';\n\n// Comparator Types\nexport {\n ComparatorTabValue,\n DEFAULT_COMPARATOR_LABELS,\n DEFAULT_COMPARATOR_TABS,\n COMPARATOR_CHART_COLORS,\n} from './types/comparator';\nexport type {\n ComparisonType,\n ComparatorTabType,\n ComparisonItem,\n KnowledgeAreaData,\n CurricularComponentData,\n CompetencyData,\n NationalAverageData,\n ComparatorData,\n ComparatorApiClient,\n ComparatorStoreState,\n UseComparatorReturn,\n ComparatorLabels,\n ComparatorTab,\n} from './types/comparator';\n\n// Comparator Hook\nexport {\n createUseComparator,\n createComparatorHook,\n} from './hooks/useComparator';\nexport type { UseComparatorConfig } from './hooks/useComparator';\n\n// Comparator Store\nexport {\n createComparatorStore,\n useComparatorStore,\n} from './store/comparatorStore';\nexport type { CreateComparatorStoreConfig } from './store/comparatorStore';\n\n// User Store\nexport { createUserStore } from './store/userStore';\nexport type {\n CreateUserStoreConfig,\n UserStoreApiClient,\n UserStoreState,\n} from './store/userStore';\n\n// User Types\nexport type {\n User as UserData,\n UserInfos,\n Profile,\n Institution,\n School as UserSchool,\n SchoolYear as UserSchoolYear,\n Class as UserClass,\n UserInstitution,\n Subject as UserSubject,\n SubTeacherTopicClass,\n MyDataResponse,\n UpdateMyDataRequest,\n UserTelemetryData,\n StudentDetailsResponse,\n} from './types/user';\n\n// Exam Types\nexport {\n ExamStatus,\n ExamDisplayStatus,\n mapExamStatusToDisplay,\n} from './types/examsHistory';\nexport type {\n ExamFilterOption,\n ExamApiFilterOptions,\n ExamSubject,\n ExamBreakdownItem,\n ExamHistoryResponse,\n ExamTableItem,\n ExamsHistoryApiResponse,\n ExamHistoryFilters,\n ExamPagination,\n} from './types/examsHistory';\n\nexport { ExamDraftType, ExamActivityCategory } from './types/examDrafts';\nexport type {\n ExamDraftFilters,\n ExamModelResponse,\n ExamModelTableItem,\n ExamModelsApiResponse,\n ExamModelFilters,\n ExamModelsPagination,\n} from './types/examDrafts';\n\n// Exam Hooks Factories\nexport {\n createUseExamsHistory,\n createExamsHistoryHook,\n transformExamToTableItem,\n handleExamFetchError,\n extractExamFilterOptions,\n DEFAULT_EXAMS_PAGINATION,\n DEFAULT_EXAM_FILTER_OPTIONS,\n} from './hooks/useExamsHistory';\nexport type {\n UseExamsHistoryState,\n UseExamsHistoryReturn,\n} from './hooks/useExamsHistory';\n\n// NOTE: useExamDrafts and useExamModels removed - use createUseActivityDrafts/createUseActivityModels with { activityCategory: 'PROVA' }\n\n// Exam Page Layout Component\nexport { ExamPageLayout, ExamTab } from './components/ExamPageLayout';\nexport type { ExamPageLayoutProps } from './components/ExamPageLayout';\n\n// Exam Table Configs\nexport {\n examsTableColumns,\n getExamStatusBadgeAction,\n createExamDraftsModelsTableColumns,\n} from './components/ExamPageLayout';\nexport type { ExamTableCallbacks } from './components/ExamPageLayout';\n\n// Answer Sheet Preview Components\nexport {\n AnswerSheetPreview,\n AnswerSheetsBatchPreview,\n AnswerSheetCard,\n CardContainer as AnswerSheetCardContainer,\n PageContainer as AnswerSheetPageContainer,\n PrintStyles as AnswerSheetPrintStyles,\n} from './components/ExamPageLayout';\nexport type {\n AnswerSheetPreviewProps,\n AnswerSheetsBatchPreviewProps,\n AnswerSheetData,\n AnswerSheetCardProps,\n} from './components/ExamPageLayout';\n\n// Exam Filter Helpers\nexport {\n EXAM_STATUS_OPTIONS,\n EXAM_FILTER_CATEGORY,\n EXAM_FILTER_GROUP,\n createExamDraftsModelsFiltersConfig,\n createExamHistoryFiltersConfig,\n} from './utils/examFilterHelpers';\n\n// Exam Details Types\nexport {\n StudentAnswerStatus,\n StudentAnswerDisplayStatus,\n} from './types/examDetails';\nexport type {\n ExamStudentResult,\n ExamStudentTableItem,\n ExamStats,\n ExamDetailsData,\n ExamDetailsPagination,\n ExamDetailsFilters,\n} from './types/examDetails';\n\n// Exam Details Hook Factory\nexport {\n createUseExamDetails,\n createExamDetailsHook,\n transformStudent,\n mapBackendStatusToFrontend,\n handleExamDetailsFetchError,\n DEFAULT_EXAM_DETAILS_PAGINATION,\n} from './hooks/useExamDetails';\nexport type {\n UseExamDetailsState,\n UseExamDetailsReturn,\n} from './hooks/useExamDetails';\n\n// Exam Details Layout Components\nexport {\n ExamDetailsHeader,\n ExamStatsCards,\n formatQuestions,\n ExamStudentsTable,\n createExamStudentsTableColumns,\n getExamStudentStatusBadgeAction,\n getExamStudentStatusDisplayText,\n ExamDetailsPage,\n} from './components/ExamDetailsLayout';\nexport type {\n ExamDetailsHeaderProps,\n ExamStatsCardsProps,\n ExamStudentsTableProps,\n ExamDetailsPageProps,\n} from './components/ExamDetailsLayout';\n","import { HTMLAttributes, ReactNode } from 'react';\nimport { Bell } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n error: 'bg-error-background text-error-700 focus-visible:outline-none',\n warning: 'bg-warning text-warning-800 focus-visible:outline-none',\n success: 'bg-success text-success-800 focus-visible:outline-none',\n info: 'bg-info text-info-800 focus-visible:outline-none',\n muted: 'bg-background-muted text-background-800 focus-visible:outline-none',\n },\n outlined: {\n error:\n 'bg-error text-error-700 border border-error-300 focus-visible:outline-none',\n warning:\n 'bg-warning text-warning-800 border border-warning-300 focus-visible:outline-none',\n success:\n 'bg-success text-success-800 border border-success-300 focus-visible:outline-none',\n info: 'bg-info text-info-800 border border-info-300 focus-visible:outline-none',\n muted:\n 'bg-background-muted text-background-800 border border-border-300 focus-visible:outline-none',\n },\n exams: {\n exam1: 'bg-exam-1 text-info-700 focus-visible:outline-none',\n exam2: 'bg-exam-2 text-typography-1 focus-visible:outline-none',\n exam3: 'bg-exam-3 text-typography-2 focus-visible:outline-none',\n exam4: 'bg-exam-4 text-success-700 focus-visible:outline-none',\n },\n examsOutlined: {\n exam1:\n 'bg-exam-1 text-info-700 border border-info-700 focus-visible:outline-none',\n exam2:\n 'bg-exam-2 text-typography-1 border border-typography-1 focus-visible:outline-none',\n exam3:\n 'bg-exam-3 text-typography-2 border border-typography-2 focus-visible:outline-none',\n exam4:\n 'bg-exam-4 text-success-700 border border-success-700 focus-visible:outline-none',\n },\n resultStatus: {\n negative: 'bg-error text-error-800 focus-visible:outline-none',\n positive: 'bg-success text-success-800 focus-visible:outline-none',\n },\n notification: 'text-primary',\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n small: 'text-2xs px-2 py-1',\n medium: 'text-xs px-2 py-1',\n large: 'text-sm px-2 py-1',\n} as const;\n\nconst SIZE_CLASSES_ICON = {\n small: 'size-3',\n medium: 'size-3.5',\n large: 'size-4',\n} as const;\n\n/**\n * Badge component props interface\n */\ntype BadgeProps = {\n /** Content to be displayed inside the badge */\n children?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Size of the badge */\n size?: 'small' | 'medium' | 'large';\n /** Visual variant of the badge */\n variant?:\n | 'solid'\n | 'outlined'\n | 'exams'\n | 'examsOutlined'\n | 'resultStatus'\n | 'notification';\n /** Action type of the badge */\n action?:\n | 'error'\n | 'warning'\n | 'success'\n | 'info'\n | 'muted'\n | 'exam1'\n | 'exam2'\n | 'exam3'\n | 'exam4'\n | 'positive'\n | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n notificationActive?: boolean;\n} & HTMLAttributes<HTMLDivElement>;\n\n/**\n * Badge component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the badge\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard div HTML attributes\n * @returns A styled badge element\n *\n * @example\n * ```tsx\n * <Badge variant=\"solid\" action=\"info\" size=\"medium\">\n * Information\n * </Badge>\n * ```\n */\nconst Badge = ({\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'error',\n className = '',\n notificationActive = false,\n ...props\n}: BadgeProps) => {\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const sizeClassesIcon = SIZE_CLASSES_ICON[size];\n const variantActionMap = VARIANT_ACTION_CLASSES[variant] || {};\n const variantClasses =\n typeof variantActionMap === 'string'\n ? variantActionMap\n : ((variantActionMap as Record<string, string>)[action] ??\n (variantActionMap as Record<string, string>).muted ??\n '');\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-xs font-normal gap-1 relative';\n\n const baseClassesIcon = 'flex items-center';\n if (variant === 'notification') {\n return (\n <div\n className={cn(baseClasses, variantClasses, sizeClasses, className)}\n {...props}\n >\n <Bell size={24} className=\"text-current\" aria-hidden=\"true\" />\n\n {notificationActive && (\n <span\n data-testid=\"notification-dot\"\n className=\"absolute top-[5px] right-[10px] block h-2 w-2 rounded-full bg-indicator-error ring-2 ring-white\"\n />\n )}\n </div>\n );\n }\n return (\n <div\n className={cn(baseClasses, variantClasses, sizeClasses, className)}\n {...props}\n >\n {iconLeft && (\n <span className={cn(baseClassesIcon, sizeClassesIcon)}>{iconLeft}</span>\n )}\n {children}\n {iconRight && (\n <span className={cn(baseClassesIcon, sizeClassesIcon)}>\n {iconRight}\n </span>\n )}\n </div>\n );\n};\n\nexport default Badge;\n","import { ReactNode } from 'react';\nimport katex from 'katex';\n\nexport interface KatexMathProps {\n /** LaTeX source to render */\n math: string;\n /** Render as centered display math (block) instead of inline */\n displayMode?: boolean;\n /** Called with the thrown error when KaTeX fails to parse `math` */\n renderError?: (error: unknown) => ReactNode;\n}\n\n/**\n * Renders a single LaTeX expression with KaTeX, calling `katex.renderToString`\n * directly instead of going through `react-katex`.\n *\n * Why not `react-katex`: when bundlers (Vite/esbuild dev optimizer, Rollup)\n * bundle `react-katex` they inline their OWN copy of KaTeX whose function\n * registry ends up broken — symbols render but `\\`-commands (`\\frac`, `\\cdot`,\n * `\\left`, ...) fail with a parse error. Importing `katex` directly here uses\n * the shared, correctly-bundled KaTeX (the same one `rehype-katex` uses), so\n * every command renders. See HtmlMathRenderer for the surrounding pipeline.\n */\nexport const KatexMath = ({\n math,\n displayMode = false,\n renderError,\n}: KatexMathProps) => {\n let html: string;\n try {\n html = katex.renderToString(math, {\n displayMode,\n throwOnError: true,\n });\n } catch (error_) {\n return <>{renderError ? renderError(error_) : null}</>;\n }\n\n const Tag = displayMode ? 'div' : 'span';\n return (\n <Tag\n data-testid=\"react-katex\"\n // KaTeX output is sanitized markup it generates itself from the parsed\n // LaTeX; there is no untrusted HTML passthrough here.\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n};\n\nexport default KatexMath;\n","import { CSSProperties, forwardRef, memo, ReactNode, Ref } from 'react';\nimport 'katex/dist/katex.min.css';\nimport { KatexMath } from './KatexMath';\nimport { cn } from '../../utils/utils';\nimport MarkdownMathRenderer from '../MarkdownMathRenderer/MarkdownMathRenderer';\nimport {\n isLikelyMarkdown,\n processHtmlWithMath,\n sanitizeHtmlForDisplay,\n} from './utils';\n\nexport interface HtmlMathRendererProps {\n /** HTML content to render, may contain LaTeX math expressions */\n content: string;\n /** Additional CSS class names */\n className?: string;\n /** Inline styles */\n style?: CSSProperties;\n /** Whether to sanitize HTML before rendering (default: true) */\n sanitize?: boolean;\n /** Custom error renderer for math errors */\n renderMathError?: (latex: string) => ReactNode;\n /** Test ID for testing */\n testId?: string;\n /** Whether to render as inline element (span) instead of block (div). Use when inside labels or other phrasing content. */\n inline?: boolean;\n}\n\n/**\n * HtmlMathRenderer - Renders HTML content with LaTeX math expressions\n *\n * Supports multiple LaTeX formats:\n * - Display mode: $$...$$ (centered block)\n * - Inline mode: $...$ (inline with text)\n * - LaTeX tags: <latex>...</latex>\n * - Editor spans: <span class=\"math-formula\" data-latex=\"...\">\n * - Legacy spans: <span class=\"math-expression\" data-math=\"...\">\n * - LaTeX environments: \\begin{...}...\\end{...}\n *\n * @example\n * ```tsx\n * <HtmlMathRenderer\n * content=\"<p>A fórmula é: $$x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}$$</p>\"\n * />\n * ```\n */\nconst HtmlMathRenderer = forwardRef<HTMLElement, HtmlMathRendererProps>(\n (\n {\n content,\n className,\n style,\n sanitize = true,\n renderMathError,\n testId,\n inline = false,\n },\n ref\n ) => {\n // AI-generated questions/resolutions arrive as Markdown + LaTeX. The HTML\n // pipeline below would render their `**`/`####`/`*` tokens literally and\n // collapse line breaks, so route that content to the Markdown renderer.\n // Inline usage stays on the HTML path to keep phrasing-content validity\n // (Markdown emits block elements: <p>, <ul>, <h4>, ...).\n //\n // Note: `renderMathError` is intentionally not forwarded here. The Markdown\n // path renders math via rehype-katex, which already degrades gracefully on\n // invalid LaTeX (KaTeX's built-in red error output) rather than throwing.\n // `renderMathError` is an HTML-path-only customization and is currently\n // unused by any consumer; honoring it on the Markdown path would require a\n // bespoke rehype plugin for no practical gain.\n if (!inline && content && isLikelyMarkdown(content)) {\n return (\n <MarkdownMathRenderer\n ref={ref as Ref<HTMLDivElement>}\n content={content}\n className={className}\n style={style}\n testId={testId}\n />\n );\n }\n\n const defaultErrorRenderer = (latex: string) => (\n <span className=\"text-error-600 text-sm\">Math Error: {latex}</span>\n );\n\n const errorRenderer = renderMathError || defaultErrorRenderer;\n\n const renderContent = () => {\n if (!content) return null;\n\n const processedContent = sanitize\n ? sanitizeHtmlForDisplay(content)\n : content;\n\n const parts = processHtmlWithMath(processedContent);\n\n // If all parts are text (or empty), render as plain HTML. Use the\n // joined parts (not the raw `processedContent`) so post-split fixes\n // applied inside `processHtmlWithMath` — like decoding `\\$` escapes\n // to literal `$` — actually reach the rendered output.\n if (parts.every((part) => part.type === 'text')) {\n const joinedHtml = parts.map((part) => part.content).join('');\n // Use span for inline mode to allow valid nesting in labels\n const Element = inline ? 'span' : 'div';\n return (\n <Element\n dangerouslySetInnerHTML={{\n __html: joinedHtml || processedContent,\n }}\n />\n );\n }\n\n // Generate stable keys based on content\n const getPartKey = (part: (typeof parts)[0], idx: number) => {\n const contentHash = (part.latex || part.content).slice(0, 20);\n return `${part.type}-${idx}-${contentHash}`;\n };\n\n return (\n <>\n {parts.map((part, index) => {\n const key = getPartKey(part, index);\n if (part.type === 'math' && part.latex) {\n return (\n <KatexMath\n key={key}\n math={part.latex}\n renderError={() => errorRenderer(part.latex!)}\n />\n );\n } else if (part.type === 'block-math' && part.latex) {\n // When inline mode, render inline to avoid block-level elements inside span\n if (inline) {\n return (\n <KatexMath\n key={key}\n math={part.latex}\n renderError={() => errorRenderer(part.latex!)}\n />\n );\n }\n return (\n <div key={key} className=\"my-2.5 text-center\">\n <KatexMath\n math={part.latex}\n displayMode\n renderError={() => errorRenderer(part.latex!)}\n />\n </div>\n );\n } else {\n return (\n <span\n key={key}\n dangerouslySetInnerHTML={{ __html: part.content }}\n />\n );\n }\n })}\n </>\n );\n };\n\n const sharedClassName = cn(\n // Base styles\n 'leading-relaxed',\n // Paragraph styles\n '[&_p]:mb-0',\n // Hide the KaTeX MathML accessibility layer visually (still readable\n // to screen readers). Tailwind preflight overrides the KaTeX default\n // `position: absolute; clip:...` rule, so the MathML layer ends up\n // duplicating every formula as raw text next to the visual render.\n '[&_.katex-mathml]:sr-only',\n // Table styles (only relevant for block mode, but harmless for inline)\n '[&_table]:border-collapse [&_table]:w-full [&_table]:my-2.5 [&_table]:table-auto',\n '[&_table_td]:border [&_table_td]:border-border-200 [&_table_td]:p-2 [&_table_td]:min-w-[50px] [&_table_td]:align-top',\n '[&_table_th]:border [&_table_th]:border-border-200 [&_table_th]:p-2 [&_table_th]:min-w-[50px] [&_table_th]:align-top [&_table_th]:bg-background-50 [&_table_th]:font-semibold',\n '[&_table_tr:nth-child(even)]:bg-background-50/50',\n '[&_table_tr:hover]:bg-background-100/50',\n // Image styles\n '[&_img]:max-w-full [&_img]:h-auto [&_img]:rounded-md [&_img]:my-2',\n // Link styles\n '[&_a]:text-primary-500 [&_a]:underline [&_a:hover]:text-primary-600',\n // Text formatting styles\n '[&_b]:font-bold [&_strong]:font-bold',\n '[&_i]:italic [&_em]:italic',\n '[&_u]:underline',\n className\n );\n\n if (inline) {\n return (\n <span\n ref={ref as Ref<HTMLSpanElement>}\n className={sharedClassName}\n style={style}\n data-testid={testId}\n >\n {renderContent()}\n </span>\n );\n }\n\n return (\n <div\n ref={ref as Ref<HTMLDivElement>}\n className={sharedClassName}\n style={style}\n data-testid={testId}\n >\n {renderContent()}\n </div>\n );\n }\n);\n\nHtmlMathRenderer.displayName = 'HtmlMathRenderer';\n\nexport default memo(HtmlMathRenderer);\n","import { CSSProperties, forwardRef, memo } from 'react';\nimport 'katex/dist/katex.min.css';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport { cn } from '../../utils/utils';\nimport { looksLikeLatex } from '../HtmlMathRenderer/utils';\n\nexport interface MarkdownMathRendererProps {\n /** Markdown content, may contain LaTeX math expressions ($...$ / $$...$$) */\n content: string;\n /** Additional CSS class names */\n className?: string;\n /** Inline styles */\n style?: CSSProperties;\n /** Test ID for testing */\n testId?: string;\n}\n\n/**\n * Strips zero-width / invisible characters that occasionally leak into\n * AI-generated content and break KaTeX parsing.\n */\nconst stripInvisibleChars = (str: string): string =>\n str.replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, '');\n\n/**\n * Escapes the `$` of inline `$...$` spans that do NOT look like real math, so\n * `remark-math` leaves them as literal text. Without this, currency prose like\n * \"R$ 15,00 ... R$ 42,00\" gets paired up and rendered as gibberish math.\n *\n * Reuses the exact `looksLikeLatex` heuristic the HTML renderer applies to\n * single-`$` spans, so both renderers agree on what is math vs currency.\n * Display math (`$$...$$`) is intentionally left untouched (handled below).\n */\nexport const protectCurrencyInlineMath = (markdown: string): string =>\n markdown.replaceAll(\n /(?<!\\\\)\\$(?!\\$)([^\\n$]+?)(?<!\\\\)\\$(?!\\$)/g,\n (match, inner: string) =>\n looksLikeLatex(inner) ? match : match.replaceAll('$', String.raw`\\$`)\n );\n\n/**\n * `remark-math` only renders a `$$...$$` block as centered display math when\n * the delimiters sit on their own lines (\"math flow\"). AI content usually puts\n * the whole equation on a single line (`$$x = y$$`), which would otherwise be\n * rendered inline. Reflow single-line `$$...$$` into block form so equations\n * stay centered, matching how the HTML renderer treats `$$`.\n */\nexport const reflowDisplayMath = (markdown: string): string =>\n markdown.replaceAll(\n /(?<!\\$)\\$\\$(?!\\$)([^\\n]+?)\\$\\$(?!\\$)/g,\n (_match, inner: string) => `\\n\\n$$\\n${inner.trim()}\\n$$\\n\\n`\n );\n\n/**\n * Runs `transform` over the markdown while shielding fenced code blocks and\n * inline code spans: each is stashed behind a placeholder, the transform runs\n * on the rest, then the originals are restored before the markdown reaches\n * react-markdown. Without this, the currency / display-math passes would\n * rewrite literal `$`/`$$` that authors put inside code samples (e.g. a fenced\n * block containing `price = $value`). The placeholder is purely transient (it\n * never reaches the markdown parser) and contains no `$`, so the passes ignore\n * it.\n */\nconst withProtectedCode = (\n markdown: string,\n transform: (input: string) => string\n): string => {\n const stash: string[] = [];\n const tokenized = markdown.replaceAll(\n /```[\\s\\S]*?```|`[^`\\n]*`/g,\n (segment) => {\n const token = `__CODE_SEG_${stash.length}__`;\n stash.push(segment);\n return token;\n }\n );\n return transform(tokenized).replaceAll(\n /__CODE_SEG_(\\d+)__/g,\n (_match, index: string) => stash[Number(index)]\n );\n};\n\nconst preprocessMarkdown = (content: string): string =>\n withProtectedCode(stripInvisibleChars(content), (safe) =>\n reflowDisplayMath(protectCurrencyInlineMath(safe))\n );\n\n/**\n * MarkdownMathRenderer - Renders Markdown content with embedded LaTeX math.\n *\n * Used for AI-generated questions and resolutions, which arrive as Markdown\n * (`**bold**`, `#### headings`, `* lists`, paragraphs) mixed with LaTeX\n * (`$...$` inline, `$$...$$` display). Built on `react-markdown` with\n * `remark-gfm` (tables/lists), `remark-math` + `rehype-katex` (math).\n *\n * SECURITY: raw HTML is intentionally NOT enabled (no `rehype-raw`). This\n * renderer only receives content classified as Markdown (no HTML tags) by\n * `isLikelyMarkdown`; HTML content keeps flowing through `HtmlMathRenderer`,\n * which sanitizes it. Adding raw-HTML support here would reintroduce an XSS\n * vector and requires a dedicated sanitization pipeline + security review.\n */\nconst MarkdownMathRenderer = forwardRef<\n HTMLDivElement,\n MarkdownMathRendererProps\n>(({ content, className, style, testId }, ref) => {\n const sharedClassName = cn(\n 'leading-relaxed',\n // Paragraph spacing\n '[&_p]:my-2 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0',\n // Headings\n '[&_h1]:text-xl [&_h1]:font-bold [&_h1]:mt-3 [&_h1]:mb-2',\n '[&_h2]:text-lg [&_h2]:font-bold [&_h2]:mt-3 [&_h2]:mb-2',\n '[&_h3]:text-base [&_h3]:font-semibold [&_h3]:mt-2.5 [&_h3]:mb-1.5',\n '[&_h4]:text-base [&_h4]:font-semibold [&_h4]:mt-2.5 [&_h4]:mb-1.5',\n '[&_h5]:font-semibold [&_h6]:font-semibold',\n // Lists\n '[&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-2',\n '[&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-2',\n '[&_li]:my-1 [&_li>ul]:my-1 [&_li>ol]:my-1',\n // Text formatting\n '[&_b]:font-bold [&_strong]:font-bold',\n '[&_i]:italic [&_em]:italic',\n '[&_u]:underline',\n '[&_blockquote]:border-l-4 [&_blockquote]:border-border-200 [&_blockquote]:pl-3 [&_blockquote]:text-text-700',\n '[&_code]:rounded [&_code]:bg-background-100 [&_code]:px-1 [&_code]:py-0.5 [&_code]:text-sm',\n // Hide the KaTeX MathML accessibility layer visually (still readable to\n // screen readers). Tailwind preflight overrides KaTeX's default clip\n // rule, so without this the MathML layer duplicates every formula as\n // raw text next to the visual render.\n '[&_.katex-mathml]:sr-only',\n // Display math spacing\n '[&_.katex-display]:my-2.5',\n // Tables (GFM)\n '[&_table]:border-collapse [&_table]:w-full [&_table]:my-2.5 [&_table]:table-auto',\n '[&_table_td]:border [&_table_td]:border-border-200 [&_table_td]:p-2 [&_table_td]:min-w-[50px] [&_table_td]:align-top',\n '[&_table_th]:border [&_table_th]:border-border-200 [&_table_th]:p-2 [&_table_th]:min-w-[50px] [&_table_th]:align-top [&_table_th]:bg-background-50 [&_table_th]:font-semibold',\n // Images and links\n '[&_img]:max-w-full [&_img]:h-auto [&_img]:rounded-md [&_img]:my-2',\n '[&_a]:text-primary-500 [&_a]:underline [&_a:hover]:text-primary-600',\n className\n );\n\n return (\n <div\n ref={ref}\n className={sharedClassName}\n style={style}\n data-testid={testId}\n >\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex]}\n >\n {preprocessMarkdown(content)}\n </ReactMarkdown>\n </div>\n );\n});\n\nMarkdownMathRenderer.displayName = 'MarkdownMathRenderer';\n\nexport default memo(MarkdownMathRenderer);\n","/**\n * Utilities for processing HTML content with LaTeX math expressions\n */\n\nexport interface MathPart {\n type: 'text' | 'math' | 'block-math';\n content: string;\n latex?: string;\n}\n\n/**\n * Generates a random ID for placeholder uniqueness\n * Uses crypto.randomUUID() (Web Crypto API - available in all modern browsers)\n */\nconst generateSecureRandomId = (): string => {\n return crypto.randomUUID();\n};\n\n/**\n * Cleans LaTeX string from invisible characters and decodes HTML entities\n * that the editor saved in place of math operators.\n *\n * Why decode here: KaTeX is a LaTeX parser, not an HTML parser. If the\n * source has `&lt;`/`&gt;` (because the editor HTML-escaped them on save)\n * KaTeX throws \"Expected 'EOF', got '&'\". `&lt;`/`&gt;` map to the\n * equivalent `\\lt`/`\\gt` commands. `&amp;` decodes back to a bare `&` \\u2014\n * NOT `\\&` \\u2014 because in LaTeX `&` is the alignment character (used by\n * `\\begin{align}`, matrices, etc.); rewriting it to `\\&` would break\n * alignment and stop already-escaped `\\&` from round-tripping.\n */\nexport const cleanLatex = (str: string): string => {\n return str\n .replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, '')\n .replaceAll(/&amp;lt;|&lt;/gi, String.raw`\\lt `)\n .replaceAll(/&amp;gt;|&gt;/gi, String.raw`\\gt `)\n .replaceAll(/&amp;amp;|&amp;/gi, '&')\n .trim();\n};\n\n/**\n * Heuristic that flags a string as \"likely real LaTeX math\" vs prose.\n * Used to reject `$...$` blocks that wrap regular text \\u2014 typically\n * happens when authors type `$` as a currency symbol and the renderer\n * pairs unrelated occurrences as math delimiters, sending Portuguese\n * prose to KaTeX (which then renders each letter as a math variable).\n *\n * Approach:\n * - Backslash commands / sub-super / grouping braces \\u2192 definitely math.\n * - Otherwise, treat it as PROSE only when it contains 2+ real words\n * (runs of 3+ letters). A sentence like \"15,00 pelo custo fixo\" has\n * many such words; genuine math \\u2014 `x = 1`, `a + b`, `1 < 2`, `f0`,\n * even a lone `abc` \\u2014 does not. This keeps normal spaced equations\n * rendering while still rejecting currency-`$` prose.\n */\nexport const looksLikeLatex = (str: string): boolean => {\n if (/[\\\\^_{}]/.test(str)) return true;\n const words = str.match(/[a-zA-Z]{3,}/g);\n if (words && words.length >= 2) return false;\n return true;\n};\n\n/**\n * HTML element names the backoffice RichEditor emits. Kept as a Set (instead\n * of a long regex alternation) so the tag-detection regex below stays simple\n * and cheap to reason about.\n */\nconst HTML_TAG_NAMES = new Set([\n 'p',\n 'div',\n 'span',\n 'br',\n 'b',\n 'strong',\n 'i',\n 'em',\n 'u',\n 's',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'a',\n 'img',\n 'table',\n 'thead',\n 'tbody',\n 'tfoot',\n 'tr',\n 'td',\n 'th',\n 'blockquote',\n 'pre',\n 'code',\n 'sub',\n 'sup',\n 'font',\n 'latex',\n]);\n\n/**\n * True when `content` contains a real HTML element tag (open or close) whose\n * name is one the editor produces. A single generic regex captures any\n * `<tag`/`</tag` candidate; membership is then checked against the Set, which\n * keeps the regex trivial and avoids a giant alternation.\n */\nconst containsHtmlTag = (content: string): boolean => {\n for (const match of content.matchAll(/<\\/?([a-z][a-z0-9]*)/gi)) {\n if (HTML_TAG_NAMES.has(match[1].toLowerCase())) return true;\n }\n return false;\n};\n\n/**\n * Heuristic that decides whether `content` is Markdown (as opposed to the\n * HTML the backoffice RichEditor produces). AI-generated questions and\n * resolutions arrive as Markdown + LaTeX (`**bold**`, `#### heading`,\n * `* lists`, `$...$`, `$$...$$`), whereas the editor stores HTML (`<p>`,\n * `<b>`, `<span class=\"math-formula\" data-latex=\"...\">`). The two sources are\n * cleanly separable, so we bias toward the proven HTML path:\n *\n * - If any real HTML element tag is present we return `false` and let\n * `HtmlMathRenderer` handle it exactly as before (math-formula spans,\n * currency heuristic, katex-error recovery, sanitization).\n * - Otherwise we return `true` only when an unmistakable Markdown marker is\n * present (ATX heading, bold, bullet/ordered list, GFM table, or a paragraph\n * break), which is what breaks today: Markdown rendered as HTML shows the raw\n * `**`/`####`/`*` tokens and collapses line breaks.\n *\n * Regex note: line-anchored signals use the `m` flag with `^` and restrict\n * horizontal whitespace to `[ \\t]` (never `\\s`, which also matches `\\n`). This\n * keeps each quantifier on a single line and avoids the super-linear\n * backtracking that `(?:^|\\n)\\s*…\\s+` can trigger across newlines.\n */\nexport const isLikelyMarkdown = (content: string): boolean => {\n if (!content) return false;\n\n // Presence of real HTML element tags => treat as HTML (RichEditor output).\n if (containsHtmlTag(content)) return false;\n\n const MARKDOWN_SIGNALS = [\n /^#{1,6}[ \\t]+\\S/m, // ATX heading (#, ##, ... ######)\n /\\*\\*[^*\\n]+\\*\\*/, // bold\n /__[^_\\n]+__/, // bold (underscore)\n /^[ \\t]*[-*+][ \\t]+\\S/m, // bullet list\n /^[ \\t]*\\d+\\.[ \\t]+\\S/m, // ordered list\n /\\|[ \\t]*:?-+:?[ \\t]*\\|/, // GFM table delimiter row (|---|---|)\n /\\n\\n/, // paragraph break (only reached when no HTML tag is present)\n ];\n return MARKDOWN_SIGNALS.some((pattern) => pattern.test(content));\n};\n\n/**\n * Recovers usable LaTeX source from `<span class=\"katex-error\">` wrappers\n * that previous editor cycles persisted into the database. The error's\n * `title` attribute carries the original LaTeX after \"at position N: \".\n * Replaces each wrapper with `$LATEX$` so downstream patterns can render\n * it cleanly via KaTeX.\n *\n * No-op outside browser contexts (no `document`).\n */\nconst recoverFromKatexErrorSpans = (htmlContent: string): string => {\n if (\n typeof document === 'undefined' ||\n !/class=\"[^\"]*katex-error/i.test(htmlContent)\n ) {\n return htmlContent;\n }\n\n const tempContainer = document.createElement('div');\n tempContainer.innerHTML = htmlContent;\n\n const sanitizeRecoveredLatex = (raw: string): string =>\n raw\n // Strip combining marks KaTeX puts in error titles at the error pos\n .replaceAll(/[\\u0300-\\u036F]/g, '')\n // Drop truncated tag markers leftover from broken serialization.\n // Done while literal `<`/`>` are still present (before they get\n // mapped to LaTeX commands below).\n .replaceAll(/<\\/?[a-zA-Z][a-zA-Z0-9]*\\s*>?$/g, '')\n // Map comparison operators to equivalent LaTeX commands. We match\n // both the entity forms AND the literal `<`/`>` characters: the\n // `title` attribute is entity-decoded by the DOM when read, so we\n // often get literal `<`/`>`. Mapping them to `\\lt`/`\\gt` also avoids\n // re-encoding to `&lt;`/`&gt;` on DOM serialization (which would make\n // `looksLikeLatex` reject the recovered block as non-math).\n // `&amp;` decodes to a bare `&` (the LaTeX alignment character), not\n // `\\&`, so `\\begin{align}` environments survive recovery.\n .replaceAll(/&amp;lt;|&lt;|</gi, String.raw`\\lt `)\n .replaceAll(/&amp;gt;|&gt;|>/gi, String.raw`\\gt `)\n .replaceAll(/&amp;amp;|&amp;/gi, '&')\n .trim();\n\n Array.from(tempContainer.querySelectorAll('.katex-error')).forEach(\n (errorNode) => {\n if (!tempContainer.contains(errorNode)) return;\n\n const title = errorNode.getAttribute('title') || '';\n // Note: no `\\s*` before the capture group — `\\s*(.+)` would let\n // whitespace be split ambiguously between the two, causing\n // super-linear backtracking (ReDoS). The capture is trimmed by\n // sanitizeRecoveredLatex below instead.\n const positionMatch = /at position\\s+\\d+:(.+)$/.exec(title);\n let recovered = positionMatch ? positionMatch[1] : '';\n\n if (!recovered) {\n // Fallback: collect from inner <annotation> elements, skipping the\n // visual `katex-html` layer to avoid duplicating Unicode glyphs.\n const parts: string[] = [];\n const walk = (n: Node) => {\n if (n.nodeType === Node.TEXT_NODE) {\n parts.push(n.textContent || '');\n return;\n }\n if (n.nodeType !== Node.ELEMENT_NODE) return;\n const el = n as Element;\n if (el.tagName.toLowerCase() === 'annotation') {\n parts.push(el.textContent || '');\n return;\n }\n if (el.classList.contains('katex-html')) return;\n Array.from(el.childNodes).forEach(walk);\n };\n Array.from(errorNode.childNodes).forEach(walk);\n recovered = parts.join(' ');\n }\n\n recovered = sanitizeRecoveredLatex(recovered);\n if (recovered) {\n errorNode.replaceWith(document.createTextNode(`$${recovered}$`));\n } else {\n errorNode.remove();\n }\n }\n );\n\n return tempContainer.innerHTML;\n};\n\n/**\n * Decodes `\\$` escape sequences to literal `$` characters. Applied only to\n * text fragments outside math blocks \\u2014 the `(?<!\\\\)` lookbehind in the\n * `$...$` matcher already skipped these, but the `\\` is still in the output\n * unless we decode it. Without this, currency strings like `R\\$ 130,00`\n * render with a visible backslash.\n */\nconst decodeDollarEscapes = (text: string): string =>\n text.replaceAll(String.raw`\\$`, '$');\n\n/**\n * Dangerous attributes that should be removed for XSS protection\n */\nconst DANGEROUS_ATTRIBUTES = new Set([\n 'contenteditable',\n 'srcdoc',\n 'formaction',\n 'xlink:href',\n]);\n\n/**\n * Dangerous URI schemes that should be removed from href/src attributes\n */\nconst DANGEROUS_URI_PATTERN = /^\\s*(javascript|vbscript|data):/i;\n\n/**\n * Sanitizes HTML content for safe display\n * Removes event handlers, dangerous attributes, script/style tags, and javascript: URIs\n */\nexport const sanitizeHtmlForDisplay = (htmlContent: string): string => {\n if (!htmlContent) return htmlContent;\n\n // Create a temporary div to parse HTML\n if (typeof document === 'undefined') {\n // Server-side: use regex-based sanitization as fallback\n let sanitized = htmlContent;\n // Remove script tags\n sanitized = sanitized.replaceAll(\n /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n ''\n );\n // Remove style tags\n sanitized = sanitized.replaceAll(\n /<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi,\n ''\n );\n // Remove on* event handlers (split into separate patterns to avoid ReDoS)\n sanitized = sanitized.replaceAll(/ on[a-z]+=\"[^\"]*\"/gi, '');\n sanitized = sanitized.replaceAll(/ on[a-z]+='[^']*'/gi, '');\n sanitized = sanitized.replaceAll(/ on[a-z]+=[^\\s>\"']+/gi, '');\n // Remove dangerous URI schemes (javascript, vbscript, data) - matching client-side DANGEROUS_URI_PATTERN\n sanitized = sanitized.replaceAll(\n / href=\"(?:javascript|vbscript|data):[^\"]*\"/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / href='(?:javascript|vbscript|data):[^']*'/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / src=\"(?:javascript|vbscript|data):[^\"]*\"/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / src='(?:javascript|vbscript|data):[^']*'/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / action=\"(?:javascript|vbscript|data):[^\"]*\"/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / action='(?:javascript|vbscript|data):[^']*'/gi,\n ''\n );\n return sanitized;\n }\n\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = htmlContent;\n\n // Remove script and style tags entirely\n const dangerousTags = tempDiv.querySelectorAll(\n 'script, style, iframe, object, embed'\n );\n dangerousTags.forEach((element) => element.remove());\n\n // Process all elements\n const allElements = tempDiv.querySelectorAll('*');\n allElements.forEach((element) => {\n // Get all attribute names\n const attributeNames = element.getAttributeNames();\n\n attributeNames.forEach((attrName) => {\n const lowerAttrName = attrName.toLowerCase();\n\n // Remove all on* event handler attributes (onclick, onerror, onload, etc.)\n if (lowerAttrName.startsWith('on')) {\n element.removeAttribute(attrName);\n return;\n }\n\n // Remove dangerous attributes\n if (DANGEROUS_ATTRIBUTES.has(lowerAttrName)) {\n element.removeAttribute(attrName);\n return;\n }\n\n // Check href, src, and action for dangerous URIs\n if (\n lowerAttrName === 'href' ||\n lowerAttrName === 'src' ||\n lowerAttrName === 'action'\n ) {\n const value = element.getAttribute(attrName);\n if (value && DANGEROUS_URI_PATTERN.test(value)) {\n element.removeAttribute(attrName);\n }\n }\n });\n });\n\n return tempDiv.innerHTML;\n};\n\n/**\n * Processes HTML content and extracts math expressions\n * Returns an array of parts (text and math) for rendering\n */\nexport const processHtmlWithMath = (htmlContent: string): MathPart[] => {\n if (!htmlContent) return [];\n\n // Pre-pass: recover original LaTeX from any `katex-error` wrappers that\n // older editor saves left in the content. This turns persisted error HTML\n // into clean `$LATEX$` strings so the steps below can render them.\n let processedContent = recoverFromKatexErrorSpans(htmlContent);\n const parts: MathPart[] = [];\n\n // Generate unique sentinel per call to avoid collision with content\n const sentinel = `__MATH_${generateSecureRandomId()}_`;\n\n // Step 1: Handle math-formula spans (from the editor)\n const mathFormulaPattern =\n /<span[^>]*class=\"math-formula\"[^>]*data-latex=\"([^\"]*)\"[^>]*>[\\s\\S]*?<\\/span>/g;\n processedContent = processedContent.replaceAll(\n mathFormulaPattern,\n (match, latex) => {\n const isDisplayMode = match.includes('data-display-mode=\"true\"');\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: isDisplayMode ? 'block-math' : 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 2: Handle wrapped math expressions (from math modal - legacy)\n const wrappedMathPattern =\n /<span[^>]*class=\"math-expression\"[^>]*data-math=\"([^\"]*)\"[^>]*>.*?<\\/span>/g;\n processedContent = processedContent.replaceAll(\n wrappedMathPattern,\n (match, latex) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 3: Handle raw $$...$$ expressions (display mode) - BEFORE single $\n const doubleDollarPattern = /(?<!\\\\)\\$\\$([\\s\\S]+?)\\$\\$/g;\n processedContent = processedContent.replaceAll(\n doubleDollarPattern,\n (match, latex) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'block-math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 4: Handle single $...$ expressions for inline math.\n // Skip matches whose content doesn't look like LaTeX — those are usually\n // currency `$` symbols pairing up across prose (e.g. `R$ 15,00 ... R$ 42,00`)\n // and sending Portuguese text to KaTeX produces gibberish output.\n const singleDollarPattern = /(?<!\\\\)\\$([\\s\\S]+?)\\$/g;\n processedContent = processedContent.replaceAll(\n singleDollarPattern,\n (match, latex) => {\n if (!looksLikeLatex(latex)) return match;\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 5: Handle <latex>...</latex> tags for inline math\n const latexTagPattern =\n /(?:<latex>|&lt;latex&gt;)([\\s\\S]*?)(?:<\\/latex>|&lt;\\/latex&gt;)/g;\n processedContent = processedContent.replaceAll(\n latexTagPattern,\n (match, latex) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 6: Handle standalone LaTeX environments (align, equation, pmatrix, etc.)\n const latexEnvPattern = /\\\\begin\\{([^}]+)\\}([\\s\\S]*?)\\\\end\\{\\1\\}/g;\n processedContent = processedContent.replaceAll(latexEnvPattern, (match) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'block-math',\n content: match,\n latex: cleanLatex(match),\n });\n return placeholder;\n });\n\n // Step 7: Split remaining content by placeholders\n const finalParts: MathPart[] = [];\n let currentIndex = 0;\n // Escape sentinel for regex (though it should be safe alphanumeric)\n const escapedSentinel = sentinel.replaceAll(\n /[.*+?^${}()|[\\]\\\\]/g,\n String.raw`\\$&`\n );\n const placeholderPattern = new RegExp(\n String.raw`${escapedSentinel}(\\d+)__`,\n 'g'\n );\n let match;\n\n while ((match = placeholderPattern.exec(processedContent)) !== null) {\n // Add text before math\n if (match.index > currentIndex) {\n finalParts.push({\n type: 'text',\n content: decodeDollarEscapes(\n processedContent.slice(currentIndex, match.index)\n ),\n });\n }\n\n // Add math expression\n const mathIndex = Number.parseInt(match[1], 10);\n if (parts[mathIndex]) {\n finalParts.push(parts[mathIndex]);\n }\n\n currentIndex = match.index + match[0].length;\n }\n\n // Add remaining text\n if (currentIndex < processedContent.length) {\n finalParts.push({\n type: 'text',\n content: decodeDollarEscapes(processedContent.slice(currentIndex)),\n });\n }\n\n return finalParts;\n};\n\n/**\n * Checks if content contains any math expressions\n */\nexport const containsMath = (content: string): boolean => {\n if (!content) return false;\n\n // Check for various math patterns\n const patterns = [\n /\\$\\$[\\s\\S]+?\\$\\$/, // Display mode $$...$$\n /(?<!\\\\)\\$[\\s\\S]+?\\$/, // Inline mode $...$\n /<span[^>]*class=\"math-formula\"/, // Editor spans\n /<span[^>]*class=\"math-expression\"/, // Legacy spans\n /<latex>|&lt;latex&gt;/, // LaTeX tags\n /\\\\begin\\{[^}]+\\}/, // LaTeX environments\n ];\n\n return patterns.some((pattern) => pattern.test(content));\n};\n\n/**\n * Extracts plain text from HTML content (removes all tags and LaTeX notation)\n */\nexport const stripHtml = (htmlContent: string): string => {\n if (!htmlContent) return '';\n\n let content = htmlContent;\n\n // Remove math-formula spans (keep nothing as the LaTeX is in data attribute)\n content = content.replaceAll(\n /<span[^>]*class=\"math-formula\"[^>]*>[\\s\\S]*?<\\/span>/g,\n ''\n );\n\n // Remove math-expression spans (legacy)\n content = content.replaceAll(\n /<span[^>]*class=\"math-expression\"[^>]*>[\\s\\S]*?<\\/span>/g,\n ''\n );\n\n // Remove $$...$$ block math\n content = content.replaceAll(/\\$\\$[\\s\\S]+?\\$\\$/g, '');\n\n // Remove $...$ inline math\n content = content.replaceAll(/\\$[^$]+\\$/g, '');\n\n // Remove <latex>...</latex> tags\n content = content.replaceAll(\n /(?:<latex>|&lt;latex&gt;)[\\s\\S]*?(?:<\\/latex>|&lt;\\/latex&gt;)/g,\n ''\n );\n\n // Remove LaTeX environments like \\begin{...}...\\end{...}\n // Using non-greedy match without backreference to avoid ReDoS vulnerability\n content = content.replaceAll(\n /\\\\begin\\{[a-zA-Z*]+\\}[\\s\\S]*?\\\\end\\{[a-zA-Z*]+\\}/g,\n ''\n );\n\n // Remove HTML tags\n if (typeof document === 'undefined') {\n // Server-side: use regex (excluding both < and > prevents quadratic backtracking)\n return content.replaceAll(/<[^<>]*>/g, '').trim();\n }\n\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = content;\n return (tempDiv.textContent || tempDiv.innerText || '').trim();\n};\n","import {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n} from 'react';\nimport Text from '../Text/Text';\nimport { Check, Minus } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\n\n/**\n * CheckBox size variants\n */\ntype CheckBoxSize = 'small' | 'medium' | 'large';\n\n/**\n * CheckBox visual state\n */\ntype CheckBoxState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n checkbox: 'w-4 h-4', // 16px x 16px\n textSize: 'sm' as const,\n spacing: 'gap-1.5', // 6px\n borderWidth: 'border-2',\n iconSize: 14, // pixels for Phosphor icons\n labelHeight: 'h-[21px]',\n },\n medium: {\n checkbox: 'w-5 h-5', // 20px x 20px\n textSize: 'md' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2',\n iconSize: 16, // pixels for Phosphor icons\n labelHeight: 'h-6',\n },\n large: {\n checkbox: 'w-6 h-6', // 24px x 24px\n textSize: 'lg' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-[3px]', // 3px border\n iconSize: 20, // pixels for Phosphor icons\n labelHeight: 'h-[27px]',\n },\n} as const;\n\n/**\n * Base checkbox styling classes using design system colors\n */\nconst BASE_CHECKBOX_CLASSES =\n 'rounded border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked:\n 'border-primary-950 bg-primary-950 text-text hover:border-primary-800 hover:bg-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background',\n checked: 'border-primary-800 bg-primary-800 text-text',\n },\n focused: {\n unchecked:\n 'border-indicator-info bg-background ring-2 ring-indicator-info/20',\n checked:\n 'border-indicator-info bg-primary-950 text-text ring-2 ring-indicator-info/20',\n },\n invalid: {\n unchecked: 'border-error-700 bg-background hover:border-error-600',\n checked: 'border-error-700 bg-primary-950 text-text',\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed opacity-40',\n checked:\n 'border-primary-600 bg-primary-600 text-text cursor-not-allowed opacity-40',\n },\n} as const;\n\n/**\n * CheckBox component props interface\n */\nexport type CheckBoxProps = {\n /** Label text to display next to the checkbox */\n label?: ReactNode;\n /** Size variant of the checkbox */\n size?: CheckBoxSize;\n /** Visual state of the checkbox */\n state?: CheckBoxState;\n /** Indeterminate state for partial selections */\n indeterminate?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'>;\n\n/**\n * CheckBox component for Analytica Ensino platforms\n *\n * A checkbox component with essential states, sizes and themes.\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 checkbox\n * <CheckBox label=\"Option\" />\n *\n * // Small size\n * <CheckBox size=\"small\" label=\"Small option\" />\n *\n * // Invalid state\n * <CheckBox state=\"invalid\" label=\"Required field\" />\n *\n * // Disabled state\n * <CheckBox disabled label=\"Disabled option\" />\n * ```\n */\nconst CheckBox = forwardRef<HTMLInputElement, CheckBoxProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n indeterminate = false,\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n disabled,\n id,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `checkbox-${generatedId}`;\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalChecked(event.target.checked);\n }\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Determine checkbox visual variant\n const checkVariant = checked || indeterminate ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][checkVariant];\n\n // Special border width handling for focused/hovered states and large size\n const borderWidthClass =\n state === 'focused' || (state === 'hovered' && size === 'large')\n ? 'border-[3px]'\n : sizeClasses.borderWidth;\n\n // Get final checkbox classes\n const checkboxClasses = cn(\n BASE_CHECKBOX_CLASSES,\n sizeClasses.checkbox,\n borderWidthClass,\n stylingClasses,\n className\n );\n\n // Render appropriate icon based on state\n const renderIcon = () => {\n if (indeterminate) {\n return (\n <Minus\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n if (checked) {\n return (\n <Check\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n return null;\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.spacing,\n disabled ? 'opacity-40' : ''\n )}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={ref}\n type=\"checkbox\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n onChange={handleChange}\n className=\"sr-only\"\n {...props}\n />\n\n {/* Custom styled checkbox */}\n <label htmlFor={inputId} className={checkboxClasses}>\n {/* Show appropriate icon based on state */}\n {renderIcon()}\n </label>\n\n {/* Label text */}\n {label && (\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.labelHeight\n )}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={cn(\n 'cursor-pointer select-none leading-[150%] flex items-center font-roboto',\n labelClassName\n )}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nCheckBox.displayName = 'CheckBox';\n\nexport default CheckBox;\n","import {\n InputHTMLAttributes,\n HTMLAttributes,\n ReactNode,\n forwardRef,\n useId,\n useEffect,\n useRef,\n Children,\n cloneElement,\n isValidElement,\n ReactElement,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport CheckBox from './CheckBox';\nimport { cn } from '../../utils/utils';\n\n/**\n * CheckboxList size variants\n */\ntype CheckboxListSize = 'small' | 'medium' | 'large';\n\n/**\n * CheckboxList visual state\n */\ntype CheckboxListState =\n | 'default'\n | 'hovered'\n | 'focused'\n | 'invalid'\n | 'disabled';\n\n/**\n * CheckboxList store interface\n */\ninterface CheckboxListStore {\n values: string[];\n setValues: (values: string[]) => void;\n toggleValue: (value: string) => void;\n onValuesChange?: (values: string[]) => void;\n disabled: boolean;\n name: string;\n}\n\ntype CheckboxListStoreApi = StoreApi<CheckboxListStore>;\n\n/**\n * Create a new CheckboxList store\n */\nconst createCheckboxListStore = (\n name: string,\n defaultValues: string[],\n disabled: boolean,\n onValuesChange?: (values: string[]) => void\n): CheckboxListStoreApi =>\n create<CheckboxListStore>((set, get) => ({\n values: defaultValues,\n setValues: (values) => {\n if (!get().disabled) {\n set({ values });\n get().onValuesChange?.(values);\n }\n },\n toggleValue: (value) => {\n if (!get().disabled) {\n const currentValues = get().values;\n const newValues = currentValues.includes(value)\n ? currentValues.filter((v) => v !== value)\n : [...currentValues, value];\n set({ values: newValues });\n get().onValuesChange?.(newValues);\n }\n },\n onValuesChange,\n disabled,\n name,\n }));\n\n/**\n * Hook to access CheckboxList store\n */\nexport const useCheckboxListStore = (externalStore?: CheckboxListStoreApi) => {\n if (!externalStore) {\n throw new Error('CheckboxListItem must be used within a CheckboxList');\n }\n return externalStore;\n};\n\n/**\n * Inject store into CheckboxListItem children\n */\nconst injectStore = (\n children: ReactNode,\n store: CheckboxListStoreApi\n): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n const typedChild = child as ReactElement<CheckboxListItemProps>;\n const shouldInject = typedChild.type === CheckboxListItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\n/**\n * CheckboxList component props interface\n */\nexport type CheckboxListProps = {\n /** Current selected values */\n values?: string[];\n /** Default selected values for uncontrolled usage */\n defaultValues?: string[];\n /** Callback when selection changes */\n onValuesChange?: (values: string[]) => void;\n /** Group name for all checkboxes */\n name?: string;\n /** Disabled state for the entire group */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Children components */\n children: ReactNode;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValues'>;\n\n/**\n * CheckboxList component for flexible checkbox group composition\n *\n * Uses Zustand for state management with automatic store injection.\n * Allows complete control over layout and styling by composing with CheckboxListItem.\n *\n * @example\n * ```tsx\n * <CheckboxList defaultValues={[\"option1\"]} onValuesChange={setValues}>\n * <div className=\"flex items-center gap-3\">\n * <CheckboxListItem value=\"option1\" id=\"c1\" />\n * <label htmlFor=\"c1\">Option 1</label>\n * </div>\n * <div className=\"flex items-center gap-3\">\n * <CheckboxListItem value=\"option2\" id=\"c2\" />\n * <label htmlFor=\"c2\">Option 2</label>\n * </div>\n * </CheckboxList>\n * ```\n */\nconst CheckboxList = forwardRef<HTMLDivElement, CheckboxListProps>(\n (\n {\n values: propValues,\n defaultValues = [],\n onValuesChange,\n name: propName,\n disabled = false,\n className = '',\n children,\n ...props\n },\n ref\n ) => {\n // Generate unique name if not provided\n const generatedId = useId();\n const name = propName || `checkbox-list-${generatedId}`;\n\n // Create store reference\n const storeRef = useRef<CheckboxListStoreApi>(null);\n storeRef.current ??= createCheckboxListStore(\n name,\n defaultValues,\n disabled,\n onValuesChange\n );\n const store = storeRef.current;\n\n // Get store actions\n const { setValues } = useStore(store, (s) => s);\n\n // Call onValuesChange with initial values\n useEffect(() => {\n const currentValues = store.getState().values;\n if (currentValues.length > 0 && onValuesChange) {\n onValuesChange(currentValues);\n }\n }, []);\n\n // Handle controlled values changes\n useEffect(() => {\n if (propValues !== undefined) {\n setValues(propValues);\n }\n }, [propValues, setValues]);\n\n // Update disabled state\n useEffect(() => {\n store.setState({ disabled });\n }, [disabled, store]);\n\n return (\n <div\n ref={ref}\n className={cn('flex flex-col gap-2 w-full', className)}\n aria-label={name}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\n\nCheckboxList.displayName = 'CheckboxList';\n\n/**\n * CheckboxListItem component props interface\n */\nexport type CheckboxListItemProps = {\n /** Value for this checkbox item */\n value: string;\n /** Store reference (automatically injected by CheckboxList) */\n store?: CheckboxListStoreApi;\n /** Disabled state for this specific item */\n disabled?: boolean;\n /** Size variant */\n size?: CheckboxListSize;\n /** Visual state */\n state?: CheckboxListState;\n /** Additional CSS classes */\n className?: string;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'name' | 'value' | 'checked' | 'onChange' | 'size'\n>;\n\n/**\n * CheckboxListItem component for use within CheckboxList\n *\n * A checkbox without label that works within CheckboxList context.\n * Provides just the checkbox input for maximum flexibility in composition.\n *\n * @example\n * ```tsx\n * <CheckboxList defaultValues={[\"option1\"]}>\n * <div className=\"flex items-center gap-3\">\n * <CheckboxListItem value=\"option1\" id=\"c1\" />\n * <label htmlFor=\"c1\">Option 1</label>\n * </div>\n * </CheckboxList>\n * ```\n */\nconst CheckboxListItem = forwardRef<HTMLInputElement, CheckboxListItemProps>(\n (\n {\n value,\n store: externalStore,\n disabled: itemDisabled,\n size = 'medium',\n state = 'default',\n className = '',\n id,\n ...props\n },\n ref\n ) => {\n // Get store and state\n const store = useCheckboxListStore(externalStore);\n const {\n values: groupValues,\n toggleValue,\n disabled: groupDisabled,\n name,\n } = useStore(store);\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `checkbox-item-${generatedId}`;\n\n // Determine states\n const isChecked = groupValues.includes(value);\n const isDisabled = groupDisabled || itemDisabled;\n const currentState = isDisabled ? 'disabled' : state;\n\n // Use standard CheckBox component for consistency and simplicity\n return (\n <CheckBox\n ref={ref}\n id={inputId}\n name={name}\n value={value}\n checked={isChecked}\n disabled={isDisabled}\n size={size}\n state={currentState}\n className={className}\n onChange={() => {\n if (!isDisabled) {\n toggleValue(value);\n }\n }}\n {...props}\n />\n );\n }\n);\n\nCheckboxListItem.displayName = 'CheckboxListItem';\n\nexport default CheckboxList;\nexport { CheckboxListItem };\n","import {\n InputHTMLAttributes,\n HTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n useEffect,\n useRef,\n Children,\n cloneElement,\n isValidElement,\n ReactElement,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\n\n/**\n * Radio size variants\n */\ntype RadioSize = 'small' | 'medium' | 'large' | 'extraLarge';\n\n/**\n * Radio visual state\n */\ntype RadioState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n radio: 'w-5 h-5',\n textSize: 'sm' as const,\n spacing: 'gap-1.5',\n borderWidth: 'border-2',\n dotSize: 'w-2.5 h-2.5',\n labelHeight: 'h-5',\n },\n medium: {\n radio: 'w-6 h-6',\n textSize: 'md' as const,\n spacing: 'gap-2',\n borderWidth: 'border-2',\n dotSize: 'w-3 h-3',\n labelHeight: 'h-6',\n },\n large: {\n radio: 'w-7 h-7',\n textSize: 'lg' as const,\n spacing: 'gap-2',\n borderWidth: 'border-2',\n dotSize: 'w-3.5 h-3.5',\n labelHeight: 'h-7',\n },\n extraLarge: {\n radio: 'w-8 h-8',\n textSize: 'xl' as const,\n spacing: 'gap-3',\n borderWidth: 'border-2',\n dotSize: 'w-4 h-4',\n labelHeight: 'h-8',\n },\n} as const;\n\n/**\n * Focused state maintains the same sizes as default state\n * Only adds wrapper styling, does not change radio/dot sizes\n */\n\n/**\n * Base radio styling classes using design system colors\n */\nconst BASE_RADIO_CLASSES =\n 'rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked: 'border-primary-950 bg-background hover:border-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background',\n checked: 'border-info-700 bg-background',\n },\n focused: {\n unchecked: 'border-border-400 bg-background',\n checked: 'border-primary-950 bg-background',\n },\n invalid: {\n unchecked: 'border-border-400 bg-background',\n checked: 'border-primary-950 bg-background',\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed',\n checked: 'border-primary-950 bg-background cursor-not-allowed',\n },\n} as const;\n\n/**\n * Dot styling classes for the inner dot when checked\n */\nconst DOT_CLASSES = {\n default: 'bg-primary-950',\n hovered: 'bg-info-700',\n focused: 'bg-primary-950',\n invalid: 'bg-primary-950',\n disabled: 'bg-primary-950',\n} as const;\n\n/**\n * Radio component props interface\n */\nexport type RadioProps = {\n /** Label text to display next to the radio */\n label?: ReactNode;\n /** Size variant of the radio */\n size?: RadioSize;\n /** Visual state of the radio */\n state?: RadioState;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Radio group name */\n name?: string;\n /** Radio value */\n value?: string;\n /** Default checked state for uncontrolled radios */\n defaultChecked?: boolean;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'defaultChecked'\n>;\n\n/**\n * Radio component for Analytica Ensino platforms\n *\n * A radio button component with essential states, sizes and themes.\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 radio\n * <Radio name=\"option\" value=\"1\" label=\"Option 1\" />\n *\n * // Small size\n * <Radio size=\"small\" name=\"option\" value=\"2\" label=\"Small option\" />\n *\n * // Invalid state\n * <Radio state=\"invalid\" name=\"option\" value=\"3\" label=\"Required field\" />\n *\n * // Disabled state\n * <Radio disabled name=\"option\" value=\"4\" label=\"Disabled option\" />\n *\n * // Default checked (uncontrolled)\n * <Radio defaultChecked name=\"option\" value=\"5\" label=\"Initially checked\" />\n * ```\n */\nconst Radio = forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n defaultChecked = false,\n disabled,\n id,\n name,\n value,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `radio-${generatedId}`;\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const newChecked = event.target.checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n // Prevent automatic scroll when input changes\n if (event.target) {\n event.target.blur();\n }\n\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Focused state maintains original sizes, only adds wrapper\n const actualRadioSize = sizeClasses.radio;\n const actualDotSize = sizeClasses.dotSize;\n\n // Determine radio visual variant\n const radioVariant = checked ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][radioVariant];\n\n // Border width logic - consistent across all states and sizes\n const getBorderWidth = () => {\n if (currentState === 'focused') {\n return 'border-2';\n }\n return sizeClasses.borderWidth;\n };\n\n const borderWidthClass = getBorderWidth();\n\n // Get final radio classes\n const radioClasses = cn(\n BASE_RADIO_CLASSES,\n actualRadioSize,\n borderWidthClass,\n stylingClasses,\n className\n );\n\n // Get dot classes\n const dotClasses = cn(\n actualDotSize,\n 'rounded-full',\n DOT_CLASSES[currentState],\n 'transition-all duration-200'\n );\n\n // Determine if wrapper is needed only for focused or invalid states\n const isWrapperNeeded =\n currentState === 'focused' || currentState === 'invalid';\n const wrapperBorderColor =\n currentState === 'focused'\n ? 'border-indicator-info'\n : 'border-indicator-error';\n\n // Determine text color based on state and checked status\n const getTextColor = () => {\n if (currentState === 'disabled') {\n return checked ? 'text-text-900' : 'text-text-600';\n }\n\n if (currentState === 'focused') {\n return 'text-text-900';\n }\n\n return checked ? 'text-text-900' : 'text-text-600';\n };\n\n // Determine cursor class based on disabled state\n const getCursorClass = () => {\n return currentState === 'disabled'\n ? 'cursor-not-allowed'\n : 'cursor-pointer';\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={cn(\n 'flex flex-row items-center',\n isWrapperNeeded\n ? cn('p-1 border-2', wrapperBorderColor, 'rounded-lg gap-1.5')\n : sizeClasses.spacing,\n disabled ? 'opacity-40' : ''\n )}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"radio\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n name={name}\n value={value}\n onChange={handleChange}\n className=\"sr-only\"\n style={{\n position: 'absolute',\n left: '-9999px',\n visibility: 'hidden',\n }}\n {...props}\n />\n\n {/* Custom styled radio */}\n <button\n type=\"button\"\n className={radioClasses}\n disabled={disabled}\n aria-pressed={checked}\n onClick={(e) => {\n // Prevent scroll when radio is clicked\n e.preventDefault();\n if (!disabled) {\n // Simulate click on hidden input\n if (inputRef.current) {\n inputRef.current.click();\n // Remove focus to prevent scroll behavior\n inputRef.current.blur();\n }\n }\n }}\n onKeyDown={(e) => {\n // Handle keyboard activation (Enter or Space)\n if ((e.key === 'Enter' || e.key === ' ') && !disabled) {\n e.preventDefault();\n if (inputRef.current) {\n inputRef.current.click();\n inputRef.current.blur();\n }\n }\n }}\n >\n {/* Show dot when checked */}\n {checked && <div className={dotClasses} />}\n </button>\n\n {/* Label text */}\n {label && (\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.labelHeight,\n 'flex-1 min-w-0'\n )}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={cn(\n getCursorClass(),\n 'select-none leading-normal flex items-center font-roboto truncate',\n labelClassName\n )}\n color={getTextColor()}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5 truncate\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5 truncate\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nRadio.displayName = 'Radio';\n\n/**\n * RadioGroup store interface\n */\ninterface RadioGroupStore {\n value: string;\n setValue: (value: string) => void;\n onValueChange?: (value: string) => void;\n disabled: boolean;\n name: string;\n}\n\ntype RadioGroupStoreApi = StoreApi<RadioGroupStore>;\n\n/**\n * Create a new RadioGroup store\n */\nconst createRadioGroupStore = (\n name: string,\n defaultValue: string,\n disabled: boolean,\n onValueChange?: (value: string) => void\n): RadioGroupStoreApi =>\n create<RadioGroupStore>((set, get) => ({\n value: defaultValue,\n setValue: (value) => {\n if (!get().disabled) {\n set({ value });\n get().onValueChange?.(value);\n }\n },\n onValueChange,\n disabled,\n name,\n }));\n\n/**\n * Hook to access RadioGroup store\n */\nexport const useRadioGroupStore = (externalStore?: RadioGroupStoreApi) => {\n if (!externalStore) {\n throw new Error('RadioGroupItem must be used within a RadioGroup');\n }\n return externalStore;\n};\n\n/**\n * Inject store into RadioGroupItem children\n */\nconst injectStore = (\n children: ReactNode,\n store: RadioGroupStoreApi\n): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === RadioGroupItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\n/**\n * RadioGroup component props interface\n */\nexport type RadioGroupProps = {\n /** Current selected value */\n value?: string;\n /** Default selected value for uncontrolled usage */\n defaultValue?: string;\n /** Callback when selection changes */\n onValueChange?: (value: string) => void;\n /** Group name for all radios */\n name?: string;\n /** Disabled state for the entire group */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Children components */\n children: ReactNode;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>;\n\n/**\n * RadioGroup component for flexible radio group composition\n *\n * Uses Zustand for state management with automatic store injection.\n * Allows complete control over layout and styling by composing with RadioGroupItem.\n *\n * @example\n * ```tsx\n * <RadioGroup defaultValue=\"option1\" onValueChange={setValue}>\n * <div className=\"flex items-center gap-3\">\n * <RadioGroupItem value=\"option1\" id=\"r1\" />\n * <label htmlFor=\"r1\">Option 1</label>\n * </div>\n * <div className=\"flex items-center gap-3\">\n * <RadioGroupItem value=\"option2\" id=\"r2\" />\n * <label htmlFor=\"r2\">Option 2</label>\n * </div>\n * </RadioGroup>\n * ```\n */\nconst RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n (\n {\n value: propValue,\n defaultValue = '',\n onValueChange,\n name: propName,\n disabled = false,\n className = '',\n children,\n ...props\n },\n ref\n ) => {\n // Generate unique name if not provided\n const generatedId = useId();\n const name = propName || `radio-group-${generatedId}`;\n\n // Create store reference\n const storeRef = useRef<RadioGroupStoreApi>(null);\n storeRef.current ??= createRadioGroupStore(\n name,\n defaultValue,\n disabled,\n onValueChange\n );\n const store = storeRef.current;\n\n // Get store actions\n const { setValue } = useStore(store, (s) => s);\n\n // Call onValueChange with initial value\n useEffect(() => {\n const currentValue = store.getState().value;\n if (currentValue && onValueChange) {\n onValueChange(currentValue);\n }\n }, []); // Empty dependency array for mount only\n\n // Handle controlled value changes\n useEffect(() => {\n if (propValue !== undefined) {\n setValue(propValue);\n }\n }, [propValue, setValue]);\n\n // Update disabled state\n useEffect(() => {\n store.setState({ disabled });\n }, [disabled, store]);\n\n return (\n <div\n ref={ref}\n className={className}\n role=\"radiogroup\"\n aria-label={name}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\n\nRadioGroup.displayName = 'RadioGroup';\n\n/**\n * RadioGroupItem component props interface\n */\nexport type RadioGroupItemProps = {\n /** Value for this radio item */\n value: string;\n /** Optional label rendered next to the radio (parity with CheckBox/Radio APIs) */\n label?: ReactNode;\n /** CSS classes applied to the label */\n labelClassName?: string;\n /** Store reference (automatically injected by RadioGroup) */\n store?: RadioGroupStoreApi;\n /** Disabled state for this specific item */\n disabled?: boolean;\n /** Size variant */\n size?: RadioSize;\n /** Visual state */\n state?: RadioState;\n /** Additional CSS classes */\n className?: string;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'name' | 'value' | 'checked' | 'onChange' | 'size'\n>;\n\n/**\n * RadioGroupItem component for use within RadioGroup\n *\n * A radio button that works within RadioGroup context.\n * Accepts a `label` prop for the common case (parity with CheckBox/Radio).\n * When `label` is omitted, renders just the input for custom composition.\n *\n * @example\n * ```tsx\n * // With label (recommended)\n * <RadioGroup defaultValue=\"option1\">\n * <RadioGroupItem value=\"option1\" label=\"Option 1\" />\n * <RadioGroupItem value=\"option2\" label=\"Option 2\" />\n * </RadioGroup>\n *\n * // Without label - manual composition\n * <RadioGroup defaultValue=\"option1\">\n * <div className=\"flex items-center gap-3\">\n * <RadioGroupItem value=\"option1\" id=\"r1\" />\n * <label htmlFor=\"r1\">Custom layout</label>\n * </div>\n * </RadioGroup>\n * ```\n */\nconst RadioGroupItem = forwardRef<HTMLInputElement, RadioGroupItemProps>(\n (\n {\n value,\n label,\n labelClassName,\n store: externalStore,\n disabled: itemDisabled,\n size = 'medium',\n state = 'default',\n className = '',\n id,\n ...props\n },\n ref\n ) => {\n // Get store and state\n const store = useRadioGroupStore(externalStore);\n const {\n value: groupValue,\n setValue,\n disabled: groupDisabled,\n name,\n } = useStore(store);\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `radio-item-${generatedId}`;\n\n // Determine states\n const isChecked = groupValue === value;\n const isDisabled = groupDisabled || itemDisabled;\n const currentState = isDisabled ? 'disabled' : state;\n\n // Use standard Radio component for consistency and simplicity\n return (\n <Radio\n ref={ref}\n id={inputId}\n name={name}\n value={value}\n checked={isChecked}\n disabled={isDisabled}\n size={size}\n state={currentState}\n className={className}\n label={label}\n labelClassName={labelClassName}\n onChange={(e) => {\n if (e.target.checked && !isDisabled) {\n setValue(value);\n }\n }}\n {...props}\n />\n );\n }\n);\n\nRadioGroupItem.displayName = 'RadioGroupItem';\n\nexport default Radio;\nexport { RadioGroup, RadioGroupItem };\n","import { cloneElement, ComponentType, JSX, ReactElement } from 'react';\nimport * as PhosphorIcons from '@phosphor-icons/react';\nimport { ChatPT } from '../../assets/icons/subjects/ChatPT';\nimport { ChatEN } from '../../assets/icons/subjects/ChatEN';\nimport { ChatES } from '../../assets/icons/subjects/ChatES';\nimport { BookOpenText } from '../../assets/icons/subjects/BookOpenText';\nimport { Microscope } from '../../assets/icons/subjects/Microscope';\nimport { HeadCircuit } from '../../assets/icons/subjects/HeadCircuit';\n\ntype PhosphorIconName = keyof typeof PhosphorIcons;\ntype PhosphorIconComponent = ComponentType<{\n size?: number;\n color?: string;\n weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone';\n}>;\ntype CustomIconComponent = ComponentType<{\n size: number;\n color: string;\n}>;\n\n// Custom icons act as a fallback when Phosphor doesn't expose the name —\n// Chat_* have no Phosphor equivalent, and the others stay as a safety net\n// in case future Phosphor versions rename or remove them.\nconst CUSTOM_ICONS: Record<string, CustomIconComponent> = {\n Chat_PT: ChatPT,\n Chat_EN: ChatEN,\n Chat_ES: ChatES,\n BookOpenText,\n Microscope,\n HeadCircuit,\n};\n\nexport interface IconRenderProps {\n /**\n * The name of the icon to render\n */\n iconName: string | ReactElement;\n /**\n * The color of the icon\n * @default '#000000'\n */\n color?: string;\n /**\n * The size of the icon in pixels\n * @default 24\n */\n size?: number;\n /**\n * The weight/style of the icon (for Phosphor icons)\n * @default 'regular'\n */\n weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone';\n}\n\n/**\n * Dynamic icon component that renders icons based on name\n * Supports Phosphor icons and custom Chat icons (ChatPT, ChatEN, ChatES)\n *\n * @param iconName - The name of the icon to render\n * @param color - The color of the icon\n * @param size - The size of the icon in pixels\n * @param weight - The weight/style of the icon (for Phosphor icons)\n * @returns JSX element with the corresponding icon\n */\nexport const IconRender = ({\n iconName,\n color = '#000000',\n size = 24,\n weight = 'regular',\n}: IconRenderProps): JSX.Element => {\n // Guard against undefined/null iconName\n if (!iconName) {\n const FallbackIcon = PhosphorIcons.QuestionIcon as PhosphorIconComponent;\n return <FallbackIcon size={size} color={color} weight={weight} />;\n }\n\n if (typeof iconName === 'string') {\n // @phosphor-icons/react v2 exports canonical names with an `Icon` suffix\n // (the bare name is deprecated). Backend keeps sending the bare name.\n const PhosphorIcon = PhosphorIcons[\n `${iconName}Icon` as PhosphorIconName\n ] as PhosphorIconComponent | undefined;\n if (PhosphorIcon) {\n return <PhosphorIcon size={size} color={color} weight={weight} />;\n }\n\n const CustomIcon = CUSTOM_ICONS[iconName];\n if (CustomIcon) {\n return <CustomIcon size={size} color={color} />;\n }\n\n const Fallback = PhosphorIcons.QuestionIcon as PhosphorIconComponent;\n return <Fallback size={size} color={color} weight={weight} />;\n } else {\n // Clone the ReactElement with icon props, casting to avoid TypeScript errors\n return cloneElement(iconName, {\n size,\n color: 'currentColor',\n } as Partial<{\n size: number;\n color: string;\n }>);\n }\n};\n\nexport default IconRender;\n","export const ChatPT = ({ size, color }: { size: number; color: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M27 6H5.00004C4.4696 6 3.9609 6.21071 3.58582 6.58579C3.21075 6.96086 3.00004 7.46957 3.00004 8V28C2.99773 28.3814 3.10562 28.7553 3.31074 29.0768C3.51585 29.3984 3.80947 29.6538 4.15629 29.8125C4.42057 29.9356 4.7085 29.9995 5.00004 30C5.46954 29.9989 5.92347 29.8315 6.28129 29.5275L6.29254 29.5187L10.375 26H27C27.5305 26 28.0392 25.7893 28.4142 25.4142C28.7893 25.0391 29 24.5304 29 24V8C29 7.46957 28.7893 6.96086 28.4142 6.58579C28.0392 6.21071 27.5305 6 27 6ZM27 24H10C9.75992 24.0001 9.52787 24.0866 9.34629 24.2437L5.00004 28V8H27V24Z\"\n fill={color}\n />\n <path\n d=\"M21.1758 12V20.5312H19.7168V12H21.1758ZM23.8535 12V13.1719H17.0625V12H23.8535Z\"\n fill={color}\n />\n <path\n d=\"M13.2402 17.3496H11.0195V16.1836H13.2402C13.627 16.1836 13.9395 16.1211 14.1777 15.9961C14.416 15.8711 14.5898 15.6992 14.6992 15.4805C14.8125 15.2578 14.8691 15.0039 14.8691 14.7188C14.8691 14.4492 14.8125 14.1973 14.6992 13.9629C14.5898 13.7246 14.416 13.5332 14.1777 13.3887C13.9395 13.2441 13.627 13.1719 13.2402 13.1719H11.4707V20.5312H10V12H13.2402C13.9004 12 14.4609 12.1172 14.9219 12.3516C15.3867 12.582 15.7402 12.9023 15.9824 13.3125C16.2246 13.7188 16.3457 14.1836 16.3457 14.707C16.3457 15.2578 16.2246 15.7305 15.9824 16.125C15.7402 16.5195 15.3867 16.8223 14.9219 17.0332C14.4609 17.2441 13.9004 17.3496 13.2402 17.3496Z\"\n fill={color}\n />\n </svg>\n);\n","export const ChatEN = ({ size, color }: { size: number; color: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M27 6H5.00004C4.4696 6 3.9609 6.21071 3.58582 6.58579C3.21075 6.96086 3.00004 7.46957 3.00004 8V28C2.99773 28.3814 3.10562 28.7553 3.31074 29.0768C3.51585 29.3984 3.80947 29.6538 4.15629 29.8125C4.42057 29.9356 4.7085 29.9995 5.00004 30C5.46954 29.9989 5.92347 29.8315 6.28129 29.5275L6.29254 29.5187L10.375 26H27C27.5305 26 28.0392 25.7893 28.4142 25.4142C28.7893 25.0391 29 24.5304 29 24V8C29 7.46957 28.7893 6.96086 28.4142 6.58579C28.0392 6.21071 27.5305 6 27 6ZM27 24H10C9.75992 24.0001 9.52787 24.0866 9.34629 24.2437L5.00004 28V8H27V24Z\"\n fill={color}\n />\n <path\n d=\"M22.5488 12V20.5312H21.0781L17.252 14.4199V20.5312H15.7812V12H17.252L21.0898 18.123V12H22.5488Z\"\n fill={color}\n />\n <path\n d=\"M14.584 19.3652V20.5312H10.0547V19.3652H14.584ZM10.4707 12V20.5312H9V12H10.4707ZM13.9922 15.5625V16.7109H10.0547V15.5625H13.9922ZM14.5547 12V13.1719H10.0547V12H14.5547Z\"\n fill={color}\n />\n </svg>\n);\n","export const ChatES = ({ size, color }: { size: number; color: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M27 6H5.00004C4.4696 6 3.9609 6.21071 3.58582 6.58579C3.21075 6.96086 3.00004 7.46957 3.00004 8V28C2.99773 28.3814 3.10562 28.7553 3.31074 29.0768C3.51585 29.3984 3.80947 29.6538 4.15629 29.8125C4.42057 29.9356 4.7085 29.9995 5.00004 30C5.46954 29.9989 5.92347 29.8315 6.28129 29.5275L6.29254 29.5187L10.375 26H27C27.5305 26 28.0392 25.7893 28.4142 25.4142C28.7893 25.0391 29 24.5304 29 24V8C29 7.46957 28.7893 6.96086 28.4142 6.58579C28.0392 6.21071 27.5305 6 27 6ZM27 24H10C9.75992 24.0001 9.52787 24.0866 9.34629 24.2437L5.00004 28V8H27V24Z\"\n fill={color}\n />\n <path\n d=\"M21.1426 17.8027C21.1426 17.627 21.1152 17.4707 21.0605 17.334C21.0098 17.1973 20.918 17.0723 20.7852 16.959C20.6523 16.8457 20.4648 16.7363 20.2227 16.6309C19.9844 16.5215 19.6797 16.4102 19.3086 16.2969C18.9023 16.1719 18.5273 16.0332 18.1836 15.8809C17.8438 15.7246 17.5469 15.5449 17.293 15.3418C17.0391 15.1348 16.8418 14.8984 16.7012 14.6328C16.5605 14.3633 16.4902 14.0527 16.4902 13.7012C16.4902 13.3535 16.5625 13.0371 16.707 12.752C16.8555 12.4668 17.0645 12.2207 17.334 12.0137C17.6074 11.8027 17.9297 11.6406 18.3008 11.5273C18.6719 11.4102 19.082 11.3516 19.5312 11.3516C20.1641 11.3516 20.709 11.4688 21.166 11.7031C21.627 11.9375 21.9805 12.252 22.2266 12.6465C22.4766 13.041 22.6016 13.4766 22.6016 13.9531H21.1426C21.1426 13.6719 21.082 13.4238 20.9609 13.209C20.8438 12.9902 20.6641 12.8184 20.4219 12.6934C20.1836 12.5684 19.8809 12.5059 19.5137 12.5059C19.166 12.5059 18.877 12.5586 18.6465 12.6641C18.416 12.7695 18.2441 12.9121 18.1309 13.0918C18.0176 13.2715 17.9609 13.4746 17.9609 13.7012C17.9609 13.8613 17.998 14.0078 18.0723 14.1406C18.1465 14.2695 18.2598 14.3906 18.4121 14.5039C18.5645 14.6133 18.7559 14.7168 18.9863 14.8145C19.2168 14.9121 19.4883 15.0059 19.8008 15.0957C20.2734 15.2363 20.6855 15.3926 21.0371 15.5645C21.3887 15.7324 21.6816 15.9238 21.916 16.1387C22.1504 16.3535 22.3262 16.5977 22.4434 16.8711C22.5605 17.1406 22.6191 17.4473 22.6191 17.791C22.6191 18.1504 22.5469 18.4746 22.4023 18.7637C22.2578 19.0488 22.0508 19.293 21.7812 19.4961C21.5156 19.6953 21.1953 19.8496 20.8203 19.959C20.4492 20.0645 20.0352 20.1172 19.5781 20.1172C19.168 20.1172 18.7637 20.0625 18.3652 19.9531C17.9707 19.8438 17.6113 19.6777 17.2871 19.4551C16.9629 19.2285 16.7051 18.9473 16.5137 18.6113C16.3223 18.2715 16.2266 17.875 16.2266 17.4219H17.6973C17.6973 17.6992 17.7441 17.9355 17.8379 18.1309C17.9355 18.3262 18.0703 18.4863 18.2422 18.6113C18.4141 18.7324 18.6133 18.8223 18.8398 18.8809C19.0703 18.9395 19.3164 18.9688 19.5781 18.9688C19.9219 18.9688 20.209 18.9199 20.4395 18.8223C20.6738 18.7246 20.8496 18.5879 20.9668 18.4121C21.084 18.2363 21.1426 18.0332 21.1426 17.8027Z\"\n fill={color}\n />\n <path\n d=\"M15.4512 18.834V20H10.9219V18.834H15.4512ZM11.3379 11.4688V20H9.86719V11.4688H11.3379ZM14.8594 15.0312V16.1797H10.9219V15.0312H14.8594ZM15.4219 11.4688V12.6406H10.9219V11.4688H15.4219Z\"\n fill={color}\n />\n </svg>\n);\n","export const BookOpenText = ({\n size,\n color,\n}: {\n size: number;\n color: string;\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M29 6H20C19.2238 6 18.4582 6.18073 17.7639 6.52786C17.0697 6.875 16.4657 7.37902 16 8C15.5343 7.37902 14.9303 6.875 14.2361 6.52786C13.5418 6.18073 12.7762 6 12 6H3C2.73478 6 2.48043 6.10536 2.29289 6.29289C2.10536 6.48043 2 6.73478 2 7V25C2 25.2652 2.10536 25.5196 2.29289 25.7071C2.48043 25.8946 2.73478 26 3 26H12C12.7956 26 13.5587 26.3161 14.1213 26.8787C14.6839 27.4413 15 28.2044 15 29C15 29.2652 15.1054 29.5196 15.2929 29.7071C15.4804 29.8946 15.7348 30 16 30C16.2652 30 16.5196 29.8946 16.7071 29.7071C16.8946 29.5196 17 29.2652 17 29C17 28.2044 17.3161 27.4413 17.8787 26.8787C18.4413 26.3161 19.2044 26 20 26H29C29.2652 26 29.5196 25.8946 29.7071 25.7071C29.8946 25.5196 30 25.2652 30 25V7C30 6.73478 29.8946 6.48043 29.7071 6.29289C29.5196 6.10536 29.2652 6 29 6ZM12 24H4V8H12C12.7956 8 13.5587 8.31607 14.1213 8.87868C14.6839 9.44129 15 10.2044 15 11V25C14.1353 24.3493 13.0821 23.9983 12 24ZM28 24H20C18.9179 23.9983 17.8647 24.3493 17 25V11C17 10.2044 17.3161 9.44129 17.8787 8.87868C18.4413 8.31607 19.2044 8 20 8H28V24ZM20 11H25C25.2652 11 25.5196 11.1054 25.7071 11.2929C25.8946 11.4804 26 11.7348 26 12C26 12.2652 25.8946 12.5196 25.7071 12.7071C25.5196 12.8946 25.2652 13 25 13H20C19.7348 13 19.4804 12.8946 19.2929 12.7071C19.1054 12.5196 19 12.2652 19 12C19 11.7348 19.1054 11.4804 19.2929 11.2929C19.4804 11.1054 19.7348 11 20 11ZM26 16C26 16.2652 25.8946 16.5196 25.7071 16.7071C25.5196 16.8946 25.2652 17 25 17H20C19.7348 17 19.4804 16.8946 19.2929 16.7071C19.1054 16.5196 19 16.2652 19 16C19 15.7348 19.1054 15.4804 19.2929 15.2929C19.4804 15.1054 19.7348 15 20 15H25C25.2652 15 25.5196 15.1054 25.7071 15.2929C25.8946 15.4804 26 15.7348 26 16ZM26 20C26 20.2652 25.8946 20.5196 25.7071 20.7071C25.5196 20.8946 25.2652 21 25 21H20C19.7348 21 19.4804 20.8946 19.2929 20.7071C19.1054 20.5196 19 20.2652 19 20C19 19.7348 19.1054 19.4804 19.2929 19.2929C19.4804 19.1054 19.7348 19 20 19H25C25.2652 19 25.5196 19.1054 25.7071 19.2929C25.8946 19.4804 26 19.7348 26 20Z\"\n fill={color}\n />\n </svg>\n);\n","export const Microscope = ({\n size,\n color,\n}: {\n size: number;\n color: string;\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M28 26H25.4925C26.7637 24.4552 27.5898 22.5932 27.882 20.6142C28.1743 18.6351 27.9216 16.6138 27.1511 14.7676C26.3806 12.9213 25.1215 11.32 23.5092 10.1358C21.8968 8.95153 19.9922 8.22913 18 8.04625V4C18 3.46957 17.7893 2.96086 17.4142 2.58579C17.0391 2.21071 16.5304 2 16 2H10C9.46957 2 8.96086 2.21071 8.58579 2.58579C8.21071 2.96086 8 3.46957 8 4V17C8 17.5304 8.21071 18.0391 8.58579 18.4142C8.96086 18.7893 9.46957 19 10 19H16C16.5304 19 17.0391 18.7893 17.4142 18.4142C17.7893 18.0391 18 17.5304 18 17V10.0575C19.7643 10.2552 21.4306 10.9703 22.7895 12.1128C24.1483 13.2553 25.1389 14.7742 25.6366 16.4783C26.1343 18.1824 26.1169 19.9957 25.5866 21.69C25.0563 23.3842 24.0368 24.8838 22.6562 26H4C3.73478 26 3.48043 26.1054 3.29289 26.2929C3.10536 26.4804 3 26.7348 3 27C3 27.2652 3.10536 27.5196 3.29289 27.7071C3.48043 27.8946 3.73478 28 4 28H28C28.2652 28 28.5196 27.8946 28.7071 27.7071C28.8946 27.5196 29 27.2652 29 27C29 26.7348 28.8946 26.4804 28.7071 26.2929C28.5196 26.1054 28.2652 26 28 26ZM16 17H10V4H16V17ZM9 23C8.73478 23 8.48043 22.8946 8.29289 22.7071C8.10536 22.5196 8 22.2652 8 22C8 21.7348 8.10536 21.4804 8.29289 21.2929C8.48043 21.1054 8.73478 21 9 21H17C17.2652 21 17.5196 21.1054 17.7071 21.2929C17.8946 21.4804 18 21.7348 18 22C18 22.2652 17.8946 22.5196 17.7071 22.7071C17.5196 22.8946 17.2652 23 17 23H9Z\"\n fill={color}\n />\n </svg>\n);\n","export const HeadCircuit = ({\n size,\n color,\n}: {\n size: number;\n color: string;\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M24.0625 21.4338C25.327 20.3715 26.3372 19.0392 27.0187 17.5348C27.7001 16.0304 28.0354 14.3924 28 12.7413C27.875 7.02751 23.2987 2.31626 17.595 2.01626C16.1233 1.93616 14.6506 2.15261 13.2642 2.65277C11.8778 3.15293 10.6061 3.92659 9.52453 4.92781C8.44297 5.92903 7.57365 7.13739 6.96819 8.48112C6.36272 9.82485 6.03347 11.2766 5.99997 12.75L3.19372 18.1475C3.18247 18.17 3.17122 18.1925 3.16122 18.215C2.96003 18.6839 2.94569 19.212 3.12114 19.6912C3.29659 20.1704 3.64855 20.5644 4.10497 20.7925L4.13622 20.8063L6.99997 22.1175V26C6.99997 26.5304 7.21068 27.0392 7.58576 27.4142C7.96083 27.7893 8.46954 28 8.99997 28H15C15.2652 28 15.5195 27.8947 15.7071 27.7071C15.8946 27.5196 16 27.2652 16 27C16 26.7348 15.8946 26.4804 15.7071 26.2929C15.5195 26.1054 15.2652 26 15 26H8.99997V21.4763C9.00011 21.2846 8.94517 21.0969 8.84168 20.9356C8.73818 20.7742 8.5905 20.646 8.41622 20.5663L4.99997 19L7.88372 13.4575C7.95889 13.3166 7.99878 13.1597 7.99997 13C7.99968 10.9604 8.69216 8.98124 9.96395 7.38674C11.2357 5.79224 13.0114 4.677 15 4.22376V6.17251C14.3328 6.4084 13.7704 6.87258 13.4123 7.48299C13.0543 8.0934 12.9235 8.81075 13.0432 9.50824C13.1628 10.2057 13.5252 10.8385 14.0663 11.2946C14.6074 11.7508 15.2923 12.0009 16 12.0009C16.7077 12.0009 17.3926 11.7508 17.9336 11.2946C18.4747 10.8385 18.8371 10.2057 18.9568 9.50824C19.0764 8.81075 18.9457 8.0934 18.5876 7.48299C18.2295 6.87258 17.6672 6.4084 17 6.17251V4.00001C17.1625 4.00001 17.325 4.00001 17.4875 4.01251C19.2608 4.11409 20.9649 4.73627 22.3864 5.80124C23.808 6.86621 24.8841 8.32669 25.48 10H23C22.8533 9.99995 22.7084 10.0322 22.5755 10.0944C22.4426 10.1566 22.3251 10.2473 22.2312 10.36L19.0425 14.1875C18.3774 13.9397 17.6462 13.9351 16.9781 14.1744C16.3099 14.4138 15.748 14.8817 15.3916 15.4954C15.0352 16.1092 14.9073 16.8292 15.0306 17.5281C15.1538 18.227 15.5203 18.8598 16.0652 19.3146C16.61 19.7694 17.2981 20.0168 18.0078 20.0132C18.7175 20.0095 19.4031 19.755 19.9432 19.2947C20.4834 18.8343 20.8433 18.1977 20.9594 17.4976C21.0754 16.7974 20.9402 16.0788 20.5775 15.4688L23.4687 12H25.9425C25.9725 12.26 25.9908 12.5225 25.9975 12.7875C26.0286 14.2198 25.7187 15.639 25.0931 16.9278C24.4676 18.2167 23.5445 19.3383 22.4 20.2C22.2589 20.3057 22.1484 20.4469 22.0794 20.6091C22.0105 20.7713 21.9857 20.9489 22.0075 21.1238L23.0075 29.1238C23.0379 29.3653 23.1554 29.5874 23.3379 29.7485C23.5203 29.9095 23.7553 29.9985 23.9987 29.9988C24.0405 29.9988 24.0822 29.9962 24.1237 29.9913C24.2541 29.975 24.3799 29.9333 24.4942 29.8684C24.6084 29.8035 24.7087 29.7168 24.7893 29.6131C24.87 29.5094 24.9295 29.3909 24.9643 29.2643C24.9992 29.1376 25.0087 29.0054 24.9925 28.875L24.0625 21.4338ZM16 10C15.8022 10 15.6088 9.94136 15.4444 9.83148C15.28 9.7216 15.1518 9.56542 15.0761 9.38269C15.0004 9.19997 14.9806 8.9989 15.0192 8.80492C15.0578 8.61094 15.153 8.43275 15.2929 8.2929C15.4327 8.15305 15.6109 8.05781 15.8049 8.01922C15.9989 7.98064 16.1999 8.00044 16.3827 8.07613C16.5654 8.15182 16.7216 8.27999 16.8314 8.44444C16.9413 8.60889 17 8.80223 17 9.00001C17 9.26523 16.8946 9.51958 16.7071 9.70712C16.5195 9.89465 16.2652 10 16 10ZM18 18C17.8022 18 17.6088 17.9414 17.4444 17.8315C17.28 17.7216 17.1518 17.5654 17.0761 17.3827C17.0004 17.2 16.9806 16.9989 17.0192 16.8049C17.0578 16.6109 17.153 16.4328 17.2929 16.2929C17.4327 16.153 17.6109 16.0578 17.8049 16.0192C17.9989 15.9806 18.1999 16.0004 18.3827 16.0761C18.5654 16.1518 18.7216 16.28 18.8314 16.4444C18.9413 16.6089 19 16.8022 19 17C19 17.2652 18.8946 17.5196 18.7071 17.7071C18.5195 17.8947 18.2652 18 18 18Z\"\n fill={color}\n />\n </svg>\n);\n","import { CheckCircle, XCircle } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport { RadioGroup, RadioGroupItem } from '../Radio/Radio';\nimport { forwardRef, HTMLAttributes, useId, useState } from 'react';\nimport { cn } from '../../utils/utils';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nimport { QuizVariant } from '../Quiz/Quiz.types';\nimport { OptionStatus } from '../../enums/Options';\n\n/**\n * Interface para definir uma alternativa\n */\nexport interface Alternative {\n value: string;\n label: string;\n status?: OptionStatus;\n disabled?: boolean;\n description?: string;\n}\n\n/**\n * Props do componente AlternativesList\n */\nexport interface AlternativesListProps {\n /** Lista de alternativas */\n alternatives: Alternative[];\n /** Nome do grupo de radio */\n name?: string;\n /** Valor selecionado por padrão */\n defaultValue?: string;\n /** Valor controlado */\n value?: string;\n /** Callback quando uma alternativa é selecionada */\n onValueChange?: (value: string) => void;\n /** Se o componente está desabilitado */\n disabled?: boolean;\n /** Layout das alternativas */\n layout?: 'default' | 'compact' | 'detailed';\n /** Classes CSS adicionais */\n className?: string;\n /** Modo de exibição: interativo (com radios funcionais) ou readonly (apenas visual) */\n mode?: 'interactive' | 'readonly';\n /** Valor selecionado pelo usuário (apenas para modo readonly) */\n selectedValue?: string;\n}\n\n/**\n * Componente reutilizável para exibir lista de alternativas com RadioGroup\n *\n * Suporta dois modos:\n * - `interactive`: Permite interação com radios (padrão)\n * - `readonly`: Apenas exibição visual dos estados\n *\n * @example\n * ```tsx\n * // Modo interativo (padrão)\n * <AlternativesList\n * mode=\"interactive\"\n * alternatives={[\n * { value: \"a\", label: \"Alternativa A\", status: \"correct\" },\n * { value: \"b\", label: \"Alternativa B\", status: \"incorrect\" },\n * { value: \"c\", label: \"Alternativa C\" }\n * ]}\n * defaultValue=\"a\"\n * onValueChange={(value) => console.log(value)}\n * />\n *\n * // Modo readonly - mostra seleção do usuário\n * <AlternativesList\n * mode=\"readonly\"\n * selectedValue=\"b\" // O que o usuário selecionou\n * alternatives={[\n * { value: \"a\", label: \"Resposta A\", status: \"correct\" }, // Mostra como correta\n * { value: \"b\", label: \"Resposta B\" }, // Mostra radio selecionado + badge incorreto\n * { value: \"c\", label: \"Resposta C\" }\n * ]}\n * />\n * ```\n */\nconst AlternativesList = ({\n alternatives,\n name,\n defaultValue,\n value,\n onValueChange,\n disabled = false,\n layout = 'default',\n className = '',\n mode = QuizVariant.INTERACTIVE,\n selectedValue,\n}: AlternativesListProps) => {\n // Gerar um ID único para garantir que cada instância tenha seu próprio grupo\n const uniqueId = useId();\n const groupName = name || `alternatives-${uniqueId}`;\n const [actualValue, setActualValue] = useState(value);\n // No modo readonly, não precisamos de interação\n const isReadonly = mode === 'readonly';\n const getStatusStyles = (\n status?: Alternative['status'],\n isReadonly?: boolean\n ) => {\n const hoverClass = isReadonly ? '' : 'hover:bg-background-50';\n\n switch (status) {\n case OptionStatus.CORRECT:\n return 'bg-success-background border-success-300';\n case OptionStatus.INCORRECT:\n return 'bg-error-background border-error-300';\n default:\n return `bg-background border-border-100 ${hoverClass}`;\n }\n };\n\n const getStatusBadge = (status?: Alternative['status']) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n };\n\n const getLayoutClasses = () => {\n switch (layout) {\n case 'compact':\n return 'gap-2';\n case 'detailed':\n return 'gap-4';\n default:\n return 'gap-3.5';\n }\n };\n\n // Componente para renderizar alternativa no modo readonly\n const renderReadonlyAlternative = (alternative: Alternative) => {\n const alternativeId = alternative.value;\n const isUserSelected = selectedValue === alternative.value;\n const isCorrectAnswer = alternative.status === OptionStatus.CORRECT;\n\n // Determinar o status da alternativa para visualização\n let displayStatus: Alternative['status'] = undefined;\n if (isUserSelected && !isCorrectAnswer) {\n // Usuário selecionou alternativa incorreta\n displayStatus = OptionStatus.INCORRECT;\n } else if (isCorrectAnswer) {\n // Alternativa correta (independente se foi selecionada ou não)\n displayStatus = OptionStatus.CORRECT;\n }\n\n const statusStyles = getStatusStyles(displayStatus, true);\n const statusBadge = getStatusBadge(displayStatus);\n\n // Radio visual - apenas mostra selecionado se o usuário escolheu esta alternativa\n const renderRadio = () => {\n const radioClasses = `w-6 h-6 rounded-full border-2 cursor-default transition-all duration-200 flex items-center justify-center ${\n isUserSelected\n ? 'border-primary-950 bg-background'\n : 'border-border-400 bg-background'\n }`;\n\n const dotClasses =\n 'w-3 h-3 rounded-full bg-primary-950 transition-all duration-200';\n\n return (\n <div className={radioClasses}>\n {isUserSelected && <div className={dotClasses} />}\n </div>\n );\n };\n\n if (layout === 'detailed') {\n return (\n <div\n key={alternativeId}\n className={cn(\n 'border-2 rounded-lg p-4 w-full',\n statusStyles,\n alternative.disabled ? 'opacity-50' : ''\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3 flex-1\">\n <div className=\"mt-1\">{renderRadio()}</div>\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={alternative.label}\n className={cn(\n 'block font-medium',\n selectedValue === alternative.value || statusBadge\n ? 'text-text-950'\n : 'text-text-600'\n )}\n />\n {alternative.description && (\n <p className=\"text-sm text-text-600 mt-1\">\n {alternative.description}\n </p>\n )}\n </div>\n </div>\n {statusBadge && <div className=\"flex-shrink-0\">{statusBadge}</div>}\n </div>\n </div>\n );\n }\n\n return (\n <div\n key={alternativeId}\n className={cn(\n 'flex flex-row justify-between items-start gap-2 p-2 rounded-lg w-full',\n statusStyles,\n alternative.disabled ? 'opacity-50' : ''\n )}\n >\n <div className=\"flex items-center gap-2 flex-1\">\n {renderRadio()}\n <HtmlMathRenderer\n content={alternative.label}\n className={cn(\n 'flex-1',\n selectedValue === alternative.value || statusBadge\n ? 'text-text-950'\n : 'text-text-600'\n )}\n />\n </div>\n {statusBadge && <div className=\"flex-shrink-0\">{statusBadge}</div>}\n </div>\n );\n };\n\n // Se for modo readonly, renderizar sem RadioGroup\n if (isReadonly) {\n return (\n <div\n className={cn('flex flex-col', getLayoutClasses(), 'w-full', className)}\n >\n {alternatives.map((alternative) =>\n renderReadonlyAlternative(alternative)\n )}\n </div>\n );\n }\n\n return (\n <RadioGroup\n name={groupName}\n defaultValue={defaultValue}\n value={value}\n onValueChange={(value) => {\n setActualValue(value);\n onValueChange?.(value);\n }}\n disabled={disabled}\n className={cn('flex flex-col', getLayoutClasses(), className)}\n >\n {alternatives.map((alternative, index) => {\n const alternativeId = alternative.value || `alt-${index}`;\n const statusStyles = getStatusStyles(alternative.status, false);\n const statusBadge = getStatusBadge(alternative.status);\n\n if (layout === 'detailed') {\n return (\n <div\n key={alternativeId}\n className={cn(\n 'border-2 rounded-lg p-4 transition-all',\n statusStyles,\n alternative.disabled\n ? 'opacity-50 cursor-not-allowed'\n : 'cursor-pointer'\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3 flex-1\">\n <RadioGroupItem\n value={alternative.value}\n id={alternativeId}\n disabled={alternative.disabled}\n className=\"mt-1\"\n />\n <div className=\"flex-1\">\n <label\n htmlFor={alternativeId}\n className={cn(\n 'block font-medium',\n actualValue === alternative.value\n ? 'text-text-950'\n : 'text-text-600',\n alternative.disabled\n ? 'cursor-not-allowed'\n : 'cursor-pointer'\n )}\n >\n <HtmlMathRenderer content={alternative.label} inline />\n </label>\n {alternative.description && (\n <p className=\"text-sm text-text-600 mt-1\">\n {alternative.description}\n </p>\n )}\n </div>\n </div>\n {statusBadge && (\n <div className=\"flex-shrink-0\">{statusBadge}</div>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div\n key={alternativeId}\n className={cn(\n 'flex flex-row justify-between gap-2 items-start p-2 rounded-lg transition-all',\n statusStyles,\n alternative.disabled ? 'opacity-50 cursor-not-allowed' : ''\n )}\n >\n <div className=\"flex items-center gap-2 flex-1\">\n <RadioGroupItem\n value={alternative.value}\n id={alternativeId}\n disabled={alternative.disabled}\n />\n <label\n htmlFor={alternativeId}\n className={cn(\n 'flex-1',\n actualValue === alternative.value\n ? 'text-text-950'\n : 'text-text-600',\n alternative.disabled ? 'cursor-not-allowed' : 'cursor-pointer'\n )}\n >\n <HtmlMathRenderer content={alternative.label} inline />\n </label>\n </div>\n {statusBadge && <div className=\"flex-shrink-0\">{statusBadge}</div>}\n </div>\n );\n })}\n </RadioGroup>\n );\n};\n\ninterface HeaderAlternativeProps extends HTMLAttributes<HTMLDivElement> {\n title: string;\n subTitle: string;\n content: string;\n}\n\nconst HeaderAlternative = forwardRef<HTMLDivElement, HeaderAlternativeProps>(\n ({ className, title, subTitle, content, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-background p-4 flex flex-col gap-4 rounded-xl',\n className\n )}\n {...props}\n >\n <span className=\"flex flex-col\">\n <p className=\"text-text-950 font-bold text-lg\">{title}</p>\n <p className=\"text-text-700 text-sm \">{subTitle}</p>\n </span>\n\n <HtmlMathRenderer content={content} className=\"text-text-950 text-md\" />\n </div>\n );\n }\n);\n\nexport { AlternativesList, HeaderAlternative };\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport { AlternativesList } from '../../../components/Alternative/Alternative';\nimport { OptionStatus } from '../../../enums/Options';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\n\n/**\n * Render alternative question (single choice)\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionAlternative = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n // Check if options have isCorrect defined (can auto-validate even if pending)\n const hasAutoValidation = result?.options?.some(\n (op) => op.isCorrect !== undefined && op.isCorrect !== null\n );\n\n const alternatives = question.options?.map((option) => {\n const isCorrectOption =\n result?.options?.find((op) => op.id === option.id)?.isCorrect || false;\n\n const isSelected =\n result?.selectedOptions?.some(\n (selectedOption) => selectedOption.optionId === option.id\n ) || false;\n\n // Show correct answers if not pending, OR if we can auto-validate (has isCorrect)\n const shouldShowCorrectAnswers =\n result?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO ||\n hasAutoValidation;\n\n let status: OptionStatus;\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation and no auto-validation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n\n return {\n label: option.option,\n value: option.id,\n status: status,\n };\n });\n\n if (!alternatives || alternatives.length === 0) {\n return (\n <div>\n <Text size=\"sm\" weight=\"normal\">\n Não há Alternativas\n </Text>\n </div>\n );\n }\n\n return (\n <div className=\"pt-2\">\n <AlternativesList\n mode=\"readonly\"\n key={`question-${question.id}`}\n name={`question-${question.id}`}\n layout=\"compact\"\n alternatives={alternatives}\n selectedValue={result?.selectedOptions?.[0]?.optionId || ''}\n />\n </div>\n );\n};\n","import { HtmlHTMLAttributes, useEffect, useState } from 'react';\nimport CheckboxList, { CheckboxListItem } from '../CheckBox/CheckboxList';\nimport { cn } from '../../utils/utils';\nimport { CheckCircle, XCircle, Check } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nimport { QuizVariant } from '../Quiz/Quiz.types';\nimport { OptionStatus } from '../../enums/Options';\n\ninterface Choice {\n value: string;\n label: string;\n status?: OptionStatus;\n disabled?: boolean;\n}\n\ninterface MultipleChoiceListProps extends HtmlHTMLAttributes<HTMLDivElement> {\n choices: Choice[];\n disabled?: boolean;\n name?: string;\n selectedValues?: string[];\n onHandleSelectedValues?: (values: string[]) => void;\n mode?: 'interactive' | 'readonly';\n}\n\nconst MultipleChoiceList = ({\n disabled = false,\n className = '',\n choices,\n name,\n selectedValues,\n onHandleSelectedValues,\n mode = QuizVariant.INTERACTIVE,\n}: MultipleChoiceListProps) => {\n const [actualValue, setActualValue] = useState(selectedValues);\n\n useEffect(() => {\n setActualValue(selectedValues);\n }, [selectedValues]);\n const getStatusBadge = (status: Choice['status']) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n };\n\n const getStatusStyles = (status: Choice['status']) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return 'bg-success-background border-success-300';\n case OptionStatus.INCORRECT:\n return 'bg-error-background border-error-300';\n default:\n return `bg-background border-border-100`;\n }\n };\n\n const renderVisualCheckbox = (isSelected: boolean, isDisabled: boolean) => {\n const checkboxClasses = cn(\n 'w-5 h-5 rounded border-2 cursor-default transition-all duration-200 flex items-center justify-center',\n isSelected\n ? 'border-primary-950 bg-primary-950 text-text'\n : 'border-border-400 bg-background',\n isDisabled && 'opacity-40 cursor-not-allowed'\n );\n\n return (\n <div className={checkboxClasses}>\n {isSelected && <Check size={16} weight=\"bold\" />}\n </div>\n );\n };\n\n if (mode === 'readonly') {\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n {choices.map((choice, i) => {\n const isSelected = actualValue?.includes(choice.value) || false;\n const statusStyles = getStatusStyles(choice.status);\n const statusBadge = getStatusBadge(choice.status);\n\n return (\n <div\n key={`readonly-${choice.value}-${i}`}\n className={cn(\n 'flex flex-row justify-between gap-2 items-start p-2 rounded-lg transition-all',\n statusStyles,\n choice.disabled ? 'opacity-50 cursor-not-allowed' : ''\n )}\n >\n <div className=\"flex items-center gap-2 flex-1\">\n {renderVisualCheckbox(isSelected, choice.disabled || disabled)}\n <HtmlMathRenderer\n content={choice.label}\n className={cn(\n 'flex-1',\n isSelected ||\n (choice.status && choice.status != OptionStatus.NEUTRAL)\n ? 'text-text-950'\n : 'text-text-600',\n choice.disabled || disabled\n ? 'cursor-not-allowed'\n : 'cursor-default'\n )}\n />\n </div>\n {statusBadge && (\n <div className=\"flex-shrink-0\">{statusBadge}</div>\n )}\n </div>\n );\n })}\n </div>\n );\n }\n return (\n <div\n className={cn(\n 'flex flex-row justify-between gap-2 items-start p-2 rounded-lg transition-all',\n disabled ? 'opacity-50 cursor-not-allowed' : '',\n className\n )}\n >\n <CheckboxList\n name={name}\n values={actualValue}\n onValuesChange={(v) => {\n setActualValue(v);\n onHandleSelectedValues?.(v);\n }}\n disabled={disabled}\n >\n {choices.map((choice, i) => (\n <div\n key={`interactive-${choice.value}-${i}`}\n className=\"flex flex-row gap-2 items-center\"\n >\n <CheckboxListItem\n value={choice.value}\n id={`interactive-${choice.value}-${i}`}\n disabled={choice.disabled || disabled}\n />\n\n <label\n htmlFor={`interactive-${choice.value}-${i}`}\n className={cn(\n 'flex-1',\n actualValue?.includes(choice.value)\n ? 'text-text-950'\n : 'text-text-600',\n choice.disabled || disabled\n ? 'cursor-not-allowed'\n : 'cursor-pointer'\n )}\n >\n <HtmlMathRenderer content={choice.label} />\n </label>\n </div>\n ))}\n </CheckboxList>\n </div>\n );\n};\n\nexport { MultipleChoiceList };\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport { MultipleChoiceList } from '../../../components/MultipleChoice/MultipleChoice';\nimport { OptionStatus } from '../../../enums/Options';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\n\n/**\n * Render multiple choice question\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionMultipleChoice = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n // Check if options have isCorrect defined (can auto-validate even if pending)\n const hasAutoValidation = result?.options?.some(\n (op) => op.isCorrect !== undefined && op.isCorrect !== null\n );\n\n const choices = question.options?.map((option) => {\n const isCorrectOption =\n result?.options?.find((op) => op.id === option.id)?.isCorrect || false;\n\n const isSelected = result?.selectedOptions?.some(\n (op) => op.optionId === option.id\n );\n\n // Show correct/incorrect status if not pending/blank, OR if we can auto-validate (has isCorrect)\n const shouldShowCorrectAnswers =\n (result?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n result?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO) ||\n hasAutoValidation;\n\n let status: OptionStatus;\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation and no auto-validation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n\n return {\n label: option.option,\n value: option.id,\n status,\n };\n });\n\n if (!choices || choices.length === 0) {\n return (\n <div>\n <Text size=\"sm\" weight=\"normal\">\n Não há Escolhas Múltiplas\n </Text>\n </div>\n );\n }\n\n const selectedValues =\n result?.selectedOptions?.map((op) => op.optionId) || [];\n\n return (\n <div className=\"pt-2\">\n <MultipleChoiceList\n mode=\"readonly\"\n key={`question-${question.id}`}\n name={`question-${question.id}`}\n choices={choices}\n selectedValues={selectedValues}\n />\n </div>\n );\n};\n","import {\n Fragment,\n forwardRef,\n MouseEvent,\n ReactNode,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { ANSWER_STATUS, useQuizStore } from './useQuizStore';\nimport { QuizVariant } from './Quiz.types';\nimport { TrueFalseEnum } from '../../enums/Quiz';\nimport {\n prependLetterToHtml,\n getTrueOrFalseOptionState,\n shuffleWithSeed,\n} from './Quiz.utils';\nimport { cn } from '../../utils/utils';\nimport { stripHtmlTags } from '../../utils/stringUtils';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport TextArea from '../TextArea/TextArea';\nimport { AlternativesList } from '../Alternative/Alternative';\nimport { OptionStatus } from '../../enums/Options';\nimport { MultipleChoiceList } from '../MultipleChoice/MultipleChoice';\nimport Badge from '../Badge/Badge';\nimport { CheckCircle, XCircle } from 'phosphor-react';\nimport ImageQuestion from '../../assets/img/mock-image-question.png';\nimport Text from '../Text/Text';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nexport const getStatusBadge = (status?: OptionStatus) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n};\n\nexport const getStatusStyles = (variantCorrect?: OptionStatus) => {\n switch (variantCorrect) {\n case OptionStatus.CORRECT:\n return 'bg-success-background border-success-300';\n case OptionStatus.INCORRECT:\n return 'bg-error-background border-error-300';\n default:\n return '';\n }\n};\n\n/**\n * Normalizes parsed answer data to Record<string, string> format.\n * Handles legacy array format [{ optionId, selectedValue }] by converting to { [optionId]: selectedValue }.\n */\nconst normalizeAnswerData = (parsed: unknown): Record<string, string> => {\n // Handle legacy array format: [{ optionId: string, selectedValue: string }]\n if (Array.isArray(parsed)) {\n const result: Record<string, string> = {};\n for (const item of parsed) {\n if (\n item &&\n typeof item === 'object' &&\n 'optionId' in item &&\n 'selectedValue' in item\n ) {\n result[item.optionId as string] = item.selectedValue as string;\n }\n }\n return result;\n }\n\n // Handle expected object format: { [optionId]: selectedValue }\n if (parsed && typeof parsed === 'object') {\n return parsed as Record<string, string>;\n }\n\n return {};\n};\n\n/**\n * Parses JSON answers from stored answer string.\n * In result mode, uses persisted results. Otherwise, uses current draft answers.\n * Normalizes legacy array format to expected Record<string, string> map.\n */\nconst parseStoredAnswers = (\n variant: QuizVariant,\n resultAnswer: string | null | undefined,\n currentAnswer: string | null | undefined\n): Record<string, string> => {\n if (variant === QuizVariant.RESULT) {\n if (!resultAnswer) return {};\n try {\n const parsed = JSON.parse(resultAnswer);\n return normalizeAnswerData(parsed);\n } catch {\n return {};\n }\n }\n if (currentAnswer) {\n try {\n const parsed = JSON.parse(currentAnswer);\n return normalizeAnswerData(parsed);\n } catch {\n return {};\n }\n }\n return {};\n};\n\n/**\n * Converts isCorrect boolean to status variant string.\n * Returns undefined for null/unanswered to keep neutral styling.\n */\nconst getAnswerStatus = (\n isCorrect: boolean | null\n): OptionStatus | undefined => {\n if (isCorrect === true) return OptionStatus.CORRECT;\n if (isCorrect === false) return OptionStatus.INCORRECT;\n return undefined;\n};\n\ninterface QuizVariantInterface {\n paddingBottom?: string;\n}\n\nconst QuizSubTitle = forwardRef<HTMLDivElement, { subTitle: string }>(\n ({ subTitle, ...props }, ref) => {\n return (\n <div className=\"px-4 pb-2 pt-6\" {...props} ref={ref}>\n <p className=\"font-bold text-lg text-text-950\">{subTitle}</p>\n </div>\n );\n }\n);\n\nconst QuizContainer = forwardRef<\n HTMLDivElement,\n { children: ReactNode; className?: string }\n>(({ children, className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-background rounded-t-xl px-4 pt-4 pb-[80px] h-auto flex flex-col gap-4 mb-auto',\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n});\n\nconst QuizAlternative = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n selectAnswer,\n getQuestionResultByQuestionId,\n getCurrentAnswer,\n variant,\n } = useQuizStore();\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n const currentAnswer = getCurrentAnswer();\n const alternatives = currentQuestion?.options?.map((option) => {\n let status: OptionStatus = OptionStatus.NEUTRAL;\n if (variant === QuizVariant.RESULT) {\n const isCorrectOption =\n currentQuestionResult?.options?.find((op) => op.id === option.id)\n ?.isCorrect || false;\n\n const isSelected = currentQuestionResult?.selectedOptions.some(\n (selectedOption) => selectedOption.optionId === option.id\n );\n\n // Only show correct/incorrect status if answer is not pending evaluation\n const shouldShowCorrectAnswers =\n currentQuestionResult?.answerStatus !==\n ANSWER_STATUS.PENDENTE_AVALIACAO &&\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n }\n\n return {\n label: option.option,\n value: option.id,\n status: status,\n };\n });\n\n if (!alternatives)\n return (\n <div>\n <p>Não há Alternativas</p>\n </div>\n );\n\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"space-y-4\">\n <AlternativesList\n mode={variant === QuizVariant.DEFAULT ? 'interactive' : 'readonly'}\n key={`question-${currentQuestion?.id || '1'}`}\n name={`question-${currentQuestion?.id || '1'}`}\n layout=\"compact\"\n alternatives={alternatives}\n value={\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.selectedOptions[0]?.optionId || ''\n : currentAnswer?.optionId || ''\n }\n selectedValue={\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.selectedOptions[0]?.optionId || ''\n : currentAnswer?.optionId || ''\n }\n onValueChange={(value) => {\n if (currentQuestion) {\n selectAnswer(currentQuestion.id, value);\n }\n }}\n />\n </div>\n </QuizContainer>\n </>\n );\n};\n\nconst QuizMultipleChoice = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n selectMultipleAnswer,\n getAllCurrentAnswer,\n getQuestionResultByQuestionId,\n variant,\n } = useQuizStore();\n const currentQuestion = getCurrentQuestion();\n const allCurrentAnswers = getAllCurrentAnswer();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n // Use ref to track previous values and prevent unnecessary updates\n const prevSelectedValuesRef = useRef<string[]>([]);\n const prevQuestionIdRef = useRef<string>('');\n\n // Memoize the answer IDs to prevent unnecessary re-renders\n // For MULTIPLA_ESCOLHA, we now have a single answer entry with selectedOptionIds array\n const allCurrentAnswerIds = useMemo(() => {\n if (allCurrentAnswers && allCurrentAnswers.length > 0) {\n // Prefer any row already using the new format\n const answerWithSelectedOptionIds = allCurrentAnswers.find((answer) =>\n Array.isArray(answer.selectedOptionIds)\n );\n if (answerWithSelectedOptionIds) {\n return answerWithSelectedOptionIds.selectedOptionIds ?? [];\n }\n // Fallback to old format (multiple entries with optionId)\n return allCurrentAnswers.map((answer) => answer.optionId);\n }\n return [];\n }, [allCurrentAnswers]);\n\n // Memoize the selected values to prevent infinite loops\n const selectedValues = useMemo(() => {\n return allCurrentAnswerIds?.filter((id): id is string => id !== null) || [];\n }, [allCurrentAnswerIds]);\n\n // Only update selectedValues if they actually changed or question changed\n const stableSelectedValues = useMemo(() => {\n // In result mode, always use selectedOptions from the question result\n if (variant === QuizVariant.RESULT) {\n return (\n currentQuestionResult?.selectedOptions?.map((op) => op.optionId) || []\n );\n }\n\n const currentQuestionId = currentQuestion?.id || '';\n const hasQuestionChanged = prevQuestionIdRef.current !== currentQuestionId;\n\n if (hasQuestionChanged) {\n prevQuestionIdRef.current = currentQuestionId;\n prevSelectedValuesRef.current = selectedValues;\n return selectedValues;\n }\n\n // Only update if values actually changed\n const hasValuesChanged =\n JSON.stringify(prevSelectedValuesRef.current) !==\n JSON.stringify(selectedValues);\n if (hasValuesChanged) {\n prevSelectedValuesRef.current = selectedValues;\n return selectedValues;\n }\n\n return prevSelectedValuesRef.current;\n }, [\n selectedValues,\n currentQuestion?.id,\n variant,\n currentQuestionResult?.selectedOptions,\n ]);\n\n // Memoize the callback to prevent unnecessary re-renders\n const handleSelectedValues = useCallback(\n (values: string[]) => {\n if (currentQuestion) {\n selectMultipleAnswer(currentQuestion.id, values);\n }\n },\n [currentQuestion, selectMultipleAnswer]\n );\n\n // Create a stable key to force re-mount when question changes\n const questionKey = useMemo(\n () => `question-${currentQuestion?.id || '1'}`,\n [currentQuestion?.id]\n );\n const choices = currentQuestion?.options?.map((option) => {\n let status: OptionStatus = OptionStatus.NEUTRAL;\n\n if (variant === QuizVariant.RESULT) {\n const isCorrectOption =\n currentQuestionResult?.options?.find((op) => op.id === option.id)\n ?.isCorrect || false;\n\n const isSelected = currentQuestionResult?.selectedOptions?.some(\n (op) => op.optionId === option.id\n );\n\n // Only show correct/incorrect status if answer is not pending evaluation\n const shouldShowCorrectAnswers =\n currentQuestionResult?.answerStatus !==\n ANSWER_STATUS.PENDENTE_AVALIACAO &&\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n }\n\n return {\n label: option.option,\n value: option.id,\n status: status,\n };\n });\n\n if (!choices)\n return (\n <div>\n <p>Não há Escolhas Multiplas</p>\n </div>\n );\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"space-y-4\">\n <MultipleChoiceList\n choices={choices}\n key={questionKey}\n name={questionKey}\n selectedValues={stableSelectedValues}\n onHandleSelectedValues={handleSelectedValues}\n mode={variant === QuizVariant.DEFAULT ? 'interactive' : 'readonly'}\n />\n </div>\n </QuizContainer>\n </>\n );\n};\n\nconst QuizDissertative = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n variant,\n getDissertativeCharLimit,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n const currentAnswer = getCurrentAnswer();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const charLimit = getDissertativeCharLimit();\n\n const handleAnswerChange = (value: string) => {\n if (currentQuestion) {\n selectDissertativeAnswer(currentQuestion.id, value);\n }\n };\n\n // Auto-resize function\n const adjustTextareaHeight = useCallback(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n const scrollHeight = textareaRef.current.scrollHeight;\n const minHeight = 120; // 120px minimum height\n const maxHeight = 400; // 400px maximum height\n const newHeight = Math.min(Math.max(scrollHeight, minHeight), maxHeight);\n textareaRef.current.style.height = `${newHeight}px`;\n }\n }, []);\n\n // Adjust height when currentAnswer changes\n useEffect(() => {\n adjustTextareaHeight();\n }, [currentAnswer, adjustTextareaHeight]);\n\n if (!currentQuestion) {\n return (\n <div className=\"space-y-4\">\n <p className=\"text-text-600 text-md\">Nenhuma questão disponível</p>\n </div>\n );\n }\n\n const localAnswer =\n (variant == 'result'\n ? currentQuestionResult?.answer\n : currentAnswer?.answer) || '';\n return (\n <>\n <QuizSubTitle subTitle=\"Resposta\" />\n\n <QuizContainer className={cn(variant != 'result' && paddingBottom)}>\n <div className=\"space-y-4 max-h-[600px] overflow-y-auto\">\n {variant === QuizVariant.DEFAULT ? (\n <div className=\"space-y-4\">\n <TextArea\n ref={textareaRef}\n placeholder=\"Escreva sua resposta\"\n value={localAnswer}\n onChange={(e) => handleAnswerChange(e.target.value)}\n rows={4}\n className=\"min-h-[120px] max-h-[400px] resize-none overflow-y-auto\"\n maxLength={charLimit}\n showCharacterCount={!!charLimit}\n />\n </div>\n ) : (\n <div className=\"space-y-4\">\n <p className=\"text-text-600 text-md whitespace-pre-wrap\">\n {localAnswer || 'Nenhuma resposta fornecida'}\n </p>\n </div>\n )}\n </div>\n </QuizContainer>\n\n {variant === QuizVariant.RESULT &&\n currentQuestionResult?.teacherFeedback && (\n <>\n <QuizSubTitle subTitle=\"Observação do professor\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <p className=\"text-text-600 text-md whitespace-pre-wrap\">\n {currentQuestionResult?.teacherFeedback}\n </p>\n </QuizContainer>\n </>\n )}\n </>\n );\n};\n\nconst QuizTrueOrFalse = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n variant,\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n getUserAnswerByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentAnswer = getCurrentAnswer();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n // Get the options - prefer persisted result options in result mode, fallback to live question\n const options = useMemo(() => {\n if (variant === QuizVariant.RESULT && currentQuestionResult?.options) {\n return currentQuestionResult.options;\n }\n return currentQuestion?.options || [];\n }, [variant, currentQuestionResult?.options, currentQuestion?.options]);\n\n // Parse stored answers from JSON string, handling both object and legacy array formats\n const parsedAnswers: Record<string, string> = useMemo(() => {\n return parseStoredAnswers(\n variant,\n currentQuestionResult?.answer,\n currentAnswer?.answer\n );\n }, [variant, currentQuestionResult?.answer, currentAnswer?.answer]);\n\n // Local state to track answers: { \"optionId\": \"V\" | \"F\" }\n const [localAnswers, setLocalAnswers] =\n useState<Record<string, string>>(parsedAnswers);\n\n // Sync local answers when question changes or parsed answers update\n useEffect(() => {\n setLocalAnswers(parsedAnswers);\n }, [parsedAnswers, currentQuestion?.id]);\n\n // Handle select change for an option\n const handleSelectChange = (optionId: string, value: string) => {\n if (!currentQuestion) return;\n\n // Get the LATEST answers directly from the store (not from closure)\n // This is critical to avoid stale closure issues when user selects options quickly\n const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n let baseAnswers: Record<string, string> = {};\n if (latestStoreAnswer?.answer) {\n try {\n const parsed = JSON.parse(latestStoreAnswer.answer);\n baseAnswers = normalizeAnswerData(parsed);\n } catch {\n // Invalid JSON, start fresh\n }\n }\n\n // Merge: store answers + local state + new selection\n const mergedAnswers = {\n ...baseAnswers,\n ...localAnswers,\n [optionId]: value,\n };\n setLocalAnswers(mergedAnswers);\n\n // Save to store as JSON string\n selectDissertativeAnswer(currentQuestion.id, JSON.stringify(mergedAnswers));\n };\n\n // Get the current selection for an option\n const getOptionSelection = (optionId: string): string | undefined => {\n return localAnswers[optionId];\n };\n\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n const isDefaultVariant = variant === QuizVariant.DEFAULT;\n\n // Check if we should show correct/incorrect status\n const shouldShowStatus =\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n if (options.length === 0) {\n return (\n <QuizContainer className={cn('', paddingBottom)}>\n <Text size=\"sm\" className=\"text-text-500 italic\">\n Nenhuma opção disponível para esta questão\n </Text>\n </QuizContainer>\n );\n }\n\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"flex flex-col gap-3.5\">\n {options.map((option, index) => {\n // Use helper to compute all option state\n const {\n hasAnswered,\n studentAnswer,\n correctAnswer,\n isStudentCorrect,\n variantCorrect,\n } = getTrueOrFalseOptionState(\n option.id,\n variant,\n currentQuestionResult,\n localAnswers\n );\n\n const contentWithLetter = prependLetterToHtml(\n getLetterByIndex(index),\n option.option\n );\n\n return (\n <section\n key={option.id || `option-${index}`}\n className=\"flex flex-col gap-2\"\n >\n <div\n className={cn(\n 'w-full grid grid-cols-[1fr_auto] items-start gap-4 p-2 rounded-md border',\n !isDefaultVariant && shouldShowStatus && hasAnswered\n ? getStatusStyles(variantCorrect)\n : 'border-transparent'\n )}\n >\n <HtmlMathRenderer\n content={contentWithLetter}\n className=\"text-text-900 text-sm\"\n />\n\n {isDefaultVariant ? (\n <Select\n size=\"medium\"\n value={getOptionSelection(option.id)}\n onValueChange={(value) =>\n handleSelectChange(option.id, value)\n }\n >\n <SelectTrigger className=\"w-[120px]\">\n <SelectValue placeholder=\"Selecione\" />\n </SelectTrigger>\n\n <SelectContent>\n <SelectItem value={TrueFalseEnum.VERDADEIRO}>\n Verdadeiro\n </SelectItem>\n <SelectItem value={TrueFalseEnum.FALSO}>\n Falso\n </SelectItem>\n </SelectContent>\n </Select>\n ) : (\n shouldShowStatus &&\n hasAnswered && <div>{getStatusBadge(variantCorrect)}</div>\n )}\n </div>\n\n {!isDefaultVariant && shouldShowStatus && (\n <span className=\"flex flex-row gap-2 items-center flex-wrap\">\n {hasAnswered ? (\n <>\n <Text size=\"2xs\" className=\"text-text-800\">\n Resposta selecionada: {studentAnswer}\n </Text>\n {!isStudentCorrect && (\n <Text size=\"2xs\" className=\"text-text-800\">\n | Resposta correta: {correctAnswer}\n </Text>\n )}\n </>\n ) : (\n <Text size=\"2xs\" className=\"text-text-800\">\n Não respondida | Resposta correta: {correctAnswer}\n </Text>\n )}\n </span>\n )}\n </section>\n );\n })}\n </div>\n </QuizContainer>\n </>\n );\n};\n\ninterface UserAnswer {\n option: string;\n dotOption: string | null;\n correctOption: string;\n isCorrect: boolean | null;\n}\n\nconst QuizConnectDots = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n variant,\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n getUserAnswerByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n const currentAnswer = getCurrentAnswer();\n\n // Extract options from the current question\n // Each option has: id, option (left column), correctValue (right column)\n const questionOptions = useMemo(() => {\n if (!currentQuestion?.options) return [];\n return currentQuestion.options;\n }, [currentQuestion?.options]);\n\n // Build dotsOptions from correctValue of each option (right column values)\n // Shuffle them so they don't appear in the same order as the left column\n const dotsOptions = useMemo(() => {\n const dots = questionOptions\n .map((opt) => ({ label: opt.correctValue || '' }))\n .filter((opt) => opt.label !== '');\n // Use question ID as seed for consistent shuffle\n return shuffleWithSeed(dots, currentQuestion?.id || '');\n }, [questionOptions, currentQuestion?.id]);\n\n // Build options for display (left column with correct answer mapping)\n const options = useMemo(() => {\n return questionOptions.map((opt) => ({\n id: opt.id,\n label: opt.option,\n correctOption: opt.correctValue || '',\n }));\n }, [questionOptions]);\n\n // Parse stored matching answers\n // In result mode, read from matchingAnswers array, fallback to answer JSON\n // In default mode, read from currentAnswer.answer JSON string\n const parsedAnswers: Record<string, string> = useMemo(() => {\n if (\n variant === QuizVariant.RESULT &&\n currentQuestionResult?.matchingAnswers\n ) {\n // Convert matchingAnswers array to Record<optionId, selectedValue>\n const answers: Record<string, string> = {};\n for (const match of currentQuestionResult.matchingAnswers) {\n answers[match.optionId] = match.selectedValue;\n }\n return answers;\n }\n // Fallback to answer JSON string (for older/partially migrated submissions)\n return parseStoredAnswers(\n variant,\n currentQuestionResult?.answer,\n currentAnswer?.answer\n );\n }, [\n variant,\n currentQuestionResult?.matchingAnswers,\n currentQuestionResult?.answer,\n currentAnswer?.answer,\n ]);\n\n const [userAnswers, setUserAnswers] = useState<UserAnswer[]>([]);\n\n // Initialize userAnswers from options and stored answers\n useEffect(() => {\n if (options.length > 0) {\n setUserAnswers(\n options.map((option) => {\n const storedValue = parsedAnswers[option.id] || null;\n return {\n option: option.label,\n dotOption: storedValue,\n correctOption: option.correctOption,\n isCorrect: storedValue\n ? storedValue === option.correctOption\n : null,\n };\n })\n );\n }\n }, [options, parsedAnswers]);\n\n const handleSelectDot = (optionIndex: number, dotValue: string) => {\n const option = options[optionIndex];\n if (!option || !currentQuestion) return;\n\n // Update local state\n setUserAnswers((prev) => {\n const next = [...prev];\n next[optionIndex] = {\n option: option.label,\n dotOption: dotValue,\n correctOption: option.correctOption,\n isCorrect: dotValue ? dotValue === option.correctOption : null,\n };\n return next;\n });\n\n // Get the LATEST answers directly from the store (not from closure)\n const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n let baseAnswers: Record<string, string> = {};\n if (latestStoreAnswer?.answer) {\n try {\n const parsed = JSON.parse(latestStoreAnswer.answer);\n baseAnswers = normalizeAnswerData(parsed);\n } catch {\n // Invalid JSON, start fresh\n }\n }\n\n // Persist to shared store as JSON\n const newAnswers = {\n ...baseAnswers,\n ...parsedAnswers,\n [option.id]: dotValue,\n };\n selectDissertativeAnswer(currentQuestion.id, JSON.stringify(newAnswers));\n };\n\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 'a', 'b', 'c'...\n\n const isDefaultVariant = variant === QuizVariant.DEFAULT;\n const assignedDots = new Set(\n userAnswers.map((a) => a.dotOption).filter(Boolean)\n );\n\n if (options.length === 0) {\n return (\n <QuizContainer className={cn('', paddingBottom)}>\n <Text size=\"sm\" className=\"text-text-500 italic\">\n Nenhuma opção de relacionamento disponível\n </Text>\n </QuizContainer>\n );\n }\n\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"flex flex-col gap-3.5\">\n {options.map((option, index) => {\n const answer = userAnswers[index] || {\n option: option.label,\n dotOption: null,\n correctOption: option.correctOption,\n isCorrect: null,\n };\n const variantCorrect = getAnswerStatus(answer.isCorrect);\n return (\n <section key={option.id} className=\"flex flex-col gap-2\">\n <div\n className={cn(\n 'grid grid-cols-[1fr_auto] items-center gap-4 p-2 rounded-md',\n !isDefaultVariant && variantCorrect\n ? getStatusStyles(variantCorrect)\n : ''\n )}\n >\n <Text size=\"sm\" className=\"text-text-900\">\n {getLetterByIndex(index) + ') ' + option.label}\n </Text>\n\n {isDefaultVariant ? (\n <Select\n size=\"medium\"\n value={answer.dotOption || undefined}\n onValueChange={(value) => handleSelectDot(index, value)}\n >\n <SelectTrigger\n className=\"w-[180px] overflow-hidden truncate\"\n title={answer.dotOption || undefined}\n >\n <SelectValue placeholder=\"Selecione opção\" />\n </SelectTrigger>\n\n <SelectContent>\n {dotsOptions\n .filter(\n (dot) =>\n !assignedDots.has(dot.label) ||\n answer.dotOption === dot.label\n )\n .map((dot) => (\n <SelectItem\n key={dot.label}\n value={dot.label}\n title={dot.label}\n truncate\n >\n {dot.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <div>\n {answer.isCorrect === null\n ? null\n : getStatusBadge(variantCorrect)}\n </div>\n )}\n </div>\n\n {!isDefaultVariant && (\n <span className=\"flex flex-row gap-2 items-center\">\n <Text size=\"2xs\" className=\"text-text-800\">\n Resposta selecionada: {answer.dotOption || 'Nenhuma'}\n </Text>\n {answer.isCorrect === false && (\n <Text size=\"2xs\" className=\"text-text-800\">\n Resposta correta: {answer.correctOption}\n </Text>\n )}\n </span>\n )}\n </section>\n );\n })}\n </div>\n </QuizContainer>\n </>\n );\n};\n\nconst QuizFill = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n getQuestionResultByQuestionId,\n getCurrentAnswer,\n selectDissertativeAnswer,\n variant,\n getUserAnswerByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n const currentAnswer = getCurrentAnswer();\n\n const baseId = useId();\n\n // Get the additionalContent from the question (contains text with {optionId} placeholders)\n // In result mode, prefer the persisted snapshot to match parsedAnswers\n const additionalContent =\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.additionalContent ||\n currentQuestion?.additionalContent ||\n ''\n : currentQuestion?.additionalContent || '';\n\n // Get the options from the question\n // In result mode, prefer the persisted snapshot to match parsedAnswers\n const questionOptions =\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.options || currentQuestion?.options || []\n : currentQuestion?.options || [];\n\n // Shuffled options for dropdown display (consistent per question)\n const shuffledOptions = useMemo(() => {\n return shuffleWithSeed(questionOptions, currentQuestion?.id || '');\n }, [questionOptions, currentQuestion?.id]);\n\n // Parse current answers\n // In result mode, read from fillAnswers object, fallback to answer JSON\n // In default mode, read from currentAnswer.answer JSON string\n const parsedAnswers: Record<string, string> = useMemo(() => {\n if (variant === QuizVariant.RESULT && currentQuestionResult?.fillAnswers) {\n // fillAnswers is already a Record<placeholderId, selectedOptionId>\n return currentQuestionResult.fillAnswers;\n }\n // Fallback to answer JSON string (for older/partially migrated submissions)\n return parseStoredAnswers(\n variant,\n currentQuestionResult?.answer,\n currentAnswer?.answer\n );\n }, [\n variant,\n currentQuestionResult?.fillAnswers,\n currentQuestionResult?.answer,\n currentAnswer?.answer,\n ]);\n\n const [localAnswers, setLocalAnswers] =\n useState<Record<string, string>>(parsedAnswers);\n\n // Sync local answers when question changes\n useEffect(() => {\n setLocalAnswers(parsedAnswers);\n }, [parsedAnswers, currentQuestion?.id]);\n\n // Handle select change\n const handleSelectChange = (placeholderId: string, optionId: string) => {\n if (!currentQuestion) return;\n\n // Get the LATEST answers directly from the store (not from closure)\n const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n let baseAnswers: Record<string, string> = {};\n if (latestStoreAnswer?.answer) {\n try {\n const parsed = JSON.parse(latestStoreAnswer.answer);\n baseAnswers = normalizeAnswerData(parsed);\n } catch {\n // Invalid JSON, start fresh\n }\n }\n\n const newAnswers = {\n ...baseAnswers,\n ...localAnswers,\n [placeholderId]: optionId,\n };\n setLocalAnswers(newAnswers);\n\n // Save to store as JSON string\n selectDissertativeAnswer(currentQuestion.id, JSON.stringify(newAnswers));\n };\n\n // Get option text by ID\n const getOptionTextById = (optionId: string): string => {\n const option = questionOptions.find((opt) => opt.id === optionId);\n return option?.option || '';\n };\n\n // Check if an answer is correct (for result mode)\n const isAnswerCorrect = (placeholderId: string): boolean => {\n const selectedOptionId = localAnswers[placeholderId];\n // The placeholder ID is the correct option ID\n return selectedOptionId === placeholderId;\n };\n\n // Render the select for default mode\n const renderDefaultSelect = (placeholderId: string) => {\n const selectedOptionId = localAnswers[placeholderId];\n\n return (\n <span\n key={placeholderId}\n className=\"inline-block align-middle mx-1 my-2\"\n style={{ display: 'inline-block', verticalAlign: 'middle' }}\n >\n <Select\n value={selectedOptionId || undefined}\n onValueChange={(value) => handleSelectChange(placeholderId, value)}\n >\n <SelectTrigger\n className=\"w-auto min-w-[120px] max-w-[200px] h-7 px-2 bg-background border-gray-300 overflow-hidden truncate\"\n title={\n shuffledOptions.find((o) => o.id === selectedOptionId)?.option\n }\n >\n <SelectValue placeholder=\"Selecione opção\" />\n </SelectTrigger>\n <SelectContent>\n {shuffledOptions.map((option) => (\n <SelectItem\n key={option.id}\n value={option.id}\n title={option.option}\n truncate\n >\n {option.option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n );\n };\n\n // Render the result badge\n const renderResultBadge = (placeholderId: string) => {\n const selectedOptionId = localAnswers[placeholderId];\n const selectedOptionText = getOptionTextById(selectedOptionId);\n const isCorrect = isAnswerCorrect(placeholderId);\n\n if (!selectedOptionId) {\n return (\n <span\n key={placeholderId}\n className=\"inline-block align-middle mx-1 my-2\"\n style={{ display: 'inline-block', verticalAlign: 'middle' }}\n >\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n </span>\n );\n }\n\n return (\n <span\n key={placeholderId}\n className=\"inline-block align-middle mx-1 my-2\"\n style={{ display: 'inline-block', verticalAlign: 'middle' }}\n >\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n <span className=\"text-text-900\">{selectedOptionText}</span>\n </Badge>\n </span>\n );\n };\n\n // Render the correct answer for resolution\n const renderResolutionAnswer = (placeholderId: string) => {\n // The placeholderId IS the correct option ID\n const correctOptionText = getOptionTextById(placeholderId);\n\n return (\n <span className=\"inline mx-1 text-success-600 font-semibold border-b-2 border-success-600\">\n {correctOptionText}\n </span>\n );\n };\n\n // Parse text and render with selects\n const renderTextWithSelects = (text: string, isResolution?: boolean) => {\n const elements: Array<{ element: string | ReactNode; id: string }> = [];\n let lastIndex = 0;\n const nextId = () => elements.length;\n\n // Match {uuid} placeholders (UUID format or any alphanumeric with hyphens)\n const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n let match;\n\n while ((match = regex.exec(text)) !== null) {\n const [fullMatch, placeholderId] = match;\n const startIndex = match.index;\n\n // Add text before the placeholder\n if (startIndex > lastIndex) {\n elements.push({\n element: text.slice(lastIndex, startIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n // Add the appropriate element based on variant and mode\n if (isResolution) {\n elements.push({\n element: renderResolutionAnswer(placeholderId),\n id: `${baseId}-resolution-${nextId()}`,\n });\n } else if (variant === QuizVariant.DEFAULT) {\n elements.push({\n element: renderDefaultSelect(placeholderId),\n id: `${baseId}-select-${nextId()}`,\n });\n } else {\n elements.push({\n element: renderResultBadge(placeholderId),\n id: `${baseId}-result-${nextId()}`,\n });\n }\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Add remaining text\n if (lastIndex < text.length) {\n elements.push({\n element: text.slice(lastIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n return elements;\n };\n\n // Render HTML content with selects replacing placeholders\n const renderHtmlWithSelects = (\n htmlContent: string,\n isResolution?: boolean\n ) => {\n // For now, we'll strip HTML and render plain text with selects\n // This preserves the placeholder functionality while handling HTML content\n const textContent = stripHtmlTags(htmlContent);\n return renderTextWithSelects(textContent, isResolution);\n };\n\n if (!currentQuestion || !additionalContent) {\n return (\n <>\n <QuizSubTitle subTitle=\"Preenchimento\" />\n <QuizContainer className=\"h-auto pb-0\">\n <div className=\"space-y-6 px-4 h-auto\">\n <Text\n size=\"md\"\n color=\"text-text-600\"\n weight=\"normal\"\n className={cn(paddingBottom)}\n >\n Nenhum conteúdo disponível para esta questão.\n </Text>\n </div>\n </QuizContainer>\n </>\n );\n }\n\n return (\n <>\n <QuizSubTitle subTitle=\"Preencha as lacunas\" />\n\n <QuizContainer\n className={cn('', variant !== QuizVariant.RESULT && paddingBottom)}\n >\n <div className=\"px-4\">\n <Text\n as=\"div\"\n size=\"lg\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderHtmlWithSelects(additionalContent).map((element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n ))}\n </Text>\n </div>\n </QuizContainer>\n\n {variant === QuizVariant.RESULT && (\n <>\n <QuizSubTitle subTitle=\"Resposta correta\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"px-4\">\n <Text\n as=\"div\"\n size=\"lg\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderHtmlWithSelects(additionalContent, true).map(\n (element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n )\n )}\n </Text>\n </div>\n </QuizContainer>\n </>\n )}\n </>\n );\n};\n\nconst QuizImageQuestion = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n variant,\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentAnswer = getCurrentAnswer();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n // Get image URL from additionalContent\n const imageUrl = currentQuestion?.additionalContent || '';\n\n // Parse correct coordinates from first option (stored as JSON: {\"x\": number, \"y\": number})\n const correctPositionRelative = useMemo(() => {\n if (!currentQuestion?.options || currentQuestion.options.length === 0) {\n return { x: 0.5, y: 0.5 }; // Default center\n }\n try {\n const coords = JSON.parse(currentQuestion.options[0].option);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n // Coordinates are stored as percentages (0-100), convert to relative (0-1)\n return { x: coords.x / 100, y: coords.y / 100 };\n }\n } catch {\n // Fall back to default\n }\n return { x: 0.5, y: 0.5 };\n }, [currentQuestion?.options]);\n\n // Calculate correctRadiusRelative automatically based on the circle dimensions\n const calculateCorrectRadiusRelative = (): number => {\n // The correct answer circle has width: 15% and height: 30%\n // We'll use the average of these as the radius\n const circleWidthRelative = 0.15; // 15%\n const circleHeightRelative = 0.3; // 30%\n\n // Calculate the average radius (half of the average of width and height)\n const averageRadius = (circleWidthRelative + circleHeightRelative) / 4;\n\n // Add a small tolerance for better user experience\n const tolerance = 0.02; // 2% tolerance\n\n return averageRadius + tolerance;\n };\n\n const correctRadiusRelative = calculateCorrectRadiusRelative();\n\n // Parse user's answer from stored JSON or result\n const storedUserAnswer = useMemo(() => {\n if (variant === QuizVariant.RESULT && currentQuestionResult?.answer) {\n try {\n const coords = JSON.parse(currentQuestionResult.answer);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n return { x: coords.x / 100, y: coords.y / 100 };\n }\n } catch {\n // Fall back to null\n }\n } else if (currentAnswer?.answer) {\n try {\n const coords = JSON.parse(currentAnswer.answer);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n return { x: coords.x / 100, y: coords.y / 100 };\n }\n } catch {\n // Fall back to null\n }\n }\n return null;\n }, [variant, currentQuestionResult?.answer, currentAnswer?.answer]);\n\n const [clickPositionRelative, setClickPositionRelative] = useState<{\n x: number;\n y: number;\n } | null>(storedUserAnswer);\n\n // Sync with stored answer when it changes\n useEffect(() => {\n setClickPositionRelative(storedUserAnswer);\n }, [storedUserAnswer]);\n\n // Helper function to safely convert click coordinates to relative coordinates\n const convertToRelativeCoordinates = (\n x: number,\n y: number,\n rect: DOMRect\n ): { x: number; y: number } => {\n // Guard against division by zero or extremely small dimensions\n const safeWidth = Math.max(rect.width, 0.001);\n const safeHeight = Math.max(rect.height, 0.001);\n\n // Convert to relative coordinates and clamp to [0, 1] range\n const xRelative = Math.max(0, Math.min(1, x / safeWidth));\n const yRelative = Math.max(0, Math.min(1, y / safeHeight));\n\n return { x: xRelative, y: yRelative };\n };\n\n const handleImageClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (variant === QuizVariant.RESULT) return;\n\n const rect = event.currentTarget.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n\n // Use helper function for safe conversion\n const positionRelative = convertToRelativeCoordinates(x, y, rect);\n setClickPositionRelative(positionRelative);\n\n // Save the answer to the store (as percentages 0-100)\n if (currentQuestion) {\n const answerJson = JSON.stringify({\n x: Math.round(positionRelative.x * 100),\n y: Math.round(positionRelative.y * 100),\n });\n selectDissertativeAnswer(currentQuestion.id, answerJson);\n }\n };\n\n const handleKeyboardActivate = () => {\n if (variant === QuizVariant.RESULT) return;\n // Choose a deterministic position for keyboard activation; center is a reasonable default\n const centerPosition = { x: 0.5, y: 0.5 };\n setClickPositionRelative(centerPosition);\n\n // Save the answer to the store (as percentages 0-100)\n if (currentQuestion) {\n const answerJson = JSON.stringify({\n x: Math.round(centerPosition.x * 100),\n y: Math.round(centerPosition.y * 100),\n });\n selectDissertativeAnswer(currentQuestion.id, answerJson);\n }\n };\n\n const isCorrect = () => {\n if (!clickPositionRelative) return false;\n\n const distance = Math.sqrt(\n Math.pow(clickPositionRelative.x - correctPositionRelative.x, 2) +\n Math.pow(clickPositionRelative.y - correctPositionRelative.y, 2)\n );\n\n return distance <= correctRadiusRelative;\n };\n\n const getUserCircleColorClasses = () => {\n if (variant === QuizVariant.DEFAULT) {\n return 'bg-indicator-primary/70 border-[#F8CC2E]';\n }\n\n if (variant === QuizVariant.RESULT) {\n return isCorrect()\n ? 'bg-success-600/70 border-white' // Green for correct answer\n : 'bg-indicator-error/70 border-white'; // Red for incorrect answer\n }\n\n return 'bg-success-600/70 border-white';\n };\n\n return (\n <>\n <QuizSubTitle subTitle=\"Clique na área correta\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div\n data-testid=\"quiz-image-container\"\n className=\"space-y-6 p-3 relative inline-block\"\n >\n {variant == 'result' && (\n <div\n data-testid=\"quiz-legend\"\n className=\"flex items-center gap-4 text-xs\"\n >\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-primary/70 border border-[#F8CC2E]\"></div>\n <span className=\"text-text-600 font-medium text-sm\">\n Área correta\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-success-600/70 border border-white\"></div>\n <span className=\"text-text-600 font-medium text-sm\">\n Resposta correta\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-error/70 border border-white\"></div>\n <span className=\"text-text-600 font-medium text-sm\">\n Resposta incorreta\n </span>\n </div>\n </div>\n )}\n\n <button\n data-testid=\"quiz-image-button\"\n type=\"button\"\n className=\"relative cursor-pointer w-full h-full border-0 bg-transparent p-0\"\n onClick={handleImageClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleKeyboardActivate();\n }\n }}\n aria-label=\"Área da imagem interativa\"\n >\n <img\n data-testid=\"quiz-image\"\n src={imageUrl || ImageQuestion}\n alt=\"Question\"\n className=\"w-full h-auto rounded-md\"\n />\n\n {/* Correct answer circle - only show in result variant */}\n {variant === QuizVariant.RESULT && (\n <div\n data-testid=\"quiz-correct-circle\"\n className=\"absolute rounded-full bg-indicator-primary/70 border-4 border-[#F8CC2E] pointer-events-none\"\n style={{\n minWidth: '50px',\n maxWidth: '160px',\n width: '15%',\n aspectRatio: '1 / 1',\n left: `calc(${correctPositionRelative.x * 100}% - 7.5%)`,\n top: `calc(${correctPositionRelative.y * 100}% - 15%)`,\n }}\n />\n )}\n\n {/* User's answer circle */}\n {clickPositionRelative && (\n <div\n data-testid=\"quiz-user-circle\"\n className={`absolute rounded-full border-4 pointer-events-none ${getUserCircleColorClasses()}`}\n style={{\n minWidth: '30px',\n maxWidth: '52px',\n width: '5%',\n aspectRatio: '1 / 1',\n left: `calc(${clickPositionRelative.x * 100}% - 2.5%)`,\n top: `calc(${clickPositionRelative.y * 100}% - 2.5%)`,\n }}\n />\n )}\n </button>\n </div>\n </QuizContainer>\n </>\n );\n};\n\nexport {\n QuizSubTitle,\n QuizContainer,\n QuizMultipleChoice,\n QuizDissertative,\n QuizTrueOrFalse,\n QuizConnectDots,\n QuizFill,\n QuizImageQuestion,\n QuizAlternative,\n};\n","import {\n QuizVariant,\n type QuestionAnswerResult,\n type TrueOrFalseOptionState,\n} from './Quiz.types';\nimport { TrueFalseEnum } from '../../enums/Quiz';\nimport { OptionStatus } from '../../enums/Options';\n\n/**\n * Helper function to format exam info (bank - year)\n * @param examBoard - The exam board/bank name\n * @param examYear - The exam year\n * @returns Formatted string like \"(ENEM - 2023)\" or empty string if no info\n */\nexport const formatExamInfo = (\n examBoard: string | null | undefined,\n examYear: string | null | undefined\n): string => {\n if (examBoard && examYear) {\n return `(${examBoard} - ${examYear})`;\n }\n if (examBoard) {\n return `(${examBoard})`;\n }\n if (examYear) {\n return `(${examYear})`;\n }\n return '';\n};\n\n/**\n * Shuffle array using a seed for consistent ordering per question\n * Uses Fisher-Yates shuffle with seeded random for deterministic results\n */\nexport const shuffleWithSeed = <T>(array: T[], seed: string): T[] => {\n const shuffled = [...array];\n // Simple hash function to convert string seed to number\n let hash = 0;\n for (let i = 0; i < seed.length; i++) {\n const char = seed.codePointAt(i) ?? 0;\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n // Fisher-Yates shuffle with seeded random\n const seededRandom = (max: number) => {\n hash = (hash * 1103515245 + 12345) & 0x7fffffff;\n return hash % max;\n };\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = seededRandom(i + 1);\n [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n }\n return shuffled;\n};\n\n/**\n * Helper to prepend letter to HTML content (handles <p> tags)\n * @example prependLetterToHtml('a', '<p>Text</p>') => '<p>a) Text</p>'\n * @example prependLetterToHtml('a', 'Text') => 'a) Text'\n */\nexport const prependLetterToHtml = (letter: string, html: string): string => {\n if (html.trim().startsWith('<p>')) {\n return html.replace(/^(\\s*<p>)/, `$1${letter}) `);\n }\n return `${letter}) ${html}`;\n};\n\n/**\n * Compute state for a true/false option\n * Handles both interactive (default) and result modes\n */\nexport const getTrueOrFalseOptionState = (\n optionId: string,\n variant: string,\n currentQuestionResult: QuestionAnswerResult | null | undefined,\n localAnswers: Record<string, string>\n): TrueOrFalseOptionState => {\n // Get whether the statement is TRUE or FALSE from persisted result\n const correctAnswerOption = currentQuestionResult?.options?.find(\n (op) => op.id === optionId\n );\n const isStatementTrue =\n variant === QuizVariant.RESULT\n ? (correctAnswerOption?.isCorrect ?? false)\n : false;\n\n // Get student's selection from selectedOptions\n const studentSelection =\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.selectedOptions?.find(\n (op) => op.optionId === optionId\n )\n : undefined;\n\n // Determine if answered and what was marked\n const hasAnswered =\n variant === QuizVariant.RESULT\n ? studentSelection !== undefined\n : !!localAnswers[optionId];\n\n const studentMarkedTrue =\n variant === QuizVariant.RESULT\n ? (studentSelection?.isCorrect ?? false)\n : localAnswers[optionId] === TrueFalseEnum.VERDADEIRO;\n\n // Compute display values\n const getStudentAnswerDisplay = (): string => {\n if (variant !== QuizVariant.RESULT) {\n return localAnswers[optionId] || '-';\n }\n if (!hasAnswered) {\n return '-';\n }\n return studentMarkedTrue ? TrueFalseEnum.VERDADEIRO : TrueFalseEnum.FALSO;\n };\n const studentAnswer = getStudentAnswerDisplay();\n\n const correctAnswer = isStatementTrue\n ? TrueFalseEnum.VERDADEIRO\n : TrueFalseEnum.FALSO;\n const isStudentCorrect = hasAnswered && studentMarkedTrue === isStatementTrue;\n const variantCorrect = isStudentCorrect\n ? OptionStatus.CORRECT\n : OptionStatus.INCORRECT;\n\n return {\n isStatementTrue,\n hasAnswered,\n studentMarkedTrue,\n studentAnswer,\n correctAnswer,\n isStudentCorrect,\n variantCorrect,\n };\n};\n","/**\n * Strip HTML tags from a string\n * SSR-safe: uses DOMParser in browser, iterative fallback on server\n *\n * @param html - String that may contain HTML tags\n * @returns String with HTML tags removed\n *\n * @example\n * stripHtmlTags('<p>Hello <strong>World</strong></p>') // 'Hello World'\n * stripHtmlTags('No tags here') // 'No tags here'\n */\nexport function stripHtmlTags(html: string): string {\n if (globalThis.window !== undefined && typeof DOMParser !== 'undefined') {\n const doc = new DOMParser().parseFromString(html, 'text/html');\n return doc.body.textContent || '';\n }\n // Server-side fallback: iterative O(n) approach to avoid regex backtracking\n let result = '';\n let inTag = false;\n for (const char of html) {\n if (char === '<') {\n inTag = true;\n } else if (char === '>') {\n inTag = false;\n } else if (!inTag) {\n result += char;\n }\n }\n return result;\n}\n","import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n useState,\n useCallback,\n ButtonHTMLAttributes,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useId,\n CSSProperties,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { CaretDown, Check, WarningCircle } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\n\nconst VARIANT_CLASSES = {\n outlined: 'border-2 rounded-lg focus:border-primary-950',\n underlined: 'border-b-2 focus:border-primary-950',\n rounded: 'border-2 rounded-full focus:border-primary-950',\n} as const;\n\nconst SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n large: 'text-lg',\n 'extra-large': 'text-lg',\n} as const;\n\nconst HEIGHT_CLASSES = {\n small: 'h-8',\n medium: 'h-9',\n large: 'h-10',\n 'extra-large': 'h-12',\n} as const;\n\nconst PADDING_CLASSES = {\n small: 'px-2 py-1',\n medium: 'px-3 py-2',\n large: 'px-4 py-3',\n 'extra-large': 'px-5 py-4',\n} as const;\n\ninterface TriggerRect {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\ntype SelectAlign = 'start' | 'center' | 'end';\n\ninterface SelectStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n value: string;\n setValue: (value: string) => void;\n selectedLabel: ReactNode;\n setSelectedLabel: (label: ReactNode) => void;\n onValueChange?: (value: string) => void;\n triggerRect: TriggerRect | null;\n setTriggerRect: (rect: TriggerRect | null) => void;\n}\n\ntype SelectStoreApi = StoreApi<SelectStore>;\n\nexport function createSelectStore(\n onValueChange?: (value: string) => void\n): SelectStoreApi {\n return create<SelectStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n value: '',\n setValue: (value) => set({ value }),\n selectedLabel: '',\n setSelectedLabel: (label) => set({ selectedLabel: label }),\n onValueChange,\n triggerRect: null,\n setTriggerRect: (rect) => set({ triggerRect: rect }),\n }));\n}\n\nexport const useSelectStore = (externalStore?: SelectStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a Select (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nexport function getLabelAsNode(children: ReactNode): ReactNode {\n if (typeof children === 'string' || typeof children === 'number') {\n return children;\n }\n const flattened = Children.toArray(children);\n\n if (flattened.length === 1) return flattened[0];\n\n return <>{flattened}</>;\n}\n\ninterface SelectProps {\n className?: string;\n children: ReactNode;\n defaultValue?: string;\n value?: string;\n onValueChange?: (value: string) => void;\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n label?: string;\n helperText?: string;\n errorMessage?: string;\n id?: string;\n}\n\nconst injectStore = (\n children: ReactNode,\n store: SelectStoreApi,\n size: string,\n selectId: string\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: SelectStoreApi;\n children?: ReactNode;\n size?: string;\n selectId?: string;\n }>;\n\n const newProps: Partial<{\n store: SelectStoreApi;\n children: ReactNode;\n size: string;\n selectId: string;\n }> = {\n store,\n };\n\n // Pass size to SelectTrigger, selectId to both Trigger and Content\n if (typedChild.type === SelectTrigger) {\n newProps.size = size;\n newProps.selectId = selectId;\n }\n\n if (typedChild.type === SelectContent) {\n newProps.selectId = selectId;\n }\n\n if (typedChild.props.children) {\n newProps.children = injectStore(\n typedChild.props.children,\n store,\n size,\n selectId\n );\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\nconst Select = ({\n children,\n defaultValue = '',\n className,\n value: propValue,\n onValueChange,\n size = 'small',\n label,\n helperText,\n errorMessage,\n id,\n}: SelectProps) => {\n const storeRef = useRef<SelectStoreApi | null>(null);\n storeRef.current ??= createSelectStore(onValueChange);\n const store = storeRef.current;\n\n const selectRef = useRef<HTMLDivElement>(null);\n const { open, setOpen, setValue, selectedLabel } = useStore(store, (s) => s);\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const selectId = id ?? `select-${generatedId}`;\n\n const findLabelForValue = (\n children: ReactNode,\n targetValue: string\n ): string | null => {\n let found: string | null = null;\n const search = (nodes: ReactNode) => {\n Children.forEach(nodes, (child) => {\n if (!isValidElement(child)) return;\n const typedChild = child as ReactElement<{\n value?: string;\n children?: ReactNode;\n }>;\n if (\n typedChild.type === SelectItem &&\n typedChild.props.value === targetValue\n ) {\n if (typeof typedChild.props.children === 'string')\n found = typedChild.props.children;\n }\n if (typedChild.props.children && !found)\n search(typedChild.props.children);\n });\n };\n search(children);\n return found;\n };\n\n useEffect(() => {\n if (!selectedLabel && defaultValue) {\n const label = findLabelForValue(children, defaultValue);\n if (label) store.setState({ selectedLabel: label });\n }\n }, [children, defaultValue, selectedLabel]);\n\n useEffect(() => {\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n const target = event.target as Node;\n // Check if click is inside the trigger container\n const isInsideTrigger = selectRef.current?.contains(target);\n // Check if click is inside the portaled content (scoped to this Select instance)\n const portaledMenu = document.body.querySelector(\n `[role=\"menu\"][data-select-id=\"${selectId}\"]`\n );\n const isInsidePortaledMenu = portaledMenu?.contains(target);\n\n if (!isInsideTrigger && !isInsidePortaledMenu) {\n setOpen(false);\n }\n };\n\n const handleArrowKeys = (event: globalThis.KeyboardEvent) => {\n // Find the portaled menu in the body (scoped to this Select instance)\n const selectContent = document.body.querySelector(\n `[role=\"menu\"][data-select-id=\"${selectId}\"]`\n );\n if (selectContent) {\n event.preventDefault();\n const items = Array.from(\n selectContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n const focused = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focused);\n\n let nextIndex: number;\n if (event.key === 'ArrowDown') {\n nextIndex =\n currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n items[nextIndex]?.focus();\n }\n };\n\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleArrowKeys);\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleArrowKeys);\n };\n }, [open, selectId, setOpen]);\n\n useEffect(() => {\n // Skip when the consumer isn't using controlled mode\n if (propValue === undefined) return;\n setValue(propValue);\n // Resolve the label for the new value; if it can't be resolved (empty\n // value, or a value with no matching SelectItem), clear the stale label\n // so the placeholder takes over.\n const label = findLabelForValue(children, propValue);\n store.setState({ selectedLabel: label ?? '' });\n }, [propValue, children]);\n\n const sizeClasses = SIZE_CLASSES[size];\n\n return (\n <div className={cn('w-full', className)}>\n {/* Label */}\n {label && (\n <label\n htmlFor={selectId}\n className={cn('block font-bold text-text-900 mb-1.5', sizeClasses)}\n >\n {label}\n </label>\n )}\n\n {/* Select Container */}\n <div className={cn('relative w-full')} ref={selectRef}>\n {injectStore(children, store, size, selectId)}\n </div>\n\n {/* Helper Text or Error Message */}\n {(helperText || errorMessage) && (\n <div className=\"mt-1.5 gap-1.5\">\n {helperText && <p className=\"text-sm text-text-500\">{helperText}</p>}\n {errorMessage && (\n <p className=\"flex gap-1 items-center text-sm text-indicator-error\">\n <WarningCircle size={16} /> {errorMessage}\n </p>\n )}\n </div>\n )}\n </div>\n );\n};\n\nconst SelectValue = ({\n placeholder,\n store: externalStore,\n}: {\n placeholder?: string;\n store?: SelectStoreApi;\n}) => {\n const store = useSelectStore(externalStore);\n\n const selectedLabel = useStore(store, (s) => s.selectedLabel);\n const value = useStore(store, (s) => s.value);\n return (\n <span className=\"text-inherit flex gap-2 items-center\">\n {selectedLabel || placeholder || value}\n </span>\n );\n};\n\ninterface SelectTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n className?: string;\n invalid?: boolean;\n variant?: 'outlined' | 'underlined' | 'rounded';\n store?: SelectStoreApi;\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n selectId?: string;\n}\n\nconst SelectTrigger = forwardRef<HTMLButtonElement, SelectTriggerProps>(\n (\n {\n className,\n invalid = false,\n variant = 'outlined',\n store: externalStore,\n disabled,\n size = 'medium',\n selectId,\n type = 'button',\n ...props\n },\n ref\n ) => {\n const store = useSelectStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const internalRef = useRef<HTMLButtonElement>(null);\n\n const setRefs = useCallback(\n (element: HTMLButtonElement | null) => {\n internalRef.current = element;\n if (typeof ref === 'function') {\n ref(element);\n } else if (ref) {\n ref.current = element;\n }\n },\n [ref]\n );\n\n const updateTriggerRect = useCallback(() => {\n if (internalRef.current) {\n const rect = internalRef.current.getBoundingClientRect();\n store.setState({\n triggerRect: {\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n },\n });\n }\n }, [store]);\n\n // Update triggerRect on scroll/resize while open\n useEffect(() => {\n if (!open) return;\n\n const handleUpdate = () => {\n updateTriggerRect();\n };\n\n window.addEventListener('scroll', handleUpdate, true);\n window.addEventListener('resize', handleUpdate);\n\n return () => {\n window.removeEventListener('scroll', handleUpdate, true);\n window.removeEventListener('resize', handleUpdate);\n };\n }, [open, updateTriggerRect]);\n\n const toggleOpen = () => {\n const newOpen = !open;\n if (newOpen) {\n updateTriggerRect();\n }\n store.setState({ open: newOpen });\n };\n\n const variantClasses = VARIANT_CLASSES[variant];\n const heightClasses = HEIGHT_CLASSES[size];\n const paddingClasses = PADDING_CLASSES[size];\n\n return (\n <button\n ref={setRefs}\n id={selectId}\n type={type}\n className={cn(\n 'flex w-full items-center justify-between border-border-300',\n heightClasses,\n paddingClasses,\n invalid &&\n `${variant == 'underlined' ? 'border-b-2' : 'border-2'} border-indicator-error text-text-600`,\n disabled\n ? 'cursor-not-allowed text-text-400 pointer-events-none opacity-50'\n : 'cursor-pointer hover:bg-background-50 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground',\n !invalid && !disabled ? 'text-text-700' : '',\n variantClasses,\n className\n )}\n onClick={toggleOpen}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-controls={open ? 'select-content' : undefined}\n {...props}\n >\n {props.children}\n <CaretDown\n className={cn(\n 'h-[1em] w-[1em] opacity-50 transition-transform',\n open ? 'rotate-180' : ''\n )}\n />\n </button>\n );\n }\n);\nSelectTrigger.displayName = 'SelectTrigger';\n\nfunction applyVerticalPosition(\n styles: CSSProperties,\n triggerRect: TriggerRect,\n side: 'top' | 'bottom',\n align: SelectAlign,\n gap: number\n): void {\n styles.top =\n side === 'top'\n ? triggerRect.top - gap\n : triggerRect.top + triggerRect.height + gap;\n styles.transform = side === 'top' ? 'translateY(-100%)' : undefined;\n\n if (align === 'start') {\n styles.left = triggerRect.left;\n } else if (align === 'center') {\n styles.left = triggerRect.left + triggerRect.width / 2;\n styles.transform =\n side === 'top' ? 'translate(-50%, -100%)' : 'translateX(-50%)';\n } else {\n styles.left = triggerRect.left + triggerRect.width;\n styles.transform =\n side === 'top' ? 'translate(-100%, -100%)' : 'translateX(-100%)';\n }\n}\n\nfunction applyHorizontalPosition(\n styles: CSSProperties,\n triggerRect: TriggerRect,\n side: 'left' | 'right',\n align: SelectAlign,\n gap: number\n): void {\n styles.left =\n side === 'left'\n ? triggerRect.left - gap\n : triggerRect.left + triggerRect.width + gap;\n styles.transform = side === 'left' ? 'translateX(-100%)' : undefined;\n\n if (align === 'start') {\n styles.top = triggerRect.top;\n } else if (align === 'center') {\n styles.top = triggerRect.top + triggerRect.height / 2;\n styles.transform =\n side === 'left' ? 'translate(-100%, -50%)' : 'translateY(-50%)';\n } else {\n styles.top = triggerRect.top + triggerRect.height;\n styles.transform =\n side === 'left' ? 'translate(-100%, -100%)' : 'translateY(-100%)';\n }\n}\n\ninterface SelectContentProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n store?: SelectStoreApi;\n selectId?: string;\n}\n\nconst SelectContent = forwardRef<HTMLDivElement, SelectContentProps>(\n (\n {\n children,\n className,\n align = 'start',\n side = 'bottom',\n store: externalStore,\n selectId,\n ...props\n },\n ref\n ) => {\n const store = useSelectStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const triggerRect = useStore(store, (s) => s.triggerRect);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!open || !mounted) return null;\n\n // Calculate position based on trigger rect\n const getPositionStyles = (): CSSProperties => {\n if (!triggerRect) {\n return {};\n }\n\n const gap = 4;\n const styles: CSSProperties = {\n position: 'fixed',\n zIndex: 9999,\n };\n\n const isVertical = side === 'top' || side === 'bottom';\n\n if (isVertical) {\n applyVerticalPosition(styles, triggerRect, side, align, gap);\n } else {\n applyHorizontalPosition(styles, triggerRect, side, align, gap);\n }\n\n return styles;\n };\n\n const content = (\n <div\n role=\"menu\"\n ref={ref}\n data-select-id={selectId}\n style={getPositionStyles()}\n className={cn(\n 'bg-secondary min-w-[210px] max-h-[300px] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md border-border-100',\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n // Render using portal to escape overflow constraints\n return createPortal(content, document.body);\n }\n);\nSelectContent.displayName = 'SelectContent';\n\ninterface SelectItemProps extends HTMLAttributes<HTMLDivElement> {\n value: string;\n disabled?: boolean;\n store?: SelectStoreApi;\n truncate?: boolean;\n}\n\nconst SelectItem = forwardRef<HTMLDivElement, SelectItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n truncate = false,\n ...props\n },\n ref\n ) => {\n const store = useSelectStore(externalStore);\n const {\n value: selectedValue,\n setValue,\n setOpen,\n setSelectedLabel,\n onValueChange,\n } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n const labelNode = getLabelAsNode(children);\n if (!disabled) {\n // Always set the clicked value, even if it's already selected\n setValue(value);\n setSelectedLabel(labelNode);\n setOpen(false);\n onValueChange?.(value);\n }\n props.onClick?.(e as MouseEvent<HTMLDivElement>);\n };\n\n return (\n <div\n role=\"menuitem\"\n aria-disabled={disabled}\n ref={ref}\n className={`\n bg-secondary focus-visible:bg-background-50\n relative flex select-none items-center gap-2 rounded-sm p-3 outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400 pointer-events-none opacity-50'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n ${selectedValue === value && 'bg-background-50'}\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n {selectedValue === value && <Check className=\"\" />}\n </span>\n {truncate ? (\n <span className=\"truncate block max-w-[200px]\">{children}</span>\n ) : (\n children\n )}\n </div>\n );\n }\n);\n\nSelectItem.displayName = 'SelectItem';\n\nexport default Select;\nexport { SelectTrigger, SelectContent, SelectItem, SelectValue };\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport { getStatusStyles } from '../../../components/Quiz/QuizContent';\nimport Text from '../../../components/Text/Text';\nimport { cn } from '../../../utils/utils';\nimport type { QuestionRendererProps } from '../types';\nimport { getStatusBadge } from '../components';\nimport { HtmlMathRenderer } from '../../../components/HtmlMathRenderer';\nimport { TrueFalseEnum } from '../../../enums/Quiz';\nimport { OptionStatus } from '../../../enums/Options';\n\n/**\n * Render true or false question\n * Each option has a statement, and student marks V or F for each\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionTrueOrFalse = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n const options = question.options || [];\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n const shouldShowStatus =\n result?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n result?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n return (\n <div className=\"pt-2\">\n <div className=\"flex flex-col gap-3.5\">\n {options.map((option, index) => {\n // Find student's answer for this option\n const studentSelection = result?.selectedOptions?.find(\n (op) => op.optionId === option.id\n );\n\n // Get the correct answer from options array (if the statement is true or false)\n const correctAnswerOption = result?.options?.find(\n (op) => op.id === option.id\n );\n const hasCorrectAnswer = correctAnswerOption?.isCorrect !== undefined;\n const statementIsTrue = correctAnswerOption?.isCorrect ?? false;\n\n // Student's answer: isCorrect in selectedOptions represents what user marked\n // isCorrect: true = user marked V (Verdadeiro)\n // isCorrect: false = user marked F (Falso)\n const hasAnswered = studentSelection !== undefined;\n const studentMarkedTrue = studentSelection?.isCorrect ?? false;\n\n // Determine if student's answer is correct (only valid when we have the correct answer)\n // Student is correct if their mark matches the statement's truth value\n const isStudentCorrect =\n hasCorrectAnswer &&\n hasAnswered &&\n studentMarkedTrue === statementIsTrue;\n\n // Only show correctness styling when we have the official answer\n const canShowCorrectness = shouldShowStatus && hasCorrectAnswer;\n const variantCorrect = isStudentCorrect\n ? OptionStatus.CORRECT\n : OptionStatus.INCORRECT;\n const studentAnswer = studentMarkedTrue\n ? TrueFalseEnum.VERDADEIRO\n : TrueFalseEnum.FALSO;\n const correctAnswer = statementIsTrue\n ? TrueFalseEnum.VERDADEIRO\n : TrueFalseEnum.FALSO;\n\n return (\n <section\n key={option.id || `option-${index}`}\n className=\"flex flex-col gap-2\"\n >\n <div\n className={cn(\n 'flex flex-row justify-between items-center gap-2 p-2 rounded-md border',\n canShowCorrectness && hasAnswered\n ? getStatusStyles(variantCorrect)\n : ''\n )}\n >\n <Text as=\"span\" size=\"sm\" weight=\"normal\" color=\"text-text-900\">\n {getLetterByIndex(index).concat(') ')}\n <HtmlMathRenderer content={option.option} inline />\n </Text>\n\n {canShowCorrectness && hasAnswered && (\n <div className=\"flex-shrink-0\">\n {getStatusBadge(\n isStudentCorrect\n ? OptionStatus.CORRECT\n : OptionStatus.INCORRECT\n )}\n </div>\n )}\n </div>\n\n {canShowCorrectness && (\n <span className=\"flex flex-row gap-2 items-center flex-wrap\">\n {hasAnswered ? (\n <>\n <Text size=\"2xs\" weight=\"normal\" color=\"text-text-800\">\n Resposta selecionada: {studentAnswer}\n </Text>\n {!isStudentCorrect && (\n <Text size=\"2xs\" weight=\"normal\" color=\"text-text-800\">\n | Resposta correta: {correctAnswer}\n </Text>\n )}\n </>\n ) : (\n <Text size=\"2xs\" weight=\"normal\" color=\"text-text-800\">\n Não respondida | Resposta correta: {correctAnswer}\n </Text>\n )}\n </span>\n )}\n </section>\n );\n })}\n </div>\n </div>\n );\n};\n","import { Fragment, useId, type ReactNode } from 'react';\nimport Badge from '../../../components/Badge/Badge';\nimport { CheckCircle, XCircle } from 'phosphor-react';\nimport { cn } from '../../utils';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\nimport { stripHtmlTags } from '../../stringUtils';\nimport { OptionStatus } from '../../../enums/Options';\n\n/**\n * Get status badge component\n */\nexport const getStatusBadge = (status?: OptionStatus): ReactNode => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n};\n\n/**\n * Container component for question content\n */\nexport const QuestionContainer = ({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) => {\n return (\n <div\n className={cn(\n 'bg-background rounded-t-xl px-4 pt-4 pb-[80px] h-auto flex flex-col gap-4 mb-auto',\n className\n )}\n >\n {children}\n </div>\n );\n};\n\n/**\n * Subtitle component for question sections\n */\nexport const QuestionSubTitle = ({ subTitle }: { subTitle: string }) => {\n return (\n <div className=\"px-4 pb-2 pt-6\">\n <Text size=\"md\" weight=\"bold\" color=\"text-text-950\">\n {subTitle}\n </Text>\n </div>\n );\n};\n\n/**\n * Internal component for fill in the blanks question\n * Uses useId hook to generate unique IDs\n *\n * Data structure:\n * - additionalContent: HTML text with {placeholderId} placeholders\n * - fillAnswers: Record<placeholderId, selectedOptionId> (what student chose)\n * - options: Array<{ id, option }> where id is placeholderId AND correct optionId\n * - Correctness: selectedOptionId === placeholderId means correct\n */\nexport const FillQuestionContent = ({\n question,\n result,\n}: QuestionRendererProps) => {\n const baseId = useId();\n\n // Get additionalContent (contains HTML with {placeholderId} placeholders)\n // Falls back to question.statement for older questions that may not have additionalContent\n const additionalContent =\n result?.additionalContent ||\n question.additionalContent ||\n question.statement ||\n '';\n\n // Strip HTML tags for clean text rendering\n const cleanText = stripHtmlTags(additionalContent);\n\n // Get options array (id is placeholderId, option is the text)\n const options =\n (\n result as {\n options?: Array<{ id: string; option: string; isCorrect: boolean }>;\n }\n )?.options ||\n question.options ||\n [];\n\n // Build a map of optionId -> option text for quick lookup\n const optionTextMap: Record<string, string> = {};\n options.forEach((opt) => {\n optionTextMap[opt.id] = opt.option;\n });\n\n // Get fillAnswers: Record<placeholderId, selectedOptionId>\n const fillAnswers: Record<string, string> = {};\n try {\n const resultWithFill = result as {\n fillAnswers?: Record<string, string> | null;\n };\n if (resultWithFill?.fillAnswers) {\n Object.assign(fillAnswers, resultWithFill.fillAnswers);\n } else if (result?.answer) {\n const parsed =\n typeof result.answer === 'string'\n ? JSON.parse(result.answer)\n : result.answer;\n if (typeof parsed === 'object') {\n Object.assign(fillAnswers, parsed);\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n // Helper to get option text by ID - returns null if not found\n const getOptionTextById = (optionId: string): string | null => {\n if (!optionId) return null;\n return optionTextMap[optionId] ?? null;\n };\n\n // Check if answer is correct (selectedOptionId === placeholderId)\n const isAnswerCorrect = (placeholderId: string): boolean => {\n const selectedOptionId = fillAnswers[placeholderId];\n return selectedOptionId === placeholderId;\n };\n\n // Render student answer badge\n const renderStudentBadge = (placeholderId: string) => {\n const selectedOptionId = fillAnswers[placeholderId];\n const selectedOptionText = getOptionTextById(selectedOptionId);\n const isCorrect = isAnswerCorrect(placeholderId);\n\n if (!selectedOptionId) {\n return (\n <span className=\"inline-block align-middle mx-1 my-1\">\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n </span>\n );\n }\n\n // Handle case where option ID exists but text is not found\n const displayText = selectedOptionText ?? 'Opção não encontrada';\n\n return (\n <span className=\"inline-block align-middle mx-1 my-1\">\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n {displayText}\n </Badge>\n </span>\n );\n };\n\n // Render correct answer\n const renderCorrectAnswer = (placeholderId: string) => {\n // The placeholderId IS the correct option ID\n const correctOptionText = getOptionTextById(placeholderId);\n const displayText = correctOptionText ?? '[Resposta não disponível]';\n return (\n <span className=\"inline mx-1 text-success-600 font-semibold border-b-2 border-success-600\">\n {displayText}\n </span>\n );\n };\n\n // Parse text and render with elements\n const renderTextWithElements = (text: string, isCorrectAnswer: boolean) => {\n const elements: Array<{ element: string | ReactNode; id: string }> = [];\n let lastIndex = 0;\n const nextId = () => elements.length;\n\n const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n let match;\n\n while ((match = regex.exec(text)) !== null) {\n const [fullMatch, placeholderId] = match;\n const startIndex = match.index;\n\n // Add text before placeholder\n if (startIndex > lastIndex) {\n elements.push({\n element: text.slice(lastIndex, startIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n // Add the appropriate element\n if (isCorrectAnswer) {\n elements.push({\n element: renderCorrectAnswer(placeholderId),\n id: `${baseId}-answer-sheet-${nextId()}`,\n });\n } else {\n elements.push({\n element: renderStudentBadge(placeholderId),\n id: `${baseId}-student-${nextId()}`,\n });\n }\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Add remaining text\n if (lastIndex < text.length) {\n elements.push({\n element: text.slice(lastIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n return elements;\n };\n\n if (!additionalContent) {\n return (\n <div className=\"pt-2\">\n <Text size=\"md\" color=\"text-text-600\" weight=\"normal\">\n Nenhum conteúdo disponível para esta questão.\n </Text>\n </div>\n );\n }\n\n return (\n <div className=\"pt-2 space-y-4\">\n <div className=\"space-y-2\">\n <Text size=\"xs\" weight=\"normal\" color=\"text-text-500\">\n Resposta do aluno:\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n <Text\n as=\"div\"\n size=\"md\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderTextWithElements(cleanText, false).map((element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n ))}\n </Text>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Text size=\"xs\" weight=\"normal\" color=\"text-text-500\">\n Gabarito:\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n <Text\n as=\"div\"\n size=\"md\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderTextWithElements(cleanText, true).map((element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n ))}\n </Text>\n </div>\n </div>\n </div>\n );\n};\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\nimport { HtmlMathRenderer } from '../../../components/HtmlMathRenderer';\n\n/**\n * Render essay/dissertative question (readonly mode for correction)\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionDissertative = ({\n result,\n}: Omit<QuestionRendererProps, 'question'>): ReactNode => {\n const localAnswer = result?.answer || '';\n\n return (\n <div className=\"pt-2 space-y-4\">\n <div className=\"space-y-2\">\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-950\">\n Resposta do aluno\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n {localAnswer ? (\n <HtmlMathRenderer\n content={localAnswer}\n className=\"text-sm text-text-700\"\n />\n ) : (\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-700\">\n Nenhuma resposta fornecida\n </Text>\n )}\n </div>\n </div>\n\n {result?.answerStatus === ANSWER_STATUS.RESPOSTA_INCORRETA &&\n result?.teacherFeedback && (\n <div className=\"space-y-2\">\n <Text size=\"xs\" weight=\"normal\" color=\"text-text-500\">\n Observação do professor:\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n <HtmlMathRenderer\n content={result.teacherFeedback}\n className=\"text-sm text-text-700\"\n />\n </div>\n </div>\n )}\n </div>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { QuestionRendererProps } from '../types';\nimport { FillQuestionContent } from '../components';\n\n/**\n * Render fill in the blanks question\n * Shows text with student answers highlighted (green if correct, red if wrong)\n * Also shows a correct answers section\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionFill = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n return <FillQuestionContent question={question} result={result} />;\n};\n","import type { ReactNode } from 'react';\nimport ImageQuestion from '../../../assets/img/mock-image-question.png';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\n\n/**\n * Render image question\n * Shows image with clickable area, correct answer circle, and user's answer circle\n */\nexport const renderQuestionImage = ({\n result,\n}: Omit<QuestionRendererProps, 'question'>): ReactNode => {\n // Extract position data from result or question\n // Assuming correct position is stored in question metadata or result\n const correctPositionRelative = { x: 0.48, y: 0.45 }; // Default, should come from question data\n const correctRadiusRelative = 0.1; // Default radius\n\n // Get user's answer position from result\n // This would typically be stored in result.answer as coordinates\n let userPositionRelative: { x: number; y: number } | null = null;\n try {\n if (result?.answer) {\n const parsed =\n typeof result.answer === 'string'\n ? JSON.parse(result.answer)\n : result.answer;\n if (\n parsed &&\n typeof parsed.x === 'number' &&\n typeof parsed.y === 'number'\n ) {\n userPositionRelative = { x: parsed.x, y: parsed.y };\n }\n }\n } catch {\n userPositionRelative = null;\n }\n\n // Determine if answer is correct (within radius)\n const isCorrect = userPositionRelative\n ? Math.sqrt(\n Math.pow(userPositionRelative.x - correctPositionRelative.x, 2) +\n Math.pow(userPositionRelative.y - correctPositionRelative.y, 2)\n ) <= correctRadiusRelative\n : false;\n\n const getUserCircleColorClasses = () => {\n if (!userPositionRelative) return '';\n return isCorrect\n ? 'bg-success-600/70 border-white'\n : 'bg-indicator-error/70 border-white';\n };\n\n // Calculate position descriptions for accessibility\n const getPositionDescription = (x: number, y: number): string => {\n const xPercent = Math.round(x * 100);\n const yPercent = Math.round(y * 100);\n return `${xPercent}% da esquerda, ${yPercent}% do topo`;\n };\n\n const getSpatialRelationship = (): string => {\n if (!userPositionRelative) {\n return `Área correta localizada em ${getPositionDescription(\n correctPositionRelative.x,\n correctPositionRelative.y\n )}. Nenhuma resposta do aluno fornecida.`;\n }\n\n const deltaX = userPositionRelative.x - correctPositionRelative.x;\n const deltaY = userPositionRelative.y - correctPositionRelative.y;\n const distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n const distancePercent = Math.round(distance * 100);\n\n let direction: string;\n if (Math.abs(deltaX) > Math.abs(deltaY)) {\n direction = deltaX > 0 ? 'à direita' : 'à esquerda';\n } else {\n direction = deltaY > 0 ? 'abaixo' : 'acima';\n }\n\n const correctPos = getPositionDescription(\n correctPositionRelative.x,\n correctPositionRelative.y\n );\n const userPos = getPositionDescription(\n userPositionRelative.x,\n userPositionRelative.y\n );\n\n return `Área correta localizada em ${correctPos}. Resposta do aluno em ${userPos}. A resposta do aluno está ${distancePercent}% de distância ${direction} da área correta. ${isCorrect ? 'A resposta está dentro da área de tolerância e é considerada correta.' : 'A resposta está fora da área de tolerância e é considerada incorreta.'}`;\n };\n\n const correctPositionDescription = getPositionDescription(\n correctPositionRelative.x,\n correctPositionRelative.y\n );\n const imageAltText = `Questão de imagem com área correta localizada em ${correctPositionDescription}`;\n\n return (\n <div className=\"pt-2 space-y-4\">\n {/* Legend */}\n <div className=\"flex items-center gap-4 text-xs\">\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-primary/70 border border-[#F8CC2E]\"></div>\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-600\">\n Área correta\n </Text>\n </div>\n {userPositionRelative && (\n <>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-success-600/70 border border-white\"></div>\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-600\">\n Resposta correta\n </Text>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-error/70 border border-white\"></div>\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-600\">\n Resposta incorreta\n </Text>\n </div>\n </>\n )}\n </div>\n\n {/* Image container */}\n <div className=\"relative w-full\">\n {/* Hidden text summary for screen readers */}\n <div className=\"sr-only\">{getSpatialRelationship()}</div>\n\n <img\n src={ImageQuestion}\n alt={imageAltText}\n className=\"w-full h-auto rounded-md\"\n />\n\n {/* Correct answer circle */}\n <div\n role=\"img\"\n aria-label={`Área correta marcada em ${correctPositionDescription}`}\n className=\"absolute rounded-full bg-indicator-primary/70 border-4 border-[#F8CC2E] pointer-events-none\"\n style={{\n minWidth: '50px',\n maxWidth: '160px',\n width: '15%',\n aspectRatio: '1 / 1',\n left: `calc(${correctPositionRelative.x * 100}% - 7.5%)`,\n top: `calc(${correctPositionRelative.y * 100}% - 15%)`,\n }}\n >\n <Text\n size=\"sm\"\n weight=\"normal\"\n color=\"text-text-600\"\n className=\"sr-only\"\n >\n Círculo amarelo indicando a área correta da resposta, posicionado em{' '}\n {correctPositionDescription}\n </Text>\n </div>\n\n {/* User's answer circle */}\n {userPositionRelative && (\n <div\n role=\"img\"\n aria-label={`Resposta do aluno marcada em ${getPositionDescription(\n userPositionRelative.x,\n userPositionRelative.y\n )}, ${isCorrect ? 'correta' : 'incorreta'}`}\n className={`absolute rounded-full border-4 pointer-events-none ${getUserCircleColorClasses()}`}\n style={{\n minWidth: '30px',\n maxWidth: '52px',\n width: '5%',\n aspectRatio: '1 / 1',\n left: `calc(${userPositionRelative.x * 100}% - 2.5%)`,\n top: `calc(${userPositionRelative.y * 100}% - 2.5%)`,\n }}\n >\n <Text\n size=\"sm\"\n weight=\"normal\"\n color=\"text-text-600\"\n className=\"sr-only\"\n >\n Círculo {isCorrect ? 'verde' : 'vermelho'} indicando a resposta do\n aluno, posicionado em{' '}\n {getPositionDescription(\n userPositionRelative.x,\n userPositionRelative.y\n )}\n . A resposta está{' '}\n {Math.round(\n Math.sqrt(\n Math.pow(\n userPositionRelative.x - correctPositionRelative.x,\n 2\n ) +\n Math.pow(\n userPositionRelative.y - correctPositionRelative.y,\n 2\n )\n ) * 100\n )}\n % de distância da área correta e é considerada{' '}\n {isCorrect ? 'correta' : 'incorreta'}.\n </Text>\n </div>\n )}\n </div>\n </div>\n );\n};\n","import type { ReactNode } from 'react';\nimport { cn } from '../../../utils/utils';\nimport Text from '../../../components/Text/Text';\nimport { QuestionSubTitle, QuestionContainer } from '../components';\n\n/**\n * Render connect dots question (not implemented)\n */\nexport const renderQuestionConnectDots = ({\n paddingBottom,\n}: {\n paddingBottom?: string;\n} = {}): ReactNode => {\n return (\n <>\n <QuestionSubTitle subTitle=\"Tipo de questão: Ligar Pontos\" />\n <QuestionContainer className={cn('', paddingBottom)}>\n <div className=\"space-y-4\">\n <Text size=\"md\" weight=\"normal\" color=\"text-text-600\">\n Tipo de questão: Ligar Pontos (não implementado)\n </Text>\n </div>\n </QuestionContainer>\n </>\n );\n};\n","import type { ReactNode } from 'react';\nimport { QUESTION_TYPE } from '../../components/Quiz/useQuizStore';\nimport { renderQuestionAlternative } from './alternative';\nimport { renderQuestionMultipleChoice } from './multipleChoice';\nimport { renderQuestionTrueOrFalse } from './trueOrFalse';\nimport { renderQuestionDissertative } from './dissertative';\nimport { renderQuestionFill } from './fill';\nimport { renderQuestionImage } from './image';\nimport { renderQuestionConnectDots } from './connectDots';\nimport type { QuestionRendererProps } from './types';\n\n// Re-export types\nexport type { QuestionRendererProps } from './types';\n\n// Re-export components\nexport {\n getStatusBadge,\n QuestionContainer,\n QuestionSubTitle,\n FillQuestionContent,\n} from './components';\n\n// Re-export individual renderers\nexport { renderQuestionAlternative } from './alternative';\nexport { renderQuestionMultipleChoice } from './multipleChoice';\nexport { renderQuestionTrueOrFalse } from './trueOrFalse';\nexport { renderQuestionDissertative } from './dissertative';\nexport { renderQuestionFill } from './fill';\nexport { renderQuestionImage } from './image';\nexport { renderQuestionConnectDots } from './connectDots';\n\n/**\n * Map question types to their render functions\n */\nconst questionRendererMap = {\n [QUESTION_TYPE.ALTERNATIVA]: renderQuestionAlternative,\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: renderQuestionMultipleChoice,\n [QUESTION_TYPE.VERDADEIRO_FALSO]: renderQuestionTrueOrFalse,\n [QUESTION_TYPE.DISSERTATIVA]: renderQuestionDissertative,\n [QUESTION_TYPE.PREENCHER_LACUNAS]: renderQuestionFill,\n [QUESTION_TYPE.IMAGEM]: renderQuestionImage,\n [QUESTION_TYPE.RELACIONAR]: renderQuestionConnectDots,\n};\n\n/**\n * Render question based on question type\n * @param props - Question renderer props\n * @returns Rendered question content\n */\nexport const renderQuestion = (props: QuestionRendererProps): ReactNode => {\n const { question } = props;\n const renderer = questionRendererMap[question.questionType];\n\n if (!renderer) {\n // Fallback: try to render based on options presence\n if (question.options && question.options.length > 0) {\n return renderQuestionAlternative(props);\n }\n return renderQuestionDissertative({ result: props.result });\n }\n\n // Handle renderers with different prop requirements\n switch (question.questionType) {\n case QUESTION_TYPE.DISSERTATIVA:\n return renderQuestionDissertative({ result: props.result });\n case QUESTION_TYPE.IMAGEM:\n return renderQuestionImage({ result: props.result });\n case QUESTION_TYPE.RELACIONAR:\n return renderQuestionConnectDots({ paddingBottom: '' });\n case QUESTION_TYPE.ALTERNATIVA:\n case QUESTION_TYPE.MULTIPLA_ESCOLHA:\n case QUESTION_TYPE.VERDADEIRO_FALSO:\n case QUESTION_TYPE.PREENCHER_LACUNAS:\n return renderer(props);\n default:\n return null;\n }\n};\n\n/**\n * Type for question renderer map\n */\nexport type QuestionRendererMap = Record<QUESTION_TYPE, () => ReactNode>;\n\n/**\n * Render from a map of renderers\n * @param renderers - Map of question type to render function\n * @param questionType - Type of question to render\n * @returns Rendered content or null\n */\nexport const renderFromMap = (\n renderers: QuestionRendererMap,\n questionType?: QUESTION_TYPE\n) => {\n if (!questionType) return null;\n const renderer = renderers[questionType];\n return renderer ? renderer() : null;\n};\n","import { QUESTION_TYPE } from '../components/Quiz/useQuizStore';\n\n/**\n * Map question types to display labels\n */\nexport const questionTypeLabels: Record<QUESTION_TYPE, string> = {\n [QUESTION_TYPE.ALTERNATIVA]: 'Alternativa',\n [QUESTION_TYPE.VERDADEIRO_FALSO]: 'Verdadeiro ou Falso',\n [QUESTION_TYPE.DISSERTATIVA]: 'Discursiva',\n [QUESTION_TYPE.IMAGEM]: 'Imagem',\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: 'Múltipla Escolha',\n [QUESTION_TYPE.RELACIONAR]: 'Relacionar',\n [QUESTION_TYPE.PREENCHER_LACUNAS]: 'Preencher Lacunas',\n};\n","import { HtmlHTMLAttributes, useMemo, useId, ReactNode } from 'react';\nimport { cn } from '../../utils/utils';\nimport { parseContent } from '../../utils/parseContent';\nimport { CheckCircle, XCircle } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport Text from '../Text/Text';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport { QuizVariant } from '../Quiz/Quiz.types';\n\nexport interface FillInBlanksOption {\n id: string;\n option: string;\n}\n\nexport interface FillInBlanksProps extends HtmlHTMLAttributes<HTMLDivElement> {\n /** The text content with {uuid} placeholders */\n content: string;\n /** Available options to fill in the blanks */\n options: FillInBlanksOption[];\n /** Current answers as a map of placeholderId -> selectedOptionId */\n answers?: Record<string, string>;\n /** Callback when an answer changes (only for interactive mode) */\n onAnswerChange?: (placeholderId: string, optionId: string) => void;\n /** Display mode */\n mode?: 'interactive' | 'readonly' | 'result';\n /** Whether component is disabled (only for interactive mode) */\n disabled?: boolean;\n}\n\n/**\n * FillInBlanks component for displaying fill-in-the-blanks questions\n *\n * @example\n * // Readonly mode - shows correct answers with green underlined text\n * <FillInBlanks\n * content=\"A {uuid-1} é uma {uuid-2}.\"\n * options={[{ id: 'uuid-1', option: 'Terra' }, { id: 'uuid-2', option: 'planeta' }]}\n * mode=\"readonly\"\n * />\n *\n * @example\n * // Interactive mode - shows select dropdowns\n * <FillInBlanks\n * content=\"A {uuid-1} é uma {uuid-2}.\"\n * options={[{ id: 'uuid-1', option: 'Terra' }, { id: 'uuid-2', option: 'planeta' }]}\n * mode=\"interactive\"\n * answers={answers}\n * onAnswerChange={(placeholderId, optionId) => setAnswers({...answers, [placeholderId]: optionId})}\n * />\n *\n * @example\n * // Result mode - shows badges with correct/incorrect indicators\n * <FillInBlanks\n * content=\"A {uuid-1} é uma {uuid-2}.\"\n * options={[{ id: 'uuid-1', option: 'Terra' }, { id: 'uuid-2', option: 'planeta' }]}\n * mode=\"result\"\n * answers={userAnswers}\n * />\n */\nconst FillInBlanks = ({\n content,\n options,\n answers = {},\n onAnswerChange,\n mode = QuizVariant.INTERACTIVE,\n disabled = false,\n className,\n ...props\n}: FillInBlanksProps) => {\n const baseId = useId();\n\n // Create a map of option IDs to their text\n const optionsMap = useMemo(() => {\n return new Map(options.map((opt) => [opt.id, opt.option]));\n }, [options]);\n\n // Parse the content into parts\n const parsedParts = useMemo(() => parseContent(content), [content]);\n\n // Get option text by ID\n const getOptionText = (optionId: string): string => {\n return optionsMap.get(optionId) || '';\n };\n\n // Check if an answer is correct (the placeholderId IS the correct option ID)\n const isAnswerCorrect = (placeholderId: string): boolean => {\n const selectedOptionId = answers[placeholderId];\n return selectedOptionId === placeholderId;\n };\n\n // Render select for interactive mode\n const renderSelect = (placeholderId: string, index: number) => {\n const selectedOptionId = answers[placeholderId];\n\n return (\n <span\n key={`${baseId}-select-${index}`}\n className={cn(\n 'inline-block align-middle mx-1',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <Select\n value={selectedOptionId || undefined}\n onValueChange={(value) => onAnswerChange?.(placeholderId, value)}\n >\n <SelectTrigger className=\"w-auto min-w-[120px] h-7 px-2 bg-background border-gray-300\">\n <SelectValue placeholder=\"Selecione\" />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {option.option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n );\n };\n\n // Render correct answer for readonly mode\n const renderCorrectAnswer = (placeholderId: string, index: number) => {\n const correctText = getOptionText(placeholderId);\n\n return (\n <span\n key={`${baseId}-answer-${index}`}\n className=\"text-success-600 underline font-medium\"\n >\n {correctText}\n </span>\n );\n };\n\n // Render result badge\n const renderResultBadge = (placeholderId: string, index: number) => {\n const selectedOptionId = answers[placeholderId];\n const selectedText = getOptionText(selectedOptionId);\n const isCorrect = isAnswerCorrect(placeholderId);\n\n if (!selectedOptionId) {\n return (\n <span\n key={`${baseId}-result-${index}`}\n className=\"inline-block align-middle mx-1\"\n >\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n </span>\n );\n }\n\n return (\n <span\n key={`${baseId}-result-${index}`}\n className=\"inline-block align-middle mx-1\"\n >\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n <span className=\"text-text-900\">{selectedText}</span>\n </Badge>\n </span>\n );\n };\n\n // Render the appropriate element based on mode\n const renderPlaceholder = (\n placeholderId: string,\n index: number\n ): ReactNode => {\n switch (mode) {\n case QuizVariant.INTERACTIVE:\n return renderSelect(placeholderId, index);\n case QuizVariant.READONLY:\n return renderCorrectAnswer(placeholderId, index);\n case QuizVariant.RESULT:\n return renderResultBadge(placeholderId, index);\n default:\n return renderCorrectAnswer(placeholderId, index);\n }\n };\n\n // Build the rendered content\n const renderedContent = useMemo(() => {\n return parsedParts.map((part, index) => {\n if (part.type === 'text') {\n return <span key={`${baseId}-text-${index}`}>{part.value}</span>;\n }\n return renderPlaceholder(part.value, index);\n });\n }, [parsedParts, baseId, mode, answers, options, disabled]);\n\n return (\n <div className={cn('leading-relaxed', className)} {...props}>\n <Text size=\"sm\" className=\"text-text-900\">\n {renderedContent}\n </Text>\n </div>\n );\n};\n\nexport { FillInBlanks };\n","import { stripHtmlTags } from './stringUtils';\n\nexport interface ParsedContentPart {\n type: 'text' | 'placeholder';\n value: string;\n}\n\n/**\n * Parse content and extract text parts and placeholder IDs\n * Extracts {uuid} placeholders from text content, stripping HTML tags first\n *\n * @param content - String that may contain HTML and {uuid} placeholders\n * @returns Array of parsed parts with type ('text' or 'placeholder') and value\n *\n * @example\n * parseContent('Hello {uuid-1} world {uuid-2}')\n * // Returns: [\n * // { type: 'text', value: 'Hello ' },\n * // { type: 'placeholder', value: 'uuid-1' },\n * // { type: 'text', value: ' world ' },\n * // { type: 'placeholder', value: 'uuid-2' }\n * // ]\n */\nexport function parseContent(content: string): ParsedContentPart[] {\n const parts: ParsedContentPart[] = [];\n const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n let lastIndex = 0;\n let match;\n\n // Strip HTML tags for cleaner parsing\n const cleanContent = stripHtmlTags(content);\n\n while ((match = regex.exec(cleanContent)) !== null) {\n // Add text before the placeholder\n if (match.index > lastIndex) {\n parts.push({\n type: 'text',\n value: cleanContent.slice(lastIndex, match.index),\n });\n }\n\n // Add the placeholder\n parts.push({\n type: 'placeholder',\n value: match[1],\n });\n\n lastIndex = match.index + match[0].length;\n }\n\n // Add remaining text\n if (lastIndex < cleanContent.length) {\n parts.push({\n type: 'text',\n value: cleanContent.slice(lastIndex),\n });\n }\n\n return parts;\n}\n","import { HtmlHTMLAttributes, useMemo, useId, ReactNode } from 'react';\nimport { cn } from '../../utils/utils';\nimport { CheckCircle, XCircle, ArrowRight } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport Text from '../Text/Text';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport { QuizVariant } from '../Quiz/Quiz.types';\n\nexport interface ConnectDotsOption {\n id: string;\n option: string;\n correctValue: string;\n}\n\nexport interface ConnectDotsProps extends HtmlHTMLAttributes<HTMLDivElement> {\n /** Available options with their correct values */\n options: ConnectDotsOption[];\n /** Current answers as a map of optionId -> selectedValue */\n answers?: Record<string, string>;\n /** Callback when an answer changes (only for interactive mode) */\n onAnswerChange?: (optionId: string, selectedValue: string) => void;\n /** Display mode */\n mode?: 'interactive' | 'readonly' | 'result';\n /** Whether component is disabled (only for interactive mode) */\n disabled?: boolean;\n}\n\n/**\n * ConnectDots component for displaying matching/connect-the-dots questions\n *\n * @example\n * // Readonly mode - shows correct matches with arrows\n * <ConnectDots\n * options={[\n * { id: 'opt-1', option: 'I. Event A', correctValue: '2001' },\n * { id: 'opt-2', option: 'II. Event B', correctValue: '1989' },\n * ]}\n * mode=\"readonly\"\n * />\n *\n * @example\n * // Interactive mode - shows select dropdowns\n * <ConnectDots\n * options={[...]}\n * mode=\"interactive\"\n * answers={answers}\n * onAnswerChange={(optionId, value) => setAnswers({...answers, [optionId]: value})}\n * />\n *\n * @example\n * // Result mode - shows badges with correct/incorrect indicators\n * <ConnectDots\n * options={[...]}\n * mode=\"result\"\n * answers={userAnswers}\n * />\n */\nconst ConnectDots = ({\n options,\n answers = {},\n onAnswerChange,\n mode = QuizVariant.INTERACTIVE,\n disabled = false,\n className,\n ...props\n}: ConnectDotsProps) => {\n const baseId = useId();\n\n // Get all unique correct values for the dropdown options\n const availableValues = useMemo(() => {\n const values = options.map((opt) => opt.correctValue);\n // Remove duplicates and sort alphabetically using localeCompare\n return [...new Set(values)].sort((a, b) => a.localeCompare(b));\n }, [options]);\n\n // Check if an answer is correct\n const isAnswerCorrect = (optionId: string): boolean => {\n const option = options.find((opt) => opt.id === optionId);\n if (!option) return false;\n const selectedValue = answers[optionId];\n return selectedValue === option.correctValue;\n };\n\n // Render select for interactive mode\n const renderInteractiveItem = (option: ConnectDotsOption, index: number) => {\n const selectedValue = answers[option.id];\n\n return (\n <div\n key={`${baseId}-item-${index}`}\n className={cn(\n 'flex flex-row items-center gap-3 p-3 rounded-md border border-border-200 bg-background',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={option.option}\n className=\"text-text-900 text-sm\"\n />\n </div>\n\n <ArrowRight size={20} className=\"text-text-400 flex-shrink-0\" />\n\n <div className=\"w-[150px] flex-shrink-0\">\n <Select\n value={selectedValue || undefined}\n onValueChange={(value) => {\n if (disabled) return;\n onAnswerChange?.(option.id, value);\n }}\n >\n <SelectTrigger\n disabled={disabled}\n className=\"w-full h-8 px-2 bg-background border-gray-300\"\n >\n <SelectValue placeholder=\"Selecione\" />\n </SelectTrigger>\n <SelectContent>\n {availableValues.map((value) => (\n <SelectItem key={value} value={value}>\n {value}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n );\n };\n\n // Render correct match for readonly mode\n const renderReadonlyItem = (option: ConnectDotsOption, index: number) => {\n return (\n <div\n key={`${baseId}-readonly-${index}`}\n className=\"flex flex-row items-center gap-3 p-3 rounded-md border border-success-300 bg-success-50\"\n >\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={option.option}\n className=\"text-text-900 text-sm\"\n />\n </div>\n\n <ArrowRight size={20} className=\"text-success-600 flex-shrink-0\" />\n\n <div className=\"flex-shrink-0\">\n <Text size=\"sm\" weight=\"medium\" className=\"text-success-700\">\n {option.correctValue}\n </Text>\n </div>\n </div>\n );\n };\n\n // Render result item with correct/incorrect indicator\n const renderResultItem = (option: ConnectDotsOption, index: number) => {\n const selectedValue = answers[option.id];\n const isCorrect = isAnswerCorrect(option.id);\n const hasAnswer = !!selectedValue;\n\n // Only show success styling when answered correctly\n const isSuccess = hasAnswer && isCorrect;\n const borderStyles = isSuccess\n ? 'border-success-300 bg-success-50'\n : 'border-error-300 bg-error-50';\n const arrowColor = isSuccess ? 'text-success-600' : 'text-error-600';\n\n return (\n <div\n key={`${baseId}-result-${index}`}\n className={cn(\n 'flex flex-row items-center gap-3 p-3 rounded-md border',\n borderStyles\n )}\n >\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={option.option}\n className=\"text-text-900 text-sm\"\n />\n </div>\n\n <ArrowRight size={20} className={cn('flex-shrink-0', arrowColor)} />\n\n <div className=\"flex-shrink-0\">\n {hasAnswer ? (\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n {selectedValue}\n </Badge>\n ) : (\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n )}\n </div>\n\n {/* Show correct answer if wrong */}\n {hasAnswer && !isCorrect && (\n <Text size=\"xs\" className=\"text-success-600 flex-shrink-0\">\n (Correto: {option.correctValue})\n </Text>\n )}\n </div>\n );\n };\n\n // Render the appropriate element based on mode\n const renderItem = (option: ConnectDotsOption, index: number): ReactNode => {\n switch (mode) {\n case QuizVariant.INTERACTIVE:\n return renderInteractiveItem(option, index);\n case QuizVariant.READONLY:\n return renderReadonlyItem(option, index);\n case QuizVariant.RESULT:\n return renderResultItem(option, index);\n default:\n return renderReadonlyItem(option, index);\n }\n };\n\n // Build the rendered content\n const renderedContent = useMemo(() => {\n return options.map((option, index) => renderItem(option, index));\n }, [options, baseId, mode, answers, disabled, availableValues]);\n\n return (\n <div className={cn('flex flex-col gap-2', className)} {...props}>\n {renderedContent}\n </div>\n );\n};\n\nexport { ConnectDots };\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","VARIANT_ACTION_CLASSES","SIZE_CLASSES","import_jsx_runtime","katex","import_react","import_katex_min","import_react","match","import_jsx_runtime","ReactMarkdown","remarkGfm","remarkMath","rehypeKatex","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","SIZE_CLASSES","import_react","import_jsx_runtime","import_react","import_zustand","import_jsx_runtime","SIZE_CLASSES","STATE_CLASSES","injectStore","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_phosphor_react","import_react","import_jsx_runtime","getStatusStyles","isReadonly","getStatusBadge","value","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","getStatusBadge","getStatusStyles","import_jsx_runtime","import_react","import_zustand","import_react","import_phosphor_react","import_jsx_runtime","SIZE_CLASSES","injectStore","children","label","import_phosphor_react","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","import_phosphor_react","import_react","import_jsx_runtime","correctOptionIds"]}
1
+ {"version":3,"sources":["../../src/utils/utils.ts","../../src/components/Text/Text.tsx","../../src/components/Button/Button.tsx","../../src/components/ActivityCardQuestionBanks/ActivityCardQuestionBanks.tsx","../../src/index.ts","../../src/components/Badge/Badge.tsx","../../src/components/HtmlMathRenderer/KatexMath.tsx","../../src/components/HtmlMathRenderer/HtmlMathRenderer.tsx","../../src/components/MarkdownMathRenderer/MarkdownMathRenderer.tsx","../../src/components/HtmlMathRenderer/utils.ts","../../src/components/CheckBox/CheckBox.tsx","../../src/components/CheckBox/CheckboxList.tsx","../../src/components/Radio/Radio.tsx","../../src/components/IconRender/IconRender.tsx","../../src/assets/icons/subjects/ChatPT.tsx","../../src/assets/icons/subjects/ChatEN.tsx","../../src/assets/icons/subjects/ChatES.tsx","../../src/assets/icons/subjects/BookOpenText.tsx","../../src/assets/icons/subjects/Microscope.tsx","../../src/assets/icons/subjects/HeadCircuit.tsx","../../src/components/Alternative/Alternative.tsx","../../src/utils/questionRenderer/alternative/index.tsx","../../src/components/MultipleChoice/MultipleChoice.tsx","../../src/utils/questionRenderer/multipleChoice/index.tsx","../../src/components/Quiz/QuizContent.tsx","../../src/components/Quiz/Quiz.utils.ts","../../src/utils/stringUtils.ts","../../src/components/Select/Select.tsx","../../src/utils/questionRenderer/trueOrFalse/index.tsx","../../src/utils/questionRenderer/components/index.tsx","../../src/utils/questionRenderer/dissertative/index.tsx","../../src/utils/questionRenderer/fill/index.tsx","../../src/utils/questionRenderer/image/index.tsx","../../src/utils/questionRenderer/connectDots/index.tsx","../../src/utils/questionRenderer/index.tsx","../../src/types/questionTypes.ts","../../src/components/FillInBlanks/FillInBlanks.tsx","../../src/utils/parseContent.ts","../../src/components/ConnectDots/ConnectDots.tsx"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport { syncDropdownState } from './dropdown';\nexport {\n getSelectedIdsFromCategories,\n toggleArrayItem,\n toggleSingleValue,\n areFiltersEqual,\n} from './activityFilters';\nexport {\n mapQuestionTypeToEnum,\n mapQuestionTypeToEnumRequired,\n} from './questionTypeUtils';\nexport {\n getStatusBadgeConfig,\n formatTimeSpent,\n formatQuestionNumbers,\n formatDateToBrazilian,\n} from './activityDetailsUtils';\n\n/**\n * Format a number as a rounded percentage string\n * @param value - Number to format (0-100)\n * @returns Formatted string with % suffix (e.g., \"72%\")\n */\nexport function formatPercentageRounded(value: number): string {\n return `${Math.round(value)}%`;\n}\n\nexport { formatScore } from './formatScore';\n\n/**\n * Convert hex color to rgba with opacity for background\n * @param hex - Hex color (e.g., \"#4B0082\")\n * @param opacity - Opacity value (0-1)\n * @returns rgba string\n */\nexport function hexToRgba(hex: string, opacity: number): string {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n if (!result) return `rgba(107, 114, 128, ${opacity})`; // fallback gray\n const r = Number.parseInt(result[1], 16);\n const g = Number.parseInt(result[2], 16);\n const b = Number.parseInt(result[3], 16);\n return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n}\n\n/**\n * Maps Tailwind bg-* class to CSS variable\n * @param bgClass - Tailwind background class (e.g., \"bg-error-600\")\n * @returns CSS variable string (e.g., \"var(--color-error-600)\")\n */\nexport function bgClassToCssVar(bgClass: string): string {\n return `var(--color-${bgClass.replace('bg-', '')})`;\n}\n\n/**\n * Converts polar coordinates to Cartesian for SVG arc path calculations.\n * Angles are in degrees, with 0° at the top (12 o'clock position).\n * @param cx - Center X coordinate\n * @param cy - Center Y coordinate\n * @param r - Radius\n * @param angleDeg - Angle in degrees\n * @returns Cartesian coordinates { x, y }\n */\nexport function polarToCartesian(\n cx: number,\n cy: number,\n r: number,\n angleDeg: number\n): { x: number; y: number } {\n const rad = ((angleDeg - 90) * Math.PI) / 180;\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };\n}\n\n/**\n * Generates an SVG filled arc (pie slice) path string.\n * @param cx - Center X coordinate\n * @param cy - Center Y coordinate\n * @param r - Radius\n * @param startAngle - Start angle in degrees\n * @param endAngle - End angle in degrees\n * @returns SVG path string for the arc\n */\nexport function describeArc(\n cx: number,\n cy: number,\n r: number,\n startAngle: number,\n endAngle: number\n): string {\n const span = endAngle - startAngle;\n\n // For full circle (or near-full), use two arcs to avoid SVG arc degeneracy\n if (span >= 359.99) {\n const midAngle = startAngle + 180;\n const s = polarToCartesian(cx, cy, r, startAngle);\n const m = polarToCartesian(cx, cy, r, midAngle);\n return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 1 1 ${m.x} ${m.y} A ${r} ${r} 0 1 1 ${s.x} ${s.y} Z`;\n }\n\n const s = polarToCartesian(cx, cy, r, endAngle);\n const e = polarToCartesian(cx, cy, r, startAngle);\n const largeArc = span > 180 ? 1 : 0;\n return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 ${largeArc} 0 ${e.x} ${e.y} Z`;\n}\n\n/**\n * Retorna a cor hexadecimal com opacidade 0.3 (4d) se não estiver em dark mode.\n * Se estiver em dark mode, retorna a cor original.\n *\n * @param hexColor - Cor hexadecimal (ex: \"#0066b8\" ou \"0066b8\")\n * @param isDark - booleano indicando se está em dark mode\n * @returns string - cor hexadecimal com opacidade se necessário\n */\nexport function getSubjectColorWithOpacity(\n hexColor: string | undefined,\n isDark: boolean\n): string | undefined {\n if (!hexColor) return undefined;\n // Remove o '#' se existir\n let color = hexColor.replace(/^#/, '').toLowerCase();\n\n if (isDark) {\n // Se está em dark mode, sempre remove opacidade se existir\n if (color.length === 8) {\n color = color.slice(0, 6);\n }\n return `#${color}`;\n } else {\n // Se não está em dark mode (light mode)\n let resultColor: string;\n if (color.length === 6) {\n // Adiciona opacidade 0.3 (4D) para cores de 6 dígitos\n resultColor = `#${color}4d`;\n } else if (color.length === 8) {\n // Já tem opacidade, retorna como está\n resultColor = `#${color}`;\n } else {\n // Para outros tamanhos (3, 4, 5 dígitos), retorna como está\n resultColor = `#${color}`;\n }\n return resultColor;\n }\n}\n","import { ComponentPropsWithRef, ElementType, ReactNode } from 'react';\nimport { cn } from '../../utils/utils';\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<ComponentPropsWithRef<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 *\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: string;\n let weightClasses: string;\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={cn(baseClasses, sizeClasses, weightClasses, color, className)}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n","import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n primary:\n 'bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed',\n secondary:\n 'bg-text-950 text-text border border-text-800 hover:bg-text-800 hover:border-text-950 focus-visible:outline-none focus-visible:bg-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-text-700 active:border-text-700 disabled:bg-text-500 disabled:border-text-500 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n outline: {\n primary:\n 'bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n secondary:\n 'bg-transparent text-text-950 border border-text-800 hover:bg-background-50 hover:text-text-700 hover:border-text-700 focus-visible:border-0 focus-visible:outline-none focus-visible:text-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-text-700 active:border-text-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n link: {\n primary:\n 'bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n secondary:\n 'bg-transparent text-text-950 hover:text-text-800 focus-visible:outline-none focus-visible:text-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-text-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'text-xs px-3.5 py-2',\n small: 'text-sm px-4 py-2.5',\n medium: 'text-md px-5 py-2.5',\n large: 'text-lg px-6 py-3',\n 'extra-large': 'text-lg px-7 py-3.5',\n} as const;\n\n/**\n * Button component props interface\n */\ntype ButtonProps = {\n /** Content to be displayed inside the button */\n children: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Size of the button */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the button. Use 'raw' for no default styling */\n variant?: 'solid' | 'outline' | 'link' | 'raw';\n /** Action type of the button */\n action?: 'primary' | 'secondary' | 'positive' | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Button component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the button\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, secondary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard button HTML attributes\n * @returns A styled button element\n *\n * @example\n * ```tsx\n * <Button variant=\"solid\" action=\"primary\" size=\"medium\" onClick={() => console.log('clicked')}>\n * Click me\n * </Button>\n * ```\n */\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'primary',\n className = '',\n disabled,\n type = 'button',\n ...props\n },\n ref\n ) => {\n // Raw variant: no default styling, only className\n if (variant === 'raw') {\n return (\n <button\n ref={ref}\n className={className}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && (\n <span className=\"mr-2 flex items-center\">{iconLeft}</span>\n )}\n {children}\n {iconRight && (\n <span className=\"ml-2 flex items-center\">{iconRight}</span>\n )}\n </button>\n );\n }\n\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_ACTION_CLASSES[variant][action];\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-full cursor-pointer font-medium';\n\n return (\n <button\n ref={ref}\n className={cn(baseClasses, variantClasses, sizeClasses, className)}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && <span className=\"mr-2 flex items-center\">{iconLeft}</span>}\n {children}\n {iconRight && (\n <span className=\"ml-2 flex items-center\">{iconRight}</span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport default Button;\n","import {\n Button,\n getSubjectColorWithOpacity,\n IconRender,\n Text,\n} from '../../index';\nimport { Plus } from 'phosphor-react';\nimport { QUESTION_TYPE } from '../Quiz/useQuizStore';\nimport { prependLetterToHtml } from '../Quiz/Quiz.utils';\nimport {\n renderFromMap,\n type QuestionRendererMap,\n} from '../../utils/questionRenderer/index';\nimport { AlternativesList, type Alternative } from '../Alternative/Alternative';\nimport { OptionStatus } from '../../enums/Options';\nimport { MultipleChoiceList } from '../MultipleChoice/MultipleChoice';\nimport { FillInBlanks } from '../FillInBlanks/FillInBlanks';\nimport { ConnectDots } from '../ConnectDots/ConnectDots';\nimport { useMemo } from 'react';\nimport { questionTypeLabels } from '../../types/questionTypes';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\n\ninterface QuestionOption {\n id: string;\n option: string;\n isCorrect?: boolean;\n correctValue?: string | null;\n}\n\ninterface QuestionData {\n options: QuestionOption[];\n correctOptionIds?: string[];\n}\n\ninterface ActivityCardQuestionBanksProps {\n question?: QuestionData;\n questionType?: QUESTION_TYPE;\n iconName?: string;\n subjectColor?: string;\n isDark?: boolean;\n onAddToActivity?: () => void;\n content?: string;\n bank?: string;\n year?: string;\n statement?: string;\n additionalContent?: string | null;\n /** Enable exam mode - changes text labels from 'atividade' to 'prova' */\n enableExamMode?: boolean;\n}\n\nexport const ActivityCardQuestionBanks = ({\n question,\n questionType,\n iconName = 'BookOpen',\n subjectColor = '#000000',\n isDark = false,\n onAddToActivity,\n content,\n bank,\n year,\n statement,\n additionalContent,\n enableExamMode = false,\n}: ActivityCardQuestionBanksProps = {}) => {\n // Transform question options into Alternative format for teacher view\n const alternatives = useMemo(() => {\n if (!question?.options || questionType !== QUESTION_TYPE.ALTERNATIVA)\n return [];\n\n const correctOptionIds = question.correctOptionIds || [];\n\n return question.options.map((option) => {\n // Check isCorrect from option, fallback to correctOptionIds\n const isCorrect =\n option.isCorrect ?? correctOptionIds.includes(option.id);\n return {\n value: option.id,\n label: option.option,\n status: isCorrect ? OptionStatus.CORRECT : undefined,\n disabled: !isCorrect,\n } satisfies Alternative;\n });\n }, [question, questionType]);\n\n const correctOptionId = useMemo(() => {\n if (!question?.correctOptionIds || question.correctOptionIds.length === 0) {\n return undefined;\n }\n return question.correctOptionIds[0];\n }, [question]);\n\n // Transform question options into MultipleChoice format for teacher view\n const multipleChoices = useMemo(() => {\n if (!question?.options || questionType !== QUESTION_TYPE.MULTIPLA_ESCOLHA)\n return [];\n\n const correctOptionIds = question.correctOptionIds || [];\n\n return question.options.map((option) => {\n // Check isCorrect from option, fallback to correctOptionIds\n const isCorrect =\n option.isCorrect ?? correctOptionIds.includes(option.id);\n return {\n value: option.id,\n label: option.option,\n status: isCorrect ? OptionStatus.CORRECT : undefined,\n disabled: !isCorrect,\n };\n });\n }, [question, questionType]);\n\n const correctOptionIds = useMemo(() => {\n return question?.correctOptionIds || [];\n }, [question]);\n\n // Helper function to get letter by index\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n // Render functions for each question type\n const renderAlternative = () => {\n if (!question || alternatives.length === 0) return null;\n return (\n <div className=\"mt-4\">\n <AlternativesList\n alternatives={alternatives}\n mode=\"readonly\"\n layout=\"compact\"\n selectedValue={correctOptionId}\n name=\"teacher-question-view\"\n />\n </div>\n );\n };\n\n const renderMultipleChoice = () => {\n if (!question || multipleChoices.length === 0) return null;\n return (\n <div className=\"mt-4\">\n <MultipleChoiceList\n choices={multipleChoices}\n mode=\"readonly\"\n selectedValues={correctOptionIds}\n name=\"teacher-question-view-multiple\"\n />\n </div>\n );\n };\n\n const renderDissertative = () => {\n return (\n <div className=\"mt-4 px-2 py-4\">\n <Text size=\"sm\" className=\"text-text-600 italic\">\n Resposta do aluno\n </Text>\n </div>\n );\n };\n\n const renderTrueOrFalse = () => {\n if (!question || question.options.length === 0) return null;\n return (\n <div className=\"mt-4\">\n <div className=\"flex flex-col gap-3.5\">\n {question.options.map((option, index) => {\n // For VERDADEIRO_FALSO, use isCorrect from option\n const isCorrect =\n option.isCorrect ?? correctOptionIds.includes(option.id);\n const correctAnswer = isCorrect ? 'Verdadeiro' : 'Falso';\n const letter = getLetterByIndex(index);\n const contentWithLetter = prependLetterToHtml(\n letter,\n option.option\n );\n\n return (\n <section key={option.id} className=\"flex flex-col gap-2\">\n <div className=\"flex flex-row justify-between items-start gap-2 p-2 rounded-md border border-border-200\">\n <HtmlMathRenderer\n content={contentWithLetter}\n className=\"text-text-900 text-sm flex-1\"\n />\n\n <Text\n size=\"sm\"\n className=\"text-text-700 shrink-0 whitespace-nowrap\"\n >\n Resposta correta: {correctAnswer}\n </Text>\n </div>\n </section>\n );\n })}\n </div>\n </div>\n );\n };\n\n // Transform options for ConnectDots component\n const connectDotsOptions = useMemo(() => {\n if (!question?.options || questionType !== QUESTION_TYPE.RELACIONAR)\n return [];\n return question.options\n .filter((opt) => opt.correctValue)\n .map((opt) => ({\n id: opt.id,\n option: opt.option,\n correctValue: opt.correctValue as string,\n }));\n }, [question?.options, questionType]);\n\n const renderConnectDots = () => {\n if (connectDotsOptions.length === 0) return null;\n\n return (\n <ConnectDots\n options={connectDotsOptions}\n mode=\"readonly\"\n className=\"mt-4\"\n />\n );\n };\n\n // Transform options for FillInBlanks component\n const fillInBlanksOptions = useMemo(() => {\n if (!question?.options) return [];\n return question.options.map((opt) => ({\n id: opt.id,\n option: opt.option,\n }));\n }, [question?.options]);\n\n const renderFill = () => {\n // For PREENCHER_LACUNAS, additionalContent contains the fill-in text with placeholders\n if (!additionalContent || fillInBlanksOptions.length === 0) return null;\n\n return (\n <FillInBlanks\n content={additionalContent}\n options={fillInBlanksOptions}\n mode=\"readonly\"\n className=\"mt-4\"\n />\n );\n };\n\n // Parse image coordinates from options for IMAGEM questions\n const imageCoordinates = useMemo(() => {\n if (\n questionType !== QUESTION_TYPE.IMAGEM ||\n !question?.options?.[0]?.option\n )\n return null;\n\n try {\n const coords = JSON.parse(question.options[0].option);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n return { x: coords.x, y: coords.y };\n }\n } catch {\n // Invalid JSON, return null\n }\n return null;\n }, [question?.options, questionType]);\n\n const renderImage = () => {\n if (!additionalContent) return null;\n return (\n <div className=\"mt-4 relative inline-block\">\n <img\n src={additionalContent}\n alt=\"Imagem da questão\"\n className=\"max-w-full h-auto rounded-md border border-border-200\"\n />\n {imageCoordinates && (\n <div\n className=\"absolute w-5 h-5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-success-500 border-2 border-white shadow-md\"\n style={{\n left: `${imageCoordinates.x}%`,\n top: `${imageCoordinates.y}%`,\n }}\n />\n )}\n </div>\n );\n };\n\n // Map question types to render functions\n const questionRenderers: QuestionRendererMap = {\n [QUESTION_TYPE.ALTERNATIVA]: renderAlternative,\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: renderMultipleChoice,\n [QUESTION_TYPE.DISSERTATIVA]: renderDissertative,\n [QUESTION_TYPE.VERDADEIRO_FALSO]: renderTrueOrFalse,\n [QUESTION_TYPE.RELACIONAR]: renderConnectDots,\n [QUESTION_TYPE.PREENCHER_LACUNAS]: renderFill,\n [QUESTION_TYPE.IMAGEM]: renderImage,\n };\n\n return (\n <div className=\"w-full flex flex-col gap-2 px-4 py-6\">\n <section className=\"flex flex-row gap-2 text-text-650\">\n <div className=\"py-1 px-2 flex flex-row items-center gap-1\">\n <span\n className=\"size-4 rounded-sm flex items-center justify-center shrink-0 text-text-950\"\n style={{\n backgroundColor: getSubjectColorWithOpacity(subjectColor, isDark),\n }}\n >\n <IconRender iconName={iconName} size={14} color=\"currentColor\" />\n </span>\n <Text size=\"sm\">{content || 'Assunto não informado'}</Text>\n </div>\n\n <div className=\"py-1 px-2 flex flex-row items-center gap-1\">\n <Text size=\"sm\" className=\"\">\n {questionType\n ? questionTypeLabels[questionType]\n : 'Tipo de questão'}\n </Text>\n </div>\n\n {(bank || year) && (\n <div className=\"py-1 px-2 flex flex-row items-center gap-1\">\n <Text size=\"sm\">{[bank, year].filter(Boolean).join(' - ')}</Text>\n </div>\n )}\n </section>\n\n <section className=\"flex flex-col gap-1\">\n {statement ? (\n <HtmlMathRenderer\n content={statement}\n className=\"text-text-950 text-md font-medium\"\n />\n ) : (\n <Text size=\"md\" weight=\"medium\" className=\"text-text-950 text-md\">\n Enunciado não informado\n </Text>\n )}\n\n {renderFromMap(questionRenderers, questionType)}\n </section>\n\n <section>\n <Button\n size=\"small\"\n variant=\"outline\"\n iconLeft={<Plus />}\n className=\"w-full\"\n onClick={() => {\n if (onAddToActivity) {\n onAddToActivity();\n }\n }}\n >\n {enableExamMode ? 'Adicionar à prova' : 'Adicionar à atividade'}\n </Button>\n </section>\n </div>\n );\n};\n","// Complete bundle index - includes all components\n// Individual imports still recommended for better tree-shaking\n\n// CSS import\nimport './styles.css';\n\n// Layout Components\nexport { PageContainer } from './components/PageContainer/PageContainer';\nexport type { PageContainerProps } from './components/PageContainer/PageContainer';\n\n// Basic Components\nexport { default as Text } from './components/Text/Text';\nexport { default as Button } from './components/Button/Button';\nexport { default as Badge } from './components/Badge/Badge';\nexport { default as Alert } from './components/Alert/Alert';\nexport { default as LatexRenderer } from './components/LatexRenderer/LatexRenderer';\nexport type { LatexRendererProps } from './components/LatexRenderer/LatexRenderer';\nexport {\n HtmlMathRenderer,\n processHtmlWithMath,\n sanitizeHtmlForDisplay,\n cleanLatex,\n containsMath,\n stripHtml,\n looksLikeLatex,\n isLikelyMarkdown,\n} from './components/HtmlMathRenderer';\nexport type {\n HtmlMathRendererProps,\n MathPart,\n} from './components/HtmlMathRenderer';\nexport {\n MarkdownMathRenderer,\n protectCurrencyInlineMath,\n reflowDisplayMath,\n} from './components/MarkdownMathRenderer';\nexport type { MarkdownMathRendererProps } from './components/MarkdownMathRenderer';\nexport { default as IconButton } from './components/IconButton/IconButton';\nexport { Tooltip } from './components/Tooltip/Tooltip';\nexport type { TooltipProps } from './components/Tooltip/Tooltip';\nexport { TruncatedText } from './components/TruncatedText/TruncatedText';\nexport type {\n TruncatedTextProps,\n TruncatedTextSize,\n TruncatedTextWeight,\n TruncatedTextTooltipPosition,\n} from './components/TruncatedText/TruncatedText';\nexport { default as IconRoundedButton } from './components/IconRoundedButton/IconRoundedButton';\nexport { default as NavButton } from './components/NavButton/NavButton';\nexport { default as SelectionButton } from './components/SelectionButton/SelectionButton';\nexport { default as CheckBox } from './components/CheckBox/CheckBox';\nexport { default as ToggleSwitch } from './components/ToggleSwitch/ToggleSwitch';\nexport type { ToggleSwitchProps } from './components/ToggleSwitch/ToggleSwitch';\nexport { default as ImageUpload } from './components/ImageUpload/ImageUpload';\nexport type { ImageUploadProps } from './components/ImageUpload/ImageUpload';\nexport { default as FileDropzone } from './components/FileDropzone/FileDropzone';\nexport type {\n FileDropzoneProps,\n FileType,\n} from './components/FileDropzone/FileDropzone';\nexport {\n default as CheckboxList,\n CheckboxListItem,\n} from './components/CheckBox/CheckboxList';\n\n// CheckboxGroup Component\nexport {\n CheckboxGroup,\n type CategoryConfig,\n type Item,\n} from './components/CheckBoxGroup/CheckBoxGroup';\nexport { AlertsManager } from './components/AlertManager/AlertsManager';\nexport { useAlertFormStore } from './components/AlertManager/useAlertForm';\nexport { AlertsManagerView } from './components/AlertManagerView/AlertsManagerView';\nexport type {\n AlertViewData,\n RecipientStatus,\n} from './components/AlertManagerView/AlertsManagerView';\nexport type {\n AlertsConfig,\n AlertData,\n RecipientItem,\n} from './components/AlertManager/types';\nexport { AppHeader } from './components/AppHeader/AppHeader';\nexport type {\n AppHeaderProps,\n AppHeaderUser,\n AppHeaderSessionInfo,\n AppHeaderNotifications,\n} from './components/AppHeader/AppHeader';\nexport { AppLayout } from './components/AppLayout/AppLayout';\nexport type {\n AppLayoutProps,\n AppLayoutMenuItem,\n} from './components/AppLayout/AppLayout';\nexport {\n default as Radio,\n RadioGroup,\n RadioGroupItem,\n} from './components/Radio/Radio';\nexport { default as TextArea } from './components/TextArea/TextArea';\nexport { default as Toast } from './components/Toast/Toast';\nexport { default as Toaster } from './components/Toast/utils/Toaster';\nexport { default as Divider } from './components/Divider/Divider';\nexport { default as useToastStore } from './components/Toast/utils/ToastStore';\nexport { default as Input } from './components/Input/Input';\nexport { default as ColorPicker } from './components/ColorPicker/ColorPicker';\nexport type { ColorPickerProps } from './components/ColorPicker/ColorPicker';\nexport { default as Search } from './components/Search/Search';\nexport { default as Chips } from './components/Chips/Chips';\nexport { default as ProgressBar } from './components/ProgressBar/ProgressBar';\nexport { default as ProgressCircle } from './components/ProgressCircle/ProgressCircle';\nexport { default as Stepper } from './components/Stepper/Stepper';\nexport { default as Calendar } from './components/Calendar/Calendar';\nexport { DateTimeInput } from './components/DateTimeInput';\nexport type { DateTimeInputProps } from './components/DateTimeInput';\nexport { default as Modal } from './components/Modal/Modal';\nexport { default as CorrectActivityModal } from './components/CorrectActivityModal/CorrectActivityModal';\nexport type { CorrectActivityModalProps } from './components/CorrectActivityModal/CorrectActivityModal';\nexport {\n QUESTION_STATUS as CORRECTION_QUESTION_STATUS,\n getQuestionStatusBadgeConfig,\n convertApiResponseToCorrectionData,\n} from './utils/studentActivityCorrection';\nexport type {\n QuestionStatus as CorrectionQuestionStatus,\n StudentQuestion,\n StudentActivityCorrectionData,\n QuestionsAnswersByStudentResponse,\n} from './utils/studentActivityCorrection';\n\n// FileAttachment Component\nexport { default as FileAttachment } from './components/FileAttachment/FileAttachment';\nexport {\n generateFileId,\n formatFileSize,\n} from './components/FileAttachment/FileAttachment';\nexport type {\n FileAttachmentProps,\n AttachedFile,\n} from './components/FileAttachment/FileAttachment';\n\nexport { AlertDialog } from './components/AlertDialog/AlertDialog';\nexport { default as LoadingModal } from './components/LoadingModal/loadingModal';\nexport { default as ProgressModal } from './components/ProgressModal/ProgressModal';\nexport type { ProgressModalProps } from './components/ProgressModal/ProgressModal';\nexport { default as ScoreCircle } from './components/ScoreCircle/ScoreCircle';\nexport type {\n ScoreCircleProps,\n ScoreCircleVariant,\n} from './components/ScoreCircle/ScoreCircle';\nexport { default as ImagePreviewCard } from './components/ImagePreviewCard/ImagePreviewCard';\nexport type { ImagePreviewCardProps } from './components/ImagePreviewCard/ImagePreviewCard';\nexport { default as NotificationCard } from './components/NotificationCard/NotificationCard';\nexport { default as CalendarCard } from './components/CalendarCard/CalendarCard';\nexport type { CalendarCardProps } from './components/CalendarCard/CalendarCard';\nexport { ThemeToggle } from './components/ThemeToggle/ThemeToggle';\n\n// Choropleth Map Component\nexport { default as ChoroplethMap } from './components/ChoroplethMap/ChoroplethMap';\nexport type {\n ChoroplethMapProps,\n RegionData,\n MapBounds,\n LegendItem,\n ColorClass,\n} from './components/ChoroplethMap/ChoroplethMap.types';\n\n// Map Data Hook\nexport { createUseMapData } from './hooks/useMapData';\nexport type { UseMapDataReturn } from './hooks/useMapData';\nexport { REPORT_PERIOD, REPORT_MODAL_VARIANT } from './types/common';\nexport type {\n MapFilters as MapDataFilters,\n MapDataRegion,\n MapDataApiResponse,\n MapDataBounds,\n} from './types/mapData';\n\n// Export notification card types\nexport type {\n NotificationItem,\n NotificationGroup,\n} from './components/NotificationCard/NotificationCard';\n\n// Subject Components\nexport {\n SubjectInfo,\n getSubjectInfo,\n getSubjectIcon,\n getSubjectColorClass,\n getSubjectName,\n} from './components/SubjectInfo/SubjectInfo';\nexport type {\n SubjectData,\n IconProps as SubjectIconProps,\n} from './components/SubjectInfo/SubjectInfo';\n\n// Notification Store\nexport {\n createNotificationStore,\n formatTimeAgo,\n} from './store/notificationStore';\nexport { createUseNotificationStore } from './hooks/useNotificationStore';\nexport {\n createUseNotifications,\n createNotificationsHook,\n} from './hooks/useNotifications';\nexport { NotificationEntityType } from './types/notifications';\nexport { questionTypeLabels } from './types/questionTypes';\nexport type {\n Notification,\n NotificationType,\n BackendNotification,\n BackendNotificationsResponse,\n NotificationsResponse,\n FetchNotificationsParams,\n NotificationApiClient,\n} from './types/notifications';\nexport type {\n NotificationState,\n NotificationActions,\n NotificationStore,\n} from './store/notificationStore';\n\n// Activity Filters Data Hook (consolidated hook for all filter data)\nexport {\n createUseActivityFiltersData,\n createActivityFiltersDataHook,\n} from './hooks/useActivityFiltersData';\nexport type {\n UseActivityFiltersDataReturn,\n UseActivityFiltersDataOptions,\n} from './hooks/useActivityFiltersData';\n\n// Questions List Hook\nexport {\n createUseQuestionsList,\n createQuestionsListHook,\n} from './hooks/useQuestionsList';\nexport { CreateActivity } from './components/ActivityCreate/ActivityCreate';\nexport {\n ActivityType,\n ActivityStatus,\n} from './components/ActivityCreate/ActivityCreate';\nexport type {\n ActivityData,\n BackendFiltersFormat,\n ActivityDraftResponse,\n ActivityPreFiltersInput,\n ActivityCreatePayload,\n ActivityCreateResponse,\n School,\n SchoolYear,\n Class,\n Student,\n} from './components/ActivityCreate/ActivityCreate';\n\n// RecommendedLessonCreate Component\nexport { RecommendedLessonCreate } from './components/RecommendedLessonCreate';\nexport type {\n LessonBackendFiltersFormat,\n RecommendedLessonDraftResponse,\n RecommendedLessonData,\n RecommendedLessonPreFiltersInput,\n RecommendedLessonCreatePayload,\n RecommendedLessonCreateResponse,\n} from './components/RecommendedLessonCreate';\nexport type { UseQuestionsListReturn } from './hooks/useQuestionsList';\nexport type {\n Question as QuestionActivity,\n Pagination,\n QuestionsFilterBody,\n QuestionOptionActivity,\n KnowledgeMatrixItemActivity,\n QuestionBankYearActivity,\n PaginationActivity,\n QuestionsListResponseActivity,\n} from './types/questions';\nexport { DIFFICULTY_LEVEL_ENUM, QUESTION_STATUS_ENUM } from './types/questions';\n\n// API Types\nexport type { BaseApiClient } from './types/api';\n\n// Theme Store\nexport { useThemeStore } from './store/themeStore';\nexport type { ThemeStore, ThemeState, ThemeActions } from './store/themeStore';\n\n// Storage Keys\nexport { KEYS, FEATURE_FLAGS_KEYS } from './utils/keys';\n\n// DropdownMenu Components\nexport {\n default as DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n ProfileMenuTrigger,\n ProfileMenuFooter,\n ProfileMenuHeader,\n ProfileMenuInfo,\n ProfileMenuSection,\n MenuLabel,\n DropdownMenuSeparator,\n ProfileToggleTheme,\n} from './components/DropdownMenu/DropdownMenu';\n\nexport {\n default as Table,\n TableHeader,\n TableBody,\n TableRow,\n TableHead,\n TableCell,\n TableFooter,\n TableCaption,\n TablePagination,\n useTableSort,\n} from './components/Table/Table';\nexport type {\n UseTableSortOptions,\n SortDirection,\n} from './components/Table/Table';\n\n// Filter Components\nexport { FilterModal, useTableFilter } from './components/Filter';\nexport type {\n FilterModalProps,\n FilterConfig,\n UseTableFilterOptions,\n UseTableFilterReturn,\n} from './components/Filter';\n\n// SimulatedFilters Components\nexport {\n SimulatedFiltersModal,\n StudentsFilterSection,\n useUserAccessData as useSimulatedUserAccessData,\n useStudentsFilter as useSimulatedStudentsFilter,\n} from './components/SimulatedFilters';\nexport type {\n SimulatedFilters,\n SimulatedFiltersModalProps,\n SchoolItem as SimulatedSchoolItem,\n SchoolYearItem as SimulatedSchoolYearItem,\n ClassItem as SimulatedClassItem,\n StudentFilterItem,\n StudentGroup,\n UserAccessDataApiResponse as SimulatedUserAccessDataApiResponse,\n StudentsFilterApiResponse as SimulatedStudentsFilterApiResponse,\n StudentsFilterParams,\n UseUserAccessDataState,\n UseUserAccessDataReturn,\n UseStudentsFilterState,\n UseStudentsFilterReturn,\n StudentsFilterSectionProps,\n} from './components/SimulatedFilters';\n\n// GeneralOverviewSection Component\nexport {\n GeneralOverviewSection,\n useGeneralOverview,\n} from './components/GeneralOverviewSection';\nexport type {\n AreaKnowledgePerformance,\n EssayPerformance,\n GeneralOverviewData,\n SubjectItem as GeneralOverviewSubjectItem,\n GeneralOverviewParams,\n GeneralOverviewApiResponse,\n UseGeneralOverviewState,\n UseGeneralOverviewReturn,\n GeneralOverviewSectionProps,\n GeneralOverviewLabels,\n} from './components/GeneralOverviewSection';\n\n// AreaKnowledgeSelector Component\nexport {\n AreaKnowledgeSelector,\n ESSAY_AREA_ID,\n} from './components/AreaKnowledgeSelector';\nexport type { AreaKnowledgeSelectorProps } from './components/AreaKnowledgeSelector';\n\n// SimulatedSubjectMenu Component\nexport {\n SimulatedSubjectMenu,\n useSimulatedSubjects,\n} from './components/SimulatedSubjectMenu';\nexport type {\n SimulatedSubjectItem,\n SimulatedSubjectsApiResponse,\n UseSimulatedSubjectsState,\n UseSimulatedSubjectsReturn,\n SimulatedSubjectMenuProps,\n} from './components/SimulatedSubjectMenu';\n\n// SimulatedStudentRanking Component\nexport {\n SimulatedStudentRanking,\n SimulatedRankingCard,\n} from './components/SimulatedStudentRanking';\nexport type {\n RankingVariant,\n SimulatedStudentRankingItem,\n SimulatedStudentRankingProps,\n SimulatedRankingCardProps,\n} from './components/SimulatedStudentRanking';\n\n// PerformanceDistributionChart Component\nexport { PerformanceDistributionChart } from './components/PerformanceDistributionChart';\nexport type {\n SimulatedPerformanceCounters,\n SliceData,\n PerformanceDistributionChartProps,\n} from './components/PerformanceDistributionChart';\n\n// SimulatedStudentDetailsModal Component\nexport {\n SimulatedStudentDetailsModal,\n useSimulatedStudentDetails,\n isStudentSubjectsData,\n isStudentContentsData,\n simulationTypeToActivityFilters,\n SIMULATED_PERFORMANCE_TAG_CONFIG,\n PERFORMANCE_TAG_TO_BADGE_ACTION,\n PerformanceBadgeAction,\n ReportSimulationType,\n} from './components/SimulatedStudentDetailsModal';\nexport type {\n SimulatedPerformanceTag,\n SimulatedPerformanceTagConfig,\n SimulationType,\n StudentDetailsInfo,\n SubjectPerformanceItem,\n StudentContentPerformanceItem,\n StudentSubjectsData,\n StudentContentsData,\n StudentDetailsData,\n ActivityFilters as SimulatedActivityFilters,\n StudentDetailsParams,\n StudentDetailsApiResponse,\n UseSimulatedStudentDetailsState,\n UseSimulatedStudentDetailsReturn,\n SimulatedStudentDetailsModalProps,\n} from './components/SimulatedStudentDetailsModal';\n\n// SimulatedContentsPerformance Hook\nexport { useSimulatedContents } from './components/SimulatedContentsPerformance';\nexport type {\n SimulatedContentItem,\n ContentsPerformanceData,\n SimulatedContentsParams,\n ContentsPerformanceApiResponse,\n UseSimulatedContentsState,\n UseSimulatedContentsReturn,\n} from './components/SimulatedContentsPerformance';\n\n// SimulatedContentDetailsModal Component\nexport {\n SimulatedContentDetailsModal,\n useSimulatedContentDetails,\n} from './components/SimulatedContentDetailsModal';\nexport type {\n ContentDetailsInfo,\n ContentPerformanceCounters,\n ContentStudentItem,\n ContentStudentsPaginated,\n ContentDetailsData,\n ContentDetailsParams,\n ContentDetailsApiResponse,\n UseSimulatedContentDetailsState,\n UseSimulatedContentDetailsReturn,\n SimulatedContentDetailsModalProps,\n} from './components/SimulatedContentDetailsModal';\n\n// EssayCompetencies Components\nexport {\n EssayCompetenciesTable,\n EssayCompetenceDetailsModal,\n useEssayCompetenciesOverview,\n useEssayCompetenceDetails,\n} from './components/EssayCompetencies';\nexport type {\n EssayCompetencyOverviewItem,\n EssayCompetenciesOverviewData,\n EssayCompetenciesOverviewParams,\n EssayCompetenciesOverviewApiResponse,\n EssayCompetenceInfo,\n EssayCompetenceCounters,\n EssayCompetenceStudentItem,\n EssayCompetenceStudentsPaginated,\n EssayCompetenceDetailsData,\n EssayCompetenceDetailsParams,\n EssayCompetenceDetailsApiResponse,\n UseEssayCompetenciesOverviewState,\n UseEssayCompetenciesOverviewReturn,\n UseEssayCompetenceDetailsState,\n UseEssayCompetenceDetailsReturn,\n EssayCompetenciesTableProps,\n EssayCompetenceDetailsModalProps,\n} from './components/EssayCompetencies';\n\n// SimulatedStudentsOverview Hook\nexport { useSimulatedOverview } from './components/SimulatedStudentsOverview';\nexport type {\n SimulatedStudentItem,\n SimulatedStudentsPaginated,\n SimulatedOverviewData,\n SimulatedOverviewParams,\n SimulatedOverviewApiResponse,\n UseSimulatedOverviewState,\n UseSimulatedOverviewReturn,\n} from './components/SimulatedStudentsOverview';\n\n// EssayStudentDetailsModal Component\nexport {\n EssayStudentDetailsModal,\n useEssayStudentDetails,\n} from './components/EssayStudentDetailsModal';\nexport type {\n EssayCompetencyPerformance,\n EssayStudentInfo,\n EssayStudentDetailsData,\n EssayStudentDetailsParams,\n EssayStudentDetailsApiResponse,\n UseEssayStudentDetailsState,\n UseEssayStudentDetailsReturn,\n EssayStudentDetailsLabels,\n EssayStudentDetailsModalProps,\n} from './components/EssayStudentDetailsModal';\n\n// ActivityFilters Component\nexport {\n ActivityFilters,\n ActivityFiltersPopover,\n} from './components/ActivityFilters/ActivityFilters';\nexport type {\n ActivityFiltersProps,\n ActivityFiltersPopoverProps,\n} from './components/ActivityFilters/ActivityFilters';\nexport type {\n ActivityFiltersData,\n Bank,\n BankYear,\n KnowledgeArea,\n KnowledgeItem,\n KnowledgeStructureState,\n} from './types/activityFilters';\n\nexport type { TablePaginationProps } from './components/Table/Table';\n\n// TableProvider Component\nexport { TableProvider } from './components/TableProvider';\nexport type {\n ColumnConfig,\n TableParams,\n PaginationConfig,\n TableProviderProps,\n EmptyStateConfig,\n} from './components/TableProvider';\n\n// Select Components\nexport {\n default as Select,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectItem,\n} from './components/Select/Select';\n\n// SearchSelect Component (Select with search functionality)\nexport { default as SearchSelect } from './components/SearchSelect/SearchSelect';\nexport type {\n SearchSelectProps,\n SearchSelectOption,\n SearchSelectPagination,\n} from './components/SearchSelect/SearchSelect';\n\n// TypeSelector Component (Activity/Exam type switcher)\nexport {\n TypeSelector,\n default as TypeSelectorDefault,\n} from './components/TypeSelector';\nexport type { TypeSelectorProps } from './components/TypeSelector';\nexport {\n type ActivityCategory,\n type ActiveTab,\n type TypeLabels,\n type TypeRoutes,\n type TypeConfig,\n ATIVIDADE_LABELS,\n PROVA_LABELS,\n DEFAULT_STATUS_OPTIONS,\n getTabPath,\n getTabFromPath,\n createActivityCategoryConfig,\n} from './components/TypeSelector';\n\n// Menu Components\nexport {\n default as Menu,\n MenuItem,\n MenuOverflow,\n MenuContent,\n} from './components/Menu/Menu';\n\n// PeriodSelector Component\nexport {\n PeriodSelector,\n Period,\n PERIOD_OPTIONS,\n} from './components/PeriodSelector';\nexport type {\n PeriodTab,\n PeriodValue,\n PeriodSelectorProps,\n} from './components/PeriodSelector';\n\n// Card Components\nexport {\n CardActivitiesResults,\n CardPerformance,\n CardProgress,\n CardQuestions,\n CardResults,\n CardSimulado,\n CardStatus,\n CardTopic,\n CardTest,\n CardSimulationHistory,\n CardAudio,\n CardEssayHistory,\n EssayStatus,\n EssayReviewStatus,\n} from './components/Card/Card';\nexport type {\n EssayHistoryItem,\n EssayHistoryData,\n} from './components/Card/Card';\nexport { StatisticsCard } from './components/StatisticsCard/StatisticsCard';\nexport {\n StudentRanking,\n RankingCard,\n} from './components/StudentRanking/StudentRanking';\nexport type {\n StudentRankingProps,\n StudentRankingItem,\n StudentRankingVariant,\n RankingCardProps,\n} from './components/StudentRanking/StudentRanking';\nexport { QuestionsData } from './components/QuestionsData/QuestionsData';\nexport type {\n QuestionsDataProps,\n QuestionsDataItem,\n} from './components/QuestionsData/QuestionsData';\n\n// Skeleton Components\nexport {\n Skeleton,\n SkeletonText,\n SkeletonCircle,\n SkeletonRectangle,\n SkeletonRounded,\n SkeletonCard,\n SkeletonList,\n SkeletonTable,\n} from './components/Skeleton/Skeleton';\n\n// Media Components\nexport { default as NotFound } from './components/NotFound/NotFound';\nexport { default as RestrictedAccess } from './components/RestrictedAccess/RestrictedAccess';\nexport type { RestrictedAccessProps } from './components/RestrictedAccess/RestrictedAccess';\nexport { default as TokenValidation } from './components/TokenValidation/TokenValidation';\nexport type { TokenValidationProps } from './components/TokenValidation/TokenValidation';\nexport { default as NoSearchResult } from './components/NoSearchResult/NoSearchResult';\nexport type { NoSearchResultProps } from './components/NoSearchResult/NoSearchResult';\nexport { default as EmptyState } from './components/EmptyState/EmptyState';\nexport type { EmptyStateProps } from './components/EmptyState/EmptyState';\nexport { default as VideoPlayer } from './components/VideoPlayer/VideoPlayer';\nexport { default as Whiteboard } from './components/Whiteboard/Whiteboard';\nexport { default as DownloadButton } from './components/DownloadButton/DownloadButton';\n\n// RichEditor - WYSIWYG editor with LaTeX support (requires @tiptap/* dependencies)\nexport { RichEditor } from './components/RichEditor/RichEditor';\nexport { FormulaDialog } from './components/RichEditor/components/FormulaDialog';\nexport { MathNode } from './components/RichEditor/components/MathNode';\nexport {\n processLatexInHtml,\n unprocessLatexInHtml,\n} from './components/RichEditor/components/utils';\nexport type {\n DownloadContent,\n DownloadButtonProps,\n} from './components/DownloadButton/DownloadButton';\n\n// Auth Components\nexport type { AuthContextType } from './components/Auth/Auth';\nexport {\n AuthProvider,\n ProtectedRoute,\n PublicRoute,\n withAuth,\n useAuth,\n useAuthGuard,\n useRouteAuth,\n getRootDomain,\n} from './components/Auth/Auth';\nexport { useTokenInUrl } from './components/Auth/useTokenInUrl';\nexport {\n CardAccordation,\n AccordionGroup,\n} from './components/Accordation/index';\nexport {\n AlternativesList,\n HeaderAlternative,\n} from './components/Alternative/Alternative';\nexport { createZustandAuthAdapter } from './components/Auth/zustandAuthAdapter';\nexport { useUrlAuthentication } from './components/Auth/useUrlAuthentication';\nexport { useApiConfig } from './components/Auth/useApiConfig';\n\n// Quiz Components\nexport { QuizVariant } from './components/Quiz/Quiz.types';\nexport {\n QuizTitle,\n Quiz,\n QuizHeader,\n QuizContent,\n QuizQuestionList,\n QuizFooter,\n} from './components/Quiz/Quiz';\nexport {\n getStatusBadge,\n QuizImageQuestion,\n QuizAlternative,\n QuizMultipleChoice,\n QuizDissertative,\n QuizTrueOrFalse,\n QuizConnectDots,\n} from './components/Quiz/QuizContent';\nexport {\n QuizHeaderResult,\n QuizListResult,\n QuizResultHeaderTitle,\n QuizResultTitle,\n QuizResultPerformance,\n QuizListResultByMateria,\n} from './components/Quiz/QuizResult';\nexport { TeacherFeedbackSection } from './components/Quiz/TeacherFeedbackSection';\nexport type { TeacherFeedbackSectionProps } from './components/Quiz/TeacherFeedbackSection';\nexport { useQuizStore } from './components/Quiz/useQuizStore';\nexport { formatExamInfo } from './components/Quiz/Quiz.utils';\n\n// Quiz Types and Enums\nexport {\n QUESTION_DIFFICULTY,\n QUESTION_TYPE,\n QUESTION_STATUS,\n ANSWER_STATUS,\n SUBTYPE_ENUM,\n QUIZ_TYPE,\n} from './components/Quiz/useQuizStore';\nexport { TrueFalseEnum } from './enums/Quiz';\nexport { SubjectEnum } from './enums/SubjectEnum';\nexport type {\n QuestionResult,\n Question,\n UserAnswerItem,\n QuizState,\n QuizInterface,\n DraftAnswerItem,\n SaveDraftPayload,\n DraftApiClient,\n} from './components/Quiz/useQuizStore';\n\n// Multiple Choice and Icon Components\nexport { MultipleChoiceList } from './components/MultipleChoice/MultipleChoice';\nexport { FillInBlanks } from './components/FillInBlanks/FillInBlanks';\nexport type {\n FillInBlanksProps,\n FillInBlanksOption,\n} from './components/FillInBlanks/FillInBlanks';\nexport { ConnectDots } from './components/ConnectDots/ConnectDots';\nexport type {\n ConnectDotsProps,\n ConnectDotsOption,\n} from './components/ConnectDots/ConnectDots';\nexport { default as IconRender } from './components/IconRender/IconRender';\n\n// Hooks\nexport { useMobile, getDeviceType } from './hooks/useMobile';\nexport type { DeviceType } from './hooks/useMobile';\nexport { useTheme } from './hooks/useTheme';\nexport type { ThemeMode } from './hooks/useTheme';\nexport { useBrandingLogo } from './hooks/useBrandingLogo';\nexport type {\n BrandingLogoVariant,\n UseBrandingLogoOptions,\n} from './hooks/useBrandingLogo';\nexport { BrandingLogo } from './components/BrandingLogo/BrandingLogo';\nexport type { BrandingLogoProps } from './components/BrandingLogo/BrandingLogo';\nexport { UserIcon } from './components/UserIcon/UserIcon';\nexport type { UserIconProps } from './components/UserIcon/UserIcon';\nexport { useDraftAutoSave } from './hooks/useDraftAutoSave';\nexport type {\n ApiClient as DraftApiClientAdapter,\n UseDraftAutoSaveOptions,\n} from './hooks/useDraftAutoSave';\nexport { useCep } from './hooks/useCep';\nexport type { CepData } from './hooks/useCep';\n\n// BreadcrumbMenu Components\nexport { BreadcrumbMenu } from './components/BreadcrumbMenu/BreadcrumbMenu';\nexport type { BreadcrumbMenuProps } from './components/BreadcrumbMenu/BreadcrumbMenu';\nexport { useBreadcrumbBuilder } from './components/BreadcrumbMenu/useBreadcrumbBuilder';\nexport type {\n BreadcrumbBuilderConfig,\n BreadcrumbLevel,\n BreadcrumbLevelWithData,\n BreadcrumbLevelStatic,\n} from './components/BreadcrumbMenu/useBreadcrumbBuilder';\nexport { useUrlParams } from './components/BreadcrumbMenu/useUrlParams';\nexport type { UrlParamsConfig } from './components/BreadcrumbMenu/useUrlParams';\nexport { useBreadcrumb } from './components/BreadcrumbMenu/breadcrumbStore';\nexport type { BreadcrumbItem } from './components/BreadcrumbMenu/breadcrumbStore';\n// Auth Hooks\nexport { useAppInitialization } from './hooks/useAppInitialization';\nexport { useAppContent } from './hooks/useAppContent';\nexport { useInstitutionId, useInstitution } from './hooks/useInstitution';\nexport type { InstitutionData } from './hooks/useInstitution';\nexport { useAuthStore } from './store/authStore';\nexport { useAppStore } from './store/appStore';\nexport { useQuestionFiltersStore } from './store/questionFiltersStore';\nexport type { QuestionFiltersState } from './store/questionFiltersStore';\nexport { useLessonFiltersStore } from './store/lessonFiltersStore';\nexport type { LessonFiltersState } from './store/lessonFiltersStore';\nexport { useModulesStore } from './store/modulesStore';\nexport type { ModulesState, ModulesConfig } from './store/modulesStore';\nexport { useModules } from './hooks/useModules';\nexport type { UseModulesReturn } from './hooks/useModules';\nexport { ModuleProtectedRoute } from './components/ModuleProtectedRoute';\nexport type { ModuleProtectedRouteProps } from './components/ModuleProtectedRoute';\nexport type {\n AuthState,\n SessionInfo,\n AuthTokens,\n User,\n UserProfile,\n} from './store/authStore';\nexport { ActivityCardQuestionBanks } from './components/ActivityCardQuestionBanks/ActivityCardQuestionBanks';\nexport { ActivityCardQuestionPreview } from './components/ActivityCardQuestionPreview/ActivityCardQuestionPreview';\nexport { ActivityListQuestions } from './components/ActivityListQuestions/ActivityListQuestions';\nexport type { ActivityListQuestionsProps } from './components/ActivityListQuestions/ActivityListQuestions';\nexport type {\n ActivityCardQuestionPreviewProps,\n MatchingPairPreview,\n} from './components/ActivityCardQuestionPreview/ActivityCardQuestionPreview';\nexport { ActivityPreview } from './components/ActivityPreview/ActivityPreview';\nexport type {\n ActivityPreviewProps,\n PreviewQuestion,\n} from './components/ActivityPreview/ActivityPreview';\n\nexport { LessonPreview } from './components/LessonPreview/LessonPreview';\nexport type {\n LessonPreviewProps,\n PreviewLesson,\n} from './components/LessonPreview/LessonPreview';\n\nexport {\n QuestionsPdfGenerator,\n QuestionsPdfContent,\n useQuestionsPdfPrint,\n} from './components/QuestionsPdfGenerator';\nexport type { QuestionsPdfGeneratorProps } from './components/QuestionsPdfGenerator';\n// Utils\nexport {\n cn,\n getSubjectColorWithOpacity,\n syncDropdownState,\n getSelectedIdsFromCategories,\n toggleArrayItem,\n toggleSingleValue,\n formatScore,\n formatPercentageRounded,\n} from './utils/utils';\nexport { convertActivityFiltersToQuestionsFilter } from './utils/questionFiltersConverter';\nexport {\n MASK_TYPE,\n applyInputMask,\n formatCep,\n formatCnpj,\n formatCpf,\n formatDocument,\n formatPhone,\n maskCepInput,\n maskCnpjInput,\n maskCpfInput,\n maskPhoneInput,\n} from './utils/brazilianFormatters';\nexport { BR_STATES_FULL, UF_LIST } from './utils/brazilianStates';\nexport type { UF } from './utils/brazilianStates';\nexport { default as MaskedInput } from './components/MaskedInput/MaskedInput';\nexport type { MaskedInputProps } from './components/MaskedInput/MaskedInput';\nexport { default as HierarchicalCheckboxGroup } from './components/HierarchicalCheckboxGroup/HierarchicalCheckboxGroup';\nexport type {\n HierarchicalCheckboxGroupItem,\n HierarchicalCheckboxGroupProps,\n HierarchicalCheckboxItem,\n HierarchicalCheckboxItemsLayout,\n} from './components/HierarchicalCheckboxGroup/HierarchicalCheckboxGroup';\nexport {\n mapQuestionTypeToEnum,\n mapQuestionTypeToEnumRequired,\n} from './utils/questionTypeUtils';\n// Activity Details Types\nexport {\n STUDENT_ACTIVITY_STATUS,\n ACTIVITY_AVAILABILITY,\n studentActivityStatusSchema,\n} from './types/activityDetails';\n\n// Lesson Availability Types\nexport { LESSON_AVAILABILITY } from './types/lessonAvailability';\nexport type {\n LessonAvailability,\n LessonAvailabilityResult,\n} from './types/lessonAvailability';\n\n// Lesson Availability Utils\nexport {\n checkLessonAvailability,\n isLessonNotYetAvailable,\n isLessonExpired,\n} from './utils/lessonAvailabilityUtils';\n\n// Activity Details Utils\nexport {\n getStatusBadgeConfig,\n formatTimeSpent,\n formatQuestionNumbers,\n formatDateToBrazilian,\n} from './utils/utils';\nexport type {\n StudentActivityStatus,\n ActivityAvailability,\n ActivityStudentData,\n Pagination as ActivityDetailsPagination,\n GeneralStats,\n QuestionStats,\n ActivityMetadata,\n ActivityDetailsData,\n ActivityDetailsQueryParams,\n ActivityStudentTableItem,\n StatusBadgeConfig,\n} from './types/activityDetails';\n\n// Activity Details Component\nexport { ActivityDetails } from './components/ActivityDetails/ActivityDetails';\nexport type { ActivityDetailsProps } from './components/ActivityDetails/ActivityDetails';\nexport { useActivityDetails } from './hooks/useActivityDetails';\nexport type { UseActivityDetailsReturn } from './hooks/useActivityDetails';\n\n// Support Components\nexport {\n Support,\n TicketModal,\n getCategoryIcon,\n supportSchema,\n} from './components/Support';\nexport type {\n SupportProps,\n TicketModalProps,\n SupportFormData,\n} from './components/Support';\n\n// Support Types\nexport {\n SupportStatus,\n SupportCategory,\n getStatusBadgeAction,\n getStatusText,\n getCategoryText,\n mapApiStatusToInternal,\n mapInternalStatusToApi,\n SupportType,\n} from './types/support';\nexport type {\n TicketStatus,\n ProblemType,\n TabType,\n SupportResponse,\n SupportTicket,\n CreateSupportTicketRequest,\n CreateSupportTicketResponse,\n SupportTicketAPI,\n SupportPagination,\n GetSupportTicketsResponse,\n SupportAnswerAPI,\n GetSupportAnswersResponse,\n SubmitSupportAnswerRequest,\n SubmitSupportAnswerResponse,\n SupportApiClient,\n SupportFeatureFlags,\n} from './types/support';\n\n// Zendesk Widget Component\nexport { ZendeskWidget } from './components/ZendeskWidget';\nexport type { ZendeskWidgetProps } from './components/ZendeskWidget';\n\n// Support Feature Flag Hook\nexport { useSupportFeatureFlag } from './hooks/useSupportFeatureFlag';\nexport type {\n UseSupportFeatureFlagConfig,\n UseSupportFeatureFlagReturn,\n} from './hooks/useSupportFeatureFlag';\n\n// SendActivityModal Component\nexport { SendActivityModal } from './components/SendActivityModal';\nexport { useSendActivityModal } from './components/SendActivityModal';\nexport type {\n SendActivityModalProps,\n SendActivityFormData,\n ActivitySubtype,\n StepErrors,\n StepState,\n StepConfig,\n SendActivityModalInitialData,\n} from './components/SendActivityModal';\nexport {\n validateActivityStep,\n validateRecipientStep,\n validateDeadlineStep,\n validateStep,\n isStepValid,\n isFormValid,\n ERROR_MESSAGES,\n} from './components/SendActivityModal';\n\n// ChooseActivityModelModal Component\nexport { ChooseActivityModelModal } from './components/ChooseActivityModelModal';\nexport type { ChooseActivityModelModalProps } from './components/ChooseActivityModelModal';\n\n// SaveActivityModelModal Component\nexport { SaveActivityModelModal } from './components/SaveActivityModelModal';\nexport type { SaveActivityModelModalProps } from './components/SaveActivityModelModal';\n\n// SendLessonModal Component\nexport { SendLessonModal } from './components/SendLessonModal';\nexport { useSendLessonModal } from './components/SendLessonModal';\nexport type {\n SendLessonModalProps,\n SendLessonFormData,\n StepErrors as SendLessonStepErrors,\n StepState as SendLessonStepState,\n StepConfig as SendLessonStepConfig,\n} from './components/SendLessonModal';\n\n// Recommended Lessons / RecommendedClass History Component\nexport {\n RecommendedLessonsHistory,\n RecommendedClassPageTab,\n} from './components/RecommendedLessonsHistory';\nexport type { RecommendedLessonsHistoryProps } from './components/RecommendedLessonsHistory';\n\n// Recommended Lesson Details Component\nexport {\n RecommendedLessonDetails,\n StudentPerformanceModal,\n} from './components/RecommendedLessonDetails';\nexport type {\n RecommendedLessonDetailsProps,\n StudentPerformanceModalProps,\n StudentPerformanceData,\n StudentPerformanceLabels,\n LessonProgress,\n LessonQuestion,\n QuestionAlternative,\n LessonDetailsLabels,\n DisplayStudent,\n} from './components/RecommendedLessonDetails';\n\n// Recommended Lessons Hook Factory\nexport {\n createUseRecommendedLessonsHistory,\n createRecommendedLessonsHistoryHook,\n determineRecommendedClassStatus,\n transformRecommendedClassToTableItem,\n handleRecommendedClassFetchError,\n recommendedClassHistoryApiResponseSchema,\n} from './hooks/useRecommendedLessons';\nexport type {\n UseRecommendedLessonsHistoryState,\n UseRecommendedLessonsHistoryReturn,\n} from './hooks/useRecommendedLessons';\n\n// Recommended Lessons Page Hook Factory\nexport {\n createUseRecommendedLessonsPage,\n createRecommendedLessonsPageHook,\n} from './hooks/useRecommendedLessonsPage';\nexport type {\n UseRecommendedLessonsPageConfig,\n UseRecommendedLessonsPageReturn,\n RecommendedLessonsApiClient,\n RecommendedLessonsUserData,\n RecommendedLessonsPagePaths,\n RecommendedLessonsPageEndpoints,\n RecommendedLessonsPageTexts,\n UserInstitution as RecommendedLessonsUserInstitution,\n SubTeacherTopicClass as RecommendedLessonsSubTeacherTopicClass,\n} from './hooks/useRecommendedLessonsPage';\n\n// Recommended Lesson Details Hook Factory\nexport {\n createUseRecommendedLessonDetails,\n createRecommendedLessonDetailsHook,\n handleLessonDetailsFetchError,\n recommendedClassApiResponseSchema,\n recommendedClassDetailsApiResponseSchema,\n historyApiResponseSchema,\n} from './hooks/useRecommendedLessonDetails';\nexport type {\n UseRecommendedLessonDetailsState,\n UseRecommendedLessonDetailsReturn,\n LessonDetailsApiClient,\n} from './hooks/useRecommendedLessonDetails';\n\n// Recommended Lessons Types\nexport {\n RecommendedClassApiStatus,\n RecommendedClassDisplayStatus,\n RecommendedClassBadgeActionType,\n getRecommendedClassStatusBadgeAction,\n RECOMMENDED_CLASS_FILTER_STATUS_OPTIONS,\n RECOMMENDED_CLASS_STATUS_OPTIONS,\n StudentLessonStatus,\n getStudentStatusBadgeAction,\n isDeadlinePassed,\n deriveStudentStatus,\n formatDaysToComplete,\n RecommendedClassDraftType,\n RECOMMENDED_CLASS_ACTIVITY_STATUS,\n} from './types/recommendedLessons';\nexport type {\n RecommendedClassSubject,\n RecommendedClassCreator,\n RecommendedClassStats,\n RecommendedClassBreakdown,\n RecommendedClassData,\n RecommendedClassHistoryItem,\n RecommendedClassTableItem,\n RecommendedClassHistoryApiResponse,\n RecommendedClassHistoryFilters,\n RecommendedClassHistoryPagination,\n RecommendedClassFilterOption,\n RecommendedClassUserFilterData,\n // Lesson Details API Types\n RecommendedClassDetailStudent,\n RecommendedClassDetailAggregated,\n RecommendedClassDetailContentPerformanceItem,\n RecommendedClassDetailContentPerformance,\n RecommendedClassDetailsData,\n RecommendedClassDetailsApiResponse,\n RecommendedClassLessonSubject,\n RecommendedClassLesson,\n RecommendedClassLessonProgress,\n RecommendedClassLessonsItem,\n RecommendedClassMetadata,\n RecommendedClassApiResponse,\n LessonDetailsData,\n // RecommendedClass Models Types\n RecommendedClassModelResponse,\n RecommendedClassModelTableItem,\n RecommendedClassModelsApiResponse,\n RecommendedClassModelFilters,\n RecommendedClassModelPagination,\n // RecommendedClass Activity Types\n RecommendedClassActivityStatus,\n RecommendedClassActivity,\n RecommendedClassSupUsersActivities,\n RecommendedClassActivities,\n} from './types/recommendedLessons';\n\n// RecommendedClass Models Hook Factory\nexport {\n createUseRecommendedClassModels,\n createRecommendedClassModelsHook,\n transformRecommendedClassModelToTableItem,\n handleRecommendedClassModelFetchError,\n recommendedClassModelsApiResponseSchema,\n DEFAULT_RECOMMENDED_CLASS_MODELS_PAGINATION,\n} from './hooks/useRecommendedClassModels';\nexport type {\n UseRecommendedClassModelsState,\n UseRecommendedClassModelsReturn,\n} from './hooks/useRecommendedClassModels';\n\n// RecommendedClass Drafts Hook Factory\nexport {\n createUseRecommendedClassDrafts,\n createRecommendedClassDraftsHook,\n handleRecommendedClassDraftFetchError,\n DEFAULT_RECOMMENDED_CLASS_DRAFTS_PAGINATION,\n} from './hooks/useRecommendedClassDrafts';\nexport type {\n UseRecommendedClassDraftsState,\n UseRecommendedClassDraftsReturn,\n} from './hooks/useRecommendedClassDrafts';\n\n// RecommendedClass Drafts Tab Component\nexport { RecommendedClassDraftsTab } from './components/RecommendedLessonsHistory/tabs/DraftsTab';\nexport type { RecommendedClassDraftsTabProps } from './components/RecommendedLessonsHistory/tabs/DraftsTab';\n\n// Activities History Component\nexport { ActivitiesHistory } from './components/ActivitiesHistory';\nexport type { ActivitiesHistoryProps } from './components/ActivitiesHistory';\n\n// Activity Page Layout Component\nexport {\n ActivityPageLayout,\n ActivityTab,\n} from './components/ActivityPageLayout';\nexport type { ActivityPageLayoutProps } from './components/ActivityPageLayout';\n\n// Unified History Page Component\nexport { UnifiedHistoryPage } from './components/UnifiedHistoryPage';\nexport type {\n UnifiedHistoryPageProps,\n UserData as UnifiedHistoryPageUserData,\n ApiFilterOptions as UnifiedHistoryPageApiFilterOptions,\n} from './components/UnifiedHistoryPage';\n\n// Unified Draft Model Page Component\nexport { UnifiedDraftModelPage } from './components/UnifiedDraftModelPage';\nexport type {\n UnifiedDraftModelPageProps,\n UserData as UnifiedDraftModelPageUserData,\n} from './components/UnifiedDraftModelPage';\n\n// Activities History Hook Factory\nexport {\n createUseActivitiesHistory,\n createActivitiesHistoryHook,\n transformActivityToTableItem,\n extractActivityFilterOptions,\n DEFAULT_ACTIVITIES_PAGINATION,\n DEFAULT_ACTIVITY_FILTER_OPTIONS,\n} from './hooks/useActivitiesHistory';\nexport type {\n UseActivitiesHistoryOptions,\n UseActivitiesHistoryState,\n UseActivitiesHistoryReturn,\n ActivityApiFilterOptions,\n} from './hooks/useActivitiesHistory';\n\n// Activity Drafts Hook Factory\nexport {\n createUseActivityDrafts,\n createActivityDraftsHook,\n transformDraftToTableItem as transformActivityDraftToTableItem,\n DEFAULT_DRAFTS_PAGINATION,\n} from './hooks/useActivityDrafts';\nexport type {\n UseActivityDraftsOptions,\n UseActivityDraftsState,\n UseActivityDraftsReturn,\n} from './hooks/useActivityDrafts';\n\n// Activity Models Hook Factory\nexport {\n createUseActivityModels,\n createActivityModelsHook,\n transformModelToTableItem,\n DEFAULT_MODELS_PAGINATION,\n} from './hooks/useActivityModels';\n\n// Activity Draft Model Page Hook (shared logic for drafts/models pages)\nexport { useActivityDraftModelPage } from './hooks/useActivityDraftModelPage';\nexport type {\n UseActivityDraftModelPageOptions,\n UseActivityDraftModelPageReturn,\n} from './hooks/useActivityDraftModelPage';\nexport type {\n UseActivityModelsOptions,\n UseActivityModelsState,\n UseActivityModelsReturn,\n} from './hooks/useActivityModels';\n\n// Students Highlight Hook Factory\nexport {\n createUseStudentsHighlight,\n createStudentsHighlightHook,\n calculatePerformancePercentage,\n transformStudentHighlightItem,\n handleStudentsHighlightFetchError,\n studentsHighlightApiResponseSchema,\n PERIOD_TABS,\n} from './hooks/useStudentsHighlight';\nexport type {\n StudentsHighlightPeriod,\n StudentsHighlightType,\n TrendDirection,\n StudentsHighlightFilters,\n StudentHighlightApiItem,\n StudentsHighlightApiResponse,\n StudentHighlightItem,\n UseStudentsHighlightState,\n UseStudentsHighlightReturn,\n} from './hooks/useStudentsHighlight';\n\n// Questions Data Hook Factory\nexport {\n createUseQuestionsData,\n createQuestionsDataHook,\n transformQuestionsData,\n handleQuestionsDataFetchError,\n questionsDataApiResponseSchema,\n} from './hooks/useQuestionsData';\nexport type {\n QuestionsDataPeriod,\n QuestionsDataTrendDirection,\n QuestionsDataFilters,\n QuestionsDataTrend,\n QuestionsDataApiData,\n QuestionsDataApiResponse,\n QuestionsDataHookResult,\n UseQuestionsDataState,\n UseQuestionsDataReturn,\n} from './hooks/useQuestionsData';\n\n// Activities History Types\nexport {\n ActivityApiStatus,\n ActivityDisplayStatus,\n ActivityBadgeActionType,\n ActivityDraftType,\n getActivityStatusBadgeAction,\n mapActivityStatusToDisplay,\n ACTIVITY_FILTER_STATUS_OPTIONS,\n} from './types/activitiesHistory';\nexport type {\n ActivityHistoryResponse,\n ActivityTableItem,\n ActivityPagination,\n ActivitiesHistoryApiResponse,\n ActivityHistoryFilters,\n ActivityDraftFilters,\n ActivityModelResponse,\n ActivityModelTableItem,\n ActivityModelsApiResponse,\n ActivityModelFilters,\n ActivityFilterOption,\n ActivityUserFilterData,\n} from './types/activitiesHistory';\n\n// Subject Mappers\nexport {\n mapSubjectNameToEnum,\n mapSubjectEnumToName,\n} from './utils/subjectMappers';\n\n// Subject Cell Renderer\nexport { renderSubjectCell } from './utils/renderSubjectCell';\nexport { renderTextCell } from './utils/renderTextCell';\n\n// Filter Helpers (robust version with deduplication)\nexport {\n getSchoolOptionsFromUserData,\n getSubjectOptionsFromUserData,\n getSchoolYearOptionsFromUserData,\n getClassOptionsFromUserData,\n buildUserFilterData,\n mergeFilterOptions,\n} from './utils/filterHelpers';\nexport type {\n UserInstitutionData,\n SubTeacherTopicClassData,\n UserFilterSourceData,\n} from './utils/filterHelpers';\n\n// Draft Model Filter Helpers\nexport { createDraftsModelsFiltersConfig } from './utils/draftModelFilterHelpers';\n\n// Pagination Types\nexport type { PaginationData } from './types/pagination';\n\n// Chat Hooks\nexport { useChat, createUseChat, WS_STATES } from './hooks/useChat';\nexport type { UseChatOptions, UseChatReturn } from './hooks/useChat';\nexport { useChatRooms, createUseChatRooms } from './hooks/useChatRooms';\nexport type {\n UseChatRoomsOptions,\n UseChatRoomsReturn,\n} from './hooks/useChatRooms';\n\n// Chat Types\nexport { CHAT_MESSAGE_TYPES, PROFILE_ROLES } from './types/chat';\nexport type {\n ChatMessageType,\n ChatUser,\n AvailableUsers,\n ChatRoom,\n ChatRoomWithDetails,\n ChatMessage,\n ChatParticipant,\n WSUserInfo,\n WSClientMessageType,\n WSServerMessageType,\n WSClientMessage,\n WSServerMessage,\n ChatApiClient,\n AvailableUsersResponse,\n CreateRoomResponse,\n GetRoomsResponse,\n GetRoomDetailsResponse,\n} from './types/chat';\n\n// Chat Component\nexport { Chat, ChatLoading } from './components/Chat';\nexport type { ChatProps } from './components/Chat';\n\n// Chat Utils\nexport {\n getChatWsUrl,\n getChatUserInfo,\n isChatUserInfoValid,\n} from './utils/chatUtils';\nexport type { ChatUserInfo } from './utils/chatUtils';\n\n// Chatbot Hook\nexport { createUseChatbot } from './hooks/useChatbot';\nexport type { UseChatbotReturn } from './hooks/useChatbot';\n\n// Chatbot Types\nexport { CHATBOT_MESSAGE_ROLES } from './types/chatbot';\nexport type {\n ChatbotRole,\n ChatbotMessage as ChatbotMessageData,\n ChatbotConversation,\n ChatbotCurrentContext,\n SendChatbotMessagePayload,\n SendChatbotMessageResult,\n ChatbotUser,\n ChatbotApiClient,\n} from './types/chatbot';\n\n// Chatbot Components\nexport {\n Chatbot,\n ChatbotFab,\n ChatbotPanel,\n ChatbotMessageList,\n ChatbotMessage,\n ChatbotInput,\n ChatbotTypingIndicator,\n ChatbotConversationList,\n ChatbotContentRenderer,\n} from './components/Chatbot';\nexport type {\n ChatbotProps,\n ChatbotFabProps,\n ChatbotPanelProps,\n ChatbotMessageListProps,\n ChatbotMessageProps,\n ChatbotInputProps,\n ChatbotTypingIndicatorProps,\n ChatbotConversationListProps,\n ChatbotContentRendererProps,\n} from './components/Chatbot';\n\n// Accessibility Widget\nexport {\n AccessibilityWidget,\n AccessibilityFab,\n AccessibilityPanel,\n LibrasFab,\n VLibrasLoader,\n ReadingAid,\n ColorBlindFilters,\n TTSController,\n WebSpeechProvider,\n} from './components/AccessibilityWidget';\nexport type {\n AccessibilityWidgetProps,\n AccessibilityFabProps,\n AccessibilityFabPosition,\n AccessibilityFabVerticalAlign,\n AccessibilityPanelProps,\n LibrasFabProps,\n TTSProvider,\n TTSVoice,\n TTSSpeakOptions,\n TTSProviderEvents,\n} from './components/AccessibilityWidget';\n\n// Accessibility Store + Hook\nexport {\n useAccessibilityStore,\n DEFAULT_ACCESSIBILITY_PREFERENCES,\n ColorBlindMode,\n getColorBlindClass,\n getColorBlindFilterId,\n} from './store/accessibilityStore';\nexport type {\n AccessibilityStore,\n AccessibilityState,\n AccessibilityActions,\n AccessibilityPreferences,\n ContrastMode,\n SaturationMode,\n FontSizeLevel,\n SpacingLevel,\n ReadingAid as ReadingAidMode,\n TTSMode,\n TTSStatus,\n} from './store/accessibilityStore';\nexport { useA11yPreferences } from './hooks/useA11yPreferences';\nexport { useA11yKeyboardShortcut } from './hooks/useA11yKeyboardShortcut';\nexport { useTTS } from './hooks/useTTS';\nexport type { UseTTSReturn } from './hooks/useTTS';\n\n// Forum Component\nexport { Forum } from './components/Forum/Forum';\nexport type { ForumProps } from './components/Forum/Forum';\n\n// Forum Hook\nexport { createUseForum } from './hooks/useForum';\nexport type { UseForumReturn } from './hooks/useForum';\n\n// Forum Types\nexport type {\n ForumPostBase,\n ForumTopic,\n ForumReply,\n ForumPagination,\n ForumTopicsResponse,\n ForumTopicDetailResponse,\n ForumApiClient,\n} from './types/forum';\n\n// General Activity Types (calendar, activity list)\nexport {\n ActivityStatus as GeneralActivityStatus,\n ActivityFilter,\n CalendarActivityStatus,\n} from './types/activities';\nexport type {\n Activity,\n CalendarActivity,\n ActivityResponse,\n CalendarActivitiesResponse,\n} from './types/activities';\n\n// Send Activity Hook\nexport { useSendActivity } from './hooks/useSendActivity';\nexport type {\n UseSendActivityConfig,\n UseSendActivityReturn,\n SendActivityCategoriesData,\n CreateActivityPayload,\n StudentPayload,\n ActivityModelItem,\n RecipientItem as SendActivityRecipientItem,\n} from './types/sendActivity';\n\n// Performance Types and Utils\nexport {\n PERFORMANCE_TAG_CONFIG,\n getPerformanceTag,\n getPerformanceTagConfig,\n} from './types/performance';\nexport { PerformanceTag } from './types/performance';\nexport type { PerformanceTagConfig, TimeInterval } from './types/performance';\n\n// Student Performance Details Modal\nexport { StudentPerformanceDetailsModal } from './components/StudentPerformanceDetailsModal';\nexport type {\n StudentPerformanceDetailsModalProps,\n StudentPerformanceDetailsData,\n StudentPerformanceDetailsLabels,\n ActivityProgress,\n} from './components/StudentPerformanceDetailsModal';\n\n// Student Lesson Progress Modal\nexport { StudentLessonProgressModal } from './components/StudentLessonProgressModal';\nexport type {\n StudentLessonProgressModalProps,\n StudentLessonProgressData,\n StudentLessonProgressLabels,\n TopicProgressItem,\n SubtopicProgressItem,\n ContentProgressItem,\n LessonProgressStatus,\n} from './components/StudentLessonProgressModal';\nexport { DEFAULT_LESSON_PROGRESS_LABELS } from './components/StudentLessonProgressModal';\n\n// TimeChart Components\nexport {\n TimeChart,\n TIME_CHART_CATEGORY_KEY,\n STUDENT_CATEGORIES,\n DEFAULT_CATEGORIES,\n calculateHourTicks,\n bgClassToCssVar,\n} from './components/TimeChart/TimeChart';\nexport type {\n TimeChartProps,\n TimeChartData,\n TimeChartCategory,\n TimeChartDayData,\n TimeChartRequest,\n TimeChartStudentPeriodItem,\n TimeChartStudentItemBreakdown,\n TimeChartStudentData,\n TimeChartDefaultPeriodItem,\n TimeChartDefaultItemBreakdown,\n TimeChartDefaultData,\n TimeChartResponse,\n} from './components/TimeChart/TimeChart';\n\n// TimeReport Components\nexport {\n TimeReport,\n TimeCard,\n formatHoursToTime,\n getTrendDirection,\n formatVariation,\n} from './components/TimeReport/TimeReport';\nexport type {\n TimeReportProps,\n TimeCardProps,\n TimeReportTab,\n TimeCardData,\n TimeCardTrend,\n TimeReportPeriod,\n TimeReportRequest,\n TimeMetric,\n TimeReportData,\n TimeReportResponse,\n} from './components/TimeReport/TimeReport';\n\n// PerformanceReport Components\nexport {\n PerformanceReport,\n PerformanceCard,\n} from './components/PerformanceReport/PerformanceReport';\nexport type {\n PerformanceReportProps,\n PerformanceCardProps,\n PerformanceReportTab,\n PerformanceCardData,\n PerformanceReportPeriod,\n PerformanceReportRequest,\n PerformanceStudentData,\n PerformanceDefaultData,\n PerformanceReportResponse,\n} from './components/PerformanceReport/PerformanceReport';\n\n// PerformanceQuestionsData Components\nexport {\n PerformanceQuestionsData,\n PerformanceQuestionsVariant,\n} from './components/PerformanceQuestionsData/PerformanceQuestionsData';\nexport type {\n PerformanceQuestionsDataProps,\n QuestionsVariantData,\n ContentVariantData,\n PerformanceFilterOption,\n PerformanceFilterConfig,\n PerformanceQuestionsPeriod,\n PerformanceQuestionsRequest,\n PerformanceQuestionsStudentResponse,\n PerformanceQuestionsDefaultResponse,\n} from './components/PerformanceQuestionsData/PerformanceQuestionsData';\n\n// PerformanceRanking Components\nexport { PerformanceRanking } from './components/PerformanceRanking/PerformanceRanking';\nexport type {\n PerformanceRankingProps,\n PerformanceRankingItem,\n PerformanceRankingData,\n GroupedBy,\n} from './components/PerformanceRanking/PerformanceRanking';\n\n// PerformanceReportModal Components\nexport {\n PerformanceReportModal,\n PerformanceReportModalVariant,\n} from './components/PerformanceReportModal/PerformanceReportModal';\nexport type {\n PerformanceReportModalProps,\n UserPerformanceRequest,\n UserPerformanceQuestionStats,\n UserPerformanceMaterialStats,\n UserPerformanceLesson,\n UserPerformanceStudentData,\n UserPerformanceProfessionalData,\n} from './components/PerformanceReportModal/PerformanceReportModal';\n\n// AccessReportModal Components\nexport {\n AccessReportModal,\n AccessReportModalVariant,\n} from './components/AccessReportModal/AccessReportModal';\nexport type {\n AccessReportModalProps,\n AccessReportStudentData,\n AccessReportProfessionalData,\n AccessReportTimePercentage,\n AccessReportUser,\n AccessReportByPlatform,\n} from './components/AccessReportModal/AccessReportModal';\n\n// DownloadModal Components\nexport { default as DownloadModal } from './components/DownloadModal/DownloadModal';\nexport { DOWNLOAD_FORMAT } from './enums/DownloadFormat';\nexport { FILTER_CATEGORY, FILTER_GROUP } from './enums/FilterEnums';\nexport type {\n DownloadModalProps,\n DownloadFormat,\n} from './components/DownloadModal/DownloadModal';\n\n// PrintableUsersTable Component\nexport { default as PrintableUsersTable } from './components/PrintableUsersTable/PrintableUsersTable';\nexport type { PrintableUsersTableProps } from './components/PrintableUsersTable/PrintableUsersTable';\n\n// Report Export Utils\nexport { downloadExcel } from './utils/exportExcel';\nexport { printAsPdf } from './utils/exportPdf';\n\n// Report Export Types\nexport type { ExcelCell, SheetConfig } from './utils/exportExcel';\n\n// SimulatedPerformance Component\nexport {\n useSimulatedPerformance,\n SimulatedPerformanceView,\n SCORE_TYPE_OPTIONS,\n SimulatedViewTab,\n} from './components/SimulatedPerformance';\nexport type {\n UseSimulatedPerformanceOptions,\n UseSimulatedPerformanceReturn,\n SimulatedPerformanceViewProps,\n} from './components/SimulatedPerformance';\n\n// ComparatorChart Components\nexport {\n // Base chart components\n Legend as ComparatorLegend,\n PercentageScale,\n ChartArea,\n BarChartRow,\n // Content components\n KnowledgeAreasContent,\n CurricularComponentsContent,\n CompetenciesContent,\n NationalAverageCard,\n NationalAveragesContent,\n // UI components\n ComparatorEmptyState,\n ComparatorLoadingState,\n ComparatorSelectTypeStep,\n ComparatorSelectItemsStep,\n ComparatorTabContent,\n // Main view\n ComparatorView,\n} from './components/ComparatorChart';\nexport type {\n LegendProps as ComparatorLegendProps,\n LegendItem as ComparatorLegendItem,\n ChartAreaProps,\n BarChartRowProps,\n BarChartValue,\n KnowledgeAreasContentProps,\n CurricularComponentsContentProps,\n CompetenciesContentProps,\n NationalAverageCardProps,\n NationalAveragesContentProps,\n ComparatorEmptyStateProps,\n ComparatorSelectTypeStepProps,\n ComparatorSelectItemsStepProps,\n ComparatorTabContentProps,\n ComparatorViewProps,\n} from './components/ComparatorChart';\n\n// Comparator Types\nexport {\n ComparatorTabValue,\n DEFAULT_COMPARATOR_LABELS,\n DEFAULT_COMPARATOR_TABS,\n COMPARATOR_CHART_COLORS,\n} from './types/comparator';\nexport type {\n ComparisonType,\n ComparatorTabType,\n ComparisonItem,\n KnowledgeAreaData,\n CurricularComponentData,\n CompetencyData,\n NationalAverageData,\n ComparatorData,\n ComparatorApiClient,\n ComparatorStoreState,\n UseComparatorReturn,\n ComparatorLabels,\n ComparatorTab,\n} from './types/comparator';\n\n// Comparator Hook\nexport {\n createUseComparator,\n createComparatorHook,\n} from './hooks/useComparator';\nexport type { UseComparatorConfig } from './hooks/useComparator';\n\n// Comparator Store\nexport {\n createComparatorStore,\n useComparatorStore,\n} from './store/comparatorStore';\nexport type { CreateComparatorStoreConfig } from './store/comparatorStore';\n\n// User Store\nexport { createUserStore } from './store/userStore';\nexport type {\n CreateUserStoreConfig,\n UserStoreApiClient,\n UserStoreState,\n} from './store/userStore';\n\n// User Types\nexport type {\n User as UserData,\n UserInfos,\n Profile,\n Institution,\n School as UserSchool,\n SchoolYear as UserSchoolYear,\n Class as UserClass,\n UserInstitution,\n Subject as UserSubject,\n SubTeacherTopicClass,\n MyDataResponse,\n UpdateMyDataRequest,\n UserTelemetryData,\n StudentDetailsResponse,\n} from './types/user';\n\n// Exam Types\nexport {\n ExamStatus,\n ExamDisplayStatus,\n mapExamStatusToDisplay,\n} from './types/examsHistory';\nexport type {\n ExamFilterOption,\n ExamApiFilterOptions,\n ExamSubject,\n ExamBreakdownItem,\n ExamHistoryResponse,\n ExamTableItem,\n ExamsHistoryApiResponse,\n ExamHistoryFilters,\n ExamPagination,\n} from './types/examsHistory';\n\nexport { ExamDraftType, ExamActivityCategory } from './types/examDrafts';\nexport type {\n ExamDraftFilters,\n ExamModelResponse,\n ExamModelTableItem,\n ExamModelsApiResponse,\n ExamModelFilters,\n ExamModelsPagination,\n} from './types/examDrafts';\n\n// Exam Hooks Factories\nexport {\n createUseExamsHistory,\n createExamsHistoryHook,\n transformExamToTableItem,\n handleExamFetchError,\n extractExamFilterOptions,\n DEFAULT_EXAMS_PAGINATION,\n DEFAULT_EXAM_FILTER_OPTIONS,\n} from './hooks/useExamsHistory';\nexport type {\n UseExamsHistoryState,\n UseExamsHistoryReturn,\n} from './hooks/useExamsHistory';\n\n// NOTE: useExamDrafts and useExamModels removed - use createUseActivityDrafts/createUseActivityModels with { activityCategory: 'PROVA' }\n\n// Exam Page Layout Component\nexport { ExamPageLayout, ExamTab } from './components/ExamPageLayout';\nexport type { ExamPageLayoutProps } from './components/ExamPageLayout';\n\n// Exam Table Configs\nexport {\n examsTableColumns,\n getExamStatusBadgeAction,\n createExamDraftsModelsTableColumns,\n} from './components/ExamPageLayout';\nexport type { ExamTableCallbacks } from './components/ExamPageLayout';\n\n// Answer Sheet Preview Components\nexport {\n AnswerSheetPreview,\n AnswerSheetsBatchPreview,\n AnswerSheetCard,\n CardContainer as AnswerSheetCardContainer,\n PageContainer as AnswerSheetPageContainer,\n PrintStyles as AnswerSheetPrintStyles,\n} from './components/ExamPageLayout';\nexport type {\n AnswerSheetPreviewProps,\n AnswerSheetsBatchPreviewProps,\n AnswerSheetData,\n AnswerSheetCardProps,\n} from './components/ExamPageLayout';\n\n// Exam Filter Helpers\nexport {\n EXAM_STATUS_OPTIONS,\n EXAM_FILTER_CATEGORY,\n EXAM_FILTER_GROUP,\n createExamDraftsModelsFiltersConfig,\n createExamHistoryFiltersConfig,\n} from './utils/examFilterHelpers';\n\n// Exam Details Types\nexport {\n StudentAnswerStatus,\n StudentAnswerDisplayStatus,\n} from './types/examDetails';\nexport type {\n ExamStudentResult,\n ExamStudentTableItem,\n ExamStats,\n ExamDetailsData,\n ExamDetailsPagination,\n ExamDetailsFilters,\n} from './types/examDetails';\n\n// Exam Details Hook Factory\nexport {\n createUseExamDetails,\n createExamDetailsHook,\n transformStudent,\n mapBackendStatusToFrontend,\n handleExamDetailsFetchError,\n DEFAULT_EXAM_DETAILS_PAGINATION,\n} from './hooks/useExamDetails';\nexport type {\n UseExamDetailsState,\n UseExamDetailsReturn,\n} from './hooks/useExamDetails';\n\n// Exam Details Layout Components\nexport {\n ExamDetailsHeader,\n ExamStatsCards,\n formatQuestions,\n ExamStudentsTable,\n createExamStudentsTableColumns,\n getExamStudentStatusBadgeAction,\n getExamStudentStatusDisplayText,\n ExamDetailsPage,\n} from './components/ExamDetailsLayout';\nexport type {\n ExamDetailsHeaderProps,\n ExamStatsCardsProps,\n ExamStudentsTableProps,\n ExamDetailsPageProps,\n} from './components/ExamDetailsLayout';\n","import { HTMLAttributes, ReactNode } from 'react';\nimport { Bell } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n error: 'bg-error-background text-error-700 focus-visible:outline-none',\n warning: 'bg-warning text-warning-800 focus-visible:outline-none',\n success: 'bg-success text-success-800 focus-visible:outline-none',\n info: 'bg-info text-info-800 focus-visible:outline-none',\n muted: 'bg-background-muted text-background-800 focus-visible:outline-none',\n },\n outlined: {\n error:\n 'bg-error text-error-700 border border-error-300 focus-visible:outline-none',\n warning:\n 'bg-warning text-warning-800 border border-warning-300 focus-visible:outline-none',\n success:\n 'bg-success text-success-800 border border-success-300 focus-visible:outline-none',\n info: 'bg-info text-info-800 border border-info-300 focus-visible:outline-none',\n muted:\n 'bg-background-muted text-background-800 border border-border-300 focus-visible:outline-none',\n },\n exams: {\n exam1: 'bg-exam-1 text-info-700 focus-visible:outline-none',\n exam2: 'bg-exam-2 text-typography-1 focus-visible:outline-none',\n exam3: 'bg-exam-3 text-typography-2 focus-visible:outline-none',\n exam4: 'bg-exam-4 text-success-700 focus-visible:outline-none',\n },\n examsOutlined: {\n exam1:\n 'bg-exam-1 text-info-700 border border-info-700 focus-visible:outline-none',\n exam2:\n 'bg-exam-2 text-typography-1 border border-typography-1 focus-visible:outline-none',\n exam3:\n 'bg-exam-3 text-typography-2 border border-typography-2 focus-visible:outline-none',\n exam4:\n 'bg-exam-4 text-success-700 border border-success-700 focus-visible:outline-none',\n },\n resultStatus: {\n negative: 'bg-error text-error-800 focus-visible:outline-none',\n positive: 'bg-success text-success-800 focus-visible:outline-none',\n },\n notification: 'text-primary',\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n small: 'text-2xs px-2 py-1',\n medium: 'text-xs px-2 py-1',\n large: 'text-sm px-2 py-1',\n} as const;\n\nconst SIZE_CLASSES_ICON = {\n small: 'size-3',\n medium: 'size-3.5',\n large: 'size-4',\n} as const;\n\n/**\n * Badge component props interface\n */\ntype BadgeProps = {\n /** Content to be displayed inside the badge */\n children?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Size of the badge */\n size?: 'small' | 'medium' | 'large';\n /** Visual variant of the badge */\n variant?:\n | 'solid'\n | 'outlined'\n | 'exams'\n | 'examsOutlined'\n | 'resultStatus'\n | 'notification';\n /** Action type of the badge */\n action?:\n | 'error'\n | 'warning'\n | 'success'\n | 'info'\n | 'muted'\n | 'exam1'\n | 'exam2'\n | 'exam3'\n | 'exam4'\n | 'positive'\n | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n notificationActive?: boolean;\n} & HTMLAttributes<HTMLDivElement>;\n\n/**\n * Badge component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the badge\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard div HTML attributes\n * @returns A styled badge element\n *\n * @example\n * ```tsx\n * <Badge variant=\"solid\" action=\"info\" size=\"medium\">\n * Information\n * </Badge>\n * ```\n */\nconst Badge = ({\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'error',\n className = '',\n notificationActive = false,\n ...props\n}: BadgeProps) => {\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const sizeClassesIcon = SIZE_CLASSES_ICON[size];\n const variantActionMap = VARIANT_ACTION_CLASSES[variant] || {};\n const variantClasses =\n typeof variantActionMap === 'string'\n ? variantActionMap\n : ((variantActionMap as Record<string, string>)[action] ??\n (variantActionMap as Record<string, string>).muted ??\n '');\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-xs font-normal gap-1 relative';\n\n const baseClassesIcon = 'flex items-center';\n if (variant === 'notification') {\n return (\n <div\n className={cn(baseClasses, variantClasses, sizeClasses, className)}\n {...props}\n >\n <Bell size={24} className=\"text-current\" aria-hidden=\"true\" />\n\n {notificationActive && (\n <span\n data-testid=\"notification-dot\"\n className=\"absolute top-[5px] right-[10px] block h-2 w-2 rounded-full bg-indicator-error ring-2 ring-white\"\n />\n )}\n </div>\n );\n }\n return (\n <div\n className={cn(baseClasses, variantClasses, sizeClasses, className)}\n {...props}\n >\n {iconLeft && (\n <span className={cn(baseClassesIcon, sizeClassesIcon)}>{iconLeft}</span>\n )}\n {children}\n {iconRight && (\n <span className={cn(baseClassesIcon, sizeClassesIcon)}>\n {iconRight}\n </span>\n )}\n </div>\n );\n};\n\nexport default Badge;\n","import { ReactNode } from 'react';\nimport katex from 'katex';\n\nexport interface KatexMathProps {\n /** LaTeX source to render */\n math: string;\n /** Render as centered display math (block) instead of inline */\n displayMode?: boolean;\n /** Called with the thrown error when KaTeX fails to parse `math` */\n renderError?: (error: unknown) => ReactNode;\n}\n\n/**\n * Renders a single LaTeX expression with KaTeX, calling `katex.renderToString`\n * directly instead of going through `react-katex`.\n *\n * Why not `react-katex`: when bundlers (Vite/esbuild dev optimizer, Rollup)\n * bundle `react-katex` they inline their OWN copy of KaTeX whose function\n * registry ends up broken — symbols render but `\\`-commands (`\\frac`, `\\cdot`,\n * `\\left`, ...) fail with a parse error. Importing `katex` directly here uses\n * the shared, correctly-bundled KaTeX (the same one `rehype-katex` uses), so\n * every command renders. See HtmlMathRenderer for the surrounding pipeline.\n */\nexport const KatexMath = ({\n math,\n displayMode = false,\n renderError,\n}: KatexMathProps) => {\n let html: string;\n try {\n html = katex.renderToString(math, {\n displayMode,\n throwOnError: true,\n });\n } catch (error_) {\n return <>{renderError ? renderError(error_) : null}</>;\n }\n\n const Tag = displayMode ? 'div' : 'span';\n return (\n <Tag\n data-testid=\"react-katex\"\n // KaTeX output is sanitized markup it generates itself from the parsed\n // LaTeX; there is no untrusted HTML passthrough here.\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n};\n\nexport default KatexMath;\n","import { CSSProperties, forwardRef, memo, ReactNode, Ref } from 'react';\nimport 'katex/dist/katex.min.css';\nimport { KatexMath } from './KatexMath';\nimport { cn } from '../../utils/utils';\nimport MarkdownMathRenderer from '../MarkdownMathRenderer/MarkdownMathRenderer';\nimport {\n isLikelyMarkdown,\n processHtmlWithMath,\n sanitizeHtmlForDisplay,\n} from './utils';\n\nexport interface HtmlMathRendererProps {\n /** HTML content to render, may contain LaTeX math expressions */\n content: string;\n /** Additional CSS class names */\n className?: string;\n /** Inline styles */\n style?: CSSProperties;\n /** Whether to sanitize HTML before rendering (default: true) */\n sanitize?: boolean;\n /** Custom error renderer for math errors */\n renderMathError?: (latex: string) => ReactNode;\n /** Test ID for testing */\n testId?: string;\n /** Whether to render as inline element (span) instead of block (div). Use when inside labels or other phrasing content. */\n inline?: boolean;\n}\n\n/**\n * HtmlMathRenderer - Renders HTML content with LaTeX math expressions\n *\n * Supports multiple LaTeX formats:\n * - Display mode: $$...$$ (centered block)\n * - Inline mode: $...$ (inline with text)\n * - LaTeX tags: <latex>...</latex>\n * - Editor spans: <span class=\"math-formula\" data-latex=\"...\">\n * - Legacy spans: <span class=\"math-expression\" data-math=\"...\">\n * - LaTeX environments: \\begin{...}...\\end{...}\n *\n * @example\n * ```tsx\n * <HtmlMathRenderer\n * content=\"<p>A fórmula é: $$x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}$$</p>\"\n * />\n * ```\n */\nconst HtmlMathRenderer = forwardRef<HTMLElement, HtmlMathRendererProps>(\n (\n {\n content,\n className,\n style,\n sanitize = true,\n renderMathError,\n testId,\n inline = false,\n },\n ref\n ) => {\n // AI-generated questions/resolutions arrive as Markdown + LaTeX. The HTML\n // pipeline below would render their `**`/`####`/`*` tokens literally and\n // collapse line breaks, so route that content to the Markdown renderer.\n // Inline usage stays on the HTML path to keep phrasing-content validity\n // (Markdown emits block elements: <p>, <ul>, <h4>, ...).\n //\n // Note: `renderMathError` is intentionally not forwarded here. The Markdown\n // path renders math via rehype-katex, which already degrades gracefully on\n // invalid LaTeX (KaTeX's built-in red error output) rather than throwing.\n // `renderMathError` is an HTML-path-only customization and is currently\n // unused by any consumer; honoring it on the Markdown path would require a\n // bespoke rehype plugin for no practical gain.\n if (!inline && content && isLikelyMarkdown(content)) {\n return (\n <MarkdownMathRenderer\n ref={ref as Ref<HTMLDivElement>}\n content={content}\n className={className}\n style={style}\n testId={testId}\n />\n );\n }\n\n const defaultErrorRenderer = (latex: string) => (\n <span className=\"text-error-600 text-sm\">Math Error: {latex}</span>\n );\n\n const errorRenderer = renderMathError || defaultErrorRenderer;\n\n const renderContent = () => {\n if (!content) return null;\n\n const processedContent = sanitize\n ? sanitizeHtmlForDisplay(content)\n : content;\n\n const parts = processHtmlWithMath(processedContent);\n\n // If all parts are text (or empty), render as plain HTML. Use the\n // joined parts (not the raw `processedContent`) so post-split fixes\n // applied inside `processHtmlWithMath` — like decoding `\\$` escapes\n // to literal `$` — actually reach the rendered output.\n if (parts.every((part) => part.type === 'text')) {\n const joinedHtml = parts.map((part) => part.content).join('');\n // Use span for inline mode to allow valid nesting in labels\n const Element = inline ? 'span' : 'div';\n return (\n <Element\n dangerouslySetInnerHTML={{\n __html: joinedHtml || processedContent,\n }}\n />\n );\n }\n\n // Generate stable keys based on content\n const getPartKey = (part: (typeof parts)[0], idx: number) => {\n const contentHash = (part.latex || part.content).slice(0, 20);\n return `${part.type}-${idx}-${contentHash}`;\n };\n\n return (\n <>\n {parts.map((part, index) => {\n const key = getPartKey(part, index);\n if (part.type === 'math' && part.latex) {\n return (\n <KatexMath\n key={key}\n math={part.latex}\n renderError={() => errorRenderer(part.latex!)}\n />\n );\n } else if (part.type === 'block-math' && part.latex) {\n // When inline mode, render inline to avoid block-level elements inside span\n if (inline) {\n return (\n <KatexMath\n key={key}\n math={part.latex}\n renderError={() => errorRenderer(part.latex!)}\n />\n );\n }\n return (\n <div key={key} className=\"my-2.5 text-center\">\n <KatexMath\n math={part.latex}\n displayMode\n renderError={() => errorRenderer(part.latex!)}\n />\n </div>\n );\n } else {\n return (\n <span\n key={key}\n dangerouslySetInnerHTML={{ __html: part.content }}\n />\n );\n }\n })}\n </>\n );\n };\n\n const sharedClassName = cn(\n // Base styles\n 'leading-relaxed',\n // Paragraph styles\n '[&_p]:mb-0',\n // Hide the KaTeX MathML accessibility layer visually (still readable\n // to screen readers). Tailwind preflight overrides the KaTeX default\n // `position: absolute; clip:...` rule, so the MathML layer ends up\n // duplicating every formula as raw text next to the visual render.\n '[&_.katex-mathml]:sr-only',\n // Table styles (only relevant for block mode, but harmless for inline)\n '[&_table]:border-collapse [&_table]:w-full [&_table]:my-2.5 [&_table]:table-auto',\n '[&_table_td]:border [&_table_td]:border-border-200 [&_table_td]:p-2 [&_table_td]:min-w-[50px] [&_table_td]:align-top',\n '[&_table_th]:border [&_table_th]:border-border-200 [&_table_th]:p-2 [&_table_th]:min-w-[50px] [&_table_th]:align-top [&_table_th]:bg-background-50 [&_table_th]:font-semibold',\n '[&_table_tr:nth-child(even)]:bg-background-50/50',\n '[&_table_tr:hover]:bg-background-100/50',\n // Image styles\n '[&_img]:max-w-full [&_img]:h-auto [&_img]:rounded-md [&_img]:my-2',\n // Link styles\n '[&_a]:text-primary-500 [&_a]:underline [&_a:hover]:text-primary-600',\n // Text formatting styles\n '[&_b]:font-bold [&_strong]:font-bold',\n '[&_i]:italic [&_em]:italic',\n '[&_u]:underline',\n className\n );\n\n if (inline) {\n return (\n <span\n ref={ref as Ref<HTMLSpanElement>}\n className={sharedClassName}\n style={style}\n data-testid={testId}\n >\n {renderContent()}\n </span>\n );\n }\n\n return (\n <div\n ref={ref as Ref<HTMLDivElement>}\n className={sharedClassName}\n style={style}\n data-testid={testId}\n >\n {renderContent()}\n </div>\n );\n }\n);\n\nHtmlMathRenderer.displayName = 'HtmlMathRenderer';\n\nexport default memo(HtmlMathRenderer);\n","import { CSSProperties, forwardRef, memo } from 'react';\nimport 'katex/dist/katex.min.css';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport { cn } from '../../utils/utils';\nimport { looksLikeLatex } from '../HtmlMathRenderer/utils';\n\nexport interface MarkdownMathRendererProps {\n /** Markdown content, may contain LaTeX math expressions ($...$ / $$...$$) */\n content: string;\n /** Additional CSS class names */\n className?: string;\n /** Inline styles */\n style?: CSSProperties;\n /** Test ID for testing */\n testId?: string;\n}\n\n/**\n * Strips zero-width / invisible characters that occasionally leak into\n * AI-generated content and break KaTeX parsing.\n */\nconst stripInvisibleChars = (str: string): string =>\n str.replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, '');\n\n/**\n * Escapes the `$` of inline `$...$` spans that do NOT look like real math, so\n * `remark-math` leaves them as literal text. Without this, currency prose like\n * \"R$ 15,00 ... R$ 42,00\" gets paired up and rendered as gibberish math.\n *\n * Reuses the exact `looksLikeLatex` heuristic the HTML renderer applies to\n * single-`$` spans, so both renderers agree on what is math vs currency.\n * Display math (`$$...$$`) is intentionally left untouched (handled below).\n */\nexport const protectCurrencyInlineMath = (markdown: string): string =>\n markdown.replaceAll(\n /(?<!\\\\)\\$(?!\\$)([^\\n$]+?)(?<!\\\\)\\$(?!\\$)/g,\n (match, inner: string) =>\n looksLikeLatex(inner) ? match : match.replaceAll('$', String.raw`\\$`)\n );\n\n/**\n * `remark-math` only renders a `$$...$$` block as centered display math when\n * the delimiters sit on their own lines (\"math flow\"). AI content usually puts\n * the whole equation on a single line (`$$x = y$$`), which would otherwise be\n * rendered inline. Reflow single-line `$$...$$` into block form so equations\n * stay centered, matching how the HTML renderer treats `$$`.\n */\nexport const reflowDisplayMath = (markdown: string): string =>\n markdown.replaceAll(\n /(?<!\\$)\\$\\$(?!\\$)([^\\n]+?)\\$\\$(?!\\$)/g,\n (_match, inner: string) => `\\n\\n$$\\n${inner.trim()}\\n$$\\n\\n`\n );\n\n/**\n * Runs `transform` over the markdown while shielding fenced code blocks and\n * inline code spans: each is stashed behind a placeholder, the transform runs\n * on the rest, then the originals are restored before the markdown reaches\n * react-markdown. Without this, the currency / display-math passes would\n * rewrite literal `$`/`$$` that authors put inside code samples (e.g. a fenced\n * block containing `price = $value`). The placeholder is purely transient (it\n * never reaches the markdown parser) and contains no `$`, so the passes ignore\n * it.\n */\nconst withProtectedCode = (\n markdown: string,\n transform: (input: string) => string\n): string => {\n const stash: string[] = [];\n const tokenized = markdown.replaceAll(\n /```[\\s\\S]*?```|`[^`\\n]*`/g,\n (segment) => {\n const token = `__CODE_SEG_${stash.length}__`;\n stash.push(segment);\n return token;\n }\n );\n return transform(tokenized).replaceAll(\n /__CODE_SEG_(\\d+)__/g,\n (_match, index: string) => stash[Number(index)]\n );\n};\n\nconst preprocessMarkdown = (content: string): string =>\n withProtectedCode(stripInvisibleChars(content), (safe) =>\n reflowDisplayMath(protectCurrencyInlineMath(safe))\n );\n\n/**\n * MarkdownMathRenderer - Renders Markdown content with embedded LaTeX math.\n *\n * Used for AI-generated questions and resolutions, which arrive as Markdown\n * (`**bold**`, `#### headings`, `* lists`, paragraphs) mixed with LaTeX\n * (`$...$` inline, `$$...$$` display). Built on `react-markdown` with\n * `remark-gfm` (tables/lists), `remark-math` + `rehype-katex` (math).\n *\n * SECURITY: raw HTML is intentionally NOT enabled (no `rehype-raw`). This\n * renderer only receives content classified as Markdown (no HTML tags) by\n * `isLikelyMarkdown`; HTML content keeps flowing through `HtmlMathRenderer`,\n * which sanitizes it. Adding raw-HTML support here would reintroduce an XSS\n * vector and requires a dedicated sanitization pipeline + security review.\n */\nconst MarkdownMathRenderer = forwardRef<\n HTMLDivElement,\n MarkdownMathRendererProps\n>(({ content, className, style, testId }, ref) => {\n const sharedClassName = cn(\n 'leading-relaxed',\n // Paragraph spacing\n '[&_p]:my-2 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0',\n // Headings\n '[&_h1]:text-xl [&_h1]:font-bold [&_h1]:mt-3 [&_h1]:mb-2',\n '[&_h2]:text-lg [&_h2]:font-bold [&_h2]:mt-3 [&_h2]:mb-2',\n '[&_h3]:text-base [&_h3]:font-semibold [&_h3]:mt-2.5 [&_h3]:mb-1.5',\n '[&_h4]:text-base [&_h4]:font-semibold [&_h4]:mt-2.5 [&_h4]:mb-1.5',\n '[&_h5]:font-semibold [&_h6]:font-semibold',\n // Lists\n '[&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-2',\n '[&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-2',\n '[&_li]:my-1 [&_li>ul]:my-1 [&_li>ol]:my-1',\n // Text formatting\n '[&_b]:font-bold [&_strong]:font-bold',\n '[&_i]:italic [&_em]:italic',\n '[&_u]:underline',\n '[&_blockquote]:border-l-4 [&_blockquote]:border-border-200 [&_blockquote]:pl-3 [&_blockquote]:text-text-700',\n '[&_code]:rounded [&_code]:bg-background-100 [&_code]:px-1 [&_code]:py-0.5 [&_code]:text-sm',\n // Hide the KaTeX MathML accessibility layer visually (still readable to\n // screen readers). Tailwind preflight overrides KaTeX's default clip\n // rule, so without this the MathML layer duplicates every formula as\n // raw text next to the visual render.\n '[&_.katex-mathml]:sr-only',\n // Display math spacing\n '[&_.katex-display]:my-2.5',\n // Tables (GFM)\n '[&_table]:border-collapse [&_table]:w-full [&_table]:my-2.5 [&_table]:table-auto',\n '[&_table_td]:border [&_table_td]:border-border-200 [&_table_td]:p-2 [&_table_td]:min-w-[50px] [&_table_td]:align-top',\n '[&_table_th]:border [&_table_th]:border-border-200 [&_table_th]:p-2 [&_table_th]:min-w-[50px] [&_table_th]:align-top [&_table_th]:bg-background-50 [&_table_th]:font-semibold',\n // Images and links\n '[&_img]:max-w-full [&_img]:h-auto [&_img]:rounded-md [&_img]:my-2',\n '[&_a]:text-primary-500 [&_a]:underline [&_a:hover]:text-primary-600',\n className\n );\n\n return (\n <div\n ref={ref}\n className={sharedClassName}\n style={style}\n data-testid={testId}\n >\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex]}\n >\n {preprocessMarkdown(content)}\n </ReactMarkdown>\n </div>\n );\n});\n\nMarkdownMathRenderer.displayName = 'MarkdownMathRenderer';\n\nexport default memo(MarkdownMathRenderer);\n","/**\n * Utilities for processing HTML content with LaTeX math expressions\n */\n\nexport interface MathPart {\n type: 'text' | 'math' | 'block-math';\n content: string;\n latex?: string;\n}\n\n/**\n * Generates a random ID for placeholder uniqueness\n * Uses crypto.randomUUID() (Web Crypto API - available in all modern browsers)\n */\nconst generateSecureRandomId = (): string => {\n return crypto.randomUUID();\n};\n\n/**\n * Cleans LaTeX string from invisible characters and decodes HTML entities\n * that the editor saved in place of math operators.\n *\n * Why decode here: KaTeX is a LaTeX parser, not an HTML parser. If the\n * source has `&lt;`/`&gt;` (because the editor HTML-escaped them on save)\n * KaTeX throws \"Expected 'EOF', got '&'\". `&lt;`/`&gt;` map to the\n * equivalent `\\lt`/`\\gt` commands. `&amp;` decodes back to a bare `&` \\u2014\n * NOT `\\&` \\u2014 because in LaTeX `&` is the alignment character (used by\n * `\\begin{align}`, matrices, etc.); rewriting it to `\\&` would break\n * alignment and stop already-escaped `\\&` from round-tripping.\n */\nexport const cleanLatex = (str: string): string => {\n return str\n .replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, '')\n .replaceAll(/&amp;lt;|&lt;/gi, String.raw`\\lt `)\n .replaceAll(/&amp;gt;|&gt;/gi, String.raw`\\gt `)\n .replaceAll(/&amp;amp;|&amp;/gi, '&')\n .trim();\n};\n\n/**\n * Heuristic that flags a string as \"likely real LaTeX math\" vs prose.\n * Used to reject `$...$` blocks that wrap regular text \\u2014 typically\n * happens when authors type `$` as a currency symbol and the renderer\n * pairs unrelated occurrences as math delimiters, sending Portuguese\n * prose to KaTeX (which then renders each letter as a math variable).\n *\n * Approach:\n * - Backslash commands / sub-super / grouping braces \\u2192 definitely math.\n * - Otherwise, treat it as PROSE only when it contains 2+ real words\n * (runs of 3+ letters). A sentence like \"15,00 pelo custo fixo\" has\n * many such words; genuine math \\u2014 `x = 1`, `a + b`, `1 < 2`, `f0`,\n * even a lone `abc` \\u2014 does not. This keeps normal spaced equations\n * rendering while still rejecting currency-`$` prose.\n */\nexport const looksLikeLatex = (str: string): boolean => {\n if (/[\\\\^_{}]/.test(str)) return true;\n const words = str.match(/[a-zA-Z]{3,}/g);\n if (words && words.length >= 2) return false;\n return true;\n};\n\n/**\n * HTML element names the backoffice RichEditor emits. Kept as a Set (instead\n * of a long regex alternation) so the tag-detection regex below stays simple\n * and cheap to reason about.\n */\nconst HTML_TAG_NAMES = new Set([\n 'p',\n 'div',\n 'span',\n 'br',\n 'b',\n 'strong',\n 'i',\n 'em',\n 'u',\n 's',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'a',\n 'img',\n 'table',\n 'thead',\n 'tbody',\n 'tfoot',\n 'tr',\n 'td',\n 'th',\n 'blockquote',\n 'pre',\n 'code',\n 'sub',\n 'sup',\n 'font',\n 'latex',\n]);\n\n/**\n * True when `content` contains a real HTML element tag (open or close) whose\n * name is one the editor produces. A single generic regex captures any\n * `<tag`/`</tag` candidate; membership is then checked against the Set, which\n * keeps the regex trivial and avoids a giant alternation.\n */\nconst containsHtmlTag = (content: string): boolean => {\n for (const match of content.matchAll(/<\\/?([a-z][a-z0-9]*)/gi)) {\n if (HTML_TAG_NAMES.has(match[1].toLowerCase())) return true;\n }\n return false;\n};\n\n/**\n * Heuristic that decides whether `content` is Markdown (as opposed to the\n * HTML the backoffice RichEditor produces). AI-generated questions and\n * resolutions arrive as Markdown + LaTeX (`**bold**`, `#### heading`,\n * `* lists`, `$...$`, `$$...$$`), whereas the editor stores HTML (`<p>`,\n * `<b>`, `<span class=\"math-formula\" data-latex=\"...\">`). The two sources are\n * cleanly separable, so we bias toward the proven HTML path:\n *\n * - If any real HTML element tag is present we return `false` and let\n * `HtmlMathRenderer` handle it exactly as before (math-formula spans,\n * currency heuristic, katex-error recovery, sanitization).\n * - Otherwise we return `true` only when an unmistakable Markdown marker is\n * present (ATX heading, bold, bullet/ordered list, GFM table, or a paragraph\n * break), which is what breaks today: Markdown rendered as HTML shows the raw\n * `**`/`####`/`*` tokens and collapses line breaks.\n *\n * Regex note: line-anchored signals use the `m` flag with `^` and restrict\n * horizontal whitespace to `[ \\t]` (never `\\s`, which also matches `\\n`). This\n * keeps each quantifier on a single line and avoids the super-linear\n * backtracking that `(?:^|\\n)\\s*…\\s+` can trigger across newlines.\n */\nexport const isLikelyMarkdown = (content: string): boolean => {\n if (!content) return false;\n\n // Presence of real HTML element tags => treat as HTML (RichEditor output).\n if (containsHtmlTag(content)) return false;\n\n const MARKDOWN_SIGNALS = [\n /^#{1,6}[ \\t]+\\S/m, // ATX heading (#, ##, ... ######)\n /\\*\\*[^*\\n]+\\*\\*/, // bold\n /__[^_\\n]+__/, // bold (underscore)\n /^[ \\t]*[-*+][ \\t]+\\S/m, // bullet list\n /^[ \\t]*\\d+\\.[ \\t]+\\S/m, // ordered list\n /\\|[ \\t]*:?-+:?[ \\t]*\\|/, // GFM table delimiter row (|---|---|)\n /\\n\\n/, // paragraph break (only reached when no HTML tag is present)\n ];\n return MARKDOWN_SIGNALS.some((pattern) => pattern.test(content));\n};\n\n/**\n * Recovers usable LaTeX source from `<span class=\"katex-error\">` wrappers\n * that previous editor cycles persisted into the database. The error's\n * `title` attribute carries the original LaTeX after \"at position N: \".\n * Replaces each wrapper with `$LATEX$` so downstream patterns can render\n * it cleanly via KaTeX.\n *\n * No-op outside browser contexts (no `document`).\n */\nconst recoverFromKatexErrorSpans = (htmlContent: string): string => {\n if (\n typeof document === 'undefined' ||\n !/class=\"[^\"]*katex-error/i.test(htmlContent)\n ) {\n return htmlContent;\n }\n\n const tempContainer = document.createElement('div');\n tempContainer.innerHTML = htmlContent;\n\n const sanitizeRecoveredLatex = (raw: string): string =>\n raw\n // Strip combining marks KaTeX puts in error titles at the error pos\n .replaceAll(/[\\u0300-\\u036F]/g, '')\n // Drop truncated tag markers leftover from broken serialization.\n // Done while literal `<`/`>` are still present (before they get\n // mapped to LaTeX commands below).\n .replaceAll(/<\\/?[a-zA-Z][a-zA-Z0-9]*\\s*>?$/g, '')\n // Map comparison operators to equivalent LaTeX commands. We match\n // both the entity forms AND the literal `<`/`>` characters: the\n // `title` attribute is entity-decoded by the DOM when read, so we\n // often get literal `<`/`>`. Mapping them to `\\lt`/`\\gt` also avoids\n // re-encoding to `&lt;`/`&gt;` on DOM serialization (which would make\n // `looksLikeLatex` reject the recovered block as non-math).\n // `&amp;` decodes to a bare `&` (the LaTeX alignment character), not\n // `\\&`, so `\\begin{align}` environments survive recovery.\n .replaceAll(/&amp;lt;|&lt;|</gi, String.raw`\\lt `)\n .replaceAll(/&amp;gt;|&gt;|>/gi, String.raw`\\gt `)\n .replaceAll(/&amp;amp;|&amp;/gi, '&')\n .trim();\n\n Array.from(tempContainer.querySelectorAll('.katex-error')).forEach(\n (errorNode) => {\n if (!tempContainer.contains(errorNode)) return;\n\n const title = errorNode.getAttribute('title') || '';\n // Note: no `\\s*` before the capture group — `\\s*(.+)` would let\n // whitespace be split ambiguously between the two, causing\n // super-linear backtracking (ReDoS). The capture is trimmed by\n // sanitizeRecoveredLatex below instead.\n const positionMatch = /at position\\s+\\d+:(.+)$/.exec(title);\n let recovered = positionMatch ? positionMatch[1] : '';\n\n if (!recovered) {\n // Fallback: collect from inner <annotation> elements, skipping the\n // visual `katex-html` layer to avoid duplicating Unicode glyphs.\n const parts: string[] = [];\n const walk = (n: Node) => {\n if (n.nodeType === Node.TEXT_NODE) {\n parts.push(n.textContent || '');\n return;\n }\n if (n.nodeType !== Node.ELEMENT_NODE) return;\n const el = n as Element;\n if (el.tagName.toLowerCase() === 'annotation') {\n parts.push(el.textContent || '');\n return;\n }\n if (el.classList.contains('katex-html')) return;\n Array.from(el.childNodes).forEach(walk);\n };\n Array.from(errorNode.childNodes).forEach(walk);\n recovered = parts.join(' ');\n }\n\n recovered = sanitizeRecoveredLatex(recovered);\n if (recovered) {\n errorNode.replaceWith(document.createTextNode(`$${recovered}$`));\n } else {\n errorNode.remove();\n }\n }\n );\n\n return tempContainer.innerHTML;\n};\n\n/**\n * Decodes `\\$` escape sequences to literal `$` characters. Applied only to\n * text fragments outside math blocks \\u2014 the `(?<!\\\\)` lookbehind in the\n * `$...$` matcher already skipped these, but the `\\` is still in the output\n * unless we decode it. Without this, currency strings like `R\\$ 130,00`\n * render with a visible backslash.\n */\nconst decodeDollarEscapes = (text: string): string =>\n text.replaceAll(String.raw`\\$`, '$');\n\n/**\n * Dangerous attributes that should be removed for XSS protection\n */\nconst DANGEROUS_ATTRIBUTES = new Set([\n 'contenteditable',\n 'srcdoc',\n 'formaction',\n 'xlink:href',\n]);\n\n/**\n * Dangerous URI schemes that should be removed from href/src attributes\n */\nconst DANGEROUS_URI_PATTERN = /^\\s*(javascript|vbscript|data):/i;\n\n/**\n * Sanitizes HTML content for safe display\n * Removes event handlers, dangerous attributes, script/style tags, and javascript: URIs\n */\nexport const sanitizeHtmlForDisplay = (htmlContent: string): string => {\n if (!htmlContent) return htmlContent;\n\n // Create a temporary div to parse HTML\n if (typeof document === 'undefined') {\n // Server-side: use regex-based sanitization as fallback\n let sanitized = htmlContent;\n // Remove script tags\n sanitized = sanitized.replaceAll(\n /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n ''\n );\n // Remove style tags\n sanitized = sanitized.replaceAll(\n /<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi,\n ''\n );\n // Remove on* event handlers (split into separate patterns to avoid ReDoS)\n sanitized = sanitized.replaceAll(/ on[a-z]+=\"[^\"]*\"/gi, '');\n sanitized = sanitized.replaceAll(/ on[a-z]+='[^']*'/gi, '');\n sanitized = sanitized.replaceAll(/ on[a-z]+=[^\\s>\"']+/gi, '');\n // Remove dangerous URI schemes (javascript, vbscript, data) - matching client-side DANGEROUS_URI_PATTERN\n sanitized = sanitized.replaceAll(\n / href=\"(?:javascript|vbscript|data):[^\"]*\"/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / href='(?:javascript|vbscript|data):[^']*'/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / src=\"(?:javascript|vbscript|data):[^\"]*\"/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / src='(?:javascript|vbscript|data):[^']*'/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / action=\"(?:javascript|vbscript|data):[^\"]*\"/gi,\n ''\n );\n sanitized = sanitized.replaceAll(\n / action='(?:javascript|vbscript|data):[^']*'/gi,\n ''\n );\n return sanitized;\n }\n\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = htmlContent;\n\n // Remove script and style tags entirely\n const dangerousTags = tempDiv.querySelectorAll(\n 'script, style, iframe, object, embed'\n );\n dangerousTags.forEach((element) => element.remove());\n\n // Process all elements\n const allElements = tempDiv.querySelectorAll('*');\n allElements.forEach((element) => {\n // Get all attribute names\n const attributeNames = element.getAttributeNames();\n\n attributeNames.forEach((attrName) => {\n const lowerAttrName = attrName.toLowerCase();\n\n // Remove all on* event handler attributes (onclick, onerror, onload, etc.)\n if (lowerAttrName.startsWith('on')) {\n element.removeAttribute(attrName);\n return;\n }\n\n // Remove dangerous attributes\n if (DANGEROUS_ATTRIBUTES.has(lowerAttrName)) {\n element.removeAttribute(attrName);\n return;\n }\n\n // Check href, src, and action for dangerous URIs\n if (\n lowerAttrName === 'href' ||\n lowerAttrName === 'src' ||\n lowerAttrName === 'action'\n ) {\n const value = element.getAttribute(attrName);\n if (value && DANGEROUS_URI_PATTERN.test(value)) {\n element.removeAttribute(attrName);\n }\n }\n });\n });\n\n return tempDiv.innerHTML;\n};\n\n/**\n * Processes HTML content and extracts math expressions\n * Returns an array of parts (text and math) for rendering\n */\nexport const processHtmlWithMath = (htmlContent: string): MathPart[] => {\n if (!htmlContent) return [];\n\n // Pre-pass: recover original LaTeX from any `katex-error` wrappers that\n // older editor saves left in the content. This turns persisted error HTML\n // into clean `$LATEX$` strings so the steps below can render them.\n let processedContent = recoverFromKatexErrorSpans(htmlContent);\n const parts: MathPart[] = [];\n\n // Generate unique sentinel per call to avoid collision with content\n const sentinel = `__MATH_${generateSecureRandomId()}_`;\n\n // Step 1: Handle math-formula spans (from the editor)\n const mathFormulaPattern =\n /<span[^>]*class=\"math-formula\"[^>]*data-latex=\"([^\"]*)\"[^>]*>[\\s\\S]*?<\\/span>/g;\n processedContent = processedContent.replaceAll(\n mathFormulaPattern,\n (match, latex) => {\n const isDisplayMode = match.includes('data-display-mode=\"true\"');\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: isDisplayMode ? 'block-math' : 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 2: Handle wrapped math expressions (from math modal - legacy)\n const wrappedMathPattern =\n /<span[^>]*class=\"math-expression\"[^>]*data-math=\"([^\"]*)\"[^>]*>.*?<\\/span>/g;\n processedContent = processedContent.replaceAll(\n wrappedMathPattern,\n (match, latex) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 3: Handle raw $$...$$ expressions (display mode) - BEFORE single $\n const doubleDollarPattern = /(?<!\\\\)\\$\\$([\\s\\S]+?)\\$\\$/g;\n processedContent = processedContent.replaceAll(\n doubleDollarPattern,\n (match, latex) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'block-math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 4: Handle single $...$ expressions for inline math.\n // Skip matches whose content doesn't look like LaTeX — those are usually\n // currency `$` symbols pairing up across prose (e.g. `R$ 15,00 ... R$ 42,00`)\n // and sending Portuguese text to KaTeX produces gibberish output.\n const singleDollarPattern = /(?<!\\\\)\\$([\\s\\S]+?)\\$/g;\n processedContent = processedContent.replaceAll(\n singleDollarPattern,\n (match, latex) => {\n if (!looksLikeLatex(latex)) return match;\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 5: Handle <latex>...</latex> tags for inline math\n const latexTagPattern =\n /(?:<latex>|&lt;latex&gt;)([\\s\\S]*?)(?:<\\/latex>|&lt;\\/latex&gt;)/g;\n processedContent = processedContent.replaceAll(\n latexTagPattern,\n (match, latex) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'math',\n content: match,\n latex: cleanLatex(latex),\n });\n return placeholder;\n }\n );\n\n // Step 6: Handle standalone LaTeX environments (align, equation, pmatrix, etc.)\n const latexEnvPattern = /\\\\begin\\{([^}]+)\\}([\\s\\S]*?)\\\\end\\{\\1\\}/g;\n processedContent = processedContent.replaceAll(latexEnvPattern, (match) => {\n const placeholder = `${sentinel}${parts.length}__`;\n parts.push({\n type: 'block-math',\n content: match,\n latex: cleanLatex(match),\n });\n return placeholder;\n });\n\n // Step 7: Split remaining content by placeholders\n const finalParts: MathPart[] = [];\n let currentIndex = 0;\n // Escape sentinel for regex (though it should be safe alphanumeric)\n const escapedSentinel = sentinel.replaceAll(\n /[.*+?^${}()|[\\]\\\\]/g,\n String.raw`\\$&`\n );\n const placeholderPattern = new RegExp(\n String.raw`${escapedSentinel}(\\d+)__`,\n 'g'\n );\n let match;\n\n while ((match = placeholderPattern.exec(processedContent)) !== null) {\n // Add text before math\n if (match.index > currentIndex) {\n finalParts.push({\n type: 'text',\n content: decodeDollarEscapes(\n processedContent.slice(currentIndex, match.index)\n ),\n });\n }\n\n // Add math expression\n const mathIndex = Number.parseInt(match[1], 10);\n if (parts[mathIndex]) {\n finalParts.push(parts[mathIndex]);\n }\n\n currentIndex = match.index + match[0].length;\n }\n\n // Add remaining text\n if (currentIndex < processedContent.length) {\n finalParts.push({\n type: 'text',\n content: decodeDollarEscapes(processedContent.slice(currentIndex)),\n });\n }\n\n return finalParts;\n};\n\n/**\n * Checks if content contains any math expressions\n */\nexport const containsMath = (content: string): boolean => {\n if (!content) return false;\n\n // Check for various math patterns\n const patterns = [\n /\\$\\$[\\s\\S]+?\\$\\$/, // Display mode $$...$$\n /(?<!\\\\)\\$[\\s\\S]+?\\$/, // Inline mode $...$\n /<span[^>]*class=\"math-formula\"/, // Editor spans\n /<span[^>]*class=\"math-expression\"/, // Legacy spans\n /<latex>|&lt;latex&gt;/, // LaTeX tags\n /\\\\begin\\{[^}]+\\}/, // LaTeX environments\n ];\n\n return patterns.some((pattern) => pattern.test(content));\n};\n\n/**\n * Extracts plain text from HTML content (removes all tags and LaTeX notation)\n */\nexport const stripHtml = (htmlContent: string): string => {\n if (!htmlContent) return '';\n\n let content = htmlContent;\n\n // Remove math-formula spans (keep nothing as the LaTeX is in data attribute)\n content = content.replaceAll(\n /<span[^>]*class=\"math-formula\"[^>]*>[\\s\\S]*?<\\/span>/g,\n ''\n );\n\n // Remove math-expression spans (legacy)\n content = content.replaceAll(\n /<span[^>]*class=\"math-expression\"[^>]*>[\\s\\S]*?<\\/span>/g,\n ''\n );\n\n // Remove $$...$$ block math\n content = content.replaceAll(/\\$\\$[\\s\\S]+?\\$\\$/g, '');\n\n // Remove $...$ inline math\n content = content.replaceAll(/\\$[^$]+\\$/g, '');\n\n // Remove <latex>...</latex> tags\n content = content.replaceAll(\n /(?:<latex>|&lt;latex&gt;)[\\s\\S]*?(?:<\\/latex>|&lt;\\/latex&gt;)/g,\n ''\n );\n\n // Remove LaTeX environments like \\begin{...}...\\end{...}\n // Using non-greedy match without backreference to avoid ReDoS vulnerability\n content = content.replaceAll(\n /\\\\begin\\{[a-zA-Z*]+\\}[\\s\\S]*?\\\\end\\{[a-zA-Z*]+\\}/g,\n ''\n );\n\n // Remove HTML tags\n if (typeof document === 'undefined') {\n // Server-side: use regex (excluding both < and > prevents quadratic backtracking)\n return content.replaceAll(/<[^<>]*>/g, '').trim();\n }\n\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = content;\n return (tempDiv.textContent || tempDiv.innerText || '').trim();\n};\n","import {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n} from 'react';\nimport Text from '../Text/Text';\nimport { Check, Minus } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\n\n/**\n * CheckBox size variants\n */\ntype CheckBoxSize = 'small' | 'medium' | 'large';\n\n/**\n * CheckBox visual state\n */\ntype CheckBoxState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n checkbox: 'w-4 h-4', // 16px x 16px\n textSize: 'sm' as const,\n spacing: 'gap-1.5', // 6px\n borderWidth: 'border-2',\n iconSize: 14, // pixels for Phosphor icons\n labelHeight: 'h-[21px]',\n },\n medium: {\n checkbox: 'w-5 h-5', // 20px x 20px\n textSize: 'md' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2',\n iconSize: 16, // pixels for Phosphor icons\n labelHeight: 'h-6',\n },\n large: {\n checkbox: 'w-6 h-6', // 24px x 24px\n textSize: 'lg' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-[3px]', // 3px border\n iconSize: 20, // pixels for Phosphor icons\n labelHeight: 'h-[27px]',\n },\n} as const;\n\n/**\n * Base checkbox styling classes using design system colors\n */\nconst BASE_CHECKBOX_CLASSES =\n 'rounded border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked:\n 'border-primary-950 bg-primary-950 text-text hover:border-primary-800 hover:bg-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background',\n checked: 'border-primary-800 bg-primary-800 text-text',\n },\n focused: {\n unchecked:\n 'border-indicator-info bg-background ring-2 ring-indicator-info/20',\n checked:\n 'border-indicator-info bg-primary-950 text-text ring-2 ring-indicator-info/20',\n },\n invalid: {\n unchecked: 'border-error-700 bg-background hover:border-error-600',\n checked: 'border-error-700 bg-primary-950 text-text',\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed opacity-40',\n checked:\n 'border-primary-600 bg-primary-600 text-text cursor-not-allowed opacity-40',\n },\n} as const;\n\n/**\n * CheckBox component props interface\n */\nexport type CheckBoxProps = {\n /** Label text to display next to the checkbox */\n label?: ReactNode;\n /** Size variant of the checkbox */\n size?: CheckBoxSize;\n /** Visual state of the checkbox */\n state?: CheckBoxState;\n /** Indeterminate state for partial selections */\n indeterminate?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'>;\n\n/**\n * CheckBox component for Analytica Ensino platforms\n *\n * A checkbox component with essential states, sizes and themes.\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 checkbox\n * <CheckBox label=\"Option\" />\n *\n * // Small size\n * <CheckBox size=\"small\" label=\"Small option\" />\n *\n * // Invalid state\n * <CheckBox state=\"invalid\" label=\"Required field\" />\n *\n * // Disabled state\n * <CheckBox disabled label=\"Disabled option\" />\n * ```\n */\nconst CheckBox = forwardRef<HTMLInputElement, CheckBoxProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n indeterminate = false,\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n disabled,\n id,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `checkbox-${generatedId}`;\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalChecked(event.target.checked);\n }\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Determine checkbox visual variant\n const checkVariant = checked || indeterminate ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][checkVariant];\n\n // Special border width handling for focused/hovered states and large size\n const borderWidthClass =\n state === 'focused' || (state === 'hovered' && size === 'large')\n ? 'border-[3px]'\n : sizeClasses.borderWidth;\n\n // Get final checkbox classes\n const checkboxClasses = cn(\n BASE_CHECKBOX_CLASSES,\n sizeClasses.checkbox,\n borderWidthClass,\n stylingClasses,\n className\n );\n\n // Render appropriate icon based on state\n const renderIcon = () => {\n if (indeterminate) {\n return (\n <Minus\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n if (checked) {\n return (\n <Check\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n return null;\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.spacing,\n disabled ? 'opacity-40' : ''\n )}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={ref}\n type=\"checkbox\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n onChange={handleChange}\n className=\"sr-only\"\n {...props}\n />\n\n {/* Custom styled checkbox */}\n <label htmlFor={inputId} className={checkboxClasses}>\n {/* Show appropriate icon based on state */}\n {renderIcon()}\n </label>\n\n {/* Label text */}\n {label && (\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.labelHeight\n )}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={cn(\n 'cursor-pointer select-none leading-[150%] flex items-center font-roboto',\n labelClassName\n )}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nCheckBox.displayName = 'CheckBox';\n\nexport default CheckBox;\n","import {\n InputHTMLAttributes,\n HTMLAttributes,\n ReactNode,\n forwardRef,\n useId,\n useEffect,\n useRef,\n Children,\n cloneElement,\n isValidElement,\n ReactElement,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport CheckBox from './CheckBox';\nimport { cn } from '../../utils/utils';\n\n/**\n * CheckboxList size variants\n */\ntype CheckboxListSize = 'small' | 'medium' | 'large';\n\n/**\n * CheckboxList visual state\n */\ntype CheckboxListState =\n | 'default'\n | 'hovered'\n | 'focused'\n | 'invalid'\n | 'disabled';\n\n/**\n * CheckboxList store interface\n */\ninterface CheckboxListStore {\n values: string[];\n setValues: (values: string[]) => void;\n toggleValue: (value: string) => void;\n onValuesChange?: (values: string[]) => void;\n disabled: boolean;\n name: string;\n}\n\ntype CheckboxListStoreApi = StoreApi<CheckboxListStore>;\n\n/**\n * Create a new CheckboxList store\n */\nconst createCheckboxListStore = (\n name: string,\n defaultValues: string[],\n disabled: boolean,\n onValuesChange?: (values: string[]) => void\n): CheckboxListStoreApi =>\n create<CheckboxListStore>((set, get) => ({\n values: defaultValues,\n setValues: (values) => {\n if (!get().disabled) {\n set({ values });\n get().onValuesChange?.(values);\n }\n },\n toggleValue: (value) => {\n if (!get().disabled) {\n const currentValues = get().values;\n const newValues = currentValues.includes(value)\n ? currentValues.filter((v) => v !== value)\n : [...currentValues, value];\n set({ values: newValues });\n get().onValuesChange?.(newValues);\n }\n },\n onValuesChange,\n disabled,\n name,\n }));\n\n/**\n * Hook to access CheckboxList store\n */\nexport const useCheckboxListStore = (externalStore?: CheckboxListStoreApi) => {\n if (!externalStore) {\n throw new Error('CheckboxListItem must be used within a CheckboxList');\n }\n return externalStore;\n};\n\n/**\n * Inject store into CheckboxListItem children\n */\nconst injectStore = (\n children: ReactNode,\n store: CheckboxListStoreApi\n): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n const typedChild = child as ReactElement<CheckboxListItemProps>;\n const shouldInject = typedChild.type === CheckboxListItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\n/**\n * CheckboxList component props interface\n */\nexport type CheckboxListProps = {\n /** Current selected values */\n values?: string[];\n /** Default selected values for uncontrolled usage */\n defaultValues?: string[];\n /** Callback when selection changes */\n onValuesChange?: (values: string[]) => void;\n /** Group name for all checkboxes */\n name?: string;\n /** Disabled state for the entire group */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Children components */\n children: ReactNode;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValues'>;\n\n/**\n * CheckboxList component for flexible checkbox group composition\n *\n * Uses Zustand for state management with automatic store injection.\n * Allows complete control over layout and styling by composing with CheckboxListItem.\n *\n * @example\n * ```tsx\n * <CheckboxList defaultValues={[\"option1\"]} onValuesChange={setValues}>\n * <div className=\"flex items-center gap-3\">\n * <CheckboxListItem value=\"option1\" id=\"c1\" />\n * <label htmlFor=\"c1\">Option 1</label>\n * </div>\n * <div className=\"flex items-center gap-3\">\n * <CheckboxListItem value=\"option2\" id=\"c2\" />\n * <label htmlFor=\"c2\">Option 2</label>\n * </div>\n * </CheckboxList>\n * ```\n */\nconst CheckboxList = forwardRef<HTMLDivElement, CheckboxListProps>(\n (\n {\n values: propValues,\n defaultValues = [],\n onValuesChange,\n name: propName,\n disabled = false,\n className = '',\n children,\n ...props\n },\n ref\n ) => {\n // Generate unique name if not provided\n const generatedId = useId();\n const name = propName || `checkbox-list-${generatedId}`;\n\n // Create store reference\n const storeRef = useRef<CheckboxListStoreApi>(null);\n storeRef.current ??= createCheckboxListStore(\n name,\n defaultValues,\n disabled,\n onValuesChange\n );\n const store = storeRef.current;\n\n // Get store actions\n const { setValues } = useStore(store, (s) => s);\n\n // Call onValuesChange with initial values\n useEffect(() => {\n const currentValues = store.getState().values;\n if (currentValues.length > 0 && onValuesChange) {\n onValuesChange(currentValues);\n }\n }, []);\n\n // Handle controlled values changes\n useEffect(() => {\n if (propValues !== undefined) {\n setValues(propValues);\n }\n }, [propValues, setValues]);\n\n // Update disabled state\n useEffect(() => {\n store.setState({ disabled });\n }, [disabled, store]);\n\n return (\n <div\n ref={ref}\n className={cn('flex flex-col gap-2 w-full', className)}\n aria-label={name}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\n\nCheckboxList.displayName = 'CheckboxList';\n\n/**\n * CheckboxListItem component props interface\n */\nexport type CheckboxListItemProps = {\n /** Value for this checkbox item */\n value: string;\n /** Store reference (automatically injected by CheckboxList) */\n store?: CheckboxListStoreApi;\n /** Disabled state for this specific item */\n disabled?: boolean;\n /** Size variant */\n size?: CheckboxListSize;\n /** Visual state */\n state?: CheckboxListState;\n /** Additional CSS classes */\n className?: string;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'name' | 'value' | 'checked' | 'onChange' | 'size'\n>;\n\n/**\n * CheckboxListItem component for use within CheckboxList\n *\n * A checkbox without label that works within CheckboxList context.\n * Provides just the checkbox input for maximum flexibility in composition.\n *\n * @example\n * ```tsx\n * <CheckboxList defaultValues={[\"option1\"]}>\n * <div className=\"flex items-center gap-3\">\n * <CheckboxListItem value=\"option1\" id=\"c1\" />\n * <label htmlFor=\"c1\">Option 1</label>\n * </div>\n * </CheckboxList>\n * ```\n */\nconst CheckboxListItem = forwardRef<HTMLInputElement, CheckboxListItemProps>(\n (\n {\n value,\n store: externalStore,\n disabled: itemDisabled,\n size = 'medium',\n state = 'default',\n className = '',\n id,\n ...props\n },\n ref\n ) => {\n // Get store and state\n const store = useCheckboxListStore(externalStore);\n const {\n values: groupValues,\n toggleValue,\n disabled: groupDisabled,\n name,\n } = useStore(store);\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `checkbox-item-${generatedId}`;\n\n // Determine states\n const isChecked = groupValues.includes(value);\n const isDisabled = groupDisabled || itemDisabled;\n const currentState = isDisabled ? 'disabled' : state;\n\n // Use standard CheckBox component for consistency and simplicity\n return (\n <CheckBox\n ref={ref}\n id={inputId}\n name={name}\n value={value}\n checked={isChecked}\n disabled={isDisabled}\n size={size}\n state={currentState}\n className={className}\n onChange={() => {\n if (!isDisabled) {\n toggleValue(value);\n }\n }}\n {...props}\n />\n );\n }\n);\n\nCheckboxListItem.displayName = 'CheckboxListItem';\n\nexport default CheckboxList;\nexport { CheckboxListItem };\n","import {\n InputHTMLAttributes,\n HTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n useEffect,\n useRef,\n Children,\n cloneElement,\n isValidElement,\n ReactElement,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\n\n/**\n * Radio size variants\n */\ntype RadioSize = 'small' | 'medium' | 'large' | 'extraLarge';\n\n/**\n * Radio visual state\n */\ntype RadioState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n radio: 'w-5 h-5',\n textSize: 'sm' as const,\n spacing: 'gap-1.5',\n borderWidth: 'border-2',\n dotSize: 'w-2.5 h-2.5',\n labelHeight: 'h-5',\n },\n medium: {\n radio: 'w-6 h-6',\n textSize: 'md' as const,\n spacing: 'gap-2',\n borderWidth: 'border-2',\n dotSize: 'w-3 h-3',\n labelHeight: 'h-6',\n },\n large: {\n radio: 'w-7 h-7',\n textSize: 'lg' as const,\n spacing: 'gap-2',\n borderWidth: 'border-2',\n dotSize: 'w-3.5 h-3.5',\n labelHeight: 'h-7',\n },\n extraLarge: {\n radio: 'w-8 h-8',\n textSize: 'xl' as const,\n spacing: 'gap-3',\n borderWidth: 'border-2',\n dotSize: 'w-4 h-4',\n labelHeight: 'h-8',\n },\n} as const;\n\n/**\n * Focused state maintains the same sizes as default state\n * Only adds wrapper styling, does not change radio/dot sizes\n */\n\n/**\n * Base radio styling classes using design system colors\n */\nconst BASE_RADIO_CLASSES =\n 'rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked: 'border-primary-950 bg-background hover:border-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background',\n checked: 'border-info-700 bg-background',\n },\n focused: {\n unchecked: 'border-border-400 bg-background',\n checked: 'border-primary-950 bg-background',\n },\n invalid: {\n unchecked: 'border-border-400 bg-background',\n checked: 'border-primary-950 bg-background',\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed',\n checked: 'border-primary-950 bg-background cursor-not-allowed',\n },\n} as const;\n\n/**\n * Dot styling classes for the inner dot when checked\n */\nconst DOT_CLASSES = {\n default: 'bg-primary-950',\n hovered: 'bg-info-700',\n focused: 'bg-primary-950',\n invalid: 'bg-primary-950',\n disabled: 'bg-primary-950',\n} as const;\n\n/**\n * Radio component props interface\n */\nexport type RadioProps = {\n /** Label text to display next to the radio */\n label?: ReactNode;\n /** Size variant of the radio */\n size?: RadioSize;\n /** Visual state of the radio */\n state?: RadioState;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Radio group name */\n name?: string;\n /** Radio value */\n value?: string;\n /** Default checked state for uncontrolled radios */\n defaultChecked?: boolean;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'defaultChecked'\n>;\n\n/**\n * Radio component for Analytica Ensino platforms\n *\n * A radio button component with essential states, sizes and themes.\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 radio\n * <Radio name=\"option\" value=\"1\" label=\"Option 1\" />\n *\n * // Small size\n * <Radio size=\"small\" name=\"option\" value=\"2\" label=\"Small option\" />\n *\n * // Invalid state\n * <Radio state=\"invalid\" name=\"option\" value=\"3\" label=\"Required field\" />\n *\n * // Disabled state\n * <Radio disabled name=\"option\" value=\"4\" label=\"Disabled option\" />\n *\n * // Default checked (uncontrolled)\n * <Radio defaultChecked name=\"option\" value=\"5\" label=\"Initially checked\" />\n * ```\n */\nconst Radio = forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n defaultChecked = false,\n disabled,\n id,\n name,\n value,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `radio-${generatedId}`;\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const newChecked = event.target.checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n // Prevent automatic scroll when input changes\n if (event.target) {\n event.target.blur();\n }\n\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Focused state maintains original sizes, only adds wrapper\n const actualRadioSize = sizeClasses.radio;\n const actualDotSize = sizeClasses.dotSize;\n\n // Determine radio visual variant\n const radioVariant = checked ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][radioVariant];\n\n // Border width logic - consistent across all states and sizes\n const getBorderWidth = () => {\n if (currentState === 'focused') {\n return 'border-2';\n }\n return sizeClasses.borderWidth;\n };\n\n const borderWidthClass = getBorderWidth();\n\n // Get final radio classes\n const radioClasses = cn(\n BASE_RADIO_CLASSES,\n actualRadioSize,\n borderWidthClass,\n stylingClasses,\n className\n );\n\n // Get dot classes\n const dotClasses = cn(\n actualDotSize,\n 'rounded-full',\n DOT_CLASSES[currentState],\n 'transition-all duration-200'\n );\n\n // Determine if wrapper is needed only for focused or invalid states\n const isWrapperNeeded =\n currentState === 'focused' || currentState === 'invalid';\n const wrapperBorderColor =\n currentState === 'focused'\n ? 'border-indicator-info'\n : 'border-indicator-error';\n\n // Determine text color based on state and checked status\n const getTextColor = () => {\n if (currentState === 'disabled') {\n return checked ? 'text-text-900' : 'text-text-600';\n }\n\n if (currentState === 'focused') {\n return 'text-text-900';\n }\n\n return checked ? 'text-text-900' : 'text-text-600';\n };\n\n // Determine cursor class based on disabled state\n const getCursorClass = () => {\n return currentState === 'disabled'\n ? 'cursor-not-allowed'\n : 'cursor-pointer';\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={cn(\n 'flex flex-row items-center',\n isWrapperNeeded\n ? cn('p-1 border-2', wrapperBorderColor, 'rounded-lg gap-1.5')\n : sizeClasses.spacing,\n disabled ? 'opacity-40' : ''\n )}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"radio\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n name={name}\n value={value}\n onChange={handleChange}\n className=\"sr-only\"\n style={{\n position: 'absolute',\n left: '-9999px',\n visibility: 'hidden',\n }}\n {...props}\n />\n\n {/* Custom styled radio */}\n <button\n type=\"button\"\n className={radioClasses}\n disabled={disabled}\n aria-pressed={checked}\n onClick={(e) => {\n // Prevent scroll when radio is clicked\n e.preventDefault();\n if (!disabled) {\n // Simulate click on hidden input\n if (inputRef.current) {\n inputRef.current.click();\n // Remove focus to prevent scroll behavior\n inputRef.current.blur();\n }\n }\n }}\n onKeyDown={(e) => {\n // Handle keyboard activation (Enter or Space)\n if ((e.key === 'Enter' || e.key === ' ') && !disabled) {\n e.preventDefault();\n if (inputRef.current) {\n inputRef.current.click();\n inputRef.current.blur();\n }\n }\n }}\n >\n {/* Show dot when checked */}\n {checked && <div className={dotClasses} />}\n </button>\n\n {/* Label text */}\n {label && (\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.labelHeight,\n 'flex-1 min-w-0'\n )}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={cn(\n getCursorClass(),\n 'select-none leading-normal flex items-center font-roboto truncate',\n labelClassName\n )}\n color={getTextColor()}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5 truncate\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5 truncate\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nRadio.displayName = 'Radio';\n\n/**\n * RadioGroup store interface\n */\ninterface RadioGroupStore {\n value: string;\n setValue: (value: string) => void;\n onValueChange?: (value: string) => void;\n disabled: boolean;\n name: string;\n}\n\ntype RadioGroupStoreApi = StoreApi<RadioGroupStore>;\n\n/**\n * Create a new RadioGroup store\n */\nconst createRadioGroupStore = (\n name: string,\n defaultValue: string,\n disabled: boolean,\n onValueChange?: (value: string) => void\n): RadioGroupStoreApi =>\n create<RadioGroupStore>((set, get) => ({\n value: defaultValue,\n setValue: (value) => {\n if (!get().disabled) {\n set({ value });\n get().onValueChange?.(value);\n }\n },\n onValueChange,\n disabled,\n name,\n }));\n\n/**\n * Hook to access RadioGroup store\n */\nexport const useRadioGroupStore = (externalStore?: RadioGroupStoreApi) => {\n if (!externalStore) {\n throw new Error('RadioGroupItem must be used within a RadioGroup');\n }\n return externalStore;\n};\n\n/**\n * Inject store into RadioGroupItem children\n */\nconst injectStore = (\n children: ReactNode,\n store: RadioGroupStoreApi\n): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === RadioGroupItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\n/**\n * RadioGroup component props interface\n */\nexport type RadioGroupProps = {\n /** Current selected value */\n value?: string;\n /** Default selected value for uncontrolled usage */\n defaultValue?: string;\n /** Callback when selection changes */\n onValueChange?: (value: string) => void;\n /** Group name for all radios */\n name?: string;\n /** Disabled state for the entire group */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Children components */\n children: ReactNode;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>;\n\n/**\n * RadioGroup component for flexible radio group composition\n *\n * Uses Zustand for state management with automatic store injection.\n * Allows complete control over layout and styling by composing with RadioGroupItem.\n *\n * @example\n * ```tsx\n * <RadioGroup defaultValue=\"option1\" onValueChange={setValue}>\n * <div className=\"flex items-center gap-3\">\n * <RadioGroupItem value=\"option1\" id=\"r1\" />\n * <label htmlFor=\"r1\">Option 1</label>\n * </div>\n * <div className=\"flex items-center gap-3\">\n * <RadioGroupItem value=\"option2\" id=\"r2\" />\n * <label htmlFor=\"r2\">Option 2</label>\n * </div>\n * </RadioGroup>\n * ```\n */\nconst RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n (\n {\n value: propValue,\n defaultValue = '',\n onValueChange,\n name: propName,\n disabled = false,\n className = '',\n children,\n ...props\n },\n ref\n ) => {\n // Generate unique name if not provided\n const generatedId = useId();\n const name = propName || `radio-group-${generatedId}`;\n\n // Create store reference\n const storeRef = useRef<RadioGroupStoreApi>(null);\n storeRef.current ??= createRadioGroupStore(\n name,\n defaultValue,\n disabled,\n onValueChange\n );\n const store = storeRef.current;\n\n // Get store actions\n const { setValue } = useStore(store, (s) => s);\n\n // Call onValueChange with initial value\n useEffect(() => {\n const currentValue = store.getState().value;\n if (currentValue && onValueChange) {\n onValueChange(currentValue);\n }\n }, []); // Empty dependency array for mount only\n\n // Handle controlled value changes\n useEffect(() => {\n if (propValue !== undefined) {\n setValue(propValue);\n }\n }, [propValue, setValue]);\n\n // Update disabled state\n useEffect(() => {\n store.setState({ disabled });\n }, [disabled, store]);\n\n return (\n <div\n ref={ref}\n className={className}\n role=\"radiogroup\"\n aria-label={name}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\n\nRadioGroup.displayName = 'RadioGroup';\n\n/**\n * RadioGroupItem component props interface\n */\nexport type RadioGroupItemProps = {\n /** Value for this radio item */\n value: string;\n /** Optional label rendered next to the radio (parity with CheckBox/Radio APIs) */\n label?: ReactNode;\n /** CSS classes applied to the label */\n labelClassName?: string;\n /** Store reference (automatically injected by RadioGroup) */\n store?: RadioGroupStoreApi;\n /** Disabled state for this specific item */\n disabled?: boolean;\n /** Size variant */\n size?: RadioSize;\n /** Visual state */\n state?: RadioState;\n /** Additional CSS classes */\n className?: string;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'name' | 'value' | 'checked' | 'onChange' | 'size'\n>;\n\n/**\n * RadioGroupItem component for use within RadioGroup\n *\n * A radio button that works within RadioGroup context.\n * Accepts a `label` prop for the common case (parity with CheckBox/Radio).\n * When `label` is omitted, renders just the input for custom composition.\n *\n * @example\n * ```tsx\n * // With label (recommended)\n * <RadioGroup defaultValue=\"option1\">\n * <RadioGroupItem value=\"option1\" label=\"Option 1\" />\n * <RadioGroupItem value=\"option2\" label=\"Option 2\" />\n * </RadioGroup>\n *\n * // Without label - manual composition\n * <RadioGroup defaultValue=\"option1\">\n * <div className=\"flex items-center gap-3\">\n * <RadioGroupItem value=\"option1\" id=\"r1\" />\n * <label htmlFor=\"r1\">Custom layout</label>\n * </div>\n * </RadioGroup>\n * ```\n */\nconst RadioGroupItem = forwardRef<HTMLInputElement, RadioGroupItemProps>(\n (\n {\n value,\n label,\n labelClassName,\n store: externalStore,\n disabled: itemDisabled,\n size = 'medium',\n state = 'default',\n className = '',\n id,\n ...props\n },\n ref\n ) => {\n // Get store and state\n const store = useRadioGroupStore(externalStore);\n const {\n value: groupValue,\n setValue,\n disabled: groupDisabled,\n name,\n } = useStore(store);\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `radio-item-${generatedId}`;\n\n // Determine states\n const isChecked = groupValue === value;\n const isDisabled = groupDisabled || itemDisabled;\n const currentState = isDisabled ? 'disabled' : state;\n\n // Use standard Radio component for consistency and simplicity\n return (\n <Radio\n ref={ref}\n id={inputId}\n name={name}\n value={value}\n checked={isChecked}\n disabled={isDisabled}\n size={size}\n state={currentState}\n className={className}\n label={label}\n labelClassName={labelClassName}\n onChange={(e) => {\n if (e.target.checked && !isDisabled) {\n setValue(value);\n }\n }}\n {...props}\n />\n );\n }\n);\n\nRadioGroupItem.displayName = 'RadioGroupItem';\n\nexport default Radio;\nexport { RadioGroup, RadioGroupItem };\n","import { cloneElement, ComponentType, JSX, ReactElement } from 'react';\nimport * as PhosphorIcons from '@phosphor-icons/react';\nimport { ChatPT } from '../../assets/icons/subjects/ChatPT';\nimport { ChatEN } from '../../assets/icons/subjects/ChatEN';\nimport { ChatES } from '../../assets/icons/subjects/ChatES';\nimport { BookOpenText } from '../../assets/icons/subjects/BookOpenText';\nimport { Microscope } from '../../assets/icons/subjects/Microscope';\nimport { HeadCircuit } from '../../assets/icons/subjects/HeadCircuit';\n\ntype PhosphorIconName = keyof typeof PhosphorIcons;\ntype PhosphorIconComponent = ComponentType<{\n size?: number;\n color?: string;\n weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone';\n}>;\ntype CustomIconComponent = ComponentType<{\n size: number;\n color: string;\n}>;\n\n// Custom icons act as a fallback when Phosphor doesn't expose the name —\n// Chat_* have no Phosphor equivalent, and the others stay as a safety net\n// in case future Phosphor versions rename or remove them.\nconst CUSTOM_ICONS: Record<string, CustomIconComponent> = {\n Chat_PT: ChatPT,\n Chat_EN: ChatEN,\n Chat_ES: ChatES,\n BookOpenText,\n Microscope,\n HeadCircuit,\n};\n\nexport interface IconRenderProps {\n /**\n * The name of the icon to render\n */\n iconName: string | ReactElement;\n /**\n * The color of the icon\n * @default '#000000'\n */\n color?: string;\n /**\n * The size of the icon in pixels\n * @default 24\n */\n size?: number;\n /**\n * The weight/style of the icon (for Phosphor icons)\n * @default 'regular'\n */\n weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone';\n}\n\n/**\n * Dynamic icon component that renders icons based on name\n * Supports Phosphor icons and custom Chat icons (ChatPT, ChatEN, ChatES)\n *\n * @param iconName - The name of the icon to render\n * @param color - The color of the icon\n * @param size - The size of the icon in pixels\n * @param weight - The weight/style of the icon (for Phosphor icons)\n * @returns JSX element with the corresponding icon\n */\nexport const IconRender = ({\n iconName,\n color = '#000000',\n size = 24,\n weight = 'regular',\n}: IconRenderProps): JSX.Element => {\n // Guard against undefined/null iconName\n if (!iconName) {\n const FallbackIcon = PhosphorIcons.QuestionIcon as PhosphorIconComponent;\n return <FallbackIcon size={size} color={color} weight={weight} />;\n }\n\n if (typeof iconName === 'string') {\n // @phosphor-icons/react v2 exports canonical names with an `Icon` suffix\n // (the bare name is deprecated). Backend keeps sending the bare name.\n const PhosphorIcon = PhosphorIcons[\n `${iconName}Icon` as PhosphorIconName\n ] as PhosphorIconComponent | undefined;\n if (PhosphorIcon) {\n return <PhosphorIcon size={size} color={color} weight={weight} />;\n }\n\n const CustomIcon = CUSTOM_ICONS[iconName];\n if (CustomIcon) {\n return <CustomIcon size={size} color={color} />;\n }\n\n const Fallback = PhosphorIcons.QuestionIcon as PhosphorIconComponent;\n return <Fallback size={size} color={color} weight={weight} />;\n } else {\n // Clone the ReactElement with icon props, casting to avoid TypeScript errors\n return cloneElement(iconName, {\n size,\n color: 'currentColor',\n } as Partial<{\n size: number;\n color: string;\n }>);\n }\n};\n\nexport default IconRender;\n","export const ChatPT = ({ size, color }: { size: number; color: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M27 6H5.00004C4.4696 6 3.9609 6.21071 3.58582 6.58579C3.21075 6.96086 3.00004 7.46957 3.00004 8V28C2.99773 28.3814 3.10562 28.7553 3.31074 29.0768C3.51585 29.3984 3.80947 29.6538 4.15629 29.8125C4.42057 29.9356 4.7085 29.9995 5.00004 30C5.46954 29.9989 5.92347 29.8315 6.28129 29.5275L6.29254 29.5187L10.375 26H27C27.5305 26 28.0392 25.7893 28.4142 25.4142C28.7893 25.0391 29 24.5304 29 24V8C29 7.46957 28.7893 6.96086 28.4142 6.58579C28.0392 6.21071 27.5305 6 27 6ZM27 24H10C9.75992 24.0001 9.52787 24.0866 9.34629 24.2437L5.00004 28V8H27V24Z\"\n fill={color}\n />\n <path\n d=\"M21.1758 12V20.5312H19.7168V12H21.1758ZM23.8535 12V13.1719H17.0625V12H23.8535Z\"\n fill={color}\n />\n <path\n d=\"M13.2402 17.3496H11.0195V16.1836H13.2402C13.627 16.1836 13.9395 16.1211 14.1777 15.9961C14.416 15.8711 14.5898 15.6992 14.6992 15.4805C14.8125 15.2578 14.8691 15.0039 14.8691 14.7188C14.8691 14.4492 14.8125 14.1973 14.6992 13.9629C14.5898 13.7246 14.416 13.5332 14.1777 13.3887C13.9395 13.2441 13.627 13.1719 13.2402 13.1719H11.4707V20.5312H10V12H13.2402C13.9004 12 14.4609 12.1172 14.9219 12.3516C15.3867 12.582 15.7402 12.9023 15.9824 13.3125C16.2246 13.7188 16.3457 14.1836 16.3457 14.707C16.3457 15.2578 16.2246 15.7305 15.9824 16.125C15.7402 16.5195 15.3867 16.8223 14.9219 17.0332C14.4609 17.2441 13.9004 17.3496 13.2402 17.3496Z\"\n fill={color}\n />\n </svg>\n);\n","export const ChatEN = ({ size, color }: { size: number; color: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M27 6H5.00004C4.4696 6 3.9609 6.21071 3.58582 6.58579C3.21075 6.96086 3.00004 7.46957 3.00004 8V28C2.99773 28.3814 3.10562 28.7553 3.31074 29.0768C3.51585 29.3984 3.80947 29.6538 4.15629 29.8125C4.42057 29.9356 4.7085 29.9995 5.00004 30C5.46954 29.9989 5.92347 29.8315 6.28129 29.5275L6.29254 29.5187L10.375 26H27C27.5305 26 28.0392 25.7893 28.4142 25.4142C28.7893 25.0391 29 24.5304 29 24V8C29 7.46957 28.7893 6.96086 28.4142 6.58579C28.0392 6.21071 27.5305 6 27 6ZM27 24H10C9.75992 24.0001 9.52787 24.0866 9.34629 24.2437L5.00004 28V8H27V24Z\"\n fill={color}\n />\n <path\n d=\"M22.5488 12V20.5312H21.0781L17.252 14.4199V20.5312H15.7812V12H17.252L21.0898 18.123V12H22.5488Z\"\n fill={color}\n />\n <path\n d=\"M14.584 19.3652V20.5312H10.0547V19.3652H14.584ZM10.4707 12V20.5312H9V12H10.4707ZM13.9922 15.5625V16.7109H10.0547V15.5625H13.9922ZM14.5547 12V13.1719H10.0547V12H14.5547Z\"\n fill={color}\n />\n </svg>\n);\n","export const ChatES = ({ size, color }: { size: number; color: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M27 6H5.00004C4.4696 6 3.9609 6.21071 3.58582 6.58579C3.21075 6.96086 3.00004 7.46957 3.00004 8V28C2.99773 28.3814 3.10562 28.7553 3.31074 29.0768C3.51585 29.3984 3.80947 29.6538 4.15629 29.8125C4.42057 29.9356 4.7085 29.9995 5.00004 30C5.46954 29.9989 5.92347 29.8315 6.28129 29.5275L6.29254 29.5187L10.375 26H27C27.5305 26 28.0392 25.7893 28.4142 25.4142C28.7893 25.0391 29 24.5304 29 24V8C29 7.46957 28.7893 6.96086 28.4142 6.58579C28.0392 6.21071 27.5305 6 27 6ZM27 24H10C9.75992 24.0001 9.52787 24.0866 9.34629 24.2437L5.00004 28V8H27V24Z\"\n fill={color}\n />\n <path\n d=\"M21.1426 17.8027C21.1426 17.627 21.1152 17.4707 21.0605 17.334C21.0098 17.1973 20.918 17.0723 20.7852 16.959C20.6523 16.8457 20.4648 16.7363 20.2227 16.6309C19.9844 16.5215 19.6797 16.4102 19.3086 16.2969C18.9023 16.1719 18.5273 16.0332 18.1836 15.8809C17.8438 15.7246 17.5469 15.5449 17.293 15.3418C17.0391 15.1348 16.8418 14.8984 16.7012 14.6328C16.5605 14.3633 16.4902 14.0527 16.4902 13.7012C16.4902 13.3535 16.5625 13.0371 16.707 12.752C16.8555 12.4668 17.0645 12.2207 17.334 12.0137C17.6074 11.8027 17.9297 11.6406 18.3008 11.5273C18.6719 11.4102 19.082 11.3516 19.5312 11.3516C20.1641 11.3516 20.709 11.4688 21.166 11.7031C21.627 11.9375 21.9805 12.252 22.2266 12.6465C22.4766 13.041 22.6016 13.4766 22.6016 13.9531H21.1426C21.1426 13.6719 21.082 13.4238 20.9609 13.209C20.8438 12.9902 20.6641 12.8184 20.4219 12.6934C20.1836 12.5684 19.8809 12.5059 19.5137 12.5059C19.166 12.5059 18.877 12.5586 18.6465 12.6641C18.416 12.7695 18.2441 12.9121 18.1309 13.0918C18.0176 13.2715 17.9609 13.4746 17.9609 13.7012C17.9609 13.8613 17.998 14.0078 18.0723 14.1406C18.1465 14.2695 18.2598 14.3906 18.4121 14.5039C18.5645 14.6133 18.7559 14.7168 18.9863 14.8145C19.2168 14.9121 19.4883 15.0059 19.8008 15.0957C20.2734 15.2363 20.6855 15.3926 21.0371 15.5645C21.3887 15.7324 21.6816 15.9238 21.916 16.1387C22.1504 16.3535 22.3262 16.5977 22.4434 16.8711C22.5605 17.1406 22.6191 17.4473 22.6191 17.791C22.6191 18.1504 22.5469 18.4746 22.4023 18.7637C22.2578 19.0488 22.0508 19.293 21.7812 19.4961C21.5156 19.6953 21.1953 19.8496 20.8203 19.959C20.4492 20.0645 20.0352 20.1172 19.5781 20.1172C19.168 20.1172 18.7637 20.0625 18.3652 19.9531C17.9707 19.8438 17.6113 19.6777 17.2871 19.4551C16.9629 19.2285 16.7051 18.9473 16.5137 18.6113C16.3223 18.2715 16.2266 17.875 16.2266 17.4219H17.6973C17.6973 17.6992 17.7441 17.9355 17.8379 18.1309C17.9355 18.3262 18.0703 18.4863 18.2422 18.6113C18.4141 18.7324 18.6133 18.8223 18.8398 18.8809C19.0703 18.9395 19.3164 18.9688 19.5781 18.9688C19.9219 18.9688 20.209 18.9199 20.4395 18.8223C20.6738 18.7246 20.8496 18.5879 20.9668 18.4121C21.084 18.2363 21.1426 18.0332 21.1426 17.8027Z\"\n fill={color}\n />\n <path\n d=\"M15.4512 18.834V20H10.9219V18.834H15.4512ZM11.3379 11.4688V20H9.86719V11.4688H11.3379ZM14.8594 15.0312V16.1797H10.9219V15.0312H14.8594ZM15.4219 11.4688V12.6406H10.9219V11.4688H15.4219Z\"\n fill={color}\n />\n </svg>\n);\n","export const BookOpenText = ({\n size,\n color,\n}: {\n size: number;\n color: string;\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M29 6H20C19.2238 6 18.4582 6.18073 17.7639 6.52786C17.0697 6.875 16.4657 7.37902 16 8C15.5343 7.37902 14.9303 6.875 14.2361 6.52786C13.5418 6.18073 12.7762 6 12 6H3C2.73478 6 2.48043 6.10536 2.29289 6.29289C2.10536 6.48043 2 6.73478 2 7V25C2 25.2652 2.10536 25.5196 2.29289 25.7071C2.48043 25.8946 2.73478 26 3 26H12C12.7956 26 13.5587 26.3161 14.1213 26.8787C14.6839 27.4413 15 28.2044 15 29C15 29.2652 15.1054 29.5196 15.2929 29.7071C15.4804 29.8946 15.7348 30 16 30C16.2652 30 16.5196 29.8946 16.7071 29.7071C16.8946 29.5196 17 29.2652 17 29C17 28.2044 17.3161 27.4413 17.8787 26.8787C18.4413 26.3161 19.2044 26 20 26H29C29.2652 26 29.5196 25.8946 29.7071 25.7071C29.8946 25.5196 30 25.2652 30 25V7C30 6.73478 29.8946 6.48043 29.7071 6.29289C29.5196 6.10536 29.2652 6 29 6ZM12 24H4V8H12C12.7956 8 13.5587 8.31607 14.1213 8.87868C14.6839 9.44129 15 10.2044 15 11V25C14.1353 24.3493 13.0821 23.9983 12 24ZM28 24H20C18.9179 23.9983 17.8647 24.3493 17 25V11C17 10.2044 17.3161 9.44129 17.8787 8.87868C18.4413 8.31607 19.2044 8 20 8H28V24ZM20 11H25C25.2652 11 25.5196 11.1054 25.7071 11.2929C25.8946 11.4804 26 11.7348 26 12C26 12.2652 25.8946 12.5196 25.7071 12.7071C25.5196 12.8946 25.2652 13 25 13H20C19.7348 13 19.4804 12.8946 19.2929 12.7071C19.1054 12.5196 19 12.2652 19 12C19 11.7348 19.1054 11.4804 19.2929 11.2929C19.4804 11.1054 19.7348 11 20 11ZM26 16C26 16.2652 25.8946 16.5196 25.7071 16.7071C25.5196 16.8946 25.2652 17 25 17H20C19.7348 17 19.4804 16.8946 19.2929 16.7071C19.1054 16.5196 19 16.2652 19 16C19 15.7348 19.1054 15.4804 19.2929 15.2929C19.4804 15.1054 19.7348 15 20 15H25C25.2652 15 25.5196 15.1054 25.7071 15.2929C25.8946 15.4804 26 15.7348 26 16ZM26 20C26 20.2652 25.8946 20.5196 25.7071 20.7071C25.5196 20.8946 25.2652 21 25 21H20C19.7348 21 19.4804 20.8946 19.2929 20.7071C19.1054 20.5196 19 20.2652 19 20C19 19.7348 19.1054 19.4804 19.2929 19.2929C19.4804 19.1054 19.7348 19 20 19H25C25.2652 19 25.5196 19.1054 25.7071 19.2929C25.8946 19.4804 26 19.7348 26 20Z\"\n fill={color}\n />\n </svg>\n);\n","export const Microscope = ({\n size,\n color,\n}: {\n size: number;\n color: string;\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M28 26H25.4925C26.7637 24.4552 27.5898 22.5932 27.882 20.6142C28.1743 18.6351 27.9216 16.6138 27.1511 14.7676C26.3806 12.9213 25.1215 11.32 23.5092 10.1358C21.8968 8.95153 19.9922 8.22913 18 8.04625V4C18 3.46957 17.7893 2.96086 17.4142 2.58579C17.0391 2.21071 16.5304 2 16 2H10C9.46957 2 8.96086 2.21071 8.58579 2.58579C8.21071 2.96086 8 3.46957 8 4V17C8 17.5304 8.21071 18.0391 8.58579 18.4142C8.96086 18.7893 9.46957 19 10 19H16C16.5304 19 17.0391 18.7893 17.4142 18.4142C17.7893 18.0391 18 17.5304 18 17V10.0575C19.7643 10.2552 21.4306 10.9703 22.7895 12.1128C24.1483 13.2553 25.1389 14.7742 25.6366 16.4783C26.1343 18.1824 26.1169 19.9957 25.5866 21.69C25.0563 23.3842 24.0368 24.8838 22.6562 26H4C3.73478 26 3.48043 26.1054 3.29289 26.2929C3.10536 26.4804 3 26.7348 3 27C3 27.2652 3.10536 27.5196 3.29289 27.7071C3.48043 27.8946 3.73478 28 4 28H28C28.2652 28 28.5196 27.8946 28.7071 27.7071C28.8946 27.5196 29 27.2652 29 27C29 26.7348 28.8946 26.4804 28.7071 26.2929C28.5196 26.1054 28.2652 26 28 26ZM16 17H10V4H16V17ZM9 23C8.73478 23 8.48043 22.8946 8.29289 22.7071C8.10536 22.5196 8 22.2652 8 22C8 21.7348 8.10536 21.4804 8.29289 21.2929C8.48043 21.1054 8.73478 21 9 21H17C17.2652 21 17.5196 21.1054 17.7071 21.2929C17.8946 21.4804 18 21.7348 18 22C18 22.2652 17.8946 22.5196 17.7071 22.7071C17.5196 22.8946 17.2652 23 17 23H9Z\"\n fill={color}\n />\n </svg>\n);\n","export const HeadCircuit = ({\n size,\n color,\n}: {\n size: number;\n color: string;\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M24.0625 21.4338C25.327 20.3715 26.3372 19.0392 27.0187 17.5348C27.7001 16.0304 28.0354 14.3924 28 12.7413C27.875 7.02751 23.2987 2.31626 17.595 2.01626C16.1233 1.93616 14.6506 2.15261 13.2642 2.65277C11.8778 3.15293 10.6061 3.92659 9.52453 4.92781C8.44297 5.92903 7.57365 7.13739 6.96819 8.48112C6.36272 9.82485 6.03347 11.2766 5.99997 12.75L3.19372 18.1475C3.18247 18.17 3.17122 18.1925 3.16122 18.215C2.96003 18.6839 2.94569 19.212 3.12114 19.6912C3.29659 20.1704 3.64855 20.5644 4.10497 20.7925L4.13622 20.8063L6.99997 22.1175V26C6.99997 26.5304 7.21068 27.0392 7.58576 27.4142C7.96083 27.7893 8.46954 28 8.99997 28H15C15.2652 28 15.5195 27.8947 15.7071 27.7071C15.8946 27.5196 16 27.2652 16 27C16 26.7348 15.8946 26.4804 15.7071 26.2929C15.5195 26.1054 15.2652 26 15 26H8.99997V21.4763C9.00011 21.2846 8.94517 21.0969 8.84168 20.9356C8.73818 20.7742 8.5905 20.646 8.41622 20.5663L4.99997 19L7.88372 13.4575C7.95889 13.3166 7.99878 13.1597 7.99997 13C7.99968 10.9604 8.69216 8.98124 9.96395 7.38674C11.2357 5.79224 13.0114 4.677 15 4.22376V6.17251C14.3328 6.4084 13.7704 6.87258 13.4123 7.48299C13.0543 8.0934 12.9235 8.81075 13.0432 9.50824C13.1628 10.2057 13.5252 10.8385 14.0663 11.2946C14.6074 11.7508 15.2923 12.0009 16 12.0009C16.7077 12.0009 17.3926 11.7508 17.9336 11.2946C18.4747 10.8385 18.8371 10.2057 18.9568 9.50824C19.0764 8.81075 18.9457 8.0934 18.5876 7.48299C18.2295 6.87258 17.6672 6.4084 17 6.17251V4.00001C17.1625 4.00001 17.325 4.00001 17.4875 4.01251C19.2608 4.11409 20.9649 4.73627 22.3864 5.80124C23.808 6.86621 24.8841 8.32669 25.48 10H23C22.8533 9.99995 22.7084 10.0322 22.5755 10.0944C22.4426 10.1566 22.3251 10.2473 22.2312 10.36L19.0425 14.1875C18.3774 13.9397 17.6462 13.9351 16.9781 14.1744C16.3099 14.4138 15.748 14.8817 15.3916 15.4954C15.0352 16.1092 14.9073 16.8292 15.0306 17.5281C15.1538 18.227 15.5203 18.8598 16.0652 19.3146C16.61 19.7694 17.2981 20.0168 18.0078 20.0132C18.7175 20.0095 19.4031 19.755 19.9432 19.2947C20.4834 18.8343 20.8433 18.1977 20.9594 17.4976C21.0754 16.7974 20.9402 16.0788 20.5775 15.4688L23.4687 12H25.9425C25.9725 12.26 25.9908 12.5225 25.9975 12.7875C26.0286 14.2198 25.7187 15.639 25.0931 16.9278C24.4676 18.2167 23.5445 19.3383 22.4 20.2C22.2589 20.3057 22.1484 20.4469 22.0794 20.6091C22.0105 20.7713 21.9857 20.9489 22.0075 21.1238L23.0075 29.1238C23.0379 29.3653 23.1554 29.5874 23.3379 29.7485C23.5203 29.9095 23.7553 29.9985 23.9987 29.9988C24.0405 29.9988 24.0822 29.9962 24.1237 29.9913C24.2541 29.975 24.3799 29.9333 24.4942 29.8684C24.6084 29.8035 24.7087 29.7168 24.7893 29.6131C24.87 29.5094 24.9295 29.3909 24.9643 29.2643C24.9992 29.1376 25.0087 29.0054 24.9925 28.875L24.0625 21.4338ZM16 10C15.8022 10 15.6088 9.94136 15.4444 9.83148C15.28 9.7216 15.1518 9.56542 15.0761 9.38269C15.0004 9.19997 14.9806 8.9989 15.0192 8.80492C15.0578 8.61094 15.153 8.43275 15.2929 8.2929C15.4327 8.15305 15.6109 8.05781 15.8049 8.01922C15.9989 7.98064 16.1999 8.00044 16.3827 8.07613C16.5654 8.15182 16.7216 8.27999 16.8314 8.44444C16.9413 8.60889 17 8.80223 17 9.00001C17 9.26523 16.8946 9.51958 16.7071 9.70712C16.5195 9.89465 16.2652 10 16 10ZM18 18C17.8022 18 17.6088 17.9414 17.4444 17.8315C17.28 17.7216 17.1518 17.5654 17.0761 17.3827C17.0004 17.2 16.9806 16.9989 17.0192 16.8049C17.0578 16.6109 17.153 16.4328 17.2929 16.2929C17.4327 16.153 17.6109 16.0578 17.8049 16.0192C17.9989 15.9806 18.1999 16.0004 18.3827 16.0761C18.5654 16.1518 18.7216 16.28 18.8314 16.4444C18.9413 16.6089 19 16.8022 19 17C19 17.2652 18.8946 17.5196 18.7071 17.7071C18.5195 17.8947 18.2652 18 18 18Z\"\n fill={color}\n />\n </svg>\n);\n","import { CheckCircle, XCircle } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport { RadioGroup, RadioGroupItem } from '../Radio/Radio';\nimport { forwardRef, HTMLAttributes, useId, useState } from 'react';\nimport { cn } from '../../utils/utils';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nimport { QuizVariant } from '../Quiz/Quiz.types';\nimport { OptionStatus } from '../../enums/Options';\n\n/**\n * Interface para definir uma alternativa\n */\nexport interface Alternative {\n value: string;\n label: string;\n status?: OptionStatus;\n disabled?: boolean;\n description?: string;\n}\n\n/**\n * Props do componente AlternativesList\n */\nexport interface AlternativesListProps {\n /** Lista de alternativas */\n alternatives: Alternative[];\n /** Nome do grupo de radio */\n name?: string;\n /** Valor selecionado por padrão */\n defaultValue?: string;\n /** Valor controlado */\n value?: string;\n /** Callback quando uma alternativa é selecionada */\n onValueChange?: (value: string) => void;\n /** Se o componente está desabilitado */\n disabled?: boolean;\n /** Layout das alternativas */\n layout?: 'default' | 'compact' | 'detailed';\n /** Classes CSS adicionais */\n className?: string;\n /** Modo de exibição: interativo (com radios funcionais) ou readonly (apenas visual) */\n mode?: 'interactive' | 'readonly';\n /** Valor selecionado pelo usuário (apenas para modo readonly) */\n selectedValue?: string;\n}\n\n/**\n * Componente reutilizável para exibir lista de alternativas com RadioGroup\n *\n * Suporta dois modos:\n * - `interactive`: Permite interação com radios (padrão)\n * - `readonly`: Apenas exibição visual dos estados\n *\n * @example\n * ```tsx\n * // Modo interativo (padrão)\n * <AlternativesList\n * mode=\"interactive\"\n * alternatives={[\n * { value: \"a\", label: \"Alternativa A\", status: \"correct\" },\n * { value: \"b\", label: \"Alternativa B\", status: \"incorrect\" },\n * { value: \"c\", label: \"Alternativa C\" }\n * ]}\n * defaultValue=\"a\"\n * onValueChange={(value) => console.log(value)}\n * />\n *\n * // Modo readonly - mostra seleção do usuário\n * <AlternativesList\n * mode=\"readonly\"\n * selectedValue=\"b\" // O que o usuário selecionou\n * alternatives={[\n * { value: \"a\", label: \"Resposta A\", status: \"correct\" }, // Mostra como correta\n * { value: \"b\", label: \"Resposta B\" }, // Mostra radio selecionado + badge incorreto\n * { value: \"c\", label: \"Resposta C\" }\n * ]}\n * />\n * ```\n */\nconst AlternativesList = ({\n alternatives,\n name,\n defaultValue,\n value,\n onValueChange,\n disabled = false,\n layout = 'default',\n className = '',\n mode = QuizVariant.INTERACTIVE,\n selectedValue,\n}: AlternativesListProps) => {\n // Gerar um ID único para garantir que cada instância tenha seu próprio grupo\n const uniqueId = useId();\n const groupName = name || `alternatives-${uniqueId}`;\n const [actualValue, setActualValue] = useState(value);\n // No modo readonly, não precisamos de interação\n const isReadonly = mode === 'readonly';\n const getStatusStyles = (\n status?: Alternative['status'],\n isReadonly?: boolean\n ) => {\n const hoverClass = isReadonly ? '' : 'hover:bg-background-50';\n\n switch (status) {\n case OptionStatus.CORRECT:\n return 'bg-success-background border-success-300';\n case OptionStatus.INCORRECT:\n return 'bg-error-background border-error-300';\n default:\n return `bg-background border-border-100 ${hoverClass}`;\n }\n };\n\n const getStatusBadge = (status?: Alternative['status']) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n };\n\n const getLayoutClasses = () => {\n switch (layout) {\n case 'compact':\n return 'gap-2';\n case 'detailed':\n return 'gap-4';\n default:\n return 'gap-3.5';\n }\n };\n\n // Componente para renderizar alternativa no modo readonly\n const renderReadonlyAlternative = (alternative: Alternative) => {\n const alternativeId = alternative.value;\n const isUserSelected = selectedValue === alternative.value;\n const isCorrectAnswer = alternative.status === OptionStatus.CORRECT;\n\n // Determinar o status da alternativa para visualização\n let displayStatus: Alternative['status'] = undefined;\n if (isUserSelected && !isCorrectAnswer) {\n // Usuário selecionou alternativa incorreta\n displayStatus = OptionStatus.INCORRECT;\n } else if (isCorrectAnswer) {\n // Alternativa correta (independente se foi selecionada ou não)\n displayStatus = OptionStatus.CORRECT;\n }\n\n const statusStyles = getStatusStyles(displayStatus, true);\n const statusBadge = getStatusBadge(displayStatus);\n\n // Radio visual - apenas mostra selecionado se o usuário escolheu esta alternativa\n const renderRadio = () => {\n const radioClasses = `w-6 h-6 rounded-full border-2 cursor-default transition-all duration-200 flex items-center justify-center ${\n isUserSelected\n ? 'border-primary-950 bg-background'\n : 'border-border-400 bg-background'\n }`;\n\n const dotClasses =\n 'w-3 h-3 rounded-full bg-primary-950 transition-all duration-200';\n\n return (\n <div className={radioClasses}>\n {isUserSelected && <div className={dotClasses} />}\n </div>\n );\n };\n\n if (layout === 'detailed') {\n return (\n <div\n key={alternativeId}\n className={cn(\n 'border-2 rounded-lg p-4 w-full',\n statusStyles,\n alternative.disabled ? 'opacity-50' : ''\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3 flex-1\">\n <div className=\"mt-1\">{renderRadio()}</div>\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={alternative.label}\n className={cn(\n 'block font-medium',\n selectedValue === alternative.value || statusBadge\n ? 'text-text-950'\n : 'text-text-600'\n )}\n />\n {alternative.description && (\n <p className=\"text-sm text-text-600 mt-1\">\n {alternative.description}\n </p>\n )}\n </div>\n </div>\n {statusBadge && <div className=\"flex-shrink-0\">{statusBadge}</div>}\n </div>\n </div>\n );\n }\n\n return (\n <div\n key={alternativeId}\n className={cn(\n 'flex flex-row justify-between items-start gap-2 p-2 rounded-lg w-full',\n statusStyles,\n alternative.disabled ? 'opacity-50' : ''\n )}\n >\n <div className=\"flex items-center gap-2 flex-1\">\n {renderRadio()}\n <HtmlMathRenderer\n content={alternative.label}\n className={cn(\n 'flex-1',\n selectedValue === alternative.value || statusBadge\n ? 'text-text-950'\n : 'text-text-600'\n )}\n />\n </div>\n {statusBadge && <div className=\"flex-shrink-0\">{statusBadge}</div>}\n </div>\n );\n };\n\n // Se for modo readonly, renderizar sem RadioGroup\n if (isReadonly) {\n return (\n <div\n className={cn('flex flex-col', getLayoutClasses(), 'w-full', className)}\n >\n {alternatives.map((alternative) =>\n renderReadonlyAlternative(alternative)\n )}\n </div>\n );\n }\n\n return (\n <RadioGroup\n name={groupName}\n defaultValue={defaultValue}\n value={value}\n onValueChange={(value) => {\n setActualValue(value);\n onValueChange?.(value);\n }}\n disabled={disabled}\n className={cn('flex flex-col', getLayoutClasses(), className)}\n >\n {alternatives.map((alternative, index) => {\n const alternativeId = alternative.value || `alt-${index}`;\n const statusStyles = getStatusStyles(alternative.status, false);\n const statusBadge = getStatusBadge(alternative.status);\n\n if (layout === 'detailed') {\n return (\n <div\n key={alternativeId}\n className={cn(\n 'border-2 rounded-lg p-4 transition-all',\n statusStyles,\n alternative.disabled\n ? 'opacity-50 cursor-not-allowed'\n : 'cursor-pointer'\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3 flex-1\">\n <RadioGroupItem\n value={alternative.value}\n id={alternativeId}\n disabled={alternative.disabled}\n className=\"mt-1\"\n />\n <div className=\"flex-1\">\n <label\n htmlFor={alternativeId}\n className={cn(\n 'block font-medium',\n actualValue === alternative.value\n ? 'text-text-950'\n : 'text-text-600',\n alternative.disabled\n ? 'cursor-not-allowed'\n : 'cursor-pointer'\n )}\n >\n <HtmlMathRenderer content={alternative.label} inline />\n </label>\n {alternative.description && (\n <p className=\"text-sm text-text-600 mt-1\">\n {alternative.description}\n </p>\n )}\n </div>\n </div>\n {statusBadge && (\n <div className=\"flex-shrink-0\">{statusBadge}</div>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div\n key={alternativeId}\n className={cn(\n 'flex flex-row justify-between gap-2 items-start p-2 rounded-lg transition-all',\n statusStyles,\n alternative.disabled ? 'opacity-50 cursor-not-allowed' : ''\n )}\n >\n <div className=\"flex items-center gap-2 flex-1\">\n <RadioGroupItem\n value={alternative.value}\n id={alternativeId}\n disabled={alternative.disabled}\n />\n <label\n htmlFor={alternativeId}\n className={cn(\n 'flex-1',\n actualValue === alternative.value\n ? 'text-text-950'\n : 'text-text-600',\n alternative.disabled ? 'cursor-not-allowed' : 'cursor-pointer'\n )}\n >\n <HtmlMathRenderer content={alternative.label} inline />\n </label>\n </div>\n {statusBadge && <div className=\"flex-shrink-0\">{statusBadge}</div>}\n </div>\n );\n })}\n </RadioGroup>\n );\n};\n\ninterface HeaderAlternativeProps extends HTMLAttributes<HTMLDivElement> {\n title: string;\n subTitle: string;\n content: string;\n}\n\nconst HeaderAlternative = forwardRef<HTMLDivElement, HeaderAlternativeProps>(\n ({ className, title, subTitle, content, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-background p-4 flex flex-col gap-4 rounded-xl',\n className\n )}\n {...props}\n >\n <span className=\"flex flex-col\">\n <p className=\"text-text-950 font-bold text-lg\">{title}</p>\n <p className=\"text-text-700 text-sm \">{subTitle}</p>\n </span>\n\n <HtmlMathRenderer content={content} className=\"text-text-950 text-md\" />\n </div>\n );\n }\n);\n\nexport { AlternativesList, HeaderAlternative };\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport { AlternativesList } from '../../../components/Alternative/Alternative';\nimport { OptionStatus } from '../../../enums/Options';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\n\n/**\n * Render alternative question (single choice)\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionAlternative = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n // Check if options have isCorrect defined (can auto-validate even if pending)\n const hasAutoValidation = result?.options?.some(\n (op) => op.isCorrect !== undefined && op.isCorrect !== null\n );\n\n const alternatives = question.options?.map((option) => {\n const isCorrectOption =\n result?.options?.find((op) => op.id === option.id)?.isCorrect || false;\n\n const isSelected =\n result?.selectedOptions?.some(\n (selectedOption) => selectedOption.optionId === option.id\n ) || false;\n\n // Show correct answers if not pending, OR if we can auto-validate (has isCorrect)\n const shouldShowCorrectAnswers =\n result?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO ||\n hasAutoValidation;\n\n let status: OptionStatus;\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation and no auto-validation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n\n return {\n label: option.option,\n value: option.id,\n status: status,\n };\n });\n\n if (!alternatives || alternatives.length === 0) {\n return (\n <div>\n <Text size=\"sm\" weight=\"normal\">\n Não há Alternativas\n </Text>\n </div>\n );\n }\n\n return (\n <div className=\"pt-2\">\n <AlternativesList\n mode=\"readonly\"\n key={`question-${question.id}`}\n name={`question-${question.id}`}\n layout=\"compact\"\n alternatives={alternatives}\n selectedValue={result?.selectedOptions?.[0]?.optionId || ''}\n />\n </div>\n );\n};\n","import { HtmlHTMLAttributes, useEffect, useState } from 'react';\nimport CheckboxList, { CheckboxListItem } from '../CheckBox/CheckboxList';\nimport { cn } from '../../utils/utils';\nimport { CheckCircle, XCircle, Check } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nimport { QuizVariant } from '../Quiz/Quiz.types';\nimport { OptionStatus } from '../../enums/Options';\n\ninterface Choice {\n value: string;\n label: string;\n status?: OptionStatus;\n disabled?: boolean;\n}\n\ninterface MultipleChoiceListProps extends HtmlHTMLAttributes<HTMLDivElement> {\n choices: Choice[];\n disabled?: boolean;\n name?: string;\n selectedValues?: string[];\n onHandleSelectedValues?: (values: string[]) => void;\n mode?: 'interactive' | 'readonly';\n}\n\nconst MultipleChoiceList = ({\n disabled = false,\n className = '',\n choices,\n name,\n selectedValues,\n onHandleSelectedValues,\n mode = QuizVariant.INTERACTIVE,\n}: MultipleChoiceListProps) => {\n const [actualValue, setActualValue] = useState(selectedValues);\n\n useEffect(() => {\n setActualValue(selectedValues);\n }, [selectedValues]);\n const getStatusBadge = (status: Choice['status']) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n };\n\n const getStatusStyles = (status: Choice['status']) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return 'bg-success-background border-success-300';\n case OptionStatus.INCORRECT:\n return 'bg-error-background border-error-300';\n default:\n return `bg-background border-border-100`;\n }\n };\n\n const renderVisualCheckbox = (isSelected: boolean, isDisabled: boolean) => {\n const checkboxClasses = cn(\n 'w-5 h-5 rounded border-2 cursor-default transition-all duration-200 flex items-center justify-center',\n isSelected\n ? 'border-primary-950 bg-primary-950 text-text'\n : 'border-border-400 bg-background',\n isDisabled && 'opacity-40 cursor-not-allowed'\n );\n\n return (\n <div className={checkboxClasses}>\n {isSelected && <Check size={16} weight=\"bold\" />}\n </div>\n );\n };\n\n if (mode === 'readonly') {\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n {choices.map((choice, i) => {\n const isSelected = actualValue?.includes(choice.value) || false;\n const statusStyles = getStatusStyles(choice.status);\n const statusBadge = getStatusBadge(choice.status);\n\n return (\n <div\n key={`readonly-${choice.value}-${i}`}\n className={cn(\n 'flex flex-row justify-between gap-2 items-start p-2 rounded-lg transition-all',\n statusStyles,\n choice.disabled ? 'opacity-50 cursor-not-allowed' : ''\n )}\n >\n <div className=\"flex items-center gap-2 flex-1\">\n {renderVisualCheckbox(isSelected, choice.disabled || disabled)}\n <HtmlMathRenderer\n content={choice.label}\n className={cn(\n 'flex-1',\n isSelected ||\n (choice.status && choice.status != OptionStatus.NEUTRAL)\n ? 'text-text-950'\n : 'text-text-600',\n choice.disabled || disabled\n ? 'cursor-not-allowed'\n : 'cursor-default'\n )}\n />\n </div>\n {statusBadge && (\n <div className=\"flex-shrink-0\">{statusBadge}</div>\n )}\n </div>\n );\n })}\n </div>\n );\n }\n return (\n <div\n className={cn(\n 'flex flex-row justify-between gap-2 items-start p-2 rounded-lg transition-all',\n disabled ? 'opacity-50 cursor-not-allowed' : '',\n className\n )}\n >\n <CheckboxList\n name={name}\n values={actualValue}\n onValuesChange={(v) => {\n setActualValue(v);\n onHandleSelectedValues?.(v);\n }}\n disabled={disabled}\n >\n {choices.map((choice, i) => (\n <div\n key={`interactive-${choice.value}-${i}`}\n className=\"flex flex-row gap-2 items-center\"\n >\n <CheckboxListItem\n value={choice.value}\n id={`interactive-${choice.value}-${i}`}\n disabled={choice.disabled || disabled}\n />\n\n <label\n htmlFor={`interactive-${choice.value}-${i}`}\n className={cn(\n 'flex-1',\n actualValue?.includes(choice.value)\n ? 'text-text-950'\n : 'text-text-600',\n choice.disabled || disabled\n ? 'cursor-not-allowed'\n : 'cursor-pointer'\n )}\n >\n <HtmlMathRenderer content={choice.label} />\n </label>\n </div>\n ))}\n </CheckboxList>\n </div>\n );\n};\n\nexport { MultipleChoiceList };\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport { MultipleChoiceList } from '../../../components/MultipleChoice/MultipleChoice';\nimport { OptionStatus } from '../../../enums/Options';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\n\n/**\n * Render multiple choice question\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionMultipleChoice = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n // Check if options have isCorrect defined (can auto-validate even if pending)\n const hasAutoValidation = result?.options?.some(\n (op) => op.isCorrect !== undefined && op.isCorrect !== null\n );\n\n const choices = question.options?.map((option) => {\n const isCorrectOption =\n result?.options?.find((op) => op.id === option.id)?.isCorrect || false;\n\n const isSelected = result?.selectedOptions?.some(\n (op) => op.optionId === option.id\n );\n\n // Show correct/incorrect status if not pending/blank, OR if we can auto-validate (has isCorrect)\n const shouldShowCorrectAnswers =\n (result?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n result?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO) ||\n hasAutoValidation;\n\n let status: OptionStatus;\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation and no auto-validation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n\n return {\n label: option.option,\n value: option.id,\n status,\n };\n });\n\n if (!choices || choices.length === 0) {\n return (\n <div>\n <Text size=\"sm\" weight=\"normal\">\n Não há Escolhas Múltiplas\n </Text>\n </div>\n );\n }\n\n const selectedValues =\n result?.selectedOptions?.map((op) => op.optionId) || [];\n\n return (\n <div className=\"pt-2\">\n <MultipleChoiceList\n mode=\"readonly\"\n key={`question-${question.id}`}\n name={`question-${question.id}`}\n choices={choices}\n selectedValues={selectedValues}\n />\n </div>\n );\n};\n","import {\n Fragment,\n forwardRef,\n MouseEvent,\n ReactNode,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { ANSWER_STATUS, useQuizStore } from './useQuizStore';\nimport { QuizVariant } from './Quiz.types';\nimport { TrueFalseEnum } from '../../enums/Quiz';\nimport {\n prependLetterToHtml,\n getTrueOrFalseOptionState,\n shuffleWithSeed,\n} from './Quiz.utils';\nimport { cn } from '../../utils/utils';\nimport { stripHtmlTags } from '../../utils/stringUtils';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport TextArea from '../TextArea/TextArea';\nimport { AlternativesList } from '../Alternative/Alternative';\nimport { OptionStatus } from '../../enums/Options';\nimport { MultipleChoiceList } from '../MultipleChoice/MultipleChoice';\nimport Badge from '../Badge/Badge';\nimport { CheckCircle, XCircle } from 'phosphor-react';\nimport ImageQuestion from '../../assets/img/mock-image-question.png';\nimport Text from '../Text/Text';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nexport const getStatusBadge = (status?: OptionStatus) => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n};\n\nexport const getStatusStyles = (variantCorrect?: OptionStatus) => {\n switch (variantCorrect) {\n case OptionStatus.CORRECT:\n return 'bg-success-background border-success-300';\n case OptionStatus.INCORRECT:\n return 'bg-error-background border-error-300';\n default:\n return '';\n }\n};\n\n/**\n * Normalizes parsed answer data to Record<string, string> format.\n * Handles legacy array format [{ optionId, selectedValue }] by converting to { [optionId]: selectedValue }.\n */\nconst normalizeAnswerData = (parsed: unknown): Record<string, string> => {\n // Handle legacy array format: [{ optionId: string, selectedValue: string }]\n if (Array.isArray(parsed)) {\n const result: Record<string, string> = {};\n for (const item of parsed) {\n if (\n item &&\n typeof item === 'object' &&\n 'optionId' in item &&\n 'selectedValue' in item\n ) {\n result[item.optionId as string] = item.selectedValue as string;\n }\n }\n return result;\n }\n\n // Handle expected object format: { [optionId]: selectedValue }\n if (parsed && typeof parsed === 'object') {\n return parsed as Record<string, string>;\n }\n\n return {};\n};\n\n/**\n * Parses JSON answers from stored answer string.\n * In result mode, uses persisted results. Otherwise, uses current draft answers.\n * Normalizes legacy array format to expected Record<string, string> map.\n */\nconst parseStoredAnswers = (\n variant: QuizVariant,\n resultAnswer: string | null | undefined,\n currentAnswer: string | null | undefined\n): Record<string, string> => {\n if (variant === QuizVariant.RESULT) {\n if (!resultAnswer) return {};\n try {\n const parsed = JSON.parse(resultAnswer);\n return normalizeAnswerData(parsed);\n } catch {\n return {};\n }\n }\n if (currentAnswer) {\n try {\n const parsed = JSON.parse(currentAnswer);\n return normalizeAnswerData(parsed);\n } catch {\n return {};\n }\n }\n return {};\n};\n\n/**\n * Converts isCorrect boolean to status variant string.\n * Returns undefined for null/unanswered to keep neutral styling.\n */\nconst getAnswerStatus = (\n isCorrect: boolean | null\n): OptionStatus | undefined => {\n if (isCorrect === true) return OptionStatus.CORRECT;\n if (isCorrect === false) return OptionStatus.INCORRECT;\n return undefined;\n};\n\ninterface QuizVariantInterface {\n paddingBottom?: string;\n}\n\nconst QuizSubTitle = forwardRef<HTMLDivElement, { subTitle: string }>(\n ({ subTitle, ...props }, ref) => {\n return (\n <div className=\"px-4 pb-2 pt-6\" {...props} ref={ref}>\n <p className=\"font-bold text-lg text-text-950\">{subTitle}</p>\n </div>\n );\n }\n);\n\nconst QuizContainer = forwardRef<\n HTMLDivElement,\n { children: ReactNode; className?: string }\n>(({ children, className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-background rounded-t-xl px-4 pt-4 pb-[80px] h-auto flex flex-col gap-4 mb-auto',\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n});\n\nconst QuizAlternative = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n selectAnswer,\n getQuestionResultByQuestionId,\n getCurrentAnswer,\n variant,\n } = useQuizStore();\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n const currentAnswer = getCurrentAnswer();\n const alternatives = currentQuestion?.options?.map((option) => {\n let status: OptionStatus = OptionStatus.NEUTRAL;\n if (variant === QuizVariant.RESULT) {\n const isCorrectOption =\n currentQuestionResult?.options?.find((op) => op.id === option.id)\n ?.isCorrect || false;\n\n const isSelected = currentQuestionResult?.selectedOptions.some(\n (selectedOption) => selectedOption.optionId === option.id\n );\n\n // Only show correct/incorrect status if answer is not pending evaluation\n const shouldShowCorrectAnswers =\n currentQuestionResult?.answerStatus !==\n ANSWER_STATUS.PENDENTE_AVALIACAO &&\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n }\n\n return {\n label: option.option,\n value: option.id,\n status: status,\n };\n });\n\n if (!alternatives)\n return (\n <div>\n <p>Não há Alternativas</p>\n </div>\n );\n\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"space-y-4\">\n <AlternativesList\n mode={variant === QuizVariant.DEFAULT ? 'interactive' : 'readonly'}\n key={`question-${currentQuestion?.id || '1'}`}\n name={`question-${currentQuestion?.id || '1'}`}\n layout=\"compact\"\n alternatives={alternatives}\n value={\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.selectedOptions[0]?.optionId || ''\n : currentAnswer?.optionId || ''\n }\n selectedValue={\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.selectedOptions[0]?.optionId || ''\n : currentAnswer?.optionId || ''\n }\n onValueChange={(value) => {\n if (currentQuestion) {\n selectAnswer(currentQuestion.id, value);\n }\n }}\n />\n </div>\n </QuizContainer>\n </>\n );\n};\n\nconst QuizMultipleChoice = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n selectMultipleAnswer,\n getAllCurrentAnswer,\n getQuestionResultByQuestionId,\n variant,\n } = useQuizStore();\n const currentQuestion = getCurrentQuestion();\n const allCurrentAnswers = getAllCurrentAnswer();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n // Use ref to track previous values and prevent unnecessary updates\n const prevSelectedValuesRef = useRef<string[]>([]);\n const prevQuestionIdRef = useRef<string>('');\n\n // Memoize the answer IDs to prevent unnecessary re-renders\n // For MULTIPLA_ESCOLHA, we now have a single answer entry with selectedOptionIds array\n const allCurrentAnswerIds = useMemo(() => {\n if (allCurrentAnswers && allCurrentAnswers.length > 0) {\n // Prefer any row already using the new format\n const answerWithSelectedOptionIds = allCurrentAnswers.find((answer) =>\n Array.isArray(answer.selectedOptionIds)\n );\n if (answerWithSelectedOptionIds) {\n return answerWithSelectedOptionIds.selectedOptionIds ?? [];\n }\n // Fallback to old format (multiple entries with optionId)\n return allCurrentAnswers.map((answer) => answer.optionId);\n }\n return [];\n }, [allCurrentAnswers]);\n\n // Memoize the selected values to prevent infinite loops\n const selectedValues = useMemo(() => {\n return allCurrentAnswerIds?.filter((id): id is string => id !== null) || [];\n }, [allCurrentAnswerIds]);\n\n // Only update selectedValues if they actually changed or question changed\n const stableSelectedValues = useMemo(() => {\n // In result mode, always use selectedOptions from the question result\n if (variant === QuizVariant.RESULT) {\n return (\n currentQuestionResult?.selectedOptions?.map((op) => op.optionId) || []\n );\n }\n\n const currentQuestionId = currentQuestion?.id || '';\n const hasQuestionChanged = prevQuestionIdRef.current !== currentQuestionId;\n\n if (hasQuestionChanged) {\n prevQuestionIdRef.current = currentQuestionId;\n prevSelectedValuesRef.current = selectedValues;\n return selectedValues;\n }\n\n // Only update if values actually changed\n const hasValuesChanged =\n JSON.stringify(prevSelectedValuesRef.current) !==\n JSON.stringify(selectedValues);\n if (hasValuesChanged) {\n prevSelectedValuesRef.current = selectedValues;\n return selectedValues;\n }\n\n return prevSelectedValuesRef.current;\n }, [\n selectedValues,\n currentQuestion?.id,\n variant,\n currentQuestionResult?.selectedOptions,\n ]);\n\n // Memoize the callback to prevent unnecessary re-renders\n const handleSelectedValues = useCallback(\n (values: string[]) => {\n if (currentQuestion) {\n selectMultipleAnswer(currentQuestion.id, values);\n }\n },\n [currentQuestion, selectMultipleAnswer]\n );\n\n // Create a stable key to force re-mount when question changes\n const questionKey = useMemo(\n () => `question-${currentQuestion?.id || '1'}`,\n [currentQuestion?.id]\n );\n const choices = currentQuestion?.options?.map((option) => {\n let status: OptionStatus = OptionStatus.NEUTRAL;\n\n if (variant === QuizVariant.RESULT) {\n const isCorrectOption =\n currentQuestionResult?.options?.find((op) => op.id === option.id)\n ?.isCorrect || false;\n\n const isSelected = currentQuestionResult?.selectedOptions?.some(\n (op) => op.optionId === option.id\n );\n\n // Only show correct/incorrect status if answer is not pending evaluation\n const shouldShowCorrectAnswers =\n currentQuestionResult?.answerStatus !==\n ANSWER_STATUS.PENDENTE_AVALIACAO &&\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n if (shouldShowCorrectAnswers) {\n if (isCorrectOption) {\n status = OptionStatus.CORRECT;\n } else if (isSelected && !isCorrectOption) {\n status = OptionStatus.INCORRECT;\n } else {\n status = OptionStatus.NEUTRAL;\n }\n } else {\n // When pending evaluation, show all options as neutral\n status = OptionStatus.NEUTRAL;\n }\n }\n\n return {\n label: option.option,\n value: option.id,\n status: status,\n };\n });\n\n if (!choices)\n return (\n <div>\n <p>Não há Escolhas Multiplas</p>\n </div>\n );\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"space-y-4\">\n <MultipleChoiceList\n choices={choices}\n key={questionKey}\n name={questionKey}\n selectedValues={stableSelectedValues}\n onHandleSelectedValues={handleSelectedValues}\n mode={variant === QuizVariant.DEFAULT ? 'interactive' : 'readonly'}\n />\n </div>\n </QuizContainer>\n </>\n );\n};\n\nconst QuizDissertative = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n variant,\n getDissertativeCharLimit,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n const currentAnswer = getCurrentAnswer();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const charLimit = getDissertativeCharLimit();\n\n const handleAnswerChange = (value: string) => {\n if (currentQuestion) {\n selectDissertativeAnswer(currentQuestion.id, value);\n }\n };\n\n // Auto-resize function\n const adjustTextareaHeight = useCallback(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n const scrollHeight = textareaRef.current.scrollHeight;\n const minHeight = 120; // 120px minimum height\n const maxHeight = 400; // 400px maximum height\n const newHeight = Math.min(Math.max(scrollHeight, minHeight), maxHeight);\n textareaRef.current.style.height = `${newHeight}px`;\n }\n }, []);\n\n // Adjust height when currentAnswer changes\n useEffect(() => {\n adjustTextareaHeight();\n }, [currentAnswer, adjustTextareaHeight]);\n\n if (!currentQuestion) {\n return (\n <div className=\"space-y-4\">\n <p className=\"text-text-600 text-md\">Nenhuma questão disponível</p>\n </div>\n );\n }\n\n const localAnswer =\n (variant == 'result'\n ? currentQuestionResult?.answer\n : currentAnswer?.answer) || '';\n return (\n <>\n <QuizSubTitle subTitle=\"Resposta\" />\n\n <QuizContainer className={cn(variant != 'result' && paddingBottom)}>\n <div className=\"space-y-4 max-h-[600px] overflow-y-auto\">\n {variant === QuizVariant.DEFAULT ? (\n <div className=\"space-y-4\">\n <TextArea\n ref={textareaRef}\n placeholder=\"Escreva sua resposta\"\n value={localAnswer}\n onChange={(e) => handleAnswerChange(e.target.value)}\n rows={4}\n className=\"min-h-[120px] max-h-[400px] resize-none overflow-y-auto\"\n maxLength={charLimit}\n showCharacterCount={!!charLimit}\n />\n </div>\n ) : (\n <div className=\"space-y-4\">\n <p className=\"text-text-600 text-md whitespace-pre-wrap\">\n {localAnswer || 'Nenhuma resposta fornecida'}\n </p>\n </div>\n )}\n </div>\n </QuizContainer>\n\n {variant === QuizVariant.RESULT &&\n currentQuestionResult?.teacherFeedback && (\n <>\n <QuizSubTitle subTitle=\"Observação do professor\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <p className=\"text-text-600 text-md whitespace-pre-wrap\">\n {currentQuestionResult?.teacherFeedback}\n </p>\n </QuizContainer>\n </>\n )}\n </>\n );\n};\n\nconst QuizTrueOrFalse = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n variant,\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n getUserAnswerByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentAnswer = getCurrentAnswer();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n // Get the options - prefer persisted result options in result mode, fallback to live question\n const options = useMemo(() => {\n if (variant === QuizVariant.RESULT && currentQuestionResult?.options) {\n return currentQuestionResult.options;\n }\n return currentQuestion?.options || [];\n }, [variant, currentQuestionResult?.options, currentQuestion?.options]);\n\n // Parse stored answers from JSON string, handling both object and legacy array formats\n const parsedAnswers: Record<string, string> = useMemo(() => {\n return parseStoredAnswers(\n variant,\n currentQuestionResult?.answer,\n currentAnswer?.answer\n );\n }, [variant, currentQuestionResult?.answer, currentAnswer?.answer]);\n\n // Local state to track answers: { \"optionId\": \"V\" | \"F\" }\n const [localAnswers, setLocalAnswers] =\n useState<Record<string, string>>(parsedAnswers);\n\n // Sync local answers when question changes or parsed answers update\n useEffect(() => {\n setLocalAnswers(parsedAnswers);\n }, [parsedAnswers, currentQuestion?.id]);\n\n // Handle select change for an option\n const handleSelectChange = (optionId: string, value: string) => {\n if (!currentQuestion) return;\n\n // Get the LATEST answers directly from the store (not from closure)\n // This is critical to avoid stale closure issues when user selects options quickly\n const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n let baseAnswers: Record<string, string> = {};\n if (latestStoreAnswer?.answer) {\n try {\n const parsed = JSON.parse(latestStoreAnswer.answer);\n baseAnswers = normalizeAnswerData(parsed);\n } catch {\n // Invalid JSON, start fresh\n }\n }\n\n // Merge: store answers + local state + new selection\n const mergedAnswers = {\n ...baseAnswers,\n ...localAnswers,\n [optionId]: value,\n };\n setLocalAnswers(mergedAnswers);\n\n // Save to store as JSON string\n selectDissertativeAnswer(currentQuestion.id, JSON.stringify(mergedAnswers));\n };\n\n // Get the current selection for an option\n const getOptionSelection = (optionId: string): string | undefined => {\n return localAnswers[optionId];\n };\n\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n const isDefaultVariant = variant === QuizVariant.DEFAULT;\n\n // Check if we should show correct/incorrect status\n const shouldShowStatus =\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n if (options.length === 0) {\n return (\n <QuizContainer className={cn('', paddingBottom)}>\n <Text size=\"sm\" className=\"text-text-500 italic\">\n Nenhuma opção disponível para esta questão\n </Text>\n </QuizContainer>\n );\n }\n\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"flex flex-col gap-3.5\">\n {options.map((option, index) => {\n // Use helper to compute all option state\n const {\n hasAnswered,\n studentAnswer,\n correctAnswer,\n isStudentCorrect,\n variantCorrect,\n } = getTrueOrFalseOptionState(\n option.id,\n variant,\n currentQuestionResult,\n localAnswers\n );\n\n const contentWithLetter = prependLetterToHtml(\n getLetterByIndex(index),\n option.option\n );\n\n return (\n <section\n key={option.id || `option-${index}`}\n className=\"flex flex-col gap-2\"\n >\n <div\n className={cn(\n 'w-full grid grid-cols-[1fr_auto] items-start gap-4 p-2 rounded-md border',\n !isDefaultVariant && shouldShowStatus && hasAnswered\n ? getStatusStyles(variantCorrect)\n : 'border-transparent'\n )}\n >\n <HtmlMathRenderer\n content={contentWithLetter}\n className=\"text-text-900 text-sm\"\n />\n\n {isDefaultVariant ? (\n <Select\n size=\"medium\"\n value={getOptionSelection(option.id)}\n onValueChange={(value) =>\n handleSelectChange(option.id, value)\n }\n >\n <SelectTrigger className=\"w-[120px]\">\n <SelectValue placeholder=\"Selecione\" />\n </SelectTrigger>\n\n <SelectContent>\n <SelectItem value={TrueFalseEnum.VERDADEIRO}>\n Verdadeiro\n </SelectItem>\n <SelectItem value={TrueFalseEnum.FALSO}>\n Falso\n </SelectItem>\n </SelectContent>\n </Select>\n ) : (\n shouldShowStatus &&\n hasAnswered && <div>{getStatusBadge(variantCorrect)}</div>\n )}\n </div>\n\n {!isDefaultVariant && shouldShowStatus && (\n <span className=\"flex flex-row gap-2 items-center flex-wrap\">\n {hasAnswered ? (\n <>\n <Text size=\"2xs\" className=\"text-text-800\">\n Resposta selecionada: {studentAnswer}\n </Text>\n {!isStudentCorrect && (\n <Text size=\"2xs\" className=\"text-text-800\">\n | Resposta correta: {correctAnswer}\n </Text>\n )}\n </>\n ) : (\n <Text size=\"2xs\" className=\"text-text-800\">\n Não respondida | Resposta correta: {correctAnswer}\n </Text>\n )}\n </span>\n )}\n </section>\n );\n })}\n </div>\n </QuizContainer>\n </>\n );\n};\n\ninterface UserAnswer {\n option: string;\n dotOption: string | null;\n correctOption: string;\n isCorrect: boolean | null;\n}\n\nconst QuizConnectDots = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n variant,\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n getUserAnswerByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n const currentAnswer = getCurrentAnswer();\n\n // Extract options from the current question\n // Each option has: id, option (left column), correctValue (right column)\n const questionOptions = useMemo(() => {\n if (!currentQuestion?.options) return [];\n return currentQuestion.options;\n }, [currentQuestion?.options]);\n\n // Build dotsOptions from correctValue of each option (right column values)\n // Shuffle them so they don't appear in the same order as the left column\n const dotsOptions = useMemo(() => {\n const dots = questionOptions\n .map((opt) => ({ label: opt.correctValue || '' }))\n .filter((opt) => opt.label !== '');\n // Use question ID as seed for consistent shuffle\n return shuffleWithSeed(dots, currentQuestion?.id || '');\n }, [questionOptions, currentQuestion?.id]);\n\n // Build options for display (left column with correct answer mapping)\n const options = useMemo(() => {\n return questionOptions.map((opt) => ({\n id: opt.id,\n label: opt.option,\n correctOption: opt.correctValue || '',\n }));\n }, [questionOptions]);\n\n // Parse stored matching answers\n // In result mode, read from matchingAnswers array, fallback to answer JSON\n // In default mode, read from currentAnswer.answer JSON string\n const parsedAnswers: Record<string, string> = useMemo(() => {\n if (\n variant === QuizVariant.RESULT &&\n currentQuestionResult?.matchingAnswers\n ) {\n // Convert matchingAnswers array to Record<optionId, selectedValue>\n const answers: Record<string, string> = {};\n for (const match of currentQuestionResult.matchingAnswers) {\n answers[match.optionId] = match.selectedValue;\n }\n return answers;\n }\n // Fallback to answer JSON string (for older/partially migrated submissions)\n return parseStoredAnswers(\n variant,\n currentQuestionResult?.answer,\n currentAnswer?.answer\n );\n }, [\n variant,\n currentQuestionResult?.matchingAnswers,\n currentQuestionResult?.answer,\n currentAnswer?.answer,\n ]);\n\n const [userAnswers, setUserAnswers] = useState<UserAnswer[]>([]);\n\n // Initialize userAnswers from options and stored answers\n useEffect(() => {\n if (options.length > 0) {\n setUserAnswers(\n options.map((option) => {\n const storedValue = parsedAnswers[option.id] || null;\n return {\n option: option.label,\n dotOption: storedValue,\n correctOption: option.correctOption,\n isCorrect: storedValue\n ? storedValue === option.correctOption\n : null,\n };\n })\n );\n }\n }, [options, parsedAnswers]);\n\n const handleSelectDot = (optionIndex: number, dotValue: string) => {\n const option = options[optionIndex];\n if (!option || !currentQuestion) return;\n\n // Update local state\n setUserAnswers((prev) => {\n const next = [...prev];\n next[optionIndex] = {\n option: option.label,\n dotOption: dotValue,\n correctOption: option.correctOption,\n isCorrect: dotValue ? dotValue === option.correctOption : null,\n };\n return next;\n });\n\n // Get the LATEST answers directly from the store (not from closure)\n const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n let baseAnswers: Record<string, string> = {};\n if (latestStoreAnswer?.answer) {\n try {\n const parsed = JSON.parse(latestStoreAnswer.answer);\n baseAnswers = normalizeAnswerData(parsed);\n } catch {\n // Invalid JSON, start fresh\n }\n }\n\n // Persist to shared store as JSON\n const newAnswers = {\n ...baseAnswers,\n ...parsedAnswers,\n [option.id]: dotValue,\n };\n selectDissertativeAnswer(currentQuestion.id, JSON.stringify(newAnswers));\n };\n\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 'a', 'b', 'c'...\n\n const isDefaultVariant = variant === QuizVariant.DEFAULT;\n const assignedDots = new Set(\n userAnswers.map((a) => a.dotOption).filter(Boolean)\n );\n\n if (options.length === 0) {\n return (\n <QuizContainer className={cn('', paddingBottom)}>\n <Text size=\"sm\" className=\"text-text-500 italic\">\n Nenhuma opção de relacionamento disponível\n </Text>\n </QuizContainer>\n );\n }\n\n return (\n <>\n <QuizSubTitle subTitle=\"Alternativas\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"flex flex-col gap-3.5\">\n {options.map((option, index) => {\n const answer = userAnswers[index] || {\n option: option.label,\n dotOption: null,\n correctOption: option.correctOption,\n isCorrect: null,\n };\n const variantCorrect = getAnswerStatus(answer.isCorrect);\n return (\n <section key={option.id} className=\"flex flex-col gap-2\">\n <div\n className={cn(\n 'grid grid-cols-[1fr_auto] items-center gap-4 p-2 rounded-md',\n !isDefaultVariant && variantCorrect\n ? getStatusStyles(variantCorrect)\n : ''\n )}\n >\n <HtmlMathRenderer\n content={prependLetterToHtml(\n getLetterByIndex(index),\n option.label\n )}\n className=\"text-text-900 text-sm\"\n />\n\n {isDefaultVariant ? (\n <Select\n size=\"medium\"\n value={answer.dotOption || undefined}\n onValueChange={(value) => handleSelectDot(index, value)}\n >\n <SelectTrigger\n className=\"w-[180px] overflow-hidden truncate\"\n title={\n answer.dotOption\n ? stripHtmlTags(answer.dotOption)\n : undefined\n }\n >\n <SelectValue placeholder=\"Selecione opção\" />\n </SelectTrigger>\n\n <SelectContent>\n {dotsOptions\n .filter(\n (dot) =>\n !assignedDots.has(dot.label) ||\n answer.dotOption === dot.label\n )\n .map((dot) => (\n <SelectItem\n key={dot.label}\n value={dot.label}\n title={stripHtmlTags(dot.label)}\n truncate\n >\n {stripHtmlTags(dot.label)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <div>\n {answer.isCorrect === null\n ? null\n : getStatusBadge(variantCorrect)}\n </div>\n )}\n </div>\n\n {!isDefaultVariant && (\n <span className=\"flex flex-row gap-2 items-center\">\n <Text size=\"2xs\" className=\"text-text-800\">\n Resposta selecionada:{' '}\n {answer.dotOption\n ? stripHtmlTags(answer.dotOption)\n : 'Nenhuma'}\n </Text>\n {answer.isCorrect === false && (\n <Text size=\"2xs\" className=\"text-text-800\">\n Resposta correta: {stripHtmlTags(answer.correctOption)}\n </Text>\n )}\n </span>\n )}\n </section>\n );\n })}\n </div>\n </QuizContainer>\n </>\n );\n};\n\nconst QuizFill = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n getCurrentQuestion,\n getQuestionResultByQuestionId,\n getCurrentAnswer,\n selectDissertativeAnswer,\n variant,\n getUserAnswerByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n const currentAnswer = getCurrentAnswer();\n\n const baseId = useId();\n\n // Get the additionalContent from the question (contains text with {optionId} placeholders)\n // In result mode, prefer the persisted snapshot to match parsedAnswers\n const additionalContent =\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.additionalContent ||\n currentQuestion?.additionalContent ||\n ''\n : currentQuestion?.additionalContent || '';\n\n // Get the options from the question\n // In result mode, prefer the persisted snapshot to match parsedAnswers\n const questionOptions =\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.options || currentQuestion?.options || []\n : currentQuestion?.options || [];\n\n // Shuffled options for dropdown display (consistent per question)\n const shuffledOptions = useMemo(() => {\n return shuffleWithSeed(questionOptions, currentQuestion?.id || '');\n }, [questionOptions, currentQuestion?.id]);\n\n // Parse current answers\n // In result mode, read from fillAnswers object, fallback to answer JSON\n // In default mode, read from currentAnswer.answer JSON string\n const parsedAnswers: Record<string, string> = useMemo(() => {\n if (variant === QuizVariant.RESULT && currentQuestionResult?.fillAnswers) {\n // fillAnswers is already a Record<placeholderId, selectedOptionId>\n return currentQuestionResult.fillAnswers;\n }\n // Fallback to answer JSON string (for older/partially migrated submissions)\n return parseStoredAnswers(\n variant,\n currentQuestionResult?.answer,\n currentAnswer?.answer\n );\n }, [\n variant,\n currentQuestionResult?.fillAnswers,\n currentQuestionResult?.answer,\n currentAnswer?.answer,\n ]);\n\n const [localAnswers, setLocalAnswers] =\n useState<Record<string, string>>(parsedAnswers);\n\n // Sync local answers when question changes\n useEffect(() => {\n setLocalAnswers(parsedAnswers);\n }, [parsedAnswers, currentQuestion?.id]);\n\n // Handle select change\n const handleSelectChange = (placeholderId: string, optionId: string) => {\n if (!currentQuestion) return;\n\n // Get the LATEST answers directly from the store (not from closure)\n const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n let baseAnswers: Record<string, string> = {};\n if (latestStoreAnswer?.answer) {\n try {\n const parsed = JSON.parse(latestStoreAnswer.answer);\n baseAnswers = normalizeAnswerData(parsed);\n } catch {\n // Invalid JSON, start fresh\n }\n }\n\n const newAnswers = {\n ...baseAnswers,\n ...localAnswers,\n [placeholderId]: optionId,\n };\n setLocalAnswers(newAnswers);\n\n // Save to store as JSON string\n selectDissertativeAnswer(currentQuestion.id, JSON.stringify(newAnswers));\n };\n\n // Get option text by ID\n const getOptionTextById = (optionId: string): string => {\n const option = questionOptions.find((opt) => opt.id === optionId);\n return stripHtmlTags(option?.option || '');\n };\n\n // Check if an answer is correct (for result mode)\n const isAnswerCorrect = (placeholderId: string): boolean => {\n const selectedOptionId = localAnswers[placeholderId];\n // The placeholder ID is the correct option ID\n return selectedOptionId === placeholderId;\n };\n\n // Render the select for default mode\n const renderDefaultSelect = (placeholderId: string) => {\n const selectedOptionId = localAnswers[placeholderId];\n\n return (\n <span\n key={placeholderId}\n className=\"inline-block align-middle mx-1 my-2\"\n style={{ display: 'inline-block', verticalAlign: 'middle' }}\n >\n <Select\n value={selectedOptionId || undefined}\n onValueChange={(value) => handleSelectChange(placeholderId, value)}\n >\n <SelectTrigger\n className=\"w-auto min-w-[120px] max-w-[200px] h-7 px-2 bg-background border-gray-300 overflow-hidden truncate\"\n title={stripHtmlTags(\n shuffledOptions.find((o) => o.id === selectedOptionId)?.option ||\n ''\n )}\n >\n <SelectValue placeholder=\"Selecione opção\" />\n </SelectTrigger>\n <SelectContent>\n {shuffledOptions.map((option) => (\n <SelectItem\n key={option.id}\n value={option.id}\n title={stripHtmlTags(option.option)}\n truncate\n >\n {stripHtmlTags(option.option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n );\n };\n\n // Render the result badge\n const renderResultBadge = (placeholderId: string) => {\n const selectedOptionId = localAnswers[placeholderId];\n const selectedOptionText = getOptionTextById(selectedOptionId);\n const isCorrect = isAnswerCorrect(placeholderId);\n\n if (!selectedOptionId) {\n return (\n <span\n key={placeholderId}\n className=\"inline-block align-middle mx-1 my-2\"\n style={{ display: 'inline-block', verticalAlign: 'middle' }}\n >\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n </span>\n );\n }\n\n return (\n <span\n key={placeholderId}\n className=\"inline-block align-middle mx-1 my-2\"\n style={{ display: 'inline-block', verticalAlign: 'middle' }}\n >\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n <span className=\"text-text-900\">{selectedOptionText}</span>\n </Badge>\n </span>\n );\n };\n\n // Render the correct answer for resolution\n const renderResolutionAnswer = (placeholderId: string) => {\n // The placeholderId IS the correct option ID\n const correctOptionText = getOptionTextById(placeholderId);\n\n return (\n <span className=\"inline mx-1 text-success-600 font-semibold border-b-2 border-success-600\">\n {correctOptionText}\n </span>\n );\n };\n\n // Parse text and render with selects\n const renderTextWithSelects = (text: string, isResolution?: boolean) => {\n const elements: Array<{ element: string | ReactNode; id: string }> = [];\n let lastIndex = 0;\n const nextId = () => elements.length;\n\n // Match {uuid} placeholders (UUID format or any alphanumeric with hyphens)\n const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n let match;\n\n while ((match = regex.exec(text)) !== null) {\n const [fullMatch, placeholderId] = match;\n const startIndex = match.index;\n\n // Add text before the placeholder\n if (startIndex > lastIndex) {\n elements.push({\n element: text.slice(lastIndex, startIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n // Add the appropriate element based on variant and mode\n if (isResolution) {\n elements.push({\n element: renderResolutionAnswer(placeholderId),\n id: `${baseId}-resolution-${nextId()}`,\n });\n } else if (variant === QuizVariant.DEFAULT) {\n elements.push({\n element: renderDefaultSelect(placeholderId),\n id: `${baseId}-select-${nextId()}`,\n });\n } else {\n elements.push({\n element: renderResultBadge(placeholderId),\n id: `${baseId}-result-${nextId()}`,\n });\n }\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Add remaining text\n if (lastIndex < text.length) {\n elements.push({\n element: text.slice(lastIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n return elements;\n };\n\n // Render HTML content with selects replacing placeholders\n const renderHtmlWithSelects = (\n htmlContent: string,\n isResolution?: boolean\n ) => {\n // For now, we'll strip HTML and render plain text with selects\n // This preserves the placeholder functionality while handling HTML content\n const textContent = stripHtmlTags(htmlContent);\n return renderTextWithSelects(textContent, isResolution);\n };\n\n if (!currentQuestion || !additionalContent) {\n return (\n <>\n <QuizSubTitle subTitle=\"Preenchimento\" />\n <QuizContainer className=\"h-auto pb-0\">\n <div className=\"space-y-6 px-4 h-auto\">\n <Text\n size=\"md\"\n color=\"text-text-600\"\n weight=\"normal\"\n className={cn(paddingBottom)}\n >\n Nenhum conteúdo disponível para esta questão.\n </Text>\n </div>\n </QuizContainer>\n </>\n );\n }\n\n return (\n <>\n <QuizSubTitle subTitle=\"Preencha as lacunas\" />\n\n <QuizContainer\n className={cn('', variant !== QuizVariant.RESULT && paddingBottom)}\n >\n <div className=\"px-4\">\n <Text\n as=\"div\"\n size=\"lg\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderHtmlWithSelects(additionalContent).map((element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n ))}\n </Text>\n </div>\n </QuizContainer>\n\n {variant === QuizVariant.RESULT && (\n <>\n <QuizSubTitle subTitle=\"Resposta correta\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div className=\"px-4\">\n <Text\n as=\"div\"\n size=\"lg\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderHtmlWithSelects(additionalContent, true).map(\n (element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n )\n )}\n </Text>\n </div>\n </QuizContainer>\n </>\n )}\n </>\n );\n};\n\nconst QuizImageQuestion = ({ paddingBottom }: QuizVariantInterface) => {\n const {\n variant,\n getCurrentQuestion,\n getCurrentAnswer,\n selectDissertativeAnswer,\n getQuestionResultByQuestionId,\n } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const currentAnswer = getCurrentAnswer();\n const currentQuestionResult = getQuestionResultByQuestionId(\n currentQuestion?.id || ''\n );\n\n // Get image URL from additionalContent\n const imageUrl = currentQuestion?.additionalContent || '';\n\n // Parse correct coordinates from first option (stored as JSON: {\"x\": number, \"y\": number})\n const correctPositionRelative = useMemo(() => {\n if (!currentQuestion?.options || currentQuestion.options.length === 0) {\n return { x: 0.5, y: 0.5 }; // Default center\n }\n try {\n const coords = JSON.parse(currentQuestion.options[0].option);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n // Coordinates are stored as percentages (0-100), convert to relative (0-1)\n return { x: coords.x / 100, y: coords.y / 100 };\n }\n } catch {\n // Fall back to default\n }\n return { x: 0.5, y: 0.5 };\n }, [currentQuestion?.options]);\n\n // Calculate correctRadiusRelative automatically based on the circle dimensions\n const calculateCorrectRadiusRelative = (): number => {\n // The correct answer circle has width: 15% and height: 30%\n // We'll use the average of these as the radius\n const circleWidthRelative = 0.15; // 15%\n const circleHeightRelative = 0.3; // 30%\n\n // Calculate the average radius (half of the average of width and height)\n const averageRadius = (circleWidthRelative + circleHeightRelative) / 4;\n\n // Add a small tolerance for better user experience\n const tolerance = 0.02; // 2% tolerance\n\n return averageRadius + tolerance;\n };\n\n const correctRadiusRelative = calculateCorrectRadiusRelative();\n\n // Parse user's answer from stored JSON or result\n const storedUserAnswer = useMemo(() => {\n if (variant === QuizVariant.RESULT && currentQuestionResult?.answer) {\n try {\n const coords = JSON.parse(currentQuestionResult.answer);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n return { x: coords.x / 100, y: coords.y / 100 };\n }\n } catch {\n // Fall back to null\n }\n } else if (currentAnswer?.answer) {\n try {\n const coords = JSON.parse(currentAnswer.answer);\n if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n return { x: coords.x / 100, y: coords.y / 100 };\n }\n } catch {\n // Fall back to null\n }\n }\n return null;\n }, [variant, currentQuestionResult?.answer, currentAnswer?.answer]);\n\n const [clickPositionRelative, setClickPositionRelative] = useState<{\n x: number;\n y: number;\n } | null>(storedUserAnswer);\n\n // Sync with stored answer when it changes\n useEffect(() => {\n setClickPositionRelative(storedUserAnswer);\n }, [storedUserAnswer]);\n\n // Helper function to safely convert click coordinates to relative coordinates\n const convertToRelativeCoordinates = (\n x: number,\n y: number,\n rect: DOMRect\n ): { x: number; y: number } => {\n // Guard against division by zero or extremely small dimensions\n const safeWidth = Math.max(rect.width, 0.001);\n const safeHeight = Math.max(rect.height, 0.001);\n\n // Convert to relative coordinates and clamp to [0, 1] range\n const xRelative = Math.max(0, Math.min(1, x / safeWidth));\n const yRelative = Math.max(0, Math.min(1, y / safeHeight));\n\n return { x: xRelative, y: yRelative };\n };\n\n const handleImageClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (variant === QuizVariant.RESULT) return;\n\n const rect = event.currentTarget.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n\n // Use helper function for safe conversion\n const positionRelative = convertToRelativeCoordinates(x, y, rect);\n setClickPositionRelative(positionRelative);\n\n // Save the answer to the store (as percentages 0-100)\n if (currentQuestion) {\n const answerJson = JSON.stringify({\n x: Math.round(positionRelative.x * 100),\n y: Math.round(positionRelative.y * 100),\n });\n selectDissertativeAnswer(currentQuestion.id, answerJson);\n }\n };\n\n const handleKeyboardActivate = () => {\n if (variant === QuizVariant.RESULT) return;\n // Choose a deterministic position for keyboard activation; center is a reasonable default\n const centerPosition = { x: 0.5, y: 0.5 };\n setClickPositionRelative(centerPosition);\n\n // Save the answer to the store (as percentages 0-100)\n if (currentQuestion) {\n const answerJson = JSON.stringify({\n x: Math.round(centerPosition.x * 100),\n y: Math.round(centerPosition.y * 100),\n });\n selectDissertativeAnswer(currentQuestion.id, answerJson);\n }\n };\n\n const isCorrect = () => {\n if (!clickPositionRelative) return false;\n\n const distance = Math.sqrt(\n Math.pow(clickPositionRelative.x - correctPositionRelative.x, 2) +\n Math.pow(clickPositionRelative.y - correctPositionRelative.y, 2)\n );\n\n return distance <= correctRadiusRelative;\n };\n\n const getUserCircleColorClasses = () => {\n if (variant === QuizVariant.DEFAULT) {\n return 'bg-indicator-primary/70 border-[#F8CC2E]';\n }\n\n if (variant === QuizVariant.RESULT) {\n return isCorrect()\n ? 'bg-success-600/70 border-white' // Green for correct answer\n : 'bg-indicator-error/70 border-white'; // Red for incorrect answer\n }\n\n return 'bg-success-600/70 border-white';\n };\n\n return (\n <>\n <QuizSubTitle subTitle=\"Clique na área correta\" />\n\n <QuizContainer className={cn('', paddingBottom)}>\n <div\n data-testid=\"quiz-image-container\"\n className=\"space-y-6 p-3 relative inline-block\"\n >\n {variant == 'result' && (\n <div\n data-testid=\"quiz-legend\"\n className=\"flex items-center gap-4 text-xs\"\n >\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-primary/70 border border-[#F8CC2E]\"></div>\n <span className=\"text-text-600 font-medium text-sm\">\n Área correta\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-success-600/70 border border-white\"></div>\n <span className=\"text-text-600 font-medium text-sm\">\n Resposta correta\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-error/70 border border-white\"></div>\n <span className=\"text-text-600 font-medium text-sm\">\n Resposta incorreta\n </span>\n </div>\n </div>\n )}\n\n <button\n data-testid=\"quiz-image-button\"\n type=\"button\"\n className=\"relative cursor-pointer w-full h-full border-0 bg-transparent p-0\"\n onClick={handleImageClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleKeyboardActivate();\n }\n }}\n aria-label=\"Área da imagem interativa\"\n >\n <img\n data-testid=\"quiz-image\"\n src={imageUrl || ImageQuestion}\n alt=\"Question\"\n className=\"w-full h-auto rounded-md\"\n />\n\n {/* Correct answer circle - only show in result variant */}\n {variant === QuizVariant.RESULT && (\n <div\n data-testid=\"quiz-correct-circle\"\n className=\"absolute rounded-full bg-indicator-primary/70 border-4 border-[#F8CC2E] pointer-events-none\"\n style={{\n minWidth: '50px',\n maxWidth: '160px',\n width: '15%',\n aspectRatio: '1 / 1',\n left: `calc(${correctPositionRelative.x * 100}% - 7.5%)`,\n top: `calc(${correctPositionRelative.y * 100}% - 15%)`,\n }}\n />\n )}\n\n {/* User's answer circle */}\n {clickPositionRelative && (\n <div\n data-testid=\"quiz-user-circle\"\n className={`absolute rounded-full border-4 pointer-events-none ${getUserCircleColorClasses()}`}\n style={{\n minWidth: '30px',\n maxWidth: '52px',\n width: '5%',\n aspectRatio: '1 / 1',\n left: `calc(${clickPositionRelative.x * 100}% - 2.5%)`,\n top: `calc(${clickPositionRelative.y * 100}% - 2.5%)`,\n }}\n />\n )}\n </button>\n </div>\n </QuizContainer>\n </>\n );\n};\n\nexport {\n QuizSubTitle,\n QuizContainer,\n QuizMultipleChoice,\n QuizDissertative,\n QuizTrueOrFalse,\n QuizConnectDots,\n QuizFill,\n QuizImageQuestion,\n QuizAlternative,\n};\n","import {\n QuizVariant,\n type QuestionAnswerResult,\n type TrueOrFalseOptionState,\n} from './Quiz.types';\nimport { TrueFalseEnum } from '../../enums/Quiz';\nimport { OptionStatus } from '../../enums/Options';\n\n/**\n * Helper function to format exam info (bank - year)\n * @param examBoard - The exam board/bank name\n * @param examYear - The exam year\n * @returns Formatted string like \"(ENEM - 2023)\" or empty string if no info\n */\nexport const formatExamInfo = (\n examBoard: string | null | undefined,\n examYear: string | null | undefined\n): string => {\n if (examBoard && examYear) {\n return `(${examBoard} - ${examYear})`;\n }\n if (examBoard) {\n return `(${examBoard})`;\n }\n if (examYear) {\n return `(${examYear})`;\n }\n return '';\n};\n\n/**\n * Shuffle array using a seed for consistent ordering per question\n * Uses Fisher-Yates shuffle with seeded random for deterministic results\n */\nexport const shuffleWithSeed = <T>(array: T[], seed: string): T[] => {\n const shuffled = [...array];\n // Simple hash function to convert string seed to number\n let hash = 0;\n for (let i = 0; i < seed.length; i++) {\n const char = seed.codePointAt(i) ?? 0;\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n // Fisher-Yates shuffle with seeded random\n const seededRandom = (max: number) => {\n hash = (hash * 1103515245 + 12345) & 0x7fffffff;\n return hash % max;\n };\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = seededRandom(i + 1);\n [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n }\n return shuffled;\n};\n\n/**\n * Helper to prepend letter to HTML content (handles <p> tags)\n * @example prependLetterToHtml('a', '<p>Text</p>') => '<p>a) Text</p>'\n * @example prependLetterToHtml('a', 'Text') => 'a) Text'\n */\nexport const prependLetterToHtml = (letter: string, html: string): string => {\n if (html.trim().startsWith('<p>')) {\n return html.replace(/^(\\s*<p>)/, `$1${letter}) `);\n }\n return `${letter}) ${html}`;\n};\n\n/**\n * Compute state for a true/false option\n * Handles both interactive (default) and result modes\n */\nexport const getTrueOrFalseOptionState = (\n optionId: string,\n variant: string,\n currentQuestionResult: QuestionAnswerResult | null | undefined,\n localAnswers: Record<string, string>\n): TrueOrFalseOptionState => {\n // Get whether the statement is TRUE or FALSE from persisted result\n const correctAnswerOption = currentQuestionResult?.options?.find(\n (op) => op.id === optionId\n );\n const isStatementTrue =\n variant === QuizVariant.RESULT\n ? (correctAnswerOption?.isCorrect ?? false)\n : false;\n\n // Get student's selection from selectedOptions\n const studentSelection =\n variant === QuizVariant.RESULT\n ? currentQuestionResult?.selectedOptions?.find(\n (op) => op.optionId === optionId\n )\n : undefined;\n\n // Determine if answered and what was marked\n const hasAnswered =\n variant === QuizVariant.RESULT\n ? studentSelection !== undefined\n : !!localAnswers[optionId];\n\n const studentMarkedTrue =\n variant === QuizVariant.RESULT\n ? (studentSelection?.isCorrect ?? false)\n : localAnswers[optionId] === TrueFalseEnum.VERDADEIRO;\n\n // Compute display values\n const getStudentAnswerDisplay = (): string => {\n if (variant !== QuizVariant.RESULT) {\n return localAnswers[optionId] || '-';\n }\n if (!hasAnswered) {\n return '-';\n }\n return studentMarkedTrue ? TrueFalseEnum.VERDADEIRO : TrueFalseEnum.FALSO;\n };\n const studentAnswer = getStudentAnswerDisplay();\n\n const correctAnswer = isStatementTrue\n ? TrueFalseEnum.VERDADEIRO\n : TrueFalseEnum.FALSO;\n const isStudentCorrect = hasAnswered && studentMarkedTrue === isStatementTrue;\n const variantCorrect = isStudentCorrect\n ? OptionStatus.CORRECT\n : OptionStatus.INCORRECT;\n\n return {\n isStatementTrue,\n hasAnswered,\n studentMarkedTrue,\n studentAnswer,\n correctAnswer,\n isStudentCorrect,\n variantCorrect,\n };\n};\n","/**\n * Strip HTML tags from a string\n * SSR-safe: uses DOMParser in browser, iterative fallback on server\n *\n * @param html - String that may contain HTML tags\n * @returns String with HTML tags removed\n *\n * @example\n * stripHtmlTags('<p>Hello <strong>World</strong></p>') // 'Hello World'\n * stripHtmlTags('No tags here') // 'No tags here'\n */\nexport function stripHtmlTags(html: string): string {\n if (globalThis.window !== undefined && typeof DOMParser !== 'undefined') {\n const doc = new DOMParser().parseFromString(html, 'text/html');\n return doc.body.textContent || '';\n }\n // Server-side fallback: iterative O(n) approach to avoid regex backtracking\n let result = '';\n let inTag = false;\n for (const char of html) {\n if (char === '<') {\n inTag = true;\n } else if (char === '>') {\n inTag = false;\n } else if (!inTag) {\n result += char;\n }\n }\n return result;\n}\n","import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n useState,\n useCallback,\n ButtonHTMLAttributes,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useId,\n CSSProperties,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { CaretDown, Check, WarningCircle } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\n\nconst VARIANT_CLASSES = {\n outlined: 'border-2 rounded-lg focus:border-primary-950',\n underlined: 'border-b-2 focus:border-primary-950',\n rounded: 'border-2 rounded-full focus:border-primary-950',\n} as const;\n\nconst SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n large: 'text-lg',\n 'extra-large': 'text-lg',\n} as const;\n\nconst HEIGHT_CLASSES = {\n small: 'h-8',\n medium: 'h-9',\n large: 'h-10',\n 'extra-large': 'h-12',\n} as const;\n\nconst PADDING_CLASSES = {\n small: 'px-2 py-1',\n medium: 'px-3 py-2',\n large: 'px-4 py-3',\n 'extra-large': 'px-5 py-4',\n} as const;\n\ninterface TriggerRect {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\ntype SelectAlign = 'start' | 'center' | 'end';\n\ninterface SelectStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n value: string;\n setValue: (value: string) => void;\n selectedLabel: ReactNode;\n setSelectedLabel: (label: ReactNode) => void;\n onValueChange?: (value: string) => void;\n triggerRect: TriggerRect | null;\n setTriggerRect: (rect: TriggerRect | null) => void;\n}\n\ntype SelectStoreApi = StoreApi<SelectStore>;\n\nexport function createSelectStore(\n onValueChange?: (value: string) => void\n): SelectStoreApi {\n return create<SelectStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n value: '',\n setValue: (value) => set({ value }),\n selectedLabel: '',\n setSelectedLabel: (label) => set({ selectedLabel: label }),\n onValueChange,\n triggerRect: null,\n setTriggerRect: (rect) => set({ triggerRect: rect }),\n }));\n}\n\nexport const useSelectStore = (externalStore?: SelectStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a Select (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nexport function getLabelAsNode(children: ReactNode): ReactNode {\n if (typeof children === 'string' || typeof children === 'number') {\n return children;\n }\n const flattened = Children.toArray(children);\n\n if (flattened.length === 1) return flattened[0];\n\n return <>{flattened}</>;\n}\n\ninterface SelectProps {\n className?: string;\n children: ReactNode;\n defaultValue?: string;\n value?: string;\n onValueChange?: (value: string) => void;\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n label?: string;\n helperText?: string;\n errorMessage?: string;\n id?: string;\n}\n\nconst injectStore = (\n children: ReactNode,\n store: SelectStoreApi,\n size: string,\n selectId: string\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: SelectStoreApi;\n children?: ReactNode;\n size?: string;\n selectId?: string;\n }>;\n\n const newProps: Partial<{\n store: SelectStoreApi;\n children: ReactNode;\n size: string;\n selectId: string;\n }> = {\n store,\n };\n\n // Pass size to SelectTrigger, selectId to both Trigger and Content\n if (typedChild.type === SelectTrigger) {\n newProps.size = size;\n newProps.selectId = selectId;\n }\n\n if (typedChild.type === SelectContent) {\n newProps.selectId = selectId;\n }\n\n if (typedChild.props.children) {\n newProps.children = injectStore(\n typedChild.props.children,\n store,\n size,\n selectId\n );\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\nconst Select = ({\n children,\n defaultValue = '',\n className,\n value: propValue,\n onValueChange,\n size = 'small',\n label,\n helperText,\n errorMessage,\n id,\n}: SelectProps) => {\n const storeRef = useRef<SelectStoreApi | null>(null);\n storeRef.current ??= createSelectStore(onValueChange);\n const store = storeRef.current;\n\n const selectRef = useRef<HTMLDivElement>(null);\n const { open, setOpen, setValue, selectedLabel } = useStore(store, (s) => s);\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const selectId = id ?? `select-${generatedId}`;\n\n const findLabelForValue = (\n children: ReactNode,\n targetValue: string\n ): string | null => {\n let found: string | null = null;\n const search = (nodes: ReactNode) => {\n Children.forEach(nodes, (child) => {\n if (!isValidElement(child)) return;\n const typedChild = child as ReactElement<{\n value?: string;\n children?: ReactNode;\n }>;\n if (\n typedChild.type === SelectItem &&\n typedChild.props.value === targetValue\n ) {\n if (typeof typedChild.props.children === 'string')\n found = typedChild.props.children;\n }\n if (typedChild.props.children && !found)\n search(typedChild.props.children);\n });\n };\n search(children);\n return found;\n };\n\n useEffect(() => {\n if (!selectedLabel && defaultValue) {\n const label = findLabelForValue(children, defaultValue);\n if (label) store.setState({ selectedLabel: label });\n }\n }, [children, defaultValue, selectedLabel]);\n\n useEffect(() => {\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n const target = event.target as Node;\n // Check if click is inside the trigger container\n const isInsideTrigger = selectRef.current?.contains(target);\n // Check if click is inside the portaled content (scoped to this Select instance)\n const portaledMenu = document.body.querySelector(\n `[role=\"menu\"][data-select-id=\"${selectId}\"]`\n );\n const isInsidePortaledMenu = portaledMenu?.contains(target);\n\n if (!isInsideTrigger && !isInsidePortaledMenu) {\n setOpen(false);\n }\n };\n\n const handleArrowKeys = (event: globalThis.KeyboardEvent) => {\n // Find the portaled menu in the body (scoped to this Select instance)\n const selectContent = document.body.querySelector(\n `[role=\"menu\"][data-select-id=\"${selectId}\"]`\n );\n if (selectContent) {\n event.preventDefault();\n const items = Array.from(\n selectContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n const focused = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focused);\n\n let nextIndex: number;\n if (event.key === 'ArrowDown') {\n nextIndex =\n currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n items[nextIndex]?.focus();\n }\n };\n\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleArrowKeys);\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleArrowKeys);\n };\n }, [open, selectId, setOpen]);\n\n useEffect(() => {\n // Skip when the consumer isn't using controlled mode\n if (propValue === undefined) return;\n setValue(propValue);\n // Resolve the label for the new value; if it can't be resolved (empty\n // value, or a value with no matching SelectItem), clear the stale label\n // so the placeholder takes over.\n const label = findLabelForValue(children, propValue);\n store.setState({ selectedLabel: label ?? '' });\n }, [propValue, children]);\n\n const sizeClasses = SIZE_CLASSES[size];\n\n return (\n <div className={cn('w-full', className)}>\n {/* Label */}\n {label && (\n <label\n htmlFor={selectId}\n className={cn('block font-bold text-text-900 mb-1.5', sizeClasses)}\n >\n {label}\n </label>\n )}\n\n {/* Select Container */}\n <div className={cn('relative w-full')} ref={selectRef}>\n {injectStore(children, store, size, selectId)}\n </div>\n\n {/* Helper Text or Error Message */}\n {(helperText || errorMessage) && (\n <div className=\"mt-1.5 gap-1.5\">\n {helperText && <p className=\"text-sm text-text-500\">{helperText}</p>}\n {errorMessage && (\n <p className=\"flex gap-1 items-center text-sm text-indicator-error\">\n <WarningCircle size={16} /> {errorMessage}\n </p>\n )}\n </div>\n )}\n </div>\n );\n};\n\nconst SelectValue = ({\n placeholder,\n store: externalStore,\n}: {\n placeholder?: string;\n store?: SelectStoreApi;\n}) => {\n const store = useSelectStore(externalStore);\n\n const selectedLabel = useStore(store, (s) => s.selectedLabel);\n const value = useStore(store, (s) => s.value);\n return (\n <span className=\"text-inherit flex gap-2 items-center\">\n {selectedLabel || placeholder || value}\n </span>\n );\n};\n\ninterface SelectTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n className?: string;\n invalid?: boolean;\n variant?: 'outlined' | 'underlined' | 'rounded';\n store?: SelectStoreApi;\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n selectId?: string;\n}\n\nconst SelectTrigger = forwardRef<HTMLButtonElement, SelectTriggerProps>(\n (\n {\n className,\n invalid = false,\n variant = 'outlined',\n store: externalStore,\n disabled,\n size = 'medium',\n selectId,\n type = 'button',\n ...props\n },\n ref\n ) => {\n const store = useSelectStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const internalRef = useRef<HTMLButtonElement>(null);\n\n const setRefs = useCallback(\n (element: HTMLButtonElement | null) => {\n internalRef.current = element;\n if (typeof ref === 'function') {\n ref(element);\n } else if (ref) {\n ref.current = element;\n }\n },\n [ref]\n );\n\n const updateTriggerRect = useCallback(() => {\n if (internalRef.current) {\n const rect = internalRef.current.getBoundingClientRect();\n store.setState({\n triggerRect: {\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n },\n });\n }\n }, [store]);\n\n // Update triggerRect on scroll/resize while open\n useEffect(() => {\n if (!open) return;\n\n const handleUpdate = () => {\n updateTriggerRect();\n };\n\n window.addEventListener('scroll', handleUpdate, true);\n window.addEventListener('resize', handleUpdate);\n\n return () => {\n window.removeEventListener('scroll', handleUpdate, true);\n window.removeEventListener('resize', handleUpdate);\n };\n }, [open, updateTriggerRect]);\n\n const toggleOpen = () => {\n const newOpen = !open;\n if (newOpen) {\n updateTriggerRect();\n }\n store.setState({ open: newOpen });\n };\n\n const variantClasses = VARIANT_CLASSES[variant];\n const heightClasses = HEIGHT_CLASSES[size];\n const paddingClasses = PADDING_CLASSES[size];\n\n return (\n <button\n ref={setRefs}\n id={selectId}\n type={type}\n className={cn(\n 'flex w-full items-center justify-between border-border-300',\n heightClasses,\n paddingClasses,\n invalid &&\n `${variant == 'underlined' ? 'border-b-2' : 'border-2'} border-indicator-error text-text-600`,\n disabled\n ? 'cursor-not-allowed text-text-400 pointer-events-none opacity-50'\n : 'cursor-pointer hover:bg-background-50 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground',\n !invalid && !disabled ? 'text-text-700' : '',\n variantClasses,\n className\n )}\n onClick={toggleOpen}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-controls={open ? 'select-content' : undefined}\n {...props}\n >\n {props.children}\n <CaretDown\n className={cn(\n 'h-[1em] w-[1em] opacity-50 transition-transform',\n open ? 'rotate-180' : ''\n )}\n />\n </button>\n );\n }\n);\nSelectTrigger.displayName = 'SelectTrigger';\n\nfunction applyVerticalPosition(\n styles: CSSProperties,\n triggerRect: TriggerRect,\n side: 'top' | 'bottom',\n align: SelectAlign,\n gap: number\n): void {\n styles.top =\n side === 'top'\n ? triggerRect.top - gap\n : triggerRect.top + triggerRect.height + gap;\n styles.transform = side === 'top' ? 'translateY(-100%)' : undefined;\n\n if (align === 'start') {\n styles.left = triggerRect.left;\n } else if (align === 'center') {\n styles.left = triggerRect.left + triggerRect.width / 2;\n styles.transform =\n side === 'top' ? 'translate(-50%, -100%)' : 'translateX(-50%)';\n } else {\n styles.left = triggerRect.left + triggerRect.width;\n styles.transform =\n side === 'top' ? 'translate(-100%, -100%)' : 'translateX(-100%)';\n }\n}\n\nfunction applyHorizontalPosition(\n styles: CSSProperties,\n triggerRect: TriggerRect,\n side: 'left' | 'right',\n align: SelectAlign,\n gap: number\n): void {\n styles.left =\n side === 'left'\n ? triggerRect.left - gap\n : triggerRect.left + triggerRect.width + gap;\n styles.transform = side === 'left' ? 'translateX(-100%)' : undefined;\n\n if (align === 'start') {\n styles.top = triggerRect.top;\n } else if (align === 'center') {\n styles.top = triggerRect.top + triggerRect.height / 2;\n styles.transform =\n side === 'left' ? 'translate(-100%, -50%)' : 'translateY(-50%)';\n } else {\n styles.top = triggerRect.top + triggerRect.height;\n styles.transform =\n side === 'left' ? 'translate(-100%, -100%)' : 'translateY(-100%)';\n }\n}\n\ninterface SelectContentProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n store?: SelectStoreApi;\n selectId?: string;\n}\n\nconst SelectContent = forwardRef<HTMLDivElement, SelectContentProps>(\n (\n {\n children,\n className,\n align = 'start',\n side = 'bottom',\n store: externalStore,\n selectId,\n ...props\n },\n ref\n ) => {\n const store = useSelectStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const triggerRect = useStore(store, (s) => s.triggerRect);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!open || !mounted) return null;\n\n // Calculate position based on trigger rect\n const getPositionStyles = (): CSSProperties => {\n if (!triggerRect) {\n return {};\n }\n\n const gap = 4;\n const styles: CSSProperties = {\n position: 'fixed',\n zIndex: 9999,\n };\n\n const isVertical = side === 'top' || side === 'bottom';\n\n if (isVertical) {\n applyVerticalPosition(styles, triggerRect, side, align, gap);\n } else {\n applyHorizontalPosition(styles, triggerRect, side, align, gap);\n }\n\n return styles;\n };\n\n const content = (\n <div\n role=\"menu\"\n ref={ref}\n data-select-id={selectId}\n style={getPositionStyles()}\n className={cn(\n 'bg-secondary min-w-[210px] max-h-[300px] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md border-border-100',\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n // Render using portal to escape overflow constraints\n return createPortal(content, document.body);\n }\n);\nSelectContent.displayName = 'SelectContent';\n\ninterface SelectItemProps extends HTMLAttributes<HTMLDivElement> {\n value: string;\n disabled?: boolean;\n store?: SelectStoreApi;\n truncate?: boolean;\n}\n\nconst SelectItem = forwardRef<HTMLDivElement, SelectItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n truncate = false,\n ...props\n },\n ref\n ) => {\n const store = useSelectStore(externalStore);\n const {\n value: selectedValue,\n setValue,\n setOpen,\n setSelectedLabel,\n onValueChange,\n } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n const labelNode = getLabelAsNode(children);\n if (!disabled) {\n // Always set the clicked value, even if it's already selected\n setValue(value);\n setSelectedLabel(labelNode);\n setOpen(false);\n onValueChange?.(value);\n }\n props.onClick?.(e as MouseEvent<HTMLDivElement>);\n };\n\n return (\n <div\n role=\"menuitem\"\n aria-disabled={disabled}\n ref={ref}\n className={`\n bg-secondary focus-visible:bg-background-50\n relative flex select-none items-center gap-2 rounded-sm p-3 outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400 pointer-events-none opacity-50'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n ${selectedValue === value && 'bg-background-50'}\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n {selectedValue === value && <Check className=\"\" />}\n </span>\n {truncate ? (\n <span className=\"truncate block max-w-[200px]\">{children}</span>\n ) : (\n children\n )}\n </div>\n );\n }\n);\n\nSelectItem.displayName = 'SelectItem';\n\nexport default Select;\nexport { SelectTrigger, SelectContent, SelectItem, SelectValue };\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport { getStatusStyles } from '../../../components/Quiz/QuizContent';\nimport Text from '../../../components/Text/Text';\nimport { cn } from '../../../utils/utils';\nimport type { QuestionRendererProps } from '../types';\nimport { getStatusBadge } from '../components';\nimport { HtmlMathRenderer } from '../../../components/HtmlMathRenderer';\nimport { TrueFalseEnum } from '../../../enums/Quiz';\nimport { OptionStatus } from '../../../enums/Options';\n\n/**\n * Render true or false question\n * Each option has a statement, and student marks V or F for each\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionTrueOrFalse = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n const options = question.options || [];\n const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n const shouldShowStatus =\n result?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n result?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n return (\n <div className=\"pt-2\">\n <div className=\"flex flex-col gap-3.5\">\n {options.map((option, index) => {\n // Find student's answer for this option\n const studentSelection = result?.selectedOptions?.find(\n (op) => op.optionId === option.id\n );\n\n // Get the correct answer from options array (if the statement is true or false)\n const correctAnswerOption = result?.options?.find(\n (op) => op.id === option.id\n );\n const hasCorrectAnswer = correctAnswerOption?.isCorrect !== undefined;\n const statementIsTrue = correctAnswerOption?.isCorrect ?? false;\n\n // Student's answer: isCorrect in selectedOptions represents what user marked\n // isCorrect: true = user marked V (Verdadeiro)\n // isCorrect: false = user marked F (Falso)\n const hasAnswered = studentSelection !== undefined;\n const studentMarkedTrue = studentSelection?.isCorrect ?? false;\n\n // Determine if student's answer is correct (only valid when we have the correct answer)\n // Student is correct if their mark matches the statement's truth value\n const isStudentCorrect =\n hasCorrectAnswer &&\n hasAnswered &&\n studentMarkedTrue === statementIsTrue;\n\n // Only show correctness styling when we have the official answer\n const canShowCorrectness = shouldShowStatus && hasCorrectAnswer;\n const variantCorrect = isStudentCorrect\n ? OptionStatus.CORRECT\n : OptionStatus.INCORRECT;\n const studentAnswer = studentMarkedTrue\n ? TrueFalseEnum.VERDADEIRO\n : TrueFalseEnum.FALSO;\n const correctAnswer = statementIsTrue\n ? TrueFalseEnum.VERDADEIRO\n : TrueFalseEnum.FALSO;\n\n return (\n <section\n key={option.id || `option-${index}`}\n className=\"flex flex-col gap-2\"\n >\n <div\n className={cn(\n 'flex flex-row justify-between items-center gap-2 p-2 rounded-md border',\n canShowCorrectness && hasAnswered\n ? getStatusStyles(variantCorrect)\n : ''\n )}\n >\n <Text as=\"span\" size=\"sm\" weight=\"normal\" color=\"text-text-900\">\n {getLetterByIndex(index).concat(') ')}\n <HtmlMathRenderer content={option.option} inline />\n </Text>\n\n {canShowCorrectness && hasAnswered && (\n <div className=\"flex-shrink-0\">\n {getStatusBadge(\n isStudentCorrect\n ? OptionStatus.CORRECT\n : OptionStatus.INCORRECT\n )}\n </div>\n )}\n </div>\n\n {canShowCorrectness && (\n <span className=\"flex flex-row gap-2 items-center flex-wrap\">\n {hasAnswered ? (\n <>\n <Text size=\"2xs\" weight=\"normal\" color=\"text-text-800\">\n Resposta selecionada: {studentAnswer}\n </Text>\n {!isStudentCorrect && (\n <Text size=\"2xs\" weight=\"normal\" color=\"text-text-800\">\n | Resposta correta: {correctAnswer}\n </Text>\n )}\n </>\n ) : (\n <Text size=\"2xs\" weight=\"normal\" color=\"text-text-800\">\n Não respondida | Resposta correta: {correctAnswer}\n </Text>\n )}\n </span>\n )}\n </section>\n );\n })}\n </div>\n </div>\n );\n};\n","import { Fragment, useId, type ReactNode } from 'react';\nimport Badge from '../../../components/Badge/Badge';\nimport { CheckCircle, XCircle } from 'phosphor-react';\nimport { cn } from '../../utils';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\nimport { stripHtmlTags } from '../../stringUtils';\nimport { OptionStatus } from '../../../enums/Options';\n\n/**\n * Get status badge component\n */\nexport const getStatusBadge = (status?: OptionStatus): ReactNode => {\n switch (status) {\n case OptionStatus.CORRECT:\n return (\n <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircle />}>\n Resposta correta\n </Badge>\n );\n case OptionStatus.INCORRECT:\n return (\n <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircle />}>\n Resposta incorreta\n </Badge>\n );\n default:\n return null;\n }\n};\n\n/**\n * Container component for question content\n */\nexport const QuestionContainer = ({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) => {\n return (\n <div\n className={cn(\n 'bg-background rounded-t-xl px-4 pt-4 pb-[80px] h-auto flex flex-col gap-4 mb-auto',\n className\n )}\n >\n {children}\n </div>\n );\n};\n\n/**\n * Subtitle component for question sections\n */\nexport const QuestionSubTitle = ({ subTitle }: { subTitle: string }) => {\n return (\n <div className=\"px-4 pb-2 pt-6\">\n <Text size=\"md\" weight=\"bold\" color=\"text-text-950\">\n {subTitle}\n </Text>\n </div>\n );\n};\n\n/**\n * Internal component for fill in the blanks question\n * Uses useId hook to generate unique IDs\n *\n * Data structure:\n * - additionalContent: HTML text with {placeholderId} placeholders\n * - fillAnswers: Record<placeholderId, selectedOptionId> (what student chose)\n * - options: Array<{ id, option }> where id is placeholderId AND correct optionId\n * - Correctness: selectedOptionId === placeholderId means correct\n */\nexport const FillQuestionContent = ({\n question,\n result,\n}: QuestionRendererProps) => {\n const baseId = useId();\n\n // Get additionalContent (contains HTML with {placeholderId} placeholders)\n // Falls back to question.statement for older questions that may not have additionalContent\n const additionalContent =\n result?.additionalContent ||\n question.additionalContent ||\n question.statement ||\n '';\n\n // Strip HTML tags for clean text rendering\n const cleanText = stripHtmlTags(additionalContent);\n\n // Get options array (id is placeholderId, option is the text)\n const options =\n (\n result as {\n options?: Array<{ id: string; option: string; isCorrect: boolean }>;\n }\n )?.options ||\n question.options ||\n [];\n\n // Build a map of optionId -> option text for quick lookup\n const optionTextMap: Record<string, string> = {};\n options.forEach((opt) => {\n optionTextMap[opt.id] = opt.option;\n });\n\n // Get fillAnswers: Record<placeholderId, selectedOptionId>\n const fillAnswers: Record<string, string> = {};\n try {\n const resultWithFill = result as {\n fillAnswers?: Record<string, string> | null;\n };\n if (resultWithFill?.fillAnswers) {\n Object.assign(fillAnswers, resultWithFill.fillAnswers);\n } else if (result?.answer) {\n const parsed =\n typeof result.answer === 'string'\n ? JSON.parse(result.answer)\n : result.answer;\n if (typeof parsed === 'object') {\n Object.assign(fillAnswers, parsed);\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n // Helper to get option text by ID - returns null if not found\n const getOptionTextById = (optionId: string): string | null => {\n if (!optionId) return null;\n return optionTextMap[optionId] ?? null;\n };\n\n // Check if answer is correct (selectedOptionId === placeholderId)\n const isAnswerCorrect = (placeholderId: string): boolean => {\n const selectedOptionId = fillAnswers[placeholderId];\n return selectedOptionId === placeholderId;\n };\n\n // Render student answer badge\n const renderStudentBadge = (placeholderId: string) => {\n const selectedOptionId = fillAnswers[placeholderId];\n const selectedOptionText = getOptionTextById(selectedOptionId);\n const isCorrect = isAnswerCorrect(placeholderId);\n\n if (!selectedOptionId) {\n return (\n <span className=\"inline-block align-middle mx-1 my-1\">\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n </span>\n );\n }\n\n // Handle case where option ID exists but text is not found\n const displayText = selectedOptionText ?? 'Opção não encontrada';\n\n return (\n <span className=\"inline-block align-middle mx-1 my-1\">\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n {displayText}\n </Badge>\n </span>\n );\n };\n\n // Render correct answer\n const renderCorrectAnswer = (placeholderId: string) => {\n // The placeholderId IS the correct option ID\n const correctOptionText = getOptionTextById(placeholderId);\n const displayText = correctOptionText ?? '[Resposta não disponível]';\n return (\n <span className=\"inline mx-1 text-success-600 font-semibold border-b-2 border-success-600\">\n {displayText}\n </span>\n );\n };\n\n // Parse text and render with elements\n const renderTextWithElements = (text: string, isCorrectAnswer: boolean) => {\n const elements: Array<{ element: string | ReactNode; id: string }> = [];\n let lastIndex = 0;\n const nextId = () => elements.length;\n\n const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n let match;\n\n while ((match = regex.exec(text)) !== null) {\n const [fullMatch, placeholderId] = match;\n const startIndex = match.index;\n\n // Add text before placeholder\n if (startIndex > lastIndex) {\n elements.push({\n element: text.slice(lastIndex, startIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n // Add the appropriate element\n if (isCorrectAnswer) {\n elements.push({\n element: renderCorrectAnswer(placeholderId),\n id: `${baseId}-answer-sheet-${nextId()}`,\n });\n } else {\n elements.push({\n element: renderStudentBadge(placeholderId),\n id: `${baseId}-student-${nextId()}`,\n });\n }\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Add remaining text\n if (lastIndex < text.length) {\n elements.push({\n element: text.slice(lastIndex),\n id: `${baseId}-text-${nextId()}`,\n });\n }\n\n return elements;\n };\n\n if (!additionalContent) {\n return (\n <div className=\"pt-2\">\n <Text size=\"md\" color=\"text-text-600\" weight=\"normal\">\n Nenhum conteúdo disponível para esta questão.\n </Text>\n </div>\n );\n }\n\n return (\n <div className=\"pt-2 space-y-4\">\n <div className=\"space-y-2\">\n <Text size=\"xs\" weight=\"normal\" color=\"text-text-500\">\n Resposta do aluno:\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n <Text\n as=\"div\"\n size=\"md\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderTextWithElements(cleanText, false).map((element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n ))}\n </Text>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Text size=\"xs\" weight=\"normal\" color=\"text-text-500\">\n Gabarito:\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n <Text\n as=\"div\"\n size=\"md\"\n color=\"text-text-900\"\n weight=\"normal\"\n className=\"leading-[2.5] *:inline\"\n >\n {renderTextWithElements(cleanText, true).map((element) => (\n <Fragment key={element.id}>{element.element}</Fragment>\n ))}\n </Text>\n </div>\n </div>\n </div>\n );\n};\n","import type { ReactNode } from 'react';\nimport { ANSWER_STATUS } from '../../../components/Quiz/useQuizStore';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\nimport { HtmlMathRenderer } from '../../../components/HtmlMathRenderer';\n\n/**\n * Render essay/dissertative question (readonly mode for correction)\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionDissertative = ({\n result,\n}: Omit<QuestionRendererProps, 'question'>): ReactNode => {\n const localAnswer = result?.answer || '';\n\n return (\n <div className=\"pt-2 space-y-4\">\n <div className=\"space-y-2\">\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-950\">\n Resposta do aluno\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n {localAnswer ? (\n <HtmlMathRenderer\n content={localAnswer}\n className=\"text-sm text-text-700\"\n />\n ) : (\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-700\">\n Nenhuma resposta fornecida\n </Text>\n )}\n </div>\n </div>\n\n {result?.answerStatus === ANSWER_STATUS.RESPOSTA_INCORRETA &&\n result?.teacherFeedback && (\n <div className=\"space-y-2\">\n <Text size=\"xs\" weight=\"normal\" color=\"text-text-500\">\n Observação do professor:\n </Text>\n <div className=\"p-3 bg-background-50 rounded-lg border border-border-100\">\n <HtmlMathRenderer\n content={result.teacherFeedback}\n className=\"text-sm text-text-700\"\n />\n </div>\n </div>\n )}\n </div>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { QuestionRendererProps } from '../types';\nimport { FillQuestionContent } from '../components';\n\n/**\n * Render fill in the blanks question\n * Shows text with student answers highlighted (green if correct, red if wrong)\n * Also shows a correct answers section\n * Returns content without wrapper (for accordion use)\n */\nexport const renderQuestionFill = ({\n question,\n result,\n}: QuestionRendererProps): ReactNode => {\n return <FillQuestionContent question={question} result={result} />;\n};\n","import type { ReactNode } from 'react';\nimport ImageQuestion from '../../../assets/img/mock-image-question.png';\nimport Text from '../../../components/Text/Text';\nimport type { QuestionRendererProps } from '../types';\n\n/**\n * Render image question\n * Shows image with clickable area, correct answer circle, and user's answer circle\n */\nexport const renderQuestionImage = ({\n result,\n}: Omit<QuestionRendererProps, 'question'>): ReactNode => {\n // Extract position data from result or question\n // Assuming correct position is stored in question metadata or result\n const correctPositionRelative = { x: 0.48, y: 0.45 }; // Default, should come from question data\n const correctRadiusRelative = 0.1; // Default radius\n\n // Get user's answer position from result\n // This would typically be stored in result.answer as coordinates\n let userPositionRelative: { x: number; y: number } | null = null;\n try {\n if (result?.answer) {\n const parsed =\n typeof result.answer === 'string'\n ? JSON.parse(result.answer)\n : result.answer;\n if (\n parsed &&\n typeof parsed.x === 'number' &&\n typeof parsed.y === 'number'\n ) {\n userPositionRelative = { x: parsed.x, y: parsed.y };\n }\n }\n } catch {\n userPositionRelative = null;\n }\n\n // Determine if answer is correct (within radius)\n const isCorrect = userPositionRelative\n ? Math.sqrt(\n Math.pow(userPositionRelative.x - correctPositionRelative.x, 2) +\n Math.pow(userPositionRelative.y - correctPositionRelative.y, 2)\n ) <= correctRadiusRelative\n : false;\n\n const getUserCircleColorClasses = () => {\n if (!userPositionRelative) return '';\n return isCorrect\n ? 'bg-success-600/70 border-white'\n : 'bg-indicator-error/70 border-white';\n };\n\n // Calculate position descriptions for accessibility\n const getPositionDescription = (x: number, y: number): string => {\n const xPercent = Math.round(x * 100);\n const yPercent = Math.round(y * 100);\n return `${xPercent}% da esquerda, ${yPercent}% do topo`;\n };\n\n const getSpatialRelationship = (): string => {\n if (!userPositionRelative) {\n return `Área correta localizada em ${getPositionDescription(\n correctPositionRelative.x,\n correctPositionRelative.y\n )}. Nenhuma resposta do aluno fornecida.`;\n }\n\n const deltaX = userPositionRelative.x - correctPositionRelative.x;\n const deltaY = userPositionRelative.y - correctPositionRelative.y;\n const distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n const distancePercent = Math.round(distance * 100);\n\n let direction: string;\n if (Math.abs(deltaX) > Math.abs(deltaY)) {\n direction = deltaX > 0 ? 'à direita' : 'à esquerda';\n } else {\n direction = deltaY > 0 ? 'abaixo' : 'acima';\n }\n\n const correctPos = getPositionDescription(\n correctPositionRelative.x,\n correctPositionRelative.y\n );\n const userPos = getPositionDescription(\n userPositionRelative.x,\n userPositionRelative.y\n );\n\n return `Área correta localizada em ${correctPos}. Resposta do aluno em ${userPos}. A resposta do aluno está ${distancePercent}% de distância ${direction} da área correta. ${isCorrect ? 'A resposta está dentro da área de tolerância e é considerada correta.' : 'A resposta está fora da área de tolerância e é considerada incorreta.'}`;\n };\n\n const correctPositionDescription = getPositionDescription(\n correctPositionRelative.x,\n correctPositionRelative.y\n );\n const imageAltText = `Questão de imagem com área correta localizada em ${correctPositionDescription}`;\n\n return (\n <div className=\"pt-2 space-y-4\">\n {/* Legend */}\n <div className=\"flex items-center gap-4 text-xs\">\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-primary/70 border border-[#F8CC2E]\"></div>\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-600\">\n Área correta\n </Text>\n </div>\n {userPositionRelative && (\n <>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-success-600/70 border border-white\"></div>\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-600\">\n Resposta correta\n </Text>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-3 h-3 rounded-full bg-indicator-error/70 border border-white\"></div>\n <Text size=\"sm\" weight=\"normal\" color=\"text-text-600\">\n Resposta incorreta\n </Text>\n </div>\n </>\n )}\n </div>\n\n {/* Image container */}\n <div className=\"relative w-full\">\n {/* Hidden text summary for screen readers */}\n <div className=\"sr-only\">{getSpatialRelationship()}</div>\n\n <img\n src={ImageQuestion}\n alt={imageAltText}\n className=\"w-full h-auto rounded-md\"\n />\n\n {/* Correct answer circle */}\n <div\n role=\"img\"\n aria-label={`Área correta marcada em ${correctPositionDescription}`}\n className=\"absolute rounded-full bg-indicator-primary/70 border-4 border-[#F8CC2E] pointer-events-none\"\n style={{\n minWidth: '50px',\n maxWidth: '160px',\n width: '15%',\n aspectRatio: '1 / 1',\n left: `calc(${correctPositionRelative.x * 100}% - 7.5%)`,\n top: `calc(${correctPositionRelative.y * 100}% - 15%)`,\n }}\n >\n <Text\n size=\"sm\"\n weight=\"normal\"\n color=\"text-text-600\"\n className=\"sr-only\"\n >\n Círculo amarelo indicando a área correta da resposta, posicionado em{' '}\n {correctPositionDescription}\n </Text>\n </div>\n\n {/* User's answer circle */}\n {userPositionRelative && (\n <div\n role=\"img\"\n aria-label={`Resposta do aluno marcada em ${getPositionDescription(\n userPositionRelative.x,\n userPositionRelative.y\n )}, ${isCorrect ? 'correta' : 'incorreta'}`}\n className={`absolute rounded-full border-4 pointer-events-none ${getUserCircleColorClasses()}`}\n style={{\n minWidth: '30px',\n maxWidth: '52px',\n width: '5%',\n aspectRatio: '1 / 1',\n left: `calc(${userPositionRelative.x * 100}% - 2.5%)`,\n top: `calc(${userPositionRelative.y * 100}% - 2.5%)`,\n }}\n >\n <Text\n size=\"sm\"\n weight=\"normal\"\n color=\"text-text-600\"\n className=\"sr-only\"\n >\n Círculo {isCorrect ? 'verde' : 'vermelho'} indicando a resposta do\n aluno, posicionado em{' '}\n {getPositionDescription(\n userPositionRelative.x,\n userPositionRelative.y\n )}\n . A resposta está{' '}\n {Math.round(\n Math.sqrt(\n Math.pow(\n userPositionRelative.x - correctPositionRelative.x,\n 2\n ) +\n Math.pow(\n userPositionRelative.y - correctPositionRelative.y,\n 2\n )\n ) * 100\n )}\n % de distância da área correta e é considerada{' '}\n {isCorrect ? 'correta' : 'incorreta'}.\n </Text>\n </div>\n )}\n </div>\n </div>\n );\n};\n","import type { ReactNode } from 'react';\nimport { cn } from '../../../utils/utils';\nimport Text from '../../../components/Text/Text';\nimport { QuestionSubTitle, QuestionContainer } from '../components';\n\n/**\n * Render connect dots question (not implemented)\n */\nexport const renderQuestionConnectDots = ({\n paddingBottom,\n}: {\n paddingBottom?: string;\n} = {}): ReactNode => {\n return (\n <>\n <QuestionSubTitle subTitle=\"Tipo de questão: Ligar Pontos\" />\n <QuestionContainer className={cn('', paddingBottom)}>\n <div className=\"space-y-4\">\n <Text size=\"md\" weight=\"normal\" color=\"text-text-600\">\n Tipo de questão: Ligar Pontos (não implementado)\n </Text>\n </div>\n </QuestionContainer>\n </>\n );\n};\n","import type { ReactNode } from 'react';\nimport { QUESTION_TYPE } from '../../components/Quiz/useQuizStore';\nimport { renderQuestionAlternative } from './alternative';\nimport { renderQuestionMultipleChoice } from './multipleChoice';\nimport { renderQuestionTrueOrFalse } from './trueOrFalse';\nimport { renderQuestionDissertative } from './dissertative';\nimport { renderQuestionFill } from './fill';\nimport { renderQuestionImage } from './image';\nimport { renderQuestionConnectDots } from './connectDots';\nimport type { QuestionRendererProps } from './types';\n\n// Re-export types\nexport type { QuestionRendererProps } from './types';\n\n// Re-export components\nexport {\n getStatusBadge,\n QuestionContainer,\n QuestionSubTitle,\n FillQuestionContent,\n} from './components';\n\n// Re-export individual renderers\nexport { renderQuestionAlternative } from './alternative';\nexport { renderQuestionMultipleChoice } from './multipleChoice';\nexport { renderQuestionTrueOrFalse } from './trueOrFalse';\nexport { renderQuestionDissertative } from './dissertative';\nexport { renderQuestionFill } from './fill';\nexport { renderQuestionImage } from './image';\nexport { renderQuestionConnectDots } from './connectDots';\n\n/**\n * Map question types to their render functions\n */\nconst questionRendererMap = {\n [QUESTION_TYPE.ALTERNATIVA]: renderQuestionAlternative,\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: renderQuestionMultipleChoice,\n [QUESTION_TYPE.VERDADEIRO_FALSO]: renderQuestionTrueOrFalse,\n [QUESTION_TYPE.DISSERTATIVA]: renderQuestionDissertative,\n [QUESTION_TYPE.PREENCHER_LACUNAS]: renderQuestionFill,\n [QUESTION_TYPE.IMAGEM]: renderQuestionImage,\n [QUESTION_TYPE.RELACIONAR]: renderQuestionConnectDots,\n};\n\n/**\n * Render question based on question type\n * @param props - Question renderer props\n * @returns Rendered question content\n */\nexport const renderQuestion = (props: QuestionRendererProps): ReactNode => {\n const { question } = props;\n const renderer = questionRendererMap[question.questionType];\n\n if (!renderer) {\n // Fallback: try to render based on options presence\n if (question.options && question.options.length > 0) {\n return renderQuestionAlternative(props);\n }\n return renderQuestionDissertative({ result: props.result });\n }\n\n // Handle renderers with different prop requirements\n switch (question.questionType) {\n case QUESTION_TYPE.DISSERTATIVA:\n return renderQuestionDissertative({ result: props.result });\n case QUESTION_TYPE.IMAGEM:\n return renderQuestionImage({ result: props.result });\n case QUESTION_TYPE.RELACIONAR:\n return renderQuestionConnectDots({ paddingBottom: '' });\n case QUESTION_TYPE.ALTERNATIVA:\n case QUESTION_TYPE.MULTIPLA_ESCOLHA:\n case QUESTION_TYPE.VERDADEIRO_FALSO:\n case QUESTION_TYPE.PREENCHER_LACUNAS:\n return renderer(props);\n default:\n return null;\n }\n};\n\n/**\n * Type for question renderer map\n */\nexport type QuestionRendererMap = Record<QUESTION_TYPE, () => ReactNode>;\n\n/**\n * Render from a map of renderers\n * @param renderers - Map of question type to render function\n * @param questionType - Type of question to render\n * @returns Rendered content or null\n */\nexport const renderFromMap = (\n renderers: QuestionRendererMap,\n questionType?: QUESTION_TYPE\n) => {\n if (!questionType) return null;\n const renderer = renderers[questionType];\n return renderer ? renderer() : null;\n};\n","import { QUESTION_TYPE } from '../components/Quiz/useQuizStore';\n\n/**\n * Map question types to display labels\n */\nexport const questionTypeLabels: Record<QUESTION_TYPE, string> = {\n [QUESTION_TYPE.ALTERNATIVA]: 'Alternativa',\n [QUESTION_TYPE.VERDADEIRO_FALSO]: 'Verdadeiro ou Falso',\n [QUESTION_TYPE.DISSERTATIVA]: 'Discursiva',\n [QUESTION_TYPE.IMAGEM]: 'Imagem',\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: 'Múltipla Escolha',\n [QUESTION_TYPE.RELACIONAR]: 'Relacionar',\n [QUESTION_TYPE.PREENCHER_LACUNAS]: 'Preencher Lacunas',\n};\n","import { HtmlHTMLAttributes, useMemo, useId, ReactNode } from 'react';\nimport { cn } from '../../utils/utils';\nimport { parseContent } from '../../utils/parseContent';\nimport { CheckCircle, XCircle } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport Text from '../Text/Text';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport { QuizVariant } from '../Quiz/Quiz.types';\n\nexport interface FillInBlanksOption {\n id: string;\n option: string;\n}\n\nexport interface FillInBlanksProps extends HtmlHTMLAttributes<HTMLDivElement> {\n /** The text content with {uuid} placeholders */\n content: string;\n /** Available options to fill in the blanks */\n options: FillInBlanksOption[];\n /** Current answers as a map of placeholderId -> selectedOptionId */\n answers?: Record<string, string>;\n /** Callback when an answer changes (only for interactive mode) */\n onAnswerChange?: (placeholderId: string, optionId: string) => void;\n /** Display mode */\n mode?: 'interactive' | 'readonly' | 'result';\n /** Whether component is disabled (only for interactive mode) */\n disabled?: boolean;\n}\n\n/**\n * FillInBlanks component for displaying fill-in-the-blanks questions\n *\n * @example\n * // Readonly mode - shows correct answers with green underlined text\n * <FillInBlanks\n * content=\"A {uuid-1} é uma {uuid-2}.\"\n * options={[{ id: 'uuid-1', option: 'Terra' }, { id: 'uuid-2', option: 'planeta' }]}\n * mode=\"readonly\"\n * />\n *\n * @example\n * // Interactive mode - shows select dropdowns\n * <FillInBlanks\n * content=\"A {uuid-1} é uma {uuid-2}.\"\n * options={[{ id: 'uuid-1', option: 'Terra' }, { id: 'uuid-2', option: 'planeta' }]}\n * mode=\"interactive\"\n * answers={answers}\n * onAnswerChange={(placeholderId, optionId) => setAnswers({...answers, [placeholderId]: optionId})}\n * />\n *\n * @example\n * // Result mode - shows badges with correct/incorrect indicators\n * <FillInBlanks\n * content=\"A {uuid-1} é uma {uuid-2}.\"\n * options={[{ id: 'uuid-1', option: 'Terra' }, { id: 'uuid-2', option: 'planeta' }]}\n * mode=\"result\"\n * answers={userAnswers}\n * />\n */\nconst FillInBlanks = ({\n content,\n options,\n answers = {},\n onAnswerChange,\n mode = QuizVariant.INTERACTIVE,\n disabled = false,\n className,\n ...props\n}: FillInBlanksProps) => {\n const baseId = useId();\n\n // Create a map of option IDs to their text\n const optionsMap = useMemo(() => {\n return new Map(options.map((opt) => [opt.id, opt.option]));\n }, [options]);\n\n // Parse the content into parts\n const parsedParts = useMemo(() => parseContent(content), [content]);\n\n // Get option text by ID\n const getOptionText = (optionId: string): string => {\n return optionsMap.get(optionId) || '';\n };\n\n // Check if an answer is correct (the placeholderId IS the correct option ID)\n const isAnswerCorrect = (placeholderId: string): boolean => {\n const selectedOptionId = answers[placeholderId];\n return selectedOptionId === placeholderId;\n };\n\n // Render select for interactive mode\n const renderSelect = (placeholderId: string, index: number) => {\n const selectedOptionId = answers[placeholderId];\n\n return (\n <span\n key={`${baseId}-select-${index}`}\n className={cn(\n 'inline-block align-middle mx-1',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <Select\n value={selectedOptionId || undefined}\n onValueChange={(value) => onAnswerChange?.(placeholderId, value)}\n >\n <SelectTrigger className=\"w-auto min-w-[120px] h-7 px-2 bg-background border-gray-300\">\n <SelectValue placeholder=\"Selecione\" />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {option.option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n );\n };\n\n // Render correct answer for readonly mode\n const renderCorrectAnswer = (placeholderId: string, index: number) => {\n const correctText = getOptionText(placeholderId);\n\n return (\n <span\n key={`${baseId}-answer-${index}`}\n className=\"text-success-600 underline font-medium\"\n >\n {correctText}\n </span>\n );\n };\n\n // Render result badge\n const renderResultBadge = (placeholderId: string, index: number) => {\n const selectedOptionId = answers[placeholderId];\n const selectedText = getOptionText(selectedOptionId);\n const isCorrect = isAnswerCorrect(placeholderId);\n\n if (!selectedOptionId) {\n return (\n <span\n key={`${baseId}-result-${index}`}\n className=\"inline-block align-middle mx-1\"\n >\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n </span>\n );\n }\n\n return (\n <span\n key={`${baseId}-result-${index}`}\n className=\"inline-block align-middle mx-1\"\n >\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n <span className=\"text-text-900\">{selectedText}</span>\n </Badge>\n </span>\n );\n };\n\n // Render the appropriate element based on mode\n const renderPlaceholder = (\n placeholderId: string,\n index: number\n ): ReactNode => {\n switch (mode) {\n case QuizVariant.INTERACTIVE:\n return renderSelect(placeholderId, index);\n case QuizVariant.READONLY:\n return renderCorrectAnswer(placeholderId, index);\n case QuizVariant.RESULT:\n return renderResultBadge(placeholderId, index);\n default:\n return renderCorrectAnswer(placeholderId, index);\n }\n };\n\n // Build the rendered content\n const renderedContent = useMemo(() => {\n return parsedParts.map((part, index) => {\n if (part.type === 'text') {\n return <span key={`${baseId}-text-${index}`}>{part.value}</span>;\n }\n return renderPlaceholder(part.value, index);\n });\n }, [parsedParts, baseId, mode, answers, options, disabled]);\n\n return (\n <div className={cn('leading-relaxed', className)} {...props}>\n <Text size=\"sm\" className=\"text-text-900\">\n {renderedContent}\n </Text>\n </div>\n );\n};\n\nexport { FillInBlanks };\n","import { stripHtmlTags } from './stringUtils';\n\nexport interface ParsedContentPart {\n type: 'text' | 'placeholder';\n value: string;\n}\n\n/**\n * Parse content and extract text parts and placeholder IDs\n * Extracts {uuid} placeholders from text content, stripping HTML tags first\n *\n * @param content - String that may contain HTML and {uuid} placeholders\n * @returns Array of parsed parts with type ('text' or 'placeholder') and value\n *\n * @example\n * parseContent('Hello {uuid-1} world {uuid-2}')\n * // Returns: [\n * // { type: 'text', value: 'Hello ' },\n * // { type: 'placeholder', value: 'uuid-1' },\n * // { type: 'text', value: ' world ' },\n * // { type: 'placeholder', value: 'uuid-2' }\n * // ]\n */\nexport function parseContent(content: string): ParsedContentPart[] {\n const parts: ParsedContentPart[] = [];\n const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n let lastIndex = 0;\n let match;\n\n // Strip HTML tags for cleaner parsing\n const cleanContent = stripHtmlTags(content);\n\n while ((match = regex.exec(cleanContent)) !== null) {\n // Add text before the placeholder\n if (match.index > lastIndex) {\n parts.push({\n type: 'text',\n value: cleanContent.slice(lastIndex, match.index),\n });\n }\n\n // Add the placeholder\n parts.push({\n type: 'placeholder',\n value: match[1],\n });\n\n lastIndex = match.index + match[0].length;\n }\n\n // Add remaining text\n if (lastIndex < cleanContent.length) {\n parts.push({\n type: 'text',\n value: cleanContent.slice(lastIndex),\n });\n }\n\n return parts;\n}\n","import { HtmlHTMLAttributes, useMemo, useId, ReactNode } from 'react';\nimport { cn } from '../../utils/utils';\nimport { CheckCircle, XCircle, ArrowRight } from 'phosphor-react';\nimport Badge from '../Badge/Badge';\nimport Text from '../Text/Text';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport { QuizVariant } from '../Quiz/Quiz.types';\n\nexport interface ConnectDotsOption {\n id: string;\n option: string;\n correctValue: string;\n}\n\nexport interface ConnectDotsProps extends HtmlHTMLAttributes<HTMLDivElement> {\n /** Available options with their correct values */\n options: ConnectDotsOption[];\n /** Current answers as a map of optionId -> selectedValue */\n answers?: Record<string, string>;\n /** Callback when an answer changes (only for interactive mode) */\n onAnswerChange?: (optionId: string, selectedValue: string) => void;\n /** Display mode */\n mode?: 'interactive' | 'readonly' | 'result';\n /** Whether component is disabled (only for interactive mode) */\n disabled?: boolean;\n}\n\n/**\n * ConnectDots component for displaying matching/connect-the-dots questions\n *\n * @example\n * // Readonly mode - shows correct matches with arrows\n * <ConnectDots\n * options={[\n * { id: 'opt-1', option: 'I. Event A', correctValue: '2001' },\n * { id: 'opt-2', option: 'II. Event B', correctValue: '1989' },\n * ]}\n * mode=\"readonly\"\n * />\n *\n * @example\n * // Interactive mode - shows select dropdowns\n * <ConnectDots\n * options={[...]}\n * mode=\"interactive\"\n * answers={answers}\n * onAnswerChange={(optionId, value) => setAnswers({...answers, [optionId]: value})}\n * />\n *\n * @example\n * // Result mode - shows badges with correct/incorrect indicators\n * <ConnectDots\n * options={[...]}\n * mode=\"result\"\n * answers={userAnswers}\n * />\n */\nconst ConnectDots = ({\n options,\n answers = {},\n onAnswerChange,\n mode = QuizVariant.INTERACTIVE,\n disabled = false,\n className,\n ...props\n}: ConnectDotsProps) => {\n const baseId = useId();\n\n // Get all unique correct values for the dropdown options\n const availableValues = useMemo(() => {\n const values = options.map((opt) => opt.correctValue);\n // Remove duplicates and sort alphabetically using localeCompare\n return [...new Set(values)].sort((a, b) => a.localeCompare(b));\n }, [options]);\n\n // Check if an answer is correct\n const isAnswerCorrect = (optionId: string): boolean => {\n const option = options.find((opt) => opt.id === optionId);\n if (!option) return false;\n const selectedValue = answers[optionId];\n return selectedValue === option.correctValue;\n };\n\n // Render select for interactive mode\n const renderInteractiveItem = (option: ConnectDotsOption, index: number) => {\n const selectedValue = answers[option.id];\n\n return (\n <div\n key={`${baseId}-item-${index}`}\n className={cn(\n 'flex flex-row items-center gap-3 p-3 rounded-md border border-border-200 bg-background',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={option.option}\n className=\"text-text-900 text-sm\"\n />\n </div>\n\n <ArrowRight size={20} className=\"text-text-400 flex-shrink-0\" />\n\n <div className=\"w-[150px] flex-shrink-0\">\n <Select\n value={selectedValue || undefined}\n onValueChange={(value) => {\n if (disabled) return;\n onAnswerChange?.(option.id, value);\n }}\n >\n <SelectTrigger\n disabled={disabled}\n className=\"w-full h-8 px-2 bg-background border-gray-300\"\n >\n <SelectValue placeholder=\"Selecione\" />\n </SelectTrigger>\n <SelectContent>\n {availableValues.map((value) => (\n <SelectItem key={value} value={value}>\n {value}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n );\n };\n\n // Render correct match for readonly mode\n const renderReadonlyItem = (option: ConnectDotsOption, index: number) => {\n return (\n <div\n key={`${baseId}-readonly-${index}`}\n className=\"flex flex-row items-center gap-3 p-3 rounded-md border border-success-300 bg-success-50\"\n >\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={option.option}\n className=\"text-text-900 text-sm\"\n />\n </div>\n\n <ArrowRight size={20} className=\"text-success-600 flex-shrink-0\" />\n\n <div className=\"flex-shrink-0\">\n <Text size=\"sm\" weight=\"medium\" className=\"text-success-700\">\n {option.correctValue}\n </Text>\n </div>\n </div>\n );\n };\n\n // Render result item with correct/incorrect indicator\n const renderResultItem = (option: ConnectDotsOption, index: number) => {\n const selectedValue = answers[option.id];\n const isCorrect = isAnswerCorrect(option.id);\n const hasAnswer = !!selectedValue;\n\n // Only show success styling when answered correctly\n const isSuccess = hasAnswer && isCorrect;\n const borderStyles = isSuccess\n ? 'border-success-300 bg-success-50'\n : 'border-error-300 bg-error-50';\n const arrowColor = isSuccess ? 'text-success-600' : 'text-error-600';\n\n return (\n <div\n key={`${baseId}-result-${index}`}\n className={cn(\n 'flex flex-row items-center gap-3 p-3 rounded-md border',\n borderStyles\n )}\n >\n <div className=\"flex-1\">\n <HtmlMathRenderer\n content={option.option}\n className=\"text-text-900 text-sm\"\n />\n </div>\n\n <ArrowRight size={20} className={cn('flex-shrink-0', arrowColor)} />\n\n <div className=\"flex-shrink-0\">\n {hasAnswer ? (\n <Badge\n variant=\"solid\"\n action={isCorrect ? 'success' : 'error'}\n iconRight={isCorrect ? <CheckCircle /> : <XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n {selectedValue}\n </Badge>\n ) : (\n <Badge\n variant=\"solid\"\n action=\"error\"\n iconRight={<XCircle />}\n size=\"large\"\n className=\"py-1 px-2\"\n >\n Não respondido\n </Badge>\n )}\n </div>\n\n {/* Show correct answer if wrong */}\n {hasAnswer && !isCorrect && (\n <Text size=\"xs\" className=\"text-success-600 flex-shrink-0\">\n (Correto: {option.correctValue})\n </Text>\n )}\n </div>\n );\n };\n\n // Render the appropriate element based on mode\n const renderItem = (option: ConnectDotsOption, index: number): ReactNode => {\n switch (mode) {\n case QuizVariant.INTERACTIVE:\n return renderInteractiveItem(option, index);\n case QuizVariant.READONLY:\n return renderReadonlyItem(option, index);\n case QuizVariant.RESULT:\n return renderResultItem(option, index);\n default:\n return renderReadonlyItem(option, index);\n }\n };\n\n // Build the rendered content\n const renderedContent = useMemo(() => {\n return options.map((option, index) => renderItem(option, index));\n }, [options, baseId, mode, answers, disabled, availableValues]);\n\n return (\n <div className={cn('flex flex-col gap-2', className)} {...props}>\n {renderedContent}\n </div>\n );\n};\n\nexport { ConnectDots };\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","VARIANT_ACTION_CLASSES","SIZE_CLASSES","import_jsx_runtime","katex","import_react","import_katex_min","import_react","match","import_jsx_runtime","ReactMarkdown","remarkGfm","remarkMath","rehypeKatex","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","SIZE_CLASSES","import_react","import_jsx_runtime","import_react","import_zustand","import_jsx_runtime","SIZE_CLASSES","STATE_CLASSES","injectStore","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_phosphor_react","import_react","import_jsx_runtime","getStatusStyles","isReadonly","getStatusBadge","value","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","getStatusBadge","getStatusStyles","import_jsx_runtime","import_react","import_zustand","import_react","import_phosphor_react","import_jsx_runtime","SIZE_CLASSES","injectStore","children","label","import_phosphor_react","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","import_react","import_phosphor_react","import_jsx_runtime","import_phosphor_react","import_react","import_jsx_runtime","correctOptionIds"]}