{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table-toolbar",
  "type": "registry:component",
  "title": "Table toolbar",
  "description": "Search, filter chips, column toggle and time range slots above a table.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@wibo/utils",
    "@wibo/button",
    "@wibo/chip",
    "@wibo/input"
  ],
  "files": [
    {
      "path": "src/patterns/table-toolbar.tsx",
      "type": "registry:component",
      "content": "import type { ComponentProps, ReactNode } from \"react\";\nimport { Search } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\nimport { Chip } from \"@/components/ui/chip\";\nimport { Input } from \"@/components/ui/input\";\n\ninterface ToolbarFilter {\n  id: string;\n  label: string;\n  value?: ReactNode;\n}\n\ninterface TableToolbarProps extends Omit<ComponentProps<\"div\">, \"children\"> {\n  searchValue?: string;\n  onSearchChange?: (value: string) => void;\n  searchPlaceholder?: string;\n  /** Active filters, shown as removable chips. */\n  filters?: ToolbarFilter[];\n  onRemoveFilter?: (id: string) => void;\n  onClearFilters?: () => void;\n  clearFiltersLabel?: string;\n  /** Trigger for adding a filter (menu or popover). */\n  filterSlot?: ReactNode;\n  /** Column visibility control, for example `DataTableColumnToggle`. */\n  columnToggle?: ReactNode;\n  /** Time range control, for example `DateRange` or a `Select` of presets. */\n  timeRange?: ReactNode;\n  /** Extra right-aligned actions. */\n  actions?: ReactNode;\n}\n\n/** Row above a table: search, filter chips, time range, column toggle. */\nfunction TableToolbar({\n  searchValue,\n  onSearchChange,\n  searchPlaceholder = \"Search\",\n  filters = [],\n  onRemoveFilter,\n  onClearFilters,\n  clearFiltersLabel = \"Clear filters\",\n  filterSlot,\n  columnToggle,\n  timeRange,\n  actions,\n  className,\n  ...props\n}: TableToolbarProps) {\n  return (\n    <div\n      data-slot=\"table-toolbar\"\n      role=\"toolbar\"\n      aria-orientation=\"horizontal\"\n      className={cn(\"flex flex-wrap items-center gap-2\", className)}\n      {...props}\n    >\n      {timeRange}\n      {onSearchChange ? (\n        <div className=\"relative w-full sm:w-64\">\n          <Search\n            aria-hidden=\"true\"\n            className=\"pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\"\n          />\n          <Input\n            type=\"search\"\n            value={searchValue ?? \"\"}\n            onChange={(event) => onSearchChange(event.target.value)}\n            placeholder={searchPlaceholder}\n            aria-label={searchPlaceholder}\n            className=\"pl-8.5\"\n          />\n        </div>\n      ) : null}\n      {filterSlot}\n      {filters.map((filter) => (\n        <Chip\n          key={filter.id}\n          label={filter.label}\n          value={filter.value}\n          onRemove={onRemoveFilter ? () => onRemoveFilter(filter.id) : undefined}\n        />\n      ))}\n      {filters.length > 0 && onClearFilters ? (\n        <Button variant=\"ghost\" size=\"sm\" onClick={onClearFilters}>\n          {clearFiltersLabel}\n        </Button>\n      ) : null}\n      {columnToggle || actions ? (\n        <div className=\"ml-auto flex items-center gap-2\">\n          {columnToggle}\n          {actions}\n        </div>\n      ) : null}\n    </div>\n  );\n}\n\nexport { TableToolbar };\nexport type { TableToolbarProps, ToolbarFilter };\n"
    }
  ]
}
