@legendapp/list 3.0.0-beta.50 → 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.native.js CHANGED
@@ -4570,12 +4570,14 @@ var flushSync = (fn) => {
4570
4570
  };
4571
4571
 
4572
4572
  // src/core/updateScroll.ts
4573
- function updateScroll(ctx, newScroll, forceUpdate) {
4573
+ function updateScroll(ctx, newScroll, forceUpdate, options) {
4574
4574
  var _a3;
4575
4575
  const state = ctx.state;
4576
4576
  const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
4577
4577
  const prevScroll = state.scroll;
4578
- state.hasScrolled = true;
4578
+ if ((options == null ? void 0 : options.markHasScrolled) !== false) {
4579
+ state.hasScrolled = true;
4580
+ }
4579
4581
  state.lastBatchingAction = Date.now();
4580
4582
  const currentTime = Date.now();
4581
4583
  const adjust = scrollAdjustHandler.getAdjust();
@@ -4794,13 +4796,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4794
4796
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4795
4797
  }
4796
4798
  }
4797
- if (previousSize === nextSize) {
4798
- return nextSize;
4799
- }
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);
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
+ }
4804
4805
  }
4805
4806
  return nextSize;
4806
4807
  }
@@ -5044,14 +5045,14 @@ function createImperativeHandle(ctx) {
5044
5045
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5045
5046
  let imperativeScrollToken = 0;
5046
5047
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5047
- const runWhenSettled = (token, run) => {
5048
+ const runWhenReady = (token, run, isReady) => {
5048
5049
  const startedAt = Date.now();
5049
5050
  let stableFrames = 0;
5050
5051
  const check = () => {
5051
5052
  if (token !== imperativeScrollToken) {
5052
5053
  return;
5053
5054
  }
5054
- if (isSettlingAfterDataChange()) {
5055
+ if (isSettlingAfterDataChange() || !isReady()) {
5055
5056
  stableFrames = 0;
5056
5057
  } else {
5057
5058
  stableFrames += 1;
@@ -5066,10 +5067,10 @@ function createImperativeHandle(ctx) {
5066
5067
  requestAnimationFrame(check);
5067
5068
  };
5068
5069
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5069
- var _a3;
5070
+ var _a3, _b;
5070
5071
  const token = ++imperativeScrollToken;
5071
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5072
- (_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);
5073
5074
  state.pendingScrollResolve = resolve;
5074
5075
  const runNow = () => {
5075
5076
  if (token !== imperativeScrollToken) {
@@ -5083,11 +5084,10 @@ function createImperativeHandle(ctx) {
5083
5084
  resolve();
5084
5085
  }
5085
5086
  };
5086
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5087
- if (isSettlingAfterDataChange()) {
5088
- runWhenSettled(token, execute);
5087
+ if (isSettlingAfterDataChange() || !isReady()) {
5088
+ runWhenReady(token, runNow, isReady);
5089
5089
  } else {
5090
- execute();
5090
+ runNow();
5091
5091
  }
5092
5092
  });
5093
5093
  const scrollIndexIntoView = (options) => {
@@ -5169,7 +5169,7 @@ function createImperativeHandle(ctx) {
5169
5169
  }),
5170
5170
  reportContentInset: (inset) => {
5171
5171
  state.contentInsetOverride = inset != null ? inset : void 0;
5172
- updateScroll(ctx, state.scroll, true);
5172
+ updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5173
5173
  },
5174
5174
  scrollIndexIntoView: (options) => runScrollWithPromise(() => scrollIndexIntoView(options)),
5175
5175
  scrollItemIntoView: ({ item, ...props }) => runScrollWithPromise(() => {
@@ -5198,15 +5198,24 @@ function createImperativeHandle(ctx) {
5198
5198
  }
5199
5199
  return false;
5200
5200
  }),
5201
- scrollToIndex: (params) => runScrollWithPromise(
5202
- () => {
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(() => {
5203
5215
  scrollToIndex(ctx, params);
5204
5216
  return true;
5205
- },
5206
- {
5207
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5208
- }
5209
- ),
5217
+ }, options);
5218
+ },
5210
5219
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5211
5220
  const data = state.props.data;
5212
5221
  const index = data.indexOf(item);
@@ -5238,32 +5247,32 @@ var addIndex = (result, dataLength, index) => {
5238
5247
  result.add(index);
5239
5248
  }
5240
5249
  };
5241
- function getAlwaysRenderIndices(config, data, keyExtractor) {
5250
+ function getAlwaysRenderIndices(config, data, keyExtractor, anchoredEndSpaceAnchorIndex) {
5242
5251
  var _a3, _b;
5243
- if (!config || data.length === 0) {
5252
+ if (data.length === 0) {
5244
5253
  return [];
5245
5254
  }
5246
5255
  const result = /* @__PURE__ */ new Set();
5247
5256
  const dataLength = data.length;
5248
- const topCount = toCount(config.top);
5257
+ const topCount = toCount(config == null ? void 0 : config.top);
5249
5258
  if (topCount > 0) {
5250
5259
  for (let i = 0; i < Math.min(topCount, dataLength); i++) {
5251
5260
  addIndex(result, dataLength, i);
5252
5261
  }
5253
5262
  }
5254
- const bottomCount = toCount(config.bottom);
5263
+ const bottomCount = toCount(config == null ? void 0 : config.bottom);
5255
5264
  if (bottomCount > 0) {
5256
5265
  for (let i = Math.max(0, dataLength - bottomCount); i < dataLength; i++) {
5257
5266
  addIndex(result, dataLength, i);
5258
5267
  }
5259
5268
  }
5260
- if ((_a3 = config.indices) == null ? void 0 : _a3.length) {
5269
+ if ((_a3 = config == null ? void 0 : config.indices) == null ? void 0 : _a3.length) {
5261
5270
  for (const index of config.indices) {
5262
5271
  if (!Number.isFinite(index)) continue;
5263
5272
  addIndex(result, dataLength, Math.floor(index));
5264
5273
  }
5265
5274
  }
5266
- if ((_b = config.keys) == null ? void 0 : _b.length) {
5275
+ if ((_b = config == null ? void 0 : config.keys) == null ? void 0 : _b.length) {
5267
5276
  const keys = new Set(config.keys);
5268
5277
  for (let i = 0; i < dataLength && keys.size > 0; i++) {
5269
5278
  const key = keyExtractor(data[i], i);
@@ -5273,6 +5282,12 @@ function getAlwaysRenderIndices(config, data, keyExtractor) {
5273
5282
  }
5274
5283
  }
5275
5284
  }
5285
+ if (anchoredEndSpaceAnchorIndex !== void 0 && Number.isFinite(anchoredEndSpaceAnchorIndex)) {
5286
+ const anchorIndex = Math.floor(anchoredEndSpaceAnchorIndex);
5287
+ for (let i = anchorIndex >= 0 ? anchorIndex : dataLength; i < dataLength; i++) {
5288
+ addIndex(result, dataLength, i);
5289
+ }
5290
+ }
5276
5291
  const indices = Array.from(result);
5277
5292
  indices.sort(sortAsc);
5278
5293
  return indices;
@@ -5436,7 +5451,7 @@ var LegendList = typedMemo(
5436
5451
  })
5437
5452
  );
5438
5453
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
5439
- var _a3, _b, _c, _d, _e, _f, _g, _h;
5454
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
5440
5455
  const noopOnScroll = React2.useCallback((_event) => {
5441
5456
  }, []);
5442
5457
  if (props.recycleItems === void 0) {
@@ -5565,9 +5580,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5565
5580
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
5566
5581
  const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
5567
5582
  const alwaysRenderIndices = React2.useMemo(() => {
5568
- const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor);
5583
+ const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor, anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
5569
5584
  return { arr: indices, set: new Set(indices) };
5570
5585
  }, [
5586
+ anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
5571
5587
  alwaysRender == null ? void 0 : alwaysRender.top,
5572
5588
  alwaysRender == null ? void 0 : alwaysRender.bottom,
5573
5589
  (_d = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _d.join(","),
@@ -5673,6 +5689,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5673
5689
  const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
5674
5690
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
5675
5691
  const anchoredEndSpaceResolved = Platform.OS === "web" && anchoredEndSpace ? { ...anchoredEndSpace, includeInEndInset: true } : anchoredEndSpace;
5692
+ const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
5676
5693
  state.props = {
5677
5694
  alignItemsAtEnd,
5678
5695
  alwaysRender,
@@ -5787,6 +5804,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5787
5804
  });
5788
5805
  }, [dataProp.length, didDataChangeLocal, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]);
5789
5806
  React2.useLayoutEffect(() => {
5807
+ var _a4;
5808
+ if (didAnchoredEndSpaceAnchorIndexChange) {
5809
+ state.scrollForNextCalculateItemsInView = void 0;
5810
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state);
5811
+ }
5790
5812
  maybeUpdateAnchoredEndSpace(ctx);
5791
5813
  }, [
5792
5814
  ctx,
@@ -5795,6 +5817,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5795
5817
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
5796
5818
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorMaxSize,
5797
5819
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorOffset,
5820
+ didAnchoredEndSpaceAnchorIndexChange,
5798
5821
  numColumnsProp
5799
5822
  ]);
5800
5823
  const onLayoutFooter = React2.useCallback(
@@ -5951,7 +5974,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5951
5974
  onScroll: onScrollHandler,
5952
5975
  recycleItems,
5953
5976
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControlElement, {
5954
- progressViewOffset: ((_g = refreshControlElement.props.progressViewOffset) != null ? _g : 0) + stylePaddingTopState
5977
+ progressViewOffset: ((_h = refreshControlElement.props.progressViewOffset) != null ? _h : 0) + stylePaddingTopState
5955
5978
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React2__namespace.createElement(
5956
5979
  ReactNative.RefreshControl,
5957
5980
  {
@@ -5962,7 +5985,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5962
5985
  ),
5963
5986
  refScrollView: combinedRef,
5964
5987
  renderScrollComponent,
5965
- scrollAdjustHandler: (_h = refState.current) == null ? void 0 : _h.scrollAdjustHandler,
5988
+ scrollAdjustHandler: (_i = refState.current) == null ? void 0 : _i.scrollAdjustHandler,
5966
5989
  scrollEventThrottle: 0,
5967
5990
  snapToIndices,
5968
5991
  stickyHeaderIndices,
package/index.native.mjs CHANGED
@@ -4549,12 +4549,14 @@ var flushSync = (fn) => {
4549
4549
  };
4550
4550
 
4551
4551
  // src/core/updateScroll.ts
4552
- function updateScroll(ctx, newScroll, forceUpdate) {
4552
+ function updateScroll(ctx, newScroll, forceUpdate, options) {
4553
4553
  var _a3;
4554
4554
  const state = ctx.state;
4555
4555
  const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
4556
4556
  const prevScroll = state.scroll;
4557
- state.hasScrolled = true;
4557
+ if ((options == null ? void 0 : options.markHasScrolled) !== false) {
4558
+ state.hasScrolled = true;
4559
+ }
4558
4560
  state.lastBatchingAction = Date.now();
4559
4561
  const currentTime = Date.now();
4560
4562
  const adjust = scrollAdjustHandler.getAdjust();
@@ -4773,13 +4775,12 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4773
4775
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4774
4776
  }
4775
4777
  }
4776
- if (previousSize === nextSize) {
4777
- return nextSize;
4778
- }
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);
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
+ }
4783
4784
  }
4784
4785
  return nextSize;
4785
4786
  }
@@ -5023,14 +5024,14 @@ function createImperativeHandle(ctx) {
5023
5024
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5024
5025
  let imperativeScrollToken = 0;
5025
5026
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5026
- const runWhenSettled = (token, run) => {
5027
+ const runWhenReady = (token, run, isReady) => {
5027
5028
  const startedAt = Date.now();
5028
5029
  let stableFrames = 0;
5029
5030
  const check = () => {
5030
5031
  if (token !== imperativeScrollToken) {
5031
5032
  return;
5032
5033
  }
5033
- if (isSettlingAfterDataChange()) {
5034
+ if (isSettlingAfterDataChange() || !isReady()) {
5034
5035
  stableFrames = 0;
5035
5036
  } else {
5036
5037
  stableFrames += 1;
@@ -5045,10 +5046,10 @@ function createImperativeHandle(ctx) {
5045
5046
  requestAnimationFrame(check);
5046
5047
  };
5047
5048
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5048
- var _a3;
5049
+ var _a3, _b;
5049
5050
  const token = ++imperativeScrollToken;
5050
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5051
- (_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);
5052
5053
  state.pendingScrollResolve = resolve;
5053
5054
  const runNow = () => {
5054
5055
  if (token !== imperativeScrollToken) {
@@ -5062,11 +5063,10 @@ function createImperativeHandle(ctx) {
5062
5063
  resolve();
5063
5064
  }
5064
5065
  };
5065
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5066
- if (isSettlingAfterDataChange()) {
5067
- runWhenSettled(token, execute);
5066
+ if (isSettlingAfterDataChange() || !isReady()) {
5067
+ runWhenReady(token, runNow, isReady);
5068
5068
  } else {
5069
- execute();
5069
+ runNow();
5070
5070
  }
5071
5071
  });
5072
5072
  const scrollIndexIntoView = (options) => {
@@ -5148,7 +5148,7 @@ function createImperativeHandle(ctx) {
5148
5148
  }),
5149
5149
  reportContentInset: (inset) => {
5150
5150
  state.contentInsetOverride = inset != null ? inset : void 0;
5151
- updateScroll(ctx, state.scroll, true);
5151
+ updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5152
5152
  },
5153
5153
  scrollIndexIntoView: (options) => runScrollWithPromise(() => scrollIndexIntoView(options)),
5154
5154
  scrollItemIntoView: ({ item, ...props }) => runScrollWithPromise(() => {
@@ -5177,15 +5177,24 @@ function createImperativeHandle(ctx) {
5177
5177
  }
5178
5178
  return false;
5179
5179
  }),
5180
- scrollToIndex: (params) => runScrollWithPromise(
5181
- () => {
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(() => {
5182
5194
  scrollToIndex(ctx, params);
5183
5195
  return true;
5184
- },
5185
- {
5186
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5187
- }
5188
- ),
5196
+ }, options);
5197
+ },
5189
5198
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5190
5199
  const data = state.props.data;
5191
5200
  const index = data.indexOf(item);
@@ -5217,32 +5226,32 @@ var addIndex = (result, dataLength, index) => {
5217
5226
  result.add(index);
5218
5227
  }
5219
5228
  };
5220
- function getAlwaysRenderIndices(config, data, keyExtractor) {
5229
+ function getAlwaysRenderIndices(config, data, keyExtractor, anchoredEndSpaceAnchorIndex) {
5221
5230
  var _a3, _b;
5222
- if (!config || data.length === 0) {
5231
+ if (data.length === 0) {
5223
5232
  return [];
5224
5233
  }
5225
5234
  const result = /* @__PURE__ */ new Set();
5226
5235
  const dataLength = data.length;
5227
- const topCount = toCount(config.top);
5236
+ const topCount = toCount(config == null ? void 0 : config.top);
5228
5237
  if (topCount > 0) {
5229
5238
  for (let i = 0; i < Math.min(topCount, dataLength); i++) {
5230
5239
  addIndex(result, dataLength, i);
5231
5240
  }
5232
5241
  }
5233
- const bottomCount = toCount(config.bottom);
5242
+ const bottomCount = toCount(config == null ? void 0 : config.bottom);
5234
5243
  if (bottomCount > 0) {
5235
5244
  for (let i = Math.max(0, dataLength - bottomCount); i < dataLength; i++) {
5236
5245
  addIndex(result, dataLength, i);
5237
5246
  }
5238
5247
  }
5239
- if ((_a3 = config.indices) == null ? void 0 : _a3.length) {
5248
+ if ((_a3 = config == null ? void 0 : config.indices) == null ? void 0 : _a3.length) {
5240
5249
  for (const index of config.indices) {
5241
5250
  if (!Number.isFinite(index)) continue;
5242
5251
  addIndex(result, dataLength, Math.floor(index));
5243
5252
  }
5244
5253
  }
5245
- if ((_b = config.keys) == null ? void 0 : _b.length) {
5254
+ if ((_b = config == null ? void 0 : config.keys) == null ? void 0 : _b.length) {
5246
5255
  const keys = new Set(config.keys);
5247
5256
  for (let i = 0; i < dataLength && keys.size > 0; i++) {
5248
5257
  const key = keyExtractor(data[i], i);
@@ -5252,6 +5261,12 @@ function getAlwaysRenderIndices(config, data, keyExtractor) {
5252
5261
  }
5253
5262
  }
5254
5263
  }
5264
+ if (anchoredEndSpaceAnchorIndex !== void 0 && Number.isFinite(anchoredEndSpaceAnchorIndex)) {
5265
+ const anchorIndex = Math.floor(anchoredEndSpaceAnchorIndex);
5266
+ for (let i = anchorIndex >= 0 ? anchorIndex : dataLength; i < dataLength; i++) {
5267
+ addIndex(result, dataLength, i);
5268
+ }
5269
+ }
5255
5270
  const indices = Array.from(result);
5256
5271
  indices.sort(sortAsc);
5257
5272
  return indices;
@@ -5415,7 +5430,7 @@ var LegendList = typedMemo(
5415
5430
  })
5416
5431
  );
5417
5432
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
5418
- var _a3, _b, _c, _d, _e, _f, _g, _h;
5433
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
5419
5434
  const noopOnScroll = useCallback((_event) => {
5420
5435
  }, []);
5421
5436
  if (props.recycleItems === void 0) {
@@ -5544,9 +5559,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5544
5559
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
5545
5560
  const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
5546
5561
  const alwaysRenderIndices = useMemo(() => {
5547
- const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor);
5562
+ const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor, anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
5548
5563
  return { arr: indices, set: new Set(indices) };
5549
5564
  }, [
5565
+ anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
5550
5566
  alwaysRender == null ? void 0 : alwaysRender.top,
5551
5567
  alwaysRender == null ? void 0 : alwaysRender.bottom,
5552
5568
  (_d = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _d.join(","),
@@ -5652,6 +5668,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5652
5668
  const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
5653
5669
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
5654
5670
  const anchoredEndSpaceResolved = Platform.OS === "web" && anchoredEndSpace ? { ...anchoredEndSpace, includeInEndInset: true } : anchoredEndSpace;
5671
+ const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
5655
5672
  state.props = {
5656
5673
  alignItemsAtEnd,
5657
5674
  alwaysRender,
@@ -5766,6 +5783,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5766
5783
  });
5767
5784
  }, [dataProp.length, didDataChangeLocal, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]);
5768
5785
  useLayoutEffect(() => {
5786
+ var _a4;
5787
+ if (didAnchoredEndSpaceAnchorIndexChange) {
5788
+ state.scrollForNextCalculateItemsInView = void 0;
5789
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state);
5790
+ }
5769
5791
  maybeUpdateAnchoredEndSpace(ctx);
5770
5792
  }, [
5771
5793
  ctx,
@@ -5774,6 +5796,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5774
5796
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
5775
5797
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorMaxSize,
5776
5798
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorOffset,
5799
+ didAnchoredEndSpaceAnchorIndexChange,
5777
5800
  numColumnsProp
5778
5801
  ]);
5779
5802
  const onLayoutFooter = useCallback(
@@ -5930,7 +5953,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5930
5953
  onScroll: onScrollHandler,
5931
5954
  recycleItems,
5932
5955
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React2.cloneElement(refreshControlElement, {
5933
- progressViewOffset: ((_g = refreshControlElement.props.progressViewOffset) != null ? _g : 0) + stylePaddingTopState
5956
+ progressViewOffset: ((_h = refreshControlElement.props.progressViewOffset) != null ? _h : 0) + stylePaddingTopState
5934
5957
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React2.createElement(
5935
5958
  RefreshControl,
5936
5959
  {
@@ -5941,7 +5964,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5941
5964
  ),
5942
5965
  refScrollView: combinedRef,
5943
5966
  renderScrollComponent,
5944
- scrollAdjustHandler: (_h = refState.current) == null ? void 0 : _h.scrollAdjustHandler,
5967
+ scrollAdjustHandler: (_i = refState.current) == null ? void 0 : _i.scrollAdjustHandler,
5945
5968
  scrollEventThrottle: 0,
5946
5969
  snapToIndices,
5947
5970
  stickyHeaderIndices,
@@ -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> {
@@ -220,9 +221,28 @@ type LegendListRef = Omit<LegendListRef$1, "getNativeScrollRef" | "getScrollResp
220
221
  reportContentInset(inset?: Partial<Insets$1> | null): void;
221
222
  };
222
223
 
223
- type KeyboardChatScrollViewPropsUnique = Omit<KeyboardChatScrollViewProps, keyof ScrollViewProps | "inverted" | "ScrollViewComponent" | "blankSpace">;
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
@@ -27,7 +27,28 @@ function _interopNamespace(e) {
27
27
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
28
 
29
29
  // src/integrations/keyboard-chat.tsx
30
- var { typedForwardRef } = reactNative.internal;
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,
@@ -38,6 +59,8 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
38
59
  offset,
39
60
  ...rest
40
61
  } = props;
62
+ const refLegendList = React.useRef(null);
63
+ const combinedRef = useCombinedRef(forwardedRef, refLegendList);
41
64
  const blankSpace = reactNativeReanimated.useSharedValue(0);
42
65
  React.useEffect(() => {
43
66
  if (!anchoredEndSpace) {
@@ -58,6 +81,10 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
58
81
  }
59
82
  };
60
83
  }, [anchoredEndSpace, blankSpace]);
84
+ const onContentInsetChange = React.useCallback((insets) => {
85
+ var _a;
86
+ (_a = refLegendList.current) == null ? void 0 : _a.reportContentInset(insets);
87
+ }, []);
61
88
  const memoList = React.useCallback(
62
89
  (scrollProps) => {
63
90
  return /* @__PURE__ */ React__namespace.createElement(
@@ -67,9 +94,9 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
67
94
  applyWorkaroundForContentInsetHitTestBug,
68
95
  blankSpace,
69
96
  extraContentPadding,
70
- freeze,
71
97
  keyboardLiftBehavior,
72
- offset
98
+ offset,
99
+ onContentInsetChange
73
100
  }
74
101
  );
75
102
  },
@@ -79,6 +106,7 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
79
106
  extraContentPadding,
80
107
  freeze,
81
108
  keyboardLiftBehavior,
109
+ onContentInsetChange,
82
110
  offset
83
111
  ]
84
112
  );
@@ -87,7 +115,7 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
87
115
  AnimatedLegendListInternal,
88
116
  {
89
117
  anchoredEndSpace: anchoredEndSpaceWithBlankSpace,
90
- ref: forwardedRef,
118
+ ref: combinedRef,
91
119
  renderScrollComponent: memoList,
92
120
  ...rest
93
121
  }
@@ -95,3 +123,4 @@ var KeyboardChatLegendList = typedForwardRef(function KeyboardChatLegendList2(pr
95
123
  });
96
124
 
97
125
  exports.KeyboardChatLegendList = KeyboardChatLegendList;
126
+ exports.useKeyboardScrollToEnd = useKeyboardScrollToEnd;