@taiga-ui/addon-table 4.52.0-canary.c107f6a → 4.52.0-canary.ca43bcb

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.
Files changed (34) hide show
  1. package/README.md +2 -2
  2. package/components/reorder/reorder.component.d.ts +6 -9
  3. package/components/reorder/reorder.options.d.ts +1 -3
  4. package/components/table/directives/cell.directive.d.ts +2 -2
  5. package/components/table/directives/direction-order.directive.d.ts +5 -3
  6. package/components/table/directives/head.directive.d.ts +2 -2
  7. package/components/table/directives/resized.directive.d.ts +2 -1
  8. package/components/table/directives/sort-by.directive.d.ts +10 -6
  9. package/components/table/directives/sortable.directive.d.ts +5 -7
  10. package/components/table/directives/table.directive.d.ts +14 -10
  11. package/components/table/pipes/table-sort.pipe.d.ts +4 -4
  12. package/components/table/table-expand/table-expand.component.d.ts +4 -6
  13. package/components/table/table.options.d.ts +1 -3
  14. package/components/table/tbody/tbody.component.d.ts +5 -8
  15. package/components/table/td/td.component.d.ts +3 -2
  16. package/components/table/th/th.component.d.ts +7 -7
  17. package/components/table/th-group/th-group.component.d.ts +4 -7
  18. package/components/table/tr/tr.component.d.ts +2 -0
  19. package/components/table-pagination/table-pagination.component.d.ts +10 -11
  20. package/components/table-pagination/table-pagination.options.d.ts +1 -3
  21. package/directives/table-control/checkbox-row.directive.d.ts +2 -2
  22. package/directives/table-filters/generic-filter.directive.d.ts +2 -1
  23. package/directives/table-filters/table-filter.directive.d.ts +3 -3
  24. package/fesm2022/taiga-ui-addon-table-components-reorder.mjs +31 -44
  25. package/fesm2022/taiga-ui-addon-table-components-reorder.mjs.map +1 -1
  26. package/fesm2022/taiga-ui-addon-table-components-table-pagination.mjs +31 -51
  27. package/fesm2022/taiga-ui-addon-table-components-table-pagination.mjs.map +1 -1
  28. package/fesm2022/taiga-ui-addon-table-components-table.mjs +138 -219
  29. package/fesm2022/taiga-ui-addon-table-components-table.mjs.map +1 -1
  30. package/fesm2022/taiga-ui-addon-table-directives-table-control.mjs +9 -10
  31. package/fesm2022/taiga-ui-addon-table-directives-table-control.mjs.map +1 -1
  32. package/fesm2022/taiga-ui-addon-table-directives-table-filters.mjs +12 -17
  33. package/fesm2022/taiga-ui-addon-table-directives-table-filters.mjs.map +1 -1
  34. package/package.json +5 -5
@@ -1,17 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ChangeDetectionStrategy, ViewEncapsulation, Component, inject, TemplateRef, Input, Directive, InjectionToken, ChangeDetectorRef, EventEmitter, signal, Output, forwardRef, ContentChildren, Pipe, SkipSelf, PLATFORM_ID, computed, ViewChild, ContentChild } from '@angular/core';
3
- import { map, distinctUntilChanged, catchError, EMPTY, combineLatest, debounceTime, Subject, switchMap, takeUntil, delay, filter, timer, of, ReplaySubject, startWith } from 'rxjs';
4
- import { tuiProvideOptions, tuiWithStyles, tuiProvide, tuiDefaultSort, tuiPure } from '@taiga-ui/cdk/utils/miscellaneous';
2
+ import { ChangeDetectionStrategy, ViewEncapsulation, Component, input, inject, TemplateRef, Directive, ChangeDetectorRef, output, signal, Input, effect, forwardRef, untracked, computed, contentChildren, Pipe, SkipSelf, viewChild, PLATFORM_ID, model, contentChild } from '@angular/core';
3
+ import { toSignal, outputToObservable, outputFromObservable, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
4
+ import { tuiWithStyles, tuiSetSignal, tuiDefaultSort, tuiPure } from '@taiga-ui/cdk/utils/miscellaneous';
5
+ import { map, distinctUntilChanged, catchError, EMPTY, combineLatest, debounceTime, Subject, switchMap, takeUntil, delay, filter, timer, of, ReplaySubject } from 'rxjs';
6
+ import { tuiCreateOptions, tuiProvide } from '@taiga-ui/cdk/utils/di';
5
7
  import { IntersectionObserverService, WA_INTERSECTION_THRESHOLD, WA_INTERSECTION_ROOT_MARGIN } from '@ng-web-apis/intersection-observer';
6
8
  import { tuiButtonOptionsProvider } from '@taiga-ui/core/components/button';
7
9
  import { TUI_TEXTFIELD_OPTIONS, TuiTextfieldComponent } from '@taiga-ui/core/components/textfield';
8
10
  import { tuiBadgeOptionsProvider } from '@taiga-ui/kit/components/badge';
9
11
  import { tuiChipOptionsProvider } from '@taiga-ui/kit/components/chip';
10
12
  import { tuiProgressOptionsProvider } from '@taiga-ui/kit/components/progress';
11
- import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
12
- import { tuiWatch, tuiTypedFromEvent, tuiPreventDefault, tuiZoneOptimized, tuiQueryListChanges } from '@taiga-ui/cdk/observables';
13
+ import { tuiWatch, tuiTypedFromEvent, tuiPreventDefault, tuiZoneOptimized } from '@taiga-ui/cdk/observables';
13
14
  import { DOCUMENT, AsyncPipe, NgTemplateOutlet, isPlatformServer } from '@angular/common';
14
- import { EMPTY_CLIENT_RECT, EMPTY_QUERY } from '@taiga-ui/cdk/constants';
15
+ import { EMPTY_CLIENT_RECT } from '@taiga-ui/cdk/constants';
15
16
  import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom';
16
17
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
17
18
  import { TuiIcon } from '@taiga-ui/core/components/icon';
@@ -34,20 +35,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
34
35
 
35
36
  class TuiTableCell {
36
37
  constructor() {
37
- this.tuiCell = '';
38
+ this.tuiCell = input('');
38
39
  this.template = inject((TemplateRef));
39
40
  }
40
41
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableCell, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
41
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableCell, isStandalone: true, selector: "ng-template[tuiCell]", inputs: { tuiCell: "tuiCell" }, ngImport: i0 }); }
42
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: TuiTableCell, isStandalone: true, selector: "ng-template[tuiCell]", inputs: { tuiCell: { classPropertyName: "tuiCell", publicName: "tuiCell", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
42
43
  }
43
44
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableCell, decorators: [{
44
45
  type: Directive,
45
46
  args: [{
46
47
  selector: 'ng-template[tuiCell]',
47
48
  }]
48
- }], propDecorators: { tuiCell: [{
49
- type: Input
50
- }] } });
49
+ }] });
51
50
 
52
51
  const TuiSortDirection = {
53
52
  Asc: 1,
@@ -66,12 +65,7 @@ const TUI_TABLE_DEFAULT_OPTIONS = {
66
65
  off: '@tui.chevrons-up-down',
67
66
  },
68
67
  };
69
- const TUI_TABLE_OPTIONS = new InjectionToken(ngDevMode ? 'TUI_TABLE_OPTIONS' : '', {
70
- factory: () => TUI_TABLE_DEFAULT_OPTIONS,
71
- });
72
- function tuiTableOptionsProvider(options) {
73
- return tuiProvideOptions(TUI_TABLE_OPTIONS, options, TUI_TABLE_DEFAULT_OPTIONS);
74
- }
68
+ const [TUI_TABLE_OPTIONS, tuiTableOptionsProvider] = tuiCreateOptions(TUI_TABLE_DEFAULT_OPTIONS);
75
69
 
76
70
  // TODO: Consider making universal and moving to CDK
