@tamagui/sheet 2.3.2 → 2.3.3-1782462397214

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.
Files changed (44) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/cjs/SheetImplementationCustom.cjs +36 -28
  3. package/dist/cjs/SheetImplementationCustom.native.js +40 -32
  4. package/dist/cjs/SheetImplementationCustom.native.js.map +1 -1
  5. package/dist/cjs/SheetScrollView.cjs +34 -15
  6. package/dist/cjs/SheetScrollView.native.js +36 -16
  7. package/dist/cjs/SheetScrollView.native.js.map +1 -1
  8. package/dist/cjs/useGestureHandlerPan.cjs +61 -8
  9. package/dist/cjs/useGestureHandlerPan.native.js +64 -8
  10. package/dist/cjs/useGestureHandlerPan.native.js.map +1 -1
  11. package/dist/esm/SheetImplementationCustom.mjs +37 -31
  12. package/dist/esm/SheetImplementationCustom.mjs.map +1 -1
  13. package/dist/esm/SheetImplementationCustom.native.js +41 -35
  14. package/dist/esm/SheetImplementationCustom.native.js.map +1 -1
  15. package/dist/esm/SheetScrollView.mjs +34 -15
  16. package/dist/esm/SheetScrollView.mjs.map +1 -1
  17. package/dist/esm/SheetScrollView.native.js +36 -16
  18. package/dist/esm/SheetScrollView.native.js.map +1 -1
  19. package/dist/esm/useGestureHandlerPan.mjs +62 -9
  20. package/dist/esm/useGestureHandlerPan.mjs.map +1 -1
  21. package/dist/esm/useGestureHandlerPan.native.js +65 -9
  22. package/dist/esm/useGestureHandlerPan.native.js.map +1 -1
  23. package/dist/jsx/SheetImplementationCustom.mjs +37 -31
  24. package/dist/jsx/SheetImplementationCustom.mjs.map +1 -1
  25. package/dist/jsx/SheetImplementationCustom.native.js +40 -32
  26. package/dist/jsx/SheetImplementationCustom.native.js.map +1 -1
  27. package/dist/jsx/SheetScrollView.mjs +34 -15
  28. package/dist/jsx/SheetScrollView.mjs.map +1 -1
  29. package/dist/jsx/SheetScrollView.native.js +36 -16
  30. package/dist/jsx/SheetScrollView.native.js.map +1 -1
  31. package/dist/jsx/useGestureHandlerPan.mjs +62 -9
  32. package/dist/jsx/useGestureHandlerPan.mjs.map +1 -1
  33. package/dist/jsx/useGestureHandlerPan.native.js +64 -8
  34. package/dist/jsx/useGestureHandlerPan.native.js.map +1 -1
  35. package/package.json +20 -20
  36. package/src/SheetImplementationCustom.tsx +54 -46
  37. package/src/SheetScrollView.tsx +30 -11
  38. package/src/types.tsx +3 -0
  39. package/src/useGestureHandlerPan.tsx +64 -10
  40. package/types/SheetImplementationCustom.d.ts.map +1 -1
  41. package/types/SheetScrollView.d.ts.map +1 -1
  42. package/types/types.d.ts +1 -0
  43. package/types/types.d.ts.map +1 -1
  44. package/types/useGestureHandlerPan.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/sheet",
3
- "version": "2.3.2",
3
+ "version": "2.3.3-1782462397214",
4
4
  "license": "MIT",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
@@ -54,27 +54,27 @@
54
54
  "clean": "tamagui-build clean"
55
55
  },
