cozy-ui 94.0.0 → 95.0.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 CHANGED
@@ -1,3 +1,29 @@
1
+ # [95.0.0](https://github.com/cozy/cozy-ui/compare/v94.1.0...v95.0.0) (2023-10-03)
2
+
3
+
4
+ ### Features
5
+
6
+ * **Modal:** Re-export Modal component ([1ad81f6](https://github.com/cozy/cozy-ui/commit/1ad81f6))
7
+ * **Viewer:** Use Modal by default instead Overlay in app ([7510557](https://github.com/cozy/cozy-ui/commit/7510557))
8
+
9
+
10
+ ### BREAKING CHANGES
11
+
12
+ * **Viewer:** The Viewer is now wrapped with
13
+ a Modal by default.
14
+ You can remove the deprecated `Overlay` component
15
+ (which wraps the `Viewer` component) from your applications.
16
+ Or if you want to keep your implementation,
17
+ please use the `disableModal` props
18
+ on your `Viewer` components.
19
+
20
+ # [94.1.0](https://github.com/cozy/cozy-ui/compare/v94.0.0...v94.1.0) (2023-10-02)
21
+
22
+
23
+ ### Features
24
+
25
+ * **NestedSelect:** Add NestedSelectResponsive and BottomSheet ([d1659fe](https://github.com/cozy/cozy-ui/commit/d1659fe))
26
+
1
27
  # [94.0.0](https://github.com/cozy/cozy-ui/compare/v93.5.0...v94.0.0) (2023-10-02)
2
28
 
3
29
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "94.0.0",
3
+ "version": "95.0.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -9,7 +9,7 @@ will make sure that even your custom Dialogs will behave as CozyDialogs.
9
9
  import Dialog, { DialogTitle, DialogActions } from 'cozy-ui/transpiled/react/Dialog'
10
10
  import { DialogBackButton, DialogCloseButton, useCozyDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
11
11
  import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
12
- import DemoProvider from 'cozy-ui/transpiled/react/providers/DemoProvider'
12
+ import DemoProvider from 'cozy-ui/docs/components/DemoProvider'
13
13
  import Alerter from 'cozy-ui/transpiled/react/deprecated/Alerter'
14
14
 
15
15
  import Divider from 'cozy-ui/transpiled/react/Divider'
@@ -0,0 +1 @@
1
+ Re-export of @material-ui. See [the official API](https://v4.mui.com/api/modal/).
@@ -0,0 +1,3 @@
1
+ import Modal from '@material-ui/core/Modal'
2
+
3
+ export default Modal
@@ -0,0 +1,43 @@
1
+ import React from 'react'
2
+ import cx from 'classnames'
3
+
4
+ import Icon from '../Icon'
5
+ import IconButton from '../IconButton'
6
+ import ArrowUpIcon from '../Icons/ArrowUp'
7
+ import BottomSheet, { BottomSheetHeader, BottomSheetItem } from '../BottomSheet'
8
+ import Typography from '../Typography'
9
+ import Divider from '../Divider'
10
+
11
+ import NestedSelect from './NestedSelect'
12
+
13
+ const HeaderComponent = ({ title, showBack, onClickBack }) => {
14
+ return (
15
+ <>
16
+ <BottomSheetHeader
17
+ className={cx('u-h-3', { 'u-pl-half u-pr-3': showBack })}
18
+ >
19
+ {showBack && (
20
+ <IconButton onClick={onClickBack}>
21
+ <Icon icon={ArrowUpIcon} rotate={-90} />
22
+ </IconButton>
23
+ )}
24
+ <Typography className="u-w-100" variant="h6" align="center">
25
+ {title}
26
+ </Typography>
27
+ </BottomSheetHeader>
28
+ <Divider />
29
+ </>
30
+ )
31
+ }
32
+
33
+ const SelfBottomSheet = props => {
34
+ return (
35
+ <BottomSheet backdrop onClose={props.onClose}>
36
+ <BottomSheetItem disableGutters>
37
+ <NestedSelect HeaderComponent={HeaderComponent} {...props} />
38
+ </BottomSheetItem>
39
+ </BottomSheet>
40
+ )
41
+ }
42
+
43
+ export default SelfBottomSheet
@@ -18,7 +18,8 @@ const ItemRow = ({
18
18
  isSelected,
19
19
  radioPosition,
20
20
  isLast,
21
- ellipsis
21
+ ellipsis,
22
+ noDivider
22
23
  }) => {
23
24
  const { isDesktop } = useBreakpoints()
24
25
 
@@ -76,7 +77,7 @@ const ItemRow = ({
76
77
  ? item.action.Component({ item, ...item.action.props })
77
78
  : null}
78
79
  </ListItem>
79
- {!isLast && <Divider />}
80
+ {noDivider ? null : !isLast && <Divider />}
80
81
  </>
81
82
  )
82
83
  }
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import omit from 'lodash/omit'
4
4
 
5
+ import List from '../List'
5
6
  import Input from '../Input'
6
7
  import Typography from '../Typography'
7
8
  import ItemRow from './ItemRow'
@@ -81,7 +82,8 @@ class NestedSelect extends Component {
81
82
  title,
82
83
  transformParentItem,
83
84
  radioPosition,
84
- ellipsis
85
+ ellipsis,
86
+ noDivider
85
87
  } = this.props
86
88
  const { history, searchValue, searchResult } = this.state
87
89
  const current = history[0]
@@ -119,6 +121,7 @@ class NestedSelect extends Component {
119
121
  onClick={this.handleClickItem}
120
122
  isSelected={isSelectedWithLevel(parentItem)}
121
123
  ellipsis={ellipsis}
124
+ noDivider={noDivider}
122
125
  />
123
126
  ) : null}
124
127
  {searchOptions && level === 0 && (
@@ -149,6 +152,7 @@ class NestedSelect extends Component {
149
152
  isSelected={isSelectedWithLevel(item)}
150
153
  isLast={index === searchResult.length - 1}
151
154
  ellipsis={ellipsis}
155
+ noDivider={noDivider}
152
156
  />
153
157
  ))
154
158
  )
@@ -162,6 +166,7 @@ class NestedSelect extends Component {
162
166
  isSelected={isSelectedWithLevel(item)}
163
167
  isLast={index === children.length - 1}
164
168
  ellipsis={ellipsis}
169
+ noDivider={noDivider}
165
170
  />
166
171
  ))
167
172
  )}
@@ -172,7 +177,7 @@ class NestedSelect extends Component {
172
177
  }
173
178
 
174
179
  NestedSelect.defaultProps = {
175
- ContentComponent: 'div',
180
+ ContentComponent: List,
176
181
  HeaderComponent: null,
177
182
  transformParentItem: x => x,
178
183
  radioPosition: 'right'
@@ -191,25 +196,16 @@ const ItemPropType = PropTypes.shape({
191
196
  })
192
197
 
193
198
  NestedSelect.propTypes = {
194
- /**
195
- * Can be set to "right" or "left". Defaults to "right"
196
- */
199
+ /** Can be set to "right" or "left". Defaults to "right" */
197
200
  radioPosition: PropTypes.oneOf(['left', 'right']),
198
201
 
199
- /**
200
- * The whole option item is passed to this function when selected
201
- */
202
+ /** The whole option item is passed to this function when selected */
202
203
  onSelect: PropTypes.func.isRequired,
203
204
 
204
- /**
205
- * Determines if the row looks selected. The `option` is
206
- * passed as an argument.
207
- */
205
+ /** Determines if the row looks selected. The `option` is passed as an argument. */
208
206
  isSelected: PropTypes.func.isRequired,
209
207
 
210
- /**
211
- * Options that will be rendered as nested lists of choices
212
- */
208
+ /** Options that will be rendered as nested lists of choices */
213
209
  options: PropTypes.shape({
214
210
  children: PropTypes.arrayOf(ItemPropType)
215
211
  }),
@@ -242,10 +238,11 @@ NestedSelect.propTypes = {
242
238
  onSearch: PropTypes.func.isRequired
243
239
  }),
244
240
 
245
- /**
246
- * To manage ellipsis on ItemRow
247
- */
248
- ellipsis: PropTypes.bool
241
+ /** To manage ellipsis on ItemRow */
242
+ ellipsis: PropTypes.bool,
243
+
244
+ /** Remove dividers after each row */
245
+ noDivider: PropTypes.bool
249
246
  }
250
247
 
251
248
  export default NestedSelect
@@ -1,18 +1,22 @@
1
+ You can use `react/NestedSelect/NestedSelectResponsive` wich provides automaticaly a modal on desktop and bottomsheet on mobile, or directly `react/NestedSelect/Modal` and `react/NestedSelect/BottomSheet`.
2
+
1
3
  ```jsx
4
+ import DemoProvider from 'cozy-ui/docs/components/DemoProvider'
5
+ import Variants from 'cozy-ui/docs/components/Variants'
2
6
  import { useState } from 'react'
3
- import Button from 'cozy-ui/transpiled/react/deprecated/Button'
7
+ import Button from 'cozy-ui/transpiled/react/Buttons'
4
8
  import Circle from 'cozy-ui/transpiled/react/Circle'
5
9
  import Icon from 'cozy-ui/transpiled/react/Icon'
6
10
  import SettingIcon from 'cozy-ui/transpiled/react/Icons/Setting'
7
- import NestedSelectModal from 'cozy-ui/transpiled/react/NestedSelect/Modal'
11
+ import NestedSelectResponsive from 'cozy-ui/transpiled/react/NestedSelect/NestedSelectResponsive'
8
12
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
9
13
  import IconButton from 'cozy-ui/transpiled/react/IconButton'
10
14
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
11
15
  import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
12
16
  import Checkbox from 'cozy-ui/transpiled/react/Checkbox'
13
17
  import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
14
- import DemoProvider from 'cozy-ui/transpiled/react/providers/DemoProvider'
15
18
  import palette from 'cozy-ui/transpiled/react/palette'
19
+ import Typography from 'cozy-ui/transpiled/react/Typography'
16
20
 
17
21
  const Image = ({ letter }) => (
18
22
  <Circle backgroundColor={palette.melon}>
@@ -83,8 +87,9 @@ const transformParentItem = item => ({
83
87
 
84
88
  const StaticExample = () => {
85
89
  const { isMobile } = useBreakpoints()
90
+
86
91
  return (
87
- <NestedSelectModal
92
+ <NestedSelectResponsive
88
93
  radioPosition={isMobile ? 'left' : 'right'}
89
94
  canSelectParent={true}
90
95
  onSelect={x => x}
@@ -93,6 +98,7 @@ const StaticExample = () => {
93
98
  options={options}
94
99
  title="Please select letter"
95
100
  transformParentItem={transformParentItem}
101
+ onClose={() => {}}
96
102
  />
97
103
  )
98
104
  }
@@ -105,13 +111,12 @@ const isParent = (item, childItem) => {
105
111
  }
106
112
 
107
113
  const InteractiveExample = () => {
108
- const [leftRadio, setLeftRadio] = useState(false)
109
- const [searchOptions, setSearchOptions] = useState(null)
110
- const [withEllipsis, setWithEllipsis] = useState(true)
111
114
  const [showingModal, setShowingModal] = useState(false)
112
115
  const [selectedItem, setSelected] = useState({ title: 'A' })
116
+
113
117
  const showModal = () => setShowingModal(true)
114
118
  const hideModal = () => setShowingModal(false)
119
+
115
120
  const isSelected = (item, level) => {
116
121
  if (!selectedItem) {
117
122
  return false
@@ -123,33 +128,19 @@ const InteractiveExample = () => {
123
128
  return false
124
129
  }
125
130
 
126
- const handleClickLeftRadio = () => {
127
- setLeftRadio(!leftRadio)
128
- }
129
- const handleClickWithEllipsis = () => {
130
- setWithEllipsis(prev => !prev)
131
- }
132
-
133
- const handleClickWithSearch = e => {
134
- if (e.target.checked) {
135
- const searchOpts = {
136
- placeholderSearch: 'Placeholder Search',
137
- noDataLabel: 'No Data Found',
138
- onSearch: (value) => {
139
- return options.children.filter(o => o.description && o.description.toLowerCase().includes(value.toLowerCase()))
140
- },
141
- displaySearchResultItem: item =>
142
- <ListItem key={item.id} dense button divider>
143
- <ListItemText
144
- primary={item.description}
145
- ellipsis
146
- />
147
- </ListItem>
148
- }
149
- setSearchOptions(searchOpts)
150
- } else {
151
- setSearchOptions(null)
152
- }
131
+ const searchOptions = {
132
+ placeholderSearch: 'Placeholder Search',
133
+ noDataLabel: 'No Data Found',
134
+ onSearch: (value) => {
135
+ return options.children.filter(o => o.description && o.description.toLowerCase().includes(value.toLowerCase()))
136
+ },
137
+ displaySearchResultItem: item =>
138
+ <ListItem key={item.id} dense button divider>
139
+ <ListItemText
140
+ primary={item.description}
141
+ ellipsis
142
+ />
143
+ </ListItem>
153
144
  }
154
145
 
155
146
  const handleSelect = item => {
@@ -159,62 +150,43 @@ const InteractiveExample = () => {
159
150
  }, RADIO_BUTTON_ANIM_DURATION)
160
151
  }
161
152
 
153
+ const initialVariants = [{ noDivider: false, leftRadio: false, withSearch: false, withEllipsis: true }]
154
+
162
155
  return (
163
- <>
164
- <Checkbox
165
- label='radio to the left'
166
- readOnly
167
- name='leftRadio'
168
- value={leftRadio}
169
- checked={leftRadio}
170
- onClick={handleClickLeftRadio}
171
- />
172
- <Checkbox
173
- label='with search'
174
- readOnly
175
- name='withSearch'
176
- value={!!searchOptions}
177
- checked={!!searchOptions}
178
- onClick={handleClickWithSearch}
179
- />
180
- <Checkbox
181
- label='without ellipsis'
182
- readOnly
183
- name='withEllipsis'
184
- value={!!withEllipsis}
185
- checked={!!withEllipsis}
186
- onClick={handleClickWithEllipsis}
187
- />
188
- { selectedItem && (
189
- <>Selected: { selectedItem.title }<br/></>
190
- )}
191
- <Button className='u-ml-0' label='Select' onClick={showModal} />
192
- { showingModal && (
193
- <NestedSelectModal
194
- canSelectParent={true}
195
- onSelect={handleSelect}
196
- onClose={hideModal}
197
- isSelected={isSelected}
198
- options={options}
199
- radioPosition={leftRadio ? 'left' : 'right'}
200
- title="Please select letter"
201
- transformParentItem={transformParentItem}
202
- searchOptions={searchOptions}
203
- ellipsis={withEllipsis}
204
- />
156
+ <Variants initialVariants={initialVariants} screenshotAllVariants>
157
+ {variant => (
158
+ <>
159
+ {selectedItem && (
160
+ <Typography paragraph>Selected item: { selectedItem.title }</Typography>
161
+ )}
162
+ <Button className='u-ml-0' label='Select' onClick={showModal} />
163
+ {showingModal && (
164
+ <NestedSelectResponsive
165
+ canSelectParent={true}
166
+ onSelect={handleSelect}
167
+ onClose={hideModal}
168
+ isSelected={isSelected}
169
+ options={options}
170
+ radioPosition={variant.leftRadio ? 'left' : 'right'}
171
+ title="Please select letter"
172
+ transformParentItem={transformParentItem}
173
+ searchOptions={variant.withSearch ? searchOpts : undefined}
174
+ ellipsis={variant.withEllipsis}
175
+ noDivider={variant.noDivider}
176
+ />
177
+ )}
178
+ </>
205
179
  )}
206
- </>
180
+ </Variants>
207
181
  )
208
182
  }
209
183
 
210
184
  ;
211
185
 
212
- <>
213
- <DemoProvider>
214
- {isTesting()
215
- ? <StaticExample />
216
- : <InteractiveExample />
217
- }
218
- </DemoProvider>
219
- </>
186
+ <DemoProvider>
187
+ {isTesting()
188
+ ? <StaticExample />
189
+ : <InteractiveExample />
190
+ }
191
+ </DemoProvider>
220
192
  ```
@@ -0,0 +1,15 @@
1
+ import React from 'react'
2
+
3
+ import useBreakpoints from '../providers/Breakpoints'
4
+ import BottomSheet from './BottomSheet'
5
+ import Modal from './Modal'
6
+
7
+ const NestedSelectResponsive = props => {
8
+ const { isMobile } = useBreakpoints()
9
+
10
+ const Wrapper = isMobile ? BottomSheet : Modal
11
+
12
+ return <Wrapper {...props} />
13
+ }
14
+
15
+ export default NestedSelectResponsive
@@ -1,2 +1,4 @@
1
1
  export { default } from './NestedSelect'
2
2
  export { default as NestedSelectModal } from './Modal'
3
+ export { default as NestedSelectBottomSheet } from './BottomSheet'
4
+ export { default as NestedSelectResponsive } from './NestedSelectResponsive'
@@ -293,7 +293,7 @@ the options to be displayed on top of all the layers.
293
293
  ```jsx
294
294
  import { useState, useEffect } from 'react'
295
295
  import { Dialog } from 'cozy-ui/transpiled/react/CozyDialogs'
296
- import DemoProvider from 'cozy-ui/transpiled/react/providers/DemoProvider'
296
+ import DemoProvider from 'cozy-ui/docs/components/DemoProvider'
297
297
 
298
298
  import Button from 'cozy-ui/transpiled/react/deprecated/Button'
299
299
  import Typography from 'cozy-ui/transpiled/react/Typography'
@@ -1,6 +1,6 @@
1
1
  The `Viewer` component can be used to display the content of various file types.
2
2
 
3
- Once rendered, the `Viewer` will take up all the available space in it's container (using `position: absolute`). It can be paired with the `Overlay` component to take up the whole screen.
3
+ Once rendered, the `Viewer` will take up all the available space in it's container (using `position: absolute`).
4
4
 
5
5
  The `Viewer` can display an **information panel** to show additional information about the current file (e.g. whether a file is certified).
6
6
 
@@ -21,12 +21,14 @@ The `Viewer` can display an **information panel** to show additional information
21
21
  * **renderFallbackExtraContent** : `<function>` – A render prop that is called when a file can't be displayed
22
22
  * **disablePanel** : `<boolean>` – Show/Hide the panel containing more information about the file only on Desktop
23
23
  * **disableFooter** : `<boolean>` – Show/Hide the panel containing more information about the file only on Phone & Tablet devices
24
+ * **disableModal** : `<boolean>` – To avoid wrapping the Viewer with a Modal component (wrapper of Viewer)
24
25
  * **editPathByModelProps** : `<object>` – Edit path by model properties
25
26
  * **information** : `<string>` – URL used to edit the file when editing a `information` type metadata (text, date)
26
27
  * **page** : `<string>` – URL used to edit the file when editing a `page` type metadata (side of the document)
27
28
  * **onChangeRequest** : `<function>` - Called with (nextFile, nextIndex) when the user requests to navigate to another file
28
29
  * **onCloseRequest** : `<function>` - Called when the user wants to leave the Viewer
29
30
  * **componentsProps** : `<object>` – Props passed to components with the same name
31
+ * **modalProps** : `<object>` – Props passed to Modal component
30
32
  * **OnlyOfficeViewer** : `<object>` – Used to open an Only Office file
31
33
  * **isEnabled** : `<boolean>` – Whether Only Office is enabled on the server
32
34
  * **opener** : `<function>` – To open the Only Office file
@@ -54,7 +56,6 @@ import Icon from 'cozy-ui/transpiled/react/Icon'
54
56
  import CarbonCopyIcon from 'cozy-ui/transpiled/react/Icons/CarbonCopy'
55
57
  // The DemoProvider inserts a fake cozy-client in the React context.
56
58
  import DemoProvider from './docs/DemoProvider'
57
- import Overlay from 'cozy-ui/transpiled/react/deprecated/Overlay'
58
59
  import Button from 'cozy-ui/transpiled/react/Buttons'
59
60
  import DownloadIcon from 'cozy-ui/transpiled/react/Icons/Download'
60
61
  import ShareIcon from 'cozy-ui/transpiled/react/Icons/Share'
@@ -218,33 +219,31 @@ const editPathByModelProps = {
218
219
  )}
219
220
  <Button label="Open viewer" variant="ghost" size="small" onClick={toggleViewer} />
220
221
  {state.viewerOpened && (
221
- <Overlay>
222
- <Viewer
223
- files={files}
224
- currentIndex={state.currentIndex}
225
- currentURL={state.currentURL}
226
- showNavigation={variant.navigation}
227
- editPathByModelProps={editPathByModelProps}
228
- onCloseRequest={toggleViewer}
229
- onChangeRequest={onFileChange}
230
- componentsProps={{
231
- OnlyOfficeViewer: {
232
- isEnabled: variant.onlyOfficeEnabled,
233
- opener: () => alert('This is a demo, no Only Office opener here')
234
- },
235
- toolbarProps:{
236
- showToolbar: variant.toolbar,
237
- showClose: state.showToolbarCloseButton,
238
- showFilePath: state.showToolbarWithPath
239
- }
240
- }}
241
- >
242
- <FooterActionButtons>
243
- <ShareButtonFake />
244
- <ForwardOrDownloadButton />
245
- </FooterActionButtons>
246
- </Viewer>
247
- </Overlay>
222
+ <Viewer
223
+ files={files}
224
+ currentIndex={state.currentIndex}
225
+ currentURL={state.currentURL}
226
+ showNavigation={variant.navigation}
227
+ editPathByModelProps={editPathByModelProps}
228
+ onCloseRequest={toggleViewer}
229
+ onChangeRequest={onFileChange}
230
+ componentsProps={{
231
+ OnlyOfficeViewer: {
232
+ isEnabled: variant.onlyOfficeEnabled,
233
+ opener: () => alert('This is a demo, no Only Office opener here')
234
+ },
235
+ toolbarProps:{
236
+ showToolbar: variant.toolbar,
237
+ showClose: state.showToolbarCloseButton,
238
+ showFilePath: state.showToolbarWithPath
239
+ }
240
+ }}
241
+ >
242
+ <FooterActionButtons>
243
+ <ShareButtonFake />
244
+ <ForwardOrDownloadButton />
245
+ </FooterActionButtons>
246
+ </Viewer>
248
247
  )}
249
248
  </>
250
249
  )
@@ -5,6 +5,8 @@ import cx from 'classnames'
5
5
  import useBreakpoints from '../providers/Breakpoints'
6
6
  import { FileDoctype } from '../proptypes'
7
7
 
8
+ import Modal from '../Modal'
9
+ import { useCozyTheme } from '../providers/CozyTheme'
8
10
  import { toolbarPropsPropType } from './proptypes'
9
11
  import { isValidForPanel } from './helpers'
10
12
  import Viewer from './Viewer'
@@ -124,4 +126,39 @@ ViewerContainer.defaultProps = {
124
126
  showNavigation: true
125
127
  }
126
128
 
127
- export default ViewerContainer
129
+ const ViewerContainerWrapper = ({ disableModal, ...props }) => {
130
+ const cozyTheme = useCozyTheme()
131
+ const { modalProps = { open: true } } = props.componentsProps || {}
132
+
133
+ if (disableModal) {
134
+ return <ViewerContainer {...props} />
135
+ }
136
+
137
+ return (
138
+ <Modal {...modalProps} className={`CozyTheme--${cozyTheme}`}>
139
+ {/* This div is needed for the Modal ref */}
140
+ <div>
141
+ <ViewerContainer {...props} />
142
+ </div>
143
+ </Modal>
144
+ )
145
+ }
146
+
147
+ ViewerContainerWrapper.defaultProps = {
148
+ componentsProps: {
149
+ modalProps: {
150
+ open: true
151
+ }
152
+ }
153
+ }
154
+
155
+ ViewerContainerWrapper.propTypes = {
156
+ /** To avoid wrapping the Viewer with a Modal component */
157
+ disableModal: PropTypes.bool,
158
+ /** Props passed to Modal component */
159
+ componentsProps: PropTypes.shape({
160
+ modalProps: PropTypes.object
161
+ })
162
+ }
163
+
164
+ export default ViewerContainerWrapper
package/react/index.js CHANGED
@@ -132,3 +132,4 @@ export { default as TimelineItem } from './TimelineItem'
132
132
  export { default as TimelineOppositeContent } from './TimelineOppositeContent'
133
133
  export { default as TimelineSeparator } from './TimelineSeparator'
134
134
  export { default as AlertProvider, useAlert } from './Alert'
135
+ export { default as Modal } from './Modal'
@@ -0,0 +1,2 @@
1
+ import Modal from '@material-ui/core/Modal';
2
+ export default Modal;
@@ -0,0 +1,43 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React from 'react';
3
+ import cx from 'classnames';
4
+ import Icon from "cozy-ui/transpiled/react/Icon";
5
+ import IconButton from "cozy-ui/transpiled/react/IconButton";
6
+ import ArrowUpIcon from "cozy-ui/transpiled/react/Icons/ArrowUp";
7
+ import BottomSheet, { BottomSheetHeader, BottomSheetItem } from "cozy-ui/transpiled/react/BottomSheet";
8
+ import Typography from "cozy-ui/transpiled/react/Typography";
9
+ import Divider from "cozy-ui/transpiled/react/Divider";
10
+ import NestedSelect from "cozy-ui/transpiled/react/NestedSelect/NestedSelect";
11
+
12
+ var HeaderComponent = function HeaderComponent(_ref) {
13
+ var title = _ref.title,
14
+ showBack = _ref.showBack,
15
+ onClickBack = _ref.onClickBack;
16
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(BottomSheetHeader, {
17
+ className: cx('u-h-3', {
18
+ 'u-pl-half u-pr-3': showBack
19
+ })
20
+ }, showBack && /*#__PURE__*/React.createElement(IconButton, {
21
+ onClick: onClickBack
22
+ }, /*#__PURE__*/React.createElement(Icon, {
23
+ icon: ArrowUpIcon,
24
+ rotate: -90
25
+ })), /*#__PURE__*/React.createElement(Typography, {
26
+ className: "u-w-100",
27
+ variant: "h6",
28
+ align: "center"
29
+ }, title)), /*#__PURE__*/React.createElement(Divider, null));
30
+ };
31
+
32
+ var SelfBottomSheet = function SelfBottomSheet(props) {
33
+ return /*#__PURE__*/React.createElement(BottomSheet, {
34
+ backdrop: true,
35
+ onClose: props.onClose
36
+ }, /*#__PURE__*/React.createElement(BottomSheetItem, {
37
+ disableGutters: true
38
+ }, /*#__PURE__*/React.createElement(NestedSelect, _extends({
39
+ HeaderComponent: HeaderComponent
40
+ }, props))));
41
+ };
42
+
43
+ export default SelfBottomSheet;
@@ -25,7 +25,8 @@ var ItemRow = function ItemRow(_ref) {
25
25
  isSelected = _ref.isSelected,
26
26
  radioPosition = _ref.radioPosition,
27
27
  isLast = _ref.isLast,
28
- ellipsis = _ref.ellipsis;
28
+ ellipsis = _ref.ellipsis,
29
+ noDivider = _ref.noDivider;
29
30
 
30
31
  var _useBreakpoints = useBreakpoints(),
31
32
  isDesktop = _useBreakpoints.isDesktop;
@@ -66,7 +67,7 @@ var ItemRow = function ItemRow(_ref) {
66
67
  flexItem: true
67
68
  }), item.action ? item.action.Component(_objectSpread({
68
69
  item: item
69
- }, item.action.props)) : null), !isLast && /*#__PURE__*/React.createElement(Divider, null));
70
+ }, item.action.props)) : null), noDivider ? null : !isLast && /*#__PURE__*/React.createElement(Divider, null));
70
71
  };
71
72
 
72
73
  export default ItemRow;
@@ -15,6 +15,7 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
15
15
  import React, { Component } from 'react';
16
16
  import PropTypes from 'prop-types';
17
17
  import omit from 'lodash/omit';
18
+ import List from "cozy-ui/transpiled/react/List";
18
19
  import Input from "cozy-ui/transpiled/react/Input";
19
20
  import Typography from "cozy-ui/transpiled/react/Typography";
20
21
  import ItemRow from "cozy-ui/transpiled/react/NestedSelect/ItemRow";
@@ -118,7 +119,8 @@ var NestedSelect = /*#__PURE__*/function (_Component) {
118
119
  title = _this$props.title,
119
120
  transformParentItem = _this$props.transformParentItem,
120
121
  radioPosition = _this$props.radioPosition,
121
- ellipsis = _this$props.ellipsis;
122
+ ellipsis = _this$props.ellipsis,
123
+ noDivider = _this$props.noDivider;
122
124
  var _this$state = this.state,
123
125
  history = _this$state.history,
124
126
  searchValue = _this$state.searchValue,
@@ -159,7 +161,8 @@ var NestedSelect = /*#__PURE__*/function (_Component) {
159
161
  item: parentItem,
160
162
  onClick: this.handleClickItem,
161
163
  isSelected: isSelectedWithLevel(parentItem),
162
- ellipsis: ellipsis
164
+ ellipsis: ellipsis,
165
+ noDivider: noDivider
163
166
  }) : null, searchOptions && level === 0 && /*#__PURE__*/React.createElement("div", {
164
167
  className: "u-mh-1 u-mb-half"
165
168
  }, /*#__PURE__*/React.createElement(Input, {
@@ -177,7 +180,8 @@ var NestedSelect = /*#__PURE__*/function (_Component) {
177
180
  onClick: _this2.handleClickItem,
178
181
  isSelected: isSelectedWithLevel(item),
179
182
  isLast: index === searchResult.length - 1,
180
- ellipsis: ellipsis
183
+ ellipsis: ellipsis,
184
+ noDivider: noDivider
181
185
  });
182
186
  }) : children.map(function (item, index) {
183
187
  return /*#__PURE__*/React.createElement(ItemRow, {
@@ -187,7 +191,8 @@ var NestedSelect = /*#__PURE__*/function (_Component) {
187
191
  onClick: _this2.handleClickItem,
188
192
  isSelected: isSelectedWithLevel(item),
189
193
  isLast: index === children.length - 1,
190
- ellipsis: ellipsis
194
+ ellipsis: ellipsis,
195
+ noDivider: noDivider
191
196
  });
192
197
  })));
193
198
  }
@@ -197,7 +202,7 @@ var NestedSelect = /*#__PURE__*/function (_Component) {
197
202
  }(Component);
198
203
 
199
204
  NestedSelect.defaultProps = {
200
- ContentComponent: 'div',
205
+ ContentComponent: List,
201
206
  HeaderComponent: null,
202
207
  transformParentItem: function transformParentItem(x) {
203
208
  return x;
@@ -220,25 +225,16 @@ var ItemPropType = PropTypes.shape({
220
225
  children: PropTypes.array
221
226
  });
222
227
  NestedSelect.propTypes = {
223
- /**
224
- * Can be set to "right" or "left". Defaults to "right"
225
- */
228
+ /** Can be set to "right" or "left". Defaults to "right" */
226
229
  radioPosition: PropTypes.oneOf(['left', 'right']),
227
230
 
228
- /**
229
- * The whole option item is passed to this function when selected
230
- */
231
+ /** The whole option item is passed to this function when selected */
231
232
  onSelect: PropTypes.func.isRequired,
232
233
 
233
- /**
234
- * Determines if the row looks selected. The `option` is
235
- * passed as an argument.
236
- */
234
+ /** Determines if the row looks selected. The `option` is passed as an argument. */
237
235
  isSelected: PropTypes.func.isRequired,
238
236
 
239
- /**
240
- * Options that will be rendered as nested lists of choices
241
- */
237
+ /** Options that will be rendered as nested lists of choices */
242
238
  options: PropTypes.shape({
243
239
  children: PropTypes.arrayOf(ItemPropType)
244
240
  }),
@@ -271,9 +267,10 @@ NestedSelect.propTypes = {
271
267
  onSearch: PropTypes.func.isRequired
272
268
  }),
273
269
 
274
- /**
275
- * To manage ellipsis on ItemRow
276
- */
277
- ellipsis: PropTypes.bool
270
+ /** To manage ellipsis on ItemRow */
271
+ ellipsis: PropTypes.bool,
272
+
273
+ /** Remove dividers after each row */
274
+ noDivider: PropTypes.bool
278
275
  };
279
276
  export default NestedSelect;
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import useBreakpoints from "cozy-ui/transpiled/react/providers/Breakpoints";
3
+ import BottomSheet from "cozy-ui/transpiled/react/NestedSelect/BottomSheet";
4
+ import Modal from "cozy-ui/transpiled/react/NestedSelect/Modal";
5
+
6
+ var NestedSelectResponsive = function NestedSelectResponsive(props) {
7
+ var _useBreakpoints = useBreakpoints(),
8
+ isMobile = _useBreakpoints.isMobile;
9
+
10
+ var Wrapper = isMobile ? BottomSheet : Modal;
11
+ return /*#__PURE__*/React.createElement(Wrapper, props);
12
+ };
13
+
14
+ export default NestedSelectResponsive;
@@ -1,2 +1,4 @@
1
1
  export { default } from './NestedSelect';
2
- export { default as NestedSelectModal } from './Modal';
2
+ export { default as NestedSelectModal } from './Modal';
3
+ export { default as NestedSelectBottomSheet } from './BottomSheet';
4
+ export { default as NestedSelectResponsive } from './NestedSelectResponsive';
@@ -1,7 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
- var _excluded = ["className", "disableFooter", "disablePanel", "editPathByModelProps", "children", "componentsProps"];
4
+ var _excluded = ["className", "disableFooter", "disablePanel", "editPathByModelProps", "children", "componentsProps"],
5
+ _excluded2 = ["disableModal"];
5
6
 
6
7
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
7
8
 
@@ -12,6 +13,8 @@ import PropTypes from 'prop-types';
12
13
  import cx from 'classnames';
13
14
  import useBreakpoints from "cozy-ui/transpiled/react/providers/Breakpoints";
14
15
  import { FileDoctype } from "cozy-ui/transpiled/react/proptypes";
16
+ import Modal from "cozy-ui/transpiled/react/Modal";
17
+ import { useCozyTheme } from "cozy-ui/transpiled/react/providers/CozyTheme";
15
18
  import { toolbarPropsPropType } from "cozy-ui/transpiled/react/Viewer/proptypes";
16
19
  import { isValidForPanel } from "cozy-ui/transpiled/react/Viewer/helpers";
17
20
  import Viewer from "cozy-ui/transpiled/react/Viewer/Viewer";
@@ -136,4 +139,42 @@ ViewerContainer.defaultProps = {
136
139
  currentIndex: 0,
137
140
  showNavigation: true
138
141
  };
139
- export default ViewerContainer;
142
+
143
+ var ViewerContainerWrapper = function ViewerContainerWrapper(_ref) {
144
+ var disableModal = _ref.disableModal,
145
+ props = _objectWithoutProperties(_ref, _excluded2);
146
+
147
+ var cozyTheme = useCozyTheme();
148
+
149
+ var _ref2 = props.componentsProps || {},
150
+ _ref2$modalProps = _ref2.modalProps,
151
+ modalProps = _ref2$modalProps === void 0 ? {
152
+ open: true
153
+ } : _ref2$modalProps;
154
+
155
+ if (disableModal) {
156
+ return /*#__PURE__*/React.createElement(ViewerContainer, props);
157
+ }
158
+
159
+ return /*#__PURE__*/React.createElement(Modal, _extends({}, modalProps, {
160
+ className: "CozyTheme--".concat(cozyTheme)
161
+ }), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(ViewerContainer, props)));
162
+ };
163
+
164
+ ViewerContainerWrapper.defaultProps = {
165
+ componentsProps: {
166
+ modalProps: {
167
+ open: true
168
+ }
169
+ }
170
+ };
171
+ ViewerContainerWrapper.propTypes = {
172
+ /** To avoid wrapping the Viewer with a Modal component */
173
+ disableModal: PropTypes.bool,
174
+
175
+ /** Props passed to Modal component */
176
+ componentsProps: PropTypes.shape({
177
+ modalProps: PropTypes.object
178
+ })
179
+ };
180
+ export default ViewerContainerWrapper;
@@ -105,4 +105,5 @@ export { default as TimelineDot } from './TimelineDot';
105
105
  export { default as TimelineItem } from './TimelineItem';
106
106
  export { default as TimelineOppositeContent } from './TimelineOppositeContent';
107
107
  export { default as TimelineSeparator } from './TimelineSeparator';
108
- export { default as AlertProvider, useAlert } from './Alert';
108
+ export { default as AlertProvider, useAlert } from './Alert';
109
+ export { default as Modal } from './Modal';