77
71
  class TuiStuck {
@@ -116,38 +110,41 @@ class TuiTableDirective {
116
110
  this.options = inject(TUI_TABLE_OPTIONS);
117
111
  this.cdr = inject(ChangeDetectorRef);
118
112
  this.nothing = tuiWithStyles(Styles);
119
- this.columns = [];
120
- this.direction = this.options.direction;
113
+ this.columns = input([]);
114
+ this.direction = input(this.options.direction);
121
115
  this.sorter = EMPTY_COMPARATOR;
122
116
  /**
123
117
  * @deprecated: use sortChange
124
118
  */
125
- this.directionChange = new EventEmitter();
119
+ this.directionChange = output();
126
120
  /**
127
121
  * @deprecated: use sortChange
128
122
  */
129
- this.sorterChange = new EventEmitter();
130
- this.sortChange = combineLatest([
131
- this.sorterChange,
132
- this.directionChange,
123
+ this.directionChange$ = outputToObservable(this.directionChange);
124
+ /**
125
+ * @deprecated: use sortChange
126
+ */
127
+ this.sorterChange = output();
128
+ this.sorterChange$ = outputToObservable(this.sorterChange);
129
+ this.sortChange$ = combineLatest([
130
+ this.sorterChange$,
131
+ this.directionChange$,
133
132
  ]).pipe(debounceTime(0), map(([sortComparator, sortDirection]) => ({
134
133
  sortBy: sortComparator,
135
134
  orderBy: sortDirection,
136
135
  sortComparator,
137
136
  sortDirection,
138
137
  })));
138
+ this.sortChange = outputFromObservable(this.sortChange$);
139
139
  this.appearance = signal('table');
140
- this.size = signal(this.options.size);
140
+ this.size = input(this.options.size);
141
141
  this.cleaner = signal(false);
142
142
  // TODO: refactor to signal inputs after Angular update
143
143
  this.change$ = new Subject();
144
144
  }
145
- set sizeSetter(size) {
146
- this.size.set(size);
147
- }
148
145
  updateSorterAndDirection(sorter) {
149
146
  if (this.sorter === sorter) {
150
- this.updateSorter(this.sorter, this.direction === TuiSortDirection.Asc
147
+ this.updateSorter(this.sorter, this.direction() === TuiSortDirection.Asc
151
148
  ? TuiSortDirection.Desc
152
149
  : TuiSortDirection.Asc);
153
150
  }
@@ -163,13 +160,13 @@ class TuiTableDirective {
163
160
  }
164
161
  updateSorter(sorter, direction = TuiSortDirection.Asc) {
165
162
  this.sorter = sorter || EMPTY_COMPARATOR.bind({});
166
- this.direction = direction;
163
+ tuiSetSignal(this.direction, direction);
167
164
  this.sorterChange.emit(sorter);
168
- this.directionChange.emit(this.direction);
165
+ this.directionChange.emit(this.direction());
169
166
  this.change$.next();
170
167
  }
171
168
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
172
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableDirective, isStandalone: true, selector: "table[tuiTable]", inputs: { columns: "columns", direction: "direction", sorter: "sorter", sizeSetter: ["size", "sizeSetter"] }, outputs: { directionChange: "directionChange", sorterChange: "sorterChange", sortChange: "sortChange" }, host: { properties: { "attr.data-size": "size()" } }, providers: [
169
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: TuiTableDirective, isStandalone: true, selector: "table[tuiTable]", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, sorter: { classPropertyName: "sorter", publicName: "sorter", isSignal: false, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { directionChange: "directionChange", sorterChange: "sorterChange", sortChange: "sortChange" }, host: { attributes: { "tuiTable": "" }, properties: { "attr.data-size": "size()" } }, providers: [
173
170
  {
174
171
  provide: WA_INTERSECTION_ROOT_MARGIN,
175
172
  useValue: '10000px 10000px 10000px 0px',
@@ -198,78 +195,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
198
195
  ],
199
196
  hostDirectives: [TuiStuck],
200
197
  host: {
198
+ tuiTable: '',
201
199
  '[attr.data-size]': 'size()',
202
200
  },
203
201
  }]
204
- }], propDecorators: { columns: [{
202
+ }], propDecorators: { sorter: [{
205
203
  type: Input
206
- }], direction: [{
207
- type: Input
208
- }], sorter: [{
209
- type: Input
210
- }], directionChange: [{
211
- type: Output
212
- }], sorterChange: [{
213
- type: Output
214
- }], sortChange: [{
215
- type: Output
216
- }], sizeSetter: [{
217
- type: Input,
218
- args: ['size']
219
204
  }] } });
220
205
 
221
206
  class TuiTableDirectionOrder {
222
207
  constructor() {
223
208
  this.table = inject((TuiTableDirective));
209
+ this.directionOrderChange$ = this.table.directionChange$.pipe(map((dir) => (dir === 1 ? 'asc' : 'desc')));
224
210
  /**
225
211
  * @deprecated: use tuiSortChange
226
212
  */
227
- this.directionOrderChange = this.table.directionChange.pipe(map((dir) => (dir === 1 ? 'asc' : 'desc')));
228
- }
229
- set directionOrder(order) {
230
- this.table.direction =
231
- order === 'asc' ? TuiSortDirection.Asc : TuiSortDirection.Desc;
213
+ this.directionOrderChange = outputFromObservable(this.directionOrderChange$);
214
+ this.directionOrder = input();
215
+ this.setTableDirection = effect((_, order = this.directionOrder()) => {
216
+ tuiSetSignal(this.table.direction, order === 'asc' ? TuiSortDirection.Asc : TuiSortDirection.Desc);
217
+ });
232
218
  }
233
219
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableDirectionOrder, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
234
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableDirectionOrder, isStandalone: true, selector: "table[tuiTable][tuiDirectionOrder]", inputs: { directionOrder: "directionOrder" }, outputs: { directionOrderChange: "directionOrderChange" }, ngImport: i0 }); }
220
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: TuiTableDirectionOrder, isStandalone: true, selector: "table[tuiTable][tuiDirectionOrder]", inputs: { directionOrder: { classPropertyName: "directionOrder", publicName: "directionOrder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { directionOrderChange: "directionOrderChange" }, ngImport: i0 }); }
235
221
  }
236
222
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableDirectionOrder, decorators: [{
237
223
  type: Directive,
238
224
  args: [{
239
225
  selector: 'table[tuiTable][tuiDirectionOrder]',
240
226
  }]
241
- }], propDecorators: { directionOrderChange: [{
242
- type: Output
243
- }], directionOrder: [{
244
- type: Input
245
- }] } });
227
+ }] });
246
228
 
247
229
  class TuiTableHead {
248
230
  constructor() {
249
- this.tuiHead = '';
231
+ this.tuiHead = input.required();
250
232
  this.template = inject((TemplateRef));
251
233
  }
252
234
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableHead, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
253
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableHead, isStandalone: true, selector: "[tuiHead]", inputs: { tuiHead: "tuiHead" }, ngImport: i0 }); }
235
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: TuiTableHead, isStandalone: true, selector: "[tuiHead]", inputs: { tuiHead: { classPropertyName: "tuiHead", publicName: "tuiHead", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
254
236
  }
255
237
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableHead, decorators: [{
256
238
  type: Directive,
257
239
  args: [{
258
240
  selector: '[tuiHead]',
259
241
  }]
260
- }], propDecorators: { tuiHead: [{
261
- type: Input,
262
- args: [{ required: true }]
263
- }] } });
242
+ }] });
264
243
 
265
244
  class TuiTableResized {
266
245
  constructor() {
267
246
  this.doc = inject(DOCUMENT);
268
247
  this.el = tuiInjectElement();
269
- this.tuiResized = tuiTypedFromEvent(this.el, 'mousedown').pipe(tuiPreventDefault(), switchMap(() => {
248
+ this.tuiResized$ = tuiTypedFromEvent(this.el, 'mousedown').pipe(tuiPreventDefault(), switchMap(() => {
270
249
  const { width, right } = this.el.closest('th')?.getBoundingClientRect() || EMPTY_CLIENT_RECT;
271
250
  return tuiTypedFromEvent(this.doc, 'mousemove').pipe(distinctUntilChanged(), map(({ clientX }) => width + clientX - right), takeUntil(tuiTypedFromEvent(this.doc, 'mouseup')));
272
251
  }));
252
+ this.tuiResized = outputFromObservable(this.tuiResized$);
273
253
  }
274
254
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableResized, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
275
255
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableResized, isStandalone: true, selector: "[tuiResized]", outputs: { tuiResized: "tuiResized" }, ngImport: i0 }); }
@@ -279,9 +259,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
279
259
  args: [{
280
260
  selector: '[tuiResized]',
281
261
  }]
282
- }], propDecorators: { tuiResized: [{
283
- type: Output
284
- }] } });
262
+ }] });
285
263
 
286
264
  /// <reference types="@taiga-ui/tsconfig/ng-dev-mode" />
