analytica-frontend-lib 1.0.43 → 1.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/DropdownMenu/DropdownMenu.tsx","../../src/components/Button/Button.tsx"],"sourcesContent":["import { SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button from '../Button/Button';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n const newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {\n store,\n };\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({ children, open, onOpenChange }: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const isControlled = open !== undefined;\n const uncontrolledOpen = useStore(store, (s) => s.open);\n const currentOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = (newOpen: boolean) => {\n onOpenChange?.(newOpen);\n if (!isControlled) store.setState({ open: newOpen });\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n useEffect(() => {\n onOpenChange?.(currentOpen);\n if (currentOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [currentOpen]);\n\n useEffect(() => {\n if (isControlled) {\n store.setState({ open: open });\n }\n }, []);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = ({\n className,\n children,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <Button\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n if (onClick) onClick(e);\n }}\n aria-expanded={open}\n className={`${className}`}\n {...props}\n >\n {children}\n </Button>\n );\n};\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'p-1',\n profile: 'p-6',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`text-sm w-full ${inset ? 'pl-8' : ''} ${className ?? ''}`}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst MenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n return (\n <div\n ref={ref}\n role=\"menu\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e as MouseEvent<HTMLDivElement>);\n setOpen(false);\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <span className=\"w-full text-md\">{children}</span>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={`my-1 h-px bg-border-200 ${className}`}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={`rounded-lg size-10 bg-background-50 flex items-center justify-center ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-background-100 flex items-center justify-center\">\n <User className=\"text-background-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={`\n flex flex-row gap-4 items-center\n ${className}\n `}\n {...props}\n >\n <span className=\"size-16 bg-background-100 rounded-full flex items-center justify-center\">\n <User size={34} className=\"text-background-950\" />\n </span>\n <div className=\"flex flex-col \">\n <p className=\"text-xl font-bold text-text-950\">{name}</p>\n <p className=\"text-md text-text-600\">{email}</p>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`\n flex flex-col p-2\n ${className}\n `}\n {...props}\n >\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={`w-full ${className}`}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut />\n </span>\n <span>Sair</span>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n MenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n};\n","import { ButtonHTMLAttributes, ReactNode } from 'react';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n primary:\n 'bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n outline: {\n primary:\n 'bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n link: {\n primary:\n 'bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'text-xs px-3.5 py-2',\n small: 'text-sm px-4 py-2.5',\n medium: 'text-md px-5 py-2.5',\n large: 'text-lg px-6 py-3',\n 'extra-large': 'text-lg px-7 py-3.5',\n} as const;\n\n/**\n * Button component props interface\n */\ntype ButtonProps = {\n /** Content to be displayed inside the button */\n children: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Size of the button */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the button */\n variant?: 'solid' | 'outline' | 'link';\n /** Action type of the button */\n action?: 'primary' | 'positive' | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Button component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the button\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard button HTML attributes\n * @returns A styled button element\n *\n * @example\n * ```tsx\n * <Button variant=\"solid\" action=\"primary\" size=\"medium\" onClick={() => console.log('clicked')}>\n * Click me\n * </Button>\n * ```\n */\nconst Button = ({\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'primary',\n className = '',\n disabled,\n type = 'button',\n ...props\n}: ButtonProps) => {\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_ACTION_CLASSES[variant][action];\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-full cursor-pointer font-medium';\n\n return (\n <button\n className={`${baseClasses} ${variantClasses} ${sizeClasses} ${className}`}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && <span className=\"mr-2 flex items-center\">{iconLeft}</span>}\n {children}\n {iconRight && <span className=\"ml-2 flex items-center\">{iconRight}</span>}\n </button>\n );\n};\n\nexport default Button;\n"],"mappings":"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","names":["import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/components/DropdownMenu/DropdownMenu.tsx","../../src/components/Button/Button.tsx"],"sourcesContent":["import { SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button from '../Button/Button';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n const newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {\n store,\n };\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({\n children,\n open: propOpen,\n onOpenChange,\n}: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const { open, setOpen: storeSetOpen } = useStore(store, (s) => s);\n\n const setOpen = (newOpen: boolean) => {\n storeSetOpen(newOpen);\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n useEffect(() => {\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [open]);\n\n useEffect(() => {\n setOpen(open);\n onOpenChange?.(open);\n }, [open, onOpenChange]);\n\n useEffect(() => {\n if (propOpen) {\n setOpen(propOpen);\n }\n }, [propOpen]);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = ({\n className,\n children,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <Button\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n if (onClick) onClick(e);\n }}\n aria-expanded={open}\n className={`${className}`}\n {...props}\n >\n {children}\n </Button>\n );\n};\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'p-1',\n profile: 'p-6',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`text-sm w-full ${inset ? 'pl-8' : ''} ${className ?? ''}`}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst MenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n return (\n <div\n ref={ref}\n role=\"menu\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e as MouseEvent<HTMLDivElement>);\n setOpen(false);\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <span className=\"w-full text-md\">{children}</span>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={`my-1 h-px bg-border-200 ${className}`}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={`rounded-lg size-10 bg-background-50 flex items-center justify-center ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-background-100 flex items-center justify-center\">\n <User className=\"text-background-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={`\n flex flex-row gap-4 items-center\n ${className}\n `}\n {...props}\n >\n <span className=\"size-16 bg-background-100 rounded-full flex items-center justify-center\">\n <User size={34} className=\"text-background-950\" />\n </span>\n <div className=\"flex flex-col \">\n <p className=\"text-xl font-bold text-text-950\">{name}</p>\n <p className=\"text-md text-text-600\">{email}</p>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`\n flex flex-col p-2\n ${className}\n `}\n {...props}\n >\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={`w-full ${className}`}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut />\n </span>\n <span>Sair</span>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n MenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n};\n","import { ButtonHTMLAttributes, ReactNode } from 'react';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n primary:\n 'bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n outline: {\n primary:\n 'bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n link: {\n primary:\n 'bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'text-xs px-3.5 py-2',\n small: 'text-sm px-4 py-2.5',\n medium: 'text-md px-5 py-2.5',\n large: 'text-lg px-6 py-3',\n 'extra-large': 'text-lg px-7 py-3.5',\n} as const;\n\n/**\n * Button component props interface\n */\ntype ButtonProps = {\n /** Content to be displayed inside the button */\n children: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Size of the button */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the button */\n variant?: 'solid' | 'outline' | 'link';\n /** Action type of the button */\n action?: 'primary' | 'positive' | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Button component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the button\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard button HTML attributes\n * @returns A styled button element\n *\n * @example\n * ```tsx\n * <Button variant=\"solid\" action=\"primary\" size=\"medium\" onClick={() => console.log('clicked')}>\n * Click me\n * </Button>\n * ```\n */\nconst Button = ({\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'primary',\n className = '',\n disabled,\n type = 'button',\n ...props\n}: ButtonProps) => {\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_ACTION_CLASSES[variant][action];\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-full cursor-pointer font-medium';\n\n return (\n <button\n className={`${baseClasses} ${variantClasses} ${sizeClasses} ${className}`}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && <span className=\"mr-2 flex items-center\">{iconLeft}</span>}\n {children}\n {iconRight && <span className=\"ml-2 flex items-center\">{iconRight}</span>}\n </button>\n );\n};\n\nexport default Button;\n"],"mappings":"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","names":["import_jsx_runtime"]}
@@ -100,16 +100,17 @@ var injectStore = (children, store) => {
100
100
  return child;
101
101
  });