56
56
  "dependencies": {
57
- "@tamagui/adapt": "2.3.2",
58
- "@tamagui/animate-presence": "2.3.2",
59
- "@tamagui/animations-react-native": "2.3.2",
60
- "@tamagui/compose-refs": "2.3.2",
61
- "@tamagui/constants": "2.3.2",
62
- "@tamagui/core": "2.3.2",
63
- "@tamagui/create-context": "2.3.2",
64
- "@tamagui/helpers": "2.3.2",
65
- "@tamagui/native": "2.3.2",
66
- "@tamagui/portal": "2.3.2",
67
- "@tamagui/remove-scroll": "2.3.2",
68
- "@tamagui/scroll-view": "2.3.2",
69
- "@tamagui/stacks": "2.3.2",
70
- "@tamagui/use-constant": "2.3.2",
71
- "@tamagui/use-controllable-state": "2.3.2",
72
- "@tamagui/use-did-finish-ssr": "2.3.2",
73
- "@tamagui/use-keyboard-visible": "2.3.2",
74
- "@tamagui/z-index-stack": "2.3.2"
57
+ "@tamagui/adapt": "2.3.3-1782462397214",
58
+ "@tamagui/animate-presence": "2.3.3-1782462397214",
59
+ "@tamagui/animations-react-native": "2.3.3-1782462397214",
60
+ "@tamagui/compose-refs": "2.3.3-1782462397214",
61
+ "@tamagui/constants": "2.3.3-1782462397214",
62
+ "@tamagui/core": "2.3.3-1782462397214",
63
+ "@tamagui/create-context": "2.3.3-1782462397214",
64
+ "@tamagui/helpers": "2.3.3-1782462397214",
65
+ "@tamagui/native": "2.3.3-1782462397214",
66
+ "@tamagui/portal": "2.3.3-1782462397214",
67
+ "@tamagui/remove-scroll": "2.3.3-1782462397214",
68
+ "@tamagui/scroll-view": "2.3.3-1782462397214",
69
+ "@tamagui/stacks": "2.3.3-1782462397214",
70
+ "@tamagui/use-constant": "2.3.3-1782462397214",
71
+ "@tamagui/use-controllable-state": "2.3.3-1782462397214",
72
+ "@tamagui/use-did-finish-ssr": "2.3.3-1782462397214",
73
+ "@tamagui/use-keyboard-visible": "2.3.3-1782462397214",
74
+ "@tamagui/z-index-stack": "2.3.3-1782462397214"
75
75
  },