287
265
  class TuiTableTh {
@@ -290,67 +268,57 @@ class TuiTableTh {
290
268
  this.head = inject(TuiTableHead, {
291
269
  optional: true,
292
270
  });
293
- this.width = null;
271
+ this.width = signal(null);
294
272
  this.table = inject(forwardRef(() => TuiTableDirective), { optional: true });
295
- this.minWidth = -Infinity;
296
- this.maxWidth = Infinity;
273
+ this.minWidth = input(-Infinity);
274
+ this.maxWidth = input(Infinity);
297
275
  this.sorter = this.head
298
276
  ? (a, b) => tuiDefaultSort(a[this.key], b[this.key])
299
277
  : null;
300
- this.resizable = this.options.resizable;
301
- this.sticky = this.options.sticky;
302
- this.requiredSort = this.options.requiredSort;
278
+ this.resizable = input(this.options.resizable);
279
+ this.sticky = input(this.options.sticky);
280
+ this.requiredSort = input(this.options.requiredSort);
303
281
  }
304
282
  get key() {
305
283
  if (!this.head) {
306
284
  throw new TuiTableSortKeyException();
307
285
  }
308
- return this.head.tuiHead;
286
+ return this.head.tuiHead();
309
287
  }
310
288
  get isCurrent() {
311
289
  return !!this.sorter && !!this.table && this.sorter === this.table.sorter;
312
290
  }
313
291
  get icon() {
314
292
  if (this.isCurrent) {
315
- return this.table?.direction === TuiSortDirection.Asc
293
+ return this.table?.direction() === TuiSortDirection.Asc
316
294
  ? this.options.sortIcons.asc
317
295
  : this.options.sortIcons.desc;
318
296
  }
319
297
  return this.options.sortIcons.off;
320
298
  }
321
299
  updateSorterAndDirection() {
322
- const sorter = this.requiredSort ? this.sorter : null;
300
+ const sorter = this.requiredSort() ? this.sorter : null;
323
301
  this.table?.updateSorterAndDirection(this.isCurrentAndDescDirection ? sorter : this.sorter);
324
302
  }
325
303
  onResized(width) {
326
- this.width = Math.min(Math.max(width, this.minWidth), this.maxWidth);
304
+ this.width.set(Math.min(Math.max(width, this.minWidth()), this.maxWidth()));
327
305
  }
328
306
  get isCurrentAndDescDirection() {
329
307
  return (this.sorter === this.table?.sorter &&
330
- this.table?.direction === TuiSortDirection.Desc);
308
+ this.table?.direction() === TuiSortDirection.Desc);
331
309
  }
