first commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# ngx-pretext-table
|
||||
|
||||
Variable-height virtual scrolling for PrimeNG `p-table`, powered by [@chenglou/pretext](https://github.com/chenglou/pretext).
|
||||
|
||||
PrimeNG's built-in virtual scroll only supports **fixed row heights** (`virtualScrollItemSize`). This library replaces it with pretext-calculated variable row heights — no DOM measurement, no layout thrashing, O(log n) scroll lookup.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install ngx-pretext-table @chenglou/pretext
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { Component } from '@angular/core';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import {
|
||||
PretextVirtualScrollDirective,
|
||||
PretextScrollEvent,
|
||||
PretextColumnDef,
|
||||
} from 'ngx-pretext-table';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [TableModule, PretextVirtualScrollDirective],
|
||||
template: `
|
||||
<div pretextVirtualScroll
|
||||
[data]="data"
|
||||
[columns]="columns"
|
||||
[font]="'14px system-ui'"
|
||||
[lineHeight]="20"
|
||||
[rowPadding]="16"
|
||||
[scrollHeight]="'500px'"
|
||||
(visibleRangeChange)="onRange($event)">
|
||||
|
||||
<p-table [value]="visibleData" [scrollable]="false">
|
||||
<ng-template pTemplate="body" let-row let-i="rowIndex">
|
||||
<tr [style.height.px]="rowHeights[i]">
|
||||
<td>{{ row.name }}</td>
|
||||
<td>{{ row.description }}</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class MyComponent {
|
||||
data = [/* your data */];
|
||||
|
||||
// field + available text width (column width minus padding)
|
||||
columns: PretextColumnDef[] = [
|
||||
{ field: 'name', width: 184 },
|
||||
{ field: 'description', width: 384 },
|
||||
];
|
||||
|
||||
visibleData: any[] = [];
|
||||
rowHeights: number[] = [];
|
||||
|
||||
onRange(e: PretextScrollEvent) {
|
||||
this.visibleData = this.data.slice(e.start, e.end);
|
||||
this.rowHeights = e.rowHeights;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `PretextVirtualScrollDirective`
|
||||
|
||||
| Input | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `data` | `any[]` | required | Full data array |
|
||||
| `columns` | `PretextColumnDef[]` | required | Column field + text width |
|
||||
| `font` | `string` | `'14px system-ui'` | CSS font shorthand |
|
||||
| `lineHeight` | `number` | `20` | Line height in px |
|
||||
| `rowPadding` | `number` | `16` | Vertical padding per row |
|
||||
| `minRowHeight` | `number` | `32` | Minimum row height |
|
||||
| `rowGap` | `number` | `0` | Gap between rows |
|
||||
| `scrollHeight` | `string` | `'400px'` | Viewport height |
|
||||
| `bufferRows` | `number` | `5` | Buffer rows above/below |
|
||||
|
||||
| Output | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `visibleRangeChange` | `PretextScrollEvent` | Emits when visible range changes |
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `scrollToIndex(index, behavior?)` | Scroll to a specific row |
|
||||
|
||||
### `PretextRowHeightService`
|
||||
|
||||
Low-level service for direct control:
|
||||
|
||||
```typescript
|
||||
const cache = service.prepareRows(data, columns, font);
|
||||
const heights = service.calculateRowHeights(cache, columns, lineHeight, padding);
|
||||
const positions = service.buildPositionIndex(heights);
|
||||
const range = service.findVisibleRange(positions, scrollTop, viewportHeight);
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Prepare** (once) — `@chenglou/pretext` segments text and measures via canvas
|
||||
2. **Layout** (on resize) — pure arithmetic, ~0.0002ms per cell, no DOM access
|
||||
3. **Scroll** (continuous) — O(log n) binary search in cumulative position arrays
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user