analytica-frontend-lib 1.1.53 → 1.1.55
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.
- package/dist/DropdownMenu/index.d.mts +5 -1
- package/dist/DropdownMenu/index.d.ts +5 -1
- package/dist/DropdownMenu/index.js +606 -37
- package/dist/DropdownMenu/index.js.map +1 -1
- package/dist/DropdownMenu/index.mjs +605 -37
- package/dist/DropdownMenu/index.mjs.map +1 -1
- package/dist/Modal/index.d.mts +14 -5
- package/dist/Modal/index.d.ts +14 -5
- package/dist/Modal/index.js +216 -31
- package/dist/Modal/index.js.map +1 -1
- package/dist/Modal/index.mjs +217 -32
- package/dist/Modal/index.mjs.map +1 -1
- package/dist/Modal/utils/videoUtils/index.d.mts +28 -0
- package/dist/Modal/utils/videoUtils/index.d.ts +28 -0
- package/dist/Modal/utils/videoUtils/index.js +76 -0
- package/dist/Modal/utils/videoUtils/index.js.map +1 -0
- package/dist/Modal/utils/videoUtils/index.mjs +49 -0
- package/dist/Modal/utils/videoUtils/index.mjs.map +1 -0
- package/dist/NotificationCard/index.js +716 -295
- package/dist/NotificationCard/index.js.map +1 -1
- package/dist/NotificationCard/index.mjs +713 -292
- package/dist/NotificationCard/index.mjs.map +1 -1
- package/dist/Quiz/index.js +154 -26
- package/dist/Quiz/index.js.map +1 -1
- package/dist/Quiz/index.mjs +166 -38
- package/dist/Quiz/index.mjs.map +1 -1
- package/dist/Search/index.js +625 -58
- package/dist/Search/index.js.map +1 -1
- package/dist/Search/index.mjs +628 -61
- package/dist/Search/index.mjs.map +1 -1
- package/dist/ThemeToggle/index.d.mts +8 -49
- package/dist/ThemeToggle/index.d.ts +8 -49
- package/dist/ThemeToggle/index.js +128 -114
- package/dist/ThemeToggle/index.js.map +1 -1
- package/dist/ThemeToggle/index.mjs +119 -105
- package/dist/ThemeToggle/index.mjs.map +1 -1
- package/dist/hooks/useTheme/index.d.mts +1 -1
- package/dist/hooks/useTheme/index.d.ts +1 -1
- package/dist/hooks/useTheme/index.js.map +1 -1
- package/dist/hooks/useTheme/index.mjs.map +1 -1
- package/dist/index.css +10 -39
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +995 -825
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1083 -914
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +10 -39
- package/dist/styles.css.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ThemeToggle/ThemeToggle.tsx","../../src/utils/utils.ts","../../src/hooks/useTheme.ts"],"sourcesContent":["import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\nimport { useTheme } from '../../hooks/useTheme';\n\n/**\n * ThemeToggle component props interface\n */\nexport type ThemeToggleProps = {\n /** Modo de exibição do toggle */\n variant?: 'simple' | 'detailed' | 'buttons';\n /** Tamanho do componente */\n size?: 'sm' | 'md' | 'lg';\n /** Mostrar ícones nos botões */\n showIcons?: boolean;\n /** Mostrar labels nos botões */\n showLabels?: boolean;\n /** Classes CSS adicionais */\n className?: string;\n /** Conteúdo customizado para o botão simples */\n children?: ReactNode;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'>;\n\n/**\n * ThemeToggle component for Analytica Ensino platforms\n *\n * Componente para alternar entre temas light, dark e system.\n * Oferece diferentes variantes de exibição e tamanhos.\n * Integra com o hook useTheme para gerenciamento de estado.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param variant - Modo de exibição (simple, detailed, buttons)\n * @param size - Tamanho do componente (sm, md, lg)\n * @param showIcons - Mostrar ícones nos botões\n * @param showLabels - Mostrar labels nos botões\n * @param className - Classes CSS adicionais\n * @param children - Conteúdo customizado para o botão simples\n */\nexport const ThemeToggle = forwardRef<HTMLButtonElement, ThemeToggleProps>(\n (\n {\n variant = 'simple',\n size = 'md',\n showIcons = true,\n showLabels = true,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const { themeMode, isDark, toggleTheme, setTheme } = useTheme();\n\n // Classes base para tamanhos\n const sizeClasses = {\n sm: 'text-sm px-3 py-1.5',\n md: 'text-md px-4 py-2',\n lg: 'text-lg px-5 py-2.5',\n };\n\n // Classes para botões ativos\n const activeClasses = 'bg-primary-500 text-white';\n const inactiveClasses =\n 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600';\n\n // Classes base para botões\n const baseButtonClasses =\n 'inline-flex items-center justify-center gap-2 rounded-md border border-gray-300 dark:border-gray-600 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500';\n const smallButtonClasses =\n 'px-3 py-1.5 rounded-md text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500';\n\n // Função para renderizar botão de tema\n const renderThemeButton = (\n theme: 'light' | 'dark' | 'system',\n icon: string,\n label: string,\n isActive: boolean,\n buttonSize?: 'sm' | 'md' | 'lg'\n ) => {\n const buttonClasses = buttonSize\n ? cn(baseButtonClasses, sizeClasses[buttonSize])\n : smallButtonClasses;\n const stateClasses = isActive ? activeClasses : inactiveClasses;\n\n return (\n <button\n type=\"button\"\n onClick={() => setTheme(theme)}\n className={cn(buttonClasses, stateClasses)}\n {...(buttonSize ? props : {})}\n >\n {showIcons && icon}\n {showLabels && label}\n </button>\n );\n };\n\n // Renderizar botão simples\n if (variant === 'simple') {\n return (\n <button\n type=\"button\"\n ref={ref}\n onClick={toggleTheme}\n className={cn(\n 'inline-flex items-center justify-center gap-2 rounded-md border border-gray-300 dark:border-gray-600 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',\n sizeClasses[size],\n className\n )}\n {...props}\n >\n {children || (\n <>\n {showIcons && (isDark ? '☀️' : '🌙')}\n {showLabels && (isDark ? 'Claro' : 'Escuro')}\n </>\n )}\n </button>\n );\n }\n\n // Renderizar botões detalhados\n if (variant === 'detailed') {\n const getLabel = () => {\n if (themeMode === 'system') return 'Sistema';\n if (isDark) return 'Escuro';\n return 'Claro';\n };\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n <div className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n Tema: {getLabel()}\n </div>\n <div className=\"flex gap-1\">\n {renderThemeButton('light', '☀️ ', 'Claro', themeMode === 'light')}\n {renderThemeButton('dark', '🌙 ', 'Escuro', themeMode === 'dark')}\n {renderThemeButton(\n 'system',\n '⚙️ ',\n 'Sistema',\n themeMode === 'system'\n )}\n </div>\n </div>\n );\n }\n\n // Renderizar botões separados\n if (variant === 'buttons') {\n return (\n <div className={cn('flex gap-2', className)}>\n {renderThemeButton(\n 'light',\n '☀️',\n 'Claro',\n themeMode === 'light',\n size\n )}\n {renderThemeButton(\n 'dark',\n '🌙',\n 'Escuro',\n themeMode === 'dark',\n size\n )}\n {renderThemeButton(\n 'system',\n '⚙️',\n 'Sistema',\n themeMode === 'system',\n size\n )}\n </div>\n );\n }\n\n return null;\n }\n);\n\nThemeToggle.displayName = 'ThemeToggle';\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","import { useEffect, useState, useCallback, useRef } from 'react';\n\ntype ThemeMode = 'light' | 'dark' | 'system';\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 */\nexport const useTheme = () => {\n const [themeMode, setThemeMode] = useState<ThemeMode>('system');\n const [isDark, setIsDark] = useState(false);\n\n // Ref para manter o estado atual do tema de forma síncrona\n const themeModeRef = useRef<ThemeMode>('system');\n\n // Função para aplicar o tema baseado no modo selecionado\n const applyTheme = useCallback((mode: ThemeMode) => {\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 setIsDark(true);\n } else if (mode === 'light') {\n if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n }\n setIsDark(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 setIsDark(true);\n } else if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n setIsDark(false);\n }\n }\n }, []);\n\n // Função para alternar entre os temas\n const toggleTheme = useCallback(() => {\n let newMode: ThemeMode;\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 setThemeMode(newMode);\n themeModeRef.current = newMode;\n applyTheme(newMode);\n localStorage.setItem('theme-mode', newMode);\n }, [themeMode, applyTheme]);\n\n // Função para definir um tema específico\n const setTheme = useCallback(\n (mode: ThemeMode) => {\n setThemeMode(mode);\n themeModeRef.current = mode;\n applyTheme(mode);\n localStorage.setItem('theme-mode', mode);\n },\n [applyTheme]\n );\n\n useEffect(() => {\n const htmlElement = document.documentElement;\n\n // Salva o theme original do white label na primeira execução\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 // Carrega o tema salvo no localStorage ou usa 'system' como padrão\n const savedThemeMode = localStorage.getItem('theme-mode') as ThemeMode;\n const initialMode = savedThemeMode || 'system';\n\n // Se não há tema salvo, persiste 'system' como padrão\n if (!savedThemeMode) {\n localStorage.setItem('theme-mode', 'system');\n }\n\n setThemeMode(initialMode);\n themeModeRef.current = initialMode;\n applyTheme(initialMode);\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 const handleSystemThemeChange = () => {\n // Usa o ref para ter acesso ao estado atual de forma síncrona\n if (themeModeRef.current === 'system') {\n applyTheme('system');\n }\n };\n\n mediaQuery.addEventListener('change', handleSystemThemeChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleSystemThemeChange);\n };\n }, [applyTheme]);\n\n return {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n };\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ThemeToggle/ThemeToggle.tsx","../../src/components/SelectionButton/SelectionButton.tsx","../../src/utils/utils.ts","../../src/hooks/useTheme.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","import { useEffect, useState, useCallback, useRef } from 'react';\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\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 */\nexport const useTheme = () => {\n const [themeMode, setThemeMode] = useState<ThemeMode>('system');\n const [isDark, setIsDark] = useState(false);\n\n // Ref para manter o estado atual do tema de forma síncrona\n const themeModeRef = useRef<ThemeMode>('system');\n\n // Função para aplicar o tema baseado no modo selecionado\n const applyTheme = useCallback((mode: ThemeMode) => {\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 setIsDark(true);\n } else if (mode === 'light') {\n if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n }\n setIsDark(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 setIsDark(true);\n } else if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n setIsDark(false);\n }\n }\n }, []);\n\n // Função para alternar entre os temas\n const toggleTheme = useCallback(() => {\n let newMode: ThemeMode;\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 setThemeMode(newMode);\n themeModeRef.current = newMode;\n applyTheme(newMode);\n localStorage.setItem('theme-mode', newMode);\n }, [themeMode, applyTheme]);\n\n // Função para definir um tema específico\n const setTheme = useCallback(\n (mode: ThemeMode) => {\n setThemeMode(mode);\n themeModeRef.current = mode;\n applyTheme(mode);\n localStorage.setItem('theme-mode', mode);\n },\n [applyTheme]\n );\n\n useEffect(() => {\n const htmlElement = document.documentElement;\n\n // Salva o theme original do white label na primeira execução\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 // Carrega o tema salvo no localStorage ou usa 'system' como padrão\n const savedThemeMode = localStorage.getItem('theme-mode') as ThemeMode;\n const initialMode = savedThemeMode || 'system';\n\n // Se não há tema salvo, persiste 'system' como padrão\n if (!savedThemeMode) {\n localStorage.setItem('theme-mode', 'system');\n }\n\n setThemeMode(initialMode);\n themeModeRef.current = initialMode;\n applyTheme(initialMode);\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 const handleSystemThemeChange = () => {\n // Usa o ref para ter acesso ao estado atual de forma síncrona\n if (themeModeRef.current === 'system') {\n applyTheme('system');\n }\n };\n\n mediaQuery.addEventListener('change', handleSystemThemeChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleSystemThemeChange);\n };\n }, [applyTheme]);\n\n return {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n };\n};\n"],"mappings":";AAAA,SAAS,MAAM,WAAW;AAC1B,SAAS,YAAAA,WAAU,aAAAC,kBAAiB;;;ACDpC,SAA0C,kBAAkB;;;ACA5D,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ADgGM,SAQE,KARF;AA1CN,IAAM,kBAAkB;AAAA,EACtB,CACE,EAAE,MAAM,OAAO,WAAW,OAAO,YAAY,IAAI,UAAU,GAAG,MAAM,GACpE,QACG;AAEH,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,eAAe,WACjB,CAAC,oBAAoB,UAAU,iBAAiB,aAAa,IAC7D,CAAC;AAEL,UAAM,aAAa,CAAC,GAAG,aAAa,GAAG,YAAY,EAAE,KAAK,GAAG;AAE7D,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW,GAAG,YAAY,SAAS;AAAA,QACnC;AAAA,QACA,gBAAc;AAAA,QACb,GAAG;AAAA,QAEJ;AAAA,8BAAC,UAAK,WAAU,4CAA4C,gBAAK;AAAA,UACjE,oBAAC,UAAM,iBAAM;AAAA;AAAA;AAAA,IACf;AAAA,EAEJ;AACF;AAEA,gBAAgB,cAAc;AAE9B,IAAO,0BAAQ;;;AEtHf,SAAS,WAAW,UAAU,aAAa,cAAc;AAQlD,IAAM,WAAW,MAAM;AAC5B,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB,QAAQ;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAG1C,QAAM,eAAe,OAAkB,QAAQ;AAG/C,QAAM,aAAa,YAAY,CAAC,SAAoB;AAClD,UAAM,cAAc,SAAS;AAC7B,UAAM,gBAAgB,YAAY,aAAa,qBAAqB;AAEpE,QAAI,SAAS,QAAQ;AACnB,kBAAY,aAAa,cAAc,MAAM;AAC7C,gBAAU,IAAI;AAAA,IAChB,WAAW,SAAS,SAAS;AAC3B,UAAI,eAAe;AACjB,oBAAY,aAAa,cAAc,aAAa;AAAA,MACtD;AACA,gBAAU,KAAK;AAAA,IACjB,WAAW,SAAS,UAAU;AAC5B,YAAM,eAAe,OAAO;AAAA,QAC1B;AAAA,MACF,EAAE;AACF,UAAI,cAAc;AAChB,oBAAY,aAAa,cAAc,MAAM;AAC7C,kBAAU,IAAI;AAAA,MAChB,WAAW,eAAe;AACxB,oBAAY,aAAa,cAAc,aAAa;AACpD,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI;AACJ,QAAI,cAAc,SAAS;AACzB,gBAAU;AAAA,IACZ,WAAW,cAAc,QAAQ;AAC/B,gBAAU;AAAA,IACZ,OAAO;AAEL,gBAAU;AAAA,IACZ;AACA,iBAAa,OAAO;AACpB,iBAAa,UAAU;AACvB,eAAW,OAAO;AAClB,iBAAa,QAAQ,cAAc,OAAO;AAAA,EAC5C,GAAG,CAAC,WAAW,UAAU,CAAC;AAG1B,QAAM,WAAW;AAAA,IACf,CAAC,SAAoB;AACnB,mBAAa,IAAI;AACjB,mBAAa,UAAU;AACvB,iBAAW,IAAI;AACf,mBAAa,QAAQ,cAAc,IAAI;AAAA,IACzC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,YAAU,MAAM;AACd,UAAM,cAAc,SAAS;AAG7B,UAAM,eAAe,YAAY,aAAa,YAAY;AAC1D,QAAI,gBAAgB,CAAC,YAAY,aAAa,qBAAqB,GAAG;AACpE,kBAAY,aAAa,uBAAuB,YAAY;AAAA,IAC9D;AAGA,UAAM,iBAAiB,aAAa,QAAQ,YAAY;AACxD,UAAM,cAAc,kBAAkB;AAGtC,QAAI,CAAC,gBAAgB;AACnB,mBAAa,QAAQ,cAAc,QAAQ;AAAA,IAC7C;AAEA,iBAAa,WAAW;AACxB,iBAAa,UAAU;AACvB,eAAW,WAAW;AAGtB,UAAM,aAAa,OAAO,WAAW,8BAA8B;AACnE,UAAM,0BAA0B,MAAM;AAEpC,UAAI,aAAa,YAAY,UAAU;AACrC,mBAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAEA,eAAW,iBAAiB,UAAU,uBAAuB;AAE7D,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,uBAAuB;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AHvFY,gBAAAC,YAAA;AAhBL,IAAM,cAAc,CAAC;AAAA,EAC1B,UAAU;AAAA,EACV;AACF,MAAwB;AACtB,QAAM,EAAE,WAAW,SAAS,IAAI,SAAS;AACzC,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAoB,SAAS;AAG/D,EAAAC,WAAU,MAAM;AACd,iBAAa,SAAS;AAAA,EACxB,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,eAAe;AAAA,IACnB;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,gBAAAF,KAAC,OAAI,MAAM,IAAI;AAAA,IACvB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,gBAAAA,KAAC,QAAK,MAAM,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,QAAO;AAAA,UACP,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,OAAM;AAAA,UAEN,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,GAAE;AAAA,cACF,MAAK;AAAA;AAAA,UACP;AAAA;AAAA,MACF;AAAA,IAEJ;AAAA,EACF;AAEA,QAAM,oBAAoB,CAAC,kBAA6B;AACtD,QAAI,YAAY,aAAa;AAC3B,mBAAa,aAAa;AAAA,IAC5B,OAAO;AACL,eAAS,aAAa;AAAA,IACxB;AAEA,QAAI,UAAU;AACZ,eAAS,aAAa;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,eAAe,YAAY,cAAc,YAAY;AAE3D,SACE,gBAAAA,KAAC,SAAI,WAAU,qCACZ,uBAAa,IAAI,CAAC,SACjB,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,UAAU,iBAAiB,KAAK;AAAA,MAChC,SAAS,MAAM,kBAAkB,KAAK,EAAE;AAAA,MACxC,WAAU;AAAA;AAAA,IALL,KAAK;AAAA,EAMZ,CACD,GACH;AAEJ;","names":["useState","useEffect","jsx","useState","useEffect"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from 'react';\n\
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from 'react';\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\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 */\nexport const useTheme = () => {\n const [themeMode, setThemeMode] = useState<ThemeMode>('system');\n const [isDark, setIsDark] = useState(false);\n\n // Ref para manter o estado atual do tema de forma síncrona\n const themeModeRef = useRef<ThemeMode>('system');\n\n // Função para aplicar o tema baseado no modo selecionado\n const applyTheme = useCallback((mode: ThemeMode) => {\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 setIsDark(true);\n } else if (mode === 'light') {\n if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n }\n setIsDark(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 setIsDark(true);\n } else if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n setIsDark(false);\n }\n }\n }, []);\n\n // Função para alternar entre os temas\n const toggleTheme = useCallback(() => {\n let newMode: ThemeMode;\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 setThemeMode(newMode);\n themeModeRef.current = newMode;\n applyTheme(newMode);\n localStorage.setItem('theme-mode', newMode);\n }, [themeMode, applyTheme]);\n\n // Função para definir um tema específico\n const setTheme = useCallback(\n (mode: ThemeMode) => {\n setThemeMode(mode);\n themeModeRef.current = mode;\n applyTheme(mode);\n localStorage.setItem('theme-mode', mode);\n },\n [applyTheme]\n );\n\n useEffect(() => {\n const htmlElement = document.documentElement;\n\n // Salva o theme original do white label na primeira execução\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 // Carrega o tema salvo no localStorage ou usa 'system' como padrão\n const savedThemeMode = localStorage.getItem('theme-mode') as ThemeMode;\n const initialMode = savedThemeMode || 'system';\n\n // Se não há tema salvo, persiste 'system' como padrão\n if (!savedThemeMode) {\n localStorage.setItem('theme-mode', 'system');\n }\n\n setThemeMode(initialMode);\n themeModeRef.current = initialMode;\n applyTheme(initialMode);\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 const handleSystemThemeChange = () => {\n // Usa o ref para ter acesso ao estado atual de forma síncrona\n if (themeModeRef.current === 'system') {\n applyTheme('system');\n }\n };\n\n mediaQuery.addEventListener('change', handleSystemThemeChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleSystemThemeChange);\n };\n }, [applyTheme]);\n\n return {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAyD;AAQlD,IAAM,WAAW,MAAM;AAC5B,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAoB,QAAQ;AAC9D,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAS,KAAK;AAG1C,QAAM,mBAAe,qBAAkB,QAAQ;AAG/C,QAAM,iBAAa,0BAAY,CAAC,SAAoB;AAClD,UAAM,cAAc,SAAS;AAC7B,UAAM,gBAAgB,YAAY,aAAa,qBAAqB;AAEpE,QAAI,SAAS,QAAQ;AACnB,kBAAY,aAAa,cAAc,MAAM;AAC7C,gBAAU,IAAI;AAAA,IAChB,WAAW,SAAS,SAAS;AAC3B,UAAI,eAAe;AACjB,oBAAY,aAAa,cAAc,aAAa;AAAA,MACtD;AACA,gBAAU,KAAK;AAAA,IACjB,WAAW,SAAS,UAAU;AAC5B,YAAM,eAAe,OAAO;AAAA,QAC1B;AAAA,MACF,EAAE;AACF,UAAI,cAAc;AAChB,oBAAY,aAAa,cAAc,MAAM;AAC7C,kBAAU,IAAI;AAAA,MAChB,WAAW,eAAe;AACxB,oBAAY,aAAa,cAAc,aAAa;AACpD,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,kBAAc,0BAAY,MAAM;AACpC,QAAI;AACJ,QAAI,cAAc,SAAS;AACzB,gBAAU;AAAA,IACZ,WAAW,cAAc,QAAQ;AAC/B,gBAAU;AAAA,IACZ,OAAO;AAEL,gBAAU;AAAA,IACZ;AACA,iBAAa,OAAO;AACpB,iBAAa,UAAU;AACvB,eAAW,OAAO;AAClB,iBAAa,QAAQ,cAAc,OAAO;AAAA,EAC5C,GAAG,CAAC,WAAW,UAAU,CAAC;AAG1B,QAAM,eAAW;AAAA,IACf,CAAC,SAAoB;AACnB,mBAAa,IAAI;AACjB,mBAAa,UAAU;AACvB,iBAAW,IAAI;AACf,mBAAa,QAAQ,cAAc,IAAI;AAAA,IACzC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,8BAAU,MAAM;AACd,UAAM,cAAc,SAAS;AAG7B,UAAM,eAAe,YAAY,aAAa,YAAY;AAC1D,QAAI,gBAAgB,CAAC,YAAY,aAAa,qBAAqB,GAAG;AACpE,kBAAY,aAAa,uBAAuB,YAAY;AAAA,IAC9D;AAGA,UAAM,iBAAiB,aAAa,QAAQ,YAAY;AACxD,UAAM,cAAc,kBAAkB;AAGtC,QAAI,CAAC,gBAAgB;AACnB,mBAAa,QAAQ,cAAc,QAAQ;AAAA,IAC7C;AAEA,iBAAa,WAAW;AACxB,iBAAa,UAAU;AACvB,eAAW,WAAW;AAGtB,UAAM,aAAa,OAAO,WAAW,8BAA8B;AACnE,UAAM,0BAA0B,MAAM;AAEpC,UAAI,aAAa,YAAY,UAAU;AACrC,mBAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAEA,eAAW,iBAAiB,UAAU,uBAAuB;AAE7D,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,uBAAuB;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from 'react';\n\
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from 'react';\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\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 */\nexport const useTheme = () => {\n const [themeMode, setThemeMode] = useState<ThemeMode>('system');\n const [isDark, setIsDark] = useState(false);\n\n // Ref para manter o estado atual do tema de forma síncrona\n const themeModeRef = useRef<ThemeMode>('system');\n\n // Função para aplicar o tema baseado no modo selecionado\n const applyTheme = useCallback((mode: ThemeMode) => {\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 setIsDark(true);\n } else if (mode === 'light') {\n if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n }\n setIsDark(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 setIsDark(true);\n } else if (originalTheme) {\n htmlElement.setAttribute('data-theme', originalTheme);\n setIsDark(false);\n }\n }\n }, []);\n\n // Função para alternar entre os temas\n const toggleTheme = useCallback(() => {\n let newMode: ThemeMode;\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 setThemeMode(newMode);\n themeModeRef.current = newMode;\n applyTheme(newMode);\n localStorage.setItem('theme-mode', newMode);\n }, [themeMode, applyTheme]);\n\n // Função para definir um tema específico\n const setTheme = useCallback(\n (mode: ThemeMode) => {\n setThemeMode(mode);\n themeModeRef.current = mode;\n applyTheme(mode);\n localStorage.setItem('theme-mode', mode);\n },\n [applyTheme]\n );\n\n useEffect(() => {\n const htmlElement = document.documentElement;\n\n // Salva o theme original do white label na primeira execução\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 // Carrega o tema salvo no localStorage ou usa 'system' como padrão\n const savedThemeMode = localStorage.getItem('theme-mode') as ThemeMode;\n const initialMode = savedThemeMode || 'system';\n\n // Se não há tema salvo, persiste 'system' como padrão\n if (!savedThemeMode) {\n localStorage.setItem('theme-mode', 'system');\n }\n\n setThemeMode(initialMode);\n themeModeRef.current = initialMode;\n applyTheme(initialMode);\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 const handleSystemThemeChange = () => {\n // Usa o ref para ter acesso ao estado atual de forma síncrona\n if (themeModeRef.current === 'system') {\n applyTheme('system');\n }\n };\n\n mediaQuery.addEventListener('change', handleSystemThemeChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleSystemThemeChange);\n };\n }, [applyTheme]);\n\n return {\n themeMode,\n isDark,\n toggleTheme,\n setTheme,\n };\n};\n"],"mappings":";AAAA,SAAS,WAAW,UAAU,aAAa,cAAc;AAQlD,IAAM,WAAW,MAAM;AAC5B,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB,QAAQ;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAG1C,QAAM,eAAe,OAAkB,QAAQ;AAG/C,QAAM,aAAa,YAAY,CAAC,SAAoB;AAClD,UAAM,cAAc,SAAS;AAC7B,UAAM,gBAAgB,YAAY,aAAa,qBAAqB;AAEpE,QAAI,SAAS,QAAQ;AACnB,kBAAY,aAAa,cAAc,MAAM;AAC7C,gBAAU,IAAI;AAAA,IAChB,WAAW,SAAS,SAAS;AAC3B,UAAI,eAAe;AACjB,oBAAY,aAAa,cAAc,aAAa;AAAA,MACtD;AACA,gBAAU,KAAK;AAAA,IACjB,WAAW,SAAS,UAAU;AAC5B,YAAM,eAAe,OAAO;AAAA,QAC1B;AAAA,MACF,EAAE;AACF,UAAI,cAAc;AAChB,oBAAY,aAAa,cAAc,MAAM;AAC7C,kBAAU,IAAI;AAAA,MAChB,WAAW,eAAe;AACxB,oBAAY,aAAa,cAAc,aAAa;AACpD,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI;AACJ,QAAI,cAAc,SAAS;AACzB,gBAAU;AAAA,IACZ,WAAW,cAAc,QAAQ;AAC/B,gBAAU;AAAA,IACZ,OAAO;AAEL,gBAAU;AAAA,IACZ;AACA,iBAAa,OAAO;AACpB,iBAAa,UAAU;AACvB,eAAW,OAAO;AAClB,iBAAa,QAAQ,cAAc,OAAO;AAAA,EAC5C,GAAG,CAAC,WAAW,UAAU,CAAC;AAG1B,QAAM,WAAW;AAAA,IACf,CAAC,SAAoB;AACnB,mBAAa,IAAI;AACjB,mBAAa,UAAU;AACvB,iBAAW,IAAI;AACf,mBAAa,QAAQ,cAAc,IAAI;AAAA,IACzC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,YAAU,MAAM;AACd,UAAM,cAAc,SAAS;AAG7B,UAAM,eAAe,YAAY,aAAa,YAAY;AAC1D,QAAI,gBAAgB,CAAC,YAAY,aAAa,qBAAqB,GAAG;AACpE,kBAAY,aAAa,uBAAuB,YAAY;AAAA,IAC9D;AAGA,UAAM,iBAAiB,aAAa,QAAQ,YAAY;AACxD,UAAM,cAAc,kBAAkB;AAGtC,QAAI,CAAC,gBAAgB;AACnB,mBAAa,QAAQ,cAAc,QAAQ;AAAA,IAC7C;AAEA,iBAAa,WAAW;AACxB,iBAAa,UAAU;AACvB,eAAW,WAAW;AAGtB,UAAM,aAAa,OAAO,WAAW,8BAA8B;AACnE,UAAM,0BAA0B,MAAM;AAEpC,UAAI,aAAa,YAAY,UAAU;AACrC,mBAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAEA,eAAW,iBAAiB,UAAU,uBAAuB;AAE7D,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,uBAAuB;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
package/dist/index.css
CHANGED
|
@@ -121,6 +121,7 @@
|
|
|
121
121
|
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
122
122
|
--blur-xs: 4px;
|
|
123
123
|
--blur-sm: 8px;
|
|
124
|
+
--aspect-video: 16 / 9;
|
|
124
125
|
--default-transition-duration: 150ms;
|
|
125
126
|
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
126
127
|
--default-font-family: var(--font-sans);
|
|
@@ -740,6 +741,9 @@
|
|
|
740
741
|
.table {
|
|
741
742
|
display: table;
|
|
742
743
|
}
|
|
744
|
+
.aspect-video {
|
|
745
|
+
aspect-ratio: var(--aspect-video);
|
|
746
|
+
}
|
|
743
747
|
.size-3 {
|
|
744
748
|
width: calc(var(--spacing) * 3);
|
|
745
749
|
height: calc(var(--spacing) * 3);
|
|
@@ -871,6 +875,9 @@
|
|
|
871
875
|
.h-\[90px\] {
|
|
872
876
|
height: 90px;
|
|
873
877
|
}
|
|
878
|
+
.h-\[122px\] {
|
|
879
|
+
height: 122px;
|
|
880
|
+
}
|
|
874
881
|
.h-\[152px\] {
|
|
875
882
|
height: 152px;
|
|
876
883
|
}
|
|
@@ -1042,6 +1049,9 @@
|
|
|
1042
1049
|
.w-\[110px\] {
|
|
1043
1050
|
width: 110px;
|
|
1044
1051
|
}
|
|
1052
|
+
.w-\[122px\] {
|
|
1053
|
+
width: 122px;
|
|
1054
|
+
}
|
|
1045
1055
|
.w-\[131px\] {
|
|
1046
1056
|
width: 131px;
|
|
1047
1057
|
}
|
|
@@ -2770,9 +2780,6 @@
|
|
|
2770
2780
|
.py-1 {
|
|
2771
2781
|
padding-block: calc(var(--spacing) * 1);
|
|
2772
2782
|
}
|
|
2773
|
-
.py-1\.5 {
|
|
2774
|
-
padding-block: calc(var(--spacing) * 1.5);
|
|
2775
|
-
}
|
|
2776
2783
|
.py-2 {
|
|
2777
2784
|
padding-block: calc(var(--spacing) * 2);
|
|
2778
2785
|
}
|
|
@@ -4922,13 +4929,6 @@
|
|
|
4922
4929
|
}
|
|
4923
4930
|
}
|
|
4924
4931
|
}
|
|
4925
|
-
.hover\:bg-gray-300 {
|
|
4926
|
-
&:hover {
|
|
4927
|
-
@media (hover: hover) {
|
|
4928
|
-
background-color: var(--color-gray-300);
|
|
4929
|
-
}
|
|
4930
|
-
}
|
|
4931
|
-
}
|
|
4932
4932
|
.hover\:bg-green-600 {
|
|
4933
4933
|
&:hover {
|
|
4934
4934
|
@media (hover: hover) {
|
|
@@ -8130,11 +8130,6 @@
|
|
|
8130
8130
|
--tw-ring-color: var(--color-indicator-info);
|
|
8131
8131
|
}
|
|
8132
8132
|
}
|
|
8133
|
-
.focus-visible\:ring-primary-500 {
|
|
8134
|
-
&:focus-visible {
|
|
8135
|
-
--tw-ring-color: var(--color-primary-500);
|
|
8136
|
-
}
|
|
8137
|
-
}
|
|
8138
8133
|
.focus-visible\:ring-primary-600 {
|
|
8139
8134
|
&:focus-visible {
|
|
8140
8135
|
--tw-ring-color: var(--color-primary-600);
|
|
@@ -18271,30 +18266,6 @@
|
|
|
18271
18266
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
18272
18267
|
}
|
|
18273
18268
|
}
|
|
18274
|
-
.dark\:border-gray-600 {
|
|
18275
|
-
@media (prefers-color-scheme: dark) {
|
|
18276
|
-
border-color: var(--color-gray-600);
|
|
18277
|
-
}
|
|
18278
|
-
}
|
|
18279
|
-
.dark\:bg-gray-700 {
|
|
18280
|
-
@media (prefers-color-scheme: dark) {
|
|
18281
|
-
background-color: var(--color-gray-700);
|
|
18282
|
-
}
|
|
18283
|
-
}
|
|
18284
|
-
.dark\:text-gray-300 {
|
|
18285
|
-
@media (prefers-color-scheme: dark) {
|
|
18286
|
-
color: var(--color-gray-300);
|
|
18287
|
-
}
|
|
18288
|
-
}
|
|
18289
|
-
.dark\:hover\:bg-gray-600 {
|
|
18290
|
-
@media (prefers-color-scheme: dark) {
|
|
18291
|
-
&:hover {
|
|
18292
|
-
@media (hover: hover) {
|
|
18293
|
-
background-color: var(--color-gray-600);
|
|
18294
|
-
}
|
|
18295
|
-
}
|
|
18296
|
-
}
|
|
18297
|
-
}
|
|
18298
18269
|
.\[\&_tr\:first-child\]\:border-0 {
|
|
18299
18270
|
& tr:first-child {
|
|
18300
18271
|
border-style: var(--tw-border-style);
|