{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tabs",
  "title": "UI Tabs",
  "description": "A tabs widget whose active-tab state is a pure function of the timeline; the sliding indicator, label colors, and panel crossfade are keyframed/derived presets.",
  "dependencies": ["remotion"],
  "registryDependencies": ["@remocn/remocn-ui"],
  "files": [
    {
      "path": "registry/remocn-ui/tabs/index.tsx",
      "content": "\"use client\";\n\nimport { mixOklch, type RemocnTheme, useRemocnTheme } from \"@/lib/remocn-ui\";\n\nexport type TabsState = string;\n\ntype TabsVariant = \"pill\" | \"underline\";\n\nexport interface TabsProps {\n  state?: TabsState;\n  style?: TabsStyle;\n  items?: string[];\n  contents?: string[];\n  contentHeight?: number;\n  variant?: TabsVariant;\n  theme?: Partial<RemocnTheme>;\n  className?: string;\n}\n\nconst WIDTH = 440;\n\nconst DEFAULT_ITEMS = [\"Account\", \"Password\", \"Settings\"];\n\nconst DEFAULT_CONTENTS = [\n  \"Make changes to your account here.\",\n  \"Change your password here.\",\n  \"Manage your notification settings.\",\n];\n\nexport interface TabsStyle {\n  indicatorOffset: number;\n}\n\nexport interface TabsStyleContext {\n  items: string[];\n  variant: TabsVariant;\n  trackBg: string;\n  activeFg: string;\n  inactiveFg: string;\n  indicatorBg: string;\n  border: string;\n  radius: number;\n  panelFg: string;\n}\n\nexport function tabsStyleContext(\n  items: string[],\n  variant: TabsVariant,\n  theme: RemocnTheme,\n): TabsStyleContext {\n  return {\n    items,\n    variant,\n    trackBg: theme.muted,\n    activeFg: theme.foreground,\n    inactiveFg: theme.mutedForeground,\n    indicatorBg: variant === \"underline\" ? theme.primary : theme.background,\n    border: theme.border,\n    radius: theme.radius,\n    panelFg: theme.mutedForeground,\n  };\n}\n\nexport function tabsStyle(state: TabsState, ctx: TabsStyleContext): TabsStyle {\n  const i = ctx.items.indexOf(state);\n  return { indicatorOffset: i < 0 ? 0 : i };\n}\n\nexport function Tabs({\n  state = DEFAULT_ITEMS[0],\n  style,\n  items = DEFAULT_ITEMS,\n  contents = DEFAULT_CONTENTS,\n  contentHeight = 72,\n  variant = \"pill\",\n  theme: themeOverride,\n  className,\n}: TabsProps) {\n  const theme = useRemocnTheme(themeOverride, \"light\");\n\n  const ctx = tabsStyleContext(items, variant, theme);\n  const v = style ?? tabsStyle(state, ctx);\n\n  const isPill = ctx.variant === \"pill\";\n  const trackPad = isPill ? 4 : 0;\n  const innerWidth = WIDTH - trackPad * 2;\n  const segmentWidth = innerWidth / items.length;\n  const rowHeight = 40;\n  const indicatorX = trackPad + v.indicatorOffset * segmentWidth;\n\n  return (\n    <div\n      className={className}\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      <div style={{ width: WIDTH }}>\n        {}\n        <div\n          style={{\n            position: \"relative\",\n            height: rowHeight,\n            padding: trackPad,\n            boxSizing: \"border-box\",\n            display: \"flex\",\n            background: isPill ? ctx.trackBg : \"transparent\",\n            borderRadius: isPill ? ctx.radius : 0,\n            borderBottom: isPill ? undefined : `1px solid ${ctx.border}`,\n          }}\n        >\n          {}\n          <div\n            style={\n              isPill\n                ? {\n                    position: \"absolute\",\n                    top: trackPad,\n                    left: indicatorX,\n                    width: segmentWidth,\n                    height: rowHeight - trackPad * 2,\n                    background: ctx.indicatorBg,\n                    borderRadius: ctx.radius - 3,\n                    boxShadow: \"0 1px 2px rgba(0,0,0,0.1)\",\n                  }\n                : {\n                    position: \"absolute\",\n                    bottom: 0,\n                    left: indicatorX,\n                    width: segmentWidth,\n                    height: 2,\n                    background: ctx.indicatorBg,\n                  }\n            }\n          />\n          {}\n          {items.map((item, i) => {\n            const proximity = Math.max(0, 1 - Math.abs(i - v.indicatorOffset));\n            return (\n              <span\n                key={item}\n                style={{\n                  position: \"relative\",\n                  width: segmentWidth,\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  justifyContent: \"center\",\n                  fontSize: 14,\n                  fontWeight: 500,\n                  letterSpacing: \"-0.01em\",\n                  color: mixOklch(ctx.inactiveFg, ctx.activeFg, proximity),\n                }}\n              >\n                {item}\n              </span>\n            );\n          })}\n        </div>\n        {}\n        <div\n          style={{\n            position: \"relative\",\n            height: contentHeight,\n            marginTop: 16,\n          }}\n        >\n          {items.map((item, i) => {\n            const proximity = Math.max(0, 1 - Math.abs(i - v.indicatorOffset));\n            return (\n              <div\n                key={item}\n                style={{\n                  position: \"absolute\",\n                  inset: 0,\n                  opacity: proximity,\n                  fontSize: 14,\n                  lineHeight: 1.5,\n                  color: ctx.panelFg,\n                }}\n              >\n                {contents[i]}\n              </div>\n            );\n          })}\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/tabs.tsx"
    },
    {
      "path": "registry/remocn-ui/tabs/use-tabs-transition.ts",
      "content": "\"use client\";\n\nimport {\n  type TabsState,\n  type TabsStyle,\n  tabsStyle,\n  tabsStyleContext,\n} from \"@/components/remocn/tabs\";\nimport {\n  easings,\n  type RemocnTheme,\n  type Step,\n  useRemocnTheme,\n  useStateTransition,\n} from \"@/lib/remocn-ui\";\n\nconst DEFAULT_ITEMS = [\"Account\", \"Password\", \"Settings\"];\n\nexport const DEFAULT_DURATION = 14;\n\nexport function tweenTabsStyle(\n  a: TabsStyle,\n  b: TabsStyle,\n  t: number,\n): TabsStyle {\n  return {\n    indicatorOffset:\n      a.indicatorOffset + (b.indicatorOffset - a.indicatorOffset) * t,\n  };\n}\n\nexport interface TabsTransitionOptions {\n  items?: string[];\n  variant?: \"pill\" | \"underline\";\n  theme?: Partial<RemocnTheme>;\n  mode?: \"light\" | \"dark\";\n  speed?: number;\n  defaultDuration?: number;\n}\n\nexport function useTabsTransition(\n  steps: Step<TabsState>[],\n  opts: TabsTransitionOptions = {},\n): TabsStyle {\n  const {\n    items = DEFAULT_ITEMS,\n    variant = \"pill\",\n    theme: themeOverride,\n    mode,\n    speed = 1,\n    defaultDuration = DEFAULT_DURATION,\n  } = opts;\n  const theme = useRemocnTheme(themeOverride, mode);\n  const ctx = tabsStyleContext(items, variant, theme);\n  const { from, to, progress } = useStateTransition(\n    steps,\n    items[0],\n    speed,\n    defaultDuration,\n  );\n  const t = easings.out(progress);\n  return tweenTabsStyle(tabsStyle(from, ctx), tabsStyle(to, ctx), t);\n}\n",
      "type": "registry:component",
      "target": "components/remocn/use-tabs-transition.ts"
    }
  ],
  "type": "registry:component"
}
