@legendapp/list 3.0.0-beta.51 → 3.0.0-beta.52

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.js CHANGED
@@ -5326,13 +5326,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5326
5326
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5327
5327
  }
5328
5328
  }
5329
- if (previousSize === nextSize) {
5330
- return nextSize;
5331
- }
5332
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5333
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5334
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5335
- updateScroll(ctx, state.scroll, true);
5329
+ if (previousSize !== nextSize) {
5330
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5331
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5332
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5333
+ updateScroll(ctx, state.scroll, true);
5334
+ }
5336
5335
  }
5337
5336
  return nextSize;
5338
5337
  }
@@ -5561,14 +5560,14 @@ function createImperativeHandle(ctx) {
5561
5560
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5562
5561
  let imperativeScrollToken = 0;
5563
5562
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5564
- const runWhenSettled = (token, run) => {
5563
+ const runWhenReady = (token, run, isReady) => {
5565
5564
  const startedAt = Date.now();
5566
5565
  let stableFrames = 0;
5567
5566
  const check = () => {
5568
5567
  if (token !== imperativeScrollToken) {
5569
5568
  return;
5570
5569
  }
5571
- if (isSettlingAfterDataChange()) {
5570
+ if (isSettlingAfterDataChange() || !isReady()) {
5572
5571
  stableFrames = 0;
5573
5572
  } else {
5574
5573
  stableFrames += 1;
@@ -5583,10 +5582,10 @@ function createImperativeHandle(ctx) {
5583
5582
  requestAnimationFrame(check);
5584
5583
  };
5585
5584
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5586
- var _a3;
5585
+ var _a3, _b;
5587
5586
  const token = ++imperativeScrollToken;
5588
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5589
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5587
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5588
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5590
5589
  state.pendingScrollResolve = resolve;
5591
5590
  const runNow = () => {
5592
5591
  if (token !== imperativeScrollToken) {
@@ -5600,11 +5599,10 @@ function createImperativeHandle(ctx) {
5600
5599
  resolve();
5601
5600
  }
5602
5601
  };
5603
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5604
- if (isSettlingAfterDataChange()) {
5605
- runWhenSettled(token, execute);
5602
+ if (isSettlingAfterDataChange() || !isReady()) {
5603
+ runWhenReady(token, runNow, isReady);
5606
5604
  } else {
5607
- execute();
5605
+ runNow();
5608
5606
  }
5609
5607
  });
5610
5608
  const scrollIndexIntoView = (options) => {
@@ -5715,15 +5713,24 @@ function createImperativeHandle(ctx) {
5715
5713
  }
5716
5714
  return false;
5717
5715
  }),
5718
- scrollToIndex: (params) => runScrollWithPromise(
5719
- () => {
5716
+ scrollToIndex: (params) => {
5717
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5718
+ const options = shouldWaitForOutOfRangeTarget ? {
5719
+ isReady: () => {
5720
+ var _a3;
5721
+ const props = state.props;
5722
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5723
+ const lastIndex = props.data.length - 1;
5724
+ const isInRange = params.index < props.data.length;
5725
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5726
+ return isInRange && !shouldWaitForAnchorSize;
5727
+ }
5728
+ } : void 0;
5729
+ return runScrollWithPromise(() => {
5720
5730
  scrollToIndex(ctx, params);
5721
5731
  return true;
5722
- },
5723
- {
5724
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5725
- }
5726
- ),
5732
+ }, options);
5733
+ },
5727
5734
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5728
5735
  const data = state.props.data;
5729
5736
  const index = data.indexOf(item);
package/index.mjs CHANGED
@@ -5305,13 +5305,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5305
5305
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5306
5306
  }
5307
5307
  }
5308
- if (previousSize === nextSize) {
5309
- return nextSize;
5310
- }
5311
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5312
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5313
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5314
- updateScroll(ctx, state.scroll, true);
5308
+ if (previousSize !== nextSize) {
5309
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5310
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5311
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5312
+ updateScroll(ctx, state.scroll, true);
5313
+ }
5315
5314
  }
5316
5315
  return nextSize;
5317
5316
  }
@@ -5540,14 +5539,14 @@ function createImperativeHandle(ctx) {
5540
5539
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5541
5540
  let imperativeScrollToken = 0;
5542
5541
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5543
- const runWhenSettled = (token, run) => {
5542
+ const runWhenReady = (token, run, isReady) => {
5544
5543
  const startedAt = Date.now();
5545
5544
  let stableFrames = 0;
5546
5545
  const check = () => {
5547
5546
  if (token !== imperativeScrollToken) {
5548
5547
  return;
5549
5548
  }
5550
- if (isSettlingAfterDataChange()) {
5549
+ if (isSettlingAfterDataChange() || !isReady()) {
5551
5550
  stableFrames = 0;
5552
5551
  } else {
5553
5552
  stableFrames += 1;
@@ -5562,10 +5561,10 @@ function createImperativeHandle(ctx) {
5562
5561
  requestAnimationFrame(check);
5563
5562
  };
5564
5563
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5565
- var _a3;
5564
+ var _a3, _b;
5566
5565
  const token = ++imperativeScrollToken;
5567
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5568
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5566
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5567
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5569
5568
  state.pendingScrollResolve = resolve;
5570
5569
  const runNow = () => {
5571
5570
  if (token !== imperativeScrollToken) {
@@ -5579,11 +5578,10 @@ function createImperativeHandle(ctx) {
5579
5578
  resolve();
5580
5579
  }
5581
5580
  };
5582
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5583
- if (isSettlingAfterDataChange()) {
5584
- runWhenSettled(token, execute);
5581
+ if (isSettlingAfterDataChange() || !isReady()) {
5582
+ runWhenReady(token, runNow, isReady);
5585
5583
  } else {
5586
- execute();
5584
+ runNow();
5587
5585
  }
5588
5586
  });
5589
5587
  const scrollIndexIntoView = (options) => {
@@ -5694,15 +5692,24 @@ function createImperativeHandle(ctx) {
5694
5692
  }
5695
5693
  return false;
5696
5694
  }),
5697
- scrollToIndex: (params) => runScrollWithPromise(
5698
- () => {
5695
+ scrollToIndex: (params) => {
5696
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5697
+ const options = shouldWaitForOutOfRangeTarget ? {
5698
+ isReady: () => {
5699
+ var _a3;
5700
+ const props = state.props;
5701
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5702
+ const lastIndex = props.data.length - 1;
5703
+ const isInRange = params.index < props.data.length;
5704
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5705
+ return isInRange && !shouldWaitForAnchorSize;
5706
+ }
5707
+ } : void 0;
5708
+ return runScrollWithPromise(() => {
5699
5709
  scrollToIndex(ctx, params);
5700
5710
  return true;
5701
- },
5702
- {
5703
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5704
- }
5705
- ),
5711
+ }, options);
5712
+ },
5706
5713
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5707
5714
  const data = state.props.data;
5708
5715
  const index = data.indexOf(item);
package/index.native.js CHANGED
@@ -4796,13 +4796,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4796
4796
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4797
4797
  }
4798
4798
  }
4799
- if (previousSize === nextSize) {
4800
- return nextSize;
4801
- }
4802
- set$(ctx, "anchoredEndSpaceSize", nextSize);
4803
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4804
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4805
- updateScroll(ctx, state.scroll, true);
4799
+ if (previousSize !== nextSize) {
4800
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4801
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4802
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4803
+ updateScroll(ctx, state.scroll, true);
4804
+ }
4806
4805
  }
4807
4806
  return nextSize;
4808
4807
  }
@@ -5046,14 +5045,14 @@ function createImperativeHandle(ctx) {
5046
5045
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5047
5046
  let imperativeScrollToken = 0;
5048
5047
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5049
- const runWhenSettled = (token, run) => {
5048
+ const runWhenReady = (token, run, isReady) => {
5050
5049
  const startedAt = Date.now();
5051
5050
  let stableFrames = 0;
5052
5051
  const check = () => {
5053
5052
  if (token !== imperativeScrollToken) {
5054
5053
  return;
5055
5054
  }
5056
- if (isSettlingAfterDataChange()) {
5055
+ if (isSettlingAfterDataChange() || !isReady()) {
5057
5056
  stableFrames = 0;
5058
5057
  } else {
5059
5058
  stableFrames += 1;
@@ -5068,10 +5067,10 @@ function createImperativeHandle(ctx) {
5068
5067
  requestAnimationFrame(check);
5069
5068
  };
5070
5069
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5071
- var _a3;
5070
+ var _a3, _b;
5072
5071
  const token = ++imperativeScrollToken;
5073
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5074
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5072
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5073
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5075
5074
  state.pendingScrollResolve = resolve;
5076
5075
  const runNow = () => {
5077
5076
  if (token !== imperativeScrollToken) {
@@ -5085,11 +5084,10 @@ function createImperativeHandle(ctx) {
5085
5084
  resolve();
5086
5085
  }
5087
5086
  };
5088
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5089
- if (isSettlingAfterDataChange()) {
5090
- runWhenSettled(token, execute);
5087
+ if (isSettlingAfterDataChange() || !isReady()) {
5088
+ runWhenReady(token, runNow, isReady);
5091
5089
  } else {
5092
- execute();
5090
+ runNow();
5093
5091
  }
5094
5092
  });
5095
5093
  const scrollIndexIntoView = (options) => {
@@ -5200,15 +5198,24 @@ function createImperativeHandle(ctx) {
5200
5198
  }
5201
5199
  return false;
5202
5200
  }),
5203
- scrollToIndex: (params) => runScrollWithPromise(
5204
- () => {
5201
+ scrollToIndex: (params) => {
5202
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5203
+ const options = shouldWaitForOutOfRangeTarget ? {
5204
+ isReady: () => {
5205
+ var _a3;
5206
+ const props = state.props;
5207
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5208
+ const lastIndex = props.data.length - 1;
5209
+ const isInRange = params.index < props.data.length;
5210
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5211
+ return isInRange && !shouldWaitForAnchorSize;
5212
+ }
5213
+ } : void 0;
5214
+ return runScrollWithPromise(() => {
5205
5215
  scrollToIndex(ctx, params);
5206
5216
  return true;
5207
- },
5208
- {
5209
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5210
- }
5211
- ),
5217
+ }, options);
5218
+ },
5212
5219
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5213
5220
  const data = state.props.data;
5214
5221
  const index = data.indexOf(item);
package/index.native.mjs CHANGED
@@ -4775,13 +4775,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4775
4775
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4776
4776
  }
4777
4777
  }
4778
- if (previousSize === nextSize) {
4779
- return nextSize;
4780
- }
4781
- set$(ctx, "anchoredEndSpaceSize", nextSize);
4782
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4783
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4784
- updateScroll(ctx, state.scroll, true);
4778
+ if (previousSize !== nextSize) {
4779
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4780
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4781
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4782
+ updateScroll(ctx, state.scroll, true);
4783
+ }
4785
4784
  }
4786
4785
  return nextSize;
4787
4786
  }
@@ -5025,14 +5024,14 @@ function createImperativeHandle(ctx) {
5025
5024
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5026
5025
  let imperativeScrollToken = 0;
5027
5026
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5028
- const runWhenSettled = (token, run) => {
5027
+ const runWhenReady = (token, run, isReady) => {
5029
5028
  const startedAt = Date.now();
5030
5029
  let stableFrames = 0;
5031
5030
  const check = () => {
5032
5031
  if (token !== imperativeScrollToken) {
5033
5032
  return;
5034
5033
  }
5035
- if (isSettlingAfterDataChange()) {
5034
+ if (isSettlingAfterDataChange() || !isReady()) {
5036
5035
  stableFrames = 0;
5037
5036
  } else {
5038
5037
  stableFrames += 1;
@@ -5047,10 +5046,10 @@ function createImperativeHandle(ctx) {
5047
5046
  requestAnimationFrame(check);
5048
5047
  };
5049
5048
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5050
- var _a3;
5049
+ var _a3, _b;
5051
5050
  const token = ++imperativeScrollToken;
5052
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5053
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5051
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5052
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5054
5053
  state.pendingScrollResolve = resolve;
5055
5054
  const runNow = () => {
5056
5055
  if (token !== imperativeScrollToken) {
@@ -5064,11 +5063,10 @@ function createImperativeHandle(ctx) {
5064
5063
  resolve();
5065
5064
  }
5066
5065
  };
5067
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5068
- if (isSettlingAfterDataChange()) {
5069
- runWhenSettled(token, execute);
5066
+ if (isSettlingAfterDataChange() || !isReady()) {
5067
+ runWhenReady(token, runNow, isReady);
5070
5068
  } else {
5071
- execute();
5069
+ runNow();
5072
5070
  }
5073
5071
  });
5074
5072
  const scrollIndexIntoView = (options) => {
@@ -5179,15 +5177,24 @@ function createImperativeHandle(ctx) {
5179
5177
  }
5180
5178
  return false;
5181
5179
  }),
5182
- scrollToIndex: (params) => runScrollWithPromise(
5183
- () => {
5180
+ scrollToIndex: (params) => {
5181
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5182
+ const options = shouldWaitForOutOfRangeTarget ? {
5183
+ isReady: () => {
5184
+ var _a3;
5185
+ const props = state.props;
5186
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5187
+ const lastIndex = props.data.length - 1;
5188
+ const isInRange = params.index < props.data.length;
5189
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5190
+ return isInRange && !shouldWaitForAnchorSize;
5191
+ }
5192
+ } : void 0;
5193
+ return runScrollWithPromise(() => {
5184
5194
  scrollToIndex(ctx, params);
5185
5195
  return true;
5186
- },
5187
- {
5188
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5189
- }
5190
- ),
5196
+ }, options);
5197
+ },
5191
5198
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5192
5199
  const data = state.props.data;
5193
5200
  const index = data.indexOf(item);
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ScrollViewComponent, ScrollResponderMixin, Insets as Insets$1, ScrollViewProps } from 'react-native';
3
3
  import { KeyboardChatScrollViewProps } from 'react-native-keyboard-controller';
4
+ import { SharedValue } from 'react-native-reanimated';
4
5
  import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
5
6
 
6
7
  interface MaintainVisibleContentPositionNormalized<ItemT = any> {
@@ -221,8 +222,27 @@ type LegendListRef = Omit<LegendListRef$1, "getNativeScrollRef" | "getScrollResp
221
222
  };
222
223
 
223
224
  type KeyboardChatScrollViewPropsUnique = Omit<KeyboardChatScrollViewProps, keyof ScrollViewProps | "inverted" | "ScrollViewComponent" | "blankSpace" | "onContentInsetChange">;
225
+ type ScrollMessageToEndOptions = {
226
+ animated: boolean;
227
+ closeKeyboard: boolean;
228
+ };
229
+ type KeyboardScrollToEndListRef = {
230
+ current: {
231
+ scrollToEnd(params?: {
232
+ animated?: boolean;
233
+ }): Promise<void>;
234
+ } | null;
235
+ };
236
+ type UseKeyboardScrollToEndOptions = {
237
+ freeze?: SharedValue<boolean>;
238
+ listRef: KeyboardScrollToEndListRef;
239
+ };
240
+ declare function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }: UseKeyboardScrollToEndOptions): {
241
+ freeze: SharedValue<boolean>;
242
+ scrollMessageToEnd: ({ animated, closeKeyboard }: ScrollMessageToEndOptions) => Promise<void>;
243
+ };
224
244
  declare const KeyboardChatLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "anchoredEndSpace" | "renderScrollComponent"> & KeyboardChatScrollViewPropsUnique & {
225
245
  anchoredEndSpace?: AnchoredEndSpaceConfig;
226
246
  } & React.RefAttributes<LegendListRef>) => React.ReactElement | null;
227
247
 
228
- export { KeyboardChatLegendList };
248
+ export { KeyboardChatLegendList, useKeyboardScrollToEnd };
package/keyboard-chat.js CHANGED
@@ -28,6 +28,27 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
28
 
29
29
  // src/integrations/keyboard-chat.tsx
30
30
  var { typedForwardRef, useCombinedRef } = reactNative.internal;
31
+ function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }) {
32
+ const internalFreeze = reactNativeReanimated.useSharedValue(false);
33
+ const freeze = freezeProp != null ? freezeProp : internalFreeze;
34
+ const scrollMessageToEnd = React.useCallback(
35
+ async ({ animated, closeKeyboard }) => {
36
+ const listRefCurrent = listRef.current;
37
+ if (listRefCurrent) {
38
+ freeze.set(true);
39
+ const dismissPromise = closeKeyboard && reactNativeKeyboardController.KeyboardController.dismiss();
40
+ const scrollPromise = listRefCurrent.scrollToEnd({ animated });
41
+ await Promise.all([scrollPromise, dismissPromise]);
42
+ freeze.set(false);
43
+ }
44
+ },
45
+ [freeze, listRef]
46
+ );
47
+ return {
48
+ freeze,
49
+ scrollMessageToEnd
50
+ };
51
+ }
31
52
  var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(props, forwardedRef) {
32
53
  const {
33
54
  anchoredEndSpace,
@@ -73,7 +94,6 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
73
94
  applyWorkaroundForContentInsetHitTestBug,
74
95
  blankSpace,
75
96
  extraContentPadding,
76
- freeze,
77
97
  keyboardLiftBehavior,
78
98
  offset,
79
99
  onContentInsetChange
@@ -103,3 +123,4 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
103
123
  });
104
124
 
105
125
  exports.KeyboardChatLegendList = KeyboardChatLegendList;
126
+ exports.useKeyboardScrollToEnd = useKeyboardScrollToEnd;
package/keyboard-chat.mjs CHANGED
@@ -1,12 +1,33 @@
1
1
  import * as React from 'react';
2
2
  import { useRef, useEffect, useMemo, useCallback } from 'react';
3
- import { KeyboardChatScrollView } from 'react-native-keyboard-controller';
3
+ import { KeyboardChatScrollView, KeyboardController } from 'react-native-keyboard-controller';
4
4
  import { useSharedValue } from 'react-native-reanimated';
5
5
  import { internal } from '@legendapp/list/react-native';
6
6
  import { AnimatedLegendList } from '@legendapp/list/reanimated';
7
7
 
8
8
  // src/integrations/keyboard-chat.tsx
9
9
  var { typedForwardRef, useCombinedRef } = internal;
10
+ function useKeyboardScrollToEnd({ freeze: freezeProp, listRef }) {
11
+ const internalFreeze = useSharedValue(false);
12
+ const freeze = freezeProp != null ? freezeProp : internalFreeze;
13
+ const scrollMessageToEnd = useCallback(
14
+ async ({ animated, closeKeyboard }) => {
15
+ const listRefCurrent = listRef.current;
16
+ if (listRefCurrent) {
17
+ freeze.set(true);
18
+ const dismissPromise = closeKeyboard && KeyboardController.dismiss();
19
+ const scrollPromise = listRefCurrent.scrollToEnd({ animated });
20
+ await Promise.all([scrollPromise, dismissPromise]);
21
+ freeze.set(false);
22
+ }
23
+ },
24
+ [freeze, listRef]
25
+ );
26
+ return {
27
+ freeze,
28
+ scrollMessageToEnd
29
+ };
30
+ }
10
31
  var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(props, forwardedRef) {
11
32
  const {
12
33
  anchoredEndSpace,
@@ -52,7 +73,6 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
52
73
  applyWorkaroundForContentInsetHitTestBug,
53
74
  blankSpace,
54
75
  extraContentPadding,
55
- freeze,
56
76
  keyboardLiftBehavior,
57
77
  offset,
58
78
  onContentInsetChange
@@ -81,4 +101,4 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
81
101
  );
82
102
  });
83
103
 
84
- export { KeyboardChatLegendList };
104
+ export { KeyboardChatLegendList, useKeyboardScrollToEnd };
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ScrollViewComponent, ScrollResponderMixin, Insets as Insets$1, ScrollViewProps } from 'react-native';
3
3
  import { KeyboardChatScrollViewProps } from 'react-native-keyboard-controller';
