@dhis2-ui/tab 9.10.3 → 9.11.1-beta.1

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.
Files changed (33) hide show
  1. package/build/cjs/index.js +0 -2
  2. package/build/cjs/tab/features/accepts_children/index.js +0 -1
  3. package/build/cjs/tab/features/accepts_icon/index.js +0 -1
  4. package/build/cjs/tab/features/is_clickable/index.js +2 -3
  5. package/build/cjs/tab/index.js +0 -1
  6. package/build/cjs/tab/tab.e2e.stories.js +28 -0
  7. package/build/cjs/tab/tab.js +8 -25
  8. package/build/cjs/tab-bar/animated-side-scroll.js +0 -7
  9. package/build/cjs/tab-bar/detect-horizontal-scrollbar-height.js +12 -3
  10. package/build/cjs/tab-bar/features/accepts_children/index.js +0 -1
  11. package/build/cjs/tab-bar/features/auto_hides_scroll_buttons/index.js +0 -1
  12. package/build/cjs/tab-bar/index.js +0 -1
  13. package/build/cjs/tab-bar/scroll-bar.js +7 -44
  14. package/build/cjs/tab-bar/scroll-button.js +2 -10
  15. package/build/cjs/tab-bar/tab-bar.e2e.stories.js +31 -0
  16. package/build/cjs/tab-bar/tab-bar.js +4 -15
  17. package/build/cjs/tab-bar/{tab-bar.stories.js → tab-bar.prod.stories.js} +23 -29
  18. package/build/cjs/tab-bar/tabs.js +6 -25
  19. package/build/es/tab/features/is_clickable/index.js +2 -2
  20. package/build/es/tab/tab.e2e.stories.js +17 -0
  21. package/build/es/tab/tab.js +4 -9
  22. package/build/es/tab-bar/animated-side-scroll.js +0 -6
  23. package/build/es/tab-bar/detect-horizontal-scrollbar-height.js +12 -2
  24. package/build/es/tab-bar/scroll-bar.js +4 -31
  25. package/build/es/tab-bar/scroll-button.js +1 -1
  26. package/build/es/tab-bar/{tab-bar.stories.e2e.js → tab-bar.e2e.stories.js} +8 -5
  27. package/build/es/tab-bar/tab-bar.js +3 -9
  28. package/build/es/tab-bar/{tab-bar.stories.js → tab-bar.prod.stories.js} +21 -6
  29. package/build/es/tab-bar/tabs.js +3 -14
  30. package/package.json +7 -7
  31. package/build/cjs/tab/tab.stories.e2e.js +0 -19
  32. package/build/cjs/tab-bar/tab-bar.stories.e2e.js +0 -26
  33. package/build/es/tab/tab.stories.e2e.js +0 -12
@@ -4,19 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.TabsWithScroller = exports.TabsWithHiddenScrollButtons = exports.TabStatesWithIcon = exports.TabStates = exports.RTL = exports.FixedTabsFillContent = exports.DefaultFluid = void 0;
7
-
8
7
  var _style = _interopRequireDefault(require("styled-jsx/style"));
9
-
10
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
-
12
9
  var _react = _interopRequireDefault(require("react"));
13
-
14
10
  var _index = require("../tab/index.js");
15
-
16
11
  var _index2 = require("./index.js");
17
-
18
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
13
  function AttachFile(_ref) {
21
14
  let {
22
15
  className
@@ -32,29 +25,45 @@ function AttachFile(_ref) {
32
25
  id: "4098137027"
33
26
  }, ["svg.jsx-4098137027{fill:inherit;height:24px;width:24px;vertical-align:middle;pointer-events:none;}"]));
34
27
  }
35
-
36
28
  AttachFile.propTypes = {
37
29
  className: _propTypes.default.string
38
30
  };
39
31
  const subtitle = 'Ssed to divide content into categories and/or sections';
