UNPKG

6.08 kBJavaScriptView Raw
1'use strict';
2
3var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4
5function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
7function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
8
9function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
10
11var React = require('react');
12var PropTypes = require('prop-types');
13var map = require('lodash.map');
14
15/**
16 * Represents tabbed navigation with a tabbed header and content.
17 */
18
19var TabNavBar = function (_React$Component) {
20 _inherits(TabNavBar, _React$Component);
21
22 /**
23 * Instantiate the tab nav bar.
24 *
25 * @param {Object} props - The props.
26 */
27 function TabNavBar(props) {
28 _classCallCheck(this, TabNavBar);
29
30 var _this = _possibleConstructorReturn(this, (TabNavBar.__proto__ || Object.getPrototypeOf(TabNavBar)).call(this, props));
31
32 _this.state = {
33 paused: false,
34 activeTabIndex: props.activeTabIndex || 0
35 };
36 return _this;
37 }
38
39 /**
40 * Handle component receiving new props.
41 *
42 * @param {Object} nextProps - The new props.
43 */
44
45
46 _createClass(TabNavBar, [{
47 key: 'componentWillReceiveProps',
48 value: function componentWillReceiveProps(nextProps) {
49 if (nextProps.activeTabIndex !== undefined) {
50 this.setState({
51 activeTabIndex: nextProps.activeTabIndex
52 });
53 }
54 }
55
56 /**
57 * Handle a tab being clicked.
58 *
59 * @param {Number} idx - The tab index.
60 * @param {Event} evt - The event.
61 */
62
63 }, {
64 key: 'onTabClicked',
65 value: function onTabClicked(idx, evt) {
66 evt.preventDefault();
67 this.setState({ activeTabIndex: idx });
68 if (this.props.onTabClicked) {
69 this.props.onTabClicked(idx, this.props.tabs[idx]);
70 }
71 }
72
73 /**
74 * Render the tabs.
75 *
76 * @returns {React.Component} The tabs.
77 */
78
79 }, {
80 key: 'renderTabs',
81 value: function renderTabs() {
82 var _this2 = this;
83
84 var listItems = map(this.props.tabs, function (tab, idx) {
85 return React.createElement(
86 'li',
87 { onClick: _this2.onTabClicked.bind(_this2, idx),
88 id: tab.replace(/ /g, '_'),
89 key: 'tab-' + idx,
90 'data-test-id': tab.toLowerCase().replace(/ /g, '-') + '-tab',
91 className: 'tab-nav-bar tab-nav-bar-tab ' + (idx === _this2.state.activeTabIndex ? 'tab-nav-bar-is-selected' : '') },
92 React.createElement(
93 'span',
94 { className: 'tab-nav-bar tab-nav-bar-link', href: '#' },
95 tab
96 )
97 );
98 });
99 return React.createElement(
100 'ul',
101 { className: 'tab-nav-bar tab-nav-bar-tabs' },
102 listItems
103 );
104 }
105
106 /**
107 * Only render the active view, mounting it and unmounting all non-active views.
108 *
109 * @return {React.Element} active view
110 */
111
112 }, {
113 key: 'renderActiveView',
114 value: function renderActiveView() {
115 return this.props.views[this.state.activeTabIndex];
116 }
117
118 /**
119 * Render all views, but only make the active view visible. This is done
120 * by wrapping all views in their own div, and setting the `hidden` class
121 * on all but the active div.
122 *
123 * @return {React.Element} div of all views
124 */
125
126 }, {
127 key: 'renderViews',
128 value: function renderViews() {
129 var _this3 = this;
130
131 var tabbedViews = map(this.props.views, function (view, idx) {
132 return React.createElement(
133 'div',
134 {
135 key: 'tab-content-' + idx,
136 'data-test-id': _this3.props.tabs[idx].toLowerCase().replace(/ /g, '-') + '-content',
137 className: idx === _this3.state.activeTabIndex ? 'tab' : 'tab hidden' },
138 view
139 );
140 });
141
142 return React.createElement(
143 'div',
144 { className: 'tab-views' },
145 tabbedViews
146 );
147 }
148
149 /**
150 * Render the component.
151 *
152 * @returns {React.Component} The component.
153 */
154
155 }, {
156 key: 'render',
157 value: function render() {
158 return React.createElement(
159 'div',
160 { className: 'tab-nav-bar tab-nav-bar-is-' + this.props.theme + '-theme' },
161 React.createElement(
162 'div',
163 { className: 'tab-nav-bar tab-nav-bar-header' },
164 this.renderTabs()
165 ),
166 this.props.mountAllViews ? this.renderViews() : this.renderActiveView()
167 );
168 }
169 }]);
170
171 return TabNavBar;
172}(React.Component);
173
174TabNavBar.propTypes = {
175 theme: PropTypes.oneOf(['dark', 'light']),
176 activeTabIndex: PropTypes.number,
177 mountAllViews: PropTypes.bool,
178 tabs: PropTypes.arrayOf(PropTypes.string).isRequired,
179 views: PropTypes.arrayOf(PropTypes.element).isRequired,
180 onTabClicked: PropTypes.func
181};
182
183TabNavBar.defaultProps = {
184 theme: 'light',
185 activeTabIndex: 0,
186 mountAllViews: true
187};
188
189TabNavBar.displayName = 'TabNavBar';
190
191module.exports = TabNavBar;
\No newline at end of file