332
310
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTh, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
333
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableTh, isStandalone: true, selector: "th[tuiTh]", inputs: { minWidth: "minWidth", maxWidth: "maxWidth", sorter: "sorter", resizable: "resizable", sticky: "sticky", requiredSort: "requiredSort" }, host: { properties: { "style.min-width.px": "width || minWidth", "style.width.px": "width || minWidth", "style.max-width.px": "width || maxWidth", "class._sticky": "sticky" } }, ngImport: i0, template: "@if (sorter && table) {\n <button\n type=\"button\"\n class=\"t-sort\"\n [class.t-sort_sorted]=\"isCurrent\"\n (click)=\"updateSorterAndDirection()\"\n >\n <ng-container [ngTemplateOutlet]=\"content\" />\n {{ table.change$ | async }}\n <tui-icon\n class=\"t-icon\"\n [icon]=\"icon\"\n />\n </button>\n} @else {\n <ng-container [ngTemplateOutlet]=\"content\" />\n}\n<ng-template #content>\n <ng-content />\n</ng-template>\n@if (resizable) {\n <div\n class=\"t-bar\"\n (tuiResized)=\"onResized($event)\"\n ></div>\n}\n", styles: [":host{transition-property:box-shadow;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:relative;top:0;block-size:var(--tui-height-m);font:var(--tui-font-text-s);text-align:start;font-weight:700;color:var(--tui-text-secondary);background:var(--tui-background-base);cursor:default;padding:0 .75rem;box-sizing:border-box;box-shadow:0 .3125rem #ededed00;border:1px solid var(--tui-border-normal);filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:not(:first-child){border-inline-start:none}:host._sticky,:host-context(._stuck) :host._sticky{position:sticky;z-index:30}:host._sticky:first-child,:host-context(._stuck) :host._sticky:first-child{left:0}:host._sticky:after,:host-context(._stuck) :host._sticky:after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;left:100%;bottom:0;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host-context(._stuck) :host{z-index:20}:host-context(tr:not(:first-child)){border-block-start:none}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);font-weight:700;padding:0 1rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);font-weight:700;padding:0 .5rem}:host-context(thead[tuiThead]){position:sticky}:host-context(table._stuck)._sticky:after{opacity:1}:host-context(thead[tuiThead]._stuck){box-shadow:0 .3125rem #edededb3}:host-context([tuiTheme=\"dark\"])._sticky:after{background:#3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck){box-shadow:0 .3125rem #3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck):first-child{box-shadow:.0625rem .3125rem #3c3c3ce6}:host-context(table[data-size=\"l\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-l)}:host-context(table[data-size=\"m\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-m)}:host-context(table[data-size=\"s\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-s)}.t-sort{transition-property:color;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;line-height:inherit;text-decoration:none;display:inline-flex;vertical-align:top;flex-direction:inherit;align-items:center;outline:none;font:inherit;text-transform:inherit;color:inherit;cursor:pointer}.t-sort_sorted{color:var(--tui-text-primary)}.t-sort:focus-visible{background:var(--tui-service-selection-background)}.t-sort:hover{color:var(--tui-text-primary)}.t-bar{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:0;bottom:0;right:-1px;inline-size:.1875rem;justify-self:flex-end;border-inline-start:2px solid transparent;background:var(--tui-status-warning);background-clip:content-box;cursor:ew-resize;opacity:0}.t-bar:hover,.t-bar:active{opacity:1}.t-icon:before{font-size:1rem}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "directive", type: TuiTableResized, selector: "[tuiResized]", outputs: ["tuiResized"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
311
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableTh, isStandalone: true, selector: "th[tuiTh]", inputs: { minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, sorter: { classPropertyName: "sorter", publicName: "sorter", isSignal: false, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, requiredSort: { classPropertyName: "requiredSort", publicName: "requiredSort", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.min-width.px": "width() || minWidth()", "style.width.px": "width() || minWidth()", "style.max-width.px": "width() || maxWidth()", "class._sticky": "sticky()" } }, ngImport: i0, template: "@if (sorter && table) {\n <button\n type=\"button\"\n class=\"t-sort\"\n [class.t-sort_sorted]=\"isCurrent\"\n (click)=\"updateSorterAndDirection()\"\n >\n <ng-container [ngTemplateOutlet]=\"content\" />\n {{ table.change$ | async }}\n <tui-icon\n class=\"t-icon\"\n [icon]=\"icon\"\n />\n </button>\n} @else {\n <ng-container [ngTemplateOutlet]=\"content\" />\n}\n<ng-template #content>\n <ng-content />\n</ng-template>\n@if (resizable()) {\n <div\n class=\"t-bar\"\n (tuiResized)=\"onResized($event)\"\n ></div>\n}\n", styles: [":host{transition-property:box-shadow;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:relative;top:0;block-size:var(--tui-height-m);font:var(--tui-font-text-s);text-align:start;font-weight:700;color:var(--tui-text-secondary);background:var(--tui-background-base);cursor:default;padding:0 .75rem;box-sizing:border-box;box-shadow:0 .3125rem #ededed00;border:1px solid var(--tui-border-normal);filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:not(:first-child){border-inline-start:none}:host._sticky,:host-context(._stuck) :host._sticky{position:sticky;z-index:30}:host._sticky:first-child,:host-context(._stuck) :host._sticky:first-child{left:0}:host._sticky:after,:host-context(._stuck) :host._sticky:after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;left:100%;bottom:0;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host-context(._stuck) :host{z-index:20}:host-context(tr:not(:first-child)){border-block-start:none}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);font-weight:700;padding:0 1rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);font-weight:700;padding:0 .5rem}:host-context(thead[tuiThead]){position:sticky}:host-context(table._stuck)._sticky:after{opacity:1}:host-context(thead[tuiThead]._stuck){box-shadow:0 .3125rem #edededb3}:host-context([tuiTheme=\"dark\"])._sticky:after{background:#3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck){box-shadow:0 .3125rem #3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck):first-child{box-shadow:.0625rem .3125rem #3c3c3ce6}:host-context(table[data-size=\"l\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-l)}:host-context(table[data-size=\"m\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-m)}:host-context(table[data-size=\"s\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-s)}.t-sort{transition-property:color;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;line-height:inherit;text-decoration:none;display:inline-flex;vertical-align:top;flex-direction:inherit;align-items:center;outline:none;font:inherit;text-transform:inherit;color:inherit;cursor:pointer}.t-sort_sorted{color:var(--tui-text-primary)}.t-sort:focus-visible{background:var(--tui-service-selection-background)}.t-sort:hover{color:var(--tui-text-primary)}.t-bar{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:0;bottom:0;right:-1px;inline-size:.1875rem;justify-self:flex-end;border-inline-start:2px solid transparent;background:var(--tui-status-warning);background-clip:content-box;cursor:ew-resize;opacity:0}.t-bar:hover,.t-bar:active{opacity:1}.t-icon:before{font-size:1rem}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "directive", type: TuiTableResized, selector: "[tuiResized]", outputs: ["tuiResized"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
334
312
  }
335
313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTh, decorators: [{
336
314
  type: Component,
337
315
  args: [{ selector: 'th[tuiTh]', imports: [AsyncPipe, NgTemplateOutlet, TuiIcon, TuiTableResized], changeDetection: ChangeDetectionStrategy.OnPush, host: {
338
- '[style.min-width.px]': 'width || minWidth',
339
- '[style.width.px]': 'width || minWidth',
340
- '[style.max-width.px]': 'width || maxWidth',
341
- '[class._sticky]': 'sticky',
342
- }, template: "@if (sorter && table) {\n <button\n type=\"button\"\n class=\"t-sort\"\n [class.t-sort_sorted]=\"isCurrent\"\n (click)=\"updateSorterAndDirection()\"\n >\n <ng-container [ngTemplateOutlet]=\"content\" />\n {{ table.change$ | async }}\n <tui-icon\n class=\"t-icon\"\n [icon]=\"icon\"\n />\n </button>\n} @else {\n <ng-container [ngTemplateOutlet]=\"content\" />\n}\n<ng-template #content>\n <ng-content />\n</ng-template>\n@if (resizable) {\n <div\n class=\"t-bar\"\n (tuiResized)=\"onResized($event)\"\n ></div>\n}\n", styles: [":host{transition-property:box-shadow;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:relative;top:0;block-size:var(--tui-height-m);font:var(--tui-font-text-s);text-align:start;font-weight:700;color:var(--tui-text-secondary);background:var(--tui-background-base);cursor:default;padding:0 .75rem;box-sizing:border-box;box-shadow:0 .3125rem #ededed00;border:1px solid var(--tui-border-normal);filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:not(:first-child){border-inline-start:none}:host._sticky,:host-context(._stuck) :host._sticky{position:sticky;z-index:30}:host._sticky:first-child,:host-context(._stuck) :host._sticky:first-child{left:0}:host._sticky:after,:host-context(._stuck) :host._sticky:after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;left:100%;bottom:0;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host-context(._stuck) :host{z-index:20}:host-context(tr:not(:first-child)){border-block-start:none}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);font-weight:700;padding:0 1rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);font-weight:700;padding:0 .5rem}:host-context(thead[tuiThead]){position:sticky}:host-context(table._stuck)._sticky:after{opacity:1}:host-context(thead[tuiThead]._stuck){box-shadow:0 .3125rem #edededb3}:host-context([tuiTheme=\"dark\"])._sticky:after{background:#3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck){box-shadow:0 .3125rem #3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck):first-child{box-shadow:.0625rem .3125rem #3c3c3ce6}:host-context(table[data-size=\"l\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-l)}:host-context(table[data-size=\"m\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-m)}:host-context(table[data-size=\"s\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-s)}.t-sort{transition-property:color;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;line-height:inherit;text-decoration:none;display:inline-flex;vertical-align:top;flex-direction:inherit;align-items:center;outline:none;font:inherit;text-transform:inherit;color:inherit;cursor:pointer}.t-sort_sorted{color:var(--tui-text-primary)}.t-sort:focus-visible{background:var(--tui-service-selection-background)}.t-sort:hover{color:var(--tui-text-primary)}.t-bar{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:0;bottom:0;right:-1px;inline-size:.1875rem;justify-self:flex-end;border-inline-start:2px solid transparent;background:var(--tui-status-warning);background-clip:content-box;cursor:ew-resize;opacity:0}.t-bar:hover,.t-bar:active{opacity:1}.t-icon:before{font-size:1rem}\n"] }]
343
- }], propDecorators: { minWidth: [{
344
- type: Input
345
- }], maxWidth: [{
346
- type: Input
347
- }], sorter: [{
348
- type: Input
349
- }], resizable: [{
350
- type: Input
351
- }], sticky: [{
352
- type: Input
353
- }], requiredSort: [{
316
+ '[style.min-width.px]': 'width() || minWidth()',
317
+ '[style.width.px]': 'width() || minWidth()',
318
+ '[style.max-width.px]': 'width() || maxWidth()',
319
+ '[class._sticky]': 'sticky()',
320
+ }, template: "@if (sorter && table) {\n <button\n type=\"button\"\n class=\"t-sort\"\n [class.t-sort_sorted]=\"isCurrent\"\n (click)=\"updateSorterAndDirection()\"\n >\n <ng-container [ngTemplateOutlet]=\"content\" />\n {{ table.change$ | async }}\n <tui-icon\n class=\"t-icon\"\n [icon]=\"icon\"\n />\n </button>\n} @else {\n <ng-container [ngTemplateOutlet]=\"content\" />\n}\n<ng-template #content>\n <ng-content />\n</ng-template>\n@if (resizable()) {\n <div\n class=\"t-bar\"\n (tuiResized)=\"onResized($event)\"\n ></div>\n}\n", styles: [":host{transition-property:box-shadow;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:relative;top:0;block-size:var(--tui-height-m);font:var(--tui-font-text-s);text-align:start;font-weight:700;color:var(--tui-text-secondary);background:var(--tui-background-base);cursor:default;padding:0 .75rem;box-sizing:border-box;box-shadow:0 .3125rem #ededed00;border:1px solid var(--tui-border-normal);filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:not(:first-child){border-inline-start:none}:host._sticky,:host-context(._stuck) :host._sticky{position:sticky;z-index:30}:host._sticky:first-child,:host-context(._stuck) :host._sticky:first-child{left:0}:host._sticky:after,:host-context(._stuck) :host._sticky:after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;left:100%;bottom:0;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host-context(._stuck) :host{z-index:20}:host-context(tr:not(:first-child)){border-block-start:none}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);font-weight:700;padding:0 1rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);font-weight:700;padding:0 .5rem}:host-context(thead[tuiThead]){position:sticky}:host-context(table._stuck)._sticky:after{opacity:1}:host-context(thead[tuiThead]._stuck){box-shadow:0 .3125rem #edededb3}:host-context([tuiTheme=\"dark\"])._sticky:after{background:#3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck){box-shadow:0 .3125rem #3c3c3ce6}:host-context([tuiTheme=\"dark\"] thead[tuiThead]._stuck):first-child{box-shadow:.0625rem .3125rem #3c3c3ce6}:host-context(table[data-size=\"l\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-l)}:host-context(table[data-size=\"m\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-m)}:host-context(table[data-size=\"s\"] thead[tuiThead] tr:nth-child(2)){top:var(--tui-height-s)}.t-sort{transition-property:color;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;line-height:inherit;text-decoration:none;display:inline-flex;vertical-align:top;flex-direction:inherit;align-items:center;outline:none;font:inherit;text-transform:inherit;color:inherit;cursor:pointer}.t-sort_sorted{color:var(--tui-text-primary)}.t-sort:focus-visible{background:var(--tui-service-selection-background)}.t-sort:hover{color:var(--tui-text-primary)}.t-bar{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:0;bottom:0;right:-1px;inline-size:.1875rem;justify-self:flex-end;border-inline-start:2px solid transparent;background:var(--tui-status-warning);background-clip:content-box;cursor:ew-resize;opacity:0}.t-bar:hover,.t-bar:active{opacity:1}.t-icon:before{font-size:1rem}\n"] }]
321
+ }], propDecorators: { sorter: [{
354
322
  type: Input
355
323
  }] } });
356
324
  class TuiTableSortKeyException extends Error {
@@ -364,94 +332,79 @@ class TuiTableSortable {
364
332
  this.table = inject((TuiTableDirective));
365
333
  this.th = inject((TuiTableTh));
366
334
  this.sortBy = inject(forwardRef(() => TuiTableSortBy));
367
- this.sorter = () => 0;
335
+ this.sortable = input(undefined, {
336
+ alias: 'tuiSortable',
337
+ transform: coerceBooleanProperty,
338
+ });
339
+ this.setSorter = effect(() => {
340
+ this.th.sorter = this.sortable() ? untracked(this.sorter) : null;
341
+ });
342
+ this.sorter = computed(() => {
343
+ return this.sortable() && this.match ? this.table.sorter : () => 0;
344
+ });
368
345
  }
369
346
  get key() {
370
347
  return this.th.key;
371
348
  }
372
- ngOnChanges() {
373
- if (this.sortable) {
374
- this.sorter = this.match ? this.table.sorter : this.sorter;
375
- this.th.sorter = this.sorter;
376
- }
377
- else {
378
- this.th.sorter = null;
379
- }
380
- }
381
349
  check() {
382
- if (this.match && this.table.sorter !== this.sorter) {
383
- this.table.updateSorter(this.sorter);
350
+ if (this.match && this.table.sorter !== this.sorter()) {
351
+ this.table.updateSorter(this.sorter());
384
352
  }
385
353
  }
386
354
  get match() {
387
- return this.sortBy.tuiSortBy === this.key;
355
+ return untracked(this.sortBy.tuiSortBy) === this.key;
388
356
  }
389
357
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableSortable, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
390
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.15", type: TuiTableSortable, isStandalone: true, selector: "th[tuiTh][tuiSortable]", inputs: { sortable: ["tuiSortable", "sortable", coerceBooleanProperty] }, usesOnChanges: true, ngImport: i0 }); }
358
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: TuiTableSortable, isStandalone: true, selector: "th[tuiTh][tuiSortable]", inputs: { sortable: { classPropertyName: "sortable", publicName: "tuiSortable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
391
359
  }
392
360
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableSortable, decorators: [{
393
361
  type: Directive,
394
362
  args: [{
395
363
  selector: 'th[tuiTh][tuiSortable]',
396
364
  }]
397
- }], propDecorators: { sortable: [{
398
- type: Input,
399
- args: [{
400
- alias: 'tuiSortable',
401
- transform: coerceBooleanProperty,
402
- }]
403
- }] } });
365
+ }] });
404
366
 
