@ng-native/components 0.2.0 → 0.4.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/dist/content-container.d.ts +25 -0
- package/dist/content-container.js +35 -0
- package/dist/content-container.js.map +1 -0
- package/dist/gestures-web.d.ts +12 -0
- package/dist/gestures-web.js +32 -0
- package/dist/gestures-web.js.map +1 -0
- package/dist/gestures.d.ts +0 -1
- package/dist/gestures.js +5 -4
- package/dist/gestures.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/keyboard-avoiding-view.d.ts +6 -1
- package/dist/keyboard-avoiding-view.js +23 -6
- package/dist/keyboard-avoiding-view.js.map +1 -1
- package/dist/pressable.d.ts +56 -4
- package/dist/pressable.js +80 -7
- package/dist/pressable.js.map +1 -1
- package/dist/reanimated-web.d.ts +18 -0
- package/dist/reanimated-web.js +59 -0
- package/dist/reanimated-web.js.map +1 -0
- package/dist/reanimated.d.ts +4 -4
- package/dist/reanimated.js +3 -3
- package/dist/reanimated.js.map +1 -1
- package/dist/refresh-control.d.ts +4 -1
- package/dist/refresh-control.js +4 -1
- package/dist/refresh-control.js.map +1 -1
- package/dist/scroll-view.d.ts +17 -1
- package/dist/scroll-view.js +59 -6
- package/dist/scroll-view.js.map +1 -1
- package/dist/section-list.d.ts +14 -2
- package/dist/section-list.js +20 -4
- package/dist/section-list.js.map +1 -1
- package/dist/stand-ins/gesture-handler.d.ts +40 -0
- package/dist/stand-ins/gesture-handler.js +43 -0
- package/dist/stand-ins/gesture-handler.js.map +1 -0
- package/dist/stand-ins/reanimated.d.ts +62 -0
- package/dist/stand-ins/reanimated.js +95 -0
- package/dist/stand-ins/reanimated.js.map +1 -0
- package/dist/stand-ins/worklets.d.ts +11 -0
- package/dist/stand-ins/worklets.js +24 -0
- package/dist/stand-ins/worklets.js.map +1 -0
- package/dist/sticky-headers.d.ts +6 -0
- package/dist/sticky-headers.js +7 -2
- package/dist/sticky-headers.js.map +1 -1
- package/dist/switch.d.ts +11 -1
- package/dist/switch.js +16 -3
- package/dist/switch.js.map +1 -1
- package/dist/text.d.ts +11 -2
- package/dist/text.js +15 -1
- package/dist/text.js.map +1 -1
- package/dist/touchable-opacity.d.ts +2 -1
- package/dist/touchable-opacity.js +3 -0
- package/dist/touchable-opacity.js.map +1 -1
- package/dist/view-base.d.ts +36 -21
- package/dist/view-base.js +91 -23
- package/dist/view-base.js.map +1 -1
- package/dist/virtual-list.d.ts +52 -7
- package/dist/virtual-list.js +132 -44
- package/dist/virtual-list.js.map +1 -1
- package/dist/worklets.d.ts +11 -0
- package/dist/worklets.js.map +1 -1
- package/dist/written-props.js +1 -0
- package/dist/written-props.js.map +1 -1
- package/dist/zero-size-warning.d.ts +30 -0
- package/dist/zero-size-warning.js +58 -0
- package/dist/zero-size-warning.js.map +1 -0
- package/package.json +19 -4
package/dist/virtual-list.d.ts
CHANGED
|
@@ -28,6 +28,16 @@ export interface VirtualRow<T> {
|
|
|
28
28
|
*/
|
|
29
29
|
readonly parked?: true;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Space around the rows, inside the scrolling content: one number for every side, or a side each,
|
|
33
|
+
* as FlatList's `contentContainerStyle` padding.
|
|
34
|
+
*/
|
|
35
|
+
export type VirtualListPadding = number | {
|
|
36
|
+
readonly top?: number;
|
|
37
|
+
readonly right?: number;
|
|
38
|
+
readonly bottom?: number;
|
|
39
|
+
readonly left?: number;
|
|
40
|
+
};
|
|
31
41
|
/** A row height: one for every row, or one per item. */
|
|
32
42
|
export type VirtualItemHeight<T> = number | ((item: T, index: number) => number);
|
|
33
43
|
/**
|
|
@@ -106,7 +116,8 @@ interface Gap<T> {
|
|
|
106
116
|
* `horizontal` swaps the axis: rows are placed by `left` and sized by `width`, and the offset is
|
|
107
117
|
* read from `contentOffset.x`. `inverted` is a scale of -1 on the list and on each row, which is
|
|
108
118
|
* how FlatList does it too - the list scrolls from the bottom and each row is flipped back the
|
|
109
|
-
* right way up, so a chat
|
|
119
|
+
* right way up. The first item is the one at the bottom, so a chat passes its messages newest
|
|
120
|
+
* first.
|
|
110
121
|
*
|
|
111
122
|
* `stickyIndices` pins a row to the leading edge while the rows under it scroll past, which is
|
|
112
123
|
* FlatList's `stickyHeaderIndices` counted without the header. `stickyHeader` pins the
|
|
@@ -143,6 +154,14 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
143
154
|
* honest the scroll bar is and the less a jump to an unmeasured row has to correct.
|
|
144
155
|
*/
|
|
145
156
|
readonly estimatedItemHeight: import("@angular/core").InputSignal<VirtualItemHeight<T>>;
|
|
157
|
+
/**
|
|
158
|
+
* Space around the rows, inside the scrolling content. The leading side comes before the first
|
|
159
|
+
* row and the trailing side after the last; the sides across the axis inset every row. The
|
|
160
|
+
* header and footer sit outside it, as FlatList's do outside `contentContainerStyle`.
|
|
161
|
+
*/
|
|
162
|
+
readonly contentPadding: import("@angular/core").InputSignal<VirtualListPadding>;
|
|
163
|
+
/** Space between one row and the next, along the axis: not before the first or after the last. */
|
|
164
|
+
readonly rowGap: import("@angular/core").InputSignalWithTransform<number, unknown>;
|
|
146
165
|
/**
|
|
147
166
|
* An item's identity, as FlatList's `keyExtractor`: what a measured height, a slot and a held
|
|
148
167
|
* position follow across an insert. Without it an item is its own key, which is enough for items
|
|
@@ -225,6 +244,12 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
225
244
|
private readonly pinning;
|
|
226
245
|
/** Rows size themselves and are laid out in flow, rather than placed at a known offset. */
|
|
227
246
|
readonly measuring: import("@angular/core").Signal<boolean>;
|
|
247
|
+
/** The padding on each side. */
|
|
248
|
+
private readonly edges;
|
|
249
|
+
/** The padding before the first row, along the axis. */
|
|
250
|
+
private readonly lead;
|
|
251
|
+
/** The rows' insets across the axis, as the props that place an absolutely positioned row. */
|
|
252
|
+
private readonly across;
|
|
228
253
|
/** Heights native has reported, by key. */
|
|
229
254
|
private readonly measured;
|
|
230
255
|
/** Bumped when a measurement changes, which is what re-sizes the list. */
|
|
@@ -243,8 +268,13 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
243
268
|
private readonly indexOfKey;
|
|
244
269
|
/** The index, with a dependency on its measurements for whoever is reading it. */
|
|
245
270
|
private layout;
|
|
246
|
-
/**
|
|
271
|
+
/**
|
|
272
|
+
* The list's own total extent along its axis: the padding at both ends, the rows, and a gap
|
|
273
|
+
* between each two of them.
|
|
274
|
+
*/
|
|
247
275
|
private readonly extent;
|
|
276
|
+
/** A fixed-height row and the gap after it. */
|
|
277
|
+
private stride;
|
|
248
278
|
protected readonly canvas: import("@angular/core").Signal<{
|
|
249
279
|
width: number;
|
|
250
280
|
flexDirection: string;
|
|
@@ -259,7 +289,7 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
259
289
|
*
|
|
260
290
|
* The list ends up scrolled from the far end with its rows in reverse, and the second flip puts
|
|
261
291
|
* each row's own content back the right way up. It is what `FlatList` does, and it is why an
|
|
262
|
-
* inverted list needs no reversed
|
|
292
|
+
* inverted list needs no reversed maths: the first item is at offset 0, which is the bottom.
|
|
263
293
|
*/
|
|
264
294
|
protected readonly flip: import("@angular/core").Signal<Readonly<Record<string, number>>[] | undefined>;
|
|
265
295
|
/**
|
|
@@ -267,12 +297,18 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
267
297
|
* A style binding validates its values as the DOM's, and warns on a list in development.
|
|
268
298
|
*/
|
|
269
299
|
private readonly flipText;
|
|
300
|
+
/**
|
|
301
|
+
* What places a row in flow: the gap after it and the padding across the axis, as margins, since
|
|
302
|
+
* native lays the row out. Empty when there are none, so a plain list commits no margins.
|
|
303
|
+
*/
|
|
304
|
+
private readonly flowSpacing;
|
|
270
305
|
/** A row in flow, flipped back when the list is inverted. One object, so rows never re-clone. */
|
|
271
306
|
private readonly flowStyle;
|
|
272
|
-
/** Top of a row. */
|
|
307
|
+
/** Top of a row: the leading padding, and every row and gap before it. */
|
|
273
308
|
private topOf;
|
|
309
|
+
/** A row's own size, without the gap after it. */
|
|
274
310
|
private heightOf;
|
|
275
|
-
/** First row whose bottom is past `y`. */
|
|
311
|
+
/** First row whose bottom, or the gap after it, is past `y`. */
|
|
276
312
|
private indexAt;
|
|
277
313
|
/** The row the viewport's leading edge is in, taken at each scroll. */
|
|
278
314
|
private anchor;
|
|
@@ -327,7 +363,16 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
327
363
|
private successorOf;
|
|
328
364
|
/** Make a queued correction, after the commit that moved the rows has gone to native. */
|
|
329
365
|
private flushScroll;
|
|
366
|
+
/** In development, a list with rows that stays at zero size; see `ZeroSizeWarning`. */
|
|
367
|
+
private readonly zeroSize;
|
|
330
368
|
constructor();
|
|
369
|
+
/** Whether the viewport has been laid out yet, so a zero in it is a measurement. */
|
|
370
|
+
private viewportMeasured;
|
|
371
|
+
/**
|
|
372
|
+
* In development, rows that arrive in a list already measured at zero, or go from one, with no
|
|
373
|
+
* new layout to say so: an update to `items` alone does not lay the viewport out again.
|
|
374
|
+
*/
|
|
375
|
+
private checkZeroSize;
|
|
331
376
|
/** The rows to render, and the edges of the run they sit in. */
|
|
332
377
|
private readonly span;
|
|
333
378
|
readonly window: import("@angular/core").Signal<VirtualRow<T>[]>;
|
|
@@ -479,7 +524,7 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
479
524
|
y?: number;
|
|
480
525
|
};
|
|
481
526
|
}>): void;
|
|
482
|
-
/**
|
|
527
|
+
/** A pinned row's translate, settled once scrolling pauses: see `STICKY_SETTLE_MS`. */
|
|
483
528
|
private settleAfterPause;
|
|
484
529
|
protected onLayout(event: NativeSyntheticEvent<{
|
|
485
530
|
layout?: {
|
|
@@ -508,7 +553,7 @@ export declare class VirtualList<T> extends ScrollViewProps {
|
|
|
508
553
|
}>): void;
|
|
509
554
|
private checkEnd;
|
|
510
555
|
static ɵfac: i0.ɵɵFactoryDeclaration<VirtualList<any>, never>;
|
|
511
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<VirtualList<any>, "virtual-list", ["virtualList"], { "items": { "alias": "items"; "required": true; "isSignal": true; }; "itemHeight": { "alias": "itemHeight"; "required": false; "isSignal": true; }; "estimatedItemHeight": { "alias": "estimatedItemHeight"; "required": false; "isSignal": true; }; "keyExtractor": { "alias": "keyExtractor"; "required": false; "isSignal": true; }; "itemType": { "alias": "itemType"; "required": false; "isSignal": true; }; "maintainVisibleContentPosition": { "alias": "maintainVisibleContentPosition"; "required": false; "isSignal": true; }; "overscan": { "alias": "overscan"; "required": false; "isSignal": true; }; "endReachedThreshold": { "alias": "endReachedThreshold"; "required": false; "isSignal": true; }; "horizontal": { "alias": "horizontal"; "required": false; "isSignal": true; }; "inverted": { "alias": "inverted"; "required": false; "isSignal": true; }; "stickyIndices": { "alias": "stickyIndices"; "required": false; "isSignal": true; }; "stickyHeader": { "alias": "stickyHeader"; "required": false; "isSignal": true; }; "keyboardShouldPersistTaps": { "alias": "keyboardShouldPersistTaps"; "required": false; "isSignal": true; }; "itemVisiblePercentThreshold": { "alias": "itemVisiblePercentThreshold"; "required": false; "isSignal": true; }; }, { "endReached": "endReached"; "viewableItemsChanged": "viewableItemsChanged"; }, ["separator", "refreshControl"], ["refresh-control", "[listHeader]", "*", "[listFooter]"], true, never>;
|
|
556
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<VirtualList<any>, "virtual-list", ["virtualList"], { "items": { "alias": "items"; "required": true; "isSignal": true; }; "itemHeight": { "alias": "itemHeight"; "required": false; "isSignal": true; }; "estimatedItemHeight": { "alias": "estimatedItemHeight"; "required": false; "isSignal": true; }; "contentPadding": { "alias": "contentPadding"; "required": false; "isSignal": true; }; "rowGap": { "alias": "rowGap"; "required": false; "isSignal": true; }; "keyExtractor": { "alias": "keyExtractor"; "required": false; "isSignal": true; }; "itemType": { "alias": "itemType"; "required": false; "isSignal": true; }; "maintainVisibleContentPosition": { "alias": "maintainVisibleContentPosition"; "required": false; "isSignal": true; }; "overscan": { "alias": "overscan"; "required": false; "isSignal": true; }; "endReachedThreshold": { "alias": "endReachedThreshold"; "required": false; "isSignal": true; }; "horizontal": { "alias": "horizontal"; "required": false; "isSignal": true; }; "inverted": { "alias": "inverted"; "required": false; "isSignal": true; }; "stickyIndices": { "alias": "stickyIndices"; "required": false; "isSignal": true; }; "stickyHeader": { "alias": "stickyHeader"; "required": false; "isSignal": true; }; "keyboardShouldPersistTaps": { "alias": "keyboardShouldPersistTaps"; "required": false; "isSignal": true; }; "itemVisiblePercentThreshold": { "alias": "itemVisiblePercentThreshold"; "required": false; "isSignal": true; }; }, { "endReached": "endReached"; "viewableItemsChanged": "viewableItemsChanged"; }, ["separator", "refreshControl"], ["refresh-control", "[listHeader]", "*", "[listFooter]"], true, never>;
|
|
512
557
|
}
|
|
513
558
|
/**
|
|
514
559
|
* Put on each row's view: `<view [virtualListRow]="row">`. Applies the row's style, and reports
|
package/dist/virtual-list.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Component, DestroyRef, Directive, ElementRef, TemplateRef, afterEveryRender, booleanAttribute, computed, contentChild, inject, input, linkedSignal, numberAttribute, output, signal, viewChild, } from '@angular/core';
|
|
1
|
+
import { Component, DestroyRef, Directive, ElementRef, TemplateRef, afterEveryRender, booleanAttribute, computed, contentChild, effect, inject, input, linkedSignal, numberAttribute, output, signal, untracked, viewChild, } from '@angular/core';
|
|
2
2
|
import { nativePlatform, pinnedRange, } from '@ng-native/fabric';
|
|
3
3
|
import { HeightIndex } from "./height-index.js";
|
|
4
4
|
import { dismissKeyboardOnTap } from "./keyboard-taps.js";
|
|
5
5
|
import { RefreshControl } from "./refresh-control.js";
|
|
6
|
+
import { STICKY_SETTLE_MS } from "./sticky-headers.js";
|
|
6
7
|
import { TemplateSlot } from "./template-slot.js";
|
|
8
|
+
import { ZeroSizeWarning, checksZeroSize, written } from "./zero-size-warning.js";
|
|
7
9
|
import { View } from "./view.js";
|
|
8
10
|
import { ScrollViewProps } from "./scroll-view-props.js";
|
|
9
11
|
import * as i0 from "@angular/core";
|
|
@@ -71,7 +73,8 @@ const HOLD_TOLERANCE = 0.5;
|
|
|
71
73
|
* `horizontal` swaps the axis: rows are placed by `left` and sized by `width`, and the offset is
|
|
72
74
|
* read from `contentOffset.x`. `inverted` is a scale of -1 on the list and on each row, which is
|
|
73
75
|
* how FlatList does it too - the list scrolls from the bottom and each row is flipped back the
|
|
74
|
-
* right way up, so a chat
|
|
76
|
+
* right way up. The first item is the one at the bottom, so a chat passes its messages newest
|
|
77
|
+
* first.
|
|
75
78
|
*
|
|
76
79
|
* `stickyIndices` pins a row to the leading edge while the rows under it scroll past, which is
|
|
77
80
|
* FlatList's `stickyHeaderIndices` counted without the header. `stickyHeader` pins the
|
|
@@ -111,6 +114,15 @@ export class VirtualList extends ScrollViewProps {
|
|
|
111
114
|
*/
|
|
112
115
|
estimatedItemHeight = input(50, /* @ts-ignore */
|
|
113
116
|
...(ngDevMode ? [{ debugName: "estimatedItemHeight" }] : /* istanbul ignore next */ []));
|
|
117
|
+
/**
|
|
118
|
+
* Space around the rows, inside the scrolling content. The leading side comes before the first
|
|
119
|
+
* row and the trailing side after the last; the sides across the axis inset every row. The
|
|
120
|
+
* header and footer sit outside it, as FlatList's do outside `contentContainerStyle`.
|
|
121
|
+
*/
|
|
122
|
+
contentPadding = input(0, /* @ts-ignore */
|
|
123
|
+
...(ngDevMode ? [{ debugName: "contentPadding" }] : /* istanbul ignore next */ []));
|
|
124
|
+
/** Space between one row and the next, along the axis: not before the first or after the last. */
|
|
125
|
+
rowGap = input(0, { ...(ngDevMode ? { debugName: "rowGap" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
114
126
|
/**
|
|
115
127
|
* An item's identity, as FlatList's `keyExtractor`: what a measured height, a slot and a held
|
|
116
128
|
* position follow across an insert. Without it an item is its own key, which is enough for items
|
|
@@ -201,6 +213,25 @@ export class VirtualList extends ScrollViewProps {
|
|
|
201
213
|
/** Rows size themselves and are laid out in flow, rather than placed at a known offset. */
|
|
202
214
|
measuring = computed(() => this.itemHeight() === undefined, /* @ts-ignore */
|
|
203
215
|
...(ngDevMode ? [{ debugName: "measuring" }] : /* istanbul ignore next */ []));
|
|
216
|
+
/** The padding on each side. */
|
|
217
|
+
edges = computed(() => {
|
|
218
|
+
const padding = this.contentPadding();
|
|
219
|
+
if (typeof padding === 'number') {
|
|
220
|
+
return { top: padding, right: padding, bottom: padding, left: padding };
|
|
221
|
+
}
|
|
222
|
+
const { top = 0, right = 0, bottom = 0, left = 0 } = padding ?? {};
|
|
223
|
+
return { top, right, bottom, left };
|
|
224
|
+
}, /* @ts-ignore */
|
|
225
|
+
...(ngDevMode ? [{ debugName: "edges" }] : /* istanbul ignore next */ []));
|
|
226
|
+
/** The padding before the first row, along the axis. */
|
|
227
|
+
lead = computed(() => this.horizontal() ? this.edges().left : this.edges().top, /* @ts-ignore */
|
|
228
|
+
...(ngDevMode ? [{ debugName: "lead" }] : /* istanbul ignore next */ []));
|
|
229
|
+
/** The rows' insets across the axis, as the props that place an absolutely positioned row. */
|
|
230
|
+
across = computed(() => {
|
|
231
|
+
const { top, right, bottom, left } = this.edges();
|
|
232
|
+
return this.horizontal() ? { top, bottom } : { left, right };
|
|
233
|
+
}, /* @ts-ignore */
|
|
234
|
+
...(ngDevMode ? [{ debugName: "across" }] : /* istanbul ignore next */ []));
|
|
204
235
|
/** Heights native has reported, by key. */
|
|
205
236
|
measured = new Map();
|
|
206
237
|
/** Bumped when a measurement changes, which is what re-sizes the list. */
|
|
@@ -225,19 +256,22 @@ export class VirtualList extends ScrollViewProps {
|
|
|
225
256
|
const height = this.itemHeight();
|
|
226
257
|
if (typeof height === 'number')
|
|
227
258
|
return null;
|
|
259
|
+
// Each row's entry is its size and the gap after it, so where a row starts counts the gaps
|
|
260
|
+
// before it without a second table.
|
|
261
|
+
const gap = this.rowGap();
|
|
228
262
|
const items = this.items();
|
|
229
263
|
const sizes = new Float64Array(items.length);
|
|
230
264
|
if (height) {
|
|
231
265
|
for (let i = 0; i < items.length; i++)
|
|
232
|
-
sizes[i] = height(items[i], i);
|
|
266
|
+
sizes[i] = height(items[i], i) + gap;
|
|
233
267
|
return new HeightIndex(sizes);
|
|
234
268
|
}
|
|
235
269
|
const estimate = this.estimatedItemHeight();
|
|
236
270
|
const keys = this.keys();
|
|
237
271
|
for (let i = 0; i < items.length; i++) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
272
|
+
const size = this.measured.get(keys ? keys[i] : items[i]) ??
|
|
273
|
+
(typeof estimate === 'number' ? estimate : estimate(items[i], i));
|
|
274
|
+
sizes[i] = size + gap;
|
|
241
275
|
}
|
|
242
276
|
return new HeightIndex(sizes);
|
|
243
277
|
}, /* @ts-ignore */
|
|
@@ -258,14 +292,23 @@ export class VirtualList extends ScrollViewProps {
|
|
|
258
292
|
this.measuredVersion();
|
|
259
293
|
return table;
|
|
260
294
|
}
|
|
261
|
-
/**
|
|
295
|
+
/**
|
|
296
|
+
* The list's own total extent along its axis: the padding at both ends, the rows, and a gap
|
|
297
|
+
* between each two of them.
|
|
298
|
+
*/
|
|
262
299
|
extent = computed(() => {
|
|
263
300
|
const table = this.layout();
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
301
|
+
const count = this.items().length;
|
|
302
|
+
const rows = table ? table.total : count * this.stride();
|
|
303
|
+
const { top, right, bottom, left } = this.edges();
|
|
304
|
+
const padding = this.horizontal() ? left + right : top + bottom;
|
|
305
|
+
return padding + (count ? rows - this.rowGap() : 0);
|
|
267
306
|
}, /* @ts-ignore */
|
|
268
307
|
...(ngDevMode ? [{ debugName: "extent" }] : /* istanbul ignore next */ []));
|
|
308
|
+
/** A fixed-height row and the gap after it. */
|
|
309
|
+
stride() {
|
|
310
|
+
return this.itemHeight() + this.rowGap();
|
|
311
|
+
}
|
|
269
312
|
canvas = computed(() => this.horizontal() ? { width: this.extent(), flexDirection: 'row' } : { height: this.extent() }, /* @ts-ignore */
|
|
270
313
|
...(ngDevMode ? [{ debugName: "canvas" }] : /* istanbul ignore next */ []));
|
|
271
314
|
/**
|
|
@@ -273,7 +316,7 @@ export class VirtualList extends ScrollViewProps {
|
|
|
273
316
|
*
|
|
274
317
|
* The list ends up scrolled from the far end with its rows in reverse, and the second flip puts
|
|
275
318
|
* each row's own content back the right way up. It is what `FlatList` does, and it is why an
|
|
276
|
-
* inverted list needs no reversed
|
|
319
|
+
* inverted list needs no reversed maths: the first item is at offset 0, which is the bottom.
|
|
277
320
|
*/
|
|
278
321
|
flip = computed(() => {
|
|
279
322
|
if (!this.inverted())
|
|
@@ -292,27 +335,45 @@ export class VirtualList extends ScrollViewProps {
|
|
|
292
335
|
return this.horizontal() ? 'scaleX(-1)' : 'scaleY(-1)';
|
|
293
336
|
}, /* @ts-ignore */
|
|
294
337
|
...(ngDevMode ? [{ debugName: "flipText" }] : /* istanbul ignore next */ []));
|
|
338
|
+
/**
|
|
339
|
+
* What places a row in flow: the gap after it and the padding across the axis, as margins, since
|
|
340
|
+
* native lays the row out. Empty when there are none, so a plain list commits no margins.
|
|
341
|
+
*/
|
|
342
|
+
flowSpacing = computed(() => {
|
|
343
|
+
const gap = this.rowGap();
|
|
344
|
+
const { top, right, bottom, left } = this.edges();
|
|
345
|
+
const spacing = this.horizontal()
|
|
346
|
+
? { marginRight: gap, marginTop: top, marginBottom: bottom }
|
|
347
|
+
: { marginBottom: gap, marginLeft: left, marginRight: right };
|
|
348
|
+
return Object.fromEntries(Object.entries(spacing).filter(([, value]) => value !== 0));
|
|
349
|
+
}, /* @ts-ignore */
|
|
350
|
+
...(ngDevMode ? [{ debugName: "flowSpacing" }] : /* istanbul ignore next */ []));
|
|
295
351
|
/** A row in flow, flipped back when the list is inverted. One object, so rows never re-clone. */
|
|
296
352
|
flowStyle = computed(() => {
|
|
297
353
|
const flip = this.flipText();
|
|
298
|
-
|
|
354
|
+
const spacing = this.flowSpacing();
|
|
355
|
+
if (!flip && Object.keys(spacing).length === 0)
|
|
356
|
+
return IN_FLOW;
|
|
357
|
+
return flip ? { ...spacing, transform: flip } : spacing;
|
|
299
358
|
}, /* @ts-ignore */
|
|
300
359
|
...(ngDevMode ? [{ debugName: "flowStyle" }] : /* istanbul ignore next */ []));
|
|
301
|
-
/** Top of a row. */
|
|
360
|
+
/** Top of a row: the leading padding, and every row and gap before it. */
|
|
302
361
|
topOf(index) {
|
|
303
362
|
const table = this.layout();
|
|
304
|
-
return table ? table.topOf(index) : index * this.
|
|
363
|
+
return this.lead() + (table ? table.topOf(index) : index * this.stride());
|
|
305
364
|
}
|
|
365
|
+
/** A row's own size, without the gap after it. */
|
|
306
366
|
heightOf(index) {
|
|
307
367
|
const table = this.layout();
|
|
308
|
-
return table ? table.heightOf(index) : this.itemHeight();
|
|
368
|
+
return table ? table.heightOf(index) - this.rowGap() : this.itemHeight();
|
|
309
369
|
}
|
|
310
|
-
/** First row whose bottom is past `y`. */
|
|
370
|
+
/** First row whose bottom, or the gap after it, is past `y`. */
|
|
311
371
|
indexAt(y) {
|
|
312
372
|
const table = this.layout();
|
|
373
|
+
const along = y - this.lead();
|
|
313
374
|
if (!table)
|
|
314
|
-
return Math.max(0, Math.floor(
|
|
315
|
-
return table.indexAt(
|
|
375
|
+
return Math.max(0, Math.floor(along / this.stride()));
|
|
376
|
+
return table.indexAt(along);
|
|
316
377
|
}
|
|
317
378
|
// --- holding position -------------------------------------------------------------------
|
|
318
379
|
/** The row the viewport's leading edge is in, taken at each scroll. */
|
|
@@ -450,6 +511,10 @@ export class VirtualList extends ScrollViewProps {
|
|
|
450
511
|
else
|
|
451
512
|
this.scrollToOffset({ offset: this.headerHeight() + pending.offset, animated: false });
|
|
452
513
|
}
|
|
514
|
+
/** In development, a list with rows that stays at zero size; see `ZeroSizeWarning`. */
|
|
515
|
+
zeroSize = checksZeroSize()
|
|
516
|
+
? new ZeroSizeWarning(() => written(this.node), () => !!this.horizontal())
|
|
517
|
+
: null;
|
|
453
518
|
constructor() {
|
|
454
519
|
super();
|
|
455
520
|
afterEveryRender(() => {
|
|
@@ -461,9 +526,25 @@ export class VirtualList extends ScrollViewProps {
|
|
|
461
526
|
inject(DestroyRef).onDestroy(() => {
|
|
462
527
|
stop();
|
|
463
528
|
clearTimeout(this.settleTimer);
|
|
529
|
+
this.zeroSize?.stop();
|
|
464
530
|
for (const held of this.drives.values())
|
|
465
531
|
held.drive.stop();
|
|
466
532
|
});
|
|
533
|
+
if (this.zeroSize)
|
|
534
|
+
this.checkZeroSize(this.zeroSize);
|
|
535
|
+
}
|
|
536
|
+
/** Whether the viewport has been laid out yet, so a zero in it is a measurement. */
|
|
537
|
+
viewportMeasured = false;
|
|
538
|
+
/**
|
|
539
|
+
* In development, rows that arrive in a list already measured at zero, or go from one, with no
|
|
540
|
+
* new layout to say so: an update to `items` alone does not lay the viewport out again.
|
|
541
|
+
*/
|
|
542
|
+
checkZeroSize(warning) {
|
|
543
|
+
effect(() => {
|
|
544
|
+
const hasRows = this.items().length > 0;
|
|
545
|
+
if (this.viewportMeasured)
|
|
546
|
+
warning.laidOut(untracked(this.viewport), hasRows);
|
|
547
|
+
});
|
|
467
548
|
}
|
|
468
549
|
// --- the window ---------------------------------------------------------------------------
|
|
469
550
|
/** The rows to render, and the edges of the run they sit in. */
|
|
@@ -520,7 +601,7 @@ export class VirtualList extends ScrollViewProps {
|
|
|
520
601
|
let lead = span ? this.topOf(span.first) : 0;
|
|
521
602
|
const pinned = this.pinnedIndex();
|
|
522
603
|
if (span && pinned !== null && pinned < span.first) {
|
|
523
|
-
lead = this.nativeSticky ? this.topOf(pinned) : lead - this.heightOf(pinned);
|
|
604
|
+
lead = this.nativeSticky ? this.topOf(pinned) : lead - this.heightOf(pinned) - this.rowGap();
|
|
524
605
|
}
|
|
525
606
|
return this.horizontal() ? { width: Math.max(0, lead) } : { height: Math.max(0, lead) };
|
|
526
607
|
}, /* @ts-ignore */
|
|
@@ -543,7 +624,7 @@ export class VirtualList extends ScrollViewProps {
|
|
|
543
624
|
style: this.nativeSticky
|
|
544
625
|
? this.stickyStyle(pinned)
|
|
545
626
|
: this.measuring()
|
|
546
|
-
? this.pinnedFlowStyle(this.topOf(first) - this.heightOf(pinned))
|
|
627
|
+
? this.pinnedFlowStyle(this.topOf(first) - this.heightOf(pinned) - this.rowGap())
|
|
547
628
|
: this.slotStyle(pinned, this.offset()),
|
|
548
629
|
}));
|
|
549
630
|
}
|
|
@@ -568,11 +649,12 @@ export class VirtualList extends ScrollViewProps {
|
|
|
568
649
|
*/
|
|
569
650
|
leadWindow(rows, pinned, first) {
|
|
570
651
|
const lead = rows[1];
|
|
571
|
-
|
|
572
|
-
|
|
652
|
+
// The pinned row's own gap already follows it in flow.
|
|
653
|
+
const between = this.topOf(first) - this.topOf(pinned) - this.heightOf(pinned) - this.rowGap();
|
|
654
|
+
if (!lead || between <= 0)
|
|
573
655
|
return;
|
|
574
656
|
const margin = this.horizontal() ? 'marginLeft' : 'marginTop';
|
|
575
|
-
rows[1] = this.hold({ ...lead, style: { ...lead.style, [margin]:
|
|
657
|
+
rows[1] = this.hold({ ...lead, style: { ...lead.style, [margin]: between } });
|
|
576
658
|
}
|
|
577
659
|
styleFor(index, pinned) {
|
|
578
660
|
if (this.nativeSticky && this.nextSticky().has(index))
|
|
@@ -587,7 +669,7 @@ export class VirtualList extends ScrollViewProps {
|
|
|
587
669
|
const shift = Math.max(0, this.offset() - at);
|
|
588
670
|
const move = `${this.horizontal() ? 'translateX' : 'translateY'}(${shift}px)`;
|
|
589
671
|
const flip = this.flipText();
|
|
590
|
-
return { zIndex: 1, transform: flip ? `${move} ${flip}` : move };
|
|
672
|
+
return { ...this.flowSpacing(), zIndex: 1, transform: flip ? `${move} ${flip}` : move };
|
|
591
673
|
}
|
|
592
674
|
/**
|
|
593
675
|
* A sticky row native moves: at its own place, with the translate native had reached when
|
|
@@ -595,7 +677,9 @@ export class VirtualList extends ScrollViewProps {
|
|
|
595
677
|
*/
|
|
596
678
|
stickyStyle(index) {
|
|
597
679
|
const horizontal = this.horizontal();
|
|
598
|
-
const style = this.measuring()
|
|
680
|
+
const style = this.measuring()
|
|
681
|
+
? { ...this.flowSpacing() }
|
|
682
|
+
: { ...this.slotStyle(index) };
|
|
599
683
|
style['zIndex'] = 1;
|
|
600
684
|
const top = this.topOf(index);
|
|
601
685
|
const shift = Math.min(Math.max(0, this.settled() - top), this.stopOf(index) - top);
|
|
@@ -740,7 +824,7 @@ export class VirtualList extends ScrollViewProps {
|
|
|
740
824
|
const index = this.indexOfKey()?.get(row.key);
|
|
741
825
|
if (index === undefined)
|
|
742
826
|
return;
|
|
743
|
-
this.table()?.set(index, size);
|
|
827
|
+
this.table()?.set(index, size + this.rowGap());
|
|
744
828
|
this.measuredVersion.update((version) => version + 1);
|
|
745
829
|
}
|
|
746
830
|
/** Drop the measurements of items long gone, so churn cannot grow the map without bound. */
|
|
@@ -805,16 +889,16 @@ export class VirtualList extends ScrollViewProps {
|
|
|
805
889
|
const size = this.heightOf(row.index);
|
|
806
890
|
const horizontal = this.horizontal();
|
|
807
891
|
const flip = this.flipText();
|
|
892
|
+
const across = this.across();
|
|
808
893
|
const cached = this.measuredGaps.get(row.key);
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
894
|
+
const placed = horizontal
|
|
895
|
+
? { ...across, left: start, width: size, transform: flip }
|
|
896
|
+
: { ...across, top: start, height: size, transform: flip };
|
|
897
|
+
if (cached && holds(cached, placed))
|
|
813
898
|
return cached;
|
|
814
|
-
}
|
|
815
899
|
const style = horizontal
|
|
816
|
-
? { position: 'absolute',
|
|
817
|
-
: { position: 'absolute',
|
|
900
|
+
? { position: 'absolute', ...across, left: start, width: size, flexDirection: 'row' }
|
|
901
|
+
: { position: 'absolute', ...across, top: start, height: size };
|
|
818
902
|
style['justifyContent'] = 'flex-end';
|
|
819
903
|
style['pointerEvents'] = 'box-none';
|
|
820
904
|
if (flip)
|
|
@@ -953,18 +1037,16 @@ export class VirtualList extends ScrollViewProps {
|
|
|
953
1037
|
const key = horizontal ? 'left' : 'top';
|
|
954
1038
|
const extent = horizontal ? 'width' : 'height';
|
|
955
1039
|
const flip = this.flipText();
|
|
1040
|
+
const across = this.across();
|
|
956
1041
|
let style = this.slots.get(index);
|
|
957
1042
|
// The flip is part of the comparison because turning the list over changes every row, and a
|
|
958
1043
|
// cached slot would otherwise keep the orientation it was built with.
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
style[key] !== start ||
|
|
962
|
-
style['transform'] !== flip ||
|
|
963
|
-
pinnedAt !== undefined;
|
|
1044
|
+
const placed = { ...across, [extent]: size, [key]: start, transform: flip };
|
|
1045
|
+
const stale = !style || pinnedAt !== undefined || !holds(style, placed);
|
|
964
1046
|
if (stale) {
|
|
965
1047
|
style = horizontal
|
|
966
|
-
? { position: 'absolute',
|
|
967
|
-
: { position: 'absolute',
|
|
1048
|
+
? { position: 'absolute', ...across, left: start, width: size }
|
|
1049
|
+
: { position: 'absolute', ...across, top: start, height: size };
|
|
968
1050
|
// A pinned row draws over the ones sliding under it; the transform is the row's half of
|
|
969
1051
|
// the inversion.
|
|
970
1052
|
if (pinnedAt !== undefined)
|
|
@@ -999,14 +1081,16 @@ export class VirtualList extends ScrollViewProps {
|
|
|
999
1081
|
this.checkEnd(along);
|
|
1000
1082
|
this.announceViewable(content);
|
|
1001
1083
|
}
|
|
1002
|
-
/**
|
|
1084
|
+
/** A pinned row's translate, settled once scrolling pauses: see `STICKY_SETTLE_MS`. */
|
|
1003
1085
|
settleAfterPause(content) {
|
|
1004
1086
|
clearTimeout(this.settleTimer);
|
|
1005
|
-
this.settleTimer = setTimeout(() => this.settled.set(content),
|
|
1087
|
+
this.settleTimer = setTimeout(() => this.settled.set(content), STICKY_SETTLE_MS);
|
|
1006
1088
|
}
|
|
1007
1089
|
onLayout(event) {
|
|
1008
1090
|
const layout = event.nativeEvent?.layout;
|
|
1009
1091
|
this.viewport.set((this.horizontal() ? layout?.width : layout?.height) ?? 0);
|
|
1092
|
+
this.viewportMeasured = true;
|
|
1093
|
+
this.zeroSize?.laidOut(this.viewport(), this.items().length > 0);
|
|
1010
1094
|
this.announceViewable(this.lastOffset);
|
|
1011
1095
|
}
|
|
1012
1096
|
/** The header's extent along the axis, which every row sits after. */
|
|
@@ -1054,7 +1138,7 @@ export class VirtualList extends ScrollViewProps {
|
|
|
1054
1138
|
this.endReached.emit({ distanceFromEnd });
|
|
1055
1139
|
}
|
|
1056
1140
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: VirtualList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1057
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.0", type: VirtualList, isStandalone: true, selector: "virtual-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, estimatedItemHeight: { classPropertyName: "estimatedItemHeight", publicName: "estimatedItemHeight", isSignal: true, isRequired: false, transformFunction: null }, keyExtractor: { classPropertyName: "keyExtractor", publicName: "keyExtractor", isSignal: true, isRequired: false, transformFunction: null }, itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, maintainVisibleContentPosition: { classPropertyName: "maintainVisibleContentPosition", publicName: "maintainVisibleContentPosition", isSignal: true, isRequired: false, transformFunction: null }, overscan: { classPropertyName: "overscan", publicName: "overscan", isSignal: true, isRequired: false, transformFunction: null }, endReachedThreshold: { classPropertyName: "endReachedThreshold", publicName: "endReachedThreshold", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, inverted: { classPropertyName: "inverted", publicName: "inverted", isSignal: true, isRequired: false, transformFunction: null }, stickyIndices: { classPropertyName: "stickyIndices", publicName: "stickyIndices", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, keyboardShouldPersistTaps: { classPropertyName: "keyboardShouldPersistTaps", publicName: "keyboardShouldPersistTaps", isSignal: true, isRequired: false, transformFunction: null }, itemVisiblePercentThreshold: { classPropertyName: "itemVisiblePercentThreshold", publicName: "itemVisiblePercentThreshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { endReached: "endReached", viewableItemsChanged: "viewableItemsChanged" }, host: { listeners: { "scroll": "onScroll($event)", "layout": "onLayout($event)", "contentSizeChange": "onContentSize($event)" }, properties: { "flexDirection": "horizontal() ? 'row' : 'column'", "horizontal": "horizontal()", "nestedScrollEnabled": "nestedScroll()", "transform": "flip()", "scrollEventThrottle": "scrollEventThrottle()" } }, queries: [{ propertyName: "separator", first: true, predicate: VirtualListSeparator, descendants: true, isSignal: true }, { propertyName: "refreshControl", first: true, predicate: RefreshControl, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "canvasView", first: true, predicate: ["rows"], descendants: true, read: ElementRef, isSignal: true }], exportAs: ["virtualList"], usesInheritance: true, ngImport: i0, template: `
|
|
1141
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.0", type: VirtualList, isStandalone: true, selector: "virtual-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, estimatedItemHeight: { classPropertyName: "estimatedItemHeight", publicName: "estimatedItemHeight", isSignal: true, isRequired: false, transformFunction: null }, contentPadding: { classPropertyName: "contentPadding", publicName: "contentPadding", isSignal: true, isRequired: false, transformFunction: null }, rowGap: { classPropertyName: "rowGap", publicName: "rowGap", isSignal: true, isRequired: false, transformFunction: null }, keyExtractor: { classPropertyName: "keyExtractor", publicName: "keyExtractor", isSignal: true, isRequired: false, transformFunction: null }, itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, maintainVisibleContentPosition: { classPropertyName: "maintainVisibleContentPosition", publicName: "maintainVisibleContentPosition", isSignal: true, isRequired: false, transformFunction: null }, overscan: { classPropertyName: "overscan", publicName: "overscan", isSignal: true, isRequired: false, transformFunction: null }, endReachedThreshold: { classPropertyName: "endReachedThreshold", publicName: "endReachedThreshold", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, inverted: { classPropertyName: "inverted", publicName: "inverted", isSignal: true, isRequired: false, transformFunction: null }, stickyIndices: { classPropertyName: "stickyIndices", publicName: "stickyIndices", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, keyboardShouldPersistTaps: { classPropertyName: "keyboardShouldPersistTaps", publicName: "keyboardShouldPersistTaps", isSignal: true, isRequired: false, transformFunction: null }, itemVisiblePercentThreshold: { classPropertyName: "itemVisiblePercentThreshold", publicName: "itemVisiblePercentThreshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { endReached: "endReached", viewableItemsChanged: "viewableItemsChanged" }, host: { listeners: { "scroll": "onScroll($event)", "layout": "onLayout($event)", "contentSizeChange": "onContentSize($event)" }, properties: { "flexDirection": "horizontal() ? 'row' : 'column'", "horizontal": "horizontal()", "nestedScrollEnabled": "nestedScroll()", "transform": "flip()", "scrollEventThrottle": "scrollEventThrottle()" } }, queries: [{ propertyName: "separator", first: true, predicate: VirtualListSeparator, descendants: true, isSignal: true }, { propertyName: "refreshControl", first: true, predicate: RefreshControl, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "canvasView", first: true, predicate: ["rows"], descendants: true, read: ElementRef, isSignal: true }], exportAs: ["virtualList"], usesInheritance: true, ngImport: i0, template: `
|
|
1058
1142
|
<ng-content select="refresh-control" />
|
|
1059
1143
|
<view [style]="headerStyle()" (layout)="onHeaderLayout($event)"
|
|
1060
1144
|
><ng-content select="[listHeader]"
|
|
@@ -1122,7 +1206,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
1122
1206
|
'(contentSizeChange)': 'onContentSize($event)',
|
|
1123
1207
|
},
|
|
1124
1208
|
}]
|
|
1125
|
-
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], estimatedItemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "estimatedItemHeight", required: false }] }], keyExtractor: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyExtractor", required: false }] }], itemType: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemType", required: false }] }], maintainVisibleContentPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "maintainVisibleContentPosition", required: false }] }], overscan: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscan", required: false }] }], endReachedThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "endReachedThreshold", required: false }] }], horizontal: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontal", required: false }] }], inverted: [{ type: i0.Input, args: [{ isSignal: true, alias: "inverted", required: false }] }], stickyIndices: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyIndices", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], keyboardShouldPersistTaps: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardShouldPersistTaps", required: false }] }], itemVisiblePercentThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemVisiblePercentThreshold", required: false }] }], endReached: [{ type: i0.Output, args: ["endReached"] }], viewableItemsChanged: [{ type: i0.Output, args: ["viewableItemsChanged"] }], separator: [{ type: i0.ContentChild, args: [i0.forwardRef(() => VirtualListSeparator), { isSignal: true }] }], refreshControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RefreshControl), { isSignal: true }] }], canvasView: [{ type: i0.ViewChild, args: ['rows', { ...{ read: ElementRef }, isSignal: true }] }] } });
|
|
1209
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], estimatedItemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "estimatedItemHeight", required: false }] }], contentPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentPadding", required: false }] }], rowGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowGap", required: false }] }], keyExtractor: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyExtractor", required: false }] }], itemType: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemType", required: false }] }], maintainVisibleContentPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "maintainVisibleContentPosition", required: false }] }], overscan: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscan", required: false }] }], endReachedThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "endReachedThreshold", required: false }] }], horizontal: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontal", required: false }] }], inverted: [{ type: i0.Input, args: [{ isSignal: true, alias: "inverted", required: false }] }], stickyIndices: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyIndices", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], keyboardShouldPersistTaps: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardShouldPersistTaps", required: false }] }], itemVisiblePercentThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemVisiblePercentThreshold", required: false }] }], endReached: [{ type: i0.Output, args: ["endReached"] }], viewableItemsChanged: [{ type: i0.Output, args: ["viewableItemsChanged"] }], separator: [{ type: i0.ContentChild, args: [i0.forwardRef(() => VirtualListSeparator), { isSignal: true }] }], refreshControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RefreshControl), { isSignal: true }] }], canvasView: [{ type: i0.ViewChild, args: ['rows', { ...{ read: ElementRef }, isSignal: true }] }] } });
|
|
1210
|
+
/** Whether a cached slot style already has every one of these props. */
|
|
1211
|
+
function holds(style, props) {
|
|
1212
|
+
return Object.entries(props).every(([prop, value]) => style[prop] === value);
|
|
1213
|
+
}
|
|
1126
1214
|
/**
|
|
1127
1215
|
* Put on each row's view: `<view [virtualListRow]="row">`. Applies the row's style, and reports
|
|
1128
1216
|
* the row's layout to the list, which is how a list of rows that size themselves learns how tall
|