{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-table",
  "title": "Data Table",
  "description": "A typed data table with sorting, scoped search, row selection, column visibility, loading and empty states, and client pagination.",
  "dependencies": [
    "@base-ui/react",
    "@tanstack/react-table",
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/rivetui/components/data-table/data-table.tsx",
      "content": "\"use client\";\n\nimport { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\";\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\";\nimport {\n  type CellData,\n  type Column,\n  type ColumnDef,\n  columnFilteringFeature,\n  columnVisibilityFeature,\n  createColumnHelper,\n  createFilteredRowModel,\n  createPaginatedRowModel,\n  createSortedRowModel,\n  filterFn_arrIncludes,\n  filterFn_equals,\n  filterFn_includesString,\n  filterFn_inDateRange,\n  filterFn_inNumberRange,\n  filterFn_weakEquals,\n  functionalUpdate,\n  globalFilteringFeature,\n  metaHelper,\n  type OnChangeFn,\n  type ReactTable,\n  type Row,\n  type RowData,\n  type RowSelectionState,\n  rowPaginationFeature,\n  rowSelectionFeature,\n  rowSortingFeature,\n  sortFn_alphanumeric,\n  sortFn_datetime,\n  sortFn_text,\n  type Table,\n  type TableOptions,\n  tableFeatures,\n  useTable,\n} from \"@tanstack/react-table\";\nimport {\n  ArrowDown,\n  ArrowUp,\n  Check,\n  ChevronDown,\n  ChevronFirst,\n  ChevronLast,\n  ChevronLeft,\n  ChevronRight,\n  ChevronsUpDown,\n  Columns2,\n  Minus,\n  Search,\n  X,\n} from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype DataTableColumnMeta = {\n  cellClassName?: string;\n  headerClassName?: string;\n  label?: string;\n};\n\nconst dataTableFeatures = tableFeatures({\n  columnVisibilityFeature,\n  columnFilteringFeature,\n  globalFilteringFeature,\n  filteredRowModel: createFilteredRowModel(),\n  filterFns: {\n    arrIncludes: filterFn_arrIncludes,\n    equals: filterFn_equals,\n    inDateRange: filterFn_inDateRange,\n    inNumberRange: filterFn_inNumberRange,\n    includesString: filterFn_includesString,\n    weakEquals: filterFn_weakEquals,\n  },\n  rowSortingFeature,\n  sortedRowModel: createSortedRowModel(),\n  sortFns: {\n    alphanumeric: sortFn_alphanumeric,\n    datetime: sortFn_datetime,\n    text: sortFn_text,\n  },\n  rowPaginationFeature,\n  paginatedRowModel: createPaginatedRowModel(),\n  rowSelectionFeature,\n  columnMeta: metaHelper<DataTableColumnMeta>(),\n});\n\ntype DataTableFeatures = typeof dataTableFeatures;\ntype DataTableCoreInstance<TData extends RowData> = Table<DataTableFeatures, TData>;\ntype DataTableInstance<TData extends RowData> = ReactTable<DataTableFeatures, TData>;\ntype DataTableColumnDef<TData extends RowData, TValue extends CellData = CellData> = ColumnDef<\n  DataTableFeatures,\n  TData,\n  TValue\n>;\ntype DataTableInitialState = NonNullable<TableOptions<DataTableFeatures, RowData>[\"initialState\"]>;\ntype DataTableRowSelectionState = RowSelectionState;\n\ntype DataTableSearchOptions = {\n  columnIds?: readonly string[];\n  label?: string;\n  placeholder?: string;\n};\n\ntype DataTablePaginationOptions = {\n  pageSize?: number;\n  pageSizeOptions?: readonly number[];\n};\n\ntype DataTableProps<TData extends RowData> = {\n  \"aria-label\"?: string;\n  className?: string;\n  columns: TableOptions<DataTableFeatures, TData>[\"columns\"];\n  data: readonly TData[];\n  defaultRowSelection?: DataTableRowSelectionState;\n  emptyState?: React.ReactNode;\n  getRowId?: TableOptions<DataTableFeatures, TData>[\"getRowId\"];\n  initialState?: TableOptions<DataTableFeatures, TData>[\"initialState\"];\n  loading?: boolean;\n  loadingRows?: number;\n  onRowSelectionChange?: (rowSelection: DataTableRowSelectionState) => void;\n  pagination?: false | DataTablePaginationOptions;\n  rowSelection?: DataTableRowSelectionState;\n  search?: string | DataTableSearchOptions;\n  tableClassName?: string;\n  toolbar?: React.ReactNode | ((table: DataTableInstance<TData>) => React.ReactNode);\n};\n\nfunction DataTable<TData extends RowData>({\n  \"aria-label\": ariaLabel = \"Data table\",\n  className,\n  columns,\n  data,\n  defaultRowSelection,\n  emptyState,\n  getRowId,\n  initialState,\n  loading = false,\n  loadingRows = 5,\n  onRowSelectionChange,\n  pagination = {},\n  rowSelection,\n  search,\n  tableClassName,\n  toolbar,\n}: DataTableProps<TData>) {\n  const [internalRowSelection, setInternalRowSelection] =\n    React.useState<DataTableRowSelectionState>(\n      () => rowSelection ?? defaultRowSelection ?? initialState?.rowSelection ?? {},\n    );\n  const controlledRowSelection = rowSelection !== undefined;\n  const resolvedRowSelection = rowSelection ?? internalRowSelection;\n  const handleRowSelectionChange = React.useCallback<OnChangeFn<DataTableRowSelectionState>>(\n    (updater) => {\n      const nextRowSelection = functionalUpdate(updater, resolvedRowSelection);\n\n      if (!controlledRowSelection) {\n        setInternalRowSelection(nextRowSelection);\n      }\n\n      onRowSelectionChange?.(nextRowSelection);\n    },\n    [controlledRowSelection, onRowSelectionChange, resolvedRowSelection],\n  );\n  const searchOptions = normalizeSearchOptions(search);\n  const paginationOptions = pagination === false ? undefined : pagination;\n  const initialPageSize = paginationOptions?.pageSize ?? 10;\n  const table = useTable({\n    features: dataTableFeatures,\n    columns,\n    data,\n    getRowId,\n    initialState: {\n      ...initialState,\n      rowSelection: resolvedRowSelection,\n      pagination: initialState?.pagination ?? {\n        pageIndex: 0,\n        pageSize: initialPageSize,\n      },\n    },\n    globalFilterFn: \"includesString\",\n    state: { rowSelection: resolvedRowSelection },\n    onRowSelectionChange: handleRowSelectionChange,\n    getColumnCanGlobalFilter: (column) => {\n      if (!column.accessorFn) {\n        return false;\n      }\n\n      return searchOptions?.columnIds ? searchOptions.columnIds.includes(column.id) : true;\n    },\n    manualPagination: pagination === false,\n  });\n  const hideableColumns = table.getAllLeafColumns().filter((column) => column.getCanHide());\n  const toolbarContent = typeof toolbar === \"function\" ? toolbar(table) : toolbar;\n  const showToolbar = Boolean(searchOptions || toolbarContent || hideableColumns.length > 0);\n  const visibleColumnCount = Math.max(table.getVisibleLeafColumns().length, 1);\n  const rows = table.getRowModel().rows;\n\n  return (\n    <div\n      data-slot=\"data-table\"\n      className={cn(\"w-full min-w-0 max-w-full border border-border bg-background\", className)}\n    >\n      {showToolbar ? (\n        <DataTableToolbar table={table} search={searchOptions} hideableColumns={hideableColumns}>\n          {toolbarContent}\n        </DataTableToolbar>\n      ) : null}\n\n      <div data-slot=\"data-table-container\" className=\"relative w-full overflow-x-auto\">\n        <table\n          data-slot=\"data-table-table\"\n          aria-label={ariaLabel}\n          aria-busy={loading || undefined}\n          className={cn(\"w-full caption-bottom border-collapse text-sm\", tableClassName)}\n        >\n          <thead data-slot=\"data-table-header\" className=\"bg-muted/40\">\n            {table.getHeaderGroups().map((headerGroup) => (\n              <tr key={headerGroup.id} className=\"border-b border-border\">\n                {headerGroup.headers.map((header) => {\n                  const sorted = header.column.getIsSorted();\n\n                  return (\n                    <th\n                      key={header.id}\n                      colSpan={header.colSpan}\n                      aria-sort={\n                        sorted === \"asc\"\n                          ? \"ascending\"\n                          : sorted === \"desc\"\n                            ? \"descending\"\n                            : undefined\n                      }\n                      className={cn(\n                        \"h-10 whitespace-nowrap px-4 text-left align-middle font-mono text-[0.6875rem] font-medium uppercase tracking-[0.12em] text-muted-foreground\",\n                        header.column.columnDef.meta?.headerClassName,\n                      )}\n                    >\n                      {header.isPlaceholder ? null : <table.FlexRender header={header} />}\n                    </th>\n                  );\n                })}\n              </tr>\n            ))}\n          </thead>\n          <tbody data-slot=\"data-table-body\">\n            {loading ? (\n              <DataTableLoadingRows columns={visibleColumnCount} rows={Math.max(1, loadingRows)} />\n            ) : rows.length > 0 ? (\n              rows.map((row) => (\n                <tr\n                  key={row.id}\n                  data-state={row.getIsSelected() ? \"selected\" : undefined}\n                  className=\"border-b border-border transition-colors duration-100 last:border-b-0 hover:bg-muted/40 data-[state=selected]:bg-muted motion-reduce:transition-none\"\n                >\n                  {row.getVisibleCells().map((cell) => (\n                    <td\n                      key={cell.id}\n                      className={cn(\n                        \"whitespace-nowrap px-4 py-3 align-middle\",\n                        cell.column.columnDef.meta?.cellClassName,\n                      )}\n                    >\n                      <table.FlexRender cell={cell} />\n                    </td>\n                  ))}\n                </tr>\n              ))\n            ) : (\n              <tr>\n                <td colSpan={visibleColumnCount} className=\"h-36 px-4 text-center\">\n                  {emptyState ?? (\n                    <div className=\"mx-auto max-w-sm\">\n                      <p className=\"text-sm font-medium\">No results</p>\n                      <p className=\"mt-1 text-xs leading-5 text-muted-foreground\">\n                        Adjust the active filters or provide a different query.\n                      </p>\n                    </div>\n                  )}\n                </td>\n              </tr>\n            )}\n          </tbody>\n        </table>\n      </div>\n\n      {paginationOptions ? <DataTablePagination table={table} options={paginationOptions} /> : null}\n\n      {loading ? (\n        <span role=\"status\" className=\"sr-only\">\n          Loading table data\n        </span>\n      ) : null}\n    </div>\n  );\n}\n\ntype DataTableColumnHeaderProps<TData extends RowData, TValue extends CellData> = Omit<\n  React.ComponentProps<\"button\">,\n  \"children\"\n> & {\n  column: Column<DataTableFeatures, TData, TValue>;\n  title: React.ReactNode;\n};\n\nfunction DataTableColumnHeader<TData extends RowData, TValue extends CellData>({\n  className,\n  column,\n  title,\n  ...props\n}: DataTableColumnHeaderProps<TData, TValue>) {\n  if (!column.getCanSort()) {\n    return <span className={className}>{title}</span>;\n  }\n\n  const sorted = column.getIsSorted();\n  const nextOrder = column.getNextSortingOrder();\n  const label =\n    nextOrder === \"asc\"\n      ? `Sort ${getColumnLabel(column)} ascending`\n      : nextOrder === \"desc\"\n        ? `Sort ${getColumnLabel(column)} descending`\n        : `Clear sorting for ${getColumnLabel(column)}`;\n\n  return (\n    <button\n      type=\"button\"\n      data-slot=\"data-table-column-header\"\n      aria-label={label}\n      className={cn(\n        \"-mx-2 inline-flex h-8 cursor-pointer items-center gap-2 px-2 text-left outline-none transition-colors duration-100 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none\",\n        className,\n      )}\n      onClick={column.getToggleSortingHandler()}\n      {...props}\n    >\n      <span>{title}</span>\n      {sorted === \"asc\" ? (\n        <ArrowUp className=\"size-3.5\" aria-hidden=\"true\" />\n      ) : sorted === \"desc\" ? (\n        <ArrowDown className=\"size-3.5\" aria-hidden=\"true\" />\n      ) : (\n        <ChevronsUpDown className=\"size-3.5 opacity-60\" aria-hidden=\"true\" />\n      )}\n      {column.getSortIndex() > 0 ? (\n        <span className=\"text-[0.5625rem] tabular-nums\">{column.getSortIndex() + 1}</span>\n      ) : null}\n    </button>\n  );\n}\n\nfunction DataTableSelectHeader<TData extends RowData>({\n  label = \"Select all rows on this page\",\n  table,\n}: {\n  label?: string;\n  table: DataTableCoreInstance<TData>;\n}) {\n  const checked = table.getIsAllPageRowsSelected();\n  const indeterminate = !checked && table.getIsSomePageRowsSelected();\n\n  return (\n    <DataTableCheckbox\n      aria-label={label}\n      checked={checked}\n      indeterminate={indeterminate}\n      onCheckedChange={(nextChecked) => table.toggleAllPageRowsSelected(nextChecked)}\n    />\n  );\n}\n\nfunction DataTableSelectCell<TData extends RowData>({\n  label = \"Select row\",\n  row,\n}: {\n  label?: string;\n  row: Row<DataTableFeatures, TData>;\n}) {\n  return (\n    <DataTableCheckbox\n      aria-label={label}\n      checked={row.getIsSelected()}\n      disabled={!row.getCanSelect()}\n      onClick={(event) => {\n        row.getToggleSelectedHandler()({\n          target: { checked: !row.getIsSelected() },\n          shiftKey: event.shiftKey,\n          nativeEvent: event.nativeEvent,\n        });\n      }}\n    />\n  );\n}\n\nfunction DataTableToolbar<TData extends RowData>({\n  children,\n  hideableColumns,\n  search,\n  table,\n}: {\n  children?: React.ReactNode;\n  hideableColumns: ReturnType<DataTableInstance<TData>[\"getAllLeafColumns\"]>;\n  search?: DataTableSearchOptions;\n  table: DataTableInstance<TData>;\n}) {\n  const searchId = React.useId();\n  const query = String(table.state.globalFilter ?? \"\");\n\n  return (\n    <div\n      data-slot=\"data-table-toolbar\"\n      className=\"flex min-w-0 flex-col gap-3 border-b border-border p-3 sm:flex-row sm:flex-wrap sm:items-center\"\n    >\n      {search ? (\n        <div className=\"relative w-full min-w-0 sm:flex-[1_1_12rem] sm:max-w-sm\">\n          <label htmlFor={searchId} className=\"sr-only\">\n            {search.label ?? \"Search table\"}\n          </label>\n          <Search\n            className=\"pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\"\n            aria-hidden=\"true\"\n          />\n          <input\n            id={searchId}\n            type=\"search\"\n            value={query}\n            autoComplete=\"off\"\n            data-1p-ignore\n            data-lpignore=\"true\"\n            placeholder={search.placeholder ?? \"Search rows…\"}\n            className=\"h-10 w-full appearance-none border border-input bg-background py-2 pr-10 pl-10 text-sm outline-none transition-[border-color,box-shadow] duration-100 placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 [&::-webkit-search-cancel-button]:appearance-none motion-reduce:transition-none\"\n            onChange={(event) => table.setGlobalFilter(event.currentTarget.value)}\n          />\n          {query ? (\n            <button\n              type=\"button\"\n              aria-label=\"Clear table search\"\n              className=\"absolute top-px right-px inline-flex h-[calc(100%-2px)] w-10 cursor-pointer items-center justify-center border-l border-input text-muted-foreground outline-none transition-colors duration-100 hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40 motion-reduce:transition-none\"\n              onClick={() => table.setGlobalFilter(\"\")}\n            >\n              <X className=\"size-3.5\" aria-hidden=\"true\" />\n            </button>\n          ) : null}\n        </div>\n      ) : null}\n\n      <div className=\"flex min-w-0 flex-wrap items-center gap-2 sm:ml-auto\">\n        {children}\n        {hideableColumns.length > 0 ? (\n          <DataTableViewOptions table={table} columns={hideableColumns} />\n        ) : null}\n      </div>\n    </div>\n  );\n}\n\nfunction DataTableViewOptions<TData extends RowData>({\n  columns,\n  table: _table,\n}: {\n  columns: ReturnType<DataTableInstance<TData>[\"getAllLeafColumns\"]>;\n  table: DataTableInstance<TData>;\n}) {\n  return (\n    <MenuPrimitive.Root>\n      <MenuPrimitive.Trigger\n        render={<DataTableControlButton />}\n        aria-label=\"Choose visible columns\"\n      >\n        <Columns2 aria-hidden=\"true\" />\n        Columns\n        <ChevronDown aria-hidden=\"true\" />\n      </MenuPrimitive.Trigger>\n      <MenuPrimitive.Portal>\n        <MenuPrimitive.Positioner align=\"end\" sideOffset={6} className=\"isolate z-50 outline-none\">\n          <MenuPrimitive.Popup className=\"min-w-52 origin-(--transform-origin) border border-border bg-popover p-1 text-popover-foreground outline-none transition-[opacity,transform] duration-100 data-ending-style:scale-[0.98] data-ending-style:opacity-0 data-starting-style:scale-[0.98] data-starting-style:opacity-0 motion-reduce:transition-none\">\n            <MenuPrimitive.Group>\n              <MenuPrimitive.GroupLabel className=\"px-3 py-2 font-mono text-[0.625rem] font-medium uppercase tracking-[0.14em] text-muted-foreground\">\n                Visible columns\n              </MenuPrimitive.GroupLabel>\n              {columns.map((column) => (\n                <MenuPrimitive.CheckboxItem\n                  key={column.id}\n                  checked={column.getIsVisible()}\n                  className=\"relative flex min-h-9 cursor-default select-none items-center py-2 pr-3 pl-9 text-sm outline-none data-highlighted:bg-accent data-highlighted:text-accent-foreground\"\n                  onCheckedChange={(checked) => column.toggleVisibility(checked)}\n                >\n                  <MenuPrimitive.CheckboxItemIndicator className=\"absolute left-3 grid size-4 place-items-center\">\n                    <Check className=\"size-3.5\" strokeWidth={2.5} aria-hidden=\"true\" />\n                  </MenuPrimitive.CheckboxItemIndicator>\n                  {getColumnLabel(column)}\n                </MenuPrimitive.CheckboxItem>\n              ))}\n            </MenuPrimitive.Group>\n          </MenuPrimitive.Popup>\n        </MenuPrimitive.Positioner>\n      </MenuPrimitive.Portal>\n    </MenuPrimitive.Root>\n  );\n}\n\nfunction DataTablePagination<TData extends RowData>({\n  options,\n  table,\n}: {\n  options: DataTablePaginationOptions;\n  table: DataTableInstance<TData>;\n}) {\n  const filteredRows = table.getFilteredRowModel().rows.length;\n  const selectedRows = table.getFilteredSelectedRowModel().rows.length;\n  const pageCount = table.getPageCount();\n  const currentPage = pageCount === 0 ? 0 : table.state.pagination.pageIndex + 1;\n  const pageSizeOptions = normalizePageSizeOptions(\n    options.pageSizeOptions,\n    table.state.pagination.pageSize,\n  );\n\n  return (\n    <div\n      data-slot=\"data-table-pagination\"\n      className=\"flex min-w-0 flex-col gap-3 border-t border-border px-3 py-3 sm:flex-row sm:items-center sm:justify-between\"\n    >\n      <p\n        className=\"font-mono text-[0.625rem] uppercase tracking-[0.12em] text-muted-foreground\"\n        aria-live=\"polite\"\n      >\n        {selectedRows > 0\n          ? `${selectedRows} of ${filteredRows} rows selected`\n          : `${filteredRows} ${filteredRows === 1 ? \"row\" : \"rows\"}`}\n      </p>\n\n      <div className=\"flex min-w-0 flex-wrap items-center gap-2 sm:justify-end\">\n        <label className=\"flex items-center gap-2 font-mono text-[0.625rem] uppercase tracking-[0.12em] text-muted-foreground\">\n          Rows\n          <span className=\"relative\">\n            <select\n              aria-label=\"Rows per page\"\n              value={table.state.pagination.pageSize}\n              className=\"h-8 cursor-pointer appearance-none border border-input bg-background pr-8 pl-3 font-mono text-xs text-foreground outline-none transition-[border-color,box-shadow] duration-100 focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none\"\n              onChange={(event) => table.setPageSize(Number(event.currentTarget.value))}\n            >\n              {pageSizeOptions.map((pageSize) => (\n                <option key={pageSize} value={pageSize}>\n                  {pageSize}\n                </option>\n              ))}\n            </select>\n            <ChevronDown\n              className=\"pointer-events-none absolute top-1/2 right-2 size-3.5 -translate-y-1/2 text-muted-foreground\"\n              aria-hidden=\"true\"\n            />\n          </span>\n        </label>\n\n        <span className=\"min-w-20 text-center font-mono text-[0.625rem] uppercase tracking-[0.12em] text-muted-foreground tabular-nums\">\n          {String(currentPage).padStart(2, \"0\")} / {String(pageCount).padStart(2, \"0\")}\n        </span>\n\n        <div className=\"flex items-center gap-1\">\n          <DataTableControlButton\n            size=\"icon\"\n            aria-label=\"First page\"\n            disabled={!table.getCanPreviousPage()}\n            onClick={() => table.firstPage()}\n          >\n            <ChevronFirst aria-hidden=\"true\" />\n          </DataTableControlButton>\n          <DataTableControlButton\n            size=\"icon\"\n            aria-label=\"Previous page\"\n            disabled={!table.getCanPreviousPage()}\n            onClick={() => table.previousPage()}\n          >\n            <ChevronLeft aria-hidden=\"true\" />\n          </DataTableControlButton>\n          <DataTableControlButton\n            size=\"icon\"\n            aria-label=\"Next page\"\n            disabled={!table.getCanNextPage()}\n            onClick={() => table.nextPage()}\n          >\n            <ChevronRight aria-hidden=\"true\" />\n          </DataTableControlButton>\n          <DataTableControlButton\n            size=\"icon\"\n            aria-label=\"Last page\"\n            disabled={!table.getCanLastPage()}\n            onClick={() => table.lastPage()}\n          >\n            <ChevronLast aria-hidden=\"true\" />\n          </DataTableControlButton>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nfunction DataTableControlButton({\n  className,\n  size = \"text\",\n  type = \"button\",\n  ...props\n}: React.ComponentProps<\"button\"> & { size?: \"icon\" | \"text\" }) {\n  return (\n    <button\n      type={type}\n      data-slot=\"data-table-control\"\n      className={cn(\n        \"inline-flex h-8 shrink-0 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap border border-border bg-background px-3 text-xs font-medium outline-none transition-[background-color,border-color,color,opacity] duration-100 hover:border-foreground/40 hover:bg-muted focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-40 motion-reduce:transition-none [&_svg]:size-3.5 [&_svg]:shrink-0\",\n        size === \"icon\" && \"w-8 px-0\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction DataTableCheckbox({ className, ...props }: CheckboxPrimitive.Root.Props) {\n  return (\n    <CheckboxPrimitive.Root\n      data-slot=\"data-table-checkbox\"\n      className={cn(\n        \"relative inline-flex size-4 shrink-0 cursor-pointer items-center justify-center border border-input bg-background text-primary-foreground outline-none transition-[background-color,border-color,box-shadow,opacity] duration-100 after:absolute after:-inset-2.5 hover:border-foreground/50 focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary data-disabled:cursor-not-allowed data-disabled:opacity-40 motion-reduce:transition-none\",\n        className,\n      )}\n      {...props}\n    >\n      <CheckboxPrimitive.Indicator className=\"group/indicator grid place-items-center text-current [&_svg]:size-3\">\n        <Check\n          className=\"group-data-[indeterminate]/indicator:hidden\"\n          strokeWidth={2.5}\n          aria-hidden=\"true\"\n        />\n        <Minus\n          className=\"hidden group-data-[indeterminate]/indicator:block\"\n          strokeWidth={2.5}\n          aria-hidden=\"true\"\n        />\n      </CheckboxPrimitive.Indicator>\n    </CheckboxPrimitive.Root>\n  );\n}\n\nfunction DataTableLoadingRows({ columns, rows }: { columns: number; rows: number }) {\n  return Array.from({ length: rows }, (_, rowIndex) => (\n    // Skeleton rows are a fixed, non-interactive sequence with no retained item state.\n    // biome-ignore lint/suspicious/noArrayIndexKey: Skeleton order and identity never change.\n    <tr key={`loading-${rowIndex}`} className=\"border-b border-border last:border-b-0\">\n      {Array.from({ length: columns }, (_, columnIndex) => (\n        // biome-ignore lint/suspicious/noArrayIndexKey: Skeleton cells are positional placeholders.\n        <td key={`loading-${rowIndex}-${columnIndex}`} className=\"px-4 py-3\">\n          <span\n            className={cn(\n              \"block h-4 animate-pulse bg-muted motion-reduce:animate-none\",\n              columnIndex % 3 === 0 ? \"w-24\" : \"w-16\",\n            )}\n          />\n        </td>\n      ))}\n    </tr>\n  ));\n}\n\nfunction createDataTableColumnHelper<TData extends RowData>() {\n  return createColumnHelper<DataTableFeatures, TData>();\n}\n\nfunction normalizeSearchOptions(search: string | DataTableSearchOptions | undefined) {\n  if (!search) {\n    return undefined;\n  }\n\n  return typeof search === \"string\" ? { columnIds: [search] } : search;\n}\n\nfunction normalizePageSizeOptions(options: readonly number[] | undefined, current: number) {\n  return Array.from(new Set([...(options ?? [10, 20, 50]), current]))\n    .filter((value) => Number.isInteger(value) && value > 0)\n    .sort((left, right) => left - right);\n}\n\nfunction getColumnLabel<TData extends RowData, TValue extends CellData>(\n  column: Column<DataTableFeatures, TData, TValue>,\n) {\n  const header = column.columnDef.header;\n\n  if (column.columnDef.meta?.label) {\n    return column.columnDef.meta.label;\n  }\n\n  if (typeof header === \"string\") {\n    return header;\n  }\n\n  return column.id\n    .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n    .replace(/[-_]+/g, \" \")\n    .replace(/^./, (character) => character.toUpperCase());\n}\n\nexport type {\n  DataTableColumnDef,\n  DataTableColumnHeaderProps,\n  DataTableColumnMeta,\n  DataTableInitialState,\n  DataTableInstance,\n  DataTablePaginationOptions,\n  DataTableProps,\n  DataTableRowSelectionState,\n  DataTableSearchOptions,\n};\nexport {\n  createDataTableColumnHelper,\n  DataTable,\n  DataTableColumnHeader,\n  DataTableSelectCell,\n  DataTableSelectHeader,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}