@tamagui/sheet 1.0.1-beta.133 → 1.0.1-beta.136

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 (47) hide show
  1. package/dist/cjs/RemoveScrollProps.js +17 -0
  2. package/dist/cjs/RemoveScrollProps.js.map +7 -0
  3. package/dist/cjs/SHEET_HANDLE_NAME.js +35 -0
  4. package/dist/cjs/SHEET_HANDLE_NAME.js.map +7 -0
  5. package/dist/cjs/Sheet.js +61 -118
  6. package/dist/cjs/Sheet.js.map +2 -2
  7. package/dist/cjs/SheetContext.js +38 -0
  8. package/dist/cjs/SheetContext.js.map +7 -0
  9. package/dist/cjs/SheetScrollView.js +115 -0
  10. package/dist/cjs/SheetScrollView.js.map +7 -0
  11. package/dist/cjs/types.js +17 -0
  12. package/dist/cjs/types.js.map +7 -0
  13. package/dist/esm/RemoveScrollProps.js +1 -0
  14. package/dist/esm/RemoveScrollProps.js.map +7 -0
  15. package/dist/esm/SHEET_HANDLE_NAME.js +9 -0
  16. package/dist/esm/SHEET_HANDLE_NAME.js.map +7 -0
  17. package/dist/esm/Sheet.js +54 -113
  18. package/dist/esm/Sheet.js.map +2 -2
  19. package/dist/esm/SheetContext.js +11 -0
  20. package/dist/esm/SheetContext.js.map +7 -0
  21. package/dist/esm/SheetScrollView.js +88 -0
  22. package/dist/esm/SheetScrollView.js.map +7 -0
  23. package/dist/esm/types.js +1 -0
  24. package/dist/esm/types.js.map +7 -0
  25. package/dist/jsx/RemoveScrollProps.js +1 -0
  26. package/dist/jsx/RemoveScrollProps.js.map +7 -0
  27. package/dist/jsx/SHEET_HANDLE_NAME.js +9 -0
  28. package/dist/jsx/SHEET_HANDLE_NAME.js.map +7 -0
  29. package/dist/jsx/Sheet.js +58 -101
  30. package/dist/jsx/Sheet.js.map +2 -2
  31. package/dist/jsx/SheetContext.js +11 -0
  32. package/dist/jsx/SheetContext.js.map +7 -0
  33. package/dist/jsx/SheetScrollView.js +77 -0
  34. package/dist/jsx/SheetScrollView.js.map +7 -0
  35. package/dist/jsx/types.js +1 -0
  36. package/dist/jsx/types.js.map +7 -0
  37. package/package.json +9 -8
  38. package/src/SHEET_HANDLE_NAME.tsx +4 -0
  39. package/src/Sheet.tsx +82 -203
  40. package/src/SheetContext.tsx +25 -0
  41. package/src/SheetScrollView.tsx +109 -0
  42. package/src/types.tsx +44 -0
  43. package/types/SHEET_HANDLE_NAME.d.ts +4 -0
  44. package/types/Sheet.d.ts +21 -56
  45. package/types/SheetContext.d.ts +36 -0
  46. package/types/SheetScrollView.d.ts +4 -0
  47. package/types/types.d.ts +40 -0
