@tamagui/sheet 1.0.1-beta.141 → 1.0.1-beta.142

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/src/Sheet.tsx CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  Slot,
5
5
  TamaguiElement,
6
6
  Theme,
7
+ getAnimationDriver,
7
8
  isClient,
8
- isWeb,
9
9
  mergeEvent,
10
10
  styled,
11
11
  themeable,
@@ -30,13 +30,7 @@ import React, {
30
30
  useRef,
31
31
  useState,
32
32
  } from 'react'
33
- import {
34
- Animated,
35
- GestureResponderEvent,
36
- PanResponder,
37
- PanResponderGestureState,
38
- View,
39
- } from 'react-native'
33
+ import { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'
40
34
 
41
35
  import { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'
42
36
  import { SheetProvider, useSheetContext } from './SheetContext'
@@ -206,6 +200,11 @@ export const Sheet = withStaticProperties(
206
200
  }
207
201
  }
208
202
 
203
+ const driver = getAnimationDriver()
204
+ if (!driver) {
205
+ throw new Error(`Must set animations in tamagui.config.ts`)
206
+ }
207
+
209
208
  // allows for sheets to be controlled by other components
210
209
  const controller = useContext(SheetControllerContext)
211
210
  const isHidden = controller?.hidden || false
@@ -269,10 +268,14 @@ export const Sheet = withStaticProperties(
269
268
  [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]
270
269
  )
271
270
 
272
- const positionValue = useRef<Animated.Value>()
273
- if (!positionValue.current) {
274
- positionValue.current = new Animated.Value(HIDDEN_SIZE)
275
- }
271
+ const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)
272
+
273
+ // native only fix
274
+ const at = useRef(0)
275
+ driver.useAnimatedNumberReaction(animatedNumber, (value) => {
276
+ at.current = value
277
+ scrollBridge.paneY = value
278
+ })
276
279
 
277
280
  const [isResizing, setIsResizing] = useState(true)
