analytica-frontend-lib 1.2.44 → 1.2.45

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.
Files changed (134) hide show
  1. package/dist/Accordation/index.js.map +1 -1
  2. package/dist/Accordation/index.mjs.map +1 -1
  3. package/dist/ActivityCardQuestionBanks/index.js.map +1 -1
  4. package/dist/ActivityCardQuestionBanks/index.mjs.map +1 -1
  5. package/dist/ActivityCardQuestionPreview/index.js.map +1 -1
  6. package/dist/ActivityCardQuestionPreview/index.mjs.map +1 -1
  7. package/dist/ActivityDetails/index.d.ts.map +1 -1
  8. package/dist/ActivityDetails/index.js +59 -50
  9. package/dist/ActivityDetails/index.js.map +1 -1
  10. package/dist/ActivityDetails/index.mjs +59 -50
  11. package/dist/ActivityDetails/index.mjs.map +1 -1
  12. package/dist/ActivityFilters/index.js.map +1 -1
  13. package/dist/ActivityFilters/index.mjs.map +1 -1
  14. package/dist/ActivityPreview/index.js.map +1 -1
  15. package/dist/ActivityPreview/index.mjs.map +1 -1
  16. package/dist/Alert/index.js.map +1 -1
  17. package/dist/Alert/index.mjs.map +1 -1
  18. package/dist/AlertDialog/index.js.map +1 -1
  19. package/dist/AlertDialog/index.mjs.map +1 -1
  20. package/dist/AlertManager/index.js.map +1 -1
  21. package/dist/AlertManager/index.mjs.map +1 -1
  22. package/dist/AlertManagerView/index.js.map +1 -1
  23. package/dist/AlertManagerView/index.mjs.map +1 -1
  24. package/dist/Alternative/index.js.map +1 -1
  25. package/dist/Alternative/index.mjs.map +1 -1
  26. package/dist/Badge/index.js.map +1 -1
  27. package/dist/Badge/index.mjs.map +1 -1
  28. package/dist/BreadcrumbMenu/index.js.map +1 -1
  29. package/dist/BreadcrumbMenu/index.mjs.map +1 -1
  30. package/dist/Button/index.js.map +1 -1
  31. package/dist/Button/index.mjs.map +1 -1
  32. package/dist/Calendar/index.js.map +1 -1
  33. package/dist/Calendar/index.mjs.map +1 -1
  34. package/dist/Card/index.js.map +1 -1
  35. package/dist/Card/index.mjs.map +1 -1
  36. package/dist/CheckBox/index.js.map +1 -1
  37. package/dist/CheckBox/index.mjs.map +1 -1
  38. package/dist/Chips/index.js.map +1 -1
  39. package/dist/Chips/index.mjs.map +1 -1
  40. package/dist/CorrectActivityModal/index.js.map +1 -1
  41. package/dist/CorrectActivityModal/index.mjs.map +1 -1
  42. package/dist/Divider/index.js.map +1 -1
  43. package/dist/Divider/index.mjs.map +1 -1
  44. package/dist/DownloadButton/index.js.map +1 -1
  45. package/dist/DownloadButton/index.mjs.map +1 -1
  46. package/dist/DropdownMenu/index.js.map +1 -1
  47. package/dist/DropdownMenu/index.mjs.map +1 -1
  48. package/dist/EmptyState/index.js.map +1 -1
  49. package/dist/EmptyState/index.mjs.map +1 -1
  50. package/dist/FileAttachment/index.js.map +1 -1
  51. package/dist/FileAttachment/index.mjs.map +1 -1
  52. package/dist/IconButton/index.js.map +1 -1
  53. package/dist/IconButton/index.mjs.map +1 -1
  54. package/dist/IconRoundedButton/index.js.map +1 -1
  55. package/dist/IconRoundedButton/index.mjs.map +1 -1
  56. package/dist/LatexRenderer/index.js.map +1 -1
  57. package/dist/LatexRenderer/index.mjs.map +1 -1
  58. package/dist/Menu/index.js.map +1 -1
  59. package/dist/Menu/index.mjs.map +1 -1
  60. package/dist/Modal/index.js.map +1 -1
  61. package/dist/Modal/index.mjs.map +1 -1
  62. package/dist/MultipleChoice/index.js.map +1 -1
  63. package/dist/MultipleChoice/index.mjs.map +1 -1
  64. package/dist/NavButton/index.js.map +1 -1
  65. package/dist/NavButton/index.mjs.map +1 -1
  66. package/dist/NoSearchResult/index.js.map +1 -1
  67. package/dist/NoSearchResult/index.mjs.map +1 -1
  68. package/dist/NotFound/index.js.map +1 -1
  69. package/dist/NotFound/index.mjs.map +1 -1
  70. package/dist/NotificationCard/index.js.map +1 -1
  71. package/dist/NotificationCard/index.mjs.map +1 -1
  72. package/dist/ProgressBar/index.js.map +1 -1
  73. package/dist/ProgressBar/index.mjs.map +1 -1
  74. package/dist/ProgressCircle/index.js.map +1 -1
  75. package/dist/ProgressCircle/index.mjs.map +1 -1
  76. package/dist/Quiz/index.js.map +1 -1
  77. package/dist/Quiz/index.mjs.map +1 -1
  78. package/dist/Radio/index.js.map +1 -1
  79. package/dist/Radio/index.mjs.map +1 -1
  80. package/dist/Search/index.js.map +1 -1
  81. package/dist/Search/index.mjs.map +1 -1
  82. package/dist/Select/index.js.map +1 -1
  83. package/dist/Select/index.mjs.map +1 -1
  84. package/dist/SelectionButton/index.js.map +1 -1
  85. package/dist/SelectionButton/index.mjs.map +1 -1
  86. package/dist/SendActivityModal/index.js.map +1 -1
  87. package/dist/SendActivityModal/index.mjs.map +1 -1
  88. package/dist/Skeleton/index.js.map +1 -1
  89. package/dist/Skeleton/index.mjs.map +1 -1
  90. package/dist/StatisticsCard/index.js.map +1 -1
  91. package/dist/StatisticsCard/index.mjs.map +1 -1
  92. package/dist/Stepper/index.js.map +1 -1
  93. package/dist/Stepper/index.mjs.map +1 -1
  94. package/dist/Support/TicketModal/index.js.map +1 -1
  95. package/dist/Support/TicketModal/index.mjs.map +1 -1
  96. package/dist/Support/index.js.map +1 -1
  97. package/dist/Support/index.mjs.map +1 -1
  98. package/dist/Table/TablePagination/index.js.map +1 -1
  99. package/dist/Table/TablePagination/index.mjs.map +1 -1
  100. package/dist/Table/index.js.map +1 -1
  101. package/dist/Table/index.mjs.map +1 -1
  102. package/dist/TableProvider/index.js.map +1 -1
  103. package/dist/TableProvider/index.mjs.map +1 -1
  104. package/dist/Text/index.js.map +1 -1
  105. package/dist/Text/index.mjs.map +1 -1
  106. package/dist/TextArea/index.js.map +1 -1
  107. package/dist/TextArea/index.mjs.map +1 -1
  108. package/dist/ThemeToggle/index.js.map +1 -1
  109. package/dist/ThemeToggle/index.mjs.map +1 -1
  110. package/dist/Toast/Toaster/index.js.map +1 -1
  111. package/dist/Toast/Toaster/index.mjs.map +1 -1
  112. package/dist/Toast/index.js.map +1 -1
  113. package/dist/Toast/index.mjs.map +1 -1
  114. package/dist/VideoPlayer/index.js.map +1 -1
  115. package/dist/VideoPlayer/index.mjs.map +1 -1
  116. package/dist/Whiteboard/index.js.map +1 -1
  117. package/dist/Whiteboard/index.mjs.map +1 -1
  118. package/dist/index.d.ts +2 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +62 -55
  121. package/dist/index.js.map +1 -1
  122. package/dist/index.mjs +62 -55
  123. package/dist/index.mjs.map +1 -1
  124. package/dist/types/activityDetails.d.ts +0 -24
  125. package/dist/types/activityDetails.d.ts.map +1 -1
  126. package/dist/utils/activityDetailsUtils.d.ts +30 -0
  127. package/dist/utils/activityDetailsUtils.d.ts.map +1 -0
  128. package/dist/utils/index.d.ts +1 -0
  129. package/dist/utils/index.d.ts.map +1 -1
  130. package/dist/utils/index.js +65 -0
  131. package/dist/utils/index.js.map +1 -1
  132. package/dist/utils/index.mjs +61 -0
  133. package/dist/utils/index.mjs.map +1 -1
  134. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/NotificationCard/NotificationCard.tsx","../../src/utils/utils.ts","../../src/components/DropdownMenu/DropdownMenu.tsx","../../src/components/Button/Button.tsx","../../src/components/Text/Text.tsx","../../src/components/Modal/Modal.tsx","../../src/components/Modal/utils/videoUtils.ts","../../src/components/ThemeToggle/ThemeToggle.tsx","../../src/components/SelectionButton/SelectionButton.tsx","../../src/hooks/useTheme.ts","../../src/store/themeStore.ts","../../src/components/Skeleton/Skeleton.tsx","../../src/components/IconButton/IconButton.tsx","../../src/components/Badge/Badge.tsx","../../src/hooks/useMobile.ts","../../src/store/notificationStore.ts"],"sourcesContent":["import { DotsThreeVertical, Bell } from 'phosphor-react';\nimport { MouseEvent, ReactNode, useState, useEffect } from 'react';\nimport { cn } from '../../utils/utils';\nimport DropdownMenu, {\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../DropdownMenu/DropdownMenu';\nimport { SkeletonCard } from '../Skeleton/Skeleton';\nimport IconButton from '../IconButton/IconButton';\nimport Modal from '../Modal/Modal';\nimport Text from '../Text/Text';\nimport Badge from '../Badge/Badge';\nimport { useMobile } from '../../hooks/useMobile';\nimport type {\n Notification,\n NotificationGroup,\n NotificationEntityType,\n} from '../../types/notifications';\nimport { formatTimeAgo } from '../../store/notificationStore';\nimport mockContentImage from '../../assets/img/mock-content.png';\n\n// Extended notification item for component usage with time string\nexport interface NotificationItem extends Omit<Notification, 'createdAt'> {\n time: string;\n createdAt: string | Date;\n}\n\n// Base props shared across all modes\ninterface BaseNotificationProps {\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Empty state image path\n */\n emptyStateImage?: string;\n /**\n * Empty state title\n */\n emptyStateTitle?: string;\n /**\n * Empty state description\n */\n emptyStateDescription?: string;\n}\n\n// Single notification card mode\ninterface SingleNotificationCardMode extends BaseNotificationProps {\n /**\n * Component mode - single card\n */\n mode: 'single';\n /**\n * The notification title\n */\n title: string;\n /**\n * The notification message content\n */\n message: string;\n /**\n * Time displayed (e.g., \"Há 3h\", \"12 Fev\")\n */\n time: string;\n /**\n * Whether the notification has been read\n */\n isRead: boolean;\n /**\n * Callback when user marks notification as read\n */\n onMarkAsRead: () => void;\n /**\n * Callback when user deletes notification\n */\n onDelete: () => void;\n /**\n * Optional callback for navigation action\n */\n onNavigate?: () => void;\n /**\n * Label for the action button (only shown if onNavigate is provided)\n */\n actionLabel?: string;\n}\n\n// List mode\ninterface NotificationListMode extends BaseNotificationProps {\n /**\n * Component mode - list\n */\n mode: 'list';\n /**\n * Array of notifications for list mode\n */\n notifications?: NotificationItem[];\n /**\n * Array of grouped notifications\n */\n groupedNotifications?: NotificationGroup[];\n /**\n * Loading state for list mode\n */\n loading?: boolean;\n /**\n * Error state for list mode\n */\n error?: string | null;\n /**\n * Callback for retry when error occurs\n */\n onRetry?: () => void;\n /**\n * Callback when user marks a notification as read in list mode\n */\n onMarkAsReadById?: (id: string) => void;\n /**\n * Callback when user deletes a notification in list mode\n */\n onDeleteById?: (id: string) => void;\n /**\n * Callback when user navigates from a notification in list mode\n */\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n /**\n * Callback when user clicks on a global notification\n */\n onGlobalNotificationClick?: (notification: Notification) => void;\n /**\n * Function to get action label for a notification\n */\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n /**\n * Custom empty state component\n */\n renderEmpty?: () => ReactNode;\n}\n\n// NotificationCenter mode\ninterface NotificationCenterMode extends BaseNotificationProps {\n /**\n * Component mode - center\n */\n mode: 'center';\n /**\n * Array of grouped notifications\n */\n groupedNotifications?: NotificationGroup[];\n /**\n * Loading state for center mode\n */\n loading?: boolean;\n /**\n * Error state for center mode\n */\n error?: string | null;\n /**\n * Callback for retry when error occurs\n */\n onRetry?: () => void;\n /**\n * Whether center mode is currently active (controls dropdown/modal visibility)\n */\n isActive?: boolean;\n /**\n * Callback when center mode is toggled\n */\n onToggleActive?: () => void;\n /**\n * Number of unread notifications for badge display\n */\n unreadCount?: number;\n /**\n * Callback when all notifications should be marked as read\n */\n onMarkAllAsRead?: () => void;\n /**\n * Callback to fetch notifications (called when center opens)\n */\n onFetchNotifications?: () => void;\n /**\n * Callback when user marks a notification as read in center mode\n */\n onMarkAsReadById?: (id: string) => void;\n /**\n * Callback when user deletes a notification in center mode\n */\n onDeleteById?: (id: string) => void;\n /**\n * Callback when user navigates from a notification in center mode\n */\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n /**\n * Function to get action label for a notification\n */\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n /**\n * Callback when dropdown open state changes (for synchronization with parent)\n */\n onOpenChange?: (open: boolean) => void;\n}\n\n// Union type for all modes\nexport type NotificationCardProps =\n | SingleNotificationCardMode\n | NotificationListMode\n | NotificationCenterMode;\n\n// Legacy interface for backward compatibility\nexport interface LegacyNotificationCardProps extends BaseNotificationProps {\n // Single notification mode props\n title?: string;\n message?: string;\n time?: string;\n isRead?: boolean;\n onMarkAsRead?: () => void;\n onDelete?: () => void;\n onNavigate?: () => void;\n actionLabel?: string;\n\n // List mode props\n notifications?: NotificationItem[];\n groupedNotifications?: NotificationGroup[];\n loading?: boolean;\n error?: string | null;\n onRetry?: () => void;\n onMarkAsReadById?: (id: string) => void;\n onDeleteById?: (id: string) => void;\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n onGlobalNotificationClick?: (notification: Notification) => void;\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n renderEmpty?: () => ReactNode;\n\n // NotificationCenter mode props\n variant?: 'card' | 'center';\n isActive?: boolean;\n onToggleActive?: () => void;\n unreadCount?: number;\n onMarkAllAsRead?: () => void;\n onFetchNotifications?: () => void;\n onOpenChange?: (open: boolean) => void;\n}\n\n/**\n * Empty state component for notifications\n */\nconst NotificationEmpty = ({\n emptyStateImage,\n emptyStateTitle = 'Nenhuma notificação no momento',\n emptyStateDescription = 'Você está em dia com todas as novidades. Volte depois para conferir atualizações!',\n}: {\n emptyStateImage?: string;\n emptyStateTitle?: string;\n emptyStateDescription?: string;\n}) => {\n return (\n <div className=\"flex flex-col items-center justify-center gap-4 p-6 w-full\">\n {/* Notification Icon */}\n {emptyStateImage && (\n <div className=\"w-20 h-20 flex items-center justify-center\">\n <img\n src={emptyStateImage}\n alt=\"Sem notificações\"\n width={82}\n height={82}\n className=\"object-contain\"\n />\n </div>\n )}\n\n {/* Title */}\n <h3 className=\"text-xl font-semibold text-text-950 text-center leading-[23px]\">\n {emptyStateTitle}\n </h3>\n\n {/* Description */}\n <p className=\"text-sm font-normal text-text-400 text-center max-w-[316px] leading-[21px]\">\n {emptyStateDescription}\n </p>\n </div>\n );\n};\n\n/**\n * Notification header component\n */\nconst NotificationHeader = ({\n unreadCount,\n variant = 'modal',\n}: {\n unreadCount: number;\n variant?: 'modal' | 'dropdown';\n}) => {\n return (\n <div className=\"flex items-center justify-between gap-2\">\n {variant === 'modal' ? (\n <Text size=\"sm\" weight=\"bold\" className=\"text-text-950\">\n Notificações\n </Text>\n ) : (\n <h3 className=\"text-sm font-semibold text-text-950\">Notificações</h3>\n )}\n {unreadCount > 0 && (\n <Badge\n variant=\"solid\"\n action=\"info\"\n size=\"small\"\n iconLeft={<Bell size={12} aria-hidden=\"true\" focusable=\"false\" />}\n className=\"border-0\"\n >\n {unreadCount === 1 ? '1 não lida' : `${unreadCount} não lidas`}\n </Badge>\n )}\n </div>\n );\n};\n\n/**\n * Single notification card component\n */\nconst SingleNotificationCard = ({\n title,\n message,\n time,\n isRead,\n onMarkAsRead,\n onDelete,\n onNavigate,\n actionLabel,\n className,\n}: {\n title: string;\n message: string;\n time: string;\n isRead: boolean;\n onMarkAsRead: () => void;\n onDelete: () => void;\n onNavigate?: () => void;\n actionLabel?: string;\n className?: string;\n}) => {\n const handleMarkAsRead = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (!isRead) {\n onMarkAsRead();\n }\n };\n\n const handleDelete = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onDelete();\n };\n\n const handleNavigate = (e: MouseEvent) => {\n e.stopPropagation();\n if (onNavigate) {\n onNavigate();\n }\n };\n\n return (\n <div\n className={cn(\n 'flex flex-col justify-center items-start p-4 gap-2 w-full bg-background border-b border-border-200',\n 'last:border-b-0',\n className\n )}\n >\n {/* Header with unread indicator and actions menu */}\n <div className=\"flex items-center gap-2 w-full\">\n {/* Unread indicator */}\n {!isRead && (\n <div className=\"w-[7px] h-[7px] bg-info-300 rounded-full flex-shrink-0\" />\n )}\n\n {/* Title */}\n <h3 className=\"font-bold text-sm leading-4 text-text-950 flex-grow\">\n {title}\n </h3>\n\n {/* Actions dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger\n className=\"flex-shrink-0 inline-flex items-center justify-center font-medium bg-transparent text-text-950 cursor-pointer hover:bg-info-50 w-6 h-6 rounded-lg\"\n aria-label=\"Menu de ações\"\n >\n <DotsThreeVertical size={24} />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-[160px]\">\n {!isRead && (\n <DropdownMenuItem\n onClick={handleMarkAsRead}\n className=\"text-text-950\"\n >\n Marcar como lida\n </DropdownMenuItem>\n )}\n <DropdownMenuItem onClick={handleDelete} className=\"text-error-600\">\n Deletar\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Message */}\n <p className=\"text-sm leading-[21px] text-text-800 w-full\">{message}</p>\n\n {/* Time and action button */}\n <div className=\"flex items-center justify-between w-full\">\n <span className=\"text-sm font-medium text-text-400\">{time}</span>\n\n {onNavigate && actionLabel && (\n <button\n type=\"button\"\n onClick={handleNavigate}\n className=\"text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer\"\n >\n {actionLabel}\n </button>\n )}\n </div>\n </div>\n );\n};\n\n/**\n * Notification list component for displaying grouped notifications\n */\nconst NotificationList = ({\n groupedNotifications = [],\n loading = false,\n error = null,\n onRetry,\n onMarkAsReadById,\n onDeleteById,\n onNavigateById,\n onGlobalNotificationClick,\n getActionLabel,\n renderEmpty,\n className,\n emptyStateImage,\n}: {\n groupedNotifications?: NotificationGroup[];\n loading?: boolean;\n error?: string | null;\n onRetry?: () => void;\n onMarkAsReadById?: (id: string) => void;\n onDeleteById?: (id: string) => void;\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n onGlobalNotificationClick?: (notification: Notification) => void;\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n renderEmpty?: () => ReactNode;\n className?: string;\n emptyStateImage?: string;\n}) => {\n // State for global notification modal when onGlobalNotificationClick is not provided\n const [globalNotificationModal, setGlobalNotificationModal] = useState<{\n isOpen: boolean;\n notification: Notification | null;\n }>({ isOpen: false, notification: null });\n\n // Default handler for global notifications when onGlobalNotificationClick is not provided\n const handleGlobalNotificationClick = (notification: Notification) => {\n if (onGlobalNotificationClick) {\n onGlobalNotificationClick(notification);\n } else {\n // Open modal as fallback\n setGlobalNotificationModal({\n isOpen: true,\n notification,\n });\n }\n };\n // Error state\n if (error) {\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 w-full\">\n <p className=\"text-sm text-error-600\">{error}</p>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"text-sm text-info-600 hover:text-info-700\"\n >\n Tentar novamente\n </button>\n )}\n </div>\n );\n }\n\n // Loading state\n if (loading) {\n return (\n <div className=\"flex flex-col gap-0 w-full\">\n {['skeleton-first', 'skeleton-second', 'skeleton-third'].map(\n (skeletonId) => (\n <SkeletonCard\n key={skeletonId}\n className=\"p-4 border-b border-border-200\"\n />\n )\n )}\n </div>\n );\n }\n\n // Empty state\n if (!groupedNotifications || groupedNotifications.length === 0) {\n return renderEmpty ? (\n <div className=\"w-full\">{renderEmpty()}</div>\n ) : (\n <NotificationEmpty />\n );\n }\n\n return (\n <div className={cn('flex flex-col gap-0 w-full', className)}>\n {groupedNotifications.map((group, idx) => (\n <div key={`${group.label}-${idx}`} className=\"flex flex-col\">\n {/* Group header */}\n <div className=\"flex items-end px-4 py-6 pb-4\">\n <h4 className=\"text-lg font-bold text-text-500 flex-grow\">\n {group.label}\n </h4>\n </div>\n\n {/* Notifications in group */}\n {group.notifications.map((notification) => {\n // Check if this is a global notification\n const isGlobalNotification =\n !notification.entityType &&\n !notification.entityId &&\n !notification.activity &&\n !notification.goal;\n\n // Determine navigation handler\n let navigationHandler: (() => void) | undefined;\n if (isGlobalNotification) {\n navigationHandler = () =>\n handleGlobalNotificationClick(notification);\n } else if (\n notification.entityType &&\n notification.entityId &&\n onNavigateById\n ) {\n navigationHandler = () =>\n onNavigateById(\n notification.entityType ?? undefined,\n notification.entityId ?? undefined\n );\n }\n\n // Determine action label\n let actionLabel: string | undefined;\n if (isGlobalNotification) {\n // For global notifications, call getActionLabel without parameters or with null\n actionLabel = getActionLabel?.(undefined);\n } else {\n // For entity-specific notifications, pass the entityType\n actionLabel = getActionLabel?.(\n notification.entityType ?? undefined\n );\n }\n\n return (\n <SingleNotificationCard\n key={notification.id}\n title={notification.title}\n message={notification.message}\n time={\n (notification as Partial<NotificationItem>).time ??\n formatTimeAgo(new Date(notification.createdAt))\n }\n isRead={notification.isRead}\n onMarkAsRead={() => onMarkAsReadById?.(notification.id)}\n onDelete={() => onDeleteById?.(notification.id)}\n onNavigate={navigationHandler}\n actionLabel={actionLabel}\n />\n );\n })}\n </div>\n ))}\n\n {/* Global notification modal for list mode */}\n <Modal\n isOpen={globalNotificationModal.isOpen}\n onClose={() =>\n setGlobalNotificationModal({ isOpen: false, notification: null })\n }\n title={globalNotificationModal.notification?.title || ''}\n description={globalNotificationModal.notification?.message || ''}\n variant=\"activity\"\n image={emptyStateImage || mockContentImage}\n actionLink={\n globalNotificationModal.notification?.actionLink || undefined\n }\n actionLabel=\"Ver mais\"\n size=\"lg\"\n />\n </div>\n );\n};\n\n// Internal props type for NotificationCenter (without mode)\ntype NotificationCenterProps = Omit<NotificationCenterMode, 'mode'>;\n\n/**\n * NotificationCenter component for modal/dropdown mode\n */\nconst NotificationCenter = ({\n isActive,\n onToggleActive,\n unreadCount = 0,\n groupedNotifications = [],\n loading = false,\n error = null,\n onRetry,\n onMarkAsReadById,\n onDeleteById,\n onNavigateById,\n getActionLabel,\n onFetchNotifications,\n onMarkAllAsRead,\n onOpenChange,\n emptyStateImage,\n emptyStateTitle,\n emptyStateDescription,\n className,\n}: NotificationCenterProps) => {\n const { isMobile } = useMobile();\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [globalNotificationModal, setGlobalNotificationModal] = useState<{\n isOpen: boolean;\n notification: Notification | null;\n }>({ isOpen: false, notification: null });\n\n // Handle mobile click\n const handleMobileClick = () => {\n setIsModalOpen(true);\n onFetchNotifications?.();\n };\n\n // Handle desktop click\n const handleDesktopClick = () => {\n onToggleActive?.();\n };\n\n // Handle dropdown open change\n const handleOpenChange = (open: boolean) => {\n const controlledByParent =\n typeof isActive === 'boolean' && typeof onToggleActive === 'function';\n\n // Always notify parent if they want the signal.\n onOpenChange?.(open);\n\n // If parent controls via toggle only (no onOpenChange), keep them in sync on close.\n if (controlledByParent && !onOpenChange && !open && isActive) {\n onToggleActive?.();\n }\n };\n\n // Fetch notifications when dropdown opens\n useEffect(() => {\n if (isActive) {\n onFetchNotifications?.();\n }\n }, [isActive, onFetchNotifications]);\n\n const renderEmptyState = () => (\n <NotificationEmpty\n emptyStateImage={emptyStateImage}\n emptyStateTitle={emptyStateTitle}\n emptyStateDescription={emptyStateDescription}\n />\n );\n\n if (isMobile) {\n return (\n <>\n <IconButton\n active={isModalOpen}\n onClick={handleMobileClick}\n icon={<Bell size={24} className=\"text-primary\" />}\n className={className}\n />\n <Modal\n isOpen={isModalOpen}\n onClose={() => setIsModalOpen(false)}\n title=\"Notificações\"\n size=\"md\"\n hideCloseButton={false}\n closeOnEscape={true}\n >\n <div className=\"flex flex-col h-full max-h-[80vh]\">\n <div className=\"px-0 pb-3 border-b border-border-200\">\n <NotificationHeader unreadCount={unreadCount} variant=\"modal\" />\n {unreadCount > 0 && onMarkAllAsRead && (\n <button\n type=\"button\"\n onClick={onMarkAllAsRead}\n className=\"text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2\"\n >\n Marcar todas como lidas\n </button>\n )}\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n <NotificationList\n groupedNotifications={groupedNotifications}\n loading={loading}\n error={error}\n onRetry={onRetry}\n onMarkAsReadById={onMarkAsReadById}\n onDeleteById={onDeleteById}\n onNavigateById={(entityType, entityId) => {\n setIsModalOpen(false);\n onNavigateById?.(entityType, entityId);\n }}\n onGlobalNotificationClick={(notification) => {\n setIsModalOpen(false);\n setGlobalNotificationModal({\n isOpen: true,\n notification,\n });\n }}\n getActionLabel={getActionLabel}\n renderEmpty={renderEmptyState}\n emptyStateImage={emptyStateImage}\n />\n </div>\n </div>\n </Modal>\n {/* Global Notification Modal (mobile) */}\n <Modal\n isOpen={globalNotificationModal.isOpen}\n onClose={() =>\n setGlobalNotificationModal({ isOpen: false, notification: null })\n }\n title={globalNotificationModal.notification?.title || ''}\n variant=\"activity\"\n description={globalNotificationModal.notification?.message}\n image={emptyStateImage || mockContentImage}\n actionLink={\n globalNotificationModal.notification?.actionLink || undefined\n }\n actionLabel=\"Ver mais\"\n size=\"lg\"\n />\n </>\n );\n }\n\n return (\n <>\n <DropdownMenu\n {...(typeof isActive === 'boolean'\n ? { open: isActive, onOpenChange: handleOpenChange }\n : { onOpenChange: handleOpenChange })}\n >\n <DropdownMenuTrigger className=\"text-primary cursor-pointer\">\n <IconButton\n active={isActive}\n onClick={handleDesktopClick}\n icon={\n <Bell\n size={24}\n className={isActive ? 'text-primary-950' : 'text-primary'}\n />\n }\n className={className}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"min-w-[320px] max-w-[400px] max-h-[500px] overflow-hidden\"\n side=\"bottom\"\n align=\"end\"\n >\n <div className=\"flex flex-col\">\n <div className=\"px-4 py-3 border-b border-border-200\">\n <NotificationHeader\n unreadCount={unreadCount}\n variant=\"dropdown\"\n />\n {unreadCount > 0 && onMarkAllAsRead && (\n <button\n type=\"button\"\n onClick={onMarkAllAsRead}\n className=\"text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2\"\n >\n Marcar todas como lidas\n </button>\n )}\n </div>\n <div className=\"max-h-[350px] overflow-y-auto\">\n <NotificationList\n groupedNotifications={groupedNotifications}\n loading={loading}\n error={error}\n onRetry={onRetry}\n onMarkAsReadById={onMarkAsReadById}\n onDeleteById={onDeleteById}\n onNavigateById={onNavigateById}\n onGlobalNotificationClick={(notification) => {\n setGlobalNotificationModal({\n isOpen: true,\n notification,\n });\n }}\n getActionLabel={getActionLabel}\n renderEmpty={renderEmptyState}\n emptyStateImage={emptyStateImage}\n />\n </div>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Global Notification Modal */}\n <Modal\n isOpen={globalNotificationModal.isOpen}\n onClose={() =>\n setGlobalNotificationModal({ isOpen: false, notification: null })\n }\n title={globalNotificationModal.notification?.title || ''}\n variant=\"activity\"\n description={globalNotificationModal.notification?.message}\n image={emptyStateImage || mockContentImage}\n actionLink={\n globalNotificationModal.notification?.actionLink || undefined\n }\n actionLabel=\"Ver mais\"\n size=\"lg\"\n />\n </>\n );\n};\n\n/**\n * NotificationCard component - can display single notification, list of notifications, or center mode\n *\n * @param props - The notification card properties\n * @returns JSX element representing the notification card, list, or center\n */\nconst NotificationCard = (props: NotificationCardProps) => {\n // Use mode discriminator to determine which component to render\n switch (props.mode) {\n case 'single':\n return (\n <SingleNotificationCard\n title={props.title}\n message={props.message}\n time={props.time}\n isRead={props.isRead}\n onMarkAsRead={props.onMarkAsRead}\n onDelete={props.onDelete}\n onNavigate={props.onNavigate}\n actionLabel={props.actionLabel}\n className={props.className}\n />\n );\n\n case 'list':\n return (\n <NotificationList\n groupedNotifications={\n props.groupedNotifications ??\n (props.notifications\n ? [\n {\n label: 'Notificações',\n notifications: props.notifications as Notification[],\n },\n ]\n : [])\n }\n loading={props.loading}\n error={props.error}\n onRetry={props.onRetry}\n onMarkAsReadById={props.onMarkAsReadById}\n onDeleteById={props.onDeleteById}\n onNavigateById={props.onNavigateById}\n onGlobalNotificationClick={props.onGlobalNotificationClick}\n getActionLabel={props.getActionLabel}\n renderEmpty={props.renderEmpty}\n className={props.className}\n emptyStateImage={props.emptyStateImage}\n />\n );\n\n case 'center':\n return <NotificationCenter {...props} />;\n\n default:\n // This should never happen with proper typing, but provides a fallback\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 w-full\">\n <p className=\"text-sm text-text-600\">\n Modo de notificação não reconhecido\n </p>\n </div>\n );\n }\n};\n\n/**\n * Legacy NotificationCard component for backward compatibility\n * Automatically detects mode based on provided props\n */\nexport const LegacyNotificationCard = (props: LegacyNotificationCardProps) => {\n // If variant is center, render NotificationCenter\n if (props.variant === 'center') {\n const centerProps: NotificationCenterMode = {\n mode: 'center',\n ...props,\n };\n return <NotificationCenter {...centerProps} />;\n }\n\n // If we have list-related props, render list mode\n if (\n props.groupedNotifications !== undefined ||\n props.notifications !== undefined ||\n props.loading ||\n props.error\n ) {\n return (\n <NotificationList\n groupedNotifications={\n props.groupedNotifications ??\n (props.notifications\n ? [\n {\n label: 'Notificações',\n notifications: props.notifications as Notification[],\n },\n ]\n : [])\n }\n loading={props.loading}\n error={props.error}\n onRetry={props.onRetry}\n onMarkAsReadById={props.onMarkAsReadById}\n onDeleteById={props.onDeleteById}\n onNavigateById={props.onNavigateById}\n onGlobalNotificationClick={props.onGlobalNotificationClick}\n getActionLabel={props.getActionLabel}\n renderEmpty={props.renderEmpty}\n className={props.className}\n emptyStateImage={props.emptyStateImage}\n />\n );\n }\n\n // If we have single notification props, render single card mode\n if (\n props.title !== undefined &&\n props.message !== undefined &&\n props.time !== undefined &&\n props.isRead !== undefined &&\n props.onMarkAsRead &&\n props.onDelete\n ) {\n const singleProps: SingleNotificationCardMode = {\n mode: 'single',\n title: props.title,\n message: props.message,\n time: props.time,\n isRead: props.isRead,\n onMarkAsRead: props.onMarkAsRead,\n onDelete: props.onDelete,\n onNavigate: props.onNavigate,\n actionLabel: props.actionLabel,\n className: props.className,\n emptyStateImage: props.emptyStateImage,\n emptyStateTitle: props.emptyStateTitle,\n emptyStateDescription: props.emptyStateDescription,\n };\n return (\n <SingleNotificationCard\n title={singleProps.title}\n message={singleProps.message}\n time={singleProps.time}\n isRead={singleProps.isRead}\n onMarkAsRead={singleProps.onMarkAsRead}\n onDelete={singleProps.onDelete}\n onNavigate={singleProps.onNavigate}\n actionLabel={singleProps.actionLabel}\n className={singleProps.className}\n />\n );\n }\n\n // Default empty state if no valid props provided\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 w-full\">\n <p className=\"text-sm text-text-600\">Nenhuma notificação configurada</p>\n </div>\n );\n};\n\nexport default NotificationCard;\nexport type { NotificationGroup };\n","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} from './activityFilters';\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 { CaretRight, SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useLayoutEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n RefObject,\n CSSProperties,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button from '../Button/Button';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\nimport Modal from '../Modal/Modal';\nimport { ThemeToggle } from '../ThemeToggle/ThemeToggle';\nimport type { ThemeMode } from '@/hooks/useTheme';\nimport { useTheme } from '../../hooks/useTheme';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n // Aqui tu checa o displayName do componente\n const displayName = (\n typedChild.type as unknown as { displayName: string }\n ).displayName;\n\n // Lista de componentes que devem receber o store\n const allowed = [\n 'DropdownMenuTrigger',\n 'DropdownContent',\n 'DropdownMenuContent',\n 'DropdownMenuSeparator',\n 'DropdownMenuItem',\n 'MenuLabel',\n 'ProfileMenuTrigger',\n 'ProfileMenuHeader',\n 'ProfileMenuFooter',\n 'ProfileToggleTheme',\n ];\n\n let newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {};\n\n if (allowed.includes(displayName)) {\n newProps.store = store;\n }\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({\n children,\n open: propOpen,\n onOpenChange,\n}: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const { open, setOpen: storeSetOpen } = useStore(store, (s) => s);\n\n const setOpen = (newOpen: boolean) => {\n storeSetOpen(newOpen);\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.indexOf(focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: Event) => {\n const target = event.target as Node;\n\n if (menuRef.current?.contains(target)) {\n return;\n }\n\n if (\n target instanceof Element &&\n target.closest('[data-dropdown-content=\"true\"]')\n ) {\n return;\n }\n\n setOpen(false);\n };\n\n useEffect(() => {\n if (open) {\n document.addEventListener('pointerdown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('pointerdown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [open]);\n\n useEffect(() => {\n onOpenChange?.(open);\n }, [open, onOpenChange]);\n\n useEffect(() => {\n if (propOpen !== undefined) {\n setOpen(propOpen);\n }\n }, [propOpen]);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, children, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n className={cn(\n 'appearance-none bg-transparent border-none p-0',\n className\n )}\n {...props}\n >\n {children}\n </button>\n );\n});\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'p-1',\n profile: 'p-6',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('text-sm w-full', inset ? 'pl-8' : '', className)}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst DropdownMenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n portal?: boolean;\n triggerRef?: RefObject<HTMLElement | null>;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n portal = false,\n triggerRef,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n const [portalPosition, setPortalPosition] = useState({ top: 0, left: 0 });\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n useLayoutEffect(() => {\n if (portal && open && triggerRef?.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n let top = rect.bottom + sideOffset;\n let left = rect.left;\n\n // Handle horizontal sides (left/right)\n if (side === 'left') {\n left = rect.left - sideOffset;\n top = rect.top;\n } else if (side === 'right') {\n left = rect.right + sideOffset;\n top = rect.top;\n } else {\n // Handle vertical sides (top/bottom)\n if (align === 'end') {\n left = rect.right;\n } else if (align === 'center') {\n left = rect.left + rect.width / 2;\n }\n\n if (side === 'top') {\n top = rect.top - sideOffset;\n }\n }\n\n setPortalPosition({ top, left });\n }\n }, [portal, open, triggerRef, align, side, sideOffset]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n if (portal) {\n return 'fixed';\n }\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const getPortalAlignStyle = () => {\n if (!portal) return {};\n\n const baseStyle: CSSProperties = {\n top: portalPosition.top,\n };\n\n if (align === 'end') {\n baseStyle.right = window.innerWidth - portalPosition.left;\n } else if (align === 'center') {\n baseStyle.left = portalPosition.left;\n baseStyle.transform = 'translateX(-50%)';\n } else {\n baseStyle.left = portalPosition.left;\n }\n\n return baseStyle;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n\n const content = (\n <div\n ref={portal ? contentRef : ref}\n role=\"menu\"\n data-dropdown-content=\"true\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n ...(portal\n ? getPortalAlignStyle()\n : {\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }),\n }}\n {...props}\n >\n {children}\n </div>\n );\n\n if (portal && typeof document !== 'undefined') {\n return createPortal(content, document.body);\n }\n\n return content;\n }\n);\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n preventClose?: boolean;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n preventClose = false,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n if (e.type === 'click') {\n onClick?.(e as MouseEvent<HTMLDivElement>);\n } else if (e.type === 'keydown') {\n // For keyboard events, call onClick if Enter or Space was pressed\n if (\n (e as KeyboardEvent<HTMLDivElement>).key === 'Enter' ||\n (e as KeyboardEvent<HTMLDivElement>).key === ' '\n ) {\n onClick?.(e as unknown as MouseEvent<HTMLDivElement>);\n }\n // honor any user-provided key handler\n props.onKeyDown?.(e as KeyboardEvent<HTMLDivElement>);\n }\n if (!preventClose) {\n setOpen(false);\n }\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\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 `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n handleClick(e);\n }\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <div className=\"w-full\">{children}</div>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('my-1 h-px bg-border-200', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={cn(\n 'rounded-lg size-10 bg-primary-50 flex items-center justify-center cursor-pointer',\n className\n )}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-primary-100 flex items-center justify-center\">\n <User className=\"text-primary-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n photoUrl?: string | null;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, photoUrl, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={cn(\n 'flex flex-row gap-4 items-center min-w-[280px]',\n className\n )}\n {...props}\n >\n <span className=\"w-16 h-16 bg-primary-100 rounded-full flex items-center justify-center overflow-hidden flex-shrink-0\">\n {photoUrl ? (\n <img\n src={photoUrl}\n alt=\"Foto de perfil\"\n className=\"w-full h-full object-cover\"\n />\n ) : (\n <User size={34} className=\"text-primary-800\" />\n )}\n </span>\n <div className=\"flex flex-col min-w-0\">\n <Text\n size=\"xl\"\n weight=\"bold\"\n color=\"text-text-950\"\n className=\"truncate\"\n >\n {name}\n </Text>\n <Text size=\"md\" color=\"text-text-600\" className=\"truncate\">\n {email}\n </Text>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuInfo = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n schoolName: string;\n classYearName: string;\n schoolYearName: string;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n schoolName,\n classYearName,\n schoolYearName,\n store: _store,\n ...props\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuInfo\"\n className={cn('flex flex-row gap-4 items-center', className)}\n {...props}\n >\n <span className=\"w-16 h-16\" />\n <div className=\"flex flex-col \">\n <Text size=\"md\" color=\"text-text-600\">\n {schoolName}\n </Text>\n\n <span className=\"flex flex-row items-center gap-2\">\n <Text size=\"md\" color=\"text-text-600\">\n {classYearName}\n </Text>\n <p className=\"text-text-600 text-xs align-middle\">●</p>\n <Text size=\"md\" color=\"text-text-600\">\n {schoolYearName}\n </Text>\n </span>\n </div>\n </div>\n );\n }\n);\nProfileMenuInfo.displayName = 'ProfileMenuInfo';\n\nconst ProfileToggleTheme = ({\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }) => {\n const { themeMode, setTheme } = useTheme();\n const [modalThemeToggle, setModalThemeToggle] = useState(false);\n const [selectedTheme, setSelectedTheme] = useState<ThemeMode>(themeMode);\n\n const internalStoreRef = useRef<DropdownStoreApi | null>(null);\n internalStoreRef.current ??= createDropdownStore();\n const store = externalStore ?? internalStoreRef.current;\n const setOpen = useStore(store, (s) => s.setOpen);\n\n const handleClick = (e: MouseEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setModalThemeToggle(true);\n };\n\n const handleSave = () => {\n setTheme(selectedTheme);\n setModalThemeToggle(false);\n setOpen(false); // Close dropdown after saving\n };\n\n const handleCancel = () => {\n setSelectedTheme(themeMode); // Reset to current theme\n setModalThemeToggle(false);\n setOpen(false); // Close dropdown after canceling\n };\n\n return (\n <>\n <DropdownMenuItem\n variant=\"profile\"\n preventClose={true}\n store={store}\n iconLeft={\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12.5 2.75C15.085 2.75276 17.5637 3.78054 19.3916 5.6084C21.2195 7.43628 22.2473 9.915 22.25 12.5C22.25 14.4284 21.6778 16.3136 20.6064 17.917C19.5352 19.5201 18.0128 20.7699 16.2314 21.5078C14.4499 22.2458 12.489 22.4387 10.5977 22.0625C8.70642 21.6863 6.96899 20.758 5.60547 19.3945C4.24197 18.031 3.31374 16.2936 2.9375 14.4023C2.56129 12.511 2.75423 10.5501 3.49219 8.76855C4.23012 6.98718 5.47982 5.46483 7.08301 4.39355C8.68639 3.32221 10.5716 2.75 12.5 2.75ZM11.75 4.28516C9.70145 4.47452 7.7973 5.42115 6.41016 6.94043C5.02299 8.4599 4.25247 10.4426 4.25 12.5C4.25247 14.5574 5.02299 16.5401 6.41016 18.0596C7.7973 19.5789 9.70145 20.5255 11.75 20.7148V4.28516Z\"\n fill=\"currentColor\"\n />\n </svg>\n }\n iconRight={<CaretRight />}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n setModalThemeToggle(true);\n }\n }}\n {...props}\n >\n <Text size=\"md\" color=\"text-text-700\">\n Aparência\n </Text>\n </DropdownMenuItem>\n\n <Modal\n isOpen={modalThemeToggle}\n onClose={handleCancel}\n title=\"Aparência\"\n size=\"md\"\n footer={\n <div className=\"flex gap-3\">\n <Button variant=\"outline\" onClick={handleCancel}>\n Cancelar\n </Button>\n <Button variant=\"solid\" onClick={handleSave}>\n Salvar\n </Button>\n </div>\n }\n >\n <div className=\"flex flex-col\">\n <p className=\"text-sm text-text-500\">Escolha o tema:</p>\n <ThemeToggle variant=\"with-save\" onToggle={setSelectedTheme} />\n </div>\n </Modal>\n </>\n );\n};\nProfileToggleTheme.displayName = 'ProfileToggleTheme';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div ref={ref} className={cn('flex flex-col p-2', className)} {...props}>\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={cn('w-full', className)}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut className=\"text-inherit\" />\n </span>\n <Text color=\"inherit\">Sair</Text>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n ProfileToggleTheme,\n ProfileMenuInfo,\n};\n","import { ButtonHTMLAttributes, ReactNode } 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 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 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 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 */\n variant?: 'solid' | 'outline' | 'link';\n /** Action type of the button */\n action?: 'primary' | '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, 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 = ({\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}: ButtonProps) => {\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 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 && <span className=\"ml-2 flex items-center\">{iconRight}</span>}\n </button>\n );\n};\n\nexport default Button;\n","import { ComponentPropsWithoutRef, 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<ComponentPropsWithoutRef<T>, keyof BaseTextProps>;\n\n/**\n * Text component for Analytica Ensino platforms\n *\n * A flexible polymorphic text component with multiple sizes, weights, and colors.\n * Automatically adapts to dark and light themes with full type safety.\n *\n * @param children - The content to display\n * @param size - The text size variant (2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl)\n * @param weight - The font weight variant (hairline, light, normal, medium, semibold, bold, extrabold, black)\n * @param color - The color variant - adapts to theme\n * @param as - The HTML tag to render - determines allowed attributes via TypeScript\n * @param className - Additional CSS classes\n * @param props - HTML attributes valid for the chosen tag only\n * @returns A styled text element with type-safe attributes\n *\n * @example\n * ```tsx\n * <Text size=\"lg\" weight=\"bold\" color=\"text-info-800\">\n * This is a large, bold text\n * </Text>\n *\n * <Text as=\"a\" href=\"/link\" target=\"_blank\">\n * Link with type-safe anchor attributes\n * </Text>\n *\n * <Text as=\"button\" onClick={handleClick} disabled>\n * Button with type-safe button attributes\n * </Text>\n * ```\n */\nconst Text = <T extends ElementType = 'p'>({\n children,\n size = 'md',\n weight = 'normal',\n color = 'text-text-950',\n as,\n className = '',\n ...props\n}: TextProps<T>) => {\n let sizeClasses = '';\n let weightClasses = '';\n\n // Text size classes mapping\n const sizeClassMap = {\n '2xs': 'text-2xs',\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-md',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n '5xl': 'text-5xl',\n '6xl': 'text-6xl',\n } as const;\n\n sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;\n\n // Font weight classes mapping\n const weightClassMap = {\n hairline: 'font-hairline',\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n black: 'font-black',\n } as const;\n\n weightClasses = weightClassMap[weight] ?? weightClassMap.normal;\n\n const baseClasses = 'font-primary';\n const Component = as ?? ('p' as ElementType);\n\n return (\n <Component\n className={cn(baseClasses, sizeClasses, weightClasses, color, className)}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n","import { ReactNode, useEffect, useId } from 'react';\nimport { X } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\nimport Button from '../Button/Button';\nimport {\n isYouTubeUrl,\n getYouTubeVideoId,\n getYouTubeEmbedUrl,\n} from './utils/videoUtils';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n xs: 'max-w-[360px]',\n sm: 'max-w-[420px]',\n md: 'max-w-[510px]',\n lg: 'max-w-[640px]',\n xl: 'max-w-[970px]',\n} as const;\n\n/**\n * Modal component props interface\n */\ntype ModalProps = {\n contentClassName?: string;\n /** Whether the modal is open */\n isOpen: boolean;\n /** Function to close the modal */\n onClose: () => void;\n /** Modal title */\n title: string;\n /** Modal description/content */\n children?: ReactNode;\n /** Size of the modal */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Additional CSS classes for the modal content */\n className?: string;\n /** Whether pressing Escape should close the modal */\n closeOnEscape?: boolean;\n /** Footer content (typically buttons) */\n footer?: ReactNode;\n /** Hide the close button */\n hideCloseButton?: boolean;\n /** Modal variant */\n variant?: 'default' | 'activity';\n /** Description for activity variant */\n description?: string;\n /** Image URL for activity variant */\n image?: string;\n /** Alt text for activity image (leave empty for decorative images) */\n imageAlt?: string;\n /** Action link for activity variant */\n actionLink?: string;\n /** Action button label for activity variant */\n actionLabel?: string;\n};\n\n/**\n * Modal component for Analytica Ensino platforms\n *\n * A flexible modal component with multiple size variants and customizable behavior.\n *\n * @param isOpen - Whether the modal is currently open\n * @param onClose - Callback function called when the modal should be closed\n * @param title - The title displayed at the top of the modal\n * @param children - The main content of the modal\n * @param size - The size variant (xs, sm, md, lg, xl)\n * @param className - Additional CSS classes for the modal content\n * @param closeOnEscape - Whether pressing Escape closes the modal (default: true)\n * @param footer - Footer content, typically action buttons\n * @param hideCloseButton - Whether to hide the X close button (default: false)\n * @returns A modal overlay with content\n *\n * @example\n * ```tsx\n * <Modal\n * isOpen={isModalOpen}\n * onClose={() => setIsModalOpen(false)}\n * title=\"Invite your team\"\n * size=\"md\"\n * footer={\n * <div className=\"flex gap-3\">\n * <Button variant=\"outline\" onClick={() => setIsModalOpen(false)}>Cancel</Button>\n * <Button variant=\"solid\" onClick={handleExplore}>Explore</Button>\n * </div>\n * }\n * >\n * Elevate user interactions with our versatile modals.\n * </Modal>\n * ```\n */\nconst Modal = ({\n isOpen,\n onClose,\n title,\n children,\n size = 'md',\n className = '',\n closeOnEscape = true,\n footer,\n hideCloseButton = false,\n variant = 'default',\n description,\n image,\n imageAlt,\n actionLink,\n actionLabel,\n contentClassName = '',\n}: ModalProps) => {\n const titleId = useId();\n\n // Handle escape key\n useEffect(() => {\n if (!isOpen || !closeOnEscape) return;\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, closeOnEscape, onClose]);\n\n // Handle body scroll lock and scrollbar shift fix\n useEffect(() => {\n if (!isOpen) return;\n\n // Calculate scrollbar width before hiding overflow\n const scrollbarWidth =\n window.innerWidth - document.documentElement.clientWidth;\n\n // Save original styles\n const originalOverflow = document.body.style.overflow;\n const originalPaddingRight = document.body.style.paddingRight;\n\n // Apply scroll lock\n document.body.style.overflow = 'hidden';\n\n // Fix scrollbar shift: add padding to compensate for lost scrollbar\n if (scrollbarWidth > 0) {\n document.body.style.paddingRight = `${scrollbarWidth}px`;\n\n // Create overlay to cover the padding area with backdrop color\n const overlay = document.createElement('div');\n overlay.id = 'modal-scrollbar-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n right: 0;\n width: ${scrollbarWidth}px;\n height: 100vh;\n background-color: rgb(0 0 0 / 0.6);\n z-index: 40;\n pointer-events: none;\n `;\n document.body.appendChild(overlay);\n }\n\n return () => {\n // Restore original styles\n document.body.style.overflow = originalOverflow;\n document.body.style.paddingRight = originalPaddingRight;\n\n // Remove overlay\n const overlay = document.getElementById('modal-scrollbar-overlay');\n if (overlay) {\n overlay.remove();\n }\n };\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const sizeClasses = SIZE_CLASSES[size];\n const baseClasses =\n 'bg-secondary-50 rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4';\n // Reset dialog default styles to prevent positioning issues\n const dialogResetClasses =\n 'p-0 m-0 border-none outline-none max-h-none static';\n const modalClasses = cn(\n baseClasses,\n sizeClasses,\n dialogResetClasses,\n className\n );\n\n // Normalize URLs missing protocol\n const normalizeUrl = (href: string) =>\n /^https?:\\/\\//i.test(href) ? href : `https://${href}`;\n\n // Handle action link click\n const handleActionClick = () => {\n if (actionLink) {\n window.open(normalizeUrl(actionLink), '_blank', 'noopener,noreferrer');\n }\n };\n\n // Activity variant rendering\n if (variant === 'activity') {\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs border-none p-0 m-0 w-full cursor-default\">\n <dialog\n className={modalClasses}\n aria-labelledby={titleId}\n aria-modal=\"true\"\n open\n >\n {/* Header simples com X */}\n <div className=\"flex justify-end p-6 pb-0\">\n {!hideCloseButton && (\n <button\n onClick={onClose}\n className=\"p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2\"\n aria-label=\"Fechar modal\"\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Conteúdo centralizado */}\n <div className=\"flex flex-col items-center px-6 pb-6 gap-5\">\n {/* Imagem ilustrativa */}\n {image && (\n <div className=\"flex justify-center\">\n <img\n src={image}\n alt={imageAlt ?? ''}\n className=\"w-[122px] h-[122px] object-contain\"\n />\n </div>\n )}\n\n {/* Título */}\n <h2\n id={titleId}\n className=\"text-lg font-semibold text-text-950 text-center\"\n >\n {title}\n </h2>\n\n {/* Descrição */}\n {description && (\n <p className=\"text-sm font-normal text-text-400 text-center max-w-md leading-[21px]\">\n {description}\n </p>\n )}\n\n {/* Ação: Botão ou Vídeo Embedado */}\n {actionLink && (\n <div className=\"w-full\">\n {(() => {\n const normalized = normalizeUrl(actionLink);\n const isYT = isYouTubeUrl(normalized);\n if (!isYT) return null;\n const id = getYouTubeVideoId(normalized);\n if (!id) {\n return (\n <Button\n variant=\"solid\"\n action=\"primary\"\n size=\"large\"\n className=\"w-full\"\n onClick={handleActionClick}\n >\n {actionLabel || 'Iniciar Atividade'}\n </Button>\n );\n }\n return (\n <iframe\n src={getYouTubeEmbedUrl(id)}\n className=\"w-full aspect-video rounded-lg\"\n allowFullScreen\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n title=\"Vídeo YouTube\"\n />\n );\n })()}\n {!isYouTubeUrl(normalizeUrl(actionLink)) && (\n <Button\n variant=\"solid\"\n action=\"primary\"\n size=\"large\"\n className=\"w-full\"\n onClick={handleActionClick}\n >\n {actionLabel || 'Iniciar Atividade'}\n </Button>\n )}\n </div>\n )}\n </div>\n </dialog>\n </div>\n );\n }\n\n // Default variant rendering\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs border-none p-0 m-0 w-full cursor-default\">\n <dialog\n className={modalClasses}\n aria-labelledby={titleId}\n aria-modal=\"true\"\n open\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-6\">\n <h2 id={titleId} className=\"text-lg font-semibold text-text-950\">\n {title}\n </h2>\n {!hideCloseButton && (\n <button\n onClick={onClose}\n className=\"p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2\"\n aria-label=\"Fechar modal\"\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Content */}\n {children && (\n <div className={cn('px-6 pb-6', contentClassName)}>\n <div className=\"text-text-500 font-normal text-sm leading-6\">\n {children}\n </div>\n </div>\n )}\n\n {/* Footer */}\n {footer && (\n <div className=\"flex justify-end gap-3 px-6 pb-6\">{footer}</div>\n )}\n </dialog>\n </div>\n );\n};\n\nexport default Modal;\n","/**\n * Video utilities for Modal component\n *\n * Utilities to handle YouTube video embedding and URL detection\n */\n\n/**\n * Check if a given URL is a YouTube URL\n *\n * @param url - The URL to check\n * @returns true if the URL is from YouTube, false otherwise\n */\nexport const isYouTubeUrl = (url: string): boolean => {\n const youtubeRegex =\n /^(https?:\\/\\/)?((www|m|music)\\.)?(youtube\\.com|youtu\\.be|youtube-nocookie\\.com)\\/.+/i;\n return youtubeRegex.test(url);\n};\n\n/**\n * Validate if hostname is a legitimate YouTube host\n *\n * @param host - The hostname to validate\n * @returns The type of YouTube host or null if invalid\n */\nconst isValidYouTubeHost = (\n host: string\n): 'youtu.be' | 'youtube' | 'nocookie' | null => {\n if (host === 'youtu.be') return 'youtu.be';\n\n const isValidYouTubeCom =\n host === 'youtube.com' ||\n (host.endsWith('.youtube.com') &&\n /^(www|m|music)\\.youtube\\.com$/.test(host));\n\n if (isValidYouTubeCom) return 'youtube';\n\n const isValidNoCookie =\n host === 'youtube-nocookie.com' ||\n (host.endsWith('.youtube-nocookie.com') &&\n /^(www|m|music)\\.youtube-nocookie\\.com$/.test(host));\n\n if (isValidNoCookie) return 'nocookie';\n\n return null;\n};\n\n/**\n * Extract video ID from youtu.be path\n *\n * @param pathname - The URL pathname\n * @returns The video ID or null\n */\nconst extractYoutuBeId = (pathname: string): string | null => {\n const firstSeg = pathname.split('/').filter(Boolean)[0];\n return firstSeg || null;\n};\n\n/**\n * Extract video ID from YouTube or nocookie domains\n *\n * @param pathname - The URL pathname\n * @param searchParams - The URL search parameters\n * @returns The video ID or null\n */\nconst extractYouTubeId = (\n pathname: string,\n searchParams: URLSearchParams\n): string | null => {\n const parts = pathname.split('/').filter(Boolean);\n const [first, second] = parts;\n\n if (first === 'embed' && second) return second;\n if (first === 'shorts' && second) return second;\n if (first === 'live' && second) return second;\n\n const v = searchParams.get('v');\n if (v) return v;\n\n return null;\n};\n\n/**\n * Extract YouTube video ID from URL\n *\n * @param url - The YouTube URL\n * @returns The video ID if found, null otherwise\n */\nexport const getYouTubeVideoId = (url: string): string | null => {\n try {\n const u = new URL(url);\n const hostType = isValidYouTubeHost(u.hostname.toLowerCase());\n\n if (!hostType) return null;\n\n if (hostType === 'youtu.be') {\n return extractYoutuBeId(u.pathname);\n }\n\n return extractYouTubeId(u.pathname, u.searchParams);\n } catch {\n return null;\n }\n};\n\n/**\n * Generate YouTube embed URL for iframe\n *\n * @param videoId - The YouTube video ID\n * @returns The embed URL for the video\n */\nexport const getYouTubeEmbedUrl = (videoId: string): string => {\n return `https://www.youtube-nocookie.com/embed/${videoId}?autoplay=0&rel=0&modestbranding=1`;\n};\n","import { Moon, Sun } from 'phosphor-react';\nimport { useState, useEffect } from 'react';\nimport SelectionButton from '../SelectionButton/SelectionButton';\nimport type { ThemeMode } from '@/hooks/useTheme';\nimport { useTheme } from '../../hooks/useTheme';\n\ninterface ThemeToggleProps {\n variant?: 'default' | 'with-save';\n onToggle?: (theme: ThemeMode) => void;\n}\n\nexport const ThemeToggle = ({\n variant = 'default',\n onToggle,\n}: ThemeToggleProps) => {\n const { themeMode, setTheme } = useTheme();\n const [tempTheme, setTempTheme] = useState<ThemeMode>(themeMode);\n\n // Update temp theme when themeMode changes externally\n useEffect(() => {\n setTempTheme(themeMode);\n }, [themeMode]);\n\n const problemTypes = [\n {\n id: 'light' as ThemeMode,\n title: 'Claro',\n icon: <Sun size={24} />,\n },\n {\n id: 'dark' as ThemeMode,\n title: 'Escuro',\n icon: <Moon size={24} />,\n },\n {\n id: 'system' as ThemeMode,\n title: 'Sistema',\n icon: (\n <svg\n width=\"25\"\n height=\"25\"\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12.5 2.75C15.085 2.75276 17.5637 3.78054 19.3916 5.6084C21.2195 7.43628 22.2473 9.915 22.25 12.5C22.25 14.4284 21.6778 16.3136 20.6064 17.917C19.5352 19.5201 18.0128 20.7699 16.2314 21.5078C14.4499 22.2458 12.489 22.4387 10.5977 22.0625C8.70642 21.6863 6.96899 20.758 5.60547 19.3945C4.24197 18.031 3.31374 16.2936 2.9375 14.4023C2.56129 12.511 2.75423 10.5501 3.49219 8.76855C4.23012 6.98718 5.47982 5.46483 7.08301 4.39355C8.68639 3.32221 10.5716 2.75 12.5 2.75ZM11.75 4.28516C9.70145 4.47452 7.7973 5.42115 6.41016 6.94043C5.02299 8.4599 4.25247 10.4426 4.25 12.5C4.25247 14.5574 5.02299 16.5401 6.41016 18.0596C7.7973 19.5789 9.70145 20.5255 11.75 20.7148V4.28516Z\"\n fill=\"#525252\"\n />\n </svg>\n ),\n },\n ];\n\n const handleThemeSelect = (selectedTheme: ThemeMode) => {\n if (variant === 'with-save') {\n setTempTheme(selectedTheme);\n } else {\n setTheme(selectedTheme);\n }\n\n if (onToggle) {\n onToggle(selectedTheme);\n }\n };\n\n const currentTheme = variant === 'with-save' ? tempTheme : themeMode;\n\n return (\n <div className=\"flex flex-row gap-2 sm:gap-4 py-2\">\n {problemTypes.map((type) => (\n <SelectionButton\n key={type.id}\n icon={type.icon}\n label={type.title}\n selected={currentTheme === type.id}\n onClick={() => handleThemeSelect(type.id)}\n className=\"w-full p-2 sm:p-4\"\n />\n ))}\n </div>\n );\n};\n","import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * SelectionButton component props interface\n */\ntype SelectionButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Texto/label a ser exibido ao lado do ícone */\n label: string;\n /** Estado de seleção do botão */\n selected?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * SelectionButton component for Analytica Ensino platforms\n *\n * Um botão com ícone e texto para ações e navegação com estado de seleção.\n * Ideal para filtros, tags, categorias, seleção de tipos, etc.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param label - O texto/label a ser exibido\n * @param selected - Estado de seleção do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button estilizado\n *\n * @example\n * ```tsx\n * <SelectionButton\n * icon={<TagIcon />}\n * label=\"Categoria\"\n * selected={false}\n * onClick={() => handleSelection()}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para foco programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * const handleFocus = () => {\n * buttonRef.current?.focus();\n * };\n *\n * <SelectionButton\n * ref={buttonRef}\n * icon={<TagIcon />}\n * label=\"Categoria\"\n * selected={isSelected}\n * onClick={() => setSelected(!isSelected)}\n * />\n * ```\n */\nconst SelectionButton = forwardRef<HTMLButtonElement, SelectionButtonProps>(\n (\n { icon, label, selected = false, className = '', disabled, ...props },\n ref\n ) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'inline-flex',\n 'items-center',\n 'justify-start',\n 'gap-2',\n 'p-4',\n 'rounded-xl',\n 'cursor-pointer',\n 'border',\n 'border-border-50',\n 'bg-background',\n 'text-sm',\n 'text-text-700',\n 'font-bold',\n 'shadow-soft-shadow-1',\n 'hover:bg-background-100',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-indicator-info',\n 'focus-visible:ring-offset-0',\n 'focus-visible:shadow-none',\n 'active:ring-2',\n 'active:ring-primary-950',\n 'active:ring-offset-0',\n 'active:shadow-none',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n ];\n\n const stateClasses = selected\n ? ['ring-primary-950', 'ring-2', 'ring-offset-0', 'shadow-none']\n : [];\n\n const allClasses = [...baseClasses, ...stateClasses].join(' ');\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(allClasses, className)}\n disabled={disabled}\n aria-pressed={selected}\n {...props}\n >\n <span className=\"flex items-center justify-center w-6 h-6\">{icon}</span>\n <span>{label}</span>\n </button>\n );\n }\n);\n\nSelectionButton.displayName = 'SelectionButton';\n\nexport default SelectionButton;\n","import { useEffect } from 'react';\nimport { useThemeStore, ThemeMode } from '../store/themeStore';\n\nexport type { ThemeMode };\n\n/**\n * Hook para gerenciar temas com suporte a alternância manual e detecção automática do sistema\n * Este hook permite alternar entre temas light, dark e automático baseado nas preferências do sistema\n * Utiliza Zustand para persistir o estado entre múltiplos arquivos e sessões\n */\nexport const useTheme = () => {\n const {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n initializeTheme,\n handleSystemThemeChange,\n } = useThemeStore();\n\n useEffect(() => {\n // Initialize theme on first render\n initializeTheme();\n\n // Listener para mudanças nas preferências do sistema (apenas quando mode é 'system')\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n\n mediaQuery.addEventListener('change', handleSystemThemeChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleSystemThemeChange);\n };\n }, [initializeTheme, handleSystemThemeChange]);\n\n return {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n };\n};\n","import { create } from 'zustand';\nimport { devtools, persist } from 'zustand/middleware';\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\n\n/**\n * Theme store state interface\n */\nexport interface ThemeState {\n /**\n * Current theme mode\n */\n themeMode: ThemeMode;\n /**\n * Whether the current theme is dark\n */\n isDark: boolean;\n}\n\n/**\n * Theme store actions interface\n */\nexport interface ThemeActions {\n /**\n * Apply theme based on the mode selected\n */\n applyTheme: (mode: ThemeMode) => void;\n /**\n * Toggle between themes\n */\n toggleTheme: () => void;\n /**\n * Set a specific theme mode\n */\n setTheme: (mode: ThemeMode) => void;\n /**\n * Initialize theme on app start\n */\n initializeTheme: () => void;\n /**\n * Handle system theme change\n */\n handleSystemThemeChange: () => void;\n}\n\nexport type ThemeStore = ThemeState & ThemeActions;\n\n/**\n * Apply theme to DOM based on mode\n */\nconst applyThemeToDOM = (mode: ThemeMode): boolean => {\n const htmlElement = document.documentElement;\n const originalTheme = htmlElement.getAttribute('data-original-theme');\n\n if (mode === 'dark') {\n htmlElement.setAttribute('data-theme', 'dark');\n return true;\n } else if (mode === 'light') {\n if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n }\n return false;\n } else if (mode === 'system') {\n const isSystemDark = window.matchMedia(\n '(prefers-color-scheme: dark)'\n ).matches;\n if (isSystemDark) {\n htmlElement.setAttribute('data-theme', 'dark');\n return true;\n } else if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n return false;\n }\n }\n return false;\n};\n\n/**\n * Save original theme from white label\n */\nconst saveOriginalTheme = () => {\n const htmlElement = document.documentElement;\n const currentTheme = htmlElement.getAttribute('data-theme');\n if (currentTheme && !htmlElement.getAttribute('data-original-theme')) {\n htmlElement.setAttribute('data-original-theme', currentTheme);\n }\n};\n\n/**\n * Theme store using Zustand with persistence\n */\nexport const useThemeStore = create<ThemeStore>()(\n devtools(\n persist(\n (set, get) => ({\n // Initial state\n themeMode: 'system',\n isDark: false,\n\n // Actions\n applyTheme: (mode: ThemeMode) => {\n const isDark = applyThemeToDOM(mode);\n set({ isDark });\n },\n\n toggleTheme: () => {\n const { themeMode, applyTheme } = get();\n let newMode: ThemeMode;\n\n if (themeMode === 'light') {\n newMode = 'dark';\n } else if (themeMode === 'dark') {\n newMode = 'light';\n } else {\n // Se estiver em 'system', vai para 'dark'\n newMode = 'dark';\n }\n\n set({ themeMode: newMode });\n applyTheme(newMode);\n },\n\n setTheme: (mode: ThemeMode) => {\n const { applyTheme } = get();\n set({ themeMode: mode });\n applyTheme(mode);\n },\n\n initializeTheme: () => {\n const { themeMode, applyTheme } = get();\n\n // Save original theme from white label\n saveOriginalTheme();\n\n // Apply the current theme mode\n applyTheme(themeMode);\n },\n\n handleSystemThemeChange: () => {\n const { themeMode, applyTheme } = get();\n // Only respond to system changes when in system mode\n if (themeMode === 'system') {\n applyTheme('system');\n }\n },\n }),\n {\n name: 'theme-store', // Nome da chave no localStorage\n partialize: (state) => ({\n themeMode: state.themeMode,\n }), // Só persiste o themeMode, não o isDark\n }\n ),\n {\n name: 'theme-store',\n }\n )\n);\n","import { forwardRef, HTMLAttributes, CSSProperties } from 'react';\nimport { cn } from '../../utils/utils';\n\ninterface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n variant?: 'text' | 'circular' | 'rectangular' | 'rounded';\n width?: string | number;\n height?: string | number;\n animation?: 'pulse' | 'none';\n lines?: number;\n spacing?: 'none' | 'small' | 'medium' | 'large';\n}\n\nconst SKELETON_ANIMATION_CLASSES = {\n pulse: 'animate-pulse',\n none: '',\n};\n\nconst SKELETON_VARIANT_CLASSES = {\n text: 'h-4 bg-background-200 rounded',\n circular: 'bg-background-200 rounded-full',\n rectangular: 'bg-background-200',\n rounded: 'bg-background-200 rounded-lg',\n};\n\nconst SPACING_CLASSES = {\n none: '',\n small: 'space-y-1',\n medium: 'space-y-2',\n large: 'space-y-3',\n};\n\nconst Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n (\n {\n variant = 'text',\n width,\n height,\n animation = 'pulse',\n lines = 1,\n spacing = 'none',\n className = '',\n children,\n ...props\n },\n ref\n ) => {\n const animationClass = SKELETON_ANIMATION_CLASSES[animation];\n const variantClass = SKELETON_VARIANT_CLASSES[variant];\n const spacingClass = SPACING_CLASSES[spacing];\n\n const style: CSSProperties = {\n width: typeof width === 'number' ? `${width}px` : width,\n height: typeof height === 'number' ? `${height}px` : height,\n };\n\n // Se for múltiplas linhas de texto\n if (variant === 'text' && lines > 1) {\n return (\n <div\n ref={ref}\n className={cn('flex flex-col', spacingClass, className)}\n {...props}\n >\n {Array.from({ length: lines }, (_, index) => (\n <div\n key={index}\n className={cn(variantClass, animationClass)}\n style={index === lines - 1 ? { width: '60%' } : undefined}\n />\n ))}\n </div>\n );\n }\n\n // Se for um único elemento\n return (\n <div\n ref={ref}\n className={cn(variantClass, animationClass, className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\n// Componentes específicos para casos comuns\nconst SkeletonText = forwardRef<HTMLDivElement, Omit<SkeletonProps, 'variant'>>(\n (props, ref) => <Skeleton ref={ref} variant=\"text\" {...props} />\n);\n\nconst SkeletonCircle = forwardRef<\n HTMLDivElement,\n Omit<SkeletonProps, 'variant'>\n>((props, ref) => <Skeleton ref={ref} variant=\"circular\" {...props} />);\n\nconst SkeletonRectangle = forwardRef<\n HTMLDivElement,\n Omit<SkeletonProps, 'variant'>\n>((props, ref) => <Skeleton ref={ref} variant=\"rectangular\" {...props} />);\n\nconst SkeletonRounded = forwardRef<\n HTMLDivElement,\n Omit<SkeletonProps, 'variant'>\n>((props, ref) => <Skeleton ref={ref} variant=\"rounded\" {...props} />);\n\n// Componente para card skeleton\ninterface SkeletonCardProps extends HTMLAttributes<HTMLDivElement> {\n showAvatar?: boolean;\n showTitle?: boolean;\n showDescription?: boolean;\n showActions?: boolean;\n lines?: number;\n}\n\nconst SkeletonCard = forwardRef<HTMLDivElement, SkeletonCardProps>(\n (\n {\n showAvatar = true,\n showTitle = true,\n showDescription = true,\n showActions = true,\n lines = 2,\n className = '',\n ...props\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'w-full p-4 bg-background border border-border-200 rounded-lg',\n className\n )}\n {...props}\n >\n <div className=\"flex items-start space-x-3\">\n {showAvatar && <SkeletonCircle width={40} height={40} />}\n\n <div className=\"flex-1 space-y-2\">\n {showTitle && <SkeletonText width=\"60%\" height={20} />}\n\n {showDescription && <SkeletonText lines={lines} spacing=\"small\" />}\n </div>\n </div>\n\n {showActions && (\n <div className=\"flex justify-end space-x-2 mt-4\">\n <SkeletonRectangle width={80} height={32} />\n <SkeletonRectangle width={80} height={32} />\n </div>\n )}\n </div>\n );\n }\n);\n\n// Componente para lista skeleton\ninterface SkeletonListProps extends HTMLAttributes<HTMLDivElement> {\n items?: number;\n showAvatar?: boolean;\n showTitle?: boolean;\n showDescription?: boolean;\n lines?: number;\n}\n\nconst SkeletonList = forwardRef<HTMLDivElement, SkeletonListProps>(\n (\n {\n items = 3,\n showAvatar = true,\n showTitle = true,\n showDescription = true,\n lines = 1,\n className = '',\n ...props\n },\n ref\n ) => {\n return (\n <div ref={ref} className={cn('space-y-3', className)} {...props}>\n {Array.from({ length: items }, (_, index) => (\n <div key={index} className=\"flex items-start space-x-3 p-3\">\n {showAvatar && <SkeletonCircle width={32} height={32} />}\n\n <div className=\"flex-1 space-y-2\">\n {showTitle && <SkeletonText width=\"40%\" height={16} />}\n\n {showDescription && (\n <SkeletonText lines={lines} spacing=\"small\" />\n )}\n </div>\n </div>\n ))}\n </div>\n );\n }\n);\n\n// Componente para tabela skeleton\ninterface SkeletonTableProps extends HTMLAttributes<HTMLDivElement> {\n rows?: number;\n columns?: number;\n showHeader?: boolean;\n}\n\nconst SkeletonTable = forwardRef<HTMLDivElement, SkeletonTableProps>(\n (\n { rows = 5, columns = 4, showHeader = true, className = '', ...props },\n ref\n ) => {\n return (\n <div ref={ref} className={cn('w-full', className)} {...props}>\n {showHeader && (\n <div className=\"flex space-x-2 mb-3\">\n {Array.from({ length: columns }, (_, index) => (\n <SkeletonText\n key={index}\n width={`${100 / columns}%`}\n height={20}\n />\n ))}\n </div>\n )}\n\n <div className=\"space-y-2\">\n {Array.from({ length: rows }, (_, rowIndex) => (\n <div key={rowIndex} className=\"flex space-x-2\">\n {Array.from({ length: columns }, (_, colIndex) => (\n <SkeletonText\n key={colIndex}\n width={`${100 / columns}%`}\n height={16}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n }\n);\n\nexport {\n Skeleton,\n SkeletonText,\n SkeletonCircle,\n SkeletonRectangle,\n SkeletonRounded,\n SkeletonCard,\n SkeletonList,\n SkeletonTable,\n};\n","import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * IconButton component props interface\n */\nexport type IconButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Tamanho do botão */\n size?: 'sm' | 'md';\n /** Estado de seleção/ativo do botão - permanece ativo até ser clicado novamente ou outro botão ser ativado */\n active?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * IconButton component for Analytica Ensino platforms\n *\n * Um botão compacto apenas com ícone, ideal para menus dropdown,\n * barras de ferramentas e ações secundárias.\n * Oferece dois tamanhos com estilo consistente.\n * Estado ativo permanece até ser clicado novamente ou outro botão ser ativado.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param size - Tamanho do botão (sm, md)\n * @param active - Estado ativo/selecionado do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button compacto estilizado apenas com ícone\n *\n * @example\n * ```tsx\n * <IconButton\n * icon={<MoreVerticalIcon />}\n * size=\"sm\"\n * onClick={() => openMenu()}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Botão ativo em uma barra de ferramentas - permanece ativo até outro clique\n * <IconButton\n * icon={<BoldIcon />}\n * active={isBold}\n * onClick={toggleBold}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para controle programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * <IconButton\n * ref={buttonRef}\n * icon={<EditIcon />}\n * size=\"md\"\n * onClick={() => startEditing()}\n * />\n * ```\n */\nconst IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n { icon, size = 'md', active = false, className = '', disabled, ...props },\n ref\n ) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'inline-flex',\n 'items-center',\n 'justify-center',\n 'rounded-lg',\n 'font-medium',\n 'bg-transparent',\n 'text-text-950',\n 'cursor-pointer',\n 'hover:bg-primary-600',\n 'hover:text-text',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-0',\n 'focus-visible:ring-indicator-info',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n 'disabled:pointer-events-none',\n ];\n\n // Classes de tamanho\n const sizeClasses = {\n sm: ['w-6', 'h-6', 'text-sm'],\n md: ['w-10', 'h-10', 'text-base'],\n };\n\n // Classes de estado ativo\n const activeClasses = active\n ? ['!bg-primary-50', '!text-primary-950', 'hover:!bg-primary-100']\n : [];\n\n const allClasses = [\n ...baseClasses,\n ...sizeClasses[size],\n ...activeClasses,\n ].join(' ');\n\n // Garantir acessibilidade com aria-label padrão\n const ariaLabel = props['aria-label'] ?? 'Botão de ação';\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(allClasses, className)}\n disabled={disabled}\n aria-pressed={active}\n aria-label={ariaLabel}\n {...props}\n >\n <span className=\"flex items-center justify-center\">{icon}</span>\n </button>\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n\nexport default IconButton;\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 { useState, useEffect } from 'react';\n\n// Mobile width in pixels\nconst MOBILE_WIDTH = 500;\n// Tablet width in pixels\nconst TABLET_WIDTH = 931;\n// Video responsive breakpoints\nconst SMALL_MOBILE_WIDTH = 425;\nconst EXTRA_SMALL_MOBILE_WIDTH = 375;\nconst ULTRA_SMALL_MOBILE_WIDTH = 375; // For video controls\nconst TINY_MOBILE_WIDTH = 320;\n// Default desktop width for SSR\nconst DEFAULT_WIDTH = 1200;\n\n/**\n * Device type based on screen width\n */\nexport type DeviceType = 'responsive' | 'desktop';\n\n/**\n * Gets the window width safely (SSR compatible)\n * @returns {number} window width or default value for SSR\n */\nconst getWindowWidth = (): number => {\n if (typeof window === 'undefined') {\n return DEFAULT_WIDTH;\n }\n return window.innerWidth;\n};\n\n/**\n * Gets the current device type based on screen width\n * @returns {DeviceType} 'responsive' for mobile/tablet (width < 931px), 'desktop' for larger screens\n */\nexport const getDeviceType = (): DeviceType => {\n const width = getWindowWidth();\n return width < TABLET_WIDTH ? 'responsive' : 'desktop';\n};\n\n/**\n * Hook to detect screen size and get responsive classes\n * @returns object with isMobile, isTablet, responsive class functions and getDeviceType\n */\nexport const useMobile = () => {\n const [isMobile, setIsMobile] = useState(false);\n const [isTablet, setIsTablet] = useState(false);\n const [isSmallMobile, setIsSmallMobile] = useState(false);\n const [isExtraSmallMobile, setIsExtraSmallMobile] = useState(false);\n const [isUltraSmallMobile, setIsUltraSmallMobile] = useState(false);\n const [isTinyMobile, setIsTinyMobile] = useState(false);\n\n useEffect(() => {\n const checkScreenSize = () => {\n const width = getWindowWidth();\n setIsMobile(width < MOBILE_WIDTH);\n setIsTablet(width < TABLET_WIDTH);\n setIsSmallMobile(width < SMALL_MOBILE_WIDTH);\n setIsExtraSmallMobile(width < EXTRA_SMALL_MOBILE_WIDTH);\n setIsUltraSmallMobile(width < ULTRA_SMALL_MOBILE_WIDTH);\n setIsTinyMobile(width < TINY_MOBILE_WIDTH);\n };\n\n checkScreenSize();\n\n window.addEventListener('resize', checkScreenSize);\n\n return () => window.removeEventListener('resize', checkScreenSize);\n }, []);\n\n /**\n * Get responsive classes for the form container\n * @returns className string for form container based on screen size\n */\n const getFormContainerClasses = (): string => {\n if (isMobile) {\n return 'w-full px-4';\n }\n if (isTablet) {\n return 'w-full px-6';\n }\n return 'w-full max-w-[992px] mx-auto px-0';\n };\n\n /**\n * Get mobile-specific classes for the header\n * @returns className string for mobile header layout\n */\n const getMobileHeaderClasses = (): string => {\n return 'flex flex-col items-start gap-4 mb-6';\n };\n\n /**\n * Get desktop-specific classes for the header\n * @returns className string for desktop header layout\n */\n const getDesktopHeaderClasses = (): string => {\n return 'flex flex-row justify-between items-center gap-6 mb-8';\n };\n\n /**\n * Get responsive classes for the header\n * @returns className string for header based on screen size\n */\n const getHeaderClasses = (): string => {\n return isMobile ? getMobileHeaderClasses() : getDesktopHeaderClasses();\n };\n\n /**\n * Get responsive classes for video container\n * @returns className string for video container aspect ratio based on screen size\n */\n const getVideoContainerClasses = (): string => {\n if (isTinyMobile) return 'aspect-square'; // 1:1 ratio for screens < 320px\n if (isExtraSmallMobile) return 'aspect-[4/3]'; // 4:3 ratio for screens < 375px\n if (isSmallMobile) return 'aspect-[16/12]'; // 16:12 ratio for screens < 425px\n return 'aspect-video'; // 16:9 ratio for larger screens\n };\n\n return {\n isMobile,\n isTablet,\n isSmallMobile,\n isExtraSmallMobile,\n isUltraSmallMobile,\n isTinyMobile,\n getFormContainerClasses,\n getHeaderClasses,\n getMobileHeaderClasses,\n getDesktopHeaderClasses,\n getVideoContainerClasses,\n getDeviceType,\n };\n};\n","import { create } from 'zustand';\nimport { devtools } from 'zustand/middleware';\nimport {\n Notification,\n NotificationGroup,\n FetchNotificationsParams,\n BackendNotificationsResponse,\n BackendNotification,\n NotificationEntityType,\n NotificationType,\n NotificationApiClient,\n} from '../types/notifications';\n\n/**\n * Notification store state interface\n */\nexport interface NotificationState {\n /**\n * List of all notifications\n */\n notifications: Notification[];\n /**\n * Number of unread notifications\n */\n unreadCount: number;\n /**\n * Loading state\n */\n loading: boolean;\n /**\n * Error state\n */\n error: string | null;\n /**\n * Whether there are more notifications to load\n */\n hasMore: boolean;\n /**\n * Current page for pagination\n */\n currentPage: number;\n}\n\n/**\n * Notification store actions interface\n */\nexport interface NotificationActions {\n /**\n * Fetch notifications from API\n */\n fetchNotifications: (params?: FetchNotificationsParams) => Promise<void>;\n /**\n * Mark a specific notification as read\n */\n markAsRead: (id: string) => Promise<void>;\n /**\n * Mark all notifications as read\n */\n markAllAsRead: () => Promise<void>;\n /**\n * Delete a notification\n */\n deleteNotification: (id: string) => Promise<void>;\n /**\n * Clear all notifications\n */\n clearNotifications: () => void;\n /**\n * Reset error state\n */\n resetError: () => void;\n /**\n * Group notifications by time periods\n */\n getGroupedNotifications: () => NotificationGroup[];\n}\n\nexport type NotificationStore = NotificationState & NotificationActions;\n\n/**\n * Convert backend notification to frontend format\n */\nconst mapBackendNotification = (\n backendNotification: BackendNotification\n): Notification => {\n let type: NotificationType = 'GENERAL';\n let entityType: NotificationEntityType | null = null;\n\n if (backendNotification.entityType) {\n // Convert to uppercase for comparison since backend returns lowercase\n const backendEntityType = backendNotification.entityType.toUpperCase();\n\n switch (backendEntityType) {\n case NotificationEntityType.ACTIVITY:\n type = 'ACTIVITY';\n entityType = NotificationEntityType.ACTIVITY;\n break;\n case NotificationEntityType.TRAIL:\n type = 'TRAIL';\n entityType = NotificationEntityType.TRAIL;\n break;\n case NotificationEntityType.GOAL:\n type = 'GOAL';\n entityType = NotificationEntityType.GOAL;\n break;\n default:\n break;\n }\n }\n\n return {\n id: backendNotification.id,\n title: backendNotification.title,\n message: backendNotification.description,\n type,\n isRead: backendNotification.read,\n createdAt: new Date(backendNotification.createdAt),\n entityType,\n entityId: backendNotification.entityId,\n sender: backendNotification.sender,\n activity: backendNotification.activity,\n goal: backendNotification.goal,\n actionLink: backendNotification.actionLink ?? null,\n };\n};\n\n/**\n * Group notifications by time periods\n */\nconst groupNotificationsByTime = (\n notifications: Notification[]\n): NotificationGroup[] => {\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const lastWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);\n const sortDesc = (a: Notification, b: Notification) =>\n +new Date(b.createdAt) - +new Date(a.createdAt);\n\n const todayNotifications = notifications\n .filter((notification) => new Date(notification.createdAt) >= today)\n .sort(sortDesc);\n\n const lastWeekNotifications = notifications\n .filter(\n (notification) =>\n new Date(notification.createdAt) >= lastWeek &&\n new Date(notification.createdAt) < today\n )\n .sort(sortDesc);\n\n const olderNotifications = notifications\n .filter((notification) => new Date(notification.createdAt) < lastWeek)\n .sort(sortDesc);\n\n const groups: NotificationGroup[] = [];\n\n if (todayNotifications.length > 0) {\n groups.push({\n label: 'Hoje',\n notifications: todayNotifications,\n });\n }\n\n if (lastWeekNotifications.length > 0) {\n groups.push({\n label: 'Última semana',\n notifications: lastWeekNotifications,\n });\n }\n\n if (olderNotifications.length > 0) {\n groups.push({\n label: 'Mais antigas',\n notifications: olderNotifications,\n });\n }\n\n return groups;\n};\n\n/**\n * Format time relative to now\n */\nexport const formatTimeAgo = (date: Date): string => {\n const now = new Date();\n const diffInMs = now.getTime() - new Date(date).getTime();\n const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60));\n const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));\n\n if (diffInHours < 24) {\n return `Há ${diffInHours}h`;\n } else if (diffInDays < 30) {\n const day = new Date(date).getDate();\n const months = [\n 'Jan',\n 'Fev',\n 'Mar',\n 'Abr',\n 'Mai',\n 'Jun',\n 'Jul',\n 'Ago',\n 'Set',\n 'Out',\n 'Nov',\n 'Dez',\n ];\n const month = months[new Date(date).getMonth()];\n return `${day} ${month}`;\n }\n\n return new Date(date).toLocaleDateString('pt-BR');\n};\n\n/**\n * Create notification store with injected API client\n */\nexport const createNotificationStore = (apiClient: NotificationApiClient) => {\n return create<NotificationStore>()(\n devtools(\n (set, get) => ({\n // Initial state\n notifications: [],\n unreadCount: 0,\n loading: false,\n error: null,\n hasMore: true,\n currentPage: 1,\n\n // Actions\n fetchNotifications: async (params: FetchNotificationsParams = {}) => {\n set({ loading: true, error: null });\n\n try {\n const response = await apiClient.get<BackendNotificationsResponse>(\n '/notifications',\n { params: { ...params } }\n );\n\n const mappedNotifications = response.data.notifications.map(\n mapBackendNotification\n );\n\n const page = response.data.pagination.page;\n const totalPages = response.data.pagination.totalPages;\n const merged =\n params.page && params.page > 1\n ? [...get().notifications, ...mappedNotifications]\n : mappedNotifications;\n // de-dup by id\n const deduped = Array.from(\n new Map(merged.map((n) => [n.id, n])).values()\n );\n\n set({\n notifications: deduped,\n unreadCount: deduped.filter((n) => !n.isRead).length,\n hasMore: page < totalPages,\n currentPage: page,\n loading: false,\n });\n } catch (error) {\n console.error('Error fetching notifications:', error);\n set({\n error: 'Erro ao carregar notificações',\n loading: false,\n });\n }\n },\n\n markAsRead: async (id: string) => {\n const { notifications } = get();\n\n // Find the notification to check if it's already read\n const notification = notifications.find((n) => n.id === id);\n\n // If notification is already read, just return without making API call\n if (notification?.isRead) {\n return;\n }\n\n try {\n await apiClient.patch(`/notifications/${id}`, { read: true });\n\n const updatedNotifications = notifications.map((notification) =>\n notification.id === id\n ? { ...notification, isRead: true }\n : notification\n );\n\n const unreadCount = updatedNotifications.filter(\n (n) => !n.isRead\n ).length;\n\n set({\n notifications: updatedNotifications,\n unreadCount,\n });\n } catch (error) {\n console.error('Error marking notification as read:', error);\n set({ error: 'Erro ao marcar notificação como lida' });\n }\n },\n\n markAllAsRead: async () => {\n const { notifications } = get();\n\n try {\n // Mark all unread notifications as read\n const unreadNotifications = notifications.filter((n) => !n.isRead);\n\n await Promise.all(\n unreadNotifications.map((notification) =>\n apiClient.patch(`/notifications/${notification.id}`, {\n read: true,\n })\n )\n );\n\n const updatedNotifications = notifications.map((notification) => ({\n ...notification,\n isRead: true,\n }));\n\n set({\n notifications: updatedNotifications,\n unreadCount: 0,\n });\n } catch (error) {\n console.error('Error marking all notifications as read:', error);\n set({ error: 'Erro ao marcar todas as notificações como lidas' });\n }\n },\n\n deleteNotification: async (id: string) => {\n const { notifications } = get();\n\n try {\n await apiClient.delete(`/notifications/${id}`);\n\n const updatedNotifications = notifications.filter(\n (notification) => notification.id !== id\n );\n\n const unreadCount = updatedNotifications.filter(\n (n) => !n.isRead\n ).length;\n\n set({\n notifications: updatedNotifications,\n unreadCount,\n });\n } catch (error) {\n console.error('Error deleting notification:', error);\n set({ error: 'Erro ao deletar notificação' });\n }\n },\n\n clearNotifications: () => {\n set({\n notifications: [],\n unreadCount: 0,\n hasMore: false,\n currentPage: 1,\n });\n },\n\n resetError: () => {\n set({ error: null });\n },\n\n getGroupedNotifications: () => {\n const { notifications } = get();\n return groupNotificationsByTime(notifications);\n },\n }),\n {\n name: 'notification-store',\n }\n )\n );\n};\n"],"mappings":"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","names":["import_phosphor_react","import_react","import_phosphor_react","import_react","import_zustand","import_jsx_runtime","import_jsx_runtime","SIZE_CLASSES","import_phosphor_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","_","import_react","import_jsx_runtime","import_phosphor_react","import_jsx_runtime","VARIANT_ACTION_CLASSES","SIZE_CLASSES","import_react","import_zustand","import_middleware","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/components/NotificationCard/NotificationCard.tsx","../../src/utils/utils.ts","../../src/components/DropdownMenu/DropdownMenu.tsx","../../src/components/Button/Button.tsx","../../src/components/Text/Text.tsx","../../src/components/Modal/Modal.tsx","../../src/components/Modal/utils/videoUtils.ts","../../src/components/ThemeToggle/ThemeToggle.tsx","../../src/components/SelectionButton/SelectionButton.tsx","../../src/hooks/useTheme.ts","../../src/store/themeStore.ts","../../src/components/Skeleton/Skeleton.tsx","../../src/components/IconButton/IconButton.tsx","../../src/components/Badge/Badge.tsx","../../src/hooks/useMobile.ts","../../src/store/notificationStore.ts"],"sourcesContent":["import { DotsThreeVertical, Bell } from 'phosphor-react';\nimport { MouseEvent, ReactNode, useState, useEffect } from 'react';\nimport { cn } from '../../utils/utils';\nimport DropdownMenu, {\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../DropdownMenu/DropdownMenu';\nimport { SkeletonCard } from '../Skeleton/Skeleton';\nimport IconButton from '../IconButton/IconButton';\nimport Modal from '../Modal/Modal';\nimport Text from '../Text/Text';\nimport Badge from '../Badge/Badge';\nimport { useMobile } from '../../hooks/useMobile';\nimport type {\n Notification,\n NotificationGroup,\n NotificationEntityType,\n} from '../../types/notifications';\nimport { formatTimeAgo } from '../../store/notificationStore';\nimport mockContentImage from '../../assets/img/mock-content.png';\n\n// Extended notification item for component usage with time string\nexport interface NotificationItem extends Omit<Notification, 'createdAt'> {\n time: string;\n createdAt: string | Date;\n}\n\n// Base props shared across all modes\ninterface BaseNotificationProps {\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Empty state image path\n */\n emptyStateImage?: string;\n /**\n * Empty state title\n */\n emptyStateTitle?: string;\n /**\n * Empty state description\n */\n emptyStateDescription?: string;\n}\n\n// Single notification card mode\ninterface SingleNotificationCardMode extends BaseNotificationProps {\n /**\n * Component mode - single card\n */\n mode: 'single';\n /**\n * The notification title\n */\n title: string;\n /**\n * The notification message content\n */\n message: string;\n /**\n * Time displayed (e.g., \"Há 3h\", \"12 Fev\")\n */\n time: string;\n /**\n * Whether the notification has been read\n */\n isRead: boolean;\n /**\n * Callback when user marks notification as read\n */\n onMarkAsRead: () => void;\n /**\n * Callback when user deletes notification\n */\n onDelete: () => void;\n /**\n * Optional callback for navigation action\n */\n onNavigate?: () => void;\n /**\n * Label for the action button (only shown if onNavigate is provided)\n */\n actionLabel?: string;\n}\n\n// List mode\ninterface NotificationListMode extends BaseNotificationProps {\n /**\n * Component mode - list\n */\n mode: 'list';\n /**\n * Array of notifications for list mode\n */\n notifications?: NotificationItem[];\n /**\n * Array of grouped notifications\n */\n groupedNotifications?: NotificationGroup[];\n /**\n * Loading state for list mode\n */\n loading?: boolean;\n /**\n * Error state for list mode\n */\n error?: string | null;\n /**\n * Callback for retry when error occurs\n */\n onRetry?: () => void;\n /**\n * Callback when user marks a notification as read in list mode\n */\n onMarkAsReadById?: (id: string) => void;\n /**\n * Callback when user deletes a notification in list mode\n */\n onDeleteById?: (id: string) => void;\n /**\n * Callback when user navigates from a notification in list mode\n */\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n /**\n * Callback when user clicks on a global notification\n */\n onGlobalNotificationClick?: (notification: Notification) => void;\n /**\n * Function to get action label for a notification\n */\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n /**\n * Custom empty state component\n */\n renderEmpty?: () => ReactNode;\n}\n\n// NotificationCenter mode\ninterface NotificationCenterMode extends BaseNotificationProps {\n /**\n * Component mode - center\n */\n mode: 'center';\n /**\n * Array of grouped notifications\n */\n groupedNotifications?: NotificationGroup[];\n /**\n * Loading state for center mode\n */\n loading?: boolean;\n /**\n * Error state for center mode\n */\n error?: string | null;\n /**\n * Callback for retry when error occurs\n */\n onRetry?: () => void;\n /**\n * Whether center mode is currently active (controls dropdown/modal visibility)\n */\n isActive?: boolean;\n /**\n * Callback when center mode is toggled\n */\n onToggleActive?: () => void;\n /**\n * Number of unread notifications for badge display\n */\n unreadCount?: number;\n /**\n * Callback when all notifications should be marked as read\n */\n onMarkAllAsRead?: () => void;\n /**\n * Callback to fetch notifications (called when center opens)\n */\n onFetchNotifications?: () => void;\n /**\n * Callback when user marks a notification as read in center mode\n */\n onMarkAsReadById?: (id: string) => void;\n /**\n * Callback when user deletes a notification in center mode\n */\n onDeleteById?: (id: string) => void;\n /**\n * Callback when user navigates from a notification in center mode\n */\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n /**\n * Function to get action label for a notification\n */\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n /**\n * Callback when dropdown open state changes (for synchronization with parent)\n */\n onOpenChange?: (open: boolean) => void;\n}\n\n// Union type for all modes\nexport type NotificationCardProps =\n | SingleNotificationCardMode\n | NotificationListMode\n | NotificationCenterMode;\n\n// Legacy interface for backward compatibility\nexport interface LegacyNotificationCardProps extends BaseNotificationProps {\n // Single notification mode props\n title?: string;\n message?: string;\n time?: string;\n isRead?: boolean;\n onMarkAsRead?: () => void;\n onDelete?: () => void;\n onNavigate?: () => void;\n actionLabel?: string;\n\n // List mode props\n notifications?: NotificationItem[];\n groupedNotifications?: NotificationGroup[];\n loading?: boolean;\n error?: string | null;\n onRetry?: () => void;\n onMarkAsReadById?: (id: string) => void;\n onDeleteById?: (id: string) => void;\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n onGlobalNotificationClick?: (notification: Notification) => void;\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n renderEmpty?: () => ReactNode;\n\n // NotificationCenter mode props\n variant?: 'card' | 'center';\n isActive?: boolean;\n onToggleActive?: () => void;\n unreadCount?: number;\n onMarkAllAsRead?: () => void;\n onFetchNotifications?: () => void;\n onOpenChange?: (open: boolean) => void;\n}\n\n/**\n * Empty state component for notifications\n */\nconst NotificationEmpty = ({\n emptyStateImage,\n emptyStateTitle = 'Nenhuma notificação no momento',\n emptyStateDescription = 'Você está em dia com todas as novidades. Volte depois para conferir atualizações!',\n}: {\n emptyStateImage?: string;\n emptyStateTitle?: string;\n emptyStateDescription?: string;\n}) => {\n return (\n <div className=\"flex flex-col items-center justify-center gap-4 p-6 w-full\">\n {/* Notification Icon */}\n {emptyStateImage && (\n <div className=\"w-20 h-20 flex items-center justify-center\">\n <img\n src={emptyStateImage}\n alt=\"Sem notificações\"\n width={82}\n height={82}\n className=\"object-contain\"\n />\n </div>\n )}\n\n {/* Title */}\n <h3 className=\"text-xl font-semibold text-text-950 text-center leading-[23px]\">\n {emptyStateTitle}\n </h3>\n\n {/* Description */}\n <p className=\"text-sm font-normal text-text-400 text-center max-w-[316px] leading-[21px]\">\n {emptyStateDescription}\n </p>\n </div>\n );\n};\n\n/**\n * Notification header component\n */\nconst NotificationHeader = ({\n unreadCount,\n variant = 'modal',\n}: {\n unreadCount: number;\n variant?: 'modal' | 'dropdown';\n}) => {\n return (\n <div className=\"flex items-center justify-between gap-2\">\n {variant === 'modal' ? (\n <Text size=\"sm\" weight=\"bold\" className=\"text-text-950\">\n Notificações\n </Text>\n ) : (\n <h3 className=\"text-sm font-semibold text-text-950\">Notificações</h3>\n )}\n {unreadCount > 0 && (\n <Badge\n variant=\"solid\"\n action=\"info\"\n size=\"small\"\n iconLeft={<Bell size={12} aria-hidden=\"true\" focusable=\"false\" />}\n className=\"border-0\"\n >\n {unreadCount === 1 ? '1 não lida' : `${unreadCount} não lidas`}\n </Badge>\n )}\n </div>\n );\n};\n\n/**\n * Single notification card component\n */\nconst SingleNotificationCard = ({\n title,\n message,\n time,\n isRead,\n onMarkAsRead,\n onDelete,\n onNavigate,\n actionLabel,\n className,\n}: {\n title: string;\n message: string;\n time: string;\n isRead: boolean;\n onMarkAsRead: () => void;\n onDelete: () => void;\n onNavigate?: () => void;\n actionLabel?: string;\n className?: string;\n}) => {\n const handleMarkAsRead = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (!isRead) {\n onMarkAsRead();\n }\n };\n\n const handleDelete = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onDelete();\n };\n\n const handleNavigate = (e: MouseEvent) => {\n e.stopPropagation();\n if (onNavigate) {\n onNavigate();\n }\n };\n\n return (\n <div\n className={cn(\n 'flex flex-col justify-center items-start p-4 gap-2 w-full bg-background border-b border-border-200',\n 'last:border-b-0',\n className\n )}\n >\n {/* Header with unread indicator and actions menu */}\n <div className=\"flex items-center gap-2 w-full\">\n {/* Unread indicator */}\n {!isRead && (\n <div className=\"w-[7px] h-[7px] bg-info-300 rounded-full flex-shrink-0\" />\n )}\n\n {/* Title */}\n <h3 className=\"font-bold text-sm leading-4 text-text-950 flex-grow\">\n {title}\n </h3>\n\n {/* Actions dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger\n className=\"flex-shrink-0 inline-flex items-center justify-center font-medium bg-transparent text-text-950 cursor-pointer hover:bg-info-50 w-6 h-6 rounded-lg\"\n aria-label=\"Menu de ações\"\n >\n <DotsThreeVertical size={24} />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-[160px]\">\n {!isRead && (\n <DropdownMenuItem\n onClick={handleMarkAsRead}\n className=\"text-text-950\"\n >\n Marcar como lida\n </DropdownMenuItem>\n )}\n <DropdownMenuItem onClick={handleDelete} className=\"text-error-600\">\n Deletar\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Message */}\n <p className=\"text-sm leading-[21px] text-text-800 w-full\">{message}</p>\n\n {/* Time and action button */}\n <div className=\"flex items-center justify-between w-full\">\n <span className=\"text-sm font-medium text-text-400\">{time}</span>\n\n {onNavigate && actionLabel && (\n <button\n type=\"button\"\n onClick={handleNavigate}\n className=\"text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer\"\n >\n {actionLabel}\n </button>\n )}\n </div>\n </div>\n );\n};\n\n/**\n * Notification list component for displaying grouped notifications\n */\nconst NotificationList = ({\n groupedNotifications = [],\n loading = false,\n error = null,\n onRetry,\n onMarkAsReadById,\n onDeleteById,\n onNavigateById,\n onGlobalNotificationClick,\n getActionLabel,\n renderEmpty,\n className,\n emptyStateImage,\n}: {\n groupedNotifications?: NotificationGroup[];\n loading?: boolean;\n error?: string | null;\n onRetry?: () => void;\n onMarkAsReadById?: (id: string) => void;\n onDeleteById?: (id: string) => void;\n onNavigateById?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n onGlobalNotificationClick?: (notification: Notification) => void;\n getActionLabel?: (entityType?: NotificationEntityType) => string | undefined;\n renderEmpty?: () => ReactNode;\n className?: string;\n emptyStateImage?: string;\n}) => {\n // State for global notification modal when onGlobalNotificationClick is not provided\n const [globalNotificationModal, setGlobalNotificationModal] = useState<{\n isOpen: boolean;\n notification: Notification | null;\n }>({ isOpen: false, notification: null });\n\n // Default handler for global notifications when onGlobalNotificationClick is not provided\n const handleGlobalNotificationClick = (notification: Notification) => {\n if (onGlobalNotificationClick) {\n onGlobalNotificationClick(notification);\n } else {\n // Open modal as fallback\n setGlobalNotificationModal({\n isOpen: true,\n notification,\n });\n }\n };\n // Error state\n if (error) {\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 w-full\">\n <p className=\"text-sm text-error-600\">{error}</p>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"text-sm text-info-600 hover:text-info-700\"\n >\n Tentar novamente\n </button>\n )}\n </div>\n );\n }\n\n // Loading state\n if (loading) {\n return (\n <div className=\"flex flex-col gap-0 w-full\">\n {['skeleton-first', 'skeleton-second', 'skeleton-third'].map(\n (skeletonId) => (\n <SkeletonCard\n key={skeletonId}\n className=\"p-4 border-b border-border-200\"\n />\n )\n )}\n </div>\n );\n }\n\n // Empty state\n if (!groupedNotifications || groupedNotifications.length === 0) {\n return renderEmpty ? (\n <div className=\"w-full\">{renderEmpty()}</div>\n ) : (\n <NotificationEmpty />\n );\n }\n\n return (\n <div className={cn('flex flex-col gap-0 w-full', className)}>\n {groupedNotifications.map((group, idx) => (\n <div key={`${group.label}-${idx}`} className=\"flex flex-col\">\n {/* Group header */}\n <div className=\"flex items-end px-4 py-6 pb-4\">\n <h4 className=\"text-lg font-bold text-text-500 flex-grow\">\n {group.label}\n </h4>\n </div>\n\n {/* Notifications in group */}\n {group.notifications.map((notification) => {\n // Check if this is a global notification\n const isGlobalNotification =\n !notification.entityType &&\n !notification.entityId &&\n !notification.activity &&\n !notification.goal;\n\n // Determine navigation handler\n let navigationHandler: (() => void) | undefined;\n if (isGlobalNotification) {\n navigationHandler = () =>\n handleGlobalNotificationClick(notification);\n } else if (\n notification.entityType &&\n notification.entityId &&\n onNavigateById\n ) {\n navigationHandler = () =>\n onNavigateById(\n notification.entityType ?? undefined,\n notification.entityId ?? undefined\n );\n }\n\n // Determine action label\n let actionLabel: string | undefined;\n if (isGlobalNotification) {\n // For global notifications, call getActionLabel without parameters or with null\n actionLabel = getActionLabel?.(undefined);\n } else {\n // For entity-specific notifications, pass the entityType\n actionLabel = getActionLabel?.(\n notification.entityType ?? undefined\n );\n }\n\n return (\n <SingleNotificationCard\n key={notification.id}\n title={notification.title}\n message={notification.message}\n time={\n (notification as Partial<NotificationItem>).time ??\n formatTimeAgo(new Date(notification.createdAt))\n }\n isRead={notification.isRead}\n onMarkAsRead={() => onMarkAsReadById?.(notification.id)}\n onDelete={() => onDeleteById?.(notification.id)}\n onNavigate={navigationHandler}\n actionLabel={actionLabel}\n />\n );\n })}\n </div>\n ))}\n\n {/* Global notification modal for list mode */}\n <Modal\n isOpen={globalNotificationModal.isOpen}\n onClose={() =>\n setGlobalNotificationModal({ isOpen: false, notification: null })\n }\n title={globalNotificationModal.notification?.title || ''}\n description={globalNotificationModal.notification?.message || ''}\n variant=\"activity\"\n image={emptyStateImage || mockContentImage}\n actionLink={\n globalNotificationModal.notification?.actionLink || undefined\n }\n actionLabel=\"Ver mais\"\n size=\"lg\"\n />\n </div>\n );\n};\n\n// Internal props type for NotificationCenter (without mode)\ntype NotificationCenterProps = Omit<NotificationCenterMode, 'mode'>;\n\n/**\n * NotificationCenter component for modal/dropdown mode\n */\nconst NotificationCenter = ({\n isActive,\n onToggleActive,\n unreadCount = 0,\n groupedNotifications = [],\n loading = false,\n error = null,\n onRetry,\n onMarkAsReadById,\n onDeleteById,\n onNavigateById,\n getActionLabel,\n onFetchNotifications,\n onMarkAllAsRead,\n onOpenChange,\n emptyStateImage,\n emptyStateTitle,\n emptyStateDescription,\n className,\n}: NotificationCenterProps) => {\n const { isMobile } = useMobile();\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [globalNotificationModal, setGlobalNotificationModal] = useState<{\n isOpen: boolean;\n notification: Notification | null;\n }>({ isOpen: false, notification: null });\n\n // Handle mobile click\n const handleMobileClick = () => {\n setIsModalOpen(true);\n onFetchNotifications?.();\n };\n\n // Handle desktop click\n const handleDesktopClick = () => {\n onToggleActive?.();\n };\n\n // Handle dropdown open change\n const handleOpenChange = (open: boolean) => {\n const controlledByParent =\n typeof isActive === 'boolean' && typeof onToggleActive === 'function';\n\n // Always notify parent if they want the signal.\n onOpenChange?.(open);\n\n // If parent controls via toggle only (no onOpenChange), keep them in sync on close.\n if (controlledByParent && !onOpenChange && !open && isActive) {\n onToggleActive?.();\n }\n };\n\n // Fetch notifications when dropdown opens\n useEffect(() => {\n if (isActive) {\n onFetchNotifications?.();\n }\n }, [isActive, onFetchNotifications]);\n\n const renderEmptyState = () => (\n <NotificationEmpty\n emptyStateImage={emptyStateImage}\n emptyStateTitle={emptyStateTitle}\n emptyStateDescription={emptyStateDescription}\n />\n );\n\n if (isMobile) {\n return (\n <>\n <IconButton\n active={isModalOpen}\n onClick={handleMobileClick}\n icon={<Bell size={24} className=\"text-primary\" />}\n className={className}\n />\n <Modal\n isOpen={isModalOpen}\n onClose={() => setIsModalOpen(false)}\n title=\"Notificações\"\n size=\"md\"\n hideCloseButton={false}\n closeOnEscape={true}\n >\n <div className=\"flex flex-col h-full max-h-[80vh]\">\n <div className=\"px-0 pb-3 border-b border-border-200\">\n <NotificationHeader unreadCount={unreadCount} variant=\"modal\" />\n {unreadCount > 0 && onMarkAllAsRead && (\n <button\n type=\"button\"\n onClick={onMarkAllAsRead}\n className=\"text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2\"\n >\n Marcar todas como lidas\n </button>\n )}\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n <NotificationList\n groupedNotifications={groupedNotifications}\n loading={loading}\n error={error}\n onRetry={onRetry}\n onMarkAsReadById={onMarkAsReadById}\n onDeleteById={onDeleteById}\n onNavigateById={(entityType, entityId) => {\n setIsModalOpen(false);\n onNavigateById?.(entityType, entityId);\n }}\n onGlobalNotificationClick={(notification) => {\n setIsModalOpen(false);\n setGlobalNotificationModal({\n isOpen: true,\n notification,\n });\n }}\n getActionLabel={getActionLabel}\n renderEmpty={renderEmptyState}\n emptyStateImage={emptyStateImage}\n />\n </div>\n </div>\n </Modal>\n {/* Global Notification Modal (mobile) */}\n <Modal\n isOpen={globalNotificationModal.isOpen}\n onClose={() =>\n setGlobalNotificationModal({ isOpen: false, notification: null })\n }\n title={globalNotificationModal.notification?.title || ''}\n variant=\"activity\"\n description={globalNotificationModal.notification?.message}\n image={emptyStateImage || mockContentImage}\n actionLink={\n globalNotificationModal.notification?.actionLink || undefined\n }\n actionLabel=\"Ver mais\"\n size=\"lg\"\n />\n </>\n );\n }\n\n return (\n <>\n <DropdownMenu\n {...(typeof isActive === 'boolean'\n ? { open: isActive, onOpenChange: handleOpenChange }\n : { onOpenChange: handleOpenChange })}\n >\n <DropdownMenuTrigger className=\"text-primary cursor-pointer\">\n <IconButton\n active={isActive}\n onClick={handleDesktopClick}\n icon={\n <Bell\n size={24}\n className={isActive ? 'text-primary-950' : 'text-primary'}\n />\n }\n className={className}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"min-w-[320px] max-w-[400px] max-h-[500px] overflow-hidden\"\n side=\"bottom\"\n align=\"end\"\n >\n <div className=\"flex flex-col\">\n <div className=\"px-4 py-3 border-b border-border-200\">\n <NotificationHeader\n unreadCount={unreadCount}\n variant=\"dropdown\"\n />\n {unreadCount > 0 && onMarkAllAsRead && (\n <button\n type=\"button\"\n onClick={onMarkAllAsRead}\n className=\"text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2\"\n >\n Marcar todas como lidas\n </button>\n )}\n </div>\n <div className=\"max-h-[350px] overflow-y-auto\">\n <NotificationList\n groupedNotifications={groupedNotifications}\n loading={loading}\n error={error}\n onRetry={onRetry}\n onMarkAsReadById={onMarkAsReadById}\n onDeleteById={onDeleteById}\n onNavigateById={onNavigateById}\n onGlobalNotificationClick={(notification) => {\n setGlobalNotificationModal({\n isOpen: true,\n notification,\n });\n }}\n getActionLabel={getActionLabel}\n renderEmpty={renderEmptyState}\n emptyStateImage={emptyStateImage}\n />\n </div>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Global Notification Modal */}\n <Modal\n isOpen={globalNotificationModal.isOpen}\n onClose={() =>\n setGlobalNotificationModal({ isOpen: false, notification: null })\n }\n title={globalNotificationModal.notification?.title || ''}\n variant=\"activity\"\n description={globalNotificationModal.notification?.message}\n image={emptyStateImage || mockContentImage}\n actionLink={\n globalNotificationModal.notification?.actionLink || undefined\n }\n actionLabel=\"Ver mais\"\n size=\"lg\"\n />\n </>\n );\n};\n\n/**\n * NotificationCard component - can display single notification, list of notifications, or center mode\n *\n * @param props - The notification card properties\n * @returns JSX element representing the notification card, list, or center\n */\nconst NotificationCard = (props: NotificationCardProps) => {\n // Use mode discriminator to determine which component to render\n switch (props.mode) {\n case 'single':\n return (\n <SingleNotificationCard\n title={props.title}\n message={props.message}\n time={props.time}\n isRead={props.isRead}\n onMarkAsRead={props.onMarkAsRead}\n onDelete={props.onDelete}\n onNavigate={props.onNavigate}\n actionLabel={props.actionLabel}\n className={props.className}\n />\n );\n\n case 'list':\n return (\n <NotificationList\n groupedNotifications={\n props.groupedNotifications ??\n (props.notifications\n ? [\n {\n label: 'Notificações',\n notifications: props.notifications as Notification[],\n },\n ]\n : [])\n }\n loading={props.loading}\n error={props.error}\n onRetry={props.onRetry}\n onMarkAsReadById={props.onMarkAsReadById}\n onDeleteById={props.onDeleteById}\n onNavigateById={props.onNavigateById}\n onGlobalNotificationClick={props.onGlobalNotificationClick}\n getActionLabel={props.getActionLabel}\n renderEmpty={props.renderEmpty}\n className={props.className}\n emptyStateImage={props.emptyStateImage}\n />\n );\n\n case 'center':\n return <NotificationCenter {...props} />;\n\n default:\n // This should never happen with proper typing, but provides a fallback\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 w-full\">\n <p className=\"text-sm text-text-600\">\n Modo de notificação não reconhecido\n </p>\n </div>\n );\n }\n};\n\n/**\n * Legacy NotificationCard component for backward compatibility\n * Automatically detects mode based on provided props\n */\nexport const LegacyNotificationCard = (props: LegacyNotificationCardProps) => {\n // If variant is center, render NotificationCenter\n if (props.variant === 'center') {\n const centerProps: NotificationCenterMode = {\n mode: 'center',\n ...props,\n };\n return <NotificationCenter {...centerProps} />;\n }\n\n // If we have list-related props, render list mode\n if (\n props.groupedNotifications !== undefined ||\n props.notifications !== undefined ||\n props.loading ||\n props.error\n ) {\n return (\n <NotificationList\n groupedNotifications={\n props.groupedNotifications ??\n (props.notifications\n ? [\n {\n label: 'Notificações',\n notifications: props.notifications as Notification[],\n },\n ]\n : [])\n }\n loading={props.loading}\n error={props.error}\n onRetry={props.onRetry}\n onMarkAsReadById={props.onMarkAsReadById}\n onDeleteById={props.onDeleteById}\n onNavigateById={props.onNavigateById}\n onGlobalNotificationClick={props.onGlobalNotificationClick}\n getActionLabel={props.getActionLabel}\n renderEmpty={props.renderEmpty}\n className={props.className}\n emptyStateImage={props.emptyStateImage}\n />\n );\n }\n\n // If we have single notification props, render single card mode\n if (\n props.title !== undefined &&\n props.message !== undefined &&\n props.time !== undefined &&\n props.isRead !== undefined &&\n props.onMarkAsRead &&\n props.onDelete\n ) {\n const singleProps: SingleNotificationCardMode = {\n mode: 'single',\n title: props.title,\n message: props.message,\n time: props.time,\n isRead: props.isRead,\n onMarkAsRead: props.onMarkAsRead,\n onDelete: props.onDelete,\n onNavigate: props.onNavigate,\n actionLabel: props.actionLabel,\n className: props.className,\n emptyStateImage: props.emptyStateImage,\n emptyStateTitle: props.emptyStateTitle,\n emptyStateDescription: props.emptyStateDescription,\n };\n return (\n <SingleNotificationCard\n title={singleProps.title}\n message={singleProps.message}\n time={singleProps.time}\n isRead={singleProps.isRead}\n onMarkAsRead={singleProps.onMarkAsRead}\n onDelete={singleProps.onDelete}\n onNavigate={singleProps.onNavigate}\n actionLabel={singleProps.actionLabel}\n className={singleProps.className}\n />\n );\n }\n\n // Default empty state if no valid props provided\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 w-full\">\n <p className=\"text-sm text-text-600\">Nenhuma notificação configurada</p>\n </div>\n );\n};\n\nexport default NotificationCard;\nexport type { NotificationGroup };\n","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} from './activityFilters';\nexport {\n getStatusBadgeConfig,\n formatTimeSpent,\n formatQuestionNumbers,\n formatDateToBrazilian,\n} from './activityDetailsUtils';\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 { CaretRight, SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useLayoutEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n RefObject,\n CSSProperties,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button from '../Button/Button';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\nimport Modal from '../Modal/Modal';\nimport { ThemeToggle } from '../ThemeToggle/ThemeToggle';\nimport type { ThemeMode } from '@/hooks/useTheme';\nimport { useTheme } from '../../hooks/useTheme';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n // Aqui tu checa o displayName do componente\n const displayName = (\n typedChild.type as unknown as { displayName: string }\n ).displayName;\n\n // Lista de componentes que devem receber o store\n const allowed = [\n 'DropdownMenuTrigger',\n 'DropdownContent',\n 'DropdownMenuContent',\n 'DropdownMenuSeparator',\n 'DropdownMenuItem',\n 'MenuLabel',\n 'ProfileMenuTrigger',\n 'ProfileMenuHeader',\n 'ProfileMenuFooter',\n 'ProfileToggleTheme',\n ];\n\n let newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {};\n\n if (allowed.includes(displayName)) {\n newProps.store = store;\n }\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({\n children,\n open: propOpen,\n onOpenChange,\n}: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const { open, setOpen: storeSetOpen } = useStore(store, (s) => s);\n\n const setOpen = (newOpen: boolean) => {\n storeSetOpen(newOpen);\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.indexOf(focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: Event) => {\n const target = event.target as Node;\n\n if (menuRef.current?.contains(target)) {\n return;\n }\n\n if (\n target instanceof Element &&\n target.closest('[data-dropdown-content=\"true\"]')\n ) {\n return;\n }\n\n setOpen(false);\n };\n\n useEffect(() => {\n if (open) {\n document.addEventListener('pointerdown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('pointerdown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [open]);\n\n useEffect(() => {\n onOpenChange?.(open);\n }, [open, onOpenChange]);\n\n useEffect(() => {\n if (propOpen !== undefined) {\n setOpen(propOpen);\n }\n }, [propOpen]);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, children, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n className={cn(\n 'appearance-none bg-transparent border-none p-0',\n className\n )}\n {...props}\n >\n {children}\n </button>\n );\n});\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'p-1',\n profile: 'p-6',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('text-sm w-full', inset ? 'pl-8' : '', className)}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst DropdownMenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n portal?: boolean;\n triggerRef?: RefObject<HTMLElement | null>;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n portal = false,\n triggerRef,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n const [portalPosition, setPortalPosition] = useState({ top: 0, left: 0 });\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n useLayoutEffect(() => {\n if (portal && open && triggerRef?.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n let top = rect.bottom + sideOffset;\n let left = rect.left;\n\n // Handle horizontal sides (left/right)\n if (side === 'left') {\n left = rect.left - sideOffset;\n top = rect.top;\n } else if (side === 'right') {\n left = rect.right + sideOffset;\n top = rect.top;\n } else {\n // Handle vertical sides (top/bottom)\n if (align === 'end') {\n left = rect.right;\n } else if (align === 'center') {\n left = rect.left + rect.width / 2;\n }\n\n if (side === 'top') {\n top = rect.top - sideOffset;\n }\n }\n\n setPortalPosition({ top, left });\n }\n }, [portal, open, triggerRef, align, side, sideOffset]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n if (portal) {\n return 'fixed';\n }\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const getPortalAlignStyle = () => {\n if (!portal) return {};\n\n const baseStyle: CSSProperties = {\n top: portalPosition.top,\n };\n\n if (align === 'end') {\n baseStyle.right = window.innerWidth - portalPosition.left;\n } else if (align === 'center') {\n baseStyle.left = portalPosition.left;\n baseStyle.transform = 'translateX(-50%)';\n } else {\n baseStyle.left = portalPosition.left;\n }\n\n return baseStyle;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n\n const content = (\n <div\n ref={portal ? contentRef : ref}\n role=\"menu\"\n data-dropdown-content=\"true\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n ...(portal\n ? getPortalAlignStyle()\n : {\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }),\n }}\n {...props}\n >\n {children}\n </div>\n );\n\n if (portal && typeof document !== 'undefined') {\n return createPortal(content, document.body);\n }\n\n return content;\n }\n);\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n preventClose?: boolean;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n preventClose = false,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n if (e.type === 'click') {\n onClick?.(e as MouseEvent<HTMLDivElement>);\n } else if (e.type === 'keydown') {\n // For keyboard events, call onClick if Enter or Space was pressed\n if (\n (e as KeyboardEvent<HTMLDivElement>).key === 'Enter' ||\n (e as KeyboardEvent<HTMLDivElement>).key === ' '\n ) {\n onClick?.(e as unknown as MouseEvent<HTMLDivElement>);\n }\n // honor any user-provided key handler\n props.onKeyDown?.(e as KeyboardEvent<HTMLDivElement>);\n }\n if (!preventClose) {\n setOpen(false);\n }\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\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 `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n handleClick(e);\n }\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <div className=\"w-full\">{children}</div>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('my-1 h-px bg-border-200', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={cn(\n 'rounded-lg size-10 bg-primary-50 flex items-center justify-center cursor-pointer',\n className\n )}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-primary-100 flex items-center justify-center\">\n <User className=\"text-primary-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n photoUrl?: string | null;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, photoUrl, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={cn(\n 'flex flex-row gap-4 items-center min-w-[280px]',\n className\n )}\n {...props}\n >\n <span className=\"w-16 h-16 bg-primary-100 rounded-full flex items-center justify-center overflow-hidden flex-shrink-0\">\n {photoUrl ? (\n <img\n src={photoUrl}\n alt=\"Foto de perfil\"\n className=\"w-full h-full object-cover\"\n />\n ) : (\n <User size={34} className=\"text-primary-800\" />\n )}\n </span>\n <div className=\"flex flex-col min-w-0\">\n <Text\n size=\"xl\"\n weight=\"bold\"\n color=\"text-text-950\"\n className=\"truncate\"\n >\n {name}\n </Text>\n <Text size=\"md\" color=\"text-text-600\" className=\"truncate\">\n {email}\n </Text>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuInfo = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n schoolName: string;\n classYearName: string;\n schoolYearName: string;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n schoolName,\n classYearName,\n schoolYearName,\n store: _store,\n ...props\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuInfo\"\n className={cn('flex flex-row gap-4 items-center', className)}\n {...props}\n >\n <span className=\"w-16 h-16\" />\n <div className=\"flex flex-col \">\n <Text size=\"md\" color=\"text-text-600\">\n {schoolName}\n </Text>\n\n <span className=\"flex flex-row items-center gap-2\">\n <Text size=\"md\" color=\"text-text-600\">\n {classYearName}\n </Text>\n <p className=\"text-text-600 text-xs align-middle\">●</p>\n <Text size=\"md\" color=\"text-text-600\">\n {schoolYearName}\n </Text>\n </span>\n </div>\n </div>\n );\n }\n);\nProfileMenuInfo.displayName = 'ProfileMenuInfo';\n\nconst ProfileToggleTheme = ({\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }) => {\n const { themeMode, setTheme } = useTheme();\n const [modalThemeToggle, setModalThemeToggle] = useState(false);\n const [selectedTheme, setSelectedTheme] = useState<ThemeMode>(themeMode);\n\n const internalStoreRef = useRef<DropdownStoreApi | null>(null);\n internalStoreRef.current ??= createDropdownStore();\n const store = externalStore ?? internalStoreRef.current;\n const setOpen = useStore(store, (s) => s.setOpen);\n\n const handleClick = (e: MouseEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setModalThemeToggle(true);\n };\n\n const handleSave = () => {\n setTheme(selectedTheme);\n setModalThemeToggle(false);\n setOpen(false); // Close dropdown after saving\n };\n\n const handleCancel = () => {\n setSelectedTheme(themeMode); // Reset to current theme\n setModalThemeToggle(false);\n setOpen(false); // Close dropdown after canceling\n };\n\n return (\n <>\n <DropdownMenuItem\n variant=\"profile\"\n preventClose={true}\n store={store}\n iconLeft={\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12.5 2.75C15.085 2.75276 17.5637 3.78054 19.3916 5.6084C21.2195 7.43628 22.2473 9.915 22.25 12.5C22.25 14.4284 21.6778 16.3136 20.6064 17.917C19.5352 19.5201 18.0128 20.7699 16.2314 21.5078C14.4499 22.2458 12.489 22.4387 10.5977 22.0625C8.70642 21.6863 6.96899 20.758 5.60547 19.3945C4.24197 18.031 3.31374 16.2936 2.9375 14.4023C2.56129 12.511 2.75423 10.5501 3.49219 8.76855C4.23012 6.98718 5.47982 5.46483 7.08301 4.39355C8.68639 3.32221 10.5716 2.75 12.5 2.75ZM11.75 4.28516C9.70145 4.47452 7.7973 5.42115 6.41016 6.94043C5.02299 8.4599 4.25247 10.4426 4.25 12.5C4.25247 14.5574 5.02299 16.5401 6.41016 18.0596C7.7973 19.5789 9.70145 20.5255 11.75 20.7148V4.28516Z\"\n fill=\"currentColor\"\n />\n </svg>\n }\n iconRight={<CaretRight />}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n setModalThemeToggle(true);\n }\n }}\n {...props}\n >\n <Text size=\"md\" color=\"text-text-700\">\n Aparência\n </Text>\n </DropdownMenuItem>\n\n <Modal\n isOpen={modalThemeToggle}\n onClose={handleCancel}\n title=\"Aparência\"\n size=\"md\"\n footer={\n <div className=\"flex gap-3\">\n <Button variant=\"outline\" onClick={handleCancel}>\n Cancelar\n </Button>\n <Button variant=\"solid\" onClick={handleSave}>\n Salvar\n </Button>\n </div>\n }\n >\n <div className=\"flex flex-col\">\n <p className=\"text-sm text-text-500\">Escolha o tema:</p>\n <ThemeToggle variant=\"with-save\" onToggle={setSelectedTheme} />\n </div>\n </Modal>\n </>\n );\n};\nProfileToggleTheme.displayName = 'ProfileToggleTheme';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div ref={ref} className={cn('flex flex-col p-2', className)} {...props}>\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={cn('w-full', className)}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut className=\"text-inherit\" />\n </span>\n <Text color=\"inherit\">Sair</Text>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n ProfileToggleTheme,\n ProfileMenuInfo,\n};\n","import { ButtonHTMLAttributes, ReactNode } 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 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 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 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 */\n variant?: 'solid' | 'outline' | 'link';\n /** Action type of the button */\n action?: 'primary' | '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, 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 = ({\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}: ButtonProps) => {\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 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 && <span className=\"ml-2 flex items-center\">{iconRight}</span>}\n </button>\n );\n};\n\nexport default Button;\n","import { ComponentPropsWithoutRef, 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<ComponentPropsWithoutRef<T>, keyof BaseTextProps>;\n\n/**\n * Text component for Analytica Ensino platforms\n *\n * A flexible polymorphic text component with multiple sizes, weights, and colors.\n * Automatically adapts to dark and light themes with full type safety.\n *\n * @param children - The content to display\n * @param size - The text size variant (2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl)\n * @param weight - The font weight variant (hairline, light, normal, medium, semibold, bold, extrabold, black)\n * @param color - The color variant - adapts to theme\n * @param as - The HTML tag to render - determines allowed attributes via TypeScript\n * @param className - Additional CSS classes\n * @param props - HTML attributes valid for the chosen tag only\n * @returns A styled text element with type-safe attributes\n *\n * @example\n * ```tsx\n * <Text size=\"lg\" weight=\"bold\" color=\"text-info-800\">\n * This is a large, bold text\n * </Text>\n *\n * <Text as=\"a\" href=\"/link\" target=\"_blank\">\n * Link with type-safe anchor attributes\n * </Text>\n *\n * <Text as=\"button\" onClick={handleClick} disabled>\n * Button with type-safe button attributes\n * </Text>\n * ```\n */\nconst Text = <T extends ElementType = 'p'>({\n children,\n size = 'md',\n weight = 'normal',\n color = 'text-text-950',\n as,\n className = '',\n ...props\n}: TextProps<T>) => {\n let sizeClasses = '';\n let weightClasses = '';\n\n // Text size classes mapping\n const sizeClassMap = {\n '2xs': 'text-2xs',\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-md',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n '5xl': 'text-5xl',\n '6xl': 'text-6xl',\n } as const;\n\n sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;\n\n // Font weight classes mapping\n const weightClassMap = {\n hairline: 'font-hairline',\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n black: 'font-black',\n } as const;\n\n weightClasses = weightClassMap[weight] ?? weightClassMap.normal;\n\n const baseClasses = 'font-primary';\n const Component = as ?? ('p' as ElementType);\n\n return (\n <Component\n className={cn(baseClasses, sizeClasses, weightClasses, color, className)}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n","import { ReactNode, useEffect, useId } from 'react';\nimport { X } from 'phosphor-react';\nimport { cn } from '../../utils/utils';\nimport Button from '../Button/Button';\nimport {\n isYouTubeUrl,\n getYouTubeVideoId,\n getYouTubeEmbedUrl,\n} from './utils/videoUtils';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n xs: 'max-w-[360px]',\n sm: 'max-w-[420px]',\n md: 'max-w-[510px]',\n lg: 'max-w-[640px]',\n xl: 'max-w-[970px]',\n} as const;\n\n/**\n * Modal component props interface\n */\ntype ModalProps = {\n contentClassName?: string;\n /** Whether the modal is open */\n isOpen: boolean;\n /** Function to close the modal */\n onClose: () => void;\n /** Modal title */\n title: string;\n /** Modal description/content */\n children?: ReactNode;\n /** Size of the modal */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Additional CSS classes for the modal content */\n className?: string;\n /** Whether pressing Escape should close the modal */\n closeOnEscape?: boolean;\n /** Footer content (typically buttons) */\n footer?: ReactNode;\n /** Hide the close button */\n hideCloseButton?: boolean;\n /** Modal variant */\n variant?: 'default' | 'activity';\n /** Description for activity variant */\n description?: string;\n /** Image URL for activity variant */\n image?: string;\n /** Alt text for activity image (leave empty for decorative images) */\n imageAlt?: string;\n /** Action link for activity variant */\n actionLink?: string;\n /** Action button label for activity variant */\n actionLabel?: string;\n};\n\n/**\n * Modal component for Analytica Ensino platforms\n *\n * A flexible modal component with multiple size variants and customizable behavior.\n *\n * @param isOpen - Whether the modal is currently open\n * @param onClose - Callback function called when the modal should be closed\n * @param title - The title displayed at the top of the modal\n * @param children - The main content of the modal\n * @param size - The size variant (xs, sm, md, lg, xl)\n * @param className - Additional CSS classes for the modal content\n * @param closeOnEscape - Whether pressing Escape closes the modal (default: true)\n * @param footer - Footer content, typically action buttons\n * @param hideCloseButton - Whether to hide the X close button (default: false)\n * @returns A modal overlay with content\n *\n * @example\n * ```tsx\n * <Modal\n * isOpen={isModalOpen}\n * onClose={() => setIsModalOpen(false)}\n * title=\"Invite your team\"\n * size=\"md\"\n * footer={\n * <div className=\"flex gap-3\">\n * <Button variant=\"outline\" onClick={() => setIsModalOpen(false)}>Cancel</Button>\n * <Button variant=\"solid\" onClick={handleExplore}>Explore</Button>\n * </div>\n * }\n * >\n * Elevate user interactions with our versatile modals.\n * </Modal>\n * ```\n */\nconst Modal = ({\n isOpen,\n onClose,\n title,\n children,\n size = 'md',\n className = '',\n closeOnEscape = true,\n footer,\n hideCloseButton = false,\n variant = 'default',\n description,\n image,\n imageAlt,\n actionLink,\n actionLabel,\n contentClassName = '',\n}: ModalProps) => {\n const titleId = useId();\n\n // Handle escape key\n useEffect(() => {\n if (!isOpen || !closeOnEscape) return;\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, closeOnEscape, onClose]);\n\n // Handle body scroll lock and scrollbar shift fix\n useEffect(() => {\n if (!isOpen) return;\n\n // Calculate scrollbar width before hiding overflow\n const scrollbarWidth =\n window.innerWidth - document.documentElement.clientWidth;\n\n // Save original styles\n const originalOverflow = document.body.style.overflow;\n const originalPaddingRight = document.body.style.paddingRight;\n\n // Apply scroll lock\n document.body.style.overflow = 'hidden';\n\n // Fix scrollbar shift: add padding to compensate for lost scrollbar\n if (scrollbarWidth > 0) {\n document.body.style.paddingRight = `${scrollbarWidth}px`;\n\n // Create overlay to cover the padding area with backdrop color\n const overlay = document.createElement('div');\n overlay.id = 'modal-scrollbar-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n right: 0;\n width: ${scrollbarWidth}px;\n height: 100vh;\n background-color: rgb(0 0 0 / 0.6);\n z-index: 40;\n pointer-events: none;\n `;\n document.body.appendChild(overlay);\n }\n\n return () => {\n // Restore original styles\n document.body.style.overflow = originalOverflow;\n document.body.style.paddingRight = originalPaddingRight;\n\n // Remove overlay\n const overlay = document.getElementById('modal-scrollbar-overlay');\n if (overlay) {\n overlay.remove();\n }\n };\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const sizeClasses = SIZE_CLASSES[size];\n const baseClasses =\n 'bg-secondary-50 rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4';\n // Reset dialog default styles to prevent positioning issues\n const dialogResetClasses =\n 'p-0 m-0 border-none outline-none max-h-none static';\n const modalClasses = cn(\n baseClasses,\n sizeClasses,\n dialogResetClasses,\n className\n );\n\n // Normalize URLs missing protocol\n const normalizeUrl = (href: string) =>\n /^https?:\\/\\//i.test(href) ? href : `https://${href}`;\n\n // Handle action link click\n const handleActionClick = () => {\n if (actionLink) {\n window.open(normalizeUrl(actionLink), '_blank', 'noopener,noreferrer');\n }\n };\n\n // Activity variant rendering\n if (variant === 'activity') {\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs border-none p-0 m-0 w-full cursor-default\">\n <dialog\n className={modalClasses}\n aria-labelledby={titleId}\n aria-modal=\"true\"\n open\n >\n {/* Header simples com X */}\n <div className=\"flex justify-end p-6 pb-0\">\n {!hideCloseButton && (\n <button\n onClick={onClose}\n className=\"p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2\"\n aria-label=\"Fechar modal\"\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Conteúdo centralizado */}\n <div className=\"flex flex-col items-center px-6 pb-6 gap-5\">\n {/* Imagem ilustrativa */}\n {image && (\n <div className=\"flex justify-center\">\n <img\n src={image}\n alt={imageAlt ?? ''}\n className=\"w-[122px] h-[122px] object-contain\"\n />\n </div>\n )}\n\n {/* Título */}\n <h2\n id={titleId}\n className=\"text-lg font-semibold text-text-950 text-center\"\n >\n {title}\n </h2>\n\n {/* Descrição */}\n {description && (\n <p className=\"text-sm font-normal text-text-400 text-center max-w-md leading-[21px]\">\n {description}\n </p>\n )}\n\n {/* Ação: Botão ou Vídeo Embedado */}\n {actionLink && (\n <div className=\"w-full\">\n {(() => {\n const normalized = normalizeUrl(actionLink);\n const isYT = isYouTubeUrl(normalized);\n if (!isYT) return null;\n const id = getYouTubeVideoId(normalized);\n if (!id) {\n return (\n <Button\n variant=\"solid\"\n action=\"primary\"\n size=\"large\"\n className=\"w-full\"\n onClick={handleActionClick}\n >\n {actionLabel || 'Iniciar Atividade'}\n </Button>\n );\n }\n return (\n <iframe\n src={getYouTubeEmbedUrl(id)}\n className=\"w-full aspect-video rounded-lg\"\n allowFullScreen\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n title=\"Vídeo YouTube\"\n />\n );\n })()}\n {!isYouTubeUrl(normalizeUrl(actionLink)) && (\n <Button\n variant=\"solid\"\n action=\"primary\"\n size=\"large\"\n className=\"w-full\"\n onClick={handleActionClick}\n >\n {actionLabel || 'Iniciar Atividade'}\n </Button>\n )}\n </div>\n )}\n </div>\n </dialog>\n </div>\n );\n }\n\n // Default variant rendering\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs border-none p-0 m-0 w-full cursor-default\">\n <dialog\n className={modalClasses}\n aria-labelledby={titleId}\n aria-modal=\"true\"\n open\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-6\">\n <h2 id={titleId} className=\"text-lg font-semibold text-text-950\">\n {title}\n </h2>\n {!hideCloseButton && (\n <button\n onClick={onClose}\n className=\"p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2\"\n aria-label=\"Fechar modal\"\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Content */}\n {children && (\n <div className={cn('px-6 pb-6', contentClassName)}>\n <div className=\"text-text-500 font-normal text-sm leading-6\">\n {children}\n </div>\n </div>\n )}\n\n {/* Footer */}\n {footer && (\n <div className=\"flex justify-end gap-3 px-6 pb-6\">{footer}</div>\n )}\n </dialog>\n </div>\n );\n};\n\nexport default Modal;\n","/**\n * Video utilities for Modal component\n *\n * Utilities to handle YouTube video embedding and URL detection\n */\n\n/**\n * Check if a given URL is a YouTube URL\n *\n * @param url - The URL to check\n * @returns true if the URL is from YouTube, false otherwise\n */\nexport const isYouTubeUrl = (url: string): boolean => {\n const youtubeRegex =\n /^(https?:\\/\\/)?((www|m|music)\\.)?(youtube\\.com|youtu\\.be|youtube-nocookie\\.com)\\/.+/i;\n return youtubeRegex.test(url);\n};\n\n/**\n * Validate if hostname is a legitimate YouTube host\n *\n * @param host - The hostname to validate\n * @returns The type of YouTube host or null if invalid\n */\nconst isValidYouTubeHost = (\n host: string\n): 'youtu.be' | 'youtube' | 'nocookie' | null => {\n if (host === 'youtu.be') return 'youtu.be';\n\n const isValidYouTubeCom =\n host === 'youtube.com' ||\n (host.endsWith('.youtube.com') &&\n /^(www|m|music)\\.youtube\\.com$/.test(host));\n\n if (isValidYouTubeCom) return 'youtube';\n\n const isValidNoCookie =\n host === 'youtube-nocookie.com' ||\n (host.endsWith('.youtube-nocookie.com') &&\n /^(www|m|music)\\.youtube-nocookie\\.com$/.test(host));\n\n if (isValidNoCookie) return 'nocookie';\n\n return null;\n};\n\n/**\n * Extract video ID from youtu.be path\n *\n * @param pathname - The URL pathname\n * @returns The video ID or null\n */\nconst extractYoutuBeId = (pathname: string): string | null => {\n const firstSeg = pathname.split('/').filter(Boolean)[0];\n return firstSeg || null;\n};\n\n/**\n * Extract video ID from YouTube or nocookie domains\n *\n * @param pathname - The URL pathname\n * @param searchParams - The URL search parameters\n * @returns The video ID or null\n */\nconst extractYouTubeId = (\n pathname: string,\n searchParams: URLSearchParams\n): string | null => {\n const parts = pathname.split('/').filter(Boolean);\n const [first, second] = parts;\n\n if (first === 'embed' && second) return second;\n if (first === 'shorts' && second) return second;\n if (first === 'live' && second) return second;\n\n const v = searchParams.get('v');\n if (v) return v;\n\n return null;\n};\n\n/**\n * Extract YouTube video ID from URL\n *\n * @param url - The YouTube URL\n * @returns The video ID if found, null otherwise\n */\nexport const getYouTubeVideoId = (url: string): string | null => {\n try {\n const u = new URL(url);\n const hostType = isValidYouTubeHost(u.hostname.toLowerCase());\n\n if (!hostType) return null;\n\n if (hostType === 'youtu.be') {\n return extractYoutuBeId(u.pathname);\n }\n\n return extractYouTubeId(u.pathname, u.searchParams);\n } catch {\n return null;\n }\n};\n\n/**\n * Generate YouTube embed URL for iframe\n *\n * @param videoId - The YouTube video ID\n * @returns The embed URL for the video\n */\nexport const getYouTubeEmbedUrl = (videoId: string): string => {\n return `https://www.youtube-nocookie.com/embed/${videoId}?autoplay=0&rel=0&modestbranding=1`;\n};\n","import { Moon, Sun } from 'phosphor-react';\nimport { useState, useEffect } from 'react';\nimport SelectionButton from '../SelectionButton/SelectionButton';\nimport type { ThemeMode } from '@/hooks/useTheme';\nimport { useTheme } from '../../hooks/useTheme';\n\ninterface ThemeToggleProps {\n variant?: 'default' | 'with-save';\n onToggle?: (theme: ThemeMode) => void;\n}\n\nexport const ThemeToggle = ({\n variant = 'default',\n onToggle,\n}: ThemeToggleProps) => {\n const { themeMode, setTheme } = useTheme();\n const [tempTheme, setTempTheme] = useState<ThemeMode>(themeMode);\n\n // Update temp theme when themeMode changes externally\n useEffect(() => {\n setTempTheme(themeMode);\n }, [themeMode]);\n\n const problemTypes = [\n {\n id: 'light' as ThemeMode,\n title: 'Claro',\n icon: <Sun size={24} />,\n },\n {\n id: 'dark' as ThemeMode,\n title: 'Escuro',\n icon: <Moon size={24} />,\n },\n {\n id: 'system' as ThemeMode,\n title: 'Sistema',\n icon: (\n <svg\n width=\"25\"\n height=\"25\"\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12.5 2.75C15.085 2.75276 17.5637 3.78054 19.3916 5.6084C21.2195 7.43628 22.2473 9.915 22.25 12.5C22.25 14.4284 21.6778 16.3136 20.6064 17.917C19.5352 19.5201 18.0128 20.7699 16.2314 21.5078C14.4499 22.2458 12.489 22.4387 10.5977 22.0625C8.70642 21.6863 6.96899 20.758 5.60547 19.3945C4.24197 18.031 3.31374 16.2936 2.9375 14.4023C2.56129 12.511 2.75423 10.5501 3.49219 8.76855C4.23012 6.98718 5.47982 5.46483 7.08301 4.39355C8.68639 3.32221 10.5716 2.75 12.5 2.75ZM11.75 4.28516C9.70145 4.47452 7.7973 5.42115 6.41016 6.94043C5.02299 8.4599 4.25247 10.4426 4.25 12.5C4.25247 14.5574 5.02299 16.5401 6.41016 18.0596C7.7973 19.5789 9.70145 20.5255 11.75 20.7148V4.28516Z\"\n fill=\"#525252\"\n />\n </svg>\n ),\n },\n ];\n\n const handleThemeSelect = (selectedTheme: ThemeMode) => {\n if (variant === 'with-save') {\n setTempTheme(selectedTheme);\n } else {\n setTheme(selectedTheme);\n }\n\n if (onToggle) {\n onToggle(selectedTheme);\n }\n };\n\n const currentTheme = variant === 'with-save' ? tempTheme : themeMode;\n\n return (\n <div className=\"flex flex-row gap-2 sm:gap-4 py-2\">\n {problemTypes.map((type) => (\n <SelectionButton\n key={type.id}\n icon={type.icon}\n label={type.title}\n selected={currentTheme === type.id}\n onClick={() => handleThemeSelect(type.id)}\n className=\"w-full p-2 sm:p-4\"\n />\n ))}\n </div>\n );\n};\n","import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * SelectionButton component props interface\n */\ntype SelectionButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Texto/label a ser exibido ao lado do ícone */\n label: string;\n /** Estado de seleção do botão */\n selected?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * SelectionButton component for Analytica Ensino platforms\n *\n * Um botão com ícone e texto para ações e navegação com estado de seleção.\n * Ideal para filtros, tags, categorias, seleção de tipos, etc.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param label - O texto/label a ser exibido\n * @param selected - Estado de seleção do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button estilizado\n *\n * @example\n * ```tsx\n * <SelectionButton\n * icon={<TagIcon />}\n * label=\"Categoria\"\n * selected={false}\n * onClick={() => handleSelection()}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para foco programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * const handleFocus = () => {\n * buttonRef.current?.focus();\n * };\n *\n * <SelectionButton\n * ref={buttonRef}\n * icon={<TagIcon />}\n * label=\"Categoria\"\n * selected={isSelected}\n * onClick={() => setSelected(!isSelected)}\n * />\n * ```\n */\nconst SelectionButton = forwardRef<HTMLButtonElement, SelectionButtonProps>(\n (\n { icon, label, selected = false, className = '', disabled, ...props },\n ref\n ) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'inline-flex',\n 'items-center',\n 'justify-start',\n 'gap-2',\n 'p-4',\n 'rounded-xl',\n 'cursor-pointer',\n 'border',\n 'border-border-50',\n 'bg-background',\n 'text-sm',\n 'text-text-700',\n 'font-bold',\n 'shadow-soft-shadow-1',\n 'hover:bg-background-100',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-indicator-info',\n 'focus-visible:ring-offset-0',\n 'focus-visible:shadow-none',\n 'active:ring-2',\n 'active:ring-primary-950',\n 'active:ring-offset-0',\n 'active:shadow-none',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n ];\n\n const stateClasses = selected\n ? ['ring-primary-950', 'ring-2', 'ring-offset-0', 'shadow-none']\n : [];\n\n const allClasses = [...baseClasses, ...stateClasses].join(' ');\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(allClasses, className)}\n disabled={disabled}\n aria-pressed={selected}\n {...props}\n >\n <span className=\"flex items-center justify-center w-6 h-6\">{icon}</span>\n <span>{label}</span>\n </button>\n );\n }\n);\n\nSelectionButton.displayName = 'SelectionButton';\n\nexport default SelectionButton;\n","import { useEffect } from 'react';\nimport { useThemeStore, ThemeMode } from '../store/themeStore';\n\nexport type { ThemeMode };\n\n/**\n * Hook para gerenciar temas com suporte a alternância manual e detecção automática do sistema\n * Este hook permite alternar entre temas light, dark e automático baseado nas preferências do sistema\n * Utiliza Zustand para persistir o estado entre múltiplos arquivos e sessões\n */\nexport const useTheme = () => {\n const {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n initializeTheme,\n handleSystemThemeChange,\n } = useThemeStore();\n\n useEffect(() => {\n // Initialize theme on first render\n initializeTheme();\n\n // Listener para mudanças nas preferências do sistema (apenas quando mode é 'system')\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n\n mediaQuery.addEventListener('change', handleSystemThemeChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleSystemThemeChange);\n };\n }, [initializeTheme, handleSystemThemeChange]);\n\n return {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n };\n};\n","import { create } from 'zustand';\nimport { devtools, persist } from 'zustand/middleware';\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\n\n/**\n * Theme store state interface\n */\nexport interface ThemeState {\n /**\n * Current theme mode\n */\n themeMode: ThemeMode;\n /**\n * Whether the current theme is dark\n */\n isDark: boolean;\n}\n\n/**\n * Theme store actions interface\n */\nexport interface ThemeActions {\n /**\n * Apply theme based on the mode selected\n */\n applyTheme: (mode: ThemeMode) => void;\n /**\n * Toggle between themes\n */\n toggleTheme: () => void;\n /**\n * Set a specific theme mode\n */\n setTheme: (mode: ThemeMode) => void;\n /**\n * Initialize theme on app start\n */\n initializeTheme: () => void;\n /**\n * Handle system theme change\n */\n handleSystemThemeChange: () => void;\n}\n\nexport type ThemeStore = ThemeState & ThemeActions;\n\n/**\n * Apply theme to DOM based on mode\n */\nconst applyThemeToDOM = (mode: ThemeMode): boolean => {\n const htmlElement = document.documentElement;\n const originalTheme = htmlElement.getAttribute('data-original-theme');\n\n if (mode === 'dark') {\n htmlElement.setAttribute('data-theme', 'dark');\n return true;\n } else if (mode === 'light') {\n if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n }\n return false;\n } else if (mode === 'system') {\n const isSystemDark = window.matchMedia(\n '(prefers-color-scheme: dark)'\n ).matches;\n if (isSystemDark) {\n htmlElement.setAttribute('data-theme', 'dark');\n return true;\n } else if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n return false;\n }\n }\n return false;\n};\n\n/**\n * Save original theme from white label\n */\nconst saveOriginalTheme = () => {\n const htmlElement = document.documentElement;\n const currentTheme = htmlElement.getAttribute('data-theme');\n if (currentTheme && !htmlElement.getAttribute('data-original-theme')) {\n htmlElement.setAttribute('data-original-theme', currentTheme);\n }\n};\n\n/**\n * Theme store using Zustand with persistence\n */\nexport const useThemeStore = create<ThemeStore>()(\n devtools(\n persist(\n (set, get) => ({\n // Initial state\n themeMode: 'system',\n isDark: false,\n\n // Actions\n applyTheme: (mode: ThemeMode) => {\n const isDark = applyThemeToDOM(mode);\n set({ isDark });\n },\n\n toggleTheme: () => {\n const { themeMode, applyTheme } = get();\n let newMode: ThemeMode;\n\n if (themeMode === 'light') {\n newMode = 'dark';\n } else if (themeMode === 'dark') {\n newMode = 'light';\n } else {\n // Se estiver em 'system', vai para 'dark'\n newMode = 'dark';\n }\n\n set({ themeMode: newMode });\n applyTheme(newMode);\n },\n\n setTheme: (mode: ThemeMode) => {\n const { applyTheme } = get();\n set({ themeMode: mode });\n applyTheme(mode);\n },\n\n initializeTheme: () => {\n const { themeMode, applyTheme } = get();\n\n // Save original theme from white label\n saveOriginalTheme();\n\n // Apply the current theme mode\n applyTheme(themeMode);\n },\n\n handleSystemThemeChange: () => {\n const { themeMode, applyTheme } = get();\n // Only respond to system changes when in system mode\n if (themeMode === 'system') {\n applyTheme('system');\n }\n },\n }),\n {\n name: 'theme-store', // Nome da chave no localStorage\n partialize: (state) => ({\n themeMode: state.themeMode,\n }), // Só persiste o themeMode, não o isDark\n }\n ),\n {\n name: 'theme-store',\n }\n )\n);\n","import { forwardRef, HTMLAttributes, CSSProperties } from 'react';\nimport { cn } from '../../utils/utils';\n\ninterface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n variant?: 'text' | 'circular' | 'rectangular' | 'rounded';\n width?: string | number;\n height?: string | number;\n animation?: 'pulse' | 'none';\n lines?: number;\n spacing?: 'none' | 'small' | 'medium' | 'large';\n}\n\nconst SKELETON_ANIMATION_CLASSES = {\n pulse: 'animate-pulse',\n none: '',\n};\n\nconst SKELETON_VARIANT_CLASSES = {\n text: 'h-4 bg-background-200 rounded',\n circular: 'bg-background-200 rounded-full',\n rectangular: 'bg-background-200',\n rounded: 'bg-background-200 rounded-lg',\n};\n\nconst SPACING_CLASSES = {\n none: '',\n small: 'space-y-1',\n medium: 'space-y-2',\n large: 'space-y-3',\n};\n\nconst Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n (\n {\n variant = 'text',\n width,\n height,\n animation = 'pulse',\n lines = 1,\n spacing = 'none',\n className = '',\n children,\n ...props\n },\n ref\n ) => {\n const animationClass = SKELETON_ANIMATION_CLASSES[animation];\n const variantClass = SKELETON_VARIANT_CLASSES[variant];\n const spacingClass = SPACING_CLASSES[spacing];\n\n const style: CSSProperties = {\n width: typeof width === 'number' ? `${width}px` : width,\n height: typeof height === 'number' ? `${height}px` : height,\n };\n\n // Se for múltiplas linhas de texto\n if (variant === 'text' && lines > 1) {\n return (\n <div\n ref={ref}\n className={cn('flex flex-col', spacingClass, className)}\n {...props}\n >\n {Array.from({ length: lines }, (_, index) => (\n <div\n key={index}\n className={cn(variantClass, animationClass)}\n style={index === lines - 1 ? { width: '60%' } : undefined}\n />\n ))}\n </div>\n );\n }\n\n // Se for um único elemento\n return (\n <div\n ref={ref}\n className={cn(variantClass, animationClass, className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\n// Componentes específicos para casos comuns\nconst SkeletonText = forwardRef<HTMLDivElement, Omit<SkeletonProps, 'variant'>>(\n (props, ref) => <Skeleton ref={ref} variant=\"text\" {...props} />\n);\n\nconst SkeletonCircle = forwardRef<\n HTMLDivElement,\n Omit<SkeletonProps, 'variant'>\n>((props, ref) => <Skeleton ref={ref} variant=\"circular\" {...props} />);\n\nconst SkeletonRectangle = forwardRef<\n HTMLDivElement,\n Omit<SkeletonProps, 'variant'>\n>((props, ref) => <Skeleton ref={ref} variant=\"rectangular\" {...props} />);\n\nconst SkeletonRounded = forwardRef<\n HTMLDivElement,\n Omit<SkeletonProps, 'variant'>\n>((props, ref) => <Skeleton ref={ref} variant=\"rounded\" {...props} />);\n\n// Componente para card skeleton\ninterface SkeletonCardProps extends HTMLAttributes<HTMLDivElement> {\n showAvatar?: boolean;\n showTitle?: boolean;\n showDescription?: boolean;\n showActions?: boolean;\n lines?: number;\n}\n\nconst SkeletonCard = forwardRef<HTMLDivElement, SkeletonCardProps>(\n (\n {\n showAvatar = true,\n showTitle = true,\n showDescription = true,\n showActions = true,\n lines = 2,\n className = '',\n ...props\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'w-full p-4 bg-background border border-border-200 rounded-lg',\n className\n )}\n {...props}\n >\n <div className=\"flex items-start space-x-3\">\n {showAvatar && <SkeletonCircle width={40} height={40} />}\n\n <div className=\"flex-1 space-y-2\">\n {showTitle && <SkeletonText width=\"60%\" height={20} />}\n\n {showDescription && <SkeletonText lines={lines} spacing=\"small\" />}\n </div>\n </div>\n\n {showActions && (\n <div className=\"flex justify-end space-x-2 mt-4\">\n <SkeletonRectangle width={80} height={32} />\n <SkeletonRectangle width={80} height={32} />\n </div>\n )}\n </div>\n );\n }\n);\n\n// Componente para lista skeleton\ninterface SkeletonListProps extends HTMLAttributes<HTMLDivElement> {\n items?: number;\n showAvatar?: boolean;\n showTitle?: boolean;\n showDescription?: boolean;\n lines?: number;\n}\n\nconst SkeletonList = forwardRef<HTMLDivElement, SkeletonListProps>(\n (\n {\n items = 3,\n showAvatar = true,\n showTitle = true,\n showDescription = true,\n lines = 1,\n className = '',\n ...props\n },\n ref\n ) => {\n return (\n <div ref={ref} className={cn('space-y-3', className)} {...props}>\n {Array.from({ length: items }, (_, index) => (\n <div key={index} className=\"flex items-start space-x-3 p-3\">\n {showAvatar && <SkeletonCircle width={32} height={32} />}\n\n <div className=\"flex-1 space-y-2\">\n {showTitle && <SkeletonText width=\"40%\" height={16} />}\n\n {showDescription && (\n <SkeletonText lines={lines} spacing=\"small\" />\n )}\n </div>\n </div>\n ))}\n </div>\n );\n }\n);\n\n// Componente para tabela skeleton\ninterface SkeletonTableProps extends HTMLAttributes<HTMLDivElement> {\n rows?: number;\n columns?: number;\n showHeader?: boolean;\n}\n\nconst SkeletonTable = forwardRef<HTMLDivElement, SkeletonTableProps>(\n (\n { rows = 5, columns = 4, showHeader = true, className = '', ...props },\n ref\n ) => {\n return (\n <div ref={ref} className={cn('w-full', className)} {...props}>\n {showHeader && (\n <div className=\"flex space-x-2 mb-3\">\n {Array.from({ length: columns }, (_, index) => (\n <SkeletonText\n key={index}\n width={`${100 / columns}%`}\n height={20}\n />\n ))}\n </div>\n )}\n\n <div className=\"space-y-2\">\n {Array.from({ length: rows }, (_, rowIndex) => (\n <div key={rowIndex} className=\"flex space-x-2\">\n {Array.from({ length: columns }, (_, colIndex) => (\n <SkeletonText\n key={colIndex}\n width={`${100 / columns}%`}\n height={16}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n }\n);\n\nexport {\n Skeleton,\n SkeletonText,\n SkeletonCircle,\n SkeletonRectangle,\n SkeletonRounded,\n SkeletonCard,\n SkeletonList,\n SkeletonTable,\n};\n","import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * IconButton component props interface\n */\nexport type IconButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Tamanho do botão */\n size?: 'sm' | 'md';\n /** Estado de seleção/ativo do botão - permanece ativo até ser clicado novamente ou outro botão ser ativado */\n active?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * IconButton component for Analytica Ensino platforms\n *\n * Um botão compacto apenas com ícone, ideal para menus dropdown,\n * barras de ferramentas e ações secundárias.\n * Oferece dois tamanhos com estilo consistente.\n * Estado ativo permanece até ser clicado novamente ou outro botão ser ativado.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param size - Tamanho do botão (sm, md)\n * @param active - Estado ativo/selecionado do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button compacto estilizado apenas com ícone\n *\n * @example\n * ```tsx\n * <IconButton\n * icon={<MoreVerticalIcon />}\n * size=\"sm\"\n * onClick={() => openMenu()}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Botão ativo em uma barra de ferramentas - permanece ativo até outro clique\n * <IconButton\n * icon={<BoldIcon />}\n * active={isBold}\n * onClick={toggleBold}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para controle programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * <IconButton\n * ref={buttonRef}\n * icon={<EditIcon />}\n * size=\"md\"\n * onClick={() => startEditing()}\n * />\n * ```\n */\nconst IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n { icon, size = 'md', active = false, className = '', disabled, ...props },\n ref\n ) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'inline-flex',\n 'items-center',\n 'justify-center',\n 'rounded-lg',\n 'font-medium',\n 'bg-transparent',\n 'text-text-950',\n 'cursor-pointer',\n 'hover:bg-primary-600',\n 'hover:text-text',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-0',\n 'focus-visible:ring-indicator-info',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n 'disabled:pointer-events-none',\n ];\n\n // Classes de tamanho\n const sizeClasses = {\n sm: ['w-6', 'h-6', 'text-sm'],\n md: ['w-10', 'h-10', 'text-base'],\n };\n\n // Classes de estado ativo\n const activeClasses = active\n ? ['!bg-primary-50', '!text-primary-950', 'hover:!bg-primary-100']\n : [];\n\n const allClasses = [\n ...baseClasses,\n ...sizeClasses[size],\n ...activeClasses,\n ].join(' ');\n\n // Garantir acessibilidade com aria-label padrão\n const ariaLabel = props['aria-label'] ?? 'Botão de ação';\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(allClasses, className)}\n disabled={disabled}\n aria-pressed={active}\n aria-label={ariaLabel}\n {...props}\n >\n <span className=\"flex items-center justify-center\">{icon}</span>\n </button>\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n\nexport default IconButton;\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 { useState, useEffect } from 'react';\n\n// Mobile width in pixels\nconst MOBILE_WIDTH = 500;\n// Tablet width in pixels\nconst TABLET_WIDTH = 931;\n// Video responsive breakpoints\nconst SMALL_MOBILE_WIDTH = 425;\nconst EXTRA_SMALL_MOBILE_WIDTH = 375;\nconst ULTRA_SMALL_MOBILE_WIDTH = 375; // For video controls\nconst TINY_MOBILE_WIDTH = 320;\n// Default desktop width for SSR\nconst DEFAULT_WIDTH = 1200;\n\n/**\n * Device type based on screen width\n */\nexport type DeviceType = 'responsive' | 'desktop';\n\n/**\n * Gets the window width safely (SSR compatible)\n * @returns {number} window width or default value for SSR\n */\nconst getWindowWidth = (): number => {\n if (typeof window === 'undefined') {\n return DEFAULT_WIDTH;\n }\n return window.innerWidth;\n};\n\n/**\n * Gets the current device type based on screen width\n * @returns {DeviceType} 'responsive' for mobile/tablet (width < 931px), 'desktop' for larger screens\n */\nexport const getDeviceType = (): DeviceType => {\n const width = getWindowWidth();\n return width < TABLET_WIDTH ? 'responsive' : 'desktop';\n};\n\n/**\n * Hook to detect screen size and get responsive classes\n * @returns object with isMobile, isTablet, responsive class functions and getDeviceType\n */\nexport const useMobile = () => {\n const [isMobile, setIsMobile] = useState(false);\n const [isTablet, setIsTablet] = useState(false);\n const [isSmallMobile, setIsSmallMobile] = useState(false);\n const [isExtraSmallMobile, setIsExtraSmallMobile] = useState(false);\n const [isUltraSmallMobile, setIsUltraSmallMobile] = useState(false);\n const [isTinyMobile, setIsTinyMobile] = useState(false);\n\n useEffect(() => {\n const checkScreenSize = () => {\n const width = getWindowWidth();\n setIsMobile(width < MOBILE_WIDTH);\n setIsTablet(width < TABLET_WIDTH);\n setIsSmallMobile(width < SMALL_MOBILE_WIDTH);\n setIsExtraSmallMobile(width < EXTRA_SMALL_MOBILE_WIDTH);\n setIsUltraSmallMobile(width < ULTRA_SMALL_MOBILE_WIDTH);\n setIsTinyMobile(width < TINY_MOBILE_WIDTH);\n };\n\n checkScreenSize();\n\n window.addEventListener('resize', checkScreenSize);\n\n return () => window.removeEventListener('resize', checkScreenSize);\n }, []);\n\n /**\n * Get responsive classes for the form container\n * @returns className string for form container based on screen size\n */\n const getFormContainerClasses = (): string => {\n if (isMobile) {\n return 'w-full px-4';\n }\n if (isTablet) {\n return 'w-full px-6';\n }\n return 'w-full max-w-[992px] mx-auto px-0';\n };\n\n /**\n * Get mobile-specific classes for the header\n * @returns className string for mobile header layout\n */\n const getMobileHeaderClasses = (): string => {\n return 'flex flex-col items-start gap-4 mb-6';\n };\n\n /**\n * Get desktop-specific classes for the header\n * @returns className string for desktop header layout\n */\n const getDesktopHeaderClasses = (): string => {\n return 'flex flex-row justify-between items-center gap-6 mb-8';\n };\n\n /**\n * Get responsive classes for the header\n * @returns className string for header based on screen size\n */\n const getHeaderClasses = (): string => {\n return isMobile ? getMobileHeaderClasses() : getDesktopHeaderClasses();\n };\n\n /**\n * Get responsive classes for video container\n * @returns className string for video container aspect ratio based on screen size\n */\n const getVideoContainerClasses = (): string => {\n if (isTinyMobile) return 'aspect-square'; // 1:1 ratio for screens < 320px\n if (isExtraSmallMobile) return 'aspect-[4/3]'; // 4:3 ratio for screens < 375px\n if (isSmallMobile) return 'aspect-[16/12]'; // 16:12 ratio for screens < 425px\n return 'aspect-video'; // 16:9 ratio for larger screens\n };\n\n return {\n isMobile,\n isTablet,\n isSmallMobile,\n isExtraSmallMobile,\n isUltraSmallMobile,\n isTinyMobile,\n getFormContainerClasses,\n getHeaderClasses,\n getMobileHeaderClasses,\n getDesktopHeaderClasses,\n getVideoContainerClasses,\n getDeviceType,\n };\n};\n","import { create } from 'zustand';\nimport { devtools } from 'zustand/middleware';\nimport {\n Notification,\n NotificationGroup,\n FetchNotificationsParams,\n BackendNotificationsResponse,\n BackendNotification,\n NotificationEntityType,\n NotificationType,\n NotificationApiClient,\n} from '../types/notifications';\n\n/**\n * Notification store state interface\n */\nexport interface NotificationState {\n /**\n * List of all notifications\n */\n notifications: Notification[];\n /**\n * Number of unread notifications\n */\n unreadCount: number;\n /**\n * Loading state\n */\n loading: boolean;\n /**\n * Error state\n */\n error: string | null;\n /**\n * Whether there are more notifications to load\n */\n hasMore: boolean;\n /**\n * Current page for pagination\n */\n currentPage: number;\n}\n\n/**\n * Notification store actions interface\n */\nexport interface NotificationActions {\n /**\n * Fetch notifications from API\n */\n fetchNotifications: (params?: FetchNotificationsParams) => Promise<void>;\n /**\n * Mark a specific notification as read\n */\n markAsRead: (id: string) => Promise<void>;\n /**\n * Mark all notifications as read\n */\n markAllAsRead: () => Promise<void>;\n /**\n * Delete a notification\n */\n deleteNotification: (id: string) => Promise<void>;\n /**\n * Clear all notifications\n */\n clearNotifications: () => void;\n /**\n * Reset error state\n */\n resetError: () => void;\n /**\n * Group notifications by time periods\n */\n getGroupedNotifications: () => NotificationGroup[];\n}\n\nexport type NotificationStore = NotificationState & NotificationActions;\n\n/**\n * Convert backend notification to frontend format\n */\nconst mapBackendNotification = (\n backendNotification: BackendNotification\n): Notification => {\n let type: NotificationType = 'GENERAL';\n let entityType: NotificationEntityType | null = null;\n\n if (backendNotification.entityType) {\n // Convert to uppercase for comparison since backend returns lowercase\n const backendEntityType = backendNotification.entityType.toUpperCase();\n\n switch (backendEntityType) {\n case NotificationEntityType.ACTIVITY:\n type = 'ACTIVITY';\n entityType = NotificationEntityType.ACTIVITY;\n break;\n case NotificationEntityType.TRAIL:\n type = 'TRAIL';\n entityType = NotificationEntityType.TRAIL;\n break;\n case NotificationEntityType.GOAL:\n type = 'GOAL';\n entityType = NotificationEntityType.GOAL;\n break;\n default:\n break;\n }\n }\n\n return {\n id: backendNotification.id,\n title: backendNotification.title,\n message: backendNotification.description,\n type,\n isRead: backendNotification.read,\n createdAt: new Date(backendNotification.createdAt),\n entityType,\n entityId: backendNotification.entityId,\n sender: backendNotification.sender,\n activity: backendNotification.activity,\n goal: backendNotification.goal,\n actionLink: backendNotification.actionLink ?? null,\n };\n};\n\n/**\n * Group notifications by time periods\n */\nconst groupNotificationsByTime = (\n notifications: Notification[]\n): NotificationGroup[] => {\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const lastWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);\n const sortDesc = (a: Notification, b: Notification) =>\n +new Date(b.createdAt) - +new Date(a.createdAt);\n\n const todayNotifications = notifications\n .filter((notification) => new Date(notification.createdAt) >= today)\n .sort(sortDesc);\n\n const lastWeekNotifications = notifications\n .filter(\n (notification) =>\n new Date(notification.createdAt) >= lastWeek &&\n new Date(notification.createdAt) < today\n )\n .sort(sortDesc);\n\n const olderNotifications = notifications\n .filter((notification) => new Date(notification.createdAt) < lastWeek)\n .sort(sortDesc);\n\n const groups: NotificationGroup[] = [];\n\n if (todayNotifications.length > 0) {\n groups.push({\n label: 'Hoje',\n notifications: todayNotifications,\n });\n }\n\n if (lastWeekNotifications.length > 0) {\n groups.push({\n label: 'Última semana',\n notifications: lastWeekNotifications,\n });\n }\n\n if (olderNotifications.length > 0) {\n groups.push({\n label: 'Mais antigas',\n notifications: olderNotifications,\n });\n }\n\n return groups;\n};\n\n/**\n * Format time relative to now\n */\nexport const formatTimeAgo = (date: Date): string => {\n const now = new Date();\n const diffInMs = now.getTime() - new Date(date).getTime();\n const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60));\n const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));\n\n if (diffInHours < 24) {\n return `Há ${diffInHours}h`;\n } else if (diffInDays < 30) {\n const day = new Date(date).getDate();\n const months = [\n 'Jan',\n 'Fev',\n 'Mar',\n 'Abr',\n 'Mai',\n 'Jun',\n 'Jul',\n 'Ago',\n 'Set',\n 'Out',\n 'Nov',\n 'Dez',\n ];\n const month = months[new Date(date).getMonth()];\n return `${day} ${month}`;\n }\n\n return new Date(date).toLocaleDateString('pt-BR');\n};\n\n/**\n * Create notification store with injected API client\n */\nexport const createNotificationStore = (apiClient: NotificationApiClient) => {\n return create<NotificationStore>()(\n devtools(\n (set, get) => ({\n // Initial state\n notifications: [],\n unreadCount: 0,\n loading: false,\n error: null,\n hasMore: true,\n currentPage: 1,\n\n // Actions\n fetchNotifications: async (params: FetchNotificationsParams = {}) => {\n set({ loading: true, error: null });\n\n try {\n const response = await apiClient.get<BackendNotificationsResponse>(\n '/notifications',\n { params: { ...params } }\n );\n\n const mappedNotifications = response.data.notifications.map(\n mapBackendNotification\n );\n\n const page = response.data.pagination.page;\n const totalPages = response.data.pagination.totalPages;\n const merged =\n params.page && params.page > 1\n ? [...get().notifications, ...mappedNotifications]\n : mappedNotifications;\n // de-dup by id\n const deduped = Array.from(\n new Map(merged.map((n) => [n.id, n])).values()\n );\n\n set({\n notifications: deduped,\n unreadCount: deduped.filter((n) => !n.isRead).length,\n hasMore: page < totalPages,\n currentPage: page,\n loading: false,\n });\n } catch (error) {\n console.error('Error fetching notifications:', error);\n set({\n error: 'Erro ao carregar notificações',\n loading: false,\n });\n }\n },\n\n markAsRead: async (id: string) => {\n const { notifications } = get();\n\n // Find the notification to check if it's already read\n const notification = notifications.find((n) => n.id === id);\n\n // If notification is already read, just return without making API call\n if (notification?.isRead) {\n return;\n }\n\n try {\n await apiClient.patch(`/notifications/${id}`, { read: true });\n\n const updatedNotifications = notifications.map((notification) =>\n notification.id === id\n ? { ...notification, isRead: true }\n : notification\n );\n\n const unreadCount = updatedNotifications.filter(\n (n) => !n.isRead\n ).length;\n\n set({\n notifications: updatedNotifications,\n unreadCount,\n });\n } catch (error) {\n console.error('Error marking notification as read:', error);\n set({ error: 'Erro ao marcar notificação como lida' });\n }\n },\n\n markAllAsRead: async () => {\n const { notifications } = get();\n\n try {\n // Mark all unread notifications as read\n const unreadNotifications = notifications.filter((n) => !n.isRead);\n\n await Promise.all(\n unreadNotifications.map((notification) =>\n apiClient.patch(`/notifications/${notification.id}`, {\n read: true,\n })\n )\n );\n\n const updatedNotifications = notifications.map((notification) => ({\n ...notification,\n isRead: true,\n }));\n\n set({\n notifications: updatedNotifications,\n unreadCount: 0,\n });\n } catch (error) {\n console.error('Error marking all notifications as read:', error);\n set({ error: 'Erro ao marcar todas as notificações como lidas' });\n }\n },\n\n deleteNotification: async (id: string) => {\n const { notifications } = get();\n\n try {\n await apiClient.delete(`/notifications/${id}`);\n\n const updatedNotifications = notifications.filter(\n (notification) => notification.id !== id\n );\n\n const unreadCount = updatedNotifications.filter(\n (n) => !n.isRead\n ).length;\n\n set({\n notifications: updatedNotifications,\n unreadCount,\n });\n } catch (error) {\n console.error('Error deleting notification:', error);\n set({ error: 'Erro ao deletar notificação' });\n }\n },\n\n clearNotifications: () => {\n set({\n notifications: [],\n unreadCount: 0,\n hasMore: false,\n currentPage: 1,\n });\n },\n\n resetError: () => {\n set({ error: null });\n },\n\n getGroupedNotifications: () => {\n const { notifications } = get();\n return groupNotificationsByTime(notifications);\n },\n }),\n {\n name: 'notification-store',\n }\n )\n );\n};\n"],"mappings":"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","names":["import_phosphor_react","import_react","import_phosphor_react","import_react","import_zustand","import_jsx_runtime","import_jsx_runtime","SIZE_CLASSES","import_phosphor_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","_","import_react","import_jsx_runtime","import_phosphor_react","import_jsx_runtime","VARIANT_ACTION_CLASSES","SIZE_CLASSES","import_react","import_zustand","import_middleware","import_jsx_runtime"]}