react-modal-sheet 5.0.0 → 5.1.0

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.
@@ -0,0 +1,52 @@
1
+ import { motion, useTransform } from 'motion/react';
2
+ import React from 'react';
3
+
4
+ import { useSheetContext } from './context';
5
+ import { styles } from './styles';
6
+ import type { SheetDragIndicatorProps } from './types';
7
+ import { applyStyles } from './utils';
8
+
9
+ export function SheetDragIndicator({
10
+ style,
11
+ className = '',
12
+ unstyled,
13
+ ...rest
14
+ }: SheetDragIndicatorProps) {
15
+ const sheetContext = useSheetContext();
16
+
17
+ const indicator1Transform = useTransform(
18
+ sheetContext.indicatorRotation,
19
+ (r) => `translateX(2px) rotate(${r}deg)`
20
+ );
21
+
22
+ const indicator2Transform = useTransform(
23
+ sheetContext.indicatorRotation,
24
+ (r) => `translateX(-2px) rotate(${-1 * r}deg)`
25
+ );
26
+
27
+ const isUnstyled = unstyled ?? sheetContext.unstyled;
28
+
29
+ const indicatorWrapperStyle = {
30
+ ...applyStyles(styles.indicatorWrapper, isUnstyled),
31
+ ...style,
32
+ };
33
+
34
+ const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
35
+
36
+ return (
37
+ <div
38
+ className={`react-modal-sheet-drag-indicator-container ${className}`}
39
+ style={indicatorWrapperStyle}
40
+ {...rest}
41
+ >
42
+ <motion.span
43
+ className="react-modal-sheet-drag-indicator"
44
+ style={{ ...indicatorStyle, transform: indicator1Transform }}
45
+ />
46
+ <motion.span
47
+ className="react-modal-sheet-drag-indicator"
48
+ style={{ ...indicatorStyle, transform: indicator2Transform }}
49
+ />
50
+ </div>
51
+ );
52
+ }
@@ -1,14 +1,18 @@
1
- import { motion, useTransform } from 'motion/react';
1
+ import { motion } from 'motion/react';
2
2
  import React, { forwardRef } from 'react';
3
3
 
4
+ import { SheetDragIndicator } from './SheetDragIndicator';
4
5
  import { useSheetContext } from './context';
5
6
  import { useDragConstraints } from './hooks/use-drag-constraints';
6
7
  import { styles } from './styles';
7
- import { type SheetDraggableProps } from './types';
8
- import { mergeRefs } from './utils';
8
+ import { type SheetHeaderProps } from './types';
9
+ import { applyStyles, mergeRefs } from './utils';
9
10
 