package/src/Sheet.tsx CHANGED
@@ -4,7 +4,6 @@ import {
4
4
  Slot,
5
5
  TamaguiElement,
6
6
  Theme,
7
- composeEventHandlers,
8
7
  isClient,
9
8
  isWeb,
10
9
  mergeEvent,
@@ -16,13 +15,11 @@ import {
16
15
  useThemeName,
17
16
  withStaticProperties,
18
17
  } from '@tamagui/core'
19
- import { ScopedProps, createContextScope } from '@tamagui/create-context'
20
18
  import { Portal } from '@tamagui/portal'
21
19
  import { RemoveScroll } from '@tamagui/remove-scroll'
22
20
  import { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'
23
21
  import { useControllableState } from '@tamagui/use-controllable-state'
24
22
  import React, {
25
- ReactNode,
26
23
  createContext,
27
24
  forwardRef,
28
25
  isValidElement,
@@ -36,74 +33,18 @@ import React, {
36
33
  import {
37
34
  Animated,
38
35
  GestureResponderEvent,
39
- NativeScrollEvent,
40
- NativeSyntheticEvent,
41
36
  PanResponder,
42
37
  PanResponderGestureState,
43
- ScrollView,
44
- ScrollViewProps,
38
+ StyleSheet,
45
39
  View,
46
40
  } from 'react-native'
47
41
 
48
- const SHEET_NAME = 'Sheet'
49
- const SHEET_HANDLE_NAME = 'SheetHandle'
42
+ import { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'
43
+ import { SheetProvider, useSheetContext } from './SheetContext'
44
+ import { SheetScrollView } from './SheetScrollView'
45
+ import { ScrollBridge, SheetProps, SheetScopedProps } from './types'
50
46
 
51
- type RemoveScrollProps = React.ComponentProps<typeof RemoveScroll>
52
-
53
- export type SheetProps = ScopedProps<
54
- {
55
- open?: boolean
56
- defaultOpen?: boolean
57
- onChangeOpen?: OpenChangeHandler
58
- position?: number
59
- defaultPosition?: number
60
- snapPoints?: number[]
61
- onChangePosition?: PositionChangeHandler
62
- children?: ReactNode
63
- dismissOnOverlayPress?: boolean
64
- dismissOnSnapToBottom?: boolean
65
- animationConfig?: Animated.SpringAnimationConfig
66
- disableDrag?: boolean
67
- modal?: boolean
68
-
69
- /**
70
- * @see https://github.com/theKashey/react-remove-scroll#usage
71
- */
72
- allowPinchZoom?: RemoveScrollProps['allowPinchZoom']
73
- },
74
- 'Sheet'
75
- >
76
-
77
- type PositionChangeHandler = (position: number) => void
78
-
79
- type OpenChangeHandler = ((open: boolean) => void) | React.Dispatch<React.SetStateAction<boolean>>
80
-
81
- type ScrollBridge = {
82
- enabled: boolean
83
- y: number
84
- scrollStartY: number
85
- drag: (dy: number) => void
86
- release: (state: { dy: number; vy: number }) => void
87
- }
88
-
89
- type SheetContextValue = Required<
90
- Pick<SheetProps, 'open' | 'position' | 'snapPoints' | 'dismissOnOverlayPress'>
91
- > & {
92
- hidden: boolean
93
- setPosition: PositionChangeHandler
94
- setOpen: React.Dispatch<React.SetStateAction<boolean>>
95
- allowPinchZoom: RemoveScrollProps['allowPinchZoom']
96
- contentRef: React.RefObject<TamaguiElement>
97
- dismissOnSnapToBottom: boolean
98
- scrollBridge: ScrollBridge
99
- modal: boolean
100
- }
101
-
102
- const [createSheetContext, createSheetScope] = createContextScope(SHEET_NAME)
103
- const [SheetProvider, useSheetContext] = createSheetContext<SheetContextValue>(
104
- SHEET_NAME,
105
- {} as any
106
- )
47
+ export { createSheetScope } from './SheetContext'
107
48
 
108
49
  /* -------------------------------------------------------------------------------------------------
109
50
  * SheetHandle
@@ -114,30 +55,31 @@ export const SheetHandleFrame = styled(XStack, {
114
55
  height: 10,
115
56
  borderRadius: 100,
116
57
  backgroundColor: '$background',
117
- position: 'absolute',
118
- pointerEvents: 'auto',
119
58
  zIndex: 10,
120
- y: -18,
121
- top: 0,
122
- left: '35%',
123
- right: '35%',
59
+ marginHorizontal: '35%',
60
+ marginBottom: '$2',
124
61
  opacity: 0.5,
125
62
 
126
63
  hoverStyle: {
127
64
  opacity: 0.7,
128
65
  },
129
- })
130
66
 
131
- type SheetScopedProps<A> = ScopedProps<A, 'Sheet'>
67
+ variants: {
68
+ open: {
69
+ true: {
70
+ pointerEvents: 'auto',
71
+ },
72
+ false: {
73
+ opacity: 0,
74
+ pointerEvents: 'none',
75
+ },
76
+ },
77
+ } as const,
78
+ })
132
79
 
133
80
  export const SheetHandle = SheetHandleFrame.extractable(
134
81
  ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {
135
82
  const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)
136
-
137
- if (context.open === false) {
138
- return null
139
- }
140
-
141
83
  return (
142
84
  <SheetHandleFrame
143
85
  onPress={() => {
@@ -146,6 +88,7 @@ export const SheetHandle = SheetHandleFrame.extractable(
146
88
  const nextPos = (context.position + 1) % max
147
89
  context.setPosition(nextPos)
148
90
  }}
91
+ open={context.open}
149
92
  {...props}
150
93
  />
151
94
  )
@@ -186,108 +129,17 @@ export const SheetOverlay = SheetOverlayFrame.extractable(
186
129
  ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {
187
130
  const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)
188
131
  return (
189
- <RemoveScroll
190
- enabled={context.open && context.modal}
191
- as={Slot}
192
- allowPinchZoom={context.allowPinchZoom}
193
- shards={[context.contentRef]}
194
- // causes lots of bugs on touch web on site
195
- removeScrollBar={false}
196
- >
197
- <SheetOverlayFrame
198
- closed={!context.open || context.hidden}
199
- {...props}
200
- onPress={mergeEvent(
201
- props.onPress,
202
- context.dismissOnOverlayPress
203
- ? () => {
204
- context.setOpen(false)
205
- }
206
- : undefined
207
- )}
208
- />
209
- </RemoveScroll>
210
- )
211
- }
212
- )
213
-
214
- /* -------------------------------------------------------------------------------------------------
215
- * SheetScrollView
216
- * -----------------------------------------------------------------------------------------------*/
217
-
218
- const SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'
219
-
220
- export const SheetScrollView = forwardRef<ScrollView, ScrollViewProps>(
221
- ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {
222
- const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)
223
- const [scrollEnabled, setScrollEnabled] = useState(true)
224
- const state = useRef({
225
- dy: 0,
226
- // store a few recent dys to get velocity on release
227
- dys: [] as number[],
228
- })
229
-
230
- const release = () => {
231
- setScrollEnabled(true)
232
- const recentDys = state.current.dys.slice(-10)
233
- const dist = recentDys.length
234
- ? recentDys.reduce((a, b, i) => a + b - (recentDys[i - 1] ?? recentDys[0]), 0)
235
- : 0
236
- const avgDy = dist / recentDys.length
237
- const vy = avgDy * 0.075
238
- state.current.dys = []
239
- scrollBridge.release({
240
- dy: state.current.dy,
241
- vy,
242
- })
243
- }
244
-
245
- return (
246
- <ScrollView
247
- ref={ref}
248
- scrollEventThrottle={16} // todo release we can just grab the last dY and estimate vY using a sample of last dYs
132
+ <SheetOverlayFrame
133
+ closed={!context.open || context.hidden}
249
134
  {...props}
250
- scrollEnabled={props.scrollEnabled || scrollEnabled}
251
- onScroll={composeEventHandlers<NativeSyntheticEvent<NativeScrollEvent>>(
252
- props.onScroll,
253
- (e) => {
254
- const { y } = e.nativeEvent.contentOffset
255
- scrollBridge.y = y
256
- if (y > 0) {
257
- scrollBridge.scrollStartY = -1
258
- }
259
- }
135
+ onPress={mergeEvent(
136
+ props.onPress,
137
+ context.dismissOnOverlayPress
138
+ ? () => {
139
+ context.setOpen(false)
140
+ }
141
+ : undefined
260
142
  )}
261
- onResponderMove={composeEventHandlers(props.onResponderMove, (e) => {
262
- const { pageY } = e.nativeEvent
263
- if (scrollBridge.y <= 0) {
264
- if (scrollBridge.scrollStartY === -1) {
265
- scrollBridge.scrollStartY = pageY
266
- }
267
- const dy = pageY - scrollBridge.scrollStartY
268
- if (dy <= 0) {
269
- setScrollEnabled(true)
270
- return
271
- }
272
- setScrollEnabled(false)
273
- scrollBridge.drag(dy)
274
- state.current.dy = dy
275
- state.current.dys.push(dy)
276
- // only do every so often, cut down to 10 again
277
- if (state.current.dys.length > 100) {
278
- state.current.dys = state.current.dys.slice(-10)
279
- }
280
- }
281
- })}
282
- onResponderReject={composeEventHandlers(props.onResponderReject, release)}
283
- onResponderTerminate={composeEventHandlers(props.onResponderTerminate, release)}
284
- onResponderRelease={composeEventHandlers(props.onResponderRelease, release)}
285
- style={[
286
- {
287
- flex: 1,
288
- },
289
- props.style,
290
- ]}
291
143
  />
292
144
  )
293
145
  }
@@ -343,7 +195,7 @@ export const Sheet = withStaticProperties(
343
195
  dismissOnSnapToBottom = false,
344
196
  disableDrag: disableDragProp,
345
197
  modal = false,
346
- allowPinchZoom,
198
+ handleDisableScroll = true,
347
199
  } = props
348
200
 
349
201
  if (process.env.NODE_ENV === 'development') {
@@ -363,9 +215,12 @@ export const Sheet = withStaticProperties(
363
215
  const scrollBridge = useConstant<ScrollBridge>(() => ({
364
216
  enabled: false,
365
217
  y: 0,
218
+ paneY: 0,
219
+ paneMinY: 0,
366
220
  scrollStartY: -1,
367
221
  drag: () => {},
368
222
  release: () => {},
223
+ scrollLock: false,
369
224
  }))
370
225
 
371
226
  const onChangeOpenInternal = (val: boolean) => {
@@ -431,6 +286,10 @@ export const Sheet = withStaticProperties(
431
286
  function stopSpring() {
432
287
  spring.current?.stop()
433
288
  spring.current = null
289
+ if (scrollBridge.onFinishAnimate) {
290
+ scrollBridge.onFinishAnimate()
291
+ scrollBridge.onFinishAnimate = undefined
292
+ }
434
293
  }
435
294
 
436
295
  // open must set position
@@ -491,6 +350,7 @@ export const Sheet = withStaticProperties(
491
350
  useEffect(() => {
492
351
  positionValue.current!.addListener(({ value }) => {
493
352
  at.current = value
353
+ scrollBridge.paneY = value
494
354
  })
495
355
  return () => {
496
356
  positionValue.current!.removeAllListeners()
@@ -505,6 +365,7 @@ export const Sheet = withStaticProperties(
505
365
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
506
366
  const pos = positionValue.current!
507
367
  const minY = positions[0]
368
+ scrollBridge.paneMinY = minY
508
369
  let startY = at.current
509
370
 
510
371
  function makeUnselectable(val: boolean) {
@@ -516,14 +377,14 @@ export const Sheet = withStaticProperties(
516
377
  }
517
378
  }
518
379
 
519
- const release = ({ vy, dy }: { dy: number; vy: number }) => {
380
+ const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {
520
381
  isExternalDrag = false
521
382
  previouslyScrolling = false
522
383
  makeUnselectable(false)
523
- const at = dy + startY
384
+ const at = dragAt + startY
524
385
  // seems liky vy goes up to about 4 at the very most (+ is down, - is up)
525
386
  // lets base our multiplier on the total layout height
526
- const end = at + frameSize * vy * 0.33
387
+ const end = at + frameSize * vy * 0.2
527
388
  let closestPoint = 0
528
389
  let dist = Infinity
529
390
  for (let i = 0; i < positions.length; i++) {
@@ -540,25 +401,28 @@ export const Sheet = withStaticProperties(
540
401
  }
541
402
 
542
403
  const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {
543
- release(state)
404
+ release({
405
+ vy: state.vy,
406
+ dragAt: state.dy,
407
+ })
544
408
  }
545
409
 
546
410
  let previouslyScrolling = false
547
411
 
548
412
  const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {
549
- if (scrollBridge.enabled) {
550
- if (scrollBridge.y !== 0) {
551
- previouslyScrolling = true
552
- return false
553
- }
554
- if (scrollBridge.y === 0 && dy < 0) {
555
- return false
556
- }
413
+ const isScrolled = scrollBridge.y !== 0
414
+ if (isScrolled) {
415
+ previouslyScrolling = true
416
+ return false
557
417
  }
558
418
  if (previouslyScrolling) {
559
419
  previouslyScrolling = false
560
420
  return true
561
421
  }
422
+ const isDraggingUp = dy < 0
423
+ if (!isScrolled && isDraggingUp) {
424
+ return false
425
+ }
562
426
  // we could do some detection of other touchables and cancel here..
563
427
  return Math.abs(dy) > 8
564
428
  }
@@ -571,27 +435,35 @@ export const Sheet = withStaticProperties(
571
435
 
572
436
  let isExternalDrag = false
573
437
 
438
+ function setPositionValue(next: number) {
439
+ // useful to debug any "jumping"
440
+ // if (process.env.NODE_ENV === 'development') {
441
+ // const moveAmt = Math.abs(pos['_value'] - next)
442
+ // if (moveAmt > 50) {
443
+ // console.warn('!!!!!!!!!!!!jump!', moveAmt)
444
+ // // debugger
445
+ // }
446
+ // }
447
+ pos.setValue(next)
448
+ }
449
+
574
450
  scrollBridge.drag = (dy) => {
575
451
  if (!isExternalDrag) {
576
452
  isExternalDrag = true
577
453
  grant()
578
454
  }
579
455
  const to = dy + startY
580
- pos.setValue(resisted(to, minY))
456
+ setPositionValue(resisted(to, minY))
581
457
  }
582
458
 
583
459
  scrollBridge.release = release
584
460
 
585
461
  return PanResponder.create({
586
- onMoveShouldSetPanResponder: (...args) => {
587
- const res = onMoveShouldSet(...args)
588
- // console.log('res', res, scrollBridge.y)
589
- return res
590
- },
462
+ onMoveShouldSetPanResponder: onMoveShouldSet,
591
463
  onPanResponderGrant: grant,
592
464
  onPanResponderMove: (_e, { dy }) => {
593
465
  const to = dy + startY
594
- pos.setValue(resisted(to, minY))
466
+ setPositionValue(resisted(to, minY))
595
467
  },
596
468
  onPanResponderEnd: finish,
597
469
  onPanResponderTerminate: finish,
@@ -640,7 +512,6 @@ export const Sheet = withStaticProperties(
640
512
  contentRef={contentRef}
641
513
  dismissOnOverlayPress={dismissOnOverlayPress}
642
514
  dismissOnSnapToBottom={dismissOnSnapToBottom}
643
- allowPinchZoom={allowPinchZoom}
644
515
  open={open}
645
516
  hidden={isHidden}
646
517
  scope={__scopeSheet}
@@ -651,8 +522,7 @@ export const Sheet = withStaticProperties(
651
522
  scrollBridge={scrollBridge}
652
523
  >
653
524
  {isResizing ? null : overlayComponent}
654
- {/* no fancy hidden animation etc for handle for now */}
655
- {isHidden ? null : handleComponent}
525
+
656
526
  <Animated.View
657
527
  ref={ref}
658
528
  {...panResponder?.panHandlers}
@@ -673,7 +543,18 @@ export const Sheet = withStaticProperties(
673
543
  transform: [{ translateY }],
674
544
  }}
675
545
  >
546
+ {handleComponent}
547
+
548
+ {/* <RemoveScroll
549
+ enabled={open && modal && handleDisableScroll}
550
+ as={Slot}
551
+ allowPinchZoom
552
+ shards={[contentRef]}
553
+ // causes lots of bugs on touch web on site
554
+ removeScrollBar={false}
555
+ > */}
676
556
  {isResizing ? null : frameComponent}
557
+ {/* </RemoveScroll> */}
677
558
  </Animated.View>
678
559
  </SheetProvider>
679
560
  )
@@ -752,5 +633,3 @@ export const SheetController = ({
752
633
  <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>
753
634
  )
754
635
  }
755
-
756
- export { createSheetScope }
@@ -0,0 +1,25 @@
1
+ import { TamaguiElement } from '@tamagui/core'
2
+ import { createContextScope } from '@tamagui/create-context'
3
+ import React from 'react'
4
+
5
+ import { SHEET_NAME } from './SHEET_HANDLE_NAME'
6
+ import { PositionChangeHandler, ScrollBridge, SheetProps } from './types'
7
+
8
+ type SheetContextValue = Required<
9
+ Pick<SheetProps, 'open' | 'position' | 'snapPoints' | 'dismissOnOverlayPress'>
10
+ > & {
11
+ hidden: boolean
12
+ setPosition: PositionChangeHandler
13
+ setOpen: React.Dispatch<React.SetStateAction<boolean>>
14
+ contentRef: React.RefObject<TamaguiElement>
15
+ dismissOnSnapToBottom: boolean
16
+ scrollBridge: ScrollBridge
17
+ modal: boolean
18
+ }
19
+
20
+ export const [createSheetContext, createSheetScope] = createContextScope(SHEET_NAME)
21
+
22
+ export const [SheetProvider, useSheetContext] = createSheetContext<SheetContextValue>(
23
+ SHEET_NAME,
24
+ {} as any
25
+ )
@@ -0,0 +1,109 @@
1
+ import React, { forwardRef, useRef, useState } from 'react'
2
+ import { ScrollView, ScrollViewProps } from 'react-native'
3
+
4
+ import { useSheetContext } from './SheetContext'
5
+ import { SheetScopedProps } from './types'
6
+
7
+ /* -------------------------------------------------------------------------------------------------
8
+ * SheetScrollView
9
+ * -----------------------------------------------------------------------------------------------*/
10
+
11
+ const SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'
12
+
13
+ export const SheetScrollView = forwardRef<ScrollView, ScrollViewProps>(
14
+ ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {
15
+ const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)
16
+ const [scrollEnabled, setScrollEnabled] = useState(true)
17
+ const state = useRef({
18
+ lastPageY: 0,
19
+ dragAt: 0,
20
+ dys: [] as number[], // store a few recent dys to get velocity on release
21
+ isScrolling: false,
22
+ })
23
+
24
+ const release = () => {
25
+ scrollBridge.scrollStartY = -1
26
+ state.current.isScrolling = false
27
+ setScrollEnabled(true)
28
+ let vy = 0
29
+ if (state.current.dys.length) {
30
+ const recentDys = state.current.dys.slice(-10)
31
+ const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0
32
+ const avgDy = dist / recentDys.length
33
+ vy = avgDy * 0.04
34
+ console.table([{ vy, avgDy, dist, recentDys }])
35
+ }
36
+ state.current.dys = []
37
+ scrollBridge.release({
38
+ dragAt: state.current.dragAt,
39
+ vy,
40
+ })
41
+ }
42
+
43
+ return (
44
+ <ScrollView
45
+ ref={ref}
46
+ scrollEventThrottle={8}
47
+ scrollEnabled={scrollEnabled}
48
+ onScroll={(e) => {
49
+ const { y } = e.nativeEvent.contentOffset
50
+ scrollBridge.y = y
51
+ if (y > 0) {
52
+ scrollBridge.scrollStartY = -1
53
+ }
54
+ }}
55
+ onStartShouldSetResponder={() => {
56
+ scrollBridge.scrollStartY = -1
57
+ return true
58
+ }}
59
+ onMoveShouldSetResponder={() => true}
60
+ onResponderMove={(e) => {
61
+ const { pageY } = e.nativeEvent
62
+
63
+ if (state.current.isScrolling) {
64
+ return
65
+ }
66
+
67
+ if (scrollBridge.scrollStartY === -1) {
68
+ scrollBridge.scrollStartY = pageY
69
+ state.current.lastPageY = pageY
70
+ }
71
+
72
+ const dragAt = pageY - scrollBridge.scrollStartY
73
+ const dy = pageY - state.current.lastPageY
74
+ state.current.lastPageY = pageY // after dy
75
+ // const isAboveStart = dragAt <= 0
76
+ // const isDraggingDown = dy > 0
77
+ // const isScrollAtTop = scrollBridge.y <= 0
78
+ const isDraggingUp = dy < 0
79
+ const isPaneAtTop = scrollBridge.paneY <= scrollBridge.paneMinY
80
+
81
+ if ((dy === 0 || isDraggingUp) && isPaneAtTop) {
82
+ state.current.isScrolling = true
83
+ setScrollEnabled(true)
84
+ return
85
+ }
86
+
87
+ setScrollEnabled(false)
88
+ scrollBridge.drag(dragAt)
89
+ state.current.dragAt = dragAt
90
+ state.current.dys.push(dy)
91
+ // only do every so often, cut down to 10 again
92
+ if (state.current.dys.length > 100) {
93
+ state.current.dys = state.current.dys.slice(-10)
94
+ }
95
+ }}
96
+ onResponderRelease={release}
97
+ // onResponderEnd={release}
98
+ // onResponderTerminate={release}
99
+ {...props}
100
+ style={[
101
+ {
102
+ flex: 1,
103
+ },
104
+ props.style,
105
+ ]}
106
+ />
107
+ )
108
+ }
109
+ )
package/src/types.tsx ADDED
@@ -0,0 +1,44 @@
1
+ import { ScopedProps } from '@tamagui/create-context'
2
+ import { RemoveScroll } from '@tamagui/remove-scroll'
3
+ import React, { ReactNode } from 'react'
4
+ import { Animated } from 'react-native'
5
+
6
+ export type SheetProps = ScopedProps<
7
+ {
8
+ open?: boolean
9
+ defaultOpen?: boolean
10
+ onChangeOpen?: OpenChangeHandler
11
+ position?: number
12
+ defaultPosition?: number
13
+ snapPoints?: number[]
14
+ onChangePosition?: PositionChangeHandler
15
+ children?: ReactNode
16
+ dismissOnOverlayPress?: boolean
17
+ dismissOnSnapToBottom?: boolean
18
+ animationConfig?: Animated.SpringAnimationConfig
19
+ handleDisableScroll?: boolean
20
+ disableDrag?: boolean
21
+ modal?: boolean
22
+ },
23
+ 'Sheet'
24
+ >
25
+
26
+ export type PositionChangeHandler = (position: number) => void
27
+
28
+ type OpenChangeHandler = ((open: boolean) => void) | React.Dispatch<React.SetStateAction<boolean>>
29
+
30
+ export type RemoveScrollProps = React.ComponentProps<typeof RemoveScroll>
31
+
32
+ export type SheetScopedProps<A> = ScopedProps<A, 'Sheet'>
33
+
34
+ export type ScrollBridge = {
35
+ enabled: boolean
36
+ y: number
37
+ paneY: number
38
+ paneMinY: number
39
+ scrollStartY: number
40
+ drag: (dy: number) => void
41
+ release: (state: { dragAt: number; vy: number }) => void
42
+ scrollLock: boolean
43
+ onFinishAnimate?: () => void
44
+ }
@@ -0,0 +1,4 @@
1
+ export declare const constants: {};
2
+ export declare const SHEET_NAME = "Sheet";
3
+ export declare const SHEET_HANDLE_NAME = "SheetHandle";
4
+ //# sourceMappingURL=SHEET_HANDLE_NAME.d.ts.map