@scion/components 22.3.0 → 22.5.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/_index.scss +37 -18
- package/design/icons/_scion-icon-font.scss +2 -2
- package/fesm2022/scion-components-common.mjs +48 -2
- package/fesm2022/scion-components-common.mjs.map +1 -1
- package/fesm2022/scion-components-icon.mjs +3 -56
- package/fesm2022/scion-components-icon.mjs.map +1 -1
- package/fesm2022/scion-components-menu.mjs +4 -4
- package/fesm2022/scion-components-menu.mjs.map +1 -1
- package/fesm2022/scion-components-splitter.mjs +1 -1
- package/fesm2022/scion-components-splitter.mjs.map +1 -1
- package/fesm2022/scion-components-table.mjs +513 -232
- package/fesm2022/scion-components-table.mjs.map +1 -1
- package/package.json +3 -3
- package/types/scion-components-common.d.ts +36 -2
- package/types/scion-components-icon.d.ts +3 -56
- package/types/scion-components-table.d.ts +457 -117
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
import { coerceSignal, createDestroyableInjector, toLazyObservable, SciComponentOutletDirective, SciAttributesDirective } from '@scion/components/common';
|
|
2
|
+
import { computed, inject, DEFAULT_CURRENCY_CODE, signal, InjectionToken, makeEnvironmentProviders, Injector, DestroyRef, runInInjectionContext, onIdle, Injectable, untracked, linkedSignal, isSignal, NgZone, effect, resource, assertNotInReactiveContext, assertInInjectionContext, Pipe, input, Component, output, viewChild, Directive, afterNextRender, ElementRef, debounced, viewChildren, ViewEncapsulation } from '@angular/core';
|
|
3
|
+
import { coerceSignal, SCI_LOCALE, createDestroyableInjector, toLazyObservable, SciComponentOutletDirective, SciAttributesDirective } from '@scion/components/common';
|
|
4
|
+
import { formatDate, DATE_PIPE_DEFAULT_OPTIONS, NgTemplateOutlet } from '@angular/common';
|
|
4
5
|
import { toObservable, rxResource, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
-
import { map, shareReplay, fromEvent, switchMap, concat, of, timer, firstValueFrom, defaultIfEmpty, throwError, skip } from 'rxjs';
|
|
6
6
|
import { Objects, clamp, runSafe, Observables, Arrays } from '@scion/toolkit/util';
|
|
7
|
-
import {
|
|
7
|
+
import { LatestTaskExecutor } from '@scion/toolkit/common';
|
|
8
|
+
import { fromEvent, switchMap, concat, of, timer, firstValueFrom, defaultIfEmpty, throwError, combineLatestWith, tap, skip } from 'rxjs';
|
|
9
|
+
import { map, startWith, first } from 'rxjs/operators';
|
|
8
10
|
import { subscribeIn } from '@scion/toolkit/operators';
|
|
9
11
|
import { SciScrollbarComponent } from '@scion/components/viewport';
|
|
10
12
|
import { dimension } from '@scion/components/dimension';
|
|
11
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
12
13
|
import { SciIconComponent } from '@scion/components/icon';
|
|
13
14
|
import { SciToolbarComponent, contributeMenu, ɵSciMenuService as _SciMenuService } from '@scion/components/menu';
|
|
14
15
|
import { UUID } from '@scion/toolkit/uuid';
|
|
@@ -18,6 +19,65 @@ import { SciThrobberComponent } from '@scion/components/throbber';
|
|
|
18
19
|
import * as i1 from '@angular/forms';
|
|
19
20
|
import { FormsModule } from '@angular/forms';
|
|
20
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Creates a {@link SciDateValue} from the given date-like input.
|
|
24
|
+
*
|
|
25
|
+
* Calling this function is expensive due to date parsing and formatting.
|
|
26
|
+
*/
|
|
27
|
+
function coerceDateValue(dateLike, options) {
|
|
28
|
+
const { format, locale, timezone } = options;
|
|
29
|
+
switch (typeof dateLike) {
|
|
30
|
+
case 'string': {
|
|
31
|
+
const isoString = ensureIso8601DatePrefix(dateLike);
|
|
32
|
+
return {
|
|
33
|
+
isoString,
|
|
34
|
+
millis: new Date(isoString).getTime(),
|
|
35
|
+
formatted: formatDate(isoString, format, locale, timezone),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
case 'number': {
|
|
39
|
+
const millis = dateLike;
|
|
40
|
+
const isoString = new Date(millis).toISOString();
|
|
41
|
+
return {
|
|
42
|
+
isoString,
|
|
43
|
+
millis,
|
|
44
|
+
formatted: formatDate(isoString, format, locale, timezone),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
case 'object': {
|
|
48
|
+
const date = dateLike;
|
|
49
|
+
const isoString = date.toISOString();
|
|
50
|
+
return {
|
|
51
|
+
isoString,
|
|
52
|
+
millis: date.getTime(),
|
|
53
|
+
formatted: formatDate(isoString, format, locale, timezone),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
case 'undefined': {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Prepends '1970-01-01' if the date prefix is missing, as required by {@link formatDate}.
|
|
63
|
+
*
|
|
64
|
+
* Uses fast ASCII character code checks (`-`, `T`, `t`) to avoid string allocation.
|
|
65
|
+
*/
|
|
66
|
+
function ensureIso8601DatePrefix(isoDate) {
|
|
67
|
+
// Check if iso string already starts with a full year date (YYYY-MM-DD)
|
|
68
|
+
if (isoDate.charCodeAt(4) === 45) { // '-'
|
|
69
|
+
return isoDate;
|
|
70
|
+
}
|
|
71
|
+
// Prepend epoch, adding 'T' separator if missing.
|
|
72
|
+
switch (isoDate.charCodeAt(0)) {
|
|
73
|
+
case 84: // 'T'
|
|
74
|
+
case 116: // 't'
|
|
75
|
+
return '1970-01-01' + isoDate;
|
|
76
|
+
default:
|
|
77
|
+
return '1970-01-01T' + isoDate;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
21
81
|
/*
|
|
22
82
|
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
23
83
|
*
|
|
@@ -28,54 +88,163 @@ import { FormsModule } from '@angular/forms';
|
|
|
28
88
|
* SPDX-License-Identifier: EPL-2.0
|
|
29
89
|
*/
|
|
30
90
|
class ɵSciTableColumnFactory {
|
|
31
|
-
|
|
91
|
+
_table;
|
|
32
92
|
columns = new Array();
|
|
33
|
-
constructor(
|
|
34
|
-
this.
|
|
93
|
+
constructor(_table) {
|
|
94
|
+
this._table = _table;
|
|
95
|
+
}
|
|
96
|
+
addStringColumn(descriptorLike, value) {
|
|
97
|
+
const descriptor = coerceColumnDescriptor(descriptorLike, value);
|
|
98
|
+
const column = this.mapToColumn(descriptor);
|
|
99
|
+
const sortable = descriptor.sortable ?? true;
|
|
100
|
+
const filterable = descriptor.filterable ?? true;
|
|
101
|
+
this.columns.push({
|
|
102
|
+
...column,
|
|
103
|
+
type: 'string',
|
|
104
|
+
value: item => coerceSignal(descriptor.value(item), { coerceUndefined: true }),
|
|
105
|
+
sortable: computed(() => this._table.sortable() && !!sortable),
|
|
106
|
+
filterable: computed(() => this._table.filterable() && !!filterable),
|
|
107
|
+
compare: typeof sortable === 'object' ? sortable.comparator : (a, b) => a.value.localeCompare(b.value),
|
|
108
|
+
matches: typeof filterable === 'object' ? filterable.matcher : (text, context) => context.value.toLowerCase().includes(text.toLowerCase()),
|
|
109
|
+
});
|
|
110
|
+
return this;
|
|
35
111
|
}
|
|
36
|
-
|
|
37
|
-
|
|
112
|
+
addNumberColumn(descriptorLike, value) {
|
|
113
|
+
const descriptor = coerceColumnDescriptor(descriptorLike, value);
|
|
114
|
+
const column = this.mapToColumn(descriptor);
|
|
115
|
+
const locale = coerceSignal(descriptor.locale ?? inject(SCI_LOCALE));
|
|
116
|
+
const currency = inject(DEFAULT_CURRENCY_CODE, { optional: true }) ?? 'USD';
|
|
117
|
+
this.columns.push({
|
|
118
|
+
...column,
|
|
119
|
+
type: 'number',
|
|
120
|
+
value: item => coerceSignal(descriptor.value(item), { coerceUndefined: true }),
|
|
121
|
+
sortable: computed(() => this._table.sortable() && (descriptor.sortable ?? true)),
|
|
122
|
+
filterable: computed(() => this._table.filterable() && (descriptor.filterable ?? true)),
|
|
123
|
+
compare: (a, b) => a.value - b.value,
|
|
124
|
+
matches: (text, context) => context.value === text,
|
|
125
|
+
format: computed(() => new Intl.NumberFormat(locale(), { currency, ...descriptor.format })),
|
|
126
|
+
});
|
|
127
|
+
return this;
|
|
38
128
|
}
|
|
39
|
-
|
|
40
|
-
|
|
129
|
+
addBooleanColumn(descriptorLike, value) {
|
|
130
|
+
const descriptor = coerceColumnDescriptor(descriptorLike, value);
|
|
131
|
+
const column = this.mapToColumn(descriptor);
|
|
132
|
+
this.columns.push({
|
|
133
|
+
...column,
|
|
134
|
+
type: 'boolean',
|
|
135
|
+
value: item => coerceSignal(descriptor.value(item), { coerceUndefined: true }),
|
|
136
|
+
sortable: computed(() => this._table.sortable() && (descriptor.sortable ?? true)),
|
|
137
|
+
filterable: computed(() => this._table.filterable() && (descriptor.filterable ?? true)),
|
|
138
|
+
compare: (a, b) => a.value === b.value ? 0 : (a.value ? 1 : -1),
|
|
139
|
+
matches: (text, context) => context.value === text,
|
|
140
|
+
});
|
|
141
|
+
return this;
|
|
41
142
|
}
|
|
42
|
-
|
|
43
|
-
|
|
143
|
+
addDateColumn(descriptorLike, value) {
|
|
144
|
+
const descriptor = coerceColumnDescriptor(descriptorLike, value);
|
|
145
|
+
const column = this.mapToColumn(descriptor);
|
|
146
|
+
const defaults = inject(DATE_PIPE_DEFAULT_OPTIONS, { optional: true });
|
|
147
|
+
const locale = coerceSignal(descriptor.locale ?? inject(SCI_LOCALE));
|
|
148
|
+
const format = descriptor.format ?? defaults?.dateFormat ?? 'mediumDate';
|
|
149
|
+
const timezone = descriptor.timezone ?? defaults?.timezone;
|
|
150
|
+
this.columns.push({
|
|
151
|
+
...column,
|
|
152
|
+
type: 'date',
|
|
153
|
+
value: item => {
|
|
154
|
+
const dateLike = coerceSignal(descriptor.value(item), { coerceUndefined: true });
|
|
155
|
+
return computed(() => coerceDateValue(dateLike(), { locale: locale(), format, timezone }));
|
|
156
|
+
},
|
|
157
|
+
sortable: computed(() => this._table.sortable() && (descriptor.sortable ?? true)),
|
|
158
|
+
filterable: computed(() => this._table.filterable() && (descriptor.filterable ?? true)),
|
|
159
|
+
compare: (a, b) => a.value.millis - b.value.millis,
|
|
160
|
+
matches: (text, context) => context.value.formatted.toLowerCase().includes(text.toLowerCase()),
|
|
161
|
+
});
|
|
162
|
+
return this;
|
|
44
163
|
}
|
|
45
|
-
addComponentColumn(
|
|
46
|
-
//
|
|
47
|
-
if (
|
|
48
|
-
throw Error('[ColumnDefinitionError] Component
|
|
49
|
-
}
|
|
50
|
-
|
|
164
|
+
addComponentColumn(descriptor) {
|
|
165
|
+
// Require a filter matcher if filterable on an array datasource.
|
|
166
|
+
if (this._table.isArrayDatasource() && descriptor.filterable === true) {
|
|
167
|
+
throw Error('[ColumnDefinitionError] Component column requires a filter matcher in order to be filterable.');
|
|
168
|
+
}
|
|
169
|
+
// Require a sort comparator if sortable on an array datasource.
|
|
170
|
+
if (this._table.isArrayDatasource() && descriptor.sortable === true) {
|
|
171
|
+
throw Error('[ColumnDefinitionError] Component column requires a sort comparator in order to be sortable.');
|
|
172
|
+
}
|
|
173
|
+
const column = this.mapToColumn(descriptor);
|
|
174
|
+
this.columns.push({
|
|
175
|
+
...column,
|
|
176
|
+
type: 'component',
|
|
177
|
+
component: descriptor.component,
|
|
178
|
+
sortable: computed(() => this._table.sortable() && !!descriptor.sortable),
|
|
179
|
+
filterable: computed(() => this._table.filterable() && !!descriptor.filterable),
|
|
180
|
+
compare: typeof descriptor.sortable === 'object' ? descriptor.sortable.comparator : () => 0,
|
|
181
|
+
matches: typeof descriptor.filterable === 'object' ? descriptor.filterable.matcher : () => true,
|
|
182
|
+
padding: descriptor.padding ?? true,
|
|
183
|
+
});
|
|
184
|
+
return this;
|
|
51
185
|
}
|
|
52
|
-
addTemplateColumn(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
186
|
+
addTemplateColumn(descriptor) {
|
|
187
|
+
// Require a filter matcher if filterable on an array datasource.
|
|
188
|
+
if (this._table.isArrayDatasource() && descriptor.filterable === true) {
|
|
189
|
+
throw Error('[ColumnDefinitionError] Template column requires a filter matcher in order to be filterable.');
|
|
190
|
+
}
|
|
191
|
+
// Require a sort comparator if sortable on an array datasource.
|
|
192
|
+
if (this._table.isArrayDatasource() && descriptor.sortable === true) {
|
|
193
|
+
throw Error('[ColumnDefinitionError] Template column requires a sort comparator in order to be sortable.');
|
|
194
|
+
}
|
|
195
|
+
const column = this.mapToColumn(descriptor);
|
|
196
|
+
this.columns.push({
|
|
197
|
+
...column,
|
|
198
|
+
type: 'template',
|
|
199
|
+
template: descriptor.template,
|
|
200
|
+
sortable: computed(() => this._table.sortable() && !!descriptor.sortable),
|
|
201
|
+
filterable: computed(() => this._table.filterable() && !!descriptor.filterable),
|
|
202
|
+
compare: typeof descriptor.sortable === 'object' ? descriptor.sortable.comparator : () => 0,
|
|
203
|
+
matches: typeof descriptor.filterable === 'object' ? descriptor.filterable.matcher : () => true,
|
|
204
|
+
padding: descriptor.padding ?? true,
|
|
205
|
+
});
|
|
206
|
+
return this;
|
|
57
207
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return { value: valueHeaderDescriptor };
|
|
65
|
-
default:
|
|
66
|
-
return valueHeaderDescriptor;
|
|
67
|
-
}
|
|
68
|
-
})();
|
|
69
|
-
if (!isSignal(this._descriptor.ɵdatasource) && (typeof config.sortable === 'object' || typeof config.filterable === 'object')) {
|
|
70
|
-
throw Error('[ColumnDefinitionError] Data sources with a loader function cannot define a custom sort or filter function. Sorting and filtering have to be done within the loader function.');
|
|
71
|
-
}
|
|
72
|
-
// Fallback to the column index as the column name.
|
|
73
|
-
const name = config.name ?? `column:${this.columns.length}`;
|
|
208
|
+
/**
|
|
209
|
+
* Maps given column descriptor to a {@link SciTableColumn}.
|
|
210
|
+
*/
|
|
211
|
+
mapToColumn(descriptor) {
|
|
212
|
+
// Require a unique column name.
|
|
213
|
+
const name = descriptor.name ?? `column:${this.columns.length}`;
|
|
74
214
|
if (this.columns.find(column => column.name === name)) {
|
|
75
|
-
throw Error(`[ColumnDefinitionError] Column names
|
|
215
|
+
throw Error(`[ColumnDefinitionError] Column names must be unique. "${name}" is defined more than once.`);
|
|
76
216
|
}
|
|
77
|
-
|
|
78
|
-
|
|
217
|
+
// Disallow a filter matcher if using a custom datasource.
|
|
218
|
+
if (!this._table.isArrayDatasource() && typeof descriptor.filterable === 'object') {
|
|
219
|
+
throw Error('[ColumnDefinitionError] Configuring a filter matcher is not supported for tables using a datasource. Filtering must be done by the datasource.');
|
|
220
|
+
}
|
|
221
|
+
// Disallow a sort comparator if using a custom datasource.
|
|
222
|
+
if (!this._table.isArrayDatasource() && typeof descriptor.sortable === 'object') {
|
|
223
|
+
throw Error('[ColumnDefinitionError] Configuring a sort comparator is not supported for tables using a datasource. Sorting must be done by the datasource.');
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
name: name,
|
|
227
|
+
header: coerceSignal(descriptor.header ?? ''),
|
|
228
|
+
resizable: computed(() => this._table.resizable() && (descriptor.resizable ?? true)),
|
|
229
|
+
width: computed(() => {
|
|
230
|
+
const userSettings = this._table.userSettings().columns?.find(column => column.name === name);
|
|
231
|
+
return userSettings?.width ? `${userSettings.width}px` : descriptor.width ?? '1fr';
|
|
232
|
+
}),
|
|
233
|
+
minWidth: descriptor.minWidth ?? 100,
|
|
234
|
+
resizing: signal(false),
|
|
235
|
+
padding: true,
|
|
236
|
+
location: { x: 0, width: 0 }, // set in `SciTableColumnComponent`
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function coerceColumnDescriptor(argument1, argument2) {
|
|
241
|
+
switch (typeof argument1) {
|
|
242
|
+
case 'string':
|
|
243
|
+
return { header: argument1, value: argument2 };
|
|
244
|
+
case 'function':
|
|
245
|
+
return { value: argument1 };
|
|
246
|
+
default:
|
|
247
|
+
return argument1;
|
|
79
248
|
}
|
|
80
249
|
}
|
|
81
250
|
|
|
@@ -122,6 +291,71 @@ function provideTableStorage(storage) {
|
|
|
122
291
|
]);
|
|
123
292
|
}
|
|
124
293
|
|
|
294
|
+
/** @inheritDoc */
|
|
295
|
+
class ɵSciTableCellValuePreloader {
|
|
296
|
+
_executor = new LatestTaskExecutor();
|
|
297
|
+
_queue = new Array(); // PERF: Do not change to signal to avoid array re-allocation on enqueue (expensive); queue size is tracked via a separate signal.
|
|
298
|
+
_queueSize = signal(0, /* @ts-ignore */
|
|
299
|
+
...(ngDevMode ? [{ debugName: "_queueSize" }] : /* istanbul ignore next */ []));
|
|
300
|
+
_injector = inject(Injector);
|
|
301
|
+
/** @inheritDoc */
|
|
302
|
+
loading = computed(() => this._queueSize() > 0, /* @ts-ignore */
|
|
303
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
304
|
+
constructor() {
|
|
305
|
+
inject(DestroyRef).onDestroy(() => {
|
|
306
|
+
this._executor.destroy();
|
|
307
|
+
this._queue.length = 0;
|
|
308
|
+
this._queueSize.set(0);
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
/** @inheritDoc */
|
|
312
|
+
queue(cellValueFn) {
|
|
313
|
+
this._queue.push(cellValueFn);
|
|
314
|
+
this._queueSize.update(size => size + 1);
|
|
315
|
+
this._executor.submit(() => this.whenIdle().then(() => this.preloadQueuedBatch(PRELOAD_BATCH_SIZE)));
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Preloads the next batch of queued cell values, FIFO, then, if the queue is not empty, schedules the next batch.
|
|
319
|
+
*/
|
|
320
|
+
async preloadQueuedBatch(batchSize) {
|
|
321
|
+
this._queue.splice(0, batchSize).forEach(fn => fn());
|
|
322
|
+
this._queueSize.set(this._queue.length);
|
|
323
|
+
// Preload next batch when idle again.
|
|
324
|
+
if (this._queue.length) {
|
|
325
|
+
this._executor.submit(() => this.whenIdle().then(() => this.preloadQueuedBatch(PRELOAD_BATCH_SIZE)));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Resolves when the browser becomes idle.
|
|
330
|
+
*
|
|
331
|
+
* @see onIdle
|
|
332
|
+
*/
|
|
333
|
+
whenIdle() {
|
|
334
|
+
return runInInjectionContext(this._injector, onIdle);
|
|
335
|
+
}
|
|
336
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ɵSciTableCellValuePreloader, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
337
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ɵSciTableCellValuePreloader });
|
|
338
|
+
}
|
|
339
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ɵSciTableCellValuePreloader, decorators: [{
|
|
340
|
+
type: Injectable
|
|
341
|
+
}], ctorParameters: () => [] });
|
|
342
|
+
const PRELOAD_BATCH_SIZE = 50_000;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Preloads cell values in the background when the browser is idle. This prevents lag with large datasets, in particular
|
|
346
|
+
* for expensive computations like formatting dates and generating ISO 8601 strings, providing faster sort and filter performance.
|
|
347
|
+
*
|
|
348
|
+
* If a cell's value is requested before background preloading finishes, it is computed synchronously.
|
|
349
|
+
*/
|
|
350
|
+
class SciTableCellValuePreloader {
|
|
351
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableCellValuePreloader, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
352
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableCellValuePreloader, providedIn: 'root', useClass: ɵSciTableCellValuePreloader });
|
|
353
|
+
}
|
|
354
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableCellValuePreloader, decorators: [{
|
|
355
|
+
type: Injectable,
|
|
356
|
+
args: [{ providedIn: 'root', useClass: ɵSciTableCellValuePreloader }]
|
|
357
|
+
}] });
|
|
358
|
+
|
|
125
359
|
/*
|
|
126
360
|
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
127
361
|
*
|
|
@@ -132,124 +366,188 @@ function provideTableStorage(storage) {
|
|
|
132
366
|
* SPDX-License-Identifier: EPL-2.0
|
|
133
367
|
*/
|
|
134
368
|
function arrayDatasource(data, columns) {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}));
|
|
146
|
-
return {
|
|
147
|
-
items,
|
|
148
|
-
columns: resolvedColumns,
|
|
149
|
-
};
|
|
150
|
-
}));
|
|
151
|
-
return (request) => {
|
|
152
|
-
const sortHash = request.sortCriteria.map(sc => `${sc.columnName}_${sc.direction}`).join('-');
|
|
153
|
-
const filterHash = request.columnFilters.map(fc => `${fc.columnName}_${fc.text}`).join('-');
|
|
154
|
-
const hash = `${sortHash}-${filterHash}-${request.tableFilter ?? ''}`;
|
|
155
|
-
if (!cache().has(hash)) {
|
|
156
|
-
const sortedAndFiltered$ = items$.pipe(map(({ items, columns }) => {
|
|
157
|
-
const sortCols = mapCriteria(request.sortCriteria, columns);
|
|
158
|
-
const filterCols = mapCriteria(request.columnFilters, columns);
|
|
159
|
-
return items
|
|
160
|
-
.filter(item => columnFilter(item, filterCols) && globalFilter(item, request.tableFilter))
|
|
161
|
-
.sort((a, b) => sort(a, b, sortCols));
|
|
162
|
-
}), shareReplay({ bufferSize: 1, refCount: true }));
|
|
163
|
-
// Only store one item in the cache.
|
|
164
|
-
// The cache is used for scrolling and multipage selection.
|
|
165
|
-
// It caches the data based on the current filter and sort.
|
|
166
|
-
cache.set(new Map().set(hash, sortedAndFiltered$));
|
|
167
|
-
}
|
|
168
|
-
return cache().get(hash).pipe(map(items => ({
|
|
169
|
-
totalCount: items.length,
|
|
170
|
-
items: items.slice(request.start, request.end).map(i => i.item),
|
|
369
|
+
const dataset = new Dataset(data, columns);
|
|
370
|
+
return markAsArrayDatasource((request) => {
|
|
371
|
+
dataset.columnFilters.set(request.columnFilters);
|
|
372
|
+
dataset.tableFilter.set(request.tableFilter);
|
|
373
|
+
dataset.sortCriteria.set(request.sortCriteria);
|
|
374
|
+
const totalCount = dataset.count;
|
|
375
|
+
const items = dataset.slice(request.start, request.end);
|
|
376
|
+
return toObservable(computed(() => ({
|
|
377
|
+
totalCount: totalCount(),
|
|
378
|
+
items: items(),
|
|
171
379
|
})));
|
|
172
|
-
};
|
|
380
|
+
});
|
|
173
381
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
382
|
+
/**
|
|
383
|
+
* Provides a filtered and sorted view on given data.
|
|
384
|
+
*/
|
|
385
|
+
class Dataset {
|
|
386
|
+
_dataview;
|
|
387
|
+
columnFilters = signal([], { ...(ngDevMode ? { debugName: "columnFilters" } : /* istanbul ignore next */ {}), equal: Objects.isEqual });
|
|
388
|
+
sortCriteria = signal([], { ...(ngDevMode ? { debugName: "sortCriteria" } : /* istanbul ignore next */ {}), equal: Objects.isEqual });
|
|
389
|
+
tableFilter = signal(undefined, /* @ts-ignore */
|
|
390
|
+
...(ngDevMode ? [{ debugName: "tableFilter" }] : /* istanbul ignore next */ []));
|
|
391
|
+
/**
|
|
392
|
+
* Returns the total count of items matching the current filters and search criteria.
|
|
393
|
+
*/
|
|
394
|
+
count = computed(() => this._dataview().length, /* @ts-ignore */
|
|
395
|
+
...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
396
|
+
constructor(data, columns) {
|
|
397
|
+
const tableCellValuePreloader = inject(SciTableCellValuePreloader);
|
|
398
|
+
const dataset = computed(() => data().map(item => ({
|
|
399
|
+
item,
|
|
400
|
+
cells: columns().reduce((cells, column) => untracked(() => {
|
|
401
|
+
// PERF: Cell values are computed lazily (on idle or first use) to defer expensive computations like date formatting.
|
|
402
|
+
const tableCellValue = 'value' in column ? new eSciTableCellValue(tableCellValuePreloader, () => column.value(item)()) : undefined;
|
|
403
|
+
return cells.set(column.name, {
|
|
404
|
+
column: column,
|
|
405
|
+
value: () => tableCellValue?.value(),
|
|
406
|
+
});
|
|
407
|
+
}), new Map()),
|
|
408
|
+
})), /* @ts-ignore */
|
|
409
|
+
...(ngDevMode ? [{ debugName: "dataset" }] : /* istanbul ignore next */ []));
|
|
410
|
+
// Memoize filtered/sorted view; recomputes only when dataset or criteria change, not when scrolling through the view, as sorting is an expensive operation.
|
|
411
|
+
this._dataview = computed(() => {
|
|
412
|
+
const rows = dataset();
|
|
413
|
+
const columnFilters = this.columnFilters();
|
|
414
|
+
const tableFilter = this.tableFilter();
|
|
415
|
+
const sortCriteria = this.sortCriteria();
|
|
416
|
+
// PERF: Do not track signals inside `Array.sort` to avoid Angular signal tracking overhead as the comparator runs repeatedly, degrading performance otherwise.
|
|
417
|
+
return untracked(() => rows
|
|
418
|
+
.filter(row => matchesRow(row, columnFilters) && matchesGlobalFilter(row, tableFilter))
|
|
419
|
+
.sort((a, b) => compareRows(a, b, sortCriteria))
|
|
420
|
+
.map(row => row.item));
|
|
421
|
+
}, /* @ts-ignore */
|
|
422
|
+
...(ngDevMode ? [{ debugName: "_dataview" }] : /* istanbul ignore next */ []));
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Returns a slice of the filtered and sorted data within the given range (start inclusive, end exclusive).
|
|
426
|
+
*/
|
|
427
|
+
slice(start, end) {
|
|
428
|
+
return computed(() => this._dataview().slice(start, end));
|
|
429
|
+
}
|
|
182
430
|
}
|
|
183
|
-
|
|
431
|
+
/**
|
|
432
|
+
* Tests whether a row matches the given global filter.
|
|
433
|
+
*/
|
|
434
|
+
function matchesGlobalFilter(row, filter) {
|
|
184
435
|
if (!filter?.trim()) {
|
|
185
436
|
return true;
|
|
186
437
|
}
|
|
187
|
-
for (const
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
438
|
+
for (const cell of row.cells.values()) {
|
|
439
|
+
const text = coerceFilterText(filter, { to: cell.column.type });
|
|
440
|
+
if (text === undefined) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
if (matchesRow(row, [{ text, columnName: cell.column.name }])) {
|
|
191
444
|
return true;
|
|
192
445
|
}
|
|
193
446
|
}
|
|
194
447
|
return false;
|
|
195
448
|
}
|
|
196
|
-
|
|
197
|
-
|
|
449
|
+
/**
|
|
450
|
+
* Tests whether a row matches the given column filters.
|
|
451
|
+
*/
|
|
452
|
+
function matchesRow(row, columnFilters) {
|
|
453
|
+
if (!columnFilters.length) {
|
|
198
454
|
return true;
|
|
199
455
|
}
|
|
200
|
-
for (const
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
case 'number':
|
|
207
|
-
return criterion.column.filter(criterion.text, { item: row.item, value: value });
|
|
208
|
-
case 'boolean':
|
|
209
|
-
return criterion.column.filter(criterion.text, { item: row.item, value: value });
|
|
210
|
-
case 'component':
|
|
211
|
-
case 'template':
|
|
212
|
-
return criterion.column.filter(criterion.text, { item: row.item, value: undefined });
|
|
213
|
-
default:
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
})();
|
|
217
|
-
// all filters must match (for now)
|
|
218
|
-
if (!filter) {
|
|
456
|
+
for (const columnFilter of columnFilters) {
|
|
457
|
+
const cell = row.cells.get(columnFilter.columnName);
|
|
458
|
+
if ('value' in cell.column && cell.value() === undefined) { // Component and template columns have no value.
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
if (!cell.column.matches(columnFilter.text, { item: row.item, value: cell.value() })) {
|
|
219
462
|
return false;
|
|
220
463
|
}
|
|
221
464
|
}
|
|
222
465
|
return true;
|
|
223
466
|
}
|
|
224
|
-
|
|
225
|
-
|
|
467
|
+
/**
|
|
468
|
+
* Compares two rows based on the given sort criteria.
|
|
469
|
+
*/
|
|
470
|
+
function compareRows(row1, row2, sortCriteria) {
|
|
471
|
+
if (!sortCriteria.length) {
|
|
226
472
|
return 0;
|
|
227
473
|
}
|
|
228
474
|
for (const criterion of sortCriteria) {
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return 0;
|
|
244
|
-
}
|
|
245
|
-
})();
|
|
246
|
-
if (sort !== 0) {
|
|
247
|
-
const dir = criterion.direction === 'asc' ? 1 : -1;
|
|
248
|
-
return sort * dir;
|
|
475
|
+
const cell1 = row1.cells.get(criterion.columnName);
|
|
476
|
+
const cell2 = row2.cells.get(criterion.columnName);
|
|
477
|
+
const value1 = cell1.value();
|
|
478
|
+
const value2 = cell2.value();
|
|
479
|
+
// Always place `undefined` values at the end, independent of the sort direction. Note that component and template columns have no value.
|
|
480
|
+
if (value1 === undefined && value2 !== undefined) {
|
|
481
|
+
return 1;
|
|
482
|
+
}
|
|
483
|
+
if (value2 === undefined && value1 !== undefined) {
|
|
484
|
+
return -1;
|
|
485
|
+
}
|
|
486
|
+
const comparison = cell1.column.compare({ item: row1.item, value: value1 }, { item: row2.item, value: value2 });
|
|
487
|
+
if (comparison !== 0) {
|
|
488
|
+
return criterion.direction === 'asc' ? comparison : -comparison;
|
|
249
489
|
}
|
|
250
490
|
}
|
|
251
491
|
return 0;
|
|
252
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Checks whether given {@link SciTableDataLoaderFn} represents an {@link arrayDatasource}.
|
|
495
|
+
*/
|
|
496
|
+
function isArrayDatasource(loader) {
|
|
497
|
+
return ARRAY_DATASOURCE_MARKER in loader;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Marks given {@link SciTableDataLoaderFn} as an array data source.
|
|
501
|
+
*/
|
|
502
|
+
function markAsArrayDatasource(loader) {
|
|
503
|
+
Object.defineProperty(loader, ARRAY_DATASOURCE_MARKER, { value: true, writable: false, enumerable: false, configurable: false });
|
|
504
|
+
return loader;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Identifies a {@link SciTableDataLoaderFn} as an {@link arrayDatasource}.
|
|
508
|
+
*/
|
|
509
|
+
const ARRAY_DATASOURCE_MARKER = Symbol('ARRAY_DATASOURCE_HINT');
|
|
510
|
+
/**
|
|
511
|
+
* Coerces the given filter text into the specified column data type.
|
|
512
|
+
*/
|
|
513
|
+
function coerceFilterText(text, options) {
|
|
514
|
+
switch (options.to) {
|
|
515
|
+
case 'number': {
|
|
516
|
+
const number = Number.parseFloat(text);
|
|
517
|
+
return !Number.isNaN(number) ? number : undefined;
|
|
518
|
+
}
|
|
519
|
+
case 'boolean': {
|
|
520
|
+
if (text === 'true' || text === '1') {
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
if (text === 'false' || text === '0') {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
default: {
|
|
529
|
+
return text;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Provides lazy loading for the cell's value, preloading it when idle for better sort/filter performance.
|
|
535
|
+
*
|
|
536
|
+
* The value is computed at most once, whether it gets preloaded during idle time or requested synchronously via {@link value()}.
|
|
537
|
+
*/
|
|
538
|
+
class eSciTableCellValue {
|
|
539
|
+
_valueFn;
|
|
540
|
+
_value;
|
|
541
|
+
constructor(preloader, _valueFn) {
|
|
542
|
+
this._valueFn = _valueFn;
|
|
543
|
+
preloader.queue(() => {
|
|
544
|
+
this._value ??= this._valueFn();
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
value() {
|
|
548
|
+
return this._value ??= untracked(() => this._valueFn());
|
|
549
|
+
}
|
|
550
|
+
}
|
|
253
551
|
|
|
254
552
|
/*
|
|
255
553
|
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
@@ -409,11 +707,14 @@ class ɵSciTable {
|
|
|
409
707
|
scrolling;
|
|
410
708
|
resizing = computed(() => this.columns().some(column => column.resizing()), /* @ts-ignore */
|
|
411
709
|
...(ngDevMode ? [{ debugName: "resizing" }] : /* istanbul ignore next */ []));
|
|
412
|
-
sortCriteria =
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
...(ngDevMode ?
|
|
710
|
+
sortCriteria = linkedSignal({ ...(ngDevMode ? { debugName: "sortCriteria" } : /* istanbul ignore next */ {}), source: () => this.columns(), // Discard stale criteria on column change.
|
|
711
|
+
computation: (columns, previous) => previous?.value.filter(criteria => columns.some(column => column.name === criteria.columnName)) ?? [],
|
|
712
|
+
equal: Objects.isEqual });
|
|
713
|
+
filterCriteria = linkedSignal({ ...(ngDevMode ? { debugName: "filterCriteria" } : /* istanbul ignore next */ {}), source: () => this.columns(), // Discard stale criteria on column change.
|
|
714
|
+
computation: (columns, previous) => previous?.value.filter(criteria => columns.some(column => column.name === criteria.columnName)) ?? [],
|
|
715
|
+
equal: Objects.isEqual });
|
|
416
716
|
_cache = new SciTableCache();
|
|
717
|
+
_tableCellValuePreloader = inject(SciTableCellValuePreloader);
|
|
417
718
|
_tableFilter = signal(null, /* @ts-ignore */
|
|
418
719
|
...(ngDevMode ? [{ debugName: "_tableFilter" }] : /* istanbul ignore next */ []));
|
|
419
720
|
_selectedItems = signal(new Map(), /* @ts-ignore */
|
|
@@ -430,7 +731,8 @@ class ɵSciTable {
|
|
|
430
731
|
computation: () => -1 });
|
|
431
732
|
criteria = computed(() => ({ sort: this.sortCriteria(), filter: this.filterCriteria(), tableFilter: this._tableFilter() }), /* @ts-ignore */
|
|
432
733
|
...(ngDevMode ? [{ debugName: "criteria" }] : /* istanbul ignore next */ []));
|
|
433
|
-
loading = this._cache.loading
|
|
734
|
+
loading = computed(() => this._cache.loading() || this._tableCellValuePreloader.loading(), /* @ts-ignore */
|
|
735
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
434
736
|
error = this._cache.error;
|
|
435
737
|
activeRow;
|
|
436
738
|
hoveredRow = computed(() => this.rowsByIndex().get(this.hoveredIndex()), /* @ts-ignore */
|
|
@@ -494,9 +796,9 @@ class ɵSciTable {
|
|
|
494
796
|
injector?.destroy();
|
|
495
797
|
injector = createDestroyableInjector({ parent: this._injector });
|
|
496
798
|
return runInInjectionContext(injector, () => {
|
|
497
|
-
const tableColumnFactory = new ɵSciTableColumnFactory(
|
|
799
|
+
const tableColumnFactory = new ɵSciTableColumnFactory(this);
|
|
498
800
|
descriptor.columns(tableColumnFactory);
|
|
499
|
-
return
|
|
801
|
+
return tableColumnFactory.columns;
|
|
500
802
|
});
|
|
501
803
|
});
|
|
502
804
|
}
|
|
@@ -573,7 +875,7 @@ class ɵSciTable {
|
|
|
573
875
|
defaultValue: 0,
|
|
574
876
|
params: () => this.tableViewRef()?.viewport,
|
|
575
877
|
stream: ({ params: viewport }) => fromEvent(viewport, 'scroll', { passive: true })
|
|
576
|
-
.pipe(map
|
|
878
|
+
.pipe(map(() => viewport.scrollTop), startWith(viewport.scrollTop), subscribeIn(fn => zone.runOutsideAngular(fn))),
|
|
577
879
|
}).value;
|
|
578
880
|
}
|
|
579
881
|
/**
|
|
@@ -585,7 +887,7 @@ class ɵSciTable {
|
|
|
585
887
|
defaultValue: false,
|
|
586
888
|
params: () => this.tableViewRef()?.viewport,
|
|
587
889
|
stream: ({ params: viewport }) => fromEvent(viewport, 'scroll', { passive: true })
|
|
588
|
-
.pipe(switchMap(() => concat(of(true), timer(150).pipe(map
|
|
890
|
+
.pipe(switchMap(() => concat(of(true), timer(150).pipe(map(() => false)))), startWith(false), subscribeIn(fn => zone.runOutsideAngular(fn))),
|
|
589
891
|
}).value;
|
|
590
892
|
}
|
|
591
893
|
/**
|
|
@@ -631,32 +933,22 @@ class ɵSciTable {
|
|
|
631
933
|
tableFilter,
|
|
632
934
|
columnFilters,
|
|
633
935
|
})), error => throwError(() => error));
|
|
936
|
+
const columns$ = toObservable(this.columns);
|
|
634
937
|
// Create a resource to track loading and error states.
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
// Synchronize total row count based on resource state.
|
|
644
|
-
effect(() => {
|
|
645
|
-
switch (rows.status()) {
|
|
646
|
-
case 'resolved': {
|
|
647
|
-
// Update count only after rows resolve to prevent premature scroll invalidation.
|
|
648
|
-
this.totalCount.set(tableResponse.value()?.totalCount);
|
|
649
|
-
break;
|
|
650
|
-
}
|
|
651
|
-
case 'error': {
|
|
652
|
-
console.error(rows.error().cause);
|
|
938
|
+
return rxResource({
|
|
939
|
+
stream: () => tableResponse$.pipe(combineLatestWith(columns$), map(([response, columns]) => ({
|
|
940
|
+
rows: this.mapItemsToRow(response.items, columns, pageStart),
|
|
941
|
+
totalCount: response.totalCount,
|
|
942
|
+
})), tap({
|
|
943
|
+
next: ({ totalCount }) => this.totalCount.set(totalCount),
|
|
944
|
+
error: error => {
|
|
945
|
+
console.error(error);
|
|
653
946
|
// Reset count to scroll to the top so the user sees the error.
|
|
654
947
|
this.totalCount.set(0);
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
948
|
+
},
|
|
949
|
+
}), map(({ rows }) => rows)),
|
|
950
|
+
defaultValue: [],
|
|
658
951
|
});
|
|
659
|
-
return rows;
|
|
660
952
|
}),
|
|
661
953
|
dispose: () => cacheEntryInjector.destroy(),
|
|
662
954
|
start: pageStart,
|
|
@@ -715,6 +1007,14 @@ class ɵSciTable {
|
|
|
715
1007
|
updateSelectedItems(updateFn) {
|
|
716
1008
|
this._selectedItems.update(updateFn);
|
|
717
1009
|
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Indicates whether the built-in array datasource is used.
|
|
1012
|
+
*
|
|
1013
|
+
* Supports out-of-the-box filtering and sorting for built-in table columns.
|
|
1014
|
+
*/
|
|
1015
|
+
isArrayDatasource() {
|
|
1016
|
+
return isArrayDatasource(this._dataLoaderFn);
|
|
1017
|
+
}
|
|
718
1018
|
reset() {
|
|
719
1019
|
this._cache.clear();
|
|
720
1020
|
this.totalCount.set(undefined);
|
|
@@ -761,32 +1061,6 @@ class ɵSciTable {
|
|
|
761
1061
|
this._cache.clear();
|
|
762
1062
|
});
|
|
763
1063
|
}
|
|
764
|
-
// TODO [dwi] Consider moving into factory
|
|
765
|
-
initColumn(type, config) {
|
|
766
|
-
// Columns with a custom component or template must provide a sort function to be sortable, because the default sort function does not work.
|
|
767
|
-
const sortable = type === 'component' || type === 'template' ? !!config.sortable : config.sortable !== false;
|
|
768
|
-
// Columns with a custom component or template must provide a filter function to be filterable, because the default filter function does not work.
|
|
769
|
-
const filterable = type === 'component' || type === 'template' ? !!config.filterable : config.filterable !== false;
|
|
770
|
-
return {
|
|
771
|
-
...config,
|
|
772
|
-
type,
|
|
773
|
-
name: config.name,
|
|
774
|
-
filter: typeof config.filterable === 'object' ? config.filterable.matcher : defaultFilter,
|
|
775
|
-
sort: typeof config.sortable === 'object' ? config.sortable.comparator : defaultSort,
|
|
776
|
-
sortable: computed(() => this.sortable() && sortable),
|
|
777
|
-
filterable: computed(() => this.filterable() && filterable),
|
|
778
|
-
resizable: computed(() => this.resizable() && (config.resizable ?? true)),
|
|
779
|
-
padding: 'padding' in config ? (config.padding ?? true) : true,
|
|
780
|
-
header: coerceSignal(config.header ?? ''),
|
|
781
|
-
width: computed(() => {
|
|
782
|
-
const userSettings = this.userSettings().columns?.find(column => column.name === config.name);
|
|
783
|
-
return userSettings?.width ? `${userSettings.width}px` : config.width ?? '1fr';
|
|
784
|
-
}),
|
|
785
|
-
minWidth: config.minWidth ?? 100,
|
|
786
|
-
resizing: signal(false),
|
|
787
|
-
location: { x: 0, width: 0 }, // injected in `SciColumnComponent`
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
1064
|
mapItemsToRow(items, columns, pageStart) {
|
|
791
1065
|
return items.map((item, i) => {
|
|
792
1066
|
const id = this.trackBy(item);
|
|
@@ -801,7 +1075,7 @@ class ɵSciTable {
|
|
|
801
1075
|
hovered: computed(() => this.hoveredRow()?.index === index),
|
|
802
1076
|
bindings: coerceTableRowBindings(this._rowBindings, item, pageStart + i),
|
|
803
1077
|
cells: columns.map(column => ({
|
|
804
|
-
value:
|
|
1078
|
+
value: 'value' in column ? column.value(item) : undefined,
|
|
805
1079
|
component: column.type === 'component' ? column.component(item) : undefined,
|
|
806
1080
|
template: column.type === 'template' ? column.template(item) : undefined,
|
|
807
1081
|
type: column.type,
|
|
@@ -855,32 +1129,6 @@ class ɵSciTable {
|
|
|
855
1129
|
});
|
|
856
1130
|
}
|
|
857
1131
|
}
|
|
858
|
-
function defaultFilter(text, { value }) {
|
|
859
|
-
if (typeof value !== typeof text) {
|
|
860
|
-
return false;
|
|
861
|
-
}
|
|
862
|
-
switch (typeof value) {
|
|
863
|
-
case 'string':
|
|
864
|
-
return value.toLowerCase().includes(text.toLowerCase());
|
|
865
|
-
default:
|
|
866
|
-
return text === value;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
function defaultSort(a, b) {
|
|
870
|
-
if (typeof a.value !== typeof b.value) {
|
|
871
|
-
return 0;
|
|
872
|
-
}
|
|
873
|
-
switch (typeof a.value) {
|
|
874
|
-
case 'string':
|
|
875
|
-
return a.value.localeCompare(b.value);
|
|
876
|
-
case 'number':
|
|
877
|
-
return a.value - b.value;
|
|
878
|
-
case 'boolean':
|
|
879
|
-
return a.value === b.value ? 0 : (a.value ? 1 : -1);
|
|
880
|
-
default:
|
|
881
|
-
return 0;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
1132
|
/**
|
|
885
1133
|
* Gets pages by range and page size, or `null` if empty. End is exclusive.
|
|
886
1134
|
*/
|
|
@@ -1383,6 +1631,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
1383
1631
|
type: Injectable
|
|
1384
1632
|
}] });
|
|
1385
1633
|
|
|
1634
|
+
/*
|
|
1635
|
+
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
1636
|
+
*
|
|
1637
|
+
* This program and the accompanying materials are made
|
|
1638
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
1639
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
1640
|
+
*
|
|
1641
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
1642
|
+
*/
|
|
1643
|
+
/**
|
|
1644
|
+
* Formats a given number based on the provided {@link Intl.NumberFormat}.
|
|
1645
|
+
*/
|
|
1646
|
+
class SciNumberPipe {
|
|
1647
|
+
transform(number, format) {
|
|
1648
|
+
return number !== undefined ? format.format(number) : undefined;
|
|
1649
|
+
}
|
|
1650
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciNumberPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1651
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.7", ngImport: i0, type: SciNumberPipe, isStandalone: true, name: "sciNumber" });
|
|
1652
|
+
}
|
|
1653
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciNumberPipe, decorators: [{
|
|
1654
|
+
type: Pipe,
|
|
1655
|
+
args: [{ name: 'sciNumber' }]
|
|
1656
|
+
}] });
|
|
1657
|
+
|
|
1386
1658
|
/*
|
|
1387
1659
|
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
1388
1660
|
*
|
|
@@ -1427,14 +1699,22 @@ class SciTableCellComponent {
|
|
|
1427
1699
|
}
|
|
1428
1700
|
computePartAttribute() {
|
|
1429
1701
|
return computed(() => {
|
|
1430
|
-
return [
|
|
1431
|
-
|
|
1702
|
+
return Arrays.distinct([
|
|
1703
|
+
// Enable column styling based on column type.
|
|
1704
|
+
`column:${this.cell().column.type}`,
|
|
1705
|
+
// Enable column styling based on column name.
|
|
1432
1706
|
this.cell().column.name,
|
|
1433
|
-
|
|
1707
|
+
// Enable row styling based on selection state.
|
|
1708
|
+
this.row().selected() ? 'row:selected' : 'row:not:selected',
|
|
1709
|
+
// Enable row styling based on active state.
|
|
1710
|
+
this.row().active() ? 'row:active' : 'row:not:active',
|
|
1711
|
+
// Enable row styling based on row bindings.
|
|
1712
|
+
...Arrays.coerce(this.row().bindings?.part()),
|
|
1713
|
+
]).join(' ');
|
|
1434
1714
|
});
|
|
1435
1715
|
}
|
|
1436
1716
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1437
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: SciTableCellComponent, isStandalone: true, selector: "sci-table-cell", inputs: { cell: { classPropertyName: "cell", publicName: "cell", isSignal: true, isRequired: true, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "attr.data-type": "cell().column.type", "attr.data-column": "cell().column.name", "attr.data-padding": "!cell().column.padding ? false : null", "attr.part": "
|
|
1717
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: SciTableCellComponent, isStandalone: true, selector: "sci-table-cell", inputs: { cell: { classPropertyName: "cell", publicName: "cell", isSignal: true, isRequired: true, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "attr.data-type": "cell().column.type", "attr.data-column": "cell().column.name", "attr.data-padding": "!cell().column.padding ? false : null", "attr.part": "partAttribute()" } }, ngImport: i0, template: "@let cell = this.cell();\n\n@switch (cell.type) {\n @case ('template') {\n <ng-template *ngTemplateOutlet=\"template(); context: templateContext()\"/>\n }\n @case ('component') {\n <ng-container *sciComponentOutlet=\"cell.component\"/>\n }\n @case ('boolean') {\n @if (cell.value() !== undefined) {\n <!-- TODO [dwi] Use another ligature for icon scion.clear -->\n <sci-icon class=\"checkbox\">{{cell.value() ? 'scion.checkmark' : 'scion.clear'}}</sci-icon>\n }\n }\n @case ('date') {\n {{cell.value()?.formatted}}\n }\n @case ('number') {\n {{cell.value() | sciNumber:cell.column.format()}}\n }\n @default {\n {{cell.value()}}\n }\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline-grid;position:relative;border-inline:var(--\\275sci-table-cell-padding-inline) solid transparent;align-items:center;overflow:hidden}:host:is([data-type=string],[data-type=number],[data-type=date]){display:inline;white-space:nowrap;text-overflow:ellipsis;line-height:var(--\\275sci-table-row-height)}:host[data-type=number]{text-align:end}:host:is([data-type=number],[data-type=date]){font-variant-numeric:tabular-nums}:host[data-padding=false]{border-inline:none;align-items:stretch}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SciIconComponent, selector: "sci-icon" }, { kind: "directive", type: SciComponentOutletDirective, selector: "ng-template[sciComponentOutlet]", inputs: ["sciComponentOutlet"] }, { kind: "pipe", type: SciNumberPipe, name: "sciNumber" }] });
|
|
1438
1718
|
}
|
|
1439
1719
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableCellComponent, decorators: [{
|
|
1440
1720
|
type: Component,
|
|
@@ -1442,12 +1722,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
1442
1722
|
'[attr.data-type]': 'cell().column.type',
|
|
1443
1723
|
'[attr.data-column]': 'cell().column.name',
|
|
1444
1724
|
'[attr.data-padding]': '!cell().column.padding ? false : null',
|
|
1445
|
-
'[attr.part]': '
|
|
1725
|
+
'[attr.part]': 'partAttribute()',
|
|
1446
1726
|
}, imports: [
|
|
1447
1727
|
NgTemplateOutlet,
|
|
1448
1728
|
SciIconComponent,
|
|
1449
1729
|
SciComponentOutletDirective,
|
|
1450
|
-
|
|
1730
|
+
SciNumberPipe,
|
|
1731
|
+
], template: "@let cell = this.cell();\n\n@switch (cell.type) {\n @case ('template') {\n <ng-template *ngTemplateOutlet=\"template(); context: templateContext()\"/>\n }\n @case ('component') {\n <ng-container *sciComponentOutlet=\"cell.component\"/>\n }\n @case ('boolean') {\n @if (cell.value() !== undefined) {\n <!-- TODO [dwi] Use another ligature for icon scion.clear -->\n <sci-icon class=\"checkbox\">{{cell.value() ? 'scion.checkmark' : 'scion.clear'}}</sci-icon>\n }\n }\n @case ('date') {\n {{cell.value()?.formatted}}\n }\n @case ('number') {\n {{cell.value() | sciNumber:cell.column.format()}}\n }\n @default {\n {{cell.value()}}\n }\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline-grid;position:relative;border-inline:var(--\\275sci-table-cell-padding-inline) solid transparent;align-items:center;overflow:hidden}:host:is([data-type=string],[data-type=number],[data-type=date]){display:inline;white-space:nowrap;text-overflow:ellipsis;line-height:var(--\\275sci-table-row-height)}:host[data-type=number]{text-align:end}:host:is([data-type=number],[data-type=date]){font-variant-numeric:tabular-nums}:host[data-padding=false]{border-inline:none;align-items:stretch}\n"] }]
|
|
1451
1732
|
}], propDecorators: { cell: [{ type: i0.Input, args: [{ isSignal: true, alias: "cell", required: true }] }], row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }] } });
|
|
1452
1733
|
|
|
1453
1734
|
/*
|
|
@@ -1489,7 +1770,7 @@ class SciTableRowComponent {
|
|
|
1489
1770
|
onRowMouseLeave(event) {
|
|
1490
1771
|
const next = event.relatedTarget;
|
|
1491
1772
|
// Do not unset hovered row when hovering a column resize splitter.
|
|
1492
|
-
if (next instanceof Element && next.closest('sci-
|
|
1773
|
+
if (next instanceof Element && next.closest('sci-splitter')) {
|
|
1493
1774
|
return;
|
|
1494
1775
|
}
|
|
1495
1776
|
this.table().hoveredIndex.set(-1);
|
|
@@ -1507,7 +1788,7 @@ class SciTableRowComponent {
|
|
|
1507
1788
|
});
|
|
1508
1789
|
}
|
|
1509
1790
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1510
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: SciTableRowComponent, isStandalone: true, selector: "sci-table-row", inputs: { row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { primaryAction: "primaryAction" }, host: { listeners: { "click": "onRowClick($event)", "dblclick": "onRowDblClick($event)", "mouseenter": "onRowMouseEnter()", "mouseleave": "onRowMouseLeave($event)" }, properties: { "attr.data-active": "row().active() ? '' : null", "attr.data-selected": "row().selected() ? '' : null", "attr.data-hovered": "row().hovered() ? '' : null", "class": "row().bindings?.cssClass?.()" } }, viewQueries: [{ propertyName: "rowActionToolbar", first: true, predicate: SciToolbarComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let row = this.row();\n@for (cell of row.cells; track cell.column.name) {\n <sci-table-cell [cell]=\"cell\" [row]=\"row\"/>\n} @empty {\n @for (column of table().columns(); track column.name) {\n <div class=\"skeleton e2e-skeleton\" [attr.data-column]=\"column.name\"></div>\n }\n}\n\n@let hasRowActions = !!table().rowActions;\n@let isRowHovered = table().hoveredRow() === row;\n@let isRowActionMenuOpen = rowActionToolbar()?.menuOpen();\n\n@if (hasRowActions && (isRowHovered || isRowActionMenuOpen)) {\n
|
|
1791
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: SciTableRowComponent, isStandalone: true, selector: "sci-table-row", inputs: { row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { primaryAction: "primaryAction" }, host: { listeners: { "click": "onRowClick($event)", "dblclick": "onRowDblClick($event)", "mouseenter": "onRowMouseEnter()", "mouseleave": "onRowMouseLeave($event)" }, properties: { "attr.data-active": "row().active() ? '' : null", "attr.data-selected": "row().selected() ? '' : null", "attr.data-hovered": "row().hovered() ? '' : null", "class": "row().bindings?.cssClass?.()" } }, viewQueries: [{ propertyName: "rowActionToolbar", first: true, predicate: SciToolbarComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let row = this.row();\n@for (cell of row.cells; track cell.column.name) {\n <sci-table-cell [cell]=\"cell\" [row]=\"row\"/>\n} @empty {\n @for (column of table().columns(); track column.name) {\n <div class=\"skeleton e2e-skeleton\" [attr.data-column]=\"column.name\"></div>\n }\n}\n\n@let hasRowActions = !!table().rowActions;\n@let isRowHovered = table().hoveredRow() === row;\n@let isRowActionMenuOpen = rowActionToolbar()?.menuOpen();\n\n@if (hasRowActions && (isRowHovered || isRowActionMenuOpen)) {\n <sci-toolbar [name]=\"rowActionsToolbarName\" (click)=\"onActionToolbarClick($event)\" class=\"row-actions\"/>\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline-grid;grid-template-columns:subgrid;grid-auto-rows:var(--sci-table-row-height);align-items:stretch;-webkit-user-select:none;user-select:none;border-bottom:var(--\\275sci-table-border-size) solid var(--sci-table-gridline-color)}:host[data-hovered]{background-color:var(--sci-table-row-background-color-hover)}:host[data-selected]{background-color:var(--sci-table-row-background-color-selected);--\\275sci-table-row-selected: true}:host[data-hovered]:not([data-selected]){border-radius:var(--sci-table-row-border-radius)}:host:is(:first-child,:not([data-selected])+sci-table-row)[data-selected]{border-top-left-radius:var(--sci-table-row-border-radius);border-top-right-radius:var(--sci-table-row-border-radius)}:host[data-selected]:not(:has(+sci-table-row[data-selected])){border-bottom-left-radius:var(--sci-table-row-border-radius);border-bottom-right-radius:var(--sci-table-row-border-radius)}@container (style(--\\275sci-table-scrolling: true)) or (style(--\\275sci-table-resizing: true)){:host{pointer-events:none}}:host:has(>div.skeleton){pointer-events:none;align-items:center}:host:has(>div.skeleton)>div.skeleton{display:inline-block;position:relative;overflow:hidden;border-radius:var(--sci-corner-small);background-color:var(--sci-color-skeleton-subtle);opacity:0;animation-name:visiblity;animation-duration:.5s;animation-timing-function:ease-in;animation-fill-mode:forwards}:host:has(>div.skeleton)>div.skeleton:after{position:absolute;inset:0;transform:translate(-100%);background-image:linear-gradient(to right,transparent 0,color-mix(in srgb,light-dark(var(--sci-static-color-white),var(--sci-static-color-black)) 30%,transparent) 50%,transparent);animation:shimmer 2s infinite;content:\"\"}@keyframes shimmer{to{transform:translate(100%)}}@keyframes visiblity{to{opacity:1}}:host:has(>div.skeleton)>div.skeleton{height:1em;margin-inline:var(--\\275sci-table-cell-padding-inline)}:host>sci-toolbar.row-actions{position:sticky;right:0;transform:translate(calc(-1 * var(--\\275sci-table-cell-padding-inline)));justify-self:end;align-self:center;border-radius:var(--sci-corner);padding:1px;background-color:var(--\\275sci-table-row-action-background-color);z-index:2;--sci-toolbar-item-background-color-hover: color-mix(in srgb, var(--\\275sci-table-row-action-background-color) 85%, light-dark(var(--sci-static-color-black), var(--sci-static-color-white)));--sci-toolbar-item-background-color-active: color-mix(in srgb, var(--\\275sci-table-row-action-background-color) 75%, light-dark(var(--sci-static-color-black), var(--sci-static-color-white)))}@container not style(--\\275sci-table-row-selected: true){:host>sci-toolbar.row-actions{--\\275sci-table-row-action-background-color: var(--sci-table-row-action-background-color)}}@container style(--\\275sci-table-row-selected: true){:host>sci-toolbar.row-actions{--\\275sci-table-row-action-background-color: var(--sci-table-row-action-background-color-selected)}}:host>sci-toolbar.row-actions:empty{display:none}\n"], dependencies: [{ kind: "component", type: SciTableCellComponent, selector: "sci-table-cell", inputs: ["cell", "row"] }, { kind: "component", type: SciToolbarComponent, selector: "sci-toolbar", inputs: ["name", "orientation", "context", "acceleratorTarget", "popoverViewContainerRef"] }] });
|
|
1511
1792
|
}
|
|
1512
1793
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableRowComponent, decorators: [{
|
|
1513
1794
|
type: Component,
|
|
@@ -1523,7 +1804,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
1523
1804
|
'(dblclick)': 'onRowDblClick($event)',
|
|
1524
1805
|
'(mouseenter)': 'onRowMouseEnter()',
|
|
1525
1806
|
'(mouseleave)': 'onRowMouseLeave($event)',
|
|
1526
|
-
}, template: "@let row = this.row();\n@for (cell of row.cells; track cell.column.name) {\n <sci-table-cell [cell]=\"cell\" [row]=\"row\"/>\n} @empty {\n @for (column of table().columns(); track column.name) {\n <div class=\"skeleton e2e-skeleton\" [attr.data-column]=\"column.name\"></div>\n }\n}\n\n@let hasRowActions = !!table().rowActions;\n@let isRowHovered = table().hoveredRow() === row;\n@let isRowActionMenuOpen = rowActionToolbar()?.menuOpen();\n\n@if (hasRowActions && (isRowHovered || isRowActionMenuOpen)) {\n
|
|
1807
|
+
}, template: "@let row = this.row();\n@for (cell of row.cells; track cell.column.name) {\n <sci-table-cell [cell]=\"cell\" [row]=\"row\"/>\n} @empty {\n @for (column of table().columns(); track column.name) {\n <div class=\"skeleton e2e-skeleton\" [attr.data-column]=\"column.name\"></div>\n }\n}\n\n@let hasRowActions = !!table().rowActions;\n@let isRowHovered = table().hoveredRow() === row;\n@let isRowActionMenuOpen = rowActionToolbar()?.menuOpen();\n\n@if (hasRowActions && (isRowHovered || isRowActionMenuOpen)) {\n <sci-toolbar [name]=\"rowActionsToolbarName\" (click)=\"onActionToolbarClick($event)\" class=\"row-actions\"/>\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline-grid;grid-template-columns:subgrid;grid-auto-rows:var(--sci-table-row-height);align-items:stretch;-webkit-user-select:none;user-select:none;border-bottom:var(--\\275sci-table-border-size) solid var(--sci-table-gridline-color)}:host[data-hovered]{background-color:var(--sci-table-row-background-color-hover)}:host[data-selected]{background-color:var(--sci-table-row-background-color-selected);--\\275sci-table-row-selected: true}:host[data-hovered]:not([data-selected]){border-radius:var(--sci-table-row-border-radius)}:host:is(:first-child,:not([data-selected])+sci-table-row)[data-selected]{border-top-left-radius:var(--sci-table-row-border-radius);border-top-right-radius:var(--sci-table-row-border-radius)}:host[data-selected]:not(:has(+sci-table-row[data-selected])){border-bottom-left-radius:var(--sci-table-row-border-radius);border-bottom-right-radius:var(--sci-table-row-border-radius)}@container (style(--\\275sci-table-scrolling: true)) or (style(--\\275sci-table-resizing: true)){:host{pointer-events:none}}:host:has(>div.skeleton){pointer-events:none;align-items:center}:host:has(>div.skeleton)>div.skeleton{display:inline-block;position:relative;overflow:hidden;border-radius:var(--sci-corner-small);background-color:var(--sci-color-skeleton-subtle);opacity:0;animation-name:visiblity;animation-duration:.5s;animation-timing-function:ease-in;animation-fill-mode:forwards}:host:has(>div.skeleton)>div.skeleton:after{position:absolute;inset:0;transform:translate(-100%);background-image:linear-gradient(to right,transparent 0,color-mix(in srgb,light-dark(var(--sci-static-color-white),var(--sci-static-color-black)) 30%,transparent) 50%,transparent);animation:shimmer 2s infinite;content:\"\"}@keyframes shimmer{to{transform:translate(100%)}}@keyframes visiblity{to{opacity:1}}:host:has(>div.skeleton)>div.skeleton{height:1em;margin-inline:var(--\\275sci-table-cell-padding-inline)}:host>sci-toolbar.row-actions{position:sticky;right:0;transform:translate(calc(-1 * var(--\\275sci-table-cell-padding-inline)));justify-self:end;align-self:center;border-radius:var(--sci-corner);padding:1px;background-color:var(--\\275sci-table-row-action-background-color);z-index:2;--sci-toolbar-item-background-color-hover: color-mix(in srgb, var(--\\275sci-table-row-action-background-color) 85%, light-dark(var(--sci-static-color-black), var(--sci-static-color-white)));--sci-toolbar-item-background-color-active: color-mix(in srgb, var(--\\275sci-table-row-action-background-color) 75%, light-dark(var(--sci-static-color-black), var(--sci-static-color-white)))}@container not style(--\\275sci-table-row-selected: true){:host>sci-toolbar.row-actions{--\\275sci-table-row-action-background-color: var(--sci-table-row-action-background-color)}}@container style(--\\275sci-table-row-selected: true){:host>sci-toolbar.row-actions{--\\275sci-table-row-action-background-color: var(--sci-table-row-action-background-color-selected)}}:host>sci-toolbar.row-actions:empty{display:none}\n"] }]
|
|
1527
1808
|
}], ctorParameters: () => [], propDecorators: { row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }], primaryAction: [{ type: i0.Output, args: ["primaryAction"] }], rowActionToolbar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SciToolbarComponent), { isSignal: true }] }] } });
|
|
1528
1809
|
|
|
1529
1810
|
/*
|
|
@@ -2214,7 +2495,7 @@ class SciTableComponent {
|
|
|
2214
2495
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: SciTableComponent, isStandalone: true, selector: "sci-table", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, table: { classPropertyName: "table", publicName: "table", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { primaryAction: "primaryAction" }, host: { properties: { "attr.name": "name()", "style.--\u0275sci-table-scrolling": "table().scrolling() ? `true` : null", "style.--\u0275sci-table-resizing": "table().resizing() ? `true` : null" } }, providers: [
|
|
2215
2496
|
provideSciTable(),
|
|
2216
2497
|
SciTableSelectionService,
|
|
2217
|
-
], viewQueries: [{ propertyName: "_viewport", first: true, predicate: SciTableViewportComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_viewportClient", first: true, predicate: SciTableGridComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_tableHeader", first: true, predicate: SciTableHeaderComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_tableBody", first: true, predicate: SciTableBodyComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_itemSizeSyntheticElement", first: true, predicate: ["item_size_synthetic_element"], descendants: true, isSignal: true }, { propertyName: "_cellPaddingSyntheticElement", first: true, predicate: ["cell_padding_synthetic_element"], descendants: true, isSignal: true }, { propertyName: "rows", predicate: SciTableRowComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let table = this.table();\n\n<sci-table-viewport #viewport>\n <sci-table-grid>\n <!-- Table header -->\n @if (table.showHeader() || table.filterable()) {\n <sci-table-header/>\n }\n\n <!-- Table body -->\n <sci-table-body sciTableKeyboardNavigator>\n @if (!table.error()) {\n <!-- Track index to reuse the table row elements -->\n @for (row of table.rows(); track $index) {\n <sci-table-row [row]=\"row\" (primaryAction)=\"onRowPrimaryAction($event)\" [sciAttributes]=\"row.bindings?.attributes()\"/>\n } @empty {\n <span class=\"message e2e-no-data\">{{('%scion.components.no_items.message' | sciText)()}}</span>\n }\n } @else {\n <span class=\"message e2e-datasource\">\n {{('%scion.components.datasource_error.message' | sciText)()}}\n\n <button (click)=\"onRetry()\" class=\"action e2e-datasource-retry\">\n <!-- TODO [dwi] Replace with SCION icon -->\n <sci-icon>refresh</sci-icon>\n <span>{{('%scion.components.retry.label' | sciText)()}}</span>\n </button>\n </span>\n }\n\n <!-- Render active row outline separately to preserve row border-radius within block selection. -->\n @if (table.activeRow()) {\n <div class=\"active-row-outline e2e-active-row-outline\"></div>\n }\n </sci-table-body>\n\n <!-- Render column splitters. -->\n <sci-table-columns [rows]=\"rows()\"/>\n </sci-table-grid>\n</sci-table-viewport>\n\n<!-- Scrollbars -->\n<sci-scrollbar direction=\"hscroll\" [viewport]=\"viewport.host\"/>\n<sci-scrollbar direction=\"vscroll\" [viewport]=\"viewport.host\"/>\n\n@if (table.loading()) {\n <sci-throbber type=\"spinner\"/>\n}\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-row-height`, relative to the table's font size if em-based. -->\n<div class=\"synthetic item-size\" #item_size_synthetic_element></div>\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-cell-padding-inline`, relative to the table's font size if em-based. -->\n<div class=\"synthetic cell-padding\" #cell_padding_synthetic_element></div>\n", styles: ["@charset \"UTF-8\";:host{display:block;overflow:hidden;--\\275sci-table-border-size: 1px;--\\275sci-table-border-color: var(--sci-color-border)}:host:is(:not(:hover):not(:active),:host(:not(:hover):not(:active))) sci-scrollbar:not(.scrolling){opacity:0}:host>sci-table-viewport{display:block;position:relative;height:100%;overflow:auto;scrollbar-width:none;isolation:isolate;box-sizing:border-box;anchor-name:--sci-table-viewport}:host>sci-table-viewport:has(sci-table-header){--\\275sci-table-header-visible: true}:host>sci-table-viewport:has(sci-table-header>sci-column-header){--\\275sci-column-header-visible: true}:host>sci-table-viewport:has(~sci-scrollbar.scrolling){--\\275sci-table-scrolling: true}:host>sci-table-viewport>sci-table-grid{display:grid;grid-template-columns:var(--\\275sci-table-columns, repeat(auto-fit,
|
|
2498
|
+
], viewQueries: [{ propertyName: "_viewport", first: true, predicate: SciTableViewportComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_viewportClient", first: true, predicate: SciTableGridComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_tableHeader", first: true, predicate: SciTableHeaderComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_tableBody", first: true, predicate: SciTableBodyComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_itemSizeSyntheticElement", first: true, predicate: ["item_size_synthetic_element"], descendants: true, isSignal: true }, { propertyName: "_cellPaddingSyntheticElement", first: true, predicate: ["cell_padding_synthetic_element"], descendants: true, isSignal: true }, { propertyName: "rows", predicate: SciTableRowComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let table = this.table();\n\n<sci-table-viewport #viewport>\n <sci-table-grid>\n <!-- Table header -->\n @if (table.showHeader() || table.filterable()) {\n <sci-table-header/>\n }\n\n <!-- Table body -->\n <sci-table-body sciTableKeyboardNavigator>\n @if (!table.error()) {\n <!-- Track index to reuse the table row elements -->\n @for (row of table.rows(); track $index) {\n <sci-table-row [row]=\"row\" (primaryAction)=\"onRowPrimaryAction($event)\" [sciAttributes]=\"row.bindings?.attributes()\"/>\n } @empty {\n <span class=\"message e2e-no-data\">{{('%scion.components.no_items.message' | sciText)()}}</span>\n }\n } @else {\n <span class=\"message e2e-datasource\">\n {{('%scion.components.datasource_error.message' | sciText)()}}\n\n <button (click)=\"onRetry()\" class=\"action e2e-datasource-retry\">\n <!-- TODO [dwi] Replace with SCION icon -->\n <sci-icon>refresh</sci-icon>\n <span>{{('%scion.components.retry.label' | sciText)()}}</span>\n </button>\n </span>\n }\n\n <!-- Render active row outline separately to preserve row border-radius within block selection. -->\n @if (table.activeRow()) {\n <div class=\"active-row-outline e2e-active-row-outline\"></div>\n }\n </sci-table-body>\n\n <!-- Render column splitters. -->\n <sci-table-columns [rows]=\"rows()\"/>\n </sci-table-grid>\n</sci-table-viewport>\n\n<!-- Scrollbars -->\n<sci-scrollbar direction=\"hscroll\" [viewport]=\"viewport.host\"/>\n<sci-scrollbar direction=\"vscroll\" [viewport]=\"viewport.host\"/>\n\n@if (table.loading()) {\n <sci-throbber type=\"spinner\" class=\"loading-indicator e2e-loading-indicator\"/>\n}\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-row-height`, relative to the table's font size if em-based. -->\n<div class=\"synthetic item-size\" #item_size_synthetic_element></div>\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-cell-padding-inline`, relative to the table's font size if em-based. -->\n<div class=\"synthetic cell-padding\" #cell_padding_synthetic_element></div>\n", styles: ["@charset \"UTF-8\";:host{display:block;overflow:hidden;--\\275sci-table-border-size: 1px;--\\275sci-table-border-color: var(--sci-color-border)}:host:is(:not(:hover):not(:active),:host(:not(:hover):not(:active))) sci-scrollbar:not(.scrolling){opacity:0}:host>sci-table-viewport{display:block;position:relative;height:100%;overflow:auto;scrollbar-width:none;isolation:isolate;box-sizing:border-box;anchor-name:--sci-table-viewport}:host>sci-table-viewport:has(sci-table-header){--\\275sci-table-header-visible: true}:host>sci-table-viewport:has(sci-table-header>sci-column-header){--\\275sci-column-header-visible: true}:host>sci-table-viewport:has(~sci-scrollbar.scrolling){--\\275sci-table-scrolling: true}:host>sci-table-viewport>sci-table-grid{display:grid;grid-template-columns:var(--\\275sci-table-columns, repeat(auto-fit, 100px)) 0;grid-auto-rows:min-content;grid-template-rows:min-content 1fr;width:min-content;min-width:100%;min-height:100%}@container not style(--\\275sci-table-header-visible: true){:host>sci-table-viewport>sci-table-grid{grid-template-rows:1fr}}:host>sci-table-viewport>sci-table-grid>sci-table-header{z-index:1;grid-row:1;grid-column:1/-1;position:sticky;top:0}:host>sci-table-viewport>sci-table-grid>sci-table-body{anchor-name:--sci-table-body;grid-row:2}@container not style(--\\275sci-table-header-visible: true){:host>sci-table-viewport>sci-table-grid>sci-table-body{grid-row:1}}:host>sci-table-viewport>sci-table-grid>sci-table-body{display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-auto-rows:var(--sci-table-row-height);outline:none;padding-top:var(--\\275sci-table-virtual-scroll-offset-top);padding-bottom:var(--\\275sci-table-virtual-scroll-offset-bottom)}:host>sci-table-viewport>sci-table-grid>sci-table-body>sci-table-row{grid-column:1/-1}:host>sci-table-viewport>sci-table-grid>sci-table-body>sci-table-row[data-active]{anchor-name:--sci-table-active-row}:host>sci-table-viewport>sci-table-grid>sci-table-body>div.active-row-outline{position:absolute;top:anchor(--sci-table-active-row top);right:anchor(--sci-table-active-row right);bottom:anchor(--sci-table-active-row bottom);left:anchor(--sci-table-active-row left);border:var(--sci-table-row-outline-width) var(--sci-table-row-outline-style) var(--sci-table-row-outline-color);border-radius:var(--sci-table-row-border-radius);pointer-events:none}:host>sci-table-viewport>sci-table-grid>sci-table-body:not(:has(sci-table-row[data-active]))>div.active-row-outline{display:none}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message{grid-column:1/-1;grid-row:auto/span 2;justify-self:center;align-self:center;display:flex;flex-direction:column;align-items:center;gap:1em;-webkit-user-select:none;user-select:none;white-space:nowrap;color:var(--sci-color-text-subtle)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message:has(button.action){grid-row:auto/span 4}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action{all:unset;display:inline-grid;place-content:center;place-items:center;padding:.25em;border-radius:var(--sci-button-border-radius);-webkit-user-select:none;user-select:none;overflow:hidden;cursor:var(--sci-button-cursor);--sci-icon-size: var(--sci-button-icon-size)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:hover:where(:not(:disabled)){background-color:var(--sci-button-background-color-hover)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:active:where(:not(:disabled)){background-color:var(--sci-button-background-color-active)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:focus:not(:focus-visible){outline:none}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:focus-visible{outline:var(--sci-button-outline-width) solid var(--sci-color-accent)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:disabled{color:var(--sci-button-text-color-disabled)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action{border:1px solid var(--sci-color-border);padding:.25em 1em}@container style(--\\275sci-table-viewport-client-width > --\\275sci-table-viewport-width){:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message{position:sticky;left:50%;right:50%;width:0}}:host>sci-table-viewport>sci-table-grid>sci-table-body:has(>span.message){z-index:2}:host>sci-table-viewport>sci-table-grid>sci-table-columns{grid-area:1/1/-1/-1;z-index:1;position:sticky;top:0;max-height:var(--\\275sci-table-viewport-height)}:host>sci-scrollbar{position:absolute}:host>sci-scrollbar[direction=vscroll]{top:calc(anchor(--sci-table-body top) + 2px);right:calc(anchor(--sci-table-viewport right) + 2px);bottom:calc(anchor(--sci-table-viewport bottom) + 2px)}:host>sci-scrollbar[direction=hscroll]{left:calc(anchor(--sci-table-viewport left) + 2px);bottom:calc(anchor(--sci-table-viewport bottom) + 1px);right:calc(anchor(--sci-table-viewport right) + 2px)}@container style(--\\275sci-table-resizing: true){:host>sci-scrollbar{pointer-events:none}}:host>sci-throbber.loading-indicator{--sci-throbber-size: 16px;position:absolute;top:calc(anchor(--sci-table-viewport top) + .5em);right:calc(anchor(--sci-table-viewport right) + .5em)}:host>div.synthetic{position:absolute;pointer-events:none;visibility:hidden}:host>div.synthetic.item-size{height:var(--sci-table-row-height)}:host>div.synthetic.cell-padding{width:var(--sci-table-cell-padding-inline)}\n"], dependencies: [{ kind: "component", type: SciTableViewportComponent, selector: "sci-table-viewport" }, { kind: "component", type: SciTableHeaderComponent, selector: "sci-table-header" }, { kind: "component", type: SciTableGridComponent, selector: "sci-table-grid" }, { kind: "component", type: SciTableBodyComponent, selector: "sci-table-body" }, { kind: "component", type: SciTableRowComponent, selector: "sci-table-row", inputs: ["row"], outputs: ["primaryAction"] }, { kind: "component", type: SciTableColumnsComponent, selector: "sci-table-columns", inputs: ["rows"] }, { kind: "directive", type: SciTableKeyboardNavigatorDirective, selector: "[sciTableKeyboardNavigator]" }, { kind: "directive", type: SciAttributesDirective, selector: "[sciAttributes]", inputs: ["sciAttributes"] }, { kind: "component", type: SciScrollbarComponent, selector: "sci-scrollbar", inputs: ["direction", "viewport"] }, { kind: "component", type: SciThrobberComponent, selector: "sci-throbber", inputs: ["type"] }, { kind: "component", type: SciIconComponent, selector: "sci-icon" }, { kind: "pipe", type: SciTextPipe, name: "sciText" }], encapsulation: i0.ViewEncapsulation.ShadowDom });
|
|
2218
2499
|
}
|
|
2219
2500
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciTableComponent, decorators: [{
|
|
2220
2501
|
type: Component,
|
|
@@ -2238,7 +2519,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
2238
2519
|
], providers: [
|
|
2239
2520
|
provideSciTable(),
|
|
2240
2521
|
SciTableSelectionService,
|
|
2241
|
-
], template: "@let table = this.table();\n\n<sci-table-viewport #viewport>\n <sci-table-grid>\n <!-- Table header -->\n @if (table.showHeader() || table.filterable()) {\n <sci-table-header/>\n }\n\n <!-- Table body -->\n <sci-table-body sciTableKeyboardNavigator>\n @if (!table.error()) {\n <!-- Track index to reuse the table row elements -->\n @for (row of table.rows(); track $index) {\n <sci-table-row [row]=\"row\" (primaryAction)=\"onRowPrimaryAction($event)\" [sciAttributes]=\"row.bindings?.attributes()\"/>\n } @empty {\n <span class=\"message e2e-no-data\">{{('%scion.components.no_items.message' | sciText)()}}</span>\n }\n } @else {\n <span class=\"message e2e-datasource\">\n {{('%scion.components.datasource_error.message' | sciText)()}}\n\n <button (click)=\"onRetry()\" class=\"action e2e-datasource-retry\">\n <!-- TODO [dwi] Replace with SCION icon -->\n <sci-icon>refresh</sci-icon>\n <span>{{('%scion.components.retry.label' | sciText)()}}</span>\n </button>\n </span>\n }\n\n <!-- Render active row outline separately to preserve row border-radius within block selection. -->\n @if (table.activeRow()) {\n <div class=\"active-row-outline e2e-active-row-outline\"></div>\n }\n </sci-table-body>\n\n <!-- Render column splitters. -->\n <sci-table-columns [rows]=\"rows()\"/>\n </sci-table-grid>\n</sci-table-viewport>\n\n<!-- Scrollbars -->\n<sci-scrollbar direction=\"hscroll\" [viewport]=\"viewport.host\"/>\n<sci-scrollbar direction=\"vscroll\" [viewport]=\"viewport.host\"/>\n\n@if (table.loading()) {\n <sci-throbber type=\"spinner\"/>\n}\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-row-height`, relative to the table's font size if em-based. -->\n<div class=\"synthetic item-size\" #item_size_synthetic_element></div>\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-cell-padding-inline`, relative to the table's font size if em-based. -->\n<div class=\"synthetic cell-padding\" #cell_padding_synthetic_element></div>\n", styles: ["@charset \"UTF-8\";:host{display:block;overflow:hidden;--\\275sci-table-border-size: 1px;--\\275sci-table-border-color: var(--sci-color-border)}:host:is(:not(:hover):not(:active),:host(:not(:hover):not(:active))) sci-scrollbar:not(.scrolling){opacity:0}:host>sci-table-viewport{display:block;position:relative;height:100%;overflow:auto;scrollbar-width:none;isolation:isolate;box-sizing:border-box;anchor-name:--sci-table-viewport}:host>sci-table-viewport:has(sci-table-header){--\\275sci-table-header-visible: true}:host>sci-table-viewport:has(sci-table-header>sci-column-header){--\\275sci-column-header-visible: true}:host>sci-table-viewport:has(~sci-scrollbar.scrolling){--\\275sci-table-scrolling: true}:host>sci-table-viewport>sci-table-grid{display:grid;grid-template-columns:var(--\\275sci-table-columns, repeat(auto-fit,
|
|
2522
|
+
], template: "@let table = this.table();\n\n<sci-table-viewport #viewport>\n <sci-table-grid>\n <!-- Table header -->\n @if (table.showHeader() || table.filterable()) {\n <sci-table-header/>\n }\n\n <!-- Table body -->\n <sci-table-body sciTableKeyboardNavigator>\n @if (!table.error()) {\n <!-- Track index to reuse the table row elements -->\n @for (row of table.rows(); track $index) {\n <sci-table-row [row]=\"row\" (primaryAction)=\"onRowPrimaryAction($event)\" [sciAttributes]=\"row.bindings?.attributes()\"/>\n } @empty {\n <span class=\"message e2e-no-data\">{{('%scion.components.no_items.message' | sciText)()}}</span>\n }\n } @else {\n <span class=\"message e2e-datasource\">\n {{('%scion.components.datasource_error.message' | sciText)()}}\n\n <button (click)=\"onRetry()\" class=\"action e2e-datasource-retry\">\n <!-- TODO [dwi] Replace with SCION icon -->\n <sci-icon>refresh</sci-icon>\n <span>{{('%scion.components.retry.label' | sciText)()}}</span>\n </button>\n </span>\n }\n\n <!-- Render active row outline separately to preserve row border-radius within block selection. -->\n @if (table.activeRow()) {\n <div class=\"active-row-outline e2e-active-row-outline\"></div>\n }\n </sci-table-body>\n\n <!-- Render column splitters. -->\n <sci-table-columns [rows]=\"rows()\"/>\n </sci-table-grid>\n</sci-table-viewport>\n\n<!-- Scrollbars -->\n<sci-scrollbar direction=\"hscroll\" [viewport]=\"viewport.host\"/>\n<sci-scrollbar direction=\"vscroll\" [viewport]=\"viewport.host\"/>\n\n@if (table.loading()) {\n <sci-throbber type=\"spinner\" class=\"loading-indicator e2e-loading-indicator\"/>\n}\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-row-height`, relative to the table's font size if em-based. -->\n<div class=\"synthetic item-size\" #item_size_synthetic_element></div>\n\n<!-- Synthetic element to compute the absolute pixel value of the `--sci-table-cell-padding-inline`, relative to the table's font size if em-based. -->\n<div class=\"synthetic cell-padding\" #cell_padding_synthetic_element></div>\n", styles: ["@charset \"UTF-8\";:host{display:block;overflow:hidden;--\\275sci-table-border-size: 1px;--\\275sci-table-border-color: var(--sci-color-border)}:host:is(:not(:hover):not(:active),:host(:not(:hover):not(:active))) sci-scrollbar:not(.scrolling){opacity:0}:host>sci-table-viewport{display:block;position:relative;height:100%;overflow:auto;scrollbar-width:none;isolation:isolate;box-sizing:border-box;anchor-name:--sci-table-viewport}:host>sci-table-viewport:has(sci-table-header){--\\275sci-table-header-visible: true}:host>sci-table-viewport:has(sci-table-header>sci-column-header){--\\275sci-column-header-visible: true}:host>sci-table-viewport:has(~sci-scrollbar.scrolling){--\\275sci-table-scrolling: true}:host>sci-table-viewport>sci-table-grid{display:grid;grid-template-columns:var(--\\275sci-table-columns, repeat(auto-fit, 100px)) 0;grid-auto-rows:min-content;grid-template-rows:min-content 1fr;width:min-content;min-width:100%;min-height:100%}@container not style(--\\275sci-table-header-visible: true){:host>sci-table-viewport>sci-table-grid{grid-template-rows:1fr}}:host>sci-table-viewport>sci-table-grid>sci-table-header{z-index:1;grid-row:1;grid-column:1/-1;position:sticky;top:0}:host>sci-table-viewport>sci-table-grid>sci-table-body{anchor-name:--sci-table-body;grid-row:2}@container not style(--\\275sci-table-header-visible: true){:host>sci-table-viewport>sci-table-grid>sci-table-body{grid-row:1}}:host>sci-table-viewport>sci-table-grid>sci-table-body{display:grid;grid-template-columns:subgrid;grid-column:1/-1;grid-auto-rows:var(--sci-table-row-height);outline:none;padding-top:var(--\\275sci-table-virtual-scroll-offset-top);padding-bottom:var(--\\275sci-table-virtual-scroll-offset-bottom)}:host>sci-table-viewport>sci-table-grid>sci-table-body>sci-table-row{grid-column:1/-1}:host>sci-table-viewport>sci-table-grid>sci-table-body>sci-table-row[data-active]{anchor-name:--sci-table-active-row}:host>sci-table-viewport>sci-table-grid>sci-table-body>div.active-row-outline{position:absolute;top:anchor(--sci-table-active-row top);right:anchor(--sci-table-active-row right);bottom:anchor(--sci-table-active-row bottom);left:anchor(--sci-table-active-row left);border:var(--sci-table-row-outline-width) var(--sci-table-row-outline-style) var(--sci-table-row-outline-color);border-radius:var(--sci-table-row-border-radius);pointer-events:none}:host>sci-table-viewport>sci-table-grid>sci-table-body:not(:has(sci-table-row[data-active]))>div.active-row-outline{display:none}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message{grid-column:1/-1;grid-row:auto/span 2;justify-self:center;align-self:center;display:flex;flex-direction:column;align-items:center;gap:1em;-webkit-user-select:none;user-select:none;white-space:nowrap;color:var(--sci-color-text-subtle)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message:has(button.action){grid-row:auto/span 4}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action{all:unset;display:inline-grid;place-content:center;place-items:center;padding:.25em;border-radius:var(--sci-button-border-radius);-webkit-user-select:none;user-select:none;overflow:hidden;cursor:var(--sci-button-cursor);--sci-icon-size: var(--sci-button-icon-size)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:hover:where(:not(:disabled)){background-color:var(--sci-button-background-color-hover)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:active:where(:not(:disabled)){background-color:var(--sci-button-background-color-active)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:focus:not(:focus-visible){outline:none}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:focus-visible{outline:var(--sci-button-outline-width) solid var(--sci-color-accent)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action:disabled{color:var(--sci-button-text-color-disabled)}:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message>button.action{border:1px solid var(--sci-color-border);padding:.25em 1em}@container style(--\\275sci-table-viewport-client-width > --\\275sci-table-viewport-width){:host>sci-table-viewport>sci-table-grid>sci-table-body>span.message{position:sticky;left:50%;right:50%;width:0}}:host>sci-table-viewport>sci-table-grid>sci-table-body:has(>span.message){z-index:2}:host>sci-table-viewport>sci-table-grid>sci-table-columns{grid-area:1/1/-1/-1;z-index:1;position:sticky;top:0;max-height:var(--\\275sci-table-viewport-height)}:host>sci-scrollbar{position:absolute}:host>sci-scrollbar[direction=vscroll]{top:calc(anchor(--sci-table-body top) + 2px);right:calc(anchor(--sci-table-viewport right) + 2px);bottom:calc(anchor(--sci-table-viewport bottom) + 2px)}:host>sci-scrollbar[direction=hscroll]{left:calc(anchor(--sci-table-viewport left) + 2px);bottom:calc(anchor(--sci-table-viewport bottom) + 1px);right:calc(anchor(--sci-table-viewport right) + 2px)}@container style(--\\275sci-table-resizing: true){:host>sci-scrollbar{pointer-events:none}}:host>sci-throbber.loading-indicator{--sci-throbber-size: 16px;position:absolute;top:calc(anchor(--sci-table-viewport top) + .5em);right:calc(anchor(--sci-table-viewport right) + .5em)}:host>div.synthetic{position:absolute;pointer-events:none;visibility:hidden}:host>div.synthetic.item-size{height:var(--sci-table-row-height)}:host>div.synthetic.cell-padding{width:var(--sci-table-cell-padding-inline)}\n"] }]
|
|
2242
2523
|
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], table: [{ type: i0.Input, args: [{ isSignal: true, alias: "table", required: true }] }], primaryAction: [{ type: i0.Output, args: ["primaryAction"] }], _viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SciTableViewportComponent), { ...{ read: ElementRef }, isSignal: true }] }], _viewportClient: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SciTableGridComponent), { ...{ read: ElementRef }, isSignal: true }] }], _tableHeader: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SciTableHeaderComponent), { ...{ read: ElementRef }, isSignal: true }] }], _tableBody: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SciTableBodyComponent), { ...{ read: ElementRef }, isSignal: true }] }], _itemSizeSyntheticElement: [{ type: i0.ViewChild, args: ['item_size_synthetic_element', { isSignal: true }] }], _cellPaddingSyntheticElement: [{ type: i0.ViewChild, args: ['cell_padding_synthetic_element', { isSignal: true }] }], rows: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => SciTableRowComponent), { isSignal: true }] }] } });
|
|
2243
2524
|
function provideSciTable() {
|
|
2244
2525
|
return {
|