4
+ export { useKeyboardScrollToEnd } from '@legendapp/list/keyboard-chat';
4
5
  import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
5
6
 
6
7
  interface MaintainVisibleContentPositionNormalized<ItemT = any> {
package/keyboard-test.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var React = require('react');
4
4
  var reactNativeKeyboardController = require('react-native-keyboard-controller');
5
+ var keyboardChat = require('@legendapp/list/keyboard-chat');
5
6
  var reactNative = require('@legendapp/list/react-native');
6
7
  var reanimated = require('@legendapp/list/reanimated');
7
8
 
@@ -49,4 +50,8 @@ var KeyboardAvoidingLegendList = typedForwardRef(function KeyboardAvoidingLegend
49
50
  return /* @__PURE__ */ React__namespace.createElement(reanimated.AnimatedLegendList, { ref: combinedRef, renderScrollComponent: memoList, ...rest });
50
51
  });
51
52
 
53
+ Object.defineProperty(exports, "useKeyboardScrollToEnd", {
54
+ enumerable: true,
55
+ get: function () { return keyboardChat.useKeyboardScrollToEnd; }
56
+ });
52
57
  exports.KeyboardAvoidingLegendList = KeyboardAvoidingLegendList;
package/keyboard-test.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useRef, useCallback } from 'react';
3
3
  import { KeyboardChatScrollView } from 'react-native-keyboard-controller';
