@angular-generic-table/core 5.0.0-rc.9 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/angular-generic-table-core.mjs +1065 -0
- package/fesm2022/angular-generic-table-core.mjs.map +1 -0
- package/package.json +10 -16
- package/scss/index.scss +231 -14
- package/types/angular-generic-table-core.d.ts +396 -0
- package/angular-generic-table-core.d.ts +0 -5
- package/esm2020/angular-generic-table-core.mjs +0 -5
- package/esm2020/lib/core.component.mjs +0 -122
- package/esm2020/lib/core.module.mjs +0 -23
- package/esm2020/lib/core.service.mjs +0 -14
- package/esm2020/lib/enums/order.enum.mjs +0 -6
- package/esm2020/lib/models/table-column.interface.mjs +0 -2
- package/esm2020/lib/models/table-config.interface.mjs +0 -2
- package/esm2020/lib/models/table-info.interface.mjs +0 -2
- package/esm2020/lib/models/table-meta.interface.mjs +0 -2
- package/esm2020/lib/models/table-row.interface.mjs +0 -2
- package/esm2020/lib/models/table-sort.interface.mjs +0 -2
- package/esm2020/lib/pagination/pagination.component.mjs +0 -63
- package/esm2020/lib/pagination/pagination.module.mjs +0 -18
- package/esm2020/lib/pipes/capital-case.pipe.mjs +0 -17
- package/esm2020/lib/pipes/dash-case.pipe.mjs +0 -17
- package/esm2020/lib/pipes/dynamic.pipe.mjs +0 -25
- package/esm2020/lib/pipes/highlight.pipe.mjs +0 -48
- package/esm2020/lib/pipes/sort-class.pipe.mjs +0 -16
- package/esm2020/lib/utilities/utilities.mjs +0 -39
- package/esm2020/public-api.mjs +0 -15
- package/fesm2015/angular-generic-table-core.mjs +0 -384
- package/fesm2015/angular-generic-table-core.mjs.map +0 -1
- package/fesm2020/angular-generic-table-core.mjs +0 -381
- package/fesm2020/angular-generic-table-core.mjs.map +0 -1
- package/lib/core.component.d.ts +0 -33
- package/lib/core.module.d.ts +0 -13
- package/lib/core.service.d.ts +0 -6
- package/lib/enums/order.enum.d.ts +0 -4
- package/lib/models/table-column.interface.d.ts +0 -15
- package/lib/models/table-config.interface.d.ts +0 -15
- package/lib/models/table-info.interface.d.ts +0 -4
- package/lib/models/table-meta.interface.d.ts +0 -8
- package/lib/models/table-row.interface.d.ts +0 -4
- package/lib/models/table-sort.interface.d.ts +0 -5
- package/lib/pagination/pagination.component.d.ts +0 -14
- package/lib/pagination/pagination.module.d.ts +0 -8
- package/lib/pipes/capital-case.pipe.d.ts +0 -7
- package/lib/pipes/dash-case.pipe.d.ts +0 -7
- package/lib/pipes/dynamic.pipe.d.ts +0 -9
- package/lib/pipes/highlight.pipe.d.ts +0 -7
- package/lib/pipes/sort-class.pipe.d.ts +0 -11
- package/lib/utilities/utilities.d.ts +0 -6
- package/public-api.d.ts +0 -11
|
@@ -0,0 +1,1065 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Pipe, Injector, inject, DestroyRef, input, output, linkedSignal, computed, signal, effect, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
|
|
3
|
+
import { Subject, fromEvent } from 'rxjs';
|
|
4
|
+
import { filter, takeUntil } from 'rxjs/operators';
|
|
5
|
+
import { toObservable } from '@angular/core/rxjs-interop';
|
|
6
|
+
import { NgComponentOutlet, NgTemplateOutlet, SlicePipe, PercentPipe, CommonModule } from '@angular/common';
|
|
7
|
+
|
|
8
|
+
let dashed;
|
|
9
|
+
dashed = (s) => s.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
|
10
|
+
let capitalize;
|
|
11
|
+
capitalize = (s) => (s.charAt(0).toUpperCase() + s.slice(1))
|
|
12
|
+
.replace(/_/g, ' ')
|
|
13
|
+
.replace(/([A-Z][a-z]+)/g, ' $1')
|
|
14
|
+
.replace(/([A-Z]{2,})/g, ' $1')
|
|
15
|
+
.replace(/\s{2,}/g, ' ')
|
|
16
|
+
.trim();
|
|
17
|
+
let chunk;
|
|
18
|
+
chunk = (array, chunkSize) => {
|
|
19
|
+
if (chunkSize < 0) {
|
|
20
|
+
throw new Error('Invalid chunk size');
|
|
21
|
+
}
|
|
22
|
+
if (chunkSize === 0 && !chunkSize) {
|
|
23
|
+
return [array];
|
|
24
|
+
}
|
|
25
|
+
const CHUNK = [];
|
|
26
|
+
for (let i = 0, len = array.length; i < len; i += chunkSize) {
|
|
27
|
+
CHUNK.push(array.slice(i, i + chunkSize));
|
|
28
|
+
}
|
|
29
|
+
return CHUNK;
|
|
30
|
+
};
|
|
31
|
+
let search;
|
|
32
|
+
search = (text, caseSensitive, data, config) => {
|
|
33
|
+
if (config.columns) {
|
|
34
|
+
const searchColumns = Object.keys(config.columns).filter(
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
(key) => config.columns &&
|
|
37
|
+
!config.columns[key]?.hidden &&
|
|
38
|
+
config.columns[key]?.search !== false);
|
|
39
|
+
const FILTERED = [];
|
|
40
|
+
for (let i = 0; i < data.length; i++) {
|
|
41
|
+
const row = data[i];
|
|
42
|
+
const match = Object.entries(row)
|
|
43
|
+
.filter(([key, value]) => searchColumns.indexOf(key) !== -1)
|
|
44
|
+
.reduce((acc, [key, value], index) => {
|
|
45
|
+
const search = config?.columns[key]?.search;
|
|
46
|
+
// if search is a function...
|
|
47
|
+
if (typeof search === 'function') {
|
|
48
|
+
// ...use search function to return value to search
|
|
49
|
+
value = search(row, key, value);
|
|
50
|
+
}
|
|
51
|
+
return (acc +
|
|
52
|
+
(index === 0 ? '' : ' ? ') +
|
|
53
|
+
(caseSensitive ? value + '' : (value + '').toLowerCase()));
|
|
54
|
+
}, '')
|
|
55
|
+
.indexOf(caseSensitive ? text : text.toLowerCase()) !== -1;
|
|
56
|
+
if (match) {
|
|
57
|
+
FILTERED[FILTERED.length] = row;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return FILTERED;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
let calculate = (data, config) => {
|
|
67
|
+
const CALCULATIONS = {};
|
|
68
|
+
const COLUMN_CALCULATIONS = {};
|
|
69
|
+
let CALCULATED = Object.entries(config.footer?.columns || {})
|
|
70
|
+
.filter(([columnName, calculations]) => Object.values(calculations || {}).filter((value) => value !== false)
|
|
71
|
+
.length >= 0)
|
|
72
|
+
.reduce((acc, [columnName, calculations], index) => {
|
|
73
|
+
acc[columnName] = Object.entries(calculations || {})
|
|
74
|
+
.filter(([calculation, value]) => value !== false)
|
|
75
|
+
.reduce((acc, [calculation, value]) => {
|
|
76
|
+
if (COLUMN_CALCULATIONS[columnName]) {
|
|
77
|
+
COLUMN_CALCULATIONS[columnName].push(calculation);
|
|
78
|
+
}
|
|
79
|
+
else if (value === true) {
|
|
80
|
+
COLUMN_CALCULATIONS[columnName] = [calculation];
|
|
81
|
+
}
|
|
82
|
+
CALCULATIONS[calculation] = true;
|
|
83
|
+
if (typeof value === 'function') {
|
|
84
|
+
value = value(data, columnName);
|
|
85
|
+
}
|
|
86
|
+
acc[calculation] = value === true ? 0 : value;
|
|
87
|
+
return acc;
|
|
88
|
+
}, {});
|
|
89
|
+
return acc;
|
|
90
|
+
}, {});
|
|
91
|
+
if (Object.keys(CALCULATED).length > 0) {
|
|
92
|
+
for (let i = 0; i < data.length; i++) {
|
|
93
|
+
Object.entries(COLUMN_CALCULATIONS).forEach(([column, calculations]) => {
|
|
94
|
+
if (calculations.indexOf('sum') > -1) {
|
|
95
|
+
CALCULATED[column].sum += data[i][column];
|
|
96
|
+
}
|
|
97
|
+
if (calculations.indexOf('avg') > -1 &&
|
|
98
|
+
calculations.indexOf('sum') === -1) {
|
|
99
|
+
if (CALCULATED[column].sum === undefined) {
|
|
100
|
+
CALCULATED[column].sum = 0;
|
|
101
|
+
}
|
|
102
|
+
CALCULATED[column].sum += data[i][column];
|
|
103
|
+
}
|
|
104
|
+
if (calculations.indexOf('max') > -1 &&
|
|
105
|
+
(!CALCULATED[column].max || +data[i][column] > CALCULATED[column].max)) {
|
|
106
|
+
CALCULATED[column].max = +data[i][column];
|
|
107
|
+
}
|
|
108
|
+
if (calculations.indexOf('min') > -1 &&
|
|
109
|
+
(!CALCULATED[column].min || +data[i][column] < CALCULATED[column].min)) {
|
|
110
|
+
CALCULATED[column].min = +data[i][column];
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
Object.entries(COLUMN_CALCULATIONS).forEach(([column, calculations]) => {
|
|
115
|
+
if (calculations.indexOf('avg') !== -1) {
|
|
116
|
+
CALCULATED[column].avg = CALCULATED[column]?.sum / data.length;
|
|
117
|
+
// if sum is not part of calculations config...
|
|
118
|
+
if (calculations.indexOf('sum') === -1 && CALCULATED[column].sum) {
|
|
119
|
+
// ...remove it
|
|
120
|
+
delete CALCULATED[column].sum;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (calculations.indexOf('count') !== -1) {
|
|
124
|
+
CALCULATED[column].count = data.length;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
calculated: CALCULATED,
|
|
130
|
+
calculations: Object.keys(CALCULATIONS).sort((a, b) => (config.footer?.rowOrder?.indexOf(a) || 0) -
|
|
131
|
+
(config.footer?.rowOrder?.indexOf(b) || 0)),
|
|
132
|
+
calculatedColumnsCount: Object.keys(CALCULATED).length || 0,
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
/** sortOnMultipleKeys
|
|
136
|
+
* @description Sort data on multiple keys with locale-aware alphanumeric comparison
|
|
137
|
+
* @param {GtSortOrder} keys - array with sort config objects to sort on, data will be sorted according to array order
|
|
138
|
+
* @returns sort function
|
|
139
|
+
*/
|
|
140
|
+
const sortOnMultipleKeys = (keys) => {
|
|
141
|
+
const order = keys.map((key) => (key.order === 'desc' ? -1 : 1));
|
|
142
|
+
return (a, b) => {
|
|
143
|
+
for (let i = 0; i < keys.length; i++) {
|
|
144
|
+
const o = keys[i].key;
|
|
145
|
+
const aVal = a[o];
|
|
146
|
+
const bVal = b[o];
|
|
147
|
+
if (aVal === bVal)
|
|
148
|
+
continue;
|
|
149
|
+
if (aVal === null || aVal === undefined)
|
|
150
|
+
return 1;
|
|
151
|
+
if (bVal === null || bVal === undefined)
|
|
152
|
+
return -1;
|
|
153
|
+
if (typeof aVal === 'string' && typeof bVal === 'string') {
|
|
154
|
+
const cmp = aVal.localeCompare(bVal, undefined, { numeric: true, sensitivity: 'base' });
|
|
155
|
+
if (cmp !== 0)
|
|
156
|
+
return cmp * order[i];
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (aVal > bVal)
|
|
160
|
+
return order[i];
|
|
161
|
+
if (aVal < bVal)
|
|
162
|
+
return -order[i];
|
|
163
|
+
}
|
|
164
|
+
return 0;
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
/** parseSortOrderParams
|
|
168
|
+
* @description Convert sort order query param to array with sort config objects
|
|
169
|
+
* @param sortParams - Query param string where each sort config object is separated by comma and order is indicated by + (ascending) or - (descending), e.g. _'name,-age'_
|
|
170
|
+
* @returns GtSortOrder - Array with sort config objects
|
|
171
|
+
*/
|
|
172
|
+
const parseSortOrderParams = (sortParams) => {
|
|
173
|
+
const sortParamsArray = sortParams.split(',');
|
|
174
|
+
return sortParamsArray.map((sortParam) => {
|
|
175
|
+
const [key, order] = sortParam.split(':');
|
|
176
|
+
return {
|
|
177
|
+
key: key.replace(/^[+-]/, ''),
|
|
178
|
+
order: order === 'desc' ? 'desc' : 'asc',
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
/** sortOrderConfigToParam
|
|
183
|
+
* @description Convert sort config object to string that can be used as query param when sorting is implemented server side
|
|
184
|
+
* @param sortConfig - Sort config object
|
|
185
|
+
* @returns string - Query param string where order is indicated by + (ascending) or - (descending), e.g. _'-name'_
|
|
186
|
+
*/
|
|
187
|
+
const sortOrderConfigToParam = (sortConfig) => {
|
|
188
|
+
const order = sortConfig.order === 'desc' ? '-' : '+';
|
|
189
|
+
return `${order}${sortConfig.key}`;
|
|
190
|
+
};
|
|
191
|
+
/** sortOrderToParams
|
|
192
|
+
* @description Convert sort order array to string that can be used as query param when sorting is implemented server side
|
|
193
|
+
* @param sortOrder - Array with sort config objects
|
|
194
|
+
* @returns string - Query param string where each sort config object is separated by comma and order is indicated by + (ascending) or - (descending), e.g. _'name,-age'_
|
|
195
|
+
*/
|
|
196
|
+
const sortOrderToParams = (sortOrder) => {
|
|
197
|
+
return sortOrder
|
|
198
|
+
.map((sortConfig) => sortOrderConfigToParam(sortConfig))
|
|
199
|
+
.join(',');
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
class CapitalCasePipe {
|
|
203
|
+
transform(s) {
|
|
204
|
+
return capitalize(s);
|
|
205
|
+
}
|
|
206
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CapitalCasePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
207
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: CapitalCasePipe, isStandalone: true, name: "capitalCase" }); }
|
|
208
|
+
}
|
|
209
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CapitalCasePipe, decorators: [{
|
|
210
|
+
type: Pipe,
|
|
211
|
+
args: [{
|
|
212
|
+
name: 'capitalCase',
|
|
213
|
+
standalone: true,
|
|
214
|
+
}]
|
|
215
|
+
}] });
|
|
216
|
+
|
|
217
|
+
class SortClassPipe {
|
|
218
|
+
transform(sortOrder, key, context = 'class') {
|
|
219
|
+
const sortIndex = sortOrder
|
|
220
|
+
? sortOrder.findIndex((s) => s.key === key)
|
|
221
|
+
: -1;
|
|
222
|
+
if (context === 'aria') {
|
|
223
|
+
if (sortIndex === -1 || !sortOrder) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
return `${sortOrder[sortIndex].order}ending`;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (context === 'class') {
|
|
231
|
+
if (sortIndex === -1 || !sortOrder) {
|
|
232
|
+
return '';
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
return `gt-sort-${sortOrder[sortIndex].order}`;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
return (sortOrder && sortOrder?.length === 1) || sortIndex < 0
|
|
240
|
+
? null
|
|
241
|
+
: sortIndex + 1 + '';
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SortClassPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
245
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: SortClassPipe, isStandalone: true, name: "sortClass" }); }
|
|
246
|
+
}
|
|
247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SortClassPipe, decorators: [{
|
|
248
|
+
type: Pipe,
|
|
249
|
+
args: [{
|
|
250
|
+
name: 'sortClass',
|
|
251
|
+
standalone: true,
|
|
252
|
+
}]
|
|
253
|
+
}] });
|
|
254
|
+
|
|
255
|
+
class DashCasePipe {
|
|
256
|
+
transform(s) {
|
|
257
|
+
return dashed(s);
|
|
258
|
+
}
|
|
259
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DashCasePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
260
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: DashCasePipe, isStandalone: true, name: "dashCase" }); }
|
|
261
|
+
}
|
|
262
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DashCasePipe, decorators: [{
|
|
263
|
+
type: Pipe,
|
|
264
|
+
args: [{
|
|
265
|
+
name: 'dashCase',
|
|
266
|
+
standalone: true,
|
|
267
|
+
}]
|
|
268
|
+
}] });
|
|
269
|
+
|
|
270
|
+
class DynamicPipe {
|
|
271
|
+
constructor(injector) {
|
|
272
|
+
this.injector = injector;
|
|
273
|
+
this._cache = new Map();
|
|
274
|
+
}
|
|
275
|
+
transform(value, requiredPipe, pipeArgs) {
|
|
276
|
+
const cached = this._cache.get(requiredPipe);
|
|
277
|
+
if (cached) {
|
|
278
|
+
return cached.transform(value, ...(pipeArgs || []));
|
|
279
|
+
}
|
|
280
|
+
const childInjector = Injector.create({
|
|
281
|
+
name: 'DynamicPipe',
|
|
282
|
+
parent: this.injector,
|
|
283
|
+
providers: [{ provide: requiredPipe }],
|
|
284
|
+
});
|
|
285
|
+
const pipe = childInjector.get(requiredPipe);
|
|
286
|
+
this._cache.set(requiredPipe, pipe);
|
|
287
|
+
return pipe.transform(value, ...(pipeArgs || []));
|
|
288
|
+
}
|
|
289
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DynamicPipe, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
290
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: DynamicPipe, isStandalone: true, name: "dynamicPipe" }); }
|
|
291
|
+
}
|
|
292
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DynamicPipe, decorators: [{
|
|
293
|
+
type: Pipe,
|
|
294
|
+
args: [{
|
|
295
|
+
name: 'dynamicPipe',
|
|
296
|
+
standalone: true,
|
|
297
|
+
}]
|
|
298
|
+
}], ctorParameters: () => [{ type: i0.Injector }] });
|
|
299
|
+
|
|
300
|
+
class HighlightPipe {
|
|
301
|
+
constructor() {
|
|
302
|
+
this._cachedTerm = null;
|
|
303
|
+
this._cachedRegex = null;
|
|
304
|
+
}
|
|
305
|
+
transform(text, searchTerm) {
|
|
306
|
+
if (!searchTerm) {
|
|
307
|
+
return text;
|
|
308
|
+
}
|
|
309
|
+
const haystackAlwaysString = text + '';
|
|
310
|
+
if (searchTerm !== this._cachedTerm) {
|
|
311
|
+
this._cachedTerm = searchTerm;
|
|
312
|
+
try {
|
|
313
|
+
this._cachedRegex = new RegExp('(' +
|
|
314
|
+
searchTerm
|
|
315
|
+
.toLowerCase()
|
|
316
|
+
.match(/".*?"|[^ ]+/g)
|
|
317
|
+
.map((needle) => needle.replace(/"(.*?)"/, '$1'))
|
|
318
|
+
.join('|') +
|
|
319
|
+
')', 'ig');
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
this._cachedRegex = null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (!this._cachedRegex) {
|
|
326
|
+
return haystackAlwaysString;
|
|
327
|
+
}
|
|
328
|
+
const containsTagPattern = /(<.*?>)(.*)(<\/.*?>)/gi;
|
|
329
|
+
const containsTagMatches = containsTagPattern.exec(haystackAlwaysString);
|
|
330
|
+
if (containsTagMatches) {
|
|
331
|
+
return (containsTagMatches[1] +
|
|
332
|
+
containsTagMatches[2].replace(this._cachedRegex, '<span class="gt-highlight-search">$1</span>') +
|
|
333
|
+
containsTagMatches[3]);
|
|
334
|
+
}
|
|
335
|
+
return haystackAlwaysString.replace(this._cachedRegex, '<span class="gt-highlight-search">$1</span>');
|
|
336
|
+
}
|
|
337
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HighlightPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
338
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HighlightPipe, isStandalone: true, name: "highlight" }); }
|
|
339
|
+
}
|
|
340
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HighlightPipe, decorators: [{
|
|
341
|
+
type: Pipe,
|
|
342
|
+
args: [{
|
|
343
|
+
name: 'highlight',
|
|
344
|
+
standalone: true,
|
|
345
|
+
}]
|
|
346
|
+
}] });
|
|
347
|
+
|
|
348
|
+
class RowSelectionPipe {
|
|
349
|
+
transform(row, selection, comparator, className) {
|
|
350
|
+
return className && comparator(row, selection) ? className : '';
|
|
351
|
+
}
|
|
352
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RowSelectionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
353
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: RowSelectionPipe, isStandalone: true, name: "rowSelection" }); }
|
|
354
|
+
}
|
|
355
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RowSelectionPipe, decorators: [{
|
|
356
|
+
type: Pipe,
|
|
357
|
+
args: [{
|
|
358
|
+
name: 'rowSelection',
|
|
359
|
+
standalone: true,
|
|
360
|
+
}]
|
|
361
|
+
}] });
|
|
362
|
+
|
|
363
|
+
class CoreComponent {
|
|
364
|
+
constructor() {
|
|
365
|
+
this._destroyRef = inject(DestroyRef);
|
|
366
|
+
this._unsubscribe$ = new Subject();
|
|
367
|
+
// ─── Inputs ───
|
|
368
|
+
this.navigationKeys = input([
|
|
369
|
+
'ArrowDown',
|
|
370
|
+
'ArrowUp',
|
|
371
|
+
'ArrowLeft',
|
|
372
|
+
'ArrowRight',
|
|
373
|
+
'Home',
|
|
374
|
+
'End',
|
|
375
|
+
], ...(ngDevMode ? [{ debugName: "navigationKeys" }] : /* istanbul ignore next */ []));
|
|
376
|
+
this.selectKeys = input(['Enter', ' '], ...(ngDevMode ? [{ debugName: "selectKeys" }] : /* istanbul ignore next */ []));
|
|
377
|
+
this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
378
|
+
this.data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
379
|
+
this.searchTerm = input(null, { ...(ngDevMode ? { debugName: "searchTerm" } : /* istanbul ignore next */ {}), alias: 'search' });
|
|
380
|
+
this.loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
381
|
+
this.sortOrderInput = input([], { ...(ngDevMode ? { debugName: "sortOrderInput" } : /* istanbul ignore next */ {}), alias: 'sortOrder' });
|
|
382
|
+
this.paginationIndexInput = input(0, { ...(ngDevMode ? { debugName: "paginationIndexInput" } : /* istanbul ignore next */ {}), alias: 'paginationIndex' });
|
|
383
|
+
this.pagingInfo = input(null, ...(ngDevMode ? [{ debugName: "pagingInfo" }] : /* istanbul ignore next */ []));
|
|
384
|
+
this.selection = input({}, ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
385
|
+
this.rowIdKey = input(undefined, ...(ngDevMode ? [{ debugName: "rowIdKey" }] : /* istanbul ignore next */ []));
|
|
386
|
+
this.generateRowId = input(true, ...(ngDevMode ? [{ debugName: "generateRowId" }] : /* istanbul ignore next */ []));
|
|
387
|
+
this.trackRowByFnInput = input(undefined, { ...(ngDevMode ? { debugName: "trackRowByFnInput" } : /* istanbul ignore next */ {}), alias: 'trackRowByFn' });
|
|
388
|
+
this.isRowSelectedFn = input(undefined, ...(ngDevMode ? [{ debugName: "isRowSelectedFn" }] : /* istanbul ignore next */ []));
|
|
389
|
+
this.customClassesInput = input({}, { ...(ngDevMode ? { debugName: "customClassesInput" } : /* istanbul ignore next */ {}), alias: 'customClasses' });
|
|
390
|
+
// ─── Outputs ───
|
|
391
|
+
this.rowClick = output();
|
|
392
|
+
this.rowSelect = output();
|
|
393
|
+
this.sortOrderChange = output();
|
|
394
|
+
this.rowActiveOutput = output({ alias: 'rowActive' });
|
|
395
|
+
this.columnSort = output();
|
|
396
|
+
this.pageChange = output();
|
|
397
|
+
// ─── Linked Signals (two-way state) ───
|
|
398
|
+
this.sortOrder = linkedSignal(() => this.sortOrderInput(), ...(ngDevMode ? [{ debugName: "sortOrder" }] : /* istanbul ignore next */ []));
|
|
399
|
+
this.currentPaginationIndex = linkedSignal(() => this.paginationIndexInput(), ...(ngDevMode ? [{ debugName: "currentPaginationIndex" }] : /* istanbul ignore next */ []));
|
|
400
|
+
// ─── Computed Signals ───
|
|
401
|
+
this.customClasses = computed(() => ({
|
|
402
|
+
selectedRow: 'gt-selected',
|
|
403
|
+
activeRow: 'gt-active',
|
|
404
|
+
...this.customClassesInput(),
|
|
405
|
+
}), ...(ngDevMode ? [{ debugName: "customClasses" }] : /* istanbul ignore next */ []));
|
|
406
|
+
this.trackRowByFn = (index, row) => {
|
|
407
|
+
const customFn = this.trackRowByFnInput();
|
|
408
|
+
if (customFn)
|
|
409
|
+
return customFn(index, row);
|
|
410
|
+
const idKey = this.rowIdKey();
|
|
411
|
+
return idKey ? row[idKey] : row?._id;
|
|
412
|
+
};
|
|
413
|
+
/** Data with mapTo expansions and row IDs applied */
|
|
414
|
+
this.expandedData = computed(() => {
|
|
415
|
+
let data = [...this.data()];
|
|
416
|
+
const config = this.config();
|
|
417
|
+
// mapTo expansion
|
|
418
|
+
if ((config.columns &&
|
|
419
|
+
!!Object.values(config.columns).find((column) => !!column.mapTo)) ||
|
|
420
|
+
(config.rows &&
|
|
421
|
+
!!Object.values(config.rows).find((column) => !!column.mapTo))) {
|
|
422
|
+
const newData = [];
|
|
423
|
+
for (let i = 0; i < data.length; i++) {
|
|
424
|
+
const row = data[i];
|
|
425
|
+
const newKeys = Object.entries(config.columns || config.rows || [])
|
|
426
|
+
.filter(([key, value]) => !!value.mapTo)
|
|
427
|
+
.reduce((previousValue, [key, value]) => ({
|
|
428
|
+
...previousValue,
|
|
429
|
+
[key]: this.nestedValue(row, value.mapTo.path, value.mapTo?.missingValue),
|
|
430
|
+
}), {});
|
|
431
|
+
newData[i] = { ...row, ...newKeys };
|
|
432
|
+
}
|
|
433
|
+
data = newData;
|
|
434
|
+
}
|
|
435
|
+
// Generate row IDs
|
|
436
|
+
if (this.generateRowId() && !this.rowIdKey() && data.length > 0) {
|
|
437
|
+
const dataWithId = [];
|
|
438
|
+
for (let i = 0; i < data.length; i++) {
|
|
439
|
+
dataWithId[i] = { ...data[i], _id: i };
|
|
440
|
+
}
|
|
441
|
+
data = dataWithId;
|
|
442
|
+
}
|
|
443
|
+
return data;
|
|
444
|
+
}, ...(ngDevMode ? [{ debugName: "expandedData" }] : /* istanbul ignore next */ []));
|
|
445
|
+
/** Filtered data (search applied, no sort) */
|
|
446
|
+
this.searchedData = computed(() => {
|
|
447
|
+
const data = [...this.expandedData()];
|
|
448
|
+
const searchBy = this.searchTerm();
|
|
449
|
+
const config = this.config();
|
|
450
|
+
const lazyLoaded = this.pagingInfo() !== null;
|
|
451
|
+
return searchBy && !lazyLoaded
|
|
452
|
+
? search(searchBy, false, data, config)
|
|
453
|
+
: data;
|
|
454
|
+
}, ...(ngDevMode ? [{ debugName: "searchedData" }] : /* istanbul ignore next */ []));
|
|
455
|
+
/** Sorted (and already searched) data */
|
|
456
|
+
this.processedData = computed(() => {
|
|
457
|
+
const data = this.searchedData();
|
|
458
|
+
const sortBy = this.sortOrder();
|
|
459
|
+
const config = this.config();
|
|
460
|
+
if (!sortBy?.length || config?.disableTableSort) {
|
|
461
|
+
return data;
|
|
462
|
+
}
|
|
463
|
+
return [...data].sort(sortOnMultipleKeys(sortBy));
|
|
464
|
+
}, ...(ngDevMode ? [{ debugName: "processedData" }] : /* istanbul ignore next */ []));
|
|
465
|
+
/** Table meta: chunked data + config + pagination info */
|
|
466
|
+
this.table = computed(() => {
|
|
467
|
+
const sorted = this.processedData();
|
|
468
|
+
const config = this.config();
|
|
469
|
+
const pi = this.pagingInfo();
|
|
470
|
+
if (pi !== null &&
|
|
471
|
+
pi.pageCurrent !== null &&
|
|
472
|
+
pi.numberOfRecords !== null &&
|
|
473
|
+
pi.pageSize !== null) {
|
|
474
|
+
return {
|
|
475
|
+
data: [sorted],
|
|
476
|
+
config,
|
|
477
|
+
info: {
|
|
478
|
+
lazyLoaded: true,
|
|
479
|
+
numberOfRecords: pi.numberOfRecords,
|
|
480
|
+
pageSize: pi.pageSize,
|
|
481
|
+
pageTotal: pi.pageTotal ?? Math.ceil(pi.numberOfRecords / pi.pageSize),
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
if (!config.pagination || config.pagination.length === 0) {
|
|
486
|
+
return {
|
|
487
|
+
data: [sorted],
|
|
488
|
+
config,
|
|
489
|
+
info: { numberOfRecords: sorted.length, pageTotal: 1 },
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
data: chunk(sorted, +(config.pagination.length || 0)),
|
|
494
|
+
config,
|
|
495
|
+
info: {
|
|
496
|
+
numberOfRecords: sorted.length,
|
|
497
|
+
pageSize: +(config.pagination.length || 0),
|
|
498
|
+
pageTotal: Math.ceil(sorted.length / +(config.pagination.length || 0)),
|
|
499
|
+
},
|
|
500
|
+
};
|
|
501
|
+
}, ...(ngDevMode ? [{ debugName: "table" }] : /* istanbul ignore next */ []));
|
|
502
|
+
/** Current table info */
|
|
503
|
+
this.tableInfoSignal = computed(() => this.table().info, ...(ngDevMode ? [{ debugName: "tableInfoSignal" }] : /* istanbul ignore next */ []));
|
|
504
|
+
/** Calculations for footer */
|
|
505
|
+
this.calculations = computed(() => calculate(this.processedData(), this.config()), ...(ngDevMode ? [{ debugName: "calculations" }] : /* istanbul ignore next */ []));
|
|
506
|
+
/** Bounded pagination index (clamped to valid range) */
|
|
507
|
+
this.boundedPaginationIndex = computed(() => {
|
|
508
|
+
const page = this.currentPaginationIndex();
|
|
509
|
+
const info = this.tableInfoSignal();
|
|
510
|
+
const pageSize = info.pageSize ?? this.config()?.pagination?.length ?? info.numberOfRecords;
|
|
511
|
+
const lastPage = Math.ceil(info.numberOfRecords / pageSize) - 1;
|
|
512
|
+
return +page < 0 ? 0 : +page > lastPage ? lastPage : +page;
|
|
513
|
+
}, ...(ngDevMode ? [{ debugName: "boundedPaginationIndex" }] : /* istanbul ignore next */ []));
|
|
514
|
+
/** Number of visible columns */
|
|
515
|
+
this.colspan = computed(() => {
|
|
516
|
+
const config = this.config();
|
|
517
|
+
if (config.columns) {
|
|
518
|
+
return Object.values(config.columns || config.rows || {}).filter((value) => value.hidden !== true).length;
|
|
519
|
+
}
|
|
520
|
+
return this.processedData().length + 1;
|
|
521
|
+
}, ...(ngDevMode ? [{ debugName: "colspan" }] : /* istanbul ignore next */ []));
|
|
522
|
+
/** Number of footer columns */
|
|
523
|
+
this.footerColspan = computed(() => {
|
|
524
|
+
const config = this.config();
|
|
525
|
+
let colspan = 0;
|
|
526
|
+
Object.values(config?.footer?.columns || {}).forEach((calculations) => {
|
|
527
|
+
if (Object.values(calculations).filter((value) => value !== false).length >=
|
|
528
|
+
0) {
|
|
529
|
+
colspan += 1;
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
return colspan;
|
|
533
|
+
}, ...(ngDevMode ? [{ debugName: "footerColspan" }] : /* istanbul ignore next */ []));
|
|
534
|
+
// ─── Row Active State ───
|
|
535
|
+
this.rowActiveState = signal({
|
|
536
|
+
row: null,
|
|
537
|
+
index: null,
|
|
538
|
+
}, ...(ngDevMode ? [{ debugName: "rowActiveState" }] : /* istanbul ignore next */ []));
|
|
539
|
+
this.activeRowIndex = null;
|
|
540
|
+
// Emit rowActive output and track index
|
|
541
|
+
this._rowActiveEffect = effect(() => {
|
|
542
|
+
const event = this.rowActiveState();
|
|
543
|
+
this.activeRowIndex = event.index;
|
|
544
|
+
this.rowActiveOutput.emit(event);
|
|
545
|
+
}, ...(ngDevMode ? [{ debugName: "_rowActiveEffect" }] : /* istanbul ignore next */ []));
|
|
546
|
+
this._columnOrder = (a, b) => {
|
|
547
|
+
return (a.value.order || 0) - (b.value.order || 0);
|
|
548
|
+
};
|
|
549
|
+
this.orderedColumns = computed(() => {
|
|
550
|
+
const config = this.config();
|
|
551
|
+
if (!config.columns)
|
|
552
|
+
return [];
|
|
553
|
+
return Object.entries(config.columns)
|
|
554
|
+
.map(([key, value]) => ({ key, value }))
|
|
555
|
+
.sort(this._columnOrder);
|
|
556
|
+
}, ...(ngDevMode ? [{ debugName: "orderedColumns" }] : /* istanbul ignore next */ []));
|
|
557
|
+
this.orderedRows = computed(() => {
|
|
558
|
+
const config = this.config();
|
|
559
|
+
if (!config.rows)
|
|
560
|
+
return [];
|
|
561
|
+
return Object.entries(config.rows)
|
|
562
|
+
.map(([key, value]) => ({ key, value }))
|
|
563
|
+
.sort(this._columnOrder);
|
|
564
|
+
}, ...(ngDevMode ? [{ debugName: "orderedRows" }] : /* istanbul ignore next */ []));
|
|
565
|
+
// ─── Keyboard Navigation ───
|
|
566
|
+
this._unsubscribeFromKeyboardEvents$ = new Subject();
|
|
567
|
+
this._keyboardArrowEvent$ = fromEvent(document, 'keydown').pipe(filter((event) => [...this.navigationKeys(), ...this.selectKeys()].indexOf(event.key) > -1));
|
|
568
|
+
}
|
|
569
|
+
/** Get tableInfo synchronously */
|
|
570
|
+
get tableInfo() {
|
|
571
|
+
return this.tableInfoSignal();
|
|
572
|
+
}
|
|
573
|
+
get sortOrder$() {
|
|
574
|
+
return (this._sortOrder$ ??= toObservable(this.sortOrder));
|
|
575
|
+
}
|
|
576
|
+
get loading$() {
|
|
577
|
+
return (this._loading$ ??= toObservable(this.loading));
|
|
578
|
+
}
|
|
579
|
+
get searchBy$() {
|
|
580
|
+
return (this._searchBy$ ??= toObservable(this.searchTerm));
|
|
581
|
+
}
|
|
582
|
+
get tableConfig$() {
|
|
583
|
+
return (this._tableConfig$ ??= toObservable(this.config));
|
|
584
|
+
}
|
|
585
|
+
get data$() {
|
|
586
|
+
return (this._data$ ??= toObservable(this.processedData));
|
|
587
|
+
}
|
|
588
|
+
get table$() {
|
|
589
|
+
return (this._table$ ??= toObservable(this.table));
|
|
590
|
+
}
|
|
591
|
+
get tableInfo$() {
|
|
592
|
+
return (this._tableInfo$ ??= toObservable(this.tableInfoSignal));
|
|
593
|
+
}
|
|
594
|
+
get currentPaginationIndex$() {
|
|
595
|
+
return (this._currentPaginationIndex$ ??= toObservable(this.boundedPaginationIndex));
|
|
596
|
+
}
|
|
597
|
+
get calculations$() {
|
|
598
|
+
return (this._calculations$ ??= toObservable(this.calculations));
|
|
599
|
+
}
|
|
600
|
+
get rowActive$() {
|
|
601
|
+
return (this._rowActive$ ??= toObservable(this.rowActiveState));
|
|
602
|
+
}
|
|
603
|
+
get colspan$() {
|
|
604
|
+
return (this._colspan$ ??= toObservable(this.colspan));
|
|
605
|
+
}
|
|
606
|
+
// ─── Pagination ───
|
|
607
|
+
get paginationIndex() {
|
|
608
|
+
return this.currentPaginationIndex();
|
|
609
|
+
}
|
|
610
|
+
set paginationIndex(value) {
|
|
611
|
+
this.currentPaginationIndex.set(value);
|
|
612
|
+
this.pageChange.emit({ index: this.boundedPaginationIndex() });
|
|
613
|
+
}
|
|
614
|
+
// ─── Methods ───
|
|
615
|
+
headerSortFn(key) {
|
|
616
|
+
return (event) => this.sortByKey(key, event);
|
|
617
|
+
}
|
|
618
|
+
_rowClick(row, index, event) {
|
|
619
|
+
this.rowClick.emit({ row, index, event });
|
|
620
|
+
}
|
|
621
|
+
_rowSelect(row, index, event) {
|
|
622
|
+
this.rowSelect.emit({ row, index, event });
|
|
623
|
+
}
|
|
624
|
+
activateRow(arg, event) {
|
|
625
|
+
if (typeof arg === 'number') {
|
|
626
|
+
const tableData = this.table();
|
|
627
|
+
const pageData = tableData.data[this.paginationIndex];
|
|
628
|
+
if (pageData && pageData[arg]) {
|
|
629
|
+
this._activateRow(pageData[arg], arg, event);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
else if (typeof arg === 'string') {
|
|
633
|
+
// TODO: implement hover by id
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
this._activateRow(null, null);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
_activateRow(row, index, event) {
|
|
640
|
+
const current = this.rowActiveState();
|
|
641
|
+
const idKey = this.rowIdKey();
|
|
642
|
+
// distinctUntilChanged equivalent
|
|
643
|
+
if (current.row && row) {
|
|
644
|
+
if (idKey && current.row[idKey] === row[idKey])
|
|
645
|
+
return;
|
|
646
|
+
if (!idKey &&
|
|
647
|
+
this.generateRowId() &&
|
|
648
|
+
current.row._id === row._id)
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (!current.row && !row && current.index === index)
|
|
652
|
+
return;
|
|
653
|
+
this.rowActiveState.set({ row, index, event });
|
|
654
|
+
}
|
|
655
|
+
/** sortByKey - Sort by key in table row */
|
|
656
|
+
sortByKey(key, $event) {
|
|
657
|
+
const shiftKey = $event?.shiftKey === true;
|
|
658
|
+
const currentOrder = this.sortOrder();
|
|
659
|
+
let sortOrderVal = 'asc';
|
|
660
|
+
let newOrder = [];
|
|
661
|
+
if (shiftKey) {
|
|
662
|
+
const existingSortPosition = currentOrder.findIndex((value) => value.key === key);
|
|
663
|
+
if (existingSortPosition === -1) {
|
|
664
|
+
newOrder = [...currentOrder, { key, order: 'asc' }];
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
sortOrderVal = currentOrder[existingSortPosition].order;
|
|
668
|
+
const newSortOrder = sortOrderVal === 'asc' ? 'desc' : 'asc';
|
|
669
|
+
newOrder = [...currentOrder];
|
|
670
|
+
newOrder[existingSortPosition] = {
|
|
671
|
+
...newOrder[existingSortPosition],
|
|
672
|
+
order: newSortOrder,
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
if (currentOrder.length > 0) {
|
|
678
|
+
const existingSortPosition = currentOrder.findIndex((value) => value.key === key);
|
|
679
|
+
if (existingSortPosition === -1) {
|
|
680
|
+
newOrder = [{ key, order: 'asc' }];
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
sortOrderVal = currentOrder[existingSortPosition].order;
|
|
684
|
+
const newSortOrder = sortOrderVal === 'asc' ? 'desc' : 'asc';
|
|
685
|
+
newOrder = [{ key, order: newSortOrder }];
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
newOrder = [{ key, order: sortOrderVal }];
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const sortEvent = {
|
|
693
|
+
key,
|
|
694
|
+
order: sortOrderVal,
|
|
695
|
+
currentSortOrder: newOrder,
|
|
696
|
+
addSortKey: shiftKey,
|
|
697
|
+
};
|
|
698
|
+
if ($event) {
|
|
699
|
+
sortEvent.event = $event;
|
|
700
|
+
}
|
|
701
|
+
this.columnSort.emit(sortEvent);
|
|
702
|
+
if (!this.tableInfo?.lazyLoaded) {
|
|
703
|
+
this.sortOrder.set(newOrder);
|
|
704
|
+
this.sortOrderChange.emit(newOrder);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
nestedValue(object, mapTo, missingValue = null) {
|
|
708
|
+
const levels = mapTo.split('.');
|
|
709
|
+
return levels.reduce((previousValue, currentValue, index) => previousValue[currentValue] ||
|
|
710
|
+
(index === levels.length - 1 ? missingValue : {}), object);
|
|
711
|
+
}
|
|
712
|
+
listenToKeyboardEvents() {
|
|
713
|
+
if (!this.config()?.activateRowOnKeyboardNavigation) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
this._unsubscribeFromKeyboardEvents$.next();
|
|
717
|
+
this._keyboardArrowEvent$
|
|
718
|
+
.pipe(takeUntil(this._unsubscribeFromKeyboardEvents$), takeUntil(this._unsubscribe$))
|
|
719
|
+
.subscribe((event) => {
|
|
720
|
+
const rows = this.processedData();
|
|
721
|
+
const currentPage = this.boundedPaginationIndex();
|
|
722
|
+
const tableInfo = this.tableInfo;
|
|
723
|
+
const selectEvent = this.selectKeys().includes(event.key);
|
|
724
|
+
if (selectEvent && this.activeRowIndex !== null) {
|
|
725
|
+
const rowIndex = this.activeRowIndex + currentPage * (tableInfo?.pageSize ?? 0);
|
|
726
|
+
this._rowSelect(rows[rowIndex], rowIndex, event);
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
const navigationEvent = this.navigationKeys().includes(event.key);
|
|
730
|
+
if (navigationEvent) {
|
|
731
|
+
this._handleNavigationEvent(event, rows, currentPage, tableInfo);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
unsubscribeFromKeyboardEvents(tableRef) {
|
|
736
|
+
if (!this.config()?.activateRowOnKeyboardNavigation) {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (tableRef !== document.activeElement) {
|
|
740
|
+
if (this.config()?.activateRowOnHover) {
|
|
741
|
+
this.activateRow(null);
|
|
742
|
+
}
|
|
743
|
+
this._unsubscribeFromKeyboardEvents$.next();
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
_handleNavigationEvent(event, rows, currentPage, tableInfo) {
|
|
747
|
+
const hasPagination = (tableInfo?.pageTotal || 0) > 1 && tableInfo;
|
|
748
|
+
const lastRowIndex = rows.length - 1;
|
|
749
|
+
let newIndex = this.activeRowIndex;
|
|
750
|
+
let indexModifier = 0;
|
|
751
|
+
if (event.key === 'Home') {
|
|
752
|
+
this.paginationIndex = 0;
|
|
753
|
+
this.activateRow(0, event);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (event.key === 'End') {
|
|
757
|
+
const indexOfLastRecord = hasPagination
|
|
758
|
+
? rows.length - (tableInfo.pageTotal - 1) * tableInfo.pageSize - 1
|
|
759
|
+
: lastRowIndex;
|
|
760
|
+
if (tableInfo?.pageTotal) {
|
|
761
|
+
this.paginationIndex = tableInfo.pageTotal - 1;
|
|
762
|
+
}
|
|
763
|
+
this.activateRow(indexOfLastRecord, event);
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (event.key === 'ArrowDown') {
|
|
767
|
+
indexModifier = 1;
|
|
768
|
+
}
|
|
769
|
+
else if (event.key === 'ArrowUp') {
|
|
770
|
+
indexModifier = -1;
|
|
771
|
+
}
|
|
772
|
+
if (newIndex === null) {
|
|
773
|
+
newIndex = 0;
|
|
774
|
+
}
|
|
775
|
+
else if (newIndex + indexModifier >= 0 &&
|
|
776
|
+
newIndex + indexModifier <= lastRowIndex) {
|
|
777
|
+
newIndex = newIndex + indexModifier;
|
|
778
|
+
}
|
|
779
|
+
if (hasPagination && tableInfo?.pageSize) {
|
|
780
|
+
const isNotLastPage = currentPage + 1 < tableInfo.pageTotal;
|
|
781
|
+
const recordsOnLastPage = rows.length - (tableInfo.pageTotal - 1) * tableInfo.pageSize - 1;
|
|
782
|
+
const maxIndex = isNotLastPage
|
|
783
|
+
? tableInfo?.pageSize - 1
|
|
784
|
+
: recordsOnLastPage;
|
|
785
|
+
if (event.key === 'ArrowLeft' && currentPage > 0) {
|
|
786
|
+
this.paginationIndex = currentPage - 1;
|
|
787
|
+
this.activateRow(newIndex, event);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
else if (event.key === 'ArrowRight' && isNotLastPage) {
|
|
791
|
+
if (currentPage + 1 === tableInfo.pageTotal - 1 &&
|
|
792
|
+
newIndex > recordsOnLastPage) {
|
|
793
|
+
this.activateRow(recordsOnLastPage, event);
|
|
794
|
+
}
|
|
795
|
+
this.paginationIndex = currentPage + 1;
|
|
796
|
+
this.activateRow(newIndex, event);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
if (currentPage > 0 &&
|
|
800
|
+
indexModifier < 0 &&
|
|
801
|
+
newIndex + indexModifier <= lastRowIndex &&
|
|
802
|
+
(this.activeRowIndex || 0) + indexModifier < 0) {
|
|
803
|
+
this.activateRow(tableInfo?.pageSize - 1, event);
|
|
804
|
+
this.paginationIndex = currentPage - 1;
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
const pageIndex = newIndex % tableInfo?.pageSize;
|
|
808
|
+
if (newIndex > maxIndex && currentPage + 1 < tableInfo.pageTotal) {
|
|
809
|
+
this.paginationIndex = currentPage + 1;
|
|
810
|
+
}
|
|
811
|
+
this.activateRow(pageIndex > maxIndex ? maxIndex : pageIndex, event);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
this.activateRow(newIndex, event);
|
|
815
|
+
}
|
|
816
|
+
ngOnDestroy() {
|
|
817
|
+
this._unsubscribe$.next();
|
|
818
|
+
this._unsubscribe$.complete();
|
|
819
|
+
this._unsubscribeFromKeyboardEvents$.next();
|
|
820
|
+
this._unsubscribeFromKeyboardEvents$.complete();
|
|
821
|
+
}
|
|
822
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CoreComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
823
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: CoreComponent, isStandalone: true, selector: "angular-generic-table", inputs: { navigationKeys: { classPropertyName: "navigationKeys", publicName: "navigationKeys", isSignal: true, isRequired: false, transformFunction: null }, selectKeys: { classPropertyName: "selectKeys", publicName: "selectKeys", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, searchTerm: { classPropertyName: "searchTerm", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, sortOrderInput: { classPropertyName: "sortOrderInput", publicName: "sortOrder", isSignal: true, isRequired: false, transformFunction: null }, paginationIndexInput: { classPropertyName: "paginationIndexInput", publicName: "paginationIndex", isSignal: true, isRequired: false, transformFunction: null }, pagingInfo: { classPropertyName: "pagingInfo", publicName: "pagingInfo", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, generateRowId: { classPropertyName: "generateRowId", publicName: "generateRowId", isSignal: true, isRequired: false, transformFunction: null }, trackRowByFnInput: { classPropertyName: "trackRowByFnInput", publicName: "trackRowByFn", isSignal: true, isRequired: false, transformFunction: null }, isRowSelectedFn: { classPropertyName: "isRowSelectedFn", publicName: "isRowSelectedFn", isSignal: true, isRequired: false, transformFunction: null }, customClassesInput: { classPropertyName: "customClassesInput", publicName: "customClasses", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClick: "rowClick", rowSelect: "rowSelect", sortOrderChange: "sortOrderChange", rowActiveOutput: "rowActive", columnSort: "columnSort", pageChange: "pageChange" }, ngImport: i0, template: "@let tableData = table();\n@let configValue = config();\n@let isLoading = loading();\n@let sortOrderValue = sortOrder();\n@let searchValue = searchTerm();\n@let rowActiveValue = rowActiveState();\n@let calculationsValue = calculations();\n@let colspanValue = colspan();\n@let footerColspanValue = footerColspan();\n@let paginationIdx = boundedPaginationIndex();\n\n<table\n [class]=\"configValue?.class || 'table'\"\n [class.table-mobile]=\"configValue?.mobileLayout\"\n [class.table-horizontal]=\"configValue?.rows\"\n [class.table-loading]=\"isLoading\"\n [class.gt-sticky-row-header]=\"configValue?.stickyHeaders?.row && configValue?.rows\"\n [class.gt-sticky-column-header]=\"configValue?.stickyHeaders?.column\"\n [attr.aria-busy]=\"isLoading === true ? true : null\"\n [tabindex]=\"configValue?.activateRowOnKeyboardNavigation ? 0 : -1\"\n #tableRef\n (focus)=\"listenToKeyboardEvents()\"\n (focusout)=\"unsubscribeFromKeyboardEvents(tableRef)\"\n (mouseenter)=\"listenToKeyboardEvents()\"\n (mouseleave)=\"unsubscribeFromKeyboardEvents(tableRef)\"\n>\n <thead>\n <tr>\n @if (configValue?.columns) {\n @for (column of orderedColumns(); track column.key) {\n @if (!column.value?.hidden) {\n <th\n class=\"{{ (column.key | dashCase) + '-column' }} {{ column.value.class }}\"\n [class.disabled]=\"isLoading\"\n [attr.aria-sort]=\"sortOrderValue | sortClass: column.key:'aria'\"\n [class.gt-sortable]=\"true\"\n scope=\"col\"\n >\n @if (column.value?.headerReplaceFull && (column.value?.headerComponent || column.value?.headerTemplateRef)) {\n @if (column.value.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"column.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: column,\n sortable: !!column.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(column.key),\n ...(column.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"column.value.headerTemplateRef!\"\n [ngTemplateOutletContext]=\"{\n column: column,\n sortable: !!column.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(column.key)\n }\"\n ></ng-container>\n }\n } @else if (column.value?.sortable) {\n <button\n [attr.data-sort-order]=\"sortOrderValue | sortClass: column.key:'order'\"\n class=\"gt-sort\"\n (click)=\"isLoading || !column.value.sortable || sortByKey(column.key, $event)\"\n >\n @if (column.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"column.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: column,\n sortable: true,\n sortOrder: sortOrderValue,\n search: searchValue,\n ...(column.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (column.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"column.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: column,\n sortable: true,\n sortOrder: sortOrderValue,\n search: searchValue\n }\"\n ></ng-container>\n } @else if (column.value?.header !== false) {\n <span>{{ column.value.header || column.key | capitalCase }}</span>\n }\n </button>\n } @else {\n @if (column.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"column.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: column,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue,\n ...(column.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (column.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"column.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: column,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue\n }\"\n ></ng-container>\n } @else if (column.value?.header !== false) {\n <span>{{ column.value.header || column.key | capitalCase }}</span>\n }\n }\n </th>\n }\n }\n }\n @if (configValue?.rows) {\n @let headerRow = orderedRows()[0];\n @if (headerRow) {\n <th\n class=\"row-header\"\n [attr.aria-sort]=\"sortOrderValue | sortClass: headerRow.key:'aria'\"\n class=\"{{ headerRow.value.sortable ? 'sort ' : '' }} {{ sortOrderValue | sortClass: headerRow.key }} {{ (headerRow.key | dashCase) + '-column' }}\"\n (click)=\"isLoading || !headerRow.value.sortable || sortByKey(headerRow.key, $event)\"\n scope=\"col\"\n >\n @if (headerRow.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"headerRow.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: headerRow,\n sortable: !!headerRow.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(headerRow.key),\n ...(headerRow.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (headerRow.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"headerRow.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: headerRow,\n sortable: !!headerRow.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(headerRow.key)\n }\"\n ></ng-container>\n } @else if (headerRow?.value?.header !== false) {\n {{ headerRow?.value?.header || headerRow.key | capitalCase }}\n }\n </th>\n @for (column of (tableData?.data || [])[0]; track $index) {\n <th class=\"{{ headerRow.value.class }}\">\n @if ((configValue.rows || {})[headerRow.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue.rows || {})[headerRow.key].component!\"\n [ngComponentOutletInputs]=\"{\n row: column,\n col: headerRow,\n index: 0,\n data: (tableData?.data || [])[0],\n search: searchValue,\n ...((configValue.rows || {})[headerRow.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n (configValue.rows || {})[headerRow.key].templateRef\n ? templateRef\n : (configValue.rows || {})[headerRow.key].transform\n ? transformData\n : rawData\n \"\n [ngTemplateOutletContext]=\"{\n row: column,\n column: headerRow,\n transform: (configValue.rows || {})[headerRow.key].transform,\n templateRef: (configValue.rows || {})[headerRow.key].templateRef,\n index: 0\n }\"\n ></ng-container>\n }\n </th>\n }\n }\n }\n </tr>\n </thead>\n @if (isLoading) {\n <tbody>\n <tr>\n <td class=\"p-0\" [colSpan]=\"colspanValue\">\n <ng-content select=\".table-loading\"></ng-content>\n </td>\n </tr>\n </tbody>\n } @else {\n @if (tableData && (tableData.data[0] || tableData.data).length > 0) {\n <tbody>\n @if (configValue?.columns) {\n @for (row of tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx]; track trackRowByFn($index, row); let i = $index) {\n <tr\n [attr.id]=\"'tableRow_' + i\"\n (click)=\"configValue?.rowClick && _rowClick(row, i, $event)\"\n (mouseenter)=\"configValue?.activateRowOnHover && _activateRow(row, i, $event)\"\n (mouseleave)=\"configValue?.activateRowOnHover && _activateRow(null, null, $event)\"\n [class]=\"[\n !!isRowSelectedFn()\n ? (row | rowSelection: selection(): isRowSelectedFn()!: customClasses().selectedRow)\n : '',\n rowActiveValue?.index === i ? customClasses().activeRow : ''\n ]\"\n >\n @for (column of orderedColumns(); track column.key) {\n @if (!column.value?.hidden) {\n <td\n class=\"{{ (column.key | dashCase) + '-column' }} {{ column.value.class }}\"\n [attr.data-label]=\"\n configValue.mobileLayout && column.value.mobileHeader\n ? column.value.mobileHeader !== true\n ? column.value.mobileHeader\n : (column.value.header || column.key | capitalCase)\n : null\n \"\n >\n @if ((configValue.columns || {})[column.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue.columns || {})[column.key].component!\"\n [ngComponentOutletInputs]=\"{\n row: row,\n col: column,\n index: i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx],\n search: searchValue,\n ...((configValue.columns || {})[column.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n searchValue && !(configValue.columns || {})[column.key].templateRef\n ? highlighted\n : (configValue.columns || {})[column.key].templateRef\n ? templateRef\n : (configValue.columns || {})[column.key].transform\n ? transformData\n : rawData\n \"\n [ngTemplateOutletContext]=\"{\n row: row,\n column: column,\n search: searchValue,\n transform: (configValue.columns || {})[column.key].transform,\n templateRef: (configValue.columns || {})[column.key].templateRef,\n index: i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx]\n }\"\n ></ng-container>\n }\n </td>\n }\n }\n </tr>\n }\n }\n @if (configValue?.rows) {\n @for (row of orderedRows() | slice: 1; track row.key; let i = $index) {\n @if (!row.value?.hidden) {\n <tr\n [attr.id]=\"'tableRow_' + i\"\n class=\"{{ (row.key | dashCase) + '-row' }}\"\n (click)=\"configValue?.rowClick && _rowClick(row, i, $event)\"\n (mouseenter)=\"configValue?.activateRowOnHover && _activateRow(row, i, $event)\"\n (mouseleave)=\"configValue?.activateRowOnHover && _activateRow(null, null, $event)\"\n [class]=\"[\n !!isRowSelectedFn()\n ? (row | rowSelection: selection(): isRowSelectedFn()!: customClasses().selectedRow)\n : '',\n rowActiveValue?.index === i ? customClasses().activeRow : ''\n ]\"\n >\n <th class=\"row-header\" scope=\"row\">\n @if (row.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"row.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: row,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue,\n ...(row.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (row.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"row.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: row,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue\n }\"\n ></ng-container>\n } @else {\n {{ row.value.header || row.key | capitalCase }}\n }\n </th>\n @for (column of (tableData?.data || [])[0]; track $index; let y = $index) {\n <td class=\"{{ row.value.class }}\">\n @if ((configValue.rows || {})[row.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue.rows || {})[row.key].component!\"\n [ngComponentOutletInputs]=\"{\n row: column,\n col: row,\n index: configValue.rows ? y : i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx],\n search: searchValue,\n ...((configValue.rows || {})[row.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n (configValue.rows || {})[row.key].templateRef\n ? templateRef\n : (configValue.rows || {})[row.key].transform\n ? transformData\n : rawData\n \"\n [ngTemplateOutletContext]=\"{\n row: column,\n column: row,\n transform: (configValue.rows || {})[row.key].transform,\n templateRef: (configValue.rows || {})[row.key].templateRef,\n index: configValue.rows ? y : i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx]\n }\"\n ></ng-container>\n }\n </td>\n }\n </tr>\n }\n }\n }\n </tbody>\n } @else {\n <tbody>\n <tr>\n <td class=\"p-0\" [colSpan]=\"colspanValue\">\n <ng-content select=\".table-no-data\"></ng-content>\n </td>\n </tr>\n </tbody>\n }\n }\n @if (tableData && tableData.data.length > 0 && !isLoading) {\n <tfoot>\n @for (calculation of calculationsValue.calculations; track calculation; let i = $index) {\n @let showHeader = colspanValue !== footerColspanValue;\n <tr>\n @if (showHeader) {\n <th\n [colSpan]=\"(colspanValue || 0) - (footerColspanValue || 0)\"\n scope=\"row\"\n >\n @if (configValue?.footer?.headers?.[calculation]) {\n {{ configValue.footer!.headers![calculation] === true ? (calculation | capitalCase) : configValue.footer!.headers![calculation] }}\n }\n </th>\n }\n @for (column of orderedColumns(); track column.key) {\n @if (!column.value?.hidden && calculationsValue.calculated[column.key]) {\n <td\n class=\"{{ (column.key | dashCase) + '-column' }} {{ column.value.class }}\"\n [attr.data-header]=\"\n !showHeader && configValue?.footer?.headers?.[calculation]\n ? configValue.footer!.headers![calculation] === true ? (calculation | capitalCase) : configValue.footer!.headers![calculation]\n : null\n \"\n [attr.data-label]=\"\n configValue?.mobileLayout && column.value.mobileHeader\n ? column.value.mobileHeader !== true\n ? column.value.mobileHeader\n : (column.value.header || column.key | capitalCase)\n : null\n \"\n [class.gt-no-content]=\"!calculationsValue.calculated[column.key][calculation]\"\n >\n @if ((configValue?.columns || {})[column.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue?.columns || {})[column.key].component!\"\n [ngComponentOutletInputs]=\"{\n value: calculationsValue.calculated[column.key][calculation],\n row: calculationsValue.calculated[column.key],\n col: column,\n column: calculation,\n index: i,\n search: searchValue,\n ...((configValue?.columns || {})[column.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n (configValue?.columns || {})[column.key].templateRef\n ? templateRef\n : (configValue?.columns || {})[column.key].transform\n ? transformFooter\n : rawFooter\n \"\n [ngTemplateOutletContext]=\"{\n value: calculationsValue.calculated[column.key][calculation],\n row: calculationsValue.calculated[column.key],\n column: calculation,\n templateRef: (configValue?.columns || {})[column.key].templateRef,\n transform: (configValue?.columns || {})[column.key].transform\n }\"\n ></ng-container>\n }\n </td>\n }\n }\n </tr>\n }\n </tfoot>\n }\n</table>\n<ng-template\n #highlighted\n let-row=\"row\"\n let-column=\"column\"\n let-search=\"search\"\n let-transform=\"transform\"\n>\n @if (!transform) {\n <div [innerHTML]=\"row[column.key] | highlight: search\"></div>\n } @else {\n <div [innerHTML]=\"row[column.key] | dynamicPipe: transform.pipe:transform?.args | highlight: search\"></div>\n }\n</ng-template>\n<ng-template #rawData let-row=\"row\" let-column=\"column\">\n {{ row[column.key] }}\n</ng-template>\n<ng-template\n #transformData\n let-row=\"row\"\n let-column=\"column\"\n let-transform=\"transform\"\n let-data=\"data\"\n>\n {{ row[column.key] | dynamicPipe: transform.pipe:transform?.args }}\n</ng-template>\n<ng-template #transformFooter let-value=\"value\" let-transform=\"transform\">\n {{ (value | dynamicPipe: transform.pipe:transform?.args) || config()?.footer?.emptyContent }}\n</ng-template>\n<ng-template #rawFooter let-value=\"value\">\n {{ value || config()?.footer?.emptyContent }}\n</ng-template>\n<ng-template\n #templateRef\n let-row=\"row\"\n let-column=\"column\"\n let-index=\"index\"\n let-templateRef=\"templateRef\"\n let-data=\"data\"\n>\n <ng-container\n [ngTemplateOutlet]=\"templateRef\"\n [ngTemplateOutletContext]=\"{\n row: row,\n col: column,\n index: index,\n data: data\n }\"\n ></ng-container>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: CapitalCasePipe, name: "capitalCase" }, { kind: "pipe", type: SortClassPipe, name: "sortClass" }, { kind: "pipe", type: DashCasePipe, name: "dashCase" }, { kind: "pipe", type: RowSelectionPipe, name: "rowSelection" }, { kind: "pipe", type: SlicePipe, name: "slice" }, { kind: "pipe", type: DynamicPipe, name: "dynamicPipe" }, { kind: "pipe", type: HighlightPipe, name: "highlight" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
824
|
+
}
|
|
825
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CoreComponent, decorators: [{
|
|
826
|
+
type: Component,
|
|
827
|
+
args: [{ selector: 'angular-generic-table', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
828
|
+
CapitalCasePipe,
|
|
829
|
+
SortClassPipe,
|
|
830
|
+
DashCasePipe,
|
|
831
|
+
RowSelectionPipe,
|
|
832
|
+
NgComponentOutlet,
|
|
833
|
+
NgTemplateOutlet,
|
|
834
|
+
SlicePipe,
|
|
835
|
+
DynamicPipe,
|
|
836
|
+
HighlightPipe,
|
|
837
|
+
], template: "@let tableData = table();\n@let configValue = config();\n@let isLoading = loading();\n@let sortOrderValue = sortOrder();\n@let searchValue = searchTerm();\n@let rowActiveValue = rowActiveState();\n@let calculationsValue = calculations();\n@let colspanValue = colspan();\n@let footerColspanValue = footerColspan();\n@let paginationIdx = boundedPaginationIndex();\n\n<table\n [class]=\"configValue?.class || 'table'\"\n [class.table-mobile]=\"configValue?.mobileLayout\"\n [class.table-horizontal]=\"configValue?.rows\"\n [class.table-loading]=\"isLoading\"\n [class.gt-sticky-row-header]=\"configValue?.stickyHeaders?.row && configValue?.rows\"\n [class.gt-sticky-column-header]=\"configValue?.stickyHeaders?.column\"\n [attr.aria-busy]=\"isLoading === true ? true : null\"\n [tabindex]=\"configValue?.activateRowOnKeyboardNavigation ? 0 : -1\"\n #tableRef\n (focus)=\"listenToKeyboardEvents()\"\n (focusout)=\"unsubscribeFromKeyboardEvents(tableRef)\"\n (mouseenter)=\"listenToKeyboardEvents()\"\n (mouseleave)=\"unsubscribeFromKeyboardEvents(tableRef)\"\n>\n <thead>\n <tr>\n @if (configValue?.columns) {\n @for (column of orderedColumns(); track column.key) {\n @if (!column.value?.hidden) {\n <th\n class=\"{{ (column.key | dashCase) + '-column' }} {{ column.value.class }}\"\n [class.disabled]=\"isLoading\"\n [attr.aria-sort]=\"sortOrderValue | sortClass: column.key:'aria'\"\n [class.gt-sortable]=\"true\"\n scope=\"col\"\n >\n @if (column.value?.headerReplaceFull && (column.value?.headerComponent || column.value?.headerTemplateRef)) {\n @if (column.value.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"column.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: column,\n sortable: !!column.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(column.key),\n ...(column.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"column.value.headerTemplateRef!\"\n [ngTemplateOutletContext]=\"{\n column: column,\n sortable: !!column.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(column.key)\n }\"\n ></ng-container>\n }\n } @else if (column.value?.sortable) {\n <button\n [attr.data-sort-order]=\"sortOrderValue | sortClass: column.key:'order'\"\n class=\"gt-sort\"\n (click)=\"isLoading || !column.value.sortable || sortByKey(column.key, $event)\"\n >\n @if (column.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"column.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: column,\n sortable: true,\n sortOrder: sortOrderValue,\n search: searchValue,\n ...(column.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (column.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"column.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: column,\n sortable: true,\n sortOrder: sortOrderValue,\n search: searchValue\n }\"\n ></ng-container>\n } @else if (column.value?.header !== false) {\n <span>{{ column.value.header || column.key | capitalCase }}</span>\n }\n </button>\n } @else {\n @if (column.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"column.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: column,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue,\n ...(column.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (column.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"column.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: column,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue\n }\"\n ></ng-container>\n } @else if (column.value?.header !== false) {\n <span>{{ column.value.header || column.key | capitalCase }}</span>\n }\n }\n </th>\n }\n }\n }\n @if (configValue?.rows) {\n @let headerRow = orderedRows()[0];\n @if (headerRow) {\n <th\n class=\"row-header\"\n [attr.aria-sort]=\"sortOrderValue | sortClass: headerRow.key:'aria'\"\n class=\"{{ headerRow.value.sortable ? 'sort ' : '' }} {{ sortOrderValue | sortClass: headerRow.key }} {{ (headerRow.key | dashCase) + '-column' }}\"\n (click)=\"isLoading || !headerRow.value.sortable || sortByKey(headerRow.key, $event)\"\n scope=\"col\"\n >\n @if (headerRow.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"headerRow.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: headerRow,\n sortable: !!headerRow.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(headerRow.key),\n ...(headerRow.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (headerRow.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"headerRow.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: headerRow,\n sortable: !!headerRow.value.sortable,\n sortOrder: sortOrderValue,\n search: searchValue,\n sort: headerSortFn(headerRow.key)\n }\"\n ></ng-container>\n } @else if (headerRow?.value?.header !== false) {\n {{ headerRow?.value?.header || headerRow.key | capitalCase }}\n }\n </th>\n @for (column of (tableData?.data || [])[0]; track $index) {\n <th class=\"{{ headerRow.value.class }}\">\n @if ((configValue.rows || {})[headerRow.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue.rows || {})[headerRow.key].component!\"\n [ngComponentOutletInputs]=\"{\n row: column,\n col: headerRow,\n index: 0,\n data: (tableData?.data || [])[0],\n search: searchValue,\n ...((configValue.rows || {})[headerRow.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n (configValue.rows || {})[headerRow.key].templateRef\n ? templateRef\n : (configValue.rows || {})[headerRow.key].transform\n ? transformData\n : rawData\n \"\n [ngTemplateOutletContext]=\"{\n row: column,\n column: headerRow,\n transform: (configValue.rows || {})[headerRow.key].transform,\n templateRef: (configValue.rows || {})[headerRow.key].templateRef,\n index: 0\n }\"\n ></ng-container>\n }\n </th>\n }\n }\n }\n </tr>\n </thead>\n @if (isLoading) {\n <tbody>\n <tr>\n <td class=\"p-0\" [colSpan]=\"colspanValue\">\n <ng-content select=\".table-loading\"></ng-content>\n </td>\n </tr>\n </tbody>\n } @else {\n @if (tableData && (tableData.data[0] || tableData.data).length > 0) {\n <tbody>\n @if (configValue?.columns) {\n @for (row of tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx]; track trackRowByFn($index, row); let i = $index) {\n <tr\n [attr.id]=\"'tableRow_' + i\"\n (click)=\"configValue?.rowClick && _rowClick(row, i, $event)\"\n (mouseenter)=\"configValue?.activateRowOnHover && _activateRow(row, i, $event)\"\n (mouseleave)=\"configValue?.activateRowOnHover && _activateRow(null, null, $event)\"\n [class]=\"[\n !!isRowSelectedFn()\n ? (row | rowSelection: selection(): isRowSelectedFn()!: customClasses().selectedRow)\n : '',\n rowActiveValue?.index === i ? customClasses().activeRow : ''\n ]\"\n >\n @for (column of orderedColumns(); track column.key) {\n @if (!column.value?.hidden) {\n <td\n class=\"{{ (column.key | dashCase) + '-column' }} {{ column.value.class }}\"\n [attr.data-label]=\"\n configValue.mobileLayout && column.value.mobileHeader\n ? column.value.mobileHeader !== true\n ? column.value.mobileHeader\n : (column.value.header || column.key | capitalCase)\n : null\n \"\n >\n @if ((configValue.columns || {})[column.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue.columns || {})[column.key].component!\"\n [ngComponentOutletInputs]=\"{\n row: row,\n col: column,\n index: i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx],\n search: searchValue,\n ...((configValue.columns || {})[column.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n searchValue && !(configValue.columns || {})[column.key].templateRef\n ? highlighted\n : (configValue.columns || {})[column.key].templateRef\n ? templateRef\n : (configValue.columns || {})[column.key].transform\n ? transformData\n : rawData\n \"\n [ngTemplateOutletContext]=\"{\n row: row,\n column: column,\n search: searchValue,\n transform: (configValue.columns || {})[column.key].transform,\n templateRef: (configValue.columns || {})[column.key].templateRef,\n index: i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx]\n }\"\n ></ng-container>\n }\n </td>\n }\n }\n </tr>\n }\n }\n @if (configValue?.rows) {\n @for (row of orderedRows() | slice: 1; track row.key; let i = $index) {\n @if (!row.value?.hidden) {\n <tr\n [attr.id]=\"'tableRow_' + i\"\n class=\"{{ (row.key | dashCase) + '-row' }}\"\n (click)=\"configValue?.rowClick && _rowClick(row, i, $event)\"\n (mouseenter)=\"configValue?.activateRowOnHover && _activateRow(row, i, $event)\"\n (mouseleave)=\"configValue?.activateRowOnHover && _activateRow(null, null, $event)\"\n [class]=\"[\n !!isRowSelectedFn()\n ? (row | rowSelection: selection(): isRowSelectedFn()!: customClasses().selectedRow)\n : '',\n rowActiveValue?.index === i ? customClasses().activeRow : ''\n ]\"\n >\n <th class=\"row-header\" scope=\"row\">\n @if (row.value?.headerComponent) {\n <ng-container\n [ngComponentOutlet]=\"row.value.headerComponent!\"\n [ngComponentOutletInputs]=\"{\n column: row,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue,\n ...(row.value.headerComponentInputs || {})\n }\"\n ></ng-container>\n } @else if (row.value?.headerTemplateRef) {\n <ng-container\n [ngTemplateOutlet]=\"row.value.headerTemplateRef\"\n [ngTemplateOutletContext]=\"{\n column: row,\n sortable: false,\n sortOrder: sortOrderValue,\n search: searchValue\n }\"\n ></ng-container>\n } @else {\n {{ row.value.header || row.key | capitalCase }}\n }\n </th>\n @for (column of (tableData?.data || [])[0]; track $index; let y = $index) {\n <td class=\"{{ row.value.class }}\">\n @if ((configValue.rows || {})[row.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue.rows || {})[row.key].component!\"\n [ngComponentOutletInputs]=\"{\n row: column,\n col: row,\n index: configValue.rows ? y : i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx],\n search: searchValue,\n ...((configValue.rows || {})[row.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n (configValue.rows || {})[row.key].templateRef\n ? templateRef\n : (configValue.rows || {})[row.key].transform\n ? transformData\n : rawData\n \"\n [ngTemplateOutletContext]=\"{\n row: column,\n column: row,\n transform: (configValue.rows || {})[row.key].transform,\n templateRef: (configValue.rows || {})[row.key].templateRef,\n index: configValue.rows ? y : i,\n data: tableData.data[tableData.info.lazyLoaded ? 0 : paginationIdx]\n }\"\n ></ng-container>\n }\n </td>\n }\n </tr>\n }\n }\n }\n </tbody>\n } @else {\n <tbody>\n <tr>\n <td class=\"p-0\" [colSpan]=\"colspanValue\">\n <ng-content select=\".table-no-data\"></ng-content>\n </td>\n </tr>\n </tbody>\n }\n }\n @if (tableData && tableData.data.length > 0 && !isLoading) {\n <tfoot>\n @for (calculation of calculationsValue.calculations; track calculation; let i = $index) {\n @let showHeader = colspanValue !== footerColspanValue;\n <tr>\n @if (showHeader) {\n <th\n [colSpan]=\"(colspanValue || 0) - (footerColspanValue || 0)\"\n scope=\"row\"\n >\n @if (configValue?.footer?.headers?.[calculation]) {\n {{ configValue.footer!.headers![calculation] === true ? (calculation | capitalCase) : configValue.footer!.headers![calculation] }}\n }\n </th>\n }\n @for (column of orderedColumns(); track column.key) {\n @if (!column.value?.hidden && calculationsValue.calculated[column.key]) {\n <td\n class=\"{{ (column.key | dashCase) + '-column' }} {{ column.value.class }}\"\n [attr.data-header]=\"\n !showHeader && configValue?.footer?.headers?.[calculation]\n ? configValue.footer!.headers![calculation] === true ? (calculation | capitalCase) : configValue.footer!.headers![calculation]\n : null\n \"\n [attr.data-label]=\"\n configValue?.mobileLayout && column.value.mobileHeader\n ? column.value.mobileHeader !== true\n ? column.value.mobileHeader\n : (column.value.header || column.key | capitalCase)\n : null\n \"\n [class.gt-no-content]=\"!calculationsValue.calculated[column.key][calculation]\"\n >\n @if ((configValue?.columns || {})[column.key].component) {\n <ng-container\n [ngComponentOutlet]=\"(configValue?.columns || {})[column.key].component!\"\n [ngComponentOutletInputs]=\"{\n value: calculationsValue.calculated[column.key][calculation],\n row: calculationsValue.calculated[column.key],\n col: column,\n column: calculation,\n index: i,\n search: searchValue,\n ...((configValue?.columns || {})[column.key].componentInputs || {})\n }\"\n ></ng-container>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"\n (configValue?.columns || {})[column.key].templateRef\n ? templateRef\n : (configValue?.columns || {})[column.key].transform\n ? transformFooter\n : rawFooter\n \"\n [ngTemplateOutletContext]=\"{\n value: calculationsValue.calculated[column.key][calculation],\n row: calculationsValue.calculated[column.key],\n column: calculation,\n templateRef: (configValue?.columns || {})[column.key].templateRef,\n transform: (configValue?.columns || {})[column.key].transform\n }\"\n ></ng-container>\n }\n </td>\n }\n }\n </tr>\n }\n </tfoot>\n }\n</table>\n<ng-template\n #highlighted\n let-row=\"row\"\n let-column=\"column\"\n let-search=\"search\"\n let-transform=\"transform\"\n>\n @if (!transform) {\n <div [innerHTML]=\"row[column.key] | highlight: search\"></div>\n } @else {\n <div [innerHTML]=\"row[column.key] | dynamicPipe: transform.pipe:transform?.args | highlight: search\"></div>\n }\n</ng-template>\n<ng-template #rawData let-row=\"row\" let-column=\"column\">\n {{ row[column.key] }}\n</ng-template>\n<ng-template\n #transformData\n let-row=\"row\"\n let-column=\"column\"\n let-transform=\"transform\"\n let-data=\"data\"\n>\n {{ row[column.key] | dynamicPipe: transform.pipe:transform?.args }}\n</ng-template>\n<ng-template #transformFooter let-value=\"value\" let-transform=\"transform\">\n {{ (value | dynamicPipe: transform.pipe:transform?.args) || config()?.footer?.emptyContent }}\n</ng-template>\n<ng-template #rawFooter let-value=\"value\">\n {{ value || config()?.footer?.emptyContent }}\n</ng-template>\n<ng-template\n #templateRef\n let-row=\"row\"\n let-column=\"column\"\n let-index=\"index\"\n let-templateRef=\"templateRef\"\n let-data=\"data\"\n>\n <ng-container\n [ngTemplateOutlet]=\"templateRef\"\n [ngTemplateOutletContext]=\"{\n row: row,\n col: column,\n index: index,\n data: data\n }\"\n ></ng-container>\n</ng-template>\n" }]
|
|
838
|
+
}], propDecorators: { navigationKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationKeys", required: false }] }], selectKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectKeys", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], sortOrderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortOrder", required: false }] }], paginationIndexInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationIndex", required: false }] }], pagingInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagingInfo", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], rowIdKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdKey", required: false }] }], generateRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "generateRowId", required: false }] }], trackRowByFnInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackRowByFn", required: false }] }], isRowSelectedFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowSelectedFn", required: false }] }], customClassesInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "customClasses", required: false }] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowSelect: [{ type: i0.Output, args: ["rowSelect"] }], sortOrderChange: [{ type: i0.Output, args: ["sortOrderChange"] }], rowActiveOutput: [{ type: i0.Output, args: ["rowActive"] }], columnSort: [{ type: i0.Output, args: ["columnSort"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }] } });
|
|
839
|
+
|
|
840
|
+
class GtDeltaComponent {
|
|
841
|
+
constructor() {
|
|
842
|
+
this.data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
843
|
+
this.index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
|
|
844
|
+
this.baseIndex = input(undefined, ...(ngDevMode ? [{ debugName: "baseIndex" }] : /* istanbul ignore next */ []));
|
|
845
|
+
this.classes = input({
|
|
846
|
+
span: 'gt-delta',
|
|
847
|
+
positive: 'text-success',
|
|
848
|
+
negative: 'text-danger',
|
|
849
|
+
}, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
850
|
+
this.key = input('value', ...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
851
|
+
this.notApplicableValue = input(null, ...(ngDevMode ? [{ debugName: "notApplicableValue" }] : /* istanbul ignore next */ []));
|
|
852
|
+
this.initialValue = input(null, ...(ngDevMode ? [{ debugName: "initialValue" }] : /* istanbul ignore next */ []));
|
|
853
|
+
this.deltaTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "deltaTemplate" }] : /* istanbul ignore next */ []));
|
|
854
|
+
this.value = computed(() => {
|
|
855
|
+
const data = this.data();
|
|
856
|
+
if (!data || data.length === 0)
|
|
857
|
+
return undefined;
|
|
858
|
+
const index = this.index();
|
|
859
|
+
const baseIndex = this.baseIndex();
|
|
860
|
+
const key = this.key();
|
|
861
|
+
const initialValue = this.initialValue();
|
|
862
|
+
const deltaValue = index === 0
|
|
863
|
+
? initialValue
|
|
864
|
+
: data[index][key] -
|
|
865
|
+
(baseIndex === undefined
|
|
866
|
+
? data[index - 1][key]
|
|
867
|
+
: data[baseIndex][key]);
|
|
868
|
+
const baseValue = index === 0
|
|
869
|
+
? 1
|
|
870
|
+
: baseIndex === undefined
|
|
871
|
+
? data[index - 1][key]
|
|
872
|
+
: data[baseIndex][key];
|
|
873
|
+
const relative = index === 0
|
|
874
|
+
? initialValue
|
|
875
|
+
: Math.sign(deltaValue) *
|
|
876
|
+
Math.abs(deltaValue / baseValue);
|
|
877
|
+
return {
|
|
878
|
+
relative: Number.isFinite(relative)
|
|
879
|
+
? relative
|
|
880
|
+
: index === 0
|
|
881
|
+
? initialValue
|
|
882
|
+
: this.notApplicableValue(),
|
|
883
|
+
absolute: deltaValue,
|
|
884
|
+
};
|
|
885
|
+
}, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
886
|
+
}
|
|
887
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GtDeltaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
888
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: GtDeltaComponent, isStandalone: true, selector: "gt-delta", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, baseIndex: { classPropertyName: "baseIndex", publicName: "baseIndex", isSignal: true, isRequired: false, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, notApplicableValue: { classPropertyName: "notApplicableValue", publicName: "notApplicableValue", isSignal: true, isRequired: false, transformFunction: null }, initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, deltaTemplate: { classPropertyName: "deltaTemplate", publicName: "deltaTemplate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
889
|
+
@let delta = value();
|
|
890
|
+
@if (delta) {
|
|
891
|
+
<span
|
|
892
|
+
[class]="[
|
|
893
|
+
classes().span,
|
|
894
|
+
delta.absolute > 0
|
|
895
|
+
? classes().positive
|
|
896
|
+
: delta.absolute < 0
|
|
897
|
+
? classes().negative
|
|
898
|
+
: null
|
|
899
|
+
]"
|
|
900
|
+
[class.gt-delta-positive]="delta.absolute > 0"
|
|
901
|
+
[class.gt-delta-negative]="delta.absolute < 0"
|
|
902
|
+
>
|
|
903
|
+
<ng-container
|
|
904
|
+
[ngTemplateOutlet]="deltaTemplate() || defaultTemplate"
|
|
905
|
+
[ngTemplateOutletContext]="{ delta }"
|
|
906
|
+
></ng-container>
|
|
907
|
+
</span>
|
|
908
|
+
<ng-template #defaultTemplate let-delta="delta">
|
|
909
|
+
@if (delta.relative !== null && delta.relative !== undefined) {
|
|
910
|
+
@if (typeof delta.relative === 'number') {
|
|
911
|
+
<span>{{ delta.relative | percent: '1.0-2' }}</span>
|
|
912
|
+
} @else {
|
|
913
|
+
<span>{{ delta.relative }}</span>
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
</ng-template>
|
|
917
|
+
}
|
|
918
|
+
`, isInline: true, styles: [":host{display:inline-block}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: PercentPipe, name: "percent" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
919
|
+
}
|
|
920
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GtDeltaComponent, decorators: [{
|
|
921
|
+
type: Component,
|
|
922
|
+
args: [{ selector: 'gt-delta', template: `
|
|
923
|
+
@let delta = value();
|
|
924
|
+
@if (delta) {
|
|
925
|
+
<span
|
|
926
|
+
[class]="[
|
|
927
|
+
classes().span,
|
|
928
|
+
delta.absolute > 0
|
|
929
|
+
? classes().positive
|
|
930
|
+
: delta.absolute < 0
|
|
931
|
+
? classes().negative
|
|
932
|
+
: null
|
|
933
|
+
]"
|
|
934
|
+
[class.gt-delta-positive]="delta.absolute > 0"
|
|
935
|
+
[class.gt-delta-negative]="delta.absolute < 0"
|
|
936
|
+
>
|
|
937
|
+
<ng-container
|
|
938
|
+
[ngTemplateOutlet]="deltaTemplate() || defaultTemplate"
|
|
939
|
+
[ngTemplateOutletContext]="{ delta }"
|
|
940
|
+
></ng-container>
|
|
941
|
+
</span>
|
|
942
|
+
<ng-template #defaultTemplate let-delta="delta">
|
|
943
|
+
@if (delta.relative !== null && delta.relative !== undefined) {
|
|
944
|
+
@if (typeof delta.relative === 'number') {
|
|
945
|
+
<span>{{ delta.relative | percent: '1.0-2' }}</span>
|
|
946
|
+
} @else {
|
|
947
|
+
<span>{{ delta.relative }}</span>
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
</ng-template>
|
|
951
|
+
}
|
|
952
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, imports: [PercentPipe, NgTemplateOutlet], styles: [":host{display:inline-block}\n"] }]
|
|
953
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }], baseIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "baseIndex", required: false }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: false }] }], notApplicableValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "notApplicableValue", required: false }] }], initialValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValue", required: false }] }], deltaTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "deltaTemplate", required: false }] }] } });
|
|
954
|
+
|
|
955
|
+
class GenericTableCoreModule {
|
|
956
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GenericTableCoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
957
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: GenericTableCoreModule, imports: [CoreComponent, GtDeltaComponent], exports: [CoreComponent, GtDeltaComponent] }); }
|
|
958
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GenericTableCoreModule }); }
|
|
959
|
+
}
|
|
960
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GenericTableCoreModule, decorators: [{
|
|
961
|
+
type: NgModule,
|
|
962
|
+
args: [{
|
|
963
|
+
imports: [CoreComponent, GtDeltaComponent],
|
|
964
|
+
exports: [CoreComponent, GtDeltaComponent],
|
|
965
|
+
}]
|
|
966
|
+
}] });
|
|
967
|
+
|
|
968
|
+
class PaginationComponent {
|
|
969
|
+
constructor() {
|
|
970
|
+
this.table = input.required(...(ngDevMode ? [{ debugName: "table" }] : /* istanbul ignore next */ []));
|
|
971
|
+
this.pagingInfo = input(undefined, ...(ngDevMode ? [{ debugName: "pagingInfo" }] : /* istanbul ignore next */ []));
|
|
972
|
+
this.paginationLength = input(5, ...(ngDevMode ? [{ debugName: "paginationLength" }] : /* istanbul ignore next */ []));
|
|
973
|
+
this.classes = input({
|
|
974
|
+
ul: 'pagination',
|
|
975
|
+
li: 'page-item',
|
|
976
|
+
button: 'page-link',
|
|
977
|
+
}, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
978
|
+
this.ariaLabels = input({
|
|
979
|
+
nav: 'Table pagination',
|
|
980
|
+
button: 'Go to page ',
|
|
981
|
+
}, ...(ngDevMode ? [{ debugName: "ariaLabels" }] : /* istanbul ignore next */ []));
|
|
982
|
+
/** Page numbers to display in the pagination component */
|
|
983
|
+
this.paginationListItems = computed(() => {
|
|
984
|
+
const tbl = this.table();
|
|
985
|
+
const info = tbl.tableInfoSignal();
|
|
986
|
+
const currentPage = tbl.boundedPaginationIndex();
|
|
987
|
+
return this._generateList(info.pageTotal, currentPage);
|
|
988
|
+
}, ...(ngDevMode ? [{ debugName: "paginationListItems" }] : /* istanbul ignore next */ []));
|
|
989
|
+
/** Current page from the table */
|
|
990
|
+
this.currentPosition = computed(() => {
|
|
991
|
+
return this.table().boundedPaginationIndex();
|
|
992
|
+
}, ...(ngDevMode ? [{ debugName: "currentPosition" }] : /* istanbul ignore next */ []));
|
|
993
|
+
}
|
|
994
|
+
_generateList(numberOfPages, currentPosition) {
|
|
995
|
+
const paginationLen = this.paginationLength();
|
|
996
|
+
const middle = Math.floor(paginationLen / 2);
|
|
997
|
+
const length = numberOfPages < paginationLen ? numberOfPages : paginationLen;
|
|
998
|
+
return Array.from({ length }, (_, i) => {
|
|
999
|
+
if (i === 0) {
|
|
1000
|
+
return 1;
|
|
1001
|
+
}
|
|
1002
|
+
else if (numberOfPages < paginationLen) {
|
|
1003
|
+
return i + 1;
|
|
1004
|
+
}
|
|
1005
|
+
else if (i + 1 === length) {
|
|
1006
|
+
return numberOfPages;
|
|
1007
|
+
}
|
|
1008
|
+
else if (currentPosition > middle &&
|
|
1009
|
+
currentPosition < numberOfPages - middle) {
|
|
1010
|
+
return i + currentPosition - (middle - 1);
|
|
1011
|
+
}
|
|
1012
|
+
else if (currentPosition > middle &&
|
|
1013
|
+
currentPosition < numberOfPages - (middle - 1)) {
|
|
1014
|
+
return i + currentPosition - middle;
|
|
1015
|
+
}
|
|
1016
|
+
else if (currentPosition > middle &&
|
|
1017
|
+
currentPosition === numberOfPages - (middle - 1)) {
|
|
1018
|
+
return i + currentPosition - (middle + 1);
|
|
1019
|
+
}
|
|
1020
|
+
else if (currentPosition > middle &&
|
|
1021
|
+
currentPosition === numberOfPages - 1) {
|
|
1022
|
+
return i + currentPosition - (middle + 2);
|
|
1023
|
+
}
|
|
1024
|
+
else {
|
|
1025
|
+
return i + 1;
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
goToPage(index) {
|
|
1030
|
+
const tbl = this.table();
|
|
1031
|
+
if (tbl) {
|
|
1032
|
+
tbl.paginationIndex = index - 1;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1036
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: PaginationComponent, isStandalone: true, selector: "angular-generic-table-pagination", inputs: { table: { classPropertyName: "table", publicName: "table", isSignal: true, isRequired: true, transformFunction: null }, pagingInfo: { classPropertyName: "pagingInfo", publicName: "pagingInfo", isSignal: true, isRequired: false, transformFunction: null }, paginationLength: { classPropertyName: "paginationLength", publicName: "paginationLength", isSignal: true, isRequired: false, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null }, ariaLabels: { classPropertyName: "ariaLabels", publicName: "ariaLabels", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let links = paginationListItems();\n@let currentPos = currentPosition();\n@let classesValue = classes();\n@let ariaLabelsValue = ariaLabels();\n\n@if (links && links.length > 1) {\n <nav\n role=\"navigation\"\n [attr.aria-label]=\"ariaLabelsValue.nav\"\n class=\"gt-pagination\"\n [class]=\"classesValue.nav\"\n >\n <ul [class]=\"classesValue.ul\">\n @for (position of links; track position; let i = $index; let last = $last) {\n <li\n [class]=\"classesValue.li\"\n [class.active]=\"position === (currentPos || 0) + 1\"\n >\n <button\n [class]=\"classesValue.button\"\n [attr.aria-label]=\"ariaLabelsValue.button + position\"\n (click)=\"goToPage(position)\"\n >\n {{ position }}\n </button>\n </li>\n @if (position + 1 !== links[i + 1] && !last) {\n <li [class]=\"classesValue.li\" class=\"gt-ellipsis\">\n <button [class]=\"classesValue.button\" disabled tabindex=\"-1\"></button>\n </li>\n }\n }\n </ul>\n </nav>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1037
|
+
}
|
|
1038
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
1039
|
+
type: Component,
|
|
1040
|
+
args: [{ selector: 'angular-generic-table-pagination', changeDetection: ChangeDetectionStrategy.OnPush, template: "@let links = paginationListItems();\n@let currentPos = currentPosition();\n@let classesValue = classes();\n@let ariaLabelsValue = ariaLabels();\n\n@if (links && links.length > 1) {\n <nav\n role=\"navigation\"\n [attr.aria-label]=\"ariaLabelsValue.nav\"\n class=\"gt-pagination\"\n [class]=\"classesValue.nav\"\n >\n <ul [class]=\"classesValue.ul\">\n @for (position of links; track position; let i = $index; let last = $last) {\n <li\n [class]=\"classesValue.li\"\n [class.active]=\"position === (currentPos || 0) + 1\"\n >\n <button\n [class]=\"classesValue.button\"\n [attr.aria-label]=\"ariaLabelsValue.button + position\"\n (click)=\"goToPage(position)\"\n >\n {{ position }}\n </button>\n </li>\n @if (position + 1 !== links[i + 1] && !last) {\n <li [class]=\"classesValue.li\" class=\"gt-ellipsis\">\n <button [class]=\"classesValue.button\" disabled tabindex=\"-1\"></button>\n </li>\n }\n }\n </ul>\n </nav>\n}\n" }]
|
|
1041
|
+
}], propDecorators: { table: [{ type: i0.Input, args: [{ isSignal: true, alias: "table", required: true }] }], pagingInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagingInfo", required: false }] }], paginationLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLength", required: false }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }], ariaLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabels", required: false }] }] } });
|
|
1042
|
+
|
|
1043
|
+
class GenericTablePaginationModule {
|
|
1044
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GenericTablePaginationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1045
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: GenericTablePaginationModule, imports: [CommonModule, PaginationComponent], exports: [PaginationComponent] }); }
|
|
1046
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GenericTablePaginationModule, imports: [CommonModule] }); }
|
|
1047
|
+
}
|
|
1048
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GenericTablePaginationModule, decorators: [{
|
|
1049
|
+
type: NgModule,
|
|
1050
|
+
args: [{
|
|
1051
|
+
imports: [CommonModule, PaginationComponent],
|
|
1052
|
+
exports: [PaginationComponent],
|
|
1053
|
+
}]
|
|
1054
|
+
}] });
|
|
1055
|
+
|
|
1056
|
+
/*
|
|
1057
|
+
* Public API Surface of core
|
|
1058
|
+
*/
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Generated bundle index. Do not edit.
|
|
1062
|
+
*/
|
|
1063
|
+
|
|
1064
|
+
export { CapitalCasePipe, CoreComponent, DashCasePipe, DynamicPipe, GenericTableCoreModule, GenericTablePaginationModule, GtDeltaComponent, HighlightPipe, PaginationComponent, SortClassPipe, calculate, capitalize, chunk, dashed, parseSortOrderParams, search, sortOnMultipleKeys, sortOrderConfigToParam, sortOrderToParams };
|
|
1065
|
+
//# sourceMappingURL=angular-generic-table-core.mjs.map
|