76
76
  "devDependencies": {
77
- "@tamagui/build": "2.3.2",
77
+ "@tamagui/build": "2.3.3-1782462397214",
78
78
  "react": ">=19",
79
79
  "react-native": "0.83.2",
80
80
  "react-native-gesture-handler": "~2.30.0",
@@ -309,8 +309,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
309
309
  const keyboardStableFrameHeight =
310
310
  isWebKbSheet && isKeyboardVisible && frameSize > 0 ? frameSize : 0
311
311
 
312
- const { useAnimatedNumber, useAnimatedNumberStyle, useAnimatedNumberReaction } =
313
- animationDriver
312
+ const { useAnimatedNumber, useAnimatedNumberStyle } = animationDriver
314
313
  const AnimatedView = (animationDriver.View ?? TamaguiView) as typeof Animated.View
315
314
 
316
315
  useIsomorphicLayoutEffect(() => {
@@ -346,42 +345,52 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
346
345
  // safety fallback timer for sheet close opacity
347
346
  const opacityFallbackTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)
348
347
 
349
- useAnimatedNumberReaction(
350
- {
351
- value: animatedNumber,
352
- hostRef: sheetRef,
353
- },
354
- React.useCallback(
355
- (value) => {
356
- at.current = value
357
- scrollBridge.paneY = value
358
- // update isAtTop for scroll enable/disable
359
- // activePositions[0] is the top snap point (keyboard-adjusted minY)
360
- const minY = activePositions[0]
361
- const wasAtTop = scrollBridge.isAtTop
362
- const nowAtTop = value <= minY + 5
363
- if (wasAtTop !== nowAtTop) {
364
- scrollBridge.isAtTop = nowAtTop
365
- // when reaching top, enable scroll; when leaving top, disable scroll
366
- // this preemptively sets scroll state before any gestures start
367
- if (nowAtTop) {
368
- // if scroll drifted during drag (e.g. fast swipe from position 1),
369
- // reset it to 0 before enabling free scroll
370
- if (scrollBridge.y > 0) {
371
- scrollBridge.forceScrollTo?.(0)
372
- scrollBridge.y = 0
373
- }
374
- scrollBridge.scrollLockY = undefined
375
- scrollBridge.setScrollEnabled?.(true)
376
- } else {
377
- scrollBridge.scrollLockY = 0
378
- scrollBridge.setScrollEnabled?.(false)
379
- }
348
+ const syncAnimatedPosition = useEvent((value: number) => {
349
+ at.current = value
350
+ scrollBridge.paneY = value
351
+
352
+ // update isAtTop for scroll enable/disable. activePositions[0] is the
353
+ // top snap point (keyboard-adjusted minY).
354
+ const minY = activePositions[0]
355
+ const wasAtTop = scrollBridge.isAtTop
356
+ const nowAtTop = value <= minY + 5
357
+ if (wasAtTop === nowAtTop) return
358
+
359
+ scrollBridge.isAtTop = nowAtTop
360
+ if (nowAtTop) {
361
+ if (scrollBridge.lockScrollAtTop) {
362
+ if (scrollBridge.y > 0) {
363
+ scrollBridge.forceScrollTo?.(0)
364
+ scrollBridge.y = 0
380
365
  }
381
- },
382
- [animationDriver, activePositions]
383
- )
384
- )
366
+ scrollBridge.scrollLockY = 0
367
+ scrollBridge.setScrollEnabled?.(false, 0)
368
+ return
369
+ }
370
+ // if scroll drifted during drag (e.g. fast swipe from position 1),
371
+ // reset it to 0 before enabling free scroll.
372
+ if (scrollBridge.y > 0) {
373
+ scrollBridge.forceScrollTo?.(0)
374
+ scrollBridge.y = 0
375
+ }
376
+ scrollBridge.scrollLockY = undefined
377
+ scrollBridge.setScrollEnabled?.(true)
378
+ } else {
379
+ scrollBridge.scrollLockY = 0
380
+ scrollBridge.setScrollEnabled?.(false)
381
+ }
382
+ })
383
+
384
+ const setAnimatedPositionDirect = useEvent((value: number) => {
385
+ syncAnimatedPosition(value)
386
+ animatedNumber.setValue(value, { type: 'direct' })
387
+ })
388
+
389
+ const getAnimatedPosition = useEvent(() => {
390
+ const value = animatedNumber.getValue()
391
+ syncAnimatedPosition(value)
392
+ return value
393
+ })
385
394
 
386
395
  function stopSpring() {
387
396
  animatedNumber.stop()
@@ -422,6 +431,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
422
431
  }
423
432
 
424
433
  const animationCompleteCallback = () => {
434
+ syncAnimatedPosition(toValue)
425
435
  if (opacityFallbackTimer.current) {
426
436
  clearTimeout(opacityFallbackTimer.current)
427
437
  opacityFallbackTimer.current = null
@@ -485,6 +495,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
485
495
  duration: 0,
486
496
  },
487
497
  () => {
498
+ syncAnimatedPosition(screenSize)
488
499
  // imperfect but struggling to render properly here
489
500
  setTimeout(() => {
490
501
  setDisableAnimation(false)
@@ -678,7 +689,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
678
689
  const grant = () => {
679
690
  setPanning(true)
680
691
  stopSpring()
681
- startY = at.current
692
+ startY = getAnimatedPosition()
682
693
  }
683
694
 
684
695
  let isExternalDrag = false
@@ -700,7 +711,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
700
711
  grant()
701
712
  }
702
713
  const to = dy + startY
703
- animatedNumber.setValue(resisted(to, minY), { type: 'direct' })
714
+ setAnimatedPositionDirect(resisted(to, minY))
704
715
  }
705
716
 
706
717
  scrollBridge.release = release
@@ -733,7 +744,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
733
744
  scrollBridge.setParentDragging(true)
734
745
  }
735
746
 
736
- animatedNumber.setValue(to, { type: 'direct' })
747
+ setAnimatedPositionDirect(to)
737
748
  },
738
749
  onPanResponderEnd: finish,
739
750
  onPanResponderTerminate: finish,
@@ -799,15 +810,12 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
799
810
  stopSpring,
800
811
  scrollBridge,
801
812
  setIsDragging,
802
- getCurrentPosition: () => at.current,
813
+ getCurrentPosition: getAnimatedPosition,
803
814
  resisted,
804
815
  disableDrag,
805
816
  isShowingInnerSheet,
806
- setAnimatedPosition: (val: number) => {
807
- // directly set the animated value for smooth dragging
808
- at.current = val
809
- animatedNumber.setValue(val, { type: 'direct' })
810
- },
817
+ // directly set the animated value for smooth dragging
818
+ setAnimatedPosition: setAnimatedPositionDirect,
811
819
  dismissOnSnapToBottom,
812
820
  snapPointsMode,
813
821
  isKeyboardVisible,
@@ -90,16 +90,28 @@ export const SheetScrollView = React.forwardRef<
90
90
 
91
91
  // RNGH scroll locking state
92
92
  const currentScrollOffset = useRef(0)
93
+ const lastEmittedScrollOffset = useRef(0)
93
94
  const lockedScrollY = useRef(0)
94
95
  const focusedInputScrollFrame = useRef(0)
95
96
 
96
97
  const setScrollEnabled = (next: boolean, lockTo?: number) => {
97
98
  if (!next) {
98
- const lockY = lockTo ?? currentScrollOffset.current
99
+ const lockY = lockTo ?? scrollBridge.scrollLockY ?? currentScrollOffset.current
100
+ if (scrollBridge.enabled === false && scrollBridge.scrollLockY === lockY) {
101
+ return
102
+ }
103
+ scrollBridge.enabled = false
99
104
  lockedScrollY.current = lockY
100
105
  scrollBridge.scrollLockY = lockY
101
- scrollRef.current?.scrollTo?.({ x: 0, y: lockY, animated: false })
106
+ if (currentScrollOffset.current !== lockY) {
107
+ scrollRef.current?.scrollTo?.({ x: 0, y: lockY, animated: false })
108
+ currentScrollOffset.current = lockY
109
+ }
102
110
  } else {
111
+ if (scrollBridge.enabled === true && scrollBridge.scrollLockY === undefined) {
112
+ return
113
+ }
114
+ scrollBridge.enabled = true
103
115
  lockedScrollY.current = currentScrollOffset.current
104
116
  scrollBridge.scrollLockY = undefined
105
117
  }
@@ -107,6 +119,7 @@ export const SheetScrollView = React.forwardRef<
107
119
 
108
120
  const forceScrollTo = (y: number) => {
109
121
  scrollRef.current?.scrollTo?.({ x: 0, y, animated: false })
122
+ currentScrollOffset.current = y
110
123
  }
111
124
 
112
125
  const scrollFocusedInputClearOfKeyboard = React.useCallback(() => {
@@ -259,22 +272,27 @@ export const SheetScrollView = React.forwardRef<
259
272
  animated: false,
260
273
  })
261
274
  }
275
+ currentScrollOffset.current = scrollBridge.scrollLockY
262
276
  scrollBridge.y = scrollBridge.scrollLockY
263
- onScroll?.({
264
- ...e,
265
- nativeEvent: {
266
- ...e.nativeEvent,
267
- contentOffset: {
268
- ...e.nativeEvent.contentOffset,
269
- y: scrollBridge.scrollLockY,
277
+ if (lastEmittedScrollOffset.current !== scrollBridge.scrollLockY) {
278
+ lastEmittedScrollOffset.current = scrollBridge.scrollLockY
279
+ onScroll?.({
280
+ ...e,
281
+ nativeEvent: {
282
+ ...e.nativeEvent,
283
+ contentOffset: {
284
+ ...e.nativeEvent.contentOffset,
285
+ y: scrollBridge.scrollLockY,
286
+ },
270
287
  },
271
- },
272
- })
288
+ })
289
+ }
273
290
  return
274
291
  }
275
292
 
276
293
  scrollBridge.y = y
277
294
  if (y > 0) scrollBridge.scrollStartY = -1
295
+ lastEmittedScrollOffset.current = y
278
296
  onScroll?.(e)
279
297
  }}
280
298
  contentContainerStyle={{ minHeight: '100%' }}
@@ -306,6 +324,7 @@ export const SheetScrollView = React.forwardRef<
306
324
  currentScrollOffset.current = y
307
325
  scrollBridge.y = y
308
326
  if (y > 0) scrollBridge.scrollStartY = -1
327
+ lastEmittedScrollOffset.current = y
309
328
  onScroll?.(e)
310
329
  }}