405
367
  class TuiTableSortBy {
406
368
  constructor() {
407
- this.sortables = EMPTY_QUERY;
369
+ this.sortables = contentChildren(TuiTableSortable, {
370
+ descendants: true,
371
+ });
408
372
  this.table = inject((TuiTableDirective));
409
373
  /**
410
- * @deprecated: use tuiSortChange
374
+ * @deprecated
411
375
  */
412
- this.tuiSortByChange = this.table.sorterChange.pipe(
376
+ this.tuiSortByChange$ = this.table.sorterChange$.pipe(
413
377
  // delay is for getting actual ContentChildren (sortables) https://github.com/angular/angular/issues/38976
414
- delay(0), filter(() => !!this.sortables.length), map((sorter) => this.getKey(sorter)));
415
- this.tuiSortChange = combineLatest([
416
- this.tuiSortByChange,
417
- this.table.directionChange,
378
+ delay(0), filter(() => !!this.sortables().length), map((sorter) => this.getKey(sorter)));
379
+ /**
380
+ * @deprecated: use tuiSortChange
381
+ */
382
+ this.tuiSortByChange = outputFromObservable(this.tuiSortByChange$);
383
+ this.tuiSortChange$ = combineLatest([
384
+ this.tuiSortByChange$,
385
+ this.table.directionChange$,
418
386
  ]).pipe(debounceTime(0), map(([sortKey, sortDirection]) => ({
419
387
  sortBy: sortKey,
420
388
  orderBy: sortDirection,
421
389
  sortKey,
422
390
  sortDirection,
423
391
  })));
424
- this.tuiSortBy = null;
425
- }
426
- set sortBy(sortBy) {
427
- this.tuiSortBy = sortBy;
428
- this.checkSortables();
429
- }
430
- checkSortables() {
431
- this.sortables.forEach((s) => s.check());
392
+ this.tuiSortChange = outputFromObservable(this.tuiSortChange$);
393
+ this.tuiSortBy = input(null);
394
+ this.checkSortables = effect((_, __ = this.tuiSortBy()) => untracked(this.sortables).forEach((s) => s.check()));
432
395
  }
433
396
  getKey(sorter) {
434
- return this.sortables.find((s) => s.sorter === sorter)?.key || null;
397
+ return this.sortables().find((s) => s.sorter() === sorter)?.key || null;
435
398
  }
436
399
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableSortBy, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
437
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableSortBy, isStandalone: true, selector: "table[tuiTable][tuiSortBy]", inputs: { sortBy: ["tuiSortBy", "sortBy"] }, outputs: { tuiSortByChange: "tuiSortByChange", tuiSortChange: "tuiSortChange" }, queries: [{ propertyName: "sortables", predicate: TuiTableSortable, descendants: true }], ngImport: i0 }); }
400
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "19.2.15", type: TuiTableSortBy, isStandalone: true, selector: "table[tuiTable][tuiSortBy]", inputs: { tuiSortBy: { classPropertyName: "tuiSortBy", publicName: "tuiSortBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tuiSortByChange: "tuiSortByChange", tuiSortChange: "tuiSortChange" }, queries: [{ propertyName: "sortables", predicate: TuiTableSortable, descendants: true, isSignal: true }], ngImport: i0 }); }
438
401
  }
439
402
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableSortBy, decorators: [{
440
403
  type: Directive,
441
404
  args: [{
442
405
  selector: 'table[tuiTable][tuiSortBy]',
443
406
  }]
444
- }], propDecorators: { sortables: [{
445
- type: ContentChildren,
446
- args: [TuiTableSortable, { descendants: true }]
447
- }], tuiSortByChange: [{
448
- type: Output
449
- }], tuiSortChange: [{
450
- type: Output
451
- }], sortBy: [{
452
- type: Input,
453
- args: ['tuiSortBy']
454
- }] } });
407
+ }] });
455
408
 
456
409
  class TuiTableThead {
457
410
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableThead, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -481,7 +434,7 @@ class TuiTableSortPipe {
481
434
  this.table = inject((TuiTableDirective));
482
435
  }
483
436
  transform(data) {
484
- return this.sort(data ?? [], this.table.sorter, this.table.direction);
437
+ return this.sort(data ?? [], this.table.sorter, this.table.direction());
485
438
  }
486
439
  sort(data, sorter, direction) {
487
440
  return [...data].sort((a, b) => direction * sorter(a, b));
@@ -516,38 +469,33 @@ const TUI_TABLE_PROVIDER = [
516
469
 
517
470
  class TuiTableExpand {
518
471
  constructor() {
472
+ this.content = viewChild('content');
519
473
  this.el = tuiInjectElement();
520
474
  this.server = isPlatformServer(inject(PLATFORM_ID));
521
475
  this.transitioning = signal(false);
522
- this.contentHeight = computed((_ = this.expanded()) => this.update());
476
+ this.contentHeight = computed((_ = this.expanded()) => this.update(this.content()));
523
477
  this.visible$ = new Subject();
524
478
  this.sub = this.visible$
525
479
  .pipe(switchMap((v) => (v ? timer(500).pipe(map(() => v)) : of(v))), takeUntilDestroyed())
526
480
  .subscribe((visible) => this.el.classList.toggle('_visible', visible));
527
- this.expandedChange = new EventEmitter();
528
- this.expanded = signal(inject(TUI_TABLE_OPTIONS).open);
529
- }
530
- set expandedSetter(open) {
531
- this.expanded.set(open);
532
- this.transitioning.set(true);
481
+ this.expanded = model(inject(TUI_TABLE_OPTIONS).open);
482
+ this.transitioningEffect = effect((_, __ = this.expanded()) => this.transitioning.set(true));
533
483
  }
534
484
  toggle() {
535
485
  this.expanded.set(!this.expanded());
536
- this.transitioning.set(true);
537
- this.expandedChange.emit(this.expanded());
538
486
  }
539
- update() {
540
- if (!this.content || this.server) {
487
+ update(content) {
488
+ if (!content || this.server) {
541
489
  return 0;
542
490
  }
543
- const el = this.content.nativeElement;
491
+ const el = content.nativeElement;
544
492
  el.style.setProperty('display', 'block');
545
493
  const height = el.getBoundingClientRect().height;
546
494
  el.style.removeProperty('display');
547
495
  return height;
548
496
  }
549
497
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableExpand, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
550
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableExpand, isStandalone: true, selector: "tui-table-expand", inputs: { expandedSetter: ["expanded", "expandedSetter"] }, outputs: { expandedChange: "expandedChange" }, host: { attributes: { "ngSkipHydration": "true" }, listeners: { "tuiPresentChange": "visible$.next($event)" } }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], hostDirectives: [{ directive: i1.TuiPresent, outputs: ["tuiPresentChange", "tuiPresentChange"] }], ngImport: i0, template: "<div\n #content\n class=\"t-content\"\n [class.t-content_open]=\"expanded() && !transitioning()\"\n>\n <ng-content />\n</div>\n\n<div\n class=\"t-filler\"\n [class.t-filler_open]=\"expanded()\"\n [style.--t-height.px]=\"contentHeight()\"\n (animationcancel)=\"transitioning.set(false)\"\n (animationend)=\"transitioning.set(false)\"\n (animationstart)=\"transitioning.set(true)\"\n></div>\n", styles: ["@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes open{0%{block-size:0}to{block-size:var(--t-height)}}@keyframes close{0%{block-size:var(--t-height)}to{block-size:0}}:host{display:contents}:host:not(._visible){--tui-duration: 0ms}.t-content{display:none}.t-content_open{display:contents}.t-content_open ::ng-deep tr{animation:fade-in var(--tui-duration)}.t-filler{animation:close calc(var(--tui-duration) + 1ms)}.t-filler_open{animation:open calc(var(--tui-duration) + 1ms)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
498
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.15", type: TuiTableExpand, isStandalone: true, selector: "tui-table-expand", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { attributes: { "ngSkipHydration": "true" }, listeners: { "tuiPresentChange": "visible$.next($event)" } }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.TuiPresent, outputs: ["tuiPresentChange", "tuiPresentChange"] }], ngImport: i0, template: "<div\n #content\n class=\"t-content\"\n [class.t-content_open]=\"expanded() && !transitioning()\"\n>\n <ng-content />\n</div>\n\n<div\n class=\"t-filler\"\n [class.t-filler_open]=\"expanded()\"\n [style.--t-height.px]=\"contentHeight()\"\n (animationcancel)=\"transitioning.set(false)\"\n (animationend)=\"transitioning.set(false)\"\n (animationstart)=\"transitioning.set(true)\"\n></div>\n", styles: ["@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes open{0%{block-size:0}to{block-size:var(--t-height)}}@keyframes close{0%{block-size:var(--t-height)}to{block-size:0}}:host{display:contents}:host:not(._visible){--tui-duration: 0ms}.t-content{display:none}.t-content_open{display:contents}.t-content_open ::ng-deep tr{animation:fade-in var(--tui-duration)}.t-filler{animation:close calc(var(--tui-duration) + 1ms)}.t-filler_open{animation:open calc(var(--tui-duration) + 1ms)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
551
499
  }
552
500
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableExpand, decorators: [{
553
501
  type: Component,
@@ -560,116 +508,87 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
560
508
  ngSkipHydration: 'true',
561
509
  '(tuiPresentChange)': 'visible$.next($event)',
562
510
  }, template: "<div\n #content\n class=\"t-content\"\n [class.t-content_open]=\"expanded() && !transitioning()\"\n>\n <ng-content />\n</div>\n\n<div\n class=\"t-filler\"\n [class.t-filler_open]=\"expanded()\"\n [style.--t-height.px]=\"contentHeight()\"\n (animationcancel)=\"transitioning.set(false)\"\n (animationend)=\"transitioning.set(false)\"\n (animationstart)=\"transitioning.set(true)\"\n></div>\n", styles: ["@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes open{0%{block-size:0}to{block-size:var(--t-height)}}@keyframes close{0%{block-size:var(--t-height)}to{block-size:0}}:host{display:contents}:host:not(._visible){--tui-duration: 0ms}.t-content{display:none}.t-content_open{display:contents}.t-content_open ::ng-deep tr{animation:fade-in var(--tui-duration)}.t-filler{animation:close calc(var(--tui-duration) + 1ms)}.t-filler_open{animation:open calc(var(--tui-duration) + 1ms)}\n"] }]
563
- }], propDecorators: { content: [{
564
- type: ViewChild,
565
- args: ['content', { static: true }]
566
- }], expandedChange: [{
567
- type: Output
568
- }], expandedSetter: [{
569
- type: Input,
570
- args: ['expanded']
571
- }] } });
511
+ }] });
572
512
 
