{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"action-bar","type":"registry:ui","title":"Action Bar","description":"The bar that rises while rows are selected: the count, actions for them, and a way to clear.","dependencies":["lucide-react"],"registryDependencies":["https://dashral.com/r/utils.json","https://dashral.com/r/lib-locale.json"],"files":[{"path":"registry/dashral/action-bar.tsx","type":"registry:file","target":"components/dashral/action-bar.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\nimport { XIcon } from \"lucide-react\"\n\nimport { useLocale } from \"./lib/locale\"\nimport { cn } from \"./lib/utils\"\n\ntype ActionBarProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  /** Whether it shows: usually while something is selected (`open={selected.length > 0}`). */\n  open: boolean\n  /** How many are selected: \"3 selected\", in the locale's plural. */\n  count?: number\n  /** In place of \"3 selected\", e.g. \"3 invoices selected\". */\n  label?: React.ReactNode\n  /** The buttons: Delete, Export, Move to…, a menu of more. */\n  actions: React.ReactNode\n  /** An × that clears the selection, and Escape inside the bar does the same. */\n  onClear?: () => void\n  /** fixed (default): floating at the bottom of the window, centred. inline: in the page's flow, e.g. at a card's foot. */\n  position?: \"fixed\" | \"inline\"\n  /** Names the toolbar for screen readers. \"Actions for the selection\" by default. */\n  \"aria-label\"?: string\n  classNames?: { label?: string; actions?: string }\n}\n\n/**\n * The bar that rises from the bottom while rows are selected, in one tag: the count, the actions for them and a way to\n * clear the selection. It slides up and fades in on the spring, and away again, staying in the page while hidden so\n * nothing jumps. The count is announced as it changes.\n */\nfunction ActionBar({\n  open,\n  count,\n  label,\n  actions,\n  onClear,\n  position = \"fixed\",\n  className,\n  classNames,\n  \"aria-label\": ariaLabel,\n  ...props\n}: ActionBarProps) {\n  const { t } = useLocale()\n  // Keeps the last count while it slides away, so \"0 selected\" never shows on the way out.\n  const [shown, setShown] = React.useState(count)\n  if (open && count !== shown) setShown(count)\n  const text = label ?? (shown !== undefined ? t(\"selectedCount\", { count: shown }) : null)\n\n  return (\n    <div\n      role=\"toolbar\"\n      data-slot=\"action-bar\"\n      data-state={open ? \"open\" : \"closed\"}\n      aria-label={ariaLabel ?? t(\"selectionActions\")}\n      aria-hidden={!open}\n      // While hidden it can't be tabbed into or clicked.\n      inert={!open}\n      onKeyDown={(event) => {\n        if (event.key === \"Escape\" && onClear) {\n          event.stopPropagation()\n          onClear()\n        }\n      }}\n      className={cn(\n        \"flex items-center gap-2 rounded-xl border bg-popover p-1.5 ps-3 text-sm text-popover-foreground shadow-lg\",\n        position === \"fixed\" && \"fixed inset-x-4 bottom-4 z-40 mx-auto w-auto max-w-fit max-sm:max-w-none\",\n        // Up and in on the spring; down and out quicker. Hidden, it stays in place (no layout shift) but invisible.\n        \"transition-[translate,opacity,visibility] motion-reduce:transition-[opacity,visibility]\",\n        open\n          ? \"visible translate-y-0 opacity-100 duration-(--duration-considered) ease-spring\"\n          : \"invisible translate-y-4 opacity-0 duration-(--duration-standard) ease-exit motion-reduce:translate-y-0\",\n        className\n      )}\n      {...props}\n    >\n      {text !== null && (\n        <span role=\"status\" className={cn(\"min-w-0 shrink-0 font-medium tabular-nums whitespace-nowrap\", classNames?.label)}>\n          {text}\n        </span>\n      )}\n      <span aria-hidden className=\"mx-1 h-5 w-px shrink-0 bg-border\" />\n      <div className={cn(\"flex min-w-0 flex-1 items-center gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\", classNames?.actions)}>{actions}</div>\n      {onClear && (\n        <button\n          type=\"button\"\n          aria-label={t(\"clearSelection\")}\n          onClick={onClear}\n          className=\"grid size-8 shrink-0 place-items-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 [&_svg]:size-4\"\n        >\n          <XIcon aria-hidden />\n        </button>\n      )}\n    </div>\n  )\n}\n\nexport { ActionBar, type ActionBarProps }\n"}],"cssVars":{"theme":{"ease-standard":"var(--ease-standard)","ease-enter":"var(--ease-enter)","ease-exit":"var(--ease-exit)","ease-spring":"var(--ease-spring)"},"light":{"duration-fast":"160ms","duration-standard":"240ms","duration-considered":"480ms","ease-standard":"cubic-bezier(0.2, 0, 0, 1)","ease-enter":"cubic-bezier(0, 0, 0, 1)","ease-exit":"cubic-bezier(0.3, 0, 1, 1)","ease-spring":"linear(0, 0.071 4%, 0.234 8%, 0.433 12%, 0.626 17%, 0.791 21%, 0.917 25%, 1.004 29%, 1.055 33%, 1.079 38%, 1.083 42%, 1.075 46%, 1.06 50%, 1.043 54%, 1.027 58%, 1.015 62%, 1.005 67%, 0.998 71%, 0.995 75%, 0.993 79%, 0.993 83%, 0.994 88%, 0.995 92%, 0.997 96%, 1)"},"dark":{}}}