@legendapp/list 3.6.0 → 3.7.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/keyboard.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
+ var reactNative$1 = require('react-native');
4
5
  var reactNativeKeyboardController = require('react-native-keyboard-controller');
5
6
  var reactNativeReanimated = require('react-native-reanimated');
6
7
  var reactNative = require('@legendapp/list/react-native');
@@ -59,19 +60,61 @@ function useKeyboardChatComposerInset(_listRef, composerRef, initialHeight = 0)
59
60
  );
60
61
  return { contentInsetEndAdjustment, onComposerLayout };
61
62
  }
63
+ var DISMISS_TIMEOUT_MS = 2e3;
64
+ function dismissKeyboard() {
65
+ let timer;
66
+ const timeout = new Promise((resolve) => {
67
+ timer = setTimeout(resolve, DISMISS_TIMEOUT_MS);
68
+ });
69
+ return Promise.race([reactNativeKeyboardController.KeyboardController.dismiss(), timeout]).catch(() => {
70
+ }).finally(() => clearTimeout(timer));
71
+ }
72
+ var endScrollFreezes = /* @__PURE__ */ new WeakMap();
73
+ var keyboardCloses = /* @__PURE__ */ new WeakMap();
74
+ function getEndScrollFreeze(freeze) {
75
+ let owned = endScrollFreezes.get(freeze);
76
+ if (!owned) {
77
+ owned = reactNativeReanimated.makeMutable(false);
78
+ endScrollFreezes.set(freeze, owned);
79
+ }
80
+ return owned;
81
+ }
82
+ function setFreeze(freeze, value, onSet, animated = false) {
83
+ const owned = getEndScrollFreeze(freeze);
84
+ reactNativeReanimated.runOnUI(() => {
85
+ "worklet";
86
+ owned.value = value ? animated ? "animated" : "immediate" : false;
87
+ freeze.value = value;
88
+ if (onSet) reactNativeReanimated.runOnJS(onSet)();
89
+ })();
90
+ }
62
91
  function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }) {
63
92
  const internalFreeze = reactNativeReanimated.useSharedValue(false);
64
93
  const freeze = freezeProp != null ? freezeProp : internalFreeze;
94
+ const latestRequest = React.useRef(0);
95
+ const closing = React.useRef(void 0);
96
+ const preparedClose = React.useRef(false);
65
97
  const scrollMessageToEnd = React.useCallback(
66
98
  async ({ animated, closeKeyboard }) => {
67
- const listRefCurrent = listRef.current;
68
- if (listRefCurrent) {
69
- freeze.set(true);
70
- const dismissPromise = closeKeyboard && reactNativeKeyboardController.KeyboardController.dismiss();
71
- const scrollPromise = listRefCurrent.scrollToEnd({ animated });
72
- await Promise.all([scrollPromise, dismissPromise]);
73
- freeze.set(false);
99
+ var _a;
100
+ const list = listRef.current;
101
+ if (!list) return;
102
+ if (closeKeyboard && ((_a = keyboardCloses.get(freeze)) == null ? void 0 : _a.prepare())) preparedClose.current = true;
103
+ const scrollPromise = list.scrollToEnd({ animated });
104
+ const request = ++latestRequest.current;
105
+ const frozen = new Promise((resolve) => setFreeze(freeze, true, resolve, preparedClose.current));
106
+ if (closeKeyboard && !closing.current) {
107
+ closing.current = frozen.then(dismissKeyboard).finally(() => {
108
+ closing.current = void 0;
109
+ });
74
110
  }
111
+ await Promise.all([scrollPromise, closing.current]).finally(() => {
112
+ var _a2;
113
+ if (request === latestRequest.current) {
114
+ preparedClose.current = false;
115
+ setFreeze(freeze, false, (_a2 = keyboardCloses.get(freeze)) == null ? void 0 : _a2.restore);
116
+ }
117
+ });
75
118
  },
76
119
  [freeze, listRef]
77
120
  );
@@ -81,6 +124,7 @@ function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }) {
81
124
  };
