@dhis2-ui/button 7.7.10 → 7.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,17 +31,17 @@ const ButtonStrip = ({
31
31
  dataTest
32
32
  }) => /*#__PURE__*/_react.default.createElement("div", {
33
33
  "data-test": dataTest,
34
- className: _style.default.dynamic([["2823325675", [_uiConstants.spacers.dp16]]]) + " " + ((0, _classnames.default)(className, {
34
+ className: _style.default.dynamic([["1268901109", [_uiConstants.spacers.dp8]]]) + " " + ((0, _classnames.default)(className, {
35
35
  start: !middle && !end,
36
36
  middle,
37
37
  end
38
38
  }) || "")
39
39
  }, _react.Children.map(children, child => /*#__PURE__*/_react.default.createElement("div", {
40
- className: _style.default.dynamic([["2823325675", [_uiConstants.spacers.dp16]]]) + " " + "box"
40
+ className: _style.default.dynamic([["1268901109", [_uiConstants.spacers.dp8]]]) + " " + "box"
41
41
  }, child)), /*#__PURE__*/_react.default.createElement(_style.default, {
42
- id: "2823325675",
43
- dynamic: [_uiConstants.spacers.dp16]
44
- }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}", "div.middle.__jsx-style-dynamic-selector{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", "div.end.__jsx-style-dynamic-selector{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;}", `.box.__jsx-style-dynamic-selector{margin-left:${_uiConstants.spacers.dp16};}`, ".box.__jsx-style-dynamic-selector:first-child{margin-left:0;}"]));
42
+ id: "1268901109",
43
+ dynamic: [_uiConstants.spacers.dp8]
44
+ }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}", "div.middle.__jsx-style-dynamic-selector{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", "div.end.__jsx-style-dynamic-selector{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;}", `.box.__jsx-style-dynamic-selector{margin-left:${_uiConstants.spacers.dp8};}`, ".box.__jsx-style-dynamic-selector:first-child{margin-left:0;}"]));
45
45
 
46
46
  exports.ButtonStrip = ButtonStrip;
47
47
  const alignmentPropType = (0, _propTypes.mutuallyExclusive)(['middle', 'end'], _propTypes2.default.bool);
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ var _layer = require("@dhis2-ui/layer");
4
+
5
+ var _popper = require("@dhis2-ui/popper");
6
+
7
+ var _enzyme = require("enzyme");
8
+
9
+ var _react = _interopRequireDefault(require("react"));
10
+
11
+ var _testUtils = require("react-dom/test-utils");
12
+
13
+ var _index = require("../../index.js");
14
+
15
+ var _dropdownButton = require("../dropdown-button.js");
16
+
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
+
19
+ describe('<DropdownButton>', () => {
20
+ describe('controlled mode', () => {
21
+ describe('open state', () => {
22
+ const onClick = jest.fn();
23
+
24
+ const Component = /*#__PURE__*/_react.default.createElement(_dropdownButton.DropdownButton, {
25
+ onClick: onClick,
26
+ open: true,
27
+ component: /*#__PURE__*/_react.default.createElement("span", null, "test")
28
+ });
29
+
30
+ it('shows the Popper when open is true', async () => {
31
+ // TODO: https://github.com/popperjs/react-popper/issues/350
32
+ const wrapper = (0, _enzyme.mount)(Component);
33
+ await (0, _testUtils.act)(async () => await null);
34
+ const popper = wrapper.find(_popper.Popper);
35
+ expect(popper).toHaveLength(1);
36
+ expect(popper.find('span').text()).toEqual('test');
37
+ });
38
+ it('passes an "open" property to the callback payload with the next open state', async () => {
39
+ // TODO: https://github.com/popperjs/react-popper/issues/350
40
+ const wrapper = (0, _enzyme.mount)(Component);
41
+ await (0, _testUtils.act)(async () => await null);
42
+ wrapper.find(_layer.Layer).simulate('click');
43
+ expect(onClick).toHaveBeenCalledTimes(1);
44
+ const args = onClick.mock.calls[0];
45
+ expect(args).toHaveLength(2);
46
+ expect(args[0]).toEqual(expect.objectContaining({
47
+ open: false
48
+ }));
49
+ });
50
+ });
51
+ describe('closed state', () => {
52
+ const onClick = jest.fn();
53
+ const wrapper = (0, _enzyme.mount)( /*#__PURE__*/_react.default.createElement(_dropdownButton.DropdownButton, {
54
+ onClick: onClick,
55
+ open: false,
56
+ component: /*#__PURE__*/_react.default.createElement("span", null, "test")
57
+ }));
58
+ it('it does not show the Popper when open is false', () => {
59
+ const popper = wrapper.find(_popper.Popper);
60
+ expect(popper).toHaveLength(0);
61
+ });
62
+ it('passes an "open" property to the callback payload with the next open state (false)', () => {
63
+ wrapper.find(_index.Button).simulate('click');
64
+ expect(onClick).toHaveBeenCalledTimes(1);
65
+ const args = onClick.mock.calls[0];
66
+ expect(args).toHaveLength(2);
67
+ expect(args[0]).toEqual(expect.objectContaining({
68
+ open: true
69
+ }));
70
+ });
71
+ });
72
+ });
73
+ });
@@ -11,9 +11,11 @@ var _layer = require("@dhis2-ui/layer");
11
11
 
12
12
  var _popper = require("@dhis2-ui/popper");
13
13
 
14
+ var _propTypes = require("@dhis2/prop-types");
15
+
14
16
  var _uiConstants = require("@dhis2/ui-constants");
15
17
 
16
- var _propTypes = _interopRequireDefault(require("prop-types"));
18
+ var _propTypes2 = _interopRequireDefault(require("prop-types"));
17
19
 
18
20
  var _react = _interopRequireWildcard(require("react"));
19
21
 
@@ -43,7 +45,7 @@ function ArrowDown({
43
45
  }
44
46
 
45
47
  ArrowDown.propTypes = {
46
- className: _propTypes.default.string
48
+ className: _propTypes2.default.string
47
49
  };
48
50
 
49
51
  function ArrowUp({
@@ -63,7 +65,7 @@ function ArrowUp({
63
65
  }
64
66
 
65
67
  ArrowUp.propTypes = {
66
- className: _propTypes.default.string
68
+ className: _propTypes2.default.string
67
69
  };
68
70
  const arrow = {
69
71
  styles: /*#__PURE__*/_react.default.createElement(_style.default, {
@@ -82,28 +84,33 @@ class DropdownButton extends _react.Component {
82
84
 
83
85
  _defineProperty(this, "anchorRef", /*#__PURE__*/_react.default.createRef());
84
86
 
85
- _defineProperty(this, "onToggle", ({
87
+ _defineProperty(this, "onClickHandler", ({
86
88
  name,
87
89
  value
88
90
  }, event) => {
89
- this.setState({
90
- open: !this.state.open
91
- }, () => {
91
+ const handleClick = open => {
92
92
  if (this.props.onClick) {
93
93
  this.props.onClick({
94
94
  name,
95
95
  value,
96
- open: this.state.open
96
+ open
97
97
  }, event);
98
98
  }
99
- });
99
+ };
100
+
101
+ if (typeof this.props.open === 'boolean') {
102
+ handleClick(!this.props.open);
103
+ } else {
104
+ this.setState({
105
+ open: !this.state.open
106
+ }, () => {
107
+ handleClick(this.state.open);
108
+ });
109
+ }
100
110
  });
101
111
  }
102
112
 
103
113
  render() {
104
- const {
105
- open
106
- } = this.state;
107
114
  const {
108
115
  component,
109
116
  children,
@@ -122,6 +129,7 @@ class DropdownButton extends _react.Component {
122
129
  initialFocus,
123
130
  dataTest
124
131
  } = this.props;
132
+ const open = typeof this.props.open === 'boolean' ? this.props.open : this.state.open;
125
133
  const ArrowIconComponent = open ? ArrowUp : ArrowDown;
126
134
  return /*#__PURE__*/_react.default.createElement("div", {
127
135
  ref: this.anchorRef,
@@ -136,7 +144,7 @@ class DropdownButton extends _react.Component {
136
144
  primary: primary,
137
145
  secondary: secondary,
138
146
  small: small,
139
- onClick: this.onToggle,
147
+ onClick: this.onClickHandler,
140
148
  name: name,
141
149
  value: value,
142
150
  tabIndex: tabIndex,
@@ -145,7 +153,7 @@ class DropdownButton extends _react.Component {
145
153
  }, children, /*#__PURE__*/_react.default.createElement(ArrowIconComponent, {
146
154
  className: "jsx-3163060161" + " " + (arrow.className || "")
147
155
  })), open && /*#__PURE__*/_react.default.createElement(_layer.Layer, {
148
- onClick: this.onToggle,
156
+ onClick: this.onClickHandler,
149
157
  transparent: true
150
158
  }, /*#__PURE__*/_react.default.createElement(_popper.Popper, {
151
159
  dataTest: `${dataTest}-popper`,
@@ -164,26 +172,29 @@ DropdownButton.defaultProps = {
164
172
  };
165
173
  DropdownButton.propTypes = {
166
174
  /** Children to render inside the buton */
167
- children: _propTypes.default.node,
168
- className: _propTypes.default.string,
175
+ children: _propTypes2.default.node,
176
+ className: _propTypes2.default.string,
169
177
 
170
178
  /** Component to show/hide when button is clicked */
171
- component: _propTypes.default.element,
172
- dataTest: _propTypes.default.string,
179
+ component: _propTypes2.default.element,
180
+ dataTest: _propTypes2.default.string,
173
181
 
174
182
  /** Button variant. Mutually exclusive with `primary` and `secondary` props */
175
183
  destructive: _uiConstants.sharedPropTypes.buttonVariantPropType,
176
184
 
177
185
  /** Make the button non-interactive */
178
- disabled: _propTypes.default.bool,
179
- icon: _propTypes.default.element,
186
+ disabled: _propTypes2.default.bool,
187
+ icon: _propTypes2.default.element,
180
188
 
181
189
  /** Grants button initial focus on the page */
182
- initialFocus: _propTypes.default.bool,
190
+ initialFocus: _propTypes2.default.bool,
183
191
 
184
192
  /** Button size. Mutually exclusive with `small` prop */
185
193
  large: _uiConstants.sharedPropTypes.sizePropType,
186
- name: _propTypes.default.string,
194
+ name: _propTypes2.default.string,
195
+
196
+ /** Controls popper visibility. When implementing this prop the component becomes a controlled component */
197
+ open: _propTypes2.default.bool,
187
198
 
188
199
  /** Button variant. Mutually exclusive with `destructive` and `secondary` props */
189
200
  primary: _uiConstants.sharedPropTypes.buttonVariantPropType,
@@ -193,15 +204,17 @@ DropdownButton.propTypes = {
193
204
 
194
205
  /** Button size. Mutually exclusive with `large` prop */
195
206
  small: _uiConstants.sharedPropTypes.sizePropType,
196
- tabIndex: _propTypes.default.string,
207
+ tabIndex: _propTypes2.default.string,
197
208
 
198
209
  /** Type of button. Can take advantage of different default behavior */
199
- type: _propTypes.default.oneOf(['submit', 'reset', 'button']),
200
- value: _propTypes.default.string,
210
+ type: _propTypes2.default.oneOf(['submit', 'reset', 'button']),
211
+ value: _propTypes2.default.string,
201
212
 
202
213
  /**
203
214
  * Callback triggered on click.
204
215
  * Called with signature `({ name: string, value: string, open: bool }, event)`
216
+ * Is required when using the `open` prop to override the internal
217
+ * state.
205
218
  */
206
- onClick: _propTypes.default.func
219
+ onClick: (0, _propTypes.requiredIf)(props => typeof props.open === 'boolean', _propTypes2.default.func)
207
220
  };
@@ -3,17 +3,21 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.InitialFocus = exports.WithMenu = exports.Large = exports.Small = exports.Disabled = exports.Destructive = exports.Secondary = exports.Primary = exports.WithClick = exports.Default = exports.default = void 0;
6
+ exports.ManualControl = exports.Open = exports.InitialFocus = exports.WithMenu = exports.Large = exports.Small = exports.Disabled = exports.Destructive = exports.Secondary = exports.Primary = exports.WithClick = exports.Default = exports.default = void 0;
7
7
 
8
8
  var _menu = require("@dhis2-ui/menu");
9
9
 
10
10
  var _uiConstants = require("@dhis2/ui-constants");
11
11
 
12
- var _react = _interopRequireDefault(require("react"));
12
+ var _react = _interopRequireWildcard(require("react"));
13
13
 
14
14
  var _index = require("./index.js");
15
15
 
16
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
+
18
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
+
20
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
17
21
 
18
22
  const description = `
19
23
  Presents several actions to a user in a small space. Can replace single, individual buttons. Should only be used for actions that are related to one another. Ensure the button has a useful level that communicates that actions are contained within. Dropdown buttons do not have an explicit action, only expanding the list of contained actions.
@@ -23,13 +27,6 @@ import { DropdownButton } from '@dhis2/ui'
23
27
  \`\`\`
24
28
  `;
25
29
 
26
- window.onClick = (payload, event) => {
27
- console.log('onClick payload', payload);
28
- console.log('onClick event', event);
29
- };
30
-
31
- const onClick = (...args) => window.onClick(...args);
32
-
33
30
  const Simple = /*#__PURE__*/_react.default.createElement("span", null, "Simplest thing");
34
31
 
35
32
  const {
@@ -75,7 +72,9 @@ exports.Default = Default;
75
72
  const WithClick = Template.bind({});
76
73
  exports.WithClick = WithClick;
77
74
  WithClick.args = {
78
- onClick: onClick
75
+ onClick: ({
76
+ open
77
+ }) => console.log('onClick: the dropdown is open: ', open)
79
78
  };
80
79
  const Primary = Template.bind({});
81
80
  exports.Primary = Primary;
@@ -140,4 +139,36 @@ InitialFocus.parameters = {
140
139
  docs: {
141
140
  disable: true
142
141
  }
143
- };
142
+ };
143
+
144
+ const OpenTemplate = args => {
145
+ return /*#__PURE__*/_react.default.createElement(_index.DropdownButton, args);
146
+ };
147
+
148
+ const Open = OpenTemplate.bind({});
149
+ exports.Open = Open;
150
+ Open.args = {
151
+ open: true,
152
+ component: Simple,
153
+ onClick: () => {}
154
+ };
155
+
156
+ const ManualControlTemplate = args => {
157
+ const [isOpen, setIsOpen] = (0, _react.useState)(true);
158
+
159
+ const handleOpen = () => setIsOpen(false);
160
+
161
+ const Menu = /*#__PURE__*/_react.default.createElement("ul", null, /*#__PURE__*/_react.default.createElement("li", null, "First option does nothing"), /*#__PURE__*/_react.default.createElement("li", {
162
+ onClick: handleOpen
163
+ }, "Close the dropdown"));
164
+
165
+ return /*#__PURE__*/_react.default.createElement(_index.DropdownButton, _extends({}, args, {
166
+ onClick: () => setIsOpen(!isOpen),
167
+ open: isOpen,
168
+ component: Menu
169
+ }));
170
+ };
171
+
172
+ const ManualControl = ManualControlTemplate.bind({});
173
+ exports.ManualControl = ManualControl;
174
+ ManualControl.args = {};
@@ -13,17 +13,17 @@ const ButtonStrip = ({
13
13
  dataTest
14
14
  }) => /*#__PURE__*/React.createElement("div", {
15
15
  "data-test": dataTest,
16
- className: _JSXStyle.dynamic([["2823325675", [spacers.dp16]]]) + " " + (cx(className, {
16
+ className: _JSXStyle.dynamic([["1268901109", [spacers.dp8]]]) + " " + (cx(className, {
17
17
  start: !middle && !end,
18
18
  middle,
19
19
  end
20
20
  }) || "")
21
21
  }, Children.map(children, child => /*#__PURE__*/React.createElement("div", {
22
- className: _JSXStyle.dynamic([["2823325675", [spacers.dp16]]]) + " " + "box"
22
+ className: _JSXStyle.dynamic([["1268901109", [spacers.dp8]]]) + " " + "box"
23
23
  }, child)), /*#__PURE__*/React.createElement(_JSXStyle, {
24
- id: "2823325675",
25
- dynamic: [spacers.dp16]
26
- }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}", "div.middle.__jsx-style-dynamic-selector{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", "div.end.__jsx-style-dynamic-selector{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;}", `.box.__jsx-style-dynamic-selector{margin-left:${spacers.dp16};}`, ".box.__jsx-style-dynamic-selector:first-child{margin-left:0;}"]));
24
+ id: "1268901109",
25
+ dynamic: [spacers.dp8]
26
+ }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}", "div.middle.__jsx-style-dynamic-selector{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", "div.end.__jsx-style-dynamic-selector{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;}", `.box.__jsx-style-dynamic-selector{margin-left:${spacers.dp8};}`, ".box.__jsx-style-dynamic-selector:first-child{margin-left:0;}"]));
27
27
 
28
28
  const alignmentPropType = mutuallyExclusive(['middle', 'end'], PropTypes.bool);
29
29
  ButtonStrip.defaultProps = {
@@ -0,0 +1,60 @@
1
+ import { Layer } from '@dhis2-ui/layer';
2
+ import { Popper } from '@dhis2-ui/popper';
3
+ import { mount } from 'enzyme';
4
+ import React from 'react';
5
+ import { act } from 'react-dom/test-utils';
6
+ import { Button } from '../../index.js';
7
+ import { DropdownButton } from '../dropdown-button.js';
8
+ describe('<DropdownButton>', () => {
9
+ describe('controlled mode', () => {
10
+ describe('open state', () => {
11
+ const onClick = jest.fn();
12
+ const Component = /*#__PURE__*/React.createElement(DropdownButton, {
13
+ onClick: onClick,
14
+ open: true,
15
+ component: /*#__PURE__*/React.createElement("span", null, "test")
16
+ });
17
+ it('shows the Popper when open is true', async () => {
18
+ // TODO: https://github.com/popperjs/react-popper/issues/350
19
+ const wrapper = mount(Component);
20
+ await act(async () => await null);
21
+ const popper = wrapper.find(Popper);
22
+ expect(popper).toHaveLength(1);
23
+ expect(popper.find('span').text()).toEqual('test');
24
+ });
25
+ it('passes an "open" property to the callback payload with the next open state', async () => {
26
+ // TODO: https://github.com/popperjs/react-popper/issues/350
27
+ const wrapper = mount(Component);
28
+ await act(async () => await null);
29
+ wrapper.find(Layer).simulate('click');
30
+ expect(onClick).toHaveBeenCalledTimes(1);
31
+ const args = onClick.mock.calls[0];
32
+ expect(args).toHaveLength(2);
33
+ expect(args[0]).toEqual(expect.objectContaining({
34
+ open: false
35
+ }));
36
+ });
37
+ });
38
+ describe('closed state', () => {
39
+ const onClick = jest.fn();
40
+ const wrapper = mount( /*#__PURE__*/React.createElement(DropdownButton, {
41
+ onClick: onClick,
42
+ open: false,
43
+ component: /*#__PURE__*/React.createElement("span", null, "test")
44
+ }));
45
+ it('it does not show the Popper when open is false', () => {
46
+ const popper = wrapper.find(Popper);
47
+ expect(popper).toHaveLength(0);
48
+ });
49
+ it('passes an "open" property to the callback payload with the next open state (false)', () => {
50
+ wrapper.find(Button).simulate('click');
51
+ expect(onClick).toHaveBeenCalledTimes(1);
52
+ const args = onClick.mock.calls[0];
53
+ expect(args).toHaveLength(2);
54
+ expect(args[0]).toEqual(expect.objectContaining({
55
+ open: true
56
+ }));
57
+ });
58
+ });
59
+ });
60
+ });
@@ -4,6 +4,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
4
4
 
5
5
  import { Layer } from '@dhis2-ui/layer';
6
6
  import { Popper } from '@dhis2-ui/popper';
7
+ import { requiredIf } from '@dhis2/prop-types';
7
8
  import { spacers, sharedPropTypes } from '@dhis2/ui-constants';
8
9
  import PropTypes from 'prop-types';
9
10
  import React, { Component } from 'react';
@@ -64,28 +65,33 @@ class DropdownButton extends Component {
64
65
 
65
66
  _defineProperty(this, "anchorRef", /*#__PURE__*/React.createRef());
66
67
 
67
- _defineProperty(this, "onToggle", ({
68
+ _defineProperty(this, "onClickHandler", ({
68
69
  name,
69
70
  value
70
71
  }, event) => {
71
- this.setState({
72
- open: !this.state.open
73
- }, () => {
72
+ const handleClick = open => {
74
73
  if (this.props.onClick) {
75
74
  this.props.onClick({
76
75
  name,
77
76
  value,
78
- open: this.state.open
77
+ open
79
78
  }, event);
80
79
  }
81
- });
80
+ };
81
+
82
+ if (typeof this.props.open === 'boolean') {
83
+ handleClick(!this.props.open);
84
+ } else {
85
+ this.setState({
86
+ open: !this.state.open
87
+ }, () => {
88
+ handleClick(this.state.open);
89
+ });
90
+ }
82
91
  });
83
92
  }
84
93
 
85
94
  render() {
86
- const {
87
- open
88
- } = this.state;
89
95
  const {
90
96
  component,
91
97
  children,
@@ -104,6 +110,7 @@ class DropdownButton extends Component {
104
110
  initialFocus,
105
111
  dataTest
106
112
  } = this.props;
113
+ const open = typeof this.props.open === 'boolean' ? this.props.open : this.state.open;
107
114
  const ArrowIconComponent = open ? ArrowUp : ArrowDown;
108
115
  return /*#__PURE__*/React.createElement("div", {
109
116
  ref: this.anchorRef,
@@ -118,7 +125,7 @@ class DropdownButton extends Component {
118
125
  primary: primary,
119
126
  secondary: secondary,
120
127
  small: small,
121
- onClick: this.onToggle,
128
+ onClick: this.onClickHandler,
122
129
  name: name,
123
130
  value: value,
124
131
  tabIndex: tabIndex,
@@ -127,7 +134,7 @@ class DropdownButton extends Component {
127
134
  }, children, /*#__PURE__*/React.createElement(ArrowIconComponent, {
128
135
  className: "jsx-3163060161" + " " + (arrow.className || "")
129
136
  })), open && /*#__PURE__*/React.createElement(Layer, {
130
- onClick: this.onToggle,
137
+ onClick: this.onClickHandler,
131
138
  transparent: true
132
139
  }, /*#__PURE__*/React.createElement(Popper, {
133
140
  dataTest: `${dataTest}-popper`,
@@ -166,6 +173,9 @@ DropdownButton.propTypes = {
166
173
  large: sharedPropTypes.sizePropType,
167
174
  name: PropTypes.string,
168
175
 
176
+ /** Controls popper visibility. When implementing this prop the component becomes a controlled component */
177
+ open: PropTypes.bool,
178
+
169
179
  /** Button variant. Mutually exclusive with `destructive` and `secondary` props */
170
180
  primary: sharedPropTypes.buttonVariantPropType,
171
181
 
@@ -183,7 +193,9 @@ DropdownButton.propTypes = {
183
193
  /**
184
194
  * Callback triggered on click.
185
195
  * Called with signature `({ name: string, value: string, open: bool }, event)`
196
+ * Is required when using the `open` prop to override the internal
197
+ * state.
186
198
  */
187
- onClick: PropTypes.func
199
+ onClick: requiredIf(props => typeof props.open === 'boolean', PropTypes.func)
188
200
  };
189
201
  export { DropdownButton };
@@ -1,6 +1,8 @@
1
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
+
1
3
  import { FlyoutMenu, MenuItem } from '@dhis2-ui/menu';
2
4
  import { sharedPropTypes } from '@dhis2/ui-constants';
3
- import React from 'react';
5
+ import React, { useState } from 'react';
4
6
  import { DropdownButton } from './index.js';
5
7
  const description = `
6
8
  Presents several actions to a user in a small space. Can replace single, individual buttons. Should only be used for actions that are related to one another. Ensure the button has a useful level that communicates that actions are contained within. Dropdown buttons do not have an explicit action, only expanding the list of contained actions.
@@ -9,14 +11,6 @@ Presents several actions to a user in a small space. Can replace single, individ
9
11
  import { DropdownButton } from '@dhis2/ui'
10
12
  \`\`\`
11
13
  `;
12
-
13
- window.onClick = (payload, event) => {
14
- console.log('onClick payload', payload);
15
- console.log('onClick event', event);
16
- };
17
-
18
- const onClick = (...args) => window.onClick(...args);
19
-
20
14
  const Simple = /*#__PURE__*/React.createElement("span", null, "Simplest thing");
21
15
  const {
22
16
  sizeArgType,
@@ -58,7 +52,9 @@ const Template = args => /*#__PURE__*/React.createElement(DropdownButton, args);
58
52
  export const Default = Template.bind({});
59
53
  export const WithClick = Template.bind({});
60
54
  WithClick.args = {
61
- onClick: onClick
55
+ onClick: ({
56
+ open
57
+ }) => console.log('onClick: the dropdown is open: ', open)
62
58
  };
63
59
  export const Primary = Template.bind({});
64
60
  Primary.args = {
@@ -115,4 +111,33 @@ InitialFocus.parameters = {
115
111
  docs: {
116
112
  disable: true
117
113
  }
118
- };
114
+ };
115
+
116
+ const OpenTemplate = args => {
117
+ return /*#__PURE__*/React.createElement(DropdownButton, args);
118
+ };
119
+
120
+ export const Open = OpenTemplate.bind({});
121
+ Open.args = {
122
+ open: true,
123
+ component: Simple,
124
+ onClick: () => {}
125
+ };
126
+
127
+ const ManualControlTemplate = args => {
128
+ const [isOpen, setIsOpen] = useState(true);
129
+
130
+ const handleOpen = () => setIsOpen(false);
131
+
132
+ const Menu = /*#__PURE__*/React.createElement("ul", null, /*#__PURE__*/React.createElement("li", null, "First option does nothing"), /*#__PURE__*/React.createElement("li", {
133
+ onClick: handleOpen
134
+ }, "Close the dropdown"));
135
+ return /*#__PURE__*/React.createElement(DropdownButton, _extends({}, args, {
136
+ onClick: () => setIsOpen(!isOpen),
137
+ open: isOpen,
138
+ component: Menu
139
+ }));
140
+ };
141
+
142
+ export const ManualControl = ManualControlTemplate.bind({});
143
+ ManualControl.args = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2-ui/button",
3
- "version": "7.7.10",
3
+ "version": "7.9.1",
4
4
  "description": "UI Button",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,11 +32,11 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@dhis2/prop-types": "^3.0.0-beta.1",
35
- "@dhis2-ui/layer": "7.7.10",
36
- "@dhis2-ui/loader": "7.7.10",
37
- "@dhis2-ui/popper": "7.7.10",
38
- "@dhis2/ui-constants": "7.7.10",
39
- "@dhis2/ui-icons": "7.7.10",
35
+ "@dhis2-ui/layer": "7.9.1",
36
+ "@dhis2-ui/loader": "7.9.1",
37
+ "@dhis2-ui/popper": "7.9.1",
38
+ "@dhis2/ui-constants": "7.9.1",
39
+ "@dhis2/ui-icons": "7.9.1",
40
40
  "classnames": "^2.3.1",
41
41
  "prop-types": "^15.7.2"
42
42
  },