102
102
  };
103
- var DropdownMenu = ({ children, open, onOpenChange }) => {
103
+ var DropdownMenu = ({
104
+ children,
105
+ open: propOpen,
106
+ onOpenChange
107
+ }) => {
104
108
  const storeRef = useRef(null);
105
109
  storeRef.current ??= createDropdownStore();
106
110
  const store = storeRef.current;
107
- const isControlled = open !== void 0;
108
- const uncontrolledOpen = useStore(store, (s) => s.open);
109
- const currentOpen = isControlled ? open : uncontrolledOpen;
111
+ const { open, setOpen: storeSetOpen } = useStore(store, (s) => s);
110
112
  const setOpen = (newOpen) => {
111
- onOpenChange?.(newOpen);
112
- if (!isControlled) store.setState({ open: newOpen });
113
+ storeSetOpen(newOpen);
113
114
  };
114
115
  const menuRef = useRef(null);
115
116
  const handleArrowDownOrArrowUp = (event) => {
@@ -146,8 +147,7 @@ var DropdownMenu = ({ children, open, onOpenChange }) => {
146
147
  }
147
148
  };
148
149
  useEffect(() => {
149
- onOpenChange?.(currentOpen);
150
- if (currentOpen) {
150
+ if (open) {
151
151
  document.addEventListener("mousedown", handleClickOutside);
152
152
  document.addEventListener("keydown", handleDownkey);
153
153
  }
@@ -155,12 +155,16 @@ var DropdownMenu = ({ children, open, onOpenChange }) => {
155
155
  document.removeEventListener("mousedown", handleClickOutside);
156
156
  document.removeEventListener("keydown", handleDownkey);
157
157
  };
158
- }, [currentOpen]);
158
+ }, [open]);
159
+ useEffect(() => {
160
+ setOpen(open);
161
+ onOpenChange?.(open);
162
+ }, [open, onOpenChange]);
159
163
  useEffect(() => {
160
- if (isControlled) {
161
- store.setState({ open });
164
+ if (propOpen) {
165
+ setOpen(propOpen);
162
166
  }
163
- }, []);
167
+ }, [propOpen]);
164
168
  return /* @__PURE__ */ jsx2("div", { className: "relative", ref: menuRef, children: injectStore(children, store) });
165
169
  };
