{"version":3,"sources":["../../src/components/ThemeToggle/ThemeToggle.tsx","../../src/components/SelectionButton/SelectionButton.tsx","../../src/utils/utils.ts","../../src/hooks/useTheme.ts","../../src/store/themeStore.ts"],"sourcesContent":["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 { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n\nexport { syncDropdownState } from './dropdown';\nexport {\n  getSelectedIdsFromCategories,\n  toggleArrayItem,\n  toggleSingleValue,\n  areFiltersEqual,\n} from './activityFilters';\nexport {\n  mapQuestionTypeToEnum,\n  mapQuestionTypeToEnumRequired,\n} from './questionTypeUtils';\nexport {\n  getStatusBadgeConfig,\n  formatTimeSpent,\n  formatQuestionNumbers,\n  formatDateToBrazilian,\n} from './activityDetailsUtils';\n\n/**\n * 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 { 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"],"mappings":"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","names":["useEffect","jsx","useEffect"]}