82
125
  }
83
126
  var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(props, forwardedRef) {
127
+ var _a, _b;
84
128
  const {
85
129
  anchoredEndSpace,
86
130
  applyWorkaroundForContentInsetHitTestBug,
@@ -88,11 +132,61 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
88
132
  freeze,
89
133
  keyboardLiftBehavior,
90
134
  keyboardOffset,
135
+ refScrollView,
91
136
  ...rest
92
137
  } = props;
93
138
  const refLegendList = React.useRef(null);
94
139
  const combinedRef = useCombinedRef(forwardedRef, refLegendList);
140
+ const staticContentInsetRef = React.useRef(rest.contentInset);
141
+ staticContentInsetRef.current = rest.contentInset;
95
142
  const blankSpace = reactNativeReanimated.useSharedValue(0);
143
+ const scrollRef = reactNativeReanimated.useAnimatedRef();
144
+ const combinedScrollRef = useCombinedRef(scrollRef, refScrollView);
145
+ const scrollOffset = reactNativeReanimated.useScrollViewOffset(scrollRef);
146
+ const dimensions = reactNativeReanimated.useSharedValue({ content: 0, viewport: 0 });
147
+ const frozenClose = reactNativeReanimated.useSharedValue(false);
148
+ const closeOffset = reactNativeReanimated.useSharedValue(0);
149
+ const endScrollFreeze = typeof freeze === "object" ? getEndScrollFreeze(freeze) : void 0;
150
+ const reportedInsets = React.useRef(void 0);
151
+ const initialKeyboardHeight = reactNativeKeyboardController.KeyboardController.state().height;
152
+ const keyboard = reactNativeReanimated.useSharedValue({ height: initialKeyboardHeight, progress: initialKeyboardHeight > 0 ? 1 : 0 });
153
+ const keyboardTarget = reactNativeReanimated.useSharedValue(initialKeyboardHeight);
154
+ const isHorizontal = !!rest.horizontal;
155
+ const reportViewabilityInset = React.useCallback((inset) => {
156
+ var _a2, _b2;
157
+ (_b2 = (_a2 = refLegendList.current) == null ? void 0 : _a2.reportViewabilityInsetEndInternal) == null ? void 0 : _b2.call(_a2, inset);
158
+ }, []);
159
+ const onKeyboardMove = (event) => {
160
+ "worklet";
161
+ keyboard.value = { height: event.height, progress: event.progress };
162
+ };
163
+ reactNativeKeyboardController.useKeyboardHandler(
164
+ {
165
+ onEnd: onKeyboardMove,
166
+ onInteractive: onKeyboardMove,
167
+ onMove: onKeyboardMove,
168
+ onStart: (event) => {
169
+ "worklet";
170
+ keyboardTarget.value = event.height;
171
+ if (event.height === 0 && !frozenClose.value) closeOffset.value = scrollOffset.value;
172
+ frozenClose.value = event.height === 0 && !!(endScrollFreeze == null ? void 0 : endScrollFreeze.value);
173
+ }
174
+ },
175
+ [endScrollFreeze]
176
+ );
177
+ reactNativeReanimated.useAnimatedReaction(
178
+ // Blank space extends the scroll range but does not obscure content.
179
+ () => {
180
+ var _a2;
181
+ return isHorizontal ? 0 : Math.max(0, keyboard.value.height - (keyboardOffset != null ? keyboardOffset : 0) * keyboard.value.progress) + Math.max(0, (_a2 = contentInsetEndAdjustment == null ? void 0 : contentInsetEndAdjustment.value) != null ? _a2 : 0);
182
+ },
183
+ (current, previous) => {
184
+ if (current !== previous) {
185
+ reactNativeReanimated.runOnJS(reportViewabilityInset)(current);
186
+ }
187
+ },
188
+ [contentInsetEndAdjustment, isHorizontal, keyboard, keyboardOffset, reportViewabilityInset]
189
+ );
96
190
  React.useEffect(() => {
97
191
  if (!anchoredEndSpace) {
98
192
  blankSpace.value = 0;
@@ -105,16 +199,90 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
105
199
  return {
106
200
  ...anchoredEndSpace,
107
201
  onSizeChanged: (size) => {
108
- var _a;
202
+ var _a2;
109
203
  blankSpace.value = size;
110
- (_a = anchoredEndSpace.onSizeChanged) == null ? void 0 : _a.call(anchoredEndSpace, size);
204
+ (_a2 = anchoredEndSpace.onSizeChanged) == null ? void 0 : _a2.call(anchoredEndSpace, size);
111
205
  }
112
206
  };
113
207
  }, [anchoredEndSpace, blankSpace]);
114
- const onContentInsetChange = React.useCallback((insets) => {
115
- var _a;
116
- (_a = refLegendList.current) == null ? void 0 : _a.reportContentInset(insets);
208
+ const staticBottomInset = reactNative$1.Platform.OS === "ios" ? (_b = (_a = rest.contentInset) == null ? void 0 : _a.bottom) != null ? _b : 0 : 0;
209
+ const getEndInset = React.useCallback(
210
+ (keyboardInset = 0) => {
211
+ "worklet";
212
+ var _a2;
213
+ const padding = keyboardInset + ((_a2 = contentInsetEndAdjustment == null ? void 0 : contentInsetEndAdjustment.value) != null ? _a2 : 0);
214
+ return staticBottomInset + Math.min(dimensions.value.viewport, Math.max(blankSpace.value, padding));
215
+ },
216
+ [blankSpace, contentInsetEndAdjustment, dimensions, staticBottomInset]
217
+ );
218
+ const onContentInsetChange = React.useCallback(
219
+ (insets) => {
220
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
221
+ const staticInset = staticContentInsetRef.current;
222
+ if (reactNative$1.Platform.OS !== "ios" && staticInset) {
223
+ insets = {
224
+ bottom: Math.max(0, ((_a2 = insets.bottom) != null ? _a2 : 0) - ((_b2 = staticInset.bottom) != null ? _b2 : 0)),
225
+ left: Math.max(0, ((_c = insets.left) != null ? _c : 0) - ((_d = staticInset.left) != null ? _d : 0)),
226
+ right: Math.max(0, ((_e = insets.right) != null ? _e : 0) - ((_f = staticInset.right) != null ? _f : 0)),
227
+ top: Math.max(0, ((_g = insets.top) != null ? _g : 0) - ((_h = staticInset.top) != null ? _h : 0))
228
+ };
229
+ }
230
+ reportedInsets.current = insets;
231
+ const list = refLegendList.current;
232
+ if ((endScrollFreeze == null ? void 0 : endScrollFreeze.value) === "animated") {
233
+ (_i = list == null ? void 0 : list.reportContentInsetForScrollInternal) == null ? void 0 : _i.call(list, { ...insets, bottom: getEndInset() });
234
+ } else if (keyboardTarget.value > 0 && (list == null ? void 0 : list.reportContentInsetForScrollInternal)) {
235
+ list.reportContentInsetForScrollInternal(insets);
236
+ } else {
237
+ list == null ? void 0 : list.reportContentInset(insets);
238
+ }
239
+ },
240
+ [endScrollFreeze, getEndInset, keyboardTarget]
241
+ );
242
+ const reportClosingInset = React.useCallback((bottom) => {
243
+ var _a2;
244
+ (_a2 = refLegendList.current) == null ? void 0 : _a2.reportContentInset({ ...reportedInsets.current, bottom });
117
245
  }, []);
246
+ React.useLayoutEffect(() => {
247
+ if (typeof freeze !== "object") return;
248
+ keyboardCloses.set(freeze, {
249
+ prepare: () => {
250
+ var _a2;
251
+ const report = (_a2 = refLegendList.current) == null ? void 0 : _a2.reportContentInsetForScrollInternal;
252
+ if (isHorizontal || !dimensions.value.viewport || keyboard.value.height === 0 || !report) return false;
253
+ report({ ...reportedInsets.current, bottom: getEndInset() });
254
+ return true;
255
+ },
256
+ restore: () => {
257
+ var _a2;
258
+ if (keyboard.value.height > 0 && reportedInsets.current) {
259
+ (_a2 = refLegendList.current) == null ? void 0 : _a2.reportContentInset(reportedInsets.current);
260
+ }
261
+ }
262
+ });
263
+ return () => {
264
+ keyboardCloses.delete(freeze);
265
+ };
266
+ }, [dimensions, freeze, getEndInset, isHorizontal, keyboard]);
267
+ reactNativeReanimated.useAnimatedReaction(
268
+ () => frozenClose.value && (endScrollFreeze == null ? void 0 : endScrollFreeze.value) === "immediate" && typeof freeze === "object" && freeze.value ? { height: keyboard.value.height, scroll: scrollOffset.value } : null,
269
+ (current, previous) => {
270
+ if (!current) {
271
+ frozenClose.value = false;
272
+ return;
273
+ }
274
+ if (isHorizontal || !dimensions.value.viewport) return;
275
+ closeOffset.value = Math.min(closeOffset.value, current.scroll);
276
+ const keyboardInset = Math.max(0, current.height - (keyboardOffset != null ? keyboardOffset : 0) * keyboard.value.progress);
277
+ const contentEnd = dimensions.value.content - dimensions.value.viewport;
278
+ const keyboardEndInset = getEndInset(keyboardInset);
279
+ const inset = Math.max(getEndInset(), Math.min(keyboardEndInset, closeOffset.value - contentEnd));
280
+ if (current.height === 0 && (previous == null ? void 0 : previous.height) !== 0) reactNativeReanimated.runOnJS(reportClosingInset)(getEndInset());
281
+ const end = Math.max(0, contentEnd + inset);
282
+ if (current.scroll > end) reactNativeReanimated.scrollTo(scrollRef, 0, end, false);
283
+ },
284
+ [freeze, getEndInset, isHorizontal, keyboardOffset, reportClosingInset]
285
+ );
118
286
  const memoList = React.useCallback(
119
287
  (scrollProps) => {
120
288
  return /* @__PURE__ */ React__namespace.createElement(
@@ -127,7 +295,17 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
127
295
  freeze,
128
296
  keyboardLiftBehavior,
129
297
  offset: keyboardOffset,
130
- onContentInsetChange
298
+ onContentInsetChange,
299
+ onContentSizeChange: (width, height) => {
300
+ var _a2;
301
+ dimensions.value = { ...dimensions.value, content: height };
302
+ (_a2 = scrollProps.onContentSizeChange) == null ? void 0 : _a2.call(scrollProps, width, height);
303
+ },
304
+ onLayout: (event) => {
305
+ var _a2;
306
+ dimensions.value = { ...dimensions.value, viewport: event.nativeEvent.layout.height };
307
+ (_a2 = scrollProps.onLayout) == null ? void 0 : _a2.call(scrollProps, event);
308
+ }
131
309
  }
132
310
  );
133
311
  },
@@ -135,6 +313,7 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
135
313
  applyWorkaroundForContentInsetHitTestBug,
136
314
  blankSpace,
137
315
  contentInsetEndAdjustment,
316
+ dimensions,
138
317
  freeze,
139
318
  keyboardLiftBehavior,
140
319
  keyboardOffset,
@@ -148,6 +327,7 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
148
327
  anchoredEndSpace: anchoredEndSpaceWithBlankSpace,
149
328
  anchoredEndSpaceOwnerInternal: "scroll",
150
329
  ref: combinedRef,
330
+ refScrollView: combinedScrollRef,
151
331
  renderScrollComponent: memoList,
152
332
  ...rest
153
333
  }
package/keyboard.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react';
2
- import { useRef, useEffect, useMemo, useCallback, useLayoutEffect } from 'react';
3
- import { KeyboardChatScrollView, KeyboardController } from 'react-native-keyboard-controller';
4
- import { useSharedValue } from 'react-native-reanimated';
2
+ import { useRef, useCallback, useEffect, useMemo, useLayoutEffect } from 'react';
3
+ import { Platform } from 'react-native';
4
+ import { KeyboardChatScrollView, KeyboardController, useKeyboardHandler } from 'react-native-keyboard-controller';
5
+ import { useSharedValue, useAnimatedRef, useScrollViewOffset, useAnimatedReaction, runOnJS, scrollTo, makeMutable, runOnUI } from 'react-native-reanimated';
5
6
  import { internal } from '@legendapp/list/react-native';
6
7
  import { AnimatedLegendList } from '@legendapp/list/reanimated';
7
8
 
@@ -38,19 +39,61 @@ function useKeyboardChatComposerInset(_listRef, composerRef, initialHeight = 0)
38
39
  );
39
40
  return { contentInsetEndAdjustment, onComposerLayout };
40
41
  }
42
+ var DISMISS_TIMEOUT_MS = 2e3;
43
+ function dismissKeyboard() {
44
+ let timer;
45
+ const timeout = new Promise((resolve) => {
46
+ timer = setTimeout(resolve, DISMISS_TIMEOUT_MS);
47
+ });
48
+ return Promise.race([KeyboardController.dismiss(), timeout]).catch(() => {
49
+ }).finally(() => clearTimeout(timer));
50
+ }
51
+ var endScrollFreezes = /* @__PURE__ */ new WeakMap();
52
+ var keyboardCloses = /* @__PURE__ */ new WeakMap();
53
+ function getEndScrollFreeze(freeze) {
54
+ let owned = endScrollFreezes.get(freeze);
55
+ if (!owned) {
56
+ owned = makeMutable(false);
57
+ endScrollFreezes.set(freeze, owned);
58
+ }
59
+ return owned;
60
+ }
61
+ function setFreeze(freeze, value, onSet, animated = false) {
62
+ const owned = getEndScrollFreeze(freeze);
63
+ runOnUI(() => {
64
+ "worklet";
65
+ owned.value = value ? animated ? "animated" : "immediate" : false;
66
+ freeze.value = value;
67
+ if (onSet) runOnJS(onSet)();
68
+ })();
69
+ }
41
70
  function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }) {
42
71
  const internalFreeze = useSharedValue(false);
43
72
  const freeze = freezeProp != null ? freezeProp : internalFreeze;
73
+ const latestRequest = useRef(0);
74
+ const closing = useRef(void 0);
75
+ const preparedClose = useRef(false);
44
76
  const scrollMessageToEnd = useCallback(
45
77
  async ({ animated, closeKeyboard }) => {
46
- const listRefCurrent = listRef.current;
47
- if (listRefCurrent) {
48
- freeze.set(true);
49
- const dismissPromise = closeKeyboard && KeyboardController.dismiss();
50
- const scrollPromise = listRefCurrent.scrollToEnd({ animated });
51
- await Promise.all([scrollPromise, dismissPromise]);
52
- freeze.set(false);
78
+ var _a;
79
+ const list = listRef.current;
80
+ if (!list) return;
81
+ if (closeKeyboard && ((_a = keyboardCloses.get(freeze)) == null ? void 0 : _a.prepare())) preparedClose.current = true;
82
+ const scrollPromise = list.scrollToEnd({ animated });
83
+ const request = ++latestRequest.current;
84
+ const frozen = new Promise((resolve) => setFreeze(freeze, true, resolve, preparedClose.current));
85
+ if (closeKeyboard && !closing.current) {
86
+ closing.current = frozen.then(dismissKeyboard).finally(() => {
87
+ closing.current = void 0;
88
+ });
53
89
  }
90
+ await Promise.all([scrollPromise, closing.current]).finally(() => {
91
+ var _a2;
92
+ if (request === latestRequest.current) {
93
+ preparedClose.current = false;
94
+ setFreeze(freeze, false, (_a2 = keyboardCloses.get(freeze)) == null ? void 0 : _a2.restore);
95
+ }
96
+ });
54
97
  },
55
98
  [freeze, listRef]
56
99
  );
@@ -60,6 +103,7 @@ function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }) {
60
103
  };
