{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "resizable-styled",
  "title": "Resizable essentials",
  "description": "Styled resizable: the essentials set. 5 decorative resizable variations (HorizontalResizable, VerticalResizable, HandleResizable, NestedResizable, GlassResizable) on the ai2 token system, powered by framer-motion, reduced-motion aware and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "motion@^12.42.2",
    "lucide-react@^1.23.0"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/resizable-styled.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { GripHorizontal, GripVertical } from \"lucide-react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Resizable family: 5 self-contained split-panel components (NO\n   react-resizable-panels, NO radix). Each holds an internal percentage (pct) state;\n   dragging the handle with the pointer updates pct, and it can also be adjusted\n   with the arrow keys. Deterministic (no Date.now / Math.random). The separator\n   uses role=\"separator\" + aria-orientation + aria-valuenow/min/max, tabIndex=0.\n   Color comes ONLY from semantic tokens; alpha via color-mix (never var(--x)/0.4).\n   Gated on framer's useReducedMotion (under reduced motion the handle spring is\n   disabled; the drag itself is always instant). size -> container height. */\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\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\ninterface ResizableProps {\n  className?: string\n  size?: StyledSize\n  start?: React.ReactNode\n  end?: React.ReactNode\n}\n\n/* The grip dots inside the handle: they grow slightly on hover and while active (fixed under reduced). */\nfunction Grip({\n  orientation,\n  active,\n}: {\n  orientation: Orientation\n  active: boolean\n}) {\n  const reduce = useReducedMotion()\n  const Icon = orientation === \"horizontal\" ? GripVertical : GripHorizontal\n  return (\n    <motion.span\n      aria-hidden=\"true\"\n      className=\"pointer-events-none flex items-center justify-center text-muted-foreground [&_svg]:size-4 [&_svg]:shrink-0\"\n      animate={reduce ? undefined : { scale: active ? 1.15 : 1 }}\n      transition={reduce ? { duration: 0 } : { type: \"spring\", stiffness: 500, damping: 30 }}\n    >\n      <Icon />\n    </motion.span>\n  )\n}\n\n/* HorizontalResizable: sol/sag panel, ince dikey ayirici cizgisi (grip yok). */\nexport function HorizontalResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\n  return (\n    <div\n      data-slot=\"styled-resizable\"\n      ref={containerRef}\n      className={cn(\n        \"flex w-full select-none overflow-hidden rounded-xl border border-border\",\n        height[size],\n        className\n      )}\n    >\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-stretch bg-border transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\",\n          dragging ? \"bg-primary\" : \"hover:bg-primary/70\"\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/* VerticalResizable: ust/alt panel, ince yatay ayirici cizgisi. */\nexport function VerticalResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"vertical\")\n  return (\n    <div\n      data-slot=\"styled-resizable\"\n      ref={containerRef}\n      className={cn(\n        \"flex w-full select-none flex-col overflow-hidden rounded-xl border border-border\",\n        height[size],\n        className\n      )}\n    >\n      <div style={{ height: `${pct}%` }} className=\"w-full\">\n        {start ?? <Pane label=\"Ust panel\" tone=\"bg-surface-2\" />}\n      </div>\n      <div\n        {...separatorProps}\n        className={cn(\n          \"relative flex w-full h-px shrink-0 cursor-row-resize bg-border transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-x-0 after:-inset-y-1.5 after:content-['']\",\n          dragging ? \"bg-primary\" : \"hover:bg-primary/70\"\n        )}\n      />\n      <div style={{ height: `${100 - pct}%` }} className=\"w-full\">\n        {end ?? <Pane label=\"Alt panel\" tone=\"bg-surface-3\" />}\n      </div>\n    </div>\n  )\n}\n\n/* HandleResizable: sol/sag panel, ortada gorunur kavrama tutamacli genis ayirici. */\nexport function HandleResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\n  return (\n    <div\n      data-slot=\"styled-resizable\"\n      ref={containerRef}\n      className={cn(\n        \"flex w-full select-none overflow-hidden rounded-xl border border-border\",\n        height[size],\n        className\n      )}\n    >\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 flex h-full w-1.5 shrink-0 cursor-col-resize items-center justify-center bg-border transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1 after:content-['']\",\n          dragging ? \"bg-primary/40\" : \"hover:bg-primary/25\"\n        )}\n      >\n        <span\n          className={cn(\n            \"z-10 flex h-8 items-center justify-center rounded-full border border-border bg-background shadow-sm transition-colors\",\n            dragging && \"border-primary\"\n          )}\n        >\n          <Grip orientation=\"horizontal\" active={dragging} />\n        </span>\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/* NestedResizable: a left/right split; the right side splits again into top/bottom\n   within itself. */\nexport function NestedResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const outer = useResizable(\"horizontal\", 42)\n  const inner = useResizable(\"vertical\", 55)\n  return (\n    <div\n      data-slot=\"styled-resizable\"\n      ref={outer.containerRef}\n      className={cn(\n        \"flex w-full select-none overflow-hidden rounded-xl border border-border\",\n        height[size],\n        className\n      )}\n    >\n      <div style={{ width: `${outer.pct}%` }} className=\"h-full\">\n        {start ?? <Pane label=\"Kenar cubugu\" tone=\"bg-surface-3\" />}\n      </div>\n      <div\n        {...outer.separatorProps}\n        className={cn(\n          \"relative flex h-full w-px shrink-0 cursor-col-resize bg-border transition-colors\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1.5 after:content-['']\",\n          outer.dragging ? \"bg-primary\" : \"hover:bg-primary/70\"\n        )}\n      />\n      <div style={{ width: `${100 - outer.pct}%` }} className=\"h-full\">\n        <div ref={inner.containerRef} className=\"flex h-full w-full flex-col\">\n          <div style={{ height: `${inner.pct}%` }} className=\"w-full\">\n            {end ?? <Pane label=\"Icerik\" tone=\"bg-surface-2\" />}\n          </div>\n          <div\n            {...inner.separatorProps}\n            className={cn(\n              \"relative flex h-px w-full shrink-0 cursor-row-resize bg-border transition-colors\",\n              focusRing,\n              \"after:absolute after:inset-x-0 after:-inset-y-1.5 after:content-['']\",\n              inner.dragging ? \"bg-primary\" : \"hover:bg-primary/70\"\n            )}\n          />\n          <div style={{ height: `${100 - inner.pct}%` }} className=\"w-full\">\n            <Pane label=\"Konsol\" tone=\"bg-muted\" />\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n\n/* GlassResizable: sol/sag panel, frosted cam ayirici (backdrop-blur + color-mix yuzey). */\nexport function GlassResizable({ className, size = \"md\", start, end }: ResizableProps) {\n  const { pct, containerRef, dragging, separatorProps } = useResizable(\"horizontal\")\n  return (\n    <div\n      data-slot=\"styled-resizable\"\n      ref={containerRef}\n      className={cn(\n        \"flex w-full select-none overflow-hidden rounded-xl border border-border\",\n        height[size],\n        className\n      )}\n    >\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 flex h-full w-2 shrink-0 cursor-col-resize items-center justify-center\",\n          \"border-x border-[color-mix(in_oklab,var(--color-foreground)_12%,transparent)]\",\n          \"bg-[color-mix(in_oklab,var(--color-background)_55%,transparent)] transition-colors supports-[backdrop-filter]:backdrop-blur-md\",\n          focusRing,\n          \"after:absolute after:inset-y-0 after:-inset-x-1 after:content-['']\",\n          dragging && \"bg-[color-mix(in_oklab,var(--color-primary)_30%,transparent)]\"\n        )}\n      >\n        <span\n          aria-hidden=\"true\"\n          className={cn(\n            \"z-10 h-8 w-1 rounded-full transition-colors\",\n            dragging\n              ? \"bg-primary\"\n              : \"bg-[color-mix(in_oklab,var(--color-foreground)_35%,transparent)]\"\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",
      "type": "registry:component",
      "target": "components/ui/resizable-styled.tsx"
    }
  ],
  "categories": [
    "styled",
    "resizable"
  ],
  "type": "registry:component"
}