UNPKG

16.9 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.ActionButtonStyle = exports.TabListStyle = undefined;
7
8var _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; };
9
10var _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; }; }();
11
12var _templateObject = _taggedTemplateLiteral(['\n background-color: white;\n text-align: left;\n position: relative;\n white-space: nowrap;\n overflow: hidden;\n width: auto;\n padding: ', ';\n'], ['\n background-color: white;\n text-align: left;\n position: relative;\n white-space: nowrap;\n overflow: hidden;\n width: auto;\n padding: ', ';\n']),
13 _templateObject2 = _taggedTemplateLiteral(['\n overflow: hidden;\n'], ['\n overflow: hidden;\n']),
14 _templateObject3 = _taggedTemplateLiteral(['\n padding-left: 0;\n position: relative;\n margin: 0;\n list-style: none;\n display: inline-block;\n transition: transform .3s cubic-bezier(.42, 0, .58, 1);\n'], ['\n padding-left: 0;\n position: relative;\n margin: 0;\n list-style: none;\n display: inline-block;\n transition: transform .3s cubic-bezier(.42, 0, .58, 1);\n']),
15 _templateObject4 = _taggedTemplateLiteral(['\n height: 100%;\n width ', 'px;\n text-align: center;\n border: 1px solid #d9d9d9;\n border-bottom: 0;\n border-radius: 4px 4px 0 0;\n background: #f9f9f9;\n > svg {\n padding-top: 11px;\n }\n'], ['\n height: 100%;\n width ', 'px;\n text-align: center;\n border: 1px solid #d9d9d9;\n border-bottom: 0;\n border-radius: 4px 4px 0 0;\n background: #f9f9f9;\n > svg {\n padding-top: 11px;\n }\n']),
16 _templateObject5 = _taggedTemplateLiteral(['\n display: inline-block;\n filter: none;\n position: absolute;\n ', ';\n &:hover {\n cursor: pointer;\n }\n'], ['\n display: inline-block;\n filter: none;\n position: absolute;\n ', ';\n &:hover {\n cursor: pointer;\n }\n']),
17 _templateObject6 = _taggedTemplateLiteral(['\n display: inline-block;\n filter: none;\n position: absolute;\n left: 0;\n &:hover {\n cursor: pointer;\n }\n'], ['\n display: inline-block;\n filter: none;\n position: absolute;\n left: 0;\n &:hover {\n cursor: pointer;\n }\n']);
18
19var _react = require('react');
20
21var React = _interopRequireWildcard(_react);
22
23var _styledComponents = require('styled-components');
24
25var _styledComponents2 = _interopRequireDefault(_styledComponents);
26
27var _invariant = require('invariant');
28
29var _invariant2 = _interopRequireDefault(_invariant);
30
31var _IconSvg = require('./IconSvg');
32
33var _isType = require('./utils/isType');
34
35var _TabModal = require('./TabModal');
36
37var _TabModal2 = _interopRequireDefault(_TabModal);
38
39function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40
41function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
42
43function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
44
45function _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; }
46
47function _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; }
48
49function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
50
51var buttonWidth = 35;
52var getPadding = function getPadding(_ref) {
53 var showModalButton = _ref.showModalButton,
54 showArrowButton = _ref.showArrowButton;
55
56 var paddingLeft = 0;
57 var paddingRight = 0;
58 if (showModalButton) {
59 paddingLeft += buttonWidth;
60 }
61 if (showArrowButton) {
62 paddingLeft += buttonWidth;
63 paddingRight += buttonWidth;
64 if (showModalButton) {
65 paddingLeft += 2;
66 }
67 }
68 if (paddingLeft > 0) {
69 paddingLeft += 3;
70 }
71 if (paddingRight > 0) {
72 paddingRight += 3;
73 }
74 return '0 ' + paddingRight + 'px 0 ' + paddingLeft + 'px';
75};
76
77var TabListStyle = _styledComponents2.default.div(_templateObject, function (props) {
78 return getPadding(props);
79});
80
81var ListInner = _styledComponents2.default.div(_templateObject2);
82
83var ListScroll = _styledComponents2.default.ul(_templateObject3);
84
85var ActionButtonStyle = _styledComponents2.default.div(_templateObject4, buttonWidth);
86
87var makeScrollButton = function makeScrollButton(ActionButton) {
88 return (0, _styledComponents2.default)(ActionButton)(_templateObject5, function (props) {
89 return props.left ? props.showModalButton ? 'left: ' + (buttonWidth + 2) + 'px' : 'left: 0' : 'right: 0';
90 });
91};
92
93var makeFoldButton = function makeFoldButton(ActionButton) {
94 return (0, _styledComponents2.default)(ActionButton)(_templateObject6);
95};
96
97var TabListComponent = function (_React$Component) {
98 _inherits(TabListComponent, _React$Component);
99
100 function TabListComponent(props) {
101 _classCallCheck(this, TabListComponent);
102
103 var _this = _possibleConstructorReturn(this, (TabListComponent.__proto__ || Object.getPrototypeOf(TabListComponent)).call(this, props));
104
105 _this.handleScroll = _this.handleScroll.bind(_this);
106 _this.toggleModal = _this.toggleModal.bind(_this);
107 _this.renderTabs = _this.renderTabs.bind(_this);
108 _this.renderArrowButton = _this.renderArrowButton.bind(_this);
109 _this.isShowModalButton = _this.isShowModalButton.bind(_this);
110 _this.isShowArrowButton = _this.isShowArrowButton.bind(_this);
111 _this.scrollPosition = 0;
112 _this.tabRefs = [];
113 _this.state = {
114 modalIsOpen: false,
115 showArrowButton: false,
116 showModalButton: false
117 };
118 return _this;
119 }
120
121 _createClass(TabListComponent, [{
122 key: 'componentDidMount',
123 value: function componentDidMount() {
124 this.isShowArrowButton();
125 this.isShowModalButton();
126 if (this.props.activeIndex > 0) this.scrollToIndex(this.props.activeIndex, 'left');
127 }
128 }, {
129 key: 'componentDidUpdate',
130 value: function componentDidUpdate(prevProps, prevState) {
131 if (prevProps.children.length !== this.props.children.length) {
132 this.isShowArrowButton();
133 this.isShowModalButton();
134 }
135
136 if (prevProps.activeIndex !== this.props.activeIndex) {
137 //if we scroll to the last tab, alignment is set to the right side of the tab
138 var rectSide = this.props.activeIndex === this.props.children.length - 1 ? 'right' : 'left';
139 this.scrollToIndex(this.props.activeIndex, rectSide);
140 }
141 // if prev state show arrow button, and current state doesn't show
142 // need to reset the scroll position, or some tabs will be hided by container.
143 if (prevState.showArrowButton && !this.state.showArrowButton) {
144 this.scrollToZero();
145 }
146
147 if (prevProps.showModalButton !== this.props.showModalButton) {
148 this.isShowModalButton();
149 }
150
151 if (prevProps.showArrowButton !== this.props.showArrowButton) {
152 this.isShowArrowButton();
153 }
154 }
155 }, {
156 key: 'getTabNode',
157 value: function getTabNode(tab) {
158 if (tab.__INTERNAL_NODE) {
159 // normal tab
160 return tab.__INTERNAL_NODE;
161 } else if (tab.__DRAG_TAB_INTERNAL_NODE) {
162 // drag tab
163 return tab.__DRAG_TAB_INTERNAL_NODE.node;
164 }
165 }
166 }, {
167 key: 'unifyScrollMax',
168 value: function unifyScrollMax(width) {
169 return parseFloat(width / 3 * 2);
170 }
171 }, {
172 key: 'handleScroll',
173 value: function handleScroll(direction) {
174 var leftMove = 0;
175 var containerOffset = this.listContainer.getBoundingClientRect();
176 var containerWidth = this.listContainer.offsetWidth;
177 var tabFirstOffset = this.getTabNode(this.tabRefs[0]).getBoundingClientRect();
178 var tabLastOffset = this.getTabNode(this.tabRefs[this.tabRefs.length - 1]).getBoundingClientRect();
179
180 if (direction === 'right') {
181 leftMove = tabLastOffset.right - containerOffset.right;
182 if (leftMove > containerWidth) {
183 leftMove = this.unifyScrollMax(containerWidth);
184 }
185 } else if (direction === 'left') {
186 leftMove = tabFirstOffset.left - containerOffset.left;
187 if (-leftMove > containerWidth) {
188 leftMove = -this.unifyScrollMax(containerWidth);
189 }
190 }
191 this.scrollPosition += leftMove;
192 if (this.scrollPosition < 0) {
193 this.scrollPosition = 0;
194 }
195
196 this.listScroll.style.transform = 'translate3d(-' + this.scrollPosition + 'px, 0, 0)';
197 }
198
199 // $FlowFixMe
200
201 }, {
202 key: 'scrollToIndex',
203 value: function scrollToIndex(index, rectSide) {
204 var tabOffset = this.getTabNode(this.tabRefs[index]).getBoundingClientRect();
205 var containerOffset = this.listContainer.getBoundingClientRect();
206 // Cancel scrolling if the tab is visible
207 if (tabOffset.right < containerOffset.right && tabOffset.left > containerOffset.left) return;
208 var leftMove = tabOffset[rectSide] - containerOffset[rectSide];
209 this.scrollPosition += leftMove;
210 if (this.scrollPosition < 0) {
211 this.scrollPosition = 0;
212 }
213 this.listScroll.style.transform = 'translate3d(-' + this.scrollPosition + 'px, 0, 0)';
214 }
215 }, {
216 key: 'scrollToZero',
217 value: function scrollToZero() {
218 this.listScroll.style.transform = 'translate3d(0, 0, 0)';
219 }
220 }, {
221 key: 'toggleModal',
222 value: function toggleModal(open) {
223 var _this2 = this;
224
225 this.setState({ modalIsOpen: open }, function () {
226 if (!open) {
227 // $FlowFixMe
228 _this2.scrollToIndex(_this2.props.activeIndex, 'right');
229 }
230 });
231 }
232 }, {
233 key: 'isShowModalButton',
234 value: function isShowModalButton() {
235 var showModalButton = this.props.showModalButton;
236
237 if ((0, _isType.isNumber)(showModalButton)) {
238 // $FlowFixMe, weired. currently set showModalButton as number | bool, but don't know why flow only can recognize it as bool
239 showModalButton = this.props.children.length >= showModalButton;
240 }
241 this.setState({ showModalButton: showModalButton });
242 }
243 }, {
244 key: 'isShowArrowButton',
245 value: function isShowArrowButton() {
246 var showArrowButton = this.props.showArrowButton;
247
248 if (showArrowButton === 'auto') {
249 var tabWidth = 0;
250 var containerWidth = this.listContainer.offsetWidth;
251 showArrowButton = false;
252 for (var index = 0; index < this.tabRefs.length; index++) {
253 var tab = this.getTabNode(this.tabRefs[index]);
254 tabWidth += tab.offsetWidth;
255 if (tabWidth >= containerWidth) {
256 showArrowButton = true;
257 break;
258 }
259 }
260 }
261 // $FlowFixMe: flow will show 'auto' is not bool, but with this logic, showArrowButton will never be 'auto'
262 this.setState({ showArrowButton: showArrowButton });
263 }
264 }, {
265 key: 'renderTabs',
266 value: function renderTabs() {
267 var _this3 = this;
268
269 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
270 var isModal = arguments[1];
271 var _props = this.props,
272 children = _props.children,
273 activeIndex = _props.activeIndex,
274 handleTabChange = _props.handleTabChange,
275 handleEdit = _props.handleEdit,
276 customStyle = _props.customStyle;
277
278 var props = {
279 handleTabChange: handleTabChange,
280 handleEdit: handleEdit,
281 //$FlowFixMe
282 CustomTabStyle: customStyle.Tab
283 };
284 if (!isModal) {
285 this.tabRefs = [];
286 }
287 return React.Children.map(children, function (child, index) {
288 return React.cloneElement(child, _extends({
289 key: index,
290 active: index === activeIndex,
291 index: index,
292 tabIndex: index,
293 ref: function ref(node) {
294 if (!isModal && node) {
295 _this3.tabRefs.push(node);
296 }
297 }
298 }, props, options));
299 });
300 }
301 }, {
302 key: 'renderArrowButton',
303 value: function renderArrowButton(ScrollButton) {
304 var _this4 = this;
305
306 var showArrowButton = this.state.showArrowButton;
307
308 if (showArrowButton) {
309 return React.createElement(
310 'div',
311 null,
312 React.createElement(
313 ScrollButton,
314 { left: true,
315 onClick: function onClick() {
316 _this4.handleScroll('left');
317 },
318 ref: function ref(node) {
319 return _this4.leftArrowNode = node;
320 },
321 showModalButton: this.state.showModalButton },
322 React.createElement(_IconSvg.LeftIcon, null)
323 ),
324 React.createElement(
325 ScrollButton,
326 { onClick: function onClick() {
327 _this4.handleScroll('right');
328 },
329 ref: function ref(node) {
330 return _this4.rightArrowNode = node;
331 } },
332 React.createElement(_IconSvg.RightIcon, null)
333 )
334 );
335 }
336 return null;
337 }
338 }, {
339 key: 'render',
340 value: function render() {
341 var _this5 = this;
342
343 var _props2 = this.props,
344 customStyle = _props2.customStyle,
345 activeIndex = _props2.activeIndex,
346 handleTabChange = _props2.handleTabChange,
347 handleTabSequence = _props2.handleTabSequence,
348 ExtraButton = _props2.ExtraButton;
349 var modalIsOpen = this.state.modalIsOpen;
350
351 var TabList = customStyle.TabList || TabListStyle;
352 var ActionButton = customStyle.ActionButton || ActionButtonStyle;
353 var ScrollButton = makeScrollButton(ActionButton);
354 var FoldButton = makeFoldButton(ActionButton);
355 (0, _invariant2.default)(this.props.children, 'React-tabtab Error: You MUST pass at least one tab');
356 return React.createElement(
357 'div',
358 null,
359 ExtraButton ? ExtraButton : null,
360 React.createElement(
361 TabList,
362 { hasExtraButton: !!ExtraButton,
363 showModalButton: this.state.showModalButton,
364 showArrowButton: this.state.showArrowButton },
365 this.state.showModalButton ? React.createElement(
366 FoldButton,
367 { ref: function ref(node) {
368 return _this5.foldNode = node;
369 },
370 onClick: this.toggleModal.bind(this, true),
371 showArrowButton: this.state.showArrowButton },
372 React.createElement(_IconSvg.BulletIcon, null)
373 ) : null,
374 this.renderArrowButton(ScrollButton),
375 React.createElement(
376 ListInner,
377 { ref: function ref(node) {
378 return _this5.listContainer = node;
379 } },
380 React.createElement(
381 ListScroll,
382 { ref: function ref(node) {
383 return _this5.listScroll = node;
384 }, role: 'tablist' },
385 this.renderTabs()
386 )
387 )
388 ),
389 modalIsOpen ? React.createElement(
390 _TabModal2.default,
391 { closeModal: this.toggleModal.bind(this, false),
392 handleTabSequence: handleTabSequence,
393 handleTabChange: handleTabChange,
394 activeIndex: activeIndex },
395 this.renderTabs({ vertical: true }, true)
396 ) : null
397 );
398 }
399 }]);
400
401 return TabListComponent;
402}(React.Component);
403
404exports.default = TabListComponent;
405
406
407TabListComponent.displayName = 'TabList';
408
409exports.TabListStyle = TabListStyle;
410exports.ActionButtonStyle = ActionButtonStyle;
\No newline at end of file