@legendapp/list 0.2.2 → 0.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/index.d.mts +3 -3
- package/index.d.ts +3 -3
- package/index.js +478 -349
- package/index.mjs +480 -351
- package/package.json +1 -4
package/index.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var React2 = require('react');
|
|
4
|
-
var state = require('@legendapp/state');
|
|
5
|
-
var enableReactNativeComponents = require('@legendapp/state/config/enableReactNativeComponents');
|
|
6
|
-
var react = require('@legendapp/state/react');
|
|
7
4
|
var reactNative = require('react-native');
|
|
8
5
|
|
|
9
6
|
function _interopNamespace(e) {
|
|
@@ -27,405 +24,537 @@ function _interopNamespace(e) {
|
|
|
27
24
|
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
28
25
|
|
|
29
26
|
// src/LegendList.tsx
|
|
30
|
-
|
|
27
|
+
var LeanView = React2__namespace.forwardRef((props, ref) => {
|
|
28
|
+
return React2__namespace.createElement("RCTView", { ...props, ref });
|
|
29
|
+
});
|
|
30
|
+
LeanView.displayName = "RCTView";
|
|
31
|
+
var ContextListener = React2__namespace.createContext(null);
|
|
32
|
+
function StateProvider({ children }) {
|
|
33
|
+
const [value] = React2__namespace.useState(() => ({
|
|
34
|
+
listeners: /* @__PURE__ */ new Map(),
|
|
35
|
+
values: /* @__PURE__ */ new Map()
|
|
36
|
+
}));
|
|
37
|
+
return /* @__PURE__ */ React2__namespace.createElement(ContextListener.Provider, { value }, children);
|
|
38
|
+
}
|
|
39
|
+
function useStateContext() {
|
|
40
|
+
return React2__namespace.useContext(ContextListener);
|
|
41
|
+
}
|
|
42
|
+
function use$(signalName) {
|
|
43
|
+
const { listeners, values } = React2__namespace.useContext(ContextListener);
|
|
44
|
+
const [_, setState] = React2__namespace.useState(0);
|
|
45
|
+
React2__namespace.useMemo(() => {
|
|
46
|
+
const render = () => setState((prev) => prev > 1e4 ? 0 : prev + 1);
|
|
47
|
+
listeners.set(signalName, render);
|
|
48
|
+
}, []);
|
|
49
|
+
return values.get(signalName);
|
|
50
|
+
}
|
|
51
|
+
function peek$(signalName, ctx) {
|
|
52
|
+
const { values } = ctx || React2__namespace.useContext(ContextListener);
|
|
53
|
+
return values.get(signalName);
|
|
54
|
+
}
|
|
55
|
+
function set$(signalName, ctx, value) {
|
|
56
|
+
var _a;
|
|
57
|
+
const { listeners, values } = ctx || React2__namespace.useContext(ContextListener);
|
|
58
|
+
if (values.get(signalName) !== value) {
|
|
59
|
+
values.set(signalName, value);
|
|
60
|
+
(_a = listeners.get(signalName)) == null ? void 0 : _a();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/$View.tsx
|
|
65
|
+
function $View({ $key, $style, ...rest }) {
|
|
66
|
+
use$($key);
|
|
67
|
+
const style = $style();
|
|
68
|
+
return /* @__PURE__ */ React2__namespace.createElement(LeanView, { style, ...rest });
|
|
69
|
+
}
|
|
31
70
|
var Container = ({
|
|
32
|
-
|
|
71
|
+
id,
|
|
33
72
|
recycleItems,
|
|
34
|
-
|
|
73
|
+
horizontal,
|
|
35
74
|
getRenderedItem,
|
|
36
75
|
onLayout,
|
|
37
76
|
ItemSeparatorComponent
|
|
38
77
|
}) => {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const itemIndex =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
const ctx = useStateContext();
|
|
79
|
+
const numItems = ItemSeparatorComponent ? use$("numItems") : 0;
|
|
80
|
+
const itemIndex = use$(`containerIndex${id}`);
|
|
81
|
+
if (itemIndex < 0) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const createStyle = () => {
|
|
85
|
+
const position = peek$(`containerPosition${id}`, ctx);
|
|
86
|
+
return horizontal ? {
|
|
87
|
+
flexDirection: "row",
|
|
88
|
+
position: "absolute",
|
|
89
|
+
top: 0,
|
|
90
|
+
bottom: 0,
|
|
91
|
+
left: position,
|
|
92
|
+
opacity: position < 0 ? 0 : 1
|
|
93
|
+
} : {
|
|
94
|
+
position: "absolute",
|
|
95
|
+
left: 0,
|
|
96
|
+
right: 0,
|
|
97
|
+
top: position,
|
|
98
|
+
opacity: position < 0 ? 0 : 1
|
|
99
|
+
};
|
|
56
100
|
};
|
|
57
|
-
|
|
58
|
-
|
|
101
|
+
const renderedItem = getRenderedItem(itemIndex);
|
|
102
|
+
return /* @__PURE__ */ React2__namespace.createElement(
|
|
103
|
+
$View,
|
|
59
104
|
{
|
|
60
|
-
key: id
|
|
105
|
+
$key: `containerPosition${id}`,
|
|
61
106
|
$style: createStyle,
|
|
62
107
|
onLayout: (event) => {
|
|
63
|
-
const index = $
|
|
108
|
+
const index = peek$(`containerIndex${id}`, ctx);
|
|
64
109
|
const length = Math.round(event.nativeEvent.layout[horizontal ? "width" : "height"]);
|
|
65
110
|
onLayout(index, length);
|
|
66
111
|
}
|
|
67
112
|
},
|
|
68
|
-
/* @__PURE__ */ React2__namespace.createElement(
|
|
69
|
-
ItemSeparatorComponent && itemIndex
|
|
113
|
+
recycleItems ? renderedItem : /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, { key: itemIndex }, renderedItem),
|
|
114
|
+
ItemSeparatorComponent && itemIndex < numItems - 1 && ItemSeparatorComponent
|
|
70
115
|
);
|
|
71
116
|
};
|
|
72
117
|
|
|
118
|
+
// src/Containers.tsx
|
|
119
|
+
var Containers = React2__namespace.memo(function Containers2({
|
|
120
|
+
horizontal,
|
|
121
|
+
recycleItems,
|
|
122
|
+
ItemSeparatorComponent,
|
|
123
|
+
updateItemLength,
|
|
124
|
+
getRenderedItem
|
|
125
|
+
}) {
|
|
126
|
+
const ctx = useStateContext();
|
|
127
|
+
const numContainers = use$("numContainers");
|
|
128
|
+
const containers = [];
|
|
129
|
+
for (let i = 0; i < numContainers; i++) {
|
|
130
|
+
containers.push(
|
|
131
|
+
/* @__PURE__ */ React2__namespace.createElement(
|
|
132
|
+
Container,
|
|
133
|
+
{
|
|
134
|
+
id: i,
|
|
135
|
+
key: i,
|
|
136
|
+
recycleItems,
|
|
137
|
+
horizontal,
|
|
138
|
+
getRenderedItem,
|
|
139
|
+
onLayout: updateItemLength,
|
|
140
|
+
ItemSeparatorComponent
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return /* @__PURE__ */ React2__namespace.createElement(
|
|
146
|
+
$View,
|
|
147
|
+
{
|
|
148
|
+
$key: "totalLength",
|
|
149
|
+
$style: () => horizontal ? {
|
|
150
|
+
width: peek$("totalLength", ctx)
|
|
151
|
+
} : {
|
|
152
|
+
height: peek$("totalLength", ctx)
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
containers
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// src/ListComponent.tsx
|
|
160
|
+
var getComponent = (Component) => {
|
|
161
|
+
if (React2__namespace.isValidElement(Component)) {
|
|
162
|
+
return Component;
|
|
163
|
+
}
|
|
164
|
+
if (Component) {
|
|
165
|
+
return /* @__PURE__ */ React2__namespace.createElement(Component, null);
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
};
|
|
169
|
+
var ListComponent = React2__namespace.memo(function ListComponent2({
|
|
170
|
+
style,
|
|
171
|
+
contentContainerStyle,
|
|
172
|
+
horizontal,
|
|
173
|
+
initialContentOffset,
|
|
174
|
+
recycleItems,
|
|
175
|
+
ItemSeparatorComponent,
|
|
176
|
+
alignItemsAtEnd,
|
|
177
|
+
handleScroll,
|
|
178
|
+
onLayout,
|
|
179
|
+
ListHeaderComponent,
|
|
180
|
+
ListHeaderComponentStyle,
|
|
181
|
+
ListFooterComponent,
|
|
182
|
+
ListFooterComponentStyle,
|
|
183
|
+
getRenderedItem,
|
|
184
|
+
updateItemLength,
|
|
185
|
+
refScroller,
|
|
186
|
+
...rest
|
|
187
|
+
}) {
|
|
188
|
+
const ctx = useStateContext();
|
|
189
|
+
return /* @__PURE__ */ React2__namespace.createElement(
|
|
190
|
+
reactNative.ScrollView,
|
|
191
|
+
{
|
|
192
|
+
style,
|
|
193
|
+
contentContainerStyle: [
|
|
194
|
+
contentContainerStyle,
|
|
195
|
+
horizontal ? {
|
|
196
|
+
height: "100%"
|
|
197
|
+
} : {}
|
|
198
|
+
],
|
|
199
|
+
onScroll: handleScroll,
|
|
200
|
+
onLayout,
|
|
201
|
+
scrollEventThrottle: 32,
|
|
202
|
+
horizontal,
|
|
203
|
+
contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
|
|
204
|
+
...rest,
|
|
205
|
+
ref: refScroller
|
|
206
|
+
},
|
|
207
|
+
alignItemsAtEnd && /* @__PURE__ */ React2__namespace.createElement($View, { $key: "paddingTop", $style: () => ({ height: peek$("paddingTop", ctx) }) }),
|
|
208
|
+
ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
|
|
209
|
+
/* @__PURE__ */ React2__namespace.createElement(
|
|
210
|
+
Containers,
|
|
211
|
+
{
|
|
212
|
+
horizontal,
|
|
213
|
+
recycleItems,
|
|
214
|
+
getRenderedItem,
|
|
215
|
+
ItemSeparatorComponent: ItemSeparatorComponent && getComponent(ItemSeparatorComponent),
|
|
216
|
+
updateItemLength
|
|
217
|
+
}
|
|
218
|
+
),
|
|
219
|
+
ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
|
|
73
223
|
// src/LegendList.tsx
|
|
74
|
-
enableReactNativeComponents.enableReactNativeComponents();
|
|
75
224
|
var DEFAULT_SCROLL_BUFFER = 0;
|
|
76
225
|
var POSITION_OUT_OF_VIEW = -1e4;
|
|
77
226
|
var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
style,
|
|
84
|
-
contentContainerStyle,
|
|
85
|
-
initialContainers,
|
|
86
|
-
drawDistance,
|
|
87
|
-
recycleItems = true,
|
|
88
|
-
onEndReachedThreshold,
|
|
89
|
-
maintainScrollAtEnd = false,
|
|
90
|
-
maintainScrollAtEndThreshold = 0.1,
|
|
91
|
-
alignItemsAtEnd = false,
|
|
92
|
-
keyExtractor,
|
|
93
|
-
renderItem,
|
|
94
|
-
estimatedItemLength,
|
|
95
|
-
onEndReached,
|
|
96
|
-
onViewableRangeChanged,
|
|
97
|
-
ListHeaderComponent,
|
|
98
|
-
ListHeaderComponentStyle,
|
|
99
|
-
ListFooterComponent,
|
|
100
|
-
ListFooterComponentStyle,
|
|
101
|
-
ItemSeparatorComponent,
|
|
102
|
-
...rest
|
|
103
|
-
} = props;
|
|
104
|
-
const internalRef = React2.useRef(null);
|
|
105
|
-
const refScroller = forwardedRef || internalRef;
|
|
106
|
-
const containers$ = react.useObservable(() => []);
|
|
107
|
-
const paddingTop$ = react.useObservable(0);
|
|
108
|
-
const visibleRange$ = react.useObservable(() => ({
|
|
109
|
-
start: 0,
|
|
110
|
-
end: 0,
|
|
111
|
-
totalLength: 0,
|
|
112
|
-
scroll: 0,
|
|
113
|
-
topPad: 0
|
|
114
|
-
}));
|
|
115
|
-
const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_SCROLL_BUFFER;
|
|
116
|
-
const refPositions = React2.useRef();
|
|
117
|
-
const getId = (index) => {
|
|
118
|
-
var _a;
|
|
119
|
-
const data2 = (_a = refPositions.current) == null ? void 0 : _a.data;
|
|
120
|
-
if (!data2) {
|
|
121
|
-
return "";
|
|
122
|
-
}
|
|
123
|
-
const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
|
|
124
|
-
return ret + "";
|
|
125
|
-
};
|
|
126
|
-
if (!refPositions.current) {
|
|
127
|
-
refPositions.current = {
|
|
128
|
-
lengths: /* @__PURE__ */ new Map(),
|
|
129
|
-
positions: /* @__PURE__ */ new Map(),
|
|
130
|
-
pendingAdjust: 0,
|
|
131
|
-
animFrame: null,
|
|
132
|
-
isStartReached: false,
|
|
133
|
-
isEndReached: false,
|
|
134
|
-
isAtBottom: false,
|
|
227
|
+
return /* @__PURE__ */ React2__namespace.createElement(StateProvider, null, /* @__PURE__ */ React2__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
|
|
228
|
+
});
|
|
229
|
+
var LegendListInner = React2.forwardRef(
|
|
230
|
+
function LegendListInner2(props, forwardedRef) {
|
|
231
|
+
const {
|
|
135
232
|
data,
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
(
|
|
233
|
+
initialScrollIndex,
|
|
234
|
+
initialScrollOffset,
|
|
235
|
+
horizontal,
|
|
236
|
+
style: styleProp,
|
|
237
|
+
contentContainerStyle: contentContainerStyleProp,
|
|
238
|
+
initialContainers,
|
|
239
|
+
drawDistance,
|
|
240
|
+
recycleItems = true,
|
|
241
|
+
onEndReachedThreshold = 0.5,
|
|
242
|
+
maintainScrollAtEnd = false,
|
|
243
|
+
maintainScrollAtEndThreshold = 0.1,
|
|
244
|
+
alignItemsAtEnd = false,
|
|
245
|
+
keyExtractor,
|
|
246
|
+
renderItem,
|
|
247
|
+
estimatedItemLength,
|
|
248
|
+
onEndReached,
|
|
249
|
+
onViewableRangeChanged,
|
|
250
|
+
...rest
|
|
251
|
+
} = props;
|
|
252
|
+
const ctx = useStateContext();
|
|
253
|
+
const internalRef = React2.useRef(null);
|
|
254
|
+
const refScroller = forwardedRef || internalRef;
|
|
255
|
+
const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_SCROLL_BUFFER;
|
|
256
|
+
const styleFlattened = reactNative.StyleSheet.flatten(styleProp);
|
|
257
|
+
const style = React2.useMemo(() => styleFlattened, [JSON.stringify(styleProp)]);
|
|
258
|
+
const contentContainerStyleFlattened = reactNative.StyleSheet.flatten(contentContainerStyleProp);
|
|
259
|
+
const contentContainerStyle = React2.useMemo(
|
|
260
|
+
() => contentContainerStyleFlattened,
|
|
261
|
+
[JSON.stringify(contentContainerStyleProp)]
|
|
262
|
+
);
|
|
263
|
+
const refState = React2.useRef();
|
|
264
|
+
const getId = (index) => {
|
|
167
265
|
var _a;
|
|
168
|
-
const data2 = (_a =
|
|
266
|
+
const data2 = (_a = refState.current) == null ? void 0 : _a.data;
|
|
169
267
|
if (!data2) {
|
|
170
|
-
return
|
|
268
|
+
return "";
|
|
171
269
|
}
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
270
|
+
const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
|
|
271
|
+
return ret + "";
|
|
272
|
+
};
|
|
273
|
+
if (!refState.current) {
|
|
274
|
+
refState.current = {
|
|
275
|
+
lengths: /* @__PURE__ */ new Map(),
|
|
276
|
+
positions: /* @__PURE__ */ new Map(),
|
|
277
|
+
pendingAdjust: 0,
|
|
278
|
+
animFrame: null,
|
|
279
|
+
isStartReached: false,
|
|
280
|
+
isEndReached: false,
|
|
281
|
+
isAtBottom: false,
|
|
282
|
+
data,
|
|
283
|
+
idsInFirstRender: void 0,
|
|
284
|
+
hasScrolled: false,
|
|
285
|
+
scrollLength: reactNative.Dimensions.get("window")[horizontal ? "width" : "height"],
|
|
286
|
+
startBuffered: 0,
|
|
287
|
+
startNoBuffer: 0,
|
|
288
|
+
endBuffered: 0,
|
|
289
|
+
endNoBuffer: 0,
|
|
290
|
+
scroll: 0,
|
|
291
|
+
topPad: 0
|
|
292
|
+
};
|
|
293
|
+
refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
|
|
185
294
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
for (let i = 0; i < data2.length; i++) {
|
|
196
|
-
const id = getId(i);
|
|
197
|
-
const length = (_a = lengths.get(id)) != null ? _a : estimatedItemLength(i);
|
|
198
|
-
if (positions.get(id) !== top) {
|
|
199
|
-
positions.set(id, top);
|
|
295
|
+
refState.current.data = data;
|
|
296
|
+
set$(`numItems`, ctx, data.length);
|
|
297
|
+
const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : initialScrollIndex ? initialScrollIndex * estimatedItemLength(initialScrollIndex) : void 0;
|
|
298
|
+
const setTotalLength = (length) => {
|
|
299
|
+
set$(`totalLength`, ctx, length);
|
|
300
|
+
const screenLength = refState.current.scrollLength;
|
|
301
|
+
if (alignItemsAtEnd) {
|
|
302
|
+
const listPaddingTop = ((style == null ? void 0 : style.paddingTop) || 0) + ((contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) || 0);
|
|
303
|
+
set$(`paddingTop`, ctx, Math.max(0, screenLength - length - listPaddingTop));
|
|
200
304
|
}
|
|
201
|
-
|
|
202
|
-
|
|
305
|
+
};
|
|
306
|
+
const allocateContainers = React2.useCallback(() => {
|
|
307
|
+
const scrollLength = refState.current.scrollLength;
|
|
308
|
+
const numContainers = initialContainers || Math.ceil((scrollLength + scrollBuffer * 2) / estimatedItemLength(0)) + 4;
|
|
309
|
+
for (let i = 0; i < numContainers; i++) {
|
|
310
|
+
set$(`containerIndex${i}`, ctx, -1);
|
|
311
|
+
set$(`containerPosition${i}`, ctx, POSITION_OUT_OF_VIEW);
|
|
203
312
|
}
|
|
204
|
-
|
|
205
|
-
|
|
313
|
+
set$(`numContainers`, ctx, numContainers);
|
|
314
|
+
}, []);
|
|
315
|
+
const getRenderedItem = React2.useCallback(
|
|
316
|
+
(index) => {
|
|
317
|
+
var _a;
|
|
318
|
+
const data2 = (_a = refState.current) == null ? void 0 : _a.data;
|
|
319
|
+
if (!data2) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const renderedItem = renderItem == null ? void 0 : renderItem({
|
|
323
|
+
item: data2[index],
|
|
324
|
+
index
|
|
325
|
+
});
|
|
326
|
+
return renderedItem;
|
|
327
|
+
},
|
|
328
|
+
[renderItem]
|
|
329
|
+
);
|
|
330
|
+
const calculateItemsInView = React2.useCallback(() => {
|
|
331
|
+
var _a, _b;
|
|
332
|
+
const {
|
|
333
|
+
data: data2,
|
|
334
|
+
scrollLength,
|
|
335
|
+
scroll: scrollState,
|
|
336
|
+
topPad,
|
|
337
|
+
startNoBuffer: startNoBufferState,
|
|
338
|
+
startBuffered: startBufferedState,
|
|
339
|
+
endNoBuffer: endNoBufferState,
|
|
340
|
+
endBuffered: endBufferedState
|
|
341
|
+
} = refState.current;
|
|
342
|
+
if (!data2) {
|
|
343
|
+
return;
|
|
206
344
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
345
|
+
const scroll = scrollState - topPad;
|
|
346
|
+
const { lengths, positions } = refState.current;
|
|
347
|
+
let top = 0;
|
|
348
|
+
let startNoBuffer = null;
|
|
349
|
+
let startBuffered = null;
|
|
350
|
+
let endNoBuffer = null;
|
|
351
|
+
let endBuffered = null;
|
|
352
|
+
for (let i = 0; i < data2.length; i++) {
|
|
353
|
+
const id = getId(i);
|
|
354
|
+
const length = (_a = lengths.get(id)) != null ? _a : estimatedItemLength(i);
|
|
355
|
+
if (positions.get(id) !== top) {
|
|
356
|
+
positions.set(id, top);
|
|
210
357
|
}
|
|
211
|
-
if (
|
|
212
|
-
|
|
213
|
-
} else {
|
|
214
|
-
break;
|
|
358
|
+
if (startNoBuffer === null && top + length > scroll) {
|
|
359
|
+
startNoBuffer = i;
|
|
215
360
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (startBuffered !== null && endBuffered !== null) {
|
|
227
|
-
for (let i = startBuffered; i <= endBuffered; i++) {
|
|
228
|
-
let isContained = false;
|
|
229
|
-
for (let j = 0; j < containers2.length; j++) {
|
|
230
|
-
const container = containers2[j];
|
|
231
|
-
if (container.itemIndex === i) {
|
|
232
|
-
isContained = true;
|
|
361
|
+
if (startBuffered === null && top + length > scroll - scrollBuffer) {
|
|
362
|
+
startBuffered = i;
|
|
363
|
+
}
|
|
364
|
+
if (startNoBuffer !== null) {
|
|
365
|
+
if (top <= scroll + scrollLength) {
|
|
366
|
+
endNoBuffer = i;
|
|
367
|
+
}
|
|
368
|
+
if (top <= scroll + scrollLength + scrollBuffer) {
|
|
369
|
+
endBuffered = i;
|
|
370
|
+
} else {
|
|
233
371
|
break;
|
|
234
372
|
}
|
|
235
373
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
374
|
+
top += length;
|
|
375
|
+
}
|
|
376
|
+
Object.assign(refState.current, {
|
|
377
|
+
startBuffered,
|
|
378
|
+
startNoBuffer,
|
|
379
|
+
endBuffered,
|
|
380
|
+
endNoBuffer
|
|
381
|
+
});
|
|
382
|
+
if (startBuffered !== null && endBuffered !== null) {
|
|
383
|
+
const prevNumContainers = ctx.values.get("numContainers");
|
|
384
|
+
let numContainers = prevNumContainers;
|
|
385
|
+
for (let i = startBuffered; i <= endBuffered; i++) {
|
|
386
|
+
let isContained = false;
|
|
387
|
+
for (let j = 0; j < numContainers; j++) {
|
|
388
|
+
const index = peek$(`containerIndex${j}`, ctx);
|
|
389
|
+
if (index === i) {
|
|
390
|
+
isContained = true;
|
|
243
391
|
break;
|
|
244
392
|
}
|
|
245
393
|
}
|
|
246
|
-
if (!
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
394
|
+
if (!isContained) {
|
|
395
|
+
let didRecycle = false;
|
|
396
|
+
for (let u = 0; u < numContainers; u++) {
|
|
397
|
+
const index = peek$(`containerIndex${u}`, ctx);
|
|
398
|
+
if (index < startBuffered || index > endBuffered) {
|
|
399
|
+
set$(`containerIndex${u}`, ctx, i);
|
|
400
|
+
didRecycle = true;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (!didRecycle) {
|
|
405
|
+
if (__DEV__) {
|
|
406
|
+
console.warn(
|
|
407
|
+
"[legend-list] No container to recycle, consider increasing initialContainers or estimatedItemLength",
|
|
408
|
+
i
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
const id = numContainers;
|
|
412
|
+
numContainers++;
|
|
413
|
+
set$(`containerIndex${id}`, ctx, i);
|
|
414
|
+
set$(`containerPosition${id}`, ctx, POSITION_OUT_OF_VIEW);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (numContainers !== prevNumContainers) {
|
|
419
|
+
set$(`numContainers`, ctx, numContainers);
|
|
420
|
+
}
|
|
421
|
+
for (let i = 0; i < numContainers; i++) {
|
|
422
|
+
const itemIndex = peek$(`containerIndex${i}`, ctx);
|
|
423
|
+
const item = data2[itemIndex];
|
|
424
|
+
if (item) {
|
|
425
|
+
const id = getId(itemIndex);
|
|
426
|
+
if (itemIndex < startBuffered || itemIndex > endBuffered) {
|
|
427
|
+
set$(`containerPosition${i}`, ctx, POSITION_OUT_OF_VIEW);
|
|
428
|
+
} else {
|
|
429
|
+
const pos = (_b = positions.get(id)) != null ? _b : -1;
|
|
430
|
+
const prevPos = peek$(`containerPosition${i}`, ctx);
|
|
431
|
+
if (pos >= 0 && pos !== prevPos) {
|
|
432
|
+
set$(`containerPosition${i}`, ctx, pos);
|
|
433
|
+
}
|
|
252
434
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (onViewableRangeChanged) {
|
|
438
|
+
if (startNoBuffer !== startNoBufferState || startBuffered !== startBufferedState || endNoBuffer !== endNoBufferState || endBuffered !== endBufferedState) {
|
|
439
|
+
onViewableRangeChanged({
|
|
440
|
+
start: startNoBuffer,
|
|
441
|
+
startBuffered,
|
|
442
|
+
end: endNoBuffer,
|
|
443
|
+
endBuffered,
|
|
444
|
+
items: data2.slice(startNoBuffer, endNoBuffer + 1)
|
|
257
445
|
});
|
|
258
446
|
}
|
|
259
447
|
}
|
|
260
448
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
449
|
+
}, [data]);
|
|
450
|
+
React2.useMemo(() => {
|
|
451
|
+
var _a, _b;
|
|
452
|
+
allocateContainers();
|
|
453
|
+
calculateItemsInView();
|
|
454
|
+
const lengths = (_a = refState.current) == null ? void 0 : _a.lengths;
|
|
455
|
+
let totalLength = 0;
|
|
456
|
+
for (let i = 0; i < data.length; i++) {
|
|
457
|
+
const id = getId(i);
|
|
458
|
+
totalLength += (_b = lengths.get(id)) != null ? _b : estimatedItemLength(i);
|
|
459
|
+
}
|
|
460
|
+
setTotalLength(totalLength);
|
|
461
|
+
}, []);
|
|
462
|
+
const checkAtBottom = () => {
|
|
463
|
+
var _a;
|
|
464
|
+
const { scrollLength, scroll } = refState.current;
|
|
465
|
+
const totalLength = peek$("totalLength", ctx);
|
|
466
|
+
const distanceFromEnd = totalLength - scroll - scrollLength;
|
|
467
|
+
if (refState.current) {
|
|
468
|
+
refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
|
|
469
|
+
}
|
|
470
|
+
if (onEndReached && !((_a = refState.current) == null ? void 0 : _a.isEndReached)) {
|
|
471
|
+
if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
|
|
472
|
+
if (refState.current) {
|
|
473
|
+
refState.current.isEndReached = true;
|
|
273
474
|
}
|
|
475
|
+
onEndReached({ distanceFromEnd });
|
|
274
476
|
}
|
|
275
477
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
478
|
+
};
|
|
479
|
+
React2.useMemo(() => {
|
|
480
|
+
if (refState.current) {
|
|
481
|
+
refState.current.isEndReached = false;
|
|
482
|
+
}
|
|
483
|
+
calculateItemsInView();
|
|
484
|
+
checkAtBottom();
|
|
485
|
+
}, [data]);
|
|
486
|
+
const updateItemLength = React2.useCallback((index, length) => {
|
|
487
|
+
var _a, _b, _c, _d, _e;
|
|
488
|
+
const data2 = (_a = refState.current) == null ? void 0 : _a.data;
|
|
489
|
+
if (!data2) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const lengths = (_b = refState.current) == null ? void 0 : _b.lengths;
|
|
493
|
+
const id = getId(index);
|
|
494
|
+
const wasInFirstRender = (_c = refState.current) == null ? void 0 : _c.idsInFirstRender.has(id);
|
|
495
|
+
const prevLength = lengths.get(id) || (wasInFirstRender ? estimatedItemLength(index) : 0);
|
|
496
|
+
if (!prevLength || prevLength !== length) {
|
|
497
|
+
lengths.set(id, length);
|
|
498
|
+
const totalLength = peek$("totalLength", ctx);
|
|
499
|
+
setTotalLength(totalLength + (length - prevLength));
|
|
500
|
+
if (((_d = refState.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
|
|
501
|
+
requestAnimationFrame(() => {
|
|
502
|
+
var _a2;
|
|
503
|
+
(_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
|
|
504
|
+
animated: true
|
|
505
|
+
});
|
|
284
506
|
});
|
|
285
507
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
state.endBatch();
|
|
289
|
-
}, [data]);
|
|
290
|
-
React2.useMemo(() => {
|
|
291
|
-
var _a, _b;
|
|
292
|
-
allocateContainers();
|
|
293
|
-
calculateItemsInView();
|
|
294
|
-
const lengths = (_a = refPositions.current) == null ? void 0 : _a.lengths;
|
|
295
|
-
let totalLength = 0;
|
|
296
|
-
for (let i = 0; i < data.length; i++) {
|
|
297
|
-
const id = getId(i);
|
|
298
|
-
totalLength += (_b = lengths.get(id)) != null ? _b : estimatedItemLength(i);
|
|
299
|
-
}
|
|
300
|
-
setTotalLength(totalLength);
|
|
301
|
-
}, []);
|
|
302
|
-
const checkAtBottom = () => {
|
|
303
|
-
var _a;
|
|
304
|
-
const scrollLength = refPositions.current.scrollLength;
|
|
305
|
-
const newScroll = visibleRange$.scroll.peek();
|
|
306
|
-
const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - scrollLength;
|
|
307
|
-
if (refPositions.current) {
|
|
308
|
-
refPositions.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
|
|
309
|
-
}
|
|
310
|
-
if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
|
|
311
|
-
if (distanceFromEnd < (onEndReachedThreshold || 0.5) * scrollLength) {
|
|
312
|
-
if (refPositions.current) {
|
|
313
|
-
refPositions.current.isEndReached = true;
|
|
508
|
+
if (!((_e = refState.current) == null ? void 0 : _e.animFrame)) {
|
|
509
|
+
calculateItemsInView();
|
|
314
510
|
}
|
|
315
|
-
onEndReached({ distanceFromEnd });
|
|
316
511
|
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
refPositions.current.isEndReached = false;
|
|
512
|
+
}, []);
|
|
513
|
+
const handleScrollDebounced = React2.useCallback(() => {
|
|
514
|
+
calculateItemsInView();
|
|
515
|
+
checkAtBottom();
|
|
516
|
+
if (refState.current) {
|
|
517
|
+
refState.current.animFrame = null;
|
|
324
518
|
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const lengths = (_b = refPositions.current) == null ? void 0 : _b.lengths;
|
|
337
|
-
const id = getId(index);
|
|
338
|
-
const wasInFirstRender = (_c = refPositions.current) == null ? void 0 : _c.idsInFirstRender.has(id);
|
|
339
|
-
const prevLength = lengths.get(id) || (wasInFirstRender ? estimatedItemLength(index) : 0);
|
|
340
|
-
if (!prevLength || prevLength !== length) {
|
|
341
|
-
state.beginBatch();
|
|
342
|
-
lengths.set(id, length);
|
|
343
|
-
setTotalLength(visibleRange$.totalLength.peek() + (length - prevLength));
|
|
344
|
-
if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
|
|
345
|
-
requestAnimationFrame(() => {
|
|
346
|
-
var _a2;
|
|
347
|
-
(_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
|
|
348
|
-
animated: true
|
|
349
|
-
});
|
|
350
|
-
});
|
|
519
|
+
}, []);
|
|
520
|
+
const onLayout = React2.useCallback((event) => {
|
|
521
|
+
const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
|
|
522
|
+
refState.current.scrollLength = scrollLength;
|
|
523
|
+
}, []);
|
|
524
|
+
const handleScroll = React2.useCallback((event) => {
|
|
525
|
+
refState.current.hasScrolled = true;
|
|
526
|
+
const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
|
|
527
|
+
refState.current.scroll = newScroll;
|
|
528
|
+
if (refState.current && !refState.current.animFrame) {
|
|
529
|
+
refState.current.animFrame = requestAnimationFrame(handleScrollDebounced);
|
|
351
530
|
}
|
|
352
|
-
|
|
531
|
+
}, []);
|
|
532
|
+
React2.useEffect(() => {
|
|
533
|
+
if (initialContentOffset) {
|
|
534
|
+
handleScroll({
|
|
535
|
+
nativeEvent: { contentOffset: { y: initialContentOffset } }
|
|
536
|
+
});
|
|
353
537
|
calculateItemsInView();
|
|
354
538
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const handleScrollDebounced = React2.useCallback(() => {
|
|
359
|
-
calculateItemsInView();
|
|
360
|
-
checkAtBottom();
|
|
361
|
-
if (refPositions.current) {
|
|
362
|
-
refPositions.current.animFrame = null;
|
|
363
|
-
}
|
|
364
|
-
}, []);
|
|
365
|
-
const onLayout = (event) => {
|
|
366
|
-
const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
|
|
367
|
-
refPositions.current.scrollLength = scrollLength;
|
|
368
|
-
};
|
|
369
|
-
const handleScroll = React2.useCallback((event) => {
|
|
370
|
-
refPositions.current.hasScrolled = true;
|
|
371
|
-
const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
|
|
372
|
-
visibleRange$.scroll.set(newScroll);
|
|
373
|
-
if (refPositions.current && !refPositions.current.animFrame) {
|
|
374
|
-
refPositions.current.animFrame = requestAnimationFrame(handleScrollDebounced);
|
|
375
|
-
}
|
|
376
|
-
}, []);
|
|
377
|
-
React2.useEffect(() => {
|
|
378
|
-
if (initialContentOffset) {
|
|
379
|
-
handleScroll({
|
|
380
|
-
nativeEvent: { contentOffset: { y: initialContentOffset } }
|
|
381
|
-
});
|
|
382
|
-
calculateItemsInView();
|
|
383
|
-
}
|
|
384
|
-
}, []);
|
|
385
|
-
return /* @__PURE__ */ React2__namespace.createElement(
|
|
386
|
-
react.Reactive.ScrollView,
|
|
387
|
-
{
|
|
388
|
-
style,
|
|
389
|
-
contentContainerStyle: [
|
|
390
|
-
contentContainerStyle,
|
|
391
|
-
horizontal ? {
|
|
392
|
-
height: "100%"
|
|
393
|
-
} : {}
|
|
394
|
-
],
|
|
395
|
-
onScroll: handleScroll,
|
|
396
|
-
onLayout,
|
|
397
|
-
scrollEventThrottle: 32,
|
|
398
|
-
horizontal,
|
|
399
|
-
contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
|
|
400
|
-
...rest,
|
|
401
|
-
ref: refScroller
|
|
402
|
-
},
|
|
403
|
-
alignItemsAtEnd && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: () => ({ height: paddingTop$.get() }) }),
|
|
404
|
-
ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
|
|
405
|
-
/* @__PURE__ */ React2__namespace.createElement(
|
|
406
|
-
react.Reactive.View,
|
|
539
|
+
}, []);
|
|
540
|
+
return /* @__PURE__ */ React2__namespace.createElement(
|
|
541
|
+
ListComponent,
|
|
407
542
|
{
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}
|
|
425
|
-
))
|
|
426
|
-
),
|
|
427
|
-
ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: ListFooterComponentStyle }, ListFooterComponent)
|
|
428
|
-
);
|
|
429
|
-
});
|
|
543
|
+
...rest,
|
|
544
|
+
contentContainerStyle,
|
|
545
|
+
style,
|
|
546
|
+
horizontal,
|
|
547
|
+
refScroller,
|
|
548
|
+
initialContentOffset,
|
|
549
|
+
getRenderedItem,
|
|
550
|
+
updateItemLength,
|
|
551
|
+
handleScroll,
|
|
552
|
+
onLayout,
|
|
553
|
+
recycleItems,
|
|
554
|
+
alignItemsAtEnd
|
|
555
|
+
}
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
);
|
|
430
559
|
|
|
431
560
|
exports.LegendList = LegendList;
|