311
330
  contentContainerStyle={{ minHeight: '100%' }}
package/src/types.tsx CHANGED
@@ -126,6 +126,9 @@ export type ScrollBridge = {
126
126
  _lastTouchY?: number
127
127
  // scroll lock position for forcing scroll back when pan handles
128
128
  scrollLockY?: number
129
+ // keep scroll locked while a drag that started below the top snap is still
130
+ // deciding whether to hand off into content scrolling.
131
+ lockScrollAtTop?: boolean
129
132
  // force scroll to position (compensates for async setNativeProps)
130
133
  forceScrollTo?: (y: number) => void
131
134
  // whether sheet is at top position (for scroll enable/disable)
@@ -1,5 +1,5 @@
1
1
  import { isWeb } from '@tamagui/constants'
2
- import { useCallback, useMemo, useRef, type RefObject } from 'react'
2
+ import { useCallback, useEffect, useMemo, useRef, type RefObject } from 'react'
3
3
  import { getGestureHandlerState, isGestureHandlerEnabled } from './gestureState'
4
4
  import { getSheetReleasePosition } from './keyboardAvoidance'
5
5
  import type { ScrollBridge, SnapPointsMode } from './types'
@@ -7,6 +7,7 @@ import type { ScrollBridge, SnapPointsMode } from './types'
7
7
  // threshold in pixels for considering sheet "at top" position
8
8
  // allows for small measurement variations
9
9
  const AT_TOP_THRESHOLD = 5
10
+ const SCROLL_HANDOFF_THRESHOLD = 160
10
11
 
11
12
  interface GesturePanConfig {
12
13
  positions: number[]
@@ -104,18 +105,45 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
104
105
  frozenIsKeyboardVisible: false,
105
106
  // whether pan gesture actually started (vs just a tap in onBegin)
106
107
  panStarted: false,
108
+ startedBelowTop: false,
109
+ upwardDragAfterTop: 0,
110
+ scrollUnlockedAfterTop: false,
111
+ keepScrollLockedAfterEnd: false,
107
112
  })