4
+ export { useKeyboardScrollToEnd } from '@legendapp/list/keyboard-chat';
4
5
  import { internal } from '@legendapp/list/react-native';
5
6
  import { AnimatedLegendList } from '@legendapp/list/reanimated';
6
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "3.0.0-beta.51",
3
+ "version": "3.0.0-beta.52",
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,
package/react-native.js CHANGED
@@ -4796,13 +4796,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4796
4796
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4797
4797
  }
4798
4798
  }
4799
- if (previousSize === nextSize) {
4800
- return nextSize;
4801
- }
4802
- set$(ctx, "anchoredEndSpaceSize", nextSize);
4803
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4804
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4805
- updateScroll(ctx, state.scroll, true);
4799
+ if (previousSize !== nextSize) {
4800
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4801
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4802
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4803
+ updateScroll(ctx, state.scroll, true);
4804
+ }
4806
4805
  }
4807
4806
  return nextSize;
4808
4807
  }
@@ -5046,14 +5045,14 @@ function createImperativeHandle(ctx) {
5046
5045
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5047
5046
  let imperativeScrollToken = 0;
5048
5047
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5049
- const runWhenSettled = (token, run) => {
5048
+ const runWhenReady = (token, run, isReady) => {
5050
5049
  const startedAt = Date.now();
5051
5050
  let stableFrames = 0;
5052
5051
  const check = () => {
5053
5052
  if (token !== imperativeScrollToken) {
5054
5053
  return;
5055
5054
  }
5056
- if (isSettlingAfterDataChange()) {
5055
+ if (isSettlingAfterDataChange() || !isReady()) {
5057
5056
  stableFrames = 0;
5058
5057
  } else {
5059
5058
  stableFrames += 1;
@@ -5068,10 +5067,10 @@ function createImperativeHandle(ctx) {
5068
5067
  requestAnimationFrame(check);
5069
5068
  };
5070
5069
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5071
- var _a3;
5070
+ var _a3, _b;
5072
5071
  const token = ++imperativeScrollToken;
5073
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5074
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5072
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5073
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5075
5074
  state.pendingScrollResolve = resolve;
5076
5075
  const runNow = () => {
5077
5076
  if (token !== imperativeScrollToken) {
@@ -5085,11 +5084,10 @@ function createImperativeHandle(ctx) {
5085
5084
  resolve();
5086
5085
  }
5087
5086
  };
5088
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5089
- if (isSettlingAfterDataChange()) {
5090
- runWhenSettled(token, execute);
5087
+ if (isSettlingAfterDataChange() || !isReady()) {
5088
+ runWhenReady(token, runNow, isReady);
5091
5089
  } else {
5092
- execute();
5090
+ runNow();
5093
5091
  }
5094
5092
  });
5095
5093
  const scrollIndexIntoView = (options) => {
@@ -5200,15 +5198,24 @@ function createImperativeHandle(ctx) {
5200
5198
  }
5201
5199
  return false;
5202
5200
  }),
5203
- scrollToIndex: (params) => runScrollWithPromise(
5204
- () => {
5201
+ scrollToIndex: (params) => {
5202
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5203
+ const options = shouldWaitForOutOfRangeTarget ? {
5204
+ isReady: () => {
5205
+ var _a3;
5206
+ const props = state.props;
5207
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5208
+ const lastIndex = props.data.length - 1;
5209
+ const isInRange = params.index < props.data.length;
5210
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5211
+ return isInRange && !shouldWaitForAnchorSize;
5212
+ }
5213
+ } : void 0;
5214
+ return runScrollWithPromise(() => {
5205
5215
  scrollToIndex(ctx, params);
5206
5216
  return true;
5207
- },
5208
- {
5209
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5210
- }
5211
- ),
5217
+ }, options);
5218
+ },
5212
5219
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5213
5220
  const data = state.props.data;
5214
5221
  const index = data.indexOf(item);
package/react-native.mjs CHANGED
@@ -4775,13 +4775,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4775
4775
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4776
4776
  }
4777
4777
  }
4778
- if (previousSize === nextSize) {
4779
- return nextSize;
4780
- }
4781
- set$(ctx, "anchoredEndSpaceSize", nextSize);
4782
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4783
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4784
- updateScroll(ctx, state.scroll, true);
4778
+ if (previousSize !== nextSize) {
4779
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4780
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4781
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4782
+ updateScroll(ctx, state.scroll, true);
4783
+ }
4785
4784
  }
4786
4785
  return nextSize;
4787
4786
  }
@@ -5025,14 +5024,14 @@ function createImperativeHandle(ctx) {
5025
5024
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5026
5025
  let imperativeScrollToken = 0;
5027
5026
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5028
- const runWhenSettled = (token, run) => {
5027
+ const runWhenReady = (token, run, isReady) => {
5029
5028
  const startedAt = Date.now();
5030
5029
  let stableFrames = 0;
5031
5030
  const check = () => {
5032
5031
  if (token !== imperativeScrollToken) {
5033
5032
  return;
5034
5033
  }
5035
- if (isSettlingAfterDataChange()) {
5034
+ if (isSettlingAfterDataChange() || !isReady()) {
5036
5035
  stableFrames = 0;
5037
5036
  } else {
5038
5037
  stableFrames += 1;
@@ -5047,10 +5046,10 @@ function createImperativeHandle(ctx) {
5047
5046
  requestAnimationFrame(check);
5048
5047
  };
5049
5048
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5050
- var _a3;
5049
+ var _a3, _b;
5051
5050
  const token = ++imperativeScrollToken;
5052
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5053
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5051
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5052
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5054
5053
  state.pendingScrollResolve = resolve;
5055
5054
  const runNow = () => {
5056
5055
  if (token !== imperativeScrollToken) {
@@ -5064,11 +5063,10 @@ function createImperativeHandle(ctx) {
5064
5063
  resolve();
5065
5064
  }
5066
5065
  };
5067
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5068
- if (isSettlingAfterDataChange()) {
5069
- runWhenSettled(token, execute);
5066
+ if (isSettlingAfterDataChange() || !isReady()) {
5067
+ runWhenReady(token, runNow, isReady);
5070
5068
  } else {
5071
- execute();
5069
+ runNow();
5072
5070
  }
5073
5071
  });
5074
5072
  const scrollIndexIntoView = (options) => {
@@ -5179,15 +5177,24 @@ function createImperativeHandle(ctx) {
5179
5177
  }
5180
5178
  return false;
5181
5179
  }),
5182
- scrollToIndex: (params) => runScrollWithPromise(
5183
- () => {
5180
+ scrollToIndex: (params) => {
5181
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5182
+ const options = shouldWaitForOutOfRangeTarget ? {
5183
+ isReady: () => {
5184
+ var _a3;
5185
+ const props = state.props;
5186
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5187
+ const lastIndex = props.data.length - 1;
5188
+ const isInRange = params.index < props.data.length;
5189
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5190
+ return isInRange && !shouldWaitForAnchorSize;
5191
+ }
5192
+ } : void 0;
5193
+ return runScrollWithPromise(() => {
5184
5194
  scrollToIndex(ctx, params);
5185
5195
  return true;
5186
- },
5187
- {
5188
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5189
- }
5190
- ),
5196
+ }, options);
5197
+ },
5191
5198
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5192
5199
  const data = state.props.data;
5193
5200
  const index = data.indexOf(item);
@@ -5329,13 +5329,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5329
5329
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5330
5330
  }
5331
5331
  }
5332
- if (previousSize === nextSize) {
5333
- return nextSize;
5334
- }
5335
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5336
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5337
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5338
- updateScroll(ctx, state.scroll, true);
5332
+ if (previousSize !== nextSize) {
5333
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5334
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5335
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5336
+ updateScroll(ctx, state.scroll, true);
5337
+ }
5339
5338
  }
5340
5339
  return nextSize;
5341
5340
  }
@@ -5564,14 +5563,14 @@ function createImperativeHandle(ctx) {
5564
5563
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5565
5564
  let imperativeScrollToken = 0;
5566
5565
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5567
- const runWhenSettled = (token, run) => {
5566
+ const runWhenReady = (token, run, isReady) => {
5568
5567
  const startedAt = Date.now();
5569
5568
  let stableFrames = 0;
5570
5569
  const check = () => {
5571
5570
  if (token !== imperativeScrollToken) {
5572
5571
  return;
5573
5572
  }
5574
- if (isSettlingAfterDataChange()) {
5573
+ if (isSettlingAfterDataChange() || !isReady()) {
5575
5574
  stableFrames = 0;
5576
5575
  } else {
5577
5576
  stableFrames += 1;
@@ -5586,10 +5585,10 @@ function createImperativeHandle(ctx) {
5586
5585
  requestAnimationFrame(check);
5587
5586
  };
5588
5587
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5589
- var _a3;
5588
+ var _a3, _b;
5590
5589
  const token = ++imperativeScrollToken;
5591
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5592
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5590
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5591
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5593
5592
  state.pendingScrollResolve = resolve;
5594
5593
  const runNow = () => {
5595
5594
  if (token !== imperativeScrollToken) {
@@ -5603,11 +5602,10 @@ function createImperativeHandle(ctx) {
5603
5602
  resolve();
5604
5603
  }
5605
5604
  };
5606
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5607
- if (isSettlingAfterDataChange()) {
5608
- runWhenSettled(token, execute);
5605
+ if (isSettlingAfterDataChange() || !isReady()) {
5606
+ runWhenReady(token, runNow, isReady);
5609
5607
  } else {
5610
- execute();
5608
+ runNow();
5611
5609
  }
5612
5610
  });
5613
5611
  const scrollIndexIntoView = (options) => {
@@ -5718,15 +5716,24 @@ function createImperativeHandle(ctx) {
5718
5716
  }
5719
5717
  return false;
5720
5718
  }),
5721
- scrollToIndex: (params) => runScrollWithPromise(
5722
- () => {
5719
+ scrollToIndex: (params) => {
5720
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5721
+ const options = shouldWaitForOutOfRangeTarget ? {
5722
+ isReady: () => {
5723
+ var _a3;
5724
+ const props = state.props;
5725
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5726
+ const lastIndex = props.data.length - 1;
5727
+ const isInRange = params.index < props.data.length;
5728
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5729
+ return isInRange && !shouldWaitForAnchorSize;
5730
+ }
5731
+ } : void 0;
5732
+ return runScrollWithPromise(() => {
5723
5733
  scrollToIndex(ctx, params);
5724
5734
  return true;
5725
- },
5726
- {
5727
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5728
- }
5729
- ),
5735
+ }, options);
5736
+ },
5730
5737
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5731
5738
  const data = state.props.data;
5732
5739
  const index = data.indexOf(item);
@@ -5308,13 +5308,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5308
5308
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5309
5309
  }
5310
5310
  }
5311
- if (previousSize === nextSize) {
5312
- return nextSize;
5313
- }
5314
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5315
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5316
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5317
- updateScroll(ctx, state.scroll, true);
5311
+ if (previousSize !== nextSize) {
5312
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5313
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5314
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5315
+ updateScroll(ctx, state.scroll, true);
5316
+ }
5318
5317
  }
5319
5318
  return nextSize;
5320
5319
  }
@@ -5543,14 +5542,14 @@ function createImperativeHandle(ctx) {
5543
5542
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5544
5543
  let imperativeScrollToken = 0;
5545
5544
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5546
- const runWhenSettled = (token, run) => {
5545
+ const runWhenReady = (token, run, isReady) => {
5547
5546
  const startedAt = Date.now();
5548
5547
  let stableFrames = 0;
5549
5548
  const check = () => {
5550
5549
  if (token !== imperativeScrollToken) {
5551
5550
  return;
5552
5551
  }
5553
- if (isSettlingAfterDataChange()) {
5552
+ if (isSettlingAfterDataChange() || !isReady()) {
5554
5553
  stableFrames = 0;
5555
5554
  } else {
5556
5555
  stableFrames += 1;
@@ -5565,10 +5564,10 @@ function createImperativeHandle(ctx) {
5565
5564
  requestAnimationFrame(check);
5566
5565
  };
5567
5566
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5568
- var _a3;
5567
+ var _a3, _b;
5569
5568
  const token = ++imperativeScrollToken;
5570
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5571
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5569
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5570
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5572
5571
  state.pendingScrollResolve = resolve;
5573
5572
  const runNow = () => {
5574
5573
  if (token !== imperativeScrollToken) {
@@ -5582,11 +5581,10 @@ function createImperativeHandle(ctx) {
5582
5581
  resolve();
5583
5582
  }
5584
5583
  };
5585
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5586
- if (isSettlingAfterDataChange()) {
5587
- runWhenSettled(token, execute);
5584
+ if (isSettlingAfterDataChange() || !isReady()) {
5585
+ runWhenReady(token, runNow, isReady);
5588
5586
  } else {
5589
- execute();
5587
+ runNow();
5590
5588
  }
5591
5589
  });
5592
5590
  const scrollIndexIntoView = (options) => {
@@ -5697,15 +5695,24 @@ function createImperativeHandle(ctx) {
5697
5695
  }
5698
5696
  return false;
5699
5697
  }),
5700
- scrollToIndex: (params) => runScrollWithPromise(
5701
- () => {
5698
+ scrollToIndex: (params) => {
5699
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5700
+ const options = shouldWaitForOutOfRangeTarget ? {
5701
+ isReady: () => {
5702
+ var _a3;
5703
+ const props = state.props;
5704
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5705
+ const lastIndex = props.data.length - 1;
5706
+ const isInRange = params.index < props.data.length;
5707
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5708
+ return isInRange && !shouldWaitForAnchorSize;
5709
+ }
5710
+ } : void 0;
5711
+ return runScrollWithPromise(() => {
5702
5712
  scrollToIndex(ctx, params);
5703
5713
  return true;
5704
- },
5705
- {
5706
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5707
- }
5708
- ),
5714
+ }, options);
5715
+ },
5709
5716
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5710
5717
  const data = state.props.data;
5711
5718
  const index = data.indexOf(item);
package/react.js CHANGED
@@ -5329,13 +5329,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5329
5329
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5330
5330
  }
5331
5331
  }
5332
- if (previousSize === nextSize) {
5333
- return nextSize;
5334
- }
5335
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5336
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5337
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5338
- updateScroll(ctx, state.scroll, true);
5332
+ if (previousSize !== nextSize) {
5333
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5334
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5335
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5336
+ updateScroll(ctx, state.scroll, true);
5337
+ }
5339
5338
  }
5340
5339
  return nextSize;
5341
5340
  }
@@ -5564,14 +5563,14 @@ function createImperativeHandle(ctx) {
5564
5563
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5565
5564
  let imperativeScrollToken = 0;
5566
5565
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5567
- const runWhenSettled = (token, run) => {
5566
+ const runWhenReady = (token, run, isReady) => {
5568
5567
  const startedAt = Date.now();
5569
5568
  let stableFrames = 0;
5570
5569
  const check = () => {
5571
5570
  if (token !== imperativeScrollToken) {
5572
5571
  return;
5573
5572
  }
5574
- if (isSettlingAfterDataChange()) {
5573
+ if (isSettlingAfterDataChange() || !isReady()) {
5575
5574
  stableFrames = 0;
5576
5575
  } else {
5577
5576
  stableFrames += 1;
@@ -5586,10 +5585,10 @@ function createImperativeHandle(ctx) {
5586
5585
  requestAnimationFrame(check);
5587
5586
  };
5588
5587
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5589
- var _a3;
5588
+ var _a3, _b;
5590
5589
  const token = ++imperativeScrollToken;
5591
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5592
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5590
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5591
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5593
5592
  state.pendingScrollResolve = resolve;
5594
5593
  const runNow = () => {
5595
5594
  if (token !== imperativeScrollToken) {
@@ -5603,11 +5602,10 @@ function createImperativeHandle(ctx) {
5603
5602
  resolve();
5604
5603
  }
5605
5604
  };
5606
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5607
- if (isSettlingAfterDataChange()) {
5608
- runWhenSettled(token, execute);
5605
+ if (isSettlingAfterDataChange() || !isReady()) {
5606
+ runWhenReady(token, runNow, isReady);
5609
5607
  } else {
5610
- execute();
5608
+ runNow();
5611
5609
  }
5612
5610
  });
5613
5611
  const scrollIndexIntoView = (options) => {
@@ -5718,15 +5716,24 @@ function createImperativeHandle(ctx) {
5718
5716
  }
5719
5717
  return false;
5720
5718
  }),
5721
- scrollToIndex: (params) => runScrollWithPromise(
5722
- () => {
5719
+ scrollToIndex: (params) => {
5720
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5721
+ const options = shouldWaitForOutOfRangeTarget ? {
5722
+ isReady: () => {
5723
+ var _a3;
5724
+ const props = state.props;
5725
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5726
+ const lastIndex = props.data.length - 1;
5727
+ const isInRange = params.index < props.data.length;
5728
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5729
+ return isInRange && !shouldWaitForAnchorSize;
5730
+ }
5731
+ } : void 0;
5732
+ return runScrollWithPromise(() => {
5723
5733
  scrollToIndex(ctx, params);
5724
5734
  return true;
5725
- },
5726
- {
5727
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5728
- }
5729
- ),
5735
+ }, options);
5736
+ },
5730
5737
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5731
5738
  const data = state.props.data;
5732
5739
  const index = data.indexOf(item);
package/react.mjs CHANGED
@@ -5308,13 +5308,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5308
5308
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5309
5309
  }
5310
5310
  }
5311
- if (previousSize === nextSize) {
5312
- return nextSize;
5313
- }
5314
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5315
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5316
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5317
- updateScroll(ctx, state.scroll, true);
5311
+ if (previousSize !== nextSize) {
5312
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5313
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5314
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5315
+ updateScroll(ctx, state.scroll, true);
5316
+ }
5318
5317
  }
5319
5318
  return nextSize;
5320
5319
  }
@@ -5543,14 +5542,14 @@ function createImperativeHandle(ctx) {
5543
5542
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5544
5543
  let imperativeScrollToken = 0;
5545
5544
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5546
- const runWhenSettled = (token, run) => {
5545
+ const runWhenReady = (token, run, isReady) => {
5547
5546
  const startedAt = Date.now();
5548
5547
  let stableFrames = 0;
5549
5548
  const check = () => {
5550
5549
  if (token !== imperativeScrollToken) {
5551
5550
  return;
5552
5551
  }
5553
- if (isSettlingAfterDataChange()) {
5552
+ if (isSettlingAfterDataChange() || !isReady()) {
5554
5553
  stableFrames = 0;
5555
5554
  } else {
5556
5555
  stableFrames += 1;
@@ -5565,10 +5564,10 @@ function createImperativeHandle(ctx) {
5565
5564
  requestAnimationFrame(check);
5566
5565
  };
5567
5566
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5568
- var _a3;
5567
+ var _a3, _b;
5569
5568
  const token = ++imperativeScrollToken;
5570
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5571
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5569
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5570
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5572
5571
  state.pendingScrollResolve = resolve;
5573
5572
  const runNow = () => {
5574
5573
  if (token !== imperativeScrollToken) {
@@ -5582,11 +5581,10 @@ function createImperativeHandle(ctx) {
5582
5581
  resolve();
5583
5582
  }
5584
5583
  };
5585
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5586
- if (isSettlingAfterDataChange()) {
5587
- runWhenSettled(token, execute);
5584
+ if (isSettlingAfterDataChange() || !isReady()) {
5585
+ runWhenReady(token, runNow, isReady);
5588
5586
  } else {
5589
- execute();
5587
+ runNow();
5590
5588
  }
5591
5589
  });
5592
5590
  const scrollIndexIntoView = (options) => {
@@ -5697,15 +5695,24 @@ function createImperativeHandle(ctx) {
5697
5695
  }
5698
5696
  return false;
5699
5697
  }),
5700
- scrollToIndex: (params) => runScrollWithPromise(
5701
- () => {
5698
+ scrollToIndex: (params) => {
5699
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5700
+ const options = shouldWaitForOutOfRangeTarget ? {
5701
+ isReady: () => {
5702
+ var _a3;
5703
+ const props = state.props;
5704
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5705
+ const lastIndex = props.data.length - 1;
5706
+ const isInRange = params.index < props.data.length;
5707
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5708
+ return isInRange && !shouldWaitForAnchorSize;
5709
+ }
5710
+ } : void 0;
5711
+ return runScrollWithPromise(() => {
5702
5712
  scrollToIndex(ctx, params);
5703
5713
  return true;
5704
- },
5705
- {
5706
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5707
- }
5708
- ),
5714
+ }, options);
5715
+ },
5709
5716
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5710
5717
  const data = state.props.data;
5711
5718
  const index = data.indexOf(item);