cozy-ui 60.3.0 → 60.4.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/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/react/BottomSheet/BottomSheet.jsx +190 -0
- package/react/BottomSheet/BottomSheetHeader.jsx +23 -0
- package/react/BottomSheet/BottomSheetItem.jsx +35 -0
- package/react/BottomSheet/README.md +33 -0
- package/react/BottomSheet/index.jsx +3 -0
- package/react/Viewer/Footer/BottomSheetContent.jsx +15 -53
- package/react/Viewer/Footer/FooterContent.jsx +11 -15
- package/react/Viewer/Readme.md +0 -1
- package/react/index.js +1 -0
- package/transpiled/react/BottomSheet/BottomSheet.js +202 -0
- package/transpiled/react/BottomSheet/BottomSheetHeader.js +20 -0
- package/transpiled/react/BottomSheet/BottomSheetItem.js +35 -0
- package/transpiled/react/BottomSheet/index.js +3 -0
- package/transpiled/react/Viewer/Footer/BottomSheetContent.js +12 -44
- package/transpiled/react/Viewer/Footer/FooterContent.js +17 -11
- package/transpiled/react/index.js +2 -1
- package/react/Viewer/Footer/BottomSheetWrapper.jsx +0 -121
- package/transpiled/react/Viewer/Footer/BottomSheetWrapper.js +0 -136
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# [60.4.0](https://github.com/cozy/cozy-ui/compare/v60.3.0...v60.4.0) (2022-01-20)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Add new BottomSheet component ([7064202](https://github.com/cozy/cozy-ui/commit/7064202))
|
|
7
|
+
* Replace the Viewer BottomSheet by the new one ([184b5af](https://github.com/cozy/cozy-ui/commit/184b5af))
|
|
8
|
+
|
|
1
9
|
# [60.3.0](https://github.com/cozy/cozy-ui/compare/v60.2.0...v60.3.0) (2022-01-19)
|
|
2
10
|
|
|
3
11
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef, useMemo } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { BottomSheet as MuiBottomSheet } from 'mui-bottom-sheet'
|
|
4
|
+
|
|
5
|
+
import Stack from 'cozy-ui/transpiled/react/Stack'
|
|
6
|
+
import Paper from 'cozy-ui/transpiled/react/Paper'
|
|
7
|
+
|
|
8
|
+
const makeStyles = ({ isTopPosition }) => ({
|
|
9
|
+
root: {
|
|
10
|
+
borderTopLeftRadius: '1rem',
|
|
11
|
+
borderTopRightRadius: '1rem',
|
|
12
|
+
transition: 'border-radius 0.5s',
|
|
13
|
+
zIndex: 'var(--zIndex-drawer)',
|
|
14
|
+
boxShadow: '0 6px 16px 0 rgba(0, 0, 0, 0.5)',
|
|
15
|
+
backgroundColor: 'var(--paperBackgroundColor)',
|
|
16
|
+
...(isTopPosition && {
|
|
17
|
+
borderTopLeftRadius: 0,
|
|
18
|
+
borderTopRightRadius: 0,
|
|
19
|
+
boxShadow: '0 0 1px 0 rgba(0, 0, 0, 0.5)'
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
indicator: {
|
|
23
|
+
width: '4rem',
|
|
24
|
+
height: '0.25rem',
|
|
25
|
+
borderRadius: '99px',
|
|
26
|
+
backgroundColor: 'var(--secondaryTextColor)'
|
|
27
|
+
},
|
|
28
|
+
stack: {
|
|
29
|
+
backgroundColor: 'var(--defaultBackgroundColor)'
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export const defaultBottomSheetSpringConfig = {
|
|
34
|
+
tension: 165,
|
|
35
|
+
friction: 17,
|
|
36
|
+
clamp: true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const defaultSettings = {
|
|
40
|
+
mediumHeightRatio: 0.33
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const computeMaxHeight = toolbarProps => {
|
|
44
|
+
const { ref, height } = toolbarProps
|
|
45
|
+
let computedToolbarHeight = 1
|
|
46
|
+
|
|
47
|
+
if (height) {
|
|
48
|
+
computedToolbarHeight = height
|
|
49
|
+
} else if (ref && ref.current) {
|
|
50
|
+
computedToolbarHeight = ref.current.offsetHeight
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return window.innerHeight - computedToolbarHeight
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const BottomSheet = ({ toolbarProps, settings, children }) => {
|
|
57
|
+
const innerContentRef = useRef()
|
|
58
|
+
const headerRef = useRef()
|
|
59
|
+
const headerContentRef = useRef()
|
|
60
|
+
const [isTopPosition, setIsTopPosition] = useState(false)
|
|
61
|
+
const [peekHeights, setPeekHeights] = useState(null)
|
|
62
|
+
const [initPos, setInitPos] = useState(null)
|
|
63
|
+
const [bottomSpacerHeight, setBottomSpacerHeight] = useState(0)
|
|
64
|
+
|
|
65
|
+
const { mediumHeightRatio } = useMemo(() => settings || defaultSettings, [
|
|
66
|
+
settings
|
|
67
|
+
])
|
|
68
|
+
const styles = useMemo(() => makeStyles({ isTopPosition }), [isTopPosition])
|
|
69
|
+
|
|
70
|
+
// hack to prevent pull-down-to-refresh behavior when dragging down the bottom sheet.
|
|
71
|
+
// Needed for iOS Safari
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
document.body.style.overflow = 'hidden'
|
|
74
|
+
return () => {
|
|
75
|
+
document.body.style.overflow = 'auto'
|
|
76
|
+
}
|
|
77
|
+
}, [])
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const headerContent = headerContentRef.current
|
|
81
|
+
const maxHeight = computeMaxHeight(toolbarProps)
|
|
82
|
+
const mediumHeight = Math.round(maxHeight * mediumHeightRatio)
|
|
83
|
+
|
|
84
|
+
const actionButtonsHeight = headerContent
|
|
85
|
+
? parseFloat(getComputedStyle(headerContent).getPropertyValue('height'))
|
|
86
|
+
: 0
|
|
87
|
+
const actionButtonsBottomMargin = headerContent
|
|
88
|
+
? parseFloat(
|
|
89
|
+
getComputedStyle(headerContent).getPropertyValue('padding-bottom')
|
|
90
|
+
)
|
|
91
|
+
: 0
|
|
92
|
+
const minHeight =
|
|
93
|
+
headerRef.current.offsetHeight +
|
|
94
|
+
actionButtonsHeight +
|
|
95
|
+
actionButtonsBottomMargin
|
|
96
|
+
|
|
97
|
+
// Used so that the bottomSheet can be opened to the top,
|
|
98
|
+
// without stopping at the content height
|
|
99
|
+
const bottomSpacerHeight = maxHeight - innerContentRef.current.offsetHeight
|
|
100
|
+
|
|
101
|
+
setPeekHeights([minHeight, mediumHeight, maxHeight])
|
|
102
|
+
setInitPos(mediumHeight)
|
|
103
|
+
setBottomSpacerHeight(bottomSpacerHeight)
|
|
104
|
+
}, [
|
|
105
|
+
innerContentRef,
|
|
106
|
+
headerContentRef.current,
|
|
107
|
+
toolbarProps,
|
|
108
|
+
mediumHeightRatio
|
|
109
|
+
])
|
|
110
|
+
|
|
111
|
+
const handleOnIndexChange = snapIndex => {
|
|
112
|
+
const maxHeightSnapIndex = peekHeights.length - 1
|
|
113
|
+
|
|
114
|
+
if (snapIndex === maxHeightSnapIndex && !isTopPosition) {
|
|
115
|
+
setIsTopPosition(true)
|
|
116
|
+
}
|
|
117
|
+
if (snapIndex !== maxHeightSnapIndex && isTopPosition) {
|
|
118
|
+
setIsTopPosition(false)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const overriddenChildren = React.Children.map(children, child => {
|
|
123
|
+
if (child.type.name === 'BottomSheetHeader') {
|
|
124
|
+
return React.cloneElement(child, { headerContentRef })
|
|
125
|
+
}
|
|
126
|
+
return child
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<MuiBottomSheet
|
|
131
|
+
peekHeights={peekHeights}
|
|
132
|
+
defaultHeight={initPos}
|
|
133
|
+
backdrop={false}
|
|
134
|
+
fullHeight={false}
|
|
135
|
+
onIndexChange={snapIndex => handleOnIndexChange(snapIndex)}
|
|
136
|
+
styles={{ root: styles.root }}
|
|
137
|
+
threshold={0}
|
|
138
|
+
// springConfig doc : https://www.react-spring.io/docs/hooks/api
|
|
139
|
+
springConfig={{
|
|
140
|
+
tension: defaultBottomSheetSpringConfig.tension,
|
|
141
|
+
friction: defaultBottomSheetSpringConfig.friction,
|
|
142
|
+
clamp: defaultBottomSheetSpringConfig.clamp
|
|
143
|
+
}}
|
|
144
|
+
disabledClosing={true}
|
|
145
|
+
snapPointSeekerMode="next"
|
|
146
|
+
>
|
|
147
|
+
<div ref={innerContentRef}>
|
|
148
|
+
<Paper
|
|
149
|
+
data-testid="bottomSheet-header"
|
|
150
|
+
className="u-w-100 u-h-2-half u-pos-relative u-flex u-flex-items-center u-flex-justify-center"
|
|
151
|
+
ref={headerRef}
|
|
152
|
+
elevation={0}
|
|
153
|
+
square
|
|
154
|
+
>
|
|
155
|
+
<div style={styles.indicator} />
|
|
156
|
+
</Paper>
|
|
157
|
+
<Stack
|
|
158
|
+
style={styles.stack}
|
|
159
|
+
className="u-flex u-flex-column u-ov-hidden"
|
|
160
|
+
spacing="s"
|
|
161
|
+
>
|
|
162
|
+
{overriddenChildren}
|
|
163
|
+
</Stack>
|
|
164
|
+
</div>
|
|
165
|
+
<div style={{ height: bottomSpacerHeight }} />
|
|
166
|
+
</MuiBottomSheet>
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
BottomSheet.defaultProps = {
|
|
171
|
+
classes: {},
|
|
172
|
+
toolbarProps: {}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
BottomSheet.propTypes = {
|
|
176
|
+
/** Toolbar properties */
|
|
177
|
+
toolbarProps: PropTypes.shape({
|
|
178
|
+
/** React reference of the toolbar node */
|
|
179
|
+
ref: PropTypes.bool,
|
|
180
|
+
/** Toolbar height value */
|
|
181
|
+
height: PropTypes.func
|
|
182
|
+
}),
|
|
183
|
+
/** Settings that can be modified */
|
|
184
|
+
settings: PropTypes.shape({
|
|
185
|
+
/** Height of the middle snap point, expressed as a percentage of the viewport height */
|
|
186
|
+
mediumHeightRatio: PropTypes.number
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export default React.memo(BottomSheet)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import cx from 'classnames'
|
|
3
|
+
|
|
4
|
+
import Paper from 'cozy-ui/transpiled/react/Paper'
|
|
5
|
+
|
|
6
|
+
const BottomSheetHeader = ({ className, headerContentRef, children }) => {
|
|
7
|
+
return (
|
|
8
|
+
<Paper
|
|
9
|
+
ref={headerContentRef}
|
|
10
|
+
className={cx('u-flex u-flex-items-center', className)}
|
|
11
|
+
elevation={0}
|
|
12
|
+
square
|
|
13
|
+
>
|
|
14
|
+
{children}
|
|
15
|
+
</Paper>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
BottomSheetHeader.defaultProps = {
|
|
20
|
+
classes: {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default BottomSheetHeader
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import cx from 'classnames'
|
|
4
|
+
|
|
5
|
+
import Paper from 'cozy-ui/transpiled/react/Paper'
|
|
6
|
+
|
|
7
|
+
const BottomSheetItem = ({
|
|
8
|
+
children,
|
|
9
|
+
disableGutters,
|
|
10
|
+
disableElevation,
|
|
11
|
+
className,
|
|
12
|
+
...props
|
|
13
|
+
}) => {
|
|
14
|
+
return (
|
|
15
|
+
<Paper
|
|
16
|
+
elevation={disableElevation ? 0 : 0} // need to set correct shadow values before setting a real elevation value
|
|
17
|
+
square
|
|
18
|
+
className={cx({ 'u-p-1': !disableGutters }, className)}
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</Paper>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
BottomSheetItem.propTypes = {
|
|
27
|
+
/** CSS classes */
|
|
28
|
+
className: PropTypes.string,
|
|
29
|
+
/** Disables default padding */
|
|
30
|
+
disableGutters: PropTypes.bool,
|
|
31
|
+
/** Disables default paper elevation */
|
|
32
|
+
disableElevation: PropTypes.bool
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default React.memo(BottomSheetItem)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Displays content coming up from the bottom of the screen. The pane can be swiped to the top of the screen.
|
|
2
|
+
|
|
3
|
+
```jsx
|
|
4
|
+
import BottomSheet, { BottomSheetItem, BottomSheetHeader } from 'cozy-ui/transpiled/react/BottomSheet'
|
|
5
|
+
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
6
|
+
|
|
7
|
+
// <-- only usefull for the documentation
|
|
8
|
+
initialState = { isBottomSheetDisplayed: isTesting() }
|
|
9
|
+
const showBottomSheet = () => setState({ isBottomSheetDisplayed: true })
|
|
10
|
+
|
|
11
|
+
const settings = { mediumHeightRatio: isTesting() ? 0.90 : 0.33 }
|
|
12
|
+
// -->
|
|
13
|
+
|
|
14
|
+
;
|
|
15
|
+
|
|
16
|
+
<>
|
|
17
|
+
<Button label="Open BottomSheet" onClick={showBottomSheet} />
|
|
18
|
+
{state.isBottomSheetDisplayed && (
|
|
19
|
+
<BottomSheet settings={settings}>
|
|
20
|
+
<BottomSheetHeader className="u-ph-1 u-pb-1">
|
|
21
|
+
<Button className="u-mr-half" variant="secondary" label="Button 1" fullWidth />
|
|
22
|
+
<Button variant="secondary" label="Button 2" fullWidth />
|
|
23
|
+
</BottomSheetHeader>
|
|
24
|
+
<BottomSheetItem>
|
|
25
|
+
{content.ada.short}
|
|
26
|
+
</BottomSheetItem>
|
|
27
|
+
<BottomSheetItem disableElevation>
|
|
28
|
+
{content.ada.long}
|
|
29
|
+
</BottomSheetItem>
|
|
30
|
+
</BottomSheet>
|
|
31
|
+
)}
|
|
32
|
+
</>
|
|
33
|
+
```
|
|
@@ -1,64 +1,26 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import cx from 'classnames'
|
|
4
|
-
import { makeStyles } from '@material-ui/core/styles'
|
|
5
3
|
|
|
6
|
-
import {
|
|
4
|
+
import { BottomSheetItem } from '../../BottomSheet'
|
|
7
5
|
|
|
8
|
-
import Paper from '../../Paper'
|
|
9
|
-
import Typography from '../../Typography'
|
|
10
|
-
import Stack from '../../Stack'
|
|
11
|
-
|
|
12
|
-
import Sharing from './Sharing'
|
|
13
|
-
import ForwardButton from './ForwardButton'
|
|
14
|
-
import DownloadButton from './DownloadButton'
|
|
15
6
|
import getPanelBlocks, { panelBlocksSpecs } from '../Panel/getPanelBlocks'
|
|
16
7
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Stack
|
|
31
|
-
spacing="s"
|
|
32
|
-
className={cx('u-flex u-flex-column u-ov-hidden', styles.stack)}
|
|
33
|
-
>
|
|
34
|
-
<Paper
|
|
35
|
-
className={'u-flex u-ph-1 u-pb-1'}
|
|
36
|
-
elevation={2}
|
|
37
|
-
square
|
|
38
|
-
ref={ref}
|
|
39
|
-
>
|
|
40
|
-
{!disableSharing && <Sharing file={file} />}
|
|
41
|
-
<FileActionButton file={file} />
|
|
42
|
-
</Paper>
|
|
43
|
-
{panelBlocks.map((PanelBlock, index) => (
|
|
44
|
-
<Paper
|
|
45
|
-
key={index}
|
|
46
|
-
elevation={index === panelBlocks.length - 1 ? 0 : 2}
|
|
47
|
-
square
|
|
48
|
-
>
|
|
49
|
-
<Typography variant="h4" className={'u-pv-1 u-ph-1'}>
|
|
50
|
-
<PanelBlock file={file} contactsFullname={contactsFullname} />
|
|
51
|
-
</Typography>
|
|
52
|
-
</Paper>
|
|
53
|
-
))}
|
|
54
|
-
</Stack>
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
)
|
|
8
|
+
const BottomSheetContent = ({ file, contactsFullname }) => {
|
|
9
|
+
const panelBlocks = getPanelBlocks({ panelBlocksSpecs, file })
|
|
10
|
+
|
|
11
|
+
return panelBlocks.map((PanelBlock, index) => (
|
|
12
|
+
<BottomSheetItem
|
|
13
|
+
key={index}
|
|
14
|
+
disableElevation={index === panelBlocks.length - 1}
|
|
15
|
+
>
|
|
16
|
+
<PanelBlock file={file} contactsFullname={contactsFullname} />
|
|
17
|
+
</BottomSheetItem>
|
|
18
|
+
))
|
|
19
|
+
}
|
|
58
20
|
|
|
59
21
|
BottomSheetContent.propTypes = {
|
|
60
22
|
file: PropTypes.object.isRequired,
|
|
61
|
-
|
|
23
|
+
contactsFullname: PropTypes.string
|
|
62
24
|
}
|
|
63
25
|
|
|
64
26
|
export default BottomSheetContent
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { makeStyles } from '@material-ui/core/styles'
|
|
4
4
|
|
|
5
5
|
import { isMobileApp } from 'cozy-device-helper'
|
|
6
6
|
import { getReferencedBy, useQuery, models } from 'cozy-client'
|
|
7
7
|
|
|
8
|
+
import BottomSheet, { BottomSheetHeader } from '../../BottomSheet'
|
|
9
|
+
|
|
8
10
|
import { buildContactByIdsQuery } from '../queries'
|
|
9
11
|
import { isValidForPanel } from '../helpers'
|
|
10
12
|
import Sharing from './Sharing'
|
|
11
13
|
import ForwardButton from './ForwardButton'
|
|
12
14
|
import DownloadButton from './DownloadButton'
|
|
13
|
-
import BottomSheetWrapper from './BottomSheetWrapper'
|
|
14
15
|
import BottomSheetContent from './BottomSheetContent'
|
|
15
16
|
|
|
16
17
|
const {
|
|
@@ -32,7 +33,7 @@ const useStyles = makeStyles(theme => ({
|
|
|
32
33
|
const FooterContent = ({ file, toolbarRef, disableSharing }) => {
|
|
33
34
|
const styles = useStyles()
|
|
34
35
|
const FileActionButton = isMobileApp() ? ForwardButton : DownloadButton
|
|
35
|
-
const
|
|
36
|
+
const toolbarProps = useMemo(() => ({ ref: toolbarRef }), [toolbarRef])
|
|
36
37
|
|
|
37
38
|
const contactIds = getReferencedBy(file, 'io.cozy.contacts').map(
|
|
38
39
|
ref => ref.id
|
|
@@ -52,18 +53,13 @@ const FooterContent = ({ file, toolbarRef, disableSharing }) => {
|
|
|
52
53
|
(contactsFullname || contactIds.length === 0)
|
|
53
54
|
) {
|
|
54
55
|
return (
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<BottomSheetContent
|
|
61
|
-
|
|
62
|
-
disableSharing={disableSharing}
|
|
63
|
-
contactsFullname={contactsFullname}
|
|
64
|
-
ref={actionButtonsRef}
|
|
65
|
-
/>
|
|
66
|
-
</BottomSheetWrapper>
|
|
56
|
+
<BottomSheet toolbarProps={toolbarProps}>
|
|
57
|
+
<BottomSheetHeader className="u-ph-1 u-pb-1">
|
|
58
|
+
{!disableSharing && <Sharing file={file} />}
|
|
59
|
+
<FileActionButton file={file} />
|
|
60
|
+
</BottomSheetHeader>
|
|
61
|
+
<BottomSheetContent file={file} contactsFullname={contactsFullname} />
|
|
62
|
+
</BottomSheet>
|
|
67
63
|
)
|
|
68
64
|
}
|
|
69
65
|
|
package/react/Viewer/Readme.md
CHANGED
|
@@ -31,7 +31,6 @@ import Overlay from 'cozy-ui/transpiled/react/Overlay';
|
|
|
31
31
|
import Button from 'cozy-ui/transpiled/react/Button';
|
|
32
32
|
import DownloadIcon from 'cozy-ui/transpiled/react/Icons/Download';
|
|
33
33
|
import ShareIcon from 'cozy-ui/transpiled/react/Icons/Share';
|
|
34
|
-
import BottomSheetWrapper from 'cozy-ui/transpiled/react/Viewer/Footer/BottomSheetWrapper';
|
|
35
34
|
import { isValidForPanel } from 'cozy-ui/transpiled/react/Viewer/helpers';
|
|
36
35
|
import getPanelBlocks, { panelBlocksSpecs } from 'cozy-ui/transpiled/react/Viewer/Panel/getPanelBlocks';
|
|
37
36
|
|
package/react/index.js
CHANGED
|
@@ -99,3 +99,4 @@ export { default as Fab } from './Fab'
|
|
|
99
99
|
export { default as SquareAppIcon } from './SquareAppIcon'
|
|
100
100
|
export { default as FileImageLoader } from './FileImageLoader'
|
|
101
101
|
export { default as Radios } from './Radios'
|
|
102
|
+
export { default as BottomSheet, BottomSheetItem } from './BottomSheet'
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import _objectSpread from "@babel/runtime/helpers/objectSpread";
|
|
3
|
+
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import { BottomSheet as MuiBottomSheet } from 'mui-bottom-sheet';
|
|
6
|
+
import Stack from 'cozy-ui/transpiled/react/Stack';
|
|
7
|
+
import Paper from 'cozy-ui/transpiled/react/Paper';
|
|
8
|
+
|
|
9
|
+
var makeStyles = function makeStyles(_ref) {
|
|
10
|
+
var isTopPosition = _ref.isTopPosition;
|
|
11
|
+
return {
|
|
12
|
+
root: _objectSpread({
|
|
13
|
+
borderTopLeftRadius: '1rem',
|
|
14
|
+
borderTopRightRadius: '1rem',
|
|
15
|
+
transition: 'border-radius 0.5s',
|
|
16
|
+
zIndex: 'var(--zIndex-drawer)',
|
|
17
|
+
boxShadow: '0 6px 16px 0 rgba(0, 0, 0, 0.5)',
|
|
18
|
+
backgroundColor: 'var(--paperBackgroundColor)'
|
|
19
|
+
}, isTopPosition && {
|
|
20
|
+
borderTopLeftRadius: 0,
|
|
21
|
+
borderTopRightRadius: 0,
|
|
22
|
+
boxShadow: '0 0 1px 0 rgba(0, 0, 0, 0.5)'
|
|
23
|
+
}),
|
|
24
|
+
indicator: {
|
|
25
|
+
width: '4rem',
|
|
26
|
+
height: '0.25rem',
|
|
27
|
+
borderRadius: '99px',
|
|
28
|
+
backgroundColor: 'var(--secondaryTextColor)'
|
|
29
|
+
},
|
|
30
|
+
stack: {
|
|
31
|
+
backgroundColor: 'var(--defaultBackgroundColor)'
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export var defaultBottomSheetSpringConfig = {
|
|
37
|
+
tension: 165,
|
|
38
|
+
friction: 17,
|
|
39
|
+
clamp: true
|
|
40
|
+
};
|
|
41
|
+
var defaultSettings = {
|
|
42
|
+
mediumHeightRatio: 0.33
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
var computeMaxHeight = function computeMaxHeight(toolbarProps) {
|
|
46
|
+
var ref = toolbarProps.ref,
|
|
47
|
+
height = toolbarProps.height;
|
|
48
|
+
var computedToolbarHeight = 1;
|
|
49
|
+
|
|
50
|
+
if (height) {
|
|
51
|
+
computedToolbarHeight = height;
|
|
52
|
+
} else if (ref && ref.current) {
|
|
53
|
+
computedToolbarHeight = ref.current.offsetHeight;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return window.innerHeight - computedToolbarHeight;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
var BottomSheet = function BottomSheet(_ref2) {
|
|
60
|
+
var toolbarProps = _ref2.toolbarProps,
|
|
61
|
+
settings = _ref2.settings,
|
|
62
|
+
children = _ref2.children;
|
|
63
|
+
var innerContentRef = useRef();
|
|
64
|
+
var headerRef = useRef();
|
|
65
|
+
var headerContentRef = useRef();
|
|
66
|
+
|
|
67
|
+
var _useState = useState(false),
|
|
68
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
69
|
+
isTopPosition = _useState2[0],
|
|
70
|
+
setIsTopPosition = _useState2[1];
|
|
71
|
+
|
|
72
|
+
var _useState3 = useState(null),
|
|
73
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
74
|
+
peekHeights = _useState4[0],
|
|
75
|
+
setPeekHeights = _useState4[1];
|
|
76
|
+
|
|
77
|
+
var _useState5 = useState(null),
|
|
78
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
79
|
+
initPos = _useState6[0],
|
|
80
|
+
setInitPos = _useState6[1];
|
|
81
|
+
|
|
82
|
+
var _useState7 = useState(0),
|
|
83
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
84
|
+
bottomSpacerHeight = _useState8[0],
|
|
85
|
+
setBottomSpacerHeight = _useState8[1];
|
|
86
|
+
|
|
87
|
+
var _useMemo = useMemo(function () {
|
|
88
|
+
return settings || defaultSettings;
|
|
89
|
+
}, [settings]),
|
|
90
|
+
mediumHeightRatio = _useMemo.mediumHeightRatio;
|
|
91
|
+
|
|
92
|
+
var styles = useMemo(function () {
|
|
93
|
+
return makeStyles({
|
|
94
|
+
isTopPosition: isTopPosition
|
|
95
|
+
});
|
|
96
|
+
}, [isTopPosition]); // hack to prevent pull-down-to-refresh behavior when dragging down the bottom sheet.
|
|
97
|
+
// Needed for iOS Safari
|
|
98
|
+
|
|
99
|
+
useEffect(function () {
|
|
100
|
+
document.body.style.overflow = 'hidden';
|
|
101
|
+
return function () {
|
|
102
|
+
document.body.style.overflow = 'auto';
|
|
103
|
+
};
|
|
104
|
+
}, []);
|
|
105
|
+
useEffect(function () {
|
|
106
|
+
var headerContent = headerContentRef.current;
|
|
107
|
+
var maxHeight = computeMaxHeight(toolbarProps);
|
|
108
|
+
var mediumHeight = Math.round(maxHeight * mediumHeightRatio);
|
|
109
|
+
var actionButtonsHeight = headerContent ? parseFloat(getComputedStyle(headerContent).getPropertyValue('height')) : 0;
|
|
110
|
+
var actionButtonsBottomMargin = headerContent ? parseFloat(getComputedStyle(headerContent).getPropertyValue('padding-bottom')) : 0;
|
|
111
|
+
var minHeight = headerRef.current.offsetHeight + actionButtonsHeight + actionButtonsBottomMargin; // Used so that the bottomSheet can be opened to the top,
|
|
112
|
+
// without stopping at the content height
|
|
113
|
+
|
|
114
|
+
var bottomSpacerHeight = maxHeight - innerContentRef.current.offsetHeight;
|
|
115
|
+
setPeekHeights([minHeight, mediumHeight, maxHeight]);
|
|
116
|
+
setInitPos(mediumHeight);
|
|
117
|
+
setBottomSpacerHeight(bottomSpacerHeight);
|
|
118
|
+
}, [innerContentRef, headerContentRef.current, toolbarProps, mediumHeightRatio]);
|
|
119
|
+
|
|
120
|
+
var handleOnIndexChange = function handleOnIndexChange(snapIndex) {
|
|
121
|
+
var maxHeightSnapIndex = peekHeights.length - 1;
|
|
122
|
+
|
|
123
|
+
if (snapIndex === maxHeightSnapIndex && !isTopPosition) {
|
|
124
|
+
setIsTopPosition(true);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (snapIndex !== maxHeightSnapIndex && isTopPosition) {
|
|
128
|
+
setIsTopPosition(false);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
var overriddenChildren = React.Children.map(children, function (child) {
|
|
133
|
+
if (child.type.name === 'BottomSheetHeader') {
|
|
134
|
+
return React.cloneElement(child, {
|
|
135
|
+
headerContentRef: headerContentRef
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return child;
|
|
140
|
+
});
|
|
141
|
+
return React.createElement(MuiBottomSheet, {
|
|
142
|
+
peekHeights: peekHeights,
|
|
143
|
+
defaultHeight: initPos,
|
|
144
|
+
backdrop: false,
|
|
145
|
+
fullHeight: false,
|
|
146
|
+
onIndexChange: function onIndexChange(snapIndex) {
|
|
147
|
+
return handleOnIndexChange(snapIndex);
|
|
148
|
+
},
|
|
149
|
+
styles: {
|
|
150
|
+
root: styles.root
|
|
151
|
+
},
|
|
152
|
+
threshold: 0 // springConfig doc : https://www.react-spring.io/docs/hooks/api
|
|
153
|
+
,
|
|
154
|
+
springConfig: {
|
|
155
|
+
tension: defaultBottomSheetSpringConfig.tension,
|
|
156
|
+
friction: defaultBottomSheetSpringConfig.friction,
|
|
157
|
+
clamp: defaultBottomSheetSpringConfig.clamp
|
|
158
|
+
},
|
|
159
|
+
disabledClosing: true,
|
|
160
|
+
snapPointSeekerMode: "next"
|
|
161
|
+
}, React.createElement("div", {
|
|
162
|
+
ref: innerContentRef
|
|
163
|
+
}, React.createElement(Paper, {
|
|
164
|
+
"data-testid": "bottomSheet-header",
|
|
165
|
+
className: "u-w-100 u-h-2-half u-pos-relative u-flex u-flex-items-center u-flex-justify-center",
|
|
166
|
+
ref: headerRef,
|
|
167
|
+
elevation: 0,
|
|
168
|
+
square: true
|
|
169
|
+
}, React.createElement("div", {
|
|
170
|
+
style: styles.indicator
|
|
171
|
+
})), React.createElement(Stack, {
|
|
172
|
+
style: styles.stack,
|
|
173
|
+
className: "u-flex u-flex-column u-ov-hidden",
|
|
174
|
+
spacing: "s"
|
|
175
|
+
}, overriddenChildren)), React.createElement("div", {
|
|
176
|
+
style: {
|
|
177
|
+
height: bottomSpacerHeight
|
|
178
|
+
}
|
|
179
|
+
}));
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
BottomSheet.defaultProps = {
|
|
183
|
+
classes: {},
|
|
184
|
+
toolbarProps: {}
|
|
185
|
+
};
|
|
186
|
+
BottomSheet.propTypes = {
|
|
187
|
+
/** Toolbar properties */
|
|
188
|
+
toolbarProps: PropTypes.shape({
|
|
189
|
+
/** React reference of the toolbar node */
|
|
190
|
+
ref: PropTypes.bool,
|
|
191
|
+
|
|
192
|
+
/** Toolbar height value */
|
|
193
|
+
height: PropTypes.func
|
|
194
|
+
}),
|
|
195
|
+
|
|
196
|
+
/** Settings that can be modified */
|
|
197
|
+
settings: PropTypes.shape({
|
|
198
|
+
/** Height of the middle snap point, expressed as a percentage of the viewport height */
|
|
199
|
+
mediumHeightRatio: PropTypes.number
|
|
200
|
+
})
|
|
201
|
+
};
|
|
202
|
+
export default React.memo(BottomSheet);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import Paper from 'cozy-ui/transpiled/react/Paper';
|
|
4
|
+
|
|
5
|
+
var BottomSheetHeader = function BottomSheetHeader(_ref) {
|
|
6
|
+
var className = _ref.className,
|
|
7
|
+
headerContentRef = _ref.headerContentRef,
|
|
8
|
+
children = _ref.children;
|
|
9
|
+
return React.createElement(Paper, {
|
|
10
|
+
ref: headerContentRef,
|
|
11
|
+
className: cx('u-flex u-flex-items-center', className),
|
|
12
|
+
elevation: 0,
|
|
13
|
+
square: true
|
|
14
|
+
}, children);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
BottomSheetHeader.defaultProps = {
|
|
18
|
+
classes: {}
|
|
19
|
+
};
|
|
20
|
+
export default BottomSheetHeader;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import cx from 'classnames';
|
|
6
|
+
import Paper from 'cozy-ui/transpiled/react/Paper';
|
|
7
|
+
|
|
8
|
+
var BottomSheetItem = function BottomSheetItem(_ref) {
|
|
9
|
+
var children = _ref.children,
|
|
10
|
+
disableGutters = _ref.disableGutters,
|
|
11
|
+
disableElevation = _ref.disableElevation,
|
|
12
|
+
className = _ref.className,
|
|
13
|
+
props = _objectWithoutProperties(_ref, ["children", "disableGutters", "disableElevation", "className"]);
|
|
14
|
+
|
|
15
|
+
return React.createElement(Paper, _extends({
|
|
16
|
+
elevation: disableElevation ? 0 : 0 // need to set correct shadow values before setting a real elevation value
|
|
17
|
+
,
|
|
18
|
+
square: true,
|
|
19
|
+
className: cx({
|
|
20
|
+
'u-p-1': !disableGutters
|
|
21
|
+
}, className)
|
|
22
|
+
}, props), children);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
BottomSheetItem.propTypes = {
|
|
26
|
+
/** CSS classes */
|
|
27
|
+
className: PropTypes.string,
|
|
28
|
+
|
|
29
|
+
/** Disables default padding */
|
|
30
|
+
disableGutters: PropTypes.bool,
|
|
31
|
+
|
|
32
|
+
/** Disables default paper elevation */
|
|
33
|
+
disableElevation: PropTypes.bool
|
|
34
|
+
};
|
|
35
|
+
export default React.memo(BottomSheetItem);
|
|
@@ -1,60 +1,28 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import
|
|
4
|
-
import { makeStyles } from '@material-ui/core/styles';
|
|
5
|
-
import { isMobileApp } from 'cozy-device-helper';
|
|
6
|
-
import Paper from "cozy-ui/transpiled/react/Paper";
|
|
7
|
-
import Typography from "cozy-ui/transpiled/react/Typography";
|
|
8
|
-
import Stack from "cozy-ui/transpiled/react/Stack";
|
|
9
|
-
import Sharing from "cozy-ui/transpiled/react/Viewer/Footer/Sharing";
|
|
10
|
-
import ForwardButton from "cozy-ui/transpiled/react/Viewer/Footer/ForwardButton";
|
|
11
|
-
import DownloadButton from "cozy-ui/transpiled/react/Viewer/Footer/DownloadButton";
|
|
3
|
+
import { BottomSheetItem } from "cozy-ui/transpiled/react/BottomSheet";
|
|
12
4
|
import getPanelBlocks, { panelBlocksSpecs } from "cozy-ui/transpiled/react/Viewer/Panel/getPanelBlocks";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
stack: {
|
|
16
|
-
backgroundColor: theme.palette.background.default
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
});
|
|
20
|
-
var BottomSheetContent = forwardRef(function (_ref, ref) {
|
|
5
|
+
|
|
6
|
+
var BottomSheetContent = function BottomSheetContent(_ref) {
|
|
21
7
|
var file = _ref.file,
|
|
22
|
-
disableSharing = _ref.disableSharing,
|
|
23
8
|
contactsFullname = _ref.contactsFullname;
|
|
24
9
|
var panelBlocks = getPanelBlocks({
|
|
25
10
|
panelBlocksSpecs: panelBlocksSpecs,
|
|
26
11
|
file: file
|
|
27
12
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return React.createElement(Stack, {
|
|
31
|
-
spacing: "s",
|
|
32
|
-
className: cx('u-flex u-flex-column u-ov-hidden', styles.stack)
|
|
33
|
-
}, React.createElement(Paper, {
|
|
34
|
-
className: 'u-flex u-ph-1 u-pb-1',
|
|
35
|
-
elevation: 2,
|
|
36
|
-
square: true,
|
|
37
|
-
ref: ref
|
|
38
|
-
}, !disableSharing && React.createElement(Sharing, {
|
|
39
|
-
file: file
|
|
40
|
-
}), React.createElement(FileActionButton, {
|
|
41
|
-
file: file
|
|
42
|
-
})), panelBlocks.map(function (PanelBlock, index) {
|
|
43
|
-
return React.createElement(Paper, {
|
|
13
|
+
return panelBlocks.map(function (PanelBlock, index) {
|
|
14
|
+
return React.createElement(BottomSheetItem, {
|
|
44
15
|
key: index,
|
|
45
|
-
|
|
46
|
-
square: true
|
|
47
|
-
}, React.createElement(Typography, {
|
|
48
|
-
variant: "h4",
|
|
49
|
-
className: 'u-pv-1 u-ph-1'
|
|
16
|
+
disableElevation: index === panelBlocks.length - 1
|
|
50
17
|
}, React.createElement(PanelBlock, {
|
|
51
18
|
file: file,
|
|
52
19
|
contactsFullname: contactsFullname
|
|
53
|
-
}))
|
|
54
|
-
})
|
|
55
|
-
}
|
|
20
|
+
}));
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
56
24
|
BottomSheetContent.propTypes = {
|
|
57
25
|
file: PropTypes.object.isRequired,
|
|
58
|
-
|
|
26
|
+
contactsFullname: PropTypes.string
|
|
59
27
|
};
|
|
60
28
|
export default BottomSheetContent;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/objectSpread";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { makeStyles } from '@material-ui/core/styles';
|
|
5
5
|
import { isMobileApp } from 'cozy-device-helper';
|
|
6
6
|
import { getReferencedBy, useQuery, models } from 'cozy-client';
|
|
7
|
+
import BottomSheet, { BottomSheetHeader } from "cozy-ui/transpiled/react/BottomSheet";
|
|
7
8
|
import { buildContactByIdsQuery } from "cozy-ui/transpiled/react/Viewer/queries";
|
|
8
9
|
import { isValidForPanel } from "cozy-ui/transpiled/react/Viewer/helpers";
|
|
9
10
|
import Sharing from "cozy-ui/transpiled/react/Viewer/Footer/Sharing";
|
|
10
11
|
import ForwardButton from "cozy-ui/transpiled/react/Viewer/Footer/ForwardButton";
|
|
11
12
|
import DownloadButton from "cozy-ui/transpiled/react/Viewer/Footer/DownloadButton";
|
|
12
|
-
import BottomSheetWrapper from "cozy-ui/transpiled/react/Viewer/Footer/BottomSheetWrapper";
|
|
13
13
|
import BottomSheetContent from "cozy-ui/transpiled/react/Viewer/Footer/BottomSheetContent";
|
|
14
14
|
var getDisplayName = models.contact.getDisplayName;
|
|
15
15
|
var useStyles = makeStyles(function (theme) {
|
|
@@ -32,7 +32,11 @@ var FooterContent = function FooterContent(_ref) {
|
|
|
32
32
|
disableSharing = _ref.disableSharing;
|
|
33
33
|
var styles = useStyles();
|
|
34
34
|
var FileActionButton = isMobileApp() ? ForwardButton : DownloadButton;
|
|
35
|
-
var
|
|
35
|
+
var toolbarProps = useMemo(function () {
|
|
36
|
+
return {
|
|
37
|
+
ref: toolbarRef
|
|
38
|
+
};
|
|
39
|
+
}, [toolbarRef]);
|
|
36
40
|
var contactIds = getReferencedBy(file, 'io.cozy.contacts').map(function (ref) {
|
|
37
41
|
return ref.id;
|
|
38
42
|
});
|
|
@@ -50,15 +54,17 @@ var FooterContent = function FooterContent(_ref) {
|
|
|
50
54
|
if (isValidForPanel({
|
|
51
55
|
file: file
|
|
52
56
|
}) && (contactsFullname || contactIds.length === 0)) {
|
|
53
|
-
return React.createElement(
|
|
57
|
+
return React.createElement(BottomSheet, {
|
|
58
|
+
toolbarProps: toolbarProps
|
|
59
|
+
}, React.createElement(BottomSheetHeader, {
|
|
60
|
+
className: "u-ph-1 u-pb-1"
|
|
61
|
+
}, !disableSharing && React.createElement(Sharing, {
|
|
62
|
+
file: file
|
|
63
|
+
}), React.createElement(FileActionButton, {
|
|
64
|
+
file: file
|
|
65
|
+
})), React.createElement(BottomSheetContent, {
|
|
54
66
|
file: file,
|
|
55
|
-
|
|
56
|
-
toolbarRef: toolbarRef
|
|
57
|
-
}, React.createElement(BottomSheetContent, {
|
|
58
|
-
file: file,
|
|
59
|
-
disableSharing: disableSharing,
|
|
60
|
-
contactsFullname: contactsFullname,
|
|
61
|
-
ref: actionButtonsRef
|
|
67
|
+
contactsFullname: contactsFullname
|
|
62
68
|
}));
|
|
63
69
|
}
|
|
64
70
|
|
|
@@ -76,4 +76,5 @@ export { default as ProgressionBanner } from './ProgressionBanner';
|
|
|
76
76
|
export { default as Fab } from './Fab';
|
|
77
77
|
export { default as SquareAppIcon } from './SquareAppIcon';
|
|
78
78
|
export { default as FileImageLoader } from './FileImageLoader';
|
|
79
|
-
export { default as Radios } from './Radios';
|
|
79
|
+
export { default as Radios } from './Radios';
|
|
80
|
+
export { default as BottomSheet, BottomSheetItem } from './BottomSheet';
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from 'react'
|
|
2
|
-
import { BottomSheet } from 'mui-bottom-sheet'
|
|
3
|
-
import { makeStyles } from '@material-ui/core/styles'
|
|
4
|
-
|
|
5
|
-
const useStyles = ({ isTopPosition }) => ({
|
|
6
|
-
root: {
|
|
7
|
-
borderTopLeftRadius: isTopPosition ? 0 : '1rem',
|
|
8
|
-
borderTopRightRadius: isTopPosition ? 0 : '1rem',
|
|
9
|
-
transition: 'border-radius 0.5s',
|
|
10
|
-
boxShadow: '0 6px 16px 0 rgba(0, 0, 0, 0.5)'
|
|
11
|
-
}
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
const useClasses = makeStyles(theme => ({
|
|
15
|
-
header: {
|
|
16
|
-
height: '2.5rem',
|
|
17
|
-
width: '100%',
|
|
18
|
-
position: 'relative',
|
|
19
|
-
display: 'flex',
|
|
20
|
-
alignItems: 'center',
|
|
21
|
-
justifyContent: 'center'
|
|
22
|
-
},
|
|
23
|
-
indicator: {
|
|
24
|
-
width: '4rem',
|
|
25
|
-
height: '0.25rem',
|
|
26
|
-
borderRadius: '99px',
|
|
27
|
-
backgroundColor: theme.palette.text.secondary
|
|
28
|
-
}
|
|
29
|
-
}))
|
|
30
|
-
|
|
31
|
-
export const defaultBottomSheetSpringConfig = {
|
|
32
|
-
tension: 165,
|
|
33
|
-
friction: 17,
|
|
34
|
-
clamp: true
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const BottomSheetWrapper = ({
|
|
38
|
-
file,
|
|
39
|
-
actionButtonsRef,
|
|
40
|
-
toolbarRef,
|
|
41
|
-
children
|
|
42
|
-
}) => {
|
|
43
|
-
const [isTopPosition, setIsTopPosition] = useState(false)
|
|
44
|
-
const [peekHeights, setPeekHeights] = useState(null)
|
|
45
|
-
const [initPos, setInitPos] = useState(null)
|
|
46
|
-
const [bottomSpacerHeight, setBottomSpacerHeight] = useState(0)
|
|
47
|
-
const classes = useClasses()
|
|
48
|
-
const styles = useStyles({ isTopPosition })
|
|
49
|
-
const innerContentRef = useRef()
|
|
50
|
-
const headerRef = useRef()
|
|
51
|
-
|
|
52
|
-
const toolbar = toolbarRef.current
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
const maxHeight = toolbar
|
|
56
|
-
? window.innerHeight - toolbar.offsetHeight
|
|
57
|
-
: window.innerHeight
|
|
58
|
-
const mediumHeight = Math.round(maxHeight * 0.33)
|
|
59
|
-
const actionButtonsHeight = parseFloat(
|
|
60
|
-
getComputedStyle(actionButtonsRef.current).getPropertyValue('height')
|
|
61
|
-
)
|
|
62
|
-
const actionButtonsBottomMargin = 16
|
|
63
|
-
const minHeight =
|
|
64
|
-
headerRef.current.offsetHeight +
|
|
65
|
-
actionButtonsHeight +
|
|
66
|
-
actionButtonsBottomMargin
|
|
67
|
-
|
|
68
|
-
// Used so that the bottomSheet can be opened to the top,
|
|
69
|
-
// without stopping at the content height
|
|
70
|
-
const bottomSpacerHeight = maxHeight - innerContentRef.current.offsetHeight
|
|
71
|
-
|
|
72
|
-
setPeekHeights([minHeight, mediumHeight, maxHeight])
|
|
73
|
-
setInitPos(mediumHeight)
|
|
74
|
-
setBottomSpacerHeight(bottomSpacerHeight)
|
|
75
|
-
}, [toolbar, innerContentRef, file, actionButtonsRef])
|
|
76
|
-
|
|
77
|
-
const handleOnIndexChange = snapIndex => {
|
|
78
|
-
const maxHeightSnapIndex = peekHeights.length - 1
|
|
79
|
-
|
|
80
|
-
if (snapIndex === maxHeightSnapIndex && !isTopPosition) {
|
|
81
|
-
setIsTopPosition(true)
|
|
82
|
-
}
|
|
83
|
-
if (snapIndex !== maxHeightSnapIndex && isTopPosition) {
|
|
84
|
-
setIsTopPosition(false)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<BottomSheet
|
|
90
|
-
peekHeights={peekHeights}
|
|
91
|
-
defaultHeight={initPos}
|
|
92
|
-
backdrop={false}
|
|
93
|
-
fullHeight={false}
|
|
94
|
-
onIndexChange={snapIndex => handleOnIndexChange(snapIndex)}
|
|
95
|
-
styles={{ root: styles.root }}
|
|
96
|
-
threshold={0}
|
|
97
|
-
// springConfig doc : https://react-spring.io/common/configs
|
|
98
|
-
springConfig={{
|
|
99
|
-
tension: defaultBottomSheetSpringConfig.tension,
|
|
100
|
-
friction: defaultBottomSheetSpringConfig.friction,
|
|
101
|
-
clamp: defaultBottomSheetSpringConfig.clamp
|
|
102
|
-
}}
|
|
103
|
-
disabledClosing={true}
|
|
104
|
-
snapPointSeekerMode="next"
|
|
105
|
-
>
|
|
106
|
-
<div ref={innerContentRef}>
|
|
107
|
-
<div
|
|
108
|
-
data-testid="bottomSheet-header"
|
|
109
|
-
className={classes.header}
|
|
110
|
-
ref={headerRef}
|
|
111
|
-
>
|
|
112
|
-
<div className={classes.indicator} />
|
|
113
|
-
</div>
|
|
114
|
-
{children}
|
|
115
|
-
</div>
|
|
116
|
-
<div style={{ height: bottomSpacerHeight }} />
|
|
117
|
-
</BottomSheet>
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export default BottomSheetWrapper
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
3
|
-
import { BottomSheet } from 'mui-bottom-sheet';
|
|
4
|
-
import { makeStyles } from '@material-ui/core/styles';
|
|
5
|
-
|
|
6
|
-
var useStyles = function useStyles(_ref) {
|
|
7
|
-
var isTopPosition = _ref.isTopPosition;
|
|
8
|
-
return {
|
|
9
|
-
root: {
|
|
10
|
-
borderTopLeftRadius: isTopPosition ? 0 : '1rem',
|
|
11
|
-
borderTopRightRadius: isTopPosition ? 0 : '1rem',
|
|
12
|
-
transition: 'border-radius 0.5s',
|
|
13
|
-
boxShadow: '0 6px 16px 0 rgba(0, 0, 0, 0.5)'
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
var useClasses = makeStyles(function (theme) {
|
|
19
|
-
return {
|
|
20
|
-
header: {
|
|
21
|
-
height: '2.5rem',
|
|
22
|
-
width: '100%',
|
|
23
|
-
position: 'relative',
|
|
24
|
-
display: 'flex',
|
|
25
|
-
alignItems: 'center',
|
|
26
|
-
justifyContent: 'center'
|
|
27
|
-
},
|
|
28
|
-
indicator: {
|
|
29
|
-
width: '4rem',
|
|
30
|
-
height: '0.25rem',
|
|
31
|
-
borderRadius: '99px',
|
|
32
|
-
backgroundColor: theme.palette.text.secondary
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
export var defaultBottomSheetSpringConfig = {
|
|
37
|
-
tension: 165,
|
|
38
|
-
friction: 17,
|
|
39
|
-
clamp: true
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
var BottomSheetWrapper = function BottomSheetWrapper(_ref2) {
|
|
43
|
-
var file = _ref2.file,
|
|
44
|
-
actionButtonsRef = _ref2.actionButtonsRef,
|
|
45
|
-
toolbarRef = _ref2.toolbarRef,
|
|
46
|
-
children = _ref2.children;
|
|
47
|
-
|
|
48
|
-
var _useState = useState(false),
|
|
49
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
50
|
-
isTopPosition = _useState2[0],
|
|
51
|
-
setIsTopPosition = _useState2[1];
|
|
52
|
-
|
|
53
|
-
var _useState3 = useState(null),
|
|
54
|
-
_useState4 = _slicedToArray(_useState3, 2),
|
|
55
|
-
peekHeights = _useState4[0],
|
|
56
|
-
setPeekHeights = _useState4[1];
|
|
57
|
-
|
|
58
|
-
var _useState5 = useState(null),
|
|
59
|
-
_useState6 = _slicedToArray(_useState5, 2),
|
|
60
|
-
initPos = _useState6[0],
|
|
61
|
-
setInitPos = _useState6[1];
|
|
62
|
-
|
|
63
|
-
var _useState7 = useState(0),
|
|
64
|
-
_useState8 = _slicedToArray(_useState7, 2),
|
|
65
|
-
bottomSpacerHeight = _useState8[0],
|
|
66
|
-
setBottomSpacerHeight = _useState8[1];
|
|
67
|
-
|
|
68
|
-
var classes = useClasses();
|
|
69
|
-
var styles = useStyles({
|
|
70
|
-
isTopPosition: isTopPosition
|
|
71
|
-
});
|
|
72
|
-
var innerContentRef = useRef();
|
|
73
|
-
var headerRef = useRef();
|
|
74
|
-
var toolbar = toolbarRef.current;
|
|
75
|
-
useEffect(function () {
|
|
76
|
-
var maxHeight = toolbar ? window.innerHeight - toolbar.offsetHeight : window.innerHeight;
|
|
77
|
-
var mediumHeight = Math.round(maxHeight * 0.33);
|
|
78
|
-
var actionButtonsHeight = parseFloat(getComputedStyle(actionButtonsRef.current).getPropertyValue('height'));
|
|
79
|
-
var actionButtonsBottomMargin = 16;
|
|
80
|
-
var minHeight = headerRef.current.offsetHeight + actionButtonsHeight + actionButtonsBottomMargin; // Used so that the bottomSheet can be opened to the top,
|
|
81
|
-
// without stopping at the content height
|
|
82
|
-
|
|
83
|
-
var bottomSpacerHeight = maxHeight - innerContentRef.current.offsetHeight;
|
|
84
|
-
setPeekHeights([minHeight, mediumHeight, maxHeight]);
|
|
85
|
-
setInitPos(mediumHeight);
|
|
86
|
-
setBottomSpacerHeight(bottomSpacerHeight);
|
|
87
|
-
}, [toolbar, innerContentRef, file, actionButtonsRef]);
|
|
88
|
-
|
|
89
|
-
var handleOnIndexChange = function handleOnIndexChange(snapIndex) {
|
|
90
|
-
var maxHeightSnapIndex = peekHeights.length - 1;
|
|
91
|
-
|
|
92
|
-
if (snapIndex === maxHeightSnapIndex && !isTopPosition) {
|
|
93
|
-
setIsTopPosition(true);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (snapIndex !== maxHeightSnapIndex && isTopPosition) {
|
|
97
|
-
setIsTopPosition(false);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
return React.createElement(BottomSheet, {
|
|
102
|
-
peekHeights: peekHeights,
|
|
103
|
-
defaultHeight: initPos,
|
|
104
|
-
backdrop: false,
|
|
105
|
-
fullHeight: false,
|
|
106
|
-
onIndexChange: function onIndexChange(snapIndex) {
|
|
107
|
-
return handleOnIndexChange(snapIndex);
|
|
108
|
-
},
|
|
109
|
-
styles: {
|
|
110
|
-
root: styles.root
|
|
111
|
-
},
|
|
112
|
-
threshold: 0 // springConfig doc : https://react-spring.io/common/configs
|
|
113
|
-
,
|
|
114
|
-
springConfig: {
|
|
115
|
-
tension: defaultBottomSheetSpringConfig.tension,
|
|
116
|
-
friction: defaultBottomSheetSpringConfig.friction,
|
|
117
|
-
clamp: defaultBottomSheetSpringConfig.clamp
|
|
118
|
-
},
|
|
119
|
-
disabledClosing: true,
|
|
120
|
-
snapPointSeekerMode: "next"
|
|
121
|
-
}, React.createElement("div", {
|
|
122
|
-
ref: innerContentRef
|
|
123
|
-
}, React.createElement("div", {
|
|
124
|
-
"data-testid": "bottomSheet-header",
|
|
125
|
-
className: classes.header,
|
|
126
|
-
ref: headerRef
|
|
127
|
-
}, React.createElement("div", {
|
|
128
|
-
className: classes.indicator
|
|
129
|
-
})), children), React.createElement("div", {
|
|
130
|
-
style: {
|
|
131
|
-
height: bottomSpacerHeight
|
|
132
|
-
}
|
|
133
|
-
}));
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export default BottomSheetWrapper;
|