113
+ const unlockScrollTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
114
+
115
+ useEffect(() => {
116
+ return () => {
117
+ if (unlockScrollTimer.current) {
118
+ clearTimeout(unlockScrollTimer.current)
119
+ unlockScrollTimer.current = null
120
+ }
121
+ }
122
+ }, [])
108
123
 
109
124
  const onStart = useCallback(() => {
110
125
  stopSpring()
111
126
  }, [stopSpring])
112
127
 
113
128
  const onEnd = useCallback(
114
- (closestPoint: number, animationOverride?: any) => {
129
+ (closestPoint: number, animationOverride?: any, keepScrollLocked = false) => {
130
+ if (unlockScrollTimer.current) {
131
+ clearTimeout(unlockScrollTimer.current)
132
+ unlockScrollTimer.current = null
133
+ }
115
134
  setIsDragging(false)
116
135
  scrollBridge.setParentDragging(false)
117
- // re-enable scroll when gesture ends
118
- scrollBridge.setScrollEnabled?.(true)
136
+ scrollBridge.lockScrollAtTop = false
137
+ if (keepScrollLocked) {
138
+ scrollBridge.setScrollEnabled?.(false, 0)
139
+ unlockScrollTimer.current = setTimeout(() => {
140
+ unlockScrollTimer.current = null
141
+ scrollBridge.setScrollEnabled?.(true)
142
+ }, 160)
143
+ } else {
144
+ // re-enable scroll when gesture ends
145
+ scrollBridge.setScrollEnabled?.(true)
146
+ }
119
147
  setPosition(closestPoint)
120
148
  animateTo(closestPoint, animationOverride)
121
149
  },
@@ -173,6 +201,15 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
173
201
  gs.frozenPositions = [...positions]
174
202
  gs.frozenMinY = minY
175
203
  gs.frozenIsKeyboardVisible = releaseConfigRef.current.isKeyboardVisible
204
+ gs.startedBelowTop = !atTop
205
+ gs.upwardDragAfterTop = 0
206
+ gs.scrollUnlockedAfterTop = false
207
+ gs.keepScrollLockedAfterEnd = false
208
+ scrollBridge.lockScrollAtTop = false
209
+ if (unlockScrollTimer.current) {
210
+ clearTimeout(unlockScrollTimer.current)
211
+ unlockScrollTimer.current = null
212
+ }
176
213
 
177
214
  // if sheet not at top, DISABLE SCROLL immediately and lock to 0
178
215
  // this prevents scroll from firing before pan takes over
@@ -251,8 +288,18 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
251
288
  // if there's scrollable content, let scroll handle so user can scroll into content
252
289
  // resistance only applies when there's NO scrollable content
253
290
  if (hasScrollableContent) {
254
- // content is scrollable - let scroll handle (user wants to scroll down into content)
255
- panHandles = false
291
+ if (gs.startedBelowTop && !gs.scrollUnlockedAfterTop) {
292
+ gs.upwardDragAfterTop += Math.max(0, -deltaY)
293
+ if (gs.upwardDragAfterTop >= SCROLL_HANDOFF_THRESHOLD) {
294
+ gs.scrollUnlockedAfterTop = true
295
+ panHandles = false
296
+ } else {
297
+ panHandles = true
298
+ }
299
+ } else {
300
+ // content is scrollable - let scroll handle (user wants to scroll down into content)
301
+ panHandles = false
302
+ }
256
303
  } else {
257
304
  // no scrollable content -> pan handles for resistance effect
258
305
  panHandles = true
@@ -261,6 +308,7 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
261
308
  }
262
309
 
263
310
  if (panHandles) {
311
+ scrollBridge.lockScrollAtTop = gs.startedBelowTop && !gs.scrollUnlockedAfterTop
264
312
  // pan handles - disable scroll and move sheet
265
313
  // when swiping down at top after scroll was engaged: lock at current scroll position
266
314
  // (handoff from scroll to pan — preserve scroll offset)
@@ -278,17 +326,22 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
278
326
  setAnimatedPosition(newPosition)
279
327
  scrollBridge.setParentDragging(newPosition > minY)
280
328
  } else {
329
+ scrollBridge.lockScrollAtTop = false
281
330
  // scroll handles - enable scroll so it can move freely
282
331
  scrollBridge.setScrollEnabled?.(true)
332
+ scrollBridge.setParentDragging(false)
283
333
  // don't accumulate offset when scroll is handling
284
334
  }
285
335
  })