61
104
  }
62
105
  var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(props, forwardedRef) {
106
+ var _a, _b;
63
107
  const {
64
108
  anchoredEndSpace,
65
109
  applyWorkaroundForContentInsetHitTestBug,
@@ -67,11 +111,61 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
67
111
  freeze,
68
112
  keyboardLiftBehavior,
69
113
  keyboardOffset,
114
+ refScrollView,
70
115
  ...rest
71
116
  } = props;
72
117
  const refLegendList = useRef(null);
73
118
  const combinedRef = useCombinedRef(forwardedRef, refLegendList);
119
+ const staticContentInsetRef = useRef(rest.contentInset);
120
+ staticContentInsetRef.current = rest.contentInset;
74
121
  const blankSpace = useSharedValue(0);
122
+ const scrollRef = useAnimatedRef();
123
+ const combinedScrollRef = useCombinedRef(scrollRef, refScrollView);
124
+ const scrollOffset = useScrollViewOffset(scrollRef);
125
+ const dimensions = useSharedValue({ content: 0, viewport: 0 });
126
+ const frozenClose = useSharedValue(false);
127
+ const closeOffset = useSharedValue(0);
128
+ const endScrollFreeze = typeof freeze === "object" ? getEndScrollFreeze(freeze) : void 0;
129
+ const reportedInsets = useRef(void 0);
130
+ const initialKeyboardHeight = KeyboardController.state().height;
131
+ const keyboard = useSharedValue({ height: initialKeyboardHeight, progress: initialKeyboardHeight > 0 ? 1 : 0 });
132
+ const keyboardTarget = useSharedValue(initialKeyboardHeight);
133
+ const isHorizontal = !!rest.horizontal;
134
+ const reportViewabilityInset = useCallback((inset) => {
135
+ var _a2, _b2;
136
+ (_b2 = (_a2 = refLegendList.current) == null ? void 0 : _a2.reportViewabilityInsetEndInternal) == null ? void 0 : _b2.call(_a2, inset);
137
+ }, []);
138
+ const onKeyboardMove = (event) => {
139
+ "worklet";
140
+ keyboard.value = { height: event.height, progress: event.progress };
141
+ };
142
+ useKeyboardHandler(
143
+ {
144
+ onEnd: onKeyboardMove,
145
+ onInteractive: onKeyboardMove,
146
+ onMove: onKeyboardMove,
147
+ onStart: (event) => {
148
+ "worklet";
149
+ keyboardTarget.value = event.height;
150
+ if (event.height === 0 && !frozenClose.value) closeOffset.value = scrollOffset.value;
151
+ frozenClose.value = event.height === 0 && !!(endScrollFreeze == null ? void 0 : endScrollFreeze.value);
152
+ }
153
+ },
154
+ [endScrollFreeze]
155
+ );
156
+ useAnimatedReaction(
157
+ // Blank space extends the scroll range but does not obscure content.
158
+ () => {
159
+ var _a2;
160
+ return isHorizontal ? 0 : Math.max(0, keyboard.value.height - (keyboardOffset != null ? keyboardOffset : 0) * keyboard.value.progress) + Math.max(0, (_a2 = contentInsetEndAdjustment == null ? void 0 : contentInsetEndAdjustment.value) != null ? _a2 : 0);
161
+ },
162
+ (current, previous) => {
163
+ if (current !== previous) {
164
+ runOnJS(reportViewabilityInset)(current);
165
+ }
166
+ },
167
+ [contentInsetEndAdjustment, isHorizontal, keyboard, keyboardOffset, reportViewabilityInset]
168
+ );
75
169
  useEffect(() => {
76
170
  if (!anchoredEndSpace) {
77
171
  blankSpace.value = 0;
@@ -84,16 +178,90 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
84
178
  return {
85
179
  ...anchoredEndSpace,
86
180
  onSizeChanged: (size) => {
87
- var _a;
181
+ var _a2;
88
182
  blankSpace.value = size;
89
- (_a = anchoredEndSpace.onSizeChanged) == null ? void 0 : _a.call(anchoredEndSpace, size);
183
+ (_a2 = anchoredEndSpace.onSizeChanged) == null ? void 0 : _a2.call(anchoredEndSpace, size);
90
184
  }
91
185
  };
92
186
  }, [anchoredEndSpace, blankSpace]);
93
- const onContentInsetChange = useCallback((insets) => {
94
- var _a;
95
- (_a = refLegendList.current) == null ? void 0 : _a.reportContentInset(insets);
187
+ const staticBottomInset = Platform.OS === "ios" ? (_b = (_a = rest.contentInset) == null ? void 0 : _a.bottom) != null ? _b : 0 : 0;
188
+ const getEndInset = useCallback(
189
+ (keyboardInset = 0) => {
190
+ "worklet";
191
+ var _a2;
192
+ const padding = keyboardInset + ((_a2 = contentInsetEndAdjustment == null ? void 0 : contentInsetEndAdjustment.value) != null ? _a2 : 0);
193
+ return staticBottomInset + Math.min(dimensions.value.viewport, Math.max(blankSpace.value, padding));
194
+ },
195
+ [blankSpace, contentInsetEndAdjustment, dimensions, staticBottomInset]
196
+ );
197
+ const onContentInsetChange = useCallback(
198
+ (insets) => {
199
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
200
+ const staticInset = staticContentInsetRef.current;
201
+ if (Platform.OS !== "ios" && staticInset) {
202
+ insets = {
203
+ bottom: Math.max(0, ((_a2 = insets.bottom) != null ? _a2 : 0) - ((_b2 = staticInset.bottom) != null ? _b2 : 0)),
204
+ left: Math.max(0, ((_c = insets.left) != null ? _c : 0) - ((_d = staticInset.left) != null ? _d : 0)),
205
+ right: Math.max(0, ((_e = insets.right) != null ? _e : 0) - ((_f = staticInset.right) != null ? _f : 0)),
206
+ top: Math.max(0, ((_g = insets.top) != null ? _g : 0) - ((_h = staticInset.top) != null ? _h : 0))
207
+ };
208
+ }
209
+ reportedInsets.current = insets;
210
+ const list = refLegendList.current;
211
+ if ((endScrollFreeze == null ? void 0 : endScrollFreeze.value) === "animated") {
212
+ (_i = list == null ? void 0 : list.reportContentInsetForScrollInternal) == null ? void 0 : _i.call(list, { ...insets, bottom: getEndInset() });
213
+ } else if (keyboardTarget.value > 0 && (list == null ? void 0 : list.reportContentInsetForScrollInternal)) {
214
+ list.reportContentInsetForScrollInternal(insets);
215
+ } else {
216
+ list == null ? void 0 : list.reportContentInset(insets);
217
+ }
218
+ },
219
+ [endScrollFreeze, getEndInset, keyboardTarget]
220
+ );
221
+ const reportClosingInset = useCallback((bottom) => {
222
+ var _a2;
223
+ (_a2 = refLegendList.current) == null ? void 0 : _a2.reportContentInset({ ...reportedInsets.current, bottom });
96
224
  }, []);
225
+ useLayoutEffect(() => {
226
+ if (typeof freeze !== "object") return;
227
+ keyboardCloses.set(freeze, {
228
+ prepare: () => {
229
+ var _a2;
230
+ const report = (_a2 = refLegendList.current) == null ? void 0 : _a2.reportContentInsetForScrollInternal;
231
+ if (isHorizontal || !dimensions.value.viewport || keyboard.value.height === 0 || !report) return false;
232
+ report({ ...reportedInsets.current, bottom: getEndInset() });
233
+ return true;
234
+ },
235
+ restore: () => {
236
+ var _a2;
237
+ if (keyboard.value.height > 0 && reportedInsets.current) {
238
+ (_a2 = refLegendList.current) == null ? void 0 : _a2.reportContentInset(reportedInsets.current);
239
+ }
240
+ }
241
+ });
242
+ return () => {
243
+ keyboardCloses.delete(freeze);
244
+ };
245
+ }, [dimensions, freeze, getEndInset, isHorizontal, keyboard]);
246
+ useAnimatedReaction(
247
+ () => frozenClose.value && (endScrollFreeze == null ? void 0 : endScrollFreeze.value) === "immediate" && typeof freeze === "object" && freeze.value ? { height: keyboard.value.height, scroll: scrollOffset.value } : null,
248
+ (current, previous) => {
249
+ if (!current) {
250
+ frozenClose.value = false;
251
+ return;
252
+ }
253
+ if (isHorizontal || !dimensions.value.viewport) return;
254
+ closeOffset.value = Math.min(closeOffset.value, current.scroll);
255
+ const keyboardInset = Math.max(0, current.height - (keyboardOffset != null ? keyboardOffset : 0) * keyboard.value.progress);
256
+ const contentEnd = dimensions.value.content - dimensions.value.viewport;
257
+ const keyboardEndInset = getEndInset(keyboardInset);
258
+ const inset = Math.max(getEndInset(), Math.min(keyboardEndInset, closeOffset.value - contentEnd));
259
+ if (current.height === 0 && (previous == null ? void 0 : previous.height) !== 0) runOnJS(reportClosingInset)(getEndInset());
260
+ const end = Math.max(0, contentEnd + inset);
261
+ if (current.scroll > end) scrollTo(scrollRef, 0, end, false);
262
+ },
263
+ [freeze, getEndInset, isHorizontal, keyboardOffset, reportClosingInset]
264
+ );
97
265
  const memoList = useCallback(
98
266
  (scrollProps) => {
99
267
  return /* @__PURE__ */ React.createElement(
@@ -106,7 +274,17 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
106
274
  freeze,
107
275
  keyboardLiftBehavior,
108
276
  offset: keyboardOffset,
109
- onContentInsetChange
277
+ onContentInsetChange,
278
+ onContentSizeChange: (width, height) => {
279
+ var _a2;
280
+ dimensions.value = { ...dimensions.value, content: height };
281
+ (_a2 = scrollProps.onContentSizeChange) == null ? void 0 : _a2.call(scrollProps, width, height);
282
+ },
283
+ onLayout: (event) => {
284
+ var _a2;
285
+ dimensions.value = { ...dimensions.value, viewport: event.nativeEvent.layout.height };
286
+ (_a2 = scrollProps.onLayout) == null ? void 0 : _a2.call(scrollProps, event);
287
+ }
110
288
  }
111
289
  );
112
290
  },
@@ -114,6 +292,7 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
114
292
  applyWorkaroundForContentInsetHitTestBug,
115
293
  blankSpace,
116
294
  contentInsetEndAdjustment,
295
+ dimensions,
117
296
  freeze,
118
297
  keyboardLiftBehavior,
119
298
  keyboardOffset,
@@ -127,6 +306,7 @@ var KeyboardAwareLegendList = typedForwardRef(function KeyboardAwareLegendList2(
127
306
  anchoredEndSpace: anchoredEndSpaceWithBlankSpace,
128
307
  anchoredEndSpaceOwnerInternal: "scroll",
129
308
  ref: combinedRef,
309
+ refScrollView: combinedScrollRef,
130
310
  renderScrollComponent: memoList,
131
311
  ...rest
132
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "3.6.0",
3
+ "version": "3.7.0",
4
4
  "description": "Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,