573
513
  class TuiTableTd {
514
+ constructor() {
515
+ this.control = contentChild((TuiControl));
516
+ this.textfield = contentChild((TuiTextfieldComponent));
517
+ }
574
518
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTd, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
575
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: TuiTableTd, isStandalone: true, selector: "th[tuiTd], td[tuiTd]", host: { properties: { "class._editable": "control || textfield" } }, queries: [{ propertyName: "control", first: true, predicate: TuiControl, descendants: true }, { propertyName: "textfield", first: true, predicate: TuiTextfieldComponent, descendants: true }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [":host{position:relative;text-align:start;background:var(--tui-background-base);border:1px solid var(--tui-border-normal);border-block-start:none;box-sizing:border-box;filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:first-child{left:0}:host:not(:first-child){border-inline-start:none}:host._editable:focus-within{z-index:1}:host._editable{padding:0!important;vertical-align:top}:host(th){position:sticky;z-index:1}:host(th):after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;bottom:0;left:100%;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host(th):focus-within:not(:disabled){z-index:11}:host-context([tuiTheme=\"dark\"]):after{background:#3c3c3ce6}:host-context(table._stuck){z-index:10}:host-context(table._stuck):last-of-type:after{opacity:1}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);padding:1rem}:host-context(table[data-size=\"m\"]){block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:.75rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);padding:.25rem .5rem}:host(td):focus-within{z-index:1}:host(td):not(:focus-within){z-index:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
519
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.15", type: TuiTableTd, isStandalone: true, selector: "th[tuiTd], td[tuiTd]", host: { properties: { "class._editable": "control() || textfield()" } }, queries: [{ propertyName: "control", first: true, predicate: (TuiControl), descendants: true, isSignal: true }, { propertyName: "textfield", first: true, predicate: (TuiTextfieldComponent), descendants: true, isSignal: true }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [":host{position:relative;text-align:start;background:var(--tui-background-base);border:1px solid var(--tui-border-normal);border-block-start:none;box-sizing:border-box;filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:first-child{left:0}:host:not(:first-child){border-inline-start:none}:host._editable:focus-within{z-index:1}:host._editable{padding:0!important;vertical-align:top}:host(th){position:sticky;z-index:1}:host(th):after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;bottom:0;left:100%;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host(th):focus-within:not(:disabled){z-index:11}:host-context([tuiTheme=\"dark\"]):after{background:#3c3c3ce6}:host-context(table._stuck){z-index:10}:host-context(table._stuck):last-of-type:after{opacity:1}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);padding:1rem}:host-context(table[data-size=\"m\"]){block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:.75rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);padding:.25rem .5rem}:host(td):focus-within{z-index:1}:host(td):not(:focus-within){z-index:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
576
520
  }
577
521
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTd, decorators: [{
578
522
  type: Component,
579
523
  args: [{ selector: 'th[tuiTd], td[tuiTd]', template: '<ng-content />', changeDetection: ChangeDetectionStrategy.OnPush, host: {
580
- '[class._editable]': 'control || textfield',
524
+ '[class._editable]': 'control() || textfield()',
581
525
  }, styles: [":host{position:relative;text-align:start;background:var(--tui-background-base);border:1px solid var(--tui-border-normal);border-block-start:none;box-sizing:border-box;filter:opacity(1)}@supports (-webkit-hyphens: none){:host{transform:translateZ(0)}}:host:first-child{left:0}:host:not(:first-child){border-inline-start:none}:host._editable:focus-within{z-index:1}:host._editable{padding:0!important;vertical-align:top}:host(th){position:sticky;z-index:1}:host(th):after{transition-property:opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;content:\"\";position:absolute;top:0;bottom:0;left:100%;inline-size:.3125rem;pointer-events:none;background:#edededb3;opacity:0}:host(th):focus-within:not(:disabled){z-index:11}:host-context([tuiTheme=\"dark\"]):after{background:#3c3c3ce6}:host-context(table._stuck){z-index:10}:host-context(table._stuck):last-of-type:after{opacity:1}:host-context(table[data-size=\"l\"]){block-size:var(--tui-height-l);font:var(--tui-font-text-m);padding:1rem}:host-context(table[data-size=\"m\"]){block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:.75rem}:host-context(table[data-size=\"s\"]){block-size:var(--tui-height-s);font:var(--tui-font-text-s);padding:.25rem .5rem}:host(td):focus-within{z-index:1}:host(td):not(:focus-within){z-index:0}\n"] }]
582
- }], propDecorators: { control: [{
583
- type: ContentChild,
584
- args: [TuiControl]
585
- }], textfield: [{
586
- type: ContentChild,
587
- args: [TuiTextfieldComponent]
588
- }] } });
526
+ }] });
589
527
 
590
528
  class TuiTableTr {
591
529
  constructor() {
592
- this.cells = EMPTY_QUERY;
530
+ this.cells = contentChildren(forwardRef(() => TuiTableCell));
593
531
  this.body = inject(forwardRef(() => TuiTableTbody));
594
532
  this.contentReady$ = new ReplaySubject(1);
533
+ this.rows$ = toObservable(this.body.rows);
534
+ this.contentCells$ = toObservable(this.cells);
595
535
  this.table = inject(forwardRef(() => TuiTableDirective));
596
536
  this.height = toSignal(inject(ResizeObserverService, { self: true }).pipe(map(([entry]) => entry?.contentRect.height ?? 0), distinctUntilChanged(), tuiZoneOptimized()), { initialValue: 0 });
597
- this.cells$ = this.contentReady$.pipe(switchMap(() => tuiQueryListChanges(this.cells)), map((cells) => cells.reduce((record, item) => ({ ...record, [item.tuiCell]: item }), {})));
598
- this.item$ = this.contentReady$.pipe(switchMap(() => tuiQueryListChanges(this.body.rows)), map((rows) => this.body.data[rows.findIndex((row) => row === this)]));
537
+ this.cells$ = this.contentReady$.pipe(switchMap(() => this.contentCells$), map((cells) => cells.reduce((record, item) => ({ ...record, [item.tuiCell()]: item }), {})));
538
+ this.item$ = this.contentReady$.pipe(switchMap(() => this.rows$), map((rows) => this.body.data()[rows.findIndex((row) => row === this)]));
599
539
  }
600
540
  ngAfterContentInit() {
601
541
  Promise.resolve().then(() => this.contentReady$.next(true));
602
542
  }
603
543
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTr, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
604
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableTr, isStandalone: true, selector: "tr[tuiTr]", host: { properties: { "style.--t-row-height.px": "height()" } }, providers: [TUI_TABLE_PROVIDER, ResizeObserverService], queries: [{ propertyName: "cells", predicate: i0.forwardRef(() => TuiTableCell) }], ngImport: i0, template: "@if (cells$ | async; as items) {\n @for (key of table.columns; track key) {\n <ng-container [ngTemplateOutlet]=\"(items[key] && items[key].template) || plain\">\n <ng-template #plain>\n @if (item$ | async; as item) {\n <td tuiTd>\n {{ item[key] }}\n </td>\n }\n </ng-template>\n </ng-container>\n }\n} @else {\n <td></td>\n}\n<ng-content />\n", dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TuiTableTd, selector: "th[tuiTd], td[tuiTd]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
544
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableTr, isStandalone: true, selector: "tr[tuiTr]", host: { properties: { "style.--t-row-height.px": "height()" } }, providers: [TUI_TABLE_PROVIDER, ResizeObserverService], queries: [{ propertyName: "cells", predicate: i0.forwardRef(() => TuiTableCell), isSignal: true }], ngImport: i0, template: "@if (cells$ | async; as items) {\n @for (key of table.columns(); track key) {\n <ng-container [ngTemplateOutlet]=\"(items[key] && items[key].template) || plain\">\n <ng-template #plain>\n @if (item$ | async; as item) {\n <td tuiTd>\n {{ item[key] }}\n </td>\n }\n </ng-template>\n </ng-container>\n }\n} @else {\n <td></td>\n}\n<ng-content />\n", dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TuiTableTd, selector: "th[tuiTd], td[tuiTd]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
605
545
  }