40
- const description = "\nUse tabs to split related content into separate sections.\n\n- Each tab should contain content that relates to one another, but the content should not overlap.\n- Tabs are especially useful for splitting up content that may be relevant to different user groups, instead of displaying overwhelming amounts of information on a single page.\n- Do not use tabs to compare content.\n- Do not use tabs for sequential content that needs to be done in order.\n- Do not use tabs for content that needs to be viewed at the same time.\n- The number of tabs is less important than splitting content into understandable, predictable groups. Do not group together unrelated content in order to reduce tab count. Users struggle more with unpredictable tabs than too many tabs.\n\n#### Naming\n\nGive tabs short, understandable names. Try to find a word or very short phrase that summarizes the content. If you cannot find a suitable word this may mean you are trying to fit too much content under a single tab. The content of a tab should be obvious from its name.\n\nFor example: Do use \"Legends\" instead of \"Set up legends\", Do use \"Data analysis\" instead of \"Options for analysis of data\",\n\nDo not repeat a term across tabs. If tabs are used inside a 'Options' modal, it is enough to use tab names \"Data\", \"Legend\", \"Style\". Do not repeat 'options' for all, e.g. \"Data options\", \"Legend options\" etc.\n\n```js\nimport { TabBar, Tab } from '@dhis2/ui'\n```\n";
32
+ const description = `
33
+ Use tabs to split related content into separate sections.
41
34
 
35
+ - Each tab should contain content that relates to one another, but the content should not overlap.
36
+ - Tabs are especially useful for splitting up content that may be relevant to different user groups, instead of displaying overwhelming amounts of information on a single page.
37
+ - Do not use tabs to compare content.
38
+ - Do not use tabs for sequential content that needs to be done in order.
39
+ - Do not use tabs for content that needs to be viewed at the same time.
40
+ - The number of tabs is less important than splitting content into understandable, predictable groups. Do not group together unrelated content in order to reduce tab count. Users struggle more with unpredictable tabs than too many tabs.
41
+
42
+ #### Naming
43
+
44
+ Give tabs short, understandable names. Try to find a word or very short phrase that summarizes the content. If you cannot find a suitable word this may mean you are trying to fit too much content under a single tab. The content of a tab should be obvious from its name.
45
+
46
+ For example: Do use "Legends" instead of "Set up legends", Do use "Data analysis" instead of "Options for analysis of data",
47
+
48
+ Do not repeat a term across tabs. If tabs are used inside a 'Options' modal, it is enough to use tab names "Data", "Legend", "Style". Do not repeat 'options' for all, e.g. "Data options", "Legend options" etc.
49
+
50
+ \`\`\`js
51
+ import { TabBar, Tab } from '@dhis2/ui'
52
+ \`\`\`
53
+ `;
42
54
  const Wrapper = fn => /*#__PURE__*/_react.default.createElement("div", {
43
55
  style: {
44
56
  maxWidth: 700
45
57
  }
46
58
  }, fn(), /*#__PURE__*/_react.default.createElement("p", null, "Max-width of this container is 700 px"));
47
-
48
59
  window.onClick = (payload, event) => {
49
60
  console.log('onClick payload', payload);
50
61
  console.log('onClick event', event);
51
62
  };
52
-
53
63
  const onClick = function () {
54
64
  return window.onClick(...arguments);
55
65
  };
56
-
57
- var _default = {
66
+ var _default = exports.default = {
58
67
  title: 'Tab Bar',
59
68
  component: _index2.TabBar,
60
69
  subcomponents: {
@@ -70,8 +79,6 @@ var _default = {
70
79
  },
71
80
  decorators: [Wrapper]
72
81
  };
73
- exports.default = _default;
74
-
75
82
  const DefaultFluid = args => /*#__PURE__*/_react.default.createElement(_index2.TabBar, args, /*#__PURE__*/_react.default.createElement(_index.Tab, {
76
83
  onClick: onClick
77
84
  }, "Tab A"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
@@ -88,10 +95,8 @@ const DefaultFluid = args => /*#__PURE__*/_react.default.createElement(_index2.T
88
95
  }, "Tab F"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
89
96
  onClick: onClick
90
97
  }, "Tab G"));
91
-
92
98
  exports.DefaultFluid = DefaultFluid;
93
99
  DefaultFluid.storyName = 'Default (fluid)';
94
-
95
100
  const FixedTabsFillContent = args => /*#__PURE__*/_react.default.createElement(_index2.TabBar, args, /*#__PURE__*/_react.default.createElement(_index.Tab, {
96
101
  onClick: onClick
97
102
  }, "Tab A"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
@@ -108,13 +113,11 @@ const FixedTabsFillContent = args => /*#__PURE__*/_react.default.createElement(_
108
113
  }, "Tab F"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
109
114
  onClick: onClick
110
115
  }, "Tab G"));
111
-
112
116
  exports.FixedTabsFillContent = FixedTabsFillContent;
113
117
  FixedTabsFillContent.args = {
114
118
  fixed: true
115
119
  };
116
120
  FixedTabsFillContent.storyName = 'Fixed - tabs fill content';
117
-
118
121
  const TabsWithScroller = args => /*#__PURE__*/_react.default.createElement(_index2.TabBar, args, /*#__PURE__*/_react.default.createElement(_index.Tab, {
119
122
  onClick: onClick
120
123
  }, "Tab A"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
@@ -153,13 +156,11 @@ const TabsWithScroller = args => /*#__PURE__*/_react.default.createElement(_inde
153
156
  }, "Tab Q"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
154
157
  onClick: onClick
155
158
  }, "Tab R"));
156
-
157
159
  exports.TabsWithScroller = TabsWithScroller;
158
160
  TabsWithScroller.args = {
159
161
  scrollable: true
160
162
  };
161
163
  TabsWithScroller.storyName = 'Tabs with scroller';
162
-
163
164
  const TabsWithHiddenScrollButtons = args => /*#__PURE__*/_react.default.createElement(_index2.TabBar, args, /*#__PURE__*/_react.default.createElement(_index.Tab, {
164
165
  onClick: onClick
165
166
  }, "Tab A"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
@@ -167,13 +168,11 @@ const TabsWithHiddenScrollButtons = args => /*#__PURE__*/_react.default.createEl
167
168
  }, "Tab B"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
168
169
  onClick: onClick
169
170
  }, "Tab C"));
