# Data Table

Tabular data with columns and rows.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any docs URL. An agent skill is available at [/.well-known/agent-skills/site-skill.md](/.well-known/agent-skills/site-skill.md).

## Installation

```bash
npx shadcn@latest add @angular-pdfcn/takumi/data-table
```

To install manually, add the dependencies:

```bash
npm install takumi-pdf @takumi-rs/helpers
```

Then copy these files into your project and update the import paths to match your setup:

- `components/pdf/data-table/data-table.styles.ts`
- `components/pdf/data-table/data-table.ts`
- `components/pdf/data-table/data-table.types.ts`
- `lib/resolve-color.ts`
- `components/pdf/theme-provider.ts`
- `lib/pdf-renderer.ts`
- `lib/pdf-primitives.ts`
- `lib/render.ts`
- `lib/pdf-themes/professional.ts`
- `lib/pdf-themes/primitives.ts`
- `types/pdf-themes.ts`
- `types/pdf-components.ts`
- `components/pdf/table/table.styles.ts`
- `components/pdf/table/table.ts`
- `components/pdf/table/table.types.ts`

## Usage

```ts
import { Component } from "@angular/core";

import { PdfDataTable } from "@/components/pdf/data-table/data-table";
import type { DataTableColumn } from "@/components/pdf/data-table/data-table.types";
import { PdfHeading } from "@/components/pdf/heading/heading";
import { PdfSection } from "@/components/pdf/section/section";
import { PdfcnThemeProvider } from "@/components/pdf/theme-provider";
import {
  TakumiDocument,
  TakumiPage,
} from "@/lib/pdf-primitives";

const data = [
  { dept: "Engineering", id: 1, name: "Alice Johnson", status: "Active" },
  { dept: "Marketing", id: 2, name: "Bob Smith", status: "Active" },
  { dept: "Design", id: 3, name: "Carol Lee", status: "Inactive" },
  { dept: "Engineering", id: 4, name: "Dan Wilson", status: "Active" },
  { dept: "Sales", id: 5, name: "Eve Brown", status: "Active" },
  { dept: "Support", id: 6, name: "Frank Chen", status: "Active" },
  { dept: "Product", id: 7, name: "Grace Kim", status: "Active" },
  { dept: "Marketing", id: 8, name: "Hank Davis", status: "Inactive" },
];

const columns: DataTableColumn<(typeof data)[number]>[] = [
  { align: "center", header: "ID", key: "id" },
  { header: "Name", key: "name" },
  { header: "Department", key: "dept" },
  { align: "center", header: "Status", key: "status" },
];

@Component({
  imports: [
    TakumiDocument,
    TakumiPage,
    PdfcnThemeProvider,
    PdfDataTable,
    PdfHeading,
    PdfSection,
  ],
  template: `
    <takumi-document>
      <takumi-page size="A4">
        <pdf-theme-provider>
          <pdf-section spacing="none">
            <pdf-heading [level]="3">Team Directory</pdf-heading>
            <pdf-data-table
              size="compact"
              variant="striped"
              [columns]="columns"
              [data]="data"
            />
          </pdf-section>
        </pdf-theme-provider>
      </takumi-page>
    </takumi-document>
  `,
})
export class DataTableDemo {
  protected readonly columns = columns;
  protected readonly data = data;
}
```

### Variants

Use any `TableVariant` for the table treatment and `size="compact"` for denser reports.

```angular-html
<pdf-data-table
  [columns]="columns"
  [data]="rows"
  variant="striped"
  size="compact"
/>
```

## API Reference

### PdfDataTable

| Input     | Type                                                                                        | Default     |
| --------- | ------------------------------------------------------------------------------------------- | ----------- |
| `columns` | `DataTableColumn<T>[]`                                                                      | -           |
| `data`    | `T[]`                                                                                       | -           |
| `variant` | `'line' \| 'grid' \| 'minimal' \| 'striped' \| 'compact' \| 'bordered' \| 'primary-header'` | `'grid'`    |
| `footer`  | `Partial<Record<keyof T, string \| number>>`                                                | -           |
| `stripe`  | `boolean`                                                                                   | `false`     |
| `size`    | `'default' \| 'compact'`                                                                    | `'default'` |
| `noWrap`  | `boolean`                                                                                   | `false`     |
| `style`   | `Style`                                                                                     | -           |

### DataTableColumn

`key` is the row-field accessor. For example, `key: "name"` reads `row.name`.

`render` and `renderFooter` take a `TemplateRef`. A cell template gets the value as `$implicit` and the row as `row`. A footer template gets the footer value as `$implicit`.

```angular-ts
@Component({
  selector: "app-totals",
  imports: [PdfDataTable],
  template: `
    <ng-template #amount let-value let-row="row"
      >{{ row.currency }} {{ value }}</ng-template
    >
    <pdf-data-table [columns]="columns()" [data]="rows" />
  `,
})
export class Totals {
  protected readonly rows: Row[] = [
    { amount: 120, currency: "USD", item: "Design" },
  ];
  private readonly amount =
    viewChild<TemplateRef<DataTableCellContext<Row>>>("amount");
  protected readonly columns = computed((): DataTableColumn<Row>[] => [
    { header: "Item", key: "item" },
    { align: "right", header: "Amount", key: "amount", render: this.amount() },
  ]);
}
```

| Field          | Type                                   | Default  |
| -------------- | -------------------------------------- | -------- |
| `key`          | `keyof T & string`                     | -        |
| `header`       | `string`                               | -        |
| `align`        | `'left' \| 'center' \| 'right'`        | `'left'` |
| `width`        | `string \| number`                     | -        |
| `render`       | `TemplateRef<DataTableCellContext<T>>` | -        |
| `renderFooter` | `TemplateRef<DataTableFooterContext>`  | -        |