{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dropdown-menu",
  "type": "registry:ui",
  "title": "DropdownMenu",
  "description": "React Aria backed action menu primitive with provider-aware portals, controlled open state, menu sections, shortcuts, disabled and destructive items, submenus, Motion-only presence and item feedback, reduced-motion handling, and positioning props.",
  "dependencies": [
    "motion@^12.43.0",
    "react-aria@^3.52.1",
    "react-aria-components@^1.21.1"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json",
    "https://components.dethink.co.uk/r/button.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/dropdown-menu/dropdown-menu.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/dropdown-menu/dropdown-menu.tsx",
      "content": "import {\n  Button as AriaButton,\n  Header as AriaHeader,\n  Keyboard as AriaKeyboard,\n  Menu as AriaMenu,\n  MenuItem as AriaMenuItem,\n  MenuSection as AriaMenuSection,\n  MenuTrigger as AriaMenuTrigger,\n  OverlayTriggerStateContext,\n  Popover as AriaPopover,\n  Separator as AriaSeparator,\n  SubmenuTrigger as AriaSubmenuTrigger,\n  Text as AriaText,\n  type ButtonProps as AriaButtonProps,\n  type HeaderProps as AriaHeaderProps,\n  type MenuItemProps as AriaMenuItemProps,\n  type MenuItemRenderProps as AriaMenuItemRenderProps,\n  type MenuProps as AriaMenuProps,\n  type MenuSectionProps as AriaMenuSectionProps,\n  type MenuTriggerProps as AriaMenuTriggerProps,\n  type PopoverProps as AriaPopoverProps,\n  type SeparatorProps as AriaSeparatorProps,\n  type SubmenuTriggerProps as AriaSubmenuTriggerProps,\n  type TextProps as AriaTextProps,\n} from \"react-aria-components\";\nimport { useIsSSR } from \"react-aria\";\nimport { useHydrated } from \"../../utils/use-hydrated\";\nimport {\n  AnimatePresence,\n  motion,\n  usePresence,\n  useReducedMotion,\n  type Transition,\n} from \"motion/react\";\nimport {\n  Children,\n  createContext,\n  forwardRef,\n  type ForwardedRef,\n  type HTMLAttributes,\n  type ReactElement,\n  type ReactNode,\n  useContext,\n  useMemo,\n} from \"react\";\nimport {\n  Button,\n  buttonClassNames,\n  type ButtonSize,\n  type ButtonVariant,\n} from \"../button\";\nimport {\n  DethinkPortalProvider,\n  useProviderPortalRoot,\n  useScopedOverlayState,\n} from \"../../utils/provider-portal\";\nimport {\n  PositionedOverlayArrow,\n  type PositionedOverlayArrowProps,\n  positionedOverlayArrowClassNames,\n  positionedOverlayDropdownMenuDefaults,\n  positionedOverlayDropdownSubmenuDefaults,\n  positionedOverlaySurfaceClassNames,\n  resolvePositionedOverlayPositionProps,\n} from \"../../utils/positioned-overlay\";\nimport type { PositionedOverlayPositionProps } from \"../../utils/positioned-overlay\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface DropdownMenuProps extends Omit<\n  AriaMenuTriggerProps,\n  \"children\" | \"isOpen\" | \"onOpenChange\"\n> {\n  \"data-slot\"?: string;\n  children?: ReactNode;\n  className?: string;\n  motionPreset?: DropdownMenuMotionPreset;\n  onOpenChange?: (open: boolean) => void;\n  open?: boolean;\n  reducedMotion?: boolean;\n}\n\nexport type DropdownMenuMotionPreset = \"none\" | \"subtle\" | \"standard\";\n\nexport interface DropdownMenuTriggerProps extends Omit<\n  AriaButtonProps,\n  \"children\" | \"className\" | \"isDisabled\"\n> {\n  \"data-slot\"?: string;\n  children?: ReactNode;\n  className?: string;\n  disabled?: boolean;\n  size?: ButtonSize;\n  variant?: ButtonVariant;\n}\n\nexport interface DropdownMenuContentProps<T extends object = object>\n  extends Omit<AriaMenuProps<T>, \"className\">, PositionedOverlayPositionProps {\n  \"data-slot\"?: string;\n  anchorRef?: AriaPopoverProps[\"triggerRef\"];\n  arrowClassName?: string;\n  arrowShapeClassName?: string;\n  className?: string;\n  menuClassName?: string;\n  showArrow?: boolean;\n}\n\nexport interface DropdownMenuSubmenuContentProps<\n  T extends object = object,\n> extends DropdownMenuContentProps<T> {}\n\nexport interface DropdownMenuItemProps<T extends object = object> extends Omit<\n  AriaMenuItemProps<T>,\n  \"children\" | \"className\" | \"isDisabled\"\n> {\n  children?: ReactNode | ((opts: AriaMenuItemRenderProps) => ReactNode);\n  className?: string;\n  destructive?: boolean;\n  disabled?: boolean;\n}\n\nexport interface DropdownMenuSectionProps<\n  T extends object = object,\n> extends Omit<AriaMenuSectionProps<T>, \"className\"> {\n  className?: string;\n}\n\nexport interface DropdownMenuSubmenuProps extends Omit<\n  AriaSubmenuTriggerProps,\n  \"children\"\n> {\n  children: ReactElement[];\n}\n\nexport interface DropdownMenuArrowProps extends PositionedOverlayArrowProps {}\n\nexport interface DropdownMenuLabelProps extends Omit<\n  AriaHeaderProps,\n  \"className\"\n> {\n  className?: string;\n}\n\nexport interface DropdownMenuSeparatorProps extends Omit<\n  AriaSeparatorProps,\n  \"className\"\n> {\n  className?: string;\n}\n\nexport interface DropdownMenuItemIconProps extends HTMLAttributes<HTMLSpanElement> {}\n\nexport interface DropdownMenuItemLabelProps extends Omit<\n  AriaTextProps,\n  \"className\" | \"slot\"\n> {\n  className?: string;\n}\n\nexport interface DropdownMenuItemDescriptionProps extends Omit<\n  AriaTextProps,\n  \"className\" | \"slot\"\n> {\n  className?: string;\n}\n\nexport interface DropdownMenuItemShortcutProps extends HTMLAttributes<HTMLElement> {\n  className?: string;\n}\n\nconst dropdownMenuRootClasses = \"contents\";\n\nconst dropdownMenuPositionerClasses = \"z-50 overflow-visible outline-none\";\n\nconst dropdownMenuContentClasses =\n  \"min-w-[var(--dt-dropdown-menu-min-width,13rem)] max-w-[min(var(--dt-dropdown-menu-max-width,18rem),calc(100vw_-_var(--dt-space-4)))] overflow-visible p-[var(--dt-space-1)]\";\n\nconst dropdownMenuMenuClasses =\n  \"grid max-h-[min(var(--dt-dropdown-menu-max-height,20rem),calc(100dvh_-_var(--dt-space-4)))] gap-0 overflow-auto outline-none\";\n\nconst dropdownMenuItemClasses =\n  \"group/dropdown-menu-item grid min-h-8 cursor-default grid-cols-[1rem_minmax(0,1fr)_auto] items-center gap-[var(--dt-space-2)] rounded-sm px-[var(--dt-space-2)] py-[var(--dt-space-1-5)] text-sm leading-5 text-foreground outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[focus-visible]:ring-2 data-[focus-visible]:ring-ring data-[focused]:bg-muted data-[hovered]:bg-muted data-[open]:bg-muted data-[pressed]:bg-muted/80 data-[selected]:bg-muted data-[destructive=true]:text-destructive data-[destructive=true]:data-[focused]:bg-destructive/10 data-[destructive=true]:data-[hovered]:bg-destructive/10 data-[destructive=true]:data-[pressed]:bg-destructive/15 data-[destructive=true]:data-[selected]:bg-destructive/10 forced-colors:data-[selected]:outline forced-colors:data-[selected]:outline-1 forced-colors:data-[selected]:outline-[Highlight]\";\n\nconst dropdownMenuItemIconClasses =\n  \"flex size-4 shrink-0 items-center justify-center text-muted-foreground group-data-[destructive=true]/dropdown-menu-item:text-destructive [&>svg]:size-4\";\n\nconst dropdownMenuItemLabelClasses = \"min-w-0 truncate\";\n\nconst dropdownMenuItemDescriptionClasses =\n  \"col-start-2 min-w-0 text-xs leading-5 text-muted-foreground group-data-[destructive=true]/dropdown-menu-item:text-destructive/80\";\n\nconst dropdownMenuItemShortcutClasses =\n  \"ms-[var(--dt-space-4)] justify-self-end rounded-sm bg-muted px-[var(--dt-space-1)] py-0.5 font-mono text-[0.6875rem] leading-4 text-muted-foreground\";\n\nconst dropdownMenuLabelClasses =\n  \"px-[var(--dt-space-2)] py-[var(--dt-space-1-5)] text-xs font-semibold uppercase tracking-normal text-muted-foreground\";\n\nconst dropdownMenuSeparatorClasses =\n  \"my-[var(--dt-space-1)] h-px border-0 bg-border\";\n\nconst dropdownMenuSectionClasses = \"grid gap-0\";\n\nconst dropdownMenuSubmenuIconClasses =\n  \"ms-[var(--dt-space-2)] size-4 justify-self-end text-muted-foreground rtl:rotate-180\";\n\ninterface DropdownMenuMotionContextValue {\n  motionPreset: DropdownMenuMotionPreset;\n  reducedMotion: boolean;\n}\n\nconst DropdownMenuMotionContext = createContext<DropdownMenuMotionContextValue>(\n  {\n    motionPreset: \"standard\",\n    reducedMotion: false,\n  },\n);\n\nconst dropdownMenuMotionSettings: Record<\n  DropdownMenuMotionPreset,\n  {\n    distance: number;\n    duration: number;\n    itemFocusScale: number;\n    itemPressScale: number;\n    surfaceScale: number;\n  }\n> = {\n  none: {\n    distance: 0,\n    duration: 0,\n    itemFocusScale: 1,\n    itemPressScale: 1,\n    surfaceScale: 1,\n  },\n  subtle: {\n    distance: 2,\n    duration: 0.12,\n    itemFocusScale: 1.002,\n    itemPressScale: 0.99,\n    surfaceScale: 0.995,\n  },\n  standard: {\n    distance: 4,\n    duration: 0.16,\n    itemFocusScale: 1.004,\n    itemPressScale: 0.985,\n    surfaceScale: 0.985,\n  },\n};\n\nconst dropdownMenuMotionEase = [0.16, 1, 0.3, 1] as const;\n\nfunction getDropdownMenuSurfaceOffset(placement: string, distance: number) {\n  const side = placement.split(\" \")[0];\n\n  switch (side) {\n    case \"top\":\n      return { x: 0, y: distance };\n    case \"left\":\n      return { x: distance, y: 0 };\n    case \"right\":\n      return { x: -distance, y: 0 };\n    default:\n      return { x: 0, y: -distance };\n  }\n}\n\nexport function dropdownMenuClassNames({\n  className,\n}: Pick<DropdownMenuProps, \"className\"> = {}) {\n  return cn(dropdownMenuRootClasses, className);\n}\n\nexport function dropdownMenuTriggerClassNames({\n  className,\n  size = \"md\",\n  variant = \"outline\",\n}: Pick<DropdownMenuTriggerProps, \"className\" | \"size\" | \"variant\"> = {}) {\n  return buttonClassNames({ className, size, variant });\n}\n\nexport function dropdownMenuContentClassNames({\n  className,\n}: Pick<DropdownMenuContentProps, \"className\"> = {}) {\n  return cn(\n    positionedOverlaySurfaceClassNames({ animation: \"none\" }),\n    dropdownMenuContentClasses,\n    className,\n  );\n}\n\nexport function dropdownMenuMenuClassNames({\n  className,\n}: {\n  className?: string;\n} = {}) {\n  return cn(dropdownMenuMenuClasses, className);\n}\n\nexport function dropdownMenuItemClassNames({\n  className,\n}: Pick<DropdownMenuItemProps, \"className\"> = {}) {\n  return cn(dropdownMenuItemClasses, className);\n}\n\nexport function dropdownMenuItemIconClassNames({\n  className,\n}: Pick<DropdownMenuItemIconProps, \"className\"> = {}) {\n  return cn(dropdownMenuItemIconClasses, className);\n}\n\nexport function dropdownMenuItemLabelClassNames({\n  className,\n}: Pick<DropdownMenuItemLabelProps, \"className\"> = {}) {\n  return cn(dropdownMenuItemLabelClasses, className);\n}\n\nexport function dropdownMenuItemDescriptionClassNames({\n  className,\n}: Pick<DropdownMenuItemDescriptionProps, \"className\"> = {}) {\n  return cn(dropdownMenuItemDescriptionClasses, className);\n}\n\nexport function dropdownMenuItemShortcutClassNames({\n  className,\n}: Pick<DropdownMenuItemShortcutProps, \"className\"> = {}) {\n  return cn(dropdownMenuItemShortcutClasses, className);\n}\n\nexport function dropdownMenuLabelClassNames({\n  className,\n}: Pick<DropdownMenuLabelProps, \"className\"> = {}) {\n  return cn(dropdownMenuLabelClasses, className);\n}\n\nexport function dropdownMenuSeparatorClassNames({\n  className,\n}: Pick<DropdownMenuSeparatorProps, \"className\"> = {}) {\n  return cn(dropdownMenuSeparatorClasses, className);\n}\n\nexport function dropdownMenuSectionClassNames({\n  className,\n}: Pick<DropdownMenuSectionProps, \"className\"> = {}) {\n  return cn(dropdownMenuSectionClasses, className);\n}\n\nexport function dropdownMenuArrowClassNames({\n  className,\n}: Pick<DropdownMenuArrowProps, \"className\"> = {}) {\n  return positionedOverlayArrowClassNames({ className });\n}\n\nfunction ChevronRightIcon() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className={dropdownMenuSubmenuIconClasses}\n      fill=\"none\"\n      viewBox=\"0 0 16 16\"\n    >\n      <path\n        d=\"m6 4 4 4-4 4\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"1.75\"\n      />\n    </svg>\n  );\n}\n\nfunction renderMenuItemChildren(\n  children: DropdownMenuItemProps[\"children\"],\n  opts: AriaMenuItemRenderProps,\n) {\n  const renderedChildren =\n    typeof children === \"function\" ? children(opts) : children;\n\n  if (\n    typeof renderedChildren === \"string\" ||\n    typeof renderedChildren === \"number\"\n  ) {\n    return (\n      <>\n        <DropdownMenuItemIcon aria-hidden=\"true\" />\n        <DropdownMenuItemLabel>{renderedChildren}</DropdownMenuItemLabel>\n        {opts.hasSubmenu ? <ChevronRightIcon /> : null}\n      </>\n    );\n  }\n\n  return (\n    <>\n      {renderedChildren}\n      {opts.hasSubmenu ? <ChevronRightIcon /> : null}\n    </>\n  );\n}\n\ninterface DropdownMenuMotionPopoverProps<T extends object = object> {\n  anchorRef?: AriaPopoverProps[\"triggerRef\"];\n  arrowClassName?: string;\n  arrowShapeClassName?: string;\n  children: DropdownMenuContentProps<T>[\"children\"];\n  className?: string;\n  contentSlot: string;\n  menuClassName?: string;\n  menuProps: Omit<AriaMenuProps<T>, \"children\" | \"className\">;\n  positionProps: Required<PositionedOverlayPositionProps>;\n  showArrow: boolean;\n  surfaceRef: ForwardedRef<HTMLElement>;\n}\n\nfunction DropdownMenuMotionPopover<T extends object = object>({\n  anchorRef,\n  arrowClassName,\n  arrowShapeClassName,\n  children,\n  className,\n  contentSlot,\n  menuClassName,\n  menuProps,\n  positionProps,\n  showArrow,\n  surfaceRef,\n}: DropdownMenuMotionPopoverProps<T>) {\n  const [isPresent, safeToRemove] = usePresence();\n  const { motionPreset, reducedMotion } = useContext(DropdownMenuMotionContext);\n  const settings = dropdownMenuMotionSettings[motionPreset];\n  const motionDisabled = motionPreset === \"none\";\n  const transition: Transition = {\n    duration: reducedMotion ? 0.08 : settings.duration,\n    ease: dropdownMenuMotionEase,\n  };\n\n  return (\n    <AriaPopover\n      {...positionProps}\n      isExiting={!isPresent}\n      triggerRef={anchorRef}\n      className={dropdownMenuPositionerClasses}\n    >\n      {({ placement }) => {\n        const offset = getDropdownMenuSurfaceOffset(\n          placement ?? \"bottom\",\n          settings.distance,\n        );\n        const hidden = reducedMotion\n          ? { opacity: 0 }\n          : {\n              opacity: 0,\n              scale: settings.surfaceScale,\n              x: offset.x,\n              y: offset.y,\n            };\n        const visible = reducedMotion\n          ? { opacity: 1 }\n          : { opacity: 1, scale: 1, x: 0, y: 0 };\n\n        return (\n          <motion.div\n            ref={surfaceRef as ForwardedRef<HTMLDivElement>}\n            animate={visible}\n            initial={motionDisabled ? false : hidden}\n            exit={motionDisabled ? visible : hidden}\n            data-motion={motionPreset}\n            data-placement={placement}\n            data-reduced-motion={reducedMotion ? \"\" : undefined}\n            data-slot={contentSlot}\n            data-state={isPresent ? \"open\" : \"closed\"}\n            className={dropdownMenuContentClassNames({ className })}\n            transition={motionDisabled ? { duration: 0 } : transition}\n            onAnimationComplete={() => {\n              if (!isPresent) {\n                safeToRemove?.();\n              }\n            }}\n          >\n            {showArrow ? (\n              <DropdownMenuArrow\n                className={arrowClassName}\n                shapeClassName={arrowShapeClassName}\n              />\n            ) : null}\n            <AriaMenu\n              {...menuProps}\n              data-slot=\"dropdown-menu-menu\"\n              className={dropdownMenuMenuClassNames({\n                className: menuClassName,\n              })}\n            >\n              {children}\n            </AriaMenu>\n          </motion.div>\n        );\n      }}\n    </AriaPopover>\n  );\n}\n\nfunction DropdownMenuContentRoot<T extends object = object>(\n  {\n    \"data-slot\": dataSlot,\n    anchorRef,\n    arrowBoundaryOffset,\n    arrowClassName,\n    arrowShapeClassName,\n    children,\n    className,\n    containerPadding,\n    crossOffset,\n    menuClassName,\n    offset,\n    placement,\n    shouldFlip,\n    showArrow = false,\n    ...props\n  }: DropdownMenuContentProps<T>,\n  ref: ForwardedRef<HTMLElement>,\n  defaults: Required<PositionedOverlayPositionProps> = positionedOverlayDropdownMenuDefaults,\n  contentSlot = \"dropdown-menu-content\",\n) {\n  const positionProps = resolvePositionedOverlayPositionProps(\n    {\n      arrowBoundaryOffset,\n      containerPadding,\n      crossOffset,\n      offset,\n      placement,\n      shouldFlip,\n    },\n    defaults,\n  );\n  const isSSR = useIsSSR();\n  const overlayState = useContext(OverlayTriggerStateContext);\n  const isOpen = (overlayState?.isOpen ?? false) && !isSSR;\n\n  return (\n    <AnimatePresence initial={false}>\n      {isOpen ? (\n        <DropdownMenuMotionPopover\n          key={dataSlot ?? contentSlot}\n          anchorRef={anchorRef}\n          arrowClassName={arrowClassName}\n          arrowShapeClassName={arrowShapeClassName}\n          className={className}\n          contentSlot={dataSlot ?? contentSlot}\n          menuClassName={menuClassName}\n          menuProps={props}\n          positionProps={positionProps}\n          showArrow={showArrow}\n          surfaceRef={ref}\n        >\n          {children}\n        </DropdownMenuMotionPopover>\n      ) : null}\n    </AnimatePresence>\n  );\n}\n\nexport const DropdownMenu = forwardRef<HTMLDivElement, DropdownMenuProps>(\n  (\n    {\n      \"data-slot\": dataSlot,\n      children,\n      className,\n      defaultOpen,\n      motionPreset = \"standard\",\n      onOpenChange,\n      open,\n      reducedMotion,\n      ...props\n    },\n    ref,\n  ) => {\n    const [resolvedOpen, handleOpenChange] = useScopedOverlayState({\n      open,\n      defaultOpen,\n      onOpenChange,\n    });\n    const prefersReducedMotion = useReducedMotion();\n    const hasHydrated = useHydrated();\n    const resolvedReducedMotion =\n      reducedMotion ?? (hasHydrated && prefersReducedMotion === true);\n    const { portalContainer, rootRef } = useProviderPortalRoot<HTMLDivElement>({\n      forwardedRef: ref,\n      portalSlot: \"dropdown-menu-portal-container\",\n    });\n\n    return (\n      <div\n        ref={rootRef}\n        data-slot={dataSlot ?? \"dropdown-menu\"}\n        data-motion={motionPreset}\n        data-open={resolvedOpen ? \"\" : undefined}\n        data-reduced-motion={resolvedReducedMotion ? \"\" : undefined}\n        className={dropdownMenuClassNames({ className })}\n      >\n        <DropdownMenuMotionContext.Provider\n          value={{\n            motionPreset,\n            reducedMotion: resolvedReducedMotion,\n          }}\n        >\n          <DethinkPortalProvider container={portalContainer}>\n            <AriaMenuTrigger\n              {...props}\n              isOpen={resolvedOpen}\n              onOpenChange={handleOpenChange}\n            >\n              {children}\n            </AriaMenuTrigger>\n          </DethinkPortalProvider>\n        </DropdownMenuMotionContext.Provider>\n      </div>\n    );\n  },\n);\n\nDropdownMenu.displayName = \"DropdownMenu\";\n\nexport const DropdownMenuTrigger = forwardRef<\n  HTMLButtonElement,\n  DropdownMenuTriggerProps\n>(\n  (\n    {\n      \"data-slot\": dataSlot = \"dropdown-menu-trigger\",\n      children,\n      className,\n      disabled = false,\n      size = \"md\",\n      variant = \"outline\",\n      ...props\n    },\n    ref,\n  ) => (\n    <Button\n      asChild\n      className={className}\n      data-slot={dataSlot}\n      disabled={disabled}\n      size={size}\n      variant={variant}\n    >\n      <AriaButton {...props} ref={ref} isDisabled={disabled}>\n        {children}\n      </AriaButton>\n    </Button>\n  ),\n);\n\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\nexport const DropdownMenuContent = forwardRef<\n  HTMLElement,\n  DropdownMenuContentProps\n>((props, ref) => DropdownMenuContentRoot(props, ref));\n\nDropdownMenuContent.displayName = \"DropdownMenuContent\";\n\nexport const DropdownMenuSubmenuContent = forwardRef<\n  HTMLElement,\n  DropdownMenuSubmenuContentProps\n>((props, ref) =>\n  DropdownMenuContentRoot(\n    props,\n    ref,\n    positionedOverlayDropdownSubmenuDefaults,\n    \"dropdown-menu-submenu-content\",\n  ),\n);\n\nDropdownMenuSubmenuContent.displayName = \"DropdownMenuSubmenuContent\";\n\nexport const DropdownMenuItem = forwardRef<\n  HTMLDivElement,\n  DropdownMenuItemProps\n>(\n  (\n    {\n      children,\n      className,\n      destructive = false,\n      disabled = false,\n      textValue,\n      ...props\n    },\n    ref,\n  ) => {\n    const resolvedTextValue =\n      textValue ??\n      (typeof children === \"string\" || typeof children === \"number\"\n        ? String(children)\n        : undefined);\n\n    const { motionPreset, reducedMotion } = useContext(\n      DropdownMenuMotionContext,\n    );\n    const motionSettings = dropdownMenuMotionSettings[motionPreset];\n    const motionDisabled = reducedMotion || motionPreset === \"none\";\n\n    return (\n      <AriaMenuItem\n        {...props}\n        ref={ref}\n        data-destructive={destructive ? \"true\" : undefined}\n        data-slot=\"dropdown-menu-item\"\n        isDisabled={disabled || undefined}\n        textValue={resolvedTextValue}\n        className={dropdownMenuItemClassNames({ className })}\n      >\n        {(opts) => {\n          const itemScale = opts.isPressed\n            ? motionSettings.itemPressScale\n            : opts.isFocused || opts.isHovered\n              ? motionSettings.itemFocusScale\n              : 1;\n\n          return (\n            <motion.div\n              animate={\n                motionDisabled\n                  ? { opacity: 1 }\n                  : {\n                      opacity: opts.isPressed ? 0.82 : 1,\n                      scale: itemScale,\n                    }\n              }\n              data-slot=\"dropdown-menu-item-feedback\"\n              className=\"col-span-full grid min-w-0 grid-cols-subgrid items-center gap-[var(--dt-space-2)]\"\n              transition={{\n                duration: motionDisabled ? 0 : motionSettings.duration,\n                ease: dropdownMenuMotionEase,\n              }}\n            >\n              {renderMenuItemChildren(children, opts)}\n            </motion.div>\n          );\n        }}\n      </AriaMenuItem>\n    );\n  },\n);\n\nDropdownMenuItem.displayName = \"DropdownMenuItem\";\n\nexport const DropdownMenuSection = forwardRef<\n  HTMLElement,\n  DropdownMenuSectionProps\n>(({ className, ...props }, ref) => (\n  <AriaMenuSection\n    {...props}\n    ref={ref}\n    data-slot=\"dropdown-menu-section\"\n    className={dropdownMenuSectionClassNames({ className })}\n  />\n));\n\nDropdownMenuSection.displayName = \"DropdownMenuSection\";\n\nexport const DropdownMenuSubmenu = forwardRef<\n  HTMLDivElement,\n  DropdownMenuSubmenuProps\n>(({ children, ...props }, ref) => {\n  const resolvedChildren = useMemo(\n    () => Children.toArray(children) as ReactElement[],\n    [children],\n  );\n\n  return (\n    <AriaSubmenuTrigger {...props} ref={ref}>\n      {resolvedChildren}\n    </AriaSubmenuTrigger>\n  );\n});\n\nDropdownMenuSubmenu.displayName = \"DropdownMenuSubmenu\";\n\nexport const DropdownMenuArrow = forwardRef<\n  HTMLDivElement,\n  DropdownMenuArrowProps\n>(({ className, ...props }, ref) => (\n  <PositionedOverlayArrow\n    {...props}\n    ref={ref}\n    data-slot=\"dropdown-menu-arrow\"\n    className={dropdownMenuArrowClassNames({ className })}\n  />\n));\n\nDropdownMenuArrow.displayName = \"DropdownMenuArrow\";\n\nexport const DropdownMenuLabel = forwardRef<\n  HTMLElement,\n  DropdownMenuLabelProps\n>(({ className, ...props }, ref) => (\n  <AriaHeader\n    {...props}\n    ref={ref}\n    data-slot=\"dropdown-menu-label\"\n    className={dropdownMenuLabelClassNames({ className })}\n  />\n));\n\nDropdownMenuLabel.displayName = \"DropdownMenuLabel\";\n\nexport const DropdownMenuSeparator = forwardRef<\n  HTMLElement,\n  DropdownMenuSeparatorProps\n>(({ className, ...props }, ref) => (\n  <AriaSeparator\n    {...props}\n    ref={ref}\n    data-slot=\"dropdown-menu-separator\"\n    className={dropdownMenuSeparatorClassNames({ className })}\n  />\n));\n\nDropdownMenuSeparator.displayName = \"DropdownMenuSeparator\";\n\nexport const DropdownMenuItemIcon = forwardRef<\n  HTMLSpanElement,\n  DropdownMenuItemIconProps\n>(({ className, ...props }, ref) => (\n  <span\n    {...props}\n    ref={ref}\n    data-slot=\"dropdown-menu-item-icon\"\n    className={dropdownMenuItemIconClassNames({ className })}\n  />\n));\n\nDropdownMenuItemIcon.displayName = \"DropdownMenuItemIcon\";\n\nexport const DropdownMenuItemLabel = forwardRef<\n  HTMLElement,\n  DropdownMenuItemLabelProps\n>(({ className, ...props }, ref) => (\n  <AriaText\n    {...props}\n    ref={ref}\n    slot=\"label\"\n    data-slot=\"dropdown-menu-item-label\"\n    className={dropdownMenuItemLabelClassNames({ className })}\n  />\n));\n\nDropdownMenuItemLabel.displayName = \"DropdownMenuItemLabel\";\n\nexport const DropdownMenuItemDescription = forwardRef<\n  HTMLElement,\n  DropdownMenuItemDescriptionProps\n>(({ className, ...props }, ref) => (\n  <AriaText\n    {...props}\n    ref={ref}\n    slot=\"description\"\n    data-slot=\"dropdown-menu-item-description\"\n    className={dropdownMenuItemDescriptionClassNames({ className })}\n  />\n));\n\nDropdownMenuItemDescription.displayName = \"DropdownMenuItemDescription\";\n\nexport const DropdownMenuItemShortcut = forwardRef<\n  HTMLElement,\n  DropdownMenuItemShortcutProps\n>(({ className, ...props }, ref) => (\n  <AriaKeyboard\n    {...props}\n    ref={ref}\n    data-slot=\"dropdown-menu-item-shortcut\"\n    className={dropdownMenuItemShortcutClassNames({ className })}\n  />\n));\n\nDropdownMenuItemShortcut.displayName = \"DropdownMenuItemShortcut\";\n"
    },
    {
      "path": "packages/components/src/components/dropdown-menu/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/dropdown-menu/index.ts",
      "content": "export {\n  DropdownMenu,\n  DropdownMenuArrow,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuItemDescription,\n  DropdownMenuItemIcon,\n  DropdownMenuItemLabel,\n  DropdownMenuItemShortcut,\n  DropdownMenuLabel,\n  DropdownMenuSection,\n  DropdownMenuSeparator,\n  DropdownMenuSubmenu,\n  DropdownMenuSubmenuContent,\n  DropdownMenuTrigger,\n  dropdownMenuArrowClassNames,\n  dropdownMenuClassNames,\n  dropdownMenuContentClassNames,\n  dropdownMenuItemClassNames,\n  dropdownMenuItemDescriptionClassNames,\n  dropdownMenuItemIconClassNames,\n  dropdownMenuItemLabelClassNames,\n  dropdownMenuItemShortcutClassNames,\n  dropdownMenuLabelClassNames,\n  dropdownMenuMenuClassNames,\n  dropdownMenuSectionClassNames,\n  dropdownMenuSeparatorClassNames,\n  dropdownMenuTriggerClassNames,\n  type DropdownMenuArrowProps,\n  type DropdownMenuContentProps,\n  type DropdownMenuItemDescriptionProps,\n  type DropdownMenuItemIconProps,\n  type DropdownMenuItemLabelProps,\n  type DropdownMenuItemProps,\n  type DropdownMenuItemShortcutProps,\n  type DropdownMenuLabelProps,\n  type DropdownMenuMotionPreset,\n  type DropdownMenuProps,\n  type DropdownMenuSectionProps,\n  type DropdownMenuSeparatorProps,\n  type DropdownMenuSubmenuContentProps,\n  type DropdownMenuSubmenuProps,\n  type DropdownMenuTriggerProps,\n} from \"./dropdown-menu\";\n"
    },
    {
      "path": "packages/components/src/utils/provider-portal.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/utils/provider-portal.tsx",
      "content": "import {\n  createContext,\n  type ForwardedRef,\n  type ReactNode,\n  type RefCallback,\n  useCallback,\n  useContext,\n  useEffect,\n  useRef,\n  useState,\n} from \"react\";\nimport { UNSAFE_PortalProvider } from \"react-aria/PortalProvider\";\nimport { setDethinkPortalOwner } from \"./portal-owner\";\n\nconst providerPortalDefaultClasses = \"bg-background font-sans text-foreground\";\nconst providerPortalMirroredAttributes = [\n  \"data-theme\",\n  \"data-density\",\n  \"dir\",\n] as const;\n\nexport type ProviderPortalMirroredAttribute =\n  (typeof providerPortalMirroredAttributes)[number];\n\nexport interface ProviderPortalRootOptions<T extends HTMLElement> {\n  forwardedRef?: ForwardedRef<T>;\n  portalSlot: string;\n}\n\nexport interface ProviderPortalRootState<T extends HTMLElement> {\n  portalContainer: HTMLElement | null;\n  rootRef: RefCallback<T>;\n}\n\nexport interface DethinkPortalProviderProps {\n  children?: ReactNode;\n  container: HTMLElement | null;\n}\n\nconst DethinkPortalContext = createContext(false);\nconst OverlayVisibilityContext = createContext(true);\n\n/** Persistent surfaces can dismiss overlays without unmounting their content. */\nexport function DethinkOverlayScope({\n  visible,\n  children,\n}: {\n  visible: boolean;\n  children?: ReactNode;\n}) {\n  const parentVisible = useContext(OverlayVisibilityContext);\n  return (\n    <OverlayVisibilityContext.Provider value={visible && parentVisible}>\n      {children}\n    </OverlayVisibilityContext.Provider>\n  );\n}\n\nexport function useScopedOverlayState({\n  open,\n  defaultOpen = false,\n  onOpenChange,\n}: {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n}): readonly [boolean, (open: boolean) => void] {\n  const visible = useContext(OverlayVisibilityContext);\n  const [localOpen, setLocalOpen] = useState(defaultOpen);\n  const requestedOpen = open ?? localOpen;\n  const closeRequested = useRef(false);\n  const setOpen = useCallback(\n    (next: boolean) => {\n      if (next && !visible) return;\n      if (open === undefined) setLocalOpen(next);\n      onOpenChange?.(next);\n    },\n    [open, onOpenChange, visible],\n  );\n  useEffect(() => {\n    if (visible) closeRequested.current = false;\n    else if (requestedOpen && !closeRequested.current) {\n      closeRequested.current = true;\n      // Synchronize overlay state with the containing surface's lifecycle.\n      setOpen(false);\n    }\n  }, [visible, requestedOpen, setOpen]);\n  return [visible && requestedOpen, setOpen];\n}\n\nfunction assignForwardedRef<T>(\n  ref: ForwardedRef<T> | undefined,\n  value: T | null,\n) {\n  if (typeof ref === \"function\") {\n    ref(value);\n  } else if (ref) {\n    ref.current = value;\n  }\n}\n\nfunction fallbackProviderAttribute(name: ProviderPortalMirroredAttribute) {\n  if (typeof document === \"undefined\") {\n    return null;\n  }\n\n  if (name === \"data-density\") {\n    return \"default\";\n  }\n\n  if (name === \"data-theme\") {\n    return document.documentElement.getAttribute(name) ?? \"system\";\n  }\n\n  return document.documentElement.getAttribute(\"dir\") ?? document.dir ?? \"ltr\";\n}\n\nexport function syncDethinkPortalContainer({\n  container,\n  portalSlot,\n  provider,\n}: {\n  container: HTMLElement;\n  portalSlot: string;\n  provider: HTMLElement | null;\n}) {\n  const source =\n    provider ??\n    (typeof document === \"undefined\" ? null : document.documentElement);\n\n  container.setAttribute(\"data-slot\", portalSlot);\n  container.setAttribute(\"data-dethink-provider\", \"\");\n  container.className = provider?.className || providerPortalDefaultClasses;\n  container.style.cssText = provider?.getAttribute(\"style\") ?? \"\";\n  container.style.display = \"contents\";\n\n  for (const attribute of providerPortalMirroredAttributes) {\n    const value =\n      source?.getAttribute(attribute) ?? fallbackProviderAttribute(attribute);\n\n    if (value) {\n      container.setAttribute(attribute, value);\n    } else {\n      container.removeAttribute(attribute);\n    }\n  }\n}\n\nexport function useProviderPortalRoot<T extends HTMLElement>({\n  forwardedRef,\n  portalSlot,\n}: ProviderPortalRootOptions<T>): ProviderPortalRootState<T> {\n  const [portalContainer] = useState<HTMLElement | null>(() => {\n    if (typeof document === \"undefined\") {\n      return null;\n    }\n\n    return document.createElement(\"div\");\n  });\n  const [rootElement, setRootElement] = useState<T | null>(null);\n\n  const rootRef = useCallback(\n    (node: T | null) => {\n      setRootElement(node);\n      assignForwardedRef(forwardedRef, node);\n\n      if (node && portalContainer && typeof document !== \"undefined\") {\n        setDethinkPortalOwner(portalContainer, node);\n        const provider =\n          node.closest<HTMLElement>(\"[data-dethink-provider]\") ?? null;\n\n        syncDethinkPortalContainer({\n          container: portalContainer,\n          portalSlot,\n          provider,\n        });\n\n        if (!portalContainer.isConnected) {\n          document.body.appendChild(portalContainer);\n        }\n      }\n    },\n    [forwardedRef, portalContainer, portalSlot],\n  );\n\n  useEffect(() => {\n    if (!portalContainer || typeof document === \"undefined\") {\n      return undefined;\n    }\n\n    const provider =\n      rootElement?.closest<HTMLElement>(\"[data-dethink-provider]\") ?? null;\n    const syncContainer = () => {\n      syncDethinkPortalContainer({\n        container: portalContainer,\n        portalSlot,\n        provider,\n      });\n    };\n\n    syncContainer();\n    document.body.appendChild(portalContainer);\n\n    const observerTarget = provider ?? document.documentElement;\n    const observer = new MutationObserver(syncContainer);\n    observer.observe(observerTarget, {\n      attributeFilter: [\"class\", \"data-density\", \"data-theme\", \"dir\", \"style\"],\n      attributes: true,\n    });\n\n    return () => {\n      observer.disconnect();\n      portalContainer.remove();\n    };\n  }, [portalContainer, portalSlot, rootElement]);\n\n  return {\n    portalContainer,\n    rootRef,\n  };\n}\n\nexport function DethinkPortalProvider({\n  children,\n  container,\n}: DethinkPortalProviderProps) {\n  const hasDethinkPortalParent = useContext(DethinkPortalContext);\n  const content = hasDethinkPortalParent ? (\n    children\n  ) : (\n    <UNSAFE_PortalProvider getContainer={() => container}>\n      {children}\n    </UNSAFE_PortalProvider>\n  );\n\n  return (\n    <DethinkPortalContext.Provider value>\n      {content}\n    </DethinkPortalContext.Provider>\n  );\n}\n"
    },
    {
      "path": "packages/components/src/utils/portal-owner.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/portal-owner.ts",
      "content": "/**\n * Links a Dethink portal container on <body> to the component root that owns\n * it, so a modal surface (the mobile sidebar) can keep overlays opened from\n * inside it usable while it makes the rest of the page inert. A global symbol\n * key, so components copied from the registry agree without sharing imports.\n */\nconst PORTAL_OWNER: unique symbol = Symbol.for(\"dethink.portal-owner\");\n\ntype OwnedElement = Element & { [PORTAL_OWNER]?: Element };\n\nexport function setDethinkPortalOwner(container: Element, owner: Element) {\n  (container as OwnedElement)[PORTAL_OWNER] = owner;\n}\n\n/** The element owning a Dethink portal container, or null for any other element. */\nexport function getDethinkPortalOwner(element: Element): Element | null {\n  return (element as OwnedElement)[PORTAL_OWNER] ?? null;\n}\n"
    },
    {
      "path": "packages/components/src/utils/positioned-overlay.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/utils/positioned-overlay.tsx",
      "content": "import { forwardRef } from \"react\";\nimport {\n  OverlayArrow as AriaOverlayArrow,\n  type OverlayArrowProps as AriaOverlayArrowProps,\n} from \"react-aria-components\";\nimport type { Placement } from \"react-aria/useOverlayPosition\";\nimport { cn } from \"./cn\";\n\nexport type PositionedOverlayPlacement = Placement;\n\nexport interface PositionedOverlayPositionProps {\n  arrowBoundaryOffset?: number;\n  containerPadding?: number;\n  crossOffset?: number;\n  offset?: number;\n  placement?: PositionedOverlayPlacement;\n  shouldFlip?: boolean;\n}\n\nexport interface PositionedOverlaySurfaceClassNameOptions {\n  animation?: \"css\" | \"none\";\n  className?: string;\n}\n\nexport interface PositionedOverlayArrowClassNameOptions {\n  className?: string;\n}\n\nexport interface PositionedOverlayArrowProps extends Omit<\n  AriaOverlayArrowProps,\n  \"children\" | \"className\"\n> {\n  \"data-slot\"?: string;\n  className?: string;\n  shapeDataSlot?: string;\n  shapeClassName?: string;\n}\n\nexport const positionedOverlayPositionDefaults = {\n  arrowBoundaryOffset: 0,\n  containerPadding: 12,\n  crossOffset: 0,\n  offset: 0,\n  placement: \"bottom\",\n  shouldFlip: true,\n} satisfies Required<PositionedOverlayPositionProps>;\n\nexport const positionedOverlayPopoverDefaults = {\n  ...positionedOverlayPositionDefaults,\n  offset: 8,\n} satisfies Required<PositionedOverlayPositionProps>;\n\nexport const positionedOverlayTooltipDefaults = {\n  ...positionedOverlayPositionDefaults,\n  offset: 8,\n  placement: \"top\",\n} satisfies Required<PositionedOverlayPositionProps>;\n\nexport const positionedOverlayDropdownMenuDefaults = {\n  ...positionedOverlayPositionDefaults,\n  offset: 8,\n  placement: \"bottom start\",\n} satisfies Required<PositionedOverlayPositionProps>;\n\nexport const positionedOverlayDropdownSubmenuDefaults = {\n  ...positionedOverlayPositionDefaults,\n  crossOffset: -4,\n  offset: -2,\n  placement: \"right top\",\n} satisfies Required<PositionedOverlayPositionProps>;\n\nconst positionedOverlaySurfaceBaseClasses =\n  \"z-50 max-h-[min(var(--dt-overlay-max-height,18rem),calc(100dvh_-_var(--dt-space-4)))] min-w-[var(--dt-overlay-min-width,12rem)] overflow-auto rounded-md border border-border bg-background p-[var(--dt-space-3)] text-foreground shadow-lg outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring [--dt-overlay-motion-x:0px] [--dt-overlay-motion-y:var(--dt-space-1)] data-[placement=bottom]:[--dt-overlay-motion-y:calc(0px_-_var(--dt-space-1))] data-[placement=top]:[--dt-overlay-motion-y:var(--dt-space-1)] data-[placement=left]:[--dt-overlay-motion-x:var(--dt-space-1)] data-[placement=left]:[--dt-overlay-motion-y:0px] data-[placement=right]:[--dt-overlay-motion-x:calc(0px_-_var(--dt-space-1))] data-[placement=right]:[--dt-overlay-motion-y:0px] origin-center data-[placement=top]:origin-bottom data-[placement=bottom]:origin-top data-[placement=left]:origin-right data-[placement=right]:origin-left\";\n\nconst positionedOverlaySurfaceCssAnimationClasses =\n  \"motion-safe:data-[entering]:animate-overlay-in motion-safe:data-[exiting]:animate-overlay-out motion-reduce:animate-none\";\n\nconst positionedOverlayArrowBaseClasses =\n  \"group z-50 flex size-3 items-center justify-center text-background [filter:drop-shadow(0_1px_0.5px_rgb(0_0_0_/_0.06))]\";\n\nconst positionedOverlayArrowShapeBaseClasses =\n  \"block size-3 fill-background stroke-border group-data-[placement=bottom]:rotate-180 group-data-[placement=left]:-rotate-90 group-data-[placement=right]:rotate-90 [stroke-linejoin:round] [stroke-width:1px]\";\n\nexport function resolvePositionedOverlayPositionProps(\n  props: PositionedOverlayPositionProps = {},\n  defaults: Required<PositionedOverlayPositionProps> = positionedOverlayPositionDefaults,\n): Required<PositionedOverlayPositionProps> {\n  return {\n    arrowBoundaryOffset:\n      props.arrowBoundaryOffset ?? defaults.arrowBoundaryOffset,\n    containerPadding: props.containerPadding ?? defaults.containerPadding,\n    crossOffset: props.crossOffset ?? defaults.crossOffset,\n    offset: props.offset ?? defaults.offset,\n    placement: props.placement ?? defaults.placement,\n    shouldFlip: props.shouldFlip ?? defaults.shouldFlip,\n  };\n}\n\nexport function positionedOverlaySurfaceClassNames({\n  animation = \"css\",\n  className,\n}: PositionedOverlaySurfaceClassNameOptions = {}) {\n  return cn(\n    positionedOverlaySurfaceBaseClasses,\n    animation === \"css\" && positionedOverlaySurfaceCssAnimationClasses,\n    className,\n  );\n}\n\nexport function positionedOverlayArrowClassNames({\n  className,\n}: PositionedOverlayArrowClassNameOptions = {}) {\n  return cn(positionedOverlayArrowBaseClasses, className);\n}\n\nexport function positionedOverlayArrowShapeClassNames({\n  className,\n}: PositionedOverlayArrowClassNameOptions = {}) {\n  return cn(positionedOverlayArrowShapeBaseClasses, className);\n}\n\nexport const PositionedOverlayArrow = forwardRef<\n  HTMLDivElement,\n  PositionedOverlayArrowProps\n>(\n  (\n    {\n      \"data-slot\": dataSlot = \"positioned-overlay-arrow\",\n      className,\n      shapeClassName,\n      shapeDataSlot,\n      ...props\n    },\n    ref,\n  ) => (\n    <AriaOverlayArrow\n      {...props}\n      ref={ref}\n      data-slot={dataSlot}\n      className={positionedOverlayArrowClassNames({ className })}\n    >\n      <svg\n        aria-hidden=\"true\"\n        data-slot={shapeDataSlot ?? `${dataSlot}-shape`}\n        focusable=\"false\"\n        viewBox=\"0 0 12 12\"\n        className={positionedOverlayArrowShapeClassNames({\n          className: shapeClassName,\n        })}\n      >\n        <path d=\"M0 0 L6 12 L12 0\" />\n      </svg>\n    </AriaOverlayArrow>\n  ),\n);\n\nPositionedOverlayArrow.displayName = \"PositionedOverlayArrow\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
    }
  ]
}