606
546
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTr, decorators: [{
607
547
  type: Component,
608
548
  args: [{ selector: 'tr[tuiTr]', imports: [AsyncPipe, NgTemplateOutlet, TuiTableTd], changeDetection: ChangeDetectionStrategy.OnPush, providers: [TUI_TABLE_PROVIDER, ResizeObserverService], host: {
609
549
  '[style.--t-row-height.px]': 'height()',
610
- }, template: "@if (cells$ | async; as items) {\n @for (key of table.columns; track key) {\n <ng-container [ngTemplateOutlet]=\"(items[key] && items[key].template) || plain\">\n <ng-template #plain>\n @if (item$ | async; as item) {\n <td tuiTd>\n {{ item[key] }}\n </td>\n }\n </ng-template>\n </ng-container>\n }\n} @else {\n <td></td>\n}\n<ng-content />\n" }]
611
- }], propDecorators: { cells: [{
612
- type: ContentChildren,
613
- args: [forwardRef(() => TuiTableCell)]
614
- }] } });
550
+ }, template: "@if (cells$ | async; as items) {\n @for (key of table.columns(); track key) {\n <ng-container [ngTemplateOutlet]=\"(items[key] && items[key].template) || plain\">\n <ng-template #plain>\n @if (item$ | async; as item) {\n <td tuiTd>\n {{ item[key] }}\n </td>\n }\n </ng-template>\n </ng-container>\n }\n} @else {\n <td></td>\n}\n<ng-content />\n" }]
551
+ }] });
615
552
 
616
553
  class TuiTableTbody {
617
554
  constructor() {
618
555
  this.options = inject(TUI_TABLE_OPTIONS);
619
556
  this.table = inject(forwardRef(() => TuiTableDirective));
620
- this.rows = EMPTY_QUERY;
621
- this.data = [];
557
+ this.rows = contentChildren(forwardRef(() => TuiTableTr));
558
+ this.data = input([]);
622
559
  /** @deprecated: drop in v5.0, use TuiTableExpand */
623
- this.open = this.options.open;
560
+ this.heading = input();
624
561
  /** @deprecated: drop in v5.0, use TuiTableExpand */
625
- this.openChange = new EventEmitter();
562
+ this.open = model(this.options.open);
626
563
  /** @deprecated: drop in v5.0, use TuiTableExpand */
627
564
  this.onClick = () => {
628
- this.open = !this.open;
629
- this.openChange.emit(this.open);
565
+ this.open.set(!this.open());
630
566
  };
631
567
  }
632
568
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTbody, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
633
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableTbody, isStandalone: true, selector: "tbody[tuiTbody]", inputs: { data: "data", heading: "heading", open: "open" }, outputs: { openChange: "openChange" }, providers: TUI_TABLE_PROVIDER, queries: [{ propertyName: "rows", predicate: i0.forwardRef(() => TuiTableTr) }], ngImport: i0, template: "@if (heading) {\n <tr>\n <th\n class=\"t-heading\"\n [colSpan]=\"table.columns.length\"\n >\n <button\n type=\"button\"\n class=\"t-expand\"\n (click)=\"onClick()\"\n >\n <span class=\"t-name\">\n <ng-container *polymorpheusOutlet=\"heading as text\">\n {{ text }}\n </ng-container>\n </span>\n <tui-icon\n class=\"t-chevron\"\n [tuiChevron]=\"open\"\n />\n </button>\n </th>\n </tr>\n}\n@if (open) {\n <ng-content />\n}\n", styles: [":host{border-color:var(--tui-border-normal)}:host tr{border-color:inherit}.t-expand{-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;font:inherit;line-height:inherit;text-decoration:none;display:flex;inline-size:100%;block-size:100%;align-items:center;box-sizing:border-box;outline:none;font-weight:700;cursor:pointer;border-color:inherit}.t-expand:focus-visible .t-name{background:var(--tui-service-selection-background)}.t-expand:before,.t-expand:after{content:\"\";position:sticky;block-size:100%;border-inline-start:1px solid;border-color:inherit}.t-expand:before{left:0}.t-expand:after{right:0}.t-heading{transition-property:background;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:0;background:var(--tui-background-neutral-1);border-block-end:1px solid var(--tui-border-normal);border-color:inherit}.t-heading:hover{background:var(--tui-background-neutral-1-hover)}:host-context(table[data-size=\"l\"]) .t-heading{font:var(--tui-font-text-m);block-size:var(--tui-height-l)}.t-name{position:sticky;left:.75rem;display:inline-block}:host-context(table[data-size=\"l\"]) .t-name{left:1rem}.t-chevron{position:sticky;right:.75rem;margin:0 .6875rem 0 auto}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
569
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableTbody, isStandalone: true, selector: "tbody[tuiTbody]", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, providers: TUI_TABLE_PROVIDER, queries: [{ propertyName: "rows", predicate: i0.forwardRef(() => TuiTableTr), isSignal: true }], ngImport: i0, template: "@if (heading()) {\n <tr>\n <th\n class=\"t-heading\"\n [colSpan]=\"table.columns().length\"\n >\n <button\n type=\"button\"\n class=\"t-expand\"\n (click)=\"onClick()\"\n >\n <span class=\"t-name\">\n <ng-container *polymorpheusOutlet=\"heading() as text\">\n {{ text }}\n </ng-container>\n </span>\n <tui-icon\n class=\"t-chevron\"\n [tuiChevron]=\"open()\"\n />\n </button>\n </th>\n </tr>\n}\n@if (open()) {\n <ng-content />\n}\n", styles: [":host{border-color:var(--tui-border-normal)}:host tr{border-color:inherit}.t-expand{-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;font:inherit;line-height:inherit;text-decoration:none;display:flex;inline-size:100%;block-size:100%;align-items:center;box-sizing:border-box;outline:none;font-weight:700;cursor:pointer;border-color:inherit}.t-expand:focus-visible .t-name{background:var(--tui-service-selection-background)}.t-expand:before,.t-expand:after{content:\"\";position:sticky;block-size:100%;border-inline-start:1px solid;border-color:inherit}.t-expand:before{left:0}.t-expand:after{right:0}.t-heading{transition-property:background;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:0;background:var(--tui-background-neutral-1);border-block-end:1px solid var(--tui-border-normal);border-color:inherit}.t-heading:hover{background:var(--tui-background-neutral-1-hover)}:host-context(table[data-size=\"l\"]) .t-heading{font:var(--tui-font-text-m);block-size:var(--tui-height-l)}.t-name{position:sticky;left:.75rem;display:inline-block}:host-context(table[data-size=\"l\"]) .t-name{left:1rem}.t-chevron{position:sticky;right:.75rem;margin:0 .6875rem 0 auto}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
634
570
  }
635
571
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableTbody, decorators: [{
636
572
  type: Component,
637
- args: [{ selector: 'tbody[tuiTbody]', imports: [PolymorpheusOutlet, TuiChevron, TuiIcon], changeDetection: ChangeDetectionStrategy.OnPush, providers: TUI_TABLE_PROVIDER, template: "@if (heading) {\n <tr>\n <th\n class=\"t-heading\"\n [colSpan]=\"table.columns.length\"\n >\n <button\n type=\"button\"\n class=\"t-expand\"\n (click)=\"onClick()\"\n >\n <span class=\"t-name\">\n <ng-container *polymorpheusOutlet=\"heading as text\">\n {{ text }}\n </ng-container>\n </span>\n <tui-icon\n class=\"t-chevron\"\n [tuiChevron]=\"open\"\n />\n </button>\n </th>\n </tr>\n}\n@if (open) {\n <ng-content />\n}\n", styles: [":host{border-color:var(--tui-border-normal)}:host tr{border-color:inherit}.t-expand{-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;font:inherit;line-height:inherit;text-decoration:none;display:flex;inline-size:100%;block-size:100%;align-items:center;box-sizing:border-box;outline:none;font-weight:700;cursor:pointer;border-color:inherit}.t-expand:focus-visible .t-name{background:var(--tui-service-selection-background)}.t-expand:before,.t-expand:after{content:\"\";position:sticky;block-size:100%;border-inline-start:1px solid;border-color:inherit}.t-expand:before{left:0}.t-expand:after{right:0}.t-heading{transition-property:background;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:0;background:var(--tui-background-neutral-1);border-block-end:1px solid var(--tui-border-normal);border-color:inherit}.t-heading:hover{background:var(--tui-background-neutral-1-hover)}:host-context(table[data-size=\"l\"]) .t-heading{font:var(--tui-font-text-m);block-size:var(--tui-height-l)}.t-name{position:sticky;left:.75rem;display:inline-block}:host-context(table[data-size=\"l\"]) .t-name{left:1rem}.t-chevron{position:sticky;right:.75rem;margin:0 .6875rem 0 auto}\n"] }]
638
- }], propDecorators: { rows: [{
639
- type: ContentChildren,
640
- args: [forwardRef(() => TuiTableTr)]
641
- }], data: [{
642
- type: Input
643
- }], heading: [{
644
- type: Input
645
- }], open: [{
646
- type: Input
647
- }], openChange: [{
648
- type: Output
649
- }] } });
573
+ args: [{ selector: 'tbody[tuiTbody]', imports: [PolymorpheusOutlet, TuiChevron, TuiIcon], changeDetection: ChangeDetectionStrategy.OnPush, providers: TUI_TABLE_PROVIDER, template: "@if (heading()) {\n <tr>\n <th\n class=\"t-heading\"\n [colSpan]=\"table.columns().length\"\n >\n <button\n type=\"button\"\n class=\"t-expand\"\n (click)=\"onClick()\"\n >\n <span class=\"t-name\">\n <ng-container *polymorpheusOutlet=\"heading() as text\">\n {{ text }}\n </ng-container>\n </span>\n <tui-icon\n class=\"t-chevron\"\n [tuiChevron]=\"open()\"\n />\n </button>\n </th>\n </tr>\n}\n@if (open()) {\n <ng-content />\n}\n", styles: [":host{border-color:var(--tui-border-normal)}:host tr{border-color:inherit}.t-expand{-webkit-appearance:none;appearance:none;padding:0;border:0;background:none;font:inherit;line-height:inherit;text-decoration:none;display:flex;inline-size:100%;block-size:100%;align-items:center;box-sizing:border-box;outline:none;font-weight:700;cursor:pointer;border-color:inherit}.t-expand:focus-visible .t-name{background:var(--tui-service-selection-background)}.t-expand:before,.t-expand:after{content:\"\";position:sticky;block-size:100%;border-inline-start:1px solid;border-color:inherit}.t-expand:before{left:0}.t-expand:after{right:0}.t-heading{transition-property:background;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;block-size:var(--tui-height-m);font:var(--tui-font-text-s);padding:0;background:var(--tui-background-neutral-1);border-block-end:1px solid var(--tui-border-normal);border-color:inherit}.t-heading:hover{background:var(--tui-background-neutral-1-hover)}:host-context(table[data-size=\"l\"]) .t-heading{font:var(--tui-font-text-m);block-size:var(--tui-height-l)}.t-name{position:sticky;left:.75rem;display:inline-block}:host-context(table[data-size=\"l\"]) .t-name{left:1rem}.t-chevron{position:sticky;right:.75rem;margin:0 .6875rem 0 auto}\n"] }]
574
+ }] });
650
575
 
