@testgorilla/tgo-ui 11.0.1 → 11.0.2
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/testgorilla-tgo-ui-components-infinite-scroll-table.mjs +103 -15
- package/fesm2022/testgorilla-tgo-ui-components-infinite-scroll-table.mjs.map +1 -1
- package/mcp/catalog.json +1 -1
- package/package.json +1 -1
- package/types/testgorilla-tgo-ui-components-infinite-scroll-table.d.ts +35 -5
|
@@ -100,8 +100,24 @@ class InfiniteScrollTableComponent {
|
|
|
100
100
|
* the last — aligned between header and body regardless of browser/scrollbar behaviour.
|
|
101
101
|
*/
|
|
102
102
|
this.scrollbarWidth = signal(0, ...(ngDevMode ? [{ debugName: "scrollbarWidth" }] : /* istanbul ignore next */ []));
|
|
103
|
+
/**
|
|
104
|
+
* Measured height (px) of the body viewport's horizontal scrollbar. When a short list also has a
|
|
105
|
+
* horizontal scrollbar, this is added to the viewport height so the scrollbar doesn't eat into the
|
|
106
|
+
* rows' vertical space and force a spurious vertical scrollbar. Mirrors `scrollbarWidth`.
|
|
107
|
+
*/
|
|
108
|
+
this.hScrollbarHeight = signal(0, ...(ngDevMode ? [{ debugName: "hScrollbarHeight" }] : /* istanbul ignore next */ []));
|
|
103
109
|
/** Guards `loadMore` to a single emission per approach to the end. */
|
|
104
110
|
this.loadMoreArmed = true;
|
|
111
|
+
/**
|
|
112
|
+
* True when the browser can drive the header via a CSS scroll timeline (see the SCSS): the header
|
|
113
|
+
* then tracks the body's horizontal scroll on the compositor, with no per-frame main-thread work.
|
|
114
|
+
* In that case the JS `scrollLeft` sync is skipped so the offset isn't applied twice; it stays as
|
|
115
|
+
* the fallback for browsers without scroll-driven animations.
|
|
116
|
+
*/
|
|
117
|
+
this.usesScrollTimelineHeaderSync = typeof CSS !== 'undefined' &&
|
|
118
|
+
CSS !== null &&
|
|
119
|
+
typeof CSS.supports === 'function' &&
|
|
120
|
+
CSS.supports('animation-timeline: scroll()');
|
|
105
121
|
this.skeletonTheme = {
|
|
106
122
|
background: '#F4F4F4',
|
|
107
123
|
'border-radius': '4px',
|
|
@@ -143,8 +159,17 @@ class InfiniteScrollTableComponent {
|
|
|
143
159
|
this.showEmptyState = computed(() => !this.loading() && !this.error() && !this.hasData(), ...(ngDevMode ? [{ debugName: "showEmptyState" }] : /* istanbul ignore next */ []));
|
|
144
160
|
this.showErrorState = computed(() => !this.loading() && this.error() && !this.hasData(), ...(ngDevMode ? [{ debugName: "showErrorState" }] : /* istanbul ignore next */ []));
|
|
145
161
|
this.showErrorFooter = computed(() => !this.loading() && this.error() && this.hasData(), ...(ngDevMode ? [{ debugName: "showErrorFooter" }] : /* istanbul ignore next */ []));
|
|
146
|
-
/**
|
|
147
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Viewport height shrinks to the content and is capped at `maxHeight` (CSS `min()` mixes units).
|
|
164
|
+
* When a horizontal scrollbar is present it reserves that scrollbar's measured height on top of the
|
|
165
|
+
* content, so a short list doesn't overflow and grow a spurious vertical scrollbar. Still capped at
|
|
166
|
+
* `maxHeight`.
|
|
167
|
+
*/
|
|
168
|
+
this.viewportHeight = computed(() => {
|
|
169
|
+
const contentHeight = this.renderRows().length * this.rowHeight();
|
|
170
|
+
const scrollbarReserve = this.horizontalScroll() ? this.hScrollbarHeight() : 0;
|
|
171
|
+
return `min(${contentHeight + scrollbarReserve}px, ${this.maxHeight()})`;
|
|
172
|
+
}, ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
|
|
148
173
|
/** Screen-reader announcement for the busy states. */
|
|
149
174
|
this.statusMessage = computed(() => {
|
|
150
175
|
if (this.loading()) {
|
|
@@ -188,13 +213,25 @@ class InfiniteScrollTableComponent {
|
|
|
188
213
|
const subscription = new Subscription();
|
|
189
214
|
subscription.add(viewport.elementScrolled().subscribe(() => this.syncHorizontalScroll()));
|
|
190
215
|
subscription.add(viewport.renderedRangeStream.subscribe(() => this.checkLoadMore()));
|
|
191
|
-
// Keep the measured scrollbar
|
|
192
|
-
//
|
|
193
|
-
const measureScrollbar = () =>
|
|
216
|
+
// Keep the measured scrollbar dimensions current: they change when a scrollbar appears or
|
|
217
|
+
// disappears (content grows/shrinks) and on viewport resize.
|
|
218
|
+
const measureScrollbar = () => {
|
|
219
|
+
this.scrollbarWidth.set(element.offsetWidth - element.clientWidth);
|
|
220
|
+
this.hScrollbarHeight.set(element.offsetHeight - element.clientHeight);
|
|
221
|
+
this.updateHeaderScrollMetric();
|
|
222
|
+
};
|
|
194
223
|
subscription.add(viewport.renderedRangeStream.subscribe(() => measureScrollbar()));
|
|
224
|
+
// The viewport element's box can also change from things no signal captures — a flex/grid
|
|
225
|
+
// parent resizing, or a relative `maxHeight` (e.g. `70vh`) reacting to a container change.
|
|
226
|
+
// CDK caches its measured size, so re-measure the virtual viewport on any box change or it
|
|
227
|
+
// under-renders (empty tail band). The signal-driven height changes are covered by the
|
|
228
|
+
// dedicated effect below; this catches the rest.
|
|
195
229
|
let resizeObserver;
|
|
196
230
|
if (typeof ResizeObserver !== 'undefined') {
|
|
197
|
-
resizeObserver = new ResizeObserver(() =>
|
|
231
|
+
resizeObserver = new ResizeObserver(() => {
|
|
232
|
+
measureScrollbar();
|
|
233
|
+
this.scheduleViewportRemeasure();
|
|
234
|
+
});
|
|
198
235
|
resizeObserver.observe(element);
|
|
199
236
|
}
|
|
200
237
|
measureScrollbar();
|
|
@@ -210,14 +247,31 @@ class InfiniteScrollTableComponent {
|
|
|
210
247
|
onCleanup(() => {
|
|
211
248
|
subscription.unsubscribe();
|
|
212
249
|
resizeObserver?.disconnect();
|
|
213
|
-
// Cancel
|
|
250
|
+
// Cancel still-pending frames so they can't fire after the viewport leaves the DOM
|
|
214
251
|
// (e.g. flipping to the empty/error state in the same tick).
|
|
215
252
|
if (scrollSyncFrame !== undefined) {
|
|
216
253
|
cancelAnimationFrame(scrollSyncFrame);
|
|
217
254
|
}
|
|
255
|
+
if (this.remeasureFrame !== undefined) {
|
|
256
|
+
cancelAnimationFrame(this.remeasureFrame);
|
|
257
|
+
this.remeasureFrame = undefined;
|
|
258
|
+
}
|
|
218
259
|
});
|
|
219
260
|
});
|
|
220
261
|
});
|
|
262
|
+
// Re-measure the CDK viewport whenever its height changes from a signal: data growth (more render
|
|
263
|
+
// rows), a runtime `rowHeight` change (also changes total content height), or a `maxHeight` change.
|
|
264
|
+
// `CdkVirtualScrollViewport` caches its measured size and only re-measures on scroll or window
|
|
265
|
+
// resize, so a runtime height increase would otherwise leave the extra space empty with the tail
|
|
266
|
+
// rows unrendered until a manual scroll/resize. Reading these signals (not `viewportHeight()`)
|
|
267
|
+
// keeps the dependency to genuine height inputs and off horizontal-scroll state.
|
|
268
|
+
effect(() => {
|
|
269
|
+
this.renderRows();
|
|
270
|
+
this.rowHeight();
|
|
271
|
+
this.maxHeight();
|
|
272
|
+
this.columns();
|
|
273
|
+
this.scheduleViewportRemeasure();
|
|
274
|
+
});
|
|
221
275
|
// Re-arm the loadMore guard whenever the `data` input changes — a page arrived, or the set was
|
|
222
276
|
// replaced (filter/search reset, even to a shorter or same-length list). It reads `data()` only,
|
|
223
277
|
// NOT `loadingMore()`: a failed fetch clears `loadingMore` without changing `data`, so the guard
|
|
@@ -242,11 +296,13 @@ class InfiniteScrollTableComponent {
|
|
|
242
296
|
return item[key];
|
|
243
297
|
}
|
|
244
298
|
/**
|
|
245
|
-
*
|
|
246
|
-
* default.
|
|
247
|
-
*
|
|
299
|
+
* The single authoritative width for a column: its declared width, else its min-width, else the
|
|
300
|
+
* default. The template applies this identically as `flex-basis`, `min-width` AND `max-width` (with
|
|
301
|
+
* `flex-grow:0; flex-shrink:0; overflow:hidden`) to the header cell and every body cell, so a column
|
|
302
|
+
* is exactly this width in both containers — content is clipped and can never widen it. This is what
|
|
303
|
+
* keeps header and body columns aligned end-to-end regardless of cell content or horizontal scroll.
|
|
248
304
|
*/
|
|
249
|
-
|
|
305
|
+
columnWidth(column) {
|
|
250
306
|
return column.styles?.width ?? column.styles?.['min-width'] ?? '160px';
|
|
251
307
|
}
|
|
252
308
|
onRowClick(row) {
|
|
@@ -285,6 +341,38 @@ class InfiniteScrollTableComponent {
|
|
|
285
341
|
event.preventDefault();
|
|
286
342
|
this.onRowClick(row);
|
|
287
343
|
}
|
|
344
|
+
/**
|
|
345
|
+
* Re-measure the CDK virtual viewport after its box may have changed. Deferred to the next frame so
|
|
346
|
+
* it reads the settled layout and never fires a "ResizeObserver loop limit exceeded" warning when
|
|
347
|
+
* driven from the ResizeObserver; repeated triggers coalesce to a single measure. The re-measure is
|
|
348
|
+
* what makes CDK recompute the rendered range to fill a viewport whose height grew at runtime.
|
|
349
|
+
*/
|
|
350
|
+
scheduleViewportRemeasure() {
|
|
351
|
+
if (typeof requestAnimationFrame === 'undefined') {
|
|
352
|
+
this.viewport()?.checkViewportSize();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (this.remeasureFrame !== undefined) {
|
|
356
|
+
cancelAnimationFrame(this.remeasureFrame);
|
|
357
|
+
}
|
|
358
|
+
this.remeasureFrame = requestAnimationFrame(() => {
|
|
359
|
+
this.remeasureFrame = undefined;
|
|
360
|
+
// `viewport()` is null in the empty/error states and after teardown, so this safely no-ops.
|
|
361
|
+
this.viewport()?.checkViewportSize();
|
|
362
|
+
this.updateHeaderScrollMetric();
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
updateHeaderScrollMetric() {
|
|
366
|
+
if (!this.usesScrollTimelineHeaderSync) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const headerScroll = this.headerScroll()?.nativeElement;
|
|
370
|
+
if (!headerScroll) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const maxScroll = Math.max(0, headerScroll.scrollWidth - headerScroll.clientWidth);
|
|
374
|
+
headerScroll.style.setProperty('--ui-ist-header-scroll-max', `${maxScroll}px`);
|
|
375
|
+
}
|
|
288
376
|
onRetry() {
|
|
289
377
|
this.retry.emit();
|
|
290
378
|
}
|
|
@@ -297,8 +385,8 @@ class InfiniteScrollTableComponent {
|
|
|
297
385
|
const left = viewport.measureScrollOffset('left');
|
|
298
386
|
const right = viewport.measureScrollOffset('right');
|
|
299
387
|
const header = this.headerScroll();
|
|
300
|
-
if (header) {
|
|
301
|
-
header.nativeElement.scrollLeft = left;
|
|
388
|
+
if (header && !this.usesScrollTimelineHeaderSync) {
|
|
389
|
+
header.nativeElement.scrollLeft = Math.round(left);
|
|
302
390
|
}
|
|
303
391
|
this.scrollStart.set(left <= 1);
|
|
304
392
|
this.scrollEnd.set(right <= 1);
|
|
@@ -334,7 +422,7 @@ class InfiniteScrollTableComponent {
|
|
|
334
422
|
}
|
|
335
423
|
}
|
|
336
424
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
337
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: InfiniteScrollTableComponent, isStandalone: true, selector: "ui-infinite-scroll-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, isCondensed: { classPropertyName: "isCondensed", publicName: "isCondensed", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMore: { classPropertyName: "loadingMore", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, skeletonRowCount: { classPropertyName: "skeletonRowCount", publicName: "skeletonRowCount", isSignal: true, isRequired: false, transformFunction: null }, loadMoreThreshold: { classPropertyName: "loadMoreThreshold", publicName: "loadMoreThreshold", isSignal: true, isRequired: false, transformFunction: null }, noDataTemplate: { classPropertyName: "noDataTemplate", publicName: "noDataTemplate", isSignal: true, isRequired: false, transformFunction: null }, errorTemplate: { classPropertyName: "errorTemplate", publicName: "errorTemplate", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadMore: "loadMore", retry: "retry", rowClick: "rowClick", selectionChange: "selectionChange" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }, { propertyName: "headerScroll", first: true, predicate: ["headerScroll"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned),\n and its horizontal scrollLeft is synced from the body so columns stay aligned. -->\n <div\n #headerScroll\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.margin-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:1;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell:last-child{padding-right:24px}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: SkeletonComponent, selector: "ui-skeleton", inputs: ["count", "theme", "appearance", "isAiTheme", "applicationTheme"] }, { kind: "component", type: CheckboxComponent, selector: "ui-checkbox", inputs: ["disabled", "checked", "indeterminate", "companyColor", "name", "label", "multiple", "applicationTheme", "ariaLabel", "ariaRequired", "hasError", "hideBuiltInErrors", "hideLabelInErrors", "ariaLabelledby", "ariaDescribedby", "truncateText", "alignment", "tabIndex"], outputs: ["changed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
425
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: InfiniteScrollTableComponent, isStandalone: true, selector: "ui-infinite-scroll-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, isCondensed: { classPropertyName: "isCondensed", publicName: "isCondensed", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMore: { classPropertyName: "loadingMore", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, skeletonRowCount: { classPropertyName: "skeletonRowCount", publicName: "skeletonRowCount", isSignal: true, isRequired: false, transformFunction: null }, loadMoreThreshold: { classPropertyName: "loadMoreThreshold", publicName: "loadMoreThreshold", isSignal: true, isRequired: false, transformFunction: null }, noDataTemplate: { classPropertyName: "noDataTemplate", publicName: "noDataTemplate", isSignal: true, isRequired: false, transformFunction: null }, errorTemplate: { classPropertyName: "errorTemplate", publicName: "errorTemplate", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadMore: "loadMore", retry: "retry", rowClick: "rowClick", selectionChange: "selectionChange" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }, { propertyName: "headerScroll", first: true, predicate: ["headerScroll"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned).\n The outer element reserves the body's vertical-scrollbar width as right padding, so the reserved\n strip keeps the header background and bottom border; the inner element carries the horizontal\n scrollLeft synced from the body so columns stay aligned. -->\n <div\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.padding-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div #headerScroll class=\"ui-ist__header-scroll\" role=\"presentation\">\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__header-scroll{overflow:hidden}@supports (animation-timeline: scroll()){.ui-ist{timeline-scope:--ui-ist-header-x}.ui-ist__body{scroll-timeline:--ui-ist-header-x x}.ui-ist__row--header .ui-ist__cell--header:not(.ui-ist__cell--sticky-start):not(.ui-ist__cell--sticky-end){animation:ui-ist-header-follow linear both;animation-timeline:--ui-ist-header-x}}@keyframes ui-ist-header-follow{to{transform:translate(calc(-1 * var(--ui-ist-header-scroll-max, 0px)))}}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:0;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2;order:1}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell--spacer{flex:1 1 auto;min-width:0;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell--sticky-end{padding-right:24px}.ui-ist--condensed .ui-ist__cell--spacer{padding:0}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: SkeletonComponent, selector: "ui-skeleton", inputs: ["count", "theme", "appearance", "isAiTheme", "applicationTheme"] }, { kind: "component", type: CheckboxComponent, selector: "ui-checkbox", inputs: ["disabled", "checked", "indeterminate", "companyColor", "name", "label", "multiple", "applicationTheme", "ariaLabel", "ariaRequired", "hasError", "hideBuiltInErrors", "hideLabelInErrors", "ariaLabelledby", "ariaDescribedby", "truncateText", "alignment", "tabIndex"], outputs: ["changed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
338
426
|
}
|
|
339
427
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponent, decorators: [{
|
|
340
428
|
type: Component,
|
|
@@ -345,7 +433,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
|
|
|
345
433
|
CdkVirtualForOf,
|
|
346
434
|
SkeletonComponent,
|
|
347
435
|
CheckboxComponent,
|
|
348
|
-
], template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned),\n and its horizontal scrollLeft is synced from the body so columns stay aligned. -->\n <div\n #headerScroll\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.margin-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:1;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell:last-child{padding-right:24px}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
|
|
436
|
+
], template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned).\n The outer element reserves the body's vertical-scrollbar width as right padding, so the reserved\n strip keeps the header background and bottom border; the inner element carries the horizontal\n scrollLeft synced from the body so columns stay aligned. -->\n <div\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.padding-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div #headerScroll class=\"ui-ist__header-scroll\" role=\"presentation\">\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__header-scroll{overflow:hidden}@supports (animation-timeline: scroll()){.ui-ist{timeline-scope:--ui-ist-header-x}.ui-ist__body{scroll-timeline:--ui-ist-header-x x}.ui-ist__row--header .ui-ist__cell--header:not(.ui-ist__cell--sticky-start):not(.ui-ist__cell--sticky-end){animation:ui-ist-header-follow linear both;animation-timeline:--ui-ist-header-x}}@keyframes ui-ist-header-follow{to{transform:translate(calc(-1 * var(--ui-ist-header-scroll-max, 0px)))}}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:0;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2;order:1}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell--spacer{flex:1 1 auto;min-width:0;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell--sticky-end{padding-right:24px}.ui-ist--condensed .ui-ist__cell--spacer{padding:0}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
|
|
349
437
|
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], rowIdKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdKey", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], isCondensed: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCondensed", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMore", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], skeletonRowCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRowCount", required: false }] }], loadMoreThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadMoreThreshold", required: false }] }], noDataTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noDataTemplate", required: false }] }], errorTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorTemplate", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], retry: [{ type: i0.Output, args: ["retry"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], headerScroll: [{ type: i0.ViewChild, args: ['headerScroll', { isSignal: true }] }] } });
|
|
350
438
|
|
|
351
439
|
class InfiniteScrollTableComponentModule {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testgorilla-tgo-ui-components-infinite-scroll-table.mjs","sources":["../../../components/infinite-scroll-table/infinite-scroll-table.component.ts","../../../components/infinite-scroll-table/infinite-scroll-table.component.html","../../../components/infinite-scroll-table/infinite-scroll-table.component.module.ts","../../../components/infinite-scroll-table/testgorilla-tgo-ui-components-infinite-scroll-table.ts"],"sourcesContent":["import { CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport } from '@angular/cdk/scrolling';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n isDevMode,\n output,\n signal,\n TemplateRef,\n TrackByFunction,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { Subscription } from 'rxjs';\n\nimport { CheckboxComponent } from '@testgorilla/tgo-ui/components/checkbox';\nimport { SkeletonComponent } from '@testgorilla/tgo-ui/components/skeleton';\n\nimport {\n InfiniteScrollTableColumn,\n InfiniteScrollTableErrorContext,\n InfiniteScrollTableRowClick,\n InfiniteScrollTableRowSelection,\n} from './infinite-scroll-table.model';\n\n/** Internal row wrapper so real rows and skeleton placeholders flow through one virtual list. */\ntype RenderRow<T> = { kind: 'data'; item: T; index: number } | { kind: 'skeleton'; id: string };\n\n/** Default number of skeleton rows rendered for the initial (full-body) load. */\nconst DEFAULT_FIRST_LOAD_SKELETON_COUNT = 10;\n/** Number of skeleton rows appended below existing rows while the next page is fetched. */\nconst LOAD_MORE_SKELETON_COUNT = 3;\n/** Default distance (in rows) from the end at which `loadMore` fires. */\nconst DEFAULT_LOAD_MORE_THRESHOLD = 5;\n\n/** Fixed width (px) of the checkbox selection column. Must match `.ui-ist__cell--checkbox` in the SCSS. */\nconst CHECKBOX_COLUMN_WIDTH = 56;\n\n/**\n * A generic, virtualized table with scroll-driven infinite loading.\n *\n * Owns rendering, fixed-height vertical virtualization (CDK), horizontal scroll, a pinned header,\n * sticky first/last columns, first-load and load-more skeletons, and a guarded `loadMore` event.\n * All content and layout come from consumer inputs — nothing domain-specific lives here.\n *\n * Independent of `ui-table`: it reuses only stable leaf primitives (`ui-skeleton`) and duplicates\n * the column/context type shapes so consumers can migrate with a selector swap.\n */\n@Component({\n selector: 'ui-infinite-scroll-table',\n templateUrl: './infinite-scroll-table.component.html',\n styleUrls: ['./infinite-scroll-table.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n CdkVirtualScrollViewport,\n CdkFixedSizeVirtualScroll,\n CdkVirtualForOf,\n SkeletonComponent,\n CheckboxComponent,\n ],\n})\nexport class InfiniteScrollTableComponent<T> {\n /** Rows loaded so far. The consumer appends pages to this array. */\n readonly data = input.required<T[]>();\n\n /** Column definitions. The first `isSticky` column pins left; the last `isSticky` column pins right. */\n readonly columns = input.required<InfiniteScrollTableColumn<T>[]>();\n\n /**\n * Fixed row height in px — used as the virtualization `itemSize`.\n * Variable / multi-line row heights are unsupported in this variant.\n */\n readonly rowHeight = input.required<number>();\n\n /** Optional stable row identity so recycled rows re-render correctly. Takes precedence over `rowIdKey`. */\n readonly trackBy = input<TrackByFunction<T>>();\n /** Optional key on each row that holds a stable id. Used when `trackBy` is not provided. */\n readonly rowIdKey = input<string>();\n\n /**\n * Accepted for API parity with `ui-table`. In this bounded layout the header is always rendered\n * above the internal scroll region and stays visible regardless — `.ui-ist` has `overflow: hidden`,\n * so the header cannot stick to an outer scrolling page. Kept so `ui-table` templates migrate\n * unchanged. Default `true`.\n */\n readonly stickyHeader = input(true, { transform: booleanAttribute });\n\n /** Max height of the internal scroll region (e.g. `'70vh'`). The body shrinks to fit fewer rows. */\n readonly maxHeight = input<string>('70vh');\n\n /** Condensed spacing. */\n readonly isCondensed = input(false, { transform: booleanAttribute });\n\n /**\n * Enables row selection. When `true`, a dedicated checkbox column is prepended (pinned to the left)\n * and each row's checkbox reflects the row's `selected` property; toggling it emits `selectionChange`.\n * Selection stays data-driven and consumer-managed, exactly like `ui-table`. Default `false`.\n */\n readonly selectable = input(false, { transform: booleanAttribute });\n\n /** First-load state: renders a full body of skeleton rows. */\n readonly loading = input(false, { transform: booleanAttribute });\n\n /** Appends skeleton rows below the existing rows while the next page is fetched. */\n readonly loadingMore = input(false, { transform: booleanAttribute });\n\n /** Whether more pages exist. When `false`, `loadMore` never fires and the load-more skeleton is hidden. */\n readonly hasMore = input(false, { transform: booleanAttribute });\n\n /** Number of skeleton rows for the first-load state. */\n readonly skeletonRowCount = input<number>(DEFAULT_FIRST_LOAD_SKELETON_COUNT);\n\n /** How many rows from the end trigger `loadMore`. */\n readonly loadMoreThreshold = input<number>(DEFAULT_LOAD_MORE_THRESHOLD);\n\n /** Empty-state template, shown when `data` is empty and not loading. */\n readonly noDataTemplate = input<TemplateRef<unknown>>();\n\n /** Error template, shown when `error` is `true`. Receives `{ $implicit: retry, retry }` as context. */\n readonly errorTemplate = input<TemplateRef<InfiniteScrollTableErrorContext>>();\n\n /** Whether a page fetch failed. */\n readonly error = input(false, { transform: booleanAttribute });\n\n /**\n * Fires when the user scrolls within `loadMoreThreshold` rows of the end.\n * Guarded: emits only when `hasMore && !loading && !loadingMore`, and only once per approach.\n */\n readonly loadMore = output<void>();\n\n /** Fires from the error template's retry affordance. */\n readonly retry = output<void>();\n\n /** Fires when a data row is clicked; payload is the row plus its data index. */\n readonly rowClick = output<InfiniteScrollTableRowClick<T>>();\n\n /**\n * Fires when a row's selection checkbox is toggled (only when `selectable`). Payload is the row,\n * its data index, and the new selected state. The consumer updates its data's `selected` property.\n */\n readonly selectionChange = output<InfiniteScrollTableRowSelection<T>>();\n\n /** Fixed width of the checkbox column; exposed so the template can offset a sticky first column. */\n protected readonly checkboxColumnWidth = CHECKBOX_COLUMN_WIDTH;\n\n protected readonly viewport = viewChild(CdkVirtualScrollViewport);\n protected readonly headerScroll = viewChild<ElementRef<HTMLElement>>('headerScroll');\n\n /** Horizontal-scroll state, mirroring the existing table's `scrollSettings`. */\n protected readonly scrollStart = signal(true);\n protected readonly scrollEnd = signal(false);\n protected readonly horizontalScroll = signal(false);\n\n /**\n * Measured width (px) of the body viewport's vertical scrollbar. Reserved as right padding on the\n * header so the header's content width exactly equals the body's, keeping every column — including\n * the last — aligned between header and body regardless of browser/scrollbar behaviour.\n */\n protected readonly scrollbarWidth = signal(0);\n\n /** Guards `loadMore` to a single emission per approach to the end. */\n private loadMoreArmed = true;\n\n protected readonly skeletonTheme = {\n background: '#F4F4F4',\n 'border-radius': '4px',\n height: '24px',\n 'margin-bottom': '0',\n };\n\n // Sticky rule mirrors ui-table (positional): the LAST column pins right when it's sticky; any other\n // sticky column pins left. This way an actions column (always the last column) is always pinned to\n // the right, even when it's the only sticky column.\n protected readonly lastStickyKey = computed(() => {\n const columns = this.columns();\n const lastColumn = columns[columns.length - 1];\n return lastColumn?.isSticky ? lastColumn.key : undefined;\n });\n protected readonly firstStickyKey = computed(() => {\n const columns = this.columns();\n const lastIndex = columns.length - 1;\n return columns.find((column, index) => column.isSticky && index !== lastIndex)?.key;\n });\n\n /** Real rows, with skeleton placeholders in first-load / load-more states, as one virtual list. */\n protected readonly renderRows = computed<RenderRow<T>[]>(() => {\n if (this.loading()) {\n return Array.from({ length: Math.max(1, this.skeletonRowCount()) }, (_, i) => ({\n kind: 'skeleton' as const,\n id: `skeleton-first-${i}`,\n }));\n }\n\n const rows: RenderRow<T>[] = this.data().map((item, index) => ({ kind: 'data' as const, item, index }));\n\n if (this.loadingMore() && this.hasMore()) {\n for (let i = 0; i < LOAD_MORE_SKELETON_COUNT; i++) {\n rows.push({ kind: 'skeleton' as const, id: `skeleton-more-${i}` });\n }\n }\n\n return rows;\n });\n\n protected readonly hasData = computed(() => this.data().length > 0);\n /** The virtualized body is shown for the first-load skeletons and whenever there are rows. */\n protected readonly showViewport = computed(() => this.loading() || this.hasData());\n protected readonly showEmptyState = computed(() => !this.loading() && !this.error() && !this.hasData());\n protected readonly showErrorState = computed(() => !this.loading() && this.error() && !this.hasData());\n protected readonly showErrorFooter = computed(() => !this.loading() && this.error() && this.hasData());\n\n /** Viewport height shrinks to the content and is capped at `maxHeight` (CSS `min()` mixes units). */\n protected readonly viewportHeight = computed(\n () => `min(${this.renderRows().length * this.rowHeight()}px, ${this.maxHeight()})`\n );\n\n /** Screen-reader announcement for the busy states. */\n protected readonly statusMessage = computed(() => {\n if (this.loading()) {\n return 'Loading';\n }\n if (this.loadingMore()) {\n return 'Loading more rows';\n }\n return '';\n });\n\n protected readonly errorContext: InfiniteScrollTableErrorContext = {\n $implicit: () => this.onRetry(),\n retry: () => this.onRetry(),\n };\n\n protected readonly renderRowTrackBy: TrackByFunction<RenderRow<T>> = (index, row): unknown => {\n if (row.kind === 'skeleton') {\n return row.id;\n }\n const explicitTrackBy = this.trackBy();\n if (explicitTrackBy) {\n return explicitTrackBy(row.index, row.item) as unknown;\n }\n const key = this.rowIdKey();\n return key ? (row.item as Record<string, unknown>)[key] : row.index;\n };\n\n constructor() {\n // (Re-)attach scroll listeners whenever the viewport enters or leaves the DOM (empty/error states).\n // Keyed on `viewport()` only: the setup below reads other signals (through syncHorizontalScroll /\n // checkLoadMore), so it runs inside `untracked()` to avoid re-running — and tearing down the\n // subscriptions + ResizeObserver — on every data change or loading toggle.\n effect(onCleanup => {\n const viewport = this.viewport();\n if (!viewport) {\n return;\n }\n untracked(() => {\n const element = viewport.elementRef.nativeElement;\n\n // CDK inserts a generic `.cdk-virtual-scroll-content-wrapper` between the viewport\n // (role=\"rowgroup\") and the rows (role=\"row\"). Mark it presentational so the rows stay\n // owned by the rowgroup and the table's ARIA tree isn't broken for assistive tech.\n element.querySelector('.cdk-virtual-scroll-content-wrapper')?.setAttribute('role', 'presentation');\n\n const subscription = new Subscription();\n subscription.add(viewport.elementScrolled().subscribe(() => this.syncHorizontalScroll()));\n subscription.add(viewport.renderedRangeStream.subscribe(() => this.checkLoadMore()));\n\n // Keep the measured scrollbar width current: it changes when the vertical scrollbar appears\n // or disappears (content grows/shrinks) and on viewport resize.\n const measureScrollbar = (): void => this.scrollbarWidth.set(element.offsetWidth - element.clientWidth);\n subscription.add(viewport.renderedRangeStream.subscribe(() => measureScrollbar()));\n\n let resizeObserver: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(() => measureScrollbar());\n resizeObserver.observe(element);\n }\n\n measureScrollbar();\n this.syncHorizontalScroll();\n this.checkLoadMore();\n\n // The first syncHorizontalScroll() runs before the CDK viewport lays out its rows, so the\n // overflow measurement (and the sticky end-shadow) is stale. Re-sync after the next frame,\n // once layout is settled. Guarded because requestAnimationFrame is browser-only (SSR).\n let scrollSyncFrame: number | undefined;\n if (typeof requestAnimationFrame !== 'undefined') {\n scrollSyncFrame = requestAnimationFrame(() => this.syncHorizontalScroll());\n }\n\n onCleanup(() => {\n subscription.unsubscribe();\n resizeObserver?.disconnect();\n // Cancel a still-pending re-sync so it can't fire after the viewport leaves the DOM\n // (e.g. flipping to the empty/error state in the same tick).\n if (scrollSyncFrame !== undefined) {\n cancelAnimationFrame(scrollSyncFrame);\n }\n });\n });\n });\n\n // Re-arm the loadMore guard whenever the `data` input changes — a page arrived, or the set was\n // replaced (filter/search reset, even to a shorter or same-length list). It reads `data()` only,\n // NOT `loadingMore()`: a failed fetch clears `loadingMore` without changing `data`, so the guard\n // stays disarmed and never re-fires `loadMore` in a loop (the `error()` guard is a second layer).\n effect(() => {\n this.data();\n this.loadMoreArmed = true;\n });\n\n // Dev-only: without `trackBy` or `rowIdKey`, row identity falls back to the data index — the\n // weakest option exactly when rows recycle. If the consumer opts into selection without a stable\n // id, surface the sharp edge so selection state can't silently attach to the wrong row after a\n // reorder/prepend.\n effect(() => {\n if (isDevMode() && this.selectable() && !this.trackBy() && !this.rowIdKey()) {\n console.warn(\n '[ui-infinite-scroll-table] `selectable` is enabled without `trackBy` or `rowIdKey`. ' +\n 'Row identity falls back to the data index, so selection can attach to the wrong row ' +\n 'when rows are reordered or prepended. Provide `trackBy` or `rowIdKey` for stable identity.'\n );\n }\n });\n }\n\n protected getCellValue(item: T, key: string): unknown {\n return (item as Record<string, unknown>)[key];\n }\n\n /**\n * Content-independent flex-basis for a column: its declared width, else its min-width, else the\n * default. Using this (instead of `flex-basis: auto`) makes header and body cells size identically\n * so every column stays aligned regardless of the text inside header vs body cells.\n */\n protected cellBasis(column: InfiniteScrollTableColumn<T>): string {\n return column.styles?.width ?? column.styles?.['min-width'] ?? '160px';\n }\n\n protected onRowClick(row: RenderRow<T>): void {\n if (row.kind !== 'data') {\n return;\n }\n this.rowClick.emit({ ...(row.item as object), index: row.index } as InfiniteScrollTableRowClick<T>);\n }\n\n /**\n * Whether a row should show the selected highlight. Mirrors `ui-table`: only when `selectable` is\n * enabled and the row's data carries a truthy `selected` property. Skeleton rows are never selected.\n */\n protected isRowSelected(row: RenderRow<T>): boolean {\n return this.selectable() && row.kind === 'data' && Boolean((row.item as { selected?: unknown }).selected);\n }\n\n /** Emits the new selection state when a row's checkbox is toggled. Consumer-managed, like `ui-table`. */\n protected onSelectionToggle(row: RenderRow<T>, selected: boolean): void {\n if (row.kind !== 'data') {\n return;\n }\n this.selectionChange.emit({\n ...(row.item as object),\n index: row.index,\n selected,\n } as InfiniteScrollTableRowSelection<T>);\n }\n\n /**\n * Left offset (px) for a sticky-start consumer column: when the checkbox column is present it must\n * sit to the right of it, so the first sticky column is pushed over by the checkbox column width.\n */\n protected stickyStartOffset(column: InfiniteScrollTableColumn<T>): number | null {\n return this.selectable() && column.key === this.firstStickyKey() ? this.checkboxColumnWidth : null;\n }\n\n /** Keyboard equivalent of a row click (Enter/Space) for the currently focused data row. */\n protected onRowActivate(event: Event, row: RenderRow<T>): void {\n event.preventDefault();\n this.onRowClick(row);\n }\n\n private onRetry(): void {\n this.retry.emit();\n }\n\n /** Keep the header horizontally aligned with the body and update the sticky-shadow state. */\n private syncHorizontalScroll(): void {\n const viewport = this.viewport();\n if (!viewport) {\n return;\n }\n const left = viewport.measureScrollOffset('left');\n const right = viewport.measureScrollOffset('right');\n\n const header = this.headerScroll();\n if (header) {\n header.nativeElement.scrollLeft = left;\n }\n this.scrollStart.set(left <= 1);\n this.scrollEnd.set(right <= 1);\n this.horizontalScroll.set(left + right > 1);\n }\n\n /**\n * Emits `loadMore` once when the rendered range reaches the trigger zone near the end,\n * re-arming when the user scrolls back out. Mirrors the app's `ngx-infinite-scroll` semantics.\n */\n private checkLoadMore(): void {\n const viewport = this.viewport();\n // `error()` is part of the guard so a failed page pauses auto-loading until the consumer clears\n // the error (e.g. via the retry affordance), instead of immediately re-firing `loadMore`.\n if (!viewport || !this.hasMore() || this.loading() || this.loadingMore() || this.error()) {\n return;\n }\n\n const dataLength = this.data().length;\n if (dataLength === 0) {\n return;\n }\n\n const renderedEnd = viewport.getRenderedRange().end;\n // Clamp so a negative threshold can't push the trigger point past the end and silently disable\n // loadMore entirely.\n const threshold = Math.max(0, this.loadMoreThreshold());\n const inTriggerZone = renderedEnd >= dataLength - threshold;\n\n if (!inTriggerZone) {\n this.loadMoreArmed = true;\n return;\n }\n\n if (this.loadMoreArmed) {\n this.loadMoreArmed = false;\n this.loadMore.emit();\n }\n }\n}\n","<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned),\n and its horizontal scrollLeft is synced from the body so columns stay aligned. -->\n <div\n #headerScroll\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.margin-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n","import { ScrollingModule } from '@angular/cdk/scrolling';\nimport { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\n\nimport { InfiniteScrollTableComponent } from './infinite-scroll-table.component';\n\n@NgModule({\n imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent],\n exports: [InfiniteScrollTableComponent],\n})\nexport class InfiniteScrollTableComponentModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"testgorilla-tgo-ui-components-infinite-scroll-table.mjs","sources":["../../../components/infinite-scroll-table/infinite-scroll-table.component.ts","../../../components/infinite-scroll-table/infinite-scroll-table.component.html","../../../components/infinite-scroll-table/infinite-scroll-table.component.module.ts","../../../components/infinite-scroll-table/testgorilla-tgo-ui-components-infinite-scroll-table.ts"],"sourcesContent":["import { CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport } from '@angular/cdk/scrolling';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n isDevMode,\n output,\n signal,\n TemplateRef,\n TrackByFunction,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { Subscription } from 'rxjs';\n\nimport { CheckboxComponent } from '@testgorilla/tgo-ui/components/checkbox';\nimport { SkeletonComponent } from '@testgorilla/tgo-ui/components/skeleton';\n\nimport {\n InfiniteScrollTableColumn,\n InfiniteScrollTableErrorContext,\n InfiniteScrollTableRowClick,\n InfiniteScrollTableRowSelection,\n} from './infinite-scroll-table.model';\n\n/** Internal row wrapper so real rows and skeleton placeholders flow through one virtual list. */\ntype RenderRow<T> = { kind: 'data'; item: T; index: number } | { kind: 'skeleton'; id: string };\n\n/** Default number of skeleton rows rendered for the initial (full-body) load. */\nconst DEFAULT_FIRST_LOAD_SKELETON_COUNT = 10;\n/** Number of skeleton rows appended below existing rows while the next page is fetched. */\nconst LOAD_MORE_SKELETON_COUNT = 3;\n/** Default distance (in rows) from the end at which `loadMore` fires. */\nconst DEFAULT_LOAD_MORE_THRESHOLD = 5;\n\n/** Fixed width (px) of the checkbox selection column. Must match `.ui-ist__cell--checkbox` in the SCSS. */\nconst CHECKBOX_COLUMN_WIDTH = 56;\n\n/**\n * A generic, virtualized table with scroll-driven infinite loading.\n *\n * Owns rendering, fixed-height vertical virtualization (CDK), horizontal scroll, a pinned header,\n * sticky first/last columns, first-load and load-more skeletons, and a guarded `loadMore` event.\n * All content and layout come from consumer inputs — nothing domain-specific lives here.\n *\n * Independent of `ui-table`: it reuses only stable leaf primitives (`ui-skeleton`) and duplicates\n * the column/context type shapes so consumers can migrate with a selector swap.\n */\n@Component({\n selector: 'ui-infinite-scroll-table',\n templateUrl: './infinite-scroll-table.component.html',\n styleUrls: ['./infinite-scroll-table.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n CdkVirtualScrollViewport,\n CdkFixedSizeVirtualScroll,\n CdkVirtualForOf,\n SkeletonComponent,\n CheckboxComponent,\n ],\n})\nexport class InfiniteScrollTableComponent<T> {\n /** Rows loaded so far. The consumer appends pages to this array. */\n readonly data = input.required<T[]>();\n\n /** Column definitions. The first `isSticky` column pins left; the last `isSticky` column pins right. */\n readonly columns = input.required<InfiniteScrollTableColumn<T>[]>();\n\n /**\n * Fixed row height in px — used as the virtualization `itemSize`.\n * Variable / multi-line row heights are unsupported in this variant.\n */\n readonly rowHeight = input.required<number>();\n\n /** Optional stable row identity so recycled rows re-render correctly. Takes precedence over `rowIdKey`. */\n readonly trackBy = input<TrackByFunction<T>>();\n /** Optional key on each row that holds a stable id. Used when `trackBy` is not provided. */\n readonly rowIdKey = input<string>();\n\n /**\n * Accepted for API parity with `ui-table`. In this bounded layout the header is always rendered\n * above the internal scroll region and stays visible regardless — `.ui-ist` has `overflow: hidden`,\n * so the header cannot stick to an outer scrolling page. Kept so `ui-table` templates migrate\n * unchanged. Default `true`.\n */\n readonly stickyHeader = input(true, { transform: booleanAttribute });\n\n /** Max height of the internal scroll region (e.g. `'70vh'`). The body shrinks to fit fewer rows. */\n readonly maxHeight = input<string>('70vh');\n\n /** Condensed spacing. */\n readonly isCondensed = input(false, { transform: booleanAttribute });\n\n /**\n * Enables row selection. When `true`, a dedicated checkbox column is prepended (pinned to the left)\n * and each row's checkbox reflects the row's `selected` property; toggling it emits `selectionChange`.\n * Selection stays data-driven and consumer-managed, exactly like `ui-table`. Default `false`.\n */\n readonly selectable = input(false, { transform: booleanAttribute });\n\n /** First-load state: renders a full body of skeleton rows. */\n readonly loading = input(false, { transform: booleanAttribute });\n\n /** Appends skeleton rows below the existing rows while the next page is fetched. */\n readonly loadingMore = input(false, { transform: booleanAttribute });\n\n /** Whether more pages exist. When `false`, `loadMore` never fires and the load-more skeleton is hidden. */\n readonly hasMore = input(false, { transform: booleanAttribute });\n\n /** Number of skeleton rows for the first-load state. */\n readonly skeletonRowCount = input<number>(DEFAULT_FIRST_LOAD_SKELETON_COUNT);\n\n /** How many rows from the end trigger `loadMore`. */\n readonly loadMoreThreshold = input<number>(DEFAULT_LOAD_MORE_THRESHOLD);\n\n /** Empty-state template, shown when `data` is empty and not loading. */\n readonly noDataTemplate = input<TemplateRef<unknown>>();\n\n /** Error template, shown when `error` is `true`. Receives `{ $implicit: retry, retry }` as context. */\n readonly errorTemplate = input<TemplateRef<InfiniteScrollTableErrorContext>>();\n\n /** Whether a page fetch failed. */\n readonly error = input(false, { transform: booleanAttribute });\n\n /**\n * Fires when the user scrolls within `loadMoreThreshold` rows of the end.\n * Guarded: emits only when `hasMore && !loading && !loadingMore`, and only once per approach.\n */\n readonly loadMore = output<void>();\n\n /** Fires from the error template's retry affordance. */\n readonly retry = output<void>();\n\n /** Fires when a data row is clicked; payload is the row plus its data index. */\n readonly rowClick = output<InfiniteScrollTableRowClick<T>>();\n\n /**\n * Fires when a row's selection checkbox is toggled (only when `selectable`). Payload is the row,\n * its data index, and the new selected state. The consumer updates its data's `selected` property.\n */\n readonly selectionChange = output<InfiniteScrollTableRowSelection<T>>();\n\n /** Fixed width of the checkbox column; exposed so the template can offset a sticky first column. */\n protected readonly checkboxColumnWidth = CHECKBOX_COLUMN_WIDTH;\n\n protected readonly viewport = viewChild(CdkVirtualScrollViewport);\n protected readonly headerScroll = viewChild<ElementRef<HTMLElement>>('headerScroll');\n\n /** Horizontal-scroll state, mirroring the existing table's `scrollSettings`. */\n protected readonly scrollStart = signal(true);\n protected readonly scrollEnd = signal(false);\n protected readonly horizontalScroll = signal(false);\n\n /**\n * Measured width (px) of the body viewport's vertical scrollbar. Reserved as right padding on the\n * header so the header's content width exactly equals the body's, keeping every column — including\n * the last — aligned between header and body regardless of browser/scrollbar behaviour.\n */\n protected readonly scrollbarWidth = signal(0);\n\n /**\n * Measured height (px) of the body viewport's horizontal scrollbar. When a short list also has a\n * horizontal scrollbar, this is added to the viewport height so the scrollbar doesn't eat into the\n * rows' vertical space and force a spurious vertical scrollbar. Mirrors `scrollbarWidth`.\n */\n protected readonly hScrollbarHeight = signal(0);\n\n /** Guards `loadMore` to a single emission per approach to the end. */\n private loadMoreArmed = true;\n\n /** Pending frame for a deferred CDK viewport re-measure, so repeated triggers coalesce to one. */\n private remeasureFrame: number | undefined;\n\n /**\n * True when the browser can drive the header via a CSS scroll timeline (see the SCSS): the header\n * then tracks the body's horizontal scroll on the compositor, with no per-frame main-thread work.\n * In that case the JS `scrollLeft` sync is skipped so the offset isn't applied twice; it stays as\n * the fallback for browsers without scroll-driven animations.\n */\n private readonly usesScrollTimelineHeaderSync =\n typeof CSS !== 'undefined' &&\n CSS !== null &&\n typeof CSS.supports === 'function' &&\n CSS.supports('animation-timeline: scroll()');\n\n protected readonly skeletonTheme = {\n background: '#F4F4F4',\n 'border-radius': '4px',\n height: '24px',\n 'margin-bottom': '0',\n };\n\n // Sticky rule mirrors ui-table (positional): the LAST column pins right when it's sticky; any other\n // sticky column pins left. This way an actions column (always the last column) is always pinned to\n // the right, even when it's the only sticky column.\n protected readonly lastStickyKey = computed(() => {\n const columns = this.columns();\n const lastColumn = columns[columns.length - 1];\n return lastColumn?.isSticky ? lastColumn.key : undefined;\n });\n protected readonly firstStickyKey = computed(() => {\n const columns = this.columns();\n const lastIndex = columns.length - 1;\n return columns.find((column, index) => column.isSticky && index !== lastIndex)?.key;\n });\n\n /** Real rows, with skeleton placeholders in first-load / load-more states, as one virtual list. */\n protected readonly renderRows = computed<RenderRow<T>[]>(() => {\n if (this.loading()) {\n return Array.from({ length: Math.max(1, this.skeletonRowCount()) }, (_, i) => ({\n kind: 'skeleton' as const,\n id: `skeleton-first-${i}`,\n }));\n }\n\n const rows: RenderRow<T>[] = this.data().map((item, index) => ({ kind: 'data' as const, item, index }));\n\n if (this.loadingMore() && this.hasMore()) {\n for (let i = 0; i < LOAD_MORE_SKELETON_COUNT; i++) {\n rows.push({ kind: 'skeleton' as const, id: `skeleton-more-${i}` });\n }\n }\n\n return rows;\n });\n\n protected readonly hasData = computed(() => this.data().length > 0);\n /** The virtualized body is shown for the first-load skeletons and whenever there are rows. */\n protected readonly showViewport = computed(() => this.loading() || this.hasData());\n protected readonly showEmptyState = computed(() => !this.loading() && !this.error() && !this.hasData());\n protected readonly showErrorState = computed(() => !this.loading() && this.error() && !this.hasData());\n protected readonly showErrorFooter = computed(() => !this.loading() && this.error() && this.hasData());\n\n /**\n * Viewport height shrinks to the content and is capped at `maxHeight` (CSS `min()` mixes units).\n * When a horizontal scrollbar is present it reserves that scrollbar's measured height on top of the\n * content, so a short list doesn't overflow and grow a spurious vertical scrollbar. Still capped at\n * `maxHeight`.\n */\n protected readonly viewportHeight = computed(() => {\n const contentHeight = this.renderRows().length * this.rowHeight();\n const scrollbarReserve = this.horizontalScroll() ? this.hScrollbarHeight() : 0;\n return `min(${contentHeight + scrollbarReserve}px, ${this.maxHeight()})`;\n });\n\n /** Screen-reader announcement for the busy states. */\n protected readonly statusMessage = computed(() => {\n if (this.loading()) {\n return 'Loading';\n }\n if (this.loadingMore()) {\n return 'Loading more rows';\n }\n return '';\n });\n\n protected readonly errorContext: InfiniteScrollTableErrorContext = {\n $implicit: () => this.onRetry(),\n retry: () => this.onRetry(),\n };\n\n protected readonly renderRowTrackBy: TrackByFunction<RenderRow<T>> = (index, row): unknown => {\n if (row.kind === 'skeleton') {\n return row.id;\n }\n const explicitTrackBy = this.trackBy();\n if (explicitTrackBy) {\n return explicitTrackBy(row.index, row.item) as unknown;\n }\n const key = this.rowIdKey();\n return key ? (row.item as Record<string, unknown>)[key] : row.index;\n };\n\n constructor() {\n // (Re-)attach scroll listeners whenever the viewport enters or leaves the DOM (empty/error states).\n // Keyed on `viewport()` only: the setup below reads other signals (through syncHorizontalScroll /\n // checkLoadMore), so it runs inside `untracked()` to avoid re-running — and tearing down the\n // subscriptions + ResizeObserver — on every data change or loading toggle.\n effect(onCleanup => {\n const viewport = this.viewport();\n if (!viewport) {\n return;\n }\n untracked(() => {\n const element = viewport.elementRef.nativeElement;\n\n // CDK inserts a generic `.cdk-virtual-scroll-content-wrapper` between the viewport\n // (role=\"rowgroup\") and the rows (role=\"row\"). Mark it presentational so the rows stay\n // owned by the rowgroup and the table's ARIA tree isn't broken for assistive tech.\n element.querySelector('.cdk-virtual-scroll-content-wrapper')?.setAttribute('role', 'presentation');\n\n const subscription = new Subscription();\n subscription.add(viewport.elementScrolled().subscribe(() => this.syncHorizontalScroll()));\n subscription.add(viewport.renderedRangeStream.subscribe(() => this.checkLoadMore()));\n\n // Keep the measured scrollbar dimensions current: they change when a scrollbar appears or\n // disappears (content grows/shrinks) and on viewport resize.\n const measureScrollbar = (): void => {\n this.scrollbarWidth.set(element.offsetWidth - element.clientWidth);\n this.hScrollbarHeight.set(element.offsetHeight - element.clientHeight);\n this.updateHeaderScrollMetric();\n };\n subscription.add(viewport.renderedRangeStream.subscribe(() => measureScrollbar()));\n\n // The viewport element's box can also change from things no signal captures — a flex/grid\n // parent resizing, or a relative `maxHeight` (e.g. `70vh`) reacting to a container change.\n // CDK caches its measured size, so re-measure the virtual viewport on any box change or it\n // under-renders (empty tail band). The signal-driven height changes are covered by the\n // dedicated effect below; this catches the rest.\n let resizeObserver: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(() => {\n measureScrollbar();\n this.scheduleViewportRemeasure();\n });\n resizeObserver.observe(element);\n }\n\n measureScrollbar();\n this.syncHorizontalScroll();\n this.checkLoadMore();\n\n // The first syncHorizontalScroll() runs before the CDK viewport lays out its rows, so the\n // overflow measurement (and the sticky end-shadow) is stale. Re-sync after the next frame,\n // once layout is settled. Guarded because requestAnimationFrame is browser-only (SSR).\n let scrollSyncFrame: number | undefined;\n if (typeof requestAnimationFrame !== 'undefined') {\n scrollSyncFrame = requestAnimationFrame(() => this.syncHorizontalScroll());\n }\n\n onCleanup(() => {\n subscription.unsubscribe();\n resizeObserver?.disconnect();\n // Cancel still-pending frames so they can't fire after the viewport leaves the DOM\n // (e.g. flipping to the empty/error state in the same tick).\n if (scrollSyncFrame !== undefined) {\n cancelAnimationFrame(scrollSyncFrame);\n }\n if (this.remeasureFrame !== undefined) {\n cancelAnimationFrame(this.remeasureFrame);\n this.remeasureFrame = undefined;\n }\n });\n });\n });\n\n // Re-measure the CDK viewport whenever its height changes from a signal: data growth (more render\n // rows), a runtime `rowHeight` change (also changes total content height), or a `maxHeight` change.\n // `CdkVirtualScrollViewport` caches its measured size and only re-measures on scroll or window\n // resize, so a runtime height increase would otherwise leave the extra space empty with the tail\n // rows unrendered until a manual scroll/resize. Reading these signals (not `viewportHeight()`)\n // keeps the dependency to genuine height inputs and off horizontal-scroll state.\n effect(() => {\n this.renderRows();\n this.rowHeight();\n this.maxHeight();\n this.columns();\n this.scheduleViewportRemeasure();\n });\n\n // Re-arm the loadMore guard whenever the `data` input changes — a page arrived, or the set was\n // replaced (filter/search reset, even to a shorter or same-length list). It reads `data()` only,\n // NOT `loadingMore()`: a failed fetch clears `loadingMore` without changing `data`, so the guard\n // stays disarmed and never re-fires `loadMore` in a loop (the `error()` guard is a second layer).\n effect(() => {\n this.data();\n this.loadMoreArmed = true;\n });\n\n // Dev-only: without `trackBy` or `rowIdKey`, row identity falls back to the data index — the\n // weakest option exactly when rows recycle. If the consumer opts into selection without a stable\n // id, surface the sharp edge so selection state can't silently attach to the wrong row after a\n // reorder/prepend.\n effect(() => {\n if (isDevMode() && this.selectable() && !this.trackBy() && !this.rowIdKey()) {\n console.warn(\n '[ui-infinite-scroll-table] `selectable` is enabled without `trackBy` or `rowIdKey`. ' +\n 'Row identity falls back to the data index, so selection can attach to the wrong row ' +\n 'when rows are reordered or prepended. Provide `trackBy` or `rowIdKey` for stable identity.'\n );\n }\n });\n }\n\n protected getCellValue(item: T, key: string): unknown {\n return (item as Record<string, unknown>)[key];\n }\n\n /**\n * The single authoritative width for a column: its declared width, else its min-width, else the\n * default. The template applies this identically as `flex-basis`, `min-width` AND `max-width` (with\n * `flex-grow:0; flex-shrink:0; overflow:hidden`) to the header cell and every body cell, so a column\n * is exactly this width in both containers — content is clipped and can never widen it. This is what\n * keeps header and body columns aligned end-to-end regardless of cell content or horizontal scroll.\n */\n protected columnWidth(column: InfiniteScrollTableColumn<T>): string {\n return column.styles?.width ?? column.styles?.['min-width'] ?? '160px';\n }\n\n protected onRowClick(row: RenderRow<T>): void {\n if (row.kind !== 'data') {\n return;\n }\n this.rowClick.emit({ ...(row.item as object), index: row.index } as InfiniteScrollTableRowClick<T>);\n }\n\n /**\n * Whether a row should show the selected highlight. Mirrors `ui-table`: only when `selectable` is\n * enabled and the row's data carries a truthy `selected` property. Skeleton rows are never selected.\n */\n protected isRowSelected(row: RenderRow<T>): boolean {\n return this.selectable() && row.kind === 'data' && Boolean((row.item as { selected?: unknown }).selected);\n }\n\n /** Emits the new selection state when a row's checkbox is toggled. Consumer-managed, like `ui-table`. */\n protected onSelectionToggle(row: RenderRow<T>, selected: boolean): void {\n if (row.kind !== 'data') {\n return;\n }\n this.selectionChange.emit({\n ...(row.item as object),\n index: row.index,\n selected,\n } as InfiniteScrollTableRowSelection<T>);\n }\n\n /**\n * Left offset (px) for a sticky-start consumer column: when the checkbox column is present it must\n * sit to the right of it, so the first sticky column is pushed over by the checkbox column width.\n */\n protected stickyStartOffset(column: InfiniteScrollTableColumn<T>): number | null {\n return this.selectable() && column.key === this.firstStickyKey() ? this.checkboxColumnWidth : null;\n }\n\n /** Keyboard equivalent of a row click (Enter/Space) for the currently focused data row. */\n protected onRowActivate(event: Event, row: RenderRow<T>): void {\n event.preventDefault();\n this.onRowClick(row);\n }\n\n /**\n * Re-measure the CDK virtual viewport after its box may have changed. Deferred to the next frame so\n * it reads the settled layout and never fires a \"ResizeObserver loop limit exceeded\" warning when\n * driven from the ResizeObserver; repeated triggers coalesce to a single measure. The re-measure is\n * what makes CDK recompute the rendered range to fill a viewport whose height grew at runtime.\n */\n private scheduleViewportRemeasure(): void {\n if (typeof requestAnimationFrame === 'undefined') {\n this.viewport()?.checkViewportSize();\n return;\n }\n if (this.remeasureFrame !== undefined) {\n cancelAnimationFrame(this.remeasureFrame);\n }\n this.remeasureFrame = requestAnimationFrame(() => {\n this.remeasureFrame = undefined;\n // `viewport()` is null in the empty/error states and after teardown, so this safely no-ops.\n this.viewport()?.checkViewportSize();\n this.updateHeaderScrollMetric();\n });\n }\n\n private updateHeaderScrollMetric(): void {\n if (!this.usesScrollTimelineHeaderSync) {\n return;\n }\n const headerScroll = this.headerScroll()?.nativeElement;\n if (!headerScroll) {\n return;\n }\n const maxScroll = Math.max(0, headerScroll.scrollWidth - headerScroll.clientWidth);\n headerScroll.style.setProperty('--ui-ist-header-scroll-max', `${maxScroll}px`);\n }\n\n private onRetry(): void {\n this.retry.emit();\n }\n\n /** Keep the header horizontally aligned with the body and update the sticky-shadow state. */\n private syncHorizontalScroll(): void {\n const viewport = this.viewport();\n if (!viewport) {\n return;\n }\n const left = viewport.measureScrollOffset('left');\n const right = viewport.measureScrollOffset('right');\n\n const header = this.headerScroll();\n if (header && !this.usesScrollTimelineHeaderSync) {\n header.nativeElement.scrollLeft = Math.round(left);\n }\n this.scrollStart.set(left <= 1);\n this.scrollEnd.set(right <= 1);\n this.horizontalScroll.set(left + right > 1);\n }\n\n /**\n * Emits `loadMore` once when the rendered range reaches the trigger zone near the end,\n * re-arming when the user scrolls back out. Mirrors the app's `ngx-infinite-scroll` semantics.\n */\n private checkLoadMore(): void {\n const viewport = this.viewport();\n // `error()` is part of the guard so a failed page pauses auto-loading until the consumer clears\n // the error (e.g. via the retry affordance), instead of immediately re-firing `loadMore`.\n if (!viewport || !this.hasMore() || this.loading() || this.loadingMore() || this.error()) {\n return;\n }\n\n const dataLength = this.data().length;\n if (dataLength === 0) {\n return;\n }\n\n const renderedEnd = viewport.getRenderedRange().end;\n // Clamp so a negative threshold can't push the trigger point past the end and silently disable\n // loadMore entirely.\n const threshold = Math.max(0, this.loadMoreThreshold());\n const inTriggerZone = renderedEnd >= dataLength - threshold;\n\n if (!inTriggerZone) {\n this.loadMoreArmed = true;\n return;\n }\n\n if (this.loadMoreArmed) {\n this.loadMoreArmed = false;\n this.loadMore.emit();\n }\n }\n}\n","<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned).\n The outer element reserves the body's vertical-scrollbar width as right padding, so the reserved\n strip keeps the header background and bottom border; the inner element carries the horizontal\n scrollLeft synced from the body so columns stay aligned. -->\n <div\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.padding-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div #headerScroll class=\"ui-ist__header-scroll\" role=\"presentation\">\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n","import { ScrollingModule } from '@angular/cdk/scrolling';\nimport { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\n\nimport { InfiniteScrollTableComponent } from './infinite-scroll-table.component';\n\n@NgModule({\n imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent],\n exports: [InfiniteScrollTableComponent],\n})\nexport class InfiniteScrollTableComponentModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|