react-modal-sheet 1.6.3 → 1.8.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.
- package/README.md +69 -36
- package/dist/SheetBackdrop.d.ts +1 -1
- package/dist/SheetContent.d.ts +1 -1
- package/dist/SheetHeader.d.ts +1 -1
- package/dist/constants.d.ts +9 -0
- package/dist/hooks.d.ts +4 -0
- package/dist/react-modal-sheet.cjs.development.js +190 -130
- package/dist/react-modal-sheet.cjs.development.js.map +1 -1
- package/dist/react-modal-sheet.cjs.production.min.js +1 -1
- package/dist/react-modal-sheet.cjs.production.min.js.map +1 -1
- package/dist/react-modal-sheet.esm.js +192 -132
- package/dist/react-modal-sheet.esm.js.map +1 -1
- package/dist/sheet.d.ts +2 -0
- package/dist/types.d.ts +8 -4
- package/dist/utils.d.ts +6 -4
- package/package.json +2 -2
- package/src/SheetContainer.tsx +15 -12
- package/src/SheetContent.tsx +3 -3
- package/src/SheetHeader.tsx +2 -2
- package/src/constants.ts +13 -0
- package/src/hooks.tsx +35 -2
- package/src/sheet.tsx +122 -71
- package/src/types.tsx +9 -3
- package/src/utils.ts +21 -23
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
<p align='center'>
|
|
2
|
+
<img src="media/banner.jpg" alt="React Modal Sheet logo"/>
|
|
3
|
+
<p/>
|
|
4
|
+
|
|
1
5
|
<div align="center" >
|
|
2
|
-
<br/>
|
|
3
|
-
<br/>
|
|
4
|
-
<h1>🪐 React Modal Sheet</h1>
|
|
5
6
|
·
|
|
6
7
|
<i>Flexible bottom sheet component for your React apps</i>
|
|
7
8
|
·
|
|
@@ -40,11 +41,11 @@ npm install framer-motion
|
|
|
40
41
|
## Usage
|
|
41
42
|
|
|
42
43
|
```jsx
|
|
43
|
-
import React from 'react';
|
|
44
44
|
import Sheet from 'react-modal-sheet';
|
|
45
|
+
import { useState } from 'react';
|
|
45
46
|
|
|
46
47
|
function Example() {
|
|
47
|
-
const [isOpen, setOpen] =
|
|
48
|
+
const [isOpen, setOpen] = useState(false);
|
|
48
49
|
|
|
49
50
|
return (
|
|
50
51
|
<>
|
|
@@ -71,22 +72,24 @@ Also, by constructing the sheet from smaller pieces makes it easier to apply any
|
|
|
71
72
|
|
|
72
73
|
## Props
|
|
73
74
|
|
|
74
|
-
| Name
|
|
75
|
-
|
|
76
|
-
| `children`
|
|
77
|
-
| `isOpen`
|
|
78
|
-
| `onClose`
|
|
79
|
-
| `disableDrag`
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
75
|
+
| Name | Required | Default | Description |
|
|
76
|
+
|------------------------|----------|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
77
|
+
| `children` | yes | | Use `Sheet.Container/Content/Header/Backdrop` to compose your bottom sheet. |
|
|
78
|
+
| `isOpen` | yes | | Boolean that indicates whether the sheet is open or not. |
|
|
79
|
+
| `onClose` | yes | | Callback fn that is called when the sheet is closed by the user. |
|
|
80
|
+
| `disableDrag` | no | false | Disable drag for the whole sheet. |
|
|
81
|
+
| `detent` | no | `'full-height'` | The [detent](https://developer.apple.com/design/human-interface-guidelines/components/presentation/sheets#ios-ipados) in which the sheet should be in when opened. Available values: `'full-height'` or `'content-height'`. |
|
|
82
|
+
| `onOpenStart` | no | | Callback fn that is called when the sheet opening animation starts. |
|
|
83
|
+
| `onOpenEnd` | no | | Callback fn that is called when the sheet opening animation is completed. |
|
|
84
|
+
| `onCloseStart` | no | | Callback fn that is called when the sheet closing animation starts. |
|
|
85
|
+
| `onCloseEnd` | no | | Callback fn that is called when the sheet closing animation is completed. |
|
|
86
|
+
| `onSnap` | no | | Callback fn that is called with the current snap point index when the sheet snaps to a new snap point. Requires `snapPoints` prop. |
|
|
87
|
+
| `snapPoints` | no | | Eg. `[-50, 0.5, 100, 0]` - where positive values are pixels from the bottom of the screen and negative from the top. Values between 0-1 represent percentages, eg. `0.5` means 50% of window height from the bottom of the sceen. |
|
|
88
|
+
| `initialSnap` | no | 0 | Initial snap point when sheet is opened (index from `snapPoints`). |
|
|
89
|
+
| `rootId` | no | | The id of the element where the main app is mounted, eg. "root". Enables iOS modal effect. |
|
|
90
|
+
| `springConfig` | no | `DEFAULT_SPRING` | Overrides the config for the [spring animation](https://www.framer.com/api/motion/types/#spring). |
|
|
91
|
+
| `mountPoint` | no | `document.body` | HTML element that should be used as the mount point for the sheet. |
|
|
92
|
+
| `prefersReducedMotion` | no | false | Skip sheet animations (sheet instantly snaps to desired location). |
|
|
90
93
|
|
|
91
94
|
**`DEFAULT_SPRING`**
|
|
92
95
|
|
|
@@ -107,12 +110,12 @@ Spring animation happens when the sheet is opened/closed or when it snaps to a s
|
|
|
107
110
|
Imperative method that can be accessed via a ref for snapping to a snap point in given index.
|
|
108
111
|
|
|
109
112
|
```tsx
|
|
110
|
-
import React from 'react';
|
|
111
113
|
import Sheet, { SheetRef } from 'react-modal-sheet';
|
|
114
|
+
import { useState, useRef } from 'react';
|
|
112
115
|
|
|
113
116
|
function Example() {
|
|
114
|
-
const [isOpen, setOpen] =
|
|
115
|
-
const ref =
|
|
117
|
+
const [isOpen, setOpen] = useState(false);
|
|
118
|
+
const ref = useRef<SheetRef>();
|
|
116
119
|
const snapTo = (i: number) => ref.current?.snapTo(i);
|
|
117
120
|
|
|
118
121
|
return (
|
|
@@ -153,12 +156,12 @@ Similarly to the `snapTo` method the `y` value can be accessed via a ref.
|
|
|
153
156
|
The `y` value can be useful for certain situtation eg. when you want to combine snap points with scrollable sheet content and ensure that the content stays properly scrollable in any snap point. Below you can see a simplified example of this situation and for a more detailed example take a look at the [ScrollableSnapPoints](example/components/ScrollableSnapPoints.tsx) component in the example app.
|
|
154
157
|
|
|
155
158
|
```tsx
|
|
156
|
-
import React from 'react';
|
|
157
159
|
import Sheet, { SheetRef } from 'react-modal-sheet';
|
|
160
|
+
import { useState, useRef } from 'react';
|
|
158
161
|
|
|
159
162
|
function Example() {
|
|
160
|
-
const [isOpen, setOpen] =
|
|
161
|
-
const ref =
|
|
163
|
+
const [isOpen, setOpen] = useState(false);
|
|
164
|
+
const ref = useRef<SheetRef>();
|
|
162
165
|
|
|
163
166
|
return (
|
|
164
167
|
<>
|
|
@@ -189,6 +192,36 @@ function Example() {
|
|
|
189
192
|
}
|
|
190
193
|
```
|
|
191
194
|
|
|
195
|
+
### Detents
|
|
196
|
+
|
|
197
|
+
By default the sheet will take the full height of the page minus top padding and safe area inset. If you want the sheet height to be based on it's content you can pass `detent="content-height"` prop to the `Sheet` component:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
function Example() {
|
|
201
|
+
const [isOpen, setOpen] = useState(false);
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<Sheet
|
|
205
|
+
isOpen={isOpen}
|
|
206
|
+
onClose={() => setOpen(false)}
|
|
207
|
+
detent="content-height"
|
|
208
|
+
>
|
|
209
|
+
<Sheet.Container>
|
|
210
|
+
<Sheet.Content>
|
|
211
|
+
<div style={{ height: 200 }}>Some content</div>
|
|
212
|
+
</Sheet.Content>
|
|
213
|
+
</Sheet.Container>
|
|
214
|
+
</Sheet>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
If the sheet height changes dynamically the sheet will grow until it hits the maximum full height after which it becomes scrollable.
|
|
220
|
+
|
|
221
|
+
It is possible to use snap points with `detent="content-height"` **but** the snap points are restricted by the content height. For example if one of the snap points is 800px and the sheet height is only 700px then snapping to the 800px snap point would only snap to 700px since otherwise the sheet would become detached from the bottom.
|
|
222
|
+
|
|
223
|
+
> ℹ️ If you are wondering where the term `detent` comes from it's from Apple's [Human Interface Guidelines](<[detent](https://developer.apple.com/design/human-interface-guidelines/components/presentation/sheets#ios-ipados)>).
|
|
224
|
+
|
|
192
225
|
## Compound Components
|
|
193
226
|
|
|
194
227
|
### `Sheet.Container`
|
|
@@ -206,7 +239,7 @@ Sheet content acts as a drag target and makes sure that content which doesn't fi
|
|
|
206
239
|
#### Content props
|
|
207
240
|
|
|
208
241
|
| Name | Required | Default | Description |
|
|
209
|
-
|
|
242
|
+
|---------------|----------|---------|-------------------------------------|
|
|
210
243
|
| `disableDrag` | no | false | Disable drag for the sheet content. |
|
|
211
244
|
|
|
212
245
|
### `Sheet.Header`
|
|
@@ -218,7 +251,7 @@ Sheet header acts as a drag target and has a dragging direction indicator. Rende
|
|
|
218
251
|
#### Header props
|
|
219
252
|
|
|
220
253
|
| Name | Required | Default | Description |
|
|
221
|
-
|
|
254
|
+
|---------------|----------|---------|------------------------------------|
|
|
222
255
|
| `disableDrag` | no | false | Disable drag for the sheet header. |
|
|
223
256
|
|
|
224
257
|
### `Sheet.Backdrop`
|
|
@@ -300,9 +333,9 @@ You can add your own styles or override the default sheet styles via the exposed
|
|
|
300
333
|
#### CSS-in-JS
|
|
301
334
|
|
|
302
335
|
```jsx
|
|
303
|
-
import React from 'react';
|
|
304
|
-
import styled from 'styled-components';
|
|
305
336
|
import Sheet from 'react-modal-sheeet';
|
|
337
|
+
import styled from 'styled-components';
|
|
338
|
+
import { useState } from 'react';
|
|
306
339
|
|
|
307
340
|
const CustomSheet = styled(Sheet)`
|
|
308
341
|
.react-modal-sheet-backdrop {
|
|
@@ -323,7 +356,7 @@ const CustomSheet = styled(Sheet)`
|
|
|
323
356
|
`;
|
|
324
357
|
|
|
325
358
|
function Example() {
|
|
326
|
-
const [isOpen, setOpen] =
|
|
359
|
+
const [isOpen, setOpen] = useState(false);
|
|
327
360
|
|
|
328
361
|
return (
|
|
329
362
|
<>
|
|
@@ -351,8 +384,8 @@ The example below utilizes React Aria to achieve an accessible modal-like bottom
|
|
|
351
384
|
> ℹ️ The example was built by following the React Aria's [useDialog](https://react-spectrum.adobe.com/react-aria/useDialog.html) documentation.
|
|
352
385
|
|
|
353
386
|
```jsx
|
|
354
|
-
import React from 'react';
|
|
355
387
|
import Sheet from 'react-modal-sheet';
|
|
388
|
+
import { useRef } from 'react';
|
|
356
389
|
import { useOverlayTriggerState } from 'react-stately';
|
|
357
390
|
|
|
358
391
|
import {
|
|
@@ -366,7 +399,7 @@ import {
|
|
|
366
399
|
|
|
367
400
|
const A11yExample = () => {
|
|
368
401
|
const sheetState = useOverlayTriggerState({});
|
|
369
|
-
const openButtonRef =
|
|
402
|
+
const openButtonRef = useRef(null);
|
|
370
403
|
const openButton = useButton({ onPress: sheetState.open }, openButtonRef);
|
|
371
404
|
|
|
372
405
|
return (
|
|
@@ -387,14 +420,14 @@ const A11yExample = () => {
|
|
|
387
420
|
};
|
|
388
421
|
|
|
389
422
|
const SheetComp = ({ sheetState }) => {
|
|
390
|
-
const containerRef =
|
|
423
|
+
const containerRef = useRef(null);
|
|
391
424
|
const dialog = useDialog({}, containerRef);
|
|
392
425
|
const overlay = useOverlay(
|
|
393
426
|
{ onClose: sheetState.close, isOpen: true, isDismissable: true },
|
|
394
427
|
containerRef
|
|
395
428
|
);
|
|
396
429
|
|
|
397
|
-
const closeButtonRef =
|
|
430
|
+
const closeButtonRef = useRef(null);
|
|
398
431
|
const closeButton = useButton(
|
|
399
432
|
{ onPress: sheetState.close, 'aria-label': 'Close sheet' },
|
|
400
433
|
closeButtonRef
|
package/dist/SheetBackdrop.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
declare const SheetBackdrop: React.ForwardRefExoticComponent<Pick<import("framer-motion").MotionProps, "style" | "transformTemplate" | "transformValues" | "variants" | "transition" | "
|
|
2
|
+
declare const SheetBackdrop: React.ForwardRefExoticComponent<Pick<import("framer-motion").MotionProps, "style" | "transformTemplate" | "transformValues" | "variants" | "transition" | "onBeforeLayoutMeasure" | "onLayoutMeasure" | "onLayoutAnimationStart" | "onLayoutAnimationComplete" | "onUpdate" | "onAnimationStart" | "onAnimationComplete" | "onUnmount" | "onPan" | "onPanStart" | "onPanSessionStart" | "onPanEnd" | "onTap" | "onTapStart" | "onTapCancel" | "whileTap" | "whileHover" | "onHoverStart" | "onHoverEnd" | "whileFocus" | "whileInView" | "onViewportEnter" | "onViewportLeave" | "viewport" | "drag" | "whileDrag" | "dragDirectionLock" | "dragPropagation" | "dragConstraints" | "dragElastic" | "dragMomentum" | "dragTransition" | "dragControls" | "dragSnapToOrigin" | "dragListener" | "onMeasureDragConstraints" | "_dragX" | "_dragY" | "onDragStart" | "onDragEnd" | "onDrag" | "onDirectionLock" | "onDragTransitionEnd" | "layout" | "layoutId" | "layoutDependency" | "layoutScroll" | "custom" | "inherit"> & React.RefAttributes<any>>;
|
|
3
3
|
export default SheetBackdrop;
|
package/dist/SheetContent.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
declare const SheetContent: React.ForwardRefExoticComponent<Pick<import("framer-motion").MotionProps, "
|
|
2
|
+
declare const SheetContent: React.ForwardRefExoticComponent<Pick<import("framer-motion").MotionProps, "style" | "transformTemplate" | "transformValues" | "initial" | "animate" | "exit" | "variants" | "transition" | "onBeforeLayoutMeasure" | "onLayoutMeasure" | "onLayoutAnimationStart" | "onLayoutAnimationComplete" | "onUpdate" | "onAnimationStart" | "onAnimationComplete" | "onUnmount" | "onPan" | "onPanStart" | "onPanSessionStart" | "onPanEnd" | "onTap" | "onTapStart" | "onTapCancel" | "whileTap" | "whileHover" | "onHoverStart" | "onHoverEnd" | "whileFocus" | "whileInView" | "onViewportEnter" | "onViewportLeave" | "viewport" | "whileDrag" | "dragDirectionLock" | "dragPropagation" | "dragTransition" | "dragControls" | "dragSnapToOrigin" | "dragListener" | "onMeasureDragConstraints" | "_dragX" | "_dragY" | "onDirectionLock" | "onDragTransitionEnd" | "layout" | "layoutId" | "layoutDependency" | "layoutScroll" | "custom" | "inherit"> & {
|
|
3
3
|
children?: React.ReactNode;
|
|
4
4
|
disableDrag?: boolean | undefined;
|
|
5
5
|
} & React.RefAttributes<any>>;
|
package/dist/SheetHeader.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
declare const SheetHeader: React.ForwardRefExoticComponent<Pick<import("framer-motion").MotionProps, "
|
|
2
|
+
declare const SheetHeader: React.ForwardRefExoticComponent<Pick<import("framer-motion").MotionProps, "style" | "transformTemplate" | "transformValues" | "initial" | "animate" | "exit" | "variants" | "transition" | "onBeforeLayoutMeasure" | "onLayoutMeasure" | "onLayoutAnimationStart" | "onLayoutAnimationComplete" | "onUpdate" | "onAnimationStart" | "onAnimationComplete" | "onUnmount" | "onPan" | "onPanStart" | "onPanSessionStart" | "onPanEnd" | "onTap" | "onTapStart" | "onTapCancel" | "whileTap" | "whileHover" | "onHoverStart" | "onHoverEnd" | "whileFocus" | "whileInView" | "onViewportEnter" | "onViewportLeave" | "viewport" | "whileDrag" | "dragDirectionLock" | "dragPropagation" | "dragTransition" | "dragControls" | "dragSnapToOrigin" | "dragListener" | "onMeasureDragConstraints" | "_dragX" | "_dragY" | "onDirectionLock" | "onDragTransitionEnd" | "layout" | "layoutId" | "layoutDependency" | "layoutScroll" | "custom" | "inherit"> & {
|
|
3
3
|
children?: React.ReactNode;
|
|
4
4
|
disableDrag?: boolean | undefined;
|
|
5
5
|
} & React.RefAttributes<any>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const MAX_HEIGHT = "calc(100% - env(safe-area-inset-top) - 34px)";
|
|
2
|
+
export declare const IS_SSR: boolean;
|
|
3
|
+
export declare const DEFAULT_SPRING_CONFIG: {
|
|
4
|
+
stiffness: number;
|
|
5
|
+
damping: number;
|
|
6
|
+
mass: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const DRAG_CLOSE_THRESHOLD = 0.6;
|
|
9
|
+
export declare const DRAG_VELOCITY_THRESHOLD = 500;
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { SheetEvents } from './types';
|
|
3
|
+
export declare const useIsomorphicLayoutEffect: typeof React.useEffect;
|
|
3
4
|
export declare const useModalEffect: (isOpen: boolean, rootId?: string | undefined) => void;
|
|
4
5
|
export declare const useEventCallbacks: (isOpen: boolean, callbacks: React.MutableRefObject<SheetEvents>) => {
|
|
5
6
|
handleAnimationComplete: () => void;
|
|
6
7
|
};
|
|
8
|
+
export declare function useWindowHeight(): number;
|
|
9
|
+
export declare function usePrevious<T>(state: T): T | undefined;
|
|
10
|
+
export declare function useEvent<T extends (...args: any[]) => any>(handler: T): T;
|