@rivinia/table 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,514 @@
1
+ import { CellSpan, SortDirection, SortState, SpanModel, TableRow, TableRowId, TextOverflow } from "@rivinia/table";
2
+ import * as i0 from "@angular/core";
3
+ import { TemplateRef } from "@angular/core";
4
+ /**
5
+ * The column shape the grid READS — a renderer-facing contract, not a copy of
6
+ * the core type.
7
+ *
8
+ * Why not `TableColumn<any>`: that looks like the obvious "some column" type,
9
+ * but it is not a supertype of a real one. Its accessor is
10
+ * `(keyof any & string) | ((row: any) => V)` = `string | …`, and a concrete
11
+ * `keyof Person & string` is narrower, so `TableColumn<Person>` would NOT be
12
+ * assignable to `TableColumn<any>` — a consumer could not pass their own
13
+ * typed columns at all. The same inversion repeats through `SpanContext`.
14
+ *
15
+ * So the callbacks here take `any` as their PARAMETER type (always assignable
16
+ * in both directions) instead of `any` as the type argument. The result is a
17
+ * genuine supertype: every `TableColumn<T>` is assignable to it.
18
+ *
19
+ * The renderer reads `id`, `header`, `accessor`, `format`, `sortable`,
20
+ * `width`, `flex`, `align`, `hidden`, `textOverflow` and `lines`. The rest is
21
+ * declared so a column literal typed as `TableUiColumn[]` can carry the full
22
+ * core vocabulary without an excess-property error: spans are rendered from
23
+ * `[spans]` (not from the column), `comparator` belongs to the core's sorting,
24
+ * and pinning is not implemented by this entry point.
25
+ */
26
+ interface TableUiColumn {
27
+ readonly id: string;
28
+ readonly header?: string;
29
+ readonly accessor?: string | ((row: any) => unknown);
30
+ readonly sortable?: boolean;
31
+ readonly width?: string;
32
+ /** 0 = fixed; > 0 absorbs free space. */
33
+ readonly flex?: number;
34
+ readonly pinned?: 'start' | 'end';
35
+ readonly align?: 'start' | 'center' | 'end';
36
+ readonly format?: (value: any, row: any, locale: string) => string;
37
+ readonly comparator?: (a: any, b: any) => number;
38
+ readonly hidden?: boolean;
39
+ readonly textOverflow?: TextOverflow;
40
+ readonly lines?: number;
41
+ readonly merge?: 'equal' | ((row: any, anchor: any) => boolean);
42
+ readonly colSpan?: number | ((context: any) => number);
43
+ readonly span?: (context: any) => CellSpan | null | undefined;
44
+ }
45
+ /** A row as the grid reads it. `TableRow<T>` has no variance, so this is safe. */
46
+ type TableUiRow = TableRow<any>;
47
+ /** Row height + padding preset. Token values per preset are in the CSS. */
48
+ type TableUiDensity = 'compact' | 'default' | 'comfortable';
49
+ /**
50
+ * The text a grid shows on its own. Everything here is also a `[labels]`
51
+ * override, so an Arabic page gets Arabic text without a second code path.
52
+ */
53
+ interface TableUiLabels {
54
+ /** The grid's accessible name when `[ariaLabel]` is unset. */
55
+ readonly grid: string;
56
+ /** Announced while `[loading]` is true (the skeletons are decorative). */
57
+ readonly loading: string;
58
+ /** Fallback when `[error]` holds something that is not an `Error`/string. */
59
+ readonly error: string;
60
+ /** Used when `[emptyMessage]` is unset. */
61
+ readonly empty: string;
62
+ /** The grid's `aria-describedby`: what the keyboard does. */
63
+ readonly keyboardHelp: string;
64
+ }
65
+ export declare const TABLE_UI_LABELS_EN: TableUiLabels;
66
+ export declare const TABLE_UI_LABELS_AR: TableUiLabels;
67
+ /**
68
+ * The label set for a locale, defaulting to English.
69
+ *
70
+ * It is a plain function (not a DI token) because it is pure and the UI entry
71
+ * must stay usable without a provider — the same rule the core follows.
72
+ */
73
+ declare function tableUiLabels(locale: string | undefined): TableUiLabels;
74
+ /**
75
+ * What a projected `[rvTableCell]` template receives.
76
+ *
77
+ * `$implicit` is the {@link TableRow} wrapper — the same shape the `rows`
78
+ * input holds — so `let-row` is what the grid itself sees. `data` is the
79
+ * consumer's own object, `value` is the accessor's resolved value BEFORE
80
+ * `format`, and `column` is the column definition. The value is untrusted
81
+ * (`unknown`) because the grid does not know the column's value type.
82
+ *
83
+ * ```html
84
+ * <ng-template rvTableCell="actions" let-row let-data="data">
85
+ * <button (click)="open(row.id)">Open {{ data.number }}</button>
86
+ * </ng-template>
87
+ * ```
88
+ */
89
+ interface TableUiCellContext<T = unknown> {
90
+ readonly $implicit: TableRow<T>;
91
+ /** The same row under a named key, for templates that already destructure. */
92
+ readonly row: TableRow<T>;
93
+ /** The consumer's own object (`row.data`). */
94
+ readonly data: T;
95
+ /** The accessor's value before `column.format`. */
96
+ readonly value: unknown;
97
+ /** The renderer-facing column definition the grid rendered. */
98
+ readonly column: TableUiColumn;
99
+ /** Position inside the rendered page, not the index in the full data set. */
100
+ readonly rowIndex: number;
101
+ }
102
+ /** Payload of `(selectionChange)`: the new set AND which row moved it. */
103
+ interface TableUiSelectionChange<T = unknown> {
104
+ readonly selected: ReadonlySet<TableRowId>;
105
+ /** `null` when no single row caused the change (programmatic or clear-all). */
106
+ readonly row: TableRow<T> | null;
107
+ }
108
+ /** One cell as the template sees it — everything resolved, nothing computed there. */
109
+ interface RenderCell {
110
+ readonly column: TableUiColumn;
111
+ readonly columnIndex: number;
112
+ readonly rowSpan: number;
113
+ readonly colSpan: number;
114
+ readonly spanned: boolean;
115
+ readonly overflow: TextOverflow;
116
+ /** `null` unless the column is a clamp column; drives `--rv-table-clamp-lines`. */
117
+ readonly lines: number | null;
118
+ readonly text: string;
119
+ /** Id of the visually-hidden full-text node, when the cell can be cut off. */
120
+ readonly describedBy: string | null;
121
+ readonly template: TemplateRef<TableUiCellContext> | null;
122
+ readonly context: TableUiCellContext;
123
+ /** Explicit placement, so covered positions leave no auto-flow hole. */
124
+ readonly gridRow: string;
125
+ readonly gridColumn: string;
126
+ }
127
+ interface RenderRow {
128
+ /** The effective row id (`[rowKey]` applied): what selection and tracking use. */
129
+ readonly id: TableRowId;
130
+ readonly row: TableUiRow;
131
+ /** Position inside the rendered page. */
132
+ readonly rowIndex: number;
133
+ /** 1-based position in the FULL data set; the header is row 1. */
134
+ readonly ariaRowIndex: number;
135
+ readonly selected: boolean;
136
+ readonly cells: readonly RenderCell[];
137
+ }
138
+ interface TableUiState {
139
+ readonly kind: 'error' | 'empty';
140
+ readonly message: string;
141
+ }
142
+ /**
143
+ * `<rv-table>` — a `role="grid"` data grid, built from divs on purpose.
144
+ *
145
+ * ## Why not `<table>`
146
+ * An interactive grid is `role="grid"`, not `role="table"`, so the roles have
147
+ * to be written either way. Once they are, a native table adds layout
148
+ * negotiation (`table-layout`), inconsistent sticky headers and no way to span
149
+ * a cell across ROWS without owning the row structure. Divs + CSS grid keep
150
+ * the geometry explicit and the ARIA exact.
151
+ *
152
+ * ## The consumer decides what a cell contains
153
+ * The column list carries geometry and a header; the CELL is either the
154
+ * column's `accessor` (+ optional `format`) or — for an actions column, a
155
+ * badge, an avatar — a projected template keyed by column id:
156
+ *
157
+ * ```html
158
+ * <rv-table [columns]="columns()" [rows]="rows()" [spans]="spans()" selectable>
159
+ * <ng-template rvTableCell="actions" let-row let-data="data">
160
+ * <button type="button" (click)="edit(row.id)">Edit {{ data.number }}</button>
161
+ * </ng-template>
162
+ * </rv-table>
163
+ * ```
164
+ *
165
+ * The table never knows that "actions" means actions: a column with an id and
166
+ * no `accessor` renders only the projected template. A template also WINS over
167
+ * an accessor when both exist — markup is an override, not a second source of
168
+ * truth for the column list (`[columns]` stays the only one).
169
+ *
170
+ * ## Spans
171
+ * `[spans]` is the core's resolved `SpanModel`: only anchors are rendered,
172
+ * covered positions have no element at all (nothing is hidden with a flag), and
173
+ * each anchor is placed on the shared CSS grid with an explicit
174
+ * `grid-row: <start> / span <n>` and `grid-column: <start> / span <n>`. Because
175
+ * the spans are real grid spans, a merged cell survives wrapping rows and
176
+ * needs no height arithmetic. `aria-rowspan` / `aria-colspan` are written only
177
+ * when greater than 1, and every cell carries `aria-colindex` (WAI-ARIA
178
+ * requires it once the grid is not a simple matrix).
179
+ *
180
+ * ## Keyboard
181
+ * One tab stop (roving `tabindex`), moved with the arrows through
182
+ * `spans.move()` — so moving INTO a merged cell lands on its anchor and moving
183
+ * inside one leaves it. Home/End pick the first/last anchor of the row,
184
+ * PageUp/PageDown move a screen, Enter activates the row, Space toggles
185
+ * selection. Horizontal arrows mirror in RTL; vertical ones never do.
186
+ *
187
+ * ## Theming
188
+ * Every colour and shape is read AT THE USE SITE as
189
+ * `var(--rv-table-<part>, var(--rv-<semantic>, <default>))`, so one
190
+ * `:root { --rv-bg: … }` reaches the grid. Nothing is declared on the host, so
191
+ * a token set anywhere on an ancestor wins (the D42/D46 rule).
192
+ * `[density]` only changes the FALLBACK of the size tokens, so an explicit
193
+ * token still wins over the preset.
194
+ *
195
+ * The override surface is documented and stable:
196
+ * classes `.rv-table-scroller`, `.rv-table-grid`, `.rv-table-head`,
197
+ * `.rv-table-head-cell`, `.rv-table-head-button`, `.rv-table-head-label`,
198
+ * `.rv-table-body`, `.rv-table-row`, `.rv-table-cell`, `.rv-table-text`,
199
+ * `.rv-table-sort`, `.rv-table-sort-rank`, `.rv-table-state`,
200
+ * `.rv-table-skeleton`, `.rv-table-sr-only`;
201
+ * hooks `[data-density]`, `[data-loading]`, `[data-sticky]`, `[data-selectable]`
202
+ * on the host, `[data-sortable]`, `[data-sorted]`, `[data-sort-rank]`,
203
+ * `[data-sort-direction]` on a header cell, and `[data-selected]`,
204
+ * `[data-span]`, `[data-align]`, `[data-overflow]`, `[data-row]`, `[data-col]`
205
+ * on a body cell. Component styles are injected at runtime and carry the
206
+ * component's scope attribute, so a plain `.rv-table-cell { … }` in an app
207
+ * stylesheet can lose at equal specificity: scope it as
208
+ * `rv-table .rv-table-cell { … }`, or use the tokens.
209
+ */
210
+ export declare class RiviniaTableComponent {
211
+ private readonly host;
212
+ private readonly scroller;
213
+ private readonly projectedCells;
214
+ /** The columns, in render order. Hidden ones are filtered out, not counted. */
215
+ readonly columns: import("@angular/core").InputSignal<readonly TableUiColumn[]>;
216
+ /** The page's rows (already filtered/sorted/paged by the consumer or core). */
217
+ readonly rows: import("@angular/core").InputSignal<readonly TableUiRow[]>;
218
+ /** The core's resolved span matrix for `rows` + visible columns. */
219
+ readonly spans: import("@angular/core").InputSignal<SpanModel | null>;
220
+ /** While true the grid is `aria-busy`, renders skeletons and no data rows. */
221
+ readonly loading: import("@angular/core").InputSignal<boolean>;
222
+ /**
223
+ * How many skeleton rows to draw. `'auto'` (default) mirrors the rows that
224
+ * are currently rendered, at least one — so the layout does not jump.
225
+ */
226
+ readonly skeletonRows: import("@angular/core").InputSignal<number | "auto">;
227
+ /** A failed load. `null`/`undefined` means "no error". */
228
+ readonly error: import("@angular/core").InputSignal<unknown>;
229
+ /** Text of the empty state. Unset falls back to the locale's label. */
230
+ readonly emptyMessage: import("@angular/core").InputSignal<string | undefined>;
231
+ /**
232
+ * Derives the id used by selection, tracking and `(rowActivate)` from the
233
+ * row's data. Unset uses `TableRow.id`, which is already stable.
234
+ */
235
+ readonly rowKey: import("@angular/core").InputSignal<((row: any) => TableRowId) | undefined>;
236
+ /** Renders row selection: `aria-selected`, Space, and click-to-select. */
237
+ readonly selectable: import("@angular/core").InputSignal<boolean>;
238
+ /**
239
+ * The selected row ids. Two-way: `[(selected)]`. A `Set` (not an array)
240
+ * because every row asks "am I selected?" on every render.
241
+ */
242
+ readonly selected: import("@angular/core").ModelSignal<ReadonlySet<TableRowId>>;
243
+ /**
244
+ * The active sort, highest priority first. Two-way: `[(sort)]`, and the
245
+ * model's own `(sortChange)` fires whenever this component changes it.
246
+ */
247
+ readonly sort: import("@angular/core").ModelSignal<readonly SortState[]>;
248
+ readonly density: import("@angular/core").InputSignal<TableUiDensity>;
249
+ /** Sticks the header to the top of the scroller. */
250
+ readonly stickyHeader: import("@angular/core").InputSignal<boolean>;
251
+ /**
252
+ * The number of rows in the FULL result set, for `aria-rowcount` when the
253
+ * consumer pages on the server. Unset derives it from the rows' `index`,
254
+ * which is exact when the grid renders the whole set.
255
+ */
256
+ readonly totalRows: import("@angular/core").InputSignal<number | undefined>;
257
+ /** Accessible name of the grid (`aria-label`). */
258
+ readonly ariaLabel: import("@angular/core").InputSignal<string | undefined>;
259
+ /** Overrides for the built-in English/Arabic text. */
260
+ readonly labels: import("@angular/core").InputSignal<Partial<TableUiLabels> | undefined>;
261
+ /** Enter on a focused cell, or a double-click on a row. */
262
+ readonly rowActivate: import("@angular/core").OutputEmitterRef<TableUiRow>;
263
+ /**
264
+ * A row was selected/deselected by the user. The model already carries the
265
+ * new set (`selectedChange`); this output also names the row that moved.
266
+ */
267
+ readonly selectionChange: import("@angular/core").OutputEmitterRef<TableUiSelectionChange<unknown>>;
268
+ protected readonly instructionsId: string;
269
+ private readonly uid;
270
+ protected readonly visibleColumns: import("@angular/core").Signal<TableUiColumn[]>;
271
+ protected readonly columnCount: import("@angular/core").Signal<number>;
272
+ /**
273
+ * The ONE column geometry both the header and the body read.
274
+ *
275
+ * A flex column keeps its declared width as the track's FLOOR
276
+ * (`minmax(<width>, Nfr)`, design §5.2): with `minmax(0, Nfr)` a narrow
277
+ * container would collapse the column to zero and its content would vanish
278
+ * instead of scrolling. Fixed columns are their width, untouched.
279
+ */
280
+ protected readonly columnTemplate: import("@angular/core").Signal<string>;
281
+ /**
282
+ * The grid's intrinsic width, so the scroller actually scrolls instead of
283
+ * squeezing every column. It is the sum of the declared widths — which is
284
+ * why a column width should be a length (`px`, `rem`, `ch`), not `max-content`.
285
+ */
286
+ protected readonly minWidth: import("@angular/core").Signal<string>;
287
+ /**
288
+ * `aria-label` written on the HOST — `<rv-table aria-label="Invoices">` — is
289
+ * the attribute a consumer reaches for first, but the `role="grid"` element
290
+ * lives INSIDE the component, so the attribute would otherwise stop at the
291
+ * host and the grid would keep its fallback name ("Data grid"). Read on every
292
+ * change detection: it is a `getAttribute` call, and a dynamic label belongs
293
+ * on the `[ariaLabel]` input, which is reactive.
294
+ */
295
+ protected get hostLabel(): string | undefined;
296
+ protected readonly effectiveLabels: import("@angular/core").Signal<TableUiLabels>;
297
+ protected readonly locale: import("@angular/core").Signal<string>;
298
+ /** Column id → the consumer's template. Rebuilt only when content changes. */
299
+ private readonly cellTemplates;
300
+ /**
301
+ * Sort lookup by column id: direction plus 1-based priority. One map instead
302
+ * of a linear search per rendered header cell.
303
+ */
304
+ private readonly sortIndex;
305
+ /** The fully resolved view model. Nothing in the template computes. */
306
+ protected readonly renderedRows: import("@angular/core").Signal<readonly RenderRow[]>;
307
+ protected readonly skeletonList: import("@angular/core").Signal<unknown[]>;
308
+ protected readonly state: import("@angular/core").Signal<TableUiState | null>;
309
+ /**
310
+ * The rows that actually have DOM cells. While loading the skeletons replace
311
+ * them, and an error/empty state replaces them too, so the keyboard must not
312
+ * "move" into a row that has no element to focus.
313
+ */
314
+ protected readonly bodyRows: import("@angular/core").Signal<readonly RenderRow[]>;
315
+ /**
316
+ * The header row is row 1 (WAI-ARIA counts the header), so the grid's row
317
+ * count is the data count + 1. `-1` is legal ("unknown"), but a wrong count
318
+ * is worse than an honest one, so `[totalRows]` is the precise answer when
319
+ * the consumer pages on the server.
320
+ */
321
+ protected readonly rowCount: import("@angular/core").Signal<number>;
322
+ /** Row index in the rendered page; `-1` is the header row. */
323
+ private readonly active;
324
+ private pendingFocus;
325
+ /**
326
+ * The active cell, clamped to what is actually rendered. A stale row index
327
+ * (the data shrank) would otherwise leave the grid with no tab stop at all.
328
+ * While loading there are no data cells, so the header is the tab stop.
329
+ */
330
+ protected readonly effectiveActive: import("@angular/core").Signal<{
331
+ row: number;
332
+ column: number;
333
+ }>;
334
+ constructor();
335
+ protected isActive(row: number, column: number): boolean;
336
+ protected isSortable(column: TableUiColumn): boolean;
337
+ protected sortRank(column: TableUiColumn): number;
338
+ protected sortDirection(column: TableUiColumn): SortDirection | null;
339
+ /**
340
+ * `aria-sort` lives on exactly ONE header (the highest-priority sort), as
341
+ * WAI-ARIA requires; secondary sorted columns are shown with a rank badge
342
+ * and announce `none`, because the attribute has no "secondary" value.
343
+ */
344
+ protected ariaSort(column: TableUiColumn): 'ascending' | 'descending' | 'none' | null;
345
+ protected onHeaderClick(column: TableUiColumn, columnIndex: number, event: MouseEvent): void;
346
+ protected rowId(row: TableUiRow): TableRowId;
347
+ protected onRowActivate(item: RenderRow): void;
348
+ /**
349
+ * A double-click is a row activation. It is ignored when it lands on an
350
+ * interactive element inside a projected template: the action the user asked
351
+ * for (Edit, Open, a link) must not also fire the row's own activation.
352
+ */
353
+ protected onRowDoubleClick(item: RenderRow, event: MouseEvent): void;
354
+ protected onCellClick(item: RenderRow, cell: RenderCell, event: MouseEvent): void;
355
+ protected onCellFocus(row: number, column: number): void;
356
+ protected onKeydown(event: KeyboardEvent): void;
357
+ private onHeaderKey;
358
+ private cycleSort;
359
+ /**
360
+ * A page step stays inside the BODY. The header is reachable with ArrowUp,
361
+ * but PageUp from the first data row must not surprise the user by landing on
362
+ * the sort controls; page keys are a data-reading affordance.
363
+ */
364
+ private page;
365
+ private moveBy;
366
+ /** Clamp to the page, then snap onto the anchor of whatever cell is there. */
367
+ private moveTo;
368
+ private firstColumn;
369
+ private lastColumn;
370
+ /** One screen minus one row; 10 when there is no layout to measure (SSR, jsdom). */
371
+ private pageRows;
372
+ private focusCell;
373
+ /**
374
+ * Direction is read from the nearest `[dir]` FIRST, then from computed
375
+ * style: jsdom does not inherit computed direction, and `dir="auto"` needs
376
+ * the computed answer anyway.
377
+ */
378
+ private isRtl;
379
+ private buildCells;
380
+ private readValue;
381
+ private toggleRow;
382
+ private errorText;
383
+ static ɵfac: i0.ɵɵFactoryDeclaration<RiviniaTableComponent, never>;
384
+ static ɵcmp: i0.ɵɵComponentDeclaration<RiviniaTableComponent, "rv-table", never, {
385
+ "columns": {
386
+ "alias": "columns";
387
+ "required": true;
388
+ "isSignal": true;
389
+ };
390
+ "rows": {
391
+ "alias": "rows";
392
+ "required": false;
393
+ "isSignal": true;
394
+ };
395
+ "spans": {
396
+ "alias": "spans";
397
+ "required": false;
398
+ "isSignal": true;
399
+ };
400
+ "loading": {
401
+ "alias": "loading";
402
+ "required": false;
403
+ "isSignal": true;
404
+ };
405
+ "skeletonRows": {
406
+ "alias": "skeletonRows";
407
+ "required": false;
408
+ "isSignal": true;
409
+ };
410
+ "error": {
411
+ "alias": "error";
412
+ "required": false;
413
+ "isSignal": true;
414
+ };
415
+ "emptyMessage": {
416
+ "alias": "emptyMessage";
417
+ "required": false;
418
+ "isSignal": true;
419
+ };
420
+ "rowKey": {
421
+ "alias": "rowKey";
422
+ "required": false;
423
+ "isSignal": true;
424
+ };
425
+ "selectable": {
426
+ "alias": "selectable";
427
+ "required": false;
428
+ "isSignal": true;
429
+ };
430
+ "selected": {
431
+ "alias": "selected";
432
+ "required": false;
433
+ "isSignal": true;
434
+ };
435
+ "sort": {
436
+ "alias": "sort";
437
+ "required": false;
438
+ "isSignal": true;
439
+ };
440
+ "density": {
441
+ "alias": "density";
442
+ "required": false;
443
+ "isSignal": true;
444
+ };
445
+ "stickyHeader": {
446
+ "alias": "stickyHeader";
447
+ "required": false;
448
+ "isSignal": true;
449
+ };
450
+ "totalRows": {
451
+ "alias": "totalRows";
452
+ "required": false;
453
+ "isSignal": true;
454
+ };
455
+ "ariaLabel": {
456
+ "alias": "ariaLabel";
457
+ "required": false;
458
+ "isSignal": true;
459
+ };
460
+ "labels": {
461
+ "alias": "labels";
462
+ "required": false;
463
+ "isSignal": true;
464
+ };
465
+ }, {
466
+ "selected": "selectedChange";
467
+ "sort": "sortChange";
468
+ "rowActivate": "rowActivate";
469
+ "selectionChange": "selectionChange";
470
+ }, ["projectedCells"], ["[rvTableCell]"], true, never>;
471
+ }
472
+ /**
473
+ * `[rvTableCell]="columnId"` — the consumer's renderer for one column.
474
+ *
475
+ * Put it on an `<ng-template>`; the grid never renders the template directly,
476
+ * it asks for it BY COLUMN ID and instantiates it once per row. That is what
477
+ * makes an actions column possible without the table knowing anything about
478
+ * actions: the column list only declares geometry and a header, and the
479
+ * markup decides what a cell contains.
480
+ *
481
+ * ```html
482
+ * <rv-table [columns]="columns()" [rows]="rows()">
483
+ * <ng-template rvTableCell="actions" let-row let-data="data">
484
+ * <button type="button" (click)="edit(data)">Edit</button>
485
+ * </ng-template>
486
+ * </rv-table>
487
+ * ```
488
+ *
489
+ * A column whose id has no template and no `accessor` renders an empty cell,
490
+ * so declare the column for its width/header and supply the template here.
491
+ * The template wins over `accessor` when both exist: markup is an override.
492
+ *
493
+ * The context is {@link TableUiCellContext} — `$implicit` (and `row`) is the
494
+ * `TableRow`, `data` is your object, `value` is the accessor's value.
495
+ */
496
+ export declare class RvTableCell {
497
+ /**
498
+ * The id of the column this template renders. It must match a
499
+ * `TableColumn.id`; an id that matches nothing is simply never used (the
500
+ * grid cannot throw at render time for a template it was given).
501
+ */
502
+ readonly columnId: import("@angular/core").InputSignal<string>;
503
+ /** The template to instantiate. Injected from the `<ng-template>` host. */
504
+ readonly template: TemplateRef<TableUiCellContext>;
505
+ static ɵfac: i0.ɵɵFactoryDeclaration<RvTableCell, never>;
506
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RvTableCell, "[rvTableCell]", never, {
507
+ "columnId": {
508
+ "alias": "rvTableCell";
509
+ "required": true;
510
+ "isSignal": true;
511
+ };
512
+ }, {}, never, never, true, never>;
513
+ }
514
+ export type { TableUiCellContext, TableUiColumn, TableUiDensity, TableUiLabels, TableUiRow, TableUiSelectionChange };