@ng-native/components 0.0.1 → 0.1.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/LICENSE +21 -0
- package/README.md +78 -1
- package/dist/activity-indicator.d.ts +41 -0
- package/dist/activity-indicator.js +66 -0
- package/dist/activity-indicator.js.map +1 -0
- package/dist/animated-style.d.ts +31 -0
- package/dist/animated-style.js +102 -0
- package/dist/animated-style.js.map +1 -0
- package/dist/animated.d.ts +125 -0
- package/dist/animated.js +538 -0
- package/dist/animated.js.map +1 -0
- package/dist/animation.d.ts +40 -0
- package/dist/animation.js +20 -0
- package/dist/animation.js.map +1 -0
- package/dist/animations-web.d.ts +8 -0
- package/dist/animations-web.js +31 -0
- package/dist/animations-web.js.map +1 -0
- package/dist/animations.d.ts +7 -0
- package/dist/animations.js +58 -0
- package/dist/animations.js.map +1 -0
- package/dist/controlled-model.d.ts +33 -0
- package/dist/controlled-model.js +47 -0
- package/dist/controlled-model.js.map +1 -0
- package/dist/easing.d.ts +21 -0
- package/dist/easing.js +50 -0
- package/dist/easing.js.map +1 -0
- package/dist/events.d.ts +169 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/gesture-backend.d.ts +26 -0
- package/dist/gesture-backend.js +14 -0
- package/dist/gesture-backend.js.map +1 -0
- package/dist/gesture-dispatch.d.ts +67 -0
- package/dist/gesture-dispatch.js +106 -0
- package/dist/gesture-dispatch.js.map +1 -0
- package/dist/gestures.d.ts +23 -0
- package/dist/gestures.js +164 -0
- package/dist/gestures.js.map +1 -0
- package/dist/height-index.d.ts +31 -0
- package/dist/height-index.js +80 -0
- package/dist/height-index.js.map +1 -0
- package/dist/image-background.d.ts +32 -0
- package/dist/image-background.js +80 -0
- package/dist/image-background.js.map +1 -0
- package/dist/image.d.ts +79 -0
- package/dist/image.js +155 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/input-accessory-view.d.ts +16 -0
- package/dist/input-accessory-view.js +29 -0
- package/dist/input-accessory-view.js.map +1 -0
- package/dist/keyboard-avoiding-view.d.ts +79 -0
- package/dist/keyboard-avoiding-view.js +172 -0
- package/dist/keyboard-avoiding-view.js.map +1 -0
- package/dist/keyboard-dock.d.ts +126 -0
- package/dist/keyboard-dock.js +327 -0
- package/dist/keyboard-dock.js.map +1 -0
- package/dist/keyboard-taps.d.ts +12 -0
- package/dist/keyboard-taps.js +51 -0
- package/dist/keyboard-taps.js.map +1 -0
- package/dist/modal.d.ts +56 -0
- package/dist/modal.js +102 -0
- package/dist/modal.js.map +1 -0
- package/dist/native-gesture.d.ts +21 -0
- package/dist/native-gesture.js +56 -0
- package/dist/native-gesture.js.map +1 -0
- package/dist/native-ref.d.ts +7 -0
- package/dist/native-ref.js +13 -0
- package/dist/native-ref.js.map +1 -0
- package/dist/pressable.d.ts +220 -0
- package/dist/pressable.js +484 -0
- package/dist/pressable.js.map +1 -0
- package/dist/reanimated.d.ts +19 -0
- package/dist/reanimated.js +111 -0
- package/dist/reanimated.js.map +1 -0
- package/dist/refresh-control.d.ts +50 -0
- package/dist/refresh-control.js +103 -0
- package/dist/refresh-control.js.map +1 -0
- package/dist/safe-area-provider.d.ts +11 -0
- package/dist/safe-area-provider.js +70 -0
- package/dist/safe-area-provider.js.map +1 -0
- package/dist/safe-area-view.d.ts +22 -0
- package/dist/safe-area-view.js +77 -0
- package/dist/safe-area-view.js.map +1 -0
- package/dist/safe-area.d.ts +12 -0
- package/dist/safe-area.js +27 -0
- package/dist/safe-area.js.map +1 -0
- package/dist/scroll-view-props.d.ts +89 -0
- package/dist/scroll-view-props.js +153 -0
- package/dist/scroll-view-props.js.map +1 -0
- package/dist/scroll-view.d.ts +95 -0
- package/dist/scroll-view.js +181 -0
- package/dist/scroll-view.js.map +1 -0
- package/dist/section-list.d.ts +146 -0
- package/dist/section-list.js +300 -0
- package/dist/section-list.js.map +1 -0
- package/dist/sticky-headers.d.ts +41 -0
- package/dist/sticky-headers.js +118 -0
- package/dist/sticky-headers.js.map +1 -0
- package/dist/swipe-refresh-layout.d.ts +51 -0
- package/dist/swipe-refresh-layout.js +162 -0
- package/dist/swipe-refresh-layout.js.map +1 -0
- package/dist/switch.d.ts +54 -0
- package/dist/switch.js +110 -0
- package/dist/switch.js.map +1 -0
- package/dist/template-slot.d.ts +18 -0
- package/dist/template-slot.js +30 -0
- package/dist/template-slot.js.map +1 -0
- package/dist/text-input.d.ts +168 -0
- package/dist/text-input.js +312 -0
- package/dist/text-input.js.map +1 -0
- package/dist/text.d.ts +70 -0
- package/dist/text.js +111 -0
- package/dist/text.js.map +1 -0
- package/dist/touchable-opacity.d.ts +36 -0
- package/dist/touchable-opacity.js +76 -0
- package/dist/touchable-opacity.js.map +1 -0
- package/dist/transforms.d.ts +2 -0
- package/dist/transforms.js +17 -0
- package/dist/transforms.js.map +1 -0
- package/dist/view-base.d.ts +332 -0
- package/dist/view-base.js +534 -0
- package/dist/view-base.js.map +1 -0
- package/dist/view.d.ts +12 -0
- package/dist/view.js +18 -0
- package/dist/view.js.map +1 -0
- package/dist/virtual-list.d.ts +530 -0
- package/dist/virtual-list.js +1150 -0
- package/dist/virtual-list.js.map +1 -0
- package/dist/worklet-scroll.d.ts +13 -0
- package/dist/worklet-scroll.js +49 -0
- package/dist/worklet-scroll.js.map +1 -0
- package/dist/worklet-style.d.ts +13 -0
- package/dist/worklet-style.js +47 -0
- package/dist/worklet-style.js.map +1 -0
- package/dist/worklets.d.ts +89 -0
- package/dist/worklets.js +42 -0
- package/dist/worklets.js.map +1 -0
- package/dist/written-props.d.ts +6 -0
- package/dist/written-props.js +180 -0
- package/dist/written-props.js.map +1 -0
- package/package.json +88 -3
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import { TemplateRef } from '@angular/core';
|
|
2
|
+
import { type NativeSyntheticEvent } from '@ng-native/fabric';
|
|
3
|
+
import { type KeyboardShouldPersistTaps } from './keyboard-taps.ts';
|
|
4
|
+
import { ScrollViewProps } from './scroll-view-props.ts';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/** One rendered row: the item, its index, and a stable style object for its slot. */
|
|
7
|
+
export interface VirtualRow<T> {
|
|
8
|
+
readonly index: number;
|
|
9
|
+
/**
|
|
10
|
+
* A key that a row keeps while its item stays in the window, and that passes to a row arriving
|
|
11
|
+
* once it has left. `track row.slot` recycles rows: the view of a row scrolling out is reused for
|
|
12
|
+
* the one scrolling in, with only its bindings updated, rather than one destroyed and one created
|
|
13
|
+
* each time. A slot follows its item, not its position, so an insert above the window moves no
|
|
14
|
+
* row to another item.
|
|
15
|
+
*/
|
|
16
|
+
readonly slot: number;
|
|
17
|
+
/**
|
|
18
|
+
* The item's identity, from `keyExtractor`, or the item itself without one. `track row.key`
|
|
19
|
+
* gives each item a view of its own for as long as it is in the window and never recycles one,
|
|
20
|
+
* which is what a row holding state of its own, or animating, needs.
|
|
21
|
+
*/
|
|
22
|
+
readonly key: unknown;
|
|
23
|
+
readonly item: T;
|
|
24
|
+
readonly style: Record<string, unknown>;
|
|
25
|
+
/**
|
|
26
|
+
* A slot kept rendered but hidden, still bound to the last item it showed, so the next row of
|
|
27
|
+
* its type to arrive reuses its views instead of building them. Always last in the window.
|
|
28
|
+
*/
|
|
29
|
+
readonly parked?: true;
|
|
30
|
+
}
|
|
31
|
+
/** A row height: one for every row, or one per item. */
|
|
32
|
+
export type VirtualItemHeight<T> = number | ((item: T, index: number) => number);
|
|
33
|
+
/**
|
|
34
|
+
* Keep what is on screen where it is when rows are added or removed before it, as
|
|
35
|
+
* `ScrollView`'s `maintainVisibleContentPosition` does in React Native.
|
|
36
|
+
*/
|
|
37
|
+
export interface VirtualListVisiblePosition {
|
|
38
|
+
/** Rows before this index are never what the position is held by. Defaults to 0. */
|
|
39
|
+
readonly minIndexForVisible?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Within this many points of the start, show what arrived instead of holding position: a feed
|
|
42
|
+
* at its top scrolls to the new posts, a chat at its newest message follows the next one.
|
|
43
|
+
*/
|
|
44
|
+
readonly autoscrollToTopThreshold?: number;
|
|
45
|
+
}
|
|
46
|
+
/** What a separator template is given: the rows either side of it, as FlatList's `leadingItem`. */
|
|
47
|
+
export interface VirtualListSeparatorContext<T> {
|
|
48
|
+
readonly $implicit: T;
|
|
49
|
+
readonly leadingItem: T;
|
|
50
|
+
readonly trailingItem: T;
|
|
51
|
+
readonly leadingIndex: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Marks the template drawn between two rows: `<ng-template virtualListSeparator let-leading>`.
|
|
55
|
+
* FlatList's `ItemSeparatorComponent`.
|
|
56
|
+
*/
|
|
57
|
+
export declare class VirtualListSeparator<T = unknown> {
|
|
58
|
+
readonly template: TemplateRef<VirtualListSeparatorContext<T>>;
|
|
59
|
+
static ngTemplateContextGuard<T>(_directive: VirtualListSeparator<T>, context: unknown): context is VirtualListSeparatorContext<T>;
|
|
60
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<VirtualListSeparator<any>, never>;
|
|
61
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<VirtualListSeparator<any>, "ng-template[virtualListSeparator]", never, {}, {}, never, never, true, never>;
|
|
62
|
+
}
|
|
63
|
+
/** One separator the list is drawing: its slot, and what its template is told. */
|
|
64
|
+
interface Gap<T> {
|
|
65
|
+
readonly index: number;
|
|
66
|
+
readonly style: Record<string, unknown>;
|
|
67
|
+
readonly context: VirtualListSeparatorContext<T>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Windowed list: a native scroll view whose content is sized to the full list, with only the
|
|
71
|
+
* visible slice rendered. Commits as `RCTScrollView`.
|
|
72
|
+
*
|
|
73
|
+
* RN's FlatList, SectionList and VirtualizedList are a large React component tree, and none of
|
|
74
|
+
* it is reachable. This is the small equivalent. Angular's own `@for` does the rendering, so
|
|
75
|
+
* tracking, reuse and destruction all behave normally, and the loop stays in the caller's
|
|
76
|
+
* template:
|
|
77
|
+
*
|
|
78
|
+
* ```html
|
|
79
|
+
* <virtual-list #list [items]="rows()" [itemHeight]="44" (endReached)="loadMore()">
|
|
80
|
+
* <text listHeader>Header</text>
|
|
81
|
+
* @for (row of list.window(); track row.slot) {
|
|
82
|
+
* <view [virtualListRow]="row"><text>{{ row.item.label }}</text></view>
|
|
83
|
+
* }
|
|
84
|
+
* <text listFooter>Footer</text>
|
|
85
|
+
* </virtual-list>
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* With `itemHeight`, every row's size is known up front and each is absolutely positioned at its
|
|
89
|
+
* offset. Without it, rows size themselves, as a feed's posts and a chat's messages do: the window
|
|
90
|
+
* is laid out in normal flow after a spacer standing in for the rows above it, so native places
|
|
91
|
+
* every row correctly in the frame it first appears, and each row's layout tells the list its
|
|
92
|
+
* height for sizing what is not rendered. Until a row has been measured it counts as
|
|
93
|
+
* `estimatedItemHeight`. Measurements are kept by `keyExtractor`, so they follow their item across
|
|
94
|
+
* inserts, removals and moves. `virtualListRow` on each row's view applies its style and reports
|
|
95
|
+
* its layout; `[style]="row.style"` still works for fixed heights, which need no measuring.
|
|
96
|
+
*
|
|
97
|
+
* Content marked `listHeader` and `listFooter` renders above and below the rows in normal flow,
|
|
98
|
+
* as FlatList's header and footer components do. A `<refresh-control>` projects like any child.
|
|
99
|
+
*
|
|
100
|
+
* `<ng-template virtualListSeparator let-leading let-trailing="trailingItem">` is drawn between
|
|
101
|
+
* each pair of rows and not after the last, as FlatList's `ItemSeparatorComponent` is. It is drawn
|
|
102
|
+
* inside the leading row's slot, at its trailing edge, so `itemHeight` includes it the way
|
|
103
|
+
* `getItemLayout`'s `length` includes it in RN; a measured row has it drawn over its trailing edge
|
|
104
|
+
* once its height is known. The slot it sits in lets touches through to the row underneath.
|
|
105
|
+
*
|
|
106
|
+
* `horizontal` swaps the axis: rows are placed by `left` and sized by `width`, and the offset is
|
|
107
|
+
* read from `contentOffset.x`. `inverted` is a scale of -1 on the list and on each row, which is
|
|
108
|
+
* 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 transcript needs no reversed array.
|
|
110
|
+
*
|
|
111
|
+
* `stickyIndices` pins a row to the leading edge while the rows under it scroll past, which is
|
|
112
|
+
* FlatList's `stickyHeaderIndices` counted without the header. `stickyHeader` pins the
|
|
113
|
+
* `listHeader` content the same way, FlatList's index 0 when it has a `ListHeaderComponent`, and
|
|
114
|
+
* the first sticky row pushes it off as RN's sticky headers push each other. Neither is native:
|
|
115
|
+
* RN's `ScrollView.js` translates a sticky child against the scroll offset in JavaScript, and a
|
|
116
|
+
* row here follows the offset the same way while it is the current one - by its `top` when
|
|
117
|
+
* absolutely positioned, by a transform when in flow.
|
|
118
|
+
*
|
|
119
|
+
* What is on screen stays on screen when a measured row above it turns out taller or shorter than
|
|
120
|
+
* its estimate: the offset is corrected by the difference. `maintainVisibleContentPosition` does
|
|
121
|
+
* the same for rows inserted or removed above it, which a feed receiving new posts and a chat
|
|
122
|
+
* loading older messages above the ones being read both need.
|
|
123
|
+
*
|
|
124
|
+
* ponytail: viewability is `itemVisiblePercentThreshold` only: `minimumViewTime` and
|
|
125
|
+
* `waitForInteraction` are timing policy on top of the same measurement, and nothing has needed
|
|
126
|
+
* them. A separator is not told `highlighted`, which RN drives from the row's press state. A
|
|
127
|
+
* sticky header follows the scroll a commit behind native, where RN's is on the native driver. A
|
|
128
|
+
* held position is restored by a `scrollTo` after the commit, not in the mount as native
|
|
129
|
+
* `maintainVisibleContentPosition` is, so a correction made mid-fling lands where the last scroll
|
|
130
|
+
* event said the list was.
|
|
131
|
+
*/
|
|
132
|
+
export declare class VirtualList<T> extends ScrollViewProps {
|
|
133
|
+
readonly items: import("@angular/core").InputSignal<readonly T[]>;
|
|
134
|
+
/**
|
|
135
|
+
* A fixed height, or a function for variable ones, when every row's size is known up front. The
|
|
136
|
+
* function form builds a cumulative offset table and binary-searches it, which is what section
|
|
137
|
+
* lists need: a header row and an item row are different heights, so uniform maths cannot place
|
|
138
|
+
* them. Leave it unset for rows that size themselves.
|
|
139
|
+
*/
|
|
140
|
+
readonly itemHeight: import("@angular/core").InputSignal<VirtualItemHeight<T> | undefined>;
|
|
141
|
+
/**
|
|
142
|
+
* What a row that sizes itself counts as until it has been measured. The closer it is, the more
|
|
143
|
+
* honest the scroll bar is and the less a jump to an unmeasured row has to correct.
|
|
144
|
+
*/
|
|
145
|
+
readonly estimatedItemHeight: import("@angular/core").InputSignal<VirtualItemHeight<T>>;
|
|
146
|
+
/**
|
|
147
|
+
* An item's identity, as FlatList's `keyExtractor`: what a measured height, a slot and a held
|
|
148
|
+
* position follow across an insert. Without it an item is its own key, which is enough for items
|
|
149
|
+
* that are replaced, not copied, when they change.
|
|
150
|
+
*/
|
|
151
|
+
readonly keyExtractor: import("@angular/core").InputSignal<((item: T, index: number) => unknown) | undefined>;
|
|
152
|
+
/**
|
|
153
|
+
* What kind of row an item is, when rows of different kinds share the list: a text post and a
|
|
154
|
+
* photo post, a message and a date divider. A slot is only ever recycled into a row of the same
|
|
155
|
+
* type, so its views are reused rather than torn down for another kind's, as UIKit's reuse
|
|
156
|
+
* identifiers and FlashList's `getItemType` do.
|
|
157
|
+
*/
|
|
158
|
+
readonly itemType: import("@angular/core").InputSignal<((item: T, index: number) => unknown) | undefined>;
|
|
159
|
+
/** Keep what is on screen still when rows are inserted or removed before it. */
|
|
160
|
+
readonly maintainVisibleContentPosition: import("@angular/core").InputSignal<VirtualListVisiblePosition | undefined>;
|
|
161
|
+
/** Rows rendered beyond each edge of the viewport, to cover fling gaps. */
|
|
162
|
+
readonly overscan: import("@angular/core").InputSignalWithTransform<number, unknown>;
|
|
163
|
+
/** How close to the end, in viewport heights, `(endReached)` fires. RN's default is 2. */
|
|
164
|
+
readonly endReachedThreshold: import("@angular/core").InputSignalWithTransform<number, unknown>;
|
|
165
|
+
/** Lay the rows out along x instead of y, and scroll that way. */
|
|
166
|
+
readonly horizontal: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
167
|
+
/** Start at the end and scroll backwards, with every row flipped back the right way up. */
|
|
168
|
+
readonly inverted: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
169
|
+
/**
|
|
170
|
+
* Rows that pin to the leading edge while the ones under them scroll past. Ascending; a row is
|
|
171
|
+
* pinned from the moment it would leave until the next sticky row pushes it off.
|
|
172
|
+
*/
|
|
173
|
+
readonly stickyIndices: import("@angular/core").InputSignal<readonly number[]>;
|
|
174
|
+
/** Pin the `listHeader` content to the leading edge until the first sticky row pushes it off. */
|
|
175
|
+
readonly stickyHeader: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
176
|
+
/** What a tap in the list does while a text input has the keyboard up. See `ScrollView`. */
|
|
177
|
+
readonly keyboardShouldPersistTaps: import("@angular/core").InputSignal<KeyboardShouldPersistTaps>;
|
|
178
|
+
/** How much of a row must be on screen to count as viewable. RN's default is 0, meaning any. */
|
|
179
|
+
readonly itemVisiblePercentThreshold: import("@angular/core").InputSignalWithTransform<number, unknown>;
|
|
180
|
+
/**
|
|
181
|
+
* The scroll position is within `endReachedThreshold` of the end: once per item count, and again
|
|
182
|
+
* after the list has scrolled away from the end and come back.
|
|
183
|
+
*/
|
|
184
|
+
readonly endReached: import("@angular/core").OutputEmitterRef<{
|
|
185
|
+
distanceFromEnd: number;
|
|
186
|
+
}>;
|
|
187
|
+
/** Which rows are on screen, and what changed since last time. */
|
|
188
|
+
readonly viewableItemsChanged: import("@angular/core").OutputEmitterRef<{
|
|
189
|
+
viewable: readonly VirtualRow<T>[];
|
|
190
|
+
entered: readonly number[];
|
|
191
|
+
left: readonly number[];
|
|
192
|
+
}>;
|
|
193
|
+
private readonly viewport;
|
|
194
|
+
/** The leading edge of the viewport in content space, which sticky rows and viewability need. */
|
|
195
|
+
private readonly offset;
|
|
196
|
+
private readonly headerHeight;
|
|
197
|
+
/** What native reported the content measures along the axis, once it has. */
|
|
198
|
+
private contentSize;
|
|
199
|
+
/** The item count `endReached` last fired for, cleared once the list is away from the end. */
|
|
200
|
+
private endReachedFor;
|
|
201
|
+
/** Slot styles are cached so a scroll does not hand Fabric new prop objects for stable rows. */
|
|
202
|
+
private readonly slots;
|
|
203
|
+
/** A separator's slot style, per row slot style, so it is as stable as the row's own. */
|
|
204
|
+
private readonly gapStyles;
|
|
205
|
+
/** The same for a measured row's separator, by key, while its place and size stay put. */
|
|
206
|
+
private readonly measuredGaps;
|
|
207
|
+
protected readonly separator: import("@angular/core").Signal<VirtualListSeparator<T> | undefined>;
|
|
208
|
+
private readonly refreshControl;
|
|
209
|
+
/** See ScrollView: inside Android's swipe layout the list must see a drag first. */
|
|
210
|
+
protected readonly nestedScroll: import("@angular/core").Signal<true | undefined>;
|
|
211
|
+
/**
|
|
212
|
+
* Whether native moves sticky rows. Each then stays at its own place in the list and native
|
|
213
|
+
* translates it on every frame the list scrolls, as RN's `ScrollViewStickyHeader` does; a
|
|
214
|
+
* translate committed from each scroll event lands a frame or more late, and on a fast fling
|
|
215
|
+
* the row shudders and comes away from the edge.
|
|
216
|
+
*/
|
|
217
|
+
private readonly nativeSticky;
|
|
218
|
+
/** The offset once scrolling pauses, which the settled translate of a native-moved row is from. */
|
|
219
|
+
private readonly settled;
|
|
220
|
+
private settleTimer;
|
|
221
|
+
/** What native is moving, by row view, with the transform kept beside the translate. */
|
|
222
|
+
private readonly drives;
|
|
223
|
+
private readonly canvasView;
|
|
224
|
+
/** Whether the scroll offset is needed as a signal, which only pinning needs. */
|
|
225
|
+
private readonly pinning;
|
|
226
|
+
/** Rows size themselves and are laid out in flow, rather than placed at a known offset. */
|
|
227
|
+
readonly measuring: import("@angular/core").Signal<boolean>;
|
|
228
|
+
/** Heights native has reported, by key. */
|
|
229
|
+
private readonly measured;
|
|
230
|
+
/** Bumped when a measurement changes, which is what re-sizes the list. */
|
|
231
|
+
private readonly measuredVersion;
|
|
232
|
+
/** Each item's key, or null when items are their own. */
|
|
233
|
+
private readonly keys;
|
|
234
|
+
private keyAt;
|
|
235
|
+
/**
|
|
236
|
+
* Each row's size and where it starts, for variable heights; uniform rows need no index at all.
|
|
237
|
+
* Built once per change of items. A measurement changes it in place and bumps
|
|
238
|
+
* `measuredVersion`, which is what everything that reads it depends on, so a row laying out
|
|
239
|
+
* costs a walk of the tree rather than a rebuild of every offset.
|
|
240
|
+
*/
|
|
241
|
+
private readonly table;
|
|
242
|
+
/** Where each key is, so a measurement finds its row without a search. */
|
|
243
|
+
private readonly indexOfKey;
|
|
244
|
+
/** The index, with a dependency on its measurements for whoever is reading it. */
|
|
245
|
+
private layout;
|
|
246
|
+
/** The list's own total extent along its axis. */
|
|
247
|
+
private readonly extent;
|
|
248
|
+
protected readonly canvas: import("@angular/core").Signal<{
|
|
249
|
+
width: number;
|
|
250
|
+
flexDirection: string;
|
|
251
|
+
height?: undefined;
|
|
252
|
+
} | {
|
|
253
|
+
height: number;
|
|
254
|
+
width?: undefined;
|
|
255
|
+
flexDirection?: undefined;
|
|
256
|
+
}>;
|
|
257
|
+
/**
|
|
258
|
+
* `scaleY: -1` on the list, and the same on every row.
|
|
259
|
+
*
|
|
260
|
+
* The list ends up scrolled from the far end with its rows in reverse, and the second flip puts
|
|
261
|
+
* 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 array and no reversed maths.
|
|
263
|
+
*/
|
|
264
|
+
protected readonly flip: import("@angular/core").Signal<Readonly<Record<string, number>>[] | undefined>;
|
|
265
|
+
/**
|
|
266
|
+
* The flip as a style's transform: CSS text, which the engine turns into the list native reads.
|
|
267
|
+
* A style binding validates its values as the DOM's, and warns on a list in development.
|
|
268
|
+
*/
|
|
269
|
+
private readonly flipText;
|
|
270
|
+
/** A row in flow, flipped back when the list is inverted. One object, so rows never re-clone. */
|
|
271
|
+
private readonly flowStyle;
|
|
272
|
+
/** Top of a row. */
|
|
273
|
+
private topOf;
|
|
274
|
+
private heightOf;
|
|
275
|
+
/** First row whose bottom is past `y`. */
|
|
276
|
+
private indexAt;
|
|
277
|
+
/** The row the viewport's leading edge is in, taken at each scroll. */
|
|
278
|
+
private anchor;
|
|
279
|
+
/** The last offset seen. A field rather than a signal: reading it renders nothing. */
|
|
280
|
+
private lastOffset;
|
|
281
|
+
/**
|
|
282
|
+
* A correction to make once the commit that needs it is on its way to native: an offset in the
|
|
283
|
+
* rows' own space, after the header, or the very start of the list.
|
|
284
|
+
*/
|
|
285
|
+
private pendingScroll;
|
|
286
|
+
/** What moves the rows: which items, and where each one is. */
|
|
287
|
+
private readonly placement;
|
|
288
|
+
/**
|
|
289
|
+
* The first *visible* row, not the first rendered one, and not the raw scroll offset. A fling
|
|
290
|
+
* produces a scroll event per frame, and setting a signal on each one costs a change-detection
|
|
291
|
+
* pass even when the visible rows are identical. Deriving the index in the handler means most
|
|
292
|
+
* scroll events change nothing and cost nothing.
|
|
293
|
+
*
|
|
294
|
+
* Linked to the rows' placement, because that is when the row on screen can move without the
|
|
295
|
+
* user scrolling: an insert above it, or a row above it measuring differently from its estimate.
|
|
296
|
+
* The index follows the anchored row there, and the offset follows it too.
|
|
297
|
+
*/
|
|
298
|
+
private readonly visible;
|
|
299
|
+
/** Take the anchor at a row, keeping the viewport where it is. */
|
|
300
|
+
private anchorAt;
|
|
301
|
+
/**
|
|
302
|
+
* Where the row on screen went when the rows moved under it, and the offset that keeps it where
|
|
303
|
+
* the user left it. An insert or a removal is only held when the caller asked for it; a row
|
|
304
|
+
* above measuring differently always is, since nothing the user did moved anything.
|
|
305
|
+
*/
|
|
306
|
+
private reanchor;
|
|
307
|
+
/**
|
|
308
|
+
* The row under the offset native is still at, in rows that have just replaced the old ones, as
|
|
309
|
+
* a filter replaces them. Native keeps its offset whatever the items became, so the window is
|
|
310
|
+
* worked out from that, not from the old row's index, which in the new rows sits somewhere else.
|
|
311
|
+
* When the new rows end before that offset, the list is scrolled back to their end: native
|
|
312
|
+
* would otherwise stay scrolled past it, showing nothing until the next drag.
|
|
313
|
+
*/
|
|
314
|
+
private atOffset;
|
|
315
|
+
/**
|
|
316
|
+
* The index to hold the viewport at, -1 to let it move, or the start of the list when an
|
|
317
|
+
* insert lands within the autoscroll threshold of it.
|
|
318
|
+
*/
|
|
319
|
+
private heldIndex;
|
|
320
|
+
/** Scroll to what arrived at the start, rather than holding the viewport past it. */
|
|
321
|
+
private showStart;
|
|
322
|
+
/**
|
|
323
|
+
* The anchored row's new index, or the first row after it that survived when it did not. Only
|
|
324
|
+
* the rows that were rendered are searched for a successor: past those the viewport has moved
|
|
325
|
+
* on, and holding it by something off screen would be holding it by nothing the user saw.
|
|
326
|
+
*/
|
|
327
|
+
private successorOf;
|
|
328
|
+
/** Make a queued correction, after the commit that moved the rows has gone to native. */
|
|
329
|
+
private flushScroll;
|
|
330
|
+
constructor();
|
|
331
|
+
/** The rows to render, and the edges of the run they sit in. */
|
|
332
|
+
private readonly span;
|
|
333
|
+
readonly window: import("@angular/core").Signal<VirtualRow<T>[]>;
|
|
334
|
+
/**
|
|
335
|
+
* What stands in for the rows above the window when rows are in flow: their total extent, less
|
|
336
|
+
* a pinned row's, which is rendered in flow ahead of the window.
|
|
337
|
+
*/
|
|
338
|
+
protected readonly spacer: import("@angular/core").Signal<{
|
|
339
|
+
width: number;
|
|
340
|
+
height?: undefined;
|
|
341
|
+
} | {
|
|
342
|
+
height: number;
|
|
343
|
+
width?: undefined;
|
|
344
|
+
}>;
|
|
345
|
+
/** The rows from `first` up to `last`, and the pinned row above them if there is one. */
|
|
346
|
+
private rowsFor;
|
|
347
|
+
/**
|
|
348
|
+
* A pinned row native moves stays at its own place, so the rows between it and the window are
|
|
349
|
+
* made up before the window rather than after the row: new props on a view native is moving
|
|
350
|
+
* put its transform back for a frame.
|
|
351
|
+
*/
|
|
352
|
+
private leadWindow;
|
|
353
|
+
private styleFor;
|
|
354
|
+
/** A pinned row in flow, moved from where flow put it to the leading edge by a transform. */
|
|
355
|
+
private pinnedFlowStyle;
|
|
356
|
+
/**
|
|
357
|
+
* A sticky row native moves: at its own place, with the translate native had reached when
|
|
358
|
+
* scrolling paused, so the props agree with what is on screen.
|
|
359
|
+
*/
|
|
360
|
+
private stickyStyle;
|
|
361
|
+
/** Each sticky row, and the one after it, which pushes it off. */
|
|
362
|
+
private readonly nextSticky;
|
|
363
|
+
/** Where a sticky row stops, pushed off by the next: that row's top, less this row's size. */
|
|
364
|
+
private stopOf;
|
|
365
|
+
/**
|
|
366
|
+
* How native moves a rendered row, or null when it does not: along the scroll view's own
|
|
367
|
+
* offset, which counts the header, from the row's top until the next sticky row pushes it off.
|
|
368
|
+
*/
|
|
369
|
+
private stickyDrive;
|
|
370
|
+
/**
|
|
371
|
+
* Hand each rendered sticky row's view to native to move, and let go of the rest. The rows'
|
|
372
|
+
* views are the canvas's element children in window order, after the spacer, which is how
|
|
373
|
+
* `@for` over `window()` leaves them.
|
|
374
|
+
*/
|
|
375
|
+
private driveStickyRows;
|
|
376
|
+
/** Which recycling slot each rendered item holds, by key: its type, and the row it last drew. */
|
|
377
|
+
private readonly recycled;
|
|
378
|
+
/** Slots that have left the window and are kept hidden, by the type of row that held them. */
|
|
379
|
+
private readonly parked;
|
|
380
|
+
private nextSlot;
|
|
381
|
+
/** Note the row a slot is drawing, for parking it once it leaves. */
|
|
382
|
+
private hold;
|
|
383
|
+
/**
|
|
384
|
+
* Park the slots of the items that have left the window, for the items arriving.
|
|
385
|
+
*
|
|
386
|
+
* Parked rather than freed: a slot missing from the window is destroyed by `@for`, so a slot is
|
|
387
|
+
* only reused if a row of its type arrives in the same pass as it left. Kept rendered and
|
|
388
|
+
* hidden, it waits for the next row of its type however many passes later, which is what a
|
|
389
|
+
* reuse queue of cells does in UIKit.
|
|
390
|
+
*/
|
|
391
|
+
private releaseRecycled;
|
|
392
|
+
/**
|
|
393
|
+
* Keep a few hidden slots of each type once this pass has taken what it needs, dropping the
|
|
394
|
+
* oldest: `@for` destroys the views of a slot that leaves the window for good.
|
|
395
|
+
*/
|
|
396
|
+
private trimParked;
|
|
397
|
+
/** A parked row for a slot that never drew, which only a slot taken and left in one pass is. */
|
|
398
|
+
private placeholder;
|
|
399
|
+
private recycledSlot;
|
|
400
|
+
/**
|
|
401
|
+
* A row laid itself out; what `virtualListRow` calls. Only a row that sizes itself is measured,
|
|
402
|
+
* and a height that has not changed changes nothing.
|
|
403
|
+
*/
|
|
404
|
+
measureRow(row: VirtualRow<T>, layout: {
|
|
405
|
+
width?: number;
|
|
406
|
+
height?: number;
|
|
407
|
+
} | undefined): void;
|
|
408
|
+
/** Drop the measurements of items long gone, so churn cannot grow the map without bound. */
|
|
409
|
+
private forgetDeparted;
|
|
410
|
+
/** A separator for every rendered row but the list's last, in its leading row's slot. */
|
|
411
|
+
protected readonly gaps: import("@angular/core").Signal<Gap<T>[]>;
|
|
412
|
+
/** The row's own slot, laid out to put the separator at its trailing edge. */
|
|
413
|
+
private gapStyle;
|
|
414
|
+
/**
|
|
415
|
+
* A measured row's slot, over the row itself: nothing until its height is known, since drawing
|
|
416
|
+
* it at the estimate would put a line through the middle of a row that turns out taller.
|
|
417
|
+
*/
|
|
418
|
+
private measuredGapStyle;
|
|
419
|
+
/**
|
|
420
|
+
* The header's translation while it is pinned: the scroll position, held back at zero by an
|
|
421
|
+
* overscroll and at the first sticky row, which pushes it off.
|
|
422
|
+
*/
|
|
423
|
+
protected readonly headerStyle: import("@angular/core").Signal<{
|
|
424
|
+
transform: string;
|
|
425
|
+
zIndex?: undefined;
|
|
426
|
+
} | {
|
|
427
|
+
zIndex: number;
|
|
428
|
+
transform: string;
|
|
429
|
+
} | {
|
|
430
|
+
zIndex: number;
|
|
431
|
+
transform?: undefined;
|
|
432
|
+
} | undefined>;
|
|
433
|
+
/**
|
|
434
|
+
* The footer, flipped back like every row when the list is inverted, as FlatList inverts its
|
|
435
|
+
* header and footer cells too; otherwise both read upside down.
|
|
436
|
+
*/
|
|
437
|
+
protected readonly footerStyle: import("@angular/core").Signal<{
|
|
438
|
+
transform: string;
|
|
439
|
+
} | undefined>;
|
|
440
|
+
/**
|
|
441
|
+
* The sticky row currently holding the leading edge: the last one at or before the offset.
|
|
442
|
+
* Null when the list has scrolled back above the first of them.
|
|
443
|
+
*/
|
|
444
|
+
private readonly pinnedIndex;
|
|
445
|
+
/** Which rows are on screen far enough to count, by the caller's threshold. */
|
|
446
|
+
private viewableAt;
|
|
447
|
+
/** The last set announced, so the output fires on a change rather than on every frame. */
|
|
448
|
+
private announced;
|
|
449
|
+
/**
|
|
450
|
+
* Announce a change in what is on screen.
|
|
451
|
+
*
|
|
452
|
+
* Deliberately not a `computed` over a signal offset. A fling produces a scroll event per
|
|
453
|
+
* frame, and writing a signal on each one costs a change-detection pass whether or not anything
|
|
454
|
+
* moved into view; comparing here costs an array walk over the window and emits only when the
|
|
455
|
+
* set really changed.
|
|
456
|
+
*/
|
|
457
|
+
private announceViewable;
|
|
458
|
+
/**
|
|
459
|
+
* Scroll so that a row is at the start of the viewport, less `viewOffset`. The window moves
|
|
460
|
+
* there at once, and the row is held there while the rows around it are measured.
|
|
461
|
+
*/
|
|
462
|
+
scrollToIndex(options: {
|
|
463
|
+
index: number;
|
|
464
|
+
animated?: boolean;
|
|
465
|
+
viewOffset?: number;
|
|
466
|
+
}): void;
|
|
467
|
+
/** Scroll to an offset along the list's own axis: x when it is horizontal, y otherwise. */
|
|
468
|
+
scrollToOffset(options: {
|
|
469
|
+
offset: number;
|
|
470
|
+
animated?: boolean;
|
|
471
|
+
}): void;
|
|
472
|
+
scrollToEnd(options?: {
|
|
473
|
+
animated?: boolean;
|
|
474
|
+
}): void;
|
|
475
|
+
private slotStyle;
|
|
476
|
+
protected onScroll(event: NativeSyntheticEvent<{
|
|
477
|
+
contentOffset?: {
|
|
478
|
+
x?: number;
|
|
479
|
+
y?: number;
|
|
480
|
+
};
|
|
481
|
+
}>): void;
|
|
482
|
+
/** RN's sticky header commits its translate after 64 ms without a scroll event, as this does. */
|
|
483
|
+
private settleAfterPause;
|
|
484
|
+
protected onLayout(event: NativeSyntheticEvent<{
|
|
485
|
+
layout?: {
|
|
486
|
+
width?: number;
|
|
487
|
+
height?: number;
|
|
488
|
+
};
|
|
489
|
+
}>): void;
|
|
490
|
+
/** The header's extent along the axis, which every row sits after. */
|
|
491
|
+
protected onHeaderLayout(event: NativeSyntheticEvent<{
|
|
492
|
+
layout?: {
|
|
493
|
+
width?: number;
|
|
494
|
+
height?: number;
|
|
495
|
+
};
|
|
496
|
+
}>): void;
|
|
497
|
+
/**
|
|
498
|
+
* The header grew or shrank - a typing indicator in a chat's, a banner in a feed's - and every
|
|
499
|
+
* row moved with it. Held like an insert when the caller asked for that and the viewport is
|
|
500
|
+
* past the header, among the rows; at the start the user is looking at the header, and it is
|
|
501
|
+
* left to push the rows along. Made at once rather than after a render, because a layout arrives
|
|
502
|
+
* outside change detection and nothing else may be about to render.
|
|
503
|
+
*/
|
|
504
|
+
private holdPastHeader;
|
|
505
|
+
protected onContentSize(event: NativeSyntheticEvent<{
|
|
506
|
+
width?: number;
|
|
507
|
+
height?: number;
|
|
508
|
+
}>): void;
|
|
509
|
+
private checkEnd;
|
|
510
|
+
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>;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Put on each row's view: `<view [virtualListRow]="row">`. Applies the row's style, and reports
|
|
515
|
+
* the row's layout to the list, which is how a list of rows that size themselves learns how tall
|
|
516
|
+
* each one is.
|
|
517
|
+
*/
|
|
518
|
+
export declare class VirtualListRow<T = unknown> {
|
|
519
|
+
readonly row: import("@angular/core").InputSignal<VirtualRow<T>>;
|
|
520
|
+
private readonly list;
|
|
521
|
+
protected onLayout(event: NativeSyntheticEvent<{
|
|
522
|
+
layout?: {
|
|
523
|
+
width?: number;
|
|
524
|
+
height?: number;
|
|
525
|
+
};
|
|
526
|
+
}>): void;
|
|
527
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<VirtualListRow<any>, never>;
|
|
528
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<VirtualListRow<any>, "[virtualListRow]", never, { "row": { "alias": "virtualListRow"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
529
|
+
}
|
|
530
|
+
export {};
|