286
336
  .onEnd((event: { velocityY: number }) => {
287
337
  const { velocityY } = event
288
338
  const currentPos = gs.startY + gs.accumulatedOffset
339
+ const keepScrollLockedAfterEnd = gs.startedBelowTop && !gs.scrollUnlockedAfterTop
289
340
 
290
341
  // clear scroll lock
291
- scrollBridge.scrollLockY = undefined
342
+ scrollBridge.lockScrollAtTop = false
343
+ scrollBridge.scrollLockY = keepScrollLockedAfterEnd ? 0 : undefined
344
+ gs.keepScrollLockedAfterEnd = keepScrollLockedAfterEnd
292
345
 
293
346
  // use frozen positions from gesture start — keyboard may have dismissed
294
347
  // during drag (input blur), reverting activePositions. Frozen positions
@@ -301,7 +354,7 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
301
354
 
302
355
  // if sheet is at top and scroll is engaged, just stay at top
303
356
  if (currentPos <= snapMinY + AT_TOP_THRESHOLD && scrollBridge.y > 0) {
304
- onEnd(0)
357
+ onEnd(0, undefined, keepScrollLockedAfterEnd)
305
358
  return
306
359
  }
307
360
 
@@ -321,11 +374,12 @@ export function useGestureHandlerPan(config: GesturePanConfig): GesturePanResult
321
374
  isWeb,
322
375
  })
