{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "resizable-panel",
  "title": "Panel resizable",
  "description": "Styled resizable: the Panel set. 5 decorative resizable variations (HeaderResizable, TitledResizable, BadgeResizable, ToolbarResizable, TabResizable) on the ai2 token system, driven by CSS token transitions and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "lucide-react@^1.23.0"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/resizable-panel.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Minus, Square, X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Panel resizable family: 5 self-contained split panels (NO panel library, NO\n   radix). The theme idea: the panes are labelled cards with a small title bar. Each\n   export holds an internal percentage (pct) state; the separator is dragged with\n   the pointer and adjusted with the arrow keys. Deterministic (no Date.now /\n   Math.random). The separator uses role=\"separator\" + aria-orientation +\n   aria-valuenow/min/max, tabIndex=0. Color comes ONLY from semantic tokens; alpha\n   via color-mix or the Tailwind /NN. There is no motion in this family. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\ntype Orientation = \"horizontal\" | \"vertical\"\n\nconst height: Record<StyledSize, string> = {\n  sm: \"h-40\",\n  md: \"h-56\",\n  lg: \"h-72\",\n  xl: \"h-96\",\n}\n\nconst MIN = 12\nconst MAX = 88\nconst clamp = (n: number) => Math.min(MAX, Math.max(MIN, n))\n\nconst focusRing =\n  \"outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n\n/* Ortak bolme mantigi: pct state + pointer/klavye tutamac handler'lari.\n   horizontal = sol/sag panel, dikey ayirici (yatay suruklenir).\n   vertical   = ust/alt panel, yatay ayirici (dikey suruklenir). */\nfunction useResizable(orientation: Orientation, initial = 50) {\n  const [pct, setPct] = React.useState(initial)\n  const containerRef = React.useRef<HTMLDivElement>(null)\n  const [dragging, setDragging] = React.useState(false)\n\n  const applyFromPoint = React.useCallback(\n    (clientX: number, clientY: number) => {\n      const el = containerRef.current\n      if (!el) return\n      const rect = el.getBoundingClientRect()\n      const raw =\n        orientation === \"horizontal\"\n          ? ((clientX - rect.left) / rect.width) * 100\n          : ((clientY - rect.top) / rect.height) * 100\n      setPct(clamp(raw))\n    },\n    [orientation]\n  )\n\n  const onPointerDown = React.useCallback(\n    (e: React.PointerEvent<HTMLDivElement>) => {\n      e.preventDefault()\n      e.currentTarget.setPointerCapture(e.pointerId)\n      setDragging(true)\n    },\n    []\n  )\n\n  const onPointerMove = React.useCallback(\n    (e: React.PointerEvent<HTMLDivElement>) => {\n      if (!e.currentTarget.hasPointerCapture(e.pointerId)) return\n      applyFromPoint(e.clientX, e.clientY)\n    },\n    [applyFromPoint]\n  )\n\n  const onPointerUp = React.useCallback(\n    (e: React.PointerEvent<HTMLDivElement>) => {\n      if (e.currentTarget.hasPointerCapture(e.pointerId))\n        e.currentTarget.releasePointerCapture(e.pointerId)\n      setDragging(false)\n    },\n    []\n  )\n\n  const onKeyDown = React.useCallback(\n    (e: React.KeyboardEvent<HTMLDivElement>) => {\n      const dec = orientation === \"horizontal\" ? \"ArrowLeft\" : \"ArrowUp\"\n      const inc = orientation === \"horizontal\" ? \"ArrowRight\" : \"ArrowDown\"\n      if (e.key === dec) {\n        e.preventDefault()\n        setPct((p) => clamp(p - (e.shiftKey ? 10 : 2)))\n      } else if (e.key === inc) {\n        e.preventDefault()\n        setPct((p) => clamp(p + (e.shiftKey ? 10 : 2)))\n      } else if (e.key === \"Home\") {\n        e.preventDefault()\n        setPct(MIN)\n      } else if (e.key === \"End\") {\n        e.preventDefault()\n        setPct(MAX)\n      }\n    },\n    [orientation]\n  )\n\n  const separatorProps = {\n    role: \"separator\" as const,\n    \"aria-orientation\": (orientation === \"horizontal\" ? \"vertical\" : \"horizontal\") as\n      | \"vertical\"\n      | \"horizontal\",\n    \"aria-valuenow\": Math.round(pct),\n    \"aria-valuemin\": MIN,\n    \"aria-valuemax\": MAX,\n    tabIndex: 0,\n    onPointerDown,\n    onPointerMove,\n    onPointerUp,\n    onKeyDown,\n  }\n\n  return { pct, containerRef, dragging, separatorProps }\n}\n\ninterface ResizableProps {\n  className?: string\n  size?: StyledSize\n  start?: React.ReactNode\n  end?: React.ReactNode\n}\n\nconst shell =\n  \"flex w-full select-none overflow-hidden rounded-xl border border-border\"\n\nconst dividerBase =\n  \"relative h-full w-px shrink-0 cursor-col-resize transition-colors after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\"\n\n/* A titled card pane: a title bar on top, the body below. The header differs in\n   every variant. */\nfunction CardPane({\n  header,\n  label,\n  tone = \"bg-surface-2\",\n}: {\n  header: React.ReactNode\n  label: string\n  tone?: string\n}) {\n  return (\n    <div className={cn(\"flex h-full w-full flex-col overflow-hidden\", tone)}>\n      {header}\n      <div className=\"flex flex-1 items-center justify-center p-4 text-sm text-muted-foreground\">\n        {label}\n      </div>\n    </div>\n  )\n}\n\nconst headerBar =\n  \"flex h-9 shrink-0 items-center gap-2 border-b border-border bg-[color-mix(in_oklab,var(--color-background)_70%,transparent)] px-3\"\n\n/* HeaderResizable: her bolmede sade baslik cubugu (baslik metni). */\nexport function HeaderResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, separatorProps } = useResizable(\"horizontal\")\n  const header = (title: string) => (\n    <div className={headerBar}>\n      <span className=\"text-xs font-semibold text-foreground\">{title}</span>\n    </div>\n  )\n  return (\n    <div data-slot=\"styled-resizable\" ref={containerRef} className={cn(shell, height[size], className)}>\n      <div style={{ width: `${pct}%` }} className=\"h-full\">\n        {start ?? <CardPane header={header(\"Explorer\")} label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div {...separatorProps} className={cn(dividerBase, focusRing, \"bg-border hover:bg-primary/60\")} />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <CardPane header={header(\"Preview\")} label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* TitledResizable: baslik cubugunda baslik + soluk alt aciklama. */\nexport function TitledResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, separatorProps } = useResizable(\"horizontal\")\n  const header = (title: string, sub: string) => (\n    <div className={cn(headerBar, \"h-11 flex-col items-start justify-center gap-0\")}>\n      <span className=\"text-xs font-semibold leading-tight text-foreground\">{title}</span>\n      <span className=\"text-[0.65rem] leading-tight text-muted-foreground\">{sub}</span>\n    </div>\n  )\n  return (\n    <div data-slot=\"styled-resizable\" ref={containerRef} className={cn(shell, height[size], className)}>\n      <div style={{ width: `${pct}%` }} className=\"h-full\">\n        {start ?? <CardPane header={header(\"Source\", \"main.tsx\")} label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div {...separatorProps} className={cn(dividerBase, focusRing, \"bg-border hover:bg-primary/60\")} />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <CardPane header={header(\"Output\", \"console\")} label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* BadgeResizable: baslik cubugunda baslik + sagda kucuk rozet. */\nexport function BadgeResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, separatorProps } = useResizable(\"horizontal\")\n  const header = (title: string, badge: string) => (\n    <div className={cn(headerBar, \"justify-between\")}>\n      <span className=\"text-xs font-semibold text-foreground\">{title}</span>\n      <span className=\"rounded-full bg-primary/15 px-2 py-0.5 text-[0.65rem] font-medium text-primary\">\n        {badge}\n      </span>\n    </div>\n  )\n  return (\n    <div data-slot=\"styled-resizable\" ref={containerRef} className={cn(shell, height[size], className)}>\n      <div style={{ width: `${pct}%` }} className=\"h-full\">\n        {start ?? <CardPane header={header(\"Files\", \"12\")} label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div {...separatorProps} className={cn(dividerBase, focusRing, \"bg-border hover:bg-primary/60\")} />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <CardPane header={header(\"Diff\", \"new\")} label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* ToolbarResizable: baslik cubugunda baslik + sagda kucuk ikon dugmeleri. */\nexport function ToolbarResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, separatorProps } = useResizable(\"horizontal\")\n  const btn =\n    \"inline-flex size-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-[color-mix(in_oklab,var(--color-foreground)_8%,transparent)] hover:text-foreground [&_svg]:size-3 [&_i]:text-[0.7rem] [&_i]:leading-none\"\n  const header = (title: string) => (\n    <div className={cn(headerBar, \"justify-between\")}>\n      <span className=\"text-xs font-semibold text-foreground\">{title}</span>\n      <span className=\"flex items-center gap-0.5\">\n        <span aria-hidden=\"true\" className={btn}>\n          <Minus />\n        </span>\n        <span aria-hidden=\"true\" className={btn}>\n          <Square />\n        </span>\n        <span aria-hidden=\"true\" className={btn}>\n          <X />\n        </span>\n      </span>\n    </div>\n  )\n  return (\n    <div data-slot=\"styled-resizable\" ref={containerRef} className={cn(shell, height[size], className)}>\n      <div style={{ width: `${pct}%` }} className=\"h-full\">\n        {start ?? <CardPane header={header(\"Editor\")} label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div {...separatorProps} className={cn(dividerBase, focusRing, \"bg-border hover:bg-primary/60\")} />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <CardPane header={header(\"Terminal\")} label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* TabResizable: baslik cubugu tek aktif sekme gorunumunde. */\nexport function TabResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, separatorProps } = useResizable(\"horizontal\")\n  const header = (title: string) => (\n    <div className={cn(headerBar, \"gap-0 px-2\")}>\n      <span className=\"-mb-px inline-flex h-full items-center rounded-t-md border-b-2 border-primary px-2 text-xs font-semibold text-foreground\">\n        {title}\n      </span>\n    </div>\n  )\n  return (\n    <div data-slot=\"styled-resizable\" ref={containerRef} className={cn(shell, height[size], className)}>\n      <div style={{ width: `${pct}%` }} className=\"h-full\">\n        {start ?? <CardPane header={header(\"index.ts\")} label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div {...separatorProps} className={cn(dividerBase, focusRing, \"bg-border hover:bg-primary/60\")} />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <CardPane header={header(\"styles.css\")} label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/resizable-panel.tsx"
    }
  ],
  "categories": [
    "styled",
    "resizable"
  ],
  "type": "registry:component"
}