{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sidebar",
  "dependencies": [
    "@floating-ui/react",
    "class-variance-authority",
    "lucide-react",
    "motion",
    "radix-ui"
  ],
  "registryDependencies": [
    "button",
    "input",
    "separator",
    "sheet",
    "skeleton",
    "utils"
  ],
  "files": [
    {
      "path": "src/components/watermelon-ui/sidebar.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { Slot } from 'radix-ui';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { PanelLeftIcon } from 'lucide-react';\nimport { AnimatePresence, motion, type Transition } from 'motion/react';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Separator } from '@/components/ui/separator';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport {\n  Sheet,\n  SheetContent,\n  SheetDescription,\n  SheetHeader,\n  SheetTitle,\n} from '@/components/ui/sheet';\nimport {\n  TooltipProvider,\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from '@/components/watermelon-ui/tooltip-animated';\n\n\nconst SIDEBAR_COOKIE_NAME = 'sidebar_state';\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nconst SIDEBAR_WIDTH = '16rem';\nconst SIDEBAR_WIDTH_MOBILE = '18rem';\nconst SIDEBAR_WIDTH_ICON = '3rem';\nconst SIDEBAR_KEYBOARD_SHORTCUT = 'b';\n\ntype SidebarContextProps = {\n  state: 'expanded' | 'collapsed';\n  open: boolean;\n  setOpen: (open: boolean) => void;\n  openMobile: boolean;\n  setOpenMobile: (open: boolean) => void;\n  isMobile: boolean;\n  toggleSidebar: () => void;\n};\n\nconst [LocalSidebarProvider, useSidebar] =\n  getStrictContext<SidebarContextProps>('SidebarContext');\n\ntype SidebarProviderProps = React.ComponentProps<'div'> & {\n  defaultOpen?: boolean;\n  open?: boolean;\n  onOpenChange?: (open: boolean) => void;\n};\n\nfunction SidebarProvider({\n  defaultOpen = true,\n  open: openProp,\n  onOpenChange: setOpenProp,\n  className,\n  style,\n  children,\n  ...props\n}: SidebarProviderProps) {\n  const isMobile = useIsMobile();\n  const [openMobile, setOpenMobile] = React.useState(false);\n\n  // This is the internal state of the sidebar.\n  // We use openProp and setOpenProp for control from outside the component.\n  const [_open, _setOpen] = React.useState(defaultOpen);\n  const open = openProp ?? _open;\n  const setOpen = React.useCallback(\n    (value: boolean | ((value: boolean) => boolean)) => {\n      const openState = typeof value === 'function' ? value(open) : value;\n      if (setOpenProp) {\n        setOpenProp(openState);\n      } else {\n        _setOpen(openState);\n      }\n\n      // This sets the cookie to keep the sidebar state.\n      document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;\n    },\n    [setOpenProp, open],\n  );\n\n  // Helper to toggle the sidebar.\n  const toggleSidebar = React.useCallback(() => {\n    return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);\n  }, [isMobile, setOpen, setOpenMobile]);\n\n  // Adds a keyboard shortcut to toggle the sidebar.\n  React.useEffect(() => {\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (\n        event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n        (event.metaKey || event.ctrlKey)\n      ) {\n        event.preventDefault();\n        toggleSidebar();\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [toggleSidebar]);\n\n  // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n  // This makes it easier to style the sidebar with Tailwind classes.\n  const state = open ? 'expanded' : 'collapsed';\n\n  const contextValue = React.useMemo<SidebarContextProps>(\n    () => ({\n      state,\n      open,\n      setOpen,\n      isMobile,\n      openMobile,\n      setOpenMobile,\n      toggleSidebar,\n    }),\n    [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],\n  );\n\n  return (\n    <LocalSidebarProvider value={contextValue}>\n      <TooltipProvider openDelay={0}>\n        <div\n          data-slot=\"sidebar-wrapper\"\n          style={\n            {\n              '--sidebar-width': SIDEBAR_WIDTH,\n              '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,\n              ...style,\n            } as React.CSSProperties\n          }\n          className={cn(\n            'group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full',\n            className,\n          )}\n          {...props}\n        >\n          {children}\n        </div>\n      </TooltipProvider>\n    </LocalSidebarProvider>\n  );\n}\n\ntype SidebarProps = React.ComponentProps<'div'> & {\n  side?: 'left' | 'right';\n  variant?: 'sidebar' | 'floating' | 'inset';\n  collapsible?: 'offcanvas' | 'icon' | 'none';\n  containerClassName?: string;\n  animateOnHover?: boolean;\n  transition?: Transition;\n};\n\nfunction Sidebar({\n  side = 'left',\n  variant = 'sidebar',\n  collapsible = 'offcanvas',\n  className,\n  children,\n  animateOnHover = true,\n  containerClassName,\n  transition = { type: 'spring', stiffness: 350, damping: 35 },\n  ...props\n}: SidebarProps) {\n  const { isMobile, state, openMobile, setOpenMobile } = useSidebar();\n\n  if (collapsible === 'none') {\n    return (\n      <Highlight\n        enabled={animateOnHover}\n        hover\n        controlledItems\n        mode=\"parent\"\n        containerClassName={containerClassName}\n        transition={transition}\n      >\n        <div\n          data-slot=\"sidebar\"\n          className={cn(\n            'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col',\n            className,\n          )}\n          {...props}\n        >\n          {children}\n        </div>\n      </Highlight>\n    );\n  }\n\n  if (isMobile) {\n    return (\n      <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n        <SheetContent\n          data-sidebar=\"sidebar\"\n          data-slot=\"sidebar\"\n          data-mobile=\"true\"\n          className=\"bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden\"\n          style={\n            {\n              '--sidebar-width': SIDEBAR_WIDTH_MOBILE,\n            } as React.CSSProperties\n          }\n          side={side}\n        >\n          <SheetHeader className=\"sr-only\">\n            <SheetTitle>Sidebar</SheetTitle>\n            <SheetDescription>Displays the mobile sidebar.</SheetDescription>\n          </SheetHeader>\n          <Highlight\n            enabled={animateOnHover}\n            hover\n            controlledItems\n            mode=\"parent\"\n            containerClassName={cn('h-full', containerClassName)}\n            transition={transition}\n          >\n            <div className=\"flex h-full w-full flex-col\">{children}</div>\n          </Highlight>\n        </SheetContent>\n      </Sheet>\n    );\n  }\n\n  return (\n    <div\n      className=\"group peer text-sidebar-foreground hidden md:block\"\n      data-state={state}\n      data-collapsible={state === 'collapsed' ? collapsible : ''}\n      data-variant={variant}\n      data-side={side}\n      data-slot=\"sidebar\"\n    >\n      {/* This is what handles the sidebar gap on desktop */}\n      <div\n        data-slot=\"sidebar-gap\"\n        className={cn(\n          'relative w-(--sidebar-width) bg-transparent transition-[width] duration-400 ease-[cubic-bezier(0.7,-0.15,0.25,1.15)]',\n          'group-data-[collapsible=offcanvas]:w-0',\n          'group-data-[side=right]:rotate-180',\n          variant === 'floating' || variant === 'inset'\n            ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'\n            : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',\n        )}\n      />\n      <div\n        data-slot=\"sidebar-container\"\n        className={cn(\n          'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-400 ease-[cubic-bezier(0.75,0,0.25,1)] md:flex',\n          side === 'left'\n            ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'\n            : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',\n          // Adjust the padding for floating and inset variants.\n          variant === 'floating' || variant === 'inset'\n            ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'\n            : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l',\n          className,\n        )}\n        {...props}\n      >\n        <Highlight\n          containerClassName={cn('size-full', containerClassName)}\n          enabled={animateOnHover}\n          hover\n          controlledItems\n          mode=\"parent\"\n          forceUpdateBounds\n          transition={transition}\n        >\n          <div\n            data-sidebar=\"sidebar\"\n            data-slot=\"sidebar-inner\"\n            className=\"bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm\"\n          >\n            {children}\n          </div>\n        </Highlight>\n      </div>\n    </div>\n  );\n}\n\ntype SidebarTriggerProps = React.ComponentProps<typeof Button>;\n\nfunction SidebarTrigger({ className, onClick, ...props }: SidebarTriggerProps) {\n  const { toggleSidebar } = useSidebar();\n\n  return (\n    <Button\n      data-sidebar=\"trigger\"\n      data-slot=\"sidebar-trigger\"\n      variant=\"ghost\"\n      size=\"icon\"\n      className={cn('size-7', className)}\n      onClick={(event) => {\n        onClick?.(event);\n        toggleSidebar();\n      }}\n      {...props}\n    >\n      <PanelLeftIcon />\n      <span className=\"sr-only\">Toggle Sidebar</span>\n    </Button>\n  );\n}\n\ntype SidebarRailProps = React.ComponentProps<'button'>;\n\nfunction SidebarRail({ className, ...props }: SidebarRailProps) {\n  const { toggleSidebar } = useSidebar();\n\n  return (\n    <button\n      data-sidebar=\"rail\"\n      data-slot=\"sidebar-rail\"\n      aria-label=\"Toggle Sidebar\"\n      tabIndex={-1}\n      onClick={toggleSidebar}\n      title=\"Toggle Sidebar\"\n      className={cn(\n        'hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex',\n        'in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize',\n        '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',\n        'hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full',\n        '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',\n        '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarInsetProps = React.ComponentProps<'main'>;\n\nfunction SidebarInset({ className, ...props }: SidebarInsetProps) {\n  return (\n    <main\n      data-slot=\"sidebar-inset\"\n      className={cn(\n        'bg-background relative flex w-full flex-1 flex-col',\n        'md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarInputProps = React.ComponentProps<typeof Input>;\n\nfunction SidebarInput({ className, ...props }: SidebarInputProps) {\n  return (\n    <Input\n      data-slot=\"sidebar-input\"\n      data-sidebar=\"input\"\n      className={cn('bg-background h-8 w-full shadow-none', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarHeaderProps = React.ComponentProps<'div'>;\n\nfunction SidebarHeader({ className, ...props }: SidebarHeaderProps) {\n  return (\n    <div\n      data-slot=\"sidebar-header\"\n      data-sidebar=\"header\"\n      className={cn('flex flex-col gap-2 p-2', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarFooterProps = React.ComponentProps<'div'>;\n\nfunction SidebarFooter({ className, ...props }: SidebarFooterProps) {\n  return (\n    <div\n      data-slot=\"sidebar-footer\"\n      data-sidebar=\"footer\"\n      className={cn('flex flex-col gap-2 p-2', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarSeparatorProps = React.ComponentProps<typeof Separator>;\n\nfunction SidebarSeparator({ className, ...props }: SidebarSeparatorProps) {\n  return (\n    <Separator\n      data-slot=\"sidebar-separator\"\n      data-sidebar=\"separator\"\n      className={cn('bg-sidebar-border mx-2 w-auto', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarContentProps = React.ComponentProps<'div'>;\n\nfunction SidebarContent({ className, ...props }: SidebarContentProps) {\n  return (\n    <div\n      data-slot=\"sidebar-content\"\n      data-sidebar=\"content\"\n      className={cn(\n        'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarGroupProps = React.ComponentProps<'div'>;\n\nfunction SidebarGroup({ className, ...props }: SidebarGroupProps) {\n  return (\n    <div\n      data-slot=\"sidebar-group\"\n      data-sidebar=\"group\"\n      className={cn('relative flex w-full min-w-0 flex-col p-2', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarGroupLabelProps = React.ComponentProps<'div'> & {\n  asChild?: boolean;\n};\n\nfunction SidebarGroupLabel({\n  className,\n  asChild = false,\n  ...props\n}: SidebarGroupLabelProps) {\n  const Comp = asChild ? Slot.Root : 'div';\n\n  return (\n    <Comp\n      data-slot=\"sidebar-group-label\"\n      data-sidebar=\"group-label\"\n      className={cn(\n        'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-300 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\n        'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarGroupActionProps = React.ComponentProps<'button'> & {\n  asChild?: boolean;\n};\n\nfunction SidebarGroupAction({\n  className,\n  asChild = false,\n  ...props\n}: SidebarGroupActionProps) {\n  const Comp = asChild ? Slot.Root : 'button';\n\n  return (\n    <Comp\n      data-slot=\"sidebar-group-action\"\n      data-sidebar=\"group-action\"\n      className={cn(\n        'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\n        // Increases the hit area of the button on mobile.\n        'after:absolute after:-inset-2 md:after:hidden',\n        'group-data-[collapsible=icon]:hidden',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarGroupContentProps = React.ComponentProps<'div'>;\n\nfunction SidebarGroupContent({\n  className,\n  ...props\n}: SidebarGroupContentProps) {\n  return (\n    <div\n      data-slot=\"sidebar-group-content\"\n      data-sidebar=\"group-content\"\n      className={cn('w-full text-sm', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarMenuProps = React.ComponentProps<'ul'>;\n\nfunction SidebarMenu({ className, ...props }: SidebarMenuProps) {\n  return (\n    <ul\n      data-slot=\"sidebar-menu\"\n      data-sidebar=\"menu\"\n      className={cn('flex w-full min-w-0 flex-col gap-1', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarMenuItemProps = React.ComponentProps<'li'>;\n\nfunction SidebarMenuItem({ className, ...props }: SidebarMenuItemProps) {\n  return (\n    <li\n      data-slot=\"sidebar-menu-item\"\n      data-sidebar=\"menu-item\"\n      className={cn('group/menu-item relative', className)}\n      {...props}\n    />\n  );\n}\n\nconst sidebarMenuButtonActiveVariants = cva(\n  'bg-sidebar-accent text-sidebar-accent-foreground rounded-md',\n  {\n    variants: {\n      variant: {\n        default: 'bg-sidebar-accent text-sidebar-accent-foreground',\n        outline:\n          'bg-sidebar-accent text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n    },\n  },\n);\n\nconst sidebarMenuButtonVariants = cva(\n  'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] [&:not([data-highlight])]:hover:bg-sidebar-accent [&:not([data-highlight])]:hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground [&:not([data-highlight])]:data-[state=open]:hover:bg-sidebar-accent [&:not([data-highlight])]:data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',\n  {\n    variants: {\n      variant: {\n        default:\n          '[&:not([data-highlight])]:hover:bg-sidebar-accent [&:not([data-highlight])]:hover:text-sidebar-accent-foreground',\n        outline:\n          'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] [&:not([data-highlight])]:hover:bg-sidebar-accent [&:not([data-highlight])]:hover:text-sidebar-accent-foreground [&:not([data-highlight])]:hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',\n      },\n      size: {\n        default: 'h-8 text-sm',\n        sm: 'h-7 text-xs',\n        lg: 'h-12 text-sm group-data-[collapsible=icon]:p-0!',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n);\n\ntype SidebarMenuButtonProps = React.ComponentProps<'button'> & {\n  asChild?: boolean;\n  isActive?: boolean;\n  tooltip?: string | React.ComponentProps<typeof TooltipContent>;\n} & VariantProps<typeof sidebarMenuButtonVariants>;\n\nfunction SidebarMenuButton({\n  asChild = false,\n  isActive = false,\n  variant = 'default',\n  size = 'default',\n  tooltip,\n  className,\n  ...props\n}: SidebarMenuButtonProps) {\n  const Comp = asChild ? Slot.Root : 'button';\n  const { isMobile, state } = useSidebar();\n\n  const button = (\n    <HighlightItem\n      activeClassName={sidebarMenuButtonActiveVariants({ variant })}\n    >\n      <Comp\n        data-slot=\"sidebar-menu-button\"\n        data-sidebar=\"menu-button\"\n        data-size={size}\n        data-active={isActive}\n        className={cn(sidebarMenuButtonVariants({ variant, size }), className)}\n        {...props}\n      />\n    </HighlightItem>\n  );\n\n  if (!tooltip) {\n    return button;\n  }\n\n  if (typeof tooltip === 'string') {\n    tooltip = {\n      children: tooltip,\n    };\n  }\n\n  return (\n    <Tooltip side=\"right\" align=\"center\">\n      <TooltipTrigger asChild>{button}</TooltipTrigger>\n      <TooltipContent hidden={state !== 'collapsed' || isMobile} {...tooltip} />\n    </Tooltip>\n  );\n}\n\ntype SidebarMenuActionProps = React.ComponentProps<'button'> & {\n  asChild?: boolean;\n  showOnHover?: boolean;\n};\n\nfunction SidebarMenuAction({\n  className,\n  asChild = false,\n  showOnHover = false,\n  ...props\n}: SidebarMenuActionProps) {\n  const Comp = asChild ? Slot.Root : 'button';\n\n  return (\n    <Comp\n      data-slot=\"sidebar-menu-action\"\n      data-sidebar=\"menu-action\"\n      className={cn(\n        // Increases the hit area of the button on mobile.\n        'z-[1] text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\n        'after:absolute after:-inset-2 md:after:hidden',\n        'peer-data-[size=sm]/menu-button:top-1',\n        'peer-data-[size=default]/menu-button:top-1.5',\n        'peer-data-[size=lg]/menu-button:top-2.5',\n        'group-data-[collapsible=icon]:hidden',\n        showOnHover &&\n          'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarMenuBadgeProps = React.ComponentProps<'div'>;\n\nfunction SidebarMenuBadge({ className, ...props }: SidebarMenuBadgeProps) {\n  return (\n    <div\n      data-slot=\"sidebar-menu-badge\"\n      data-sidebar=\"menu-badge\"\n      className={cn(\n        'text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none',\n        'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',\n        'peer-data-[size=sm]/menu-button:top-1',\n        'peer-data-[size=default]/menu-button:top-1.5',\n        'peer-data-[size=lg]/menu-button:top-2.5',\n        'group-data-[collapsible=icon]:hidden',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarMenuSkeletonProps = React.ComponentProps<'div'> & {\n  showIcon?: boolean;\n};\n\nfunction SidebarMenuSkeleton({\n  className,\n  showIcon = false,\n  ...props\n}: SidebarMenuSkeletonProps) {\n  // Random width between 50 to 90%.\n  const [width] = React.useState(() => `${Math.floor(Math.random() * 40) + 50}%`);\n\n  return (\n    <div\n      data-slot=\"sidebar-menu-skeleton\"\n      data-sidebar=\"menu-skeleton\"\n      className={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}\n      {...props}\n    >\n      {showIcon && (\n        <Skeleton\n          className=\"size-4 rounded-md\"\n          data-sidebar=\"menu-skeleton-icon\"\n        />\n      )}\n      <Skeleton\n        className=\"h-4 max-w-(--skeleton-width) flex-1\"\n        data-sidebar=\"menu-skeleton-text\"\n        style={\n          {\n            '--skeleton-width': width,\n          } as React.CSSProperties\n        }\n      />\n    </div>\n  );\n}\n\ntype SidebarMenuSubProps = React.ComponentProps<'ul'>;\n\nfunction SidebarMenuSub({ className, ...props }: SidebarMenuSubProps) {\n  return (\n    <ul\n      data-slot=\"sidebar-menu-sub\"\n      data-sidebar=\"menu-sub\"\n      className={cn(\n        'border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5',\n        'group-data-[collapsible=icon]:hidden',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ntype SidebarMenuSubItemProps = React.ComponentProps<'li'>;\n\nfunction SidebarMenuSubItem({ className, ...props }: SidebarMenuSubItemProps) {\n  return (\n    <li\n      data-slot=\"sidebar-menu-sub-item\"\n      data-sidebar=\"menu-sub-item\"\n      className={cn('group/menu-sub-item relative', className)}\n      {...props}\n    />\n  );\n}\n\ntype SidebarMenuSubButtonProps = React.ComponentProps<'a'> & {\n  asChild?: boolean;\n  size?: 'sm' | 'md';\n  isActive?: boolean;\n};\n\nfunction SidebarMenuSubButton({\n  asChild = false,\n  size = 'md',\n  isActive = false,\n  className,\n  ...props\n}: SidebarMenuSubButtonProps) {\n  const Comp = asChild ? Slot.Root : 'a';\n\n  return (\n    <HighlightItem activeClassName=\"bg-sidebar-accent text-sidebar-accent-foreground rounded-md\">\n      <Comp\n        data-slot=\"sidebar-menu-sub-button\"\n        data-sidebar=\"menu-sub-button\"\n        data-size={size}\n        data-active={isActive}\n        className={cn(\n          'text-sidebar-foreground ring-sidebar-ring [&:not([data-highlight])]:hover:bg-sidebar-accent [&:not([data-highlight])]:hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',\n          'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',\n          size === 'sm' && 'text-xs',\n          size === 'md' && 'text-sm',\n          'group-data-[collapsible=icon]:hidden',\n          className,\n        )}\n        {...props}\n      />\n    </HighlightItem>\n  );\n}\n\nexport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarGroup,\n  SidebarGroupAction,\n  SidebarGroupContent,\n  SidebarGroupLabel,\n  SidebarHeader,\n  SidebarInput,\n  SidebarInset,\n  SidebarMenu,\n  SidebarMenuAction,\n  SidebarMenuBadge,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  SidebarMenuSkeleton,\n  SidebarMenuSub,\n  SidebarMenuSubButton,\n  SidebarMenuSubItem,\n  SidebarProvider,\n  SidebarRail,\n  SidebarSeparator,\n  SidebarTrigger,\n  useSidebar,\n};\n\n\n//Extra components \n\n\n\ntype HighlightMode = 'children' | 'parent';\n\ntype Bounds = {\n  top: number;\n  left: number;\n  width: number;\n  height: number;\n};\n\nconst DEFAULT_BOUNDS_OFFSET: Bounds = {\n  top: 0,\n  left: 0,\n  width: 0,\n  height: 0,\n};\n\ntype HighlightContextType<T extends string> = {\n  as?: keyof HTMLElementTagNameMap;\n  mode: HighlightMode;\n  activeValue: T | null;\n  setActiveValue: (value: T | null) => void;\n  setBounds: (bounds: DOMRect) => void;\n  clearBounds: () => void;\n  id: string;\n  hover: boolean;\n  click: boolean;\n  className?: string;\n  style?: React.CSSProperties;\n  activeClassName?: string;\n  setActiveClassName: (className: string) => void;\n  transition?: Transition;\n  disabled?: boolean;\n  enabled?: boolean;\n  exitDelay?: number;\n  forceUpdateBounds?: boolean;\n};\n\nconst HighlightContext = React.createContext<\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  HighlightContextType<any> | undefined\n>(undefined);\n\nfunction useHighlight<T extends string>(): HighlightContextType<T> {\n  const context = React.useContext(HighlightContext);\n  if (!context) {\n    throw new Error('useHighlight must be used within a HighlightProvider');\n  }\n  return context as unknown as HighlightContextType<T>;\n}\n\ntype BaseHighlightProps<T extends React.ElementType = 'div'> = {\n  as?: T;\n  ref?: React.Ref<HTMLDivElement>;\n  mode?: HighlightMode;\n  value?: string | null;\n  defaultValue?: string | null;\n  onValueChange?: (value: string | null) => void;\n  className?: string;\n  style?: React.CSSProperties;\n  transition?: Transition;\n  hover?: boolean;\n  click?: boolean;\n  disabled?: boolean;\n  enabled?: boolean;\n  exitDelay?: number;\n};\n\ntype ParentModeHighlightProps = {\n  boundsOffset?: Partial<Bounds>;\n  containerClassName?: string;\n  forceUpdateBounds?: boolean;\n};\n\ntype ControlledParentModeHighlightProps<T extends React.ElementType = 'div'> =\n  BaseHighlightProps<T> &\n    ParentModeHighlightProps & {\n      mode: 'parent';\n      controlledItems: true;\n      children: React.ReactNode;\n    };\n\ntype ControlledChildrenModeHighlightProps<T extends React.ElementType = 'div'> =\n  BaseHighlightProps<T> & {\n    mode?: 'children' | undefined;\n    controlledItems: true;\n    children: React.ReactNode;\n  };\n\ntype UncontrolledParentModeHighlightProps<T extends React.ElementType = 'div'> =\n  BaseHighlightProps<T> &\n    ParentModeHighlightProps & {\n      mode: 'parent';\n      controlledItems?: false;\n      itemsClassName?: string;\n      children: React.ReactElement | React.ReactElement[];\n    };\n\ntype UncontrolledChildrenModeHighlightProps<\n  T extends React.ElementType = 'div',\n> = BaseHighlightProps<T> & {\n  mode?: 'children';\n  controlledItems?: false;\n  itemsClassName?: string;\n  children: React.ReactElement | React.ReactElement[];\n};\n\ntype HighlightProps<T extends React.ElementType = 'div'> =\n  | ControlledParentModeHighlightProps<T>\n  | ControlledChildrenModeHighlightProps<T>\n  | UncontrolledParentModeHighlightProps<T>\n  | UncontrolledChildrenModeHighlightProps<T>;\n\nfunction Highlight<T extends React.ElementType = 'div'>({\n  ref,\n  ...props\n}: HighlightProps<T>) {\n  const {\n    as: Component = 'div',\n    children,\n    value,\n    defaultValue,\n    onValueChange,\n    className,\n    style,\n    transition = { type: 'spring', stiffness: 350, damping: 35 },\n    hover = false,\n    click = true,\n    enabled = true,\n    controlledItems,\n    disabled = false,\n    exitDelay = 200,\n    mode = 'children',\n  } = props;\n\n  const localRef = React.useRef<HTMLDivElement>(null);\n  React.useImperativeHandle(ref, () => localRef.current as HTMLDivElement);\n\n  const propsBoundsOffset = (props as ParentModeHighlightProps)?.boundsOffset;\n  const boundsOffset = propsBoundsOffset ?? DEFAULT_BOUNDS_OFFSET;\n  const boundsOffsetTop = boundsOffset.top ?? 0;\n  const boundsOffsetLeft = boundsOffset.left ?? 0;\n  const boundsOffsetWidth = boundsOffset.width ?? 0;\n  const boundsOffsetHeight = boundsOffset.height ?? 0;\n\n  const boundsOffsetRef = React.useRef({\n    top: boundsOffsetTop,\n    left: boundsOffsetLeft,\n    width: boundsOffsetWidth,\n    height: boundsOffsetHeight,\n  });\n\n  React.useEffect(() => {\n    boundsOffsetRef.current = {\n      top: boundsOffsetTop,\n      left: boundsOffsetLeft,\n      width: boundsOffsetWidth,\n      height: boundsOffsetHeight,\n    };\n  }, [\n    boundsOffsetTop,\n    boundsOffsetLeft,\n    boundsOffsetWidth,\n    boundsOffsetHeight,\n  ]);\n\n  const [activeValue, setActiveValue] = React.useState<string | null>(\n    value ?? defaultValue ?? null,\n  );\n  const [boundsState, setBoundsState] = React.useState<Bounds | null>(null);\n  const [activeClassNameState, setActiveClassNameState] =\n    React.useState<string>('');\n\n  const safeSetActiveValue = (id: string | null) => {\n    setActiveValue((prev) => {\n      if (prev !== id) {\n        onValueChange?.(id);\n        return id;\n      }\n      return prev;\n    });\n  };\n\n  const safeSetBoundsRef = React.useRef<\n    ((bounds: DOMRect) => void) | undefined\n  >(undefined);\n\n  React.useEffect(() => {\n    safeSetBoundsRef.current = (bounds: DOMRect) => {\n      if (!localRef.current) return;\n\n      const containerRect = localRef.current.getBoundingClientRect();\n      const offset = boundsOffsetRef.current;\n      const newBounds: Bounds = {\n        top: bounds.top - containerRect.top + offset.top,\n        left: bounds.left - containerRect.left + offset.left,\n        width: bounds.width + offset.width,\n        height: bounds.height + offset.height,\n      };\n\n      setBoundsState((prev) => {\n        if (\n          prev &&\n          prev.top === newBounds.top &&\n          prev.left === newBounds.left &&\n          prev.width === newBounds.width &&\n          prev.height === newBounds.height\n        ) {\n          return prev;\n        }\n        return newBounds;\n      });\n    };\n  });\n\n  const safeSetBounds = (bounds: DOMRect) => {\n    safeSetBoundsRef.current?.(bounds);\n  };\n\n  const clearBounds = React.useCallback(() => {\n    setBoundsState((prev) => (prev === null ? prev : null));\n  }, []);\n\n  React.useEffect(() => {\n    if (value !== undefined) setActiveValue(value);\n    else if (defaultValue !== undefined) setActiveValue(defaultValue);\n  }, [value, defaultValue]);\n\n  const id = React.useId();\n\n  React.useEffect(() => {\n    if (mode !== 'parent') return;\n    const container = localRef.current;\n    if (!container) return;\n\n    const onScroll = () => {\n      if (!activeValue) return;\n      const activeEl = container.querySelector<HTMLElement>(\n        `[data-value=\"${activeValue}\"][data-highlight=\"true\"]`,\n      );\n      if (activeEl)\n        safeSetBoundsRef.current?.(activeEl.getBoundingClientRect());\n    };\n\n    container.addEventListener('scroll', onScroll, { passive: true });\n    return () => container.removeEventListener('scroll', onScroll);\n  }, [mode, activeValue]);\n\n  const render = (children: React.ReactNode) => {\n    if (mode === 'parent') {\n      return (\n        <Component\n          ref={localRef}\n          data-slot=\"motion-highlight-container\"\n          style={{ position: 'relative', zIndex: 1 }}\n          className={(props as ParentModeHighlightProps)?.containerClassName}\n        >\n          <AnimatePresence initial={false} mode=\"wait\">\n            {boundsState && (\n              <motion.div\n                data-slot=\"motion-highlight\"\n                animate={{\n                  top: boundsState.top,\n                  left: boundsState.left,\n                  width: boundsState.width,\n                  height: boundsState.height,\n                  opacity: 1,\n                }}\n                initial={{\n                  top: boundsState.top,\n                  left: boundsState.left,\n                  width: boundsState.width,\n                  height: boundsState.height,\n                  opacity: 0,\n                }}\n                exit={{\n                  opacity: 0,\n                  transition: {\n                    ...transition,\n                    delay: (transition?.delay ?? 0) + (exitDelay ?? 0) / 1000,\n                  },\n                }}\n                transition={transition}\n                style={{ position: 'absolute', zIndex: 0, ...style }}\n                className={cn(className, activeClassNameState)}\n              />\n            )}\n          </AnimatePresence>\n          {children}\n        </Component>\n      );\n    }\n\n    return children;\n  };\n\n  return (\n    <HighlightContext.Provider\n      value={{\n        mode,\n        activeValue,\n        setActiveValue: safeSetActiveValue,\n        id,\n        hover,\n        click,\n        className,\n        style,\n        transition,\n        disabled,\n        enabled,\n        exitDelay,\n        setBounds: safeSetBounds,\n        clearBounds,\n        activeClassName: activeClassNameState,\n        setActiveClassName: setActiveClassNameState,\n        forceUpdateBounds: (props as ParentModeHighlightProps)\n          ?.forceUpdateBounds,\n      }}\n    >\n      {enabled\n        ? controlledItems\n          ? render(children)\n          : render(\n              React.Children.map(children, (child, index) => (\n                <HighlightItem key={index} className={props?.itemsClassName}>\n                  {child}\n                </HighlightItem>\n              )),\n            )\n        : children}\n    </HighlightContext.Provider>\n  );\n}\n\nfunction getNonOverridingDataAttributes(\n  element: React.ReactElement,\n  dataAttributes: Record<string, unknown>,\n): Record<string, unknown> {\n  return Object.keys(dataAttributes).reduce<Record<string, unknown>>(\n    (acc, key) => {\n      if ((element.props as Record<string, unknown>)[key] === undefined) {\n        acc[key] = dataAttributes[key];\n      }\n      return acc;\n    },\n    {},\n  );\n}\n\ntype ExtendedChildProps = React.ComponentProps<'div'> & {\n  id?: string;\n  ref?: React.Ref<HTMLElement>;\n  'data-active'?: string;\n  'data-value'?: string;\n  'data-disabled'?: boolean;\n  'data-highlight'?: boolean;\n  'data-slot'?: string;\n};\n\ntype HighlightItemProps<T extends React.ElementType = 'div'> =\n  React.ComponentProps<T> & {\n    as?: T;\n    children: React.ReactElement;\n    id?: string;\n    value?: string;\n    className?: string;\n    style?: React.CSSProperties;\n    transition?: Transition;\n    activeClassName?: string;\n    disabled?: boolean;\n    exitDelay?: number;\n    asChild?: boolean;\n    forceUpdateBounds?: boolean;\n  };\n\nfunction HighlightItem<T extends React.ElementType>({\n  ref,\n  as,\n  children,\n  id,\n  value,\n  className,\n  style,\n  transition,\n  disabled = false,\n  activeClassName,\n  exitDelay,\n  asChild = false,\n  forceUpdateBounds,\n  ...props\n}: HighlightItemProps<T>) {\n  const itemId = React.useId();\n  const {\n    activeValue,\n    setActiveValue,\n    mode,\n    setBounds,\n    clearBounds,\n    hover,\n    click,\n    enabled,\n    className: contextClassName,\n    style: contextStyle,\n    transition: contextTransition,\n    id: contextId,\n    disabled: contextDisabled,\n    exitDelay: contextExitDelay,\n    forceUpdateBounds: contextForceUpdateBounds,\n    setActiveClassName,\n  } = useHighlight();\n\n  const Component = as ?? 'div';\n  const element = children as React.ReactElement<ExtendedChildProps>;\n  const childValue =\n    id ?? value ?? element.props?.['data-value'] ?? element.props?.id ?? itemId;\n  const isActive = activeValue === childValue;\n  const isDisabled = disabled === undefined ? contextDisabled : disabled;\n  const itemTransition = transition ?? contextTransition;\n\n  const localRef = React.useRef<HTMLDivElement>(null);\n  React.useImperativeHandle(ref, () => localRef.current as HTMLDivElement);\n\n  const refCallback = React.useCallback((node: HTMLElement | null) => {\n    localRef.current = node as HTMLDivElement;\n  }, []);\n\n  React.useEffect(() => {\n    if (mode !== 'parent') return;\n    let rafId: number;\n    let previousBounds: Bounds | null = null;\n    const shouldUpdateBounds =\n      forceUpdateBounds === true ||\n      (contextForceUpdateBounds && forceUpdateBounds !== false);\n\n    const updateBounds = () => {\n      if (!localRef.current) return;\n\n      const bounds = localRef.current.getBoundingClientRect();\n\n      if (shouldUpdateBounds) {\n        if (\n          previousBounds &&\n          previousBounds.top === bounds.top &&\n          previousBounds.left === bounds.left &&\n          previousBounds.width === bounds.width &&\n          previousBounds.height === bounds.height\n        ) {\n          rafId = requestAnimationFrame(updateBounds);\n          return;\n        }\n        previousBounds = bounds;\n        rafId = requestAnimationFrame(updateBounds);\n      }\n\n      setBounds(bounds);\n    };\n\n    if (isActive) {\n      updateBounds();\n      setActiveClassName(activeClassName ?? '');\n    } else if (!activeValue) clearBounds();\n\n    if (shouldUpdateBounds) return () => cancelAnimationFrame(rafId);\n  }, [\n    mode,\n    isActive,\n    activeValue,\n    setBounds,\n    clearBounds,\n    activeClassName,\n    setActiveClassName,\n    forceUpdateBounds,\n    contextForceUpdateBounds,\n  ]);\n\n  if (!React.isValidElement(children)) return children;\n\n  const dataAttributes = {\n    'data-active': isActive ? 'true' : 'false',\n    'aria-selected': isActive,\n    'data-disabled': isDisabled,\n    'data-value': childValue,\n    'data-highlight': true,\n  };\n\n  const commonHandlers = hover\n    ? {\n        onMouseEnter: (e: React.MouseEvent<HTMLDivElement>) => {\n          setActiveValue(childValue);\n          element.props.onMouseEnter?.(e);\n        },\n        onMouseLeave: (e: React.MouseEvent<HTMLDivElement>) => {\n          setActiveValue(null);\n          element.props.onMouseLeave?.(e);\n        },\n      }\n    : click\n      ? {\n          onClick: (e: React.MouseEvent<HTMLDivElement>) => {\n            setActiveValue(childValue);\n            element.props.onClick?.(e);\n          },\n        }\n      : {};\n\n  if (asChild) {\n    if (mode === 'children') {\n      return React.cloneElement(\n        element,\n        {\n          key: childValue,\n          ref: refCallback,\n          className: cn('relative', element.props.className),\n          ...getNonOverridingDataAttributes(element, {\n            ...dataAttributes,\n            'data-slot': 'motion-highlight-item-container',\n          }),\n          ...commonHandlers,\n          ...props,\n        },\n        <>\n          <AnimatePresence initial={false} mode=\"wait\">\n            {isActive && !isDisabled && (\n              <motion.div\n                layoutId={`transition-background-${contextId}`}\n                data-slot=\"motion-highlight\"\n                style={{\n                  position: 'absolute',\n                  zIndex: 0,\n                  ...contextStyle,\n                  ...style,\n                }}\n                className={cn(contextClassName, activeClassName)}\n                transition={itemTransition}\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{\n                  opacity: 0,\n                  transition: {\n                    ...itemTransition,\n                    delay:\n                      (itemTransition?.delay ?? 0) +\n                      (exitDelay ?? contextExitDelay ?? 0) / 1000,\n                  },\n                }}\n                {...dataAttributes}\n              />\n            )}\n          </AnimatePresence>\n\n          <Component\n            data-slot=\"motion-highlight-item\"\n            style={{ position: 'relative', zIndex: 1 }}\n            className={className}\n            {...dataAttributes}\n          >\n            {children}\n          </Component>\n        </>,\n      );\n    }\n\n    return React.cloneElement(element, {\n      ref: refCallback,\n      ...getNonOverridingDataAttributes(element, {\n        ...dataAttributes,\n        'data-slot': 'motion-highlight-item',\n      }),\n      ...commonHandlers,\n    });\n  }\n\n  return enabled ? (\n    <Component\n      key={childValue}\n      ref={localRef}\n      data-slot=\"motion-highlight-item-container\"\n      className={cn(mode === 'children' && 'relative', className)}\n      {...dataAttributes}\n      {...props}\n      {...commonHandlers}\n    >\n      {mode === 'children' && (\n        <AnimatePresence initial={false} mode=\"wait\">\n          {isActive && !isDisabled && (\n            <motion.div\n              layoutId={`transition-background-${contextId}`}\n              data-slot=\"motion-highlight\"\n              style={{\n                position: 'absolute',\n                zIndex: 0,\n                ...contextStyle,\n                ...style,\n              }}\n              className={cn(contextClassName, activeClassName)}\n              transition={itemTransition}\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{\n                opacity: 0,\n                transition: {\n                  ...itemTransition,\n                  delay:\n                    (itemTransition?.delay ?? 0) +\n                    (exitDelay ?? contextExitDelay ?? 0) / 1000,\n                },\n              }}\n              {...dataAttributes}\n            />\n          )}\n        </AnimatePresence>\n      )}\n\n      {React.cloneElement(element, {\n        style: { position: 'relative', zIndex: 1 },\n        className: element.props.className,\n        ...getNonOverridingDataAttributes(element, {\n          ...dataAttributes,\n          'data-slot': 'motion-highlight-item',\n        }),\n      })}\n    </Component>\n  ) : (\n    children\n  );\n}\n\nexport {\n  Highlight,\n  HighlightItem,\n  useHighlight,\n  type HighlightProps,\n  type HighlightItemProps,\n};\n\n\n//Helper functions\n\nconst MOBILE_BREAKPOINT = 768\n\nexport function useIsMobile() {\n  const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)\n\n  React.useEffect(() => {\n    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)\n    const onChange = () => {\n      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n    }\n    mql.addEventListener(\"change\", onChange)\n    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n    return () => mql.removeEventListener(\"change\", onChange)\n  }, [])\n\n  return !!isMobile\n}\n\n\nfunction getStrictContext<T>(\n  name?: string,\n): readonly [\n  ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => React.JSX.Element,\n  () => T,\n] {\n  const Context = React.createContext<T | undefined>(undefined);\n\n  const Provider = ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => <Context.Provider value={value}>{children}</Context.Provider>;\n\n  const useSafeContext = () => {\n    const ctx = React.useContext(Context);\n    if (ctx === undefined) {\n      throw new Error(`useContext must be used within ${name ?? 'a Provider'}`);\n    }\n    return ctx;\n  };\n\n  return [Provider, useSafeContext] as const;\n}\n\nexport { getStrictContext };\n\n\n\n",
      "type": "registry:ui",
      "target": "components/ui/sidebar.tsx"
    },
    {
      "path": "src/components/watermelon-ui/tooltip-animated.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport {\n  motion,\n  AnimatePresence,\n  LayoutGroup,\n  type Transition,\n  type HTMLMotionProps,\n  isMotionComponent,\n} from 'motion/react';\nimport {\n  useFloating,\n  autoUpdate,\n  offset as floatingOffset,\n  flip,\n  shift,\n  arrow as floatingArrow,\n  FloatingPortal,\n  FloatingArrow,\n  type UseFloatingReturn,\n} from '@floating-ui/react';\nimport { cn } from '@/lib/utils';\n\ntype TooltipProviderProps = TooltipProviderPrimitiveProps;\n\nfunction TooltipProvider({ openDelay = 0, ...props }: TooltipProviderProps) {\n  return <TooltipProviderPrimitive openDelay={openDelay} {...props} />;\n}\n\ntype TooltipProps = TooltipPrimitiveProps;\n\nfunction Tooltip({ sideOffset = 10, ...props }: TooltipProps) {\n  return <TooltipPrimitive sideOffset={sideOffset} {...props} />;\n}\n\ntype TooltipTriggerProps = TooltipTriggerPrimitveProps;\n\nfunction TooltipTrigger({ ...props }: TooltipTriggerProps) {\n  return <TooltipTriggerPrimitive {...props} />;\n}\n\ntype TooltipContentProps = Omit<TooltipContentPrimiviteProps, 'asChild'> & {\n  children: React.ReactNode;\n  layout?: boolean | 'position' | 'size' | 'preserve-aspect';\n};\n\nfunction TooltipContent({\n  className,\n  children,\n  layout = 'preserve-aspect',\n  ...props\n}: TooltipContentProps) {\n  return (\n    <TooltipContentPrimitive\n      className={cn(\n        'z-50 w-fit bg-primary text-primary-foreground rounded-md',\n        className,\n      )}\n      {...props}\n    >\n      <motion.div className=\"overflow-hidden px-3 py-1.5 text-xs text-balance\">\n        <motion.div layout={layout}>{children}</motion.div>\n      </motion.div>\n      <TooltipArrowPrimitive\n        className=\"fill-primary size-3 data-[side='bottom']:translate-y-[1px] data-[side='right']:translate-x-[1px] data-[side='left']:translate-x-[-1px] data-[side='top']:translate-y-[-1px]\"\n        tipRadius={2}\n      />\n    </TooltipContentPrimitive>\n  );\n}\n\nexport {\n  TooltipProvider,\n  Tooltip,\n  TooltipTrigger,\n  TooltipContent,\n  type TooltipProviderProps,\n  type TooltipProps,\n  type TooltipTriggerProps,\n  type TooltipContentProps,\n};\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\ntype Align = 'start' | 'center' | 'end';\n\ntype TooltipData = {\n  contentProps: HTMLMotionProps<'div'>;\n  contentAsChild: boolean;\n  rect: DOMRect;\n  side: Side;\n  sideOffset: number;\n  align: Align;\n  alignOffset: number;\n  id: string;\n};\n\ntype GlobalTooltipContextType = {\n  showTooltip: (data: TooltipData) => void;\n  hideTooltip: () => void;\n  hideImmediate: () => void;\n  currentTooltip: TooltipData | null;\n  transition: Transition;\n  globalId: string;\n  setReferenceEl: (el: HTMLElement | null) => void;\n  referenceElRef: React.RefObject<HTMLElement | null>;\n};\n\nconst [GlobalTooltipProvider, useGlobalTooltip] =\n  getStrictContext<GlobalTooltipContextType>('GlobalTooltipProvider');\n\ntype TooltipContextType = {\n  props: HTMLMotionProps<'div'>;\n  setProps: React.Dispatch<React.SetStateAction<HTMLMotionProps<'div'>>>;\n  asChild: boolean;\n  setAsChild: React.Dispatch<React.SetStateAction<boolean>>;\n  side: Side;\n  sideOffset: number;\n  align: Align;\n  alignOffset: number;\n  id: string;\n};\n\nconst [LocalTooltipProvider, useTooltip] = getStrictContext<TooltipContextType>(\n  'LocalTooltipProvider',\n);\n\nfunction getResolvedSide(placement: Side | `${Side}-${Align}`) {\n  if (placement.includes('-')) {\n    return placement.split('-')[0] as Side;\n  }\n  return placement as Side;\n}\n\nfunction initialFromSide(side: Side): Partial<Record<'x' | 'y', number>> {\n  if (side === 'top') return { y: 15 };\n  if (side === 'bottom') return { y: -15 };\n  if (side === 'left') return { x: 15 };\n  return { x: -15 };\n}\n\ntype TooltipProviderPrimitiveProps = {\n  children: React.ReactNode;\n  id?: string;\n  openDelay?: number;\n  closeDelay?: number;\n  transition?: Transition;\n};\n\nfunction TooltipProviderPrimitive({\n  children,\n  id,\n  openDelay = 700,\n  closeDelay = 300,\n  transition = { type: 'spring', stiffness: 300, damping: 35 },\n}: TooltipProviderProps) {\n  const globalId = React.useId();\n  const [currentTooltip, setCurrentTooltip] =\n    React.useState<TooltipData | null>(null);\n  const timeoutRef = React.useRef<number | null>(null);\n  const lastCloseTimeRef = React.useRef<number>(0);\n  const referenceElRef = React.useRef<HTMLElement | null>(null);\n\n  const showTooltip = React.useCallback(\n    (data: TooltipData) => {\n      if (timeoutRef.current) clearTimeout(timeoutRef.current);\n      if (currentTooltip !== null) {\n        setCurrentTooltip(data);\n        return;\n      }\n      const now = Date.now();\n      const delay = now - lastCloseTimeRef.current < closeDelay ? 0 : openDelay;\n      timeoutRef.current = window.setTimeout(\n        () => setCurrentTooltip(data),\n        delay,\n      );\n    },\n    [openDelay, closeDelay, currentTooltip],\n  );\n\n  const hideTooltip = React.useCallback(() => {\n    if (timeoutRef.current) clearTimeout(timeoutRef.current);\n    timeoutRef.current = window.setTimeout(() => {\n      setCurrentTooltip(null);\n      lastCloseTimeRef.current = Date.now();\n    }, closeDelay);\n  }, [closeDelay]);\n\n  const hideImmediate = React.useCallback(() => {\n    if (timeoutRef.current) clearTimeout(timeoutRef.current);\n    setCurrentTooltip(null);\n    lastCloseTimeRef.current = Date.now();\n  }, []);\n\n  const setReferenceEl = React.useCallback((el: HTMLElement | null) => {\n    referenceElRef.current = el;\n  }, []);\n\n  React.useEffect(() => {\n    const onKeyDown = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') hideImmediate();\n    };\n    window.addEventListener('keydown', onKeyDown, true);\n    window.addEventListener('scroll', hideImmediate, true);\n    window.addEventListener('resize', hideImmediate, true);\n    return () => {\n      window.removeEventListener('keydown', onKeyDown, true);\n      window.removeEventListener('scroll', hideImmediate, true);\n      window.removeEventListener('resize', hideImmediate, true);\n    };\n  }, [hideImmediate]);\n\n  return (\n    <GlobalTooltipProvider\n      value={{\n        showTooltip,\n        hideTooltip,\n        hideImmediate,\n        currentTooltip,\n        transition,\n        globalId: id ?? globalId,\n        setReferenceEl,\n        referenceElRef,\n      }}\n    >\n      <LayoutGroup>{children}</LayoutGroup>\n      <TooltipOverlay />\n    </GlobalTooltipProvider>\n  );\n}\n\ntype RenderedTooltipContextType = {\n  side: Side;\n  align: Align;\n  open: boolean;\n};\n\nconst [RenderedTooltipProvider, useRenderedTooltip] =\n  getStrictContext<RenderedTooltipContextType>('RenderedTooltipContext');\n\ntype FloatingContextType = {\n  context: UseFloatingReturn['context'];\n  arrowRef: React.RefObject<SVGSVGElement | null>;\n};\n\nconst [FloatingProvider, useFloatingContext] =\n  getStrictContext<FloatingContextType>('FloatingContext');\n\nconst MotionTooltipArrow = motion.create(FloatingArrow);\n\ntype TooltipArrowProps = Omit<\n  React.ComponentProps<typeof MotionTooltipArrow>,\n  'context'\n> & {\n  withTransition?: boolean;\n};\n\nfunction TooltipArrowPrimitive({\n  ref,\n  withTransition = true,\n  ...props\n}: TooltipArrowProps) {\n  const { side, align, open } = useRenderedTooltip();\n  const { context, arrowRef } = useFloatingContext();\n  const { transition, globalId } = useGlobalTooltip();\n  React.useImperativeHandle(ref, () => arrowRef.current as SVGSVGElement);\n\n  const deg = { top: 0, right: 90, bottom: 180, left: -90 }[side];\n\n  return (\n    <MotionTooltipArrow\n      ref={arrowRef}\n      context={context}\n      data-state={open ? 'open' : 'closed'}\n      data-side={side}\n      data-align={align}\n      data-slot=\"tooltip-arrow\"\n      style={{ rotate: deg }}\n      layoutId={withTransition ? `tooltip-arrow-${globalId}` : undefined}\n      transition={withTransition ? transition : undefined}\n      {...props}\n    />\n  );\n}\n\ntype TooltipPortalProps = React.ComponentProps<typeof FloatingPortal>;\n\nfunction TooltipPortal(props: TooltipPortalProps) {\n  return <FloatingPortal {...props} />;\n}\n\nfunction TooltipOverlay() {\n  const { currentTooltip, transition, globalId, referenceElRef } =\n    useGlobalTooltip();\n\n  const [rendered, setRendered] = React.useState<{\n    data: TooltipData | null;\n    open: boolean;\n  }>({ data: null, open: false });\n\n  const arrowRef = React.useRef<SVGSVGElement | null>(null);\n\n  const side = rendered.data?.side ?? 'top';\n  const align = rendered.data?.align ?? 'center';\n\n  const { refs, x, y, strategy, context, update } = useFloating({\n    placement: align === 'center' ? side : `${side}-${align}`,\n    whileElementsMounted: autoUpdate,\n    middleware: [\n      floatingOffset({\n        mainAxis: rendered.data?.sideOffset ?? 0,\n        crossAxis: rendered.data?.alignOffset ?? 0,\n      }),\n      flip(),\n      shift({ padding: 8 }),\n\n      floatingArrow({ element: arrowRef }),\n    ],\n  });\n\n  React.useEffect(() => {\n    if (currentTooltip) {\n      setRendered({ data: currentTooltip, open: true });\n    } else {\n      setRendered((p) => (p.data ? { ...p, open: false } : p));\n    }\n  }, [currentTooltip]);\n\n  React.useLayoutEffect(() => {\n    if (referenceElRef.current) {\n      refs.setReference(referenceElRef.current);\n      update();\n    }\n  }, [referenceElRef, refs, update, rendered.data]);\n\n  const ready = x != null && y != null;\n  const Component = rendered.data?.contentAsChild ? Slot : motion.div;\n  const resolvedSide = getResolvedSide(context.placement);\n\n  return (\n    <AnimatePresence mode=\"wait\">\n      {rendered.data && ready && (\n        <TooltipPortal>\n          <div\n            ref={refs.setFloating}\n            data-slot=\"tooltip-overlay\"\n            data-side={resolvedSide}\n            data-align={rendered.data.align}\n            data-state={rendered.open ? 'open' : 'closed'}\n            style={{\n              position: strategy,\n              top: 0,\n              left: 0,\n              zIndex: 50,\n              transform: `translate3d(${x!}px, ${y!}px, 0)`,\n            }}\n          >\n            <FloatingProvider value={{ context, arrowRef }}>\n              <RenderedTooltipProvider\n                value={{\n                  side: resolvedSide,\n                  align: rendered.data.align,\n                  open: rendered.open,\n                }}\n              >\n                <Component\n                  data-slot=\"tooltip-content\"\n                  data-side={resolvedSide}\n                  data-align={rendered.data.align}\n                  data-state={rendered.open ? 'open' : 'closed'}\n                  layoutId={`tooltip-content-${globalId}`}\n                  initial={{\n                    opacity: 0,\n                    scale: 0,\n                    ...initialFromSide(rendered.data.side),\n                  }}\n                  animate={\n                    rendered.open\n                      ? { opacity: 1, scale: 1, x: 0, y: 0 }\n                      : {\n                        opacity: 0,\n                        scale: 0,\n                        ...initialFromSide(rendered.data.side),\n                      }\n                  }\n                  exit={{\n                    opacity: 0,\n                    scale: 0,\n                    ...initialFromSide(rendered.data.side),\n                  }}\n                  onAnimationComplete={() => {\n                    if (!rendered.open)\n                      setRendered({ data: null, open: false });\n                  }}\n                  transition={transition}\n                  {...rendered.data.contentProps}\n                  style={{\n                    position: 'relative',\n                    ...(rendered.data.contentProps?.style || {}),\n                  }}\n                />\n              </RenderedTooltipProvider>\n            </FloatingProvider>\n          </div>\n        </TooltipPortal>\n      )}\n    </AnimatePresence>\n  );\n}\n\ntype TooltipPrimitiveProps = {\n  children: React.ReactNode;\n  side?: Side;\n  sideOffset?: number;\n  align?: Align;\n  alignOffset?: number;\n};\n\nfunction TooltipPrimitive({\n  children,\n  side = 'top',\n  sideOffset = 0,\n  align = 'center',\n  alignOffset = 0,\n}: TooltipPrimitiveProps) {\n  const id = React.useId();\n  const [props, setProps] = React.useState<HTMLMotionProps<'div'>>({});\n  const [asChild, setAsChild] = React.useState(false);\n\n  return (\n    <LocalTooltipProvider\n      value={{\n        props,\n        setProps,\n        asChild,\n        setAsChild,\n        side,\n        sideOffset,\n        align,\n        alignOffset,\n        id,\n      }}\n    >\n      {children}\n    </LocalTooltipProvider>\n  );\n}\n\ntype TooltipContentPrimiviteProps = WithAsChild<HTMLMotionProps<'div'>>;\n\nfunction shallowEqualWithoutChildren(\n  a?: HTMLMotionProps<'div'>,\n  b?: HTMLMotionProps<'div'>,\n) {\n  if (a === b) return true;\n  if (!a || !b) return false;\n  const keysA = Object.keys(a).filter((k) => k !== 'children');\n  const keysB = Object.keys(b).filter((k) => k !== 'children');\n  if (keysA.length !== keysB.length) return false;\n  for (const k of keysA) {\n    // @ts-expect-error index\n    if (a[k] !== b[k]) return false;\n  }\n  return true;\n}\n\nfunction TooltipContentPrimitive({ asChild = false, ...props }: TooltipContentPrimiviteProps) {\n  const { setProps, setAsChild } = useTooltip();\n  const lastPropsRef = React.useRef<HTMLMotionProps<'div'> | undefined>(\n    undefined,\n  );\n\n  React.useEffect(() => {\n    if (!shallowEqualWithoutChildren(lastPropsRef.current, props)) {\n      lastPropsRef.current = props;\n      setProps(props);\n    }\n  }, [props, setProps]);\n\n  React.useEffect(() => {\n    setAsChild(asChild);\n  }, [asChild, setAsChild]);\n\n  return null;\n}\n\ntype TooltipTriggerPrimitveProps = WithAsChild<HTMLMotionProps<'div'>>;\n\nfunction TooltipTriggerPrimitive({\n  ref,\n  onMouseEnter,\n  onMouseLeave,\n  onFocus,\n  onBlur,\n  onPointerDown,\n  asChild = false,\n  ...props\n}: TooltipTriggerPrimitveProps) {\n  const {\n    props: contentProps,\n    asChild: contentAsChild,\n    side,\n    sideOffset,\n    align,\n    alignOffset,\n    id,\n  } = useTooltip();\n  const {\n    showTooltip,\n    hideTooltip,\n    hideImmediate,\n    currentTooltip,\n    setReferenceEl,\n  } = useGlobalTooltip();\n\n  const triggerRef = React.useRef<HTMLDivElement>(null);\n  React.useImperativeHandle(ref, () => triggerRef.current as HTMLDivElement);\n\n  const suppressNextFocusRef = React.useRef(false);\n\n  const handleOpen = React.useCallback(() => {\n    if (!triggerRef.current) return;\n    setReferenceEl(triggerRef.current);\n    const rect = triggerRef.current.getBoundingClientRect();\n    showTooltip({\n      contentProps,\n      contentAsChild,\n      rect,\n      side,\n      sideOffset,\n      align,\n      alignOffset,\n      id,\n    });\n  }, [\n    showTooltip,\n    setReferenceEl,\n    contentProps,\n    contentAsChild,\n    side,\n    sideOffset,\n    align,\n    alignOffset,\n    id,\n  ]);\n\n  const handlePointerDown = React.useCallback(\n    (e: React.PointerEvent<HTMLDivElement>) => {\n      onPointerDown?.(e);\n      if (currentTooltip?.id === id) {\n        suppressNextFocusRef.current = true;\n        hideImmediate();\n        Promise.resolve().then(() => {\n          suppressNextFocusRef.current = false;\n        });\n      }\n    },\n    [onPointerDown, currentTooltip?.id, id, hideImmediate],\n  );\n\n  const handleMouseEnter = React.useCallback(\n    (e: React.MouseEvent<HTMLDivElement>) => {\n      onMouseEnter?.(e);\n      handleOpen();\n    },\n    [handleOpen, onMouseEnter],\n  );\n\n  const handleMouseLeave = React.useCallback(\n    (e: React.MouseEvent<HTMLDivElement>) => {\n      onMouseLeave?.(e);\n      hideTooltip();\n    },\n    [hideTooltip, onMouseLeave],\n  );\n\n  const handleFocus = React.useCallback(\n    (e: React.FocusEvent<HTMLDivElement>) => {\n      onFocus?.(e);\n      if (suppressNextFocusRef.current) return;\n      handleOpen();\n    },\n    [handleOpen, onFocus],\n  );\n\n  const handleBlur = React.useCallback(\n    (e: React.FocusEvent<HTMLDivElement>) => {\n      onBlur?.(e);\n      hideTooltip();\n    },\n    [hideTooltip, onBlur],\n  );\n\n  const Component = asChild ? Slot : motion.div;\n\n  return (\n    <Component\n      ref={triggerRef}\n      onPointerDown={handlePointerDown}\n      onMouseEnter={handleMouseEnter}\n      onMouseLeave={handleMouseLeave}\n      onFocus={handleFocus}\n      onBlur={handleBlur}\n      data-slot=\"tooltip-trigger\"\n      data-side={side}\n      data-align={align}\n      data-state={currentTooltip?.id === id ? 'open' : 'closed'}\n      {...props}\n    />\n  );\n}\n\nfunction getStrictContext<T>(\n  name?: string,\n): readonly [\n  ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => React.JSX.Element,\n  () => T,\n] {\n  const Context = React.createContext<T | undefined>(undefined);\n\n  const Provider = ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => <Context.Provider value={value}>{children}</Context.Provider>;\n\n  const useSafeContext = () => {\n    const ctx = React.useContext(Context);\n    if (ctx === undefined) {\n      throw new Error(`useContext must be used within ${name ?? 'a Provider'}`);\n    }\n    return ctx;\n  };\n\n  return [Provider, useSafeContext] as const;\n}\n\nexport { getStrictContext };\n\ntype AnyProps = Record<string, unknown>;\n\ntype DOMMotionProps<T extends HTMLElement = HTMLElement> = Omit<\n  HTMLMotionProps<keyof HTMLElementTagNameMap>,\n  'ref'\n> & { ref?: React.Ref<T> };\n\ntype WithAsChild<Base extends object> =\n  | (Base & { asChild: true; children: React.ReactElement })\n  | (Base & { asChild?: false | undefined });\n\ntype SlotProps<T extends HTMLElement = HTMLElement> = {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  children?: any;\n} & DOMMotionProps<T>;\n\nfunction mergeRefs<T>(\n  ...refs: (React.Ref<T> | undefined)[]\n): React.RefCallback<T> {\n  return (node) => {\n    refs.forEach((ref) => {\n      if (!ref) return;\n      if (typeof ref === 'function') {\n        ref(node);\n      } else {\n        (ref as React.RefObject<T | null>).current = node;\n      }\n    });\n  };\n}\n\nfunction mergeProps<T extends HTMLElement>(\n  childProps: AnyProps,\n  slotProps: DOMMotionProps<T>,\n): AnyProps {\n  const merged: AnyProps = { ...childProps, ...slotProps };\n\n  if (childProps.className || slotProps.className) {\n    merged.className = cn(\n      childProps.className as string,\n      slotProps.className as string,\n    );\n  }\n\n  if (childProps.style || slotProps.style) {\n    merged.style = {\n      ...(childProps.style as React.CSSProperties),\n      ...(slotProps.style as React.CSSProperties),\n    };\n  }\n\n  return merged;\n}\n\nconst motionCache = new Map<React.ElementType, React.ElementType>();\n\nfunction getMotionComponent(type: React.ElementType) {\n  if (typeof type === 'object' && type !== null && isMotionComponent(type)) return type;\n  if (!motionCache.has(type)) {\n    motionCache.set(type, motion.create(type));\n  }\n  return motionCache.get(type)!;\n}\n\nfunction Slot<T extends HTMLElement = HTMLElement>({\n  children,\n  ref,\n  ...props\n}: SlotProps<T>) {\n  if (!React.isValidElement(children)) return null;\n\n  const ComponentType = getMotionComponent(children.type as React.ElementType);\n\n  const { ref: childRef, ...childProps } = children.props as AnyProps;\n\n  const mergedProps = mergeProps(childProps, props);\n\n  return (\n    // eslint-disable-next-line react-hooks/static-components\n    <ComponentType {...mergedProps} ref={mergeRefs(childRef as React.Ref<T>, ref)} />\n  );\n}\n\nexport {\n  Slot,\n  type SlotProps,\n  type WithAsChild,\n  type DOMMotionProps,\n  type AnyProps,\n};\n",
      "type": "registry:component",
      "target": "components/watermelon-ui/tooltip-animated.tsx"
    }
  ],
  "type": "registry:ui"
}