323
376
 
324
- onEnd(closestPoint)
377
+ onEnd(closestPoint, undefined, keepScrollLockedAfterEnd)
325
378
  })
326
379
  .onFinalize(() => {
327
380
  // clear scroll lock on finalize too (safety)
328
- scrollBridge.scrollLockY = undefined
381
+ scrollBridge.lockScrollAtTop = false
382
+ scrollBridge.scrollLockY = gs.keepScrollLockedAfterEnd ? 0 : undefined
329
383
  if (gs.panStarted) {
330
384
  // real pan gesture — reset isDragging (also un-pauses keyboard handler + flushes)
331
385
  setIsDragging(false)
@@ -1 +1 @@
1
- {"version":3,"file":"SheetImplementationCustom.d.ts","sourceRoot":"","sources":["../src/SheetImplementationCustom.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAOvC,OAAO,EAA4B,IAAI,EAAE,MAAM,cAAc,CAAA;AAmB7D,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,SAAS,CAAA;AAmCzD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAo9BrC,CAAA"}
1
+ {"version":3,"file":"SheetImplementationCustom.d.ts","sourceRoot":"","sources":["../src/SheetImplementationCustom.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAOvC,OAAO,EAA4B,IAAI,EAAE,MAAM,cAAc,CAAA;AAmB7D,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,SAAS,CAAA;AAmCzD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BA49BrC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SheetScrollView.d.ts","sourceRoot":"","sources":["../src/SheetScrollView.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,cAAc,CAAA;AAgB9D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCAyS3B,CAAA"}
1
+ {"version":3,"file":"SheetScrollView.d.ts","sourceRoot":"","sources":["../src/SheetScrollView.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,cAAc,CAAA;AAgB9D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCA4T3B,CAAA"}
package/types/types.d.ts CHANGED
@@ -102,6 +102,7 @@ export type ScrollBridge = {
102
102
  setScrollEnabled?: (enabled: boolean, lockTo?: number) => void;
103
103
  _lastTouchY?: number;
104
104
  scrollLockY?: number;
105
+ lockScrollAtTop?: boolean;
105
106
  forceScrollTo?: (y: number) => void;
106
107
  isAtTop?: boolean;
107
108
  snapToPosition?: (positionIndex: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useGestureHandlerPan.d.ts","sourceRoot":"","sources":["../src/useGestureHandlerPan.tsx"],"names":[],"mappings":"AACA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGpE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAM3D,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IACzD,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,kBAAkB,EAAE,MAAM,MAAM,CAAA;IAChC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAE3B,mBAAmB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAE1C,gBAAgB,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IAExC,oBAAoB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CAC1C;AAED,UAAU,gBAAgB;IACxB,UAAU,EAAE,GAAG,GAAG,IAAI,CAAA;IACtB,aAAa,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IAC7B,qBAAqB,EAAE,OAAO,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAuT/E"}
1
+ {"version":3,"file":"useGestureHandlerPan.d.ts","sourceRoot":"","sources":["../src/useGestureHandlerPan.tsx"],"names":[],"mappings":"AACA,OAAO,EAA2C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAG/E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAO3D,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IACzD,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,kBAAkB,EAAE,MAAM,MAAM,CAAA;IAChC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAE3B,mBAAmB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAE1C,gBAAgB,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IAExC,oBAAoB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CAC1C;AAED,UAAU,gBAAgB;IACxB,UAAU,EAAE,GAAG,GAAG,IAAI,CAAA;IACtB,aAAa,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IAC7B,qBAAqB,EAAE,OAAO,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CA4W/E"}