{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dropdown-menu",
  "title": "UI Dropdown Menu",
  "description": "A dropdown menu whose opened/closed state is a pure function of the timeline; the trigger reuses the Button primitive and the reveal panel composes DropdownMenuItem rows. The panel fade, scale, lift, and chevron are keyframed presets.",
  "dependencies": ["remotion"],
  "registryDependencies": [
    "@remocn/remocn-ui",
    "@remocn/button",
    "@remocn/dropdown-menu-item"
  ],
  "files": [
    {
      "path": "registry/remocn-ui/dropdown-menu/index.tsx",
      "content": "\"use client\";\n\nimport {\n  type ButtonStyle,\n  type ButtonStyleContext,\n  buttonStyle,\n  buttonStyleContext,\n} from \"@/components/remocn/button\";\nimport {\n  DropdownMenuItemRow,\n  type DropdownMenuItemStyle,\n  type DropdownMenuItemStyleContext,\n  dropdownMenuItemStyle,\n  dropdownMenuItemStyleContext,\n} from \"@/components/remocn/dropdown-menu-item\";\nimport { type RemocnTheme, useRemocnTheme } from \"@/lib/remocn-ui\";\n\nexport type DropdownMenuState = \"opened\" | \"closed\";\n\nexport interface DropdownMenuStyle {\n  panelOpacity: number;\n  panelScale: number;\n  panelTranslateY: number;\n  chevronRotation: number;\n}\n\nexport interface DropdownMenuStyleContext {\n  triggerCtx: ButtonStyleContext;\n  panelBg: string;\n  panelBorder: string;\n  triggerFg: string;\n  mutedFg: string;\n  radius: number;\n  itemCtx: DropdownMenuItemStyleContext;\n}\n\nexport function dropdownMenuStyleContext(\n  theme: RemocnTheme,\n): DropdownMenuStyleContext {\n  return {\n    triggerCtx: buttonStyleContext(\"outline\", theme),\n    panelBg: theme.popover,\n    panelBorder: theme.border,\n    triggerFg: theme.foreground,\n    mutedFg: theme.mutedForeground,\n    radius: theme.radius,\n    itemCtx: dropdownMenuItemStyleContext(theme),\n  };\n}\n\nexport function dropdownMenuStyle(\n  state: DropdownMenuState,\n  _ctx: DropdownMenuStyleContext,\n): DropdownMenuStyle {\n  switch (state) {\n    case \"opened\":\n      return {\n        panelOpacity: 1,\n        panelScale: 1,\n        panelTranslateY: 0,\n        chevronRotation: 180,\n      };\n    default:\n      return {\n        panelOpacity: 0,\n        panelScale: 0.96,\n        panelTranslateY: -4,\n        chevronRotation: 0,\n      };\n  }\n}\n\nconst WIDTH = 240;\n\nexport interface DropdownMenuProps {\n  state?: DropdownMenuState;\n  style?: DropdownMenuStyle;\n  label?: string;\n  items?: string[];\n  highlightedIndex?: number;\n  pressedIndex?: number;\n  itemStyles?: (DropdownMenuItemStyle | undefined)[];\n  triggerStyle?: ButtonStyle;\n  theme?: Partial<RemocnTheme>;\n  className?: string;\n}\n\nexport function DropdownMenu({\n  state = \"closed\",\n  style,\n  label = \"Options\",\n  items = [\"Profile\", \"Billing\", \"Settings\", \"Log out\"],\n  highlightedIndex = -1,\n  pressedIndex = -1,\n  itemStyles,\n  triggerStyle,\n  theme: themeOverride,\n  className,\n}: DropdownMenuProps) {\n  const theme = useRemocnTheme(themeOverride, \"light\");\n\n  const ctx = dropdownMenuStyleContext(theme);\n  const v = style ?? dropdownMenuStyle(state, ctx);\n\n  const trigger = triggerStyle ?? buttonStyle(\"idle\", ctx.triggerCtx);\n\n  return (\n    <div\n      className={className}\n      style={{\n        position: \"absolute\",\n        inset: 0,\n        display: \"flex\",\n        alignItems: \"flex-start\",\n        justifyContent: \"center\",\n        paddingTop: 220,\n        background: \"transparent\",\n        fontFamily:\n          \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\",\n      }}\n    >\n      <div style={{ position: \"relative\", width: WIDTH }}>\n        {}\n        <div\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n            justifyContent: \"space-between\",\n            gap: 12,\n            width: WIDTH,\n            height: 40,\n            padding: \"0 16px\",\n            fontSize: 15,\n            fontWeight: 500,\n            letterSpacing: \"-0.01em\",\n            color: ctx.triggerFg,\n            background: trigger.background,\n            border: `1px solid ${ctx.panelBorder}`,\n            borderRadius: ctx.radius,\n            transform: `translateY(${trigger.translateY}px) scale(${trigger.scale})`,\n            boxSizing: \"border-box\",\n          }}\n        >\n          <span>{label}</span>\n          <svg\n            width={16}\n            height={16}\n            viewBox=\"0 0 24 24\"\n            fill=\"none\"\n            style={{\n              flexShrink: 0,\n              transform: `rotate(${v.chevronRotation}deg)`,\n            }}\n          >\n            <path\n              d=\"M6 9l6 6 6-6\"\n              stroke={ctx.mutedFg}\n              strokeWidth=\"2.2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            />\n          </svg>\n        </div>\n        {}\n        <div\n          style={{\n            position: \"absolute\",\n            top: 48,\n            left: 0,\n            width: WIDTH,\n            opacity: v.panelOpacity,\n            transform: `translateY(${v.panelTranslateY}px) scale(${v.panelScale})`,\n            transformOrigin: \"top\",\n            background: ctx.panelBg,\n            border: `1px solid ${ctx.panelBorder}`,\n            borderRadius: ctx.radius + 2,\n            padding: 4,\n            display: \"flex\",\n            flexDirection: \"column\",\n            gap: 2,\n            boxShadow: \"0 12px 32px -8px rgba(0,0,0,0.18)\",\n            boxSizing: \"border-box\",\n          }}\n        >\n          {items.map((item, i) => {\n            const override = itemStyles?.[i];\n            const rowState =\n              i === pressedIndex\n                ? \"press\"\n                : i === highlightedIndex\n                  ? \"hover\"\n                  : \"idle\";\n            const rowStyle =\n              override ?? dropdownMenuItemStyle(rowState, ctx.itemCtx);\n            return (\n              <DropdownMenuItemRow\n                key={item}\n                style={rowStyle}\n                label={item}\n                width={WIDTH - 8}\n                theme={themeOverride}\n              />\n            );\n          })}\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/dropdown-menu.tsx"
    },
    {
      "path": "registry/remocn-ui/dropdown-menu/use-dropdown-menu-transition.ts",
      "content": "\"use client\";\n\nimport {\n  type DropdownMenuState,\n  type DropdownMenuStyle,\n  dropdownMenuStyle,\n  dropdownMenuStyleContext,\n} from \"@/components/remocn/dropdown-menu\";\nimport {\n  easings,\n  type RemocnTheme,\n  type Step,\n  useRemocnTheme,\n  useStateTransition,\n} from \"@/lib/remocn-ui\";\n\nexport const DEFAULT_DURATION = 12;\n\nexport function tweenDropdownMenuStyle(\n  a: DropdownMenuStyle,\n  b: DropdownMenuStyle,\n  t: number,\n): DropdownMenuStyle {\n  return {\n    panelOpacity: a.panelOpacity + (b.panelOpacity - a.panelOpacity) * t,\n    panelScale: a.panelScale + (b.panelScale - a.panelScale) * t,\n    panelTranslateY:\n      a.panelTranslateY + (b.panelTranslateY - a.panelTranslateY) * t,\n    chevronRotation:\n      a.chevronRotation + (b.chevronRotation - a.chevronRotation) * t,\n  };\n}\n\nexport interface DropdownMenuTransitionOptions {\n  theme?: Partial<RemocnTheme>;\n  mode?: \"light\" | \"dark\";\n  primary?: string;\n  speed?: number;\n  defaultDuration?: number;\n}\n\nexport function useDropdownMenuTransition(\n  steps: Step<DropdownMenuState>[],\n  opts: DropdownMenuTransitionOptions = {},\n): DropdownMenuStyle {\n  const {\n    theme: themeOverride,\n    mode,\n    primary,\n    speed = 1,\n    defaultDuration = DEFAULT_DURATION,\n  } = opts;\n  const theme = useRemocnTheme(\n    { ...themeOverride, ...(primary ? { primary } : {}) },\n    mode,\n  );\n  const ctx = dropdownMenuStyleContext(theme);\n  const { from, to, progress } = useStateTransition(\n    steps,\n    \"closed\",\n    speed,\n    defaultDuration,\n  );\n  const t = easings.out(progress);\n  return tweenDropdownMenuStyle(\n    dropdownMenuStyle(from, ctx),\n    dropdownMenuStyle(to, ctx),\n    t,\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/use-dropdown-menu-transition.ts"
    }
  ],
  "type": "registry:component"
}
