analytica-frontend-lib 1.0.52 → 1.0.54

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.
@@ -224,7 +224,7 @@ var MenuLabel = forwardRef(({ className, inset, store: _store, ...props }, ref)
224
224
  );
225
225
  });
226
226
  MenuLabel.displayName = "MenuLabel";
227
- var MenuContent = forwardRef(
227
+ var DropdownMenuContent = forwardRef(
228
228
  ({
229
229
  className,
230
230
  align = "start",
@@ -277,7 +277,7 @@ var MenuContent = forwardRef(
277
277
  );
278
278
  }
279
279
  );
280
- MenuContent.displayName = "MenuContent";
280
+ DropdownMenuContent.displayName = "DropdownMenuContent";
281
281
  var DropdownMenuItem = forwardRef(
282
282
  ({
283
283
  className,
@@ -439,10 +439,10 @@ var ProfileMenuFooter = ({
439
439
  ProfileMenuFooter.displayName = "ProfileMenuFooter";
440
440
  var DropdownMenu_default = DropdownMenu;
441
441
  export {
442
+ DropdownMenuContent,
442
443
  DropdownMenuItem,
443
444
  DropdownMenuSeparator,
444
445
  DropdownMenuTrigger,
445
- MenuContent,
446
446
  MenuLabel,
447
447
  ProfileMenuFooter,
448
448
  ProfileMenuHeader,
@@ -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 = ({\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"]}
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 DropdownMenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile';\n sideOffset?: number;\n store?: DropdownStoreApi;\n }\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);\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n }\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 DropdownMenuContent,\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"]}
@@ -3,25 +3,31 @@ import * as react from 'react';
3
3
  import { HTMLAttributes, ReactNode } from 'react';
4
4
  import { StoreApi } from 'zustand';
5
5
 
6
+ type MenuVariant = 'menu' | 'menu2' | 'breadcrumb';
6
7
  interface MenuStore {
7
8
  value: string;
8
9
  setValue: (value: string) => void;
9
10
  }
10
11
  type MenuStoreApi = StoreApi<MenuStore>;
11
12
  declare const useMenuStore: (externalStore?: MenuStoreApi) => MenuStoreApi;
12
- interface MenuProps extends HTMLAttributes<HTMLUListElement> {
13
+ interface MenuProps extends HTMLAttributes<HTMLDivElement> {
13
14
  children: ReactNode;
14
15
  defaultValue: string;
15
16
  value?: string;
16
- variant?: 'menu' | 'menu2' | 'breadcrumb';
17
+ variant?: MenuVariant;
17
18
  onValueChange?: (value: string) => void;
18
19
  }
19
- declare const Menu: react.ForwardRefExoticComponent<MenuProps & react.RefAttributes<HTMLUListElement>>;
20
+ declare const Menu: react.ForwardRefExoticComponent<MenuProps & react.RefAttributes<HTMLDivElement>>;
21
+ interface MenuContentProps extends HTMLAttributes<HTMLUListElement> {
22
+ children: ReactNode;
23
+ variant?: MenuVariant;
24
+ }
25
+ declare const MenuContent: react.ForwardRefExoticComponent<MenuContentProps & react.RefAttributes<HTMLUListElement>>;
20
26
  interface MenuItemProps extends HTMLAttributes<HTMLLIElement> {
21
27
  value: string;
22
28
  disabled?: boolean;
23
29
  store?: MenuStoreApi;
24
- variant?: 'menu' | 'menu2' | 'breadcrumb';
30
+ variant?: MenuVariant;
25
31
  }
26
32
  declare const MenuItem: react.ForwardRefExoticComponent<MenuItemProps & react.RefAttributes<HTMLLIElement>>;
27
33
  declare const MenuItemIcon: ({ className, icon, ...props }: HTMLAttributes<HTMLSpanElement> & {
@@ -30,7 +36,7 @@ declare const MenuItemIcon: ({ className, icon, ...props }: HTMLAttributes<HTMLS
30
36
  declare const MenuSeparator: react.ForwardRefExoticComponent<HTMLAttributes<HTMLLIElement> & react.RefAttributes<HTMLLIElement>>;
31
37
  declare const internalScroll: (container: HTMLUListElement | null, direction: "left" | "right") => void;
32
38
  declare const internalCheckScroll: (container: HTMLUListElement | null, setShowLeftArrow: (v: boolean) => void, setShowRightArrow: (v: boolean) => void) => void;
33
- interface MenuOverflowProps extends HTMLAttributes<HTMLUListElement> {
39
+ interface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {
34
40
  children: ReactNode;
35
41
  defaultValue: string;
36
42
  value?: string;
@@ -38,4 +44,4 @@ interface MenuOverflowProps extends HTMLAttributes<HTMLUListElement> {
38
44
  }
39
45
  declare const MenuOverflow: ({ children, className, defaultValue, value, onValueChange, ...props }: MenuOverflowProps) => react_jsx_runtime.JSX.Element;
40
46
 
41
- export { Menu, MenuItem, MenuItemIcon, MenuOverflow, MenuSeparator, Menu as default, internalCheckScroll, internalScroll, useMenuStore };
47
+ export { Menu, MenuContent, MenuItem, MenuItemIcon, MenuOverflow, MenuSeparator, Menu as default, internalCheckScroll, internalScroll, useMenuStore };
@@ -3,25 +3,31 @@ import * as react from 'react';
3
3
  import { HTMLAttributes, ReactNode } from 'react';
4
4
  import { StoreApi } from 'zustand';
5
5
 
6
+ type MenuVariant = 'menu' | 'menu2' | 'breadcrumb';
6
7
  interface MenuStore {
7
8
  value: string;
8
9
  setValue: (value: string) => void;
9
10
  }
10
11
  type MenuStoreApi = StoreApi<MenuStore>;
11
12
  declare const useMenuStore: (externalStore?: MenuStoreApi) => MenuStoreApi;
12
- interface MenuProps extends HTMLAttributes<HTMLUListElement> {
13
+ interface MenuProps extends HTMLAttributes<HTMLDivElement> {
13
14
  children: ReactNode;
14
15
  defaultValue: string;
15
16
  value?: string;
16
- variant?: 'menu' | 'menu2' | 'breadcrumb';
17
+ variant?: MenuVariant;
17
18
  onValueChange?: (value: string) => void;
18
19
  }
19
- declare const Menu: react.ForwardRefExoticComponent<MenuProps & react.RefAttributes<HTMLUListElement>>;
20
+ declare const Menu: react.ForwardRefExoticComponent<MenuProps & react.RefAttributes<HTMLDivElement>>;
21
+ interface MenuContentProps extends HTMLAttributes<HTMLUListElement> {
22
+ children: ReactNode;
23
+ variant?: MenuVariant;
24
+ }
25
+ declare const MenuContent: react.ForwardRefExoticComponent<MenuContentProps & react.RefAttributes<HTMLUListElement>>;
20
26
  interface MenuItemProps extends HTMLAttributes<HTMLLIElement> {
21
27
  value: string;
22
28
  disabled?: boolean;
23
29
  store?: MenuStoreApi;
24
- variant?: 'menu' | 'menu2' | 'breadcrumb';
30
+ variant?: MenuVariant;
25
31
  }
26
32
  declare const MenuItem: react.ForwardRefExoticComponent<MenuItemProps & react.RefAttributes<HTMLLIElement>>;
27
33
  declare const MenuItemIcon: ({ className, icon, ...props }: HTMLAttributes<HTMLSpanElement> & {
@@ -30,7 +36,7 @@ declare const MenuItemIcon: ({ className, icon, ...props }: HTMLAttributes<HTMLS
30
36
  declare const MenuSeparator: react.ForwardRefExoticComponent<HTMLAttributes<HTMLLIElement> & react.RefAttributes<HTMLLIElement>>;
31
37
  declare const internalScroll: (container: HTMLUListElement | null, direction: "left" | "right") => void;
32
38
  declare const internalCheckScroll: (container: HTMLUListElement | null, setShowLeftArrow: (v: boolean) => void, setShowRightArrow: (v: boolean) => void) => void;
33
- interface MenuOverflowProps extends HTMLAttributes<HTMLUListElement> {
39
+ interface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {
34
40
  children: ReactNode;
35
41
  defaultValue: string;
36
42
  value?: string;
@@ -38,4 +44,4 @@ interface MenuOverflowProps extends HTMLAttributes<HTMLUListElement> {
38
44
  }
39
45
  declare const MenuOverflow: ({ children, className, defaultValue, value, onValueChange, ...props }: MenuOverflowProps) => react_jsx_runtime.JSX.Element;
40
46
 
41
- export { Menu, MenuItem, MenuItemIcon, MenuOverflow, MenuSeparator, Menu as default, internalCheckScroll, internalScroll, useMenuStore };
47
+ export { Menu, MenuContent, MenuItem, MenuItemIcon, MenuOverflow, MenuSeparator, Menu as default, internalCheckScroll, internalScroll, useMenuStore };
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var Menu_exports = {};
22
22
  __export(Menu_exports, {
23
23
  Menu: () => Menu,
24
+ MenuContent: () => MenuContent,
24
25
  MenuItem: () => MenuItem,
25
26
  MenuItemIcon: () => MenuItemIcon,
26
27
  MenuOverflow: () => MenuOverflow,
@@ -45,7 +46,7 @@ var useMenuStore = (externalStore) => {
45
46
  };
46
47
  var VARIANT_CLASSES = {
47
48
  menu: "bg-background shadow-soft-shadow-1",
48
- menu2: "overflow-x-auto scroll-smooth",
49
+ menu2: "",
49
50
  breadcrumb: ""
50
51
  };
51
52
  var Menu = (0, import_react.forwardRef)(
@@ -68,10 +69,10 @@ var Menu = (0, import_react.forwardRef)(
68
69
  (0, import_react.useEffect)(() => {
69
70
  onValueChange?.(value);
70
71
  }, [value, onValueChange]);
71
- const baseClasses = "w-full flex flex-row items-center gap-2 py-2 px-6";
72
+ const baseClasses = "w-full py-2 px-6 flex flex-row items-center justify-center";
72
73
  const variantClasses = VARIANT_CLASSES[variant];
73
74
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
74
- "ul",
75
+ "div",
75
76
  {
76
77
  ref,
77
78
  className: `
@@ -79,7 +80,6 @@ var Menu = (0, import_react.forwardRef)(
79
80
  ${variantClasses}
80
81
  ${className ?? ""}
81
82
  `,
82
- style: variant === "menu2" ? { scrollbarWidth: "none", msOverflowStyle: "none" } : void 0,
83
83
  ...props,
84
84
  children: injectStore(children, store)
85
85
  }
@@ -87,6 +87,27 @@ var Menu = (0, import_react.forwardRef)(
87
87
  }
88
88
  );
89
89
  Menu.displayName = "Menu";
90
+ var MenuContent = (0, import_react.forwardRef)(
91
+ ({ className, children, variant = "menu", ...props }, ref) => {
92
+ const baseClasses = "w-full flex flex-row items-center gap-2";
93
+ const variantClasses = variant === "menu2" ? "overflow-x-auto scroll-smooth" : "";
94
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
95
+ "ul",
96
+ {
97
+ ref,
98
+ className: `
99
+ ${baseClasses}
100
+ ${variantClasses}
101
+ ${className ?? ""}
102
+ `,
103
+ style: variant === "menu2" ? { scrollbarWidth: "none", msOverflowStyle: "none" } : void 0,
104
+ ...props,
105
+ children
106
+ }
107
+ );
108
+ }
109
+ );
110
+ MenuContent.displayName = "MenuContent";
90
111
  var MenuItem = (0, import_react.forwardRef)(
91
112
  ({
92
113
  className,
@@ -251,7 +272,7 @@ var MenuOverflow = ({
251
272
  "button",
252
273
  {
253
274
  onClick: () => internalScroll(containerRef.current, "left"),
254
- className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md",
275
+ className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer",
255
276
  "data-testid": "scroll-left-button",
256
277
  children: [
257
278
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_phosphor_react.CaretLeft, { size: 16 }),
@@ -262,20 +283,19 @@ var MenuOverflow = ({
262
283
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
263
284
  Menu,
264
285
  {
265
- ref: containerRef,
266
- variant: "menu2",
267
286
  defaultValue,
268
287
  onValueChange,
269
288
  value,
289
+ variant: "menu2",
270
290
  ...props,
271
- children
291
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuContent, { ref: containerRef, variant: "menu2", children })
272
292
  }
273
293
  ),
274
294
  showRightArrow && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
275
295
  "button",
276
296
  {
277
297
  onClick: () => internalScroll(containerRef.current, "right"),
278
- className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md",
298
+ className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer",
279
299
  "data-testid": "scroll-right-button",
280
300
  children: [
281
301
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_phosphor_react.CaretRight, { size: 16 }),
@@ -300,6 +320,7 @@ var Menu_default = Menu;
300
320
  // Annotate the CommonJS export names for ESM import in node:
301
321
  0 && (module.exports = {
302
322
  Menu,
323
+ MenuContent,
303
324
  MenuItem,
304
325
  MenuItemIcon,
305
326
  MenuOverflow,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: 'overflow-x-auto scroll-smooth',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLUListElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses = 'w-full flex flex-row items-center gap-2 py-2 px-6';\n\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {injectStore(children, store)}\n </ul>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n onMouseDown: (e: MouseEvent<HTMLLIElement>) => {\n e.preventDefault();\n },\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs \n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-primary-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit\n ${selectedValue === value ? 'border-b-primary-950' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n ref={containerRef}\n variant=\"menu2\"\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n {...props}\n >\n {children}\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport { Menu, MenuItem, MenuSeparator, MenuOverflow, MenuItemIcon };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ntype MenuVariant = 'menu' | 'menu2' | 'breadcrumb';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: MenuVariant;\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: '',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLDivElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses =\n 'w-full py-2 px-6 flex flex-row items-center justify-center';\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuContentProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n variant?: MenuVariant;\n}\n\nconst MenuContent = forwardRef<HTMLUListElement, MenuContentProps>(\n ({ className, children, variant = 'menu', ...props }, ref) => {\n const baseClasses = 'w-full flex flex-row items-center gap-2';\n\n const variantClasses =\n variant === 'menu2' ? 'overflow-x-auto scroll-smooth' : '';\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {children}\n </ul>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: MenuVariant;\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n onMouseDown: (e: MouseEvent<HTMLLIElement>) => {\n e.preventDefault();\n },\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs \n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-primary-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit\n ${selectedValue === value ? 'border-b-primary-950' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n variant=\"menu2\"\n {...props}\n >\n <MenuContent ref={containerRef} variant=\"menu2\">\n {children}\n </MenuContent>\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport {\n Menu,\n MenuContent,\n MenuItem,\n MenuSeparator,\n MenuOverflow,\n MenuItemIcon,\n};\n"],"mappings":"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","names":[]}
@@ -21,7 +21,7 @@ var useMenuStore = (externalStore) => {
21
21
  };
22
22
  var VARIANT_CLASSES = {
23
23
  menu: "bg-background shadow-soft-shadow-1",
24
- menu2: "overflow-x-auto scroll-smooth",
24
+ menu2: "",
25
25
  breadcrumb: ""
26
26
  };
27
27
  var Menu = forwardRef(
@@ -44,10 +44,10 @@ var Menu = forwardRef(
44
44
  useEffect(() => {
45
45
  onValueChange?.(value);
46
46
  }, [value, onValueChange]);
47
- const baseClasses = "w-full flex flex-row items-center gap-2 py-2 px-6";
47
+ const baseClasses = "w-full py-2 px-6 flex flex-row items-center justify-center";
48
48
  const variantClasses = VARIANT_CLASSES[variant];
49
49
  return /* @__PURE__ */ jsx(
50
- "ul",
50
+ "div",
51
51
  {
52
52
  ref,
53
53
  className: `
@@ -55,7 +55,6 @@ var Menu = forwardRef(
55
55
  ${variantClasses}
56
56
  ${className ?? ""}
57
57
  `,
58
- style: variant === "menu2" ? { scrollbarWidth: "none", msOverflowStyle: "none" } : void 0,
59
58
  ...props,
60
59
  children: injectStore(children, store)
61
60
  }
@@ -63,6 +62,27 @@ var Menu = forwardRef(
63
62
  }
64
63
  );
65
64
  Menu.displayName = "Menu";
65
+ var MenuContent = forwardRef(
66
+ ({ className, children, variant = "menu", ...props }, ref) => {
67
+ const baseClasses = "w-full flex flex-row items-center gap-2";
68
+ const variantClasses = variant === "menu2" ? "overflow-x-auto scroll-smooth" : "";
69
+ return /* @__PURE__ */ jsx(
70
+ "ul",
71
+ {
72
+ ref,
73
+ className: `
74
+ ${baseClasses}
75
+ ${variantClasses}
76
+ ${className ?? ""}
77
+ `,
78
+ style: variant === "menu2" ? { scrollbarWidth: "none", msOverflowStyle: "none" } : void 0,
79
+ ...props,
80
+ children
81
+ }
82
+ );
83
+ }
84
+ );
85
+ MenuContent.displayName = "MenuContent";
66
86
  var MenuItem = forwardRef(
67
87
  ({
68
88
  className,
@@ -227,7 +247,7 @@ var MenuOverflow = ({
227
247
  "button",
228
248
  {
229
249
  onClick: () => internalScroll(containerRef.current, "left"),
230
- className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md",
250
+ className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer",
231
251
  "data-testid": "scroll-left-button",
232
252
  children: [
233
253
  /* @__PURE__ */ jsx(CaretLeft, { size: 16 }),
@@ -238,20 +258,19 @@ var MenuOverflow = ({
238
258
  /* @__PURE__ */ jsx(
239
259
  Menu,
240
260
  {
241
- ref: containerRef,
242
- variant: "menu2",
243
261
  defaultValue,
244
262
  onValueChange,
245
263
  value,
264
+ variant: "menu2",
246
265
  ...props,
247
- children
266
+ children: /* @__PURE__ */ jsx(MenuContent, { ref: containerRef, variant: "menu2", children })
248
267
  }
249
268
  ),
250
269
  showRightArrow && /* @__PURE__ */ jsxs(
251
270
  "button",
252
271
  {
253
272
  onClick: () => internalScroll(containerRef.current, "right"),
254
- className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md",
273
+ className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer",
255
274
  "data-testid": "scroll-right-button",
256
275
  children: [
257
276
  /* @__PURE__ */ jsx(CaretRight, { size: 16 }),
@@ -275,6 +294,7 @@ var injectStore = (children, store) => Children.map(children, (child) => {
275
294
  var Menu_default = Menu;
276
295
  export {
277
296
  Menu,
297
+ MenuContent,
278
298
  MenuItem,
279
299
  MenuItemIcon,
280
300
  MenuOverflow,