cozy-ui 69.1.0 → 69.2.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,11 @@
1
+ # [69.2.0](https://github.com/cozy/cozy-ui/compare/v69.1.0...v69.2.0) (2022-07-07)
2
+
3
+
4
+ ### Features
5
+
6
+ * **BottomDrawer:** Add possibility to use it with long content ([59296f0](https://github.com/cozy/cozy-ui/commit/59296f0))
7
+ * **Overlay:** Add ref propagation ([6a0b3f0](https://github.com/cozy/cozy-ui/commit/6a0b3f0))
8
+
1
9
  # [69.1.0](https://github.com/cozy/cozy-ui/compare/v69.0.0...v69.1.0) (2022-07-05)
2
10
 
3
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "69.1.0",
3
+ "version": "69.2.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -1,25 +1,34 @@
1
1
  Displays content coming up from the bottom of the screen.
2
2
 
3
3
  ```jsx
4
- import BottomDrawer from 'cozy-ui/transpiled/react/BottomDrawer';
5
- import Card from 'cozy-ui/transpiled/react/Card';
6
- import Button from 'cozy-ui/transpiled/react/Button';
7
- import Typography from "cozy-ui/transpiled/react/Typography";
4
+ import BottomDrawer from 'cozy-ui/transpiled/react/BottomDrawer'
5
+ import Paper from 'cozy-ui/transpiled/react/Paper'
6
+ import Button from 'cozy-ui/transpiled/react/Buttons'
7
+ import Typography from "cozy-ui/transpiled/react/Typography"
8
+ import Variants from 'cozy-ui/docs/components/Variants'
8
9
 
9
- initialState = { isDrawerDisplayed: isTesting() };
10
+ const initialState = { isDrawerDisplayed: isTesting() }
11
+ const initialVariants = [{ longText: false }]
10
12
 
11
13
  const showDrawer = () => setState({ isDrawerDisplayed: true });
12
- const hideDrawer = () => setState({ isDrawerDisplayed: false });
14
+ const hideDrawer = () => setState({ isDrawerDisplayed: false })
13
15
 
14
- <div>
15
- <Button onClick={showDrawer}>Open drawer</Button>
16
- {state.isDrawerDisplayed &&
17
- <BottomDrawer onClose={hideDrawer}>
18
- <Card className="u-bg-white">
19
- <Typography className="u-mb-1" variant="h5">This is a card in a drawer</Typography>
20
- <Typography className="u-mb-1" variant="body1">This is some card content. Content can be small or huge.</Typography>
21
- <Button className="u-ml-0" label="Demo button" />
22
- </Card>
23
- </BottomDrawer>}
24
- </div>
16
+ ;
17
+
18
+ <Variants initialVariants={initialVariants}>
19
+ {variant => (
20
+ <>
21
+ <Button variant="ghost" size="small" onClick={showDrawer} label="Open drawer" />
22
+
23
+ {state.isDrawerDisplayed &&
24
+ <BottomDrawer onClose={hideDrawer}>
25
+ <Paper className="u-p-1" style={{ borderRadius: '1rem 1rem 0 0' }}>
26
+ <Typography variant="h5" paragraph>This is a paper in a drawer</Typography>
27
+ <Typography paragraph>{variant.longText ? content.ada.long : content.ada.short}</Typography>
28
+ <Button label="Demo button" onClick={() => console.info('huhu')} />
29
+ </Paper>
30
+ </BottomDrawer>}
31
+ </>
32
+ )}
33
+ </Variants>
25
34
  ```
@@ -1,4 +1,4 @@
1
- import React, { Component } from 'react'
1
+ import React, { Component, createRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import Hammer from 'hammerjs'
4
4
  import once from 'lodash/once'
@@ -13,6 +13,8 @@ class BottomDrawer extends Component {
13
13
  constructor(props) {
14
14
  super(props)
15
15
  this.state = { closing: false }
16
+ this.menuRef = createRef()
17
+ this.wrapperRef = createRef()
16
18
  }
17
19
 
18
20
  componentDidMount() {
@@ -22,7 +24,7 @@ class BottomDrawer extends Component {
22
24
 
23
25
  componentWillUnmount() {
24
26
  this.gesturesHandler.destroy()
25
- this.menuNode.current.style = '' // Drops the node style in case it gets recycled, see https://github.com/cozy/cozy-ui/pull/602
27
+ this.menuRef.current.style = '' // Drops the node style in case it gets recycled, see https://github.com/cozy/cozy-ui/pull/602
26
28
  }
27
29
 
28
30
  initialAppear() {
@@ -35,21 +37,21 @@ class BottomDrawer extends Component {
35
37
  }
36
38
 
37
39
  turnTransitionsOn() {
38
- this.menuNode.current.classList.add(styles['with-transition'])
40
+ this.menuRef.current.classList.add(styles['with-transition'])
39
41
  }
40
42
 
41
43
  turnTransitionsOff() {
42
- this.menuNode.current.classList.remove(styles['with-transition'])
44
+ this.menuRef.current.classList.remove(styles['with-transition'])
43
45
  }
44
46
 
45
47
  attachEvents() {
46
- this.gesturesHandler = new Hammer.Manager(this.wrapperNode.current, {
48
+ this.gesturesHandler = new Hammer.Manager(this.wrapperRef.current, {
47
49
  recognizers: [[Hammer.Pan, { direction: Hammer.DIRECTION_VERTICAL }]]
48
50
  })
49
51
 
50
52
  // to be completely accurate, `maximumGestureDelta` should be the difference between the top of the menu and the
51
53
  // bottom of the page; but using the height is much easier to compute and accurate enough.
52
- const maximumGestureDistance = this.menuNode.current.getBoundingClientRect()
54
+ const maximumGestureDistance = this.menuRef.current.getBoundingClientRect()
53
55
  .height
54
56
  // between 0 and 1, how far down the gesture must be to be considered complete upon release
55
57
  const minimumCloseDistance = 0.6
@@ -97,47 +99,47 @@ class BottomDrawer extends Component {
97
99
  applyTransformation(progress) {
98
100
  // constrain between 0 and 1.1 (go a bit further than 1 to be hidden completely)
99
101
  const progressToApply = Math.min(1.1, Math.max(0, progress))
100
- this.menuNode.current.style.transform =
102
+ this.menuRef.current.style.transform =
101
103
  'translateY(' + progressToApply * 100 + '%)'
102
104
  }
103
105
 
104
106
  animateClose = () => {
107
+ const { current: menuNode } = this.menuRef
105
108
  this.setState({ closing: true })
106
109
 
107
110
  // we need to transition the menu to the bottom before dismissing it
108
- const close = once(() => {
109
- this.menuNode.current &&
110
- this.menuNode.current.removeEventListener('transitionend', close)
111
- this.close()
112
- })
111
+ const close = menuNode =>
112
+ once(() => {
113
+ menuNode?.removeEventListener('transitionend', close(menuNode))
114
+ this.close()
115
+ })
113
116
 
114
- this.menuNode.current &&
115
- this.menuNode.current.addEventListener('transitionend', close, false)
117
+ menuNode?.addEventListener('transitionend', close(menuNode), false)
116
118
  // in case transitionend is not called, for example if the element is removed
117
- setTimeout(close, TRANSITION_DURATION)
119
+ setTimeout(close(menuNode), TRANSITION_DURATION)
118
120
 
119
121
  this.applyTransformation(1.1)
120
122
  }
121
123
 
122
124
  close = () => {
125
+ const { onClose } = this.props
123
126
  this.setState({ closing: true })
124
- this.props.onClose && this.props.onClose()
127
+ onClose && onClose()
125
128
  }
126
129
 
127
130
  render() {
128
131
  const { children } = this.props
129
132
  const { closing } = this.state
130
- this.menuNode = React.createRef()
131
- this.wrapperNode = React.createRef()
133
+
132
134
  return (
133
135
  <RemoveScroll>
134
- <div ref={this.wrapperNode}>
136
+ <div ref={this.wrapperRef}>
135
137
  <Overlay
136
138
  style={{ opacity: closing ? 0 : 1 }}
137
139
  onClick={this.animateClose}
138
140
  onEscape={this.animateClose}
139
141
  >
140
- <div ref={this.menuNode} className={styles['BottomDrawer-content']}>
142
+ <div ref={this.menuRef} className={styles['BottomDrawer-content']}>
141
143
  {children}
142
144
  </div>
143
145
  </Overlay>
@@ -8,11 +8,12 @@
8
8
  @extends $transition-transform-ease-out
9
9
 
10
10
  .BottomDrawer-content
11
- z-index $drawer-index
12
- position fixed
13
- bottom 0
14
- left 0
15
- right 0
16
- width 100%
17
- margin 0
18
-
11
+ z-index $drawer-index
12
+ position fixed
13
+ bottom 0
14
+ left 0
15
+ right 0
16
+ width 100%
17
+ margin 0
18
+ max-height 100vh
19
+ overflow-y auto
@@ -7,7 +7,7 @@ import { RemoveScroll } from 'react-remove-scroll'
7
7
 
8
8
  const ESC_KEYCODE = 27
9
9
 
10
- const nonDOMProps = ['onEscape', 'children', 'className']
10
+ const nonDOMProps = ['onEscape', 'children', 'className', 'innerRef']
11
11
 
12
12
  const bodyTallerThanWindow = () => {
13
13
  return document.body.getBoundingClientRect().height > window.innerHeight
@@ -45,7 +45,7 @@ class Overlay extends Component {
45
45
  }
46
46
 
47
47
  render() {
48
- const { children, className } = this.props
48
+ const { children, className, innerRef } = this.props
49
49
  const domProps = omit(this.props, nonDOMProps)
50
50
  // We use Overlay when opening an ActionMenu.
51
51
  // We don't want to block the scroll on Desktop if the ActionMenu
@@ -53,10 +53,12 @@ class Overlay extends Component {
53
53
  // @todo Overlay should not RemoveScroll by itself. It should
54
54
  // be done by lower component (like ActionMenu / Dialog / Modal...)
55
55
  const Wrapper = bodyTallerThanWindow() ? React.Fragment : RemoveScroll
56
+
56
57
  return (
57
58
  <div
58
- onClick={this.handleClick}
59
+ ref={innerRef}
59
60
  className={cx(styles['c-overlay'], className)}
61
+ onClick={this.handleClick}
60
62
  {...domProps}
61
63
  >
62
64
  <Wrapper>{children}</Wrapper>
@@ -71,4 +73,6 @@ Overlay.propTypes = {
71
73
  onEscape: PropTypes.func
72
74
  }
73
75
 
74
- export default Overlay
76
+ export default React.forwardRef((props, ref) => (
77
+ <Overlay innerRef={ref} {...props} />
78
+ ))
@@ -10,7 +10,7 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
10
10
 
11
11
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
12
12
 
13
- import React, { Component } from 'react';
13
+ import React, { Component, createRef } from 'react';
14
14
  import PropTypes from 'prop-types';
15
15
  import Hammer from 'hammerjs';
16
16
  import once from 'lodash/once';
@@ -37,34 +37,43 @@ var BottomDrawer = /*#__PURE__*/function (_Component) {
37
37
  _this = _super.call(this, props);
38
38
 
39
39
  _defineProperty(_assertThisInitialized(_this), "animateClose", function () {
40
+ var menuNode = _this.menuRef.current;
41
+
40
42
  _this.setState({
41
43
  closing: true
42
44
  }); // we need to transition the menu to the bottom before dismissing it
43
45
 
44
46
 
45
- var close = once(function () {
46
- _this.menuNode.current && _this.menuNode.current.removeEventListener('transitionend', close);
47
+ var close = function close(menuNode) {
48
+ return once(function () {
49
+ menuNode === null || menuNode === void 0 ? void 0 : menuNode.removeEventListener('transitionend', close(menuNode));
47
50
 
48
- _this.close();
49
- });
50
- _this.menuNode.current && _this.menuNode.current.addEventListener('transitionend', close, false); // in case transitionend is not called, for example if the element is removed
51
+ _this.close();
52
+ });
53
+ };
51
54
 
52
- setTimeout(close, TRANSITION_DURATION);
55
+ menuNode === null || menuNode === void 0 ? void 0 : menuNode.addEventListener('transitionend', close(menuNode), false); // in case transitionend is not called, for example if the element is removed
56
+
57
+ setTimeout(close(menuNode), TRANSITION_DURATION);
53
58
 
54
59
  _this.applyTransformation(1.1);
55
60
  });
56
61
 
57
62
  _defineProperty(_assertThisInitialized(_this), "close", function () {
63
+ var onClose = _this.props.onClose;
64
+
58
65
  _this.setState({
59
66
  closing: true
60
67
  });
61
68
 
62
- _this.props.onClose && _this.props.onClose();
69
+ onClose && onClose();
63
70
  });
64
71
 
65
72
  _this.state = {
66
73
  closing: false
67
74
  };
75
+ _this.menuRef = /*#__PURE__*/createRef();
76
+ _this.wrapperRef = /*#__PURE__*/createRef();
68
77
  return _this;
69
78
  }
70
79
 
@@ -78,7 +87,7 @@ var BottomDrawer = /*#__PURE__*/function (_Component) {
78
87
  key: "componentWillUnmount",
79
88
  value: function componentWillUnmount() {
80
89
  this.gesturesHandler.destroy();
81
- this.menuNode.current.style = ''; // Drops the node style in case it gets recycled, see https://github.com/cozy/cozy-ui/pull/602
90
+ this.menuRef.current.style = ''; // Drops the node style in case it gets recycled, see https://github.com/cozy/cozy-ui/pull/602
82
91
  }
83
92
  }, {
84
93
  key: "initialAppear",
@@ -96,26 +105,26 @@ var BottomDrawer = /*#__PURE__*/function (_Component) {
96
105
  }, {
97
106
  key: "turnTransitionsOn",
98
107
  value: function turnTransitionsOn() {
99
- this.menuNode.current.classList.add(styles['with-transition']);
108
+ this.menuRef.current.classList.add(styles['with-transition']);
100
109
  }
101
110
  }, {
102
111
  key: "turnTransitionsOff",
103
112
  value: function turnTransitionsOff() {
104
- this.menuNode.current.classList.remove(styles['with-transition']);
113
+ this.menuRef.current.classList.remove(styles['with-transition']);
105
114
  }
106
115
  }, {
107
116
  key: "attachEvents",
108
117
  value: function attachEvents() {
109
118
  var _this3 = this;
110
119
 
111
- this.gesturesHandler = new Hammer.Manager(this.wrapperNode.current, {
120
+ this.gesturesHandler = new Hammer.Manager(this.wrapperRef.current, {
112
121
  recognizers: [[Hammer.Pan, {
113
122
  direction: Hammer.DIRECTION_VERTICAL
114
123
  }]]
115
124
  }); // to be completely accurate, `maximumGestureDelta` should be the difference between the top of the menu and the
116
125
  // bottom of the page; but using the height is much easier to compute and accurate enough.
117
126
 
118
- var maximumGestureDistance = this.menuNode.current.getBoundingClientRect().height; // between 0 and 1, how far down the gesture must be to be considered complete upon release
127
+ var maximumGestureDistance = this.menuRef.current.getBoundingClientRect().height; // between 0 and 1, how far down the gesture must be to be considered complete upon release
119
128
 
120
129
  var minimumCloseDistance = 0.6; // a gesture faster than this will dismiss the menu, regardless of distance traveled
121
130
 
@@ -162,17 +171,15 @@ var BottomDrawer = /*#__PURE__*/function (_Component) {
162
171
  value: function applyTransformation(progress) {
163
172
  // constrain between 0 and 1.1 (go a bit further than 1 to be hidden completely)
164
173
  var progressToApply = Math.min(1.1, Math.max(0, progress));
165
- this.menuNode.current.style.transform = 'translateY(' + progressToApply * 100 + '%)';
174
+ this.menuRef.current.style.transform = 'translateY(' + progressToApply * 100 + '%)';
166
175
  }
167
176
  }, {
168
177
  key: "render",
169
178
  value: function render() {
170
179
  var children = this.props.children;
171
180
  var closing = this.state.closing;
172
- this.menuNode = /*#__PURE__*/React.createRef();
173
- this.wrapperNode = /*#__PURE__*/React.createRef();
174
181
  return /*#__PURE__*/React.createElement(RemoveScroll, null, /*#__PURE__*/React.createElement("div", {
175
- ref: this.wrapperNode
182
+ ref: this.wrapperRef
176
183
  }, /*#__PURE__*/React.createElement(Overlay, {
177
184
  style: {
178
185
  opacity: closing ? 0 : 1
@@ -180,7 +187,7 @@ var BottomDrawer = /*#__PURE__*/function (_Component) {
180
187
  onClick: this.animateClose,
181
188
  onEscape: this.animateClose
182
189
  }, /*#__PURE__*/React.createElement("div", {
183
- ref: this.menuNode,
190
+ ref: this.menuRef,
184
191
  className: styles['BottomDrawer-content']
185
192
  }, children))));
186
193
  }
@@ -20,7 +20,7 @@ import omit from 'lodash/omit';
20
20
  import PropTypes from 'prop-types';
21
21
  import { RemoveScroll } from 'react-remove-scroll';
22
22
  var ESC_KEYCODE = 27;
23
- var nonDOMProps = ['onEscape', 'children', 'className'];
23
+ var nonDOMProps = ['onEscape', 'children', 'className', 'innerRef'];
24
24
 
25
25
  var bodyTallerThanWindow = function bodyTallerThanWindow() {
26
26
  return document.body.getBoundingClientRect().height > window.innerHeight;
@@ -83,7 +83,8 @@ var Overlay = /*#__PURE__*/function (_Component) {
83
83
  value: function render() {
84
84
  var _this$props = this.props,
85
85
  children = _this$props.children,
86
- className = _this$props.className;
86
+ className = _this$props.className,
87
+ innerRef = _this$props.innerRef;
87
88
  var domProps = omit(this.props, nonDOMProps); // We use Overlay when opening an ActionMenu.
88
89
  // We don't want to block the scroll on Desktop if the ActionMenu
89
90
  // is displayed. So no RemoveScroll if the content is too small
@@ -92,8 +93,9 @@ var Overlay = /*#__PURE__*/function (_Component) {
92
93
 
93
94
  var Wrapper = bodyTallerThanWindow() ? React.Fragment : RemoveScroll;
94
95
  return /*#__PURE__*/React.createElement("div", _extends({
95
- onClick: this.handleClick,
96
- className: cx(styles['c-overlay'], className)
96
+ ref: innerRef,
97
+ className: cx(styles['c-overlay'], className),
98
+ onClick: this.handleClick
97
99
  }, domProps), /*#__PURE__*/React.createElement(Wrapper, null, children));
98
100
  }
99
101
  }]);
@@ -106,4 +108,8 @@ Overlay.propTypes = {
106
108
  children: PropTypes.node,
107
109
  onEscape: PropTypes.func
108
110
  };
109
- export default Overlay;
111
+ export default /*#__PURE__*/React.forwardRef(function (props, ref) {
112
+ return /*#__PURE__*/React.createElement(Overlay, _extends({
113
+ innerRef: ref
114
+ }, props));
115
+ });