{
  "$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": [
    "@base-ui/react",
    "lucide-react",
    "motion",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "utils",
    "button"
  ],
  "files": [
    {
      "path": "registry/base/ui/bulk-action-bar.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { XIcon } from \"lucide-react\"\nimport { AnimatePresence, motion, MotionConfig } from \"motion/react\"\nimport { Toolbar as ToolbarPrimitive } from \"@base-ui/react/toolbar\"\n\nimport { cn } from \"@/registry/default/lib/utils\"\nimport { Button } from \"@/registry/base/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 subscribeToNothing() {\n  return () => {}\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}: ToolbarPrimitive.Root.Props &\n  VariantProps<typeof bulkActionBarVariants> & {\n    selectedCount: number\n    onClear: () => void\n  }) {\n  const isClient = React.useSyncExternalStore(\n    subscribeToNothing,\n    () => true,\n    () => false\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\n                render={\n                  <Button\n                    variant=\"ghost\"\n                    size=\"icon\"\n                    aria-label=\"Clear selection\"\n                    onClick={onClear}\n                    className=\"size-8\"\n                  />\n                }\n              >\n                <XIcon />\n              </ToolbarPrimitive.Button>\n            </ToolbarPrimitive.Root>\n          </motion.div>\n        )}\n      </AnimatePresence>\n    </MotionConfig>\n  )\n\n  if (placement === \"container\") return bar\n  return isClient ? createPortal(bar, document.body) : null\n}\n\nfunction BulkActionBarButton({\n  variant = \"ghost\",\n  size = \"sm\",\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  return (\n    <ToolbarPrimitive.Button\n      render={\n        <Button\n          data-slot=\"bulk-action-bar-button\"\n          variant={variant}\n          size={size}\n          {...props}\n        />\n      }\n    />\n  )\n}\n\nexport { BulkActionBar, BulkActionBarButton, bulkActionBarVariants }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}