@botuyo/chat-widget-standalone 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-chat-ui-EAAXXtnK.js","sources":["../src/chat-widget/i18n/translations.ts","../src/chat-widget/i18n/LanguageContext.tsx","../src/chat-widget/i18n/useTranslations.ts","../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js","../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js","../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js","../node_modules/lucide-react/dist/esm/defaultAttributes.js","../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js","../node_modules/lucide-react/dist/esm/Icon.js","../node_modules/lucide-react/dist/esm/createLucideIcon.js","../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js","../node_modules/lucide-react/dist/esm/icons/arrow-right.js","../node_modules/lucide-react/dist/esm/icons/check-check.js","../node_modules/lucide-react/dist/esm/icons/chevron-left.js","../node_modules/lucide-react/dist/esm/icons/chevron-right.js","../node_modules/lucide-react/dist/esm/icons/download.js","../node_modules/lucide-react/dist/esm/icons/external-link.js","../node_modules/lucide-react/dist/esm/icons/file.js","../node_modules/lucide-react/dist/esm/icons/heart.js","../node_modules/lucide-react/dist/esm/icons/image.js","../node_modules/lucide-react/dist/esm/icons/loader-circle.js","../node_modules/lucide-react/dist/esm/icons/map-pin.js","../node_modules/lucide-react/dist/esm/icons/message-circle.js","../node_modules/lucide-react/dist/esm/icons/mic.js","../node_modules/lucide-react/dist/esm/icons/pause.js","../node_modules/lucide-react/dist/esm/icons/play.js","../node_modules/lucide-react/dist/esm/icons/plus.js","../node_modules/lucide-react/dist/esm/icons/send.js","../node_modules/lucide-react/dist/esm/icons/shield-check.js","../node_modules/lucide-react/dist/esm/icons/trash-2.js","../node_modules/lucide-react/dist/esm/icons/x.js","../node_modules/lucide-react/dist/esm/icons/zoom-in.js","../node_modules/clsx/dist/clsx.mjs","../node_modules/tailwind-merge/dist/bundle-mjs.mjs","../src/lib/utils.ts","../src/chat-widget/utils/theme.ts","../src/chat-widget/utils/logger.ts","../src/chat-widget/utils/defaultAssets.ts","../node_modules/@tanstack/virtual-core/dist/esm/utils.js","../node_modules/@tanstack/virtual-core/dist/esm/index.js","../node_modules/@tanstack/react-virtual/dist/esm/index.js","../src/chat-widget/components/MessageBubble.tsx","../src/chat-widget/components/TypingIndicator.tsx","../src/chat-widget/utils/dateUtils.ts","../src/chat-widget/components/MessageList.tsx","../src/chat-widget/utils/fileValidation.ts","../src/chat-widget/components/InputArea.tsx","../src/chat-widget/utils/performance.ts","../src/chat-widget/hooks/useIsMobile.ts","../src/chat-widget/hooks/useDynamicHeight.ts","../src/chat-widget/components/ChatWindow.tsx","../src/chat-widget/hooks/useFocusTrap.ts"],"sourcesContent":["/**\r\n * Sistema de internacionalización del Chat Widget\r\n * Idiomas soportados: español, inglés, portugués, francés\r\n */\r\n\r\nexport const translations = {\r\n es: {\r\n // Estado de conexión\r\n online: 'En línea',\r\n offline: 'Desconectado',\r\n connecting: 'Conectando...',\r\n\r\n // Footer\r\n con_amor_paseo_libre: 'Con ❤️ por BotUyo',\r\n\r\n // Input area\r\n preview: 'Vista previa',\r\n fotos: 'Fotos',\r\n ubicacion: 'Ubicación',\r\n input_placeholder: 'Escribe un mensaje...',\r\n send: 'Enviar',\r\n attach_photo: 'Adjuntar foto',\r\n attach_location: 'Compartir ubicación',\r\n recording: 'Grabando...',\r\n\r\n // Errores\r\n rate_limit_exceeded: 'Has enviado demasiados mensajes. Espera un momento.',\r\n connection_error: 'Error de conexión',\r\n file_too_large: 'Archivo demasiado grande',\r\n invalid_file: 'Tipo de archivo no válido',\r\n\r\n // Extracted (común)\r\n extracted: {\r\n assistant: 'Asistente',\r\n anterior: 'Anterior',\r\n siguiente: 'Siguiente',\r\n cerrar: 'Cerrar',\r\n cerrar_chat: 'Cerrar chat',\r\n abrir_chat: 'Abrir chat',\r\n ver_ubicacion: 'Ver ubicación',\r\n },\r\n\r\n // Accesibilidad (A11y)\r\n accessibility: {\r\n closeChat: 'Cerrar ventana de chat',\r\n closeChatHint: 'Presiona Escape para cerrar',\r\n chatMessages: 'Mensajes del chat',\r\n messageHistory: 'Historial de mensajes',\r\n dialogDescription:\r\n 'Ventana de chat con {{botName}}. Presiona Escape para cerrar. Usa Ctrl+Enter para enviar mensajes.',\r\n sendMessage: 'Enviar mensaje',\r\n sendMessageHint: 'Presiona Enter o Ctrl+Enter para enviar',\r\n typeMessage: 'Escribe tu mensaje aquí',\r\n botMessage: 'Mensaje del asistente',\r\n userMessage: 'Tu mensaje',\r\n messageFrom: 'Mensaje de {{sender}}',\r\n messageTime: 'Enviado {{time}}',\r\n newMessage: 'Nuevo mensaje recibido',\r\n },\r\n },\r\n en: {\r\n // Connection status\r\n online: 'Online',\r\n offline: 'Offline',\r\n connecting: 'Connecting...',\r\n\r\n // Footer\r\n con_amor_paseo_libre: 'With ❤️ by BotUyo',\r\n\r\n // Input area\r\n preview: 'Preview',\r\n fotos: 'Photos',\r\n ubicacion: 'Location',\r\n input_placeholder: 'Type a message...',\r\n send: 'Send',\r\n attach_photo: 'Attach photo',\r\n attach_location: 'Share location',\r\n recording: 'Recording...',\r\n\r\n // Errors\r\n rate_limit_exceeded: 'You have sent too many messages. Please wait.',\r\n connection_error: 'Connection error',\r\n file_too_large: 'File too large',\r\n invalid_file: 'Invalid file type',\r\n\r\n // Extracted (common)\r\n extracted: {\r\n assistant: 'Assistant',\r\n anterior: 'Previous',\r\n siguiente: 'Next',\r\n cerrar: 'Close',\r\n cerrar_chat: 'Close chat',\r\n abrir_chat: 'Open chat',\r\n ver_ubicacion: 'View location',\r\n },\r\n\r\n // Accessibility (A11y)\r\n accessibility: {\r\n closeChat: 'Close chat window',\r\n closeChatHint: 'Press Escape to close',\r\n chatMessages: 'Chat messages',\r\n messageHistory: 'Message history',\r\n dialogDescription:\r\n 'Chat window with {{botName}}. Press Escape to close. Use Ctrl+Enter to send messages.',\r\n sendMessage: 'Send message',\r\n sendMessageHint: 'Press Enter or Ctrl+Enter to send',\r\n typeMessage: 'Type your message here',\r\n botMessage: 'Assistant message',\r\n userMessage: 'Your message',\r\n messageFrom: 'Message from {{sender}}',\r\n messageTime: 'Sent {{time}}',\r\n newMessage: 'New message received',\r\n },\r\n },\r\n pt: {\r\n // Estado da conexão\r\n online: 'Online',\r\n offline: 'Desconectado',\r\n connecting: 'Conectando...',\r\n\r\n // Rodapé\r\n con_amor_paseo_libre: 'Com ❤️ por BotUyo',\r\n\r\n // Área de entrada\r\n preview: 'Visualizar',\r\n fotos: 'Fotos',\r\n ubicacion: 'Localização',\r\n input_placeholder: 'Digite uma mensagem...',\r\n send: 'Enviar',\r\n attach_photo: 'Anexar foto',\r\n attach_location: 'Compartilhar localização',\r\n recording: 'Gravando...',\r\n\r\n // Erros\r\n rate_limit_exceeded: 'Você enviou muitas mensagens. Aguarde um momento.',\r\n connection_error: 'Erro de conexão',\r\n file_too_large: 'Arquivo muito grande',\r\n invalid_file: 'Tipo de arquivo inválido',\r\n\r\n // Extraído (comum)\r\n extracted: {\r\n assistant: 'Assistente',\r\n anterior: 'Anterior',\r\n siguiente: 'Próximo',\r\n cerrar: 'Fechar',\r\n cerrar_chat: 'Fechar chat',\r\n abrir_chat: 'Abrir chat',\r\n ver_ubicacion: 'Ver localização',\r\n },\r\n\r\n // Acessibilidade (A11y)\r\n accessibility: {\r\n closeChat: 'Fechar janela de chat',\r\n closeChatHint: 'Pressione Escape para fechar',\r\n chatMessages: 'Mensagens do chat',\r\n messageHistory: 'Histórico de mensagens',\r\n dialogDescription:\r\n 'Janela de chat com {{botName}}. Pressione Escape para fechar. Use Ctrl+Enter para enviar mensagens.',\r\n sendMessage: 'Enviar mensagem',\r\n sendMessageHint: 'Pressione Enter ou Ctrl+Enter para enviar',\r\n typeMessage: 'Digite sua mensagem aqui',\r\n botMessage: 'Mensagem do assistente',\r\n userMessage: 'Sua mensagem',\r\n messageFrom: 'Mensagem de {{sender}}',\r\n messageTime: 'Enviado {{time}}',\r\n newMessage: 'Nova mensagem recebida',\r\n },\r\n },\r\n fr: {\r\n // État de connexion\r\n online: 'En ligne',\r\n offline: 'Déconnecté',\r\n connecting: 'Connexion...',\r\n\r\n // Pied de page\r\n con_amor_paseo_libre: 'Avec ❤️ par BotUyo',\r\n\r\n // Zone de saisie\r\n preview: 'Aperçu',\r\n fotos: 'Photos',\r\n ubicacion: 'Emplacement',\r\n input_placeholder: 'Tapez un message...',\r\n send: 'Envoyer',\r\n attach_photo: 'Joindre une photo',\r\n attach_location: 'Partager la localisation',\r\n recording: 'Enregistrement...',\r\n\r\n // Erreurs\r\n rate_limit_exceeded: 'Vous avez envoyé trop de messages. Veuillez patienter.',\r\n connection_error: 'Erreur de connexion',\r\n file_too_large: 'Fichier trop volumineux',\r\n invalid_file: 'Type de fichier invalide',\r\n\r\n // Extrait (commun)\r\n extracted: {\r\n assistant: 'Assistant',\r\n anterior: 'Précédent',\r\n siguiente: 'Suivant',\r\n cerrar: 'Fermer',\r\n cerrar_chat: 'Fermer le chat',\r\n abrir_chat: 'Ouvrir le chat',\r\n ver_ubicacion: \"Voir l'emplacement\",\r\n },\r\n\r\n // Accessibilité (A11y)\r\n accessibility: {\r\n closeChat: 'Fermer la fenêtre de chat',\r\n closeChatHint: 'Appuyez sur Échap pour fermer',\r\n chatMessages: 'Messages du chat',\r\n messageHistory: 'Historique des messages',\r\n dialogDescription:\r\n 'Fenêtre de chat avec {{botName}}. Appuyez sur Échap pour fermer. Utilisez Ctrl+Entrée pour envoyer des messages.',\r\n sendMessage: 'Envoyer un message',\r\n sendMessageHint: 'Appuyez sur Entrée ou Ctrl+Entrée pour envoyer',\r\n typeMessage: 'Tapez votre message ici',\r\n botMessage: \"Message de l'assistant\",\r\n userMessage: 'Votre message',\r\n messageFrom: 'Message de {{sender}}',\r\n messageTime: 'Envoyé {{time}}',\r\n newMessage: 'Nouveau message reçu',\r\n },\r\n },\r\n}\r\n\r\nexport type SupportedLocale = keyof typeof translations\r\n\r\n// Detección automática de idioma\r\nexport function detectLanguage(): SupportedLocale {\r\n if (typeof navigator === 'undefined') return 'es'\r\n\r\n const browserLang = navigator.language.split('-')[0] as SupportedLocale\r\n return translations[browserLang] ? browserLang : 'es'\r\n}\r\n","/**\r\n * Contexto de idioma para el Chat Widget\r\n * Permite cambio dinámico de idioma con persistencia en localStorage\r\n */\r\n\r\nimport { createContext, useContext, useState, useEffect, type ReactNode } from 'react'\r\nimport { type SupportedLocale, detectLanguage } from './translations'\r\n\r\ninterface LanguageContextType {\r\n locale: SupportedLocale\r\n setLocale: (locale: SupportedLocale) => void\r\n}\r\n\r\nconst LanguageContext = createContext<LanguageContextType | undefined>(undefined)\r\n\r\nconst LOCALE_STORAGE_KEY = 'botuyo-chat-locale'\r\n\r\ninterface LanguageProviderProps {\r\n children: ReactNode\r\n defaultLocale?: SupportedLocale\r\n}\r\n\r\n/**\r\n * Provider de idioma con detección automática y persistencia\r\n *\r\n * @example\r\n * <LanguageProvider>\r\n * <ChatWidget />\r\n * </LanguageProvider>\r\n */\r\nexport function LanguageProvider({ children, defaultLocale }: LanguageProviderProps) {\r\n const [locale, setLocaleState] = useState<SupportedLocale>(() => {\r\n // 1. Prioridad a prop defaultLocale\r\n if (defaultLocale) return defaultLocale\r\n\r\n // 2. Segundo, intentar desde localStorage\r\n if (typeof window !== 'undefined') {\r\n const stored = localStorage.getItem(LOCALE_STORAGE_KEY) as SupportedLocale | null\r\n if (stored) return stored\r\n }\r\n\r\n // 3. Finalmente, detección automática del navegador\r\n return detectLanguage()\r\n })\r\n\r\n const setLocale = (newLocale: SupportedLocale) => {\r\n // Validar que el locale sea soportado\r\n const supportedLocales: SupportedLocale[] = ['es', 'en', 'pt', 'fr']\r\n if (!supportedLocales.includes(newLocale)) {\r\n console.warn(`[BotUyo] Locale \"${newLocale}\" no es soportado. Manteniendo \"${locale}\"`)\r\n return\r\n }\r\n\r\n setLocaleState(newLocale)\r\n if (typeof window !== 'undefined') {\r\n localStorage.setItem(LOCALE_STORAGE_KEY, newLocale)\r\n }\r\n }\r\n\r\n // Efecto para manejar cambios del idioma del navegador\r\n useEffect(() => {\r\n if (typeof window === 'undefined' || defaultLocale) return\r\n\r\n const handleLanguageChange = () => {\r\n const stored = localStorage.getItem(LOCALE_STORAGE_KEY)\r\n if (!stored) {\r\n // Si no hay preferencia guardada, actualizar con idioma del navegador\r\n setLocaleState(detectLanguage())\r\n }\r\n }\r\n\r\n window.addEventListener('languagechange', handleLanguageChange)\r\n return () => window.removeEventListener('languagechange', handleLanguageChange)\r\n }, [defaultLocale])\r\n\r\n return (\r\n <LanguageContext.Provider value={{ locale, setLocale }}>{children}</LanguageContext.Provider>\r\n )\r\n}\r\n\r\n/**\r\n * Hook para acceder al idioma actual del widget\r\n *\r\n * @example\r\n * const { locale, setLocale } = useLanguage()\r\n * setLocale('en') // Cambiar a inglés\r\n */\r\nexport function useLanguage() {\r\n const context = useContext(LanguageContext)\r\n if (context === undefined) {\r\n throw new Error('useLanguage debe usarse dentro de un LanguageProvider')\r\n }\r\n return context\r\n}\r\n","/**\r\n * Hook de internacionalización para el Chat Widget\r\n * Sistema multi-idioma con detección automática y contexto global\r\n */\r\n\r\nimport { useCallback } from 'react'\r\nimport { translations, type SupportedLocale } from './translations'\r\nimport { useLanguage } from './LanguageContext'\r\n\r\n// Función helper para obtener valor anidado\r\nfunction getNestedValue(obj: any, path: string): string {\r\n return path.split('.').reduce((current, key) => current?.[key], obj) || path\r\n}\r\n\r\n/**\r\n * Hook para acceder a las traducciones con soporte multi-idioma\r\n * Usa el contexto global de idioma automáticamente\r\n *\r\n * @example\r\n * const { t, setLocale, currentLocale } = useTranslations()\r\n * t('online') // 'En línea' (si locale es 'es')\r\n * t('extracted.cerrar') // 'Cerrar'\r\n * setLocale('en') // Cambiar a inglés\r\n */\r\nexport function useTranslations(namespace?: string) {\r\n const { locale: currentLocale, setLocale } = useLanguage()\r\n\r\n const t = useCallback(\r\n (key: string): string => {\r\n const messages = translations[currentLocale]\r\n const fullKey = namespace ? `${namespace}.${key}` : key\r\n const translation = getNestedValue(messages, fullKey)\r\n return translation || key\r\n },\r\n [currentLocale, namespace]\r\n )\r\n\r\n return {\r\n t,\r\n setLocale,\r\n currentLocale,\r\n }\r\n}\r\n\r\n/**\r\n * Función para obtener traducción directamente sin hook\r\n * Útil para uso fuera de componentes\r\n */\r\nexport function t(key: string, locale: SupportedLocale = 'es'): string {\r\n return getNestedValue(translations[locale], key) || key\r\n}\r\n\r\nexport default useTranslations\r\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.js';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.js';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { toKebabCase } from './shared/src/utils/toKebabCase.js';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"m12 5 7 7-7 7\", key: \"xquz4c\" }]\n];\nconst ArrowRight = createLucideIcon(\"arrow-right\", __iconNode);\n\nexport { __iconNode, ArrowRight as default };\n//# sourceMappingURL=arrow-right.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M18 6 7 17l-5-5\", key: \"116fxf\" }],\n [\"path\", { d: \"m22 10-7.5 7.5L13 16\", key: \"ke71qq\" }]\n];\nconst CheckCheck = createLucideIcon(\"check-check\", __iconNode);\n\nexport { __iconNode, CheckCheck as default };\n//# sourceMappingURL=check-check.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]];\nconst ChevronLeft = createLucideIcon(\"chevron-left\", __iconNode);\n\nexport { __iconNode, ChevronLeft as default };\n//# sourceMappingURL=chevron-left.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"m9 18 6-6-6-6\", key: \"mthhwq\" }]];\nconst ChevronRight = createLucideIcon(\"chevron-right\", __iconNode);\n\nexport { __iconNode, ChevronRight as default };\n//# sourceMappingURL=chevron-right.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 15V3\", key: \"m9g1x1\" }],\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"path\", { d: \"m7 10 5 5 5-5\", key: \"brsn70\" }]\n];\nconst Download = createLucideIcon(\"download\", __iconNode);\n\nexport { __iconNode, Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"M10 14 21 3\", key: \"gplh6r\" }],\n [\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\", key: \"a6xqqp\" }]\n];\nconst ExternalLink = createLucideIcon(\"external-link\", __iconNode);\n\nexport { __iconNode, ExternalLink as default };\n//# sourceMappingURL=external-link.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }]\n];\nconst File = createLucideIcon(\"file\", __iconNode);\n\nexport { __iconNode, File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5\",\n key: \"mvr1a0\"\n }\n ]\n];\nconst Heart = createLucideIcon(\"heart\", __iconNode);\n\nexport { __iconNode, Heart as default };\n//# sourceMappingURL=heart.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", ry: \"2\", key: \"1m3agn\" }],\n [\"circle\", { cx: \"9\", cy: \"9\", r: \"2\", key: \"af1f0g\" }],\n [\"path\", { d: \"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\", key: \"1xmnt7\" }]\n];\nconst Image = createLucideIcon(\"image\", __iconNode);\n\nexport { __iconNode, Image as default };\n//# sourceMappingURL=image.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]];\nconst LoaderCircle = createLucideIcon(\"loader-circle\", __iconNode);\n\nexport { __iconNode, LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n];\nconst MapPin = createLucideIcon(\"map-pin\", __iconNode);\n\nexport { __iconNode, MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719\",\n key: \"1sd12s\"\n }\n ]\n];\nconst MessageCircle = createLucideIcon(\"message-circle\", __iconNode);\n\nexport { __iconNode, MessageCircle as default };\n//# sourceMappingURL=message-circle.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 19v3\", key: \"npa21l\" }],\n [\"path\", { d: \"M19 10v2a7 7 0 0 1-14 0v-2\", key: \"1vc78b\" }],\n [\"rect\", { x: \"9\", y: \"2\", width: \"6\", height: \"13\", rx: \"3\", key: \"s6n7sd\" }]\n];\nconst Mic = createLucideIcon(\"mic\", __iconNode);\n\nexport { __iconNode, Mic as default };\n//# sourceMappingURL=mic.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { x: \"14\", y: \"3\", width: \"5\", height: \"18\", rx: \"1\", key: \"kaeet6\" }],\n [\"rect\", { x: \"5\", y: \"3\", width: \"5\", height: \"18\", rx: \"1\", key: \"1wsw3u\" }]\n];\nconst Pause = createLucideIcon(\"pause\", __iconNode);\n\nexport { __iconNode, Pause as default };\n//# sourceMappingURL=pause.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\",\n key: \"10ikf1\"\n }\n ]\n];\nconst Play = createLucideIcon(\"play\", __iconNode);\n\nexport { __iconNode, Play as default };\n//# sourceMappingURL=play.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n];\nconst Plus = createLucideIcon(\"plus\", __iconNode);\n\nexport { __iconNode, Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\",\n key: \"1ffxy3\"\n }\n ],\n [\"path\", { d: \"m21.854 2.147-10.94 10.939\", key: \"12cjpa\" }]\n];\nconst Send = createLucideIcon(\"send\", __iconNode);\n\nexport { __iconNode, Send as default };\n//# sourceMappingURL=send.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n];\nconst ShieldCheck = createLucideIcon(\"shield-check\", __iconNode);\n\nexport { __iconNode, ShieldCheck as default };\n//# sourceMappingURL=shield-check.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n];\nconst X = createLucideIcon(\"x\", __iconNode);\n\nexport { __iconNode, X as default };\n//# sourceMappingURL=x.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"line\", { x1: \"21\", x2: \"16.65\", y1: \"21\", y2: \"16.65\", key: \"13gj7c\" }],\n [\"line\", { x1: \"11\", x2: \"11\", y1: \"8\", y2: \"14\", key: \"1vmskp\" }],\n [\"line\", { x1: \"8\", x2: \"14\", y1: \"11\", y2: \"11\", key: \"durymu\" }]\n];\nconst ZoomIn = createLucideIcon(\"zoom-in\", __iconNode);\n\nexport { __iconNode, ZoomIn as default };\n//# sourceMappingURL=zoom-in.js.map\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","/**\n * Concatenates two arrays faster than the array spread operator.\n */\nconst concatArrays = (array1, array2) => {\n // Pre-allocate for better V8 optimization\n const combinedArray = new Array(array1.length + array2.length);\n for (let i = 0; i < array1.length; i++) {\n combinedArray[i] = array1[i];\n }\n for (let i = 0; i < array2.length; i++) {\n combinedArray[array1.length + i] = array2[i];\n }\n return combinedArray;\n};\n\n// Factory function ensures consistent object shapes\nconst createClassValidatorObject = (classGroupId, validator) => ({\n classGroupId,\n validator\n});\n// Factory ensures consistent ClassPartObject shape\nconst createClassPartObject = (nextPart = new Map(), validators = null, classGroupId) => ({\n nextPart,\n validators,\n classGroupId\n});\nconst CLASS_PART_SEPARATOR = '-';\nconst EMPTY_CONFLICTS = [];\n// I use two dots here because one dot is used as prefix for class groups in plugins\nconst ARBITRARY_PROPERTY_PREFIX = 'arbitrary..';\nconst createClassGroupUtils = config => {\n const classMap = createClassMap(config);\n const {\n conflictingClassGroups,\n conflictingClassGroupModifiers\n } = config;\n const getClassGroupId = className => {\n if (className.startsWith('[') && className.endsWith(']')) {\n return getGroupIdForArbitraryProperty(className);\n }\n const classParts = className.split(CLASS_PART_SEPARATOR);\n // Classes like `-inset-1` produce an empty string as first classPart. We assume that classes for negative values are used correctly and skip it.\n const startIndex = classParts[0] === '' && classParts.length > 1 ? 1 : 0;\n return getGroupRecursive(classParts, startIndex, classMap);\n };\n const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => {\n if (hasPostfixModifier) {\n const modifierConflicts = conflictingClassGroupModifiers[classGroupId];\n const baseConflicts = conflictingClassGroups[classGroupId];\n if (modifierConflicts) {\n if (baseConflicts) {\n // Merge base conflicts with modifier conflicts\n return concatArrays(baseConflicts, modifierConflicts);\n }\n // Only modifier conflicts\n return modifierConflicts;\n }\n // Fall back to without postfix if no modifier conflicts\n return baseConflicts || EMPTY_CONFLICTS;\n }\n return conflictingClassGroups[classGroupId] || EMPTY_CONFLICTS;\n };\n return {\n getClassGroupId,\n getConflictingClassGroupIds\n };\n};\nconst getGroupRecursive = (classParts, startIndex, classPartObject) => {\n const classPathsLength = classParts.length - startIndex;\n if (classPathsLength === 0) {\n return classPartObject.classGroupId;\n }\n const currentClassPart = classParts[startIndex];\n const nextClassPartObject = classPartObject.nextPart.get(currentClassPart);\n if (nextClassPartObject) {\n const result = getGroupRecursive(classParts, startIndex + 1, nextClassPartObject);\n if (result) return result;\n }\n const validators = classPartObject.validators;\n if (validators === null) {\n return undefined;\n }\n // Build classRest string efficiently by joining from startIndex onwards\n const classRest = startIndex === 0 ? classParts.join(CLASS_PART_SEPARATOR) : classParts.slice(startIndex).join(CLASS_PART_SEPARATOR);\n const validatorsLength = validators.length;\n for (let i = 0; i < validatorsLength; i++) {\n const validatorObj = validators[i];\n if (validatorObj.validator(classRest)) {\n return validatorObj.classGroupId;\n }\n }\n return undefined;\n};\n/**\n * Get the class group ID for an arbitrary property.\n *\n * @param className - The class name to get the group ID for. Is expected to be string starting with `[` and ending with `]`.\n */\nconst getGroupIdForArbitraryProperty = className => className.slice(1, -1).indexOf(':') === -1 ? undefined : (() => {\n const content = className.slice(1, -1);\n const colonIndex = content.indexOf(':');\n const property = content.slice(0, colonIndex);\n return property ? ARBITRARY_PROPERTY_PREFIX + property : undefined;\n})();\n/**\n * Exported for testing only\n */\nconst createClassMap = config => {\n const {\n theme,\n classGroups\n } = config;\n return processClassGroups(classGroups, theme);\n};\n// Split into separate functions to maintain monomorphic call sites\nconst processClassGroups = (classGroups, theme) => {\n const classMap = createClassPartObject();\n for (const classGroupId in classGroups) {\n const group = classGroups[classGroupId];\n processClassesRecursively(group, classMap, classGroupId, theme);\n }\n return classMap;\n};\nconst processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => {\n const len = classGroup.length;\n for (let i = 0; i < len; i++) {\n const classDefinition = classGroup[i];\n processClassDefinition(classDefinition, classPartObject, classGroupId, theme);\n }\n};\n// Split into separate functions for each type to maintain monomorphic call sites\nconst processClassDefinition = (classDefinition, classPartObject, classGroupId, theme) => {\n if (typeof classDefinition === 'string') {\n processStringDefinition(classDefinition, classPartObject, classGroupId);\n return;\n }\n if (typeof classDefinition === 'function') {\n processFunctionDefinition(classDefinition, classPartObject, classGroupId, theme);\n return;\n }\n processObjectDefinition(classDefinition, classPartObject, classGroupId, theme);\n};\nconst processStringDefinition = (classDefinition, classPartObject, classGroupId) => {\n const classPartObjectToEdit = classDefinition === '' ? classPartObject : getPart(classPartObject, classDefinition);\n classPartObjectToEdit.classGroupId = classGroupId;\n};\nconst processFunctionDefinition = (classDefinition, classPartObject, classGroupId, theme) => {\n if (isThemeGetter(classDefinition)) {\n processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme);\n return;\n }\n if (classPartObject.validators === null) {\n classPartObject.validators = [];\n }\n classPartObject.validators.push(createClassValidatorObject(classGroupId, classDefinition));\n};\nconst processObjectDefinition = (classDefinition, classPartObject, classGroupId, theme) => {\n const entries = Object.entries(classDefinition);\n const len = entries.length;\n for (let i = 0; i < len; i++) {\n const [key, value] = entries[i];\n processClassesRecursively(value, getPart(classPartObject, key), classGroupId, theme);\n }\n};\nconst getPart = (classPartObject, path) => {\n let current = classPartObject;\n const parts = path.split(CLASS_PART_SEPARATOR);\n const len = parts.length;\n for (let i = 0; i < len; i++) {\n const part = parts[i];\n let next = current.nextPart.get(part);\n if (!next) {\n next = createClassPartObject();\n current.nextPart.set(part, next);\n }\n current = next;\n }\n return current;\n};\n// Type guard maintains monomorphic check\nconst isThemeGetter = func => 'isThemeGetter' in func && func.isThemeGetter === true;\n\n// LRU cache implementation using plain objects for simplicity\nconst createLruCache = maxCacheSize => {\n if (maxCacheSize < 1) {\n return {\n get: () => undefined,\n set: () => {}\n };\n }\n let cacheSize = 0;\n let cache = Object.create(null);\n let previousCache = Object.create(null);\n const update = (key, value) => {\n cache[key] = value;\n cacheSize++;\n if (cacheSize > maxCacheSize) {\n cacheSize = 0;\n previousCache = cache;\n cache = Object.create(null);\n }\n };\n return {\n get(key) {\n let value = cache[key];\n if (value !== undefined) {\n return value;\n }\n if ((value = previousCache[key]) !== undefined) {\n update(key, value);\n return value;\n }\n },\n set(key, value) {\n if (key in cache) {\n cache[key] = value;\n } else {\n update(key, value);\n }\n }\n };\n};\nconst IMPORTANT_MODIFIER = '!';\nconst MODIFIER_SEPARATOR = ':';\nconst EMPTY_MODIFIERS = [];\n// Pre-allocated result object shape for consistency\nconst createResultObject = (modifiers, hasImportantModifier, baseClassName, maybePostfixModifierPosition, isExternal) => ({\n modifiers,\n hasImportantModifier,\n baseClassName,\n maybePostfixModifierPosition,\n isExternal\n});\nconst createParseClassName = config => {\n const {\n prefix,\n experimentalParseClassName\n } = config;\n /**\n * Parse class name into parts.\n *\n * Inspired by `splitAtTopLevelOnly` used in Tailwind CSS\n * @see https://github.com/tailwindlabs/tailwindcss/blob/v3.2.2/src/util/splitAtTopLevelOnly.js\n */\n let parseClassName = className => {\n // Use simple array with push for better performance\n const modifiers = [];\n let bracketDepth = 0;\n let parenDepth = 0;\n let modifierStart = 0;\n let postfixModifierPosition;\n const len = className.length;\n for (let index = 0; index < len; index++) {\n const currentCharacter = className[index];\n if (bracketDepth === 0 && parenDepth === 0) {\n if (currentCharacter === MODIFIER_SEPARATOR) {\n modifiers.push(className.slice(modifierStart, index));\n modifierStart = index + 1;\n continue;\n }\n if (currentCharacter === '/') {\n postfixModifierPosition = index;\n continue;\n }\n }\n if (currentCharacter === '[') bracketDepth++;else if (currentCharacter === ']') bracketDepth--;else if (currentCharacter === '(') parenDepth++;else if (currentCharacter === ')') parenDepth--;\n }\n const baseClassNameWithImportantModifier = modifiers.length === 0 ? className : className.slice(modifierStart);\n // Inline important modifier check\n let baseClassName = baseClassNameWithImportantModifier;\n let hasImportantModifier = false;\n if (baseClassNameWithImportantModifier.endsWith(IMPORTANT_MODIFIER)) {\n baseClassName = baseClassNameWithImportantModifier.slice(0, -1);\n hasImportantModifier = true;\n } else if (\n /**\n * In Tailwind CSS v3 the important modifier was at the start of the base class name. This is still supported for legacy reasons.\n * @see https://github.com/dcastil/tailwind-merge/issues/513#issuecomment-2614029864\n */\n baseClassNameWithImportantModifier.startsWith(IMPORTANT_MODIFIER)) {\n baseClassName = baseClassNameWithImportantModifier.slice(1);\n hasImportantModifier = true;\n }\n const maybePostfixModifierPosition = postfixModifierPosition && postfixModifierPosition > modifierStart ? postfixModifierPosition - modifierStart : undefined;\n return createResultObject(modifiers, hasImportantModifier, baseClassName, maybePostfixModifierPosition);\n };\n if (prefix) {\n const fullPrefix = prefix + MODIFIER_SEPARATOR;\n const parseClassNameOriginal = parseClassName;\n parseClassName = className => className.startsWith(fullPrefix) ? parseClassNameOriginal(className.slice(fullPrefix.length)) : createResultObject(EMPTY_MODIFIERS, false, className, undefined, true);\n }\n if (experimentalParseClassName) {\n const parseClassNameOriginal = parseClassName;\n parseClassName = className => experimentalParseClassName({\n className,\n parseClassName: parseClassNameOriginal\n });\n }\n return parseClassName;\n};\n\n/**\n * Sorts modifiers according to following schema:\n * - Predefined modifiers are sorted alphabetically\n * - When an arbitrary variant appears, it must be preserved which modifiers are before and after it\n */\nconst createSortModifiers = config => {\n // Pre-compute weights for all known modifiers for O(1) comparison\n const modifierWeights = new Map();\n // Assign weights to sensitive modifiers (highest priority, but preserve order)\n config.orderSensitiveModifiers.forEach((mod, index) => {\n modifierWeights.set(mod, 1000000 + index); // High weights for sensitive mods\n });\n return modifiers => {\n const result = [];\n let currentSegment = [];\n // Process modifiers in one pass\n for (let i = 0; i < modifiers.length; i++) {\n const modifier = modifiers[i];\n // Check if modifier is sensitive (starts with '[' or in orderSensitiveModifiers)\n const isArbitrary = modifier[0] === '[';\n const isOrderSensitive = modifierWeights.has(modifier);\n if (isArbitrary || isOrderSensitive) {\n // Sort and flush current segment alphabetically\n if (currentSegment.length > 0) {\n currentSegment.sort();\n result.push(...currentSegment);\n currentSegment = [];\n }\n result.push(modifier);\n } else {\n // Regular modifier - add to current segment for batch sorting\n currentSegment.push(modifier);\n }\n }\n // Sort and add any remaining segment items\n if (currentSegment.length > 0) {\n currentSegment.sort();\n result.push(...currentSegment);\n }\n return result;\n };\n};\nconst createConfigUtils = config => ({\n cache: createLruCache(config.cacheSize),\n parseClassName: createParseClassName(config),\n sortModifiers: createSortModifiers(config),\n ...createClassGroupUtils(config)\n});\nconst SPLIT_CLASSES_REGEX = /\\s+/;\nconst mergeClassList = (classList, configUtils) => {\n const {\n parseClassName,\n getClassGroupId,\n getConflictingClassGroupIds,\n sortModifiers\n } = configUtils;\n /**\n * Set of classGroupIds in following format:\n * `{importantModifier}{variantModifiers}{classGroupId}`\n * @example 'float'\n * @example 'hover:focus:bg-color'\n * @example 'md:!pr'\n */\n const classGroupsInConflict = [];\n const classNames = classList.trim().split(SPLIT_CLASSES_REGEX);\n let result = '';\n for (let index = classNames.length - 1; index >= 0; index -= 1) {\n const originalClassName = classNames[index];\n const {\n isExternal,\n modifiers,\n hasImportantModifier,\n baseClassName,\n maybePostfixModifierPosition\n } = parseClassName(originalClassName);\n if (isExternal) {\n result = originalClassName + (result.length > 0 ? ' ' + result : result);\n continue;\n }\n let hasPostfixModifier = !!maybePostfixModifierPosition;\n let classGroupId = getClassGroupId(hasPostfixModifier ? baseClassName.substring(0, maybePostfixModifierPosition) : baseClassName);\n if (!classGroupId) {\n if (!hasPostfixModifier) {\n // Not a Tailwind class\n result = originalClassName + (result.length > 0 ? ' ' + result : result);\n continue;\n }\n classGroupId = getClassGroupId(baseClassName);\n if (!classGroupId) {\n // Not a Tailwind class\n result = originalClassName + (result.length > 0 ? ' ' + result : result);\n continue;\n }\n hasPostfixModifier = false;\n }\n // Fast path: skip sorting for empty or single modifier\n const variantModifier = modifiers.length === 0 ? '' : modifiers.length === 1 ? modifiers[0] : sortModifiers(modifiers).join(':');\n const modifierId = hasImportantModifier ? variantModifier + IMPORTANT_MODIFIER : variantModifier;\n const classId = modifierId + classGroupId;\n if (classGroupsInConflict.indexOf(classId) > -1) {\n // Tailwind class omitted due to conflict\n continue;\n }\n classGroupsInConflict.push(classId);\n const conflictGroups = getConflictingClassGroupIds(classGroupId, hasPostfixModifier);\n for (let i = 0; i < conflictGroups.length; ++i) {\n const group = conflictGroups[i];\n classGroupsInConflict.push(modifierId + group);\n }\n // Tailwind class not in conflict\n result = originalClassName + (result.length > 0 ? ' ' + result : result);\n }\n return result;\n};\n\n/**\n * The code in this file is copied from https://github.com/lukeed/clsx and modified to suit the needs of tailwind-merge better.\n *\n * Specifically:\n * - Runtime code from https://github.com/lukeed/clsx/blob/v1.2.1/src/index.js\n * - TypeScript types from https://github.com/lukeed/clsx/blob/v1.2.1/clsx.d.ts\n *\n * Original code has MIT license: Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\n */\nconst twJoin = (...classLists) => {\n let index = 0;\n let argument;\n let resolvedValue;\n let string = '';\n while (index < classLists.length) {\n if (argument = classLists[index++]) {\n if (resolvedValue = toValue(argument)) {\n string && (string += ' ');\n string += resolvedValue;\n }\n }\n }\n return string;\n};\nconst toValue = mix => {\n // Fast path for strings\n if (typeof mix === 'string') {\n return mix;\n }\n let resolvedValue;\n let string = '';\n for (let k = 0; k < mix.length; k++) {\n if (mix[k]) {\n if (resolvedValue = toValue(mix[k])) {\n string && (string += ' ');\n string += resolvedValue;\n }\n }\n }\n return string;\n};\nconst createTailwindMerge = (createConfigFirst, ...createConfigRest) => {\n let configUtils;\n let cacheGet;\n let cacheSet;\n let functionToCall;\n const initTailwindMerge = classList => {\n const config = createConfigRest.reduce((previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig), createConfigFirst());\n configUtils = createConfigUtils(config);\n cacheGet = configUtils.cache.get;\n cacheSet = configUtils.cache.set;\n functionToCall = tailwindMerge;\n return tailwindMerge(classList);\n };\n const tailwindMerge = classList => {\n const cachedResult = cacheGet(classList);\n if (cachedResult) {\n return cachedResult;\n }\n const result = mergeClassList(classList, configUtils);\n cacheSet(classList, result);\n return result;\n };\n functionToCall = initTailwindMerge;\n return (...args) => functionToCall(twJoin(...args));\n};\nconst fallbackThemeArr = [];\nconst fromTheme = key => {\n const themeGetter = theme => theme[key] || fallbackThemeArr;\n themeGetter.isThemeGetter = true;\n return themeGetter;\n};\nconst arbitraryValueRegex = /^\\[(?:(\\w[\\w-]*):)?(.+)\\]$/i;\nconst arbitraryVariableRegex = /^\\((?:(\\w[\\w-]*):)?(.+)\\)$/i;\nconst fractionRegex = /^\\d+\\/\\d+$/;\nconst tshirtUnitRegex = /^(\\d+(\\.\\d+)?)?(xs|sm|md|lg|xl)$/;\nconst lengthUnitRegex = /\\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\\b(calc|min|max|clamp)\\(.+\\)|^0$/;\nconst colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\\(.+\\)$/;\n// Shadow always begins with x and y offset separated by underscore optionally prepended by inset\nconst shadowRegex = /^(inset_)?-?((\\d+)?\\.?(\\d+)[a-z]+|0)_-?((\\d+)?\\.?(\\d+)[a-z]+|0)/;\nconst imageRegex = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\\(.+\\)$/;\nconst isFraction = value => fractionRegex.test(value);\nconst isNumber = value => !!value && !Number.isNaN(Number(value));\nconst isInteger = value => !!value && Number.isInteger(Number(value));\nconst isPercent = value => value.endsWith('%') && isNumber(value.slice(0, -1));\nconst isTshirtSize = value => tshirtUnitRegex.test(value);\nconst isAny = () => true;\nconst isLengthOnly = value =>\n// `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths.\n// For example, `hsl(0 0% 0%)` would be classified as a length without this check.\n// I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough.\nlengthUnitRegex.test(value) && !colorFunctionRegex.test(value);\nconst isNever = () => false;\nconst isShadow = value => shadowRegex.test(value);\nconst isImage = value => imageRegex.test(value);\nconst isAnyNonArbitrary = value => !isArbitraryValue(value) && !isArbitraryVariable(value);\nconst isArbitrarySize = value => getIsArbitraryValue(value, isLabelSize, isNever);\nconst isArbitraryValue = value => arbitraryValueRegex.test(value);\nconst isArbitraryLength = value => getIsArbitraryValue(value, isLabelLength, isLengthOnly);\nconst isArbitraryNumber = value => getIsArbitraryValue(value, isLabelNumber, isNumber);\nconst isArbitraryPosition = value => getIsArbitraryValue(value, isLabelPosition, isNever);\nconst isArbitraryImage = value => getIsArbitraryValue(value, isLabelImage, isImage);\nconst isArbitraryShadow = value => getIsArbitraryValue(value, isLabelShadow, isShadow);\nconst isArbitraryVariable = value => arbitraryVariableRegex.test(value);\nconst isArbitraryVariableLength = value => getIsArbitraryVariable(value, isLabelLength);\nconst isArbitraryVariableFamilyName = value => getIsArbitraryVariable(value, isLabelFamilyName);\nconst isArbitraryVariablePosition = value => getIsArbitraryVariable(value, isLabelPosition);\nconst isArbitraryVariableSize = value => getIsArbitraryVariable(value, isLabelSize);\nconst isArbitraryVariableImage = value => getIsArbitraryVariable(value, isLabelImage);\nconst isArbitraryVariableShadow = value => getIsArbitraryVariable(value, isLabelShadow, true);\n// Helpers\nconst getIsArbitraryValue = (value, testLabel, testValue) => {\n const result = arbitraryValueRegex.exec(value);\n if (result) {\n if (result[1]) {\n return testLabel(result[1]);\n }\n return testValue(result[2]);\n }\n return false;\n};\nconst getIsArbitraryVariable = (value, testLabel, shouldMatchNoLabel = false) => {\n const result = arbitraryVariableRegex.exec(value);\n if (result) {\n if (result[1]) {\n return testLabel(result[1]);\n }\n return shouldMatchNoLabel;\n }\n return false;\n};\n// Labels\nconst isLabelPosition = label => label === 'position' || label === 'percentage';\nconst isLabelImage = label => label === 'image' || label === 'url';\nconst isLabelSize = label => label === 'length' || label === 'size' || label === 'bg-size';\nconst isLabelLength = label => label === 'length';\nconst isLabelNumber = label => label === 'number';\nconst isLabelFamilyName = label => label === 'family-name';\nconst isLabelShadow = label => label === 'shadow';\nconst validators = /*#__PURE__*/Object.defineProperty({\n __proto__: null,\n isAny,\n isAnyNonArbitrary,\n isArbitraryImage,\n isArbitraryLength,\n isArbitraryNumber,\n isArbitraryPosition,\n isArbitraryShadow,\n isArbitrarySize,\n isArbitraryValue,\n isArbitraryVariable,\n isArbitraryVariableFamilyName,\n isArbitraryVariableImage,\n isArbitraryVariableLength,\n isArbitraryVariablePosition,\n isArbitraryVariableShadow,\n isArbitraryVariableSize,\n isFraction,\n isInteger,\n isNumber,\n isPercent,\n isTshirtSize\n}, Symbol.toStringTag, {\n value: 'Module'\n});\nconst getDefaultConfig = () => {\n /**\n * Theme getters for theme variable namespaces\n * @see https://tailwindcss.com/docs/theme#theme-variable-namespaces\n */\n /***/\n const themeColor = fromTheme('color');\n const themeFont = fromTheme('font');\n const themeText = fromTheme('text');\n const themeFontWeight = fromTheme('font-weight');\n const themeTracking = fromTheme('tracking');\n const themeLeading = fromTheme('leading');\n const themeBreakpoint = fromTheme('breakpoint');\n const themeContainer = fromTheme('container');\n const themeSpacing = fromTheme('spacing');\n const themeRadius = fromTheme('radius');\n const themeShadow = fromTheme('shadow');\n const themeInsetShadow = fromTheme('inset-shadow');\n const themeTextShadow = fromTheme('text-shadow');\n const themeDropShadow = fromTheme('drop-shadow');\n const themeBlur = fromTheme('blur');\n const themePerspective = fromTheme('perspective');\n const themeAspect = fromTheme('aspect');\n const themeEase = fromTheme('ease');\n const themeAnimate = fromTheme('animate');\n /**\n * Helpers to avoid repeating the same scales\n *\n * We use functions that create a new array every time they're called instead of static arrays.\n * This ensures that users who modify any scale by mutating the array (e.g. with `array.push(element)`) don't accidentally mutate arrays in other parts of the config.\n */\n /***/\n const scaleBreak = () => ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column'];\n const scalePosition = () => ['center', 'top', 'bottom', 'left', 'right', 'top-left',\n // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378\n 'left-top', 'top-right',\n // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378\n 'right-top', 'bottom-right',\n // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378\n 'right-bottom', 'bottom-left',\n // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378\n 'left-bottom'];\n const scalePositionWithArbitrary = () => [...scalePosition(), isArbitraryVariable, isArbitraryValue];\n const scaleOverflow = () => ['auto', 'hidden', 'clip', 'visible', 'scroll'];\n const scaleOverscroll = () => ['auto', 'contain', 'none'];\n const scaleUnambiguousSpacing = () => [isArbitraryVariable, isArbitraryValue, themeSpacing];\n const scaleInset = () => [isFraction, 'full', 'auto', ...scaleUnambiguousSpacing()];\n const scaleGridTemplateColsRows = () => [isInteger, 'none', 'subgrid', isArbitraryVariable, isArbitraryValue];\n const scaleGridColRowStartAndEnd = () => ['auto', {\n span: ['full', isInteger, isArbitraryVariable, isArbitraryValue]\n }, isInteger, isArbitraryVariable, isArbitraryValue];\n const scaleGridColRowStartOrEnd = () => [isInteger, 'auto', isArbitraryVariable, isArbitraryValue];\n const scaleGridAutoColsRows = () => ['auto', 'min', 'max', 'fr', isArbitraryVariable, isArbitraryValue];\n const scaleAlignPrimaryAxis = () => ['start', 'end', 'center', 'between', 'around', 'evenly', 'stretch', 'baseline', 'center-safe', 'end-safe'];\n const scaleAlignSecondaryAxis = () => ['start', 'end', 'center', 'stretch', 'center-safe', 'end-safe'];\n const scaleMargin = () => ['auto', ...scaleUnambiguousSpacing()];\n const scaleSizing = () => [isFraction, 'auto', 'full', 'dvw', 'dvh', 'lvw', 'lvh', 'svw', 'svh', 'min', 'max', 'fit', ...scaleUnambiguousSpacing()];\n const scaleColor = () => [themeColor, isArbitraryVariable, isArbitraryValue];\n const scaleBgPosition = () => [...scalePosition(), isArbitraryVariablePosition, isArbitraryPosition, {\n position: [isArbitraryVariable, isArbitraryValue]\n }];\n const scaleBgRepeat = () => ['no-repeat', {\n repeat: ['', 'x', 'y', 'space', 'round']\n }];\n const scaleBgSize = () => ['auto', 'cover', 'contain', isArbitraryVariableSize, isArbitrarySize, {\n size: [isArbitraryVariable, isArbitraryValue]\n }];\n const scaleGradientStopPosition = () => [isPercent, isArbitraryVariableLength, isArbitraryLength];\n const scaleRadius = () => [\n // Deprecated since Tailwind CSS v4.0.0\n '', 'none', 'full', themeRadius, isArbitraryVariable, isArbitraryValue];\n const scaleBorderWidth = () => ['', isNumber, isArbitraryVariableLength, isArbitraryLength];\n const scaleLineStyle = () => ['solid', 'dashed', 'dotted', 'double'];\n const scaleBlendMode = () => ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'];\n const scaleMaskImagePosition = () => [isNumber, isPercent, isArbitraryVariablePosition, isArbitraryPosition];\n const scaleBlur = () => [\n // Deprecated since Tailwind CSS v4.0.0\n '', 'none', themeBlur, isArbitraryVariable, isArbitraryValue];\n const scaleRotate = () => ['none', isNumber, isArbitraryVariable, isArbitraryValue];\n const scaleScale = () => ['none', isNumber, isArbitraryVariable, isArbitraryValue];\n const scaleSkew = () => [isNumber, isArbitraryVariable, isArbitraryValue];\n const scaleTranslate = () => [isFraction, 'full', ...scaleUnambiguousSpacing()];\n return {\n cacheSize: 500,\n theme: {\n animate: ['spin', 'ping', 'pulse', 'bounce'],\n aspect: ['video'],\n blur: [isTshirtSize],\n breakpoint: [isTshirtSize],\n color: [isAny],\n container: [isTshirtSize],\n 'drop-shadow': [isTshirtSize],\n ease: ['in', 'out', 'in-out'],\n font: [isAnyNonArbitrary],\n 'font-weight': ['thin', 'extralight', 'light', 'normal', 'medium', 'semibold', 'bold', 'extrabold', 'black'],\n 'inset-shadow': [isTshirtSize],\n leading: ['none', 'tight', 'snug', 'normal', 'relaxed', 'loose'],\n perspective: ['dramatic', 'near', 'normal', 'midrange', 'distant', 'none'],\n radius: [isTshirtSize],\n shadow: [isTshirtSize],\n spacing: ['px', isNumber],\n text: [isTshirtSize],\n 'text-shadow': [isTshirtSize],\n tracking: ['tighter', 'tight', 'normal', 'wide', 'wider', 'widest']\n },\n classGroups: {\n // --------------\n // --- Layout ---\n // --------------\n /**\n * Aspect Ratio\n * @see https://tailwindcss.com/docs/aspect-ratio\n */\n aspect: [{\n aspect: ['auto', 'square', isFraction, isArbitraryValue, isArbitraryVariable, themeAspect]\n }],\n /**\n * Container\n * @see https://tailwindcss.com/docs/container\n * @deprecated since Tailwind CSS v4.0.0\n */\n container: ['container'],\n /**\n * Columns\n * @see https://tailwindcss.com/docs/columns\n */\n columns: [{\n columns: [isNumber, isArbitraryValue, isArbitraryVariable, themeContainer]\n }],\n /**\n * Break After\n * @see https://tailwindcss.com/docs/break-after\n */\n 'break-after': [{\n 'break-after': scaleBreak()\n }],\n /**\n * Break Before\n * @see https://tailwindcss.com/docs/break-before\n */\n 'break-before': [{\n 'break-before': scaleBreak()\n }],\n /**\n * Break Inside\n * @see https://tailwindcss.com/docs/break-inside\n */\n 'break-inside': [{\n 'break-inside': ['auto', 'avoid', 'avoid-page', 'avoid-column']\n }],\n /**\n * Box Decoration Break\n * @see https://tailwindcss.com/docs/box-decoration-break\n */\n 'box-decoration': [{\n 'box-decoration': ['slice', 'clone']\n }],\n /**\n * Box Sizing\n * @see https://tailwindcss.com/docs/box-sizing\n */\n box: [{\n box: ['border', 'content']\n }],\n /**\n * Display\n * @see https://tailwindcss.com/docs/display\n */\n display: ['block', 'inline-block', 'inline', 'flex', 'inline-flex', 'table', 'inline-table', 'table-caption', 'table-cell', 'table-column', 'table-column-group', 'table-footer-group', 'table-header-group', 'table-row-group', 'table-row', 'flow-root', 'grid', 'inline-grid', 'contents', 'list-item', 'hidden'],\n /**\n * Screen Reader Only\n * @see https://tailwindcss.com/docs/display#screen-reader-only\n */\n sr: ['sr-only', 'not-sr-only'],\n /**\n * Floats\n * @see https://tailwindcss.com/docs/float\n */\n float: [{\n float: ['right', 'left', 'none', 'start', 'end']\n }],\n /**\n * Clear\n * @see https://tailwindcss.com/docs/clear\n */\n clear: [{\n clear: ['left', 'right', 'both', 'none', 'start', 'end']\n }],\n /**\n * Isolation\n * @see https://tailwindcss.com/docs/isolation\n */\n isolation: ['isolate', 'isolation-auto'],\n /**\n * Object Fit\n * @see https://tailwindcss.com/docs/object-fit\n */\n 'object-fit': [{\n object: ['contain', 'cover', 'fill', 'none', 'scale-down']\n }],\n /**\n * Object Position\n * @see https://tailwindcss.com/docs/object-position\n */\n 'object-position': [{\n object: scalePositionWithArbitrary()\n }],\n /**\n * Overflow\n * @see https://tailwindcss.com/docs/overflow\n */\n overflow: [{\n overflow: scaleOverflow()\n }],\n /**\n * Overflow X\n * @see https://tailwindcss.com/docs/overflow\n */\n 'overflow-x': [{\n 'overflow-x': scaleOverflow()\n }],\n /**\n * Overflow Y\n * @see https://tailwindcss.com/docs/overflow\n */\n 'overflow-y': [{\n 'overflow-y': scaleOverflow()\n }],\n /**\n * Overscroll Behavior\n * @see https://tailwindcss.com/docs/overscroll-behavior\n */\n overscroll: [{\n overscroll: scaleOverscroll()\n }],\n /**\n * Overscroll Behavior X\n * @see https://tailwindcss.com/docs/overscroll-behavior\n */\n 'overscroll-x': [{\n 'overscroll-x': scaleOverscroll()\n }],\n /**\n * Overscroll Behavior Y\n * @see https://tailwindcss.com/docs/overscroll-behavior\n */\n 'overscroll-y': [{\n 'overscroll-y': scaleOverscroll()\n }],\n /**\n * Position\n * @see https://tailwindcss.com/docs/position\n */\n position: ['static', 'fixed', 'absolute', 'relative', 'sticky'],\n /**\n * Top / Right / Bottom / Left\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n inset: [{\n inset: scaleInset()\n }],\n /**\n * Right / Left\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n 'inset-x': [{\n 'inset-x': scaleInset()\n }],\n /**\n * Top / Bottom\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n 'inset-y': [{\n 'inset-y': scaleInset()\n }],\n /**\n * Start\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n start: [{\n start: scaleInset()\n }],\n /**\n * End\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n end: [{\n end: scaleInset()\n }],\n /**\n * Top\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n top: [{\n top: scaleInset()\n }],\n /**\n * Right\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n right: [{\n right: scaleInset()\n }],\n /**\n * Bottom\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n bottom: [{\n bottom: scaleInset()\n }],\n /**\n * Left\n * @see https://tailwindcss.com/docs/top-right-bottom-left\n */\n left: [{\n left: scaleInset()\n }],\n /**\n * Visibility\n * @see https://tailwindcss.com/docs/visibility\n */\n visibility: ['visible', 'invisible', 'collapse'],\n /**\n * Z-Index\n * @see https://tailwindcss.com/docs/z-index\n */\n z: [{\n z: [isInteger, 'auto', isArbitraryVariable, isArbitraryValue]\n }],\n // ------------------------\n // --- Flexbox and Grid ---\n // ------------------------\n /**\n * Flex Basis\n * @see https://tailwindcss.com/docs/flex-basis\n */\n basis: [{\n basis: [isFraction, 'full', 'auto', themeContainer, ...scaleUnambiguousSpacing()]\n }],\n /**\n * Flex Direction\n * @see https://tailwindcss.com/docs/flex-direction\n */\n 'flex-direction': [{\n flex: ['row', 'row-reverse', 'col', 'col-reverse']\n }],\n /**\n * Flex Wrap\n * @see https://tailwindcss.com/docs/flex-wrap\n */\n 'flex-wrap': [{\n flex: ['nowrap', 'wrap', 'wrap-reverse']\n }],\n /**\n * Flex\n * @see https://tailwindcss.com/docs/flex\n */\n flex: [{\n flex: [isNumber, isFraction, 'auto', 'initial', 'none', isArbitraryValue]\n }],\n /**\n * Flex Grow\n * @see https://tailwindcss.com/docs/flex-grow\n */\n grow: [{\n grow: ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Flex Shrink\n * @see https://tailwindcss.com/docs/flex-shrink\n */\n shrink: [{\n shrink: ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Order\n * @see https://tailwindcss.com/docs/order\n */\n order: [{\n order: [isInteger, 'first', 'last', 'none', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Grid Template Columns\n * @see https://tailwindcss.com/docs/grid-template-columns\n */\n 'grid-cols': [{\n 'grid-cols': scaleGridTemplateColsRows()\n }],\n /**\n * Grid Column Start / End\n * @see https://tailwindcss.com/docs/grid-column\n */\n 'col-start-end': [{\n col: scaleGridColRowStartAndEnd()\n }],\n /**\n * Grid Column Start\n * @see https://tailwindcss.com/docs/grid-column\n */\n 'col-start': [{\n 'col-start': scaleGridColRowStartOrEnd()\n }],\n /**\n * Grid Column End\n * @see https://tailwindcss.com/docs/grid-column\n */\n 'col-end': [{\n 'col-end': scaleGridColRowStartOrEnd()\n }],\n /**\n * Grid Template Rows\n * @see https://tailwindcss.com/docs/grid-template-rows\n */\n 'grid-rows': [{\n 'grid-rows': scaleGridTemplateColsRows()\n }],\n /**\n * Grid Row Start / End\n * @see https://tailwindcss.com/docs/grid-row\n */\n 'row-start-end': [{\n row: scaleGridColRowStartAndEnd()\n }],\n /**\n * Grid Row Start\n * @see https://tailwindcss.com/docs/grid-row\n */\n 'row-start': [{\n 'row-start': scaleGridColRowStartOrEnd()\n }],\n /**\n * Grid Row End\n * @see https://tailwindcss.com/docs/grid-row\n */\n 'row-end': [{\n 'row-end': scaleGridColRowStartOrEnd()\n }],\n /**\n * Grid Auto Flow\n * @see https://tailwindcss.com/docs/grid-auto-flow\n */\n 'grid-flow': [{\n 'grid-flow': ['row', 'col', 'dense', 'row-dense', 'col-dense']\n }],\n /**\n * Grid Auto Columns\n * @see https://tailwindcss.com/docs/grid-auto-columns\n */\n 'auto-cols': [{\n 'auto-cols': scaleGridAutoColsRows()\n }],\n /**\n * Grid Auto Rows\n * @see https://tailwindcss.com/docs/grid-auto-rows\n */\n 'auto-rows': [{\n 'auto-rows': scaleGridAutoColsRows()\n }],\n /**\n * Gap\n * @see https://tailwindcss.com/docs/gap\n */\n gap: [{\n gap: scaleUnambiguousSpacing()\n }],\n /**\n * Gap X\n * @see https://tailwindcss.com/docs/gap\n */\n 'gap-x': [{\n 'gap-x': scaleUnambiguousSpacing()\n }],\n /**\n * Gap Y\n * @see https://tailwindcss.com/docs/gap\n */\n 'gap-y': [{\n 'gap-y': scaleUnambiguousSpacing()\n }],\n /**\n * Justify Content\n * @see https://tailwindcss.com/docs/justify-content\n */\n 'justify-content': [{\n justify: [...scaleAlignPrimaryAxis(), 'normal']\n }],\n /**\n * Justify Items\n * @see https://tailwindcss.com/docs/justify-items\n */\n 'justify-items': [{\n 'justify-items': [...scaleAlignSecondaryAxis(), 'normal']\n }],\n /**\n * Justify Self\n * @see https://tailwindcss.com/docs/justify-self\n */\n 'justify-self': [{\n 'justify-self': ['auto', ...scaleAlignSecondaryAxis()]\n }],\n /**\n * Align Content\n * @see https://tailwindcss.com/docs/align-content\n */\n 'align-content': [{\n content: ['normal', ...scaleAlignPrimaryAxis()]\n }],\n /**\n * Align Items\n * @see https://tailwindcss.com/docs/align-items\n */\n 'align-items': [{\n items: [...scaleAlignSecondaryAxis(), {\n baseline: ['', 'last']\n }]\n }],\n /**\n * Align Self\n * @see https://tailwindcss.com/docs/align-self\n */\n 'align-self': [{\n self: ['auto', ...scaleAlignSecondaryAxis(), {\n baseline: ['', 'last']\n }]\n }],\n /**\n * Place Content\n * @see https://tailwindcss.com/docs/place-content\n */\n 'place-content': [{\n 'place-content': scaleAlignPrimaryAxis()\n }],\n /**\n * Place Items\n * @see https://tailwindcss.com/docs/place-items\n */\n 'place-items': [{\n 'place-items': [...scaleAlignSecondaryAxis(), 'baseline']\n }],\n /**\n * Place Self\n * @see https://tailwindcss.com/docs/place-self\n */\n 'place-self': [{\n 'place-self': ['auto', ...scaleAlignSecondaryAxis()]\n }],\n // Spacing\n /**\n * Padding\n * @see https://tailwindcss.com/docs/padding\n */\n p: [{\n p: scaleUnambiguousSpacing()\n }],\n /**\n * Padding X\n * @see https://tailwindcss.com/docs/padding\n */\n px: [{\n px: scaleUnambiguousSpacing()\n }],\n /**\n * Padding Y\n * @see https://tailwindcss.com/docs/padding\n */\n py: [{\n py: scaleUnambiguousSpacing()\n }],\n /**\n * Padding Start\n * @see https://tailwindcss.com/docs/padding\n */\n ps: [{\n ps: scaleUnambiguousSpacing()\n }],\n /**\n * Padding End\n * @see https://tailwindcss.com/docs/padding\n */\n pe: [{\n pe: scaleUnambiguousSpacing()\n }],\n /**\n * Padding Top\n * @see https://tailwindcss.com/docs/padding\n */\n pt: [{\n pt: scaleUnambiguousSpacing()\n }],\n /**\n * Padding Right\n * @see https://tailwindcss.com/docs/padding\n */\n pr: [{\n pr: scaleUnambiguousSpacing()\n }],\n /**\n * Padding Bottom\n * @see https://tailwindcss.com/docs/padding\n */\n pb: [{\n pb: scaleUnambiguousSpacing()\n }],\n /**\n * Padding Left\n * @see https://tailwindcss.com/docs/padding\n */\n pl: [{\n pl: scaleUnambiguousSpacing()\n }],\n /**\n * Margin\n * @see https://tailwindcss.com/docs/margin\n */\n m: [{\n m: scaleMargin()\n }],\n /**\n * Margin X\n * @see https://tailwindcss.com/docs/margin\n */\n mx: [{\n mx: scaleMargin()\n }],\n /**\n * Margin Y\n * @see https://tailwindcss.com/docs/margin\n */\n my: [{\n my: scaleMargin()\n }],\n /**\n * Margin Start\n * @see https://tailwindcss.com/docs/margin\n */\n ms: [{\n ms: scaleMargin()\n }],\n /**\n * Margin End\n * @see https://tailwindcss.com/docs/margin\n */\n me: [{\n me: scaleMargin()\n }],\n /**\n * Margin Top\n * @see https://tailwindcss.com/docs/margin\n */\n mt: [{\n mt: scaleMargin()\n }],\n /**\n * Margin Right\n * @see https://tailwindcss.com/docs/margin\n */\n mr: [{\n mr: scaleMargin()\n }],\n /**\n * Margin Bottom\n * @see https://tailwindcss.com/docs/margin\n */\n mb: [{\n mb: scaleMargin()\n }],\n /**\n * Margin Left\n * @see https://tailwindcss.com/docs/margin\n */\n ml: [{\n ml: scaleMargin()\n }],\n /**\n * Space Between X\n * @see https://tailwindcss.com/docs/margin#adding-space-between-children\n */\n 'space-x': [{\n 'space-x': scaleUnambiguousSpacing()\n }],\n /**\n * Space Between X Reverse\n * @see https://tailwindcss.com/docs/margin#adding-space-between-children\n */\n 'space-x-reverse': ['space-x-reverse'],\n /**\n * Space Between Y\n * @see https://tailwindcss.com/docs/margin#adding-space-between-children\n */\n 'space-y': [{\n 'space-y': scaleUnambiguousSpacing()\n }],\n /**\n * Space Between Y Reverse\n * @see https://tailwindcss.com/docs/margin#adding-space-between-children\n */\n 'space-y-reverse': ['space-y-reverse'],\n // --------------\n // --- Sizing ---\n // --------------\n /**\n * Size\n * @see https://tailwindcss.com/docs/width#setting-both-width-and-height\n */\n size: [{\n size: scaleSizing()\n }],\n /**\n * Width\n * @see https://tailwindcss.com/docs/width\n */\n w: [{\n w: [themeContainer, 'screen', ...scaleSizing()]\n }],\n /**\n * Min-Width\n * @see https://tailwindcss.com/docs/min-width\n */\n 'min-w': [{\n 'min-w': [themeContainer, 'screen', /** Deprecated. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */\n 'none', ...scaleSizing()]\n }],\n /**\n * Max-Width\n * @see https://tailwindcss.com/docs/max-width\n */\n 'max-w': [{\n 'max-w': [themeContainer, 'screen', 'none', /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */\n 'prose', /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */\n {\n screen: [themeBreakpoint]\n }, ...scaleSizing()]\n }],\n /**\n * Height\n * @see https://tailwindcss.com/docs/height\n */\n h: [{\n h: ['screen', 'lh', ...scaleSizing()]\n }],\n /**\n * Min-Height\n * @see https://tailwindcss.com/docs/min-height\n */\n 'min-h': [{\n 'min-h': ['screen', 'lh', 'none', ...scaleSizing()]\n }],\n /**\n * Max-Height\n * @see https://tailwindcss.com/docs/max-height\n */\n 'max-h': [{\n 'max-h': ['screen', 'lh', ...scaleSizing()]\n }],\n // ------------------\n // --- Typography ---\n // ------------------\n /**\n * Font Size\n * @see https://tailwindcss.com/docs/font-size\n */\n 'font-size': [{\n text: ['base', themeText, isArbitraryVariableLength, isArbitraryLength]\n }],\n /**\n * Font Smoothing\n * @see https://tailwindcss.com/docs/font-smoothing\n */\n 'font-smoothing': ['antialiased', 'subpixel-antialiased'],\n /**\n * Font Style\n * @see https://tailwindcss.com/docs/font-style\n */\n 'font-style': ['italic', 'not-italic'],\n /**\n * Font Weight\n * @see https://tailwindcss.com/docs/font-weight\n */\n 'font-weight': [{\n font: [themeFontWeight, isArbitraryVariable, isArbitraryNumber]\n }],\n /**\n * Font Stretch\n * @see https://tailwindcss.com/docs/font-stretch\n */\n 'font-stretch': [{\n 'font-stretch': ['ultra-condensed', 'extra-condensed', 'condensed', 'semi-condensed', 'normal', 'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded', isPercent, isArbitraryValue]\n }],\n /**\n * Font Family\n * @see https://tailwindcss.com/docs/font-family\n */\n 'font-family': [{\n font: [isArbitraryVariableFamilyName, isArbitraryValue, themeFont]\n }],\n /**\n * Font Variant Numeric\n * @see https://tailwindcss.com/docs/font-variant-numeric\n */\n 'fvn-normal': ['normal-nums'],\n /**\n * Font Variant Numeric\n * @see https://tailwindcss.com/docs/font-variant-numeric\n */\n 'fvn-ordinal': ['ordinal'],\n /**\n * Font Variant Numeric\n * @see https://tailwindcss.com/docs/font-variant-numeric\n */\n 'fvn-slashed-zero': ['slashed-zero'],\n /**\n * Font Variant Numeric\n * @see https://tailwindcss.com/docs/font-variant-numeric\n */\n 'fvn-figure': ['lining-nums', 'oldstyle-nums'],\n /**\n * Font Variant Numeric\n * @see https://tailwindcss.com/docs/font-variant-numeric\n */\n 'fvn-spacing': ['proportional-nums', 'tabular-nums'],\n /**\n * Font Variant Numeric\n * @see https://tailwindcss.com/docs/font-variant-numeric\n */\n 'fvn-fraction': ['diagonal-fractions', 'stacked-fractions'],\n /**\n * Letter Spacing\n * @see https://tailwindcss.com/docs/letter-spacing\n */\n tracking: [{\n tracking: [themeTracking, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Line Clamp\n * @see https://tailwindcss.com/docs/line-clamp\n */\n 'line-clamp': [{\n 'line-clamp': [isNumber, 'none', isArbitraryVariable, isArbitraryNumber]\n }],\n /**\n * Line Height\n * @see https://tailwindcss.com/docs/line-height\n */\n leading: [{\n leading: [/** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */\n themeLeading, ...scaleUnambiguousSpacing()]\n }],\n /**\n * List Style Image\n * @see https://tailwindcss.com/docs/list-style-image\n */\n 'list-image': [{\n 'list-image': ['none', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * List Style Position\n * @see https://tailwindcss.com/docs/list-style-position\n */\n 'list-style-position': [{\n list: ['inside', 'outside']\n }],\n /**\n * List Style Type\n * @see https://tailwindcss.com/docs/list-style-type\n */\n 'list-style-type': [{\n list: ['disc', 'decimal', 'none', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Text Alignment\n * @see https://tailwindcss.com/docs/text-align\n */\n 'text-alignment': [{\n text: ['left', 'center', 'right', 'justify', 'start', 'end']\n }],\n /**\n * Placeholder Color\n * @deprecated since Tailwind CSS v3.0.0\n * @see https://v3.tailwindcss.com/docs/placeholder-color\n */\n 'placeholder-color': [{\n placeholder: scaleColor()\n }],\n /**\n * Text Color\n * @see https://tailwindcss.com/docs/text-color\n */\n 'text-color': [{\n text: scaleColor()\n }],\n /**\n * Text Decoration\n * @see https://tailwindcss.com/docs/text-decoration\n */\n 'text-decoration': ['underline', 'overline', 'line-through', 'no-underline'],\n /**\n * Text Decoration Style\n * @see https://tailwindcss.com/docs/text-decoration-style\n */\n 'text-decoration-style': [{\n decoration: [...scaleLineStyle(), 'wavy']\n }],\n /**\n * Text Decoration Thickness\n * @see https://tailwindcss.com/docs/text-decoration-thickness\n */\n 'text-decoration-thickness': [{\n decoration: [isNumber, 'from-font', 'auto', isArbitraryVariable, isArbitraryLength]\n }],\n /**\n * Text Decoration Color\n * @see https://tailwindcss.com/docs/text-decoration-color\n */\n 'text-decoration-color': [{\n decoration: scaleColor()\n }],\n /**\n * Text Underline Offset\n * @see https://tailwindcss.com/docs/text-underline-offset\n */\n 'underline-offset': [{\n 'underline-offset': [isNumber, 'auto', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Text Transform\n * @see https://tailwindcss.com/docs/text-transform\n */\n 'text-transform': ['uppercase', 'lowercase', 'capitalize', 'normal-case'],\n /**\n * Text Overflow\n * @see https://tailwindcss.com/docs/text-overflow\n */\n 'text-overflow': ['truncate', 'text-ellipsis', 'text-clip'],\n /**\n * Text Wrap\n * @see https://tailwindcss.com/docs/text-wrap\n */\n 'text-wrap': [{\n text: ['wrap', 'nowrap', 'balance', 'pretty']\n }],\n /**\n * Text Indent\n * @see https://tailwindcss.com/docs/text-indent\n */\n indent: [{\n indent: scaleUnambiguousSpacing()\n }],\n /**\n * Vertical Alignment\n * @see https://tailwindcss.com/docs/vertical-align\n */\n 'vertical-align': [{\n align: ['baseline', 'top', 'middle', 'bottom', 'text-top', 'text-bottom', 'sub', 'super', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Whitespace\n * @see https://tailwindcss.com/docs/whitespace\n */\n whitespace: [{\n whitespace: ['normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'break-spaces']\n }],\n /**\n * Word Break\n * @see https://tailwindcss.com/docs/word-break\n */\n break: [{\n break: ['normal', 'words', 'all', 'keep']\n }],\n /**\n * Overflow Wrap\n * @see https://tailwindcss.com/docs/overflow-wrap\n */\n wrap: [{\n wrap: ['break-word', 'anywhere', 'normal']\n }],\n /**\n * Hyphens\n * @see https://tailwindcss.com/docs/hyphens\n */\n hyphens: [{\n hyphens: ['none', 'manual', 'auto']\n }],\n /**\n * Content\n * @see https://tailwindcss.com/docs/content\n */\n content: [{\n content: ['none', isArbitraryVariable, isArbitraryValue]\n }],\n // -------------------\n // --- Backgrounds ---\n // -------------------\n /**\n * Background Attachment\n * @see https://tailwindcss.com/docs/background-attachment\n */\n 'bg-attachment': [{\n bg: ['fixed', 'local', 'scroll']\n }],\n /**\n * Background Clip\n * @see https://tailwindcss.com/docs/background-clip\n */\n 'bg-clip': [{\n 'bg-clip': ['border', 'padding', 'content', 'text']\n }],\n /**\n * Background Origin\n * @see https://tailwindcss.com/docs/background-origin\n */\n 'bg-origin': [{\n 'bg-origin': ['border', 'padding', 'content']\n }],\n /**\n * Background Position\n * @see https://tailwindcss.com/docs/background-position\n */\n 'bg-position': [{\n bg: scaleBgPosition()\n }],\n /**\n * Background Repeat\n * @see https://tailwindcss.com/docs/background-repeat\n */\n 'bg-repeat': [{\n bg: scaleBgRepeat()\n }],\n /**\n * Background Size\n * @see https://tailwindcss.com/docs/background-size\n */\n 'bg-size': [{\n bg: scaleBgSize()\n }],\n /**\n * Background Image\n * @see https://tailwindcss.com/docs/background-image\n */\n 'bg-image': [{\n bg: ['none', {\n linear: [{\n to: ['t', 'tr', 'r', 'br', 'b', 'bl', 'l', 'tl']\n }, isInteger, isArbitraryVariable, isArbitraryValue],\n radial: ['', isArbitraryVariable, isArbitraryValue],\n conic: [isInteger, isArbitraryVariable, isArbitraryValue]\n }, isArbitraryVariableImage, isArbitraryImage]\n }],\n /**\n * Background Color\n * @see https://tailwindcss.com/docs/background-color\n */\n 'bg-color': [{\n bg: scaleColor()\n }],\n /**\n * Gradient Color Stops From Position\n * @see https://tailwindcss.com/docs/gradient-color-stops\n */\n 'gradient-from-pos': [{\n from: scaleGradientStopPosition()\n }],\n /**\n * Gradient Color Stops Via Position\n * @see https://tailwindcss.com/docs/gradient-color-stops\n */\n 'gradient-via-pos': [{\n via: scaleGradientStopPosition()\n }],\n /**\n * Gradient Color Stops To Position\n * @see https://tailwindcss.com/docs/gradient-color-stops\n */\n 'gradient-to-pos': [{\n to: scaleGradientStopPosition()\n }],\n /**\n * Gradient Color Stops From\n * @see https://tailwindcss.com/docs/gradient-color-stops\n */\n 'gradient-from': [{\n from: scaleColor()\n }],\n /**\n * Gradient Color Stops Via\n * @see https://tailwindcss.com/docs/gradient-color-stops\n */\n 'gradient-via': [{\n via: scaleColor()\n }],\n /**\n * Gradient Color Stops To\n * @see https://tailwindcss.com/docs/gradient-color-stops\n */\n 'gradient-to': [{\n to: scaleColor()\n }],\n // ---------------\n // --- Borders ---\n // ---------------\n /**\n * Border Radius\n * @see https://tailwindcss.com/docs/border-radius\n */\n rounded: [{\n rounded: scaleRadius()\n }],\n /**\n * Border Radius Start\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-s': [{\n 'rounded-s': scaleRadius()\n }],\n /**\n * Border Radius End\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-e': [{\n 'rounded-e': scaleRadius()\n }],\n /**\n * Border Radius Top\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-t': [{\n 'rounded-t': scaleRadius()\n }],\n /**\n * Border Radius Right\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-r': [{\n 'rounded-r': scaleRadius()\n }],\n /**\n * Border Radius Bottom\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-b': [{\n 'rounded-b': scaleRadius()\n }],\n /**\n * Border Radius Left\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-l': [{\n 'rounded-l': scaleRadius()\n }],\n /**\n * Border Radius Start Start\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-ss': [{\n 'rounded-ss': scaleRadius()\n }],\n /**\n * Border Radius Start End\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-se': [{\n 'rounded-se': scaleRadius()\n }],\n /**\n * Border Radius End End\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-ee': [{\n 'rounded-ee': scaleRadius()\n }],\n /**\n * Border Radius End Start\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-es': [{\n 'rounded-es': scaleRadius()\n }],\n /**\n * Border Radius Top Left\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-tl': [{\n 'rounded-tl': scaleRadius()\n }],\n /**\n * Border Radius Top Right\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-tr': [{\n 'rounded-tr': scaleRadius()\n }],\n /**\n * Border Radius Bottom Right\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-br': [{\n 'rounded-br': scaleRadius()\n }],\n /**\n * Border Radius Bottom Left\n * @see https://tailwindcss.com/docs/border-radius\n */\n 'rounded-bl': [{\n 'rounded-bl': scaleRadius()\n }],\n /**\n * Border Width\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w': [{\n border: scaleBorderWidth()\n }],\n /**\n * Border Width X\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-x': [{\n 'border-x': scaleBorderWidth()\n }],\n /**\n * Border Width Y\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-y': [{\n 'border-y': scaleBorderWidth()\n }],\n /**\n * Border Width Start\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-s': [{\n 'border-s': scaleBorderWidth()\n }],\n /**\n * Border Width End\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-e': [{\n 'border-e': scaleBorderWidth()\n }],\n /**\n * Border Width Top\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-t': [{\n 'border-t': scaleBorderWidth()\n }],\n /**\n * Border Width Right\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-r': [{\n 'border-r': scaleBorderWidth()\n }],\n /**\n * Border Width Bottom\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-b': [{\n 'border-b': scaleBorderWidth()\n }],\n /**\n * Border Width Left\n * @see https://tailwindcss.com/docs/border-width\n */\n 'border-w-l': [{\n 'border-l': scaleBorderWidth()\n }],\n /**\n * Divide Width X\n * @see https://tailwindcss.com/docs/border-width#between-children\n */\n 'divide-x': [{\n 'divide-x': scaleBorderWidth()\n }],\n /**\n * Divide Width X Reverse\n * @see https://tailwindcss.com/docs/border-width#between-children\n */\n 'divide-x-reverse': ['divide-x-reverse'],\n /**\n * Divide Width Y\n * @see https://tailwindcss.com/docs/border-width#between-children\n */\n 'divide-y': [{\n 'divide-y': scaleBorderWidth()\n }],\n /**\n * Divide Width Y Reverse\n * @see https://tailwindcss.com/docs/border-width#between-children\n */\n 'divide-y-reverse': ['divide-y-reverse'],\n /**\n * Border Style\n * @see https://tailwindcss.com/docs/border-style\n */\n 'border-style': [{\n border: [...scaleLineStyle(), 'hidden', 'none']\n }],\n /**\n * Divide Style\n * @see https://tailwindcss.com/docs/border-style#setting-the-divider-style\n */\n 'divide-style': [{\n divide: [...scaleLineStyle(), 'hidden', 'none']\n }],\n /**\n * Border Color\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color': [{\n border: scaleColor()\n }],\n /**\n * Border Color X\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-x': [{\n 'border-x': scaleColor()\n }],\n /**\n * Border Color Y\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-y': [{\n 'border-y': scaleColor()\n }],\n /**\n * Border Color S\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-s': [{\n 'border-s': scaleColor()\n }],\n /**\n * Border Color E\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-e': [{\n 'border-e': scaleColor()\n }],\n /**\n * Border Color Top\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-t': [{\n 'border-t': scaleColor()\n }],\n /**\n * Border Color Right\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-r': [{\n 'border-r': scaleColor()\n }],\n /**\n * Border Color Bottom\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-b': [{\n 'border-b': scaleColor()\n }],\n /**\n * Border Color Left\n * @see https://tailwindcss.com/docs/border-color\n */\n 'border-color-l': [{\n 'border-l': scaleColor()\n }],\n /**\n * Divide Color\n * @see https://tailwindcss.com/docs/divide-color\n */\n 'divide-color': [{\n divide: scaleColor()\n }],\n /**\n * Outline Style\n * @see https://tailwindcss.com/docs/outline-style\n */\n 'outline-style': [{\n outline: [...scaleLineStyle(), 'none', 'hidden']\n }],\n /**\n * Outline Offset\n * @see https://tailwindcss.com/docs/outline-offset\n */\n 'outline-offset': [{\n 'outline-offset': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Outline Width\n * @see https://tailwindcss.com/docs/outline-width\n */\n 'outline-w': [{\n outline: ['', isNumber, isArbitraryVariableLength, isArbitraryLength]\n }],\n /**\n * Outline Color\n * @see https://tailwindcss.com/docs/outline-color\n */\n 'outline-color': [{\n outline: scaleColor()\n }],\n // ---------------\n // --- Effects ---\n // ---------------\n /**\n * Box Shadow\n * @see https://tailwindcss.com/docs/box-shadow\n */\n shadow: [{\n shadow: [\n // Deprecated since Tailwind CSS v4.0.0\n '', 'none', themeShadow, isArbitraryVariableShadow, isArbitraryShadow]\n }],\n /**\n * Box Shadow Color\n * @see https://tailwindcss.com/docs/box-shadow#setting-the-shadow-color\n */\n 'shadow-color': [{\n shadow: scaleColor()\n }],\n /**\n * Inset Box Shadow\n * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-shadow\n */\n 'inset-shadow': [{\n 'inset-shadow': ['none', themeInsetShadow, isArbitraryVariableShadow, isArbitraryShadow]\n }],\n /**\n * Inset Box Shadow Color\n * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-shadow-color\n */\n 'inset-shadow-color': [{\n 'inset-shadow': scaleColor()\n }],\n /**\n * Ring Width\n * @see https://tailwindcss.com/docs/box-shadow#adding-a-ring\n */\n 'ring-w': [{\n ring: scaleBorderWidth()\n }],\n /**\n * Ring Width Inset\n * @see https://v3.tailwindcss.com/docs/ring-width#inset-rings\n * @deprecated since Tailwind CSS v4.0.0\n * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158\n */\n 'ring-w-inset': ['ring-inset'],\n /**\n * Ring Color\n * @see https://tailwindcss.com/docs/box-shadow#setting-the-ring-color\n */\n 'ring-color': [{\n ring: scaleColor()\n }],\n /**\n * Ring Offset Width\n * @see https://v3.tailwindcss.com/docs/ring-offset-width\n * @deprecated since Tailwind CSS v4.0.0\n * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158\n */\n 'ring-offset-w': [{\n 'ring-offset': [isNumber, isArbitraryLength]\n }],\n /**\n * Ring Offset Color\n * @see https://v3.tailwindcss.com/docs/ring-offset-color\n * @deprecated since Tailwind CSS v4.0.0\n * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158\n */\n 'ring-offset-color': [{\n 'ring-offset': scaleColor()\n }],\n /**\n * Inset Ring Width\n * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-ring\n */\n 'inset-ring-w': [{\n 'inset-ring': scaleBorderWidth()\n }],\n /**\n * Inset Ring Color\n * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-ring-color\n */\n 'inset-ring-color': [{\n 'inset-ring': scaleColor()\n }],\n /**\n * Text Shadow\n * @see https://tailwindcss.com/docs/text-shadow\n */\n 'text-shadow': [{\n 'text-shadow': ['none', themeTextShadow, isArbitraryVariableShadow, isArbitraryShadow]\n }],\n /**\n * Text Shadow Color\n * @see https://tailwindcss.com/docs/text-shadow#setting-the-shadow-color\n */\n 'text-shadow-color': [{\n 'text-shadow': scaleColor()\n }],\n /**\n * Opacity\n * @see https://tailwindcss.com/docs/opacity\n */\n opacity: [{\n opacity: [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Mix Blend Mode\n * @see https://tailwindcss.com/docs/mix-blend-mode\n */\n 'mix-blend': [{\n 'mix-blend': [...scaleBlendMode(), 'plus-darker', 'plus-lighter']\n }],\n /**\n * Background Blend Mode\n * @see https://tailwindcss.com/docs/background-blend-mode\n */\n 'bg-blend': [{\n 'bg-blend': scaleBlendMode()\n }],\n /**\n * Mask Clip\n * @see https://tailwindcss.com/docs/mask-clip\n */\n 'mask-clip': [{\n 'mask-clip': ['border', 'padding', 'content', 'fill', 'stroke', 'view']\n }, 'mask-no-clip'],\n /**\n * Mask Composite\n * @see https://tailwindcss.com/docs/mask-composite\n */\n 'mask-composite': [{\n mask: ['add', 'subtract', 'intersect', 'exclude']\n }],\n /**\n * Mask Image\n * @see https://tailwindcss.com/docs/mask-image\n */\n 'mask-image-linear-pos': [{\n 'mask-linear': [isNumber]\n }],\n 'mask-image-linear-from-pos': [{\n 'mask-linear-from': scaleMaskImagePosition()\n }],\n 'mask-image-linear-to-pos': [{\n 'mask-linear-to': scaleMaskImagePosition()\n }],\n 'mask-image-linear-from-color': [{\n 'mask-linear-from': scaleColor()\n }],\n 'mask-image-linear-to-color': [{\n 'mask-linear-to': scaleColor()\n }],\n 'mask-image-t-from-pos': [{\n 'mask-t-from': scaleMaskImagePosition()\n }],\n 'mask-image-t-to-pos': [{\n 'mask-t-to': scaleMaskImagePosition()\n }],\n 'mask-image-t-from-color': [{\n 'mask-t-from': scaleColor()\n }],\n 'mask-image-t-to-color': [{\n 'mask-t-to': scaleColor()\n }],\n 'mask-image-r-from-pos': [{\n 'mask-r-from': scaleMaskImagePosition()\n }],\n 'mask-image-r-to-pos': [{\n 'mask-r-to': scaleMaskImagePosition()\n }],\n 'mask-image-r-from-color': [{\n 'mask-r-from': scaleColor()\n }],\n 'mask-image-r-to-color': [{\n 'mask-r-to': scaleColor()\n }],\n 'mask-image-b-from-pos': [{\n 'mask-b-from': scaleMaskImagePosition()\n }],\n 'mask-image-b-to-pos': [{\n 'mask-b-to': scaleMaskImagePosition()\n }],\n 'mask-image-b-from-color': [{\n 'mask-b-from': scaleColor()\n }],\n 'mask-image-b-to-color': [{\n 'mask-b-to': scaleColor()\n }],\n 'mask-image-l-from-pos': [{\n 'mask-l-from': scaleMaskImagePosition()\n }],\n 'mask-image-l-to-pos': [{\n 'mask-l-to': scaleMaskImagePosition()\n }],\n 'mask-image-l-from-color': [{\n 'mask-l-from': scaleColor()\n }],\n 'mask-image-l-to-color': [{\n 'mask-l-to': scaleColor()\n }],\n 'mask-image-x-from-pos': [{\n 'mask-x-from': scaleMaskImagePosition()\n }],\n 'mask-image-x-to-pos': [{\n 'mask-x-to': scaleMaskImagePosition()\n }],\n 'mask-image-x-from-color': [{\n 'mask-x-from': scaleColor()\n }],\n 'mask-image-x-to-color': [{\n 'mask-x-to': scaleColor()\n }],\n 'mask-image-y-from-pos': [{\n 'mask-y-from': scaleMaskImagePosition()\n }],\n 'mask-image-y-to-pos': [{\n 'mask-y-to': scaleMaskImagePosition()\n }],\n 'mask-image-y-from-color': [{\n 'mask-y-from': scaleColor()\n }],\n 'mask-image-y-to-color': [{\n 'mask-y-to': scaleColor()\n }],\n 'mask-image-radial': [{\n 'mask-radial': [isArbitraryVariable, isArbitraryValue]\n }],\n 'mask-image-radial-from-pos': [{\n 'mask-radial-from': scaleMaskImagePosition()\n }],\n 'mask-image-radial-to-pos': [{\n 'mask-radial-to': scaleMaskImagePosition()\n }],\n 'mask-image-radial-from-color': [{\n 'mask-radial-from': scaleColor()\n }],\n 'mask-image-radial-to-color': [{\n 'mask-radial-to': scaleColor()\n }],\n 'mask-image-radial-shape': [{\n 'mask-radial': ['circle', 'ellipse']\n }],\n 'mask-image-radial-size': [{\n 'mask-radial': [{\n closest: ['side', 'corner'],\n farthest: ['side', 'corner']\n }]\n }],\n 'mask-image-radial-pos': [{\n 'mask-radial-at': scalePosition()\n }],\n 'mask-image-conic-pos': [{\n 'mask-conic': [isNumber]\n }],\n 'mask-image-conic-from-pos': [{\n 'mask-conic-from': scaleMaskImagePosition()\n }],\n 'mask-image-conic-to-pos': [{\n 'mask-conic-to': scaleMaskImagePosition()\n }],\n 'mask-image-conic-from-color': [{\n 'mask-conic-from': scaleColor()\n }],\n 'mask-image-conic-to-color': [{\n 'mask-conic-to': scaleColor()\n }],\n /**\n * Mask Mode\n * @see https://tailwindcss.com/docs/mask-mode\n */\n 'mask-mode': [{\n mask: ['alpha', 'luminance', 'match']\n }],\n /**\n * Mask Origin\n * @see https://tailwindcss.com/docs/mask-origin\n */\n 'mask-origin': [{\n 'mask-origin': ['border', 'padding', 'content', 'fill', 'stroke', 'view']\n }],\n /**\n * Mask Position\n * @see https://tailwindcss.com/docs/mask-position\n */\n 'mask-position': [{\n mask: scaleBgPosition()\n }],\n /**\n * Mask Repeat\n * @see https://tailwindcss.com/docs/mask-repeat\n */\n 'mask-repeat': [{\n mask: scaleBgRepeat()\n }],\n /**\n * Mask Size\n * @see https://tailwindcss.com/docs/mask-size\n */\n 'mask-size': [{\n mask: scaleBgSize()\n }],\n /**\n * Mask Type\n * @see https://tailwindcss.com/docs/mask-type\n */\n 'mask-type': [{\n 'mask-type': ['alpha', 'luminance']\n }],\n /**\n * Mask Image\n * @see https://tailwindcss.com/docs/mask-image\n */\n 'mask-image': [{\n mask: ['none', isArbitraryVariable, isArbitraryValue]\n }],\n // ---------------\n // --- Filters ---\n // ---------------\n /**\n * Filter\n * @see https://tailwindcss.com/docs/filter\n */\n filter: [{\n filter: [\n // Deprecated since Tailwind CSS v3.0.0\n '', 'none', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Blur\n * @see https://tailwindcss.com/docs/blur\n */\n blur: [{\n blur: scaleBlur()\n }],\n /**\n * Brightness\n * @see https://tailwindcss.com/docs/brightness\n */\n brightness: [{\n brightness: [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Contrast\n * @see https://tailwindcss.com/docs/contrast\n */\n contrast: [{\n contrast: [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Drop Shadow\n * @see https://tailwindcss.com/docs/drop-shadow\n */\n 'drop-shadow': [{\n 'drop-shadow': [\n // Deprecated since Tailwind CSS v4.0.0\n '', 'none', themeDropShadow, isArbitraryVariableShadow, isArbitraryShadow]\n }],\n /**\n * Drop Shadow Color\n * @see https://tailwindcss.com/docs/filter-drop-shadow#setting-the-shadow-color\n */\n 'drop-shadow-color': [{\n 'drop-shadow': scaleColor()\n }],\n /**\n * Grayscale\n * @see https://tailwindcss.com/docs/grayscale\n */\n grayscale: [{\n grayscale: ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Hue Rotate\n * @see https://tailwindcss.com/docs/hue-rotate\n */\n 'hue-rotate': [{\n 'hue-rotate': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Invert\n * @see https://tailwindcss.com/docs/invert\n */\n invert: [{\n invert: ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Saturate\n * @see https://tailwindcss.com/docs/saturate\n */\n saturate: [{\n saturate: [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Sepia\n * @see https://tailwindcss.com/docs/sepia\n */\n sepia: [{\n sepia: ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Filter\n * @see https://tailwindcss.com/docs/backdrop-filter\n */\n 'backdrop-filter': [{\n 'backdrop-filter': [\n // Deprecated since Tailwind CSS v3.0.0\n '', 'none', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Blur\n * @see https://tailwindcss.com/docs/backdrop-blur\n */\n 'backdrop-blur': [{\n 'backdrop-blur': scaleBlur()\n }],\n /**\n * Backdrop Brightness\n * @see https://tailwindcss.com/docs/backdrop-brightness\n */\n 'backdrop-brightness': [{\n 'backdrop-brightness': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Contrast\n * @see https://tailwindcss.com/docs/backdrop-contrast\n */\n 'backdrop-contrast': [{\n 'backdrop-contrast': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Grayscale\n * @see https://tailwindcss.com/docs/backdrop-grayscale\n */\n 'backdrop-grayscale': [{\n 'backdrop-grayscale': ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Hue Rotate\n * @see https://tailwindcss.com/docs/backdrop-hue-rotate\n */\n 'backdrop-hue-rotate': [{\n 'backdrop-hue-rotate': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Invert\n * @see https://tailwindcss.com/docs/backdrop-invert\n */\n 'backdrop-invert': [{\n 'backdrop-invert': ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Opacity\n * @see https://tailwindcss.com/docs/backdrop-opacity\n */\n 'backdrop-opacity': [{\n 'backdrop-opacity': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Saturate\n * @see https://tailwindcss.com/docs/backdrop-saturate\n */\n 'backdrop-saturate': [{\n 'backdrop-saturate': [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Backdrop Sepia\n * @see https://tailwindcss.com/docs/backdrop-sepia\n */\n 'backdrop-sepia': [{\n 'backdrop-sepia': ['', isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n // --------------\n // --- Tables ---\n // --------------\n /**\n * Border Collapse\n * @see https://tailwindcss.com/docs/border-collapse\n */\n 'border-collapse': [{\n border: ['collapse', 'separate']\n }],\n /**\n * Border Spacing\n * @see https://tailwindcss.com/docs/border-spacing\n */\n 'border-spacing': [{\n 'border-spacing': scaleUnambiguousSpacing()\n }],\n /**\n * Border Spacing X\n * @see https://tailwindcss.com/docs/border-spacing\n */\n 'border-spacing-x': [{\n 'border-spacing-x': scaleUnambiguousSpacing()\n }],\n /**\n * Border Spacing Y\n * @see https://tailwindcss.com/docs/border-spacing\n */\n 'border-spacing-y': [{\n 'border-spacing-y': scaleUnambiguousSpacing()\n }],\n /**\n * Table Layout\n * @see https://tailwindcss.com/docs/table-layout\n */\n 'table-layout': [{\n table: ['auto', 'fixed']\n }],\n /**\n * Caption Side\n * @see https://tailwindcss.com/docs/caption-side\n */\n caption: [{\n caption: ['top', 'bottom']\n }],\n // ---------------------------------\n // --- Transitions and Animation ---\n // ---------------------------------\n /**\n * Transition Property\n * @see https://tailwindcss.com/docs/transition-property\n */\n transition: [{\n transition: ['', 'all', 'colors', 'opacity', 'shadow', 'transform', 'none', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Transition Behavior\n * @see https://tailwindcss.com/docs/transition-behavior\n */\n 'transition-behavior': [{\n transition: ['normal', 'discrete']\n }],\n /**\n * Transition Duration\n * @see https://tailwindcss.com/docs/transition-duration\n */\n duration: [{\n duration: [isNumber, 'initial', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Transition Timing Function\n * @see https://tailwindcss.com/docs/transition-timing-function\n */\n ease: [{\n ease: ['linear', 'initial', themeEase, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Transition Delay\n * @see https://tailwindcss.com/docs/transition-delay\n */\n delay: [{\n delay: [isNumber, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Animation\n * @see https://tailwindcss.com/docs/animation\n */\n animate: [{\n animate: ['none', themeAnimate, isArbitraryVariable, isArbitraryValue]\n }],\n // ------------------\n // --- Transforms ---\n // ------------------\n /**\n * Backface Visibility\n * @see https://tailwindcss.com/docs/backface-visibility\n */\n backface: [{\n backface: ['hidden', 'visible']\n }],\n /**\n * Perspective\n * @see https://tailwindcss.com/docs/perspective\n */\n perspective: [{\n perspective: [themePerspective, isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Perspective Origin\n * @see https://tailwindcss.com/docs/perspective-origin\n */\n 'perspective-origin': [{\n 'perspective-origin': scalePositionWithArbitrary()\n }],\n /**\n * Rotate\n * @see https://tailwindcss.com/docs/rotate\n */\n rotate: [{\n rotate: scaleRotate()\n }],\n /**\n * Rotate X\n * @see https://tailwindcss.com/docs/rotate\n */\n 'rotate-x': [{\n 'rotate-x': scaleRotate()\n }],\n /**\n * Rotate Y\n * @see https://tailwindcss.com/docs/rotate\n */\n 'rotate-y': [{\n 'rotate-y': scaleRotate()\n }],\n /**\n * Rotate Z\n * @see https://tailwindcss.com/docs/rotate\n */\n 'rotate-z': [{\n 'rotate-z': scaleRotate()\n }],\n /**\n * Scale\n * @see https://tailwindcss.com/docs/scale\n */\n scale: [{\n scale: scaleScale()\n }],\n /**\n * Scale X\n * @see https://tailwindcss.com/docs/scale\n */\n 'scale-x': [{\n 'scale-x': scaleScale()\n }],\n /**\n * Scale Y\n * @see https://tailwindcss.com/docs/scale\n */\n 'scale-y': [{\n 'scale-y': scaleScale()\n }],\n /**\n * Scale Z\n * @see https://tailwindcss.com/docs/scale\n */\n 'scale-z': [{\n 'scale-z': scaleScale()\n }],\n /**\n * Scale 3D\n * @see https://tailwindcss.com/docs/scale\n */\n 'scale-3d': ['scale-3d'],\n /**\n * Skew\n * @see https://tailwindcss.com/docs/skew\n */\n skew: [{\n skew: scaleSkew()\n }],\n /**\n * Skew X\n * @see https://tailwindcss.com/docs/skew\n */\n 'skew-x': [{\n 'skew-x': scaleSkew()\n }],\n /**\n * Skew Y\n * @see https://tailwindcss.com/docs/skew\n */\n 'skew-y': [{\n 'skew-y': scaleSkew()\n }],\n /**\n * Transform\n * @see https://tailwindcss.com/docs/transform\n */\n transform: [{\n transform: [isArbitraryVariable, isArbitraryValue, '', 'none', 'gpu', 'cpu']\n }],\n /**\n * Transform Origin\n * @see https://tailwindcss.com/docs/transform-origin\n */\n 'transform-origin': [{\n origin: scalePositionWithArbitrary()\n }],\n /**\n * Transform Style\n * @see https://tailwindcss.com/docs/transform-style\n */\n 'transform-style': [{\n transform: ['3d', 'flat']\n }],\n /**\n * Translate\n * @see https://tailwindcss.com/docs/translate\n */\n translate: [{\n translate: scaleTranslate()\n }],\n /**\n * Translate X\n * @see https://tailwindcss.com/docs/translate\n */\n 'translate-x': [{\n 'translate-x': scaleTranslate()\n }],\n /**\n * Translate Y\n * @see https://tailwindcss.com/docs/translate\n */\n 'translate-y': [{\n 'translate-y': scaleTranslate()\n }],\n /**\n * Translate Z\n * @see https://tailwindcss.com/docs/translate\n */\n 'translate-z': [{\n 'translate-z': scaleTranslate()\n }],\n /**\n * Translate None\n * @see https://tailwindcss.com/docs/translate\n */\n 'translate-none': ['translate-none'],\n // ---------------------\n // --- Interactivity ---\n // ---------------------\n /**\n * Accent Color\n * @see https://tailwindcss.com/docs/accent-color\n */\n accent: [{\n accent: scaleColor()\n }],\n /**\n * Appearance\n * @see https://tailwindcss.com/docs/appearance\n */\n appearance: [{\n appearance: ['none', 'auto']\n }],\n /**\n * Caret Color\n * @see https://tailwindcss.com/docs/just-in-time-mode#caret-color-utilities\n */\n 'caret-color': [{\n caret: scaleColor()\n }],\n /**\n * Color Scheme\n * @see https://tailwindcss.com/docs/color-scheme\n */\n 'color-scheme': [{\n scheme: ['normal', 'dark', 'light', 'light-dark', 'only-dark', 'only-light']\n }],\n /**\n * Cursor\n * @see https://tailwindcss.com/docs/cursor\n */\n cursor: [{\n cursor: ['auto', 'default', 'pointer', 'wait', 'text', 'move', 'help', 'not-allowed', 'none', 'context-menu', 'progress', 'cell', 'crosshair', 'vertical-text', 'alias', 'copy', 'no-drop', 'grab', 'grabbing', 'all-scroll', 'col-resize', 'row-resize', 'n-resize', 'e-resize', 's-resize', 'w-resize', 'ne-resize', 'nw-resize', 'se-resize', 'sw-resize', 'ew-resize', 'ns-resize', 'nesw-resize', 'nwse-resize', 'zoom-in', 'zoom-out', isArbitraryVariable, isArbitraryValue]\n }],\n /**\n * Field Sizing\n * @see https://tailwindcss.com/docs/field-sizing\n */\n 'field-sizing': [{\n 'field-sizing': ['fixed', 'content']\n }],\n /**\n * Pointer Events\n * @see https://tailwindcss.com/docs/pointer-events\n */\n 'pointer-events': [{\n 'pointer-events': ['auto', 'none']\n }],\n /**\n * Resize\n * @see https://tailwindcss.com/docs/resize\n */\n resize: [{\n resize: ['none', '', 'y', 'x']\n }],\n /**\n * Scroll Behavior\n * @see https://tailwindcss.com/docs/scroll-behavior\n */\n 'scroll-behavior': [{\n scroll: ['auto', 'smooth']\n }],\n /**\n * Scroll Margin\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-m': [{\n 'scroll-m': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin X\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-mx': [{\n 'scroll-mx': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin Y\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-my': [{\n 'scroll-my': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin Start\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-ms': [{\n 'scroll-ms': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin End\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-me': [{\n 'scroll-me': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin Top\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-mt': [{\n 'scroll-mt': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin Right\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-mr': [{\n 'scroll-mr': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin Bottom\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-mb': [{\n 'scroll-mb': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Margin Left\n * @see https://tailwindcss.com/docs/scroll-margin\n */\n 'scroll-ml': [{\n 'scroll-ml': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-p': [{\n 'scroll-p': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding X\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-px': [{\n 'scroll-px': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding Y\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-py': [{\n 'scroll-py': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding Start\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-ps': [{\n 'scroll-ps': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding End\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-pe': [{\n 'scroll-pe': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding Top\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-pt': [{\n 'scroll-pt': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding Right\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-pr': [{\n 'scroll-pr': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding Bottom\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-pb': [{\n 'scroll-pb': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Padding Left\n * @see https://tailwindcss.com/docs/scroll-padding\n */\n 'scroll-pl': [{\n 'scroll-pl': scaleUnambiguousSpacing()\n }],\n /**\n * Scroll Snap Align\n * @see https://tailwindcss.com/docs/scroll-snap-align\n */\n 'snap-align': [{\n snap: ['start', 'end', 'center', 'align-none']\n }],\n /**\n * Scroll Snap Stop\n * @see https://tailwindcss.com/docs/scroll-snap-stop\n */\n 'snap-stop': [{\n snap: ['normal', 'always']\n }],\n /**\n * Scroll Snap Type\n * @see https://tailwindcss.com/docs/scroll-snap-type\n */\n 'snap-type': [{\n snap: ['none', 'x', 'y', 'both']\n }],\n /**\n * Scroll Snap Type Strictness\n * @see https://tailwindcss.com/docs/scroll-snap-type\n */\n 'snap-strictness': [{\n snap: ['mandatory', 'proximity']\n }],\n /**\n * Touch Action\n * @see https://tailwindcss.com/docs/touch-action\n */\n touch: [{\n touch: ['auto', 'none', 'manipulation']\n }],\n /**\n * Touch Action X\n * @see https://tailwindcss.com/docs/touch-action\n */\n 'touch-x': [{\n 'touch-pan': ['x', 'left', 'right']\n }],\n /**\n * Touch Action Y\n * @see https://tailwindcss.com/docs/touch-action\n */\n 'touch-y': [{\n 'touch-pan': ['y', 'up', 'down']\n }],\n /**\n * Touch Action Pinch Zoom\n * @see https://tailwindcss.com/docs/touch-action\n */\n 'touch-pz': ['touch-pinch-zoom'],\n /**\n * User Select\n * @see https://tailwindcss.com/docs/user-select\n */\n select: [{\n select: ['none', 'text', 'all', 'auto']\n }],\n /**\n * Will Change\n * @see https://tailwindcss.com/docs/will-change\n */\n 'will-change': [{\n 'will-change': ['auto', 'scroll', 'contents', 'transform', isArbitraryVariable, isArbitraryValue]\n }],\n // -----------\n // --- SVG ---\n // -----------\n /**\n * Fill\n * @see https://tailwindcss.com/docs/fill\n */\n fill: [{\n fill: ['none', ...scaleColor()]\n }],\n /**\n * Stroke Width\n * @see https://tailwindcss.com/docs/stroke-width\n */\n 'stroke-w': [{\n stroke: [isNumber, isArbitraryVariableLength, isArbitraryLength, isArbitraryNumber]\n }],\n /**\n * Stroke\n * @see https://tailwindcss.com/docs/stroke\n */\n stroke: [{\n stroke: ['none', ...scaleColor()]\n }],\n // ---------------------\n // --- Accessibility ---\n // ---------------------\n /**\n * Forced Color Adjust\n * @see https://tailwindcss.com/docs/forced-color-adjust\n */\n 'forced-color-adjust': [{\n 'forced-color-adjust': ['auto', 'none']\n }]\n },\n conflictingClassGroups: {\n overflow: ['overflow-x', 'overflow-y'],\n overscroll: ['overscroll-x', 'overscroll-y'],\n inset: ['inset-x', 'inset-y', 'start', 'end', 'top', 'right', 'bottom', 'left'],\n 'inset-x': ['right', 'left'],\n 'inset-y': ['top', 'bottom'],\n flex: ['basis', 'grow', 'shrink'],\n gap: ['gap-x', 'gap-y'],\n p: ['px', 'py', 'ps', 'pe', 'pt', 'pr', 'pb', 'pl'],\n px: ['pr', 'pl'],\n py: ['pt', 'pb'],\n m: ['mx', 'my', 'ms', 'me', 'mt', 'mr', 'mb', 'ml'],\n mx: ['mr', 'ml'],\n my: ['mt', 'mb'],\n size: ['w', 'h'],\n 'font-size': ['leading'],\n 'fvn-normal': ['fvn-ordinal', 'fvn-slashed-zero', 'fvn-figure', 'fvn-spacing', 'fvn-fraction'],\n 'fvn-ordinal': ['fvn-normal'],\n 'fvn-slashed-zero': ['fvn-normal'],\n 'fvn-figure': ['fvn-normal'],\n 'fvn-spacing': ['fvn-normal'],\n 'fvn-fraction': ['fvn-normal'],\n 'line-clamp': ['display', 'overflow'],\n rounded: ['rounded-s', 'rounded-e', 'rounded-t', 'rounded-r', 'rounded-b', 'rounded-l', 'rounded-ss', 'rounded-se', 'rounded-ee', 'rounded-es', 'rounded-tl', 'rounded-tr', 'rounded-br', 'rounded-bl'],\n 'rounded-s': ['rounded-ss', 'rounded-es'],\n 'rounded-e': ['rounded-se', 'rounded-ee'],\n 'rounded-t': ['rounded-tl', 'rounded-tr'],\n 'rounded-r': ['rounded-tr', 'rounded-br'],\n 'rounded-b': ['rounded-br', 'rounded-bl'],\n 'rounded-l': ['rounded-tl', 'rounded-bl'],\n 'border-spacing': ['border-spacing-x', 'border-spacing-y'],\n 'border-w': ['border-w-x', 'border-w-y', 'border-w-s', 'border-w-e', 'border-w-t', 'border-w-r', 'border-w-b', 'border-w-l'],\n 'border-w-x': ['border-w-r', 'border-w-l'],\n 'border-w-y': ['border-w-t', 'border-w-b'],\n 'border-color': ['border-color-x', 'border-color-y', 'border-color-s', 'border-color-e', 'border-color-t', 'border-color-r', 'border-color-b', 'border-color-l'],\n 'border-color-x': ['border-color-r', 'border-color-l'],\n 'border-color-y': ['border-color-t', 'border-color-b'],\n translate: ['translate-x', 'translate-y', 'translate-none'],\n 'translate-none': ['translate', 'translate-x', 'translate-y', 'translate-z'],\n 'scroll-m': ['scroll-mx', 'scroll-my', 'scroll-ms', 'scroll-me', 'scroll-mt', 'scroll-mr', 'scroll-mb', 'scroll-ml'],\n 'scroll-mx': ['scroll-mr', 'scroll-ml'],\n 'scroll-my': ['scroll-mt', 'scroll-mb'],\n 'scroll-p': ['scroll-px', 'scroll-py', 'scroll-ps', 'scroll-pe', 'scroll-pt', 'scroll-pr', 'scroll-pb', 'scroll-pl'],\n 'scroll-px': ['scroll-pr', 'scroll-pl'],\n 'scroll-py': ['scroll-pt', 'scroll-pb'],\n touch: ['touch-x', 'touch-y', 'touch-pz'],\n 'touch-x': ['touch'],\n 'touch-y': ['touch'],\n 'touch-pz': ['touch']\n },\n conflictingClassGroupModifiers: {\n 'font-size': ['leading']\n },\n orderSensitiveModifiers: ['*', '**', 'after', 'backdrop', 'before', 'details-content', 'file', 'first-letter', 'first-line', 'marker', 'placeholder', 'selection']\n };\n};\n\n/**\n * @param baseConfig Config where other config will be merged into. This object will be mutated.\n * @param configExtension Partial config to merge into the `baseConfig`.\n */\nconst mergeConfigs = (baseConfig, {\n cacheSize,\n prefix,\n experimentalParseClassName,\n extend = {},\n override = {}\n}) => {\n overrideProperty(baseConfig, 'cacheSize', cacheSize);\n overrideProperty(baseConfig, 'prefix', prefix);\n overrideProperty(baseConfig, 'experimentalParseClassName', experimentalParseClassName);\n overrideConfigProperties(baseConfig.theme, override.theme);\n overrideConfigProperties(baseConfig.classGroups, override.classGroups);\n overrideConfigProperties(baseConfig.conflictingClassGroups, override.conflictingClassGroups);\n overrideConfigProperties(baseConfig.conflictingClassGroupModifiers, override.conflictingClassGroupModifiers);\n overrideProperty(baseConfig, 'orderSensitiveModifiers', override.orderSensitiveModifiers);\n mergeConfigProperties(baseConfig.theme, extend.theme);\n mergeConfigProperties(baseConfig.classGroups, extend.classGroups);\n mergeConfigProperties(baseConfig.conflictingClassGroups, extend.conflictingClassGroups);\n mergeConfigProperties(baseConfig.conflictingClassGroupModifiers, extend.conflictingClassGroupModifiers);\n mergeArrayProperties(baseConfig, extend, 'orderSensitiveModifiers');\n return baseConfig;\n};\nconst overrideProperty = (baseObject, overrideKey, overrideValue) => {\n if (overrideValue !== undefined) {\n baseObject[overrideKey] = overrideValue;\n }\n};\nconst overrideConfigProperties = (baseObject, overrideObject) => {\n if (overrideObject) {\n for (const key in overrideObject) {\n overrideProperty(baseObject, key, overrideObject[key]);\n }\n }\n};\nconst mergeConfigProperties = (baseObject, mergeObject) => {\n if (mergeObject) {\n for (const key in mergeObject) {\n mergeArrayProperties(baseObject, mergeObject, key);\n }\n }\n};\nconst mergeArrayProperties = (baseObject, mergeObject, key) => {\n const mergeValue = mergeObject[key];\n if (mergeValue !== undefined) {\n baseObject[key] = baseObject[key] ? baseObject[key].concat(mergeValue) : mergeValue;\n }\n};\nconst extendTailwindMerge = (configExtension, ...createConfig) => typeof configExtension === 'function' ? createTailwindMerge(getDefaultConfig, configExtension, ...createConfig) : createTailwindMerge(() => mergeConfigs(getDefaultConfig(), configExtension), ...createConfig);\nconst twMerge = /*#__PURE__*/createTailwindMerge(getDefaultConfig);\nexport { createTailwindMerge, extendTailwindMerge, fromTheme, getDefaultConfig, mergeConfigs, twJoin, twMerge, validators };\n//# sourceMappingURL=bundle-mjs.mjs.map\n","import { clsx, type ClassValue } from 'clsx'\r\nimport { twMerge } from 'tailwind-merge'\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs))\r\n}\r\n","/**\r\n * @package @botuyo/chat-widget\r\n * Sistema de Temas y CSS Variables\r\n *\r\n * Este módulo centraliza toda la gestión de temas del widget.\r\n * Exporta temas predefinidos, utilidades y constantes.\r\n */\r\n\r\nimport { ChatTheme } from '../types'\r\n\r\n/**\r\n * ===================================\r\n * CSS VARIABLES (HSL Format)\r\n * ===================================\r\n */\r\n\r\nexport interface CSSVariables {\r\n background: string // Fondo principal\r\n foreground: string // Texto principal\r\n card: string // Fondo de tarjetas\r\n cardForeground: string // Texto en tarjetas\r\n primary: string // Color primario\r\n primaryForeground: string // Texto sobre primario\r\n muted: string // Fondos atenuados\r\n mutedForeground: string // Texto atenuado\r\n border: string // Bordes\r\n destructive: string // Color de error\r\n radius: string // Radio de bordes\r\n\r\n // Design System - Spacing\r\n spacing1?: string // 0.25rem (4px) - Extra small\r\n spacing2?: string // 0.5rem (8px) - Small\r\n spacing3?: string // 0.75rem (12px) - Medium small\r\n spacing4?: string // 1rem (16px) - Medium (default)\r\n spacing5?: string // 1.25rem (20px) - Medium large\r\n spacing6?: string // 1.5rem (24px) - Large\r\n spacing8?: string // 2rem (32px) - Extra large\r\n}\r\n\r\n/**\r\n * Valores CSS por defecto (Light Mode - BotUyo)\r\n */\r\nexport const DEFAULT_CSS_VARIABLES: CSSVariables = {\r\n background: '0 0% 100%', // Blanco\r\n foreground: '240 10% 3.9%', // Negro azulado\r\n card: '0 0% 100%', // Blanco\r\n cardForeground: '240 10% 3.9%', // Negro azulado\r\n primary: '160 84% 39%', // Verde BotUyo\r\n primaryForeground: '0 0% 100%', // Blanco\r\n muted: '240 4.8% 95.9%', // Gris claro\r\n mutedForeground: '240 3.8% 46.1%', // Gris oscuro\r\n border: '240 5.9% 90%', // Gris borde\r\n destructive: '0 84.2% 60.2%', // Rojo\r\n radius: '0.5rem', // 8px\r\n\r\n // Design System - Spacing\r\n spacing1: '0.25rem', // 4px\r\n spacing2: '0.5rem', // 8px\r\n spacing3: '0.75rem', // 12px\r\n spacing4: '1rem', // 16px (default)\r\n spacing5: '0.75rem', // 12px (padding default)\r\n spacing6: '1.5rem', // 24px\r\n spacing8: '2rem', // 32px\r\n}\r\n\r\n/**\r\n * Valores CSS para Dark Mode\r\n */\r\nexport const DARK_CSS_VARIABLES: CSSVariables = {\r\n background: '240 10% 3.9%', // Fondo oscuro\r\n foreground: '0 0% 98%', // Texto claro\r\n card: '240 10% 10%', // Tarjetas oscuras\r\n cardForeground: '0 0% 98%', // Texto claro\r\n primary: '160 84% 39%', // Verde BotUyo\r\n primaryForeground: '0 0% 100%', // Blanco\r\n muted: '240 3.7% 15.9%', // Gris oscuro\r\n mutedForeground: '240 5% 64.9%', // Gris claro\r\n border: '240 3.7% 15.9%', // Bordes oscuros\r\n destructive: '0 63% 31%', // Rojo oscuro\r\n radius: '0.5rem', // 8px\r\n\r\n // Design System - Spacing (mismo que light)\r\n spacing1: '0.25rem',\r\n spacing2: '0.5rem',\r\n spacing3: '0.75rem',\r\n spacing4: '1rem',\r\n spacing5: '0.75rem',\r\n spacing6: '1.5rem',\r\n spacing8: '2rem',\r\n}\r\n\r\n/**\r\n * ===================================\r\n * TEMAS PREDEFINIDOS\r\n * ===================================\r\n *\r\n * Cada tema está diseñado para ser visualmente único y distintivo.\r\n * Los usuarios pueden personalizar cualquier valor, y el sistema de merge\r\n * garantiza que los valores faltantes se completen con defaults.\r\n */\r\n\r\n/**\r\n * TEMA DEFAULT - BotUyo (Verde Fresco)\r\n * Tema por defecto cuando no se envía configuración\r\n */\r\nexport const DEFAULT_THEME: Required<\r\n Omit<\r\n ChatTheme,\r\n | 'avatars'\r\n | 'emotion'\r\n | 'starterPrompt'\r\n | 'launcherBorderRadius'\r\n | 'borderRadius'\r\n | 'bubbleStyles'\r\n | 'promptPersistence'\r\n | 'avatarScale'\r\n | 'height'\r\n | 'bottom'\r\n | 'defaultLocale'\r\n >\r\n> = {\r\n primaryColor: 'hsl(160, 84%, 39%)',\r\n botName: 'Asistente',\r\n logoUrl: '',\r\n position: 'bottom-right',\r\n welcomeMessage: '¡Hola! ¿En qué puedo ayudarte?',\r\n inputPlaceholder: 'Escribe un mensaje...',\r\n cssVariables: DEFAULT_CSS_VARIABLES,\r\n}\r\n\r\n/**\r\n * TEMA OCEAN - Azul Profundo\r\n * Diseño profesional y corporativo con tonos azules\r\n */\r\nexport const OCEAN_THEME: ChatTheme = {\r\n primaryColor: 'hsl(211, 100%, 50%)',\r\n botName: 'Ocean Assistant',\r\n welcomeMessage: 'Bienvenido, ¿cómo puedo ayudarte?',\r\n cssVariables: {\r\n background: '210 25% 98%',\r\n foreground: '210 50% 10%',\r\n card: '210 20% 97%',\r\n cardForeground: '210 50% 10%',\r\n primary: '211 100% 50%',\r\n primaryForeground: '0 0% 100%',\r\n muted: '210 20% 95%',\r\n mutedForeground: '210 15% 40%',\r\n border: '210 20% 88%',\r\n destructive: '0 84% 60%',\r\n radius: '0.75rem',\r\n spacing5: '1rem', // 16px - más espacioso\r\n },\r\n}\r\n\r\n/**\r\n * TEMA SUNSET - Naranja Cálido\r\n * Diseño energético y amigable con tonos cálidos\r\n */\r\nexport const SUNSET_THEME: ChatTheme = {\r\n primaryColor: 'hsl(24, 95%, 53%)',\r\n botName: 'Sunset Helper',\r\n welcomeMessage: '👋 ¡Hola! Estoy aquí para ayudarte',\r\n inputPlaceholder: '¿Qué necesitas?',\r\n cssVariables: {\r\n background: '30 40% 98%',\r\n foreground: '20 30% 15%',\r\n card: '30 35% 96%',\r\n cardForeground: '20 30% 15%',\r\n primary: '24 95% 53%',\r\n primaryForeground: '0 0% 100%',\r\n muted: '30 25% 94%',\r\n mutedForeground: '20 15% 35%',\r\n border: '30 20% 85%',\r\n destructive: '0 84% 60%',\r\n radius: '1.25rem', // Bordes muy redondeados\r\n spacing3: '1rem', // 16px - gaps más amplios\r\n spacing5: '1.25rem', // 20px - padding generoso\r\n },\r\n}\r\n\r\n/**\r\n * TEMA MIDNIGHT - Negro Premium\r\n * Diseño oscuro y minimalista de alto contraste\r\n */\r\nexport const MIDNIGHT_THEME: ChatTheme = {\r\n primaryColor: 'hsl(0, 0%, 100%)',\r\n botName: 'Midnight AI',\r\n welcomeMessage: 'Hello.',\r\n inputPlaceholder: 'Type a message...',\r\n cssVariables: {\r\n background: '0 0% 7%',\r\n foreground: '0 0% 98%',\r\n card: '0 0% 10%',\r\n cardForeground: '0 0% 98%',\r\n primary: '0 0% 100%',\r\n primaryForeground: '0 0% 0%',\r\n muted: '0 0% 15%',\r\n mutedForeground: '0 0% 70%',\r\n border: '0 0% 20%',\r\n destructive: '0 84% 60%',\r\n radius: '0.25rem', // Bordes cuadrados\r\n spacing1: '0.125rem', // 2px - muy compacto\r\n spacing2: '0.25rem', // 4px\r\n spacing3: '0.5rem', // 8px\r\n spacing5: '0.625rem', // 10px - muy compacto\r\n },\r\n}\r\n\r\n/**\r\n * TEMA NATURE - Verde Bosque\r\n * Diseño natural y relajante\r\n */\r\nexport const NATURE_THEME: ChatTheme = {\r\n primaryColor: 'hsl(142, 71%, 45%)',\r\n botName: 'Nature Guide',\r\n welcomeMessage: '🌿 ¡Hola! ¿En qué puedo asistirte?',\r\n cssVariables: {\r\n background: '140 30% 97%',\r\n foreground: '140 40% 15%',\r\n card: '140 25% 95%',\r\n cardForeground: '140 40% 15%',\r\n primary: '142 71% 45%',\r\n primaryForeground: '0 0% 100%',\r\n muted: '140 20% 92%',\r\n mutedForeground: '140 15% 35%',\r\n border: '140 20% 85%',\r\n destructive: '0 84% 60%',\r\n radius: '0.875rem',\r\n },\r\n}\r\n\r\n/**\r\n * ===================================\r\n * UTILIDADES\r\n * ===================================\r\n */\r\n\r\n/**\r\n * Sistema de Merge de Temas con Prioridades\r\n *\r\n * PRIORIDAD (de mayor a menor):\r\n * 1. Tema del proyecto (userTheme) - Lo que el usuario define en su código\r\n * 2. Tema del socket (socketTheme) - Lo que viene de la API/configuración remota\r\n * 3. Tema por defecto (DEFAULT_THEME) - Valores fallback\r\n *\r\n * El merge es PROFUNDO para cssVariables, garantizando que cada propiedad\r\n * individual se complete con su fallback correspondiente.\r\n */\r\nexport function mergeThemeWithDefaults(\r\n userTheme?: Partial<ChatTheme>,\r\n socketTheme?: Partial<ChatTheme>\r\n): Required<\r\n Omit<\r\n ChatTheme,\r\n | 'avatars'\r\n | 'emotion'\r\n | 'starterPrompt'\r\n | 'launcherBorderRadius'\r\n | 'borderRadius'\r\n | 'bubbleStyles'\r\n | 'promptPersistence'\r\n | 'avatarScale'\r\n | 'height'\r\n | 'bottom'\r\n | 'defaultLocale'\r\n >\r\n> {\r\n // Merge de cssVariables con prioridad: user > socket > default\r\n const mergedCssVariables: CSSVariables = {\r\n ...DEFAULT_CSS_VARIABLES,\r\n ...(socketTheme?.cssVariables || {}),\r\n ...(userTheme?.cssVariables || {}),\r\n }\r\n\r\n return {\r\n primaryColor:\r\n userTheme?.primaryColor || socketTheme?.primaryColor || DEFAULT_THEME.primaryColor,\r\n botName: userTheme?.botName || socketTheme?.botName || DEFAULT_THEME.botName,\r\n logoUrl: userTheme?.logoUrl || socketTheme?.logoUrl || DEFAULT_THEME.logoUrl,\r\n position: userTheme?.position || socketTheme?.position || DEFAULT_THEME.position,\r\n welcomeMessage:\r\n userTheme?.welcomeMessage || socketTheme?.welcomeMessage || DEFAULT_THEME.welcomeMessage,\r\n inputPlaceholder:\r\n userTheme?.inputPlaceholder ||\r\n socketTheme?.inputPlaceholder ||\r\n DEFAULT_THEME.inputPlaceholder,\r\n cssVariables: mergedCssVariables,\r\n }\r\n}\r\n\r\n/**\r\n * Obtiene el color primario con fallback\r\n */\r\nexport function getPrimaryColor(options: { primaryColor?: string }): string {\r\n return options.primaryColor || DEFAULT_THEME.primaryColor\r\n}\r\n\r\n/**\r\n * Convierte variables CSS a un objeto de estilos inline\r\n */\r\nexport function cssVariablesToInlineStyles(\r\n variables: Partial<CSSVariables>\r\n): Record<string, string> {\r\n const merged = { ...DEFAULT_CSS_VARIABLES, ...variables }\r\n return {\r\n '--background': merged.background,\r\n '--foreground': merged.foreground,\r\n '--card': merged.card,\r\n '--card-foreground': merged.cardForeground,\r\n '--primary': merged.primary,\r\n '--primary-foreground': merged.primaryForeground,\r\n '--muted': merged.muted,\r\n '--muted-foreground': merged.mutedForeground,\r\n '--border': merged.border,\r\n '--destructive': merged.destructive,\r\n '--radius': merged.radius,\r\n }\r\n}\r\n\r\n/**\r\n * Genera estilos de color sólidos desde variables CSS\r\n */\r\nexport function getSolidStyles(variables?: Partial<CSSVariables>) {\r\n const vars = { ...DEFAULT_CSS_VARIABLES, ...variables }\r\n return {\r\n background: `hsl(${vars.background})`,\r\n foreground: `hsl(${vars.foreground})`,\r\n card: `hsl(${vars.card})`,\r\n cardForeground: `hsl(${vars.cardForeground})`,\r\n primary: `hsl(${vars.primary})`,\r\n primaryForeground: `hsl(${vars.primaryForeground})`,\r\n muted: `hsl(${vars.muted})`,\r\n mutedForeground: `hsl(${vars.mutedForeground})`,\r\n border: `hsl(${vars.border})`,\r\n destructive: `hsl(${vars.destructive})`,\r\n }\r\n}\r\n\r\n/**\r\n * Retorna el tema completo con fallbacks aplicados\r\n */\r\nexport function getMergedTheme(theme: ChatTheme = {}): ChatTheme {\r\n return theme\r\n}\r\n","/**\r\n * @package @botuyo/chat-widget\r\n * Centralized logger with DEBUG flag for production builds\r\n *\r\n * Principio: Single Responsibility - solo gestionar logging\r\n */\r\n\r\ninterface Logger {\r\n log: (message: string, ...args: any[]) => void\r\n warn: (message: string, ...args: any[]) => void\r\n error: (message: string, ...args: any[]) => void\r\n debug: (message: string, ...args: any[]) => void\r\n info: (message: string, ...args: any[]) => void\r\n}\r\n\r\n/**\r\n * Determina si el modo DEBUG está activo\r\n * - En desarrollo: siempre activo\r\n * - En producción: solo si window.DEBUG = true\r\n */\r\nfunction isDebugEnabled(): boolean {\r\n if (typeof window === 'undefined') return false\r\n\r\n // Modo desarrollo (verificar modo DEV de Vite)\r\n const isDev = typeof import.meta !== 'undefined' && (import.meta as any).env?.DEV === true\r\n\r\n if (isDev) return true\r\n\r\n // Producción: verificar flag global\r\n return !!(window as any).DEBUG\r\n}\r\n\r\n/**\r\n * Logger centralizado con control de DEBUG\r\n *\r\n * Uso:\r\n * - import { logger } from '@/chat-widget/utils/logger'\r\n * - logger.log('[Component]', 'mensaje')\r\n * - logger.error('[Error]', error)\r\n *\r\n * Habilitar en producción:\r\n * - window.DEBUG = true (en consola del navegador)\r\n */\r\nexport const logger: Logger = {\r\n log: (message: string, ...args: any[]) => {\r\n if (isDebugEnabled()) {\r\n console.log(`[BotUyo] ${message}`, ...args)\r\n }\r\n },\r\n\r\n warn: (message: string, ...args: any[]) => {\r\n if (isDebugEnabled()) {\r\n console.warn(`[BotUyo] ${message}`, ...args)\r\n }\r\n },\r\n\r\n error: (message: string, ...args: any[]) => {\r\n // Errores siempre se muestran\r\n console.error(`[BotUyo] ${message}`, ...args)\r\n },\r\n\r\n debug: (message: string, ...args: any[]) => {\r\n if (isDebugEnabled()) {\r\n console.debug(`[BotUyo] ${message}`, ...args)\r\n }\r\n },\r\n\r\n info: (message: string, ...args: any[]) => {\r\n if (isDebugEnabled()) {\r\n console.info(`[BotUyo] ${message}`, ...args)\r\n }\r\n },\r\n}\r\n\r\n/**\r\n * Alternativa silenciosa para testing\r\n */\r\nexport const silentLogger: Logger = {\r\n log: () => {},\r\n warn: () => {},\r\n error: () => {},\r\n debug: () => {},\r\n info: () => {},\r\n}\r\n","/**\n * @package @botuyo/chat-widget\n * Default assets bundled inline to avoid external dependencies\n *\n * These are fallback values when the client doesn't provide custom assets.\n * All assets are embedded as data URLs or inline content to work regardless\n * of the hosting environment.\n */\n\n/**\n * Default bot avatar as an inline SVG data URL\n * Simple friendly bot icon in a circular format\n */\nexport const DEFAULT_AVATAR_URL = `data:image/svg+xml,${encodeURIComponent(`\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\" width=\"64\" height=\"64\">\n <defs>\n <linearGradient id=\"bg\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" style=\"stop-color:#10b981\"/>\n <stop offset=\"100%\" style=\"stop-color:#059669\"/>\n </linearGradient>\n </defs>\n <circle cx=\"32\" cy=\"32\" r=\"32\" fill=\"url(#bg)\"/>\n <rect x=\"16\" y=\"20\" width=\"32\" height=\"24\" rx=\"4\" fill=\"white\"/>\n <circle cx=\"24\" cy=\"30\" r=\"3\" fill=\"#10b981\"/>\n <circle cx=\"40\" cy=\"30\" r=\"3\" fill=\"#10b981\"/>\n <rect x=\"22\" y=\"36\" width=\"20\" height=\"3\" rx=\"1.5\" fill=\"#10b981\"/>\n <rect x=\"28\" y=\"12\" width=\"8\" height=\"8\" rx=\"2\" fill=\"white\"/>\n</svg>\n`)}`\n\n/**\n * Notification sound as base64-encoded WAV\n * Simple short \"ding\" sound (minimal file size)\n * Generated programmatically - a brief 440Hz tone\n */\nexport const DEFAULT_NOTIFICATION_SOUND_URL = createNotificationSoundDataUrl()\n\n/**\n * Creates a simple notification beep sound as a data URL\n * Uses Web Audio API compatible format\n */\nfunction createNotificationSoundDataUrl(): string {\n // Simple WAV header + 440Hz sine wave for 150ms at 8kHz sample rate\n // This creates a ~1.2KB audio file\n const sampleRate = 8000\n const duration = 0.15\n const frequency = 880 // Higher pitched, pleasant \"ding\"\n const numSamples = Math.floor(sampleRate * duration)\n\n // WAV file structure\n const bytesPerSample = 2\n const dataSize = numSamples * bytesPerSample\n const fileSize = 44 + dataSize\n\n const buffer = new ArrayBuffer(fileSize)\n const view = new DataView(buffer)\n\n // RIFF header\n writeString(view, 0, 'RIFF')\n view.setUint32(4, fileSize - 8, true)\n writeString(view, 8, 'WAVE')\n\n // fmt chunk\n writeString(view, 12, 'fmt ')\n view.setUint32(16, 16, true) // chunk size\n view.setUint16(20, 1, true) // PCM format\n view.setUint16(22, 1, true) // mono\n view.setUint32(24, sampleRate, true)\n view.setUint32(28, sampleRate * bytesPerSample, true) // byte rate\n view.setUint16(32, bytesPerSample, true) // block align\n view.setUint16(34, 16, true) // bits per sample\n\n // data chunk\n writeString(view, 36, 'data')\n view.setUint32(40, dataSize, true)\n\n // Generate sine wave with fade out\n for (let i = 0; i < numSamples; i++) {\n const t = i / sampleRate\n const fadeOut = 1 - i / numSamples // Linear fade out\n const sample = Math.sin(2 * Math.PI * frequency * t) * fadeOut * 0.5 * 32767\n view.setInt16(44 + i * bytesPerSample, sample, true)\n }\n\n // Convert to base64\n const bytes = new Uint8Array(buffer)\n let binary = ''\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i])\n }\n\n return `data:audio/wav;base64,${btoa(binary)}`\n}\n\nfunction writeString(view: DataView, offset: number, string: string): void {\n for (let i = 0; i < string.length; i++) {\n view.setUint8(offset + i, string.charCodeAt(i))\n }\n}\n","function memo(getDeps, fn, opts) {\n let deps = opts.initialDeps ?? [];\n let result;\n let isInitial = true;\n function memoizedFunction() {\n var _a, _b, _c;\n let depTime;\n if (opts.key && ((_a = opts.debug) == null ? void 0 : _a.call(opts))) depTime = Date.now();\n const newDeps = getDeps();\n const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);\n if (!depsChanged) {\n return result;\n }\n deps = newDeps;\n let resultTime;\n if (opts.key && ((_b = opts.debug) == null ? void 0 : _b.call(opts))) resultTime = Date.now();\n result = fn(...newDeps);\n if (opts.key && ((_c = opts.debug) == null ? void 0 : _c.call(opts))) {\n const depEndTime = Math.round((Date.now() - depTime) * 100) / 100;\n const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;\n const resultFpsPercentage = resultEndTime / 16;\n const pad = (str, num) => {\n str = String(str);\n while (str.length < num) {\n str = \" \" + str;\n }\n return str;\n };\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120)\n )}deg 100% 31%);`,\n opts == null ? void 0 : opts.key\n );\n }\n if ((opts == null ? void 0 : opts.onChange) && !(isInitial && opts.skipInitialOnChange)) {\n opts.onChange(result);\n }\n isInitial = false;\n return result;\n }\n memoizedFunction.updateDeps = (newDeps) => {\n deps = newDeps;\n };\n return memoizedFunction;\n}\nfunction notUndefined(value, msg) {\n if (value === void 0) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : \"\"}`);\n } else {\n return value;\n }\n}\nconst approxEqual = (a, b) => Math.abs(a - b) < 1.01;\nconst debounce = (targetWindow, fn, ms) => {\n let timeoutId;\n return function(...args) {\n targetWindow.clearTimeout(timeoutId);\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms);\n };\n};\nexport {\n approxEqual,\n debounce,\n memo,\n notUndefined\n};\n//# sourceMappingURL=utils.js.map\n","import { debounce, memo, notUndefined, approxEqual } from \"./utils.js\";\nconst getRect = (element) => {\n const { offsetWidth, offsetHeight } = element;\n return { width: offsetWidth, height: offsetHeight };\n};\nconst defaultKeyExtractor = (index) => index;\nconst defaultRangeExtractor = (range) => {\n const start = Math.max(range.startIndex - range.overscan, 0);\n const end = Math.min(range.endIndex + range.overscan, range.count - 1);\n const arr = [];\n for (let i = start; i <= end; i++) {\n arr.push(i);\n }\n return arr;\n};\nconst observeElementRect = (instance, cb) => {\n const element = instance.scrollElement;\n if (!element) {\n return;\n }\n const targetWindow = instance.targetWindow;\n if (!targetWindow) {\n return;\n }\n const handler = (rect) => {\n const { width, height } = rect;\n cb({ width: Math.round(width), height: Math.round(height) });\n };\n handler(getRect(element));\n if (!targetWindow.ResizeObserver) {\n return () => {\n };\n }\n const observer = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\n const entry = entries[0];\n if (entry == null ? void 0 : entry.borderBoxSize) {\n const box = entry.borderBoxSize[0];\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize });\n return;\n }\n }\n handler(getRect(element));\n };\n instance.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();\n });\n observer.observe(element, { box: \"border-box\" });\n return () => {\n observer.unobserve(element);\n };\n};\nconst addEventListenerOptions = {\n passive: true\n};\nconst observeWindowRect = (instance, cb) => {\n const element = instance.scrollElement;\n if (!element) {\n return;\n }\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight });\n };\n handler();\n element.addEventListener(\"resize\", handler, addEventListenerOptions);\n return () => {\n element.removeEventListener(\"resize\", handler);\n };\n};\nconst supportsScrollend = typeof window == \"undefined\" ? true : \"onscrollend\" in window;\nconst observeElementOffset = (instance, cb) => {\n const element = instance.scrollElement;\n if (!element) {\n return;\n }\n const targetWindow = instance.targetWindow;\n if (!targetWindow) {\n return;\n }\n let offset = 0;\n const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce(\n targetWindow,\n () => {\n cb(offset, false);\n },\n instance.options.isScrollingResetDelay\n );\n const createHandler = (isScrolling) => () => {\n const { horizontal, isRtl } = instance.options;\n offset = horizontal ? element[\"scrollLeft\"] * (isRtl && -1 || 1) : element[\"scrollTop\"];\n fallback();\n cb(offset, isScrolling);\n };\n const handler = createHandler(true);\n const endHandler = createHandler(false);\n element.addEventListener(\"scroll\", handler, addEventListenerOptions);\n const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend;\n if (registerScrollendEvent) {\n element.addEventListener(\"scrollend\", endHandler, addEventListenerOptions);\n }\n return () => {\n element.removeEventListener(\"scroll\", handler);\n if (registerScrollendEvent) {\n element.removeEventListener(\"scrollend\", endHandler);\n }\n };\n};\nconst observeWindowOffset = (instance, cb) => {\n const element = instance.scrollElement;\n if (!element) {\n return;\n }\n const targetWindow = instance.targetWindow;\n if (!targetWindow) {\n return;\n }\n let offset = 0;\n const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce(\n targetWindow,\n () => {\n cb(offset, false);\n },\n instance.options.isScrollingResetDelay\n );\n const createHandler = (isScrolling) => () => {\n offset = element[instance.options.horizontal ? \"scrollX\" : \"scrollY\"];\n fallback();\n cb(offset, isScrolling);\n };\n const handler = createHandler(true);\n const endHandler = createHandler(false);\n element.addEventListener(\"scroll\", handler, addEventListenerOptions);\n const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend;\n if (registerScrollendEvent) {\n element.addEventListener(\"scrollend\", endHandler, addEventListenerOptions);\n }\n return () => {\n element.removeEventListener(\"scroll\", handler);\n if (registerScrollendEvent) {\n element.removeEventListener(\"scrollend\", endHandler);\n }\n };\n};\nconst measureElement = (element, entry, instance) => {\n if (entry == null ? void 0 : entry.borderBoxSize) {\n const box = entry.borderBoxSize[0];\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? \"inlineSize\" : \"blockSize\"]\n );\n return size;\n }\n }\n return element[instance.options.horizontal ? \"offsetWidth\" : \"offsetHeight\"];\n};\nconst windowScroll = (offset, {\n adjustments = 0,\n behavior\n}, instance) => {\n var _a, _b;\n const toOffset = offset + adjustments;\n (_b = (_a = instance.scrollElement) == null ? void 0 : _a.scrollTo) == null ? void 0 : _b.call(_a, {\n [instance.options.horizontal ? \"left\" : \"top\"]: toOffset,\n behavior\n });\n};\nconst elementScroll = (offset, {\n adjustments = 0,\n behavior\n}, instance) => {\n var _a, _b;\n const toOffset = offset + adjustments;\n (_b = (_a = instance.scrollElement) == null ? void 0 : _a.scrollTo) == null ? void 0 : _b.call(_a, {\n [instance.options.horizontal ? \"left\" : \"top\"]: toOffset,\n behavior\n });\n};\nclass Virtualizer {\n constructor(opts) {\n this.unsubs = [];\n this.scrollElement = null;\n this.targetWindow = null;\n this.isScrolling = false;\n this.currentScrollToIndex = null;\n this.measurementsCache = [];\n this.itemSizeCache = /* @__PURE__ */ new Map();\n this.laneAssignments = /* @__PURE__ */ new Map();\n this.pendingMeasuredCacheIndexes = [];\n this.prevLanes = void 0;\n this.lanesChangedFlag = false;\n this.lanesSettling = false;\n this.scrollRect = null;\n this.scrollOffset = null;\n this.scrollDirection = null;\n this.scrollAdjustments = 0;\n this.elementsCache = /* @__PURE__ */ new Map();\n this.observer = /* @__PURE__ */ (() => {\n let _ro = null;\n const get = () => {\n if (_ro) {\n return _ro;\n }\n if (!this.targetWindow || !this.targetWindow.ResizeObserver) {\n return null;\n }\n return _ro = new this.targetWindow.ResizeObserver((entries) => {\n entries.forEach((entry) => {\n const run = () => {\n this._measureElement(entry.target, entry);\n };\n this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();\n });\n });\n };\n return {\n disconnect: () => {\n var _a;\n (_a = get()) == null ? void 0 : _a.disconnect();\n _ro = null;\n },\n observe: (target) => {\n var _a;\n return (_a = get()) == null ? void 0 : _a.observe(target, { box: \"border-box\" });\n },\n unobserve: (target) => {\n var _a;\n return (_a = get()) == null ? void 0 : _a.unobserve(target);\n }\n };\n })();\n this.range = null;\n this.setOptions = (opts2) => {\n Object.entries(opts2).forEach(([key, value]) => {\n if (typeof value === \"undefined\") delete opts2[key];\n });\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {\n },\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n gap: 0,\n indexAttribute: \"data-index\",\n initialMeasurementsCache: [],\n lanes: 1,\n isScrollingResetDelay: 150,\n enabled: true,\n isRtl: false,\n useScrollendEvent: false,\n useAnimationFrameWithResizeObserver: false,\n ...opts2\n };\n };\n this.notify = (sync) => {\n var _a, _b;\n (_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, sync);\n };\n this.maybeNotify = memo(\n () => {\n this.calculateRange();\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null\n ];\n },\n (isScrolling) => {\n this.notify(isScrolling);\n },\n {\n key: process.env.NODE_ENV !== \"production\" && \"maybeNotify\",\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null\n ]\n }\n );\n this.cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d());\n this.unsubs = [];\n this.observer.disconnect();\n this.scrollElement = null;\n this.targetWindow = null;\n };\n this._didMount = () => {\n return () => {\n this.cleanup();\n };\n };\n this._willUpdate = () => {\n var _a;\n const scrollElement = this.options.enabled ? this.options.getScrollElement() : null;\n if (this.scrollElement !== scrollElement) {\n this.cleanup();\n if (!scrollElement) {\n this.maybeNotify();\n return;\n }\n this.scrollElement = scrollElement;\n if (this.scrollElement && \"ownerDocument\" in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView;\n } else {\n this.targetWindow = ((_a = this.scrollElement) == null ? void 0 : _a.window) ?? null;\n }\n this.elementsCache.forEach((cached) => {\n this.observer.observe(cached);\n });\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect;\n this.maybeNotify();\n })\n );\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset, isScrolling) => {\n this.scrollAdjustments = 0;\n this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? \"forward\" : \"backward\" : null;\n this.scrollOffset = offset;\n this.isScrolling = isScrolling;\n this.maybeNotify();\n })\n );\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: void 0,\n behavior: void 0\n });\n }\n };\n this.getSize = () => {\n if (!this.options.enabled) {\n this.scrollRect = null;\n return 0;\n }\n this.scrollRect = this.scrollRect ?? this.options.initialRect;\n return this.scrollRect[this.options.horizontal ? \"width\" : \"height\"];\n };\n this.getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null;\n return 0;\n }\n this.scrollOffset = this.scrollOffset ?? (typeof this.options.initialOffset === \"function\" ? this.options.initialOffset() : this.options.initialOffset);\n return this.scrollOffset;\n };\n this.getFurthestMeasurement = (measurements, index) => {\n const furthestMeasurementsFound = /* @__PURE__ */ new Map();\n const furthestMeasurements = /* @__PURE__ */ new Map();\n for (let m = index - 1; m >= 0; m--) {\n const measurement = measurements[m];\n if (furthestMeasurementsFound.has(measurement.lane)) {\n continue;\n }\n const previousFurthestMeasurement = furthestMeasurements.get(\n measurement.lane\n );\n if (previousFurthestMeasurement == null || measurement.end > previousFurthestMeasurement.end) {\n furthestMeasurements.set(measurement.lane, measurement);\n } else if (measurement.end < previousFurthestMeasurement.end) {\n furthestMeasurementsFound.set(measurement.lane, true);\n }\n if (furthestMeasurementsFound.size === this.options.lanes) {\n break;\n }\n }\n return furthestMeasurements.size === this.options.lanes ? Array.from(furthestMeasurements.values()).sort((a, b) => {\n if (a.end === b.end) {\n return a.index - b.index;\n }\n return a.end - b.end;\n })[0] : void 0;\n };\n this.getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n this.options.lanes\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {\n const lanesChanged = this.prevLanes !== void 0 && this.prevLanes !== lanes;\n if (lanesChanged) {\n this.lanesChangedFlag = true;\n }\n this.prevLanes = lanes;\n this.pendingMeasuredCacheIndexes = [];\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes\n };\n },\n {\n key: false\n }\n );\n this.getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\n ({ count, paddingStart, scrollMargin, getItemKey, enabled, lanes }, itemSizeCache) => {\n if (!enabled) {\n this.measurementsCache = [];\n this.itemSizeCache.clear();\n this.laneAssignments.clear();\n return [];\n }\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index);\n }\n }\n }\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false;\n this.lanesSettling = true;\n this.measurementsCache = [];\n this.itemSizeCache.clear();\n this.laneAssignments.clear();\n this.pendingMeasuredCacheIndexes = [];\n }\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache;\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size);\n });\n }\n const min = this.lanesSettling ? 0 : this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;\n this.pendingMeasuredCacheIndexes = [];\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false;\n }\n const measurements = this.measurementsCache.slice(0, min);\n const laneLastIndex = new Array(lanes).fill(\n void 0\n );\n for (let m = 0; m < min; m++) {\n const item = measurements[m];\n if (item) {\n laneLastIndex[item.lane] = m;\n }\n }\n for (let i = min; i < count; i++) {\n const key = getItemKey(i);\n const cachedLane = this.laneAssignments.get(i);\n let lane;\n let start;\n if (cachedLane !== void 0 && this.options.lanes > 1) {\n lane = cachedLane;\n const prevIndex = laneLastIndex[lane];\n const prevInLane = prevIndex !== void 0 ? measurements[prevIndex] : void 0;\n start = prevInLane ? prevInLane.end + this.options.gap : paddingStart + scrollMargin;\n } else {\n const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i);\n start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin;\n lane = furthestMeasurement ? furthestMeasurement.lane : i % this.options.lanes;\n if (this.options.lanes > 1) {\n this.laneAssignments.set(i, lane);\n }\n }\n const measuredSize = itemSizeCache.get(key);\n const size = typeof measuredSize === \"number\" ? measuredSize : this.options.estimateSize(i);\n const end = start + size;\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane\n };\n laneLastIndex[lane] = i;\n }\n this.measurementsCache = measurements;\n return measurements;\n },\n {\n key: process.env.NODE_ENV !== \"production\" && \"getMeasurements\",\n debug: () => this.options.debug\n }\n );\n this.calculateRange = memo(\n () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n lanes\n }) : null;\n },\n {\n key: process.env.NODE_ENV !== \"production\" && \"calculateRange\",\n debug: () => this.options.debug\n }\n );\n this.getVirtualIndexes = memo(\n () => {\n let startIndex = null;\n let endIndex = null;\n const range = this.calculateRange();\n if (range) {\n startIndex = range.startIndex;\n endIndex = range.endIndex;\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex]);\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex\n ];\n },\n (rangeExtractor, overscan, count, startIndex, endIndex) => {\n return startIndex === null || endIndex === null ? [] : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count\n });\n },\n {\n key: process.env.NODE_ENV !== \"production\" && \"getVirtualIndexes\",\n debug: () => this.options.debug\n }\n );\n this.indexFromElement = (node) => {\n const attributeName = this.options.indexAttribute;\n const indexStr = node.getAttribute(attributeName);\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`\n );\n return -1;\n }\n return parseInt(indexStr, 10);\n };\n this._measureElement = (node, entry) => {\n const index = this.indexFromElement(node);\n const item = this.measurementsCache[index];\n if (!item) {\n return;\n }\n const key = item.key;\n const prevNode = this.elementsCache.get(key);\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode);\n }\n this.observer.observe(node);\n this.elementsCache.set(key, node);\n }\n if (node.isConnected) {\n this.resizeItem(index, this.options.measureElement(node, entry, this));\n }\n };\n this.resizeItem = (index, size) => {\n const item = this.measurementsCache[index];\n if (!item) {\n return;\n }\n const itemSize = this.itemSizeCache.get(item.key) ?? item.size;\n const delta = size - itemSize;\n if (delta !== 0) {\n if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments) {\n if (process.env.NODE_ENV !== \"production\" && this.options.debug) {\n console.info(\"correction\", delta);\n }\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: this.scrollAdjustments += delta,\n behavior: void 0\n });\n }\n this.pendingMeasuredCacheIndexes.push(item.index);\n this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size));\n this.notify(false);\n }\n };\n this.measureElement = (node) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached);\n this.elementsCache.delete(key);\n }\n });\n return;\n }\n this._measureElement(node, void 0);\n };\n this.getVirtualItems = memo(\n () => [this.getVirtualIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems = [];\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k];\n const measurement = measurements[i];\n virtualItems.push(measurement);\n }\n return virtualItems;\n },\n {\n key: process.env.NODE_ENV !== \"production\" && \"getVirtualItems\",\n debug: () => this.options.debug\n }\n );\n this.getVirtualItemForOffset = (offset) => {\n const measurements = this.getMeasurements();\n if (measurements.length === 0) {\n return void 0;\n }\n return notUndefined(\n measurements[findNearestBinarySearch(\n 0,\n measurements.length - 1,\n (index) => notUndefined(measurements[index]).start,\n offset\n )]\n );\n };\n this.getMaxScrollOffset = () => {\n if (!this.scrollElement) return 0;\n if (\"scrollHeight\" in this.scrollElement) {\n return this.options.horizontal ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth : this.scrollElement.scrollHeight - this.scrollElement.clientHeight;\n } else {\n const doc = this.scrollElement.document.documentElement;\n return this.options.horizontal ? doc.scrollWidth - this.scrollElement.innerWidth : doc.scrollHeight - this.scrollElement.innerHeight;\n }\n };\n this.getOffsetForAlignment = (toOffset, align, itemSize = 0) => {\n if (!this.scrollElement) return 0;\n const size = this.getSize();\n const scrollOffset = this.getScrollOffset();\n if (align === \"auto\") {\n align = toOffset >= scrollOffset + size ? \"end\" : \"start\";\n }\n if (align === \"center\") {\n toOffset += (itemSize - size) / 2;\n } else if (align === \"end\") {\n toOffset -= size;\n }\n const maxOffset = this.getMaxScrollOffset();\n return Math.max(Math.min(maxOffset, toOffset), 0);\n };\n this.getOffsetForIndex = (index, align = \"auto\") => {\n index = Math.max(0, Math.min(index, this.options.count - 1));\n const item = this.measurementsCache[index];\n if (!item) {\n return void 0;\n }\n const size = this.getSize();\n const scrollOffset = this.getScrollOffset();\n if (align === \"auto\") {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = \"end\";\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = \"start\";\n } else {\n return [scrollOffset, align];\n }\n }\n if (align === \"end\" && index === this.options.count - 1) {\n return [this.getMaxScrollOffset(), align];\n }\n const toOffset = align === \"end\" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align\n ];\n };\n this.isDynamicMode = () => this.elementsCache.size > 0;\n this.scrollToOffset = (toOffset, { align = \"start\", behavior } = {}) => {\n if (behavior === \"smooth\" && this.isDynamicMode()) {\n console.warn(\n \"The `smooth` scroll behavior is not fully supported with dynamic size.\"\n );\n }\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {\n adjustments: void 0,\n behavior\n });\n };\n this.scrollToIndex = (index, { align: initialAlign = \"auto\", behavior } = {}) => {\n if (behavior === \"smooth\" && this.isDynamicMode()) {\n console.warn(\n \"The `smooth` scroll behavior is not fully supported with dynamic size.\"\n );\n }\n index = Math.max(0, Math.min(index, this.options.count - 1));\n this.currentScrollToIndex = index;\n let attempts = 0;\n const maxAttempts = 10;\n const tryScroll = (currentAlign) => {\n if (!this.targetWindow) return;\n const offsetInfo = this.getOffsetForIndex(index, currentAlign);\n if (!offsetInfo) {\n console.warn(\"Failed to get offset for index:\", index);\n return;\n }\n const [offset, align] = offsetInfo;\n this._scrollToOffset(offset, { adjustments: void 0, behavior });\n this.targetWindow.requestAnimationFrame(() => {\n const verify = () => {\n if (this.currentScrollToIndex !== index) return;\n const currentOffset = this.getScrollOffset();\n const afterInfo = this.getOffsetForIndex(index, align);\n if (!afterInfo) {\n console.warn(\"Failed to get offset for index:\", index);\n return;\n }\n if (!approxEqual(afterInfo[0], currentOffset)) {\n scheduleRetry(align);\n }\n };\n if (this.isDynamicMode()) {\n this.targetWindow.requestAnimationFrame(verify);\n } else {\n verify();\n }\n });\n };\n const scheduleRetry = (align) => {\n if (!this.targetWindow) return;\n if (this.currentScrollToIndex !== index) return;\n attempts++;\n if (attempts < maxAttempts) {\n if (process.env.NODE_ENV !== \"production\" && this.options.debug) {\n console.info(\"Schedule retry\", attempts, maxAttempts);\n }\n this.targetWindow.requestAnimationFrame(() => tryScroll(align));\n } else {\n console.warn(\n `Failed to scroll to index ${index} after ${maxAttempts} attempts.`\n );\n }\n };\n tryScroll(initialAlign);\n };\n this.scrollBy = (delta, { behavior } = {}) => {\n if (behavior === \"smooth\" && this.isDynamicMode()) {\n console.warn(\n \"The `smooth` scroll behavior is not fully supported with dynamic size.\"\n );\n }\n this._scrollToOffset(this.getScrollOffset() + delta, {\n adjustments: void 0,\n behavior\n });\n };\n this.getTotalSize = () => {\n var _a;\n const measurements = this.getMeasurements();\n let end;\n if (measurements.length === 0) {\n end = this.options.paddingStart;\n } else if (this.options.lanes === 1) {\n end = ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0;\n } else {\n const endByLane = Array(this.options.lanes).fill(null);\n let endIndex = measurements.length - 1;\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex];\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end;\n }\n endIndex--;\n }\n end = Math.max(...endByLane.filter((val) => val !== null));\n }\n return Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0\n );\n };\n this._scrollToOffset = (offset, {\n adjustments,\n behavior\n }) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this);\n };\n this.measure = () => {\n this.itemSizeCache = /* @__PURE__ */ new Map();\n this.laneAssignments = /* @__PURE__ */ new Map();\n this.notify(false);\n };\n this.setOptions(opts);\n }\n}\nconst findNearestBinarySearch = (low, high, getCurrentValue, value) => {\n while (low <= high) {\n const middle = (low + high) / 2 | 0;\n const currentValue = getCurrentValue(middle);\n if (currentValue < value) {\n low = middle + 1;\n } else if (currentValue > value) {\n high = middle - 1;\n } else {\n return middle;\n }\n }\n if (low > 0) {\n return low - 1;\n } else {\n return 0;\n }\n};\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n lanes\n}) {\n const lastIndex = measurements.length - 1;\n const getOffset = (index) => measurements[index].start;\n if (measurements.length <= lanes) {\n return {\n startIndex: 0,\n endIndex: lastIndex\n };\n }\n let startIndex = findNearestBinarySearch(\n 0,\n lastIndex,\n getOffset,\n scrollOffset\n );\n let endIndex = startIndex;\n if (lanes === 1) {\n while (endIndex < lastIndex && measurements[endIndex].end < scrollOffset + outerSize) {\n endIndex++;\n }\n } else if (lanes > 1) {\n const endPerLane = Array(lanes).fill(0);\n while (endIndex < lastIndex && endPerLane.some((pos) => pos < scrollOffset + outerSize)) {\n const item = measurements[endIndex];\n endPerLane[item.lane] = item.end;\n endIndex++;\n }\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize);\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex];\n startPerLane[item.lane] = item.start;\n startIndex--;\n }\n startIndex = Math.max(0, startIndex - startIndex % lanes);\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - endIndex % lanes));\n }\n return { startIndex, endIndex };\n}\nexport {\n Virtualizer,\n approxEqual,\n debounce,\n defaultKeyExtractor,\n defaultRangeExtractor,\n elementScroll,\n measureElement,\n memo,\n notUndefined,\n observeElementOffset,\n observeElementRect,\n observeWindowOffset,\n observeWindowRect,\n windowScroll\n};\n//# sourceMappingURL=index.js.map\n","import * as React from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { Virtualizer, elementScroll, observeElementOffset, observeElementRect, windowScroll, observeWindowOffset, observeWindowRect } from \"@tanstack/virtual-core\";\nexport * from \"@tanstack/virtual-core\";\nconst useIsomorphicLayoutEffect = typeof document !== \"undefined\" ? React.useLayoutEffect : React.useEffect;\nfunction useVirtualizerBase({\n useFlushSync = true,\n ...options\n}) {\n const rerender = React.useReducer(() => ({}), {})[1];\n const resolvedOptions = {\n ...options,\n onChange: (instance2, sync) => {\n var _a;\n if (useFlushSync && sync) {\n flushSync(rerender);\n } else {\n rerender();\n }\n (_a = options.onChange) == null ? void 0 : _a.call(options, instance2, sync);\n }\n };\n const [instance] = React.useState(\n () => new Virtualizer(resolvedOptions)\n );\n instance.setOptions(resolvedOptions);\n useIsomorphicLayoutEffect(() => {\n return instance._didMount();\n }, []);\n useIsomorphicLayoutEffect(() => {\n return instance._willUpdate();\n });\n return instance;\n}\nfunction useVirtualizer(options) {\n return useVirtualizerBase({\n observeElementRect,\n observeElementOffset,\n scrollToFn: elementScroll,\n ...options\n });\n}\nfunction useWindowVirtualizer(options) {\n return useVirtualizerBase({\n getScrollElement: () => typeof document !== \"undefined\" ? window : null,\n observeElementRect: observeWindowRect,\n observeElementOffset: observeWindowOffset,\n scrollToFn: windowScroll,\n initialOffset: () => typeof document !== \"undefined\" ? window.scrollY : 0,\n ...options\n });\n}\nexport {\n useVirtualizer,\n useWindowVirtualizer\n};\n//# sourceMappingURL=index.js.map\n","'use client'\r\n\r\nimport { useMemo, lazy, Suspense, memo } from 'react'\r\nimport { useTranslations } from '@/chat-widget/i18n'\r\nimport ReactMarkdown from 'react-markdown'\r\nimport remarkGfm from 'remark-gfm'\r\nimport rehypeSanitize from 'rehype-sanitize'\r\nimport { CheckCheck, MapPin, ExternalLink, ArrowRight, FileIcon, Download } from './Icons'\r\nimport { cn } from '@/lib/utils'\r\nimport { getPrimaryColor } from '../utils/theme'\r\nimport type {\r\n ChatMessage,\r\n BubbleStyles,\r\n TextMessage,\r\n AudioMessage,\r\n ImageMessage,\r\n LocationMessage,\r\n FileMessage,\r\n} from '../types'\r\nimport type { EmotionAvatarMap } from './Launcher'\r\n\r\n// Lazy load componentes pesados\r\nconst AudioPlayer = lazy(() => import('./AudioPlayer').then(m => ({ default: m.AudioPlayer })))\r\nconst Gallery = lazy(() => import('./Gallery').then(m => ({ default: m.Gallery })))\r\n\r\nexport interface MessageBubbleProps {\r\n message: ChatMessage\r\n primaryColor?: string\r\n botAvatar?: string\r\n botName?: string\r\n styles?: BubbleStyles\r\n avatars?: EmotionAvatarMap\r\n isFirst?: boolean\r\n isLast?: boolean\r\n}\r\n\r\nexport const MessageBubble = memo(\r\n function MessageBubble({\r\n message,\r\n primaryColor,\r\n botAvatar,\r\n botName = 'Mar',\r\n avatars,\r\n isFirst = true,\r\n isLast = true,\r\n }: MessageBubbleProps) {\r\n const { t } = useTranslations('extracted')\r\n const isUser = message.sender === 'user'\r\n const isSystem = message.type === 'system' || message.sender === 'system'\r\n const isBot = !isUser && !isSystem\r\n\r\n const brandColor = getPrimaryColor({ primaryColor })\r\n\r\n // --- AVATAR LOGIC ---\r\n const currentAvatar = useMemo(() => {\r\n if (isUser) return null\r\n if (message.type === 'text') {\r\n const textMsg = message as TextMessage\r\n if (textMsg.emotion && avatars?.[textMsg.emotion as keyof EmotionAvatarMap]) {\r\n return avatars[textMsg.emotion as keyof EmotionAvatarMap]\r\n }\r\n }\r\n return botAvatar\r\n }, [message, avatars, botAvatar, isUser])\r\n\r\n const formatTime = (date: Date | string) => {\r\n const dateObj = new Date(date)\r\n return isNaN(dateObj.getTime())\r\n ? ''\r\n : dateObj.toLocaleTimeString([], {\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: false,\r\n })\r\n }\r\n\r\n // --- RENDERERS FOR MARKDOWN ---\r\n const RenderLink = ({ href, children }: any) => {\r\n if (!href) return null\r\n const textContent = String(children).toLowerCase()\r\n const isCTA =\r\n textContent.includes('reservar') ||\r\n textContent.includes('ver') ||\r\n textContent.includes('pagar')\r\n const isGoogleMaps = href.includes('maps.google') || href.includes('goo.gl')\r\n\r\n if (isGoogleMaps) {\r\n return (\r\n <a\r\n href={href}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"block my-2 no-underline group\"\r\n >\r\n <span\r\n className=\"flex items-center gap-3 p-3 border rounded-xl shadow-sm group-hover:border-primary/30 transition-all\"\r\n style={{ backgroundColor: 'hsl(var(--card))', borderColor: 'hsl(var(--border))' }}\r\n >\r\n <span\r\n className=\"flex-shrink-0 p-2 rounded-full\"\r\n style={{ backgroundColor: `${brandColor}1a`, color: brandColor }}\r\n >\r\n <MapPin size={16} strokeWidth={2.5} />\r\n </span>\r\n <span className=\"flex flex-col min-w-0 flex-1 text-[11px] font-bold text-foreground leading-tight uppercase tracking-tight\">\r\n {t('ver_ubicacion')}\r\n </span>\r\n <ExternalLink\r\n size={12}\r\n className=\"text-muted-foreground/40 group-hover:text-primary\"\r\n />\r\n </span>\r\n </a>\r\n )\r\n }\r\n\r\n if (isCTA) {\r\n return (\r\n <a\r\n href={href}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center justify-center gap-2 px-5 py-2.5 mt-2 text-[11px] font-black w-full sm:w-auto rounded-xl shadow-md uppercase tracking-widest transition-transform active:scale-95 text-white\"\r\n style={{ backgroundColor: brandColor }}\r\n >\r\n {children} <ArrowRight size={14} />\r\n </a>\r\n )\r\n }\r\n\r\n return (\r\n <a\r\n href={href}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"font-bold underline decoration-primary/30 hover:decoration-primary transition-all\"\r\n style={{ color: isUser ? 'inherit' : brandColor }}\r\n >\r\n {children}\r\n </a>\r\n )\r\n }\r\n\r\n const RenderImage = ({ src, alt }: any) => {\r\n if (!src) return null\r\n return (\r\n <Suspense\r\n fallback={\r\n <div className=\"my-3 animate-pulse\">\r\n <div className=\"w-full h-48 bg-muted rounded-xl\" />\r\n </div>\r\n }\r\n >\r\n <Gallery images={[{ src, alt }]} radius=\"rounded-xl\" />\r\n </Suspense>\r\n )\r\n }\r\n\r\n // --- CONTENT SWITCHER ---\r\n const renderContent = () => {\r\n switch (message.type) {\r\n case 'audio':\r\n return (\r\n <Suspense\r\n fallback={\r\n <div className=\"flex items-center gap-3 py-1 min-w-[200px] animate-pulse\">\r\n <div className=\"w-8 h-8 rounded-full bg-muted\" />\r\n <div className=\"flex-1 space-y-1\">\r\n <div className=\"h-1 w-full bg-muted rounded-full\" />\r\n </div>\r\n </div>\r\n }\r\n >\r\n <AudioPlayer\r\n url={(message as AudioMessage).content}\r\n isBot={isBot}\r\n primaryColor={primaryColor}\r\n />\r\n </Suspense>\r\n )\r\n\r\n case 'image': {\r\n const imgMsg = message as ImageMessage\r\n return (\r\n <Suspense\r\n fallback={\r\n <div className=\"my-3 animate-pulse\">\r\n <div className=\"w-full h-48 bg-muted rounded-xl\" />\r\n </div>\r\n }\r\n >\r\n <Gallery\r\n images={[\r\n {\r\n src: imgMsg.imageUrl || (imgMsg as any).content,\r\n alt: imgMsg.altText || 'Imagen',\r\n },\r\n ]}\r\n radius=\"rounded-xl\"\r\n />\r\n </Suspense>\r\n )\r\n }\r\n\r\n case 'location': {\r\n const locMsg = message as LocationMessage\r\n return (\r\n <RenderLink\r\n href={`https://www.google.com/maps/search/?api=1&query=${locMsg.latitude},${locMsg.longitude}`}\r\n >\r\n Ver ubicación\r\n </RenderLink>\r\n )\r\n }\r\n\r\n case 'file': {\r\n const fileMsg = message as FileMessage\r\n const fileExtension = fileMsg.fileName?.split('.').pop()?.toLowerCase() || ''\r\n const fileSize = fileMsg.fileSize\r\n ? `${(fileMsg.fileSize / 1024 / 1024).toFixed(2)} MB`\r\n : ''\r\n\r\n return (\r\n <a\r\n href={fileMsg.fileUrl}\r\n download={fileMsg.fileName}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"flex items-center gap-3 p-3 border rounded-xl transition-all hover:scale-[1.02] group\"\r\n style={{\r\n backgroundColor: isUser ? 'rgba(255,255,255,0.1)' : 'hsl(var(--muted))',\r\n borderColor: isUser ? 'rgba(255,255,255,0.2)' : 'hsl(var(--border))',\r\n }}\r\n >\r\n <div\r\n className=\"flex items-center justify-center w-10 h-10 rounded-lg shrink-0\"\r\n style={{\r\n backgroundColor: isUser ? 'rgba(255,255,255,0.2)' : `${brandColor}1a`,\r\n color: isUser ? 'white' : brandColor,\r\n }}\r\n >\r\n <FileIcon size={20} strokeWidth={2.5} />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-bold truncate\">{fileMsg.fileName}</p>\r\n {fileSize && (\r\n <p className=\"text-xs opacity-60 mt-0.5\">\r\n {fileExtension?.toUpperCase()} • {fileSize}\r\n </p>\r\n )}\r\n </div>\r\n <Download\r\n size={18}\r\n className=\"shrink-0 opacity-60 group-hover:opacity-100 transition-opacity\"\r\n />\r\n </a>\r\n )\r\n }\r\n\r\n default:\r\n return (\r\n <div\r\n className={cn(\r\n 'prose prose-sm max-w-none break-words leading-relaxed dark:prose-invert',\r\n isUser ? 'text-primary-foreground prose-p:text-white' : 'text-foreground'\r\n )}\r\n >\r\n <ReactMarkdown\r\n remarkPlugins={[remarkGfm]}\r\n rehypePlugins={[\r\n [\r\n rehypeSanitize,\r\n {\r\n tagNames: ['p', 'a', 'img', 'strong', 'em', 'ul', 'ol', 'li', 'br', 'span'],\r\n attributes: {\r\n a: ['href', 'target', 'rel'],\r\n img: ['src', 'alt'],\r\n span: ['className'],\r\n },\r\n protocols: {\r\n a: { href: ['http', 'https', 'mailto', 'tel'] },\r\n img: { src: ['http', 'https', 'data'] },\r\n },\r\n },\r\n ],\r\n ]}\r\n components={{\r\n a: RenderLink,\r\n img: RenderImage,\r\n p: ({ children }) => <p className=\"mb-0 last:mb-0\">{children}</p>,\r\n }}\r\n >\r\n {(message as TextMessage).content || ''}\r\n </ReactMarkdown>\r\n </div>\r\n )\r\n }\r\n }\r\n\r\n if (isSystem) {\r\n return (\r\n <div className=\"flex justify-center my-4 animate-in fade-in zoom-in-95 w-full\">\r\n <span\r\n className=\"px-3 py-1 border rounded-full text-[9px] font-black uppercase tracking-widest\"\r\n style={{\r\n backgroundColor: 'hsl(var(--muted))',\r\n borderColor: 'hsl(var(--border))',\r\n color: 'hsl(var(--muted-foreground))',\r\n }}\r\n >\r\n {(message as TextMessage).content}\r\n </span>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className={cn(\r\n 'flex w-full mb-0.5 group animate-in fade-in slide-in-from-bottom-2 duration-200',\r\n isUser ? 'justify-end' : 'justify-start gap-3',\r\n isFirst && 'mt-3',\r\n isLast && 'mb-3'\r\n )}\r\n >\r\n {/* AVATAR BOT */}\r\n {!isUser && (\r\n <div className=\"w-9 shrink-0 flex flex-col justify-end pb-1\">\r\n {isLast ? (\r\n <div\r\n className=\"h-9 w-9 rounded-full overflow-hidden border shadow-sm\"\r\n style={{\r\n borderColor: 'hsl(var(--border))',\r\n backgroundColor: 'hsl(var(--background))',\r\n }}\r\n >\r\n {currentAvatar ? (\r\n <img src={currentAvatar} alt={botName} className=\"h-full w-full object-cover\" />\r\n ) : (\r\n <div\r\n className=\"h-full w-full flex items-center justify-center text-white text-[10px] font-black uppercase\"\r\n style={{ backgroundColor: brandColor }}\r\n >\r\n {botName.charAt(0)}\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-9\" />\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* BURBUJA */}\r\n <div\r\n className={cn(\r\n 'max-w-[85%] shadow-sm transition-all duration-300 relative',\r\n isUser ? 'text-primary-foreground' : 'border',\r\n // Bordes inteligentes\r\n isUser\r\n ? cn(\r\n 'rounded-[18px]',\r\n isFirst && 'rounded-tr-[4px]',\r\n !isLast && 'rounded-br-[4px]',\r\n !isFirst && !isLast && 'rounded-r-[4px]'\r\n )\r\n : cn(\r\n 'rounded-[18px]',\r\n isFirst && 'rounded-tl-[4px]',\r\n !isLast && 'rounded-bl-[4px]',\r\n !isFirst && !isLast && 'rounded-l-[4px]'\r\n )\r\n )}\r\n style={\r\n isUser\r\n ? {\r\n padding: 'var(--spacing-4) var(--spacing-5)',\r\n backgroundColor: brandColor,\r\n boxShadow: isLast ? `0 8px 20px -6px ${brandColor}33` : 'none',\r\n }\r\n : {\r\n padding: 'var(--spacing-4) var(--spacing-5)',\r\n backgroundColor: 'hsl(var(--card))',\r\n borderColor: 'hsl(var(--border) / 0.6)',\r\n color: 'hsl(var(--foreground))',\r\n }\r\n }\r\n >\r\n {renderContent()}\r\n\r\n {/* FOOTER */}\r\n {isLast && (\r\n <div\r\n className={cn(\r\n 'flex items-center gap-1 mt-1.5 opacity-50 select-none text-[9px]',\r\n isUser ? 'justify-end' : 'justify-start'\r\n )}\r\n >\r\n <span className=\"font-bold tabular-nums uppercase tracking-tighter\">\r\n {formatTime(message.timestamp)}\r\n </span>\r\n {isUser && <CheckCheck className=\"h-2.5 w-2.5\" />}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n },\r\n (prevProps, nextProps) => {\r\n // Custom comparator: solo re-render si cambió algo relevante\r\n if (prevProps.message.id !== nextProps.message.id) return false\r\n if (prevProps.message.timestamp !== nextProps.message.timestamp) return false\r\n if (prevProps.primaryColor !== nextProps.primaryColor) return false\r\n if (prevProps.botAvatar !== nextProps.botAvatar) return false\r\n if (prevProps.botName !== nextProps.botName) return false\r\n if (prevProps.isFirst !== nextProps.isFirst) return false\r\n if (prevProps.isLast !== nextProps.isLast) return false\r\n\r\n // Comparar styles profundamente si existe\r\n if (JSON.stringify(prevProps.styles) !== JSON.stringify(nextProps.styles)) return false\r\n\r\n return true // No re-renderizar\r\n }\r\n)\r\n","'use client'\r\n\r\nimport { memo } from 'react'\r\nimport { cn } from '@/lib/utils'\r\n\r\nexport const TypingIndicator = memo(function TypingIndicator() {\r\n return (\r\n <div\r\n className={cn(\r\n 'flex items-center self-start animate-in fade-in duration-200',\r\n 'max-w-[85%] sm:max-w-[75%]'\r\n )}\r\n >\r\n <div\r\n className=\"border rounded-[18px] rounded-tl-[4px] px-4 py-3 shadow-soft-sm\"\r\n style={{\r\n backgroundColor: 'hsl(var(--card))',\r\n borderColor: 'hsl(var(--border))',\r\n }}\r\n >\r\n <div className=\"flex items-center gap-1.5\">\r\n {[0, 1, 2].map(i => (\r\n <span\r\n key={i}\r\n className=\"h-1.5 w-1.5 rounded-full animate-bounce\"\r\n style={{\r\n backgroundColor: 'hsl(var(--primary) / 0.4)',\r\n animationDelay: `${i * 150}ms`,\r\n animationDuration: '800ms',\r\n }}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n})\r\n","/**\r\n * Utilidades de formateo de fechas usando Intl nativo\r\n * Reemplaza date-fns para reducir el bundle\r\n */\r\n\r\n/**\r\n * Formatea una fecha en formato corto (día de mes, HH:mm)\r\n */\r\nexport function formatShort(date: Date): string {\r\n return new Intl.DateTimeFormat('es-ES', {\r\n day: 'numeric',\r\n month: 'long',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n }).format(date)\r\n}\r\n\r\n/**\r\n * Verifica si una fecha es hoy\r\n */\r\nexport function isToday(date: Date): boolean {\r\n const today = new Date()\r\n return (\r\n date.getDate() === today.getDate() &&\r\n date.getMonth() === today.getMonth() &&\r\n date.getFullYear() === today.getFullYear()\r\n )\r\n}\r\n\r\n/**\r\n * Verifica si una fecha fue ayer\r\n */\r\nexport function isYesterday(date: Date): boolean {\r\n const yesterday = new Date()\r\n yesterday.setDate(yesterday.getDate() - 1)\r\n return (\r\n date.getDate() === yesterday.getDate() &&\r\n date.getMonth() === yesterday.getMonth() &&\r\n date.getFullYear() === yesterday.getFullYear()\r\n )\r\n}\r\n\r\n/**\r\n * Calcula la diferencia en minutos entre dos fechas\r\n */\r\nexport function differenceInMinutes(laterDate: Date, earlierDate: Date): number {\r\n const diffMs = laterDate.getTime() - earlierDate.getTime()\r\n return Math.floor(diffMs / 1000 / 60)\r\n}\r\n\r\n/**\r\n * Formatea la hora en formato HH:mm\r\n */\r\nexport function formatTime(date: Date): string {\r\n return new Intl.DateTimeFormat('es-ES', {\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n }).format(date)\r\n}\r\n\r\n/**\r\n * Formatea fecha completa con día, mes y hora\r\n */\r\nexport function formatFull(date: Date): string {\r\n return new Intl.DateTimeFormat('es-ES', {\r\n day: 'numeric',\r\n month: 'long',\r\n year: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n }).format(date)\r\n}\r\n\r\n/**\r\n * Formatea fecha relativa (Hoy, Ayer, o fecha)\r\n */\r\nexport function formatRelative(date: Date): string {\r\n if (isToday(date)) {\r\n return `Hoy, ${formatTime(date)}`\r\n }\r\n if (isYesterday(date)) {\r\n return `Ayer, ${formatTime(date)}`\r\n }\r\n return formatShort(date)\r\n}\r\n","'use client'\r\n\r\nimport React, { useRef, useEffect, useState, memo } from 'react'\r\nimport { useVirtualizer } from '@tanstack/react-virtual'\r\nimport type { BubbleStyles, ChatMessage } from '../types'\r\nimport { MessageBubble } from './MessageBubble'\r\nimport { TypingIndicator } from './TypingIndicator'\r\nimport { getPrimaryColor } from '../utils/theme'\r\nimport type { EmotionAvatarMap } from './Launcher'\r\nimport { formatRelative, differenceInMinutes } from '../utils/dateUtils'\r\n\r\n// Umbral para activar virtualización (mejora rendimiento con >100 mensajes)\r\nconst VIRTUALIZATION_THRESHOLD = 100\r\n\r\nexport interface MessageListProps {\r\n messages: ChatMessage[]\r\n isTyping: boolean\r\n welcomeMessage?: string\r\n primaryColor?: string\r\n logoUrl?: string\r\n botName?: string\r\n bubbleStyles?: BubbleStyles\r\n avatars?: EmotionAvatarMap\r\n}\r\n\r\nexport const MessageList = memo(\r\n function MessageList({\r\n messages,\r\n isTyping,\r\n welcomeMessage = '¡Hola! ¿En qué puedo ayudarte?',\r\n primaryColor,\r\n logoUrl,\r\n botName = 'Mar',\r\n bubbleStyles,\r\n avatars,\r\n }: MessageListProps) {\r\n const messagesEndRef = useRef<HTMLDivElement>(null)\r\n const containerRef = useRef<HTMLDivElement>(null)\r\n const [isReady, setIsReady] = useState(false)\r\n const [logoError, setLogoError] = useState(false)\r\n const bgColor = getPrimaryColor({ primaryColor })\r\n\r\n // Virtualización activada solo si hay muchos mensajes\r\n const shouldVirtualize = messages.length > VIRTUALIZATION_THRESHOLD\r\n\r\n // Configuración del virtualizador\r\n const virtualizer = useVirtualizer({\r\n count: messages.length,\r\n getScrollElement: () => containerRef.current,\r\n estimateSize: () => 80, // Altura estimada por mensaje\r\n overscan: 5, // Pre-renderizar 5 items extra\r\n enabled: shouldVirtualize,\r\n })\r\n\r\n // Hidratación segura para Next.js\r\n useEffect(() => {\r\n setIsReady(true)\r\n }, [])\r\n\r\n /**\r\n * 📜 LÓGICA DE SCROLL INTELIGENTE\r\n * Se dispara cuando cambian los mensajes o el bot está escribiendo.\r\n */\r\n useEffect(() => {\r\n if (isReady && (messages.length > 0 || isTyping)) {\r\n const timer = setTimeout(() => {\r\n if (shouldVirtualize) {\r\n // Con virtualización: scroll al último índice\r\n virtualizer.scrollToIndex(messages.length - 1, {\r\n align: 'end',\r\n behavior: messages.length <= 1 ? 'auto' : 'smooth',\r\n })\r\n } else {\r\n // Sin virtualización: scroll tradicional\r\n messagesEndRef.current?.scrollIntoView({\r\n behavior: messages.length <= 1 ? 'auto' : 'smooth',\r\n block: 'end',\r\n })\r\n }\r\n }, 100)\r\n return () => clearTimeout(timer)\r\n }\r\n }, [messages.length, isTyping, isReady, shouldVirtualize, virtualizer])\r\n\r\n /**\r\n * 📅 FORMATEO DE SEPARADORES DE FECHA\r\n */\r\n const getSeparatorLabel = (date: any) => {\r\n const d = new Date(date)\r\n if (isNaN(d.getTime())) return ''\r\n return formatRelative(d)\r\n }\r\n\r\n if (!isReady) return <div className=\"flex-1 bg-background\" />\r\n\r\n // Renderizado con virtualización para listas grandes\r\n if (shouldVirtualize) {\r\n return (\r\n <div\r\n ref={containerRef}\r\n className=\"flex-1 overflow-y-auto scroll-smooth bg-background/50 scrollbar-none\"\r\n style={{ padding: 'var(--spacing-5)' }}\r\n >\r\n <div\r\n style={{\r\n height: `${virtualizer.getTotalSize()}px`,\r\n width: '100%',\r\n position: 'relative',\r\n }}\r\n >\r\n {virtualizer.getVirtualItems().map(virtualRow => {\r\n const message = messages[virtualRow.index]\r\n const index = virtualRow.index\r\n const prev = messages[index - 1]\r\n const next = messages[index + 1]\r\n\r\n const showDateSeparator =\r\n prev &&\r\n differenceInMinutes(new Date(message.timestamp), new Date(prev.timestamp)) > 15\r\n\r\n const isSameAsPrev =\r\n prev &&\r\n prev.sender === message.sender &&\r\n differenceInMinutes(new Date(message.timestamp), new Date(prev.timestamp)) < 5 &&\r\n !showDateSeparator\r\n\r\n const isSameAsNext =\r\n next &&\r\n next.sender === message.sender &&\r\n differenceInMinutes(new Date(next.timestamp), new Date(message.timestamp)) < 5\r\n\r\n return (\r\n <div\r\n key={virtualRow.key}\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n transform: `translateY(${virtualRow.start}px)`,\r\n }}\r\n >\r\n {showDateSeparator && (\r\n <div className=\"flex justify-center my-8 animate-in fade-in zoom-in-95\">\r\n <span className=\"px-4 py-1.5 bg-muted/40 backdrop-blur-md rounded-full text-[10px] font-black text-muted-foreground uppercase tracking-[0.2em] border border-border/50 shadow-sm\">\r\n {getSeparatorLabel(message.timestamp)}\r\n </span>\r\n </div>\r\n )}\r\n\r\n <MessageBubble\r\n message={message}\r\n primaryColor={primaryColor}\r\n botAvatar={logoUrl}\r\n botName={botName}\r\n styles={bubbleStyles}\r\n avatars={avatars}\r\n isFirst={!isSameAsPrev}\r\n isLast={!isSameAsNext}\r\n />\r\n </div>\r\n )\r\n })}\r\n </div>\r\n {isTyping && (\r\n <div className=\"flex items-end gap-3 mt-4 mb-2 animate-in fade-in slide-in-from-left-4 duration-500\">\r\n <div className=\"w-8 h-8 rounded-xl bg-muted/60 border border-border/50 flex items-center justify-center shrink-0 shadow-soft-sm\">\r\n <div className=\"flex gap-[2px]\">\r\n <span className=\"w-1 h-1 bg-primary/50 rounded-full animate-bounce [animation-delay:-0.3s]\" />\r\n <span className=\"w-1 h-1 bg-primary/50 rounded-full animate-bounce [animation-delay:-0.15s]\" />\r\n <span className=\"w-1 h-1 bg-primary/50 rounded-full animate-bounce\" />\r\n </div>\r\n </div>\r\n <TypingIndicator />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n // Renderizado tradicional para listas pequeñas\r\n return (\r\n <div\r\n ref={containerRef}\r\n className=\"flex-1 overflow-y-auto scroll-smooth p-4 bg-background/50 scrollbar-none\"\r\n >\r\n <div className=\"min-h-full flex flex-col justify-end\">\r\n {/* === ESTADO VACÍO / BIENVENIDA PREMIUM === */}\r\n {messages.length === 0 && (\r\n <div className=\"flex-1 flex flex-col items-center justify-center py-16 text-center animate-in fade-in zoom-in-95 duration-1000\">\r\n <div className=\"relative h-24 w-24 mb-6\">\r\n <div className=\"absolute inset-0 bg-primary/20 rounded-full animate-pulse blur-2xl\" />\r\n <div className=\"relative h-full w-full rounded-[28px] border-2 border-primary/20 overflow-hidden bg-card shadow-soft-2xl transition-transform hover:scale-105 duration-500\">\r\n {logoError ? (\r\n <div\r\n className=\"h-full w-full flex items-center justify-center text-3xl\"\r\n style={{ backgroundColor: bgColor }}\r\n >\r\n 👋\r\n </div>\r\n ) : logoUrl ? (\r\n <img\r\n src={logoUrl}\r\n className=\"object-cover h-full w-full\"\r\n alt={botName}\r\n onError={() => setLogoError(true)}\r\n />\r\n ) : (\r\n <div\r\n className=\"h-full w-full flex items-center justify-center text-3xl\"\r\n style={{ backgroundColor: bgColor }}\r\n >\r\n 👋\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"space-y-2\">\r\n <h3 className=\"font-black text-xl text-foreground uppercase tracking-tighter italic\">\r\n {botName}\r\n </h3>\r\n <p className=\"text-[12px] font-bold text-muted-foreground italic px-10 leading-relaxed opacity-60\">\r\n \"{welcomeMessage}\"\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* === LISTADO DE MENSAJES CON ESTRATEGIA DE ACUMULACIÓN === */}\r\n <div className=\"flex flex-col\" style={{ gap: 'var(--spacing-3)' }}>\r\n {messages.map((message, index) => {\r\n const prev = messages[index - 1]\r\n const next = messages[index + 1]\r\n\r\n // 1. Mostrar separador si pasaron más de 15 min desde el anterior\r\n const showDateSeparator =\r\n prev &&\r\n differenceInMinutes(new Date(message.timestamp), new Date(prev.timestamp)) > 15\r\n\r\n // 2. Lógica para pegar mensajes (Mismo autor + ventana < 5 min)\r\n const isSameAsPrev =\r\n prev &&\r\n prev.sender === message.sender &&\r\n differenceInMinutes(new Date(message.timestamp), new Date(prev.timestamp)) < 5 &&\r\n !showDateSeparator\r\n\r\n const isSameAsNext =\r\n next &&\r\n next.sender === message.sender &&\r\n differenceInMinutes(new Date(next.timestamp), new Date(message.timestamp)) < 5\r\n\r\n return (\r\n <React.Fragment key={message.id || `msg-${index}`}>\r\n {showDateSeparator && (\r\n <div className=\"flex justify-center my-8 animate-in fade-in zoom-in-95\">\r\n <span className=\"px-4 py-1.5 bg-muted/40 backdrop-blur-md rounded-full text-[10px] font-black text-muted-foreground uppercase tracking-[0.2em] border border-border/50 shadow-sm\">\r\n {getSeparatorLabel(message.timestamp)}\r\n </span>\r\n </div>\r\n )}\r\n\r\n <MessageBubble\r\n message={message}\r\n primaryColor={primaryColor}\r\n botAvatar={logoUrl}\r\n botName={botName}\r\n styles={bubbleStyles}\r\n avatars={avatars}\r\n // Props de acumulación para MessageBubble\r\n isFirst={!isSameAsPrev}\r\n isLast={!isSameAsNext}\r\n />\r\n </React.Fragment>\r\n )\r\n })}\r\n </div>\r\n\r\n {/* Espaciador final para evitar que el input tape el último mensaje */}\r\n <div ref={messagesEndRef} className=\"h-6 shrink-0\" />\r\n {/* INDICADOR DE ESCRITURA (AVATAR + ONDAS) */}\r\n </div>\r\n {isTyping && (\r\n <div className=\"flex items-end gap-3 mt-4 mb-2 animate-in fade-in slide-in-from-left-4 duration-500\">\r\n <div className=\"w-8 h-8 rounded-xl bg-muted/60 border border-border/50 flex items-center justify-center shrink-0 shadow-soft-sm\">\r\n <div className=\"flex gap-[2px]\">\r\n <span className=\"w-1 h-1 bg-primary/50 rounded-full animate-bounce [animation-delay:-0.3s]\" />\r\n <span className=\"w-1 h-1 bg-primary/50 rounded-full animate-bounce [animation-delay:-0.15s]\" />\r\n <span className=\"w-1 h-1 bg-primary/50 rounded-full animate-bounce\" />\r\n </div>\r\n </div>\r\n <TypingIndicator />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n },\r\n (prevProps, nextProps) => {\r\n // Custom comparator: reducir re-renders innecesarios\r\n if (prevProps.messages.length !== nextProps.messages.length) return false\r\n if (prevProps.isTyping !== nextProps.isTyping) return false\r\n if (prevProps.primaryColor !== nextProps.primaryColor) return false\r\n if (prevProps.botName !== nextProps.botName) return false\r\n if (prevProps.logoUrl !== nextProps.logoUrl) return false\r\n\r\n // Comparar último mensaje por ID para detectar cambios\r\n const prevLast = prevProps.messages[prevProps.messages.length - 1]\r\n const nextLast = nextProps.messages[nextProps.messages.length - 1]\r\n if (prevLast?.id !== nextLast?.id) return false\r\n\r\n return true // No re-renderizar\r\n }\r\n)\r\n","/**\r\n * @package @botuyo/chat-widget\r\n * File validation utilities with magic bytes verification\r\n *\r\n * Validates file types by checking magic bytes (file signatures)\r\n * to prevent MIME type spoofing and detect corrupted files.\r\n */\r\n\r\n/**\r\n * Magic bytes (file signatures) for common file types\r\n * First few bytes that identify the file format\r\n */\r\nconst MAGIC_BYTES = {\r\n 'image/jpeg': [0xff, 0xd8, 0xff],\r\n 'image/png': [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],\r\n 'image/webp': [0x52, 0x49, 0x46, 0x46], // RIFF\r\n 'image/gif': [0x47, 0x49, 0x46, 0x38], // GIF8\r\n 'audio/mpeg': [0xff, 0xfb], // MP3\r\n 'audio/wav': [0x52, 0x49, 0x46, 0x46], // RIFF\r\n 'audio/webm': [0x1a, 0x45, 0xdf, 0xa3],\r\n 'audio/ogg': [0x4f, 0x67, 0x67, 0x53], // OggS\r\n} as const\r\n\r\n/**\r\n * Validates a file by checking its magic bytes against expected signature\r\n *\r\n * @param file - File to validate\r\n * @returns Promise<boolean> - true if file matches expected type, false otherwise\r\n *\r\n * @example\r\n * const isValid = await validateFileType(file)\r\n * if (!isValid) {\r\n * alert('El archivo está corrupto o no es del tipo indicado')\r\n * }\r\n */\r\nexport async function validateFileType(file: File): Promise<boolean> {\r\n try {\r\n // Get magic bytes for expected MIME type\r\n const expectedBytes = MAGIC_BYTES[file.type as keyof typeof MAGIC_BYTES]\r\n\r\n if (!expectedBytes) {\r\n // Type not in our validation list, allow it\r\n return true\r\n }\r\n\r\n // Read first 12 bytes of the file\r\n const buffer = await file.slice(0, 12).arrayBuffer()\r\n const bytes = new Uint8Array(buffer)\r\n\r\n // Compare with expected magic bytes\r\n return expectedBytes.every((byte, index) => bytes[index] === byte)\r\n } catch (error) {\r\n // If validation fails, reject the file for security\r\n console.error('File validation error:', error)\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * Validates file size against maximum allowed\r\n *\r\n * @param file - File to validate\r\n * @param maxSizeMB - Maximum size in megabytes (default: 10MB)\r\n * @returns boolean - true if file is within size limit\r\n *\r\n * @example\r\n * if (!validateFileSize(file, 5)) {\r\n * alert('El archivo es demasiado grande. Máximo 5MB')\r\n * }\r\n */\r\nexport function validateFileSize(file: File, maxSizeMB: number = 10): boolean {\r\n const maxSizeBytes = maxSizeMB * 1024 * 1024\r\n return file.size <= maxSizeBytes\r\n}\r\n\r\n/**\r\n * Validates file extension matches allowed list\r\n *\r\n * @param file - File to validate\r\n * @param allowedExtensions - Array of allowed extensions (e.g., ['jpg', 'png'])\r\n * @returns boolean - true if extension is allowed\r\n *\r\n * @example\r\n * if (!validateFileExtension(file, ['jpg', 'png', 'webp'])) {\r\n * alert('Solo se permiten imágenes JPG, PNG o WebP')\r\n * }\r\n */\r\nexport function validateFileExtension(file: File, allowedExtensions: string[]): boolean {\r\n const extension = file.name.split('.').pop()?.toLowerCase()\r\n if (!extension) return false\r\n\r\n return allowedExtensions.includes(extension)\r\n}\r\n\r\n/**\r\n * Comprehensive file validation combining all checks\r\n *\r\n * @param file - File to validate\r\n * @param options - Validation options\r\n * @returns Promise<ValidationResult> - Validation result with details\r\n *\r\n * @example\r\n * const result = await validateFile(file, {\r\n * maxSizeMB: 5,\r\n * allowedExtensions: ['jpg', 'png'],\r\n * checkMagicBytes: true\r\n * })\r\n *\r\n * if (!result.valid) {\r\n * alert(result.error)\r\n * }\r\n */\r\nexport interface FileValidationOptions {\r\n maxSizeMB?: number\r\n allowedExtensions?: string[]\r\n checkMagicBytes?: boolean\r\n}\r\n\r\nexport interface ValidationResult {\r\n valid: boolean\r\n error?: string\r\n}\r\n\r\nexport async function validateFile(\r\n file: File,\r\n options: FileValidationOptions = {}\r\n): Promise<ValidationResult> {\r\n const { maxSizeMB = 10, allowedExtensions, checkMagicBytes = true } = options\r\n\r\n // Check file size\r\n if (!validateFileSize(file, maxSizeMB)) {\r\n return {\r\n valid: false,\r\n error: `El archivo es demasiado grande. Máximo ${maxSizeMB}MB`,\r\n }\r\n }\r\n\r\n // Check file extension\r\n if (allowedExtensions && !validateFileExtension(file, allowedExtensions)) {\r\n return {\r\n valid: false,\r\n error: `Extensión no permitida. Solo: ${allowedExtensions.join(', ')}`,\r\n }\r\n }\r\n\r\n // Check magic bytes\r\n if (checkMagicBytes) {\r\n const isValid = await validateFileType(file)\r\n if (!isValid) {\r\n return {\r\n valid: false,\r\n error: 'El archivo está corrupto o no es del tipo indicado',\r\n }\r\n }\r\n }\r\n\r\n return { valid: true }\r\n}\r\n","'use client'\r\n\r\nimport { useState, useRef, useMemo } from 'react'\r\nimport { useTranslations } from '@/chat-widget/i18n'\r\nimport type { MediaConfig } from '../types'\r\nimport { Send, ImageIcon, Loader2, Plus, MapPin, Mic, X, Trash2, FileIcon } from './Icons'\r\nimport { cn } from '@/lib/utils'\r\nimport { getPrimaryColor } from '../utils/theme'\r\nimport { logger } from '../utils/logger'\r\nimport { validateFile } from '../utils/fileValidation'\r\n\r\n// --- CONFIGURACIÓN ---\r\nconst MAX_CHARS = 1000\r\nconst DEFAULT_MEDIA_CONFIG: MediaConfig = {\r\n enableImages: true,\r\n enableAudio: true,\r\n enableFiles: true,\r\n enableLocation: true,\r\n allowedFileTypes: ['jpg', 'jpeg', 'png', 'webp', 'gif', 'pdf', 'doc', 'docx', 'txt', 'zip'],\r\n maxFileSizeMB: 10,\r\n}\r\n\r\n// --- INTERFACES ---\r\nexport interface Attachment {\r\n type: 'image' | 'audio' | 'file'\r\n file: File\r\n previewUrl?: string\r\n}\r\n\r\nexport interface InputAreaProps {\r\n isConnected: boolean\r\n placeholder?: string\r\n primaryColor?: string\r\n mediaConfig?: MediaConfig\r\n onSendMessage: (message: string) => void\r\n onSendAttachment?: (file: File, type: 'image' | 'audio' | 'file') => void\r\n onSendLocation?: (location: { latitude: number; longitude: number }) => void\r\n}\r\n\r\nexport function InputArea({\r\n isConnected,\r\n placeholder = 'Escribe un mensaje...',\r\n primaryColor,\r\n mediaConfig,\r\n onSendMessage,\r\n onSendAttachment,\r\n onSendLocation,\r\n}: InputAreaProps) {\r\n const { t } = useTranslations()\r\n const [inputValue, setInputValue] = useState('')\r\n const [isMenuOpen, setIsMenuOpen] = useState(false)\r\n const [isRecording, setIsRecording] = useState(false)\r\n const [recordingTime, setRecordingTime] = useState(0)\r\n const [attachment, setAttachment] = useState<Attachment | null>(null)\r\n const [isCompressing, setIsCompressing] = useState(false)\r\n const [isLoadingLocation, setIsLoadingLocation] = useState(false)\r\n\r\n const textareaRef = useRef<HTMLTextAreaElement>(null)\r\n const fileInputRef = useRef<HTMLInputElement>(null)\r\n const imageInputRef = useRef<HTMLInputElement>(null)\r\n const mediaRecorderRef = useRef<MediaRecorder | null>(null)\r\n const audioChunksRef = useRef<Blob[]>([])\r\n const timerRef = useRef<NodeJS.Timeout | null>(null)\r\n\r\n const brandColor = getPrimaryColor({ primaryColor })\r\n\r\n // Fusionar configuración de medios con valores por defecto\r\n const config = useMemo(() => ({ ...DEFAULT_MEDIA_CONFIG, ...mediaConfig }), [mediaConfig])\r\n\r\n // Verificar si hay alguna funcionalidad multimedia habilitada\r\n const hasMediaFeatures = useMemo(\r\n () => config.enableImages || config.enableAudio || config.enableFiles || config.enableLocation,\r\n [config]\r\n )\r\n\r\n // 🔥 LÓGICA DE ENVÍO CORREGIDA\r\n const handleSend = () => {\r\n const trimmedValue = inputValue.trim()\r\n\r\n if (attachment) {\r\n onSendAttachment?.(attachment.file, attachment.type)\r\n setAttachment(null)\r\n setInputValue('')\r\n } else if (trimmedValue && isConnected) {\r\n onSendMessage(trimmedValue)\r\n setInputValue('')\r\n }\r\n\r\n // Resetear altura del textarea\r\n if (textareaRef.current) {\r\n textareaRef.current.style.height = '40px'\r\n }\r\n }\r\n\r\n // 🔥 CAPTURA DE ENTER Y CTRL+ENTER (Accesibilidad mejorada)\r\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n // Enter sin modificadores: enviar mensaje\r\n if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.metaKey) {\r\n e.preventDefault()\r\n handleSend()\r\n }\r\n // Ctrl+Enter o Cmd+Enter: enviar mensaje (alternativa)\r\n else if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\r\n e.preventDefault()\r\n handleSend()\r\n }\r\n // Shift+Enter: nueva línea (comportamiento por defecto, no hacer nada)\r\n }\r\n\r\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n const val = e.target.value.slice(0, MAX_CHARS)\r\n setInputValue(val)\r\n\r\n // Auto-resize\r\n if (textareaRef.current) {\r\n textareaRef.current.style.height = '40px'\r\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`\r\n }\r\n }\r\n\r\n const handleFileSelect = async (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0]\r\n if (!file) return\r\n setIsMenuOpen(false)\r\n\r\n // Validar archivo con magic bytes\r\n const validationResult = await validateFile(file, {\r\n maxSizeMB: config.maxFileSizeMB || 10,\r\n allowedExtensions: config.allowedFileTypes || [\r\n 'jpg',\r\n 'jpeg',\r\n 'png',\r\n 'webp',\r\n 'gif',\r\n 'pdf',\r\n 'doc',\r\n 'docx',\r\n 'txt',\r\n 'zip',\r\n ],\r\n checkMagicBytes: true,\r\n })\r\n\r\n if (!validationResult.valid) {\r\n alert(validationResult.error || 'Archivo no válido')\r\n return\r\n }\r\n\r\n // Si es imagen y la compresión está habilitada, comprimir\r\n if (file.type.startsWith('image/') && config.enableImages) {\r\n setIsCompressing(true)\r\n try {\r\n // Lazy load browser-image-compression\r\n const { default: imageCompression } = await import('browser-image-compression')\r\n\r\n const options = {\r\n maxSizeMB: 0.8,\r\n maxWidthOrHeight: 1200,\r\n useWebWorker: true,\r\n }\r\n const compressedFile = await imageCompression(file, options)\r\n setAttachment({\r\n type: 'image',\r\n file: compressedFile,\r\n previewUrl: URL.createObjectURL(compressedFile),\r\n })\r\n } catch (error) {\r\n logger.error('Image compression failed:', error)\r\n // Fallback: usar imagen original sin comprimir\r\n setAttachment({\r\n type: 'image',\r\n file,\r\n previewUrl: URL.createObjectURL(file),\r\n })\r\n } finally {\r\n setIsCompressing(false)\r\n }\r\n } else {\r\n // Archivo general (PDF, DOC, etc.)\r\n setAttachment({\r\n type: 'file',\r\n file,\r\n previewUrl: '',\r\n })\r\n }\r\n }\r\n\r\n const startRecording = async () => {\r\n if (!isConnected) return\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true })\r\n const mediaRecorder = new MediaRecorder(stream)\r\n mediaRecorderRef.current = mediaRecorder\r\n audioChunksRef.current = []\r\n mediaRecorder.ondataavailable = e => audioChunksRef.current.push(e.data)\r\n mediaRecorder.onstop = () => {\r\n const audioFile = new File([new Blob(audioChunksRef.current)], 'voice.webm', {\r\n type: 'audio/webm',\r\n })\r\n onSendAttachment?.(audioFile, 'audio')\r\n }\r\n mediaRecorder.start()\r\n setIsRecording(true)\r\n timerRef.current = setInterval(() => setRecordingTime(v => v + 1), 1000)\r\n } catch {\r\n alert('Micrófono denegado o no disponible')\r\n }\r\n }\r\n\r\n const stopRecording = async (send: boolean) => {\r\n if (mediaRecorderRef.current) {\r\n if (!send) mediaRecorderRef.current.onstop = null\r\n mediaRecorderRef.current.stop()\r\n mediaRecorderRef.current.stream.getTracks().forEach(t => t.stop())\r\n }\r\n if (timerRef.current) clearInterval(timerRef.current)\r\n setIsRecording(false)\r\n setRecordingTime(0)\r\n\r\n // Validar archivo de audio antes de enviar\r\n if (send && audioChunksRef.current.length > 0) {\r\n const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/webm' })\r\n const audioFile = new File([audioBlob], `audio-${Date.now()}.webm`, {\r\n type: 'audio/webm',\r\n })\r\n\r\n // Validar archivo de audio (ahora async)\r\n const validation = await validateFile(audioFile, { maxSizeMB: 10 })\r\n if (!validation.valid) {\r\n logger.error('Audio validation failed:', validation.error)\r\n alert(validation.error)\r\n audioChunksRef.current = []\r\n return\r\n }\r\n\r\n // Si es válido, enviar\r\n onSendAttachment?.(audioFile, 'audio')\r\n audioChunksRef.current = []\r\n }\r\n }\r\n\r\n return (\r\n <div className=\"relative\">\r\n {/* PREVIEW DE ADJUNTO */}\r\n {(attachment || isCompressing) && (\r\n <div\r\n className=\"absolute bottom-full left-0 mb-2 p-2 rounded-2xl border shadow-soft-2xl animate-in slide-in-from-bottom-2 z-50\"\r\n style={{\r\n backgroundColor: 'hsl(var(--card))',\r\n borderColor: 'hsl(var(--border))',\r\n }}\r\n >\r\n <div className=\"relative w-16 h-16\">\r\n {isCompressing ? (\r\n <div className=\"w-full h-full flex flex-col items-center justify-center bg-muted rounded-xl\">\r\n <Loader2 className=\"animate-spin text-primary h-5 w-5\" />\r\n </div>\r\n ) : attachment?.type === 'image' ? (\r\n <>\r\n <img\r\n src={attachment?.previewUrl}\r\n className=\"w-full h-full object-cover rounded-xl border\"\r\n alt={t('preview')}\r\n />\r\n <button\r\n onClick={() => setAttachment(null)}\r\n className=\"absolute -top-1.5 -right-1.5 bg-destructive text-white rounded-full p-1 shadow-md hover:scale-105\"\r\n >\r\n <X size={10} strokeWidth={3} />\r\n </button>\r\n </>\r\n ) : (\r\n <>\r\n <div className=\"w-full h-full flex flex-col items-center justify-center bg-muted rounded-xl border\">\r\n <FileIcon className=\"text-primary h-6 w-6\" />\r\n <span className=\"text-[8px] mt-1 font-bold truncate max-w-[60px]\">\r\n {attachment?.file.name}\r\n </span>\r\n </div>\r\n <button\r\n onClick={() => setAttachment(null)}\r\n className=\"absolute -top-1.5 -right-1.5 bg-destructive text-white rounded-full p-1 shadow-md hover:scale-105\"\r\n >\r\n <X size={10} strokeWidth={3} />\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Input de imágenes */}\r\n <input\r\n type=\"file\"\r\n accept=\"image/*\"\r\n className=\"hidden\"\r\n ref={imageInputRef}\r\n onChange={handleFileSelect}\r\n />\r\n\r\n {/* Input de archivos generales */}\r\n <input\r\n type=\"file\"\r\n accept={config.allowedFileTypes?.map(ext => `.${ext}`).join(',')}\r\n className=\"hidden\"\r\n ref={fileInputRef}\r\n onChange={handleFileSelect}\r\n />\r\n\r\n <div className=\"flex items-center max-w-full\" style={{ gap: 'var(--spacing-3)' }}>\r\n {/* BOTÓN PLUS / MENÚ */}\r\n {hasMediaFeatures && onSendAttachment && (\r\n <div className=\"relative shrink-0\">\r\n {isMenuOpen && (\r\n <div\r\n className=\"absolute bottom-full left-0 flex flex-col animate-in fade-in slide-in-from-bottom-2 duration-300 z-[60]\"\r\n style={{ marginBottom: 'var(--spacing-2)', gap: 'var(--spacing-2)' }}\r\n >\r\n {/* Opción: Imágenes */}\r\n {config.enableImages && (\r\n <button\r\n onClick={() => imageInputRef.current?.click()}\r\n className=\"flex items-center border shadow-soft-2xl rounded-2xl transition-colors text-[10px] font-black uppercase tracking-widest\"\r\n style={{\r\n gap: 'var(--spacing-3)',\r\n padding: 'var(--spacing-3) var(--spacing-5)',\r\n backgroundColor: 'hsl(var(--card))',\r\n borderColor: 'hsl(var(--border))',\r\n color: 'hsl(var(--card-foreground))',\r\n }}\r\n >\r\n <ImageIcon size={18} className=\"text-blue-500\" /> {t('fotos')}\r\n </button>\r\n )}\r\n\r\n {/* Opción: Archivos */}\r\n {config.enableFiles && (\r\n <button\r\n onClick={() => fileInputRef.current?.click()}\r\n className=\"flex items-center border shadow-soft-2xl rounded-2xl transition-colors text-[10px] font-black uppercase tracking-widest\"\r\n style={{\r\n gap: 'var(--spacing-3)',\r\n padding: 'var(--spacing-3) var(--spacing-5)',\r\n backgroundColor: 'hsl(var(--card))',\r\n borderColor: 'hsl(var(--border))',\r\n color: 'hsl(var(--card-foreground))',\r\n }}\r\n >\r\n <FileIcon size={18} className=\"text-purple-500\" /> Archivos\r\n </button>\r\n )}\r\n\r\n {/* Opción: Ubicación */}\r\n {config.enableLocation && onSendLocation && (\r\n <button\r\n onClick={() => {\r\n setIsLoadingLocation(true)\r\n navigator.geolocation.getCurrentPosition(\r\n pos => {\r\n onSendLocation?.({\r\n latitude: pos.coords.latitude,\r\n longitude: pos.coords.longitude,\r\n })\r\n setIsLoadingLocation(false)\r\n setIsMenuOpen(false)\r\n },\r\n () => setIsLoadingLocation(false)\r\n )\r\n }}\r\n className=\"flex items-center border shadow-soft-2xl rounded-2xl transition-colors text-[10px] font-black uppercase tracking-widest\"\r\n style={{\r\n gap: 'var(--spacing-3)',\r\n padding: 'var(--spacing-3) var(--spacing-5)',\r\n backgroundColor: 'hsl(var(--card))',\r\n borderColor: 'hsl(var(--border))',\r\n color: 'hsl(var(--card-foreground))',\r\n }}\r\n >\r\n {isLoadingLocation ? (\r\n <Loader2 size={18} className=\"animate-spin\" />\r\n ) : (\r\n <MapPin size={18} className=\"text-emerald-500\" />\r\n )}{' '}\r\n {t('ubicacion')}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n <button\r\n onClick={() => setIsMenuOpen(!isMenuOpen)}\r\n className={cn(\r\n 'h-10 w-10 rounded-full flex items-center justify-center transition-all shadow-sm z-10',\r\n isMenuOpen\r\n ? 'bg-muted text-foreground rotate-45'\r\n : 'bg-muted/50 text-muted-foreground hover:bg-muted'\r\n )}\r\n >\r\n <Plus size={22} strokeWidth={2.5} />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* ÁREA DE TEXTO / GRABACIÓN */}\r\n <div\r\n className={cn(\r\n 'flex-1 relative flex items-center min-w-0 rounded-[24px] border px-4 transition-all shadow-inner',\r\n isRecording ? 'h-[44px]' : 'min-h-[40px] max-h-[120px]'\r\n )}\r\n style={{\r\n backgroundColor: isRecording ? 'hsl(var(--destructive) / 0.05)' : 'hsl(var(--muted))',\r\n borderColor: isRecording ? 'hsl(var(--destructive))' : 'hsl(var(--border))',\r\n }}\r\n >\r\n {isRecording ? (\r\n <div\r\n className=\"flex items-center w-full animate-in zoom-in-95\"\r\n style={{ gap: 'var(--spacing-4)' }}\r\n >\r\n <button\r\n onClick={() => stopRecording(false)}\r\n className=\"text-destructive/50 hover:text-destructive\"\r\n >\r\n <Trash2 size={18} />\r\n </button>\r\n <div className=\"flex-1 flex items-center\" style={{ gap: 'var(--spacing-2)' }}>\r\n <div className=\"flex gap-[3px]\">\r\n {[1, 2, 3, 4].map(i => (\r\n <span\r\n key={i}\r\n className=\"w-[3px] h-3 bg-destructive/60 rounded-full animate-pulse\"\r\n style={{ animationDelay: `${i * 0.15}s` }}\r\n />\r\n ))}\r\n </div>\r\n <span className=\"text-destructive font-black text-[11px] tabular-nums\">\r\n {Math.floor(recordingTime / 60)}:\r\n {(recordingTime % 60).toString().padStart(2, '0')}\r\n </span>\r\n </div>\r\n <button\r\n onClick={() => stopRecording(true)}\r\n className=\"w-7 h-7 rounded-full bg-destructive flex items-center justify-center text-white shadow-lg\"\r\n >\r\n <Send size={12} fill=\"currentColor\" />\r\n </button>\r\n </div>\r\n ) : (\r\n <div className=\"w-full relative flex items-center\">\r\n <textarea\r\n ref={textareaRef}\r\n rows={1}\r\n value={inputValue}\r\n onKeyDown={handleKeyDown}\r\n onChange={handleInputChange}\r\n onFocus={() => setIsMenuOpen(false)}\r\n placeholder={placeholder}\r\n aria-label={t('accessibility.typeMessage')}\r\n aria-describedby=\"send-message-hint\"\r\n aria-invalid={inputValue.length > MAX_CHARS}\r\n disabled={!isConnected}\r\n className=\"w-full bg-transparent text-sm py-2.5 outline-none resize-none overflow-hidden leading-tight pr-8 scrollbar-none disabled:opacity-50\"\r\n style={{\r\n scrollbarWidth: 'none',\r\n msOverflowStyle: 'none',\r\n color: 'hsl(var(--foreground))',\r\n }}\r\n />\r\n {/* Hint oculto para lectores de pantalla */}\r\n <span id=\"send-message-hint\" className=\"sr-only\">\r\n {t('accessibility.sendMessageHint')}\r\n </span>\r\n {inputValue.length > MAX_CHARS * 0.8 && (\r\n <span\r\n className={cn(\r\n 'absolute right-0 text-[9px] font-bold tabular-nums',\r\n inputValue.length >= MAX_CHARS ? 'text-destructive' : 'text-muted-foreground/40'\r\n )}\r\n >\r\n {MAX_CHARS - inputValue.length}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* BOTÓN DE ACCIÓN */}\r\n {!isRecording && (\r\n <>\r\n {inputValue.trim() || attachment ? (\r\n <button\r\n onClick={handleSend}\r\n disabled={!isConnected || (isCompressing && !!attachment)}\r\n className=\"h-10 w-10 rounded-full flex items-center justify-center transition-all active:scale-90 shadow-md shadow-primary/20 shrink-0 disabled:opacity-30 disabled:grayscale\"\r\n style={{ backgroundColor: brandColor }}\r\n >\r\n <Send size={18} className=\"text-white ml-0.5 fill-current\" />\r\n </button>\r\n ) : config.enableAudio && onSendAttachment ? (\r\n <button\r\n onClick={startRecording}\r\n disabled={!isConnected}\r\n className=\"h-10 w-10 rounded-full flex items-center justify-center transition-all active:scale-90 shadow-md shadow-primary/20 shrink-0 disabled:opacity-30 disabled:grayscale\"\r\n style={{ backgroundColor: brandColor }}\r\n >\r\n <Mic size={20} strokeWidth={2.5} className=\"text-white\" />\r\n </button>\r\n ) : (\r\n <button\r\n onClick={handleSend}\r\n disabled={!isConnected}\r\n className=\"h-10 w-10 rounded-full flex items-center justify-center transition-all active:scale-90 shadow-md shadow-primary/20 shrink-0 disabled:opacity-30 disabled:grayscale\"\r\n style={{ backgroundColor: brandColor }}\r\n >\r\n <Send size={18} className=\"text-white ml-0.5 fill-current\" />\r\n </button>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n}\r\n","/**\r\n * @package @botuyo/chat-widget\r\n * Performance utilities - throttle, debounce, lazy loading\r\n *\r\n * Principio: Single Responsibility - solo optimizaciones de rendimiento\r\n */\r\n\r\n/**\r\n * Throttle: limita la ejecución a una vez por intervalo\r\n * Útil para eventos frecuentes como scroll, resize, typing\r\n *\r\n * @example\r\n * const handleScroll = throttle(() => console.log('scroll'), 250)\r\n * window.addEventListener('scroll', handleScroll)\r\n */\r\nexport function throttle<T extends (...args: any[]) => any>(\r\n func: T,\r\n delay: number\r\n): (...args: Parameters<T>) => void {\r\n let lastCall = 0\r\n let timeoutId: NodeJS.Timeout | null = null\r\n\r\n return function throttled(...args: Parameters<T>) {\r\n const now = Date.now()\r\n const timeSinceLastCall = now - lastCall\r\n\r\n const execute = () => {\r\n lastCall = now\r\n func(...args)\r\n }\r\n\r\n if (timeSinceLastCall >= delay) {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId)\r\n timeoutId = null\r\n }\r\n execute()\r\n } else if (!timeoutId) {\r\n timeoutId = setTimeout(() => {\r\n execute()\r\n timeoutId = null\r\n }, delay - timeSinceLastCall)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Debounce: retrasa la ejecución hasta que pasen N ms sin nuevas llamadas\r\n * Útil para input search, auto-save, validación\r\n *\r\n * @example\r\n * const handleSearch = debounce((query) => fetchResults(query), 300)\r\n * input.addEventListener('input', (e) => handleSearch(e.target.value))\r\n */\r\nexport function debounce<T extends (...args: any[]) => any>(\r\n func: T,\r\n delay: number\r\n): (...args: Parameters<T>) => void {\r\n let timeoutId: NodeJS.Timeout | null = null\r\n\r\n return function debounced(...args: Parameters<T>) {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId)\r\n }\r\n\r\n timeoutId = setTimeout(() => {\r\n func(...args)\r\n timeoutId = null\r\n }, delay)\r\n }\r\n}\r\n\r\n/**\r\n * Memoización simple para cálculos costosos\r\n *\r\n * @example\r\n * const expensiveCalc = memoize((n: number) => fibonacci(n))\r\n */\r\nexport function memoize<T extends (...args: any[]) => any>(func: T): T {\r\n const cache = new Map<string, ReturnType<T>>()\r\n\r\n return ((...args: Parameters<T>) => {\r\n const key = JSON.stringify(args)\r\n\r\n if (cache.has(key)) {\r\n return cache.get(key)!\r\n }\r\n\r\n const result = func(...args)\r\n cache.set(key, result)\r\n return result\r\n }) as T\r\n}\r\n\r\n/**\r\n * RequestAnimationFrame throttle para animaciones suaves\r\n */\r\nexport function rafThrottle<T extends (...args: any[]) => any>(\r\n func: T\r\n): (...args: Parameters<T>) => void {\r\n let rafId: number | null = null\r\n\r\n return function throttled(...args: Parameters<T>) {\r\n if (rafId !== null) return\r\n\r\n rafId = requestAnimationFrame(() => {\r\n func(...args)\r\n rafId = null\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Batch de operaciones para reducir re-renders\r\n * Acumula llamadas y ejecuta todas juntas\r\n *\r\n * @example\r\n * const batchedUpdate = createBatcher((items) => {\r\n * setState(prev => [...prev, ...items])\r\n * }, 50)\r\n */\r\nexport function createBatcher<T>(\r\n callback: (items: T[]) => void,\r\n delay: number = 50\r\n): (item: T) => void {\r\n let batch: T[] = []\r\n let timeoutId: NodeJS.Timeout | null = null\r\n\r\n return function addToBatch(item: T) {\r\n batch.push(item)\r\n\r\n if (timeoutId) clearTimeout(timeoutId)\r\n\r\n timeoutId = setTimeout(() => {\r\n callback([...batch])\r\n batch = []\r\n timeoutId = null\r\n }, delay)\r\n }\r\n}\r\n\r\n/**\r\n * Intersection Observer para lazy loading\r\n */\r\nexport function createLazyLoader(\r\n callback: (entry: IntersectionObserverEntry) => void,\r\n options?: IntersectionObserverInit\r\n): IntersectionObserver {\r\n return new IntersectionObserver(entries => {\r\n entries.forEach(entry => {\r\n if (entry.isIntersecting) {\r\n callback(entry)\r\n }\r\n })\r\n }, options)\r\n}\r\n","import { useState, useEffect } from 'react'\r\nimport { throttle } from '../utils/performance'\r\n\r\nexport function useIsMobile(breakpoint = 640) {\r\n const [isMobile, setIsMobile] = useState(() => {\r\n // Cálculo inicial solo si estamos en browser\r\n if (typeof window === 'undefined') return false\r\n return window.innerWidth < breakpoint\r\n })\r\n\r\n useEffect(() => {\r\n // Throttle: max 1 check cada 250ms para evitar re-renders excesivos\r\n const checkMobile = throttle(() => {\r\n setIsMobile(window.innerWidth < breakpoint)\r\n }, 250)\r\n\r\n window.addEventListener('resize', checkMobile)\r\n return () => window.removeEventListener('resize', checkMobile)\r\n }, [breakpoint])\r\n\r\n return isMobile\r\n}\r\n","'use client'\r\n\r\nimport { useState, useEffect, useCallback } from 'react'\r\nimport { useIsMobile } from './useIsMobile'\r\n\r\ninterface DynamicHeightOptions {\r\n isOpen: boolean\r\n headerHeight?: number\r\n marginTop?: number\r\n height?: string // Altura personalizada (ej: '600px', '80vh')\r\n bottom?: string // Distancia desde bottom (ej: '24px', '1.5rem')\r\n}\r\n\r\nconst DESKTOP_MAX_HEIGHT = 700\r\nconst DESKTOP_MIN_HEIGHT = 500\r\nconst DESKTOP_MARGIN_TOP = 64 // 4rem\r\nconst DEFAULT_BOTTOM = '24px'\r\n\r\nexport function useDynamicHeight({ isOpen, height, bottom }: DynamicHeightOptions) {\r\n const isMobile = useIsMobile()\r\n const [dynamicHeight, setDynamicHeight] = useState<React.CSSProperties>({})\r\n\r\n const calculateHeight = useCallback(() => {\r\n if (isMobile) {\r\n // En móvil, usamos el visual viewport para ajustarnos al teclado\r\n const updateMobileHeight = () => {\r\n if (window.visualViewport) {\r\n setDynamicHeight({\r\n height: `${window.visualViewport.height}px`,\r\n width: '100%',\r\n top: `${window.visualViewport.offsetTop}px`,\r\n left: '0px',\r\n bottom: 'auto',\r\n right: 'auto',\r\n transform: 'none',\r\n })\r\n } else {\r\n // Fallback para navegadores sin visualViewport\r\n setDynamicHeight({\r\n height: '100dvh',\r\n width: '100%',\r\n top: '0px',\r\n left: '0px',\r\n })\r\n }\r\n }\r\n\r\n updateMobileHeight()\r\n window.visualViewport?.addEventListener('resize', updateMobileHeight)\r\n window.visualViewport?.addEventListener('scroll', updateMobileHeight)\r\n\r\n return () => {\r\n window.visualViewport?.removeEventListener('resize', updateMobileHeight)\r\n window.visualViewport?.removeEventListener('scroll', updateMobileHeight)\r\n }\r\n } else {\r\n // En desktop, usar altura personalizada o calcular dinámicamente\r\n if (height) {\r\n // Si hay altura personalizada, usarla directamente\r\n setDynamicHeight({\r\n height: height,\r\n bottom: bottom || DEFAULT_BOTTOM,\r\n })\r\n } else {\r\n // Calcular altura disponible dinámicamente\r\n const availableHeight = window.innerHeight - DESKTOP_MARGIN_TOP\r\n const calculatedHeight = Math.min(\r\n DESKTOP_MAX_HEIGHT,\r\n Math.max(DESKTOP_MIN_HEIGHT, availableHeight)\r\n )\r\n\r\n setDynamicHeight({\r\n height: `${calculatedHeight}px`,\r\n maxHeight: `${availableHeight}px`,\r\n bottom: bottom || DEFAULT_BOTTOM,\r\n })\r\n }\r\n }\r\n }, [isMobile, height, bottom])\r\n\r\n useEffect(() => {\r\n if (!isOpen) return\r\n\r\n const cleanup = calculateHeight()\r\n\r\n window.addEventListener('resize', calculateHeight)\r\n\r\n return () => {\r\n window.removeEventListener('resize', calculateHeight)\r\n if (cleanup) cleanup()\r\n }\r\n }, [isOpen, calculateHeight])\r\n\r\n return dynamicHeight\r\n}\r\n","'use client'\n\nimport { useEffect, useState } from 'react'\nimport { useTranslations } from '@/chat-widget/i18n'\nimport { X, ShieldCheck, Heart } from './Icons'\nimport { cn } from '@/lib/utils'\nimport type { BubbleStyles, ChatMessage, MediaConfig } from '../types'\nimport { MessageList } from './MessageList'\nimport { InputArea } from './InputArea'\nimport { getPrimaryColor } from '../utils/theme'\nimport { useIsMobile } from '../hooks/useIsMobile'\nimport { useDynamicHeight } from '../hooks/useDynamicHeight'\nimport { useFocusTrap } from '../hooks/useFocusTrap'\nimport { EmotionAvatarMap } from './Launcher'\nimport { DEFAULT_AVATAR_URL } from '../utils/defaultAssets'\n\nexport interface ChatWindowProps {\n isOpen: boolean\n isConnected: boolean\n isTyping: boolean\n messages: ChatMessage[]\n botName?: string\n logoUrl?: string\n welcomeMessage?: string\n inputPlaceholder?: string\n primaryColor?: string\n borderRadius?: string\n mediaConfig?: MediaConfig\n onClose: () => void\n onSendMessage: (message: string) => void\n position?: 'bottom-right' | 'bottom-left'\n bubbleStyles?: BubbleStyles\n avatars?: EmotionAvatarMap\n onSendAttachment?: (file: File, type: 'image' | 'audio' | 'file') => void\n onSendLocation?: (location: { latitude: number; longitude: number }) => void\n theme?: import('../types').ChatTheme\n}\n\nexport function ChatWindow({\n isOpen,\n isConnected,\n isTyping,\n messages,\n botName = 'Mar',\n logoUrl,\n welcomeMessage,\n inputPlaceholder,\n primaryColor,\n mediaConfig,\n onClose,\n onSendMessage,\n bubbleStyles,\n avatars,\n onSendAttachment,\n onSendLocation,\n theme,\n}: ChatWindowProps) {\n const [logoError, setLogoError] = useState(false)\n const { t } = useTranslations()\n const isMobile = useIsMobile()\n const themePrimary = getPrimaryColor({ primaryColor })\n const dynamicHeightStyles = useDynamicHeight({\n isOpen,\n height: theme?.height,\n bottom: theme?.bottom,\n })\n\n // Focus trap para accesibilidad\n const dialogRef = useFocusTrap({\n enabled: isOpen,\n onEscape: onClose,\n })\n\n useEffect(() => {\n if (!isOpen) return\n\n if (isMobile) {\n document.body.style.overflow = 'hidden'\n document.body.style.position = 'fixed'\n document.body.style.width = '100%'\n }\n\n return () => {\n document.body.style.overflow = ''\n document.body.style.position = ''\n document.body.style.width = ''\n }\n }, [isOpen, isMobile])\n\n if (!isOpen) return null\n\n const desktopBottom = theme?.bottom || '24px'\n const isBottomLeft = theme?.position === 'bottom-left'\n\n return (\n <>\n {/* Descripción oculta para lectores de pantalla */}\n <div id=\"chat-window-description\" className=\"sr-only\">\n {t('accessibility.dialogDescription')}\n </div>\n\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"chat-window-title\"\n aria-describedby=\"chat-window-description\"\n tabIndex={-1}\n className={cn(\n 'flex flex-col overflow-hidden transition-all duration-500 ease-[cubic-bezier(0.16,1,0.3,1)]',\n 'text-foreground z-[9999]',\n\n // 💻 DESKTOP: ANCHO Y ALTO CONTROLADO CON MARGEN DEL TECHO\n !isMobile && [\n 'fixed',\n isBottomLeft ? 'left-6' : 'right-6',\n 'w-[350px] min-w-[350px] max-w-[350px]',\n 'rounded-[32px] border shadow-soft-2xl',\n 'animate-in fade-in zoom-in-95',\n isBottomLeft ? 'slide-in-from-bottom-10' : 'slide-in-from-bottom-10',\n ],\n\n // 📱 MOBILE: Full pantalla ajustada al viewport real\n isMobile && ['fixed inset-0 w-full']\n )}\n style={{\n ...dynamicHeightStyles,\n // Aplicar bottom personalizado solo en desktop\n ...(!isMobile && { bottom: desktopBottom }),\n // 🎨 CSS VARIABLES - Los temas se aplican automáticamente\n backgroundColor: 'hsl(var(--background))',\n borderColor: 'hsl(var(--border))',\n color: 'hsl(var(--foreground))',\n }}\n >\n {/* --- HEADER --- */}\n <header\n className=\"relative shrink-0 border-b z-20\"\n style={{\n padding: 'var(--spacing-5)',\n backgroundColor: 'hsl(var(--background) / 0.9)',\n borderColor: 'hsl(var(--border))',\n backdropFilter: 'blur(24px)',\n }}\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"relative\">\n <div className=\"h-10 w-10 rounded-2xl overflow-hidden bg-primary/10 border-2 border-background shadow-soft-sm\">\n {logoError ? (\n <div className=\"h-full w-full flex items-center justify-center bg-muted text-muted-foreground\">\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z\"\n />\n </svg>\n </div>\n ) : (\n <img\n src={logoUrl || DEFAULT_AVATAR_URL}\n alt={botName}\n className=\"h-full w-full object-cover\"\n onError={() => setLogoError(true)}\n />\n )}\n </div>\n <div\n className={cn(\n 'absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded-full border-2 border-background',\n isConnected ? 'bg-emerald-500' : 'bg-amber-500 animate-pulse'\n )}\n />\n </div>\n\n <div className=\"flex flex-col\">\n <div className=\"flex items-center gap-1\">\n <span\n id=\"chat-window-title\"\n className=\"font-black text-xs uppercase tracking-tight text-foreground\"\n >\n {botName}\n </span>\n <ShieldCheck className=\"h-3 w-3 text-primary fill-primary/10\" />\n </div>\n <div id=\"chat-window-description\" className=\"flex items-center gap-1.5 mt-0.5\">\n <span className=\"flex h-1 w-1 rounded-full bg-emerald-500\" />\n <span className=\"text-[9px] font-black text-muted-foreground uppercase tracking-[0.1em]\">\n {isConnected ? t('online') : t('offline')}\n </span>\n </div>\n </div>\n </div>\n\n <button\n onClick={onClose}\n aria-label={t('accessibility.closeChat')}\n title=\"Esc\"\n className=\"h-8 w-8 flex items-center justify-center rounded-full bg-muted/60 hover:bg-muted text-foreground transition-all active:scale-90 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </div>\n </header>\n\n {/* --- CHAT CONTENT --- */}\n <main\n role=\"region\"\n aria-label={t('accessibility.chatMessages')}\n className=\"flex-1 min-h-0 relative flex flex-col\"\n style={{\n padding: 'var(--spacing-5)',\n backgroundColor: 'hsl(var(--muted))',\n }}\n >\n <MessageList\n messages={messages}\n isTyping={isTyping}\n welcomeMessage={welcomeMessage}\n primaryColor={primaryColor}\n logoUrl={logoUrl}\n botName={botName}\n bubbleStyles={bubbleStyles}\n avatars={avatars}\n />\n <div className=\"absolute top-0 left-0 right-0 h-6 bg-gradient-to-b from-background/10 to-transparent pointer-events-none\" />\n </main>\n\n {/* --- FOOTER --- */}\n <footer\n className=\"border-t\"\n style={{\n paddingTop: 'var(--spacing-5)',\n paddingLeft: 'var(--spacing-5)',\n paddingRight: 'var(--spacing-5)',\n paddingBottom: isMobile\n ? 'max(var(--spacing-3), env(safe-area-inset-bottom))'\n : 'var(--spacing-3)',\n backgroundColor: 'hsl(var(--background))',\n borderColor: 'hsl(var(--border))',\n }}\n >\n <InputArea\n isConnected={isConnected}\n placeholder={inputPlaceholder}\n primaryColor={themePrimary}\n mediaConfig={mediaConfig}\n onSendMessage={onSendMessage}\n onSendAttachment={onSendAttachment}\n onSendLocation={onSendLocation}\n />\n\n <div\n className=\"flex items-center justify-center gap-1 opacity-25 select-none\"\n style={{\n marginTop: 'var(--spacing-2)',\n paddingBottom: 'var(--spacing-1)',\n }}\n >\n <Heart className=\"h-2 w-2 text-primary fill-primary\" />\n <span className=\"text-[7px] font-bold uppercase tracking-[0.2em]\">\n {t('con_amor_paseo_libre')}\n </span>\n </div>\n </footer>\n </div>\n </>\n )\n}\n","/**\r\n * @package @botuyo/chat-widget\r\n * Focus management hook for accessible dialogs\r\n *\r\n * Principio: Single Responsibility - solo gestionar el foco del teclado\r\n */\r\n\r\nimport { useEffect, useRef } from 'react'\r\n\r\ninterface UseFocusTrapOptions {\r\n /** Si el trap está activo */\r\n enabled: boolean\r\n /** Elemento al que retornar el foco al desactivar */\r\n returnFocusRef?: React.RefObject<HTMLElement>\r\n /** Callback al cerrar con Escape */\r\n onEscape?: () => void\r\n}\r\n\r\n/**\r\n * Hook para atrapar el foco dentro de un contenedor (dialog, modal)\r\n *\r\n * Características:\r\n * - Previene que Tab salga del contenedor\r\n * - Retorna el foco al elemento anterior al cerrar\r\n * - Cierra con tecla Escape\r\n * - Compatible con lectores de pantalla\r\n *\r\n * @example\r\n * const containerRef = useFocusTrap({\r\n * enabled: isOpen,\r\n * onEscape: handleClose\r\n * })\r\n *\r\n * return <div ref={containerRef}>...</div>\r\n */\r\nexport function useFocusTrap({ enabled, returnFocusRef, onEscape }: UseFocusTrapOptions) {\r\n const containerRef = useRef<HTMLDivElement>(null)\r\n const previousActiveElementRef = useRef<HTMLElement | null>(null)\r\n\r\n useEffect(() => {\r\n if (!enabled) return\r\n\r\n // Guardar elemento activo antes de abrir\r\n previousActiveElementRef.current = document.activeElement as HTMLElement\r\n\r\n // Capturar returnFocusRef.current al inicio para evitar stale closure\r\n const returnTarget = returnFocusRef?.current\r\n\r\n // Enfocar el contenedor al abrir\r\n const container = containerRef.current\r\n if (!container) return\r\n\r\n // Pequeño delay para asegurar que el DOM está listo\r\n const focusTimeout = setTimeout(() => {\r\n // Buscar primer elemento focusable\r\n const focusable = container.querySelectorAll<HTMLElement>(\r\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\r\n )\r\n if (focusable.length > 0) {\r\n focusable[0].focus()\r\n } else {\r\n container.focus()\r\n }\r\n }, 100)\r\n\r\n // Handler para atrapar el foco con Tab\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (!container) return\r\n\r\n // Escape para cerrar\r\n if (e.key === 'Escape') {\r\n onEscape?.()\r\n return\r\n }\r\n\r\n // Tab cycling\r\n if (e.key === 'Tab') {\r\n const focusableElements = container.querySelectorAll<HTMLElement>(\r\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\r\n )\r\n\r\n if (focusableElements.length === 0) return\r\n\r\n const firstElement = focusableElements[0]\r\n const lastElement = focusableElements[focusableElements.length - 1]\r\n\r\n // Shift + Tab en el primero → ir al último\r\n if (e.shiftKey && document.activeElement === firstElement) {\r\n e.preventDefault()\r\n lastElement.focus()\r\n }\r\n // Tab en el último → ir al primero\r\n else if (!e.shiftKey && document.activeElement === lastElement) {\r\n e.preventDefault()\r\n firstElement.focus()\r\n }\r\n }\r\n }\r\n\r\n document.addEventListener('keydown', handleKeyDown)\r\n\r\n return () => {\r\n clearTimeout(focusTimeout)\r\n document.removeEventListener('keydown', handleKeyDown)\r\n\r\n // Retornar foco al elemento capturado al inicio\r\n const targetToFocus = returnTarget || previousActiveElementRef.current\r\n if (targetToFocus && typeof targetToFocus.focus === 'function') {\r\n targetToFocus.focus()\r\n }\r\n }\r\n }, [enabled, onEscape, returnFocusRef])\r\n\r\n return containerRef\r\n}\r\n"],"names":["translations","es","online","offline","connecting","con_amor_paseo_libre","preview","fotos","ubicacion","input_placeholder","send","attach_photo","attach_location","recording","rate_limit_exceeded","connection_error","file_too_large","invalid_file","extracted","assistant","anterior","siguiente","cerrar","cerrar_chat","abrir_chat","ver_ubicacion","accessibility","closeChat","closeChatHint","chatMessages","messageHistory","dialogDescription","sendMessage","sendMessageHint","typeMessage","botMessage","userMessage","messageFrom","messageTime","newMessage","en","pt","fr","detectLanguage","navigator","browserLang","language","split","LanguageContext","createContext","LOCALE_STORAGE_KEY","LanguageProvider","children","defaultLocale","locale","setLocaleState","useState","window","stored","localStorage","getItem","useEffect","handleLanguageChange","addEventListener","removeEventListener","jsx","Provider","value","setLocale","newLocale","includes","setItem","console","warn","useTranslations","namespace","currentLocale","context","useContext","Error","useLanguage","t","useCallback","key","obj","path","reduce","current","mergeClasses","classes","filter","className","index","array","Boolean","trim","indexOf","join","toPascalCase","string","camelCase","replace","match","p1","p2","toUpperCase","toLowerCase","toCamelCase","charAt","slice","defaultAttributes","xmlns","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","hasA11yProp","props","prop","startsWith","Icon","forwardRef","color","size","absoluteStrokeWidth","iconNode","rest","ref","createElement","Number","map","tag","attrs","Array","isArray","createLucideIcon","iconName","Component","displayName","ArrowRight","d","CheckCheck","ChevronLeft","ChevronRight","Download","ExternalLink","File","Heart","Image","x","y","rx","ry","cx","cy","r","LoaderCircle","MapPin","MessageCircle","Mic","Pause","Play","Plus","Send","ShieldCheck","Trash2","X","ZoomIn","x1","x2","y1","y2","e","f","n","o","length","createClassPartObject","nextPart","Map","validators","classGroupId","CLASS_PART_SEPARATOR","EMPTY_CONFLICTS","createClassGroupUtils","config","classMap","createClassMap","conflictingClassGroups","conflictingClassGroupModifiers","getClassGroupId","endsWith","getGroupIdForArbitraryProperty","classParts","startIndex","getGroupRecursive","getConflictingClassGroupIds","hasPostfixModifier","modifierConflicts","baseConflicts","array1","array2","combinedArray","i","concatArrays","classPartObject","currentClassPart","nextClassPartObject","get","result","classRest","validatorsLength","validatorObj","validator","content","colonIndex","property","theme","classGroups","processClassGroups","group","processClassesRecursively","classGroup","len","classDefinition","processClassDefinition","processObjectDefinition","processFunctionDefinition","processStringDefinition","getPart","isThemeGetter","push","createClassValidatorObject","entries","Object","parts","part","next","set","func","createLruCache","maxCacheSize","cacheSize","cache","create","previousCache","update","EMPTY_MODIFIERS","createResultObject","modifiers","hasImportantModifier","baseClassName","maybePostfixModifierPosition","isExternal","createParseClassName","prefix","experimentalParseClassName","parseClassName","postfixModifierPosition","bracketDepth","parenDepth","modifierStart","currentCharacter","baseClassNameWithImportantModifier","fullPrefix","parseClassNameOriginal","createSortModifiers","modifierWeights","orderSensitiveModifiers","forEach","mod","currentSegment","modifier","isArbitrary","isOrderSensitive","has","sort","SPLIT_CLASSES_REGEX","toValue","mix","resolvedValue","k","fallbackThemeArr","fromTheme","themeGetter","arbitraryValueRegex","arbitraryVariableRegex","fractionRegex","tshirtUnitRegex","lengthUnitRegex","colorFunctionRegex","shadowRegex","imageRegex","isFraction","test","isNumber","isNaN","isInteger","isPercent","isTshirtSize","isAny","isLengthOnly","isNever","isShadow","isImage","isAnyNonArbitrary","isArbitraryValue","isArbitraryVariable","isArbitrarySize","getIsArbitraryValue","isLabelSize","isArbitraryLength","isLabelLength","isArbitraryNumber","isLabelNumber","isArbitraryPosition","isLabelPosition","isArbitraryImage","isLabelImage","isArbitraryShadow","isLabelShadow","isArbitraryVariableLength","getIsArbitraryVariable","isArbitraryVariableFamilyName","isLabelFamilyName","isArbitraryVariablePosition","isArbitraryVariableSize","isArbitraryVariableImage","isArbitraryVariableShadow","testLabel","testValue","exec","shouldMatchNoLabel","label","twMerge","createConfigFirst","createConfigRest","configUtils","cacheGet","cacheSet","functionToCall","tailwindMerge","classList","cachedResult","sortModifiers","classGroupsInConflict","classNames","originalClassName","substring","variantModifier","modifierId","classId","conflictGroups","mergeClassList","previousConfig","createConfigCurrent","createConfigUtils","args","classLists","argument","twJoin","themeColor","themeFont","themeText","themeFontWeight","themeTracking","themeLeading","themeBreakpoint","themeContainer","themeSpacing","themeRadius","themeShadow","themeInsetShadow","themeTextShadow","themeDropShadow","themeBlur","themePerspective","themeAspect","themeEase","themeAnimate","scalePositionWithArbitrary","scaleUnambiguousSpacing","scaleInset","scaleGridTemplateColsRows","scaleGridColRowStartAndEnd","span","scaleGridColRowStartOrEnd","scaleGridAutoColsRows","scaleMargin","scaleSizing","scaleColor","scaleBgPosition","position","scaleBgSize","scaleGradientStopPosition","scaleRadius","scaleBorderWidth","scaleMaskImagePosition","scaleBlur","scaleRotate","scaleScale","scaleSkew","scaleTranslate","animate","aspect","blur","breakpoint","container","ease","font","leading","perspective","radius","shadow","spacing","text","tracking","columns","box","display","sr","float","clear","isolation","object","overflow","overscroll","inset","start","end","top","right","bottom","left","visibility","z","basis","flex","grow","shrink","order","col","row","gap","justify","items","baseline","self","p","px","py","ps","pe","pr","pb","pl","m","mx","my","ms","me","mt","mr","mb","ml","w","screen","h","list","placeholder","decoration","indent","align","whitespace","break","wrap","hyphens","bg","repeat","linear","to","radial","conic","from","via","rounded","border","divide","outline","ring","opacity","mask","closest","farthest","brightness","contrast","grayscale","invert","saturate","sepia","table","caption","transition","duration","delay","backface","rotate","scale","skew","transform","origin","translate","accent","appearance","caret","scheme","cursor","resize","scroll","snap","touch","select","cn","inputs","arguments","clsx","DEFAULT_CSS_VARIABLES","background","foreground","card","cardForeground","primary","primaryForeground","muted","mutedForeground","destructive","spacing1","spacing2","spacing3","spacing4","spacing5","spacing6","spacing8","DEFAULT_THEME","mergeThemeWithDefaults","userTheme","socketTheme","mergedCssVariables","cssVariables","primaryColor","botName","logoUrl","welcomeMessage","inputPlaceholder","getPrimaryColor","options","isDebugEnabled","DEBUG","logger","log","message","error","debug","info","DEFAULT_AVATAR_URL","encodeURIComponent","DEFAULT_NOTIFICATION_SOUND_URL","numSamples","Math","floor","sampleRate","dataSize","fileSize","buffer","ArrayBuffer","view","DataView","writeString","setUint32","setUint16","fadeOut","sample","sin","PI","setInt16","bytes","Uint8Array","binary","String","fromCharCode","btoa","createNotificationSoundDataUrl","offset","setUint8","charCodeAt","memo","getDeps","fn","opts","deps","initialDeps","isInitial","memoizedFunction","_a","_b","_c","depTime","call","Date","now","newDeps","some","dep","resultTime","depEndTime","round","resultEndTime","resultFpsPercentage","pad","str","num","max","min","onChange","skipInitialOnChange","updateDeps","notUndefined","msg","debounce","targetWindow","timeoutId","clearTimeout","setTimeout","apply","this","getRect","element","offsetWidth","offsetHeight","defaultKeyExtractor","defaultRangeExtractor","range","overscan","endIndex","count","arr","observeElementRect","instance","cb","scrollElement","handler","rect","ResizeObserver","observer","run","entry","borderBoxSize","inlineSize","blockSize","useAnimationFrameWithResizeObserver","requestAnimationFrame","observe","unobserve","addEventListenerOptions","passive","supportsScrollend","observeElementOffset","fallback","useScrollendEvent","isScrollingResetDelay","createHandler","isScrolling","horizontal","isRtl","endHandler","registerScrollendEvent","measureElement","elementScroll","adjustments","behavior","toOffset","scrollTo","Virtualizer","constructor","unsubs","currentScrollToIndex","measurementsCache","itemSizeCache","laneAssignments","pendingMeasuredCacheIndexes","prevLanes","lanesChangedFlag","lanesSettling","scrollRect","scrollOffset","scrollDirection","scrollAdjustments","elementsCache","_ro","_measureElement","target","disconnect","setOptions","opts2","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","scrollMargin","indexAttribute","initialMeasurementsCache","lanes","enabled","notify","sync","maybeNotify","calculateRange","cleanup","_didMount","_willUpdate","getScrollElement","ownerDocument","defaultView","cached","getScrollOffset","_scrollToOffset","getSize","getFurthestMeasurement","measurements","furthestMeasurementsFound","furthestMeasurements","measurement","lane","previousFurthestMeasurement","values","a","b","getMeasurementOptions","getMeasurements","keys","delete","item","laneLastIndex","cachedLane","prevIndex","prevInLane","furthestMeasurement","measuredSize","estimateSize","outerSize","lastIndex","findNearestBinarySearch","endPerLane","pos","startPerLane","getVirtualIndexes","indexFromElement","node","attributeName","indexStr","getAttribute","parseInt","prevNode","isConnected","resizeItem","delta","shouldAdjustScrollPositionOnItemSizeChange","getVirtualItems","indexes","virtualItems","getVirtualItemForOffset","getMaxScrollOffset","scrollWidth","clientWidth","scrollHeight","clientHeight","doc","document","documentElement","innerWidth","innerHeight","getOffsetForAlignment","itemSize","maxOffset","getOffsetForIndex","isDynamicMode","scrollToOffset","scrollToIndex","initialAlign","attempts","tryScroll","currentAlign","offsetInfo","verify","currentOffset","afterInfo","abs","scheduleRetry","scrollBy","getTotalSize","endByLane","val","scrollToFn","measure","low","high","getCurrentValue","middle","currentValue","useIsomorphicLayoutEffect","React.useLayoutEffect","React.useEffect","AudioPlayer","lazy","import","then","default","Gallery","MessageBubble","botAvatar","avatars","isFirst","isLast","isUser","sender","isSystem","type","isBot","brandColor","currentAvatar","useMemo","textMsg","emotion","RenderLink","href","textContent","isCTA","rel","jsxs","style","backgroundColor","borderColor","RenderImage","src","alt","Suspense","images","padding","boxShadow","url","imgMsg","imageUrl","altText","locMsg","latitude","longitude","fileMsg","fileExtension","fileName","pop","toFixed","fileUrl","download","FileIcon","ReactMarkdown","remarkPlugins","remarkGfm","rehypePlugins","rehypeSanitize","tagNames","attributes","img","protocols","components","renderContent","date","dateObj","getTime","toLocaleTimeString","hour","minute","hour12","formatTime","timestamp","prevProps","nextProps","id","JSON","stringify","styles","TypingIndicator","animationDelay","animationDuration","differenceInMinutes","laterDate","earlierDate","diffMs","Intl","DateTimeFormat","format","MessageList","messages","isTyping","bubbleStyles","messagesEndRef","useRef","containerRef","isReady","setIsReady","logoError","setLogoError","bgColor","shouldVirtualize","virtualizer","useFlushSync","rerender","React.useReducer","resolvedOptions","instance2","flushSync","React.useState","useVirtualizerBase","timer","scrollIntoView","block","getSeparatorLabel","today","getDate","getMonth","getFullYear","isToday","yesterday","setDate","isYesterday","day","month","formatShort","formatRelative","virtualRow","prev","showDateSeparator","isSameAsPrev","isSameAsNext","onError","React","Fragment","prevLast","nextLast","MAGIC_BYTES","async","validateFile","file","maxSizeMB","allowedExtensions","checkMagicBytes","maxSizeBytes","validateFileSize","valid","extension","name","validateFileExtension","isValid","expectedBytes","arrayBuffer","every","byte","validateFileType","MAX_CHARS","DEFAULT_MEDIA_CONFIG","enableImages","enableAudio","enableFiles","enableLocation","allowedFileTypes","maxFileSizeMB","InputArea","mediaConfig","onSendMessage","onSendAttachment","onSendLocation","inputValue","setInputValue","isMenuOpen","setIsMenuOpen","isRecording","setIsRecording","recordingTime","setRecordingTime","attachment","setAttachment","isCompressing","setIsCompressing","isLoadingLocation","setIsLoadingLocation","textareaRef","fileInputRef","imageInputRef","mediaRecorderRef","audioChunksRef","timerRef","hasMediaFeatures","handleSend","trimmedValue","handleFileSelect","files","validationResult","imageCompression","maxWidthOrHeight","useWebWorker","compressedFile","previewUrl","URL","createObjectURL","alert","stopRecording","onstop","stop","stream","getTracks","clearInterval","audioBlob","Blob","audioFile","validation","Loader2","onClick","accept","ext","marginBottom","click","ImageIcon","geolocation","getCurrentPosition","coords","toString","padStart","rows","onKeyDown","shiftKey","ctrlKey","metaKey","preventDefault","onFocus","disabled","scrollbarWidth","msOverflowStyle","mediaDevices","getUserMedia","audio","mediaRecorder","MediaRecorder","ondataavailable","data","setInterval","v","throttle","lastCall","timeSinceLastCall","execute","useIsMobile","isMobile","setIsMobile","checkMobile","DEFAULT_BOTTOM","ChatWindow","isOpen","onClose","themePrimary","dynamicHeightStyles","dynamicHeight","setDynamicHeight","calculateHeight","updateMobileHeight","visualViewport","offsetTop","availableHeight","calculatedHeight","maxHeight","useDynamicHeight","dialogRef","returnFocusRef","onEscape","previousActiveElementRef","activeElement","returnTarget","focusTimeout","focusable","querySelectorAll","focus","handleKeyDown","focusableElements","firstElement","lastElement","targetToFocus","useFocusTrap","body","desktopBottom","isBottomLeft","role","tabIndex","backdropFilter","title","paddingTop","paddingLeft","paddingRight","paddingBottom","marginTop"],"mappings":"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","x_google_ignoreList":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,38,39,40]}