170
-
171
171
  exports.TabsWithHiddenScrollButtons = TabsWithHiddenScrollButtons;
172
172
  TabsWithHiddenScrollButtons.args = {
173
173
  scrollable: true
174
174
  };
175
175
  TabsWithHiddenScrollButtons.storyName = 'Tabs with hidden scroll buttons';
176
-
177
176
  const TabStates = args => /*#__PURE__*/_react.default.createElement(_index2.TabBar, args, /*#__PURE__*/_react.default.createElement(_index.Tab, {
178
177
  onClick: onClick
179
178
  }, "Default"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
@@ -184,10 +183,8 @@ const TabStates = args => /*#__PURE__*/_react.default.createElement(_index2.TabB
184
183
  }, "Disabled"), /*#__PURE__*/_react.default.createElement(_index.Tab, {
185
184
  onClick: onClick
186
185
  }, "Text overflow - This tab has a very long text and it exceeds the maximum width of 320px"));
187
-
188
186
  exports.TabStates = TabStates;
189
187
  TabStates.storyName = 'Tab states';
190
-
191
188
  const TabStatesWithIcon = args => /*#__PURE__*/_react.default.createElement(_index2.TabBar, args, /*#__PURE__*/_react.default.createElement(_index.Tab, {
192
189
  onClick: onClick,
193
190
  icon: /*#__PURE__*/_react.default.createElement(AttachFile, null)
@@ -202,12 +199,9 @@ const TabStatesWithIcon = args => /*#__PURE__*/_react.default.createElement(_ind
202
199
  onClick: onClick,
203
200
  icon: /*#__PURE__*/_react.default.createElement(AttachFile, null)
204
201
  }, "Text overflow - This tab has a very long text and it exceeds the maximum width of 320px"));
205
-
206
202
  exports.TabStatesWithIcon = TabStatesWithIcon;
207
203
  TabStatesWithIcon.storyName = 'Tab states - with icon';
208
-
209
204
  const RTL = args => /*#__PURE__*/_react.default.createElement("div", {
210
205
  dir: "rtl"
211
206
  }, /*#__PURE__*/_react.default.createElement(TabStatesWithIcon, args));
212
-
213
207
  exports.RTL = RTL;
@@ -4,23 +4,14 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Tabs = void 0;
7
-
8
7
  var _style = _interopRequireDefault(require("styled-jsx/style"));
9
-
10
8
  var _uiConstants = require("@dhis2/ui-constants");
11
-
12
9
  var _classnames = _interopRequireDefault(require("classnames"));
13
-
14
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
15
-
16
11
  var _react = _interopRequireWildcard(require("react"));
17
-
18
- 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); }
19
-
20
- 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; }
21
-
22
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
-
12
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
13
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
24
15
  const Tabs = _ref => {
25
16
  let {
26
17
  children,
@@ -29,37 +20,29 @@ const Tabs = _ref => {
29
20
  } = _ref;
30
21
  const tabContainer = (0, _react.useRef)(null);
31
22
  const childrenRefs = (0, _react.useMemo)(() => _react.default.Children.map(children, () => /*#__PURE__*/_react.default.createRef()), [children]);
32
-
33
23
  const handleKeyDown = event => {
34
24
  const currentFocus = document.activeElement;
35
-
36
25
  if (tabContainer.current && tabContainer.current === currentFocus) {
37
26
  if (childrenRefs.length > 0 && childrenRefs[0].current) {
38
27
  childrenRefs[0].current.focus();
39
28
  }
40
-
41
29
  return;
42
30
  }
43
-
44
31
  const currentIndex = childrenRefs.findIndex(ref => ref.current === currentFocus);
45
-
46
32
  if (currentIndex === -1) {
47
33
  return;
48
34
  }
49
-
50
35
  if (event.key === 'ArrowRight') {
51
36
  event.preventDefault();
52
37
  const nextIndex = (currentIndex + 1) % childrenRefs.length;
53
38
  childrenRefs[nextIndex].current.focus();
54
39
  }
55
-
56
40
  if (event.key === 'ArrowLeft') {
57
41
  event.preventDefault();
58
42
  const prevIndex = (currentIndex - 1 + childrenRefs.length) % childrenRefs.length;
59
43
  childrenRefs[prevIndex].current.focus();
60
44
  }
61
45
  };
62
-
63
46
  return /*#__PURE__*/_react.default.createElement("div", {
64
47
  ref: tabContainer,
65
48
  "data-test": dataTest,
@@ -74,9 +57,8 @@ const Tabs = _ref => {
74
57
  return /*#__PURE__*/_react.default.cloneElement(child, {
75
58
  ref: childrenRefs[index]
76
59
  });
77
- } // Wrap non-element children e.g string in a <span>
78
-
79
-
60
+ }
61
+ // Wrap non-element children e.g string in a <span>
80
62
  return /*#__PURE__*/_react.default.createElement("span", {
81
63
  ref: childrenRefs[index],
82
64
  tabIndex: -1,
@@ -85,9 +67,8 @@ const Tabs = _ref => {
85
67
  }), /*#__PURE__*/_react.default.createElement(_style.default, {
86
68
  id: "771129571",
87
69
  dynamic: [_uiConstants.colors.grey400, _uiConstants.colors.white]
88
- }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;position:relative;overflow:hidden;box-shadow:inset 0 -1px 0 0 ".concat(_uiConstants.colors.grey400, ";-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;background:").concat(_uiConstants.colors.white, ";}")]));
70
+ }, [`div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;position:relative;overflow:hidden;box-shadow:inset 0 -1px 0 0 ${_uiConstants.colors.grey400};-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;background:${_uiConstants.colors.white};}`]));
89
71
  };
