{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "live-cursor",
  "type": "registry:component",
  "title": "Live Cursor",
  "description": "Remote user's cursor rendered at canvas coordinates with name + status chip.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/live-cursor/live-cursor.tsx",
      "content": "\"use client\";\n\nimport {\n  type ComponentPropsWithoutRef,\n  forwardRef,\n  type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\n/**\n * Localizable strings.\n *\n * @public\n */\nexport type LiveCursorLabels = {\n  /** Aria-label override. Defaults to `\"Live cursor\"`. */\n  region?: string;\n};\n\nconst DEFAULT_LABELS = {\n  region: \"Live cursor\",\n} as const satisfies Required<LiveCursorLabels>;\n\n/**\n * Props for {@link LiveCursor}.\n *\n * @public\n */\nexport type LiveCursorProps = {\n  /** Tailwind / arbitrary CSS color used for the pointer + name chip. Defaults to `var(--foreground)`. */\n  color?: string;\n  /** Localizable strings. */\n  labels?: LiveCursorLabels;\n  /** Display name shown in the chip. Pass `null` to hide the chip. */\n  name?: ReactNode;\n  /** Optional secondary line in the chip (e.g. status, role). */\n  status?: ReactNode;\n  /** Cursor X in canvas pixels. */\n  x: number;\n  /** Cursor Y in canvas pixels. */\n  y: number;\n} & ComponentPropsWithoutRef<\"div\">;\n\n/**\n * Remote user's cursor rendered at canvas coordinates with an optional\n * name + status chip. Pure presentation; the host owns the websocket\n * stream + maps user ids to colors.\n *\n * The wrapper is `pointer-events: none` so host gestures pass through.\n *\n * @example\n * ```tsx\n * <div className=\"relative h-screen w-screen\">\n *   <Canvas />\n *   <LiveCursor x={420} y={180} name=\"Bea\" color=\"#5b8def\" />\n * </div>\n * ```\n *\n * @public\n */\nexport const LiveCursor = forwardRef<HTMLDivElement, LiveCursorProps>(\n  (props, ref) => {\n    const { className, color, labels, name, status, x, y, ...rest } = props;\n    const resolvedLabels = { ...DEFAULT_LABELS, ...labels };\n    const resolvedColor = color ?? \"var(--foreground)\";\n    return (\n      <div\n        aria-label={\n          typeof name === \"string\"\n            ? `${resolvedLabels.region}: ${name}`\n            : resolvedLabels.region\n        }\n        className={cn(\n          \"pointer-events-none absolute z-30 flex items-start gap-1\",\n          className,\n        )}\n        data-live-cursor\n        ref={ref}\n        role=\"img\"\n        style={{ left: x, top: y }}\n        {...rest}\n      >\n        <svg\n          aria-hidden=\"true\"\n          className=\"-ml-1 -mt-1 drop-shadow-sm\"\n          data-live-cursor-pointer\n          fill={resolvedColor}\n          height={18}\n          viewBox=\"0 0 16 18\"\n          width={16}\n        >\n          <path d=\"M0 0 L0 14 L4 11 L7 17 L10 16 L7 10 L13 10 Z\" />\n        </svg>\n        {name === null || name === undefined ? null : (\n          <span\n            className=\"ml-2 mt-2 inline-flex flex-col rounded-md px-1.5 py-0.5 text-[10px] font-medium text-white shadow-sm\"\n            data-live-cursor-chip\n            style={{ backgroundColor: resolvedColor }}\n          >\n            <span>{name}</span>\n            {status ? (\n              <span className=\"text-[9px] opacity-80\" data-live-cursor-status>\n                {status}\n              </span>\n            ) : null}\n          </span>\n        )}\n      </div>\n    );\n  },\n);\nLiveCursor.displayName = \"LiveCursor\";\n",
      "type": "registry:component"
    }
  ],
  "version": "0.2.1",
  "stability": "stable"
}
