{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "bulk-action-bar",
  "title": "Bulk Action Bar",
  "description": "A floating toolbar for acting on selected rows. Escape clears the selection.",
  "dependencies": [
    "radix-ui",
    "lucide-react",
    "motion",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "utils",
    "button"
  ],
  "files": [
    {
      "path": "registry/default/ui/bulk-action-bar.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { XIcon } from \"lucide-react\"\nimport { AnimatePresence, motion, MotionConfig } from \"motion/react\"\nimport { Portal, Toolbar as ToolbarPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/registry/default/lib/utils\"\nimport { Button } from \"@/registry/default/ui/button\"\n\nconst BAR_SPRING = { type: \"spring\", bounce: 0.2, visualDuration: 0.3 } as const\nconst BAR_HIDDEN = { opacity: 0, y: 16 }\n\nconst bulkActionBarVariants = cva(\n  \"pointer-events-none inset-x-0 z-50 flex justify-center px-4\",\n  {\n    variants: {\n      placement: {\n        viewport: \"fixed bottom-6\",\n        container: \"absolute bottom-4\",\n      },\n    },\n    defaultVariants: {\n      placement: \"viewport\",\n    },\n  }\n)\n\nfunction useClearOnEscape(isActive: boolean, onClear: () => void) {\n  React.useEffect(() => {\n    if (!isActive) return\n    function handleKeyDown(event: KeyboardEvent) {\n      if (event.key !== \"Escape\" || event.defaultPrevented) return\n      onClear()\n    }\n    window.addEventListener(\"keydown\", handleKeyDown)\n    return () => window.removeEventListener(\"keydown\", handleKeyDown)\n  }, [isActive, onClear])\n}\n\nfunction SelectedCount({ count }: { count: number }) {\n  return (\n    <span className=\"flex items-center gap-1.5 px-2 text-sm whitespace-nowrap\">\n      <span className=\"relative inline-flex h-5 min-w-5 items-center justify-center overflow-hidden rounded-md bg-primary px-1 font-mono text-xs text-primary-foreground tabular-nums\">\n        <AnimatePresence mode=\"popLayout\" initial={false}>\n          <motion.span\n            key={count}\n            initial={{ y: 8, opacity: 0 }}\n            animate={{ y: 0, opacity: 1 }}\n            exit={{ y: -8, opacity: 0 }}\n            transition={BAR_SPRING}\n          >\n            {count}\n          </motion.span>\n        </AnimatePresence>\n      </span>{\" \"}\n      selected\n    </span>\n  )\n}\n\nfunction BulkActionBar({\n  selectedCount,\n  onClear,\n  placement,\n  \"aria-label\": ariaLabel = \"Bulk actions\",\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof ToolbarPrimitive.Root> &\n  VariantProps<typeof bulkActionBarVariants> & {\n    selectedCount: number\n    onClear: () => void\n  }) {\n  const isVisible = selectedCount > 0\n  useClearOnEscape(isVisible, onClear)\n\n  const bar = (\n    <MotionConfig reducedMotion=\"user\">\n      <AnimatePresence>\n        {isVisible && (\n          <motion.div\n            key=\"bulk-action-bar\"\n            initial={BAR_HIDDEN}\n            animate={{ opacity: 1, y: 0 }}\n            exit={BAR_HIDDEN}\n            transition={BAR_SPRING}\n            className={bulkActionBarVariants({ placement })}\n          >\n            <ToolbarPrimitive.Root\n              data-slot=\"bulk-action-bar\"\n              aria-label={ariaLabel}\n              className={cn(\n                \"pointer-events-auto flex max-w-full items-center gap-1 overflow-x-auto rounded-xl border bg-popover p-1.5 text-popover-foreground shadow-lg\",\n                className\n              )}\n              {...props}\n            >\n              <SelectedCount count={selectedCount} />\n              <ToolbarPrimitive.Separator className=\"mx-1 h-5 w-px shrink-0 bg-border\" />\n              {children}\n              <ToolbarPrimitive.Separator className=\"mx-1 h-5 w-px shrink-0 bg-border\" />\n              <ToolbarPrimitive.Button asChild>\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  aria-label=\"Clear selection\"\n                  onClick={onClear}\n                  className=\"size-8\"\n                >\n                  <XIcon />\n                </Button>\n              </ToolbarPrimitive.Button>\n            </ToolbarPrimitive.Root>\n          </motion.div>\n        )}\n      </AnimatePresence>\n    </MotionConfig>\n  )\n\n  if (placement === \"container\") return bar\n  return <Portal.Root>{bar}</Portal.Root>\n}\n\nfunction BulkActionBarButton({\n  variant = \"ghost\",\n  size = \"sm\",\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  return (\n    <ToolbarPrimitive.Button asChild>\n      <Button\n        data-slot=\"bulk-action-bar-button\"\n        variant={variant}\n        size={size}\n        {...props}\n      />\n    </ToolbarPrimitive.Button>\n  )\n}\n\nexport { BulkActionBar, BulkActionBarButton, bulkActionBarVariants }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}