{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "resizable-minimal",
  "title": "Minimal resizable",
  "description": "Styled resizable: the Minimal set. 5 decorative resizable variations (LineResizable, HairResizable, DotResizable, GhostResizable, BareResizable) on the ai2 token system, driven by CSS token transitions and sized sm to xl. Part of the free styled layer.",
  "dependencies": [],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/resizable-minimal.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Minimal resizable family: 5 self-contained split panels (NO panel library, NO\n   radix). The theme idea: the handle is almost invisible - a hairline, no grip\n   dots, very quiet. Each export holds an internal percentage (pct) state; the\n   separator is dragged with the pointer and adjusted with the arrow keys.\n   Deterministic (no Date.now / Math.random). The separator uses role=\"separator\" +\n   aria-orientation + aria-valuenow/min/max, tabIndex=0. Color comes ONLY from\n   semantic tokens; alpha via color-mix or the Tailwind /NN. There is no motion in\n   this family (only color transitions), so there is no motion import either. */\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\n/* Varsayilan panel: token yuzeyli, ortalanmis etiket. */\nfunction Pane({\n  label,\n  tone = \"bg-surface-2\",\n  className,\n  children,\n}: {\n  label?: string\n  tone?: string\n  className?: string\n  children?: React.ReactNode\n}) {\n  return (\n    <div\n      className={cn(\n        \"flex h-full w-full items-center justify-center overflow-hidden p-4 text-sm font-medium text-foreground\",\n        tone,\n        className\n      )}\n    >\n      {children ?? <span className=\"text-muted-foreground\">{label}</span>}\n    </div>\n  )\n}\n\nconst shell =\n  \"flex w-full select-none overflow-hidden rounded-xl border border-border\"\n\n/* LineResizable: a hairline single-pixel line; it darkens slightly on hover. */\nexport function LineResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\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 ?? <Pane label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div\n        {...separatorProps}\n        className={cn(\n          \"relative h-full w-px shrink-0 cursor-col-resize transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\",\n          dragging ? \"bg-foreground/60\" : \"bg-border hover:bg-foreground/40\"\n        )}\n      />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <Pane label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* HairResizable: even fainter than LineResizable; at rest it almost disappears. */\nexport function HairResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\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 ?? <Pane label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div\n        {...separatorProps}\n        className={cn(\n          \"relative h-full w-px shrink-0 cursor-col-resize transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\",\n          dragging ? \"bg-foreground/40\" : \"bg-border/60 hover:bg-border\"\n        )}\n      />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <Pane label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* DotResizable: a single small dot sitting on an invisible rail (not a cluster of grip dots). */\nexport function DotResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\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 ?? <Pane label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div\n        {...separatorProps}\n        className={cn(\n          \"group relative flex h-full w-px shrink-0 cursor-col-resize items-center justify-center bg-border\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\"\n        )}\n      >\n        <span\n          aria-hidden=\"true\"\n          className={cn(\n            \"size-1 rounded-full transition-colors\",\n            dragging ? \"bg-foreground\" : \"bg-muted-foreground/50 group-hover:bg-foreground/70\"\n          )}\n        />\n      </div>\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <Pane label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* GhostResizable: no line at rest; it appears only on hover or while dragging. */\nexport function GhostResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\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 ?? <Pane label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div\n        {...separatorProps}\n        className={cn(\n          \"relative h-full w-px shrink-0 cursor-col-resize transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\",\n          dragging ? \"bg-foreground/40\" : \"bg-transparent hover:bg-foreground/20\"\n        )}\n      />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <Pane label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* BareResizable: the barest form; no line at all, just the cursor and a very faint trace while dragging. The sense of separation comes entirely from the cursor. */\nexport function BareResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\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 ?? <Pane label=\"Panel bir\" tone=\"bg-surface-2\" />}\n      </div>\n      <div\n        {...separatorProps}\n        className={cn(\n          \"relative h-full w-px shrink-0 cursor-col-resize transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-2 after:content-['']\",\n          dragging ? \"bg-foreground/20\" : \"bg-transparent\"\n        )}\n      />\n      <div style={{ width: `${100 - pct}%` }} className=\"h-full\">\n        {end ?? <Pane label=\"Panel iki\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/resizable-minimal.tsx"
    }
  ],
  "categories": [
    "styled",
    "resizable"
  ],
  "type": "registry:component"
}