@shival99/z-ui 1.0.1 → 1.0.3
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.
- package/README.md +50 -77
- package/assets/css/animations.css +207 -0
- package/assets/css/base.css +76 -0
- package/assets/css/tailwind.css +53 -0
- package/assets/css/themes/gray.css +73 -0
- package/assets/css/themes/green.css +75 -0
- package/assets/css/themes/hospital.css +79 -0
- package/assets/css/themes/neutral.css +73 -0
- package/assets/css/themes/orange.css +73 -0
- package/assets/css/themes/slate.css +73 -0
- package/assets/css/themes/stone.css +73 -0
- package/assets/css/themes/violet.css +73 -0
- package/assets/css/themes/zinc.css +73 -0
- package/assets/images/avatar.svg +6 -0
- package/assets/images/logo.svg +6 -0
- package/fesm2022/shival99-z-ui-components-z-accordion.mjs +148 -0
- package/fesm2022/shival99-z-ui-components-z-accordion.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs +74 -0
- package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-button.mjs +155 -0
- package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs +2335 -0
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +240 -0
- package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-code.mjs +139 -0
- package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs +664 -0
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +55 -0
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-editor.mjs +411 -0
- package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-filter.mjs +794 -0
- package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-icon.mjs +451 -0
- package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-input.mjs +804 -0
- package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-loading.mjs +105 -0
- package/fesm2022/shival99-z-ui-components-z-loading.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-menu.mjs +351 -0
- package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-modal.mjs +722 -0
- package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs +131 -0
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-popover.mjs +917 -0
- package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-radio.mjs +154 -0
- package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-select.mjs +998 -0
- package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +139 -0
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-switch.mjs +127 -0
- package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs +2628 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs +259 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs +335 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-toast.mjs +93 -0
- package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +660 -0
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-upload.mjs +504 -0
- package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-i18n.mjs +258 -0
- package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-pipes.mjs +116 -0
- package/fesm2022/shival99-z-ui-pipes.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-providers.mjs +203 -0
- package/fesm2022/shival99-z-ui-providers.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-services.mjs +919 -0
- package/fesm2022/shival99-z-ui-services.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-utils.mjs +591 -0
- package/fesm2022/shival99-z-ui-utils.mjs.map +1 -0
- package/fesm2022/z-ui.mjs +3 -19924
- package/fesm2022/z-ui.mjs.map +1 -1
- package/package.json +132 -4
- package/types/shival99-z-ui-components-z-accordion.d.ts +55 -0
- package/types/shival99-z-ui-components-z-breadcrumb.d.ts +36 -0
- package/types/shival99-z-ui-components-z-button.d.ts +41 -0
- package/types/shival99-z-ui-components-z-calendar.d.ts +300 -0
- package/types/shival99-z-ui-components-z-checkbox.d.ts +84 -0
- package/types/shival99-z-ui-components-z-code.d.ts +35 -0
- package/types/shival99-z-ui-components-z-drawer.d.ts +232 -0
- package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +50 -0
- package/types/shival99-z-ui-components-z-editor.d.ts +115 -0
- package/types/shival99-z-ui-components-z-filter.d.ts +268 -0
- package/types/shival99-z-ui-components-z-icon.d.ts +291 -0
- package/types/shival99-z-ui-components-z-input.d.ts +188 -0
- package/types/shival99-z-ui-components-z-loading.d.ts +46 -0
- package/types/shival99-z-ui-components-z-menu.d.ts +116 -0
- package/types/shival99-z-ui-components-z-modal.d.ts +270 -0
- package/types/shival99-z-ui-components-z-pagination.d.ts +52 -0
- package/types/shival99-z-ui-components-z-popover.d.ts +134 -0
- package/types/shival99-z-ui-components-z-radio.d.ts +63 -0
- package/types/shival99-z-ui-components-z-select.d.ts +268 -0
- package/types/shival99-z-ui-components-z-skeleton.d.ts +55 -0
- package/types/shival99-z-ui-components-z-switch.d.ts +48 -0
- package/types/shival99-z-ui-components-z-table.d.ts +482 -0
- package/types/shival99-z-ui-components-z-tabs.d.ts +75 -0
- package/types/shival99-z-ui-components-z-timeline.d.ts +98 -0
- package/types/shival99-z-ui-components-z-toast.d.ts +61 -0
- package/types/shival99-z-ui-components-z-tooltip.d.ts +85 -0
- package/types/shival99-z-ui-components-z-upload.d.ts +136 -0
- package/types/shival99-z-ui-i18n.d.ts +50 -0
- package/types/shival99-z-ui-pipes.d.ts +36 -0
- package/types/shival99-z-ui-providers.d.ts +132 -0
- package/types/shival99-z-ui-services.d.ts +364 -0
- package/types/shival99-z-ui-utils.d.ts +145 -0
- package/types/z-ui.d.ts +3 -4977
|
@@ -0,0 +1,2628 @@
|
|
|
1
|
+
import { moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
|
|
2
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
3
|
+
import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
|
|
4
|
+
import * as i0 from '@angular/core';
|
|
5
|
+
import { input, inject, ElementRef, Renderer2, Directive, Pipe, TemplateRef, computed, ChangeDetectionStrategy, Component, output, DestroyRef, NgZone, signal, viewChild, untracked, effect, afterNextRender } from '@angular/core';
|
|
6
|
+
import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
|
|
7
|
+
import { ZCheckboxComponent } from '@shival99/z-ui/components/z-checkbox';
|
|
8
|
+
import { ZDrawerComponent } from '@shival99/z-ui/components/z-drawer';
|
|
9
|
+
import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
|
|
10
|
+
import { ZInputComponent } from '@shival99/z-ui/components/z-input';
|
|
11
|
+
import { ZLoadingComponent } from '@shival99/z-ui/components/z-loading';
|
|
12
|
+
import { ZPaginationComponent } from '@shival99/z-ui/components/z-pagination';
|
|
13
|
+
import { ZPopoverDirective } from '@shival99/z-ui/components/z-popover';
|
|
14
|
+
import { ZTooltipDirective } from '@shival99/z-ui/components/z-tooltip';
|
|
15
|
+
import { ZSafeHtmlPipe } from '@shival99/z-ui/pipes';
|
|
16
|
+
import { ZCacheService } from '@shival99/z-ui/services';
|
|
17
|
+
import { createAngularTable, getFacetedMinMaxValues, getFacetedUniqueValues, getFacetedRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel, getExpandedRowModel, getCoreRowModel, FlexRenderDirective } from '@tanstack/angular-table';
|
|
18
|
+
import { injectVirtualizer } from '@tanstack/angular-virtual';
|
|
19
|
+
import { NgScrollbar } from 'ngx-scrollbar';
|
|
20
|
+
import { explicitEffect } from 'ngxtension/explicit-effect';
|
|
21
|
+
import * as i1 from '@angular/forms';
|
|
22
|
+
import { FormsModule } from '@angular/forms';
|
|
23
|
+
import { ZSelectComponent } from '@shival99/z-ui/components/z-select';
|
|
24
|
+
|
|
25
|
+
class ZTableRowHoverDirective {
|
|
26
|
+
zTableRowHover = input(null, ...(ngDevMode ? [{ debugName: "zTableRowHover" }] : []));
|
|
27
|
+
_elementRef = inject((ElementRef));
|
|
28
|
+
_renderer = inject(Renderer2);
|
|
29
|
+
onMouseEnter() {
|
|
30
|
+
this._handleHover(true);
|
|
31
|
+
}
|
|
32
|
+
onMouseLeave() {
|
|
33
|
+
this._handleHover(false);
|
|
34
|
+
}
|
|
35
|
+
_handleHover(isHover) {
|
|
36
|
+
const row = this._elementRef.nativeElement;
|
|
37
|
+
const table = this.zTableRowHover() || this._findParentTable(row);
|
|
38
|
+
if (!table) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const cellsInCurrentRow = Array.from(row.children);
|
|
42
|
+
cellsInCurrentRow.forEach(cell => {
|
|
43
|
+
this._toggleCellHover(cell, isHover);
|
|
44
|
+
});
|
|
45
|
+
const tbody = table.querySelector('tbody');
|
|
46
|
+
if (!tbody) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const allRows = Array.from(tbody.querySelectorAll('tr'));
|
|
50
|
+
const currentRowIndex = allRows.indexOf(row);
|
|
51
|
+
if (currentRowIndex === -1) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const grid = [];
|
|
55
|
+
for (let rowIdx = 0; rowIdx < allRows.length; rowIdx++) {
|
|
56
|
+
const r = allRows[rowIdx];
|
|
57
|
+
const cellsInRow = Array.from(r.children);
|
|
58
|
+
cellsInRow.forEach(cell => {
|
|
59
|
+
const rowSpan = parseInt(cell.getAttribute('rowspan') || '1', 10);
|
|
60
|
+
const rowEnd = rowIdx + rowSpan - 1;
|
|
61
|
+
grid.push({
|
|
62
|
+
cell,
|
|
63
|
+
rowStart: rowIdx,
|
|
64
|
+
rowEnd: rowEnd,
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
grid.forEach(item => {
|
|
69
|
+
const coverCurrentRow = item.rowStart < currentRowIndex && item.rowEnd >= currentRowIndex;
|
|
70
|
+
if (!coverCurrentRow) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this._toggleCellHover(item.cell, isHover);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
_toggleCellHover(cell, isHover) {
|
|
77
|
+
if (isHover) {
|
|
78
|
+
this._renderer.addClass(cell, 'z-row-hover');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this._renderer.removeClass(cell, 'z-row-hover');
|
|
82
|
+
}
|
|
83
|
+
_findParentTable(element) {
|
|
84
|
+
let current = element.parentElement;
|
|
85
|
+
while (current) {
|
|
86
|
+
if (current.tagName === 'TABLE') {
|
|
87
|
+
return current;
|
|
88
|
+
}
|
|
89
|
+
current = current.parentElement;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableRowHoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
94
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: ZTableRowHoverDirective, isStandalone: true, selector: "[z-table-row-hover], [zTableRowHover]", inputs: { zTableRowHover: { classPropertyName: "zTableRowHover", publicName: "zTableRowHover", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 });
|
|
95
|
+
}
|
|
96
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableRowHoverDirective, decorators: [{
|
|
97
|
+
type: Directive,
|
|
98
|
+
args: [{
|
|
99
|
+
selector: '[z-table-row-hover], [zTableRowHover]',
|
|
100
|
+
standalone: true,
|
|
101
|
+
host: {
|
|
102
|
+
'(mouseenter)': 'onMouseEnter()',
|
|
103
|
+
'(mouseleave)': 'onMouseLeave()',
|
|
104
|
+
},
|
|
105
|
+
}]
|
|
106
|
+
}], propDecorators: { zTableRowHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTableRowHover", required: false }] }] } });
|
|
107
|
+
|
|
108
|
+
const Z_DEFAULT_ROW_HEIGHT = 40;
|
|
109
|
+
const Z_DEFAULT_VIRTUAL_OVERSCAN = 5;
|
|
110
|
+
const Z_DEFAULT_GROUP_SIZE = 1;
|
|
111
|
+
const Z_DEFAULT_COLUMN_MIN_SIZE = 80;
|
|
112
|
+
const Z_DEFAULT_DEBOUNCE_TIME = 150;
|
|
113
|
+
|
|
114
|
+
const isHeaderConfig = (config) => {
|
|
115
|
+
if (!config || typeof config !== 'object') {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return config.constructor === Object;
|
|
119
|
+
};
|
|
120
|
+
const isBodyConfig = (config) => {
|
|
121
|
+
if (!config || typeof config !== 'object') {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return config.constructor === Object;
|
|
125
|
+
};
|
|
126
|
+
const isFooterConfig = (config) => {
|
|
127
|
+
if (!config || typeof config !== 'object') {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return config.constructor === Object;
|
|
131
|
+
};
|
|
132
|
+
const getHeaderConfig = (col) => {
|
|
133
|
+
const empty = {
|
|
134
|
+
content: undefined,
|
|
135
|
+
class: undefined,
|
|
136
|
+
style: undefined,
|
|
137
|
+
align: undefined,
|
|
138
|
+
tooltip: undefined,
|
|
139
|
+
rowSpan: undefined,
|
|
140
|
+
colSpan: undefined,
|
|
141
|
+
};
|
|
142
|
+
if (!col) {
|
|
143
|
+
return empty;
|
|
144
|
+
}
|
|
145
|
+
if (!isHeaderConfig(col.header)) {
|
|
146
|
+
return { ...empty, content: col.header };
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
content: col.header.content,
|
|
150
|
+
class: col.header.class,
|
|
151
|
+
style: col.header.style,
|
|
152
|
+
align: col.header.align,
|
|
153
|
+
tooltip: col.header.tooltip,
|
|
154
|
+
rowSpan: col.header.rowSpan,
|
|
155
|
+
colSpan: col.header.colSpan,
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
const getBodyConfig = (col, ctx) => {
|
|
159
|
+
const empty = {
|
|
160
|
+
content: undefined,
|
|
161
|
+
class: undefined,
|
|
162
|
+
style: undefined,
|
|
163
|
+
align: undefined,
|
|
164
|
+
rowSpan: undefined,
|
|
165
|
+
colSpan: undefined,
|
|
166
|
+
contentClass: undefined,
|
|
167
|
+
contentStyle: undefined,
|
|
168
|
+
tooltip: undefined,
|
|
169
|
+
};
|
|
170
|
+
if (!col) {
|
|
171
|
+
return empty;
|
|
172
|
+
}
|
|
173
|
+
if (!isBodyConfig(col.body)) {
|
|
174
|
+
return { ...empty, content: col.body };
|
|
175
|
+
}
|
|
176
|
+
const { body } = col;
|
|
177
|
+
const rowSpan = typeof body.rowSpan === 'function' && ctx ? body.rowSpan(ctx) : body.rowSpan;
|
|
178
|
+
const colSpan = typeof body.colSpan === 'function' && ctx ? body.colSpan(ctx) : body.colSpan;
|
|
179
|
+
const classValue = typeof body.class === 'function' && ctx ? body.class(ctx) : body.class;
|
|
180
|
+
const styleValue = typeof body.style === 'function' && ctx ? body.style(ctx) : body.style;
|
|
181
|
+
const contentClass = typeof body.contentClass === 'function' && ctx ? body.contentClass(ctx) : body.contentClass;
|
|
182
|
+
const contentStyle = typeof body.contentStyle === 'function' && ctx ? body.contentStyle(ctx) : body.contentStyle;
|
|
183
|
+
const tooltip = typeof body.tooltip === 'function' && ctx ? body.tooltip(ctx) : body.tooltip;
|
|
184
|
+
return {
|
|
185
|
+
content: body.content,
|
|
186
|
+
class: classValue,
|
|
187
|
+
style: styleValue,
|
|
188
|
+
align: body.align,
|
|
189
|
+
rowSpan: typeof rowSpan === 'number' ? rowSpan : undefined,
|
|
190
|
+
colSpan: typeof colSpan === 'number' ? colSpan : undefined,
|
|
191
|
+
contentClass,
|
|
192
|
+
contentStyle: contentStyle,
|
|
193
|
+
tooltip,
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
const getFooterConfig = (col) => {
|
|
197
|
+
const empty = {
|
|
198
|
+
content: undefined,
|
|
199
|
+
class: undefined,
|
|
200
|
+
style: undefined,
|
|
201
|
+
align: undefined,
|
|
202
|
+
tooltip: undefined,
|
|
203
|
+
rowSpan: undefined,
|
|
204
|
+
colSpan: undefined,
|
|
205
|
+
};
|
|
206
|
+
if (!col) {
|
|
207
|
+
return empty;
|
|
208
|
+
}
|
|
209
|
+
if (!isFooterConfig(col.footer)) {
|
|
210
|
+
return { ...empty, content: col.footer };
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
content: col.footer.content,
|
|
214
|
+
class: col.footer.class,
|
|
215
|
+
style: col.footer.style,
|
|
216
|
+
align: col.footer.align,
|
|
217
|
+
tooltip: col.footer.tooltip,
|
|
218
|
+
rowSpan: col.footer.rowSpan,
|
|
219
|
+
colSpan: col.footer.colSpan,
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
const getHeaderContent = (col) => getHeaderConfig(col).content;
|
|
223
|
+
const getBodyContent = (col) => {
|
|
224
|
+
if (!col?.body) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
return isBodyConfig(col.body) ? col.body.content : col.body;
|
|
228
|
+
};
|
|
229
|
+
const getFooterContent = (col) => getFooterConfig(col).content;
|
|
230
|
+
const getBodyRowSpan = (col, ctx) => getBodyConfig(col, ctx).rowSpan;
|
|
231
|
+
const getBodyColSpan = (col, ctx) => getBodyConfig(col, ctx).colSpan;
|
|
232
|
+
const getHeaderRowSpan = (col) => getHeaderConfig(col).rowSpan;
|
|
233
|
+
const getHeaderColSpan = (col) => getHeaderConfig(col).colSpan;
|
|
234
|
+
const getFooterRowSpan = (col) => getFooterConfig(col).rowSpan;
|
|
235
|
+
const getFooterColSpan = (col) => getFooterConfig(col).colSpan;
|
|
236
|
+
function parseIconString(content) {
|
|
237
|
+
if (!content || typeof content !== 'string') {
|
|
238
|
+
return [{ type: 'text', value: content || '' }];
|
|
239
|
+
}
|
|
240
|
+
const parts = [];
|
|
241
|
+
const iconRegex = /\[icon:([^\]]+)\]/g;
|
|
242
|
+
let lastIndex = 0;
|
|
243
|
+
let match;
|
|
244
|
+
while ((match = iconRegex.exec(content)) !== null) {
|
|
245
|
+
if (match.index > lastIndex) {
|
|
246
|
+
const textPart = content.slice(lastIndex, match.index);
|
|
247
|
+
if (textPart) {
|
|
248
|
+
parts.push({ type: 'text', value: textPart });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const iconContent = match[1];
|
|
252
|
+
const attrs = iconContent.split('|');
|
|
253
|
+
const iconName = attrs[0];
|
|
254
|
+
const iconPart = { type: 'icon', value: iconName };
|
|
255
|
+
for (let i = 1; i < attrs.length; i++) {
|
|
256
|
+
const [key, val] = attrs[i].split(':');
|
|
257
|
+
if (key === 'size') {
|
|
258
|
+
iconPart.size = parseInt(val, 10);
|
|
259
|
+
}
|
|
260
|
+
if (key === 'class') {
|
|
261
|
+
iconPart.class = val;
|
|
262
|
+
}
|
|
263
|
+
if (key === 'strokeWidth') {
|
|
264
|
+
iconPart.strokeWidth = parseFloat(val);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
parts.push(iconPart);
|
|
268
|
+
lastIndex = match.index + match[0].length;
|
|
269
|
+
}
|
|
270
|
+
if (lastIndex < content.length) {
|
|
271
|
+
parts.push({ type: 'text', value: content.slice(lastIndex) });
|
|
272
|
+
}
|
|
273
|
+
return parts.length > 0 ? parts : [{ type: 'text', value: content }];
|
|
274
|
+
}
|
|
275
|
+
function stripIconSyntax(content) {
|
|
276
|
+
if (!content || typeof content !== 'string') {
|
|
277
|
+
return content || '';
|
|
278
|
+
}
|
|
279
|
+
return content.replace(/\[icon:[^\]]+\]/g, '').trim();
|
|
280
|
+
}
|
|
281
|
+
function hasIconSyntax(content) {
|
|
282
|
+
if (!content || typeof content !== 'string') {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
return /\[icon:[^\]]+\]/.test(content);
|
|
286
|
+
}
|
|
287
|
+
const findColumnConfig = (columnId, columns) => {
|
|
288
|
+
for (const col of columns) {
|
|
289
|
+
if (col.id === columnId) {
|
|
290
|
+
return col;
|
|
291
|
+
}
|
|
292
|
+
if (col.columns) {
|
|
293
|
+
const found = findColumnConfig(columnId, col.columns);
|
|
294
|
+
if (found) {
|
|
295
|
+
return found;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return undefined;
|
|
300
|
+
};
|
|
301
|
+
const deepestHeader = (header) => {
|
|
302
|
+
let last = header;
|
|
303
|
+
while (true) {
|
|
304
|
+
const next = last.isPlaceholder && last.colSpan === 1 && last.subHeaders.length === 1 ? last.subHeaders[0] : null;
|
|
305
|
+
if (!next) {
|
|
306
|
+
return last === header ? null : last;
|
|
307
|
+
}
|
|
308
|
+
last = next;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
const tableHeaderRowSpan = (header) => {
|
|
312
|
+
const deepest = deepestHeader(header);
|
|
313
|
+
const rowSpan = (deepest ? deepest.depth - header.depth : 0) + 1;
|
|
314
|
+
const above = header.depth - header.column.depth;
|
|
315
|
+
return above > 1 ? null : rowSpan;
|
|
316
|
+
};
|
|
317
|
+
const calculateCellRowSpan = (cell, columnConfig, allRows) => {
|
|
318
|
+
if (!columnConfig?.body || !isBodyConfig(columnConfig.body)) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
const rowSpanValue = columnConfig.body.rowSpan;
|
|
322
|
+
if (!rowSpanValue) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
if (typeof rowSpanValue === 'function') {
|
|
326
|
+
const rowSpan = rowSpanValue(cell.getContext());
|
|
327
|
+
return rowSpan > 1 ? rowSpan : null;
|
|
328
|
+
}
|
|
329
|
+
if (rowSpanValue > 1) {
|
|
330
|
+
const currentRowId = cell.row.id;
|
|
331
|
+
const filteredIndex = allRows.findIndex(r => r.id === currentRowId);
|
|
332
|
+
if (filteredIndex === -1) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (filteredIndex % rowSpanValue !== 0) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
const remainingRows = allRows.length - filteredIndex;
|
|
339
|
+
const actualRowSpan = Math.min(rowSpanValue, remainingRows);
|
|
340
|
+
return actualRowSpan > 1 ? actualRowSpan : null;
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
};
|
|
344
|
+
const calculateCellColSpan = (cell, columnConfig) => {
|
|
345
|
+
if (!columnConfig?.body || !isBodyConfig(columnConfig.body)) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
const colSpanValue = columnConfig.body.colSpan;
|
|
349
|
+
if (!colSpanValue) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
const colSpan = typeof colSpanValue === 'function' ? colSpanValue(cell.getContext()) : colSpanValue;
|
|
353
|
+
return colSpan > 1 ? colSpan : null;
|
|
354
|
+
};
|
|
355
|
+
const calculateHeaderRowSpan = (header, columnConfig, columns) => {
|
|
356
|
+
const configRowSpan = getHeaderRowSpan(columnConfig);
|
|
357
|
+
if (configRowSpan !== undefined && configRowSpan !== null) {
|
|
358
|
+
return configRowSpan;
|
|
359
|
+
}
|
|
360
|
+
if (columns && header.column.parent) {
|
|
361
|
+
const parentConfig = findColumnConfig(header.column.parent.id, columns);
|
|
362
|
+
const parentRowSpan = getHeaderRowSpan(parentConfig);
|
|
363
|
+
if (parentRowSpan && parentRowSpan >= 2) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const deepest = deepestHeader(header);
|
|
368
|
+
const rowSpan = (deepest ? deepest.depth - header.depth : 0) + 1;
|
|
369
|
+
const above = header.depth - header.column.depth;
|
|
370
|
+
return above > 1 ? null : rowSpan;
|
|
371
|
+
};
|
|
372
|
+
const calculateHeaderColSpan = (header, columnConfig) => {
|
|
373
|
+
const configColSpan = getHeaderColSpan(columnConfig);
|
|
374
|
+
if (configColSpan !== undefined && configColSpan !== null) {
|
|
375
|
+
return configColSpan;
|
|
376
|
+
}
|
|
377
|
+
return header.colSpan > 1 ? header.colSpan : null;
|
|
378
|
+
};
|
|
379
|
+
const calculateFooterRowSpan = (header, columnConfig) => {
|
|
380
|
+
const configRowSpan = getFooterRowSpan(columnConfig);
|
|
381
|
+
if (configRowSpan !== undefined && configRowSpan !== null) {
|
|
382
|
+
return configRowSpan;
|
|
383
|
+
}
|
|
384
|
+
const footerContent = getFooterContent(columnConfig);
|
|
385
|
+
if (footerContent !== undefined) {
|
|
386
|
+
return 1;
|
|
387
|
+
}
|
|
388
|
+
if (header.colSpan > 1) {
|
|
389
|
+
return 1;
|
|
390
|
+
}
|
|
391
|
+
return 1;
|
|
392
|
+
};
|
|
393
|
+
const calculateFooterColSpan = (header, columnConfig) => {
|
|
394
|
+
const configColSpan = getFooterColSpan(columnConfig);
|
|
395
|
+
if (configColSpan !== undefined && configColSpan !== null) {
|
|
396
|
+
return configColSpan;
|
|
397
|
+
}
|
|
398
|
+
return header.colSpan > 1 ? header.colSpan : null;
|
|
399
|
+
};
|
|
400
|
+
const shouldCellRenderUtil = (cell, columnConfig, allRows) => {
|
|
401
|
+
if (!columnConfig?.body || !isBodyConfig(columnConfig.body)) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
const rowSpanValue = columnConfig.body.rowSpan;
|
|
405
|
+
if (!rowSpanValue) {
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
if (typeof rowSpanValue === 'function') {
|
|
409
|
+
const rowSpan = rowSpanValue(cell.getContext());
|
|
410
|
+
return rowSpan !== 0;
|
|
411
|
+
}
|
|
412
|
+
if (rowSpanValue > 1) {
|
|
413
|
+
const currentRowId = cell.row.id;
|
|
414
|
+
const filteredIndex = allRows.findIndex(r => r.id === currentRowId);
|
|
415
|
+
if (filteredIndex === -1) {
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
return filteredIndex % rowSpanValue === 0;
|
|
419
|
+
}
|
|
420
|
+
return true;
|
|
421
|
+
};
|
|
422
|
+
const shouldBodyCellRenderColSpan = (cell, allCells, columns) => {
|
|
423
|
+
const currentIndex = allCells.findIndex(c => c.id === cell.id);
|
|
424
|
+
if (currentIndex <= 0) {
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
for (let i = 0; i < currentIndex; i++) {
|
|
428
|
+
const prevCell = allCells[i];
|
|
429
|
+
const prevConfig = findColumnConfig(prevCell.column.id, columns);
|
|
430
|
+
const prevColSpan = getBodyColSpan(prevConfig, prevCell.getContext());
|
|
431
|
+
if (prevColSpan && prevColSpan > 1) {
|
|
432
|
+
if (i + prevColSpan > currentIndex) {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return true;
|
|
438
|
+
};
|
|
439
|
+
const shouldFooterRender = (header, allHeaders, columns) => {
|
|
440
|
+
const currentIndex = allHeaders.findIndex(h => h.id === header.id);
|
|
441
|
+
if (currentIndex <= 0) {
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
for (let i = 0; i < currentIndex; i++) {
|
|
445
|
+
const prevHeader = allHeaders[i];
|
|
446
|
+
const prevConfig = findColumnConfig(prevHeader.column.id, columns);
|
|
447
|
+
const prevColSpan = getFooterColSpan(prevConfig);
|
|
448
|
+
if (prevColSpan && prevColSpan > 1) {
|
|
449
|
+
if (i + prevColSpan > currentIndex) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return true;
|
|
455
|
+
};
|
|
456
|
+
const shouldHeaderRender = (header, allHeaders, columns) => {
|
|
457
|
+
const currentIndex = allHeaders.findIndex(h => h.id === header.id);
|
|
458
|
+
if (currentIndex <= 0) {
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
for (let i = 0; i < currentIndex; i++) {
|
|
462
|
+
const prevHeader = allHeaders[i];
|
|
463
|
+
const prevConfig = findColumnConfig(prevHeader.column.id, columns);
|
|
464
|
+
const prevColSpan = getHeaderColSpan(prevConfig);
|
|
465
|
+
if (prevColSpan && prevColSpan > 1) {
|
|
466
|
+
if (i + prevColSpan > currentIndex) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return true;
|
|
472
|
+
};
|
|
473
|
+
function columnConfigToColumnDef(config) {
|
|
474
|
+
const sortConfig = typeof config.sort === 'boolean' ? (config.sort ? { enabled: true } : undefined) : config.sort;
|
|
475
|
+
const filterConfig = typeof config.filter === 'boolean' ? (config.filter ? { enabled: true } : undefined) : config.filter;
|
|
476
|
+
const resolveHeaderOrFooter = (content) => {
|
|
477
|
+
if (!content) {
|
|
478
|
+
return undefined;
|
|
479
|
+
}
|
|
480
|
+
if (typeof content === 'string' || typeof content === 'number') {
|
|
481
|
+
return String(content);
|
|
482
|
+
}
|
|
483
|
+
if (typeof content === 'function') {
|
|
484
|
+
return content;
|
|
485
|
+
}
|
|
486
|
+
return undefined;
|
|
487
|
+
};
|
|
488
|
+
const columnDef = {
|
|
489
|
+
id: config.id,
|
|
490
|
+
size: config.size,
|
|
491
|
+
minSize: config.minSize ?? Z_DEFAULT_COLUMN_MIN_SIZE,
|
|
492
|
+
maxSize: config.maxSize,
|
|
493
|
+
enableSorting: sortConfig?.enabled ?? false,
|
|
494
|
+
enableColumnFilter: filterConfig?.enabled ?? false,
|
|
495
|
+
enableResizing: config.enableResizing,
|
|
496
|
+
enablePinning: config.enablePinning,
|
|
497
|
+
enableHiding: config.enableHiding,
|
|
498
|
+
filterType: filterConfig?.type,
|
|
499
|
+
filterOptions: filterConfig?.options,
|
|
500
|
+
};
|
|
501
|
+
if (config.accessorKey) {
|
|
502
|
+
columnDef.accessorKey = config.accessorKey;
|
|
503
|
+
}
|
|
504
|
+
if (config.accessorFn) {
|
|
505
|
+
columnDef.accessorFn = config.accessorFn;
|
|
506
|
+
}
|
|
507
|
+
columnDef.header = resolveHeaderOrFooter(getHeaderContent(config));
|
|
508
|
+
const bodyContent = getBodyContent(config);
|
|
509
|
+
if (typeof bodyContent === 'string' || typeof bodyContent === 'number') {
|
|
510
|
+
columnDef.cell = () => bodyContent;
|
|
511
|
+
}
|
|
512
|
+
if (typeof bodyContent === 'function') {
|
|
513
|
+
columnDef.cell = bodyContent;
|
|
514
|
+
}
|
|
515
|
+
columnDef.footer = resolveHeaderOrFooter(getFooterContent(config));
|
|
516
|
+
if (sortConfig?.sortFn) {
|
|
517
|
+
columnDef.sortingFn = sortConfig.sortFn;
|
|
518
|
+
}
|
|
519
|
+
if (filterConfig?.filterFn) {
|
|
520
|
+
columnDef.filterFn = filterConfig.filterFn;
|
|
521
|
+
}
|
|
522
|
+
if (filterConfig?.type === 'select') {
|
|
523
|
+
columnDef.filterFn = (row, columnId, filterValue) => {
|
|
524
|
+
if (!filterValue || (Array.isArray(filterValue) && filterValue.length === 0)) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
const cellValue = row.getValue(columnId);
|
|
528
|
+
if (Array.isArray(filterValue)) {
|
|
529
|
+
return filterValue.includes(cellValue);
|
|
530
|
+
}
|
|
531
|
+
return cellValue === filterValue;
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (config.columns && config.columns.length > 0) {
|
|
535
|
+
columnDef.columns = config.columns.map(subConfig => columnConfigToColumnDef(subConfig));
|
|
536
|
+
}
|
|
537
|
+
return columnDef;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const Z_TABLE_BODY_ALIGN_MAP = {
|
|
541
|
+
left: 'text-left',
|
|
542
|
+
center: 'text-center',
|
|
543
|
+
right: 'text-right',
|
|
544
|
+
};
|
|
545
|
+
class ZTableCellConfigPipe {
|
|
546
|
+
transform(cell, columns, property) {
|
|
547
|
+
const columnConfig = findColumnConfig(cell.column.id, columns);
|
|
548
|
+
const bodyConfig = getBodyConfig(columnConfig, cell.getContext());
|
|
549
|
+
switch (property) {
|
|
550
|
+
case 'cellClass':
|
|
551
|
+
return this._getCellClass(bodyConfig);
|
|
552
|
+
case 'cellStyle':
|
|
553
|
+
return bodyConfig.style || {};
|
|
554
|
+
case 'contentClass':
|
|
555
|
+
return bodyConfig.contentClass || '';
|
|
556
|
+
case 'contentStyle':
|
|
557
|
+
return bodyConfig.contentStyle || {};
|
|
558
|
+
case 'contentTooltip':
|
|
559
|
+
return bodyConfig.tooltip || '';
|
|
560
|
+
default:
|
|
561
|
+
return '';
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
_getCellClass(bodyConfig) {
|
|
565
|
+
const classes = [];
|
|
566
|
+
if (bodyConfig.align) {
|
|
567
|
+
const alignClass = Z_TABLE_BODY_ALIGN_MAP[bodyConfig.align];
|
|
568
|
+
if (alignClass) {
|
|
569
|
+
classes.push(alignClass);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (bodyConfig.class) {
|
|
573
|
+
classes.push(bodyConfig.class);
|
|
574
|
+
}
|
|
575
|
+
return classes.join(' ');
|
|
576
|
+
}
|
|
577
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableCellConfigPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
578
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableCellConfigPipe, isStandalone: true, name: "zTableCellConfig" });
|
|
579
|
+
}
|
|
580
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableCellConfigPipe, decorators: [{
|
|
581
|
+
type: Pipe,
|
|
582
|
+
args: [{
|
|
583
|
+
name: 'zTableCellConfig',
|
|
584
|
+
standalone: true,
|
|
585
|
+
pure: true,
|
|
586
|
+
}]
|
|
587
|
+
}] });
|
|
588
|
+
|
|
589
|
+
class ZTableCellOffsetPipe {
|
|
590
|
+
/**
|
|
591
|
+
* Calculate if a cell/header is at the left edge (offset = 0)
|
|
592
|
+
* Returns true if the cell should have no border-left (it's at the leftmost position)
|
|
593
|
+
*/
|
|
594
|
+
transform(item, orderedColumns) {
|
|
595
|
+
const columnId = item.column.id;
|
|
596
|
+
// Find the index of this column in the ordered columns list
|
|
597
|
+
const columnIndex = orderedColumns.findIndex(col => col.id === columnId);
|
|
598
|
+
// If it's the first column (index 0), it's at the left edge
|
|
599
|
+
if (columnIndex === 0) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
// For headers with colSpan, check if any of its leaf columns is the first
|
|
603
|
+
if ('getLeafHeaders' in item) {
|
|
604
|
+
const header = item;
|
|
605
|
+
const leafHeaders = header.getLeafHeaders();
|
|
606
|
+
for (const leaf of leafHeaders) {
|
|
607
|
+
const leafIndex = orderedColumns.findIndex(col => col.id === leaf.column.id);
|
|
608
|
+
if (leafIndex === 0) {
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableCellOffsetPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
616
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableCellOffsetPipe, isStandalone: true, name: "zTableCellOffset" });
|
|
617
|
+
}
|
|
618
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableCellOffsetPipe, decorators: [{
|
|
619
|
+
type: Pipe,
|
|
620
|
+
args: [{
|
|
621
|
+
name: 'zTableCellOffset',
|
|
622
|
+
standalone: true,
|
|
623
|
+
pure: true,
|
|
624
|
+
}]
|
|
625
|
+
}] });
|
|
626
|
+
|
|
627
|
+
const Z_TABLE_ALIGN_MAP = {
|
|
628
|
+
left: 'text-left',
|
|
629
|
+
center: 'text-center',
|
|
630
|
+
right: 'text-right',
|
|
631
|
+
};
|
|
632
|
+
class ZTableColumnConfigPipe {
|
|
633
|
+
transform(columnId, columns, property) {
|
|
634
|
+
const columnConfig = findColumnConfig(columnId, columns);
|
|
635
|
+
switch (property) {
|
|
636
|
+
case 'headerClass': {
|
|
637
|
+
const headerConfig = getHeaderConfig(columnConfig);
|
|
638
|
+
return headerConfig.class || '';
|
|
639
|
+
}
|
|
640
|
+
case 'headerStyle': {
|
|
641
|
+
const headerConfig = getHeaderConfig(columnConfig);
|
|
642
|
+
return headerConfig.style || {};
|
|
643
|
+
}
|
|
644
|
+
case 'headerTooltip': {
|
|
645
|
+
const headerConfig = getHeaderConfig(columnConfig);
|
|
646
|
+
return headerConfig.tooltip || '';
|
|
647
|
+
}
|
|
648
|
+
case 'headerAlignClass': {
|
|
649
|
+
const headerConfig = getHeaderConfig(columnConfig);
|
|
650
|
+
return headerConfig.align ? Z_TABLE_ALIGN_MAP[headerConfig.align] || '' : '';
|
|
651
|
+
}
|
|
652
|
+
case 'footerClass': {
|
|
653
|
+
const footerConfig = getFooterConfig(columnConfig);
|
|
654
|
+
return footerConfig.class || '';
|
|
655
|
+
}
|
|
656
|
+
case 'footerStyle': {
|
|
657
|
+
const footerConfig = getFooterConfig(columnConfig);
|
|
658
|
+
return footerConfig.style || {};
|
|
659
|
+
}
|
|
660
|
+
case 'footerTooltip': {
|
|
661
|
+
const footerConfig = getFooterConfig(columnConfig);
|
|
662
|
+
return footerConfig.tooltip || '';
|
|
663
|
+
}
|
|
664
|
+
case 'footerAlignClass': {
|
|
665
|
+
const footerConfig = getFooterConfig(columnConfig);
|
|
666
|
+
return footerConfig.align ? Z_TABLE_ALIGN_MAP[footerConfig.align] || '' : '';
|
|
667
|
+
}
|
|
668
|
+
case 'hasBodyRowSpan':
|
|
669
|
+
return columnConfig ? isBodyConfig(columnConfig.body) && columnConfig.body.rowSpan !== undefined : false;
|
|
670
|
+
case 'footerContent': {
|
|
671
|
+
const footerConfig = getFooterConfig(columnConfig);
|
|
672
|
+
return footerConfig.content || '';
|
|
673
|
+
}
|
|
674
|
+
default:
|
|
675
|
+
return '';
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnConfigPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
679
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnConfigPipe, isStandalone: true, name: "zTableColumnConfig" });
|
|
680
|
+
}
|
|
681
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnConfigPipe, decorators: [{
|
|
682
|
+
type: Pipe,
|
|
683
|
+
args: [{
|
|
684
|
+
name: 'zTableColumnConfig',
|
|
685
|
+
standalone: true,
|
|
686
|
+
pure: true,
|
|
687
|
+
}]
|
|
688
|
+
}] });
|
|
689
|
+
|
|
690
|
+
class ZTableColumnHeaderPipe {
|
|
691
|
+
transform(columnId, columns) {
|
|
692
|
+
const columnConfig = findColumnConfig(columnId, columns);
|
|
693
|
+
if (!columnConfig) {
|
|
694
|
+
return columnId;
|
|
695
|
+
}
|
|
696
|
+
const headerConfig = getHeaderConfig(columnConfig);
|
|
697
|
+
if (typeof headerConfig.content === 'string') {
|
|
698
|
+
return stripIconSyntax(headerConfig.content);
|
|
699
|
+
}
|
|
700
|
+
return columnId;
|
|
701
|
+
}
|
|
702
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnHeaderPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
703
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnHeaderPipe, isStandalone: true, name: "zTableColumnHeader" });
|
|
704
|
+
}
|
|
705
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnHeaderPipe, decorators: [{
|
|
706
|
+
type: Pipe,
|
|
707
|
+
args: [{
|
|
708
|
+
name: 'zTableColumnHeader',
|
|
709
|
+
standalone: true,
|
|
710
|
+
pure: true,
|
|
711
|
+
}]
|
|
712
|
+
}] });
|
|
713
|
+
|
|
714
|
+
class ZTableColumnParentsPipe {
|
|
715
|
+
transform(columnId, columns) {
|
|
716
|
+
const parents = [];
|
|
717
|
+
this._findParents(columnId, columns, parents);
|
|
718
|
+
return parents.length > 0 ? parents.join(' › ') : '';
|
|
719
|
+
}
|
|
720
|
+
_findParents(columnId, columns, parents, currentParents = []) {
|
|
721
|
+
for (const col of columns) {
|
|
722
|
+
if (col.id === columnId) {
|
|
723
|
+
parents.push(...currentParents);
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
if (col.columns && col.columns.length > 0) {
|
|
727
|
+
const parentName = this._getColumnName(col);
|
|
728
|
+
const found = this._findParents(columnId, col.columns, parents, [...currentParents, parentName]);
|
|
729
|
+
if (found) {
|
|
730
|
+
return true;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
_getColumnName(col) {
|
|
737
|
+
const headerConfig = getHeaderConfig(col);
|
|
738
|
+
if (typeof headerConfig.content === 'string') {
|
|
739
|
+
return stripIconSyntax(headerConfig.content);
|
|
740
|
+
}
|
|
741
|
+
return col.id;
|
|
742
|
+
}
|
|
743
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnParentsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
744
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnParentsPipe, isStandalone: true, name: "zTableColumnParents" });
|
|
745
|
+
}
|
|
746
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableColumnParentsPipe, decorators: [{
|
|
747
|
+
type: Pipe,
|
|
748
|
+
args: [{
|
|
749
|
+
name: 'zTableColumnParents',
|
|
750
|
+
standalone: true,
|
|
751
|
+
pure: true,
|
|
752
|
+
}]
|
|
753
|
+
}] });
|
|
754
|
+
|
|
755
|
+
class ZTableFooterContentPipe {
|
|
756
|
+
transform(footerGroup, columns) {
|
|
757
|
+
return footerGroup.headers.some(header => {
|
|
758
|
+
const columnConfig = findColumnConfig(header.column.id, columns);
|
|
759
|
+
return columnConfig?.footer !== undefined;
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableFooterContentPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
763
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableFooterContentPipe, isStandalone: true, name: "zTableFooterContent" });
|
|
764
|
+
}
|
|
765
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableFooterContentPipe, decorators: [{
|
|
766
|
+
type: Pipe,
|
|
767
|
+
args: [{
|
|
768
|
+
name: 'zTableFooterContent',
|
|
769
|
+
standalone: true,
|
|
770
|
+
pure: true,
|
|
771
|
+
}]
|
|
772
|
+
}] });
|
|
773
|
+
|
|
774
|
+
class ZTableHasIconPipe {
|
|
775
|
+
transform(content) {
|
|
776
|
+
if (typeof content !== 'string') {
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
return hasIconSyntax(content);
|
|
780
|
+
}
|
|
781
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableHasIconPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
782
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableHasIconPipe, isStandalone: true, name: "zTableHasIcon" });
|
|
783
|
+
}
|
|
784
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableHasIconPipe, decorators: [{
|
|
785
|
+
type: Pipe,
|
|
786
|
+
args: [{
|
|
787
|
+
name: 'zTableHasIcon',
|
|
788
|
+
standalone: true,
|
|
789
|
+
pure: true,
|
|
790
|
+
}]
|
|
791
|
+
}] });
|
|
792
|
+
|
|
793
|
+
class ZTableHeaderPinPipe {
|
|
794
|
+
transform(item, property, columns, _orderedLeafColumns) {
|
|
795
|
+
switch (property) {
|
|
796
|
+
case 'isLastLeftPinned':
|
|
797
|
+
return this._isHeaderLastLeftPinned(item, columns ?? []);
|
|
798
|
+
case 'isFirstRightPinned':
|
|
799
|
+
return this._isHeaderFirstRightPinned(item);
|
|
800
|
+
case 'isLastRightPinned':
|
|
801
|
+
return this._isHeaderLastRightPinned(item, columns ?? []);
|
|
802
|
+
default:
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
_isHeaderLastLeftPinned(header, columns) {
|
|
807
|
+
const leafHeaders = header.getLeafHeaders();
|
|
808
|
+
const hasLastLeftPinnedLeaf = leafHeaders.some(lh => lh.column.getIsPinned() === 'left' && lh.column.getIsLastColumn('left'));
|
|
809
|
+
if (hasLastLeftPinnedLeaf) {
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
const columnConfig = findColumnConfig(header.column.id, columns);
|
|
813
|
+
const configColSpan = getHeaderColSpan(columnConfig);
|
|
814
|
+
if (configColSpan && configColSpan > 1) {
|
|
815
|
+
const { headers: allHeadersInGroup } = header.headerGroup;
|
|
816
|
+
const currentIndex = allHeadersInGroup.findIndex(h => h.id === header.id);
|
|
817
|
+
if (currentIndex !== -1) {
|
|
818
|
+
const endIndex = currentIndex + configColSpan - 1;
|
|
819
|
+
if (endIndex < allHeadersInGroup.length) {
|
|
820
|
+
const targetHeader = allHeadersInGroup[endIndex];
|
|
821
|
+
const targetLeafHeaders = targetHeader.getLeafHeaders();
|
|
822
|
+
return targetLeafHeaders.some(lh => lh.column.getIsPinned() === 'left' && lh.column.getIsLastColumn('left'));
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
_isHeaderFirstRightPinned(header) {
|
|
829
|
+
const leafHeaders = header.getLeafHeaders();
|
|
830
|
+
return leafHeaders.some(lh => lh.column.getIsPinned() === 'right' && lh.column.getIsFirstColumn('right'));
|
|
831
|
+
}
|
|
832
|
+
_isHeaderLastRightPinned(header, columns) {
|
|
833
|
+
const leafHeaders = header.getLeafHeaders();
|
|
834
|
+
const hasLastRightPinnedLeaf = leafHeaders.some(lh => lh.column.getIsPinned() === 'right' && lh.column.getIsLastColumn('right'));
|
|
835
|
+
if (hasLastRightPinnedLeaf) {
|
|
836
|
+
return true;
|
|
837
|
+
}
|
|
838
|
+
const columnConfig = findColumnConfig(header.column.id, columns);
|
|
839
|
+
const configColSpan = getHeaderColSpan(columnConfig);
|
|
840
|
+
if (configColSpan && configColSpan > 1) {
|
|
841
|
+
const { headers: allHeadersInGroup } = header.headerGroup;
|
|
842
|
+
const currentIndex = allHeadersInGroup.findIndex(h => h.id === header.id);
|
|
843
|
+
if (currentIndex !== -1) {
|
|
844
|
+
const endIndex = currentIndex + configColSpan - 1;
|
|
845
|
+
if (endIndex < allHeadersInGroup.length) {
|
|
846
|
+
const targetHeader = allHeadersInGroup[endIndex];
|
|
847
|
+
const targetLeafHeaders = targetHeader.getLeafHeaders();
|
|
848
|
+
return targetLeafHeaders.some(lh => lh.column.getIsPinned() === 'right' && lh.column.getIsLastColumn('right'));
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
return false;
|
|
853
|
+
}
|
|
854
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableHeaderPinPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
855
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableHeaderPinPipe, isStandalone: true, name: "zTableHeaderPin" });
|
|
856
|
+
}
|
|
857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableHeaderPinPipe, decorators: [{
|
|
858
|
+
type: Pipe,
|
|
859
|
+
args: [{
|
|
860
|
+
name: 'zTableHeaderPin',
|
|
861
|
+
standalone: true,
|
|
862
|
+
pure: true,
|
|
863
|
+
}]
|
|
864
|
+
}] });
|
|
865
|
+
|
|
866
|
+
class ZTablePinningStylesPipe {
|
|
867
|
+
transform(column, item, type, tableOrCells, columns) {
|
|
868
|
+
if (type === 'body') {
|
|
869
|
+
const allCells = Array.isArray(tableOrCells) ? tableOrCells : undefined;
|
|
870
|
+
return this._getBodyPinningStyles(column, item, allCells, columns || []);
|
|
871
|
+
}
|
|
872
|
+
if (type === 'header' && item && tableOrCells && !Array.isArray(tableOrCells)) {
|
|
873
|
+
return this._getHeaderPinningStyles(column, item, tableOrCells, columns || []);
|
|
874
|
+
}
|
|
875
|
+
return {};
|
|
876
|
+
}
|
|
877
|
+
_getBodyPinningStyles(column, cell, allCells, columns) {
|
|
878
|
+
const isPinned = column.getIsPinned();
|
|
879
|
+
let leftOffset = column.getStart('left');
|
|
880
|
+
let rightOffset = column.getAfter('right');
|
|
881
|
+
if (allCells && cell && isPinned === 'left') {
|
|
882
|
+
const currentIdx = allCells.findIndex(c => c.id === cell.id);
|
|
883
|
+
if (currentIdx > 0) {
|
|
884
|
+
let calculatedOffset = 0;
|
|
885
|
+
for (let i = 0; i < currentIdx; i++) {
|
|
886
|
+
const prevCell = allCells[i];
|
|
887
|
+
if (!shouldBodyCellRenderColSpan(prevCell, allCells, columns)) {
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
const prevConfig = findColumnConfig(prevCell.column.id, columns);
|
|
891
|
+
const prevColSpan = getBodyColSpan(prevConfig, prevCell.getContext());
|
|
892
|
+
if (prevColSpan && prevColSpan > 1) {
|
|
893
|
+
let spanWidth = prevCell.column.getSize();
|
|
894
|
+
for (let j = 1; j < prevColSpan && i + j < allCells.length; j++) {
|
|
895
|
+
spanWidth += allCells[i + j].column.getSize();
|
|
896
|
+
}
|
|
897
|
+
calculatedOffset += spanWidth;
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
calculatedOffset += prevCell.column.getSize();
|
|
901
|
+
}
|
|
902
|
+
leftOffset = calculatedOffset;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
if (allCells && cell && isPinned === 'right') {
|
|
906
|
+
const currentIdx = allCells.findIndex(c => c.id === cell.id);
|
|
907
|
+
if (currentIdx === allCells.length - 1) {
|
|
908
|
+
rightOffset = 0;
|
|
909
|
+
}
|
|
910
|
+
if (currentIdx >= 0 && currentIdx < allCells.length - 1) {
|
|
911
|
+
let calculatedOffset = 0;
|
|
912
|
+
for (let i = currentIdx + 1; i < allCells.length; i++) {
|
|
913
|
+
const nextCell = allCells[i];
|
|
914
|
+
if (!shouldBodyCellRenderColSpan(nextCell, allCells, columns)) {
|
|
915
|
+
continue;
|
|
916
|
+
}
|
|
917
|
+
const nextConfig = findColumnConfig(nextCell.column.id, columns);
|
|
918
|
+
const nextColSpan = getBodyColSpan(nextConfig, nextCell.getContext());
|
|
919
|
+
if (nextColSpan && nextColSpan > 1) {
|
|
920
|
+
let spanWidth = nextCell.column.getSize();
|
|
921
|
+
for (let j = 1; j < nextColSpan && i + j < allCells.length; j++) {
|
|
922
|
+
spanWidth += allCells[i + j].column.getSize();
|
|
923
|
+
}
|
|
924
|
+
calculatedOffset += spanWidth;
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
calculatedOffset += nextCell.column.getSize();
|
|
928
|
+
}
|
|
929
|
+
rightOffset = calculatedOffset;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
return {
|
|
933
|
+
left: isPinned === 'left' ? `${leftOffset}px` : undefined,
|
|
934
|
+
right: isPinned === 'right' ? `${rightOffset}px` : undefined,
|
|
935
|
+
position: isPinned ? 'sticky' : 'relative',
|
|
936
|
+
zIndex: isPinned ? 1 : 0,
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
_getHeaderPinningStyles(column, headerCurrent, table, columns) {
|
|
940
|
+
const isPinnedColumn = column.getIsPinned();
|
|
941
|
+
const leftPositions = {};
|
|
942
|
+
const headerGroupsAll = table.getHeaderGroups();
|
|
943
|
+
for (const headerGroup of headerGroupsAll) {
|
|
944
|
+
for (const header of headerGroup.headers) {
|
|
945
|
+
leftPositions[header.id] = header.getStart('left');
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
const newOffsetLeft = {};
|
|
949
|
+
const newOffsetRight = {};
|
|
950
|
+
let isChildPinned = undefined;
|
|
951
|
+
if (isPinnedColumn) {
|
|
952
|
+
const headerGroups = headerCurrent.headerGroup.headers;
|
|
953
|
+
const leafHeaders = headerCurrent.getLeafHeaders();
|
|
954
|
+
const filterChild = leafHeaders.filter(h => h.column.id !== column.id);
|
|
955
|
+
if (filterChild.length === 0) {
|
|
956
|
+
isChildPinned = isPinnedColumn;
|
|
957
|
+
}
|
|
958
|
+
for (const child of filterChild) {
|
|
959
|
+
const isPinned = child.column.getIsPinned();
|
|
960
|
+
if (isPinned) {
|
|
961
|
+
isChildPinned = isPinned;
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (isChildPinned === 'left') {
|
|
966
|
+
const temp = [...headerGroups];
|
|
967
|
+
const headersBeforeCurrent = [];
|
|
968
|
+
for (let i = 0; i < temp.length; i++) {
|
|
969
|
+
const indexOfHeader = temp.findIndex(h => h.id === headerCurrent.id);
|
|
970
|
+
if (i < indexOfHeader) {
|
|
971
|
+
const leafs = temp[i].getLeafHeaders();
|
|
972
|
+
const hasLeftPinned = leafs.some(lh => lh.column.getIsPinned() === 'left');
|
|
973
|
+
if (hasLeftPinned) {
|
|
974
|
+
headersBeforeCurrent.push(temp[i]);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
newOffsetLeft[headerCurrent.id] = headersBeforeCurrent.reduce((sum, h) => {
|
|
979
|
+
if (!shouldHeaderRender(h, headerGroups, columns)) {
|
|
980
|
+
return sum;
|
|
981
|
+
}
|
|
982
|
+
if (h.subHeaders.length > 0) {
|
|
983
|
+
const subSum = h.subHeaders
|
|
984
|
+
.filter(subH => subH.column.getIsPinned() === 'left')
|
|
985
|
+
.filter(subH => shouldHeaderRender(subH, h.subHeaders, columns))
|
|
986
|
+
.reduce((subAcc, subH) => {
|
|
987
|
+
const config = findColumnConfig(subH.column.id, columns);
|
|
988
|
+
const colSpan = getHeaderColSpan(config);
|
|
989
|
+
if (colSpan && colSpan > 1) {
|
|
990
|
+
const currentIdx = h.subHeaders.findIndex(sh => sh.id === subH.id);
|
|
991
|
+
let totalWidth = subH.column.getSize();
|
|
992
|
+
for (let j = 1; j < colSpan && currentIdx + j < h.subHeaders.length; j++) {
|
|
993
|
+
totalWidth += h.subHeaders[currentIdx + j].column.getSize();
|
|
994
|
+
}
|
|
995
|
+
return subAcc + totalWidth;
|
|
996
|
+
}
|
|
997
|
+
return subAcc + subH.column.getSize();
|
|
998
|
+
}, 0);
|
|
999
|
+
return sum + subSum;
|
|
1000
|
+
}
|
|
1001
|
+
const config = findColumnConfig(h.column.id, columns);
|
|
1002
|
+
const colSpan = getHeaderColSpan(config);
|
|
1003
|
+
if (colSpan && colSpan > 1) {
|
|
1004
|
+
const currentIdx = headerGroups.findIndex(hg => hg.id === h.id);
|
|
1005
|
+
let totalWidth = h.column.getSize();
|
|
1006
|
+
for (let j = 1; j < colSpan && currentIdx + j < headerGroups.length; j++) {
|
|
1007
|
+
totalWidth += headerGroups[currentIdx + j].column.getSize();
|
|
1008
|
+
}
|
|
1009
|
+
return sum + totalWidth;
|
|
1010
|
+
}
|
|
1011
|
+
return sum + h.column.getSize();
|
|
1012
|
+
}, 0);
|
|
1013
|
+
}
|
|
1014
|
+
if (isChildPinned === 'right') {
|
|
1015
|
+
const headersAfterCurrent = [];
|
|
1016
|
+
const temp = [...headerGroups].reverse();
|
|
1017
|
+
for (let i = 0; i < temp.length; i++) {
|
|
1018
|
+
const indexOfHeader = temp.findIndex(h => h.id === headerCurrent.id);
|
|
1019
|
+
if (i < indexOfHeader) {
|
|
1020
|
+
headersAfterCurrent.push(temp[i]);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
newOffsetRight[headerCurrent.id] = headersAfterCurrent.reduce((sum, h) => {
|
|
1024
|
+
if (!shouldHeaderRender(h, headerGroups, columns)) {
|
|
1025
|
+
return sum;
|
|
1026
|
+
}
|
|
1027
|
+
if (h.subHeaders.length > 0) {
|
|
1028
|
+
const subSum = h.subHeaders
|
|
1029
|
+
.filter(subH => subH.column.getIsPinned() === 'right')
|
|
1030
|
+
.filter(subH => shouldHeaderRender(subH, h.subHeaders, columns))
|
|
1031
|
+
.reduce((subAcc, subH) => {
|
|
1032
|
+
const config = findColumnConfig(subH.column.id, columns);
|
|
1033
|
+
const colSpan = getHeaderColSpan(config);
|
|
1034
|
+
if (colSpan && colSpan > 1) {
|
|
1035
|
+
const currentIdx = h.subHeaders.findIndex(sh => sh.id === subH.id);
|
|
1036
|
+
let totalWidth = subH.column.getSize();
|
|
1037
|
+
for (let j = 1; j < colSpan && currentIdx + j < h.subHeaders.length; j++) {
|
|
1038
|
+
totalWidth += h.subHeaders[currentIdx + j].column.getSize();
|
|
1039
|
+
}
|
|
1040
|
+
return subAcc + totalWidth;
|
|
1041
|
+
}
|
|
1042
|
+
return subAcc + subH.column.getSize();
|
|
1043
|
+
}, 0);
|
|
1044
|
+
return sum + subSum;
|
|
1045
|
+
}
|
|
1046
|
+
const config = findColumnConfig(h.column.id, columns);
|
|
1047
|
+
const colSpan = getHeaderColSpan(config);
|
|
1048
|
+
if (colSpan && colSpan > 1) {
|
|
1049
|
+
const currentIdx = headerGroups.findIndex(hg => hg.id === h.id);
|
|
1050
|
+
let totalWidth = h.column.getSize();
|
|
1051
|
+
for (let j = 1; j < colSpan && currentIdx + j < headerGroups.length; j++) {
|
|
1052
|
+
totalWidth += headerGroups[currentIdx + j].column.getSize();
|
|
1053
|
+
}
|
|
1054
|
+
return sum + totalWidth;
|
|
1055
|
+
}
|
|
1056
|
+
return sum + h.column.getSize();
|
|
1057
|
+
}, 0);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
const leftValue = isChildPinned === 'left'
|
|
1061
|
+
? newOffsetLeft[headerCurrent.id] !== undefined
|
|
1062
|
+
? newOffsetLeft[headerCurrent.id]
|
|
1063
|
+
: leftPositions[headerCurrent.id]
|
|
1064
|
+
: undefined;
|
|
1065
|
+
return {
|
|
1066
|
+
position: isChildPinned ? 'sticky' : 'relative',
|
|
1067
|
+
zIndex: isChildPinned ? 1 : 0,
|
|
1068
|
+
left: leftValue !== undefined ? `${leftValue}px` : undefined,
|
|
1069
|
+
right: isChildPinned === 'right' ? `${newOffsetRight[headerCurrent.id]}px` : undefined,
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTablePinningStylesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1073
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTablePinningStylesPipe, isStandalone: true, name: "zTablePinningStyles" });
|
|
1074
|
+
}
|
|
1075
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTablePinningStylesPipe, decorators: [{
|
|
1076
|
+
type: Pipe,
|
|
1077
|
+
args: [{
|
|
1078
|
+
name: 'zTablePinningStyles',
|
|
1079
|
+
standalone: true,
|
|
1080
|
+
pure: true,
|
|
1081
|
+
}]
|
|
1082
|
+
}] });
|
|
1083
|
+
|
|
1084
|
+
class ZTableRowPipe {
|
|
1085
|
+
transform(row, table, property, virtualRowHeight) {
|
|
1086
|
+
switch (property) {
|
|
1087
|
+
case 'isLastTopPinned':
|
|
1088
|
+
return this._isLastTopPinnedRow(row, table);
|
|
1089
|
+
case 'isFirstBottomPinned':
|
|
1090
|
+
return this._isFirstBottomPinnedRow(row, table);
|
|
1091
|
+
case 'pinningStyles':
|
|
1092
|
+
return this._getRowPinningStyles(row, table, virtualRowHeight ?? 40);
|
|
1093
|
+
default:
|
|
1094
|
+
return false;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
_isLastTopPinnedRow(row, table) {
|
|
1098
|
+
const topRows = table.getTopRows();
|
|
1099
|
+
if (topRows.length === 0) {
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
return row.getPinnedIndex() === topRows.length - 1;
|
|
1103
|
+
}
|
|
1104
|
+
_isFirstBottomPinnedRow(row, table) {
|
|
1105
|
+
const bottomRows = table.getBottomRows();
|
|
1106
|
+
if (bottomRows.length === 0) {
|
|
1107
|
+
return false;
|
|
1108
|
+
}
|
|
1109
|
+
return row.getPinnedIndex() === bottomRows.length - 1;
|
|
1110
|
+
}
|
|
1111
|
+
_getRowPinningStyles(row, table, virtualRowHeight) {
|
|
1112
|
+
const pinned = row.getIsPinned();
|
|
1113
|
+
if (!pinned) {
|
|
1114
|
+
return {};
|
|
1115
|
+
}
|
|
1116
|
+
const pinnedIndex = row.getPinnedIndex();
|
|
1117
|
+
const defaultHeight = virtualRowHeight + 2;
|
|
1118
|
+
if (pinned === 'top') {
|
|
1119
|
+
let offset = 0;
|
|
1120
|
+
const topRows = table.getTopRows();
|
|
1121
|
+
for (let i = 0; i < pinnedIndex; i++) {
|
|
1122
|
+
const rowEl = document.querySelector(`tr[data-row-id="${topRows[i].id}"]`);
|
|
1123
|
+
offset += rowEl ? rowEl.getBoundingClientRect().height : defaultHeight;
|
|
1124
|
+
}
|
|
1125
|
+
return { position: 'sticky', top: `${offset}px`, zIndex: 2 };
|
|
1126
|
+
}
|
|
1127
|
+
if (pinned === 'bottom') {
|
|
1128
|
+
let offset = 0;
|
|
1129
|
+
const bottomRows = table.getBottomRows();
|
|
1130
|
+
for (let i = 0; i < pinnedIndex; i++) {
|
|
1131
|
+
const rowEl = document.querySelector(`tr[data-row-id="${bottomRows[i].id}"]`);
|
|
1132
|
+
offset += rowEl ? rowEl.getBoundingClientRect().height : defaultHeight;
|
|
1133
|
+
}
|
|
1134
|
+
return { position: 'sticky', bottom: `${offset}px`, zIndex: 2 };
|
|
1135
|
+
}
|
|
1136
|
+
return {};
|
|
1137
|
+
}
|
|
1138
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableRowPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1139
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableRowPipe, isStandalone: true, name: "zTableRow" });
|
|
1140
|
+
}
|
|
1141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableRowPipe, decorators: [{
|
|
1142
|
+
type: Pipe,
|
|
1143
|
+
args: [{
|
|
1144
|
+
name: 'zTableRow',
|
|
1145
|
+
standalone: true,
|
|
1146
|
+
pure: true,
|
|
1147
|
+
}]
|
|
1148
|
+
}] });
|
|
1149
|
+
|
|
1150
|
+
class ZTableSpanPipe {
|
|
1151
|
+
transform(item, columns, property, allRows) {
|
|
1152
|
+
const columnConfig = findColumnConfig(item.column.id, columns);
|
|
1153
|
+
switch (property) {
|
|
1154
|
+
case 'cellRowSpan':
|
|
1155
|
+
return calculateCellRowSpan(item, columnConfig, allRows ?? []);
|
|
1156
|
+
case 'cellColSpan':
|
|
1157
|
+
return calculateCellColSpan(item, columnConfig);
|
|
1158
|
+
case 'headerRowSpan':
|
|
1159
|
+
return calculateHeaderRowSpan(item, columnConfig, columns);
|
|
1160
|
+
case 'headerColSpan':
|
|
1161
|
+
return calculateHeaderColSpan(item, columnConfig);
|
|
1162
|
+
case 'footerRowSpan':
|
|
1163
|
+
return calculateFooterRowSpan(item, columnConfig);
|
|
1164
|
+
case 'footerColSpan':
|
|
1165
|
+
return calculateFooterColSpan(item, columnConfig);
|
|
1166
|
+
case 'shouldRender':
|
|
1167
|
+
return shouldCellRenderUtil(item, columnConfig, allRows ?? []);
|
|
1168
|
+
default:
|
|
1169
|
+
return null;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableSpanPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1173
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableSpanPipe, isStandalone: true, name: "zTableSpan" });
|
|
1174
|
+
}
|
|
1175
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableSpanPipe, decorators: [{
|
|
1176
|
+
type: Pipe,
|
|
1177
|
+
args: [{
|
|
1178
|
+
name: 'zTableSpan',
|
|
1179
|
+
standalone: true,
|
|
1180
|
+
pure: true,
|
|
1181
|
+
}]
|
|
1182
|
+
}] });
|
|
1183
|
+
|
|
1184
|
+
class ZTableIsTemplateRefPipe {
|
|
1185
|
+
transform(value) {
|
|
1186
|
+
return value instanceof TemplateRef;
|
|
1187
|
+
}
|
|
1188
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableIsTemplateRefPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1189
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableIsTemplateRefPipe, isStandalone: true, name: "zTableIsTemplateRef" });
|
|
1190
|
+
}
|
|
1191
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableIsTemplateRefPipe, decorators: [{
|
|
1192
|
+
type: Pipe,
|
|
1193
|
+
args: [{
|
|
1194
|
+
name: 'zTableIsTemplateRef',
|
|
1195
|
+
standalone: true,
|
|
1196
|
+
pure: true,
|
|
1197
|
+
}]
|
|
1198
|
+
}] });
|
|
1199
|
+
|
|
1200
|
+
class ZTableBodyCellRenderPipe {
|
|
1201
|
+
transform(cell, allCells, columns) {
|
|
1202
|
+
return shouldBodyCellRenderColSpan(cell, allCells, columns);
|
|
1203
|
+
}
|
|
1204
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableBodyCellRenderPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1205
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableBodyCellRenderPipe, isStandalone: true, name: "zTableBodyCellRender" });
|
|
1206
|
+
}
|
|
1207
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableBodyCellRenderPipe, decorators: [{
|
|
1208
|
+
type: Pipe,
|
|
1209
|
+
args: [{
|
|
1210
|
+
name: 'zTableBodyCellRender',
|
|
1211
|
+
standalone: true,
|
|
1212
|
+
pure: true,
|
|
1213
|
+
}]
|
|
1214
|
+
}] });
|
|
1215
|
+
|
|
1216
|
+
class ZTableFooterRenderPipe {
|
|
1217
|
+
transform(header, allHeaders, columns) {
|
|
1218
|
+
return shouldFooterRender(header, allHeaders, columns);
|
|
1219
|
+
}
|
|
1220
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableFooterRenderPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1221
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableFooterRenderPipe, isStandalone: true, name: "zTableFooterRender" });
|
|
1222
|
+
}
|
|
1223
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableFooterRenderPipe, decorators: [{
|
|
1224
|
+
type: Pipe,
|
|
1225
|
+
args: [{
|
|
1226
|
+
name: 'zTableFooterRender',
|
|
1227
|
+
standalone: true,
|
|
1228
|
+
pure: true,
|
|
1229
|
+
}]
|
|
1230
|
+
}] });
|
|
1231
|
+
|
|
1232
|
+
class ZTableHeaderRenderPipe {
|
|
1233
|
+
transform(header, allHeaders, columns) {
|
|
1234
|
+
return shouldHeaderRender(header, allHeaders, columns);
|
|
1235
|
+
}
|
|
1236
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableHeaderRenderPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1237
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZTableHeaderRenderPipe, isStandalone: true, name: "zTableHeaderRender" });
|
|
1238
|
+
}
|
|
1239
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableHeaderRenderPipe, decorators: [{
|
|
1240
|
+
type: Pipe,
|
|
1241
|
+
args: [{
|
|
1242
|
+
name: 'zTableHeaderRender',
|
|
1243
|
+
standalone: true,
|
|
1244
|
+
pure: true,
|
|
1245
|
+
}]
|
|
1246
|
+
}] });
|
|
1247
|
+
|
|
1248
|
+
class ZTableFilterComponent {
|
|
1249
|
+
zColumn = input.required(...(ngDevMode ? [{ debugName: "zColumn" }] : []));
|
|
1250
|
+
zTable = input.required(...(ngDevMode ? [{ debugName: "zTable" }] : []));
|
|
1251
|
+
_debounceTimeout = null;
|
|
1252
|
+
_debounceMs = 300;
|
|
1253
|
+
_columnDef = computed(() => this.zColumn().columnDef, ...(ngDevMode ? [{ debugName: "_columnDef" }] : []));
|
|
1254
|
+
filterType = computed(() => this._columnDef().filterType, ...(ngDevMode ? [{ debugName: "filterType" }] : []));
|
|
1255
|
+
columnFilterValue = computed(() => this.zColumn().getFilterValue(), ...(ngDevMode ? [{ debugName: "columnFilterValue" }] : []));
|
|
1256
|
+
minValue = computed(() => this.zColumn().getFacetedMinMaxValues()?.[0] ?? '', ...(ngDevMode ? [{ debugName: "minValue" }] : []));
|
|
1257
|
+
maxValue = computed(() => this.zColumn().getFacetedMinMaxValues()?.[1] ?? '', ...(ngDevMode ? [{ debugName: "maxValue" }] : []));
|
|
1258
|
+
rangeMinValue = computed(() => {
|
|
1259
|
+
const value = this.columnFilterValue();
|
|
1260
|
+
if (!Array.isArray(value)) {
|
|
1261
|
+
return '';
|
|
1262
|
+
}
|
|
1263
|
+
return value[0] ?? '';
|
|
1264
|
+
}, ...(ngDevMode ? [{ debugName: "rangeMinValue" }] : []));
|
|
1265
|
+
rangeMaxValue = computed(() => {
|
|
1266
|
+
const value = this.columnFilterValue();
|
|
1267
|
+
if (!Array.isArray(value)) {
|
|
1268
|
+
return '';
|
|
1269
|
+
}
|
|
1270
|
+
return value[1] ?? '';
|
|
1271
|
+
}, ...(ngDevMode ? [{ debugName: "rangeMaxValue" }] : []));
|
|
1272
|
+
selectOptions = computed(() => {
|
|
1273
|
+
const columnDef = this._columnDef();
|
|
1274
|
+
const allOption = { label: 'All', value: '' };
|
|
1275
|
+
if (columnDef.filterOptions && columnDef.filterOptions.length > 0) {
|
|
1276
|
+
return [allOption, ...columnDef.filterOptions];
|
|
1277
|
+
}
|
|
1278
|
+
const uniqueValues = Array.from(this.zColumn().getFacetedUniqueValues().keys()).sort().slice(0, 5000);
|
|
1279
|
+
return [allOption, ...uniqueValues.map(v => ({ label: String(v), value: String(v) }))];
|
|
1280
|
+
}, ...(ngDevMode ? [{ debugName: "selectOptions" }] : []));
|
|
1281
|
+
ngOnDestroy() {
|
|
1282
|
+
if (this._debounceTimeout) {
|
|
1283
|
+
clearTimeout(this._debounceTimeout);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
onMinChangeDebounced(value) {
|
|
1287
|
+
this._debounce(() => {
|
|
1288
|
+
const numValue = value === null || value === '' ? undefined : Number(value);
|
|
1289
|
+
this.zColumn().setFilterValue((old) => [numValue, old?.[1]]);
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
onMaxChangeDebounced(value) {
|
|
1293
|
+
this._debounce(() => {
|
|
1294
|
+
const numValue = value === null || value === '' ? undefined : Number(value);
|
|
1295
|
+
this.zColumn().setFilterValue((old) => [old?.[0], numValue]);
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
onTextChangeDebounced(value) {
|
|
1299
|
+
this._debounce(() => {
|
|
1300
|
+
this.zColumn().setFilterValue(value);
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
onSelectChange(value) {
|
|
1304
|
+
if (typeof value === 'object' && value !== null && 'value' in value) {
|
|
1305
|
+
this.zColumn().setFilterValue(value.value || undefined);
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
this.zColumn().setFilterValue(value || undefined);
|
|
1309
|
+
}
|
|
1310
|
+
_debounce(fn) {
|
|
1311
|
+
if (this._debounceTimeout) {
|
|
1312
|
+
clearTimeout(this._debounceTimeout);
|
|
1313
|
+
}
|
|
1314
|
+
this._debounceTimeout = setTimeout(fn, this._debounceMs);
|
|
1315
|
+
}
|
|
1316
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1317
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZTableFilterComponent, isStandalone: true, selector: "z-table-filter", inputs: { zColumn: { classPropertyName: "zColumn", publicName: "zColumn", isSignal: true, isRequired: true, transformFunction: null }, zTable: { classPropertyName: "zTable", publicName: "zTable", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "z-table-filter block" }, ngImport: i0, template: `
|
|
1318
|
+
@switch (filterType()) {
|
|
1319
|
+
@case ('range') {
|
|
1320
|
+
<div class="flex gap-1">
|
|
1321
|
+
<z-input
|
|
1322
|
+
zType="number"
|
|
1323
|
+
zSize="sm"
|
|
1324
|
+
zPlaceholder="Min"
|
|
1325
|
+
[ngModel]="rangeMinValue()"
|
|
1326
|
+
(ngModelChange)="onMinChangeDebounced($event)"
|
|
1327
|
+
class="min-w-0 flex-1"
|
|
1328
|
+
/>
|
|
1329
|
+
<z-input
|
|
1330
|
+
zType="number"
|
|
1331
|
+
zSize="sm"
|
|
1332
|
+
zPlaceholder="Max"
|
|
1333
|
+
[ngModel]="rangeMaxValue()"
|
|
1334
|
+
(ngModelChange)="onMaxChangeDebounced($event)"
|
|
1335
|
+
class="min-w-0 flex-1"
|
|
1336
|
+
/>
|
|
1337
|
+
</div>
|
|
1338
|
+
}
|
|
1339
|
+
@case ('select') {
|
|
1340
|
+
<z-select
|
|
1341
|
+
zSize="sm"
|
|
1342
|
+
[zOptions]="selectOptions()"
|
|
1343
|
+
[ngModel]="columnFilterValue()?.toString() ?? ''"
|
|
1344
|
+
zPlaceholder="All"
|
|
1345
|
+
(ngModelChange)="onSelectChange($event)"
|
|
1346
|
+
class="w-full min-w-0"
|
|
1347
|
+
/>
|
|
1348
|
+
}
|
|
1349
|
+
@case ('number') {
|
|
1350
|
+
<z-input
|
|
1351
|
+
zType="number"
|
|
1352
|
+
zSize="sm"
|
|
1353
|
+
zAllowClear
|
|
1354
|
+
zPlaceholder="Search..."
|
|
1355
|
+
[ngModel]="columnFilterValue()?.toString() ?? ''"
|
|
1356
|
+
(ngModelChange)="onTextChangeDebounced($event)"
|
|
1357
|
+
class="w-full"
|
|
1358
|
+
/>
|
|
1359
|
+
}
|
|
1360
|
+
@default {
|
|
1361
|
+
<z-input
|
|
1362
|
+
zType="text"
|
|
1363
|
+
zSize="sm"
|
|
1364
|
+
zAllowClear
|
|
1365
|
+
zPlaceholder="Search..."
|
|
1366
|
+
[ngModel]="(columnFilterValue() ?? '').toString()"
|
|
1367
|
+
(ngModelChange)="onTextChangeDebounced($event)"
|
|
1368
|
+
class="w-full"
|
|
1369
|
+
/>
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest"], outputs: ["zOnSearch", "zOnChange", "zControl"], exportAs: ["zInput"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zControl"], exportAs: ["zSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1373
|
+
}
|
|
1374
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableFilterComponent, decorators: [{
|
|
1375
|
+
type: Component,
|
|
1376
|
+
args: [{
|
|
1377
|
+
selector: 'z-table-filter',
|
|
1378
|
+
imports: [FormsModule, ZInputComponent, ZSelectComponent],
|
|
1379
|
+
standalone: true,
|
|
1380
|
+
template: `
|
|
1381
|
+
@switch (filterType()) {
|
|
1382
|
+
@case ('range') {
|
|
1383
|
+
<div class="flex gap-1">
|
|
1384
|
+
<z-input
|
|
1385
|
+
zType="number"
|
|
1386
|
+
zSize="sm"
|
|
1387
|
+
zPlaceholder="Min"
|
|
1388
|
+
[ngModel]="rangeMinValue()"
|
|
1389
|
+
(ngModelChange)="onMinChangeDebounced($event)"
|
|
1390
|
+
class="min-w-0 flex-1"
|
|
1391
|
+
/>
|
|
1392
|
+
<z-input
|
|
1393
|
+
zType="number"
|
|
1394
|
+
zSize="sm"
|
|
1395
|
+
zPlaceholder="Max"
|
|
1396
|
+
[ngModel]="rangeMaxValue()"
|
|
1397
|
+
(ngModelChange)="onMaxChangeDebounced($event)"
|
|
1398
|
+
class="min-w-0 flex-1"
|
|
1399
|
+
/>
|
|
1400
|
+
</div>
|
|
1401
|
+
}
|
|
1402
|
+
@case ('select') {
|
|
1403
|
+
<z-select
|
|
1404
|
+
zSize="sm"
|
|
1405
|
+
[zOptions]="selectOptions()"
|
|
1406
|
+
[ngModel]="columnFilterValue()?.toString() ?? ''"
|
|
1407
|
+
zPlaceholder="All"
|
|
1408
|
+
(ngModelChange)="onSelectChange($event)"
|
|
1409
|
+
class="w-full min-w-0"
|
|
1410
|
+
/>
|
|
1411
|
+
}
|
|
1412
|
+
@case ('number') {
|
|
1413
|
+
<z-input
|
|
1414
|
+
zType="number"
|
|
1415
|
+
zSize="sm"
|
|
1416
|
+
zAllowClear
|
|
1417
|
+
zPlaceholder="Search..."
|
|
1418
|
+
[ngModel]="columnFilterValue()?.toString() ?? ''"
|
|
1419
|
+
(ngModelChange)="onTextChangeDebounced($event)"
|
|
1420
|
+
class="w-full"
|
|
1421
|
+
/>
|
|
1422
|
+
}
|
|
1423
|
+
@default {
|
|
1424
|
+
<z-input
|
|
1425
|
+
zType="text"
|
|
1426
|
+
zSize="sm"
|
|
1427
|
+
zAllowClear
|
|
1428
|
+
zPlaceholder="Search..."
|
|
1429
|
+
[ngModel]="(columnFilterValue() ?? '').toString()"
|
|
1430
|
+
(ngModelChange)="onTextChangeDebounced($event)"
|
|
1431
|
+
class="w-full"
|
|
1432
|
+
/>
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
`,
|
|
1436
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1437
|
+
host: {
|
|
1438
|
+
class: 'z-table-filter block',
|
|
1439
|
+
},
|
|
1440
|
+
}]
|
|
1441
|
+
}], propDecorators: { zColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "zColumn", required: true }] }], zTable: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTable", required: true }] }] } });
|
|
1442
|
+
|
|
1443
|
+
class ZTableIconTextComponent {
|
|
1444
|
+
zText = input('', ...(ngDevMode ? [{ debugName: "zText" }] : []));
|
|
1445
|
+
zTooltip = input('', ...(ngDevMode ? [{ debugName: "zTooltip" }] : []));
|
|
1446
|
+
hostEl = inject(ElementRef).nativeElement;
|
|
1447
|
+
parts = computed(() => parseIconString(this.zText()), ...(ngDevMode ? [{ debugName: "parts" }] : []));
|
|
1448
|
+
tooltipContent = computed(() => {
|
|
1449
|
+
const tooltip = this.zTooltip();
|
|
1450
|
+
if (tooltip) {
|
|
1451
|
+
if (typeof tooltip === 'string') {
|
|
1452
|
+
return stripIconSyntax(tooltip);
|
|
1453
|
+
}
|
|
1454
|
+
if (tooltip.content && typeof tooltip.content === 'string') {
|
|
1455
|
+
return stripIconSyntax(tooltip.content);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
return stripIconSyntax(this.zText());
|
|
1459
|
+
}, ...(ngDevMode ? [{ debugName: "tooltipContent" }] : []));
|
|
1460
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableIconTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1461
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZTableIconTextComponent, isStandalone: true, selector: "z-table-icon-text", inputs: { zText: { classPropertyName: "zText", publicName: "zText", isSignal: true, isRequired: false, transformFunction: null }, zTooltip: { classPropertyName: "zTooltip", publicName: "zTooltip", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1462
|
+
<span class="z-table-icon-text-inner">
|
|
1463
|
+
@for (part of parts(); track $index) {
|
|
1464
|
+
@if (part.type === 'icon') {
|
|
1465
|
+
<z-icon
|
|
1466
|
+
class="shrink-0"
|
|
1467
|
+
[zType]="$any(part.value)"
|
|
1468
|
+
[zSize]="$any(part.size ?? 14)"
|
|
1469
|
+
[zStrokeWidth]="part.strokeWidth ?? 1.5"
|
|
1470
|
+
[ngClass]="part.class ?? ''"
|
|
1471
|
+
/>
|
|
1472
|
+
} @else {
|
|
1473
|
+
<span
|
|
1474
|
+
class="truncate select-text"
|
|
1475
|
+
z-tooltip
|
|
1476
|
+
[zContent]="tooltipContent()"
|
|
1477
|
+
[zTriggerElement]="hostEl"
|
|
1478
|
+
[innerHTML]="part.value | zSafeHtml"
|
|
1479
|
+
></span>
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
</span>
|
|
1483
|
+
`, isInline: true, styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.z-table-icon-text-inner{display:inline-flex;align-items:center;gap:4px;line-height:1.2;min-width:0;max-width:100%}span.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTrigger", "zTooltipType", "zTooltipSize", "zClass", "zShowDelay", "zHideDelay", "zArrow", "zDisabled", "zOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "pipe", type: ZSafeHtmlPipe, name: "zSafeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1484
|
+
}
|
|
1485
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableIconTextComponent, decorators: [{
|
|
1486
|
+
type: Component,
|
|
1487
|
+
args: [{ selector: 'z-table-icon-text', imports: [NgClass, ZIconComponent, ZTooltipDirective, ZSafeHtmlPipe], standalone: true, template: `
|
|
1488
|
+
<span class="z-table-icon-text-inner">
|
|
1489
|
+
@for (part of parts(); track $index) {
|
|
1490
|
+
@if (part.type === 'icon') {
|
|
1491
|
+
<z-icon
|
|
1492
|
+
class="shrink-0"
|
|
1493
|
+
[zType]="$any(part.value)"
|
|
1494
|
+
[zSize]="$any(part.size ?? 14)"
|
|
1495
|
+
[zStrokeWidth]="part.strokeWidth ?? 1.5"
|
|
1496
|
+
[ngClass]="part.class ?? ''"
|
|
1497
|
+
/>
|
|
1498
|
+
} @else {
|
|
1499
|
+
<span
|
|
1500
|
+
class="truncate select-text"
|
|
1501
|
+
z-tooltip
|
|
1502
|
+
[zContent]="tooltipContent()"
|
|
1503
|
+
[zTriggerElement]="hostEl"
|
|
1504
|
+
[innerHTML]="part.value | zSafeHtml"
|
|
1505
|
+
></span>
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
</span>
|
|
1509
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.z-table-icon-text-inner{display:inline-flex;align-items:center;gap:4px;line-height:1.2;min-width:0;max-width:100%}span.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
|
|
1510
|
+
}], propDecorators: { zText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zText", required: false }] }], zTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltip", required: false }] }] } });
|
|
1511
|
+
|
|
1512
|
+
/* eslint-disable @stylistic/indent */
|
|
1513
|
+
class ZTableComponent {
|
|
1514
|
+
zConfig = input({ data: [], columns: [], mode: 'local' }, ...(ngDevMode ? [{ debugName: "zConfig" }] : []));
|
|
1515
|
+
zLoading = input(false, ...(ngDevMode ? [{ debugName: "zLoading" }] : []));
|
|
1516
|
+
zKey = input('', ...(ngDevMode ? [{ debugName: "zKey" }] : []));
|
|
1517
|
+
zChange = output();
|
|
1518
|
+
zControl = output();
|
|
1519
|
+
_destroyRef = inject(DestroyRef);
|
|
1520
|
+
_ngZone = inject(NgZone);
|
|
1521
|
+
_isSyncingScroll = signal(false, ...(ngDevMode ? [{ debugName: "_isSyncingScroll" }] : []));
|
|
1522
|
+
_savedScrollLeft = signal(0, ...(ngDevMode ? [{ debugName: "_savedScrollLeft" }] : []));
|
|
1523
|
+
_resizeObserver = null;
|
|
1524
|
+
_settingsDebounceTimeout = null;
|
|
1525
|
+
_filterEmitDebounceTimeout = null;
|
|
1526
|
+
isProcessing = signal(false, ...(ngDevMode ? [{ debugName: "isProcessing" }] : []));
|
|
1527
|
+
theadWrapper = viewChild('theadWrapper', ...(ngDevMode ? [{ debugName: "theadWrapper" }] : []));
|
|
1528
|
+
tbodyContainer = viewChild('tbodyContainer', ...(ngDevMode ? [{ debugName: "tbodyContainer" }] : []));
|
|
1529
|
+
tbodyWrapper = viewChild('tbodyWrapper', ...(ngDevMode ? [{ debugName: "tbodyWrapper" }] : []));
|
|
1530
|
+
tbodyScrollbar = viewChild('tbodyWrapper', ...(ngDevMode ? [{ debugName: "tbodyScrollbar" }] : []));
|
|
1531
|
+
tfootWrapper = viewChild('tfootWrapper', ...(ngDevMode ? [{ debugName: "tfootWrapper" }] : []));
|
|
1532
|
+
expandedRowTemplate = viewChild('expandedRowTemplate', ...(ngDevMode ? [{ debugName: "expandedRowTemplate" }] : []));
|
|
1533
|
+
columnPinning = signal({ left: [], right: [] }, ...(ngDevMode ? [{ debugName: "columnPinning" }] : []));
|
|
1534
|
+
columnVisibility = signal({}, ...(ngDevMode ? [{ debugName: "columnVisibility" }] : []));
|
|
1535
|
+
columnOrder = signal([], ...(ngDevMode ? [{ debugName: "columnOrder" }] : []));
|
|
1536
|
+
expanded = signal({}, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
|
|
1537
|
+
rowSelection = signal({}, ...(ngDevMode ? [{ debugName: "rowSelection" }] : []));
|
|
1538
|
+
rowPinning = signal({ top: [], bottom: [] }, ...(ngDevMode ? [{ debugName: "rowPinning" }] : []));
|
|
1539
|
+
columnFilters = signal([], ...(ngDevMode ? [{ debugName: "columnFilters" }] : []));
|
|
1540
|
+
globalFilter = signal('', ...(ngDevMode ? [{ debugName: "globalFilter" }] : []));
|
|
1541
|
+
pagination = signal({ pageIndex: 1, pageSize: 10 }, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
|
|
1542
|
+
sorting = signal([], ...(ngDevMode ? [{ debugName: "sorting" }] : []));
|
|
1543
|
+
_tanstackPagination = computed(() => ({
|
|
1544
|
+
...this.pagination(),
|
|
1545
|
+
pageIndex: Math.max(0, this.pagination().pageIndex - 1),
|
|
1546
|
+
}), ...(ngDevMode ? [{ debugName: "_tanstackPagination" }] : []));
|
|
1547
|
+
hasVerticalScroll = signal(false, ...(ngDevMode ? [{ debugName: "hasVerticalScroll" }] : []));
|
|
1548
|
+
hasHorizontalScroll = signal(false, ...(ngDevMode ? [{ debugName: "hasHorizontalScroll" }] : []));
|
|
1549
|
+
showSettingsDrawer = signal(false, ...(ngDevMode ? [{ debugName: "showSettingsDrawer" }] : []));
|
|
1550
|
+
showHorizontalBorder = signal(true, ...(ngDevMode ? [{ debugName: "showHorizontalBorder" }] : []));
|
|
1551
|
+
showVerticalBorder = signal(true, ...(ngDevMode ? [{ debugName: "showVerticalBorder" }] : []));
|
|
1552
|
+
showHeaderFooterShadow = signal(true, ...(ngDevMode ? [{ debugName: "showHeaderFooterShadow" }] : []));
|
|
1553
|
+
hasScrollLeft = signal(false, ...(ngDevMode ? [{ debugName: "hasScrollLeft" }] : []));
|
|
1554
|
+
hasScrollRight = signal(false, ...(ngDevMode ? [{ debugName: "hasScrollRight" }] : []));
|
|
1555
|
+
_columnPinVersion = signal(0, ...(ngDevMode ? [{ debugName: "_columnPinVersion" }] : []));
|
|
1556
|
+
_dataForceUpdate = signal(0, ...(ngDevMode ? [{ debugName: "_dataForceUpdate" }] : []));
|
|
1557
|
+
pinnedColumnIds = computed(() => {
|
|
1558
|
+
this._columnPinVersion();
|
|
1559
|
+
return this.columnOrder().filter(id => {
|
|
1560
|
+
if (id === 'expand' || id === 'select') {
|
|
1561
|
+
return false;
|
|
1562
|
+
}
|
|
1563
|
+
const column = this.table.getColumn(id);
|
|
1564
|
+
return column && column.getIsPinned();
|
|
1565
|
+
});
|
|
1566
|
+
}, ...(ngDevMode ? [{ debugName: "pinnedColumnIds" }] : []));
|
|
1567
|
+
pendingVisibleColumns = signal([], ...(ngDevMode ? [{ debugName: "pendingVisibleColumns" }] : []));
|
|
1568
|
+
pendingColumnOrder = signal([], ...(ngDevMode ? [{ debugName: "pendingColumnOrder" }] : []));
|
|
1569
|
+
pendingShowHeaderFooterShadow = signal(true, ...(ngDevMode ? [{ debugName: "pendingShowHeaderFooterShadow" }] : []));
|
|
1570
|
+
hasBodyRowSpan = computed(() => {
|
|
1571
|
+
const columns = this.zConfig().columns ?? [];
|
|
1572
|
+
const checkRowSpan = (col) => {
|
|
1573
|
+
if (isBodyConfig(col.body) && col.body.rowSpan !== undefined) {
|
|
1574
|
+
return true;
|
|
1575
|
+
}
|
|
1576
|
+
if (col.columns?.length) {
|
|
1577
|
+
return col.columns.some(c => checkRowSpan(c));
|
|
1578
|
+
}
|
|
1579
|
+
return false;
|
|
1580
|
+
};
|
|
1581
|
+
return columns.some(c => checkRowSpan(c));
|
|
1582
|
+
}, ...(ngDevMode ? [{ debugName: "hasBodyRowSpan" }] : []));
|
|
1583
|
+
hasSelectColumn = computed(() => {
|
|
1584
|
+
const columns = this.zConfig().columns ?? [];
|
|
1585
|
+
return columns.some(c => c.id === 'select');
|
|
1586
|
+
}, ...(ngDevMode ? [{ debugName: "hasSelectColumn" }] : []));
|
|
1587
|
+
hasExpandColumn = computed(() => {
|
|
1588
|
+
const columns = this.zConfig().columns ?? [];
|
|
1589
|
+
return columns.some(c => c.id === 'expand');
|
|
1590
|
+
}, ...(ngDevMode ? [{ debugName: "hasExpandColumn" }] : []));
|
|
1591
|
+
hasFiltering = computed(() => {
|
|
1592
|
+
const columns = this.zConfig().columns ?? [];
|
|
1593
|
+
const checkFilter = (col) => {
|
|
1594
|
+
const filterConfig = typeof col.filter === 'boolean' ? { enabled: col.filter } : col.filter;
|
|
1595
|
+
if (filterConfig?.enabled) {
|
|
1596
|
+
return true;
|
|
1597
|
+
}
|
|
1598
|
+
if (col.columns?.length) {
|
|
1599
|
+
return col.columns.some(c => checkFilter(c));
|
|
1600
|
+
}
|
|
1601
|
+
return false;
|
|
1602
|
+
};
|
|
1603
|
+
return columns.some(c => checkFilter(c));
|
|
1604
|
+
}, ...(ngDevMode ? [{ debugName: "hasFiltering" }] : []));
|
|
1605
|
+
hasSorting = computed(() => {
|
|
1606
|
+
const columns = this.zConfig().columns ?? [];
|
|
1607
|
+
const checkSorting = (col) => {
|
|
1608
|
+
const sortConfig = typeof col.sort === 'boolean' ? { enabled: col.sort } : col.sort;
|
|
1609
|
+
if (sortConfig?.enabled) {
|
|
1610
|
+
return true;
|
|
1611
|
+
}
|
|
1612
|
+
if (col.columns?.length) {
|
|
1613
|
+
return col.columns.some(c => checkSorting(c));
|
|
1614
|
+
}
|
|
1615
|
+
return false;
|
|
1616
|
+
};
|
|
1617
|
+
return columns.some(c => checkSorting(c));
|
|
1618
|
+
}, ...(ngDevMode ? [{ debugName: "hasSorting" }] : []));
|
|
1619
|
+
_data = computed(() => {
|
|
1620
|
+
this._dataForceUpdate();
|
|
1621
|
+
return this.zConfig().data ?? [];
|
|
1622
|
+
}, ...(ngDevMode ? [{ debugName: "_data" }] : []));
|
|
1623
|
+
_columns = computed(() => {
|
|
1624
|
+
let cols = this.zConfig().columns ?? [];
|
|
1625
|
+
cols = this._filterVisibleColumns(cols);
|
|
1626
|
+
if (this.hasBodyRowSpan()) {
|
|
1627
|
+
cols = cols.filter(c => c.id !== 'expand');
|
|
1628
|
+
}
|
|
1629
|
+
const hasExpandColumn = cols.some(c => c.id === 'expand');
|
|
1630
|
+
const hasSelectColumn = cols.some(c => c.id === 'select');
|
|
1631
|
+
const needsActionsColumn = this.zConfig().enableRowPinning && !hasExpandColumn && !hasSelectColumn && !this.hasBodyRowSpan();
|
|
1632
|
+
if (needsActionsColumn) {
|
|
1633
|
+
cols = [
|
|
1634
|
+
{
|
|
1635
|
+
id: 'actions',
|
|
1636
|
+
header: '',
|
|
1637
|
+
cell: '',
|
|
1638
|
+
size: 30,
|
|
1639
|
+
minSize: 30,
|
|
1640
|
+
maxSize: 30,
|
|
1641
|
+
enableSorting: false,
|
|
1642
|
+
enableFiltering: false,
|
|
1643
|
+
enableResizing: false,
|
|
1644
|
+
enableHiding: false,
|
|
1645
|
+
},
|
|
1646
|
+
...cols,
|
|
1647
|
+
];
|
|
1648
|
+
}
|
|
1649
|
+
return cols.map(c => {
|
|
1650
|
+
const colDef = columnConfigToColumnDef(c);
|
|
1651
|
+
if (colDef.id === 'select') {
|
|
1652
|
+
colDef.size = 50;
|
|
1653
|
+
colDef.minSize = 50;
|
|
1654
|
+
colDef.maxSize = 50;
|
|
1655
|
+
colDef.enableResizing = false;
|
|
1656
|
+
}
|
|
1657
|
+
if (colDef.id === 'expand' || colDef.id === 'actions') {
|
|
1658
|
+
colDef.size = 50;
|
|
1659
|
+
colDef.minSize = 50;
|
|
1660
|
+
colDef.maxSize = 50;
|
|
1661
|
+
colDef.enableResizing = false;
|
|
1662
|
+
}
|
|
1663
|
+
return colDef;
|
|
1664
|
+
});
|
|
1665
|
+
}, ...(ngDevMode ? [{ debugName: "_columns" }] : []));
|
|
1666
|
+
isVirtual = computed(() => {
|
|
1667
|
+
const { virtual } = this.zConfig();
|
|
1668
|
+
if (!virtual) {
|
|
1669
|
+
return false;
|
|
1670
|
+
}
|
|
1671
|
+
if (typeof virtual === 'boolean') {
|
|
1672
|
+
return virtual;
|
|
1673
|
+
}
|
|
1674
|
+
return virtual.enabled;
|
|
1675
|
+
}, ...(ngDevMode ? [{ debugName: "isVirtual" }] : []));
|
|
1676
|
+
_virtualConfig = computed(() => {
|
|
1677
|
+
const { virtual } = this.zConfig();
|
|
1678
|
+
if (!virtual || typeof virtual === 'boolean') {
|
|
1679
|
+
return {
|
|
1680
|
+
enabled: !!virtual,
|
|
1681
|
+
rowHeight: Z_DEFAULT_ROW_HEIGHT,
|
|
1682
|
+
overscan: Z_DEFAULT_VIRTUAL_OVERSCAN,
|
|
1683
|
+
groupSize: Z_DEFAULT_GROUP_SIZE,
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
return {
|
|
1687
|
+
enabled: virtual.enabled,
|
|
1688
|
+
rowHeight: virtual.rowHeight ?? Z_DEFAULT_ROW_HEIGHT,
|
|
1689
|
+
overscan: virtual.overscan ?? Z_DEFAULT_VIRTUAL_OVERSCAN,
|
|
1690
|
+
groupSize: virtual.groupSize ?? Z_DEFAULT_GROUP_SIZE,
|
|
1691
|
+
};
|
|
1692
|
+
}, ...(ngDevMode ? [{ debugName: "_virtualConfig" }] : []));
|
|
1693
|
+
virtualRowHeight = computed(() => this._virtualConfig().rowHeight ?? Z_DEFAULT_ROW_HEIGHT, ...(ngDevMode ? [{ debugName: "virtualRowHeight" }] : []));
|
|
1694
|
+
groupSize = computed(() => this._virtualConfig().groupSize ?? Z_DEFAULT_GROUP_SIZE, ...(ngDevMode ? [{ debugName: "groupSize" }] : []));
|
|
1695
|
+
groupHeight = computed(() => this.groupSize() * this.virtualRowHeight(), ...(ngDevMode ? [{ debugName: "groupHeight" }] : []));
|
|
1696
|
+
dynamicGroups = computed(() => {
|
|
1697
|
+
if (!this.isVirtual()) {
|
|
1698
|
+
return [];
|
|
1699
|
+
}
|
|
1700
|
+
this.columnFilters();
|
|
1701
|
+
this.globalFilter();
|
|
1702
|
+
this.sorting();
|
|
1703
|
+
this.pagination();
|
|
1704
|
+
const rows = untracked(() => this.table.getRowModel().rows);
|
|
1705
|
+
const rowHeight = this.virtualRowHeight();
|
|
1706
|
+
const groups = [];
|
|
1707
|
+
let i = 0;
|
|
1708
|
+
while (i < rows.length) {
|
|
1709
|
+
const startIndex = i;
|
|
1710
|
+
let maxRowSpan = 1;
|
|
1711
|
+
const row = rows[i];
|
|
1712
|
+
const cells = untracked(() => row.getAllCells());
|
|
1713
|
+
for (const cell of cells) {
|
|
1714
|
+
const columnConfig = this._findColumnConfig(cell.column.id);
|
|
1715
|
+
const rowSpanValue = getBodyRowSpan(columnConfig, cell.getContext());
|
|
1716
|
+
if (rowSpanValue && rowSpanValue > maxRowSpan) {
|
|
1717
|
+
maxRowSpan = rowSpanValue;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
const groupRowCount = Math.max(1, maxRowSpan);
|
|
1721
|
+
const endIndex = Math.min(i + groupRowCount - 1, rows.length - 1);
|
|
1722
|
+
groups.push({
|
|
1723
|
+
startIndex,
|
|
1724
|
+
endIndex,
|
|
1725
|
+
rowCount: endIndex - startIndex + 1,
|
|
1726
|
+
height: (endIndex - startIndex + 1) * rowHeight,
|
|
1727
|
+
});
|
|
1728
|
+
i = endIndex + 1;
|
|
1729
|
+
}
|
|
1730
|
+
return groups;
|
|
1731
|
+
}, ...(ngDevMode ? [{ debugName: "dynamicGroups" }] : []));
|
|
1732
|
+
hasFooter = computed(() => {
|
|
1733
|
+
const columns = this.zConfig().columns ?? [];
|
|
1734
|
+
const checkFooter = (col) => {
|
|
1735
|
+
if (col.footer) {
|
|
1736
|
+
return true;
|
|
1737
|
+
}
|
|
1738
|
+
if (col.columns?.length) {
|
|
1739
|
+
return col.columns.some(c => checkFooter(c));
|
|
1740
|
+
}
|
|
1741
|
+
return false;
|
|
1742
|
+
};
|
|
1743
|
+
return columns.some(c => checkFooter(c));
|
|
1744
|
+
}, ...(ngDevMode ? [{ debugName: "hasFooter" }] : []));
|
|
1745
|
+
isEmpty = computed(() => this.table.getRowModel().rows.length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : []));
|
|
1746
|
+
isEmptyData = computed(() => this._data().length === 0, ...(ngDevMode ? [{ debugName: "isEmptyData" }] : []));
|
|
1747
|
+
isNoSearchResults = computed(() => {
|
|
1748
|
+
const isServerMode = this.zConfig().mode === 'server';
|
|
1749
|
+
const hasActiveFilter = this.globalFilter().trim() !== '' || this.columnFilters().length > 0;
|
|
1750
|
+
const noFilteredResults = this.isEmpty();
|
|
1751
|
+
if (isServerMode) {
|
|
1752
|
+
const totalCount = this.zConfig().totalCount ?? 0;
|
|
1753
|
+
const hasPotentialData = totalCount > 0 || hasActiveFilter;
|
|
1754
|
+
return hasPotentialData && noFilteredResults && hasActiveFilter;
|
|
1755
|
+
}
|
|
1756
|
+
const hasSourceData = this._data().length > 0;
|
|
1757
|
+
return hasSourceData && noFilteredResults && hasActiveFilter;
|
|
1758
|
+
}, ...(ngDevMode ? [{ debugName: "isNoSearchResults" }] : []));
|
|
1759
|
+
orderedLeafColumns = computed(() => {
|
|
1760
|
+
const leftCols = this.table.getLeftLeafColumns();
|
|
1761
|
+
const centerCols = this.table.getCenterLeafColumns();
|
|
1762
|
+
const rightCols = this.table.getRightLeafColumns();
|
|
1763
|
+
return [...leftCols, ...centerCols, ...rightCols];
|
|
1764
|
+
}, ...(ngDevMode ? [{ debugName: "orderedLeafColumns" }] : []));
|
|
1765
|
+
orderedHeaderGroups = computed(() => {
|
|
1766
|
+
void this.columnPinning();
|
|
1767
|
+
void this.columnOrder();
|
|
1768
|
+
const leftGroups = this.table.getLeftHeaderGroups();
|
|
1769
|
+
const centerGroups = this.table.getCenterHeaderGroups();
|
|
1770
|
+
const rightGroups = this.table.getRightHeaderGroups();
|
|
1771
|
+
const maxRows = Math.max(leftGroups.length, centerGroups.length, rightGroups.length);
|
|
1772
|
+
const result = [];
|
|
1773
|
+
for (let i = 0; i < maxRows; i++) {
|
|
1774
|
+
const leftHeaders = leftGroups[i]?.headers ?? [];
|
|
1775
|
+
const centerHeaders = centerGroups[i]?.headers ?? [];
|
|
1776
|
+
const rightHeaders = rightGroups[i]?.headers ?? [];
|
|
1777
|
+
result.push({
|
|
1778
|
+
id: `row-${i}`,
|
|
1779
|
+
headers: [...leftHeaders, ...centerHeaders, ...rightHeaders],
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
return result;
|
|
1783
|
+
}, ...(ngDevMode ? [{ debugName: "orderedHeaderGroups" }] : []));
|
|
1784
|
+
orderedFooterGroups = computed(() => {
|
|
1785
|
+
void this.columnPinning();
|
|
1786
|
+
void this.columnOrder();
|
|
1787
|
+
const leftGroups = this.table.getLeftFooterGroups();
|
|
1788
|
+
const centerGroups = this.table.getCenterFooterGroups();
|
|
1789
|
+
const rightGroups = this.table.getRightFooterGroups();
|
|
1790
|
+
const maxRows = Math.max(leftGroups.length, centerGroups.length, rightGroups.length);
|
|
1791
|
+
const result = [];
|
|
1792
|
+
for (let i = 0; i < maxRows; i++) {
|
|
1793
|
+
const leftHeaders = leftGroups[i]?.headers ?? [];
|
|
1794
|
+
const centerHeaders = centerGroups[i]?.headers ?? [];
|
|
1795
|
+
const rightHeaders = rightGroups[i]?.headers ?? [];
|
|
1796
|
+
const depth = leftGroups[i]?.depth ?? centerGroups[i]?.depth ?? rightGroups[i]?.depth ?? i;
|
|
1797
|
+
result.push({
|
|
1798
|
+
id: `footer-row-${i}`,
|
|
1799
|
+
depth,
|
|
1800
|
+
headers: [...leftHeaders, ...centerHeaders, ...rightHeaders],
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
return result;
|
|
1804
|
+
}, ...(ngDevMode ? [{ debugName: "orderedFooterGroups" }] : []));
|
|
1805
|
+
bottomRowsReversed = computed(() => [...this.table.getBottomRows()].reverse(), ...(ngDevMode ? [{ debugName: "bottomRowsReversed" }] : []));
|
|
1806
|
+
totalWidth = computed(() => {
|
|
1807
|
+
const columns = this.table.getAllLeafColumns();
|
|
1808
|
+
return columns.reduce((sum, col) => sum + col.getSize(), 0);
|
|
1809
|
+
}, ...(ngDevMode ? [{ debugName: "totalWidth" }] : []));
|
|
1810
|
+
shouldHeaderShowShadow = computed(() => this.showHeaderFooterShadow() && this.table.getTopRows().length === 0, ...(ngDevMode ? [{ debugName: "shouldHeaderShowShadow" }] : []));
|
|
1811
|
+
shouldFooterShowShadow = computed(() => this.showHeaderFooterShadow() && this.table.getBottomRows().length === 0, ...(ngDevMode ? [{ debugName: "shouldFooterShowShadow" }] : []));
|
|
1812
|
+
dynamicGroupRows = computed(() => {
|
|
1813
|
+
const rows = this.table.getRowModel().rows;
|
|
1814
|
+
const groups = this.dynamicGroups();
|
|
1815
|
+
const size = this.groupSize();
|
|
1816
|
+
const result = [];
|
|
1817
|
+
if (groups.length > 0) {
|
|
1818
|
+
for (const group of groups) {
|
|
1819
|
+
result.push(rows.slice(group.startIndex, group.endIndex + 1));
|
|
1820
|
+
}
|
|
1821
|
+
return result;
|
|
1822
|
+
}
|
|
1823
|
+
const totalGroups = Math.ceil(rows.length / size);
|
|
1824
|
+
for (let i = 0; i < totalGroups; i++) {
|
|
1825
|
+
const startIndex = i * size;
|
|
1826
|
+
const endIndex = Math.min(startIndex + size, rows.length);
|
|
1827
|
+
result.push(rows.slice(startIndex, endIndex));
|
|
1828
|
+
}
|
|
1829
|
+
return result;
|
|
1830
|
+
}, ...(ngDevMode ? [{ debugName: "dynamicGroupRows" }] : []));
|
|
1831
|
+
dynamicGroupHeights = computed(() => {
|
|
1832
|
+
const groups = this.dynamicGroups();
|
|
1833
|
+
const rowHeight = this.virtualRowHeight();
|
|
1834
|
+
const defaultHeight = this.groupSize() * rowHeight;
|
|
1835
|
+
if (groups.length > 0) {
|
|
1836
|
+
return groups.map(group => group.height);
|
|
1837
|
+
}
|
|
1838
|
+
const rows = this.table.getRowModel().rows;
|
|
1839
|
+
const size = this.groupSize();
|
|
1840
|
+
const totalGroups = Math.ceil(rows.length / size);
|
|
1841
|
+
return Array(totalGroups).fill(defaultHeight);
|
|
1842
|
+
}, ...(ngDevMode ? [{ debugName: "dynamicGroupHeights" }] : []));
|
|
1843
|
+
columnSizing = computed(() => this.table.getState().columnSizing, ...(ngDevMode ? [{ debugName: "columnSizing" }] : []));
|
|
1844
|
+
columnSizingInfo = computed(() => this.table.getState().columnSizingInfo, ...(ngDevMode ? [{ debugName: "columnSizingInfo" }] : []));
|
|
1845
|
+
columnSizeVars = computed(() => {
|
|
1846
|
+
void this.columnSizing();
|
|
1847
|
+
void this.columnSizingInfo();
|
|
1848
|
+
void this.columnOrder();
|
|
1849
|
+
void this.columnVisibility();
|
|
1850
|
+
void this.columnPinning();
|
|
1851
|
+
void this._columns();
|
|
1852
|
+
const headers = untracked(() => this.table.getFlatHeaders());
|
|
1853
|
+
const colSizes = {};
|
|
1854
|
+
for (const header of headers) {
|
|
1855
|
+
colSizes[`--header-${header.id}-size`] = header.getSize();
|
|
1856
|
+
colSizes[`--col-${header.column.id}-size`] = header.column.getSize();
|
|
1857
|
+
}
|
|
1858
|
+
return colSizes;
|
|
1859
|
+
}, ...(ngDevMode ? [{ debugName: "columnSizeVars" }] : []));
|
|
1860
|
+
table = createAngularTable(() => {
|
|
1861
|
+
const config = this.zConfig();
|
|
1862
|
+
const isServerMode = config.mode === 'server';
|
|
1863
|
+
const pageSize = this.pagination().pageSize || 10;
|
|
1864
|
+
const pageCount = isServerMode && config.totalRows ? Math.ceil(config.totalRows / pageSize) : undefined;
|
|
1865
|
+
return {
|
|
1866
|
+
data: this._data(),
|
|
1867
|
+
columns: this._columns(),
|
|
1868
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1869
|
+
getExpandedRowModel: this.hasExpandColumn() ? getExpandedRowModel() : undefined,
|
|
1870
|
+
getFilteredRowModel: !isServerMode && this.hasFiltering() ? getFilteredRowModel() : undefined,
|
|
1871
|
+
getSortedRowModel: !isServerMode && this.hasSorting() ? getSortedRowModel() : undefined,
|
|
1872
|
+
getPaginationRowModel: !isServerMode && config.enablePagination ? getPaginationRowModel() : undefined,
|
|
1873
|
+
getFacetedRowModel: !isServerMode && this.hasFiltering() ? getFacetedRowModel() : undefined,
|
|
1874
|
+
getFacetedUniqueValues: !isServerMode && this.hasFiltering() ? getFacetedUniqueValues() : undefined,
|
|
1875
|
+
getFacetedMinMaxValues: !isServerMode && this.hasFiltering() ? getFacetedMinMaxValues() : undefined,
|
|
1876
|
+
manualFiltering: isServerMode,
|
|
1877
|
+
manualSorting: isServerMode,
|
|
1878
|
+
manualPagination: isServerMode,
|
|
1879
|
+
pageCount: pageCount,
|
|
1880
|
+
columnResizeMode: 'onChange',
|
|
1881
|
+
enableRowSelection: this.hasSelectColumn(),
|
|
1882
|
+
enableSubRowSelection: this.hasSelectColumn() && !!config.getSubRows,
|
|
1883
|
+
enableRowPinning: config.enableRowPinning ?? false,
|
|
1884
|
+
enableMultiSort: config.enableMultiSort ?? false,
|
|
1885
|
+
keepPinnedRows: true,
|
|
1886
|
+
getRowId: config.getRowId
|
|
1887
|
+
? (originalRow, index, parent) => config.getRowId?.(originalRow, index, parent?.original, this._data()) ?? `${index}`
|
|
1888
|
+
: (_row, index) => `${index}`,
|
|
1889
|
+
getSubRows: config.getSubRows
|
|
1890
|
+
? (originalRow, index) => config.getSubRows?.(originalRow, index, undefined, this._data())
|
|
1891
|
+
: undefined,
|
|
1892
|
+
getRowCanExpand: config.getRowCanExpand ?? (() => true),
|
|
1893
|
+
state: {
|
|
1894
|
+
columnPinning: this.columnPinning(),
|
|
1895
|
+
columnVisibility: this.columnVisibility(),
|
|
1896
|
+
columnOrder: this.columnOrder(),
|
|
1897
|
+
expanded: this.expanded(),
|
|
1898
|
+
rowSelection: this.rowSelection(),
|
|
1899
|
+
rowPinning: this.rowPinning(),
|
|
1900
|
+
columnFilters: this.columnFilters(),
|
|
1901
|
+
globalFilter: this.globalFilter(),
|
|
1902
|
+
pagination: this._tanstackPagination(),
|
|
1903
|
+
sorting: this.sorting(),
|
|
1904
|
+
},
|
|
1905
|
+
onColumnPinningChange: updater => {
|
|
1906
|
+
const newState = typeof updater === 'function' ? updater(this.columnPinning()) : updater;
|
|
1907
|
+
this.columnPinning.set(newState);
|
|
1908
|
+
},
|
|
1909
|
+
onColumnVisibilityChange: updater => {
|
|
1910
|
+
const newState = typeof updater === 'function' ? updater(this.columnVisibility()) : updater;
|
|
1911
|
+
this.columnVisibility.set(newState);
|
|
1912
|
+
},
|
|
1913
|
+
onColumnOrderChange: updater => {
|
|
1914
|
+
const newState = typeof updater === 'function' ? updater(this.columnOrder()) : updater;
|
|
1915
|
+
this.columnOrder.set(newState);
|
|
1916
|
+
},
|
|
1917
|
+
onExpandedChange: updater => {
|
|
1918
|
+
const newState = typeof updater === 'function' ? updater(this.expanded()) : updater;
|
|
1919
|
+
this.expanded.set(newState);
|
|
1920
|
+
this.zChange.emit({
|
|
1921
|
+
type: 'expand',
|
|
1922
|
+
data: { expanded: newState },
|
|
1923
|
+
});
|
|
1924
|
+
},
|
|
1925
|
+
onRowSelectionChange: updater => {
|
|
1926
|
+
const currentState = this.rowSelection();
|
|
1927
|
+
const newState = typeof updater === 'function' ? updater(currentState) : updater;
|
|
1928
|
+
this._handleRowSelectionWithParents(newState);
|
|
1929
|
+
},
|
|
1930
|
+
onColumnFiltersChange: updater => {
|
|
1931
|
+
const newState = typeof updater === 'function' ? updater(this.columnFilters()) : updater;
|
|
1932
|
+
this._runAsyncStateUpdate(() => {
|
|
1933
|
+
this.columnFilters.set(newState);
|
|
1934
|
+
if (this.zConfig().mode !== 'server') {
|
|
1935
|
+
this.pagination.update(p => ({ ...p, pageIndex: 1 }));
|
|
1936
|
+
}
|
|
1937
|
+
this._emitFilterChangeDebounced(newState, this.globalFilter());
|
|
1938
|
+
});
|
|
1939
|
+
},
|
|
1940
|
+
onGlobalFilterChange: updater => {
|
|
1941
|
+
const newState = typeof updater === 'function' ? updater(this.globalFilter()) : updater;
|
|
1942
|
+
this._runAsyncStateUpdate(() => {
|
|
1943
|
+
this.globalFilter.set(newState);
|
|
1944
|
+
if (this.zConfig().mode !== 'server') {
|
|
1945
|
+
this.pagination.update(p => ({ ...p, pageIndex: 1 }));
|
|
1946
|
+
}
|
|
1947
|
+
this._emitFilterChangeDebounced(this.columnFilters(), newState);
|
|
1948
|
+
});
|
|
1949
|
+
},
|
|
1950
|
+
onPaginationChange: updater => {
|
|
1951
|
+
const newState = typeof updater === 'function' ? updater(this._tanstackPagination()) : updater;
|
|
1952
|
+
const adjustedState = { ...newState, pageIndex: newState.pageIndex + 1 };
|
|
1953
|
+
this.pagination.set(adjustedState);
|
|
1954
|
+
this.zChange.emit({
|
|
1955
|
+
type: 'page',
|
|
1956
|
+
data: { pageIndex: adjustedState.pageIndex, pageSize: adjustedState.pageSize, emitType: 'auto' },
|
|
1957
|
+
});
|
|
1958
|
+
},
|
|
1959
|
+
onSortingChange: updater => {
|
|
1960
|
+
const newState = typeof updater === 'function' ? updater(this.sorting()) : updater;
|
|
1961
|
+
this._runAsyncStateUpdate(() => {
|
|
1962
|
+
this.sorting.set(newState);
|
|
1963
|
+
if (this.zConfig().mode !== 'server') {
|
|
1964
|
+
this.pagination.update(p => ({ ...p, pageIndex: 1 }));
|
|
1965
|
+
}
|
|
1966
|
+
this.zChange.emit({ type: 'sort', data: { sorting: newState } });
|
|
1967
|
+
});
|
|
1968
|
+
},
|
|
1969
|
+
onRowPinningChange: updater => {
|
|
1970
|
+
const newState = typeof updater === 'function' ? updater(this.rowPinning()) : updater;
|
|
1971
|
+
this.rowPinning.set(newState);
|
|
1972
|
+
},
|
|
1973
|
+
meta: {
|
|
1974
|
+
updateData: (rowIndex, columnId, value) => {
|
|
1975
|
+
const row = this.table.getRowModel().rows[rowIndex];
|
|
1976
|
+
if (row) {
|
|
1977
|
+
this.zChange.emit({
|
|
1978
|
+
type: 'cellClick',
|
|
1979
|
+
data: {
|
|
1980
|
+
row: row.original,
|
|
1981
|
+
rowId: row.id,
|
|
1982
|
+
columnId,
|
|
1983
|
+
value,
|
|
1984
|
+
},
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
},
|
|
1988
|
+
},
|
|
1989
|
+
debugTable: false,
|
|
1990
|
+
};
|
|
1991
|
+
});
|
|
1992
|
+
_virtualGroupCount = computed(() => {
|
|
1993
|
+
if (!this.isVirtual()) {
|
|
1994
|
+
return 0;
|
|
1995
|
+
}
|
|
1996
|
+
const totalRows = untracked(() => this.table.getRowModel().rows.length);
|
|
1997
|
+
return Math.ceil(totalRows / this.groupSize());
|
|
1998
|
+
}, ...(ngDevMode ? [{ debugName: "_virtualGroupCount" }] : []));
|
|
1999
|
+
virtualizer = injectVirtualizer(() => {
|
|
2000
|
+
const groups = this.dynamicGroups();
|
|
2001
|
+
const rowHeight = this.virtualRowHeight();
|
|
2002
|
+
return {
|
|
2003
|
+
scrollElement: this.tbodyWrapper()?.nativeElement,
|
|
2004
|
+
count: groups.length > 0 ? groups.length : this._virtualGroupCount(),
|
|
2005
|
+
estimateSize: (index) => {
|
|
2006
|
+
if (groups.length > 0 && groups[index]) {
|
|
2007
|
+
return groups[index].height;
|
|
2008
|
+
}
|
|
2009
|
+
return rowHeight;
|
|
2010
|
+
},
|
|
2011
|
+
overscan: this._virtualConfig().overscan ?? Z_DEFAULT_VIRTUAL_OVERSCAN,
|
|
2012
|
+
};
|
|
2013
|
+
});
|
|
2014
|
+
constructor() {
|
|
2015
|
+
effect(() => {
|
|
2016
|
+
const cfg = this.zConfig();
|
|
2017
|
+
const initial = cfg.initialState;
|
|
2018
|
+
untracked(() => {
|
|
2019
|
+
if (initial) {
|
|
2020
|
+
if (initial.columnPinning) {
|
|
2021
|
+
this.columnPinning.set(initial.columnPinning);
|
|
2022
|
+
}
|
|
2023
|
+
if (initial.columnVisibility) {
|
|
2024
|
+
this.columnVisibility.set(initial.columnVisibility);
|
|
2025
|
+
}
|
|
2026
|
+
if (initial.sorting) {
|
|
2027
|
+
this.sorting.set(initial.sorting);
|
|
2028
|
+
}
|
|
2029
|
+
if (initial.columnFilters) {
|
|
2030
|
+
this.columnFilters.set(initial.columnFilters);
|
|
2031
|
+
}
|
|
2032
|
+
if (initial.globalFilter) {
|
|
2033
|
+
this.globalFilter.set(initial.globalFilter);
|
|
2034
|
+
}
|
|
2035
|
+
if (initial.expanded) {
|
|
2036
|
+
this.expanded.set(initial.expanded);
|
|
2037
|
+
}
|
|
2038
|
+
if (initial.rowSelection) {
|
|
2039
|
+
this.rowSelection.set(initial.rowSelection);
|
|
2040
|
+
}
|
|
2041
|
+
if (initial.rowPinning) {
|
|
2042
|
+
this.rowPinning.set(initial.rowPinning);
|
|
2043
|
+
}
|
|
2044
|
+
if (initial.pagination) {
|
|
2045
|
+
this.pagination.set(initial.pagination);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
this.showHeaderFooterShadow.set(cfg.showHeaderShadow ?? cfg.showFooterShadow ?? true);
|
|
2049
|
+
const cols = cfg.columns ?? [];
|
|
2050
|
+
const leftPinned = [...(initial?.columnPinning?.left ?? [])];
|
|
2051
|
+
const rightPinned = [...(initial?.columnPinning?.right ?? [])];
|
|
2052
|
+
const collectPinnedColumns = (columns) => {
|
|
2053
|
+
for (const col of columns) {
|
|
2054
|
+
if (col.pinned === 'left' && !leftPinned.includes(col.id)) {
|
|
2055
|
+
leftPinned.push(col.id);
|
|
2056
|
+
}
|
|
2057
|
+
if (col.pinned === 'right' && !rightPinned.includes(col.id)) {
|
|
2058
|
+
rightPinned.push(col.id);
|
|
2059
|
+
}
|
|
2060
|
+
if (col.columns) {
|
|
2061
|
+
collectPinnedColumns(col.columns);
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
2065
|
+
collectPinnedColumns(cols);
|
|
2066
|
+
if (leftPinned.length > 0 || rightPinned.length > 0) {
|
|
2067
|
+
this.columnPinning.set({ left: leftPinned, right: rightPinned });
|
|
2068
|
+
}
|
|
2069
|
+
});
|
|
2070
|
+
});
|
|
2071
|
+
effect(() => {
|
|
2072
|
+
const cfg = this.zConfig();
|
|
2073
|
+
if (cfg.enableRowPinning && !this.hasBodyRowSpan()) {
|
|
2074
|
+
const cols = cfg.columns ?? [];
|
|
2075
|
+
const hasSelect = cols.some(c => c.id === 'select');
|
|
2076
|
+
const hasExpand = cols.some(c => c.id === 'expand');
|
|
2077
|
+
untracked(() => {
|
|
2078
|
+
const currentPinning = this.columnPinning();
|
|
2079
|
+
const leftPinned = [...(currentPinning.left || [])];
|
|
2080
|
+
if (hasSelect && !leftPinned.includes('select')) {
|
|
2081
|
+
leftPinned.unshift('select');
|
|
2082
|
+
this.columnPinning.set({ ...currentPinning, left: leftPinned });
|
|
2083
|
+
}
|
|
2084
|
+
if (!hasSelect && !hasExpand && !leftPinned.includes('actions')) {
|
|
2085
|
+
leftPinned.unshift('actions');
|
|
2086
|
+
this.columnPinning.set({ ...currentPinning, left: leftPinned });
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
});
|
|
2091
|
+
afterNextRender(() => {
|
|
2092
|
+
const containerEl = this.tbodyContainer()?.nativeElement;
|
|
2093
|
+
if (containerEl && !this._resizeObserver) {
|
|
2094
|
+
this._resizeObserver = new ResizeObserver(() => {
|
|
2095
|
+
this._checkVerticalScroll();
|
|
2096
|
+
this._checkHorizontalScroll();
|
|
2097
|
+
});
|
|
2098
|
+
this._resizeObserver.observe(containerEl);
|
|
2099
|
+
this._destroyRef.onDestroy(() => {
|
|
2100
|
+
if (this._resizeObserver) {
|
|
2101
|
+
this._resizeObserver.disconnect();
|
|
2102
|
+
this._resizeObserver = null;
|
|
2103
|
+
}
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
});
|
|
2107
|
+
explicitEffect([this.columnFilters, this.globalFilter, this.pagination, this.sorting], () => {
|
|
2108
|
+
this._checkVerticalScroll();
|
|
2109
|
+
this._checkHorizontalScroll();
|
|
2110
|
+
});
|
|
2111
|
+
explicitEffect([this.zLoading, this.isProcessing], () => {
|
|
2112
|
+
const loading = this.zLoading();
|
|
2113
|
+
const processing = this.isProcessing();
|
|
2114
|
+
if (loading || processing) {
|
|
2115
|
+
const wrapperEl = this.tbodyWrapper()?.nativeElement;
|
|
2116
|
+
if (wrapperEl) {
|
|
2117
|
+
this._savedScrollLeft.set(wrapperEl.scrollLeft);
|
|
2118
|
+
}
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
setTimeout(() => {
|
|
2122
|
+
const wrapperEl = this.tbodyWrapper()?.nativeElement;
|
|
2123
|
+
if (wrapperEl) {
|
|
2124
|
+
wrapperEl.scrollTop = 0;
|
|
2125
|
+
wrapperEl.scrollLeft = this._savedScrollLeft();
|
|
2126
|
+
}
|
|
2127
|
+
}, 0);
|
|
2128
|
+
});
|
|
2129
|
+
explicitEffect([
|
|
2130
|
+
this.columnOrder,
|
|
2131
|
+
this.columnSizing,
|
|
2132
|
+
this.columnPinning,
|
|
2133
|
+
this.columnVisibility,
|
|
2134
|
+
this.showHeaderFooterShadow,
|
|
2135
|
+
this.showHorizontalBorder,
|
|
2136
|
+
this.showVerticalBorder,
|
|
2137
|
+
], () => {
|
|
2138
|
+
this._saveConfig();
|
|
2139
|
+
}, { defer: true });
|
|
2140
|
+
}
|
|
2141
|
+
ngAfterViewInit() {
|
|
2142
|
+
this._loadConfig();
|
|
2143
|
+
setTimeout(() => {
|
|
2144
|
+
this._checkVerticalScroll();
|
|
2145
|
+
this._checkHorizontalScroll();
|
|
2146
|
+
}, 100);
|
|
2147
|
+
this.zControl.emit({
|
|
2148
|
+
updateConfig: (config) => {
|
|
2149
|
+
const current = this.zConfig();
|
|
2150
|
+
Object.assign(current, config);
|
|
2151
|
+
},
|
|
2152
|
+
toggleSettings: () => {
|
|
2153
|
+
this.showSettingsDrawer.set(!this.showSettingsDrawer());
|
|
2154
|
+
},
|
|
2155
|
+
resetFilters: () => {
|
|
2156
|
+
this.columnFilters.set([]);
|
|
2157
|
+
this.globalFilter.set('');
|
|
2158
|
+
},
|
|
2159
|
+
resetSorting: () => {
|
|
2160
|
+
this.sorting.set([]);
|
|
2161
|
+
},
|
|
2162
|
+
addItem: (item) => {
|
|
2163
|
+
const current = this.zConfig();
|
|
2164
|
+
current.data = [...current.data, item];
|
|
2165
|
+
this._dataForceUpdate.update(v => v + 1);
|
|
2166
|
+
},
|
|
2167
|
+
updateItem: (id, updates, fieldKey) => {
|
|
2168
|
+
const current = this.zConfig();
|
|
2169
|
+
current.data = current.data.map((row, index) => {
|
|
2170
|
+
const rowId = fieldKey
|
|
2171
|
+
? row[fieldKey]
|
|
2172
|
+
: current.getRowId
|
|
2173
|
+
? current.getRowId(row, index, undefined, current.data)
|
|
2174
|
+
: row['id'];
|
|
2175
|
+
return rowId === id ? { ...row, ...updates } : row;
|
|
2176
|
+
});
|
|
2177
|
+
this._dataForceUpdate.update(v => v + 1);
|
|
2178
|
+
},
|
|
2179
|
+
deleteItem: (id, fieldKey) => {
|
|
2180
|
+
const current = this.zConfig();
|
|
2181
|
+
current.data = current.data.filter((row, index) => {
|
|
2182
|
+
const rowId = fieldKey
|
|
2183
|
+
? row[fieldKey]
|
|
2184
|
+
: current.getRowId
|
|
2185
|
+
? current.getRowId(row, index, undefined, current.data)
|
|
2186
|
+
: row['id'];
|
|
2187
|
+
return rowId !== id;
|
|
2188
|
+
});
|
|
2189
|
+
this._dataForceUpdate.update(v => v + 1);
|
|
2190
|
+
},
|
|
2191
|
+
getItems: () => this.zConfig().data,
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
2194
|
+
_handleRowSelectionWithParents(newState) {
|
|
2195
|
+
const stateRecord = newState;
|
|
2196
|
+
const finalState = { ...stateRecord };
|
|
2197
|
+
const allRows = this.table.getRowModel().rows;
|
|
2198
|
+
allRows.forEach(row => {
|
|
2199
|
+
if (!row.subRows || row.subRows.length === 0) {
|
|
2200
|
+
return;
|
|
2201
|
+
}
|
|
2202
|
+
const allChildrenSelected = row.subRows.every(child => finalState[child.id] === true);
|
|
2203
|
+
if (allChildrenSelected) {
|
|
2204
|
+
finalState[row.id] = true;
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
const someChildrenSelected = row.subRows.some(child => finalState[child.id] === true);
|
|
2208
|
+
if (!someChildrenSelected) {
|
|
2209
|
+
delete finalState[row.id];
|
|
2210
|
+
}
|
|
2211
|
+
});
|
|
2212
|
+
this.rowSelection.set(finalState);
|
|
2213
|
+
this.zChange.emit({
|
|
2214
|
+
type: 'select',
|
|
2215
|
+
data: { selection: finalState },
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
_runAsyncStateUpdate(updateFn) {
|
|
2219
|
+
const isServerMode = this.zConfig().mode === 'server';
|
|
2220
|
+
if (isServerMode) {
|
|
2221
|
+
updateFn();
|
|
2222
|
+
return;
|
|
2223
|
+
}
|
|
2224
|
+
this.isProcessing.set(true);
|
|
2225
|
+
setTimeout(() => {
|
|
2226
|
+
updateFn();
|
|
2227
|
+
this.isProcessing.set(false);
|
|
2228
|
+
}, this.zConfig().debounceTime ?? Z_DEFAULT_DEBOUNCE_TIME);
|
|
2229
|
+
}
|
|
2230
|
+
_emitFilterChangeDebounced(filters, search) {
|
|
2231
|
+
const isServerMode = this.zConfig().mode === 'server';
|
|
2232
|
+
if (isServerMode) {
|
|
2233
|
+
this.zChange.emit({
|
|
2234
|
+
type: 'filter',
|
|
2235
|
+
data: { filters, search },
|
|
2236
|
+
});
|
|
2237
|
+
return;
|
|
2238
|
+
}
|
|
2239
|
+
if (this._filterEmitDebounceTimeout) {
|
|
2240
|
+
clearTimeout(this._filterEmitDebounceTimeout);
|
|
2241
|
+
}
|
|
2242
|
+
this._filterEmitDebounceTimeout = setTimeout(() => {
|
|
2243
|
+
this.zChange.emit({
|
|
2244
|
+
type: 'filter',
|
|
2245
|
+
data: { filters, search },
|
|
2246
|
+
});
|
|
2247
|
+
}, 300);
|
|
2248
|
+
}
|
|
2249
|
+
_checkVerticalScroll() {
|
|
2250
|
+
const tbodyWrapperEl = this.tbodyWrapper()?.nativeElement;
|
|
2251
|
+
if (tbodyWrapperEl) {
|
|
2252
|
+
const hasScroll = tbodyWrapperEl.scrollHeight > tbodyWrapperEl.clientHeight;
|
|
2253
|
+
this.hasVerticalScroll.set(hasScroll);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
_checkHorizontalScroll() {
|
|
2257
|
+
const containerEl = this.tbodyContainer()?.nativeElement;
|
|
2258
|
+
if (containerEl) {
|
|
2259
|
+
const tableWidth = this.table.getTotalSize();
|
|
2260
|
+
const containerWidth = containerEl.clientWidth;
|
|
2261
|
+
const hasScroll = tableWidth > containerWidth;
|
|
2262
|
+
this.hasHorizontalScroll.set(hasScroll);
|
|
2263
|
+
const scrollableEl = this.tbodyWrapper()?.nativeElement;
|
|
2264
|
+
if (scrollableEl) {
|
|
2265
|
+
this._updateScrollShadowState(scrollableEl);
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
_updateScrollShadowState(element) {
|
|
2270
|
+
const { scrollLeft, scrollWidth, clientWidth } = element;
|
|
2271
|
+
const hasScrollLeft = scrollLeft > 0;
|
|
2272
|
+
const hasRightPinned = this.hasRightPinnedColumns();
|
|
2273
|
+
const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1;
|
|
2274
|
+
const hasScrollRight = hasRightPinned && !isAtEnd;
|
|
2275
|
+
this.hasScrollLeft.set(hasScrollLeft);
|
|
2276
|
+
this.hasScrollRight.set(hasScrollRight);
|
|
2277
|
+
}
|
|
2278
|
+
hasRightPinnedColumns() {
|
|
2279
|
+
return this.table.getRightLeafColumns().length > 0;
|
|
2280
|
+
}
|
|
2281
|
+
onTbodyScroll(event) {
|
|
2282
|
+
if (this._isSyncingScroll()) {
|
|
2283
|
+
return;
|
|
2284
|
+
}
|
|
2285
|
+
const target = event.target;
|
|
2286
|
+
this._syncScrollLeft(target.scrollLeft);
|
|
2287
|
+
this._updateScrollShadowState(target);
|
|
2288
|
+
}
|
|
2289
|
+
_syncScrollLeft(scrollLeft) {
|
|
2290
|
+
untracked(() => {
|
|
2291
|
+
this._isSyncingScroll.set(true);
|
|
2292
|
+
});
|
|
2293
|
+
const thead = this.theadWrapper()?.nativeElement;
|
|
2294
|
+
const tbody = this.tbodyWrapper()?.nativeElement;
|
|
2295
|
+
const tfoot = this.tfootWrapper()?.nativeElement;
|
|
2296
|
+
if (thead) {
|
|
2297
|
+
thead.scrollLeft = scrollLeft;
|
|
2298
|
+
}
|
|
2299
|
+
if (tbody) {
|
|
2300
|
+
tbody.scrollLeft = scrollLeft;
|
|
2301
|
+
}
|
|
2302
|
+
if (tfoot) {
|
|
2303
|
+
tfoot.scrollLeft = scrollLeft;
|
|
2304
|
+
}
|
|
2305
|
+
untracked(() => {
|
|
2306
|
+
this._isSyncingScroll.set(false);
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
2309
|
+
handleSort(event, handler) {
|
|
2310
|
+
event.preventDefault();
|
|
2311
|
+
if (this.zConfig().enableMultiSort) {
|
|
2312
|
+
const multiSortEvent = new MouseEvent('click', { shiftKey: true });
|
|
2313
|
+
handler?.(multiSortEvent);
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
handler?.(event);
|
|
2317
|
+
}
|
|
2318
|
+
onColumnDrop(event) {
|
|
2319
|
+
const allColumns = this.table.getAllLeafColumns();
|
|
2320
|
+
const columnIds = allColumns.filter(c => c.id !== 'select' && c.id !== 'expand').map(c => c.id);
|
|
2321
|
+
moveItemInArray(columnIds, event.previousIndex, event.currentIndex);
|
|
2322
|
+
const finalOrder = ['select', 'expand', ...columnIds];
|
|
2323
|
+
this.table.setColumnOrder(finalOrder);
|
|
2324
|
+
}
|
|
2325
|
+
onToggleAllColumns() {
|
|
2326
|
+
this.table.toggleAllColumnsVisible();
|
|
2327
|
+
}
|
|
2328
|
+
onPageChange(event, emitType = 'user') {
|
|
2329
|
+
if (emitType === 'user') {
|
|
2330
|
+
this.isProcessing.set(true);
|
|
2331
|
+
this._runAsyncStateUpdate(() => {
|
|
2332
|
+
this.pagination.set({ pageIndex: event.pageIndex, pageSize: event.pageSize });
|
|
2333
|
+
this.isProcessing.set(false);
|
|
2334
|
+
this.zChange.emit({
|
|
2335
|
+
type: 'page',
|
|
2336
|
+
data: { ...event, emitType },
|
|
2337
|
+
});
|
|
2338
|
+
});
|
|
2339
|
+
return;
|
|
2340
|
+
}
|
|
2341
|
+
this.pagination.set({ pageIndex: event.pageIndex, pageSize: event.pageSize });
|
|
2342
|
+
this.zChange.emit({
|
|
2343
|
+
type: 'page',
|
|
2344
|
+
data: { ...event, emitType },
|
|
2345
|
+
});
|
|
2346
|
+
}
|
|
2347
|
+
onSearchChange(value) {
|
|
2348
|
+
const searchValue = value === null ? '' : String(value);
|
|
2349
|
+
this.globalFilter.set(searchValue);
|
|
2350
|
+
this._runAsyncStateUpdate(() => {
|
|
2351
|
+
this.zChange.emit({
|
|
2352
|
+
type: 'search',
|
|
2353
|
+
data: {
|
|
2354
|
+
search: searchValue,
|
|
2355
|
+
filters: this.columnFilters(),
|
|
2356
|
+
sorting: this.sorting(),
|
|
2357
|
+
pagination: this.pagination(),
|
|
2358
|
+
},
|
|
2359
|
+
});
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2362
|
+
toggleHeaderFooterShadow() {
|
|
2363
|
+
this.showHeaderFooterShadow.update(v => !v);
|
|
2364
|
+
}
|
|
2365
|
+
openSettingsDrawer() {
|
|
2366
|
+
if (this.columnOrder().length === 0) {
|
|
2367
|
+
this.columnOrder.set(this.table.getAllLeafColumns().map(col => col.id));
|
|
2368
|
+
}
|
|
2369
|
+
this.pendingVisibleColumns.set(this.table
|
|
2370
|
+
.getAllLeafColumns()
|
|
2371
|
+
.filter(col => col.getIsVisible())
|
|
2372
|
+
.map(col => col.id));
|
|
2373
|
+
this.pendingColumnOrder.set(this.columnOrder());
|
|
2374
|
+
this.pendingShowHeaderFooterShadow.set(this.showHeaderFooterShadow());
|
|
2375
|
+
this.showSettingsDrawer.set(true);
|
|
2376
|
+
}
|
|
2377
|
+
onPendingColumnDrop(event) {
|
|
2378
|
+
const fullOrder = this.columnOrder();
|
|
2379
|
+
const unpinnedColumns = fullOrder.filter(id => {
|
|
2380
|
+
if (id === 'expand' || id === 'select') {
|
|
2381
|
+
return false;
|
|
2382
|
+
}
|
|
2383
|
+
const column = this.table.getColumn(id);
|
|
2384
|
+
return !column?.getIsPinned();
|
|
2385
|
+
});
|
|
2386
|
+
const movedItem = unpinnedColumns[event.previousIndex];
|
|
2387
|
+
unpinnedColumns.splice(event.previousIndex, 1);
|
|
2388
|
+
unpinnedColumns.splice(event.currentIndex, 0, movedItem);
|
|
2389
|
+
const expandSelect = fullOrder.filter(id => id === 'expand' || id === 'select');
|
|
2390
|
+
const pinnedLeft = fullOrder.filter(id => {
|
|
2391
|
+
const col = this.table.getColumn(id);
|
|
2392
|
+
return col?.getIsPinned() === 'left' && id !== 'expand' && id !== 'select';
|
|
2393
|
+
});
|
|
2394
|
+
const pinnedRight = fullOrder.filter(id => {
|
|
2395
|
+
const col = this.table.getColumn(id);
|
|
2396
|
+
return col?.getIsPinned() === 'right';
|
|
2397
|
+
});
|
|
2398
|
+
const newOrder = [...expandSelect, ...pinnedLeft, ...unpinnedColumns, ...pinnedRight];
|
|
2399
|
+
this.columnOrder.set(newOrder);
|
|
2400
|
+
}
|
|
2401
|
+
onVisibleColumnsChange(values) {
|
|
2402
|
+
if (values.length >= 2) {
|
|
2403
|
+
this.pendingVisibleColumns.set(values.map(v => String(v)));
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
onToggleColumnVisibility(columnId) {
|
|
2407
|
+
const currentVisibility = this.columnVisibility();
|
|
2408
|
+
const isVisible = currentVisibility[columnId] !== false;
|
|
2409
|
+
const allColumnIds = this.columnOrder().filter(id => id !== 'expand' && id !== 'select');
|
|
2410
|
+
const visibleCount = allColumnIds.filter(id => currentVisibility[id] !== false).length;
|
|
2411
|
+
if (isVisible) {
|
|
2412
|
+
if (visibleCount <= 2) {
|
|
2413
|
+
return;
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
if (this._settingsDebounceTimeout) {
|
|
2417
|
+
clearTimeout(this._settingsDebounceTimeout);
|
|
2418
|
+
}
|
|
2419
|
+
this._settingsDebounceTimeout = setTimeout(() => {
|
|
2420
|
+
this.columnVisibility.set({ ...this.columnVisibility(), [columnId]: !isVisible });
|
|
2421
|
+
}, 100);
|
|
2422
|
+
}
|
|
2423
|
+
onToggleColumnPin(columnId, position) {
|
|
2424
|
+
const column = this.table.getColumn(columnId);
|
|
2425
|
+
if (!column) {
|
|
2426
|
+
return;
|
|
2427
|
+
}
|
|
2428
|
+
const currentPin = column.getIsPinned();
|
|
2429
|
+
const newPosition = currentPin === position ? false : position;
|
|
2430
|
+
if (this._settingsDebounceTimeout) {
|
|
2431
|
+
clearTimeout(this._settingsDebounceTimeout);
|
|
2432
|
+
}
|
|
2433
|
+
this._settingsDebounceTimeout = setTimeout(() => {
|
|
2434
|
+
column.pin(newPosition);
|
|
2435
|
+
if (newPosition) {
|
|
2436
|
+
const columnConfig = this._findColumnConfig(columnId);
|
|
2437
|
+
if (columnConfig) {
|
|
2438
|
+
const colSpan = getHeaderColSpan(columnConfig);
|
|
2439
|
+
if (colSpan && colSpan > 1) {
|
|
2440
|
+
const allColumns = this.table.getAllLeafColumns();
|
|
2441
|
+
const currentIdx = allColumns.findIndex(c => c.id === columnId);
|
|
2442
|
+
if (currentIdx !== -1) {
|
|
2443
|
+
for (let i = 1; i < colSpan && currentIdx + i < allColumns.length; i++) {
|
|
2444
|
+
const coveredColumn = allColumns[currentIdx + i];
|
|
2445
|
+
coveredColumn.pin(newPosition);
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
this._columnPinVersion.update(v => v + 1);
|
|
2452
|
+
this._checkHorizontalScroll();
|
|
2453
|
+
}, 100);
|
|
2454
|
+
}
|
|
2455
|
+
handleColumnPin(columnId, position) {
|
|
2456
|
+
const column = this.table.getColumn(columnId);
|
|
2457
|
+
if (!column) {
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
2460
|
+
column.pin(position);
|
|
2461
|
+
if (position) {
|
|
2462
|
+
const columnConfig = this._findColumnConfig(columnId);
|
|
2463
|
+
if (columnConfig) {
|
|
2464
|
+
const colSpan = getHeaderColSpan(columnConfig);
|
|
2465
|
+
if (colSpan && colSpan > 1) {
|
|
2466
|
+
const allColumns = this.table.getAllLeafColumns();
|
|
2467
|
+
const currentIdx = allColumns.findIndex(c => c.id === columnId);
|
|
2468
|
+
if (currentIdx !== -1) {
|
|
2469
|
+
for (let i = 1; i < colSpan && currentIdx + i < allColumns.length; i++) {
|
|
2470
|
+
const coveredColumn = allColumns[currentIdx + i];
|
|
2471
|
+
coveredColumn.pin(position);
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
this._columnPinVersion.update(v => v + 1);
|
|
2478
|
+
this._checkHorizontalScroll();
|
|
2479
|
+
}
|
|
2480
|
+
_saveConfig() {
|
|
2481
|
+
const key = this.zKey();
|
|
2482
|
+
if (!key) {
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
const config = {
|
|
2486
|
+
columnOrder: this.columnOrder(),
|
|
2487
|
+
columnSizing: this.columnSizing(),
|
|
2488
|
+
columnPinning: {
|
|
2489
|
+
left: this.columnPinning().left,
|
|
2490
|
+
right: this.columnPinning().right,
|
|
2491
|
+
},
|
|
2492
|
+
columnVisibility: this.columnVisibility(),
|
|
2493
|
+
showHeaderFooterShadow: this.showHeaderFooterShadow(),
|
|
2494
|
+
showHorizontalBorder: this.showHorizontalBorder(),
|
|
2495
|
+
showVerticalBorder: this.showVerticalBorder(),
|
|
2496
|
+
};
|
|
2497
|
+
try {
|
|
2498
|
+
ZCacheService.set(`table-config-${key}`, config);
|
|
2499
|
+
}
|
|
2500
|
+
catch (error) {
|
|
2501
|
+
console.error('Failed to save table config:', error);
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
_loadConfig() {
|
|
2505
|
+
const key = this.zKey();
|
|
2506
|
+
if (!key) {
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
try {
|
|
2510
|
+
const config = ZCacheService.get(`table-config-${key}`);
|
|
2511
|
+
if (!config) {
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
if (config.columnOrder && config.columnOrder.length > 0) {
|
|
2515
|
+
this.columnOrder.set(config.columnOrder);
|
|
2516
|
+
}
|
|
2517
|
+
if (config.columnSizing) {
|
|
2518
|
+
this.table.setColumnSizing(config.columnSizing);
|
|
2519
|
+
}
|
|
2520
|
+
if (config.columnPinning) {
|
|
2521
|
+
this.columnPinning.set(config.columnPinning);
|
|
2522
|
+
}
|
|
2523
|
+
if (config.columnVisibility) {
|
|
2524
|
+
this.columnVisibility.set(config.columnVisibility);
|
|
2525
|
+
}
|
|
2526
|
+
if (typeof config.showHeaderFooterShadow === 'boolean') {
|
|
2527
|
+
this.showHeaderFooterShadow.set(config.showHeaderFooterShadow);
|
|
2528
|
+
}
|
|
2529
|
+
if (typeof config.showHorizontalBorder === 'boolean') {
|
|
2530
|
+
this.showHorizontalBorder.set(config.showHorizontalBorder);
|
|
2531
|
+
}
|
|
2532
|
+
if (typeof config.showVerticalBorder === 'boolean') {
|
|
2533
|
+
this.showVerticalBorder.set(config.showVerticalBorder);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
catch (error) {
|
|
2537
|
+
console.error('Failed to load table config:', error);
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
_findColumnConfig(columnId) {
|
|
2541
|
+
const findInColumns = (columns) => {
|
|
2542
|
+
for (const col of columns) {
|
|
2543
|
+
if (col.id === columnId) {
|
|
2544
|
+
return col;
|
|
2545
|
+
}
|
|
2546
|
+
if (col.columns) {
|
|
2547
|
+
const found = findInColumns(col.columns);
|
|
2548
|
+
if (found) {
|
|
2549
|
+
return found;
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
return undefined;
|
|
2554
|
+
};
|
|
2555
|
+
return findInColumns(this.zConfig().columns);
|
|
2556
|
+
}
|
|
2557
|
+
_filterVisibleColumns(columns) {
|
|
2558
|
+
return columns
|
|
2559
|
+
.filter(col => {
|
|
2560
|
+
const { visible } = col;
|
|
2561
|
+
if (visible === undefined) {
|
|
2562
|
+
return true;
|
|
2563
|
+
}
|
|
2564
|
+
return typeof visible === 'function' ? visible() : visible;
|
|
2565
|
+
})
|
|
2566
|
+
.map(col => {
|
|
2567
|
+
if (col.columns && col.columns.length > 0) {
|
|
2568
|
+
return {
|
|
2569
|
+
...col,
|
|
2570
|
+
columns: this._filterVisibleColumns(col.columns),
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
return col;
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2577
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZTableComponent, isStandalone: true, selector: "z-table", inputs: { zConfig: { classPropertyName: "zConfig", publicName: "zConfig", isSignal: true, isRequired: false, transformFunction: null }, zLoading: { classPropertyName: "zLoading", publicName: "zLoading", isSignal: true, isRequired: false, transformFunction: null }, zKey: { classPropertyName: "zKey", publicName: "zKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zChange: "zChange", zControl: "zControl" }, host: { classAttribute: "z-table block relative" }, viewQueries: [{ propertyName: "theadWrapper", first: true, predicate: ["theadWrapper"], descendants: true, isSignal: true }, { propertyName: "tbodyContainer", first: true, predicate: ["tbodyContainer"], descendants: true, isSignal: true }, { propertyName: "tbodyWrapper", first: true, predicate: ["tbodyWrapper"], descendants: true, isSignal: true }, { propertyName: "tbodyScrollbar", first: true, predicate: ["tbodyWrapper"], descendants: true, isSignal: true }, { propertyName: "tfootWrapper", first: true, predicate: ["tfootWrapper"], descendants: true, isSignal: true }, { propertyName: "expandedRowTemplate", first: true, predicate: ["expandedRowTemplate"], descendants: true, isSignal: true }], exportAs: ["zTable"], ngImport: i0, template: "<!-- Toolbar: Search & Settings -->\n@if (zConfig().enableSearch || zConfig().enableSettings) {\n <div class=\"z-table-toolbar mb-2 flex items-center justify-between gap-4\">\n <!-- Search -->\n @if (zConfig().enableSearch) {\n <z-input\n class=\"w-64\"\n zSize=\"sm\"\n zPlaceholder=\"Search...\"\n [zSearch]=\"true\"\n [zDebounce]=\"300\"\n (zOnSearch)=\"onSearchChange($event)\" />\n } @else {\n <div></div>\n }\n\n <!-- Settings Button -->\n @if (zConfig().enableSettings) {\n <z-button zType=\"outline\" zSize=\"sm\" zTypeIcon=\"lucideSettings\" (click)=\"openSettingsDrawer()\">Settings</z-button>\n }\n </div>\n}\n\n<div\n class=\"z-table-container shadow-xs\"\n [class.z-hide-horizontal-border]=\"!showHorizontalBorder()\"\n [class.z-hide-vertical-border]=\"!showVerticalBorder()\"\n [style.max-height]=\"zConfig().maxHeight\"\n [style.min-height]=\"zConfig().minHeight\">\n <!-- Shared colgroup template -->\n <ng-template #colGroupTpl>\n <colgroup>\n @for (column of orderedLeafColumns(); track column.id) {\n @if (column.getIsVisible()) {\n <col [style.width]=\"'calc(var(--col-' + column.id + '-size) * 1px)'\" />\n }\n }\n </colgroup>\n </ng-template>\n\n <!-- Header table -->\n <div\n class=\"z-thead-wrapper shadow-xs\"\n [class.z-shadow-header]=\"shouldHeaderShowShadow()\"\n [class.z-scroll-left]=\"hasScrollLeft()\"\n [class.z-scroll-right]=\"hasScrollRight()\"\n #theadWrapper>\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <thead>\n @for (headerGroup of orderedHeaderGroups(); track headerGroup.id) {\n <tr>\n @for (header of headerGroup.headers; track header.id) {\n @let rowSpan = header | zTableSpan: zConfig().columns : 'headerRowSpan';\n @let shouldRender = header | zTableHeaderRender: headerGroup.headers : zConfig().columns;\n @if (rowSpan && shouldRender) {\n <th\n [attr.id]=\"header.column.id\"\n [ngStyle]=\"header.column | zTablePinningStyles: header : 'header' : table : zConfig().columns\"\n [class]=\"header.column.id | zTableColumnConfig: zConfig().columns : 'headerClass'\"\n [style]=\"header.column.id | zTableColumnConfig: zConfig().columns : 'headerStyle'\"\n [class.z-sticky-left]=\"header.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"header.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"header | zTableHeaderPin: 'isLastLeftPinned' : zConfig().columns\"\n [class.z-sticky-right-first]=\"header | zTableHeaderPin: 'isFirstRightPinned' : zConfig().columns\"\n [class.z-sticky-right-last]=\"header | zTableHeaderPin: 'isLastRightPinned' : zConfig().columns\"\n [class.z-at-left-edge]=\"header | zTableCellOffset: orderedLeafColumns()\"\n [class.z-col-select]=\"header.column.id === 'select'\"\n [class.z-col-expand]=\"header.column.id === 'expand'\"\n [class.z-col-actions]=\"header.column.id === 'actions'\"\n [attr.rowspan]=\"rowSpan\"\n [attr.colspan]=\"header | zTableSpan: zConfig().columns : 'headerColSpan'\">\n @if (header.column.id === 'select') {\n <!-- Header Checkbox -->\n <div class=\"flex items-center justify-center\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"table.getIsAllRowsSelected()\"\n [zIndeterminate]=\"table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\"\n (zChange)=\"table.toggleAllRowsSelected()\" />\n </div>\n } @else if (header.column.id === 'expand') {\n <!-- Expand All Button -->\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n (click)=\"table.toggleAllRowsExpanded()\"\n class=\"hover:bg-muted flex h-6 w-6 cursor-pointer items-center justify-center rounded\">\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"transition-transform duration-200\"\n [class.rotate-90]=\"table.getIsSomeRowsExpanded()\" />\n </button>\n </div>\n } @else if (header.column.id === 'actions') {\n <!-- Empty header for actions column -->\n <div class=\"flex items-center justify-center\"></div>\n } @else {\n <!-- Header Content with Sort and Pin -->\n <div class=\"flex w-full items-center gap-1\">\n <!-- Header Text -->\n <div\n class=\"flex min-w-0 flex-1 items-center gap-1.5\"\n [class.justify-center]=\"\n (header.column.id | zTableColumnConfig: zConfig().columns : 'headerAlignClass') ===\n 'text-center'\n \"\n [class.justify-end]=\"\n (header.column.id | zTableColumnConfig: zConfig().columns : 'headerAlignClass') ===\n 'text-right'\n \">\n <ng-container\n *flexRender=\"header.column.columnDef.header; props: header.getContext(); let headerContent\">\n @if (headerContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <ng-container\n *ngTemplateOutlet=\"headerContent; context: { $implicit: header.getContext() }\" />\n } @else if (headerContent | zTableHasIcon) {\n <!-- Icon syntax rendering -->\n <z-table-icon-text\n class=\"min-w-0 truncate\"\n [zText]=\"headerContent\"\n [zTooltip]=\"header.column.id | zTableColumnConfig: zConfig().columns : 'headerTooltip'\" />\n } @else {\n <!-- Default/innerHTML rendering -->\n <span\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (header.column.id | zTableColumnConfig: zConfig().columns : 'headerTooltip') ||\n headerContent\n \"\n [innerHTML]=\"headerContent | zSafeHtml\"></span>\n }\n </ng-container>\n <!-- Sort Icon (clickable) - hidden when table has rowSpan columns -->\n @if (header.column.getCanSort() && !hasBodyRowSpan()) {\n <span\n class=\"shrink-0 cursor-pointer text-gray-500 hover:text-gray-700\"\n (click)=\"handleSort($event, header.column.getToggleSortingHandler())\">\n @if (header.column.getIsSorted() === 'asc') {\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n } @else if (header.column.getIsSorted() === 'desc') {\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n } @else {\n <z-icon zType=\"lucideArrowDownUp\" zSize=\"12\" class=\"opacity-30\" />\n }\n </span>\n }\n </div>\n\n <!-- Column Pin Popover -->\n @if (header.column.getCanPin() && zConfig().enableColumnPinning) {\n <ng-template #colPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (header.column.getIsPinned() !== 'left') {\n <button\n type=\"button\"\n (click)=\"handleColumnPin(header.column.id, 'left'); colPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"12\" />\n <span>Pin left</span>\n </button>\n }\n @if (header.column.getIsPinned() !== 'right') {\n <button\n type=\"button\"\n (click)=\"handleColumnPin(header.column.id, 'right'); colPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"12\" />\n <span>Pin right</span>\n </button>\n }\n @if (header.column.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"handleColumnPin(header.column.id, false); colPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #colPinPopover=\"zPopover\"\n [zPopoverContent]=\"colPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom-right\"\n [zOffset]=\"3\"\n class=\"z-header-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex shrink-0 cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"header.column.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"12\" class=\"rotate-90\" />\n </button>\n }\n </div>\n }\n <!-- Column Filter -->\n @if (header.column.getCanFilter() && hasFiltering()) {\n <div class=\"mt-1\">\n <z-table-filter [zColumn]=\"$any(header.column)\" [zTable]=\"$any(table)\" />\n </div>\n }\n <!-- Column Resizer -->\n @if (\n header.column.id !== 'select' &&\n header.column.id !== 'expand' &&\n zConfig().enableColumnResizing !== false\n ) {\n <div\n class=\"z-resizer\"\n [class.z-is-resizing]=\"header.column.getIsResizing()\"\n [class.z-resizer-left]=\"\n header.column.getIsPinned() === 'right' || header.column.getIsLastColumn()\n \"\n (dblclick)=\"header.column.resetSize()\"\n (mousedown)=\"header.getResizeHandler()($event)\"\n (touchstart)=\"header.getResizeHandler()($event)\"></div>\n }\n </th>\n }\n }\n </tr>\n }\n </thead>\n </table>\n </div>\n\n <!-- Body table -->\n <div\n class=\"z-tbody-wrapper relative\"\n #tbodyContainer\n [class.z-scroll-left]=\"hasScrollLeft()\"\n [class.z-scroll-right]=\"hasScrollRight()\">\n @if (zLoading() || isProcessing()) {\n <!-- Loading State -->\n <div class=\"z-loading-state\">\n <z-loading [zLoading]=\"true\" zSize=\"lg\" zText=\"Loading...\" />\n </div>\n } @else if (isEmpty()) {\n <div class=\"z-empty-state\">\n @if (isNoSearchResults()) {\n <!-- No search results -->\n <z-icon zType=\"lucideSearchX\" zSize=\"40\" class=\"text-muted-foreground/50\" />\n <p class=\"text-muted-foreground text-sm\">No results found</p>\n } @else {\n <!-- Empty data -->\n <z-icon zType=\"lucidePackageOpen\" zSize=\"40\" class=\"text-muted-foreground/50\" />\n <p class=\"text-muted-foreground text-sm\">No data</p>\n }\n </div>\n } @else {\n <ng-scrollbar class=\"z-tbody-scrollbar\" #tbodyWrapper track=\"all\" (scroll)=\"onTbodyScroll($event)\">\n @if (isVirtual()) {\n <!-- Virtual Scroll Mode -->\n <div\n class=\"z-virtual-scroll-inner\"\n [style.height.px]=\"virtualizer.getTotalSize()\"\n [style.min-width.px]=\"table.getTotalSize()\">\n @for (virtualItem of virtualizer.getVirtualItems(); track virtualItem.index) {\n @let groupRows = dynamicGroupRows()[virtualItem.index] || [];\n <div\n class=\"z-virtual-row\"\n [style.height.px]=\"dynamicGroupHeights()[virtualItem.index] ?? groupSize() * virtualRowHeight()\"\n [style.transform]=\"'translateY(' + virtualItem.start + 'px)'\">\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <tbody [class.z-has-vertical-scroll]=\"hasVerticalScroll()\">\n @for (row of groupRows; track row.id) {\n <tr\n z-table-row-hover\n [style.height.px]=\"virtualRowHeight()\"\n [class.z-child-row]=\"row.depth > 0\"\n [class.z-selected]=\"row.getIsSelected()\"\n [class.z-indeterminate-selected]=\"row.getIsSomeSelected() && !row.getIsSelected()\">\n @for (cell of row.getVisibleCells(); track cell.id) {\n @let shouldRenderRowSpan =\n cell | zTableSpan: zConfig().columns : 'shouldRender' : table.getRowModel().rows;\n @let shouldRenderColSpan =\n cell | zTableBodyCellRender: row.getVisibleCells() : zConfig().columns;\n @if (shouldRenderRowSpan && shouldRenderColSpan) {\n <td\n [ngStyle]=\"\n cell.column\n | zTablePinningStyles: cell : 'body' : row.getVisibleCells() : zConfig().columns\n \"\n [class.z-sticky-left]=\"cell.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"cell.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"\n cell.column.getIsPinned() === 'left' && cell.column.getIsLastColumn('left')\n \"\n [class.z-sticky-right-first]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsFirstColumn('right')\n \"\n [class.z-sticky-right-last]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsLastColumn('right')\n \"\n [class.z-at-left-edge]=\"cell | zTableCellOffset: orderedLeafColumns()\"\n [class.z-col-select]=\"cell.column.id === 'select'\"\n [class.z-col-expand]=\"cell.column.id === 'expand'\"\n [attr.rowspan]=\"\n cell | zTableSpan: zConfig().columns : 'cellRowSpan' : table.getRowModel().rows\n \"\n [attr.colspan]=\"cell | zTableSpan: zConfig().columns : 'cellColSpan'\"\n [class]=\"cell | zTableCellConfig: zConfig().columns : 'cellClass'\"\n [style]=\"cell | zTableCellConfig: zConfig().columns : 'cellStyle'\">\n @if (cell.column.id === 'select') {\n <!-- Row Checkbox -->\n <div class=\"flex items-center justify-center\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"cell.row.getIsSelected()\"\n [zIndeterminate]=\"cell.row.getIsSomeSelected() && !cell.row.getIsSelected()\"\n [zDisabled]=\"!cell.row.getCanSelect()\"\n (zChange)=\"cell.row.toggleSelected()\" />\n </div>\n } @else if (cell.column.id === 'expand') {\n <!-- Expand Button -->\n <div class=\"flex items-center justify-center\">\n @if (cell.row.subRows && cell.row.subRows.length > 0) {\n <button\n type=\"button\"\n (click)=\"cell.row.toggleExpanded()\"\n class=\"hover:bg-muted flex h-6 w-6 cursor-pointer items-center justify-center rounded\">\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"transition-transform duration-200\"\n [class.rotate-90]=\"cell.row.getIsExpanded()\" />\n </button>\n }\n </div>\n } @else {\n <ng-container\n *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let cellContent\">\n @if (cellContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <div\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { $implicit: cell.getContext() }\" />\n </div>\n } @else if (cellContent | zTableHasIcon) {\n <!-- Icon syntax rendering -->\n <z-table-icon-text\n [zText]=\"cellContent\"\n [zTooltip]=\"cell | zTableCellConfig: zConfig().columns : 'contentTooltip'\"\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\" />\n } @else {\n <!-- Default/innerHTML rendering -->\n <div\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (cell | zTableCellConfig: zConfig().columns : 'contentTooltip') || cellContent\n \"\n [innerHTML]=\"cellContent | zSafeHtml\"\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\"></div>\n }\n </ng-container>\n }\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n } @else {\n <!-- Normal Scroll Mode -->\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <tbody [class.z-has-vertical-scroll]=\"hasVerticalScroll()\">\n <!-- Row Template -->\n <ng-template #rowTemplate let-row>\n <tr\n z-table-row-hover\n [attr.data-row-id]=\"row.id\"\n [ngStyle]=\"row | zTableRow: table : 'pinningStyles' : virtualRowHeight()\"\n [class.z-child-row]=\"row.depth > 0\"\n [class.z-selected]=\"row.getIsSelected()\"\n [class.z-indeterminate-selected]=\"row.getIsSomeSelected() && !row.getIsSelected()\"\n [class.z-pinned-top]=\"row.getIsPinned() === 'top'\"\n [class.z-pinned-bottom]=\"row.getIsPinned() === 'bottom'\"\n [class.z-shadow-bottom]=\"\n showHeaderFooterShadow() &&\n row.getIsPinned() === 'top' &&\n (row | zTableRow: table : 'isLastTopPinned')\n \"\n [class.z-shadow-top]=\"\n showHeaderFooterShadow() &&\n row.getIsPinned() === 'bottom' &&\n (row | zTableRow: table : 'isFirstBottomPinned')\n \"\n [attr.data-depth]=\"row.depth\">\n @for (cell of row.getVisibleCells(); track cell.id) {\n @let shouldRenderRowSpan =\n cell | zTableSpan: zConfig().columns : 'shouldRender' : table.getRowModel().rows;\n @let shouldRenderColSpan = cell | zTableBodyCellRender: row.getVisibleCells() : zConfig().columns;\n @if (shouldRenderRowSpan && shouldRenderColSpan) {\n <td\n [ngStyle]=\"\n cell.column | zTablePinningStyles: cell : 'body' : row.getVisibleCells() : zConfig().columns\n \"\n [class]=\"cell | zTableCellConfig: zConfig().columns : 'cellClass'\"\n [style]=\"cell | zTableCellConfig: zConfig().columns : 'cellStyle'\"\n [class.z-sticky-left]=\"cell.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"cell.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"\n cell.column.getIsPinned() === 'left' && cell.column.getIsLastColumn('left')\n \"\n [class.z-sticky-right-first]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsFirstColumn('right')\n \"\n [class.z-sticky-right-last]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsLastColumn('right')\n \"\n [class.z-at-left-edge]=\"cell | zTableCellOffset: orderedLeafColumns()\"\n [class.z-col-select]=\"cell.column.id === 'select'\"\n [class.z-col-expand]=\"cell.column.id === 'expand'\"\n [class.z-col-actions]=\"cell.column.id === 'actions'\"\n [attr.rowspan]=\"cell | zTableSpan: zConfig().columns : 'cellRowSpan' : table.getRowModel().rows\"\n [attr.colspan]=\"cell | zTableSpan: zConfig().columns : 'cellColSpan'\">\n @if (cell.column.id === 'select') {\n <!-- Row Checkbox with Pin Button -->\n <div class=\"flex items-center justify-center gap-1\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"cell.row.getIsSelected()\"\n [zIndeterminate]=\"cell.row.getIsSomeSelected() && !cell.row.getIsSelected()\"\n [zDisabled]=\"!cell.row.getCanSelect()\"\n (zChange)=\"cell.row.toggleSelected()\" />\n @if (zConfig().enableRowPinning && cell.row.depth === 0 && !hasBodyRowSpan()) {\n <ng-template #rowPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (cell.row.getIsPinned() !== 'top') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('top'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n <span>Pin top</span>\n </button>\n }\n @if (cell.row.getIsPinned() !== 'bottom') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('bottom'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n <span>Pin bottom</span>\n </button>\n }\n @if (cell.row.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"cell.row.pin(false); rowPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #rowPinPopover=\"zPopover\"\n [zPopoverContent]=\"rowPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom\"\n class=\"z-row-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"cell.row.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"14\" class=\"rotate-90\" />\n </button>\n }\n </div>\n } @else if (cell.column.id === 'expand') {\n <!-- Expand Button with Row Pin Popover -->\n <div class=\"flex items-center justify-center gap-1\">\n @if (cell.row.subRows && cell.row.subRows.length > 0) {\n <button\n type=\"button\"\n (click)=\"cell.row.toggleExpanded()\"\n class=\"hover:bg-muted flex h-6 w-6 cursor-pointer items-center justify-center rounded\">\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"transition-transform duration-200\"\n [class.rotate-90]=\"cell.row.getIsExpanded()\" />\n </button>\n }\n @if (\n zConfig().enableRowPinning &&\n cell.row.depth === 0 &&\n !(cell.row.subRows && cell.row.subRows.length > 0) &&\n !hasBodyRowSpan()\n ) {\n <ng-template #rowPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (cell.row.getIsPinned() !== 'top') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('top'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n <span>Pin top</span>\n </button>\n }\n @if (cell.row.getIsPinned() !== 'bottom') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('bottom'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n <span>Pin bottom</span>\n </button>\n }\n @if (cell.row.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"cell.row.pin(false); rowPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #rowPinPopover=\"zPopover\"\n [zPopoverContent]=\"rowPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom\"\n class=\"z-row-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"cell.row.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"14\" class=\"rotate-90\" />\n </button>\n }\n </div>\n } @else if (cell.column.id === 'actions') {\n <!-- Actions Column - Row Pin Only (for parent rows) -->\n @if (cell.row.depth === 0 && !hasBodyRowSpan()) {\n <div class=\"flex items-center justify-center\">\n <ng-template #rowPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (cell.row.getIsPinned() !== 'top') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('top'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n <span>Pin top</span>\n </button>\n }\n @if (cell.row.getIsPinned() !== 'bottom') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('bottom'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n <span>Pin bottom</span>\n </button>\n }\n @if (cell.row.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"cell.row.pin(false); rowPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #rowPinPopover=\"zPopover\"\n [zPopoverContent]=\"rowPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom\"\n class=\"z-row-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"cell.row.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"14\" class=\"rotate-90\" />\n </button>\n </div>\n }\n } @else {\n <ng-container\n *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let cellContent\">\n @if (cellContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <div\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { $implicit: cell.getContext() }\" />\n </div>\n } @else {\n <!-- Default/innerHTML rendering -->\n <div\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (cell | zTableCellConfig: zConfig().columns : 'contentTooltip') || cellContent\n \"\n [innerHTML]=\"cellContent | zSafeHtml\"\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\"></div>\n }\n </ng-container>\n }\n </td>\n }\n }\n </tr>\n\n <!-- Expanded Row Detail -->\n @if (row.getIsExpanded() && row.depth === 0 && !row.subRows?.length && zConfig().expandedRowTemplate) {\n <tr class=\"z-expanded-row\">\n <td [attr.colspan]=\"row.getVisibleCells().length\" class=\"p-0\">\n <ng-container *ngTemplateOutlet=\"zConfig().expandedRowTemplate!; context: { $implicit: row }\" />\n </td>\n </tr>\n }\n </ng-template>\n\n <!-- Render Top Pinned Rows (hidden when filtered data is empty) -->\n @if (!isEmpty()) {\n @for (row of table.getTopRows(); track row.id) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: row }\" />\n }\n }\n\n <!-- Render Center Rows -->\n @for (row of table.getCenterRows(); track row.id) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: row }\" />\n }\n\n <!-- Render Bottom Pinned Rows (hidden when filtered data is empty) -->\n @if (!isEmpty()) {\n @for (row of bottomRowsReversed(); track row.id) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: row }\" />\n }\n }\n </tbody>\n </table>\n }\n </ng-scrollbar>\n }\n <!-- end @else -->\n </div>\n\n <!-- Footer table -->\n @if (hasFooter()) {\n <div\n class=\"z-tfoot-wrapper\"\n [class.z-shadow-footer]=\"shouldFooterShowShadow()\"\n [class.z-scroll-left]=\"hasScrollLeft()\"\n [class.z-scroll-right]=\"hasScrollRight()\"\n #tfootWrapper>\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <tfoot>\n @for (footerGroup of orderedFooterGroups(); track footerGroup.id) {\n @if (footerGroup | zTableFooterContent: zConfig().columns) {\n <tr>\n @for (footer of footerGroup.headers; track footer.id) {\n @let rowSpan = footer | zTableSpan: zConfig().columns : 'footerRowSpan';\n @let shouldRender = footer | zTableFooterRender: footerGroup.headers : zConfig().columns;\n @if (rowSpan && shouldRender) {\n <th\n [ngStyle]=\"footer.column | zTablePinningStyles: footer : 'header' : table : zConfig().columns\"\n [class]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerClass') +\n ' ' +\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass')\n \"\n [style]=\"footer.column.id | zTableColumnConfig: zConfig().columns : 'footerStyle'\"\n [class.z-sticky-left]=\"footer.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"footer.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"footer | zTableHeaderPin: 'isLastLeftPinned' : zConfig().columns\"\n [class.z-sticky-right-first]=\"footer | zTableHeaderPin: 'isFirstRightPinned' : zConfig().columns\"\n [class.z-sticky-right-last]=\"footer | zTableHeaderPin: 'isLastRightPinned' : zConfig().columns\"\n [class.z-at-left-edge]=\"footer | zTableCellOffset: orderedLeafColumns()\"\n [attr.rowspan]=\"rowSpan\"\n [attr.colspan]=\"footer | zTableSpan: zConfig().columns : 'footerColSpan'\">\n @let configFooterContent =\n footer.column.id | zTableColumnConfig: zConfig().columns : 'footerContent';\n @if (footer.column.columnDef.footer) {\n <ng-container\n *flexRender=\"footer.column.columnDef.footer; props: footer.getContext(); let footerContent\">\n <div\n class=\"flex w-full items-center\"\n [class.justify-center]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-center'\n \"\n [class.justify-end]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-right'\n \">\n @if (footerContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <ng-container\n *ngTemplateOutlet=\"footerContent; context: { $implicit: footer.getContext() }\" />\n } @else if (footerContent | zTableHasIcon) {\n <!-- Icon syntax rendering -->\n <z-table-icon-text\n [zText]=\"footerContent\"\n [zTooltip]=\"\n footer.column.id | zTableColumnConfig: zConfig().columns : 'footerTooltip'\n \" />\n } @else {\n <!-- Default/string rendering -->\n <span\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerTooltip') ||\n footerContent\n \">\n {{ footerContent }}\n </span>\n }\n </div>\n </ng-container>\n } @else if (configFooterContent) {\n <!-- Fallback for group columns without TanStack footer -->\n <div\n class=\"flex w-full items-center\"\n [class.justify-center]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-center'\n \"\n [class.justify-end]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-right'\n \">\n <span\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerTooltip') ||\n $any(configFooterContent)\n \">\n {{ configFooterContent }}\n </span>\n </div>\n }\n </th>\n }\n }\n </tr>\n }\n }\n </tfoot>\n </table>\n </div>\n }\n</div>\n\n<!-- Pagination -->\n@if (zConfig().enablePagination && zConfig().pagination?.enabled !== false) {\n @let totalRows = table.getFilteredRowModel().rows.length;\n @let totalLabel = zConfig().pagination?.totalLabel ?? '{total} total rows';\n <div class=\"mt-4 flex items-center justify-between gap-4\">\n <div class=\"text-sm text-gray-500\">\n {{ totalLabel.replace('{total}', zConfig().totalCount?.toString() || totalRows.toString()) }}\n </div>\n <z-pagination\n [zTotal]=\"zConfig().totalCount ?? totalRows\"\n [(zPageIndex)]=\"pagination().pageIndex\"\n [(zPageSize)]=\"pagination().pageSize\"\n [zPageSizeOptions]=\"zConfig().pagination?.pageSizeOptions ?? [10, 20, 50, 100]\"\n [zShowSizeChanger]=\"zConfig().pagination?.showSizeChanger ?? true\"\n [zShowQuickJumper]=\"zConfig().pagination?.showQuickJumper ?? false\"\n [zShowTotal]=\"false\"\n [zDisabled]=\"zConfig().pagination?.disabled || zLoading() || isProcessing()\"\n (zOnPageChange)=\"onPageChange($event)\" />\n </div>\n}\n\n<!-- Settings Drawer -->\n<z-drawer\n [(zVisible)]=\"showSettingsDrawer\"\n zTitle=\"Table Settings\"\n zPlacement=\"right\"\n zWidth=\"500px\"\n [zShadow]=\"true\"\n [zOkText]=\"null\"\n zCancelText=\"Close\">\n <div class=\"z-table-settings-drawer px-4\">\n <!-- Display Settings -->\n <div class=\"mb-4\">\n <h4 class=\"text-foreground mb-2 text-sm font-semibold\">Display Settings</h4>\n <p class=\"text-muted-foreground mb-3 text-xs\">Customize table appearance</p>\n <div class=\"grid grid-cols-2 gap-x-4 gap-y-3\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"showHorizontalBorder()\"\n zText=\"Horizontal Border\"\n (zChange)=\"showHorizontalBorder.set(!showHorizontalBorder())\" />\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"showVerticalBorder()\"\n zText=\"Vertical Border\"\n (zChange)=\"showVerticalBorder.set(!showVerticalBorder())\" />\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"showHeaderFooterShadow()\"\n zText=\"Header/Footer Shadow\"\n (zChange)=\"showHeaderFooterShadow.set(!showHeaderFooterShadow())\" />\n </div>\n </div>\n\n <!-- Divider -->\n <div class=\"border-border my-4 border-t\"></div>\n\n <!-- Unified Column Settings -->\n @if (zConfig().enableSettings) {\n <div class=\"mb-4\">\n <h4 class=\"text-foreground mb-2 text-sm font-semibold\">Column Settings</h4>\n <p class=\"text-muted-foreground mb-3 text-xs\">Toggle visibility, drag to reorder, and pin columns</p>\n\n <!-- Unpinned Columns (Draggable) -->\n <div cdkDropList (cdkDropListDropped)=\"onPendingColumnDrop($event)\" class=\"space-y-1.5\">\n @for (columnId of columnOrder(); track columnId; let i = $index) {\n @if (columnId !== 'expand' && columnId !== 'select') {\n @let column = table.getColumn(columnId);\n @let isPinned = column?.getIsPinned();\n @let isVisible = columnVisibility()[columnId] !== false;\n @let canPin = column?.getCanPin() !== false && zConfig().enableColumnPinning;\n @if (!isPinned) {\n <div\n cdkDrag\n [cdkDragData]=\"columnId\"\n cdkDragLockAxis=\"y\"\n [cdkDragDisabled]=\"false\"\n class=\"border-border bg-card hover:border-primary flex cursor-move items-center gap-2 rounded border px-2 py-1.5 text-sm transition-all hover:shadow-sm\"\n [class.opacity-60]=\"!isVisible\">\n <!-- Drag Handle -->\n <z-icon zType=\"lucideGripVertical\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n\n <!-- Visibility Checkbox -->\n <input\n type=\"checkbox\"\n [checked]=\"isVisible\"\n (change)=\"onToggleColumnVisibility(columnId)\"\n class=\"border-input h-4 w-4 shrink-0 cursor-pointer rounded\" />\n\n <!-- Column Name -->\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"truncate\" [class.text-muted-foreground]=\"!isVisible\">\n {{ columnId | zTableColumnHeader: zConfig().columns }}\n </span>\n @let parents = columnId | zTableColumnParents: zConfig().columns;\n @if (parents) {\n <span class=\"text-muted-foreground truncate text-[10px]\">({{ parents }})</span>\n }\n </span>\n\n <!-- Pin Buttons -->\n @if (canPin) {\n <div class=\"flex shrink-0 items-center gap-0.5\">\n <button\n type=\"button\"\n (click)=\"onToggleColumnPin(columnId, 'left')\"\n class=\"text-muted-foreground hover:bg-muted cursor-pointer rounded p-1 text-xs transition-colors\"\n title=\"Pin Left\">\n <z-icon zType=\"lucideArrowLeft\" zSize=\"12\" />\n </button>\n <button\n type=\"button\"\n (click)=\"onToggleColumnPin(columnId, 'right')\"\n class=\"text-muted-foreground hover:bg-muted cursor-pointer rounded p-1 text-xs transition-colors\"\n title=\"Pin Right\">\n <z-icon zType=\"lucideArrowRight\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n }\n }\n }\n </div>\n\n <!-- Pinned Columns Section -->\n @if (zConfig().enableColumnPinning) {\n @if (pinnedColumnIds().length > 0) {\n <div class=\"border-border mt-4 border-t pt-4\">\n <h5 class=\"text-muted-foreground mb-2 text-xs font-medium\">Pinned Columns</h5>\n <div class=\"space-y-1.5\">\n @for (columnId of pinnedColumnIds(); track columnId) {\n @let column = table.getColumn(columnId);\n @let isPinned = column?.getIsPinned();\n @let isVisible = columnVisibility()[columnId] !== false;\n <div\n class=\"border-border bg-muted/30 flex items-center gap-2 rounded border px-2 py-1.5 text-sm\"\n [class.opacity-60]=\"!isVisible\">\n <!-- Pin Icon -->\n <z-icon zType=\"lucidePin\" zSize=\"14\" class=\"text-primary shrink-0\" />\n\n <!-- Visibility Checkbox -->\n <!-- Visibility Checkbox -->\n <input\n type=\"checkbox\"\n [checked]=\"isVisible\"\n (change)=\"onToggleColumnVisibility(columnId)\"\n class=\"border-input h-4 w-4 shrink-0 cursor-pointer rounded\" />\n\n <!-- Column Name -->\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"truncate\" [class.text-muted-foreground]=\"!isVisible\">\n {{ columnId | zTableColumnHeader: zConfig().columns }}\n </span>\n @let pinnedParents = columnId | zTableColumnParents: zConfig().columns;\n @if (pinnedParents) {\n <span class=\"text-muted-foreground truncate text-[10px]\">({{ pinnedParents }})</span>\n }\n </span>\n\n <!-- Position Badge -->\n <span class=\"bg-primary/10 text-primary shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium\">\n {{ isPinned === 'left' ? 'LEFT' : 'RIGHT' }}\n </span>\n\n <!-- Unpin Button -->\n <button\n type=\"button\"\n (click)=\"onToggleColumnPin(columnId, isPinned === 'left' ? 'left' : 'right')\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground cursor-pointer rounded p-1 text-xs transition-colors\"\n title=\"Unpin\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n }\n </div>\n</z-drawer>\n", styles: [":host{display:flex;flex-direction:column;height:100%;--scrollbar-track-thickness: 7px;--scrollbar-track-color: transparent;--scrollbar-thumb-shape: 3px}.z-table-container{display:flex;flex-direction:column;position:relative;width:100%;height:100%;overflow:hidden;border-radius:8px;border:thin solid var(--border);background-color:var(--card)}.z-table-container.z-hide-horizontal-border th,.z-table-container.z-hide-horizontal-border td{border-bottom:none!important;border-top:none!important}.z-table-container.z-hide-vertical-border th,.z-table-container.z-hide-vertical-border td{border-left:none!important}table{width:fit-content;min-width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed;font-size:14px}.z-table-toolbar .z-settings-btn{transition:all .15s ease}.z-table-toolbar .z-settings-btn:hover{border-color:var(--muted-foreground)}.z-table-cell-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;-webkit-user-select:text;user-select:text}.z-thead-wrapper{background:var(--muted);overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.z-thead-wrapper::-webkit-scrollbar{display:none}.z-thead-wrapper th{height:auto;padding:8px 12px;text-align:left;vertical-align:middle;font-weight:500;color:var(--foreground);white-space:nowrap;overflow:hidden;background:var(--muted);border-left:thin solid var(--border);border-bottom:thin solid var(--border);-webkit-user-select:none;user-select:none}.z-thead-wrapper th.z-at-left-edge{border-left:none}.z-thead-wrapper th[colspan]{text-align:center;background:var(--muted);font-weight:500;color:var(--foreground)}.z-thead-wrapper.z-shadow-header{box-shadow:0 1px 3px #00000014;position:relative;z-index:15}.z-thead-wrapper.z-shadow-header:where(.dark,.dark *){box-shadow:0 1px 3px #0000004d}.z-tbody-wrapper{flex:1;min-height:200px;display:flex;flex-direction:column}.z-tbody-scrollbar{flex:1;height:100%}.z-empty-state,.z-loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:200px;height:100%;color:var(--muted-foreground);font-size:.875rem;animation:z-fade-in .2s ease-out}.z-tbody-scrollbar,.z-tbody-scrollbar table{animation:z-fade-in .2s ease-out}@keyframes z-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.z-tbody-wrapper tr{transition:background-color .15s ease}.z-tbody-wrapper tr:hover,.z-tbody-wrapper tr:hover td[style*=sticky]{background-color:var(--muted)}.z-tbody-wrapper tr.z-pinned-top td.z-sticky-left,.z-tbody-wrapper tr.z-pinned-top td.z-sticky-right,.z-tbody-wrapper tr.z-pinned-bottom td.z-sticky-left,.z-tbody-wrapper tr.z-pinned-bottom td.z-sticky-right{z-index:3}.z-tbody-wrapper tr.z-shadow-bottom{box-shadow:0 1px 3px #00000014!important;position:relative;z-index:15}.z-tbody-wrapper tr.z-shadow-bottom:where(.dark,.dark *){box-shadow:0 1px 3px #0000004d!important}.z-tbody-wrapper tr.z-shadow-top{box-shadow:0 -2px 4px #0000000d!important;position:relative;z-index:15}.z-tbody-wrapper tr.z-shadow-top:where(.dark,.dark *){box-shadow:0 -2px 4px #0003!important}.z-tbody-wrapper td{padding:8px 12px;height:40px;vertical-align:middle;color:var(--foreground);white-space:nowrap;overflow:hidden;background:var(--card);border-left:thin solid var(--border);border-bottom:thin solid var(--border);box-sizing:border-box}.z-tbody-wrapper td.z-at-left-edge{border-left:none}.z-tbody-wrapper td i{color:var(--muted-foreground);font-style:italic}.z-tbody-wrapper td[rowspan]{vertical-align:top;padding-top:12px}.z-tbody-wrapper td.z-row-hover{background-color:var(--muted)!important}.z-tbody-wrapper td.z-col-select,.z-tbody-wrapper td.z-col-expand,.z-tbody-wrapper td.z-col-actions{padding:8px 4px!important;text-align:center}.z-tbody-wrapper tr.z-child-row td.z-col-select:first-child,.z-tbody-wrapper tr.z-child-row td.z-col-expand:first-child,.z-tbody-wrapper tr.z-child-row td.z-col-actions:first-child{padding-left:0!important}.z-virtual-scroll-inner{position:relative;width:100%}.z-virtual-row{position:absolute;top:0;left:0;width:100%}tr.z-child-row td:first-child{padding-left:12px!important}tbody tr.z-selected,tbody tr.z-selected td{background-color:color-mix(in srgb,var(--primary) 15%,transparent)!important}tbody tr.z-selected:hover,tbody tr.z-selected:hover td{background-color:color-mix(in srgb,var(--primary) 20%,transparent)!important}tbody tr.z-indeterminate-selected,tbody tr.z-indeterminate-selected td{background-color:color-mix(in srgb,var(--primary) 10%,transparent)!important}tbody tr.z-indeterminate-selected:hover,tbody tr.z-indeterminate-selected:hover td{background-color:color-mix(in srgb,var(--primary) 15%,transparent)!important}tbody tr.z-pinned-top td{background-color:var(--card)!important}tbody tr.z-pinned-top:hover{background-color:var(--muted)}tbody tr.z-pinned-top:hover td{background-color:var(--muted)!important}tbody tr.z-pinned-bottom td{background-color:var(--card)!important}tbody tr.z-pinned-bottom:hover{background-color:var(--muted)}tbody tr.z-pinned-bottom:hover td,tr.z-expanded-row td{background-color:var(--muted)!important}thead th{position:relative}thead th .z-resizer{position:absolute;right:0;top:0;height:100%;width:5px;background:#0000001a;cursor:col-resize;-webkit-user-select:none;user-select:none;touch-action:none;opacity:0;transition:opacity .2s ease}thead th .z-resizer:where(.dark,.dark *){background:#ffffff1a}thead th .z-resizer:hover,thead th .z-resizer.z-is-resizing{opacity:1;background:var(--primary);opacity:.5}thead th .z-resizer.z-is-resizing{background:var(--primary);opacity:1}thead th .z-resizer.z-resizer-left{right:auto;left:0}thead th:hover .z-resizer{opacity:1}.z-thead-wrapper th.z-sticky-left,.z-thead-wrapper th.z-sticky-right,.z-tbody-wrapper th.z-sticky-left,.z-tbody-wrapper th.z-sticky-right,.z-tfoot-wrapper th.z-sticky-left,.z-tfoot-wrapper th.z-sticky-right{background-color:var(--muted);z-index:1;transform:translateZ(0);backface-visibility:hidden}.z-thead-wrapper td.z-sticky-left,.z-thead-wrapper td.z-sticky-right,.z-tbody-wrapper td.z-sticky-left,.z-tbody-wrapper td.z-sticky-right,.z-tfoot-wrapper td.z-sticky-left,.z-tfoot-wrapper td.z-sticky-right{background-color:var(--card);z-index:1;transform:translateZ(0);backface-visibility:hidden}.z-thead-wrapper th.z-sticky-left-last,.z-thead-wrapper td.z-sticky-left-last,.z-tbody-wrapper th.z-sticky-left-last,.z-tbody-wrapper td.z-sticky-left-last,.z-tfoot-wrapper th.z-sticky-left-last,.z-tfoot-wrapper td.z-sticky-left-last{position:relative;overflow:visible}.z-thead-wrapper th.z-sticky-left-last:after,.z-thead-wrapper td.z-sticky-left-last:after,.z-tbody-wrapper th.z-sticky-left-last:after,.z-tbody-wrapper td.z-sticky-left-last:after,.z-tfoot-wrapper th.z-sticky-left-last:after,.z-tfoot-wrapper td.z-sticky-left-last:after{content:\"\";position:absolute;top:0;bottom:0;right:-30px;width:30px;pointer-events:none;box-shadow:inset 10px 0 8px -8px #0000001a;z-index:10}.z-thead-wrapper th.z-sticky-left-last:after:where(.dark,.dark *),.z-thead-wrapper td.z-sticky-left-last:after:where(.dark,.dark *),.z-tbody-wrapper th.z-sticky-left-last:after:where(.dark,.dark *),.z-tbody-wrapper td.z-sticky-left-last:after:where(.dark,.dark *),.z-tfoot-wrapper th.z-sticky-left-last:after:where(.dark,.dark *),.z-tfoot-wrapper td.z-sticky-left-last:after:where(.dark,.dark *){box-shadow:inset 10px 0 8px -8px #0000004d}.z-thead-wrapper th.z-sticky-left-last:after,.z-thead-wrapper td.z-sticky-left-last:after,.z-tbody-wrapper th.z-sticky-left-last:after,.z-tbody-wrapper td.z-sticky-left-last:after,.z-tfoot-wrapper th.z-sticky-left-last:after,.z-tfoot-wrapper td.z-sticky-left-last:after{opacity:0;transition:opacity .2s ease}.z-thead-wrapper.z-scroll-left th.z-sticky-left-last:after,.z-thead-wrapper.z-scroll-left td.z-sticky-left-last:after,.z-tbody-wrapper.z-scroll-left th.z-sticky-left-last:after,.z-tbody-wrapper.z-scroll-left td.z-sticky-left-last:after,.z-tfoot-wrapper.z-scroll-left th.z-sticky-left-last:after,.z-tfoot-wrapper.z-scroll-left td.z-sticky-left-last:after{opacity:1}.z-thead-wrapper th.z-sticky-right-first,.z-thead-wrapper td.z-sticky-right-first,.z-tbody-wrapper th.z-sticky-right-first,.z-tbody-wrapper td.z-sticky-right-first,.z-tfoot-wrapper th.z-sticky-right-first,.z-tfoot-wrapper td.z-sticky-right-first{position:relative;overflow:visible}.z-thead-wrapper th.z-sticky-right-first:before,.z-thead-wrapper td.z-sticky-right-first:before,.z-tbody-wrapper th.z-sticky-right-first:before,.z-tbody-wrapper td.z-sticky-right-first:before,.z-tfoot-wrapper th.z-sticky-right-first:before,.z-tfoot-wrapper td.z-sticky-right-first:before{content:\"\";position:absolute;top:0;bottom:0;left:-30px;width:30px;pointer-events:none;box-shadow:inset -10px 0 8px -8px #0000001a;z-index:10;opacity:0;transition:opacity .2s ease}.z-thead-wrapper th.z-sticky-right-first:before:where(.dark,.dark *),.z-thead-wrapper td.z-sticky-right-first:before:where(.dark,.dark *),.z-tbody-wrapper th.z-sticky-right-first:before:where(.dark,.dark *),.z-tbody-wrapper td.z-sticky-right-first:before:where(.dark,.dark *),.z-tfoot-wrapper th.z-sticky-right-first:before:where(.dark,.dark *),.z-tfoot-wrapper td.z-sticky-right-first:before:where(.dark,.dark *){box-shadow:inset -10px 0 8px -8px #0000004d}.z-thead-wrapper.z-scroll-right th.z-sticky-right-first,.z-thead-wrapper.z-scroll-right td.z-sticky-right-first,.z-tbody-wrapper.z-scroll-right th.z-sticky-right-first,.z-tbody-wrapper.z-scroll-right td.z-sticky-right-first,.z-tfoot-wrapper.z-scroll-right th.z-sticky-right-first,.z-tfoot-wrapper.z-scroll-right td.z-sticky-right-first{border-left:none}.z-thead-wrapper.z-scroll-right th.z-sticky-right-first:before,.z-thead-wrapper.z-scroll-right td.z-sticky-right-first:before,.z-tbody-wrapper.z-scroll-right th.z-sticky-right-first:before,.z-tbody-wrapper.z-scroll-right td.z-sticky-right-first:before,.z-tfoot-wrapper.z-scroll-right th.z-sticky-right-first:before,.z-tfoot-wrapper.z-scroll-right td.z-sticky-right-first:before{opacity:1}.z-thead-wrapper th.z-sticky-right-last,.z-tfoot-wrapper th.z-sticky-right-last{position:relative}.z-thead-wrapper th.z-sticky-right-last:after,.z-tfoot-wrapper th.z-sticky-right-last:after{content:\"\";position:absolute;top:0;bottom:0;right:-30px;width:30px;background:var(--muted);pointer-events:none}.z-tfoot-wrapper{background:var(--muted);overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.z-tfoot-wrapper::-webkit-scrollbar{display:none}.z-tfoot-wrapper th{height:auto;padding:8px 12px;text-align:left;vertical-align:middle;font-weight:500;font-size:12px;color:var(--muted-foreground);text-transform:uppercase;letter-spacing:.5px;background:var(--muted);border-left:thin solid var(--border);border-top:thin solid var(--border)}.z-tfoot-wrapper th.z-at-left-edge{border-left:none}.z-tfoot-wrapper.z-shadow-footer{box-shadow:0 -2px 4px #0000000d;position:relative;z-index:15}.z-tfoot-wrapper.z-shadow-footer:where(.dark,.dark *){box-shadow:0 -2px 4px #0003}.z-pin-btn{padding:2px 4px;border-radius:4px;color:var(--muted-foreground);transition:all .15s ease}.z-pin-btn:hover{background-color:var(--muted);color:var(--foreground)}.z-pin-btn.z-pin-btn-active{color:var(--primary);background-color:var(--primary)}.z-pin-btn.z-pin-btn-active:hover{background-color:var(--primary);opacity:.8}.z-row-pin-trigger{opacity:1}.z-row-pin-trigger.text-primary{color:var(--primary)}.z-header-pin-trigger{opacity:1}.z-header-pin-trigger.text-primary{color:var(--primary)}th{overflow:hidden}th .z-header-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cdk-drag-preview{box-shadow:0 4px 12px #00000026;opacity:.9;border-radius:4px;background-color:var(--card);z-index:9999}.cdk-drag-preview:where(.dark,.dark *){box-shadow:0 4px 12px #0006}.cdk-drag-placeholder{opacity:.3;background-color:var(--muted);border:2px dashed var(--primary)}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .cdk-drag:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.z-table-settings-drawer input[type=checkbox]{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:1rem;height:1rem;border:thin solid var(--input);border-radius:.25rem;background-color:var(--background);cursor:pointer;position:relative;transition:all .2s ease}.z-table-settings-drawer input[type=checkbox]:hover{border-color:var(--primary)}.z-table-settings-drawer input[type=checkbox]:checked{background-color:var(--primary);border-color:var(--primary)}.z-table-settings-drawer input[type=checkbox]:checked:after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:.375rem;height:.625rem;border:solid var(--primary-foreground);border-width:0 2px 2px 0;transform:translate(-50%,-60%) rotate(45deg)}.z-table-settings-drawer input[type=checkbox]:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "directive", type: FlexRenderDirective, selector: "[flexRender]", inputs: ["flexRender", "flexRenderProps", "flexRenderInjector"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: ZCheckboxComponent, selector: "z-checkbox", inputs: ["class", "zType", "zSize", "zLabel", "zText", "zDisabled", "zIndeterminate", "zValue", "zOptions", "zOrientation", "zCheckAll", "zCheckAllText", "zChecked", "zGroupValue"], outputs: ["zCheckedChange", "zGroupValueChange", "zChange", "zGroupChange", "zControl"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest"], outputs: ["zOnSearch", "zOnChange", "zControl"], exportAs: ["zInput"] }, { kind: "component", type: ZLoadingComponent, selector: "z-loading", inputs: ["class", "zSpinner", "zSize", "zColor", "zText", "zOverlay", "zOverlayType", "zFullscreen", "zLoading"] }, { kind: "component", type: ZDrawerComponent, selector: "z-drawer", inputs: ["class", "zVisible", "zTitle", "zDescription", "zWidth", "zHeight", "zPlacement", "zClosable", "zMaskClosable", "zHideFooter", "zOkText", "zCancelText", "zOkDestructive", "zOkDisabled", "zLoading", "zOverlay", "zShadow", "zShape", "zContentLoading", "zSkeletonRows"], outputs: ["zOnOk", "zOnCancel", "zVisibleChange"], exportAs: ["zDrawer"] }, { kind: "component", type: ZPaginationComponent, selector: "z-pagination", inputs: ["zPageIndex", "zPageSize", "zTotal", "zPageSizeOptions", "zShowSizeChanger", "zShowQuickJumper", "zShowTotal", "zSimple", "zSize", "zDisabled", "zTotalLabel", "zPerPageLabel", "zGoToLabel"], outputs: ["zPageIndexChange", "zPageSizeChange", "zOnPageChange"] }, { kind: "component", type: ZTableFilterComponent, selector: "z-table-filter", inputs: ["zColumn", "zTable"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zManualClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl"], exportAs: ["zPopover"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTrigger", "zTooltipType", "zTooltipSize", "zClass", "zShowDelay", "zHideDelay", "zArrow", "zDisabled", "zOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "directive", type: ZTableRowHoverDirective, selector: "[z-table-row-hover], [zTableRowHover]", inputs: ["zTableRowHover"] }, { kind: "component", type: ZTableIconTextComponent, selector: "z-table-icon-text", inputs: ["zText", "zTooltip"] }, { kind: "pipe", type: ZTableIsTemplateRefPipe, name: "zTableIsTemplateRef" }, { kind: "pipe", type: ZTableHasIconPipe, name: "zTableHasIcon" }, { kind: "pipe", type: ZTableCellConfigPipe, name: "zTableCellConfig" }, { kind: "pipe", type: ZTableCellOffsetPipe, name: "zTableCellOffset" }, { kind: "pipe", type: ZTableColumnConfigPipe, name: "zTableColumnConfig" }, { kind: "pipe", type: ZTableColumnHeaderPipe, name: "zTableColumnHeader" }, { kind: "pipe", type: ZTableColumnParentsPipe, name: "zTableColumnParents" }, { kind: "pipe", type: ZTableFooterContentPipe, name: "zTableFooterContent" }, { kind: "pipe", type: ZTableHeaderPinPipe, name: "zTableHeaderPin" }, { kind: "pipe", type: ZTablePinningStylesPipe, name: "zTablePinningStyles" }, { kind: "pipe", type: ZTableRowPipe, name: "zTableRow" }, { kind: "pipe", type: ZTableSpanPipe, name: "zTableSpan" }, { kind: "pipe", type: ZTableFooterRenderPipe, name: "zTableFooterRender" }, { kind: "pipe", type: ZTableHeaderRenderPipe, name: "zTableHeaderRender" }, { kind: "pipe", type: ZTableBodyCellRenderPipe, name: "zTableBodyCellRender" }, { kind: "pipe", type: ZSafeHtmlPipe, name: "zSafeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2578
|
+
}
|
|
2579
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableComponent, decorators: [{
|
|
2580
|
+
type: Component,
|
|
2581
|
+
args: [{ selector: 'z-table', imports: [
|
|
2582
|
+
NgClass,
|
|
2583
|
+
NgStyle,
|
|
2584
|
+
NgTemplateOutlet,
|
|
2585
|
+
ScrollingModule,
|
|
2586
|
+
NgScrollbar,
|
|
2587
|
+
FlexRenderDirective,
|
|
2588
|
+
CdkDropList,
|
|
2589
|
+
CdkDrag,
|
|
2590
|
+
ZCheckboxComponent,
|
|
2591
|
+
ZIconComponent,
|
|
2592
|
+
ZInputComponent,
|
|
2593
|
+
ZLoadingComponent,
|
|
2594
|
+
ZDrawerComponent,
|
|
2595
|
+
ZPaginationComponent,
|
|
2596
|
+
ZTableFilterComponent,
|
|
2597
|
+
ZPopoverDirective,
|
|
2598
|
+
ZButtonComponent,
|
|
2599
|
+
ZTooltipDirective,
|
|
2600
|
+
ZTableRowHoverDirective,
|
|
2601
|
+
ZTableIsTemplateRefPipe,
|
|
2602
|
+
ZTableHasIconPipe,
|
|
2603
|
+
ZTableCellConfigPipe,
|
|
2604
|
+
ZTableCellOffsetPipe,
|
|
2605
|
+
ZTableColumnConfigPipe,
|
|
2606
|
+
ZTableColumnHeaderPipe,
|
|
2607
|
+
ZTableColumnParentsPipe,
|
|
2608
|
+
ZTableFooterContentPipe,
|
|
2609
|
+
ZTableHeaderPinPipe,
|
|
2610
|
+
ZTablePinningStylesPipe,
|
|
2611
|
+
ZTableRowPipe,
|
|
2612
|
+
ZTableSpanPipe,
|
|
2613
|
+
ZTableFooterRenderPipe,
|
|
2614
|
+
ZTableHeaderRenderPipe,
|
|
2615
|
+
ZTableBodyCellRenderPipe,
|
|
2616
|
+
ZTableIconTextComponent,
|
|
2617
|
+
ZSafeHtmlPipe,
|
|
2618
|
+
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2619
|
+
class: 'z-table block relative',
|
|
2620
|
+
}, exportAs: 'zTable', template: "<!-- Toolbar: Search & Settings -->\n@if (zConfig().enableSearch || zConfig().enableSettings) {\n <div class=\"z-table-toolbar mb-2 flex items-center justify-between gap-4\">\n <!-- Search -->\n @if (zConfig().enableSearch) {\n <z-input\n class=\"w-64\"\n zSize=\"sm\"\n zPlaceholder=\"Search...\"\n [zSearch]=\"true\"\n [zDebounce]=\"300\"\n (zOnSearch)=\"onSearchChange($event)\" />\n } @else {\n <div></div>\n }\n\n <!-- Settings Button -->\n @if (zConfig().enableSettings) {\n <z-button zType=\"outline\" zSize=\"sm\" zTypeIcon=\"lucideSettings\" (click)=\"openSettingsDrawer()\">Settings</z-button>\n }\n </div>\n}\n\n<div\n class=\"z-table-container shadow-xs\"\n [class.z-hide-horizontal-border]=\"!showHorizontalBorder()\"\n [class.z-hide-vertical-border]=\"!showVerticalBorder()\"\n [style.max-height]=\"zConfig().maxHeight\"\n [style.min-height]=\"zConfig().minHeight\">\n <!-- Shared colgroup template -->\n <ng-template #colGroupTpl>\n <colgroup>\n @for (column of orderedLeafColumns(); track column.id) {\n @if (column.getIsVisible()) {\n <col [style.width]=\"'calc(var(--col-' + column.id + '-size) * 1px)'\" />\n }\n }\n </colgroup>\n </ng-template>\n\n <!-- Header table -->\n <div\n class=\"z-thead-wrapper shadow-xs\"\n [class.z-shadow-header]=\"shouldHeaderShowShadow()\"\n [class.z-scroll-left]=\"hasScrollLeft()\"\n [class.z-scroll-right]=\"hasScrollRight()\"\n #theadWrapper>\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <thead>\n @for (headerGroup of orderedHeaderGroups(); track headerGroup.id) {\n <tr>\n @for (header of headerGroup.headers; track header.id) {\n @let rowSpan = header | zTableSpan: zConfig().columns : 'headerRowSpan';\n @let shouldRender = header | zTableHeaderRender: headerGroup.headers : zConfig().columns;\n @if (rowSpan && shouldRender) {\n <th\n [attr.id]=\"header.column.id\"\n [ngStyle]=\"header.column | zTablePinningStyles: header : 'header' : table : zConfig().columns\"\n [class]=\"header.column.id | zTableColumnConfig: zConfig().columns : 'headerClass'\"\n [style]=\"header.column.id | zTableColumnConfig: zConfig().columns : 'headerStyle'\"\n [class.z-sticky-left]=\"header.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"header.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"header | zTableHeaderPin: 'isLastLeftPinned' : zConfig().columns\"\n [class.z-sticky-right-first]=\"header | zTableHeaderPin: 'isFirstRightPinned' : zConfig().columns\"\n [class.z-sticky-right-last]=\"header | zTableHeaderPin: 'isLastRightPinned' : zConfig().columns\"\n [class.z-at-left-edge]=\"header | zTableCellOffset: orderedLeafColumns()\"\n [class.z-col-select]=\"header.column.id === 'select'\"\n [class.z-col-expand]=\"header.column.id === 'expand'\"\n [class.z-col-actions]=\"header.column.id === 'actions'\"\n [attr.rowspan]=\"rowSpan\"\n [attr.colspan]=\"header | zTableSpan: zConfig().columns : 'headerColSpan'\">\n @if (header.column.id === 'select') {\n <!-- Header Checkbox -->\n <div class=\"flex items-center justify-center\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"table.getIsAllRowsSelected()\"\n [zIndeterminate]=\"table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\"\n (zChange)=\"table.toggleAllRowsSelected()\" />\n </div>\n } @else if (header.column.id === 'expand') {\n <!-- Expand All Button -->\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n (click)=\"table.toggleAllRowsExpanded()\"\n class=\"hover:bg-muted flex h-6 w-6 cursor-pointer items-center justify-center rounded\">\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"transition-transform duration-200\"\n [class.rotate-90]=\"table.getIsSomeRowsExpanded()\" />\n </button>\n </div>\n } @else if (header.column.id === 'actions') {\n <!-- Empty header for actions column -->\n <div class=\"flex items-center justify-center\"></div>\n } @else {\n <!-- Header Content with Sort and Pin -->\n <div class=\"flex w-full items-center gap-1\">\n <!-- Header Text -->\n <div\n class=\"flex min-w-0 flex-1 items-center gap-1.5\"\n [class.justify-center]=\"\n (header.column.id | zTableColumnConfig: zConfig().columns : 'headerAlignClass') ===\n 'text-center'\n \"\n [class.justify-end]=\"\n (header.column.id | zTableColumnConfig: zConfig().columns : 'headerAlignClass') ===\n 'text-right'\n \">\n <ng-container\n *flexRender=\"header.column.columnDef.header; props: header.getContext(); let headerContent\">\n @if (headerContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <ng-container\n *ngTemplateOutlet=\"headerContent; context: { $implicit: header.getContext() }\" />\n } @else if (headerContent | zTableHasIcon) {\n <!-- Icon syntax rendering -->\n <z-table-icon-text\n class=\"min-w-0 truncate\"\n [zText]=\"headerContent\"\n [zTooltip]=\"header.column.id | zTableColumnConfig: zConfig().columns : 'headerTooltip'\" />\n } @else {\n <!-- Default/innerHTML rendering -->\n <span\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (header.column.id | zTableColumnConfig: zConfig().columns : 'headerTooltip') ||\n headerContent\n \"\n [innerHTML]=\"headerContent | zSafeHtml\"></span>\n }\n </ng-container>\n <!-- Sort Icon (clickable) - hidden when table has rowSpan columns -->\n @if (header.column.getCanSort() && !hasBodyRowSpan()) {\n <span\n class=\"shrink-0 cursor-pointer text-gray-500 hover:text-gray-700\"\n (click)=\"handleSort($event, header.column.getToggleSortingHandler())\">\n @if (header.column.getIsSorted() === 'asc') {\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n } @else if (header.column.getIsSorted() === 'desc') {\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n } @else {\n <z-icon zType=\"lucideArrowDownUp\" zSize=\"12\" class=\"opacity-30\" />\n }\n </span>\n }\n </div>\n\n <!-- Column Pin Popover -->\n @if (header.column.getCanPin() && zConfig().enableColumnPinning) {\n <ng-template #colPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (header.column.getIsPinned() !== 'left') {\n <button\n type=\"button\"\n (click)=\"handleColumnPin(header.column.id, 'left'); colPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"12\" />\n <span>Pin left</span>\n </button>\n }\n @if (header.column.getIsPinned() !== 'right') {\n <button\n type=\"button\"\n (click)=\"handleColumnPin(header.column.id, 'right'); colPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"12\" />\n <span>Pin right</span>\n </button>\n }\n @if (header.column.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"handleColumnPin(header.column.id, false); colPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #colPinPopover=\"zPopover\"\n [zPopoverContent]=\"colPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom-right\"\n [zOffset]=\"3\"\n class=\"z-header-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex shrink-0 cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"header.column.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"12\" class=\"rotate-90\" />\n </button>\n }\n </div>\n }\n <!-- Column Filter -->\n @if (header.column.getCanFilter() && hasFiltering()) {\n <div class=\"mt-1\">\n <z-table-filter [zColumn]=\"$any(header.column)\" [zTable]=\"$any(table)\" />\n </div>\n }\n <!-- Column Resizer -->\n @if (\n header.column.id !== 'select' &&\n header.column.id !== 'expand' &&\n zConfig().enableColumnResizing !== false\n ) {\n <div\n class=\"z-resizer\"\n [class.z-is-resizing]=\"header.column.getIsResizing()\"\n [class.z-resizer-left]=\"\n header.column.getIsPinned() === 'right' || header.column.getIsLastColumn()\n \"\n (dblclick)=\"header.column.resetSize()\"\n (mousedown)=\"header.getResizeHandler()($event)\"\n (touchstart)=\"header.getResizeHandler()($event)\"></div>\n }\n </th>\n }\n }\n </tr>\n }\n </thead>\n </table>\n </div>\n\n <!-- Body table -->\n <div\n class=\"z-tbody-wrapper relative\"\n #tbodyContainer\n [class.z-scroll-left]=\"hasScrollLeft()\"\n [class.z-scroll-right]=\"hasScrollRight()\">\n @if (zLoading() || isProcessing()) {\n <!-- Loading State -->\n <div class=\"z-loading-state\">\n <z-loading [zLoading]=\"true\" zSize=\"lg\" zText=\"Loading...\" />\n </div>\n } @else if (isEmpty()) {\n <div class=\"z-empty-state\">\n @if (isNoSearchResults()) {\n <!-- No search results -->\n <z-icon zType=\"lucideSearchX\" zSize=\"40\" class=\"text-muted-foreground/50\" />\n <p class=\"text-muted-foreground text-sm\">No results found</p>\n } @else {\n <!-- Empty data -->\n <z-icon zType=\"lucidePackageOpen\" zSize=\"40\" class=\"text-muted-foreground/50\" />\n <p class=\"text-muted-foreground text-sm\">No data</p>\n }\n </div>\n } @else {\n <ng-scrollbar class=\"z-tbody-scrollbar\" #tbodyWrapper track=\"all\" (scroll)=\"onTbodyScroll($event)\">\n @if (isVirtual()) {\n <!-- Virtual Scroll Mode -->\n <div\n class=\"z-virtual-scroll-inner\"\n [style.height.px]=\"virtualizer.getTotalSize()\"\n [style.min-width.px]=\"table.getTotalSize()\">\n @for (virtualItem of virtualizer.getVirtualItems(); track virtualItem.index) {\n @let groupRows = dynamicGroupRows()[virtualItem.index] || [];\n <div\n class=\"z-virtual-row\"\n [style.height.px]=\"dynamicGroupHeights()[virtualItem.index] ?? groupSize() * virtualRowHeight()\"\n [style.transform]=\"'translateY(' + virtualItem.start + 'px)'\">\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <tbody [class.z-has-vertical-scroll]=\"hasVerticalScroll()\">\n @for (row of groupRows; track row.id) {\n <tr\n z-table-row-hover\n [style.height.px]=\"virtualRowHeight()\"\n [class.z-child-row]=\"row.depth > 0\"\n [class.z-selected]=\"row.getIsSelected()\"\n [class.z-indeterminate-selected]=\"row.getIsSomeSelected() && !row.getIsSelected()\">\n @for (cell of row.getVisibleCells(); track cell.id) {\n @let shouldRenderRowSpan =\n cell | zTableSpan: zConfig().columns : 'shouldRender' : table.getRowModel().rows;\n @let shouldRenderColSpan =\n cell | zTableBodyCellRender: row.getVisibleCells() : zConfig().columns;\n @if (shouldRenderRowSpan && shouldRenderColSpan) {\n <td\n [ngStyle]=\"\n cell.column\n | zTablePinningStyles: cell : 'body' : row.getVisibleCells() : zConfig().columns\n \"\n [class.z-sticky-left]=\"cell.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"cell.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"\n cell.column.getIsPinned() === 'left' && cell.column.getIsLastColumn('left')\n \"\n [class.z-sticky-right-first]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsFirstColumn('right')\n \"\n [class.z-sticky-right-last]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsLastColumn('right')\n \"\n [class.z-at-left-edge]=\"cell | zTableCellOffset: orderedLeafColumns()\"\n [class.z-col-select]=\"cell.column.id === 'select'\"\n [class.z-col-expand]=\"cell.column.id === 'expand'\"\n [attr.rowspan]=\"\n cell | zTableSpan: zConfig().columns : 'cellRowSpan' : table.getRowModel().rows\n \"\n [attr.colspan]=\"cell | zTableSpan: zConfig().columns : 'cellColSpan'\"\n [class]=\"cell | zTableCellConfig: zConfig().columns : 'cellClass'\"\n [style]=\"cell | zTableCellConfig: zConfig().columns : 'cellStyle'\">\n @if (cell.column.id === 'select') {\n <!-- Row Checkbox -->\n <div class=\"flex items-center justify-center\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"cell.row.getIsSelected()\"\n [zIndeterminate]=\"cell.row.getIsSomeSelected() && !cell.row.getIsSelected()\"\n [zDisabled]=\"!cell.row.getCanSelect()\"\n (zChange)=\"cell.row.toggleSelected()\" />\n </div>\n } @else if (cell.column.id === 'expand') {\n <!-- Expand Button -->\n <div class=\"flex items-center justify-center\">\n @if (cell.row.subRows && cell.row.subRows.length > 0) {\n <button\n type=\"button\"\n (click)=\"cell.row.toggleExpanded()\"\n class=\"hover:bg-muted flex h-6 w-6 cursor-pointer items-center justify-center rounded\">\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"transition-transform duration-200\"\n [class.rotate-90]=\"cell.row.getIsExpanded()\" />\n </button>\n }\n </div>\n } @else {\n <ng-container\n *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let cellContent\">\n @if (cellContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <div\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { $implicit: cell.getContext() }\" />\n </div>\n } @else if (cellContent | zTableHasIcon) {\n <!-- Icon syntax rendering -->\n <z-table-icon-text\n [zText]=\"cellContent\"\n [zTooltip]=\"cell | zTableCellConfig: zConfig().columns : 'contentTooltip'\"\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\" />\n } @else {\n <!-- Default/innerHTML rendering -->\n <div\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (cell | zTableCellConfig: zConfig().columns : 'contentTooltip') || cellContent\n \"\n [innerHTML]=\"cellContent | zSafeHtml\"\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\"></div>\n }\n </ng-container>\n }\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n } @else {\n <!-- Normal Scroll Mode -->\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <tbody [class.z-has-vertical-scroll]=\"hasVerticalScroll()\">\n <!-- Row Template -->\n <ng-template #rowTemplate let-row>\n <tr\n z-table-row-hover\n [attr.data-row-id]=\"row.id\"\n [ngStyle]=\"row | zTableRow: table : 'pinningStyles' : virtualRowHeight()\"\n [class.z-child-row]=\"row.depth > 0\"\n [class.z-selected]=\"row.getIsSelected()\"\n [class.z-indeterminate-selected]=\"row.getIsSomeSelected() && !row.getIsSelected()\"\n [class.z-pinned-top]=\"row.getIsPinned() === 'top'\"\n [class.z-pinned-bottom]=\"row.getIsPinned() === 'bottom'\"\n [class.z-shadow-bottom]=\"\n showHeaderFooterShadow() &&\n row.getIsPinned() === 'top' &&\n (row | zTableRow: table : 'isLastTopPinned')\n \"\n [class.z-shadow-top]=\"\n showHeaderFooterShadow() &&\n row.getIsPinned() === 'bottom' &&\n (row | zTableRow: table : 'isFirstBottomPinned')\n \"\n [attr.data-depth]=\"row.depth\">\n @for (cell of row.getVisibleCells(); track cell.id) {\n @let shouldRenderRowSpan =\n cell | zTableSpan: zConfig().columns : 'shouldRender' : table.getRowModel().rows;\n @let shouldRenderColSpan = cell | zTableBodyCellRender: row.getVisibleCells() : zConfig().columns;\n @if (shouldRenderRowSpan && shouldRenderColSpan) {\n <td\n [ngStyle]=\"\n cell.column | zTablePinningStyles: cell : 'body' : row.getVisibleCells() : zConfig().columns\n \"\n [class]=\"cell | zTableCellConfig: zConfig().columns : 'cellClass'\"\n [style]=\"cell | zTableCellConfig: zConfig().columns : 'cellStyle'\"\n [class.z-sticky-left]=\"cell.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"cell.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"\n cell.column.getIsPinned() === 'left' && cell.column.getIsLastColumn('left')\n \"\n [class.z-sticky-right-first]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsFirstColumn('right')\n \"\n [class.z-sticky-right-last]=\"\n cell.column.getIsPinned() === 'right' && cell.column.getIsLastColumn('right')\n \"\n [class.z-at-left-edge]=\"cell | zTableCellOffset: orderedLeafColumns()\"\n [class.z-col-select]=\"cell.column.id === 'select'\"\n [class.z-col-expand]=\"cell.column.id === 'expand'\"\n [class.z-col-actions]=\"cell.column.id === 'actions'\"\n [attr.rowspan]=\"cell | zTableSpan: zConfig().columns : 'cellRowSpan' : table.getRowModel().rows\"\n [attr.colspan]=\"cell | zTableSpan: zConfig().columns : 'cellColSpan'\">\n @if (cell.column.id === 'select') {\n <!-- Row Checkbox with Pin Button -->\n <div class=\"flex items-center justify-center gap-1\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"cell.row.getIsSelected()\"\n [zIndeterminate]=\"cell.row.getIsSomeSelected() && !cell.row.getIsSelected()\"\n [zDisabled]=\"!cell.row.getCanSelect()\"\n (zChange)=\"cell.row.toggleSelected()\" />\n @if (zConfig().enableRowPinning && cell.row.depth === 0 && !hasBodyRowSpan()) {\n <ng-template #rowPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (cell.row.getIsPinned() !== 'top') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('top'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n <span>Pin top</span>\n </button>\n }\n @if (cell.row.getIsPinned() !== 'bottom') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('bottom'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n <span>Pin bottom</span>\n </button>\n }\n @if (cell.row.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"cell.row.pin(false); rowPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #rowPinPopover=\"zPopover\"\n [zPopoverContent]=\"rowPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom\"\n class=\"z-row-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"cell.row.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"14\" class=\"rotate-90\" />\n </button>\n }\n </div>\n } @else if (cell.column.id === 'expand') {\n <!-- Expand Button with Row Pin Popover -->\n <div class=\"flex items-center justify-center gap-1\">\n @if (cell.row.subRows && cell.row.subRows.length > 0) {\n <button\n type=\"button\"\n (click)=\"cell.row.toggleExpanded()\"\n class=\"hover:bg-muted flex h-6 w-6 cursor-pointer items-center justify-center rounded\">\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"transition-transform duration-200\"\n [class.rotate-90]=\"cell.row.getIsExpanded()\" />\n </button>\n }\n @if (\n zConfig().enableRowPinning &&\n cell.row.depth === 0 &&\n !(cell.row.subRows && cell.row.subRows.length > 0) &&\n !hasBodyRowSpan()\n ) {\n <ng-template #rowPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (cell.row.getIsPinned() !== 'top') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('top'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n <span>Pin top</span>\n </button>\n }\n @if (cell.row.getIsPinned() !== 'bottom') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('bottom'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n <span>Pin bottom</span>\n </button>\n }\n @if (cell.row.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"cell.row.pin(false); rowPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #rowPinPopover=\"zPopover\"\n [zPopoverContent]=\"rowPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom\"\n class=\"z-row-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"cell.row.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"14\" class=\"rotate-90\" />\n </button>\n }\n </div>\n } @else if (cell.column.id === 'actions') {\n <!-- Actions Column - Row Pin Only (for parent rows) -->\n @if (cell.row.depth === 0 && !hasBodyRowSpan()) {\n <div class=\"flex items-center justify-center\">\n <ng-template #rowPinPopoverContent>\n <div class=\"flex flex-col gap-0.5 p-0.5\">\n @if (cell.row.getIsPinned() !== 'top') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('top'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowUp\" zSize=\"12\" />\n <span>Pin top</span>\n </button>\n }\n @if (cell.row.getIsPinned() !== 'bottom') {\n <button\n type=\"button\"\n (click)=\"cell.row.pin('bottom'); rowPinPopover.hideImmediate()\"\n class=\"text-foreground hover:bg-muted flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideArrowDown\" zSize=\"12\" />\n <span>Pin bottom</span>\n </button>\n }\n @if (cell.row.getIsPinned()) {\n <button\n type=\"button\"\n (click)=\"cell.row.pin(false); rowPinPopover.hideImmediate()\"\n class=\"text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n <span>Unpin</span>\n </button>\n }\n </div>\n </ng-template>\n <button\n type=\"button\"\n z-popover\n #rowPinPopover=\"zPopover\"\n [zPopoverContent]=\"rowPinPopoverContent\"\n zTrigger=\"click\"\n zPosition=\"bottom\"\n class=\"z-row-pin-trigger text-muted-foreground hover:bg-muted hover:text-foreground flex cursor-pointer items-center justify-center rounded p-1\"\n [class.text-primary]=\"cell.row.getIsPinned()\">\n <z-icon zType=\"lucideEllipsis\" zSize=\"14\" class=\"rotate-90\" />\n </button>\n </div>\n }\n } @else {\n <ng-container\n *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let cellContent\">\n @if (cellContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <div\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { $implicit: cell.getContext() }\" />\n </div>\n } @else {\n <!-- Default/innerHTML rendering -->\n <div\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (cell | zTableCellConfig: zConfig().columns : 'contentTooltip') || cellContent\n \"\n [innerHTML]=\"cellContent | zSafeHtml\"\n [ngClass]=\"cell | zTableCellConfig: zConfig().columns : 'contentClass'\"\n [ngStyle]=\"cell | zTableCellConfig: zConfig().columns : 'contentStyle'\"></div>\n }\n </ng-container>\n }\n </td>\n }\n }\n </tr>\n\n <!-- Expanded Row Detail -->\n @if (row.getIsExpanded() && row.depth === 0 && !row.subRows?.length && zConfig().expandedRowTemplate) {\n <tr class=\"z-expanded-row\">\n <td [attr.colspan]=\"row.getVisibleCells().length\" class=\"p-0\">\n <ng-container *ngTemplateOutlet=\"zConfig().expandedRowTemplate!; context: { $implicit: row }\" />\n </td>\n </tr>\n }\n </ng-template>\n\n <!-- Render Top Pinned Rows (hidden when filtered data is empty) -->\n @if (!isEmpty()) {\n @for (row of table.getTopRows(); track row.id) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: row }\" />\n }\n }\n\n <!-- Render Center Rows -->\n @for (row of table.getCenterRows(); track row.id) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: row }\" />\n }\n\n <!-- Render Bottom Pinned Rows (hidden when filtered data is empty) -->\n @if (!isEmpty()) {\n @for (row of bottomRowsReversed(); track row.id) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: row }\" />\n }\n }\n </tbody>\n </table>\n }\n </ng-scrollbar>\n }\n <!-- end @else -->\n </div>\n\n <!-- Footer table -->\n @if (hasFooter()) {\n <div\n class=\"z-tfoot-wrapper\"\n [class.z-shadow-footer]=\"shouldFooterShowShadow()\"\n [class.z-scroll-left]=\"hasScrollLeft()\"\n [class.z-scroll-right]=\"hasScrollRight()\"\n #tfootWrapper>\n <table [ngStyle]=\"columnSizeVars()\" [style.width.px]=\"table.getTotalSize()\">\n <ng-container *ngTemplateOutlet=\"colGroupTpl\" />\n <tfoot>\n @for (footerGroup of orderedFooterGroups(); track footerGroup.id) {\n @if (footerGroup | zTableFooterContent: zConfig().columns) {\n <tr>\n @for (footer of footerGroup.headers; track footer.id) {\n @let rowSpan = footer | zTableSpan: zConfig().columns : 'footerRowSpan';\n @let shouldRender = footer | zTableFooterRender: footerGroup.headers : zConfig().columns;\n @if (rowSpan && shouldRender) {\n <th\n [ngStyle]=\"footer.column | zTablePinningStyles: footer : 'header' : table : zConfig().columns\"\n [class]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerClass') +\n ' ' +\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass')\n \"\n [style]=\"footer.column.id | zTableColumnConfig: zConfig().columns : 'footerStyle'\"\n [class.z-sticky-left]=\"footer.column.getIsPinned() === 'left'\"\n [class.z-sticky-right]=\"footer.column.getIsPinned() === 'right'\"\n [class.z-sticky-left-last]=\"footer | zTableHeaderPin: 'isLastLeftPinned' : zConfig().columns\"\n [class.z-sticky-right-first]=\"footer | zTableHeaderPin: 'isFirstRightPinned' : zConfig().columns\"\n [class.z-sticky-right-last]=\"footer | zTableHeaderPin: 'isLastRightPinned' : zConfig().columns\"\n [class.z-at-left-edge]=\"footer | zTableCellOffset: orderedLeafColumns()\"\n [attr.rowspan]=\"rowSpan\"\n [attr.colspan]=\"footer | zTableSpan: zConfig().columns : 'footerColSpan'\">\n @let configFooterContent =\n footer.column.id | zTableColumnConfig: zConfig().columns : 'footerContent';\n @if (footer.column.columnDef.footer) {\n <ng-container\n *flexRender=\"footer.column.columnDef.footer; props: footer.getContext(); let footerContent\">\n <div\n class=\"flex w-full items-center\"\n [class.justify-center]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-center'\n \"\n [class.justify-end]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-right'\n \">\n @if (footerContent | zTableIsTemplateRef) {\n <!-- TemplateRef rendering -->\n <ng-container\n *ngTemplateOutlet=\"footerContent; context: { $implicit: footer.getContext() }\" />\n } @else if (footerContent | zTableHasIcon) {\n <!-- Icon syntax rendering -->\n <z-table-icon-text\n [zText]=\"footerContent\"\n [zTooltip]=\"\n footer.column.id | zTableColumnConfig: zConfig().columns : 'footerTooltip'\n \" />\n } @else {\n <!-- Default/string rendering -->\n <span\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerTooltip') ||\n footerContent\n \">\n {{ footerContent }}\n </span>\n }\n </div>\n </ng-container>\n } @else if (configFooterContent) {\n <!-- Fallback for group columns without TanStack footer -->\n <div\n class=\"flex w-full items-center\"\n [class.justify-center]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-center'\n \"\n [class.justify-end]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerAlignClass') ===\n 'text-right'\n \">\n <span\n class=\"z-table-cell-text\"\n z-tooltip\n [zContent]=\"\n (footer.column.id | zTableColumnConfig: zConfig().columns : 'footerTooltip') ||\n $any(configFooterContent)\n \">\n {{ configFooterContent }}\n </span>\n </div>\n }\n </th>\n }\n }\n </tr>\n }\n }\n </tfoot>\n </table>\n </div>\n }\n</div>\n\n<!-- Pagination -->\n@if (zConfig().enablePagination && zConfig().pagination?.enabled !== false) {\n @let totalRows = table.getFilteredRowModel().rows.length;\n @let totalLabel = zConfig().pagination?.totalLabel ?? '{total} total rows';\n <div class=\"mt-4 flex items-center justify-between gap-4\">\n <div class=\"text-sm text-gray-500\">\n {{ totalLabel.replace('{total}', zConfig().totalCount?.toString() || totalRows.toString()) }}\n </div>\n <z-pagination\n [zTotal]=\"zConfig().totalCount ?? totalRows\"\n [(zPageIndex)]=\"pagination().pageIndex\"\n [(zPageSize)]=\"pagination().pageSize\"\n [zPageSizeOptions]=\"zConfig().pagination?.pageSizeOptions ?? [10, 20, 50, 100]\"\n [zShowSizeChanger]=\"zConfig().pagination?.showSizeChanger ?? true\"\n [zShowQuickJumper]=\"zConfig().pagination?.showQuickJumper ?? false\"\n [zShowTotal]=\"false\"\n [zDisabled]=\"zConfig().pagination?.disabled || zLoading() || isProcessing()\"\n (zOnPageChange)=\"onPageChange($event)\" />\n </div>\n}\n\n<!-- Settings Drawer -->\n<z-drawer\n [(zVisible)]=\"showSettingsDrawer\"\n zTitle=\"Table Settings\"\n zPlacement=\"right\"\n zWidth=\"500px\"\n [zShadow]=\"true\"\n [zOkText]=\"null\"\n zCancelText=\"Close\">\n <div class=\"z-table-settings-drawer px-4\">\n <!-- Display Settings -->\n <div class=\"mb-4\">\n <h4 class=\"text-foreground mb-2 text-sm font-semibold\">Display Settings</h4>\n <p class=\"text-muted-foreground mb-3 text-xs\">Customize table appearance</p>\n <div class=\"grid grid-cols-2 gap-x-4 gap-y-3\">\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"showHorizontalBorder()\"\n zText=\"Horizontal Border\"\n (zChange)=\"showHorizontalBorder.set(!showHorizontalBorder())\" />\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"showVerticalBorder()\"\n zText=\"Vertical Border\"\n (zChange)=\"showVerticalBorder.set(!showVerticalBorder())\" />\n <z-checkbox\n zSize=\"sm\"\n [zChecked]=\"showHeaderFooterShadow()\"\n zText=\"Header/Footer Shadow\"\n (zChange)=\"showHeaderFooterShadow.set(!showHeaderFooterShadow())\" />\n </div>\n </div>\n\n <!-- Divider -->\n <div class=\"border-border my-4 border-t\"></div>\n\n <!-- Unified Column Settings -->\n @if (zConfig().enableSettings) {\n <div class=\"mb-4\">\n <h4 class=\"text-foreground mb-2 text-sm font-semibold\">Column Settings</h4>\n <p class=\"text-muted-foreground mb-3 text-xs\">Toggle visibility, drag to reorder, and pin columns</p>\n\n <!-- Unpinned Columns (Draggable) -->\n <div cdkDropList (cdkDropListDropped)=\"onPendingColumnDrop($event)\" class=\"space-y-1.5\">\n @for (columnId of columnOrder(); track columnId; let i = $index) {\n @if (columnId !== 'expand' && columnId !== 'select') {\n @let column = table.getColumn(columnId);\n @let isPinned = column?.getIsPinned();\n @let isVisible = columnVisibility()[columnId] !== false;\n @let canPin = column?.getCanPin() !== false && zConfig().enableColumnPinning;\n @if (!isPinned) {\n <div\n cdkDrag\n [cdkDragData]=\"columnId\"\n cdkDragLockAxis=\"y\"\n [cdkDragDisabled]=\"false\"\n class=\"border-border bg-card hover:border-primary flex cursor-move items-center gap-2 rounded border px-2 py-1.5 text-sm transition-all hover:shadow-sm\"\n [class.opacity-60]=\"!isVisible\">\n <!-- Drag Handle -->\n <z-icon zType=\"lucideGripVertical\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n\n <!-- Visibility Checkbox -->\n <input\n type=\"checkbox\"\n [checked]=\"isVisible\"\n (change)=\"onToggleColumnVisibility(columnId)\"\n class=\"border-input h-4 w-4 shrink-0 cursor-pointer rounded\" />\n\n <!-- Column Name -->\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"truncate\" [class.text-muted-foreground]=\"!isVisible\">\n {{ columnId | zTableColumnHeader: zConfig().columns }}\n </span>\n @let parents = columnId | zTableColumnParents: zConfig().columns;\n @if (parents) {\n <span class=\"text-muted-foreground truncate text-[10px]\">({{ parents }})</span>\n }\n </span>\n\n <!-- Pin Buttons -->\n @if (canPin) {\n <div class=\"flex shrink-0 items-center gap-0.5\">\n <button\n type=\"button\"\n (click)=\"onToggleColumnPin(columnId, 'left')\"\n class=\"text-muted-foreground hover:bg-muted cursor-pointer rounded p-1 text-xs transition-colors\"\n title=\"Pin Left\">\n <z-icon zType=\"lucideArrowLeft\" zSize=\"12\" />\n </button>\n <button\n type=\"button\"\n (click)=\"onToggleColumnPin(columnId, 'right')\"\n class=\"text-muted-foreground hover:bg-muted cursor-pointer rounded p-1 text-xs transition-colors\"\n title=\"Pin Right\">\n <z-icon zType=\"lucideArrowRight\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n }\n }\n }\n </div>\n\n <!-- Pinned Columns Section -->\n @if (zConfig().enableColumnPinning) {\n @if (pinnedColumnIds().length > 0) {\n <div class=\"border-border mt-4 border-t pt-4\">\n <h5 class=\"text-muted-foreground mb-2 text-xs font-medium\">Pinned Columns</h5>\n <div class=\"space-y-1.5\">\n @for (columnId of pinnedColumnIds(); track columnId) {\n @let column = table.getColumn(columnId);\n @let isPinned = column?.getIsPinned();\n @let isVisible = columnVisibility()[columnId] !== false;\n <div\n class=\"border-border bg-muted/30 flex items-center gap-2 rounded border px-2 py-1.5 text-sm\"\n [class.opacity-60]=\"!isVisible\">\n <!-- Pin Icon -->\n <z-icon zType=\"lucidePin\" zSize=\"14\" class=\"text-primary shrink-0\" />\n\n <!-- Visibility Checkbox -->\n <!-- Visibility Checkbox -->\n <input\n type=\"checkbox\"\n [checked]=\"isVisible\"\n (change)=\"onToggleColumnVisibility(columnId)\"\n class=\"border-input h-4 w-4 shrink-0 cursor-pointer rounded\" />\n\n <!-- Column Name -->\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"truncate\" [class.text-muted-foreground]=\"!isVisible\">\n {{ columnId | zTableColumnHeader: zConfig().columns }}\n </span>\n @let pinnedParents = columnId | zTableColumnParents: zConfig().columns;\n @if (pinnedParents) {\n <span class=\"text-muted-foreground truncate text-[10px]\">({{ pinnedParents }})</span>\n }\n </span>\n\n <!-- Position Badge -->\n <span class=\"bg-primary/10 text-primary shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium\">\n {{ isPinned === 'left' ? 'LEFT' : 'RIGHT' }}\n </span>\n\n <!-- Unpin Button -->\n <button\n type=\"button\"\n (click)=\"onToggleColumnPin(columnId, isPinned === 'left' ? 'left' : 'right')\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground cursor-pointer rounded p-1 text-xs transition-colors\"\n title=\"Unpin\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n }\n </div>\n</z-drawer>\n", styles: [":host{display:flex;flex-direction:column;height:100%;--scrollbar-track-thickness: 7px;--scrollbar-track-color: transparent;--scrollbar-thumb-shape: 3px}.z-table-container{display:flex;flex-direction:column;position:relative;width:100%;height:100%;overflow:hidden;border-radius:8px;border:thin solid var(--border);background-color:var(--card)}.z-table-container.z-hide-horizontal-border th,.z-table-container.z-hide-horizontal-border td{border-bottom:none!important;border-top:none!important}.z-table-container.z-hide-vertical-border th,.z-table-container.z-hide-vertical-border td{border-left:none!important}table{width:fit-content;min-width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed;font-size:14px}.z-table-toolbar .z-settings-btn{transition:all .15s ease}.z-table-toolbar .z-settings-btn:hover{border-color:var(--muted-foreground)}.z-table-cell-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;-webkit-user-select:text;user-select:text}.z-thead-wrapper{background:var(--muted);overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.z-thead-wrapper::-webkit-scrollbar{display:none}.z-thead-wrapper th{height:auto;padding:8px 12px;text-align:left;vertical-align:middle;font-weight:500;color:var(--foreground);white-space:nowrap;overflow:hidden;background:var(--muted);border-left:thin solid var(--border);border-bottom:thin solid var(--border);-webkit-user-select:none;user-select:none}.z-thead-wrapper th.z-at-left-edge{border-left:none}.z-thead-wrapper th[colspan]{text-align:center;background:var(--muted);font-weight:500;color:var(--foreground)}.z-thead-wrapper.z-shadow-header{box-shadow:0 1px 3px #00000014;position:relative;z-index:15}.z-thead-wrapper.z-shadow-header:where(.dark,.dark *){box-shadow:0 1px 3px #0000004d}.z-tbody-wrapper{flex:1;min-height:200px;display:flex;flex-direction:column}.z-tbody-scrollbar{flex:1;height:100%}.z-empty-state,.z-loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:200px;height:100%;color:var(--muted-foreground);font-size:.875rem;animation:z-fade-in .2s ease-out}.z-tbody-scrollbar,.z-tbody-scrollbar table{animation:z-fade-in .2s ease-out}@keyframes z-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.z-tbody-wrapper tr{transition:background-color .15s ease}.z-tbody-wrapper tr:hover,.z-tbody-wrapper tr:hover td[style*=sticky]{background-color:var(--muted)}.z-tbody-wrapper tr.z-pinned-top td.z-sticky-left,.z-tbody-wrapper tr.z-pinned-top td.z-sticky-right,.z-tbody-wrapper tr.z-pinned-bottom td.z-sticky-left,.z-tbody-wrapper tr.z-pinned-bottom td.z-sticky-right{z-index:3}.z-tbody-wrapper tr.z-shadow-bottom{box-shadow:0 1px 3px #00000014!important;position:relative;z-index:15}.z-tbody-wrapper tr.z-shadow-bottom:where(.dark,.dark *){box-shadow:0 1px 3px #0000004d!important}.z-tbody-wrapper tr.z-shadow-top{box-shadow:0 -2px 4px #0000000d!important;position:relative;z-index:15}.z-tbody-wrapper tr.z-shadow-top:where(.dark,.dark *){box-shadow:0 -2px 4px #0003!important}.z-tbody-wrapper td{padding:8px 12px;height:40px;vertical-align:middle;color:var(--foreground);white-space:nowrap;overflow:hidden;background:var(--card);border-left:thin solid var(--border);border-bottom:thin solid var(--border);box-sizing:border-box}.z-tbody-wrapper td.z-at-left-edge{border-left:none}.z-tbody-wrapper td i{color:var(--muted-foreground);font-style:italic}.z-tbody-wrapper td[rowspan]{vertical-align:top;padding-top:12px}.z-tbody-wrapper td.z-row-hover{background-color:var(--muted)!important}.z-tbody-wrapper td.z-col-select,.z-tbody-wrapper td.z-col-expand,.z-tbody-wrapper td.z-col-actions{padding:8px 4px!important;text-align:center}.z-tbody-wrapper tr.z-child-row td.z-col-select:first-child,.z-tbody-wrapper tr.z-child-row td.z-col-expand:first-child,.z-tbody-wrapper tr.z-child-row td.z-col-actions:first-child{padding-left:0!important}.z-virtual-scroll-inner{position:relative;width:100%}.z-virtual-row{position:absolute;top:0;left:0;width:100%}tr.z-child-row td:first-child{padding-left:12px!important}tbody tr.z-selected,tbody tr.z-selected td{background-color:color-mix(in srgb,var(--primary) 15%,transparent)!important}tbody tr.z-selected:hover,tbody tr.z-selected:hover td{background-color:color-mix(in srgb,var(--primary) 20%,transparent)!important}tbody tr.z-indeterminate-selected,tbody tr.z-indeterminate-selected td{background-color:color-mix(in srgb,var(--primary) 10%,transparent)!important}tbody tr.z-indeterminate-selected:hover,tbody tr.z-indeterminate-selected:hover td{background-color:color-mix(in srgb,var(--primary) 15%,transparent)!important}tbody tr.z-pinned-top td{background-color:var(--card)!important}tbody tr.z-pinned-top:hover{background-color:var(--muted)}tbody tr.z-pinned-top:hover td{background-color:var(--muted)!important}tbody tr.z-pinned-bottom td{background-color:var(--card)!important}tbody tr.z-pinned-bottom:hover{background-color:var(--muted)}tbody tr.z-pinned-bottom:hover td,tr.z-expanded-row td{background-color:var(--muted)!important}thead th{position:relative}thead th .z-resizer{position:absolute;right:0;top:0;height:100%;width:5px;background:#0000001a;cursor:col-resize;-webkit-user-select:none;user-select:none;touch-action:none;opacity:0;transition:opacity .2s ease}thead th .z-resizer:where(.dark,.dark *){background:#ffffff1a}thead th .z-resizer:hover,thead th .z-resizer.z-is-resizing{opacity:1;background:var(--primary);opacity:.5}thead th .z-resizer.z-is-resizing{background:var(--primary);opacity:1}thead th .z-resizer.z-resizer-left{right:auto;left:0}thead th:hover .z-resizer{opacity:1}.z-thead-wrapper th.z-sticky-left,.z-thead-wrapper th.z-sticky-right,.z-tbody-wrapper th.z-sticky-left,.z-tbody-wrapper th.z-sticky-right,.z-tfoot-wrapper th.z-sticky-left,.z-tfoot-wrapper th.z-sticky-right{background-color:var(--muted);z-index:1;transform:translateZ(0);backface-visibility:hidden}.z-thead-wrapper td.z-sticky-left,.z-thead-wrapper td.z-sticky-right,.z-tbody-wrapper td.z-sticky-left,.z-tbody-wrapper td.z-sticky-right,.z-tfoot-wrapper td.z-sticky-left,.z-tfoot-wrapper td.z-sticky-right{background-color:var(--card);z-index:1;transform:translateZ(0);backface-visibility:hidden}.z-thead-wrapper th.z-sticky-left-last,.z-thead-wrapper td.z-sticky-left-last,.z-tbody-wrapper th.z-sticky-left-last,.z-tbody-wrapper td.z-sticky-left-last,.z-tfoot-wrapper th.z-sticky-left-last,.z-tfoot-wrapper td.z-sticky-left-last{position:relative;overflow:visible}.z-thead-wrapper th.z-sticky-left-last:after,.z-thead-wrapper td.z-sticky-left-last:after,.z-tbody-wrapper th.z-sticky-left-last:after,.z-tbody-wrapper td.z-sticky-left-last:after,.z-tfoot-wrapper th.z-sticky-left-last:after,.z-tfoot-wrapper td.z-sticky-left-last:after{content:\"\";position:absolute;top:0;bottom:0;right:-30px;width:30px;pointer-events:none;box-shadow:inset 10px 0 8px -8px #0000001a;z-index:10}.z-thead-wrapper th.z-sticky-left-last:after:where(.dark,.dark *),.z-thead-wrapper td.z-sticky-left-last:after:where(.dark,.dark *),.z-tbody-wrapper th.z-sticky-left-last:after:where(.dark,.dark *),.z-tbody-wrapper td.z-sticky-left-last:after:where(.dark,.dark *),.z-tfoot-wrapper th.z-sticky-left-last:after:where(.dark,.dark *),.z-tfoot-wrapper td.z-sticky-left-last:after:where(.dark,.dark *){box-shadow:inset 10px 0 8px -8px #0000004d}.z-thead-wrapper th.z-sticky-left-last:after,.z-thead-wrapper td.z-sticky-left-last:after,.z-tbody-wrapper th.z-sticky-left-last:after,.z-tbody-wrapper td.z-sticky-left-last:after,.z-tfoot-wrapper th.z-sticky-left-last:after,.z-tfoot-wrapper td.z-sticky-left-last:after{opacity:0;transition:opacity .2s ease}.z-thead-wrapper.z-scroll-left th.z-sticky-left-last:after,.z-thead-wrapper.z-scroll-left td.z-sticky-left-last:after,.z-tbody-wrapper.z-scroll-left th.z-sticky-left-last:after,.z-tbody-wrapper.z-scroll-left td.z-sticky-left-last:after,.z-tfoot-wrapper.z-scroll-left th.z-sticky-left-last:after,.z-tfoot-wrapper.z-scroll-left td.z-sticky-left-last:after{opacity:1}.z-thead-wrapper th.z-sticky-right-first,.z-thead-wrapper td.z-sticky-right-first,.z-tbody-wrapper th.z-sticky-right-first,.z-tbody-wrapper td.z-sticky-right-first,.z-tfoot-wrapper th.z-sticky-right-first,.z-tfoot-wrapper td.z-sticky-right-first{position:relative;overflow:visible}.z-thead-wrapper th.z-sticky-right-first:before,.z-thead-wrapper td.z-sticky-right-first:before,.z-tbody-wrapper th.z-sticky-right-first:before,.z-tbody-wrapper td.z-sticky-right-first:before,.z-tfoot-wrapper th.z-sticky-right-first:before,.z-tfoot-wrapper td.z-sticky-right-first:before{content:\"\";position:absolute;top:0;bottom:0;left:-30px;width:30px;pointer-events:none;box-shadow:inset -10px 0 8px -8px #0000001a;z-index:10;opacity:0;transition:opacity .2s ease}.z-thead-wrapper th.z-sticky-right-first:before:where(.dark,.dark *),.z-thead-wrapper td.z-sticky-right-first:before:where(.dark,.dark *),.z-tbody-wrapper th.z-sticky-right-first:before:where(.dark,.dark *),.z-tbody-wrapper td.z-sticky-right-first:before:where(.dark,.dark *),.z-tfoot-wrapper th.z-sticky-right-first:before:where(.dark,.dark *),.z-tfoot-wrapper td.z-sticky-right-first:before:where(.dark,.dark *){box-shadow:inset -10px 0 8px -8px #0000004d}.z-thead-wrapper.z-scroll-right th.z-sticky-right-first,.z-thead-wrapper.z-scroll-right td.z-sticky-right-first,.z-tbody-wrapper.z-scroll-right th.z-sticky-right-first,.z-tbody-wrapper.z-scroll-right td.z-sticky-right-first,.z-tfoot-wrapper.z-scroll-right th.z-sticky-right-first,.z-tfoot-wrapper.z-scroll-right td.z-sticky-right-first{border-left:none}.z-thead-wrapper.z-scroll-right th.z-sticky-right-first:before,.z-thead-wrapper.z-scroll-right td.z-sticky-right-first:before,.z-tbody-wrapper.z-scroll-right th.z-sticky-right-first:before,.z-tbody-wrapper.z-scroll-right td.z-sticky-right-first:before,.z-tfoot-wrapper.z-scroll-right th.z-sticky-right-first:before,.z-tfoot-wrapper.z-scroll-right td.z-sticky-right-first:before{opacity:1}.z-thead-wrapper th.z-sticky-right-last,.z-tfoot-wrapper th.z-sticky-right-last{position:relative}.z-thead-wrapper th.z-sticky-right-last:after,.z-tfoot-wrapper th.z-sticky-right-last:after{content:\"\";position:absolute;top:0;bottom:0;right:-30px;width:30px;background:var(--muted);pointer-events:none}.z-tfoot-wrapper{background:var(--muted);overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.z-tfoot-wrapper::-webkit-scrollbar{display:none}.z-tfoot-wrapper th{height:auto;padding:8px 12px;text-align:left;vertical-align:middle;font-weight:500;font-size:12px;color:var(--muted-foreground);text-transform:uppercase;letter-spacing:.5px;background:var(--muted);border-left:thin solid var(--border);border-top:thin solid var(--border)}.z-tfoot-wrapper th.z-at-left-edge{border-left:none}.z-tfoot-wrapper.z-shadow-footer{box-shadow:0 -2px 4px #0000000d;position:relative;z-index:15}.z-tfoot-wrapper.z-shadow-footer:where(.dark,.dark *){box-shadow:0 -2px 4px #0003}.z-pin-btn{padding:2px 4px;border-radius:4px;color:var(--muted-foreground);transition:all .15s ease}.z-pin-btn:hover{background-color:var(--muted);color:var(--foreground)}.z-pin-btn.z-pin-btn-active{color:var(--primary);background-color:var(--primary)}.z-pin-btn.z-pin-btn-active:hover{background-color:var(--primary);opacity:.8}.z-row-pin-trigger{opacity:1}.z-row-pin-trigger.text-primary{color:var(--primary)}.z-header-pin-trigger{opacity:1}.z-header-pin-trigger.text-primary{color:var(--primary)}th{overflow:hidden}th .z-header-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cdk-drag-preview{box-shadow:0 4px 12px #00000026;opacity:.9;border-radius:4px;background-color:var(--card);z-index:9999}.cdk-drag-preview:where(.dark,.dark *){box-shadow:0 4px 12px #0006}.cdk-drag-placeholder{opacity:.3;background-color:var(--muted);border:2px dashed var(--primary)}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .cdk-drag:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.z-table-settings-drawer input[type=checkbox]{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:1rem;height:1rem;border:thin solid var(--input);border-radius:.25rem;background-color:var(--background);cursor:pointer;position:relative;transition:all .2s ease}.z-table-settings-drawer input[type=checkbox]:hover{border-color:var(--primary)}.z-table-settings-drawer input[type=checkbox]:checked{background-color:var(--primary);border-color:var(--primary)}.z-table-settings-drawer input[type=checkbox]:checked:after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:.375rem;height:.625rem;border:solid var(--primary-foreground);border-width:0 2px 2px 0;transform:translate(-50%,-60%) rotate(45deg)}.z-table-settings-drawer input[type=checkbox]:disabled{opacity:.5;cursor:not-allowed}\n"] }]
|
|
2621
|
+
}], ctorParameters: () => [], propDecorators: { zConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "zConfig", required: false }] }], zLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLoading", required: false }] }], zKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "zKey", required: false }] }], zChange: [{ type: i0.Output, args: ["zChange"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], theadWrapper: [{ type: i0.ViewChild, args: ['theadWrapper', { isSignal: true }] }], tbodyContainer: [{ type: i0.ViewChild, args: ['tbodyContainer', { isSignal: true }] }], tbodyWrapper: [{ type: i0.ViewChild, args: ['tbodyWrapper', { isSignal: true }] }], tbodyScrollbar: [{ type: i0.ViewChild, args: ['tbodyWrapper', { isSignal: true }] }], tfootWrapper: [{ type: i0.ViewChild, args: ['tfootWrapper', { isSignal: true }] }], expandedRowTemplate: [{ type: i0.ViewChild, args: ['expandedRowTemplate', { isSignal: true }] }] } });
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
* Generated bundle index. Do not edit.
|
|
2625
|
+
*/
|
|
2626
|
+
|
|
2627
|
+
export { ZTableComponent, ZTableFilterComponent, ZTableIconTextComponent, columnConfigToColumnDef, findColumnConfig, getBodyConfig, getFooterConfig, getHeaderConfig, isBodyConfig, isFooterConfig, isHeaderConfig };
|
|
2628
|
+
//# sourceMappingURL=shival99-z-ui-components-z-table.mjs.map
|