{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "openlmis-table-selection",
  "title": "Table Selection",
  "description": "A page selection checkbox column and a floating selected-count bar with Clear and actions.",
  "dependencies": [
    "@tanstack/react-table@^9",
    "lucide-react@^1",
    "@base-ui/react@^1"
  ],
  "registryDependencies": [
    "button",
    "checkbox",
    "https://registry.soldevelo.com/r/openlmis-data-table.json"
  ],
  "files": [
    {
      "path": "registry/components/openlmis/table-selection/table-selection.tsx",
      "content": "\"use client\"\n\nimport {\n  createColumnHelper,\n  type Row,\n  type RowData,\n  type Table,\n} from \"@tanstack/react-table\"\nimport { MinusIcon, XIcon } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport type { DataTableFeatures } from \"@/components/blocks/openlmis/data-table/data-table\"\n\nexport type TableSelectionLabels = {\n  selectPage: string\n  selectRow: (row: string) => string\n  selectedCount: (count: number) => string\n  clearSelection: string\n}\n\n// One fixed locale, so a server render and the browser print the same digits.\nconst count = new Intl.NumberFormat(\"en-US\")\n\nconst defaultLabels: TableSelectionLabels = {\n  selectPage: \"Select Page\",\n  selectRow: (row) => `Select ${row}`,\n  selectedCount: (selected) => `${count.format(selected)} Selected`,\n  clearSelection: \"Clear Selection\",\n}\n\nfunction SelectPageCheckbox<TData extends RowData>({\n  table,\n  label,\n}: {\n  table: Table<DataTableFeatures, TData>\n  label: string\n}) {\n  const all = table.getIsAllPageRowsSelected()\n\n  return (\n    <Checkbox\n      aria-label={label}\n      checked={all}\n      disabled={table.getRowModel().rows.length === 0}\n      indeterminate={!all && table.getIsSomePageRowsSelected()}\n      onCheckedChange={(checked) => table.toggleAllPageRowsSelected(checked)}\n      render={(props, state) => (\n        <span {...props}>\n          {state.indeterminate ? (\n            <MinusIcon className=\"size-3.5\" />\n          ) : (\n            props.children\n          )}\n        </span>\n      )}\n    />\n  )\n}\n\nfunction SelectRowCheckbox<TData extends RowData>({\n  row,\n  label,\n}: {\n  row: Row<DataTableFeatures, TData>\n  label: string\n}) {\n  return (\n    <Checkbox\n      aria-label={label}\n      checked={row.getIsSelected()}\n      disabled={!row.getCanSelect()}\n      onCheckedChange={(checked) => row.toggleSelected(checked)}\n    />\n  )\n}\n\n/** A leading checkbox column; `rowLabel` names each row for its checkbox, e.g. the product name. */\nexport function selectionColumn<TData extends RowData>(\n  rowLabel: (row: TData) => string,\n  labels?: Partial<Pick<TableSelectionLabels, \"selectPage\" | \"selectRow\">>\n) {\n  const { selectPage, selectRow } = { ...defaultLabels, ...labels }\n\n  return createColumnHelper<DataTableFeatures, TData>().display({\n    id: \"select\",\n    header: ({ table }) => (\n      <SelectPageCheckbox label={selectPage} table={table} />\n    ),\n    cell: ({ row }) => (\n      <SelectRowCheckbox label={selectRow(rowLabel(row.original))} row={row} />\n    ),\n    meta: { className: \"w-10\", skeleton: \"checkbox\" },\n  })\n}\n\ntype DataTableSelectionBarProps = {\n  /** Every selected row, including those on other pages. */\n  count: number\n  onClear: () => void\n  /** Actions on the selection, e.g. a Delete button. */\n  children: ReactNode\n  labels?: Partial<\n    Pick<TableSelectionLabels, \"selectedCount\" | \"clearSelection\">\n  >\n}\n\n/** Floats at the bottom of the page while rows are selected, with the count, Clear and the actions. */\nexport function DataTableSelectionBar({\n  count: selected,\n  onClear,\n  children,\n  labels: labelOverrides,\n}: DataTableSelectionBarProps) {\n  const labels = { ...defaultLabels, ...labelOverrides }\n\n  return (\n    <div className=\"@container/selection sticky bottom-2 z-10 -mb-2 lg:-mb-4\">\n      {selected > 0 && (\n        <div className=\"mx-auto flex w-full max-w-lg flex-col gap-2 rounded-xl border bg-card p-2 shadow-lg @md/selection:flex-row @md/selection:items-center @md/selection:ps-4\">\n          <span\n            aria-hidden=\"true\"\n            className=\"px-2 pt-1 text-sm font-medium @md/selection:p-0\"\n          >\n            {labels.selectedCount(selected)}\n          </span>\n          <div className=\"flex gap-2 *:flex-1 @md/selection:ms-auto @md/selection:*:flex-none\">\n            <Button onClick={onClear} size=\"sm\" variant=\"secondary\">\n              <XIcon data-icon=\"inline-start\" />\n              {labels.clearSelection}\n            </Button>\n            {children}\n          </div>\n        </div>\n      )}\n      {/* Always mounted, so the count is announced as it changes. */}\n      <span className=\"sr-only\" role=\"status\">\n        {selected > 0 ? labels.selectedCount(selected) : \"\"}\n      </span>\n    </div>\n  )\n}",
      "type": "registry:component",
      "target": "components/openlmis/table-selection.tsx"
    }
  ],
  "cssVars": {
    "light": {
      "destructive": "oklch(0.577 0.245 27.325)",
      "destructive-foreground": "oklch(0.985 0 0)",
      "success": "oklch(0.596 0.145 163.225)",
      "success-foreground": "oklch(0.985 0 0)",
      "warning": "oklch(0.666 0.179 58.318)",
      "warning-foreground": "oklch(0.985 0 0)",
      "info": "oklch(0.55 0.13 237)",
      "info-foreground": "oklch(0.985 0 0)"
    },
    "dark": {
      "destructive": "oklch(0.704 0.191 22.216)",
      "destructive-foreground": "oklch(0.21 0.04 25)",
      "success": "oklch(0.696 0.17 162.48)",
      "success-foreground": "oklch(0.21 0.04 163)",
      "warning": "oklch(0.769 0.188 70.08)",
      "warning-foreground": "oklch(0.22 0.04 60)",
      "info": "oklch(0.7 0.14 237)",
      "info-foreground": "oklch(0.2 0.04 240)"
    }
  },
  "meta": {
    "project": "openlmis",
    "height": "445px"
  },
  "docs": "Requires a `base-*` style in components.json (the `shadcn init` default). Legacy `new-york`/`radix-*` styles install Radix primitives, which reject the `render` prop this item uses.",
  "categories": [
    "data-table"
  ],
  "type": "registry:component"
}