651
576
  class TuiTableThGroup {
652
577
  constructor() {
653
- this.heads = EMPTY_QUERY;
654
- this.heads$ = null;
578
+ this.th = contentChild(forwardRef(() => TuiTableTh));
579
+ this.heads = contentChildren(forwardRef(() => TuiTableHead));
580
+ this.computedHeads = computed(() => {
581
+ return this.heads().reduce((record, item) => ({ ...record, [item.tuiHead()]: item }), {});
582
+ });
655
583
  this.table = inject(forwardRef(() => TuiTableDirective));
656
584
  }
657
- ngAfterContentInit() {
658
- this.heads$ = this.heads.changes.pipe(startWith(null), map(() => this.heads.reduce((record, item) => ({ ...record, [item.tuiHead]: item }), {})));
659
- }
660
585
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableThGroup, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
661
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableThGroup, isStandalone: true, selector: "tr[tuiThGroup]", providers: [TUI_TABLE_PROVIDER], queries: [{ propertyName: "th", first: true, predicate: i0.forwardRef(() => TuiTableTh), descendants: true }, { propertyName: "heads", predicate: i0.forwardRef(() => TuiTableHead) }], ngImport: i0, template: "<ng-content />\n@if (heads$ | async; as headings) {\n @for (key of table.columns; track key) {\n <ng-container\n [ngTemplateOutlet]=\"headings?.[key]?.template || plain\"\n [ngTemplateOutletContext]=\"{$implicit: key}\"\n />\n }\n <ng-template\n #plain\n let-key\n >\n @if (!th && !heads.length) {\n <th tuiTh>\n {{ key.toString() }}\n </th>\n }\n </ng-template>\n}\n", dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TuiTableTh, selector: "th[tuiTh]", inputs: ["minWidth", "maxWidth", "sorter", "resizable", "sticky", "requiredSort"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
586
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TuiTableThGroup, isStandalone: true, selector: "tr[tuiThGroup]", providers: [TUI_TABLE_PROVIDER], queries: [{ propertyName: "th", first: true, predicate: i0.forwardRef(() => TuiTableTh), descendants: true, isSignal: true }, { propertyName: "heads", predicate: i0.forwardRef(() => TuiTableHead), isSignal: true }], ngImport: i0, template: "<ng-content />\n@if (computedHeads(); as headings) {\n @for (key of table.columns(); track key) {\n <ng-container\n [ngTemplateOutlet]=\"headings?.[key]?.template || plain\"\n [ngTemplateOutletContext]=\"{$implicit: key}\"\n />\n }\n <ng-template\n #plain\n let-key\n >\n @if (!th() && !heads().length) {\n <th tuiTh>\n {{ key.toString() }}\n </th>\n }\n </ng-template>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TuiTableTh, selector: "th[tuiTh]", inputs: ["minWidth", "maxWidth", "sorter", "resizable", "sticky", "requiredSort"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
662
587
  }
663
588
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TuiTableThGroup, decorators: [{
664
589
  type: Component,
665
- args: [{ selector: 'tr[tuiThGroup]', imports: [AsyncPipe, NgTemplateOutlet, TuiTableTh], changeDetection: ChangeDetectionStrategy.OnPush, providers: [TUI_TABLE_PROVIDER], template: "<ng-content />\n@if (heads$ | async; as headings) {\n @for (key of table.columns; track key) {\n <ng-container\n [ngTemplateOutlet]=\"headings?.[key]?.template || plain\"\n [ngTemplateOutletContext]=\"{$implicit: key}\"\n />\n }\n <ng-template\n #plain\n let-key\n >\n @if (!th && !heads.length) {\n <th tuiTh>\n {{ key.toString() }}\n </th>\n }\n </ng-template>\n}\n" }]
666
- }], propDecorators: { th: [{
667
- type: ContentChild,
668
- args: [forwardRef(() => TuiTableTh)]
669
- }], heads: [{
670
- type: ContentChildren,
671
- args: [forwardRef(() => TuiTableHead)]
672
- }] } });
590
+ args: [{ selector: 'tr[tuiThGroup]', imports: [NgTemplateOutlet, TuiTableTh], changeDetection: ChangeDetectionStrategy.OnPush, providers: [TUI_TABLE_PROVIDER], template: "<ng-content />\n@if (computedHeads(); as headings) {\n @for (key of table.columns(); track key) {\n <ng-container\n [ngTemplateOutlet]=\"headings?.[key]?.template || plain\"\n [ngTemplateOutletContext]=\"{$implicit: key}\"\n />\n }\n <ng-template\n #plain\n let-key\n >\n @if (!th() && !heads().length) {\n <th tuiTh>\n {{ key.toString() }}\n </th>\n }\n </ng-template>\n}\n" }]
591
+ }] });
673
592
 
674
593
  const TuiTable = [
675
594
  TuiTableDirective,