{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "primitives-base-menu",
  "title": "Base Menu",
  "description": "A list of actions in a dropdown, enhanced with keyboard navigation.",
  "dependencies": [
    "motion",
    "@base-ui-components/react"
  ],
  "registryDependencies": [
    "@animate-ui/primitives-effects-highlight",
    "@animate-ui/lib-get-strict-context",
    "@animate-ui/hooks-use-controlled-state",
    "@animate-ui/hooks-use-data-state"
  ],
  "files": [
    {
      "path": "registry/primitives/base/menu/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { Menu as MenuPrimitive } from '@base-ui-components/react/menu';\nimport { AnimatePresence, motion, type HTMLMotionProps } from 'motion/react';\n\nimport {\n  Highlight,\n  HighlightItem,\n  type HighlightItemProps,\n  type HighlightProps,\n} from '@/components/animate-ui/primitives/effects/highlight';\nimport { getStrictContext } from '@/lib/get-strict-context';\nimport { useControlledState } from '@/hooks/use-controlled-state';\nimport { useDataState } from '@/hooks/use-data-state';\n\ntype MenuActiveValueContextType = {\n  highlightedValue: string | null;\n  setHighlightedValue: (value: string | null) => void;\n};\n\ntype MenuContextType = {\n  isOpen: boolean;\n  setIsOpen: MenuProps['onOpenChange'];\n};\n\nconst [MenuActiveValueProvider, useMenuActiveValue] =\n  getStrictContext<MenuActiveValueContextType>('MenuActiveValueContext');\nconst [MenuProvider, useMenu] =\n  getStrictContext<MenuContextType>('MenuContext');\n\ntype MenuProps = React.ComponentProps<typeof MenuPrimitive.Root>;\n\nfunction Menu(props: MenuProps) {\n  const [isOpen, setIsOpen] = useControlledState({\n    value: props?.open,\n    defaultValue: props?.defaultOpen,\n    onChange: props?.onOpenChange,\n  });\n  const [highlightedValue, setHighlightedValue] = React.useState<string | null>(\n    null,\n  );\n\n  return (\n    <MenuActiveValueProvider value={{ highlightedValue, setHighlightedValue }}>\n      <MenuProvider value={{ isOpen, setIsOpen }}>\n        <MenuPrimitive.Root\n          data-slot=\"menu\"\n          {...props}\n          onOpenChange={setIsOpen}\n        />\n      </MenuProvider>\n    </MenuActiveValueProvider>\n  );\n}\n\ntype MenuTriggerProps = React.ComponentProps<typeof MenuPrimitive.Trigger>;\n\nfunction MenuTrigger(props: MenuTriggerProps) {\n  return <MenuPrimitive.Trigger data-slot=\"menu-trigger\" {...props} />;\n}\n\ntype MenuPortalProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.Portal>,\n  'keepMounted'\n>;\n\nfunction MenuPortal(props: MenuPortalProps) {\n  const { isOpen } = useMenu();\n\n  return (\n    <AnimatePresence>\n      {isOpen && (\n        <MenuPrimitive.Portal keepMounted data-slot=\"menu-portal\" {...props} />\n      )}\n    </AnimatePresence>\n  );\n}\n\ntype MenuGroupProps = React.ComponentProps<typeof MenuPrimitive.Group>;\n\nfunction MenuGroup(props: MenuGroupProps) {\n  return <MenuPrimitive.Group data-slot=\"menu-group\" {...props} />;\n}\n\ntype MenuGroupLabelProps = React.ComponentProps<\n  typeof MenuPrimitive.GroupLabel\n>;\n\nfunction MenuGroupLabel(props: MenuGroupLabelProps) {\n  return <MenuPrimitive.GroupLabel data-slot=\"menu-group-label\" {...props} />;\n}\n\ntype MenuSubmenuProps = React.ComponentProps<typeof MenuPrimitive.SubmenuRoot>;\n\nfunction MenuSubmenu(props: MenuSubmenuProps) {\n  const [isOpen, setIsOpen] = useControlledState({\n    value: props?.open,\n    defaultValue: props?.defaultOpen,\n    onChange: props?.onOpenChange,\n  });\n\n  return (\n    <MenuProvider value={{ isOpen, setIsOpen }}>\n      <MenuPrimitive.SubmenuRoot\n        data-slot=\"menu-submenu\"\n        {...props}\n        onOpenChange={setIsOpen}\n      />\n    </MenuProvider>\n  );\n}\n\ntype MenuSubmenuTriggerProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.SubmenuTrigger>,\n  'render'\n> &\n  HTMLMotionProps<'div'> & {\n    disabled?: boolean;\n  };\n\nfunction MenuSubmenuTrigger({\n  label,\n  id,\n  nativeButton,\n  ...props\n}: MenuSubmenuTriggerProps) {\n  const { setHighlightedValue } = useMenuActiveValue();\n  const [, highlightedRef] = useDataState<HTMLDivElement>(\n    'highlighted',\n    undefined,\n    (value) => {\n      if (value === true) {\n        const el = highlightedRef.current;\n        const v = el?.dataset.value || el?.id || null;\n        if (v) setHighlightedValue(v);\n      }\n    },\n  );\n\n  return (\n    <MenuPrimitive.SubmenuTrigger\n      ref={highlightedRef}\n      label={label}\n      id={id}\n      nativeButton={nativeButton}\n      data-slot=\"menu-submenu-trigger\"\n      {...props}\n    />\n  );\n}\n\ntype MenuHighlightProps = Omit<\n  HighlightProps,\n  'controlledItems' | 'enabled' | 'hover'\n> & {\n  animateOnHover?: boolean;\n};\n\nfunction MenuHighlight({\n  transition = { type: 'spring', stiffness: 350, damping: 35 },\n  ...props\n}: MenuHighlightProps) {\n  const { highlightedValue } = useMenuActiveValue();\n\n  return (\n    <Highlight\n      data-slot=\"menu-highlight\"\n      click={false}\n      controlledItems\n      transition={transition}\n      value={highlightedValue}\n      {...props}\n    />\n  );\n}\n\ntype MenuHighlightItemProps = HighlightItemProps;\n\nfunction MenuHighlightItem(props: MenuHighlightItemProps) {\n  return <HighlightItem data-slot=\"menu-highlight-item\" {...props} />;\n}\n\ntype MenuPositionerProps = React.ComponentProps<\n  typeof MenuPrimitive.Positioner\n>;\n\nfunction MenuPositioner(props: MenuPositionerProps) {\n  return <MenuPrimitive.Positioner data-slot=\"menu-positioner\" {...props} />;\n}\n\ntype MenuPopupProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.Popup>,\n  'render'\n> &\n  HTMLMotionProps<'div'>;\n\nfunction MenuPopup({\n  finalFocus,\n  id,\n  transition = { duration: 0.2 },\n  style,\n  ...props\n}: MenuPopupProps) {\n  return (\n    <MenuPrimitive.Popup\n      finalFocus={finalFocus}\n      id={id}\n      render={\n        <motion.div\n          key=\"menu-popup\"\n          data-slot=\"menu-popup\"\n          initial={{ opacity: 0, scale: 0.95 }}\n          animate={{ opacity: 1, scale: 1 }}\n          exit={{ opacity: 0, scale: 0.95 }}\n          transition={transition}\n          style={{ willChange: 'opacity, transform', ...style }}\n          {...props}\n        />\n      }\n    />\n  );\n}\n\ntype MenuItemProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.Item>,\n  'render'\n> &\n  HTMLMotionProps<'div'>;\n\nfunction MenuItem({\n  disabled,\n  label,\n  closeOnClick,\n  nativeButton,\n  id,\n  ...props\n}: MenuItemProps) {\n  const { setHighlightedValue } = useMenuActiveValue();\n  const [, highlightedRef] = useDataState<HTMLDivElement>(\n    'highlighted',\n    undefined,\n    (value) => {\n      if (value === true) {\n        const el = highlightedRef.current;\n        const v = el?.dataset.value || el?.id || null;\n        if (v) setHighlightedValue(v);\n      }\n    },\n  );\n\n  return (\n    <MenuPrimitive.Item\n      ref={highlightedRef}\n      label={label}\n      closeOnClick={closeOnClick}\n      nativeButton={nativeButton}\n      disabled={disabled}\n      id={id}\n      data-slot=\"menu-item\"\n      {...props}\n    />\n  );\n}\n\ntype MenuCheckboxItemProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.CheckboxItem>,\n  'render'\n>;\n\nfunction MenuCheckboxItem({\n  label,\n  defaultChecked,\n  checked,\n  onCheckedChange,\n  disabled,\n  closeOnClick,\n  nativeButton,\n  id,\n  ...props\n}: MenuCheckboxItemProps) {\n  const { setHighlightedValue } = useMenuActiveValue();\n  const [, highlightedRef] = useDataState<HTMLDivElement>(\n    'highlighted',\n    undefined,\n    (value) => {\n      if (value === true) {\n        const el = highlightedRef.current;\n        const v = el?.dataset.value || el?.id || null;\n        if (v) setHighlightedValue(v);\n      }\n    },\n  );\n  return (\n    <MenuPrimitive.CheckboxItem\n      ref={highlightedRef}\n      label={label}\n      checked={checked}\n      defaultChecked={defaultChecked}\n      onCheckedChange={onCheckedChange}\n      disabled={disabled}\n      closeOnClick={closeOnClick}\n      nativeButton={nativeButton}\n      id={id}\n      data-slot=\"menu-checkbox-item\"\n      {...props}\n    />\n  );\n}\n\ntype MenuCheckboxItemIndicatorProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.CheckboxItemIndicator>,\n  'render'\n> &\n  HTMLMotionProps<'div'>;\n\nfunction MenuCheckboxItemIndicator({\n  keepMounted,\n  ...props\n}: MenuCheckboxItemIndicatorProps) {\n  return (\n    <MenuPrimitive.CheckboxItemIndicator\n      data-slot=\"menu-checkbox-item-indicator\"\n      keepMounted={keepMounted}\n      render={\n        <motion.div data-slot=\"menu-checkbox-item-indicator\" {...props} />\n      }\n    />\n  );\n}\n\ntype MenuRadioGroupProps = React.ComponentProps<\n  typeof MenuPrimitive.RadioGroup\n>;\n\nfunction MenuRadioGroup(props: MenuRadioGroupProps) {\n  return <MenuPrimitive.RadioGroup data-slot=\"menu-radio-group\" {...props} />;\n}\n\ntype MenuRadioItemProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.RadioItem>,\n  'render'\n>;\n\nfunction MenuRadioItem({\n  value,\n  disabled,\n  label,\n  closeOnClick,\n  nativeButton,\n  id,\n  ...props\n}: MenuRadioItemProps) {\n  const { setHighlightedValue } = useMenuActiveValue();\n  const [, highlightedRef] = useDataState<HTMLDivElement>(\n    'highlighted',\n    undefined,\n    (value) => {\n      if (value === true) {\n        const el = highlightedRef.current;\n        const v = el?.dataset.value || el?.id || null;\n        if (v) setHighlightedValue(v);\n      }\n    },\n  );\n  return (\n    <MenuPrimitive.RadioItem\n      ref={highlightedRef}\n      value={value}\n      disabled={disabled}\n      label={label}\n      closeOnClick={closeOnClick}\n      nativeButton={nativeButton}\n      id={id}\n      data-slot=\"menu-radio-item\"\n      {...props}\n    />\n  );\n}\n\ntype MenuRadioItemIndicatorProps = Omit<\n  React.ComponentProps<typeof MenuPrimitive.RadioItemIndicator>,\n  'render'\n> &\n  HTMLMotionProps<'div'>;\n\nfunction MenuRadioItemIndicator({\n  keepMounted,\n  ...props\n}: MenuRadioItemIndicatorProps) {\n  return (\n    <MenuPrimitive.RadioItemIndicator\n      data-slot=\"menu-radio-item-indicator\"\n      keepMounted={keepMounted}\n      render={<motion.div data-slot=\"menu-radio-item-indicator\" {...props} />}\n    />\n  );\n}\n\ntype MenuShortcutProps = React.ComponentProps<'span'>;\n\nfunction MenuShortcut(props: MenuShortcutProps) {\n  return <span data-slot=\"menu-shortcut\" {...props} />;\n}\n\ntype MenuArrowProps = React.ComponentProps<typeof MenuPrimitive.Arrow>;\n\nfunction MenuArrow(props: MenuArrowProps) {\n  return <MenuPrimitive.Arrow data-slot=\"menu-arrow\" {...props} />;\n}\n\ntype MenuSeparatorProps = React.ComponentProps<typeof MenuPrimitive.Separator>;\n\nfunction MenuSeparator(props: MenuSeparatorProps) {\n  return <MenuPrimitive.Separator data-slot=\"menu-separator\" {...props} />;\n}\n\nexport {\n  Menu,\n  MenuTrigger,\n  MenuPortal,\n  MenuPositioner,\n  MenuPopup,\n  MenuArrow,\n  MenuItem,\n  MenuCheckboxItem,\n  MenuCheckboxItemIndicator,\n  MenuRadioGroup,\n  MenuRadioItem,\n  MenuRadioItemIndicator,\n  MenuGroup,\n  MenuGroupLabel,\n  MenuSeparator,\n  MenuShortcut,\n  MenuHighlight,\n  MenuHighlightItem,\n  MenuSubmenu,\n  MenuSubmenuTrigger,\n  useMenuActiveValue,\n  useMenu,\n  type MenuProps,\n  type MenuTriggerProps,\n  type MenuPortalProps,\n  type MenuPositionerProps,\n  type MenuPopupProps,\n  type MenuArrowProps,\n  type MenuItemProps,\n  type MenuCheckboxItemProps,\n  type MenuCheckboxItemIndicatorProps,\n  type MenuRadioItemProps,\n  type MenuRadioItemIndicatorProps,\n  type MenuRadioGroupProps,\n  type MenuGroupProps,\n  type MenuGroupLabelProps,\n  type MenuSeparatorProps,\n  type MenuShortcutProps,\n  type MenuHighlightProps,\n  type MenuHighlightItemProps,\n  type MenuSubmenuProps,\n  type MenuSubmenuTriggerProps,\n  type MenuActiveValueContextType,\n  type MenuContextType,\n};\n",
      "type": "registry:ui",
      "target": "components/animate-ui/primitives/base/menu.tsx"
    }
  ],
  "type": "registry:ui"
}