278
281
  useIsomorphicLayoutEffect(() => {
@@ -282,10 +285,8 @@ export const Sheet = withStaticProperties(
282
285
  // eslint-disable-next-line react-hooks/exhaustive-deps
283
286
  }, [modal])
284
287
 
285
- const spring = useRef<Animated.CompositeAnimation | null>(null)
286
288
  function stopSpring() {
287
- spring.current?.stop()
288
- spring.current = null
289
+ animatedNumber.stop()
289
290
  if (scrollBridge.onFinishAnimate) {
290
291
  scrollBridge.onFinishAnimate()
291
292
  scrollBridge.onFinishAnimate = undefined
@@ -306,7 +307,7 @@ export const Sheet = withStaticProperties(
306
307
  )
307
308
 
308
309
  const animateTo = useEvent((position: number) => {
309
- const current = positionValue.current
310
+ const current = animatedNumber.getValue()
310
311
  if (isHidden && open) return
311
312
  if (!current) return
312
313
  if (frameSize === 0) return
@@ -318,26 +319,19 @@ export const Sheet = withStaticProperties(
318
319
  if (isResizing) {
319
320
  setIsResizing(false)
320
321
  }
321
- Animated.timing(current, {
322
- useNativeDriver: !isWeb,
323
- toValue,
322
+ animatedNumber.setValue(toValue, {
323
+ type: 'timing',
324
324
  duration: 0,
325
- }).start()
325
+ })
326
326
  at.current = toValue
327
327
  return
328
328
  }
329
329
  // dont bounce on initial measure to bottom
330
330
  const overshootClamping = at.current === HIDDEN_SIZE
331
- spring.current = Animated.spring(current, {
332
- useNativeDriver: !isWeb,
333
- toValue,
334
- overshootClamping,
331
+ animatedNumber.setValue(toValue, {
335
332
  ...animationConfig,
336
- })
337
- spring.current.start(({ finished }) => {
338
- if (finished) {
339
- stopSpring()
340
- }
333
+ type: 'spring',
334
+ overshootClamping,
341
335
  })
342
336
  })
343
337
 
@@ -345,25 +339,11 @@ export const Sheet = withStaticProperties(
345
339
  animateTo(position)
346
340
  }, [isHidden, frameSize, position, animateTo])
347
341
 
348
- // native only fix
349
- const at = useRef(0)
350
- useEffect(() => {
351
- positionValue.current!.addListener(({ value }) => {
352
- at.current = value
353
- scrollBridge.paneY = value
354
- })
355
- return () => {
356
- positionValue.current!.removeAllListeners()
357
- }
358
- }, [])
359
-
360
342
  const panResponder = useMemo(
361
343
  () => {
362
344
  if (disableDrag) return
363
345
  if (!frameSize) return
364
346
 
365
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
366
- const pos = positionValue.current!
367
347
  const minY = positions[0]
368
348
  scrollBridge.paneMinY = minY
369
349
  let startY = at.current
@@ -420,8 +400,12 @@ export const Sheet = withStaticProperties(
420
400
  return true
421
401
  }
422
402
  const isDraggingUp = dy < 0
423
- if (!isScrolled && isDraggingUp) {
424
- return false
403
+ const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY
404
+ // prevent drag once at top and pulling up
405
+ if (isAtTop) {
406
+ if (!isScrolled && isDraggingUp) {
407
+ return false
408
+ }
425
409
  }
426
410
  // we could do some detection of other touchables and cancel here..
427
411
  return Math.abs(dy) > 8
@@ -435,25 +419,13 @@ export const Sheet = withStaticProperties(
435
419
 
436
420
  let isExternalDrag = false
437
421
 
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
-
450
422
  scrollBridge.drag = (dy) => {
451
423
  if (!isExternalDrag) {
452
424
  isExternalDrag = true
453
425
  grant()
454
426
  }
455
427
  const to = dy + startY
456
- setPositionValue(resisted(to, minY))
428
+ animatedNumber.setValue(resisted(to, minY), { type: 'direct' })
457
429
  }
458
430
 
459
431
  scrollBridge.release = release
@@ -463,7 +435,7 @@ export const Sheet = withStaticProperties(
463
435
  onPanResponderGrant: grant,
464
436
  onPanResponderMove: (_e, { dy }) => {
465
437
  const to = dy + startY
466
- setPositionValue(resisted(to, minY))
438
+ animatedNumber.setValue(resisted(to, minY), { type: 'direct' })
467
439
  },
468
440
  onPanResponderEnd: finish,
469
441
  onPanResponderTerminate: finish,
@@ -493,6 +465,7 @@ export const Sheet = withStaticProperties(
493
465
  overlayComponent = child
494
466
  break
495
467
  default:
468
+ // eslint-disable-next-line no-console
496
469
  console.warn('Warning: passed invalid child to Sheet', child)
497
470
  }
498
471
  }
@@ -500,11 +473,18 @@ export const Sheet = withStaticProperties(
500
473
 
501
474
  const preventShown = controller?.hidden && controller?.open
502
475
 
476
+ const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {
477
+ return {
478
+ transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],
479
+ }
480
+ })
481
+
503
482
  if (preventShown) {
504
483
  return null
505
484
  }
506
485
 
507
- const translateY = frameSize === 0 ? HIDDEN_SIZE : positionValue.current
486
+ // temp until reanimated useAnimatedNumber fix
487
+ const AnimatedView = driver['NumberView'] ?? driver.View
508
488
 
509
489
  const contents = (
510
490
  <SheetProvider
@@ -523,7 +503,7 @@ export const Sheet = withStaticProperties(
523
503
  >
524
504
  {isResizing ? null : overlayComponent}
525
505
 
526
- <Animated.View
506
+ <AnimatedView
527
507
  ref={ref}
528
508
  {...panResponder?.panHandlers}
529
509
  onLayout={(e) => {
@@ -535,13 +515,15 @@ export const Sheet = withStaticProperties(
535
515
  })
536
516
  }}
537
517
  pointerEvents={open ? 'auto' : 'none'}
538
- style={{
539
- position: 'absolute',
540
- zIndex: 10,
541
- width: '100%',
542
- height: '100%',
543
- transform: [{ translateY }],
544
- }}
518
+ style={[
519
+ {
520
+ position: 'absolute',
521
+ zIndex: 10,
522
+ width: '100%',
523
+ height: '100%',
524
+ },
525
+ animatedStyle,
526
+ ]}
545
527
  >
546
528
  {handleComponent}
547
529
 
@@ -555,7 +537,7 @@ export const Sheet = withStaticProperties(
555
537
  >
556
538
  {isResizing ? null : frameComponent}
557
539
  </RemoveScroll>
558
- </Animated.View>
540
+ </AnimatedView>
559
541
  </SheetProvider>
560
542
  )
561
543
 
@@ -588,7 +570,7 @@ function getPercentSize(point?: number, frameSize?: number) {
588
570
  return 0
589
571
  }
590
572
  const pct = point / 100
591
- const next = frameSize - pct * frameSize
573
+ const next = Math.round(frameSize - pct * frameSize)
592
574
  return next
593
575
  }
594
576
 
package/src/types.tsx CHANGED
@@ -1,7 +1,7 @@
1
+ import { AnimatedNumberStrategy } from '@tamagui/core'
1
2
  import { ScopedProps } from '@tamagui/create-context'
2
3
  import { RemoveScroll } from '@tamagui/remove-scroll'
3
4
  import React, { ReactNode } from 'react'
4
- import { Animated } from 'react-native'
5
5
 
6
6
  export type SheetProps = ScopedProps<
7
7
  {
@@ -15,7 +15,7 @@ export type SheetProps = ScopedProps<
15
15
  children?: ReactNode
16
16
  dismissOnOverlayPress?: boolean
17
17
  dismissOnSnapToBottom?: boolean
18
- animationConfig?: Animated.SpringAnimationConfig
18
+ animationConfig?: AnimatedNumberStrategy
19
19
  handleDisableScroll?: boolean
20
20
  disableDrag?: boolean
21
21
  modal?: boolean
package/types/Sheet.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { GetProps } from '@tamagui/core';
2
2
  import { XStackProps } from '@tamagui/stacks';
3
3
  import React from 'react';
4
- import { Animated, View } from 'react-native';
4
+ import { View } from 'react-native';
5
5
  import { SheetScopedProps } from './types';
6
6
  export { createSheetScope } from './SheetContext';
7
7
  export declare const SheetHandleFrame: import("@tamagui/core").TamaguiComponent<Omit<import("react-native").ViewProps, "children" | "display"> & import("@tamagui/core").RNWViewProps & import("@tamagui/core").TamaguiComponentPropsBase & import("@tamagui/core").WithThemeValues<import("@tamagui/core").StackStylePropsBase> & import("@tamagui/core").WithShorthands<import("@tamagui/core").WithThemeValues<import("@tamagui/core").StackStylePropsBase>> & Omit<{
@@ -105,7 +105,7 @@ export declare const Sheet: ((props: Omit<{
105
105
  children?: React.ReactNode;
106
106
  dismissOnOverlayPress?: boolean | undefined;
107
107
  dismissOnSnapToBottom?: boolean | undefined;
108
- animationConfig?: Animated.SpringAnimationConfig | undefined;
108
+ animationConfig?: import("@tamagui/core").AnimatedNumberStrategy | undefined;
109
109
  handleDisableScroll?: boolean | undefined;
110
110
  disableDrag?: boolean | undefined;
111
111
  modal?: boolean | undefined;
package/types/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
+ import { AnimatedNumberStrategy } from '@tamagui/core';
1
2
  import { ScopedProps } from '@tamagui/create-context';
2
3
  import { RemoveScroll } from '@tamagui/remove-scroll';
3
4
  import React, { ReactNode } from 'react';
4
- import { Animated } from 'react-native';
5
5
  export declare type SheetProps = ScopedProps<{
6
6
  open?: boolean;
7
7
  defaultOpen?: boolean;
@@ -13,7 +13,7 @@ export declare type SheetProps = ScopedProps<{
13
13
  children?: ReactNode;
14
14
  dismissOnOverlayPress?: boolean;
15
15
  dismissOnSnapToBottom?: boolean;
16
- animationConfig?: Animated.SpringAnimationConfig;
16
+ animationConfig?: AnimatedNumberStrategy;
17
17
  handleDisableScroll?: boolean;
18
18
  disableDrag?: boolean;
19
19
  modal?: boolean;
@@ -0,0 +1,19 @@
1
+ import { Animated, TextStyle, ViewStyle } from 'react-native';
2
+ import { SharedValue } from 'react-native-reanimated';
3
+ export declare function useAnimated(): {
4
+ View: any;
5
+ Text: any;
6
+ };
7
+ declare type UniversalAnimatedNumber<A> = {
8
+ getInstance(): A;
9
+ getValue(): number;
10
+ setValue(next: number): void;
11
+ };
12
+ export declare function useAnimatedNumberReanimated(initial: number): UniversalAnimatedNumber<SharedValue<number>>;
13
+ export declare function useAnimatedNumberReactionReanimated(value: UniversalAnimatedNumber<SharedValue<number>>, cb: (current: number) => void): void;
14
+ export declare function useAnimatedNumberStyleReanimated<V extends UniversalAnimatedNumber<Animated.Value>>(value: V, getStyle: (value: V) => ViewStyle | TextStyle): ViewStyle | TextStyle;
15
+ export declare function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value>;
16
+ export declare function useAnimatedNumberReaction(value: UniversalAnimatedNumber<Animated.Value>, cb: (current: number) => void): void;
17
+ export declare function useAnimatedNumberStyle<V extends UniversalAnimatedNumber<Animated.Value>>(value: V, getStyle: (value: V) => ViewStyle | TextStyle): ViewStyle | TextStyle;
18
+ export {};
19
+ //# sourceMappingURL=useAnimated.d.ts.map