@rific/scroll-view 1.0.0 → 1.1.1

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/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Blur-chrome scroll system for React Native. Drop-in replacements for `ScrollView`, `FlatList`, and `SectionList` with floating headers and footers, pull-to-search, keyboard awareness, horizontal paging, and frosted-glass chrome.
4
4
 
5
+ **[Live demo](https://rific.jaydeaton.com/demos/scroll-view)**
6
+
5
7
  ## Installation
6
8
 
7
9
  ```sh
package/dist/index.js CHANGED
@@ -61,7 +61,7 @@ module.exports = __toCommonJS(index_exports);
61
61
  var import_react6 = require("react");
62
62
  var import_react_native6 = require("react-native");
63
63
  var import_react_native_gesture_handler = require("react-native-gesture-handler");
64
- var import_react_native_reanimated6 = require("react-native-reanimated");
64
+ var import_react_native_reanimated5 = require("react-native-reanimated");
65
65
 
66
66
  // src/internal/RefreshControl.tsx
67
67
  var import_react_native = require("react-native");
@@ -90,8 +90,10 @@ var styles = import_react_native2.StyleSheet.create({
90
90
  });
91
91
 
92
92
  // src/internal/useScrollHandler.ts
93
+ var import_core = require("@rific/core");
93
94
  var import_react3 = require("react");
94
95
  var import_react_native_reanimated3 = require("react-native-reanimated");
96
+ var import_react_native_worklets = require("react-native-worklets");
95
97
 
96
98
  // src/ScrollViewContext.ts
97
99
  var import_react = require("react");
@@ -338,6 +340,8 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
338
340
  const { chromeHosted, chromeWritable, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared, stackHeightShared } = (0, import_react3.useContext)(ScrollViewContext);
339
341
  const snapUpAccum = (0, import_react_native_reanimated3.useSharedValue)(0);
340
342
  const fromBottomBounce = (0, import_react_native_reanimated3.useSharedValue)(false);
343
+ const remountSyncedKey = (0, import_core.useWorkletCallback)((y) => onRemountSynced?.(y));
344
+ const remountSyncRetryKey = (0, import_core.useWorkletCallback)((y) => onRemountSyncRetry?.(y));
341
345
  return (0, import_react_native_reanimated3.useAnimatedScrollHandler)(
342
346
  {
343
347
  onScroll: ({ contentOffset: { x, y }, contentSize: { height: contentHeight }, layoutMeasurement: { height: layoutHeight } }) => {
@@ -346,9 +350,9 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
346
350
  const target = remountSyncTarget.value;
347
351
  if (Math.abs(y - target) < REMOUNT_SYNC_TOLERANCE) {
348
352
  remountSyncTarget.value = null;
349
- if (onRemountSynced) (0, import_react_native_reanimated3.runOnJS)(onRemountSynced)(y);
353
+ if (onRemountSynced) (0, import_react_native_worklets.scheduleOnRN)(import_core.callWorkletCallback, remountSyncedKey, y);
350
354
  } else if (onRemountSyncRetry) {
351
- (0, import_react_native_reanimated3.runOnJS)(onRemountSyncRetry)(y);
355
+ (0, import_react_native_worklets.scheduleOnRN)(import_core.callWorkletCallback, remountSyncRetryKey, y);
352
356
  }
353
357
  return;
354
358
  }
@@ -428,25 +432,27 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
428
432
  // src/internal/useScrollList.ts
429
433
  var import_react5 = require("react");
430
434
  var import_react_native5 = require("react-native");
431
- var import_react_native_reanimated5 = require("react-native-reanimated");
435
+ var import_react_native_reanimated4 = require("react-native-reanimated");
432
436
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
433
437
 
434
438
  // src/useKeyboardInset.ts
439
+ var import_core2 = require("@rific/core");
435
440
  var import_react4 = require("react");
436
441
  var import_react_native4 = require("react-native");
437
442
  var import_react_native_keyboard_controller = require("react-native-keyboard-controller");
438
- var import_react_native_reanimated4 = require("react-native-reanimated");
443
+ var import_react_native_worklets2 = require("react-native-worklets");
439
444
  var useKeyboardInsetNative = () => {
440
445
  const [keyboardHeight, setKeyboardHeight] = (0, import_react4.useState)(0);
446
+ const keyboardHeightKey = (0, import_core2.useWorkletCallback)(setKeyboardHeight);
441
447
  (0, import_react_native_keyboard_controller.useKeyboardHandler)(
442
448
  {
443
449
  onMove: (e) => {
444
450
  "worklet";
445
- (0, import_react_native_reanimated4.runOnJS)(setKeyboardHeight)(e.height);
451
+ (0, import_react_native_worklets2.scheduleOnRN)(import_core2.callWorkletCallback, keyboardHeightKey, e.height);
446
452
  },
447
453
  onEnd: (e) => {
448
454
  "worklet";
449
- (0, import_react_native_reanimated4.runOnJS)(setKeyboardHeight)(e.height);
455
+ (0, import_react_native_worklets2.scheduleOnRN)(import_core2.callWorkletCallback, keyboardHeightKey, e.height);
450
456
  }
451
457
  },
452
458
  []
@@ -482,25 +488,25 @@ function useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedP
482
488
  const [startedWithHeader] = (0, import_react5.useState)(headerHeight !== null);
483
489
  const insetContentOffset = (0, import_react5.useMemo)(() => ({ x: 0, y: headerHeight !== null ? -headerHeight + (startedWithHeader && !isHorizontal && pullSearchHeight ? pullSearchHeight : 0) : 0 }), [headerHeight, isHorizontal, pullSearchHeight, startedWithHeader]);
484
490
  const contentOffset = usesContentInset ? insetContentOffset : ZERO_OFFSET;
485
- const chipHidden = (0, import_react_native_reanimated5.useSharedValue)(1);
486
- const chipStyle = (0, import_react_native_reanimated5.useAnimatedStyle)(() => {
491
+ const chipHidden = (0, import_react_native_reanimated4.useSharedValue)(1);
492
+ const chipStyle = (0, import_react_native_reanimated4.useAnimatedStyle)(() => {
487
493
  const pointerEvents = chipHidden.value ? "none" : "box-none";
488
494
  if (isHorizontal) {
489
495
  return {
490
- opacity: chipHidden.value ? (0, import_react_native_reanimated5.withTiming)(0) : (0, import_react_native_reanimated5.withTiming)(1),
496
+ opacity: chipHidden.value ? (0, import_react_native_reanimated4.withTiming)(0) : (0, import_react_native_reanimated4.withTiming)(1),
491
497
  pointerEvents,
492
498
  top: Math.max(headerHeightShared.value, insets.top) + 4,
493
- transform: [{ translateX: chipHidden.value ? (0, import_react_native_reanimated5.withTiming)(-CHIP_SLIDE) : (0, import_react_native_reanimated5.withTiming)(0) }]
499
+ transform: [{ translateX: chipHidden.value ? (0, import_react_native_reanimated4.withTiming)(-CHIP_SLIDE) : (0, import_react_native_reanimated4.withTiming)(0) }]
494
500
  };
495
501
  }
496
502
  const h = headerHeightShared.value;
497
503
  const slide = headerFixed ? 0 : snapBackHeaderShared.value ? -headerOffset.value : Math.max(0, scrollPosition.value + h - pullSearchHeightShared.value);
498
504
  const top = Math.max(h - slide, insets.top) + 4;
499
505
  return {
500
- opacity: chipHidden.value ? (0, import_react_native_reanimated5.withTiming)(0) : (0, import_react_native_reanimated5.withTiming)(1),
506
+ opacity: chipHidden.value ? (0, import_react_native_reanimated4.withTiming)(0) : (0, import_react_native_reanimated4.withTiming)(1),
501
507
  pointerEvents,
502
508
  top,
503
- transform: [{ translateY: chipHidden.value ? (0, import_react_native_reanimated5.withTiming)(-CHIP_SLIDE) : (0, import_react_native_reanimated5.withTiming)(0) }]
509
+ transform: [{ translateY: chipHidden.value ? (0, import_react_native_reanimated4.withTiming)(-CHIP_SLIDE) : (0, import_react_native_reanimated4.withTiming)(0) }]
504
510
  };
505
511
  }, [isHorizontal, headerFixed, headerHeightShared, insets.top, chipHidden, snapBackHeaderShared, headerOffset, scrollPosition, pullSearchHeightShared]);
506
512
  return { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, contentPadding, footerFixed, headerFixed, headerHeight, insets, isHorizontal: isHorizontal ?? false };
@@ -512,14 +518,14 @@ var CustomListInner = ({ chipProps, chipThreshold, component: List, renderFilter
512
518
  const { ListHeaderComponent: listHeaderComponent, contentContainerStyle: externalContentContainerStyle, ...restProps } = props;
513
519
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, contentPadding, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
514
520
  const { listGeneration, onListUnmount } = (0, import_react6.useContext)(ScrollViewContext);
515
- const capturedGeneration = (0, import_react_native_reanimated6.useSharedValue)(-1);
521
+ const capturedGeneration = (0, import_react_native_reanimated5.useSharedValue)(-1);
516
522
  (0, import_react6.useLayoutEffect)(() => {
517
523
  const generation = listGeneration.value;
518
524
  if (import_react_native6.Platform.OS === "web") {
519
525
  capturedGeneration.value = generation;
520
526
  return;
521
527
  }
522
- (0, import_react_native_reanimated6.runOnUI)((gen) => {
528
+ (0, import_react_native_reanimated5.runOnUI)((gen) => {
523
529
  "worklet";
524
530
  capturedGeneration.value = gen;
525
531
  })(generation);
@@ -594,7 +600,7 @@ var import_auto_paper2 = require("@rific/auto-paper");
594
600
  var import_react7 = require("react");
595
601
  var import_react_native7 = require("react-native");
596
602
  var import_react_native_paper2 = require("react-native-paper");
597
- var import_react_native_reanimated7 = __toESM(require("react-native-reanimated"));
603
+ var import_react_native_reanimated6 = __toESM(require("react-native-reanimated"));
598
604
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
599
605
  var import_jsx_runtime4 = require("react/jsx-runtime");
600
606
  var DOT_FULL = 8;
@@ -609,15 +615,15 @@ var PILL_HEIGHT = DOT_FULL + PILL_PAD_V * 2;
609
615
  var PILL_RADIUS = PILL_HEIGHT / 2;
610
616
  var PILL_WIDTH = CLIP_WIDTH + PILL_PAD_H * 2;
611
617
  var Dot = ({ activeColor, index, inactiveColor, pageWidth, scrollPosition }) => {
612
- const circleStyle = (0, import_react_native_reanimated7.useAnimatedStyle)(() => {
618
+ const circleStyle = (0, import_react_native_reanimated6.useAnimatedStyle)(() => {
613
619
  const page = scrollPosition.value / pageWidth;
614
620
  const distance = Math.abs(index - page);
615
621
  const t = Math.max(0, Math.min((distance - 0.5) / 2, 1));
616
622
  const size = DOT_FULL + (DOT_SMALL - DOT_FULL) * t;
617
- const backgroundColor = (0, import_react_native_reanimated7.interpolateColor)(t, [0, 1], [activeColor, inactiveColor]);
623
+ const backgroundColor = (0, import_react_native_reanimated6.interpolateColor)(t, [0, 1], [activeColor, inactiveColor]);
618
624
  return { backgroundColor, borderRadius: size / 2, height: size, width: size };
619
625
  }, [scrollPosition, pageWidth, index, activeColor, inactiveColor]);
620
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles3.dotContainer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated7.default.View, { style: circleStyle }) });
626
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles3.dotContainer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated6.default.View, { style: circleStyle }) });
621
627
  };
622
628
  var HorizontalDots = ({ total }) => {
623
629
  const { blur, footerHeightShared, scrollPosition } = (0, import_react7.useContext)(ScrollViewContext);
@@ -627,21 +633,21 @@ var HorizontalDots = ({ total }) => {
627
633
  const insetsBottom = insets.bottom;
628
634
  const activeColor = theme.colors.primary;
629
635
  const inactiveColor = theme.colors.outlineVariant;
630
- const pillContainerStyle = (0, import_react_native_reanimated7.useAnimatedStyle)(
636
+ const pillContainerStyle = (0, import_react_native_reanimated6.useAnimatedStyle)(
631
637
  () => ({
632
638
  bottom: Math.max(footerHeightShared.value, insetsBottom) + 8
633
639
  }),
634
640
  [footerHeightShared, insetsBottom]
635
641
  );
636
- const rowStyle = (0, import_react_native_reanimated7.useAnimatedStyle)(() => {
642
+ const rowStyle = (0, import_react_native_reanimated6.useAnimatedStyle)(() => {
637
643
  const page = scrollPosition.value / width;
638
644
  const maxOffset = Math.max(0, (total - CLIP_COUNT) * DOT_STEP);
639
645
  const offset = Math.max(0, Math.min((page - (CLIP_COUNT - 1) / 2) * DOT_STEP, maxOffset));
640
646
  return { transform: [{ translateX: -offset }] };
641
647
  }, [scrollPosition, width, total]);
642
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated7.default.View, { pointerEvents: "none", style: [styles3.pillContainer, pillContainerStyle], children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles3.pill, children: [
648
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated6.default.View, { pointerEvents: "none", style: [styles3.pillContainer, pillContainerStyle], children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles3.pill, children: [
643
649
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_auto_paper2.BlurView, { blur, style: import_react_native7.StyleSheet.absoluteFill }),
644
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles3.dotsClip, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated7.default.View, { style: [styles3.dotsRow, rowStyle], children: Array.from({ length: total }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dot, { activeColor, index: i, inactiveColor, pageWidth: width, scrollPosition }, i)) }) })
650
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles3.dotsClip, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated6.default.View, { style: [styles3.dotsRow, rowStyle], children: Array.from({ length: total }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dot, { activeColor, index: i, inactiveColor, pageWidth: width, scrollPosition }, i)) }) })
645
651
  ] }) });
646
652
  };
647
653
  var styles3 = import_react_native7.StyleSheet.create({
@@ -661,7 +667,7 @@ var styles3 = import_react_native7.StyleSheet.create({
661
667
 
662
668
  // src/internal/useScrollHandlerJS.ts
663
669
  var import_react8 = require("react");
664
- var import_react_native_reanimated8 = require("react-native-reanimated");
670
+ var import_react_native_reanimated7 = require("react-native-reanimated");
665
671
  var REMOUNT_RETRY_TOLERANCE = 1;
666
672
  var REMOUNT_RETRY_MAX_ATTEMPTS = 8;
667
673
  function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, jsListGeneration, remountTarget = null, scrollTo }) {
@@ -727,8 +733,8 @@ function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 10
727
733
  if (yn >= -headerHeightShared.value + pullSearchHeightShared.value) snapUpAccum.current -= delta;
728
734
  if (snapUpAccum.current >= 10) {
729
735
  snapUpAccum.current = 999;
730
- if (snapHeader) headerOffset.value = (0, import_react_native_reanimated8.withTiming)(0, { duration: 200 });
731
- if (snapFooter) footerOffset.value = (0, import_react_native_reanimated8.withTiming)(0, { duration: 200 });
736
+ if (snapHeader) headerOffset.value = (0, import_react_native_reanimated7.withTiming)(0, { duration: 200 });
737
+ if (snapFooter) footerOffset.value = (0, import_react_native_reanimated7.withTiming)(0, { duration: 200 });
732
738
  }
733
739
  }
734
740
  }
@@ -744,7 +750,7 @@ function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 10
744
750
  const settle = (0, import_react8.useCallback)(
745
751
  (revealing) => {
746
752
  if (!chromeHosted || footerFixed || !chromeWritable.value) return;
747
- footerOffset.value = (0, import_react_native_reanimated8.withTiming)(revealing ? 0 : chromeSettleTarget(footerOffset.value, stackHeightShared.value), { duration: 200 });
753
+ footerOffset.value = (0, import_react_native_reanimated7.withTiming)(revealing ? 0 : chromeSettleTarget(footerOffset.value, stackHeightShared.value), { duration: 200 });
748
754
  },
749
755
  [chromeHosted, chromeWritable, footerFixed, footerOffset, stackHeightShared]
750
756
  );
@@ -929,10 +935,12 @@ var styles4 = { measureContainer: { left: 0, opacity: 0, position: "absolute", r
929
935
  var FlatList = (0, import_react9.memo)(FlatListInner);
930
936
 
931
937
  // src/PullSearch.tsx
938
+ var import_core3 = require("@rific/core");
932
939
  var import_react10 = require("react");
933
940
  var import_react_native9 = require("react-native");
934
941
  var import_react_native_paper3 = require("react-native-paper");
935
- var import_react_native_reanimated9 = __toESM(require("react-native-reanimated"));
942
+ var import_react_native_reanimated8 = __toESM(require("react-native-reanimated"));
943
+ var import_react_native_worklets3 = require("react-native-worklets");
936
944
  var import_jsx_runtime6 = require("react/jsx-runtime");
937
945
  var PullSearch = (0, import_react10.forwardRef)(function PullSearch2({ debounce, onChangeText, onHeightChange, placeholder, value: propValue }, ref) {
938
946
  const { headerHeight, scrollPosition } = (0, import_react10.useContext)(ScrollViewContext);
@@ -951,13 +959,14 @@ var PullSearch = (0, import_react10.forwardRef)(function PullSearch2({ debounce,
951
959
  focus: () => inputRef.current?.focus()
952
960
  }));
953
961
  const blurInput = (0, import_react10.useCallback)(() => inputRef.current?.blur(), []);
954
- (0, import_react_native_reanimated9.useAnimatedReaction)(
962
+ const blurKey = (0, import_core3.useWorkletCallback)(blurInput);
963
+ (0, import_react_native_reanimated8.useAnimatedReaction)(
955
964
  () => {
956
965
  if (barHeight === 0) return false;
957
966
  return scrollPosition.value >= -(headerHeight ?? 0) + barHeight;
958
967
  },
959
968
  (isHidden, wasHidden) => {
960
- if (isHidden && !wasHidden) (0, import_react_native_reanimated9.runOnJS)(blurInput)();
969
+ if (isHidden && !wasHidden) (0, import_react_native_worklets3.scheduleOnRN)(import_core3.callWorkletCallback, blurKey);
961
970
  },
962
971
  // scrollPosition has to be listed too, not just read - see useStickyHeaders' useAnimatedReaction
963
972
  // for why: on web, without reanimated's Babel plugin active, an unlisted SharedValue mutation
@@ -988,14 +997,14 @@ var PullSearch = (0, import_react10.forwardRef)(function PullSearch2({ debounce,
988
997
  onChangeText(normalizedValue);
989
998
  return void 0;
990
999
  }, [debounce, onChangeText, value]);
991
- const animatedStyle = (0, import_react_native_reanimated9.useAnimatedStyle)(() => {
1000
+ const animatedStyle = (0, import_react_native_reanimated8.useAnimatedStyle)(() => {
992
1001
  if (barHeight === 0) return { opacity: 0 };
993
1002
  const h = headerHeight ?? 0;
994
1003
  const showY = -h;
995
1004
  const hideY = -h + barHeight;
996
- return { opacity: (0, import_react_native_reanimated9.interpolate)(scrollPosition.value, [showY, hideY], [1, 0], import_react_native_reanimated9.Extrapolation.CLAMP) };
1005
+ return { opacity: (0, import_react_native_reanimated8.interpolate)(scrollPosition.value, [showY, hideY], [1, 0], import_react_native_reanimated8.Extrapolation.CLAMP) };
997
1006
  }, [barHeight, headerHeight, scrollPosition]);
998
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated9.default.View, { onLayout: handleLayout, style: [styles5.container, animatedStyle], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper3.Searchbar, { autoCorrect: false, onChangeText: (text) => setValue((text || "").trimStart()), onClearIconPress: handleClear, placeholder, placeholderTextColor: theme.colors.onSurfaceVariant, ref: inputRef, spellCheck: false, style: styles5.input, value }) });
1007
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated8.default.View, { onLayout: handleLayout, style: [styles5.container, animatedStyle], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper3.Searchbar, { autoCorrect: false, onChangeText: (text) => setValue((text || "").trimStart()), onClearIconPress: handleClear, placeholder, placeholderTextColor: theme.colors.onSurfaceVariant, ref: inputRef, spellCheck: false, style: styles5.input, value }) });
999
1008
  });
1000
1009
  var styles5 = import_react_native9.StyleSheet.create({
1001
1010
  container: { paddingVertical: 8 },
@@ -1003,23 +1012,23 @@ var styles5 = import_react_native9.StyleSheet.create({
1003
1012
  });
1004
1013
 
1005
1014
  // src/redux/scrollViewSlice.ts
1006
- var import_core2 = require("@rific/core");
1015
+ var import_core5 = require("@rific/core");
1007
1016
 
1008
1017
  // src/ScrollViewSettingsContext.ts
1009
- var import_core = require("@rific/core");
1018
+ var import_core4 = require("@rific/core");
1010
1019
  var defaultScrollViewSettings = {
1011
1020
  backActionFixed: true,
1012
1021
  footerFixed: false,
1013
1022
  headerFixed: false,
1014
1023
  snapBack: false
1015
1024
  };
1016
- var settingsContext = (0, import_core.createSettingsContext)(defaultScrollViewSettings);
1025
+ var settingsContext = (0, import_core4.createSettingsContext)(defaultScrollViewSettings);
1017
1026
  var ScrollViewSettingsContext = settingsContext.Context;
1018
1027
  var scrollViewSettingsProvider = settingsContext.Provider;
1019
1028
  var scrollViewUseSettings = settingsContext.useSettings;
1020
1029
 
1021
1030
  // src/redux/scrollViewSlice.ts
1022
- var scrollViewSlice = (0, import_core2.createSettingsSlice)("scrollView", {
1031
+ var scrollViewSlice = (0, import_core5.createSettingsSlice)("scrollView", {
1023
1032
  initialState: defaultScrollViewSettings,
1024
1033
  fieldSetters: []
1025
1034
  });
@@ -1030,21 +1039,21 @@ var scrollViewReducer = scrollViewSlice.reducer;
1030
1039
  var import_react11 = require("react");
1031
1040
  var import_react_native10 = require("react-native");
1032
1041
  var import_react_native_gesture_handler3 = require("react-native-gesture-handler");
1033
- var import_react_native_reanimated10 = __toESM(require("react-native-reanimated"));
1042
+ var import_react_native_reanimated9 = __toESM(require("react-native-reanimated"));
1034
1043
  var import_jsx_runtime7 = require("react/jsx-runtime");
1035
1044
  var ScrollViewInner = ({ chipProps, chipThreshold, children, contentContainerStyle: externalContentContainerStyle, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }) => {
1036
1045
  const scrollView = (0, import_react11.useRef)(null);
1037
1046
  const isHorizontal = horizontal === true;
1038
1047
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, contentPadding, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, isHorizontal, keyboardAware, pullSearchHeight, style });
1039
1048
  const { listGeneration, onListUnmount } = (0, import_react11.useContext)(ScrollViewContext);
1040
- const capturedGeneration = (0, import_react_native_reanimated10.useSharedValue)(-1);
1049
+ const capturedGeneration = (0, import_react_native_reanimated9.useSharedValue)(-1);
1041
1050
  (0, import_react11.useLayoutEffect)(() => {
1042
1051
  const generation = listGeneration.value;
1043
1052
  if (import_react_native10.Platform.OS === "web") {
1044
1053
  capturedGeneration.value = generation;
1045
1054
  return;
1046
1055
  }
1047
- (0, import_react_native_reanimated10.runOnUI)((gen) => {
1056
+ (0, import_react_native_reanimated9.runOnUI)((gen) => {
1048
1057
  "worklet";
1049
1058
  capturedGeneration.value = gen;
1050
1059
  })(generation);
@@ -1075,7 +1084,7 @@ var ScrollViewInner = ({ chipProps, chipThreshold, children, contentContainerSty
1075
1084
  const detectorGesture = gesture !== void 0 ? combinedGesture : void 0;
1076
1085
  const content = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native10.View, { style: containerStyle, children: [
1077
1086
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1078
- import_react_native_reanimated10.default.ScrollView,
1087
+ import_react_native_reanimated9.default.ScrollView,
1079
1088
  {
1080
1089
  ...props,
1081
1090
  contentContainerStyle: contentPadding ? [externalContentContainerStyle, contentPadding] : externalContentContainerStyle,
@@ -1102,7 +1111,7 @@ var ScrollView = (0, import_react11.memo)(ScrollViewInner);
1102
1111
 
1103
1112
  // src/ScrollViewChromeProvider.tsx
1104
1113
  var import_react13 = require("react");
1105
- var import_react_native_reanimated11 = require("react-native-reanimated");
1114
+ var import_react_native_reanimated10 = require("react-native-reanimated");
1106
1115
 
1107
1116
  // src/ScrollViewChromeContext.ts
1108
1117
  var import_react12 = require("react");
@@ -1114,7 +1123,7 @@ var import_jsx_runtime8 = require("react/jsx-runtime");
1114
1123
  var REVEAL_DURATION = 200;
1115
1124
  var alwaysActive = () => true;
1116
1125
  var ScrollViewChromeProvider = ({ children, footprint, overhang = 0, snapBack = true, useIsActive = alwaysActive }) => {
1117
- const offset = (0, import_react_native_reanimated11.useSharedValue)(0);
1126
+ const offset = (0, import_react_native_reanimated10.useSharedValue)(0);
1118
1127
  const [claims, setClaims] = (0, import_react13.useState)([]);
1119
1128
  const [pins, setPins] = (0, import_react13.useState)(0);
1120
1129
  const activeId = claims.length > 0 ? claims[claims.length - 1] : null;
@@ -1124,7 +1133,7 @@ var ScrollViewChromeProvider = ({ children, footprint, overhang = 0, snapBack =
1124
1133
  const addPin = (0, import_react13.useCallback)(() => setPins((current) => current + 1), []);
1125
1134
  const removePin = (0, import_react13.useCallback)(() => setPins((current) => Math.max(0, current - 1)), []);
1126
1135
  const reveal = (0, import_react13.useCallback)(() => {
1127
- offset.value = (0, import_react_native_reanimated11.withTiming)(0, { duration: REVEAL_DURATION });
1136
+ offset.value = (0, import_react_native_reanimated10.withTiming)(0, { duration: REVEAL_DURATION });
1128
1137
  }, [offset]);
1129
1138
  (0, import_react13.useEffect)(() => {
1130
1139
  reveal();
@@ -1135,8 +1144,8 @@ var ScrollViewChromeProvider = ({ children, footprint, overhang = 0, snapBack =
1135
1144
  };
1136
1145
 
1137
1146
  // src/ScrollViewConfig.tsx
1138
- var import_core3 = require("@rific/core");
1139
- var scrollViewConfig = (0, import_core3.createModuleConfig)();
1147
+ var import_core6 = require("@rific/core");
1148
+ var scrollViewConfig = (0, import_core6.createModuleConfig)();
1140
1149
  var configureScrollView = scrollViewConfig.configure;
1141
1150
  var getScrollViewConfig = scrollViewConfig.getConfig;
1142
1151
  var ScrollViewConfigProvider = scrollViewConfig.Provider;
@@ -1145,7 +1154,7 @@ var ScrollViewConfigProvider = scrollViewConfig.Provider;
1145
1154
  var import_auto_paper3 = require("@rific/auto-paper");
1146
1155
  var import_react14 = require("react");
1147
1156
  var import_react_native11 = require("react-native");
1148
- var import_react_native_reanimated12 = __toESM(require("react-native-reanimated"));
1157
+ var import_react_native_reanimated11 = __toESM(require("react-native-reanimated"));
1149
1158
  var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
1150
1159
  var import_jsx_runtime9 = (
1151
1160
  // bottom: tabBarHeight (not the styles.footer default of 0) - a consuming app's own persistent
@@ -1175,7 +1184,7 @@ var ScrollViewFooter = ({ children, style }) => {
1175
1184
  }) => {
1176
1185
  if (footerHeight !== height) setFooterHeight(height);
1177
1186
  };
1178
- const footerStyle = (0, import_react_native_reanimated12.useAnimatedStyle)(() => {
1187
+ const footerStyle = (0, import_react_native_reanimated11.useAnimatedStyle)(() => {
1179
1188
  if (chromeHosted) return { transform: [{ translateY: Math.min(Math.max(footerOffset.value, 0), stackHeightShared.value) }] };
1180
1189
  if (footerFixed) return { transform: [{ translateY: 0 }] };
1181
1190
  if (snapBackFooterShared.value) return { transform: [{ translateY: footerOffset.value }] };
@@ -1195,7 +1204,7 @@ var ScrollViewFooter = ({ children, style }) => {
1195
1204
  const rowPaddingBottom = footerFixed && footerAboveKeyboard ? Math.max(bottomPadding - keyboardHeight, 0) : bottomPadding;
1196
1205
  const footerBottom = chromeHosted && footerFixed && footerAboveKeyboard ? Math.max(tabBarHeight - keyboardHeight, 0) : tabBarHeight;
1197
1206
  const { paddingBottom: consumerPaddingBottom, ...restStyle } = style ?? {};
1198
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_reanimated12.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, { bottom: footerBottom, paddingBottom: containerPaddingBottom }, footerStyle], children: [
1207
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_reanimated11.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, { bottom: footerBottom, paddingBottom: containerPaddingBottom }, footerStyle], children: [
1199
1208
  (footerHeight ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper3.BlurView, { blur, style: import_react_native11.StyleSheet.absoluteFill }),
1200
1209
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native11.View, { ref: rowRef, style: [styles6.row, restStyle, { paddingBottom: rowPaddingBottom + (typeof consumerPaddingBottom === "number" ? consumerPaddingBottom : 0) }], children })
1201
1210
  ] });
@@ -1210,7 +1219,7 @@ var import_auto_paper4 = require("@rific/auto-paper");
1210
1219
  var import_react15 = require("react");
1211
1220
  var import_react_native12 = require("react-native");
1212
1221
  var import_react_native_paper4 = require("react-native-paper");
1213
- var import_react_native_reanimated13 = __toESM(require("react-native-reanimated"));
1222
+ var import_react_native_reanimated12 = __toESM(require("react-native-reanimated"));
1214
1223
  var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
1215
1224
  var import_jsx_runtime10 = require("react/jsx-runtime");
1216
1225
  var ActionBg = ({ blur, style }) => blur ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [import_react_native12.StyleSheet.absoluteFill, styles7.actionBg, style], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_auto_paper4.BlurView, { blur: true, style: import_react_native12.StyleSheet.absoluteFill }) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [import_react_native12.StyleSheet.absoluteFill, styles7.actionBg, style], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper4.Surface, { style: import_react_native12.StyleSheet.absoluteFill, elevation: 1, children: null }) });
@@ -1221,7 +1230,7 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
1221
1230
  const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
1222
1231
  const theme = (0, import_react_native_paper4.useTheme)();
1223
1232
  const top = topInset ? insets.top : 0;
1224
- const measuredShared = (0, import_react_native_reanimated13.useSharedValue)(false);
1233
+ const measuredShared = (0, import_react_native_reanimated12.useSharedValue)(false);
1225
1234
  const handleLayout = ({
1226
1235
  nativeEvent: {
1227
1236
  layout: { height }
@@ -1241,21 +1250,21 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
1241
1250
  const actionMargin = 4;
1242
1251
  const contentMinHeight = actionSize + 2 * actionMargin;
1243
1252
  const unmeasuredHeight = top + contentMinHeight;
1244
- const translateStyle = (0, import_react_native_reanimated13.useAnimatedStyle)(() => {
1253
+ const translateStyle = (0, import_react_native_reanimated12.useAnimatedStyle)(() => {
1245
1254
  if (headerFixed) return { transform: [{ translateY: 0 }] };
1246
1255
  if (snapBackHeaderShared.value) return { transform: [{ translateY: headerOffset.value }] };
1247
1256
  const effective = scrollPosition.value + headerHeightShared.value - pullSearchHeightShared.value;
1248
1257
  if (effective <= 0) return { transform: [{ translateY: 0 }] };
1249
1258
  return { transform: [{ translateY: -effective }] };
1250
1259
  }, [headerFixed, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared]);
1251
- const blurStyle = (0, import_react_native_reanimated13.useAnimatedStyle)(() => {
1260
+ const blurStyle = (0, import_react_native_reanimated12.useAnimatedStyle)(() => {
1252
1261
  if (!measuredShared.value) return { height: unmeasuredHeight };
1253
1262
  if (!headerHeightShared.value) return { height: 0 };
1254
1263
  if (headerFixed) return { height: headerHeightShared.value };
1255
1264
  const translateY = snapBackHeaderShared.value ? headerOffset.value : -Math.max(0, scrollPosition.value + headerHeightShared.value - pullSearchHeightShared.value);
1256
1265
  return { height: Math.max(headerHeightShared.value + translateY, top) };
1257
1266
  }, [headerFixed, top, unmeasuredHeight, measuredShared, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared]);
1258
- const progressStyle = (0, import_react_native_reanimated13.useAnimatedStyle)(() => {
1267
+ const progressStyle = (0, import_react_native_reanimated12.useAnimatedStyle)(() => {
1259
1268
  const h = headerHeightShared.value;
1260
1269
  if (headerFixed) return { top: h };
1261
1270
  const slide = snapBackHeaderShared.value ? -headerOffset.value : Math.max(0, scrollPosition.value + h - pullSearchHeightShared.value);
@@ -1269,8 +1278,8 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
1269
1278
  const leadingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", left: actionMargin, position: "absolute", top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
1270
1279
  const trailingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", position: "absolute", right: actionMargin, top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
1271
1280
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1272
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_reanimated13.default.View, { pointerEvents: "none", style: [styles7.blur, blurStyle], children: headerHeight !== 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_auto_paper4.BlurView, { blur, style: [styles7.blurInner, { height: headerHeight ?? unmeasuredHeight }] }) }),
1273
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated13.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [headerHeight === null ? styles7.headerInit : styles7.header, translateStyle], children: [
1281
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_reanimated12.default.View, { pointerEvents: "none", style: [styles7.blur, blurStyle], children: headerHeight !== 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_auto_paper4.BlurView, { blur, style: [styles7.blurInner, { height: headerHeight ?? unmeasuredHeight }] }) }),
1282
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated12.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [headerHeight === null ? styles7.headerInit : styles7.header, translateStyle], children: [
1274
1283
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { ref: contentRef, style: [{ paddingTop: top }, style], children: children ?? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: [styles7.content, { minHeight: contentMinHeight }], children: [
1275
1284
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: styles7.side }),
1276
1285
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: styles7.spacer }),
@@ -1281,18 +1290,18 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
1281
1290
  ] }) }),
1282
1291
  !blur && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [styles7.divider, { backgroundColor: theme.colors.outlineVariant }] })
1283
1292
  ] }),
1284
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_reanimated13.default.View, { pointerEvents: "none", style: [styles7.progress, progressStyle], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper4.ProgressBar, { indeterminate: progress === null, visible: progressing, progress: progress ?? void 0 }) }),
1285
- backAction && (effectiveBackActionFixed ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated13.default.View, { style: leadingStyle, children: [
1293
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_reanimated12.default.View, { pointerEvents: "none", style: [styles7.progress, progressStyle], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper4.ProgressBar, { indeterminate: progress === null, visible: progressing, progress: progress ?? void 0 }) }),
1294
+ backAction && (effectiveBackActionFixed ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated12.default.View, { style: leadingStyle, children: [
1286
1295
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionBg, { blur, style: actionStyle }),
1287
1296
  backActionElement
1288
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated13.default.View, { style: [leadingStyle, translateStyle], children: [
1297
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated12.default.View, { style: [leadingStyle, translateStyle], children: [
1289
1298
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionBg, { blur, style: actionStyle }),
1290
1299
  backActionElement
1291
1300
  ] })),
1292
1301
  trailingAction && (trailingActionFixed ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: trailingStyle, children: [
1293
1302
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionBg, { blur, style: actionStyle }),
1294
1303
  trailingAction
1295
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated13.default.View, { style: [trailingStyle, translateStyle], children: [
1304
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_reanimated12.default.View, { style: [trailingStyle, translateStyle], children: [
1296
1305
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionBg, { blur, style: actionStyle }),
1297
1306
  trailingAction
1298
1307
  ] }))
@@ -1318,7 +1327,7 @@ var styles7 = import_react_native12.StyleSheet.create({
1318
1327
  var import_auto_paper5 = require("@rific/auto-paper");
1319
1328
  var import_react17 = require("react");
1320
1329
  var import_react_native13 = require("react-native");
1321
- var import_react_native_reanimated14 = require("react-native-reanimated");
1330
+ var import_react_native_reanimated13 = require("react-native-reanimated");
1322
1331
 
1323
1332
  // src/internal/ChromeRegistrar.tsx
1324
1333
  var import_react16 = require("react");
@@ -1359,24 +1368,24 @@ var ScrollViewProvider = ({ blur, chrome, children, fixed = false, footerAboveKe
1359
1368
  const [footerHeight, setFooterHeightState] = (0, import_react17.useState)(null);
1360
1369
  const [progress, setProgress] = (0, import_react17.useState)(null);
1361
1370
  const [progressing, setProgressing] = (0, import_react17.useState)(false);
1362
- const scrollPosition = (0, import_react_native_reanimated14.useSharedValue)(0);
1363
- const listGeneration = (0, import_react_native_reanimated14.useSharedValue)(0);
1371
+ const scrollPosition = (0, import_react_native_reanimated13.useSharedValue)(0);
1372
+ const listGeneration = (0, import_react_native_reanimated13.useSharedValue)(0);
1364
1373
  const jsListGeneration = (0, import_react17.useRef)(0);
1365
- const headerHeightShared = (0, import_react_native_reanimated14.useSharedValue)(0);
1366
- const footerHeightShared = (0, import_react_native_reanimated14.useSharedValue)(0);
1367
- const headerOffset = (0, import_react_native_reanimated14.useSharedValue)(0);
1368
- const ownFooterOffset = (0, import_react_native_reanimated14.useSharedValue)(0);
1369
- const ownStackHeight = (0, import_react_native_reanimated14.useSharedValue)(0);
1374
+ const headerHeightShared = (0, import_react_native_reanimated13.useSharedValue)(0);
1375
+ const footerHeightShared = (0, import_react_native_reanimated13.useSharedValue)(0);
1376
+ const headerOffset = (0, import_react_native_reanimated13.useSharedValue)(0);
1377
+ const ownFooterOffset = (0, import_react_native_reanimated13.useSharedValue)(0);
1378
+ const ownStackHeight = (0, import_react_native_reanimated13.useSharedValue)(0);
1370
1379
  const footerOffset = chromeHost ? chromeHost.offset : ownFooterOffset;
1371
- const chromeWritable = (0, import_react_native_reanimated14.useSharedValue)(!chromeHosted);
1380
+ const chromeWritable = (0, import_react_native_reanimated13.useSharedValue)(!chromeHosted);
1372
1381
  (0, import_react17.useEffect)(() => {
1373
1382
  if (!chromeHosted) chromeWritable.value = true;
1374
1383
  }, [chromeHosted, chromeWritable]);
1375
1384
  const revealChrome = chromeHost?.reveal;
1376
1385
  const stackHeightShared = chromeHosted ? ownStackHeight : footerHeightShared;
1377
- const pullSearchHeightShared = (0, import_react_native_reanimated14.useSharedValue)(0);
1378
- const snapBackHeaderShared = (0, import_react_native_reanimated14.useSharedValue)(false);
1379
- const snapBackFooterShared = (0, import_react_native_reanimated14.useSharedValue)(false);
1386
+ const pullSearchHeightShared = (0, import_react_native_reanimated13.useSharedValue)(0);
1387
+ const snapBackHeaderShared = (0, import_react_native_reanimated13.useSharedValue)(false);
1388
+ const snapBackFooterShared = (0, import_react_native_reanimated13.useSharedValue)(false);
1380
1389
  (0, import_react17.useEffect)(() => {
1381
1390
  snapBackHeaderShared.value = effectiveSnapBackHeader ?? effectiveSnapBack;
1382
1391
  snapBackFooterShared.value = chromeHosted ? chromeSnapBack : effectiveSnapBackFooter ?? effectiveSnapBack;
@@ -1450,25 +1459,28 @@ var ScrollViewSettingsProvider = scrollViewSettingsProvider;
1450
1459
  var import_react19 = require("react");
1451
1460
  var import_react_native14 = require("react-native");
1452
1461
  var import_react_native_gesture_handler4 = require("react-native-gesture-handler");
1453
- var import_react_native_reanimated16 = __toESM(require("react-native-reanimated"));
1462
+ var import_react_native_reanimated15 = __toESM(require("react-native-reanimated"));
1454
1463
 
1455
1464
  // src/internal/useStickyHeaders.ts
1465
+ var import_core7 = require("@rific/core");
1456
1466
  var import_react18 = require("react");
1457
- var import_react_native_reanimated15 = require("react-native-reanimated");
1467
+ var import_react_native_reanimated14 = require("react-native-reanimated");
1458
1468
  var import_react_native_safe_area_context5 = require("react-native-safe-area-context");
1469
+ var import_react_native_worklets4 = require("react-native-worklets");
1459
1470
  function useStickyHeaders(headerFixed, enabled) {
1460
1471
  const { headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } = (0, import_react18.useContext)(ScrollViewContext);
1461
1472
  const insetsTop = (0, import_react_native_safe_area_context5.useSafeAreaInsets)().top;
1462
- const sectionYPositions = (0, import_react_native_reanimated15.useSharedValue)([]);
1463
- const sectionHeights = (0, import_react_native_reanimated15.useSharedValue)([]);
1473
+ const sectionYPositions = (0, import_react_native_reanimated14.useSharedValue)([]);
1474
+ const sectionHeights = (0, import_react_native_reanimated14.useSharedValue)([]);
1464
1475
  const [activeIndex, setActiveIndex] = (0, import_react18.useState)(-1);
1465
- const contentIndexShared = (0, import_react_native_reanimated15.useSharedValue)(-1);
1476
+ const activeIndexKey = (0, import_core7.useWorkletCallback)(setActiveIndex);
1477
+ const contentIndexShared = (0, import_react_native_reanimated14.useSharedValue)(-1);
1466
1478
  (0, import_react18.useLayoutEffect)(() => {
1467
1479
  contentIndexShared.value = activeIndex;
1468
1480
  }, [activeIndex, contentIndexShared]);
1469
1481
  const positionsCache = (0, import_react18.useRef)([]);
1470
1482
  const heightsCache = (0, import_react18.useRef)([]);
1471
- (0, import_react_native_reanimated15.useAnimatedReaction)(
1483
+ (0, import_react_native_reanimated14.useAnimatedReaction)(
1472
1484
  () => {
1473
1485
  if (!enabled) return -1;
1474
1486
  const positions = sectionYPositions.value;
@@ -1493,7 +1505,7 @@ function useStickyHeaders(headerFixed, enabled) {
1493
1505
  return active;
1494
1506
  },
1495
1507
  (curr, prev) => {
1496
- if (curr !== prev) (0, import_react_native_reanimated15.runOnJS)(setActiveIndex)(curr);
1508
+ if (curr !== prev) (0, import_react_native_worklets4.scheduleOnRN)(import_core7.callWorkletCallback, activeIndexKey, curr);
1497
1509
  },
1498
1510
  // Same web-only reanimated gap as useAnimatedStyle elsewhere in this file: this "prepare"
1499
1511
  // function's own SharedValue reads (sectionYPositions, headerHeightShared, scrollPosition,
@@ -1502,7 +1514,7 @@ function useStickyHeaders(headerFixed, enabled) {
1502
1514
  // then never again on web, permanently freezing activeIndex/the active sticky section.
1503
1515
  [enabled, headerFixed, insetsTop, sectionYPositions, headerHeightShared, scrollPosition, snapBackHeaderShared, headerOffset, pullSearchHeightShared]
1504
1516
  );
1505
- const clipStyle = (0, import_react_native_reanimated15.useAnimatedStyle)(() => {
1517
+ const clipStyle = (0, import_react_native_reanimated14.useAnimatedStyle)(() => {
1506
1518
  const hHeight = headerHeightShared.value;
1507
1519
  const scrollPos = scrollPosition.value;
1508
1520
  let stickyTop;
@@ -1516,7 +1528,7 @@ function useStickyHeaders(headerFixed, enabled) {
1516
1528
  }
1517
1529
  return { top: stickyTop };
1518
1530
  }, [enabled, headerFixed, insetsTop, headerHeightShared, scrollPosition, snapBackHeaderShared, headerOffset, pullSearchHeightShared]);
1519
- const overlayStyle = (0, import_react_native_reanimated15.useAnimatedStyle)(() => {
1531
+ const overlayStyle = (0, import_react_native_reanimated14.useAnimatedStyle)(() => {
1520
1532
  const hidden = { opacity: 0, top: 0, transform: [{ translateY: 0 }] };
1521
1533
  if (!enabled) return hidden;
1522
1534
  const index = contentIndexShared.value;
@@ -1568,20 +1580,20 @@ function useStickyHeaders(headerFixed, enabled) {
1568
1580
 
1569
1581
  // src/SectionList.tsx
1570
1582
  var import_jsx_runtime12 = require("react/jsx-runtime");
1571
- var AnimatedSectionList = import_react_native_reanimated16.default.createAnimatedComponent(import_react_native14.SectionList);
1583
+ var AnimatedSectionList = import_react_native_reanimated15.default.createAnimatedComponent(import_react_native14.SectionList);
1572
1584
  var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }) => {
1573
1585
  const scrollView = (0, import_react19.useRef)(null);
1574
1586
  const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props;
1575
1587
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, contentPadding, footerFixed, headerFixed, headerHeight } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, hideUntilMeasured: true, keyboardAware, pullSearchHeight, style });
1576
1588
  const { listGeneration, onListUnmount } = (0, import_react19.useContext)(ScrollViewContext);
1577
- const capturedGeneration = (0, import_react_native_reanimated16.useSharedValue)(-1);
1589
+ const capturedGeneration = (0, import_react_native_reanimated15.useSharedValue)(-1);
1578
1590
  (0, import_react19.useLayoutEffect)(() => {
1579
1591
  const generation = listGeneration.value;
1580
1592
  if (import_react_native14.Platform.OS === "web") {
1581
1593
  capturedGeneration.value = generation;
1582
1594
  return;
1583
1595
  }
1584
- (0, import_react_native_reanimated16.runOnUI)((gen) => {
1596
+ (0, import_react_native_reanimated15.runOnUI)((gen) => {
1585
1597
  "worklet";
1586
1598
  capturedGeneration.value = gen;
1587
1599
  })(generation);
@@ -1702,7 +1714,7 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
1702
1714
  ),
1703
1715
  hiddenHeader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { pointerEvents: "none", style: styles8.measureContainer, children: hiddenHeader }),
1704
1716
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
1705
- usesCustomSticky && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_reanimated16.default.View, { pointerEvents: "none", style: [styles8.stickyClip, clipStyle], children: activeIndex >= 0 && activeIndex < sections.length && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_reanimated16.default.View, { style: [styles8.stickyOverlay, overlayStyle], children: renderSectionHeader({ section: sections[activeIndex] }) }) })
1717
+ usesCustomSticky && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_reanimated15.default.View, { pointerEvents: "none", style: [styles8.stickyClip, clipStyle], children: activeIndex >= 0 && activeIndex < sections.length && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_reanimated15.default.View, { style: [styles8.stickyOverlay, overlayStyle], children: renderSectionHeader({ section: sections[activeIndex] }) }) })
1706
1718
  ] });
1707
1719
  return detectorGesture ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_gesture_handler4.GestureDetector, { gesture: detectorGesture, children: content }) : content;
1708
1720
  };
@@ -1722,14 +1734,14 @@ var useScrollView = () => {
1722
1734
 
1723
1735
  // src/useScrollViewChrome.ts
1724
1736
  var import_react21 = require("react");
1725
- var import_react_native_reanimated17 = require("react-native-reanimated");
1737
+ var import_react_native_reanimated16 = require("react-native-reanimated");
1726
1738
  var noop = () => {
1727
1739
  };
1728
1740
  var useScrollViewChromeStyle = () => {
1729
1741
  const chrome = (0, import_react21.useContext)(ScrollViewChromeContext);
1730
- const fallback = (0, import_react_native_reanimated17.useSharedValue)(0);
1742
+ const fallback = (0, import_react_native_reanimated16.useSharedValue)(0);
1731
1743
  const offset = chrome?.offset ?? fallback;
1732
- return (0, import_react_native_reanimated17.useAnimatedStyle)(() => ({ transform: [{ translateY: offset.value }] }), [offset]);
1744
+ return (0, import_react_native_reanimated16.useAnimatedStyle)(() => ({ transform: [{ translateY: offset.value }] }), [offset]);
1733
1745
  };
1734
1746
  var useScrollViewChromePin = (active) => {
1735
1747
  const chrome = (0, import_react21.useContext)(ScrollViewChromeContext);
package/dist/index.mjs CHANGED
@@ -31,8 +31,10 @@ var styles = StyleSheet.create({
31
31
  });
32
32
 
33
33
  // src/internal/useScrollHandler.ts
34
+ import { callWorkletCallback, useWorkletCallback } from "@rific/core";
34
35
  import { useContext as useContext2 } from "react";
35
- import { runOnJS, useAnimatedScrollHandler, useSharedValue as useSharedValue2, withTiming } from "react-native-reanimated";
36
+ import { useAnimatedScrollHandler, useSharedValue as useSharedValue2, withTiming } from "react-native-reanimated";
37
+ import { scheduleOnRN } from "react-native-worklets";
36
38
 
37
39
  // src/ScrollViewContext.ts
38
40
  import { createContext } from "react";
@@ -279,6 +281,8 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
279
281
  const { chromeHosted, chromeWritable, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared, stackHeightShared } = useContext2(ScrollViewContext);
280
282
  const snapUpAccum = useSharedValue2(0);
281
283
  const fromBottomBounce = useSharedValue2(false);
284
+ const remountSyncedKey = useWorkletCallback((y) => onRemountSynced?.(y));
285
+ const remountSyncRetryKey = useWorkletCallback((y) => onRemountSyncRetry?.(y));
282
286
  return useAnimatedScrollHandler(
283
287
  {
284
288
  onScroll: ({ contentOffset: { x, y }, contentSize: { height: contentHeight }, layoutMeasurement: { height: layoutHeight } }) => {
@@ -287,9 +291,9 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
287
291
  const target = remountSyncTarget.value;
288
292
  if (Math.abs(y - target) < REMOUNT_SYNC_TOLERANCE) {
289
293
  remountSyncTarget.value = null;
290
- if (onRemountSynced) runOnJS(onRemountSynced)(y);
294
+ if (onRemountSynced) scheduleOnRN(callWorkletCallback, remountSyncedKey, y);
291
295
  } else if (onRemountSyncRetry) {
292
- runOnJS(onRemountSyncRetry)(y);
296
+ scheduleOnRN(callWorkletCallback, remountSyncRetryKey, y);
293
297
  }
294
298
  return;
295
299
  }
@@ -373,21 +377,23 @@ import { useAnimatedStyle, useSharedValue as useSharedValue3, withTiming as with
373
377
  import { useSafeAreaInsets } from "react-native-safe-area-context";
374
378
 
375
379
  // src/useKeyboardInset.ts
380
+ import { callWorkletCallback as callWorkletCallback2, useWorkletCallback as useWorkletCallback2 } from "@rific/core";
376
381
  import { useState as useState2 } from "react";
377
382
  import { Platform as Platform2 } from "react-native";
378
383
  import { useKeyboardHandler } from "react-native-keyboard-controller";
379
- import { runOnJS as runOnJS2 } from "react-native-reanimated";
384
+ import { scheduleOnRN as scheduleOnRN2 } from "react-native-worklets";
380
385
  var useKeyboardInsetNative = () => {
381
386
  const [keyboardHeight, setKeyboardHeight] = useState2(0);
387
+ const keyboardHeightKey = useWorkletCallback2(setKeyboardHeight);
382
388
  useKeyboardHandler(
383
389
  {
384
390
  onMove: (e) => {
385
391
  "worklet";
386
- runOnJS2(setKeyboardHeight)(e.height);
392
+ scheduleOnRN2(callWorkletCallback2, keyboardHeightKey, e.height);
387
393
  },
388
394
  onEnd: (e) => {
389
395
  "worklet";
390
- runOnJS2(setKeyboardHeight)(e.height);
396
+ scheduleOnRN2(callWorkletCallback2, keyboardHeightKey, e.height);
391
397
  }
392
398
  },
393
399
  []
@@ -870,10 +876,12 @@ var styles4 = { measureContainer: { left: 0, opacity: 0, position: "absolute", r
870
876
  var FlatList = memo2(FlatListInner);
871
877
 
872
878
  // src/PullSearch.tsx
879
+ import { callWorkletCallback as callWorkletCallback3, useWorkletCallback as useWorkletCallback3 } from "@rific/core";
873
880
  import { forwardRef, useCallback as useCallback5, useContext as useContext8, useEffect as useEffect3, useImperativeHandle, useRef as useRef5, useState as useState4 } from "react";
874
881
  import { StyleSheet as StyleSheet4 } from "react-native";
875
882
  import { Searchbar, useTheme as useTheme3 } from "react-native-paper";
876
- import Animated3, { Extrapolation, interpolate, runOnJS as runOnJS3, useAnimatedReaction, useAnimatedStyle as useAnimatedStyle3 } from "react-native-reanimated";
883
+ import Animated3, { Extrapolation, interpolate, useAnimatedReaction, useAnimatedStyle as useAnimatedStyle3 } from "react-native-reanimated";
884
+ import { scheduleOnRN as scheduleOnRN3 } from "react-native-worklets";
877
885
  import { jsx as jsx6 } from "react/jsx-runtime";
878
886
  var PullSearch = forwardRef(function PullSearch2({ debounce, onChangeText, onHeightChange, placeholder, value: propValue }, ref) {
879
887
  const { headerHeight, scrollPosition } = useContext8(ScrollViewContext);
@@ -892,13 +900,14 @@ var PullSearch = forwardRef(function PullSearch2({ debounce, onChangeText, onHei
892
900
  focus: () => inputRef.current?.focus()
893
901
  }));
894
902
  const blurInput = useCallback5(() => inputRef.current?.blur(), []);
903
+ const blurKey = useWorkletCallback3(blurInput);
895
904
  useAnimatedReaction(
896
905
  () => {
897
906
  if (barHeight === 0) return false;
898
907
  return scrollPosition.value >= -(headerHeight ?? 0) + barHeight;
899
908
  },
900
909
  (isHidden, wasHidden) => {
901
- if (isHidden && !wasHidden) runOnJS3(blurInput)();
910
+ if (isHidden && !wasHidden) scheduleOnRN3(callWorkletCallback3, blurKey);
902
911
  },
903
912
  // scrollPosition has to be listed too, not just read - see useStickyHeaders' useAnimatedReaction
904
913
  // for why: on web, without reanimated's Babel plugin active, an unlisted SharedValue mutation
@@ -1394,15 +1403,18 @@ import { Gesture as Gesture4, GestureDetector as GestureDetector4 } from "react-
1394
1403
  import Animated7, { runOnUI as runOnUI3, useSharedValue as useSharedValue10 } from "react-native-reanimated";
1395
1404
 
1396
1405
  // src/internal/useStickyHeaders.ts
1406
+ import { callWorkletCallback as callWorkletCallback4, useWorkletCallback as useWorkletCallback4 } from "@rific/core";
1397
1407
  import { useCallback as useCallback9, useContext as useContext13, useLayoutEffect as useLayoutEffect8, useRef as useRef10, useState as useState7 } from "react";
1398
- import { runOnJS as runOnJS4, useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as useSharedValue9 } from "react-native-reanimated";
1408
+ import { useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as useSharedValue9 } from "react-native-reanimated";
1399
1409
  import { useSafeAreaInsets as useSafeAreaInsets5 } from "react-native-safe-area-context";
1410
+ import { scheduleOnRN as scheduleOnRN4 } from "react-native-worklets";
1400
1411
  function useStickyHeaders(headerFixed, enabled) {
1401
1412
  const { headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } = useContext13(ScrollViewContext);
1402
1413
  const insetsTop = useSafeAreaInsets5().top;
1403
1414
  const sectionYPositions = useSharedValue9([]);
1404
1415
  const sectionHeights = useSharedValue9([]);
1405
1416
  const [activeIndex, setActiveIndex] = useState7(-1);
1417
+ const activeIndexKey = useWorkletCallback4(setActiveIndex);
1406
1418
  const contentIndexShared = useSharedValue9(-1);
1407
1419
  useLayoutEffect8(() => {
1408
1420
  contentIndexShared.value = activeIndex;
@@ -1434,7 +1446,7 @@ function useStickyHeaders(headerFixed, enabled) {
1434
1446
  return active;
1435
1447
  },
1436
1448
  (curr, prev) => {
1437
- if (curr !== prev) runOnJS4(setActiveIndex)(curr);
1449
+ if (curr !== prev) scheduleOnRN4(callWorkletCallback4, activeIndexKey, curr);
1438
1450
  },
1439
1451
  // Same web-only reanimated gap as useAnimatedStyle elsewhere in this file: this "prepare"
1440
1452
  // function's own SharedValue reads (sectionYPositions, headerHeightShared, scrollPosition,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rific/scroll-view",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Blur styled scroll system for React Native. Floating headers/footers, keyboard awareness, and scroll-away chrome",
5
5
  "keywords": [
6
6
  "react-native",
@@ -66,7 +66,7 @@
66
66
  "@infinitetoken/tsconfig": "^0.6.0",
67
67
  "@reduxjs/toolkit": "^2.12.0",
68
68
  "@rific/auto-paper": "^0.13.3",
69
- "@rific/core": "^0.3.1",
69
+ "@rific/core": "^0.5.0",
70
70
  "@testing-library/dom": "^10.4.1",
71
71
  "@testing-library/react": "^16.3.2",
72
72
  "@types/jest": "^30.0.0",
@@ -92,14 +92,15 @@
92
92
  },
93
93
  "peerDependencies": {
94
94
  "@rific/auto-paper": ">=0.10.0",
95
- "@rific/core": ">=0.1.1",
95
+ "@rific/core": ">=0.5.0",
96
96
  "react": ">=19.0.0",
97
97
  "react-native": ">=0.83.0",
98
98
  "react-native-gesture-handler": ">=2.0.0 <4.0.0",
99
99
  "react-native-keyboard-controller": ">=1.0.0",
100
100
  "react-native-paper": ">=5.0.0",
101
101
  "react-native-reanimated": ">=4.0.0",
102
- "react-native-safe-area-context": ">=5.0.0"
102
+ "react-native-safe-area-context": ">=5.0.0",
103
+ "react-native-worklets": ">=0.5.0"
103
104
  },
104
105
  "publishConfig": {
105
106
  "access": "public"
@@ -1,7 +1,9 @@
1
+ import { callWorkletCallback, useWorkletCallback } from '@rific/core'
1
2
  import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef, useState } from 'react'
2
3
  import { type LayoutChangeEvent, StyleSheet, type TextInput } from 'react-native'
3
4
  import { Searchbar, useTheme } from 'react-native-paper'
4
- import Animated, { Extrapolation, interpolate, runOnJS, useAnimatedReaction, useAnimatedStyle } from 'react-native-reanimated'
5
+ import Animated, { Extrapolation, interpolate, useAnimatedReaction, useAnimatedStyle } from 'react-native-reanimated'
6
+ import { scheduleOnRN } from 'react-native-worklets'
5
7
 
6
8
  import { ScrollViewContext } from './ScrollViewContext'
7
9
 
@@ -38,6 +40,7 @@ export const PullSearch = forwardRef<PullSearchHandle, PullSearchProps>(function
38
40
  }))
39
41
 
40
42
  const blurInput = useCallback(() => inputRef.current?.blur(), [])
43
+ const blurKey = useWorkletCallback(blurInput)
41
44
 
42
45
  useAnimatedReaction(
43
46
  () => {
@@ -45,7 +48,7 @@ export const PullSearch = forwardRef<PullSearchHandle, PullSearchProps>(function
45
48
  return scrollPosition.value >= -(headerHeight ?? 0) + barHeight
46
49
  },
47
50
  (isHidden, wasHidden) => {
48
- if (isHidden && !wasHidden) runOnJS(blurInput)()
51
+ if (isHidden && !wasHidden) scheduleOnRN(callWorkletCallback, blurKey)
49
52
  },
50
53
  // scrollPosition has to be listed too, not just read - see useStickyHeaders' useAnimatedReaction
51
54
  // for why: on web, without reanimated's Babel plugin active, an unlisted SharedValue mutation
@@ -1,6 +1,8 @@
1
+ import { callWorkletCallback, useWorkletCallback } from '@rific/core'
1
2
  import { useContext } from 'react'
2
3
  import type { SharedValue } from 'react-native-reanimated'
3
- import { runOnJS, useAnimatedScrollHandler, useSharedValue, withTiming } from 'react-native-reanimated'
4
+ import { useAnimatedScrollHandler, useSharedValue, withTiming } from 'react-native-reanimated'
5
+ import { scheduleOnRN } from 'react-native-worklets'
4
6
 
5
7
  import { ScrollViewContext } from '../ScrollViewContext'
6
8
  import { REMOUNT_SYNC_TOLERANCE } from '../useScrollInit'
@@ -24,6 +26,10 @@ export function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold
24
26
  const { chromeHosted, chromeWritable, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared, stackHeightShared } = useContext(ScrollViewContext)
25
27
  const snapUpAccum = useSharedValue(0)
26
28
  const fromBottomBounce = useSharedValue(false)
29
+ // Worklets never get the consumer's callbacks themselves: react-native-worklets holds a runOnJS target natively for as
30
+ // long as the worklet lives, which pinned the list. They call the module-level callWorkletCallback by key.
31
+ const remountSyncedKey = useWorkletCallback((y: number) => onRemountSynced?.(y))
32
+ const remountSyncRetryKey = useWorkletCallback((y: number) => onRemountSyncRetry?.(y))
27
33
 
28
34
  return useAnimatedScrollHandler(
29
35
  {
@@ -33,9 +39,9 @@ export function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold
33
39
  const target = remountSyncTarget.value
34
40
  if (Math.abs(y - target) < REMOUNT_SYNC_TOLERANCE) {
35
41
  remountSyncTarget.value = null
36
- if (onRemountSynced) runOnJS(onRemountSynced)(y)
42
+ if (onRemountSynced) scheduleOnRN(callWorkletCallback, remountSyncedKey, y)
37
43
  } else if (onRemountSyncRetry) {
38
- runOnJS(onRemountSyncRetry)(y)
44
+ scheduleOnRN(callWorkletCallback, remountSyncRetryKey, y)
39
45
  }
40
46
  return
41
47
  }
@@ -1,6 +1,8 @@
1
+ import { callWorkletCallback, useWorkletCallback } from '@rific/core'
1
2
  import { useCallback, useContext, useLayoutEffect, useRef, useState } from 'react'
2
- import { runOnJS, useAnimatedReaction, useAnimatedStyle, useSharedValue } from 'react-native-reanimated'
3
+ import { useAnimatedReaction, useAnimatedStyle, useSharedValue } from 'react-native-reanimated'
3
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
+ import { scheduleOnRN } from 'react-native-worklets'
4
6
 
5
7
  import { ScrollViewContext } from '../ScrollViewContext'
6
8
 
@@ -19,6 +21,7 @@ export function useStickyHeaders(headerFixed: boolean, enabled: boolean): Sticky
19
21
  const sectionYPositions = useSharedValue<number[]>([])
20
22
  const sectionHeights = useSharedValue<number[]>([])
21
23
  const [activeIndex, setActiveIndex] = useState(-1)
24
+ const activeIndexKey = useWorkletCallback(setActiveIndex)
22
25
  // Mirrors activeIndex React state but lives on the UI thread for overlayStyle.
23
26
  // Updated via useLayoutEffect so content and style always change together.
24
27
  const contentIndexShared = useSharedValue(-1)
@@ -60,7 +63,7 @@ export function useStickyHeaders(headerFixed: boolean, enabled: boolean): Sticky
60
63
  return active
61
64
  },
62
65
  (curr, prev) => {
63
- if (curr !== prev) runOnJS(setActiveIndex)(curr)
66
+ if (curr !== prev) scheduleOnRN(callWorkletCallback, activeIndexKey, curr)
64
67
  },
65
68
  // Same web-only reanimated gap as useAnimatedStyle elsewhere in this file: this "prepare"
66
69
  // function's own SharedValue reads (sectionYPositions, headerHeightShared, scrollPosition,
@@ -1,19 +1,21 @@
1
+ import { callWorkletCallback, useWorkletCallback } from '@rific/core'
1
2
  import { useState } from 'react'
2
3
  import { Platform } from 'react-native'
3
4
  import { useKeyboardHandler } from 'react-native-keyboard-controller'
4
- import { runOnJS } from 'react-native-reanimated'
5
+ import { scheduleOnRN } from 'react-native-worklets'
5
6
 
6
7
  const useKeyboardInsetNative = () => {
7
8
  const [keyboardHeight, setKeyboardHeight] = useState(0)
9
+ const keyboardHeightKey = useWorkletCallback(setKeyboardHeight)
8
10
  useKeyboardHandler(
9
11
  {
10
12
  onMove: (e) => {
11
13
  'worklet'
12
- runOnJS(setKeyboardHeight)(e.height)
14
+ scheduleOnRN(callWorkletCallback, keyboardHeightKey, e.height)
13
15
  },
14
16
  onEnd: (e) => {
15
17
  'worklet'
16
- runOnJS(setKeyboardHeight)(e.height)
18
+ scheduleOnRN(callWorkletCallback, keyboardHeightKey, e.height)
17
19
  }
18
20
  },
19
21
  []