{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radio",
  "title": "UI Radio",
  "description": "A radio whose checked/unchecked state is a pure function of the timeline; the ring border and inner dot pop are keyframed presets.",
  "dependencies": ["remotion"],
  "registryDependencies": ["@remocn/remocn-ui"],
  "files": [
    {
      "path": "registry/remocn-ui/radio/index.tsx",
      "content": "\"use client\";\n\nimport { type RemocnTheme, useRemocnTheme } from \"@/lib/remocn-ui\";\n\nexport type RadioState = \"unchecked\" | \"checked\";\n\ntype RadioSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface RadioProps {\n  state?: RadioState;\n  style?: RadioStyle;\n  label?: string;\n  size?: RadioSize;\n  theme?: Partial<RemocnTheme>;\n  primary?: string;\n  className?: string;\n}\n\nconst SIZE_STYLES: Record<\n  RadioSize,\n  { box: number; fontSize: number; gap: number }\n> = {\n  sm: { box: 16, fontSize: 13, gap: 8 },\n  default: { box: 20, fontSize: 15, gap: 10 },\n  lg: { box: 24, fontSize: 17, gap: 12 },\n};\n\nexport interface RadioStyle {\n  ringBorderColor: string;\n  dotOpacity: number;\n  dotScale: number;\n}\n\nexport interface RadioStyleContext {\n  uncheckedBorder: string;\n  checkedBorder: string;\n  dotColor: string;\n}\n\nexport function radioStyleContext(theme: RemocnTheme): RadioStyleContext {\n  return {\n    uncheckedBorder: theme.border,\n    checkedBorder: theme.primary,\n    dotColor: theme.primary,\n  };\n}\n\nexport function radioStyle(\n  state: RadioState,\n  ctx: RadioStyleContext,\n): RadioStyle {\n  switch (state) {\n    case \"checked\":\n      return {\n        ringBorderColor: ctx.checkedBorder,\n        dotOpacity: 1,\n        dotScale: 1,\n      };\n    default:\n      return {\n        ringBorderColor: ctx.uncheckedBorder,\n        dotOpacity: 0,\n        dotScale: 0.4,\n      };\n  }\n}\n\nexport function Radio({\n  state = \"unchecked\",\n  style,\n  label,\n  size = \"default\",\n  theme: themeOverride,\n  primary,\n  className,\n}: RadioProps) {\n  const theme = useRemocnTheme(\n    { ...themeOverride, ...(primary ? { primary } : {}) },\n    \"light\",\n  );\n\n  const sizeStyle = SIZE_STYLES[size];\n  const ctx = radioStyleContext(theme);\n  const v = style ?? radioStyle(state, ctx);\n  const boxSize = sizeStyle.box;\n\n  return (\n    <div\n      style={{\n        position: \"absolute\",\n        inset: 0,\n        display: \"flex\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        background: \"transparent\",\n        fontFamily:\n          \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\",\n      }}\n    >\n      <span\n        className={className}\n        style={{\n          display: \"inline-flex\",\n          alignItems: \"center\",\n          gap: sizeStyle.gap,\n        }}\n      >\n        {}\n        <span\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            width: boxSize,\n            height: boxSize,\n            borderRadius: \"50%\",\n            border: `1px solid ${v.ringBorderColor}`,\n            background: theme.background,\n          }}\n        >\n          {}\n          <span\n            style={{\n              width: Math.round(boxSize * 0.45),\n              height: Math.round(boxSize * 0.45),\n              borderRadius: \"50%\",\n              background: ctx.dotColor,\n              opacity: v.dotOpacity,\n              transform: `scale(${v.dotScale})`,\n            }}\n          />\n        </span>\n        {label !== undefined && (\n          <span\n            style={{\n              fontSize: sizeStyle.fontSize,\n              fontWeight: 500,\n              letterSpacing: \"-0.01em\",\n              color: theme.foreground,\n            }}\n          >\n            {label}\n          </span>\n        )}\n      </span>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/radio.tsx"
    },
    {
      "path": "registry/remocn-ui/radio/use-radio-transition.ts",
      "content": "\"use client\";\n\nimport {\n  type RadioState,\n  type RadioStyle,\n  radioStyle,\n  radioStyleContext,\n} from \"@/components/remocn/radio\";\nimport {\n  easings,\n  mixOklch,\n  type RemocnTheme,\n  type Step,\n  useRemocnTheme,\n  useStateTransition,\n} from \"@/lib/remocn-ui\";\n\nexport const DEFAULT_DURATION = 10;\n\nexport function tweenRadioStyle(\n  a: RadioStyle,\n  b: RadioStyle,\n  t: number,\n): RadioStyle {\n  return {\n    ringBorderColor: mixOklch(a.ringBorderColor, b.ringBorderColor, t),\n    dotOpacity: a.dotOpacity + (b.dotOpacity - a.dotOpacity) * t,\n    dotScale: a.dotScale + (b.dotScale - a.dotScale) * t,\n  };\n}\n\nexport interface RadioTransitionOptions {\n  theme?: Partial<RemocnTheme>;\n  mode?: \"light\" | \"dark\";\n  primary?: string;\n  speed?: number;\n  defaultDuration?: number;\n}\n\nexport function useRadioTransition(\n  steps: Step<RadioState>[],\n  opts: RadioTransitionOptions = {},\n): RadioStyle {\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 = radioStyleContext(theme);\n  const { from, to, progress } = useStateTransition(\n    steps,\n    \"unchecked\",\n    speed,\n    defaultDuration,\n  );\n  const t = easings.out(progress);\n  return tweenRadioStyle(radioStyle(from, ctx), radioStyle(to, ctx), t);\n}\n",
      "type": "registry:component",
      "target": "components/remocn/use-radio-transition.ts"
    }
  ],
  "type": "registry:component"
}