10
- export const SheetHeader = forwardRef<any, SheetDraggableProps>(
11
- ({ children, style, disableDrag, ...rest }, ref) => {
11
+ export const SheetHeader = forwardRef<any, SheetHeaderProps>(
12
+ (
13
+ { children, style, disableDrag, unstyled, className = '', ...rest },
14
+ ref
15
+ ) => {
12
16
  const sheetContext = useSheetContext();
13
17
  const dragConstraints = useDragConstraints();
14
18
  const dragProps =
@@ -16,35 +20,28 @@ export const SheetHeader = forwardRef<any, SheetDraggableProps>(
16
20
  ? undefined
17
21
  : sheetContext.dragProps;
18
22
 
19
- const indicator1Transform = useTransform(
20
- sheetContext.indicatorRotation,
21
- (r) => `translateX(2px) rotate(${r}deg)`
22
- );
23
+ const isUnstyled = unstyled ?? sheetContext.unstyled;
23
24
 
24
- const indicator2Transform = useTransform(
25
- sheetContext.indicatorRotation,
26
- (r) => `translateX(-2px) rotate(${-1 * r}deg)`
27
- );
25
+ const headerWrapperStyle = {
26
+ ...applyStyles(styles.headerWrapper, isUnstyled),
27
+ ...style,
28
+ };
29
+
30
+ const headerStyle = applyStyles(styles.header, isUnstyled);
28
31
 
29
32
  return (
30
33
  <motion.div
31
34
  {...rest}
32
35
  ref={mergeRefs([ref, dragConstraints.ref])}
33
- style={{ ...styles.headerWrapper, ...style }}
36
+ style={headerWrapperStyle}
37
+ className={`react-modal-sheet-header-container ${className}`}
34
38
  {...dragProps}
35
39
  dragConstraints={dragConstraints.ref}
36
40
  onMeasureDragConstraints={dragConstraints.onMeasure}
37
41
  >
38
42
  {children || (
39
- <div className="react-modal-sheet-header" style={styles.header}>
40
- <motion.span
41
- className="react-modal-sheet-drag-indicator"
42
- style={{ ...styles.indicator, transform: indicator1Transform }}
43
- />
44
- <motion.span
45
- className="react-modal-sheet-drag-indicator"
46
- style={{ ...styles.indicator, transform: indicator2Transform }}
47
- />
43
+ <div className="react-modal-sheet-header" style={headerStyle}>
44
+ <SheetDragIndicator />
48
45
  </div>
49
46
  )}
50
47
  </motion.div>
package/src/index.tsx CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { MotionValue } from 'motion/react';
2
- import type { RefObject } from 'react';
3
2
 
4
3
  import { SheetBackdrop } from './SheetBackdrop';
5
4
  import { SheetContainer } from './SheetContainer';
6
5
  import { SheetContent } from './SheetContent';
6
+ import { SheetDragIndicator } from './SheetDragIndicator';
7
7
  import { SheetHeader } from './SheetHeader';
8
8
  import { Sheet as SheetBase } from './sheet';
9
- import type { SheetCompound, SheetDraggableProps } from './types';
9
+ import type { SheetCompound } from './types';
10
10
 
11
11
  export interface SheetRef {
12
12
  y: MotionValue<number>;
@@ -18,16 +18,18 @@ export interface SheetRef {
18
18
  export const Sheet: SheetCompound = Object.assign(SheetBase, {
19
19
  Container: SheetContainer,
20
20
  Header: SheetHeader,
21
+ DragIndicator: SheetDragIndicator,
21
22
  Content: SheetContent,
22
23
  Backdrop: SheetBackdrop,
23
24
  });
24
25
 
25
26
  // Export types
26
- export type SheetHeaderProps = SheetDraggableProps;
27
- export type SheetContentProps = SheetDraggableProps;
28
27
  export type {
29
28
  SheetBackdropProps,
30
29
  SheetContainerProps,
30
+ SheetContentProps,
31
+ SheetDragIndicatorProps,
32
+ SheetHeaderProps,
31
33
  SheetProps,
32
34
  SheetSnapPoint,
33
35
  SheetStateInfo,
package/src/sheet.tsx CHANGED
@@ -37,6 +37,7 @@ import {
37
37
  } from './snap';
38
38
  import { styles } from './styles';
39
39
  import { type SheetContextType, type SheetProps } from './types';
40
+ import { applyStyles } from './utils';
40
41
 
41
42
  export const Sheet = forwardRef<any, SheetProps>(
42
43
  (
@@ -45,20 +46,21 @@ export const Sheet = forwardRef<any, SheetProps>(
45
46
  children,
46
47
  className = '',
47
48
  detent = 'default',
49
+ disableDismiss = false,
48
50
  disableDrag: disableDragProp = false,
49
51
  disableScrollLocking = false,
50
- disableDismiss = false,
51
52
  dragCloseThreshold = DEFAULT_DRAG_CLOSE_THRESHOLD,
52
53
  dragVelocityThreshold = DEFAULT_DRAG_VELOCITY_THRESHOLD,
54
+ initialSnap,
53
55
  isOpen,
54
56
  modalEffectRootId,
55
57
  modalEffectThreshold,
56
58
  mountPoint,
57
59
  prefersReducedMotion = false,
58
60
  snapPoints: snapPointsProp,
59
- initialSnap,
60
61
  style,
61
62
  tweenConfig = DEFAULT_TWEEN_CONFIG,
63
+ unstyled = false,
62
64
  onOpenStart,
63
65
  onOpenEnd,
64
66
  onClose,
@@ -337,6 +339,7 @@ export const Sheet = forwardRef<any, SheetProps>(
337
339
  avoidKeyboard,
338
340
  sheetBoundsRef,
339
341
  sheetRef,
342
+ unstyled,
340
343
  y,
341
344
  };
342
345
 
@@ -347,7 +350,12 @@ export const Sheet = forwardRef<any, SheetProps>(
347
350
  ref={ref}
348
351
  data-sheet-state={state}
349
352
  className={`react-modal-sheet-root ${className}`}
350
- style={{ ...styles.root, zIndex, visibility, ...style }}
353
+ style={{
354
+ ...applyStyles(styles.root, unstyled),
355
+ zIndex,
356
+ visibility,
357
+ ...style,
358
+ }}
351
359
  >
352
360
  {state !== 'closed' ? children : null}
353
361
  </motion.div>
package/src/styles.ts CHANGED
@@ -1,69 +1,110 @@
1
- import { type Properties } from 'csstype';
1
+ import type { CSSProperties } from 'react';
2
2
 
3
3
  export const styles = {
4
4
  root: {
5
- position: 'fixed',
6
- top: 0,
7
- bottom: 0,
8
- left: 0,
9
- right: 0,
10
- overflow: 'hidden',
11
- pointerEvents: 'none',
5
+ base: {
6
+ position: 'fixed',
7
+ top: 0,
8
+ bottom: 0,
9
+ left: 0,
10
+ right: 0,
11
+ overflow: 'hidden',
12
+ pointerEvents: 'none',
13
+ },
14
+ decorative: {},
12
15
  },
13
16
  backdrop: {
14
- zIndex: 1,
15
- position: 'fixed',
16
- top: 0,
17
- left: 0,
18
- width: '100%',
19
- height: '100%',
20
- backgroundColor: 'rgba(0, 0, 0, 0.2)',
21
- touchAction: 'none',
22
- border: 'none',
23
- userSelect: 'none',
24
- WebkitTapHighlightColor: 'transparent',
17
+ base: {
18
+ zIndex: 1,
19
+ position: 'fixed',
20
+ top: 0,
21
+ left: 0,
22
+ width: '100%',
23
+ height: '100%',
24
+ touchAction: 'none',
25
+ userSelect: 'none',
26
+ },
27
+ decorative: {
28
+ backgroundColor: 'rgba(0, 0, 0, 0.2)',
29
+ border: 'none',
30
+ WebkitTapHighlightColor: 'transparent',
31
+ },
25
32
  },
26
33
  container: {
27
- zIndex: 2,
28
- position: 'absolute',
29
- left: 0,
30
- bottom: 0,
31
- width: '100%',
32
- backgroundColor: '#fff',
33
- borderTopRightRadius: '8px',
34
- borderTopLeftRadius: '8px',
35
- boxShadow: '0px -2px 16px rgba(0, 0, 0, 0.3)',
36
- display: 'flex',
37
- flexDirection: 'column',
38
- pointerEvents: 'auto',
34
+ base: {
35
+ zIndex: 2,
36
+ position: 'absolute',
37
+ left: 0,
38
+ bottom: 0,
39
+ width: '100%',
40
+ pointerEvents: 'auto',
41
+ display: 'flex',
42
+ flexDirection: 'column',
43
+ },
44
+ decorative: {
45
+ backgroundColor: '#fff',
46
+ borderTopRightRadius: '8px',
47
+ borderTopLeftRadius: '8px',
48
+ boxShadow: '0px -2px 16px rgba(0, 0, 0, 0.3)',
49
+ },
39
50
  },
40
51
  headerWrapper: {
41
- width: '100%',
52
+ base: {
53
+ width: '100%',
54
+ },
55
+ decorative: {},
42
56
  },
43
57
  header: {
44
- height: '40px',
45
- width: '100%',
46
- position: 'relative',
47
- display: 'flex',
48
- alignItems: 'center',
49
- justifyContent: 'center',
58
+ base: {
59
+ width: '100%',
60
+ position: 'relative',
61
+ },
62
+ decorative: {
63
+ height: '40px',
64
+ display: 'flex',
65
+ alignItems: 'center',
66
+ justifyContent: 'center',
67
+ },
68
+ },
69
+ indicatorWrapper: {
70
+ base: {
71
+ display: 'flex',
72
+ },
73
+ decorative: {},
50
74
  },
51
75
  indicator: {
52
- width: '18px',
53
- height: '4px',
54
- borderRadius: '99px',
55
- backgroundColor: '#ddd',
76
+ base: {
77
+ display: 'inline-block',
78
+ },
79
+ decorative: {
80
+ width: '18px',
81
+ height: '4px',
82
+ borderRadius: '99px',
83
+ backgroundColor: '#ddd',
84
+ },
56
85
  },
57
86
  content: {
58
- flexGrow: 1,
59
- display: 'flex',
60
- flexDirection: 'column',
61
- minHeight: '0px',
62
- position: 'relative',
87
+ base: {
88
+ minHeight: '0px',
89
+ position: 'relative',
90
+ flexGrow: 1,
91
+ display: 'flex',
92
+ flexDirection: 'column',
93
+ },
94
+ decorative: {},
63
95
  },
64
96
  scroller: {
65
- height: '100%',
66
- overflowY: 'auto',
67
- overscrollBehaviorY: 'none',
97
+ base: {
98
+ height: '100%',
99
+ overflowY: 'auto',
100
+ overscrollBehaviorY: 'none',
101
+ },
102
+ decorative: {},
68
103
  },
69
- } satisfies Record<string, Properties>;
104
+ } satisfies Record<
105
+ string,
106
+ {
107
+ base: CSSProperties;
108
+ decorative: CSSProperties;
109
+ }
110
+ >;
package/src/types.tsx CHANGED
@@ -1,6 +1,9 @@
1
1
  import {
2
+ type CSSProperties,
2
3
  type ComponentPropsWithoutRef,
3
4
  type ForwardRefExoticComponent,
5
+ type FunctionComponent,
6
+ type HTMLAttributes,
4
7
  type ReactNode,
5
8
  type RefAttributes,
6
9
  type RefObject,
@@ -11,17 +14,20 @@ import {
11
14
  type EasingDefinition,
12
15
  type MotionProps,
13
16
  type MotionValue,
14
- type Transition,
15
17
  type motion,
16
18
  } from 'motion/react';
17
- import type { RectReadOnly } from 'react-use-measure';
18
19
 
19
20
  export type SheetDetent = 'default' | 'full' | 'content';
20
21
 
21
- type CommonProps = MotionProps & {
22
+ type CommonProps = {
22
23
  className?: string;
24
+ style?: CSSProperties;
25
+ unstyled?: boolean;
23
26
  };
24
27
 
28
+ type MotionCommonProps = Omit<MotionProps, 'initial' | 'animate' | 'exit'> &
29
+ CommonProps;
30
+
25
31
  type MotionDivProps = ComponentPropsWithoutRef<typeof motion.div>;
26
32
 
27
33
  export interface SheetTweenConfig {
@@ -30,6 +36,7 @@ export interface SheetTweenConfig {
30
36
  }
31
37
 
32
38
  export type SheetProps = {
39
+ unstyled?: boolean;
33
40
  avoidKeyboard?: boolean;
34
41
  children: ReactNode;
35
42
  detent?: SheetDetent;
@@ -54,22 +61,28 @@ export type SheetProps = {
54
61
  onSnap?: (index: number) => void;
55
62
  } & MotionDivProps;
56
63
 
57
- export type SheetContainerProps = Omit<
58
- CommonProps,
59
- 'initial' | 'animate' | 'exit' | 'onAnimationComplete'
60
- > & {
61
- children: ReactNode;
62
- };
64
+ export type SheetContainerProps = MotionCommonProps &
65
+ CommonProps & {
66
+ children: ReactNode;
67
+ };
63
68
 
64
- export type SheetDraggableProps = MotionDivProps & {
65
- children?: ReactNode;
66
- disableDrag?: boolean;
67
- };
69
+ export type SheetHeaderProps = MotionDivProps &
70
+ CommonProps & {
71
+ children?: ReactNode;
72
+ disableDrag?: boolean;
73
+ };
68
74
 
69
- export type SheetBackdropProps = Omit<
70
- CommonProps,
71
- 'initial' | 'animate' | 'exit'
72
- >;
75
+ export type SheetContentProps = MotionDivProps &
76
+ CommonProps & {
77
+ disableDrag?: boolean | ((args: SheetStateInfo) => boolean);
78
+ disableScroll?: boolean | ((args: SheetStateInfo) => boolean);
79
+ scrollRef?: RefObject<HTMLDivElement | null>;
80
+ };
81
+
82
+ export type SheetBackdropProps = MotionCommonProps & CommonProps;
83
+
84
+ export type SheetDragIndicatorProps = HTMLAttributes<HTMLDivElement> &
85
+ CommonProps;
73
86
 
74
87
  export interface SheetDragProps {
75
88
  drag: 'y';
@@ -86,12 +99,6 @@ export type SheetStateInfo = {
86
99
  currentSnap?: number;
87
100
  };
88
101
 
89
- export type SheetContentScrollableProps = MotionDivProps & {
90
- disableDrag?: boolean | ((args: SheetStateInfo) => boolean);
91
- disableScroll?: boolean | ((args: SheetStateInfo) => boolean);
92
- scrollRef?: RefObject<HTMLDivElement | null>;
93
- };
94
-
95
102
  export type SheetSnapPoint = {
96
103
  snapIndex: number;
97
104
  snapValue: number; // Absolute value from the bottom of the sheet
@@ -107,6 +114,7 @@ export interface SheetContextType {
107
114
  avoidKeyboard: boolean;
108
115
  sheetBoundsRef: (node: HTMLDivElement | null) => void;
109
116
  sheetRef: RefObject<any>;
117
+ unstyled: boolean;
110
118
  y: MotionValue<any>;
111
119
  }
112
120
 
@@ -116,30 +124,31 @@ export interface SheetScrollerContextType {
116
124
  setDragEnabled: () => void;
117
125
  }
118
126
 
127
+ type SheetComponent = ForwardRefExoticComponent<
128
+ SheetProps & RefAttributes<any>
129
+ >;
130
+
119
131
  type ContainerComponent = ForwardRefExoticComponent<
120
132
  SheetContainerProps & RefAttributes<any>
121
133
  >;
122
134
 
123
- type DraggableComponent = ForwardRefExoticComponent<
124
- SheetDraggableProps & RefAttributes<any>
135
+ type HeaderComponent = ForwardRefExoticComponent<
136
+ SheetHeaderProps & RefAttributes<any>
125
137
  >;
126
138
 
127
139
  type BackdropComponent = ForwardRefExoticComponent<
128
140
  SheetBackdropProps & RefAttributes<any>
129
141
  >;
130
142
 
131
- type SheetComponent = ForwardRefExoticComponent<
132
- SheetProps & RefAttributes<any>
133
- >;
134
-
135
- type ContentScrollableComponent = ForwardRefExoticComponent<
136
- SheetContentScrollableProps & RefAttributes<any>
143
+ type ContentComponent = ForwardRefExoticComponent<
144
+ SheetContentProps & RefAttributes<any>
137
145
  >;
138
146
 
139
147
  interface SheetCompoundComponent {
140
148
  Container: ContainerComponent;
141
- Header: DraggableComponent;
142
- Content: ContentScrollableComponent;
149
+ Header: HeaderComponent;
150
+ DragIndicator: FunctionComponent<SheetDragIndicatorProps>;
151
+ Content: ContentComponent;
143
152
  Backdrop: BackdropComponent;
144
153
  }
145
154
 
package/src/utils.ts CHANGED
@@ -1,6 +1,13 @@
1
- import { type ForwardedRef, type RefCallback, type RefObject } from 'react';
1
+ import { type CSSProperties, type ForwardedRef, type RefCallback } from 'react';
2
2
  import { IS_SSR } from './constants';
3
3
 
4
+ export function applyStyles(
5
+ styles: { base: CSSProperties; decorative: CSSProperties },
6
+ unstyled: boolean
7
+ ) {
8
+ return unstyled ? styles.base : { ...styles.base, ...styles.decorative };
9
+ }
10
+
4
11
  export function isAscendingOrder(arr: number[]) {
5
12
  for (let i = 0; i < arr.length; i++) {
6
13
  if (arr[i + 1] < arr[i]) return false;