90
-
91
72
  exports.Tabs = Tabs;
92
73
  Tabs.propTypes = {
93
74
  dataTest: _propTypes.default.string.isRequired,
@@ -1,9 +1,9 @@
1
1
  import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor';
2
2
  Given('a Tab with onClick handler is rendered', () => {
3
- cy.visitStory('Tab', 'With onClick');
3
+ cy.visitStory('Tab', 'With on click');
4
4
  });
5
5
  Given('a disabled Tab with onClick handler is rendered', () => {
6
- cy.visitStory('Tab', 'With onClick and disabled');
6
+ cy.visitStory('Tab', 'With on click and disabled');
7
7
  });
8
8
  When('the Tab is clicked', () => {
9
9
  cy.get('[data-test="dhis2-uicore-tab"]').click();
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Tab } from './tab.js';
3
+ window.onClick = window.Cypress && window.Cypress.cy.stub();
4
+ export default {
5
+ title: 'Tab'
6
+ };
7
+ export const WithOnClick = () => /*#__PURE__*/React.createElement(Tab, {
8
+ onClick: window.onClick
9
+ }, "Tab A");
10
+ export const WithChildren = () => /*#__PURE__*/React.createElement(Tab, null, "I am a child");
11
+ export const WithIcon = () => /*#__PURE__*/React.createElement(Tab, {
12
+ icon: /*#__PURE__*/React.createElement("div", null, "Icon")
13
+ }, "Children");
14
+ export const WithOnClickAndDisabled = () => /*#__PURE__*/React.createElement(Tab, {
15
+ onClick: window.onClick,
16
+ disabled: true
17
+ }, "Tab A");
@@ -1,6 +1,6 @@
1
1
  import _JSXStyle from "styled-jsx/style";
2
- import { Tooltip } from '@dhis2-ui/tooltip';
3
2
  import { colors, theme } from '@dhis2/ui-constants';
3
+ import { Tooltip } from '@dhis2-ui/tooltip';
4
4
  import cx from 'classnames';
5
5
  import PropTypes from 'prop-types';
6
6
  import React, { useState, useEffect, useRef } from 'react';
@@ -15,18 +15,15 @@ export const Tab = /*#__PURE__*/React.forwardRef((_ref, ref) => {
15
15
  dataTest
16
16
  } = _ref;
17
17
  let tabRef = useRef(null);
18
-
19
18
  if (ref) {
20
19
  tabRef = ref;
21
20
  }
22
-
23
21
  const [isOverflowing, setIsOverflowing] = useState(false);
24
22
  useEffect(() => {
25
23
  const checkOverflow = () => {
26
24
  const isOverflow = tabRef.current.scrollWidth > tabRef.current.clientWidth;
27
25
  setIsOverflowing(isOverflow);
28
26
  };
29
-
30
27
  checkOverflow();
31
28
  }, []);
32
29
  return /*#__PURE__*/React.createElement("button", {
@@ -38,10 +35,10 @@ export const Tab = /*#__PURE__*/React.forwardRef((_ref, ref) => {
38
35
  "aria-disabled": disabled ? 'true' : 'false',
39
36
  onFocus: disabled ? undefined : event => onClick({}, event),
40
37
  tabIndex: -1,
41
- className: _JSXStyle.dynamic([["2433456263", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]]) + " " + "".concat(cx('tab', className, {
38
+ className: _JSXStyle.dynamic([["2433456263", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]]) + " " + `${cx('tab', className, {
42
39
  selected,
43
40
  disabled
44
- }))
41
+ })}`
45
42
  }, icon, isOverflowing ? /*#__PURE__*/React.createElement(Tooltip, {
46
43
  content: children,
47
44
  maxWidth: '100%'
@@ -54,7 +51,7 @@ export const Tab = /*#__PURE__*/React.forwardRef((_ref, ref) => {
54
51
  }, children), /*#__PURE__*/React.createElement(_JSXStyle, {
55
52
  id: "2433456263",
56
53
  dynamic: [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]
57
- }, ["button.__jsx-style-dynamic-selector{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:bottom;height:100%;padding:16px 16px 11px;background-color:transparent;outline:none;border:none;border-bottom:1px solid ".concat(colors.grey400, ";color:").concat(colors.grey600, ";font-size:14px;line-height:20px;cursor:pointer;}"), ".fixed>button.__jsx-style-dynamic-selector{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", "button.__jsx-style-dynamic-selector::after{content:' ';display:block;position:absolute;bottom:-1px;inset-inline-start:0;height:4px;width:100%;background-color:transparent;}", "span.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:fill 150ms ease-in-out;transition:fill 150ms ease-in-out;}", "button.__jsx-style-dynamic-selector:focus{outline:3px solid ".concat(theme.focus, ";outline-offset:-3px;}"), "button.__jsx-style-dynamic-selector:focus.__jsx-style-dynamic-selector:not(:focus-visible){outline:none;}", "button.__jsx-style-dynamic-selector>svg{fill:".concat(colors.grey600, ";width:14px;height:14px;margin:0 4px 0 0;}"), "button.__jsx-style-dynamic-selector:hover{color:".concat(colors.grey900, ";}"), "button.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(colors.grey600, ";height:2px;}"), "button.__jsx-style-dynamic-selector:active.__jsx-style-dynamic-selector::after{background-color:".concat(colors.grey800, ";}"), "button.selected.__jsx-style-dynamic-selector{color:".concat(theme.primary800, ";}"), "button.selected.__jsx-style-dynamic-selector::after{background-color:".concat(theme.primary700, ";-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;}"), "button.selected.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(theme.primary700, ";height:4px;}"), "button.selected.__jsx-style-dynamic-selector>svg{fill:".concat(theme.primary700, ";}"), "button.disabled.__jsx-style-dynamic-selector{color:".concat(colors.grey500, ";cursor:not-allowed;}"), "button.disabled.__jsx-style-dynamic-selector:hover,button.selected.__jsx-style-dynamic-selector:hover{background-color:transparent;}", "button.disabled.__jsx-style-dynamic-selector>svg{fill:".concat(colors.grey500, ";}")]));
54
+ }, [`button.__jsx-style-dynamic-selector{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:bottom;height:100%;padding:16px 16px 11px;background-color:transparent;outline:none;border:none;border-bottom:1px solid ${colors.grey400};color:${colors.grey600};font-size:14px;line-height:20px;cursor:pointer;}`, ".fixed>button.__jsx-style-dynamic-selector{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", "button.__jsx-style-dynamic-selector::after{content:' ';display:block;position:absolute;bottom:-1px;inset-inline-start:0;height:4px;width:100%;background-color:transparent;}", "span.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:fill 150ms ease-in-out;transition:fill 150ms ease-in-out;}", `button.__jsx-style-dynamic-selector:focus{outline:3px solid ${theme.focus};outline-offset:-3px;}`, "button.__jsx-style-dynamic-selector:focus.__jsx-style-dynamic-selector:not(:focus-visible){outline:none;}", `button.__jsx-style-dynamic-selector>svg{fill:${colors.grey600};width:14px;height:14px;margin:0 4px 0 0;}`, `button.__jsx-style-dynamic-selector:hover{color:${colors.grey900};}`, `button.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:${colors.grey600};height:2px;}`, `button.__jsx-style-dynamic-selector:active.__jsx-style-dynamic-selector::after{background-color:${colors.grey800};}`, `button.selected.__jsx-style-dynamic-selector{color:${theme.primary800};}`, `button.selected.__jsx-style-dynamic-selector::after{background-color:${theme.primary700};-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;}`, `button.selected.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:${theme.primary700};height:4px;}`, `button.selected.__jsx-style-dynamic-selector>svg{fill:${theme.primary700};}`, `button.disabled.__jsx-style-dynamic-selector{color:${colors.grey500};cursor:not-allowed;}`, "button.disabled.__jsx-style-dynamic-selector:hover,button.selected.__jsx-style-dynamic-selector:hover{background-color:transparent;}", `button.disabled.__jsx-style-dynamic-selector>svg{fill:${colors.grey500};}`]));
58
55
  });
59
56
  Tab.defaultProps = {
60
57
  dataTest: 'dhis2-uicore-tab'
@@ -65,10 +62,8 @@ Tab.propTypes = {
65
62
  dataTest: PropTypes.string,
66
63
  disabled: PropTypes.bool,
67
64
  icon: PropTypes.element,
68
-
69
65
  /** Indicates this tab is selected */
70
66
  selected: PropTypes.bool,
71
-
72
67
  /** Called with the signature `({}, event)` */
73
68
  onClick: PropTypes.func
74
69
  };
@@ -14,13 +14,11 @@ export function animatedSideScroll(scrollBox, callback) {
14
14
  });
15
15
  window.requestAnimationFrame(step);
16
16
  }
17
-
18
17
  function getEndValue(scrollBox, startValue, goBackwards) {
19
18
  const scrollDistance = scrollBox.clientWidth * SCROLL_STEP;
20
19
  const inverter = goBackwards ? -1 : 1;
21
20
  return Math.floor(startValue + scrollDistance * inverter);
22
21
  }
23
-
24
22
  function createFrameStepper(_ref) {
25
23
  let {
26
24
  scrollBox,
@@ -34,7 +32,6 @@ function createFrameStepper(_ref) {
34
32
  if (!startTimestamp) {
35
33
  startTimestamp = timestamp;
36
34
  }
37
-
38
35
  elapsedTime = timestamp - startTimestamp;
39
36
  scrollValue = easeInOutQuad({
40
37
  currentTime: elapsedTime,
@@ -42,12 +39,10 @@ function createFrameStepper(_ref) {
42
39
  startValue,
43
40
  change
44
41
  });
45
-
46
42
  if (elapsedTime >= DURATION) {
47
43
  if (scrollValue !== endValue) {
48
44
  scrollBox.scrollLeft = endValue;
49
45
  }
50
-
51
46
  callback && callback();
52
47
  } else {
53
48
  scrollBox.scrollLeft = scrollValue;
@@ -55,7 +50,6 @@ function createFrameStepper(_ref) {
55
50
  }
56
51
  };
57
52
  }
58
-
59
53
  function easeInOutQuad(_ref2) {
60
54
  let {
61
55
  currentTime,
@@ -1,11 +1,21 @@
1
1
  let horizontalScrollbarHeight;
2
2
  const className = '__vertical-scrollbar-height-test__';
3
- const styles = "\n .".concat(className, " {\n position: absolute;\n top: -9999px;\n width: 100px;\n height: 100px;\n overflow-x: scroll;\n }\n .").concat(className, "::-webkit-scrollbar {\n display: none;\n }\n");
3
+ const styles = `
4
+ .${className} {
5
+ position: absolute;
6
+ top: -9999px;
7
+ width: 100px;
8
+ height: 100px;
9
+ overflow-x: scroll;
10
+ }
11
+ .${className}::-webkit-scrollbar {
12
+ display: none;
13
+ }
14
+ `;
4
15
  export function detectHorizontalScrollbarHeight() {
5
16
  if (horizontalScrollbarHeight) {
6
17
  return horizontalScrollbarHeight;
7
18
  }
8
-
9
19
  const style = document.createElement('style');
10
20
  style.innerHTML = styles;
11
21
  const el = document.createElement('div');
@@ -1,7 +1,7 @@
1
1
  import _JSXStyle from "styled-jsx/style";
2
-
3
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4
-
2
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
4
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
5
  import { IconChevronRight16, IconChevronLeft16 } from '@dhis2/ui-icons';
6
6
  import cx from 'classnames';
7
7
  import PropTypes from 'prop-types';
@@ -9,19 +9,13 @@ import React, { Component, createRef } from 'react';
9
9
  import { animatedSideScroll } from './animated-side-scroll.js';
10
10
  import { detectHorizontalScrollbarHeight } from './detect-horizontal-scrollbar-height.js';
11
11
  import { ScrollButton } from './scroll-button.js';
12
-
13
12
  class ScrollBar extends Component {
14
13
  constructor(props) {
15
14
  super(props);
16
-
17
15
  _defineProperty(this, "scrollBox", /*#__PURE__*/createRef());
18
-
19
16
  _defineProperty(this, "scrollArea", /*#__PURE__*/createRef());
20
-
21
17
  _defineProperty(this, "horizontalScrollBarHeight", detectHorizontalScrollbarHeight());
22
-
23
18
  _defineProperty(this, "scrollBoxResizeObserver", null);
24
-
25
19
  _defineProperty(this, "calculateShouldHideButtons", () => {
26
20
  this.setState({
27
21
  hideScrollButtonsInitialized: false
@@ -38,31 +32,24 @@ class ScrollBar extends Component {
38
32
  this.setState({
39
33
  hideScrollButtons
40
34
  });
41
-
42
35
  if (!hideScrollButtons) {
43
36
  if (this.state.scrolledToStart) {
44
37
  this.scrollLeft();
45
38
  }
46
-
47
39
  if (this.state.scrolledToEnd) {
48
40
  this.scrollRight();
49
41
  }
50
42
  }
51
-
52
43
  this.setState({
53
44
  hideScrollButtonsInitialized: true
54
45
  });
55
46
  });
56
-
57
47
  _defineProperty(this, "scrollRight", () => this.scroll());
58
-
59
48
  _defineProperty(this, "scrollLeft", () => this.scroll(true));
60
-
61
49
  _defineProperty(this, "animatedScrollCallback", () => {
62
50
  this.updateScrolledToStates();
63
51
  this.attachSideScrollListener();
64
52
  });
65
-
66
53
  _defineProperty(this, "updateScrolledToStates", () => {
67
54
  const {
68
55
  scrollLeft,
@@ -73,7 +60,6 @@ class ScrollBar extends Component {
73
60
  } = this.scrollArea.current;
74
61
  const scrolledToStart = scrollLeft <= 0;
75
62
  const scrolledToEnd = scrollLeft + offsetWidth >= areaOffsetWidth;
76
-
77
63
  if (this.state.scrolledToStart !== scrolledToStart || this.state.scrolledToEnd !== scrolledToEnd) {
78
64
  this.setState({
79
65
  scrolledToStart,
@@ -81,7 +67,6 @@ class ScrollBar extends Component {
81
67
  });
82
68
  }
83
69
  });
84
-
85
70
  this.state = {
86
71
  scrolledToStart: true,
87
72
  scrolledToEnd: false,
@@ -92,18 +77,15 @@ class ScrollBar extends Component {
92
77
  };
93
78
  this.scrollBoxResizeObserver = new ResizeObserver(this.calculateShouldHideButtons);
94
79
  }
95
-
96
80
  componentDidMount() {
97
81
  this.scrollSelectedTabIntoView();
98
82
  this.attachSideScrollListener();
99
83
  this.manageShouldHideButtons();
100
84
  }
101
-
102
85
  componentWillUnmount() {
103
86
  this.removeSideScrollListener();
104
87
  this.scrollBoxResizeObserver.disconnect();
105
88
  }
106
-
107
89
  manageShouldHideButtons() {
108
90
  const {
109
91
  current: scrollBox
@@ -111,33 +93,26 @@ class ScrollBar extends Component {
111
93
  this.scrollBoxResizeObserver.observe(scrollBox);
112
94
  this.calculateShouldHideButtons();
113
95
  }
114
-
115
96
  scroll(goBackwards) {
116
97
  this.removeSideScrollListener();
117
98
  animatedSideScroll(this.scrollBox.current, this.animatedScrollCallback, goBackwards);
118
99
  }
119
-
120
100
  scrollSelectedTabIntoView() {
121
101
  const scrollBoxEl = this.scrollBox.current;
122
102
  const tab = scrollBoxEl.querySelector('.tab.selected');
123
-
124
103
  if (tab) {
125
104
  const tabEnd = tab.offsetLeft + tab.offsetWidth;
126
-
127
105
  if (tabEnd > scrollBoxEl.offsetWidth) {
128
106
  scrollBoxEl.scrollLeft = tabEnd - scrollBoxEl.offsetWidth;
129
107
  }
130
108
  }
131
109
  }
132
-
133
110
  attachSideScrollListener() {
134
111
  this.scrollBox.current.addEventListener('scroll', this.updateScrolledToStates);
135
112
  }
136
-
137
113
  removeSideScrollListener() {
138
114
  this.scrollBox.current.removeEventListener('scroll', this.updateScrolledToStates);
139
115
  }
140
-
141
116
  render() {
142
117
  const {
143
118
  scrolledToStart,
@@ -173,13 +148,11 @@ class ScrollBar extends Component {
173
148
  }, /*#__PURE__*/React.createElement(IconChevronRight16, null)), /*#__PURE__*/React.createElement(_JSXStyle, {
174
149
  id: "4174900658",
175
150
  dynamic: [-this.horizontalScrollBarHeight]
176
- }, [".scroll-box.__jsx-style-dynamic-selector{margin-bottom:".concat(-this.horizontalScrollBarHeight, "px;}")]), /*#__PURE__*/React.createElement(_JSXStyle, {
151
+ }, [`.scroll-box.__jsx-style-dynamic-selector{margin-bottom:${-this.horizontalScrollBarHeight}px;}`]), /*#__PURE__*/React.createElement(_JSXStyle, {
177
152
  id: "191575146"
178
153
  }, [".scroll-bar.jsx-191575146{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}", ".scroll-box-clipper.jsx-191575146{overflow-y:hidden;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", ".scroll-box.jsx-191575146{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;overflow-x:scroll;-webkit-overflow-scrolling:touch;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}", ".scroll-box.jsx-191575146::-webkit-scrollbar{display:none;}", ".scroll-area.jsx-191575146{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;overflow-x:hidden;}"]));
179
154
  }
180
-
181
155
  }
182
-
183
156
  ScrollBar.propTypes = {
184
157
  children: PropTypes.node.isRequired,
185
158
  dataTest: PropTypes.string.isRequired,
@@ -19,7 +19,7 @@ export const ScrollButton = _ref => {
19
19
  }, children, /*#__PURE__*/React.createElement(_JSXStyle, {
20
20
  id: "2701682090",
21
21
  dynamic: [colors.white, colors.grey400, colors.grey600, colors.grey100, colors.grey200, colors.grey500]
22
- }, [".scroll-button.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:inherit;background-color:".concat(colors.white, ";border:none;border-bottom:1px solid ").concat(colors.grey400, ";outline:none;padding:16px 16px 11px 16px;cursor:pointer;}"), ".scroll-button.hidden.__jsx-style-dynamic-selector{display:none;}", ".scroll-button.__jsx-style-dynamic-selector svg{width:20px;height:20px;fill:".concat(colors.grey600, ";-webkit-transition:opacity 150ms ease-in-out;transition:opacity 150ms ease-in-out;opacity:1;}"), ".scroll-button.__jsx-style-dynamic-selector:hover{background-color:".concat(colors.grey100, ";}"), ".scroll-button.__jsx-style-dynamic-selector:active{background-color:".concat(colors.grey200, ";}"), ".scroll-button.disabled.__jsx-style-dynamic-selector{cursor:not-allowed;}", ".scroll-button.disabled.__jsx-style-dynamic-selector:hover{background-color:transparent;}", ".scroll-button.disabled.__jsx-style-dynamic-selector svg{fill:".concat(colors.grey500, ";}")]));
22
+ }, [`.scroll-button.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:inherit;background-color:${colors.white};border:none;border-bottom:1px solid ${colors.grey400};outline:none;padding:16px 16px 11px 16px;cursor:pointer;}`, ".scroll-button.hidden.__jsx-style-dynamic-selector{display:none;}", `.scroll-button.__jsx-style-dynamic-selector svg{width:20px;height:20px;fill:${colors.grey600};-webkit-transition:opacity 150ms ease-in-out;transition:opacity 150ms ease-in-out;opacity:1;}`, `.scroll-button.__jsx-style-dynamic-selector:hover{background-color:${colors.grey100};}`, `.scroll-button.__jsx-style-dynamic-selector:active{background-color:${colors.grey200};}`, ".scroll-button.disabled.__jsx-style-dynamic-selector{cursor:not-allowed;}", ".scroll-button.disabled.__jsx-style-dynamic-selector:hover{background-color:transparent;}", `.scroll-button.disabled.__jsx-style-dynamic-selector svg{fill:${colors.grey500};}`]));
23
23
  };
24
24
  ScrollButton.displayName = 'ScrollButton';
25
25
  ScrollButton.propTypes = {
@@ -1,18 +1,21 @@
1
- import { storiesOf } from '@storybook/react';
2
1
  import React from 'react';
3
2
  import { Tab } from '../tab/index.js';
4
3
  import { TabBar } from './index.js';
5
- storiesOf('TabBar', module).add('With children', () => /*#__PURE__*/React.createElement(TabBar, null, "I am a child")).add('Scrollable with children', () => /*#__PURE__*/React.createElement(TabBar, {
4
+ export default {
5
+ title: 'TabBar'
6
+ };
7
+ export const WithChildren = () => /*#__PURE__*/React.createElement(TabBar, null, "I am a child");
8
+ export const ScrollableWithChildren = () => /*#__PURE__*/React.createElement(TabBar, {
6
9
  scrollable: true
7
- }, "I am a child")).add('Scrollable with some tabs', () => {
10
+ }, "I am a child");
11
+ export const ScrollableWithSomeTabs = () => {
8
12
  const TabStaticWidth = () => /*#__PURE__*/React.createElement(Tab, null, /*#__PURE__*/React.createElement("div", {
9
13
  style: {
10
14
  width: 100,
11
15
  border: '1px solid black'
12
16
  }
13
17
  }, "Foo"));
14
-
15
18
  return /*#__PURE__*/React.createElement(TabBar, {
16
19
  scrollable: true
17
20
  }, /*#__PURE__*/React.createElement(TabStaticWidth, null), /*#__PURE__*/React.createElement(TabStaticWidth, null), /*#__PURE__*/React.createElement(TabStaticWidth, null));
18
- });
21
+ };
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { ScrollBar } from './scroll-bar.js';
4
4
  import { Tabs } from './tabs.js';
5
-
6
5
  const TabBar = _ref => {
7
6
  let {
8
7
  fixed,
@@ -11,28 +10,25 @@ const TabBar = _ref => {
11
10
  scrollable,
12
11
  dataTest
13
12
  } = _ref;
14
-
15
13
  if (scrollable) {
16
14
  return /*#__PURE__*/React.createElement("div", {
17
15
  className: className,
18
16
  "data-test": dataTest
19
17
  }, /*#__PURE__*/React.createElement(ScrollBar, {
20
- dataTest: "".concat(dataTest, "-scrollbar")
18
+ dataTest: `${dataTest}-scrollbar`
21
19
  }, /*#__PURE__*/React.createElement(Tabs, {
22
20
  fixed: fixed,
23
- dataTest: "".concat(dataTest, "-tabs")
21
+ dataTest: `${dataTest}-tabs`
24
22
  }, children)));
25
23
  }
26
-
27
24
  return /*#__PURE__*/React.createElement("div", {
28
25
  className: className,
29
26
  "data-test": dataTest
30
27
  }, /*#__PURE__*/React.createElement(Tabs, {
31
28
  fixed: fixed,
32
- dataTest: "".concat(dataTest, "-tabs")
29
+ dataTest: `${dataTest}-tabs`
33
30
  }, children));
34
31
  };
35
-
36
32
  TabBar.defaultProps = {
37
33
  dataTest: 'dhis2-uicore-tabbar'
38
34
  };
@@ -40,10 +36,8 @@ TabBar.propTypes = {
40
36
  children: PropTypes.node,
41
37
  className: PropTypes.string,
42
38
  dataTest: PropTypes.string,
43
-
44
39
  /** Fixed tabs fill the width of their container. If false (i.e. fluid), tabs take up an amount of space defined by the tab name. Fluid tabs should be used most of the time. */
45
40
  fixed: PropTypes.bool,
46
-
47
41
  /** Enables horizontal scrolling for many tabs that don't fit the width of the container */
48
42
  scrollable: PropTypes.bool
49
43
  };