{
  "name": "tabs",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "tabs.tsx",
      "content": "\"use client\";\r\n\r\nimport { css, themeVars as theme } from \"@yugnex/core\";\r\nimport { useControllableState } from \"@yugnex/core/client\";\r\nimport {\r\n  createContext,\r\n  forwardRef,\r\n  useContext,\r\n  useEffect,\r\n  useId,\r\n  useMemo,\r\n  useRef,\r\n  type ButtonHTMLAttributes,\r\n  type HTMLAttributes,\r\n  type KeyboardEvent,\r\n  type MutableRefObject,\r\n  type ReactNode,\r\n} from \"react\";\r\n\r\ninterface TabsContextValue {\r\n  value: string;\r\n  setValue: (value: string) => void;\r\n  baseId: string;\r\n  orderRef: MutableRefObject<string[]>;\r\n}\r\n\r\nconst TabsContext = createContext<TabsContextValue | null>(null);\r\n\r\nfunction useTabsContext(component: string): TabsContextValue {\r\n  const ctx = useContext(TabsContext);\r\n  if (!ctx) throw new Error(`<${component}> must be used within <Tabs>`);\r\n  return ctx;\r\n}\r\n\r\nfunction triggerId(baseId: string, value: string): string {\r\n  return `${baseId}-trigger-${value}`;\r\n}\r\n\r\nfunction panelId(baseId: string, value: string): string {\r\n  return `${baseId}-panel-${value}`;\r\n}\r\n\r\nconst listClass = css({\r\n  display: \"inline-flex\",\r\n  alignItems: \"center\",\r\n  gap: theme.space[1],\r\n  padding: \"4px\",\r\n  borderRadius: theme.radius.md,\r\n  backgroundColor: theme.color.muted,\r\n});\r\n\r\nconst triggerClass = css({\r\n  position: \"relative\",\r\n  display: \"inline-flex\",\r\n  alignItems: \"center\",\r\n  justifyContent: \"center\",\r\n  padding: `${theme.space[1.5]} ${theme.space[3]}`,\r\n  borderRadius: theme.radius.sm,\r\n  border: \"none\",\r\n  backgroundColor: \"transparent\",\r\n  color: theme.color.mutedForeground,\r\n  fontFamily: theme.fontFamily.sans,\r\n  fontSize: theme.fontSize.sm,\r\n  fontWeight: theme.fontWeight.medium,\r\n  cursor: \"pointer\",\r\n  transitionProperty: \"background-color, color\",\r\n  transitionDuration: theme.duration.fast,\r\n  transitionTimingFunction: theme.easing.standard,\r\n  '&[data-state=\"active\"]': {\r\n    backgroundColor: theme.color.background,\r\n    color: theme.color.foreground,\r\n    boxShadow: theme.shadow.sm,\r\n  },\r\n  \"&:focus-visible\": {\r\n    outline: `2px solid ${theme.color.ring}`,\r\n    outlineOffset: \"2px\",\r\n  },\r\n});\r\n\r\nconst panelClass = css({\r\n  marginTop: theme.space[3],\r\n  \"&:focus-visible\": {\r\n    outline: `2px solid ${theme.color.ring}`,\r\n    outlineOffset: \"2px\",\r\n  },\r\n});\r\n\r\nexport interface TabsProps {\r\n  value?: string;\r\n  defaultValue?: string;\r\n  onValueChange?: (value: string) => void;\r\n  children: ReactNode;\r\n  className?: string;\r\n}\r\n\r\nexport function Tabs({ value, defaultValue, onValueChange, children, className }: TabsProps) {\r\n  const [current, setCurrent] = useControllableState({\r\n    value,\r\n    defaultValue: defaultValue ?? \"\",\r\n    onChange: onValueChange,\r\n  });\r\n  const baseId = useId();\r\n  const orderRef = useRef<string[]>([]);\r\n\r\n  const ctx = useMemo<TabsContextValue>(\r\n    () => ({ value: current, setValue: setCurrent, baseId, orderRef }),\r\n    [current, setCurrent, baseId],\r\n  );\r\n\r\n  return (\r\n    <TabsContext.Provider value={ctx}>\r\n      <div className={className}>{children}</div>\r\n    </TabsContext.Provider>\r\n  );\r\n}\r\n\r\nexport const TabsList = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function TabsList(\r\n  { className, onKeyDown, children, ...props },\r\n  ref,\r\n) {\r\n  const { orderRef, value, setValue, baseId } = useTabsContext(\"TabsList\");\r\n\r\n  const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\r\n    onKeyDown?.(event);\r\n    if (event.defaultPrevented) return;\r\n    const order = orderRef.current;\r\n    if (order.length === 0) return;\r\n    const currentIndex = order.indexOf(value);\r\n    let nextIndex: number | null = null;\r\n    if (event.key === \"ArrowRight\") nextIndex = (currentIndex + 1 + order.length) % order.length;\r\n    else if (event.key === \"ArrowLeft\") nextIndex = (currentIndex - 1 + order.length) % order.length;\r\n    else if (event.key === \"Home\") nextIndex = 0;\r\n    else if (event.key === \"End\") nextIndex = order.length - 1;\r\n\r\n    if (nextIndex !== null) {\r\n      event.preventDefault();\r\n      const nextValue = order[nextIndex]!;\r\n      setValue(nextValue);\r\n      document.getElementById(triggerId(baseId, nextValue))?.focus();\r\n    }\r\n  };\r\n\r\n  return (\r\n    <div\r\n      ref={ref}\r\n      role=\"tablist\"\r\n      className={className ? `${listClass} ${className}` : listClass}\r\n      onKeyDown={handleKeyDown}\r\n      {...props}\r\n    >\r\n      {children}\r\n    </div>\r\n  );\r\n});\r\n\r\nexport interface TabsTriggerProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\r\n  value: string;\r\n}\r\n\r\nexport const TabsTrigger = forwardRef<HTMLButtonElement, TabsTriggerProps>(function TabsTrigger(\r\n  { value, className, children, ...props },\r\n  ref,\r\n) {\r\n  const { value: activeValue, setValue, baseId, orderRef } = useTabsContext(\"TabsTrigger\");\r\n\r\n  useEffect(() => {\r\n    if (!orderRef.current.includes(value)) orderRef.current.push(value);\r\n    return () => {\r\n      orderRef.current = orderRef.current.filter((v) => v !== value);\r\n    };\r\n  }, [value, orderRef]);\r\n\r\n  const isActive = activeValue === value;\r\n\r\n  return (\r\n    <button\r\n      ref={ref}\r\n      type=\"button\"\r\n      role=\"tab\"\r\n      id={triggerId(baseId, value)}\r\n      aria-selected={isActive}\r\n      aria-controls={panelId(baseId, value)}\r\n      data-state={isActive ? \"active\" : \"inactive\"}\r\n      tabIndex={isActive ? 0 : -1}\r\n      className={className ? `${triggerClass} ${className}` : triggerClass}\r\n      onClick={() => setValue(value)}\r\n      {...props}\r\n    >\r\n      {children}\r\n    </button>\r\n  );\r\n});\r\n\r\nexport interface TabsPanelProps extends HTMLAttributes<HTMLDivElement> {\r\n  value: string;\r\n}\r\n\r\nexport const TabsPanel = forwardRef<HTMLDivElement, TabsPanelProps>(function TabsPanel(\r\n  { value, className, children, ...props },\r\n  ref,\r\n) {\r\n  const { value: activeValue, baseId } = useTabsContext(\"TabsPanel\");\r\n  if (activeValue !== value) return null;\r\n\r\n  return (\r\n    <div\r\n      ref={ref}\r\n      role=\"tabpanel\"\r\n      id={panelId(baseId, value)}\r\n      aria-labelledby={triggerId(baseId, value)}\r\n      tabIndex={0}\r\n      className={className ? `${panelClass} ${className}` : panelClass}\r\n      {...props}\r\n    >\r\n      {children}\r\n    </div>\r\n  );\r\n});\r\n",
      "type": "registry:component"
    }
  ]
}