@testgorilla/tgo-ui 11.2.2 → 11.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/testgorilla-tgo-ui-components-core.mjs +7 -0
- package/fesm2022/testgorilla-tgo-ui-components-core.mjs.map +1 -1
- package/fesm2022/testgorilla-tgo-ui-components-dialog.mjs +9 -3
- package/fesm2022/testgorilla-tgo-ui-components-dialog.mjs.map +1 -1
- package/fesm2022/testgorilla-tgo-ui-components-infinite-scroll-table.mjs +410 -205
- 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 +203 -131
package/package.json
CHANGED
|
@@ -5,62 +5,63 @@ import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* over to a virtualized body) so consumers can migrate their column configs and cell templates
|
|
12
|
-
* with a selector swap. Types have no runtime footprint, so this is a deliberate duplication
|
|
13
|
-
* rather than a shared import — it keeps the new component fully independent of `ui-table`.
|
|
8
|
+
* The structural contract `selectable` puts on a row: the checkbox reflects `selected`, and `key` /
|
|
9
|
+
* `rowIdKey` lookups read arbitrary fields. Declared once here rather than asserted at each read site, so
|
|
10
|
+
* the requirement is discoverable from the types instead of only from the docs.
|
|
14
11
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
type InfiniteScrollTableRowLike = Record<string, unknown> & {
|
|
13
|
+
selected?: boolean;
|
|
14
|
+
};
|
|
15
|
+
interface InfiniteScrollTableColumn<T> {
|
|
16
|
+
/** Also reads the default cell value. A plain string, so a synthetic column can have no matching field. */
|
|
17
17
|
key: string;
|
|
18
18
|
/** Header label rendered when no `headerCellTemplate` is provided. */
|
|
19
19
|
title?: string;
|
|
20
|
+
headerCellTemplate?: TemplateRef<InfiniteScrollTableHeaderCellContext<T>>;
|
|
21
|
+
rowCellTemplate?: TemplateRef<InfiniteScrollTableRowCellContext<T>>;
|
|
20
22
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*/
|
|
24
|
-
headerCellTemplate?: TemplateRef<unknown>;
|
|
25
|
-
/**
|
|
26
|
-
* Consumer-supplied row cell template.
|
|
27
|
-
* Context: `{ $implicit: element, rowIndex }` — matches `ui-table`.
|
|
23
|
+
* Pins the column. Only honoured on the **first** column (pins left) and the **last** column (pins
|
|
24
|
+
* right); anywhere else it is ignored, with a dev-mode warning.
|
|
28
25
|
*/
|
|
29
|
-
rowCellTemplate?: TemplateRef<unknown>;
|
|
30
|
-
/** When set, the first sticky column pins to the left and the last sticky column pins to the right. */
|
|
31
26
|
isSticky?: boolean;
|
|
32
27
|
styles?: InfiniteScrollTableColumnStyles;
|
|
33
28
|
}
|
|
34
29
|
interface InfiniteScrollTableColumnStyles {
|
|
35
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Authoritative column width (default `160px`), applied as `flex-basis`, `min-width` AND `max-width`:
|
|
32
|
+
* the column never grows or shrinks and overflowing content is clipped, which is what keeps the header
|
|
33
|
+
* and body scroll containers pixel-aligned. Leftover row width goes to a trailing spacer instead.
|
|
34
|
+
*/
|
|
36
35
|
width?: string;
|
|
37
36
|
alignment?: InfiniteScrollTableColumnAlignment;
|
|
38
37
|
}
|
|
39
38
|
type InfiniteScrollTableColumnAlignment = 'left' | 'right' | 'center';
|
|
40
|
-
|
|
39
|
+
interface InfiniteScrollTableRowCellContext<T> {
|
|
40
|
+
$implicit: T;
|
|
41
|
+
rowIndex: number;
|
|
42
|
+
}
|
|
43
|
+
interface InfiniteScrollTableHeaderCellContext<T> {
|
|
44
|
+
$implicit: string | undefined;
|
|
45
|
+
column: InfiniteScrollTableColumn<T>;
|
|
46
|
+
colIndex: number;
|
|
47
|
+
}
|
|
41
48
|
interface InfiniteScrollTableErrorContext {
|
|
42
49
|
$implicit: () => void;
|
|
43
50
|
retry: () => void;
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* Note: this is a **shallow copy** (`{ ...row, index }`, matching `ui-table`), so a class instance's
|
|
49
|
-
* prototype is not preserved and any pre-existing `index` field on the row is overwritten.
|
|
53
|
+
* `row` is the consumer's own object by reference — not a copy — so class prototypes survive and a row's
|
|
54
|
+
* own `index` field is never shadowed. Same for `InfiniteScrollTableRowSelection`.
|
|
50
55
|
*/
|
|
51
|
-
|
|
56
|
+
interface InfiniteScrollTableRowClick<T> {
|
|
57
|
+
row: T;
|
|
52
58
|
index: number;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
* As with `rowClick`, this is a **shallow copy** (`{ ...row, index, selected }`) — no prototype, and
|
|
58
|
-
* any pre-existing `index` / `selected` field on the row is overwritten.
|
|
59
|
-
*/
|
|
60
|
-
type InfiniteScrollTableRowSelection<T> = T & {
|
|
59
|
+
}
|
|
60
|
+
interface InfiniteScrollTableRowSelection<T> {
|
|
61
|
+
row: T;
|
|
61
62
|
index: number;
|
|
62
63
|
selected: boolean;
|
|
63
|
-
}
|
|
64
|
+
}
|
|
64
65
|
|
|
65
66
|
/** Internal row wrapper so real rows and skeleton placeholders flow through one virtual list. */
|
|
66
67
|
type RenderRow<T> = {
|
|
@@ -72,177 +73,248 @@ type RenderRow<T> = {
|
|
|
72
73
|
id: string;
|
|
73
74
|
};
|
|
74
75
|
/**
|
|
75
|
-
* A generic, virtualized table with scroll-driven infinite loading.
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* sticky first/last columns, first-load and load-more skeletons, and a guarded `loadMore` event.
|
|
79
|
-
* All content and layout come from consumer inputs — nothing domain-specific lives here.
|
|
80
|
-
*
|
|
81
|
-
* Independent of `ui-table`: it reuses only stable leaf primitives (`ui-skeleton`) and duplicates
|
|
82
|
-
* the column/context type shapes so consumers can migrate with a selector swap.
|
|
76
|
+
* A generic, virtualized table with scroll-driven infinite loading. Independent of `ui-table`: it reuses
|
|
77
|
+
* only stable leaf primitives (`ui-skeleton`) and duplicates the column/context type shapes so consumers
|
|
78
|
+
* can migrate with a selector swap.
|
|
83
79
|
*/
|
|
84
80
|
declare class InfiniteScrollTableComponent<T> {
|
|
85
|
-
/** Rows loaded so far. The consumer appends pages to this array. */
|
|
86
|
-
readonly data: _angular_core.InputSignal<T[]>;
|
|
87
|
-
/** Column definitions. The first `isSticky` column pins left; the last `isSticky` column pins right. */
|
|
88
|
-
readonly columns: _angular_core.InputSignal<InfiniteScrollTableColumn<T>[]>;
|
|
89
81
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
82
|
+
* Rows loaded so far. **Must change by reference** (`[...rows, ...page]`): a signal input cannot observe
|
|
83
|
+
* `rows.push(...)`, so an in-place append renders nothing and leaves `loadMore` disarmed.
|
|
92
84
|
*/
|
|
85
|
+
readonly data: _angular_core.InputSignal<readonly T[]>;
|
|
86
|
+
readonly columns: _angular_core.InputSignal<InfiniteScrollTableColumn<T>[]>;
|
|
87
|
+
/** Fixed row height in px (the virtualization `itemSize`). Variable row heights are unsupported. */
|
|
93
88
|
readonly rowHeight: _angular_core.InputSignal<number>;
|
|
94
|
-
/**
|
|
89
|
+
/** Stable row identity so recycled rows re-render correctly. Takes precedence over `rowIdKey`. */
|
|
95
90
|
readonly trackBy: _angular_core.InputSignal<TrackByFunction<T> | undefined>;
|
|
96
|
-
/**
|
|
91
|
+
/** Key on each row holding a stable id. Used when `trackBy` is not provided. */
|
|
97
92
|
readonly rowIdKey: _angular_core.InputSignal<string | undefined>;
|
|
98
93
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* so the header cannot stick to an outer scrolling page. Kept so `ui-table` templates migrate
|
|
102
|
-
* unchanged. Default `true`.
|
|
94
|
+
* CDK's rendered buffers. Both default to a multiple of `rowHeight` (~5 and ~10 rows) rather than a
|
|
95
|
+
* fixed px value, which would mean a different row count at every `rowHeight`.
|
|
103
96
|
*/
|
|
104
|
-
readonly
|
|
97
|
+
readonly minBufferPx: _angular_core.InputSignal<number | undefined>;
|
|
98
|
+
readonly maxBufferPx: _angular_core.InputSignal<number | undefined>;
|
|
105
99
|
/** Max height of the internal scroll region (e.g. `'70vh'`). The body shrinks to fit fewer rows. */
|
|
106
100
|
readonly maxHeight: _angular_core.InputSignal<string>;
|
|
107
|
-
/**
|
|
101
|
+
/** Stretch to the parent's height instead of the content's; `maxHeight` becomes a cap, not the target. */
|
|
102
|
+
readonly fillHeight: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
108
103
|
readonly isCondensed: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
109
104
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* Selection stays data-driven and consumer-managed, exactly like `ui-table`. Default `false`.
|
|
105
|
+
* Prepends a left-pinned checkbox column driven by each row's `selected` property. Consumer-managed
|
|
106
|
+
* (like `ui-table`): toggling only emits `selectionChange`.
|
|
113
107
|
*/
|
|
114
108
|
readonly selectable: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
109
|
+
/**
|
|
110
|
+
* Makes rows focusable and activatable by click or Enter/Space. Off by default: a read-only table
|
|
111
|
+
* must not create a tab stop per rendered row or imply interactivity it does not have.
|
|
112
|
+
*/
|
|
113
|
+
readonly rowsClickable: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
115
114
|
/** First-load state: renders a full body of skeleton rows. */
|
|
116
115
|
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
117
116
|
/** Appends skeleton rows below the existing rows while the next page is fetched. */
|
|
118
117
|
readonly loadingMore: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
119
|
-
/**
|
|
118
|
+
/** Required, not defaulted: a silent "never load" default would disable the headline behaviour. */
|
|
120
119
|
readonly hasMore: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
121
|
-
/** Number of skeleton rows for the first-load state. */
|
|
122
120
|
readonly skeletonRowCount: _angular_core.InputSignal<number>;
|
|
123
|
-
/**
|
|
121
|
+
/** Number of skeleton rows appended below the loaded rows while `loadingMore` is true. */
|
|
122
|
+
readonly loadMoreSkeletonCount: _angular_core.InputSignal<number>;
|
|
123
|
+
/**
|
|
124
|
+
* Skeleton placeholder columns for a lazily-loaded column set. They deliberately sit OUTSIDE `columns`,
|
|
125
|
+
* so they cannot change which column is last and unpin a sticky last column.
|
|
126
|
+
*/
|
|
127
|
+
readonly loadingColumnCount: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
124
128
|
readonly loadMoreThreshold: _angular_core.InputSignal<number>;
|
|
125
|
-
/**
|
|
129
|
+
/** Shown when `data` is empty and not loading. */
|
|
126
130
|
readonly noDataTemplate: _angular_core.InputSignal<TemplateRef<unknown> | undefined>;
|
|
127
|
-
/**
|
|
131
|
+
/** Shown when `error` is `true`. Receives `{ $implicit: retry, retry }` as context. */
|
|
128
132
|
readonly errorTemplate: _angular_core.InputSignal<TemplateRef<InfiniteScrollTableErrorContext> | undefined>;
|
|
129
|
-
/** Whether a page fetch failed. */
|
|
130
133
|
readonly error: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
131
134
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
135
|
+
* Shown once `hasMore` goes `false` with rows loaded. Deliberately has NO built-in fallback (unlike
|
|
136
|
+
* `noDataTemplate` / `errorTemplate`): a single-page list would otherwise flash "no more results".
|
|
134
137
|
*/
|
|
138
|
+
readonly endOfListTemplate: _angular_core.InputSignal<TemplateRef<unknown> | undefined>;
|
|
139
|
+
/** Guarded: only when `hasMore && !loading && !loadingMore`, and only once per approach to the end. */
|
|
135
140
|
readonly loadMore: _angular_core.OutputEmitterRef<void>;
|
|
136
|
-
/** Fires from the error template's retry affordance. */
|
|
137
141
|
readonly retry: _angular_core.OutputEmitterRef<void>;
|
|
138
|
-
/** Fires when a data row is clicked; payload is the row plus its data index. */
|
|
139
142
|
readonly rowClick: _angular_core.OutputEmitterRef<InfiniteScrollTableRowClick<T>>;
|
|
140
|
-
/**
|
|
141
|
-
* Fires when a row's selection checkbox is toggled (only when `selectable`). Payload is the row,
|
|
142
|
-
* its data index, and the new selected state. The consumer updates its data's `selected` property.
|
|
143
|
-
*/
|
|
143
|
+
/** The consumer is expected to apply `selected` back onto its own data. */
|
|
144
144
|
readonly selectionChange: _angular_core.OutputEmitterRef<InfiniteScrollTableRowSelection<T>>;
|
|
145
|
-
/** Fixed width of the checkbox column; exposed so the template can offset a sticky first column. */
|
|
146
|
-
protected readonly checkboxColumnWidth = 56;
|
|
147
145
|
protected readonly viewport: _angular_core.Signal<CdkVirtualScrollViewport | undefined>;
|
|
148
146
|
protected readonly headerScroll: _angular_core.Signal<ElementRef<HTMLElement> | undefined>;
|
|
149
|
-
/** Horizontal-scroll state, mirroring the existing table's `scrollSettings`. */
|
|
150
147
|
protected readonly scrollStart: _angular_core.WritableSignal<boolean>;
|
|
151
148
|
protected readonly scrollEnd: _angular_core.WritableSignal<boolean>;
|
|
152
149
|
protected readonly horizontalScroll: _angular_core.WritableSignal<boolean>;
|
|
153
|
-
/**
|
|
154
|
-
* Measured width (px) of the body viewport's vertical scrollbar. Reserved as right padding on the
|
|
155
|
-
* header so the header's content width exactly equals the body's, keeping every column — including
|
|
156
|
-
* the last — aligned between header and body regardless of browser/scrollbar behaviour.
|
|
157
|
-
*/
|
|
150
|
+
/** Reserved as right padding on the header, so its content width exactly equals the body's. */
|
|
158
151
|
protected readonly scrollbarWidth: _angular_core.WritableSignal<number>;
|
|
152
|
+
/** Added to the viewport height so on a short list the scrollbar doesn't eat into the rows. */
|
|
153
|
+
protected readonly hScrollbarHeight: _angular_core.WritableSignal<number>;
|
|
159
154
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
155
|
+
* Paging latch. Three fields, one rule: `loadMore` emits at most once per page that lands while the
|
|
156
|
+
* user is inside the trigger zone. `isLoadMoreArmed` is the latch itself, written here and by
|
|
157
|
+
* `checkLoadMore`; `dataLengthAtEmit` records how long `data` was when the last emission went out, so
|
|
158
|
+
* "the requested page arrived" is a length comparison rather than a guess about scroll positions;
|
|
159
|
+
* `firstVisibleIndex` is where the user actually is.
|
|
160
|
+
*
|
|
161
|
+
* The invariant that matters: arming and firing must read the SAME trigger zone. They used to derive it
|
|
162
|
+
* from two different thresholds, which opened bands the latch could never leave.
|
|
163
163
|
*/
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
private isLoadMoreArmed;
|
|
165
|
+
private dataLengthAtEmit;
|
|
166
|
+
/** In-place-mutation detector; see the effect that reads these for the discriminator. */
|
|
167
|
+
private wasLoadingMore;
|
|
168
|
+
private lastDataReference;
|
|
169
|
+
private lastDataLength;
|
|
167
170
|
/** Pending frame for a deferred CDK viewport re-measure, so repeated triggers coalesce to one. */
|
|
168
171
|
private remeasureFrame;
|
|
172
|
+
/** Pending frame for the deferred scroll reset. Cancelled on destroy, like every other frame here. */
|
|
173
|
+
private resetScrollFrame;
|
|
174
|
+
private previousHeadIdentity;
|
|
175
|
+
/** Latches once any non-empty `data` is seen, so only the very first render is exempt from resetting. */
|
|
176
|
+
private hasSeenHead;
|
|
177
|
+
/** Previous `loading` value, for spotting the false -> true edge that starts a reset. */
|
|
178
|
+
private wasLoading;
|
|
169
179
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* In that case the JS `scrollLeft` sync is skipped so the offset isn't applied twice; it stays as
|
|
173
|
-
* the fallback for browsers without scroll-driven animations.
|
|
180
|
+
* First visible row index, kept current from `viewport.scrolledIndexChange` (no layout read) rather
|
|
181
|
+
* than `viewport.getRenderedRange().start`, which includes CDK's read-ahead buffer.
|
|
174
182
|
*/
|
|
175
|
-
private
|
|
183
|
+
private firstVisibleIndex;
|
|
176
184
|
protected readonly skeletonTheme: {
|
|
177
185
|
background: string;
|
|
178
186
|
'border-radius': string;
|
|
179
187
|
height: string;
|
|
180
188
|
'margin-bottom': string;
|
|
181
189
|
};
|
|
182
|
-
protected readonly
|
|
183
|
-
protected readonly
|
|
184
|
-
|
|
190
|
+
protected readonly stickyStartKey: _angular_core.Signal<string | undefined>;
|
|
191
|
+
protected readonly stickyEndKey: _angular_core.Signal<string | undefined>;
|
|
192
|
+
protected readonly defaultColumnWidth = "160px";
|
|
193
|
+
protected readonly effectiveMinBufferPx: _angular_core.Signal<number>;
|
|
194
|
+
/**
|
|
195
|
+
* The `Math.max` is load-bearing: CDK throws in dev mode when `maxBufferPx < minBufferPx`, which a
|
|
196
|
+
* consumer triggers just by raising `minBufferPx` above the derived default.
|
|
197
|
+
*/
|
|
198
|
+
protected readonly effectiveMaxBufferPx: _angular_core.Signal<number>;
|
|
199
|
+
/** Stable keys for the placeholder columns, so `@for` can track them across renders. */
|
|
200
|
+
protected readonly loadingColumns: _angular_core.Signal<string[]>;
|
|
185
201
|
protected readonly renderRows: _angular_core.Signal<RenderRow<T>[]>;
|
|
186
202
|
protected readonly hasData: _angular_core.Signal<boolean>;
|
|
187
|
-
/** The virtualized body is shown for the first-load skeletons and whenever there are rows. */
|
|
188
203
|
protected readonly showViewport: _angular_core.Signal<boolean>;
|
|
204
|
+
/**
|
|
205
|
+
* `loadingMore` counts as loading here too: a consumer that retries a failed first page through the same
|
|
206
|
+
* flag it uses for every page would otherwise render "no rows" with `aria-busy` set and the live region
|
|
207
|
+
* announcing a fetch.
|
|
208
|
+
*/
|
|
189
209
|
protected readonly showEmptyState: _angular_core.Signal<boolean>;
|
|
190
210
|
protected readonly showErrorState: _angular_core.Signal<boolean>;
|
|
191
211
|
protected readonly showErrorFooter: _angular_core.Signal<boolean>;
|
|
192
212
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
|
|
196
|
-
|
|
213
|
+
* The negative clauses keep this out of slots other states own, and `!loadingMore()` closes a one-tick
|
|
214
|
+
* flash: a fetch completing and the consumer flipping `hasMore` need not land in the same cycle.
|
|
215
|
+
*/
|
|
216
|
+
protected readonly showEndOfList: _angular_core.Signal<boolean>;
|
|
217
|
+
/**
|
|
218
|
+
* CSS `min()` because the cap mixes units. The scrollbar reserve stops a short list from growing a
|
|
219
|
+
* spurious vertical scrollbar; fill mode returns `null` so flex owns the sizing and the reserve is moot.
|
|
197
220
|
*/
|
|
198
|
-
protected readonly viewportHeight: _angular_core.Signal<string>;
|
|
199
|
-
|
|
200
|
-
|
|
221
|
+
protected readonly viewportHeight: _angular_core.Signal<string | null>;
|
|
222
|
+
protected readonly translationContext = "INFINITE_SCROLL_TABLE.";
|
|
223
|
+
/** A translation key, resolved in the template: screen-reader users are not all English speakers. */
|
|
224
|
+
protected readonly statusMessageKey: _angular_core.Signal<string>;
|
|
201
225
|
protected readonly errorContext: InfiniteScrollTableErrorContext;
|
|
202
226
|
protected readonly renderRowTrackBy: TrackByFunction<RenderRow<T>>;
|
|
203
227
|
constructor();
|
|
204
|
-
|
|
228
|
+
private cancelResetScrollFrame;
|
|
229
|
+
/** No-ops only when no rows are rendered: the empty state, or an error with no rows. */
|
|
230
|
+
scrollToIndex(index: number, behavior?: ScrollBehavior): void;
|
|
231
|
+
scrollToTop(behavior?: ScrollBehavior): void;
|
|
205
232
|
/**
|
|
206
|
-
* The single
|
|
207
|
-
*
|
|
208
|
-
* `flex-grow:0; flex-shrink:0; overflow:hidden`) to the header cell and every body cell, so a column
|
|
209
|
-
* is exactly this width in both containers — content is clipped and can never widen it. This is what
|
|
210
|
-
* keeps header and body columns aligned end-to-end regardless of cell content or horizontal scroll.
|
|
233
|
+
* The single place `T` is widened to its structural contract. Every field read on a row goes through
|
|
234
|
+
* here, so the assertion exists once instead of at each call site.
|
|
211
235
|
*/
|
|
236
|
+
private asRowLike;
|
|
237
|
+
protected getCellValue(item: T, key: string): unknown;
|
|
238
|
+
/** Applied as `flex-basis`, `min-width` AND `max-width` on header and body cells alike — see the SCSS. */
|
|
212
239
|
protected columnWidth(column: InfiniteScrollTableColumn<T>): string;
|
|
213
|
-
protected
|
|
214
|
-
/**
|
|
215
|
-
* Whether a row should show the selected highlight. Mirrors `ui-table`: only when `selectable` is
|
|
216
|
-
* enabled and the row's data carries a truthy `selected` property. Skeleton rows are never selected.
|
|
217
|
-
*/
|
|
240
|
+
protected emitRowClick(event: Event, row: RenderRow<T>): void;
|
|
218
241
|
protected isRowSelected(row: RenderRow<T>): boolean;
|
|
219
|
-
|
|
220
|
-
|
|
242
|
+
protected emitSelectionChange(row: RenderRow<T>, selected: boolean): void;
|
|
243
|
+
/** Reads `--ui-ist-checkbox-width` so the offset cannot drift from the checkbox column's own width. */
|
|
244
|
+
protected stickyStartLeft(column: InfiniteScrollTableColumn<T>): string | null;
|
|
221
245
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
246
|
+
* Only the outermost start-pinned cell may cast the sticky shadow: the checkbox cell is pinned too, and
|
|
247
|
+
* shadowing both would drop a shadow across the column beside it.
|
|
224
248
|
*/
|
|
225
|
-
protected
|
|
226
|
-
|
|
227
|
-
|
|
249
|
+
protected isStickyStartEdge(column: InfiniteScrollTableColumn<T>): boolean;
|
|
250
|
+
protected activateRow(event: Event, row: RenderRow<T>): void;
|
|
251
|
+
/** A clickable row matches `[tabindex]` itself, so `currentTarget` must be excluded explicitly. */
|
|
252
|
+
private isInteractiveTarget;
|
|
253
|
+
/** Whether the user is selecting text, in which case a click is a selection gesture, not activation. */
|
|
254
|
+
private hasTextSelection;
|
|
228
255
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* driven from the ResizeObserver; repeated triggers coalesce to a single measure. The re-measure is
|
|
232
|
-
* what makes CDK recompute the rendered range to fill a viewport whose height grew at runtime.
|
|
256
|
+
* Deferred a frame to read the settled layout and never trip "ResizeObserver loop limit exceeded";
|
|
257
|
+
* repeated triggers coalesce to one measure.
|
|
233
258
|
*/
|
|
234
259
|
private scheduleViewportRemeasure;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
260
|
+
/**
|
|
261
|
+
* The third `checkLoadMore` trigger, and the only one that survives a page landing without a rendered-range
|
|
262
|
+
* change. CDK emits a range only when the virtual-for LENGTH changes, so a page whose row count exactly
|
|
263
|
+
* replaces the load-more skeletons (`data + skeletons` before, `data` after) moves nothing CDK watches —
|
|
264
|
+
* and when the new rows add no scrollable height, no scroll event can ever arrive either. Runs after the
|
|
265
|
+
* re-measure so the zone is tested against the size CDK just settled on.
|
|
266
|
+
*/
|
|
267
|
+
private settleLoadMore;
|
|
268
|
+
private emitRetry;
|
|
269
|
+
/**
|
|
270
|
+
* The index fallback is identity-in-name-only — it cannot tell rows apart after a reorder — which is why
|
|
271
|
+
* the automatic scroll reset cannot work without `trackBy` or `rowIdKey`.
|
|
272
|
+
*/
|
|
273
|
+
private rowIdentity;
|
|
274
|
+
/**
|
|
275
|
+
* Assigning an absolute `scrollLeft` is drift-free by construction: it self-corrects every scroll event
|
|
276
|
+
* and the browser clamps when the header's maximum is momentarily smaller. A progress-normalized CSS
|
|
277
|
+
* scroll-timeline cannot guarantee that, which is why it was removed — do not reintroduce one.
|
|
278
|
+
*/
|
|
238
279
|
private syncHorizontalScroll;
|
|
239
280
|
/**
|
|
240
|
-
*
|
|
241
|
-
*
|
|
281
|
+
* How many rows the viewport shows. Zero until CDK has measured, which callers must treat as
|
|
282
|
+
* "unknown" rather than "none".
|
|
283
|
+
*/
|
|
284
|
+
private visibleRowCount;
|
|
285
|
+
/**
|
|
286
|
+
* Rows from the end that count as "approaching it". Capped at a screenful: a threshold wider than the
|
|
287
|
+
* viewport cannot mean approaching, and uncapped it made the zone unleavable at every scroll position,
|
|
288
|
+
* which is how an oversized `loadMoreThreshold` used to walk a whole dataset unattended. Clamped at 0 so
|
|
289
|
+
* a negative value can't push the trigger point past the end and disable paging outright.
|
|
290
|
+
*/
|
|
291
|
+
private triggerZoneRows;
|
|
292
|
+
/**
|
|
293
|
+
* The rendered range includes CDK's read-ahead buffer, so measuring it conflates the user reaching the
|
|
294
|
+
* end with CDK merely pre-rendering it. The visible end has no such slack, so it tracks the user's
|
|
295
|
+
* actual scroll position instead.
|
|
296
|
+
*/
|
|
297
|
+
private isInTriggerZone;
|
|
298
|
+
/**
|
|
299
|
+
* Re-arms the latch when something other than scrolling has to do it. Two cases, both of which used to
|
|
300
|
+
* be terminal stalls:
|
|
301
|
+
*
|
|
302
|
+
* - **The requested page landed.** `data` grew past its length at the last emission, so that emission is
|
|
303
|
+
* spent. Without this, re-arming needed the user to scroll *out* of the zone and back — impossible when
|
|
304
|
+
* the page was smaller than the threshold, and impossible to even attempt when the new rows added no
|
|
305
|
+
* scrollable height.
|
|
306
|
+
* - **The zone can't be left.** `visibleEnd` bottoms out at `visibleRows`, so while that floor sits
|
|
307
|
+
* inside the zone no amount of scrolling re-arms anything. Also covers a not-yet-measured viewport,
|
|
308
|
+
* which must count as unleavable or the first fill never starts.
|
|
309
|
+
*
|
|
310
|
+
* Deliberately not driven by `loadingMore` or `error`: a failed fetch clears `loadingMore` without
|
|
311
|
+
* growing `data`, and must stay disarmed rather than re-fire in a loop.
|
|
242
312
|
*/
|
|
313
|
+
private rearmLoadMoreIfUnreachable;
|
|
314
|
+
/** Emits at most once per page that lands while the user is inside the trigger zone. */
|
|
243
315
|
private checkLoadMore;
|
|
244
316
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<InfiniteScrollTableComponent<any>, never>;
|
|
245
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<InfiniteScrollTableComponent<any>, "ui-infinite-scroll-table", never, { "data": { "alias": "data"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": true; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "rowIdKey": { "alias": "rowIdKey"; "required": false; "isSignal": true; }; "
|
|
317
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<InfiniteScrollTableComponent<any>, "ui-infinite-scroll-table", never, { "data": { "alias": "data"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": true; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "rowIdKey": { "alias": "rowIdKey"; "required": false; "isSignal": true; }; "minBufferPx": { "alias": "minBufferPx"; "required": false; "isSignal": true; }; "maxBufferPx": { "alias": "maxBufferPx"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "fillHeight": { "alias": "fillHeight"; "required": false; "isSignal": true; }; "isCondensed": { "alias": "isCondensed"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "rowsClickable": { "alias": "rowsClickable"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "loadingMore": { "alias": "loadingMore"; "required": false; "isSignal": true; }; "hasMore": { "alias": "hasMore"; "required": true; "isSignal": true; }; "skeletonRowCount": { "alias": "skeletonRowCount"; "required": false; "isSignal": true; }; "loadMoreSkeletonCount": { "alias": "loadMoreSkeletonCount"; "required": false; "isSignal": true; }; "loadingColumnCount": { "alias": "loadingColumnCount"; "required": false; "isSignal": true; }; "loadMoreThreshold": { "alias": "loadMoreThreshold"; "required": false; "isSignal": true; }; "noDataTemplate": { "alias": "noDataTemplate"; "required": false; "isSignal": true; }; "errorTemplate": { "alias": "errorTemplate"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "endOfListTemplate": { "alias": "endOfListTemplate"; "required": false; "isSignal": true; }; }, { "loadMore": "loadMore"; "retry": "retry"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; }, never, never, true, never>;
|
|
246
318
|
}
|
|
247
319
|
|
|
248
320
|
declare class InfiniteScrollTableComponentModule {
|
|
@@ -252,4 +324,4 @@ declare class InfiniteScrollTableComponentModule {
|
|
|
252
324
|
}
|
|
253
325
|
|
|
254
326
|
export { InfiniteScrollTableComponent, InfiniteScrollTableComponentModule };
|
|
255
|
-
export type { InfiniteScrollTableColumn, InfiniteScrollTableColumnAlignment, InfiniteScrollTableColumnStyles, InfiniteScrollTableErrorContext, InfiniteScrollTableRowClick, InfiniteScrollTableRowSelection };
|
|
327
|
+
export type { InfiniteScrollTableColumn, InfiniteScrollTableColumnAlignment, InfiniteScrollTableColumnStyles, InfiniteScrollTableErrorContext, InfiniteScrollTableHeaderCellContext, InfiniteScrollTableRowCellContext, InfiniteScrollTableRowClick, InfiniteScrollTableRowLike, InfiniteScrollTableRowSelection };
|