166
170
  var DropdownMenuTrigger = ({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/DropdownMenu/DropdownMenu.tsx","../../src/components/Button/Button.tsx"],"sourcesContent":["import { SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button from '../Button/Button';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n const newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {\n store,\n };\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({ children, open, onOpenChange }: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const isControlled = open !== undefined;\n const uncontrolledOpen = useStore(store, (s) => s.open);\n const currentOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = (newOpen: boolean) => {\n onOpenChange?.(newOpen);\n if (!isControlled) store.setState({ open: newOpen });\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n useEffect(() => {\n onOpenChange?.(currentOpen);\n if (currentOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [currentOpen]);\n\n useEffect(() => {\n if (isControlled) {\n store.setState({ open: open });\n }\n }, []);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = ({\n className,\n children,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <Button\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n if (onClick) onClick(e);\n }}\n aria-expanded={open}\n className={`${className}`}\n {...props}\n >\n {children}\n </Button>\n );\n};\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'p-1',\n profile: 'p-6',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`text-sm w-full ${inset ? 'pl-8' : ''} ${className ?? ''}`}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst MenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n return (\n <div\n ref={ref}\n role=\"menu\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e as MouseEvent<HTMLDivElement>);\n setOpen(false);\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <span className=\"w-full text-md\">{children}</span>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={`my-1 h-px bg-border-200 ${className}`}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={`rounded-lg size-10 bg-background-50 flex items-center justify-center ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-background-100 flex items-center justify-center\">\n <User className=\"text-background-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={`\n flex flex-row gap-4 items-center\n ${className}\n `}\n {...props}\n >\n <span className=\"size-16 bg-background-100 rounded-full flex items-center justify-center\">\n <User size={34} className=\"text-background-950\" />\n </span>\n <div className=\"flex flex-col \">\n <p className=\"text-xl font-bold text-text-950\">{name}</p>\n <p className=\"text-md text-text-600\">{email}</p>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`\n flex flex-col p-2\n ${className}\n `}\n {...props}\n >\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={`w-full ${className}`}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut />\n </span>\n <span>Sair</span>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n MenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n};\n","import { ButtonHTMLAttributes, ReactNode } from 'react';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n primary:\n 'bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n outline: {\n primary:\n 'bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n link: {\n primary:\n 'bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'text-xs px-3.5 py-2',\n small: 'text-sm px-4 py-2.5',\n medium: 'text-md px-5 py-2.5',\n large: 'text-lg px-6 py-3',\n 'extra-large': 'text-lg px-7 py-3.5',\n} as const;\n\n/**\n * Button component props interface\n */\ntype ButtonProps = {\n /** Content to be displayed inside the button */\n children: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Size of the button */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the button */\n variant?: 'solid' | 'outline' | 'link';\n /** Action type of the button */\n action?: 'primary' | 'positive' | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Button component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the button\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard button HTML attributes\n * @returns A styled button element\n *\n * @example\n * ```tsx\n * <Button variant=\"solid\" action=\"primary\" size=\"medium\" onClick={() => console.log('clicked')}>\n * Click me\n * </Button>\n * ```\n */\nconst Button = ({\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'primary',\n className = '',\n disabled,\n type = 'button',\n ...props\n}: ButtonProps) => {\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_ACTION_CLASSES[variant][action];\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-full cursor-pointer font-medium';\n\n return (\n <button\n className={`${baseClasses} ${variantClasses} ${sizeClasses} ${className}`}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && <span className=\"mr-2 flex items-center\">{iconLeft}</span>}\n {children}\n {iconRight && <span className=\"ml-2 flex items-center\">{iconRight}</span>}\n </button>\n );\n};\n\nexport default Button;\n"],"mappings":"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","names":["jsx","jsxs"]}
1
+ {"version":3,"sources":["../../src/components/DropdownMenu/DropdownMenu.tsx","../../src/components/Button/Button.tsx"],"sourcesContent":["import { SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button from '../Button/Button';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n const newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {\n store,\n };\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({\n children,\n open: propOpen,\n onOpenChange,\n}: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const { open, setOpen: storeSetOpen } = useStore(store, (s) => s);\n\n const setOpen = (newOpen: boolean) => {\n storeSetOpen(newOpen);\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n useEffect(() => {\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [open]);\n\n useEffect(() => {\n setOpen(open);\n onOpenChange?.(open);\n }, [open, onOpenChange]);\n\n useEffect(() => {\n if (propOpen) {\n setOpen(propOpen);\n }\n }, [propOpen]);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = ({\n className,\n children,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <Button\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n if (onClick) onClick(e);\n }}\n aria-expanded={open}\n className={`${className}`}\n {...props}\n >\n {children}\n </Button>\n );\n};\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'p-1',\n profile: 'p-6',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`text-sm w-full ${inset ? 'pl-8' : ''} ${className ?? ''}`}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst MenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n return (\n <div\n ref={ref}\n role=\"menu\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e as MouseEvent<HTMLDivElement>);\n setOpen(false);\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <span className=\"w-full text-md\">{children}</span>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={`my-1 h-px bg-border-200 ${className}`}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={`rounded-lg size-10 bg-background-50 flex items-center justify-center ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-background-100 flex items-center justify-center\">\n <User className=\"text-background-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={`\n flex flex-row gap-4 items-center\n ${className}\n `}\n {...props}\n >\n <span className=\"size-16 bg-background-100 rounded-full flex items-center justify-center\">\n <User size={34} className=\"text-background-950\" />\n </span>\n <div className=\"flex flex-col \">\n <p className=\"text-xl font-bold text-text-950\">{name}</p>\n <p className=\"text-md text-text-600\">{email}</p>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`\n flex flex-col p-2\n ${className}\n `}\n {...props}\n >\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={`w-full ${className}`}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut />\n </span>\n <span>Sair</span>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n MenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n};\n","import { ButtonHTMLAttributes, ReactNode } from 'react';\n\n/**\n * Lookup table for variant and action class combinations\n */\nconst VARIANT_ACTION_CLASSES = {\n solid: {\n primary:\n 'bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n outline: {\n primary:\n 'bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n link: {\n primary:\n 'bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed',\n positive:\n 'bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed',\n negative:\n 'bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed',\n },\n} as const;\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'text-xs px-3.5 py-2',\n small: 'text-sm px-4 py-2.5',\n medium: 'text-md px-5 py-2.5',\n large: 'text-lg px-6 py-3',\n 'extra-large': 'text-lg px-7 py-3.5',\n} as const;\n\n/**\n * Button component props interface\n */\ntype ButtonProps = {\n /** Content to be displayed inside the button */\n children: ReactNode;\n /** Ícone à esquerda do texto */\n iconLeft?: ReactNode;\n /** Ícone à direita do texto */\n iconRight?: ReactNode;\n /** Size of the button */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the button */\n variant?: 'solid' | 'outline' | 'link';\n /** Action type of the button */\n action?: 'primary' | 'positive' | 'negative';\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Button component for Analytica Ensino platforms\n *\n * A flexible button component with multiple variants, sizes and actions.\n *\n * @param children - The content to display inside the button\n * @param size - The size variant (extra-small, small, medium, large, extra-large)\n * @param variant - The visual style variant (solid, outline, link)\n * @param action - The action type (primary, positive, negative)\n * @param className - Additional CSS classes\n * @param props - All other standard button HTML attributes\n * @returns A styled button element\n *\n * @example\n * ```tsx\n * <Button variant=\"solid\" action=\"primary\" size=\"medium\" onClick={() => console.log('clicked')}>\n * Click me\n * </Button>\n * ```\n */\nconst Button = ({\n children,\n iconLeft,\n iconRight,\n size = 'medium',\n variant = 'solid',\n action = 'primary',\n className = '',\n disabled,\n type = 'button',\n ...props\n}: ButtonProps) => {\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_ACTION_CLASSES[variant][action];\n\n const baseClasses =\n 'inline-flex items-center justify-center rounded-full cursor-pointer font-medium';\n\n return (\n <button\n className={`${baseClasses} ${variantClasses} ${sizeClasses} ${className}`}\n disabled={disabled}\n type={type}\n {...props}\n >\n {iconLeft && <span className=\"mr-2 flex items-center\">{iconLeft}</span>}\n {children}\n {iconRight && <span className=\"ml-2 flex items-center\">{iconRight}</span>}\n </button>\n );\n};\n\nexport default Button;\n"],"mappings":"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","names":["jsx","jsxs"]}
@@ -36,7 +36,7 @@ var STATE_CLASSES = {
36
36
  default: "border-border-300 placeholder:text-text-600 hover:border-border-400",
37
37
  error: "border-2 border-indicator-error placeholder:text-text-600",
38
38
  disabled: "border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40",
39
- "read-only": "border-border-300 !text-text-600 cursor-default focus:outline-none bg-background-50"
39
+ "read-only": "border-transparent !text-text-600 cursor-default focus:outline-none bg-transparent"
40
40
  };
41
41
  var VARIANT_CLASSES = {
42
42
  outlined: "border rounded-lg",
@@ -75,6 +75,9 @@ var getCombinedClasses = (actualState, variant) => {
75
75
  if (actualState === "error" && variant === "underlined") {
76
76
  return "border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600";
77
77
  }
78
+ if (actualState === "read-only" && variant === "underlined") {
79
+ return "border-0 border-b-0 rounded-none bg-transparent focus:outline-none !text-text-900 cursor-default";
80
+ }
78
81
  return `${stateClasses} ${variantClasses}`;
79
82
  };
80
83
  var Input = (0, import_react.forwardRef)(
@@ -105,7 +108,7 @@ var Input = (0, import_react.forwardRef)(
105
108
  [actualState, variant]
106
109
  );
107
110
  const iconSize = getIconSize(size);
108
- const baseClasses = "bg-background w-full py-2 px-3 font-normal text-text-900 focus:outline-primary-950";
111
+ const baseClasses = `bg-background w-full py-2 ${actualState === "read-only" ? "px-0" : "px-3"} font-normal text-text-900 focus:outline-primary-950`;
109
112
  const generatedId = (0, import_react.useId)();
110
113
  const inputId = id ?? `input-${generatedId}`;
111
114
  const togglePasswordVisibility = () => setShowPassword(!showPassword);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Input/Input.tsx"],"sourcesContent":["import { WarningCircle, Eye, EyeSlash } from 'phosphor-react';\nimport {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n useMemo,\n} from 'react';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n large: 'text-lg',\n 'extra-large': 'text-xl',\n} as const;\n\n/**\n * Lookup table for state classes\n */\nconst STATE_CLASSES = {\n default:\n 'border-border-300 placeholder:text-text-600 hover:border-border-400',\n error: 'border-2 border-indicator-error placeholder:text-text-600',\n disabled:\n 'border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40',\n 'read-only':\n 'border-border-300 !text-text-600 cursor-default focus:outline-none bg-background-50',\n} as const;\n\n/**\n * Lookup table for variant classes\n */\nconst VARIANT_CLASSES = {\n outlined: 'border rounded-lg',\n underlined:\n 'border-0 border-b rounded-none bg-transparent focus:outline-none focus:border-primary-950 focus:border-b-2',\n rounded: 'border rounded-full',\n} as const;\n\n/**\n * Input component props interface\n */\ntype InputProps = {\n /** Label text displayed above the input */\n label?: string;\n /** Helper text displayed below the input */\n helperText?: string;\n /** Error message displayed below the input */\n errorMessage?: string;\n /** Size of the input */\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the input */\n variant?: 'outlined' | 'underlined' | 'rounded';\n /** Current state of the input */\n state?: 'default' | 'error' | 'disabled' | 'read-only';\n /** Icon to display on the left side of the input */\n iconLeft?: ReactNode;\n /** Icon to display on the right side of the input */\n iconRight?: ReactNode;\n /** Additional CSS classes to apply to the input */\n className?: string;\n /** Additional CSS classes to apply to the container */\n containerClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>;\n\n/**\n * Input component for Analytica Ensino platforms\n *\n * A flexible input component with multiple sizes, states, and support for icons.\n * Includes label, helper text, and error message functionality.\n * Features automatic password visibility toggle for password inputs.\n *\n * @param label - Optional label text displayed above the input\n * @param helperText - Optional helper text displayed below the input\n * @param errorMessage - Optional error message displayed below the input\n * @param size - The size variant (small, medium, large, extra-large)\n * @param variant - The visual variant (outlined, underlined, rounded)\n * @param state - The current state (default, error, disabled, read-only)\n * @param iconLeft - Optional icon displayed on the left side\n * @param iconRight - Optional icon displayed on the right side (overridden by password toggle for password inputs)\n * @param type - Input type (text, email, password, etc.) - password type automatically includes show/hide toggle\n * @param className - Additional CSS classes for the input\n * @param containerClassName - Additional CSS classes for the container\n * @param props - All other standard input HTML attributes\n * @returns A styled input element with optional label and helper text\n *\n * @example\n * ```tsx\n * // Basic input\n * <Input\n * label=\"Email\"\n * placeholder=\"Digite seu email\"\n * helperText=\"Usaremos apenas para contato\"\n * size=\"medium\"\n * variant=\"outlined\"\n * state=\"default\"\n * />\n *\n * // Password input with automatic toggle\n * <Input\n * label=\"Senha\"\n * type=\"password\"\n * placeholder=\"Digite sua senha\"\n * helperText=\"Clique no olho para mostrar/ocultar\"\n * />\n * ```\n */\n// Helper functions to reduce cognitive complexity\nconst getActualState = (\n disabled?: boolean,\n readOnly?: boolean,\n errorMessage?: string,\n state?: string\n): keyof typeof STATE_CLASSES => {\n if (disabled) return 'disabled';\n if (readOnly) return 'read-only';\n if (errorMessage) return 'error';\n return (state as keyof typeof STATE_CLASSES) || 'default';\n};\n\nconst getIconSize = (size: string) => {\n const iconSizeClasses = {\n small: 'w-4 h-4',\n medium: 'w-5 h-5',\n large: 'w-6 h-6',\n 'extra-large': 'w-7 h-7',\n };\n return (\n iconSizeClasses[size as keyof typeof iconSizeClasses] ||\n iconSizeClasses.medium\n );\n};\n\nconst getPasswordToggleConfig = (\n type?: string,\n disabled?: boolean,\n readOnly?: boolean,\n showPassword?: boolean,\n iconRight?: ReactNode\n) => {\n const isPasswordType = type === 'password';\n const shouldShowPasswordToggle = isPasswordType && !disabled && !readOnly;\n\n let actualIconRight = iconRight;\n let ariaLabel: string | undefined;\n\n if (shouldShowPasswordToggle) {\n actualIconRight = showPassword ? <EyeSlash /> : <Eye />;\n ariaLabel = showPassword ? 'Ocultar senha' : 'Mostrar senha';\n }\n\n return { shouldShowPasswordToggle, actualIconRight, ariaLabel };\n};\n\nconst getCombinedClasses = (\n actualState: keyof typeof STATE_CLASSES,\n variant: keyof typeof VARIANT_CLASSES\n) => {\n const stateClasses = STATE_CLASSES[actualState];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Special case: error state with underlined variant\n if (actualState === 'error' && variant === 'underlined') {\n return 'border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600';\n }\n\n return `${stateClasses} ${variantClasses}`;\n};\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n label,\n helperText,\n errorMessage,\n size = 'medium',\n variant = 'outlined',\n state = 'default',\n iconLeft,\n iconRight,\n className = '',\n containerClassName = '',\n disabled,\n readOnly,\n id,\n type = 'text',\n ...props\n },\n ref\n ) => {\n // State for password visibility toggle\n const [showPassword, setShowPassword] = useState(false);\n const isPasswordType = type === 'password';\n const actualType = isPasswordType && showPassword ? 'text' : type;\n const actualState = getActualState(disabled, readOnly, errorMessage, state);\n\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const combinedClasses = useMemo(\n () => getCombinedClasses(actualState, variant),\n [actualState, variant]\n );\n const iconSize = getIconSize(size);\n\n const baseClasses =\n 'bg-background w-full py-2 px-3 font-normal text-text-900 focus:outline-primary-950';\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `input-${generatedId}`;\n\n // Handle password visibility toggle\n const togglePasswordVisibility = () => setShowPassword(!showPassword);\n\n // Get password toggle configuration\n const { shouldShowPasswordToggle, actualIconRight, ariaLabel } =\n getPasswordToggleConfig(\n type,\n disabled,\n readOnly,\n showPassword,\n iconRight\n );\n\n return (\n <div className={`${containerClassName}`}>\n {/* Label */}\n {label && (\n <label\n htmlFor={inputId}\n className={`block font-bold text-text-900 mb-1.5 ${sizeClasses}`}\n >\n {label}\n </label>\n )}\n\n {/* Input Container */}\n <div className=\"relative\">\n {/* Left Icon */}\n {iconLeft && (\n <div className=\"absolute left-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {iconLeft}\n </span>\n </div>\n )}\n\n {/* Input Field */}\n <input\n ref={ref}\n id={inputId}\n type={actualType}\n className={`${baseClasses} ${sizeClasses} ${combinedClasses} ${\n iconLeft ? 'pl-10' : ''\n } ${actualIconRight ? 'pr-10' : ''} ${className}`}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={actualState === 'error' ? 'true' : undefined}\n {...props}\n />\n\n {/* Right Icon */}\n {actualIconRight &&\n (shouldShowPasswordToggle ? (\n <button\n type=\"button\"\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer border-0 bg-transparent p-0\"\n onClick={togglePasswordVisibility}\n aria-label={ariaLabel}\n >\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center hover:text-text-600 transition-colors`}\n >\n {actualIconRight}\n </span>\n </button>\n ) : (\n <div className=\"absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {actualIconRight}\n </span>\n </div>\n ))}\n </div>\n\n {/* Helper Text or Error Message */}\n <div className=\"mt-1.5 gap-1.5\">\n {helperText && <p className=\"text-sm text-text-500\">{helperText}</p>}\n {errorMessage && (\n <p className=\"flex gap-1 items-center text-sm text-indicator-error\">\n <WarningCircle size={16} /> {errorMessage}\n </p>\n )}\n </div>\n </div>\n );\n }\n);\n\nexport default Input;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/Input/Input.tsx"],"sourcesContent":["import { WarningCircle, Eye, EyeSlash } from 'phosphor-react';\nimport {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n useMemo,\n} from 'react';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n large: 'text-lg',\n 'extra-large': 'text-xl',\n} as const;\n\n/**\n * Lookup table for state classes\n */\nconst STATE_CLASSES = {\n default:\n 'border-border-300 placeholder:text-text-600 hover:border-border-400',\n error: 'border-2 border-indicator-error placeholder:text-text-600',\n disabled:\n 'border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40',\n 'read-only':\n 'border-transparent !text-text-600 cursor-default focus:outline-none bg-transparent',\n} as const;\n\n/**\n * Lookup table for variant classes\n */\nconst VARIANT_CLASSES = {\n outlined: 'border rounded-lg',\n underlined:\n 'border-0 border-b rounded-none bg-transparent focus:outline-none focus:border-primary-950 focus:border-b-2',\n rounded: 'border rounded-full',\n} as const;\n\n/**\n * Input component props interface\n */\ntype InputProps = {\n /** Label text displayed above the input */\n label?: string;\n /** Helper text displayed below the input */\n helperText?: string;\n /** Error message displayed below the input */\n errorMessage?: string;\n /** Size of the input */\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the input */\n variant?: 'outlined' | 'underlined' | 'rounded';\n /** Current state of the input */\n state?: 'default' | 'error' | 'disabled' | 'read-only';\n /** Icon to display on the left side of the input */\n iconLeft?: ReactNode;\n /** Icon to display on the right side of the input */\n iconRight?: ReactNode;\n /** Additional CSS classes to apply to the input */\n className?: string;\n /** Additional CSS classes to apply to the container */\n containerClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>;\n\n/**\n * Input component for Analytica Ensino platforms\n *\n * A flexible input component with multiple sizes, states, and support for icons.\n * Includes label, helper text, and error message functionality.\n * Features automatic password visibility toggle for password inputs.\n *\n * @param label - Optional label text displayed above the input\n * @param helperText - Optional helper text displayed below the input\n * @param errorMessage - Optional error message displayed below the input\n * @param size - The size variant (small, medium, large, extra-large)\n * @param variant - The visual variant (outlined, underlined, rounded)\n * @param state - The current state (default, error, disabled, read-only)\n * @param iconLeft - Optional icon displayed on the left side\n * @param iconRight - Optional icon displayed on the right side (overridden by password toggle for password inputs)\n * @param type - Input type (text, email, password, etc.) - password type automatically includes show/hide toggle\n * @param className - Additional CSS classes for the input\n * @param containerClassName - Additional CSS classes for the container\n * @param props - All other standard input HTML attributes\n * @returns A styled input element with optional label and helper text\n *\n * @example\n * ```tsx\n * // Basic input\n * <Input\n * label=\"Email\"\n * placeholder=\"Digite seu email\"\n * helperText=\"Usaremos apenas para contato\"\n * size=\"medium\"\n * variant=\"outlined\"\n * state=\"default\"\n * />\n *\n * // Password input with automatic toggle\n * <Input\n * label=\"Senha\"\n * type=\"password\"\n * placeholder=\"Digite sua senha\"\n * helperText=\"Clique no olho para mostrar/ocultar\"\n * />\n * ```\n */\n// Helper functions to reduce cognitive complexity\nconst getActualState = (\n disabled?: boolean,\n readOnly?: boolean,\n errorMessage?: string,\n state?: string\n): keyof typeof STATE_CLASSES => {\n if (disabled) return 'disabled';\n if (readOnly) return 'read-only';\n if (errorMessage) return 'error';\n return (state as keyof typeof STATE_CLASSES) || 'default';\n};\n\nconst getIconSize = (size: string) => {\n const iconSizeClasses = {\n small: 'w-4 h-4',\n medium: 'w-5 h-5',\n large: 'w-6 h-6',\n 'extra-large': 'w-7 h-7',\n };\n return (\n iconSizeClasses[size as keyof typeof iconSizeClasses] ||\n iconSizeClasses.medium\n );\n};\n\nconst getPasswordToggleConfig = (\n type?: string,\n disabled?: boolean,\n readOnly?: boolean,\n showPassword?: boolean,\n iconRight?: ReactNode\n) => {\n const isPasswordType = type === 'password';\n const shouldShowPasswordToggle = isPasswordType && !disabled && !readOnly;\n\n let actualIconRight = iconRight;\n let ariaLabel: string | undefined;\n\n if (shouldShowPasswordToggle) {\n actualIconRight = showPassword ? <EyeSlash /> : <Eye />;\n ariaLabel = showPassword ? 'Ocultar senha' : 'Mostrar senha';\n }\n\n return { shouldShowPasswordToggle, actualIconRight, ariaLabel };\n};\n\nconst getCombinedClasses = (\n actualState: keyof typeof STATE_CLASSES,\n variant: keyof typeof VARIANT_CLASSES\n) => {\n const stateClasses = STATE_CLASSES[actualState];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Special case: error state with underlined variant\n if (actualState === 'error' && variant === 'underlined') {\n return 'border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600';\n }\n\n // Special case: read-only state with underlined variant\n if (actualState === 'read-only' && variant === 'underlined') {\n return 'border-0 border-b-0 rounded-none bg-transparent focus:outline-none !text-text-900 cursor-default';\n }\n\n return `${stateClasses} ${variantClasses}`;\n};\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n label,\n helperText,\n errorMessage,\n size = 'medium',\n variant = 'outlined',\n state = 'default',\n iconLeft,\n iconRight,\n className = '',\n containerClassName = '',\n disabled,\n readOnly,\n id,\n type = 'text',\n ...props\n },\n ref\n ) => {\n // State for password visibility toggle\n const [showPassword, setShowPassword] = useState(false);\n const isPasswordType = type === 'password';\n const actualType = isPasswordType && showPassword ? 'text' : type;\n const actualState = getActualState(disabled, readOnly, errorMessage, state);\n\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const combinedClasses = useMemo(\n () => getCombinedClasses(actualState, variant),\n [actualState, variant]\n );\n const iconSize = getIconSize(size);\n\n const baseClasses = `bg-background w-full py-2 ${\n actualState === 'read-only' ? 'px-0' : 'px-3'\n } font-normal text-text-900 focus:outline-primary-950`;\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `input-${generatedId}`;\n\n // Handle password visibility toggle\n const togglePasswordVisibility = () => setShowPassword(!showPassword);\n\n // Get password toggle configuration\n const { shouldShowPasswordToggle, actualIconRight, ariaLabel } =\n getPasswordToggleConfig(\n type,\n disabled,\n readOnly,\n showPassword,\n iconRight\n );\n\n return (\n <div className={`${containerClassName}`}>\n {/* Label */}\n {label && (\n <label\n htmlFor={inputId}\n className={`block font-bold text-text-900 mb-1.5 ${sizeClasses}`}\n >\n {label}\n </label>\n )}\n\n {/* Input Container */}\n <div className=\"relative\">\n {/* Left Icon */}\n {iconLeft && (\n <div className=\"absolute left-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {iconLeft}\n </span>\n </div>\n )}\n\n {/* Input Field */}\n <input\n ref={ref}\n id={inputId}\n type={actualType}\n className={`${baseClasses} ${sizeClasses} ${combinedClasses} ${\n iconLeft ? 'pl-10' : ''\n } ${actualIconRight ? 'pr-10' : ''} ${className}`}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={actualState === 'error' ? 'true' : undefined}\n {...props}\n />\n\n {/* Right Icon */}\n {actualIconRight &&\n (shouldShowPasswordToggle ? (\n <button\n type=\"button\"\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer border-0 bg-transparent p-0\"\n onClick={togglePasswordVisibility}\n aria-label={ariaLabel}\n >\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center hover:text-text-600 transition-colors`}\n >\n {actualIconRight}\n </span>\n </button>\n ) : (\n <div className=\"absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {actualIconRight}\n </span>\n </div>\n ))}\n </div>\n\n {/* Helper Text or Error Message */}\n <div className=\"mt-1.5 gap-1.5\">\n {helperText && <p className=\"text-sm text-text-500\">{helperText}</p>}\n {errorMessage && (\n <p className=\"flex gap-1 items-center text-sm text-indicator-error\">\n <WarningCircle size={16} /> {errorMessage}\n </p>\n )}\n </div>\n </div>\n );\n }\n);\n\nexport default Input;\n"],"mappings":"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","names":[]}
@@ -17,7 +17,7 @@ var STATE_CLASSES = {
17
17
  default: "border-border-300 placeholder:text-text-600 hover:border-border-400",
18
18
  error: "border-2 border-indicator-error placeholder:text-text-600",
19
19
  disabled: "border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40",
20
- "read-only": "border-border-300 !text-text-600 cursor-default focus:outline-none bg-background-50"
20
+ "read-only": "border-transparent !text-text-600 cursor-default focus:outline-none bg-transparent"
21
21
  };
22
22
  var VARIANT_CLASSES = {
23
23
  outlined: "border rounded-lg",
@@ -56,6 +56,9 @@ var getCombinedClasses = (actualState, variant) => {
56
56
  if (actualState === "error" && variant === "underlined") {
57
57
  return "border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600";
58
58
  }
59
+ if (actualState === "read-only" && variant === "underlined") {
60
+ return "border-0 border-b-0 rounded-none bg-transparent focus:outline-none !text-text-900 cursor-default";
61
+ }
59
62
  return `${stateClasses} ${variantClasses}`;
60
63
  };
61
64
  var Input = forwardRef(
@@ -86,7 +89,7 @@ var Input = forwardRef(
86
89
  [actualState, variant]
87
90
  );
88
91
  const iconSize = getIconSize(size);
89
- const baseClasses = "bg-background w-full py-2 px-3 font-normal text-text-900 focus:outline-primary-950";
92
+ const baseClasses = `bg-background w-full py-2 ${actualState === "read-only" ? "px-0" : "px-3"} font-normal text-text-900 focus:outline-primary-950`;
90
93
  const generatedId = useId();
91
94
  const inputId = id ?? `input-${generatedId}`;
92
95
  const togglePasswordVisibility = () => setShowPassword(!showPassword);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Input/Input.tsx"],"sourcesContent":["import { WarningCircle, Eye, EyeSlash } from 'phosphor-react';\nimport {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n useMemo,\n} from 'react';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n large: 'text-lg',\n 'extra-large': 'text-xl',\n} as const;\n\n/**\n * Lookup table for state classes\n */\nconst STATE_CLASSES = {\n default:\n 'border-border-300 placeholder:text-text-600 hover:border-border-400',\n error: 'border-2 border-indicator-error placeholder:text-text-600',\n disabled:\n 'border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40',\n 'read-only':\n 'border-border-300 !text-text-600 cursor-default focus:outline-none bg-background-50',\n} as const;\n\n/**\n * Lookup table for variant classes\n */\nconst VARIANT_CLASSES = {\n outlined: 'border rounded-lg',\n underlined:\n 'border-0 border-b rounded-none bg-transparent focus:outline-none focus:border-primary-950 focus:border-b-2',\n rounded: 'border rounded-full',\n} as const;\n\n/**\n * Input component props interface\n */\ntype InputProps = {\n /** Label text displayed above the input */\n label?: string;\n /** Helper text displayed below the input */\n helperText?: string;\n /** Error message displayed below the input */\n errorMessage?: string;\n /** Size of the input */\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the input */\n variant?: 'outlined' | 'underlined' | 'rounded';\n /** Current state of the input */\n state?: 'default' | 'error' | 'disabled' | 'read-only';\n /** Icon to display on the left side of the input */\n iconLeft?: ReactNode;\n /** Icon to display on the right side of the input */\n iconRight?: ReactNode;\n /** Additional CSS classes to apply to the input */\n className?: string;\n /** Additional CSS classes to apply to the container */\n containerClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>;\n\n/**\n * Input component for Analytica Ensino platforms\n *\n * A flexible input component with multiple sizes, states, and support for icons.\n * Includes label, helper text, and error message functionality.\n * Features automatic password visibility toggle for password inputs.\n *\n * @param label - Optional label text displayed above the input\n * @param helperText - Optional helper text displayed below the input\n * @param errorMessage - Optional error message displayed below the input\n * @param size - The size variant (small, medium, large, extra-large)\n * @param variant - The visual variant (outlined, underlined, rounded)\n * @param state - The current state (default, error, disabled, read-only)\n * @param iconLeft - Optional icon displayed on the left side\n * @param iconRight - Optional icon displayed on the right side (overridden by password toggle for password inputs)\n * @param type - Input type (text, email, password, etc.) - password type automatically includes show/hide toggle\n * @param className - Additional CSS classes for the input\n * @param containerClassName - Additional CSS classes for the container\n * @param props - All other standard input HTML attributes\n * @returns A styled input element with optional label and helper text\n *\n * @example\n * ```tsx\n * // Basic input\n * <Input\n * label=\"Email\"\n * placeholder=\"Digite seu email\"\n * helperText=\"Usaremos apenas para contato\"\n * size=\"medium\"\n * variant=\"outlined\"\n * state=\"default\"\n * />\n *\n * // Password input with automatic toggle\n * <Input\n * label=\"Senha\"\n * type=\"password\"\n * placeholder=\"Digite sua senha\"\n * helperText=\"Clique no olho para mostrar/ocultar\"\n * />\n * ```\n */\n// Helper functions to reduce cognitive complexity\nconst getActualState = (\n disabled?: boolean,\n readOnly?: boolean,\n errorMessage?: string,\n state?: string\n): keyof typeof STATE_CLASSES => {\n if (disabled) return 'disabled';\n if (readOnly) return 'read-only';\n if (errorMessage) return 'error';\n return (state as keyof typeof STATE_CLASSES) || 'default';\n};\n\nconst getIconSize = (size: string) => {\n const iconSizeClasses = {\n small: 'w-4 h-4',\n medium: 'w-5 h-5',\n large: 'w-6 h-6',\n 'extra-large': 'w-7 h-7',\n };\n return (\n iconSizeClasses[size as keyof typeof iconSizeClasses] ||\n iconSizeClasses.medium\n );\n};\n\nconst getPasswordToggleConfig = (\n type?: string,\n disabled?: boolean,\n readOnly?: boolean,\n showPassword?: boolean,\n iconRight?: ReactNode\n) => {\n const isPasswordType = type === 'password';\n const shouldShowPasswordToggle = isPasswordType && !disabled && !readOnly;\n\n let actualIconRight = iconRight;\n let ariaLabel: string | undefined;\n\n if (shouldShowPasswordToggle) {\n actualIconRight = showPassword ? <EyeSlash /> : <Eye />;\n ariaLabel = showPassword ? 'Ocultar senha' : 'Mostrar senha';\n }\n\n return { shouldShowPasswordToggle, actualIconRight, ariaLabel };\n};\n\nconst getCombinedClasses = (\n actualState: keyof typeof STATE_CLASSES,\n variant: keyof typeof VARIANT_CLASSES\n) => {\n const stateClasses = STATE_CLASSES[actualState];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Special case: error state with underlined variant\n if (actualState === 'error' && variant === 'underlined') {\n return 'border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600';\n }\n\n return `${stateClasses} ${variantClasses}`;\n};\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n label,\n helperText,\n errorMessage,\n size = 'medium',\n variant = 'outlined',\n state = 'default',\n iconLeft,\n iconRight,\n className = '',\n containerClassName = '',\n disabled,\n readOnly,\n id,\n type = 'text',\n ...props\n },\n ref\n ) => {\n // State for password visibility toggle\n const [showPassword, setShowPassword] = useState(false);\n const isPasswordType = type === 'password';\n const actualType = isPasswordType && showPassword ? 'text' : type;\n const actualState = getActualState(disabled, readOnly, errorMessage, state);\n\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const combinedClasses = useMemo(\n () => getCombinedClasses(actualState, variant),\n [actualState, variant]\n );\n const iconSize = getIconSize(size);\n\n const baseClasses =\n 'bg-background w-full py-2 px-3 font-normal text-text-900 focus:outline-primary-950';\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `input-${generatedId}`;\n\n // Handle password visibility toggle\n const togglePasswordVisibility = () => setShowPassword(!showPassword);\n\n // Get password toggle configuration\n const { shouldShowPasswordToggle, actualIconRight, ariaLabel } =\n getPasswordToggleConfig(\n type,\n disabled,\n readOnly,\n showPassword,\n iconRight\n );\n\n return (\n <div className={`${containerClassName}`}>\n {/* Label */}\n {label && (\n <label\n htmlFor={inputId}\n className={`block font-bold text-text-900 mb-1.5 ${sizeClasses}`}\n >\n {label}\n </label>\n )}\n\n {/* Input Container */}\n <div className=\"relative\">\n {/* Left Icon */}\n {iconLeft && (\n <div className=\"absolute left-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {iconLeft}\n </span>\n </div>\n )}\n\n {/* Input Field */}\n <input\n ref={ref}\n id={inputId}\n type={actualType}\n className={`${baseClasses} ${sizeClasses} ${combinedClasses} ${\n iconLeft ? 'pl-10' : ''\n } ${actualIconRight ? 'pr-10' : ''} ${className}`}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={actualState === 'error' ? 'true' : undefined}\n {...props}\n />\n\n {/* Right Icon */}\n {actualIconRight &&\n (shouldShowPasswordToggle ? (\n <button\n type=\"button\"\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer border-0 bg-transparent p-0\"\n onClick={togglePasswordVisibility}\n aria-label={ariaLabel}\n >\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center hover:text-text-600 transition-colors`}\n >\n {actualIconRight}\n </span>\n </button>\n ) : (\n <div className=\"absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {actualIconRight}\n </span>\n </div>\n ))}\n </div>\n\n {/* Helper Text or Error Message */}\n <div className=\"mt-1.5 gap-1.5\">\n {helperText && <p className=\"text-sm text-text-500\">{helperText}</p>}\n {errorMessage && (\n <p className=\"flex gap-1 items-center text-sm text-indicator-error\">\n <WarningCircle size={16} /> {errorMessage}\n </p>\n )}\n </div>\n </div>\n );\n }\n);\n\nexport default Input;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/Input/Input.tsx"],"sourcesContent":["import { WarningCircle, Eye, EyeSlash } from 'phosphor-react';\nimport {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n useMemo,\n} from 'react';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n large: 'text-lg',\n 'extra-large': 'text-xl',\n} as const;\n\n/**\n * Lookup table for state classes\n */\nconst STATE_CLASSES = {\n default:\n 'border-border-300 placeholder:text-text-600 hover:border-border-400',\n error: 'border-2 border-indicator-error placeholder:text-text-600',\n disabled:\n 'border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40',\n 'read-only':\n 'border-transparent !text-text-600 cursor-default focus:outline-none bg-transparent',\n} as const;\n\n/**\n * Lookup table for variant classes\n */\nconst VARIANT_CLASSES = {\n outlined: 'border rounded-lg',\n underlined:\n 'border-0 border-b rounded-none bg-transparent focus:outline-none focus:border-primary-950 focus:border-b-2',\n rounded: 'border rounded-full',\n} as const;\n\n/**\n * Input component props interface\n */\ntype InputProps = {\n /** Label text displayed above the input */\n label?: string;\n /** Helper text displayed below the input */\n helperText?: string;\n /** Error message displayed below the input */\n errorMessage?: string;\n /** Size of the input */\n size?: 'small' | 'medium' | 'large' | 'extra-large';\n /** Visual variant of the input */\n variant?: 'outlined' | 'underlined' | 'rounded';\n /** Current state of the input */\n state?: 'default' | 'error' | 'disabled' | 'read-only';\n /** Icon to display on the left side of the input */\n iconLeft?: ReactNode;\n /** Icon to display on the right side of the input */\n iconRight?: ReactNode;\n /** Additional CSS classes to apply to the input */\n className?: string;\n /** Additional CSS classes to apply to the container */\n containerClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>;\n\n/**\n * Input component for Analytica Ensino platforms\n *\n * A flexible input component with multiple sizes, states, and support for icons.\n * Includes label, helper text, and error message functionality.\n * Features automatic password visibility toggle for password inputs.\n *\n * @param label - Optional label text displayed above the input\n * @param helperText - Optional helper text displayed below the input\n * @param errorMessage - Optional error message displayed below the input\n * @param size - The size variant (small, medium, large, extra-large)\n * @param variant - The visual variant (outlined, underlined, rounded)\n * @param state - The current state (default, error, disabled, read-only)\n * @param iconLeft - Optional icon displayed on the left side\n * @param iconRight - Optional icon displayed on the right side (overridden by password toggle for password inputs)\n * @param type - Input type (text, email, password, etc.) - password type automatically includes show/hide toggle\n * @param className - Additional CSS classes for the input\n * @param containerClassName - Additional CSS classes for the container\n * @param props - All other standard input HTML attributes\n * @returns A styled input element with optional label and helper text\n *\n * @example\n * ```tsx\n * // Basic input\n * <Input\n * label=\"Email\"\n * placeholder=\"Digite seu email\"\n * helperText=\"Usaremos apenas para contato\"\n * size=\"medium\"\n * variant=\"outlined\"\n * state=\"default\"\n * />\n *\n * // Password input with automatic toggle\n * <Input\n * label=\"Senha\"\n * type=\"password\"\n * placeholder=\"Digite sua senha\"\n * helperText=\"Clique no olho para mostrar/ocultar\"\n * />\n * ```\n */\n// Helper functions to reduce cognitive complexity\nconst getActualState = (\n disabled?: boolean,\n readOnly?: boolean,\n errorMessage?: string,\n state?: string\n): keyof typeof STATE_CLASSES => {\n if (disabled) return 'disabled';\n if (readOnly) return 'read-only';\n if (errorMessage) return 'error';\n return (state as keyof typeof STATE_CLASSES) || 'default';\n};\n\nconst getIconSize = (size: string) => {\n const iconSizeClasses = {\n small: 'w-4 h-4',\n medium: 'w-5 h-5',\n large: 'w-6 h-6',\n 'extra-large': 'w-7 h-7',\n };\n return (\n iconSizeClasses[size as keyof typeof iconSizeClasses] ||\n iconSizeClasses.medium\n );\n};\n\nconst getPasswordToggleConfig = (\n type?: string,\n disabled?: boolean,\n readOnly?: boolean,\n showPassword?: boolean,\n iconRight?: ReactNode\n) => {\n const isPasswordType = type === 'password';\n const shouldShowPasswordToggle = isPasswordType && !disabled && !readOnly;\n\n let actualIconRight = iconRight;\n let ariaLabel: string | undefined;\n\n if (shouldShowPasswordToggle) {\n actualIconRight = showPassword ? <EyeSlash /> : <Eye />;\n ariaLabel = showPassword ? 'Ocultar senha' : 'Mostrar senha';\n }\n\n return { shouldShowPasswordToggle, actualIconRight, ariaLabel };\n};\n\nconst getCombinedClasses = (\n actualState: keyof typeof STATE_CLASSES,\n variant: keyof typeof VARIANT_CLASSES\n) => {\n const stateClasses = STATE_CLASSES[actualState];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Special case: error state with underlined variant\n if (actualState === 'error' && variant === 'underlined') {\n return 'border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600';\n }\n\n // Special case: read-only state with underlined variant\n if (actualState === 'read-only' && variant === 'underlined') {\n return 'border-0 border-b-0 rounded-none bg-transparent focus:outline-none !text-text-900 cursor-default';\n }\n\n return `${stateClasses} ${variantClasses}`;\n};\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n label,\n helperText,\n errorMessage,\n size = 'medium',\n variant = 'outlined',\n state = 'default',\n iconLeft,\n iconRight,\n className = '',\n containerClassName = '',\n disabled,\n readOnly,\n id,\n type = 'text',\n ...props\n },\n ref\n ) => {\n // State for password visibility toggle\n const [showPassword, setShowPassword] = useState(false);\n const isPasswordType = type === 'password';\n const actualType = isPasswordType && showPassword ? 'text' : type;\n const actualState = getActualState(disabled, readOnly, errorMessage, state);\n\n // Get classes from lookup tables\n const sizeClasses = SIZE_CLASSES[size];\n const combinedClasses = useMemo(\n () => getCombinedClasses(actualState, variant),\n [actualState, variant]\n );\n const iconSize = getIconSize(size);\n\n const baseClasses = `bg-background w-full py-2 ${\n actualState === 'read-only' ? 'px-0' : 'px-3'\n } font-normal text-text-900 focus:outline-primary-950`;\n\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `input-${generatedId}`;\n\n // Handle password visibility toggle\n const togglePasswordVisibility = () => setShowPassword(!showPassword);\n\n // Get password toggle configuration\n const { shouldShowPasswordToggle, actualIconRight, ariaLabel } =\n getPasswordToggleConfig(\n type,\n disabled,\n readOnly,\n showPassword,\n iconRight\n );\n\n return (\n <div className={`${containerClassName}`}>\n {/* Label */}\n {label && (\n <label\n htmlFor={inputId}\n className={`block font-bold text-text-900 mb-1.5 ${sizeClasses}`}\n >\n {label}\n </label>\n )}\n\n {/* Input Container */}\n <div className=\"relative\">\n {/* Left Icon */}\n {iconLeft && (\n <div className=\"absolute left-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {iconLeft}\n </span>\n </div>\n )}\n\n {/* Input Field */}\n <input\n ref={ref}\n id={inputId}\n type={actualType}\n className={`${baseClasses} ${sizeClasses} ${combinedClasses} ${\n iconLeft ? 'pl-10' : ''\n } ${actualIconRight ? 'pr-10' : ''} ${className}`}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={actualState === 'error' ? 'true' : undefined}\n {...props}\n />\n\n {/* Right Icon */}\n {actualIconRight &&\n (shouldShowPasswordToggle ? (\n <button\n type=\"button\"\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer border-0 bg-transparent p-0\"\n onClick={togglePasswordVisibility}\n aria-label={ariaLabel}\n >\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center hover:text-text-600 transition-colors`}\n >\n {actualIconRight}\n </span>\n </button>\n ) : (\n <div className=\"absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none\">\n <span\n className={`${iconSize} text-text-400 flex items-center justify-center`}\n >\n {actualIconRight}\n </span>\n </div>\n ))}\n </div>\n\n {/* Helper Text or Error Message */}\n <div className=\"mt-1.5 gap-1.5\">\n {helperText && <p className=\"text-sm text-text-500\">{helperText}</p>}\n {errorMessage && (\n <p className=\"flex gap-1 items-center text-sm text-indicator-error\">\n <WarningCircle size={16} /> {errorMessage}\n </p>\n )}\n </div>\n </div>\n );\n }\n);\n\nexport default Input;\n"],"mappings":"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","names":[]}