UNPKG

16.6 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 ActionButton.extend(_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 ActionButton.extend(_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 }
127 }, {
128 key: 'componentDidUpdate',
129 value: function componentDidUpdate(prevProps, prevState) {
130 if (prevProps.children.length !== this.props.children.length) {
131 this.isShowArrowButton();
132 this.isShowModalButton();
133 }
134 // if activeIndex is changed, and children is added
135 // means => add new child
136 if (prevProps.activeIndex !== this.props.activeIndex && prevProps.children.length < this.props.children.length) {
137 this.scrollToIndex(this.props.activeIndex);
138 }
139 // if prev state show arrow button, and current state doesn't show
140 // need to reset the scroll position, or some tabs will be hided by container.
141 if (prevState.showArrowButton && !this.state.showArrowButton) {
142 this.scrollToZero();
143 }
144
145 if (prevProps.showModalButton !== this.props.showModalButton) {
146 this.isShowModalButton();
147 }
148
149 if (prevProps.showArrowButton !== this.props.showArrowButton) {
150 this.isShowArrowButton();
151 }
152 }
153 }, {
154 key: 'getTabNode',
155 value: function getTabNode(tab) {
156 if (tab.__INTERNAL_NODE) {
157 // normal tab
158 return tab.__INTERNAL_NODE;
159 } else if (tab.__DRAG_TAB_INTERNAL_NODE) {
160 // drag tab
161 return tab.__DRAG_TAB_INTERNAL_NODE.node;
162 }
163 }
164 }, {
165 key: 'unifyScrollMax',
166 value: function unifyScrollMax(width) {
167 return parseFloat(width / 3 * 2);
168 }
169 }, {
170 key: 'handleScroll',
171 value: function handleScroll(direction) {
172 var leftMove = 0;
173 var containerOffset = this.listContainer.getBoundingClientRect();
174 var containerWidth = this.listContainer.offsetWidth;
175 var tabFirstOffset = this.getTabNode(this.tabRefs[0]).getBoundingClientRect();
176 var tabLastOffset = this.getTabNode(this.tabRefs[this.tabRefs.length - 1]).getBoundingClientRect();
177
178 if (direction === 'right') {
179 leftMove = tabLastOffset.right - containerOffset.right;
180 if (leftMove > containerWidth) {
181 leftMove = this.unifyScrollMax(containerWidth);
182 }
183 } else if (direction === 'left') {
184 leftMove = tabFirstOffset.left - containerOffset.left;
185 if (-leftMove > containerWidth) {
186 leftMove = -this.unifyScrollMax(containerWidth);
187 }
188 }
189 this.scrollPosition += leftMove;
190 if (this.scrollPosition < 0) {
191 this.scrollPosition = 0;
192 }
193
194 this.listScroll.style.transform = 'translate3d(-' + this.scrollPosition + 'px, 0, 0)';
195 }
196
197 // $FlowFixMe
198
199 }, {
200 key: 'scrollToIndex',
201 value: function scrollToIndex(index) {
202 var tabOffset = this.getTabNode(this.tabRefs[index]).getBoundingClientRect();
203 var containerOffset = this.listContainer.getBoundingClientRect();
204 var leftMove = tabOffset.right - containerOffset.right;
205 this.scrollPosition += leftMove;
206 if (this.scrollPosition < 0) {
207 this.scrollPosition = 0;
208 }
209 this.listScroll.style.transform = 'translate3d(-' + this.scrollPosition + 'px, 0, 0)';
210 }
211 }, {
212 key: 'scrollToZero',
213 value: function scrollToZero() {
214 this.listScroll.style.transform = 'translate3d(0, 0, 0)';
215 }
216 }, {
217 key: 'toggleModal',
218 value: function toggleModal(open) {
219 var _this2 = this;
220
221 this.setState({ modalIsOpen: open }, function () {
222 if (!open) {
223 // $FlowFixMe
224 _this2.scrollToIndex(_this2.props.activeIndex);
225 }
226 });
227 }
228 }, {
229 key: 'isShowModalButton',
230 value: function isShowModalButton() {
231 var showModalButton = this.props.showModalButton;
232
233 if ((0, _isType.isNumber)(showModalButton)) {
234 // $FlowFixMe, weired. currently set showModalButton as number | bool, but don't know why flow only can recognize it as bool
235 showModalButton = this.props.children.length >= showModalButton;
236 }
237 this.setState({ showModalButton: showModalButton });
238 }
239 }, {
240 key: 'isShowArrowButton',
241 value: function isShowArrowButton() {
242 var showArrowButton = this.props.showArrowButton;
243
244 if (showArrowButton === 'auto') {
245 var tabWidth = 0;
246 var containerWidth = this.listContainer.offsetWidth;
247 showArrowButton = false;
248 for (var index = 0; index < this.tabRefs.length; index++) {
249 var tab = this.getTabNode(this.tabRefs[index]);
250 tabWidth += tab.offsetWidth;
251 if (tabWidth >= containerWidth) {
252 showArrowButton = true;
253 break;
254 }
255 }
256 }
257 // $FlowFixMe: flow will show 'auto' is not bool, but with this logic, showArrowButton will never be 'auto'
258 this.setState({ showArrowButton: showArrowButton });
259 }
260 }, {
261 key: 'renderTabs',
262 value: function renderTabs() {
263 var _this3 = this;
264
265 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
266 var isModal = arguments[1];
267 var _props = this.props,
268 children = _props.children,
269 activeIndex = _props.activeIndex,
270 handleTabChange = _props.handleTabChange,
271 handleEdit = _props.handleEdit,
272 customStyle = _props.customStyle;
273
274 var props = {
275 handleTabChange: handleTabChange,
276 handleEdit: handleEdit,
277 //$FlowFixMe
278 CustomTabStyle: customStyle.Tab
279 };
280 if (!isModal) {
281 this.tabRefs = [];
282 }
283 return React.Children.map(children, function (child, index) {
284 return React.cloneElement(child, _extends({
285 key: index,
286 active: index === activeIndex,
287 index: index,
288 tabIndex: index,
289 ref: function ref(node) {
290 if (!isModal && node) {
291 _this3.tabRefs.push(node);
292 }
293 }
294 }, props, options));
295 });
296 }
297 }, {
298 key: 'renderArrowButton',
299 value: function renderArrowButton(ScrollButton) {
300 var _this4 = this;
301
302 var showArrowButton = this.state.showArrowButton;
303
304 if (showArrowButton) {
305 return React.createElement(
306 'div',
307 null,
308 React.createElement(
309 ScrollButton,
310 { left: true,
311 onClick: function onClick() {
312 _this4.handleScroll('left');
313 },
314 innerRef: function innerRef(node) {
315 return _this4.leftArrowNode = node;
316 },
317 showModalButton: this.state.showModalButton },
318 React.createElement(_IconSvg.LeftIcon, null)
319 ),
320 React.createElement(
321 ScrollButton,
322 { onClick: function onClick() {
323 _this4.handleScroll('right');
324 },
325 innerRef: function innerRef(node) {
326 return _this4.rightArrowNode = node;
327 } },
328 React.createElement(_IconSvg.RightIcon, null)
329 )
330 );
331 }
332 return null;
333 }
334 }, {
335 key: 'render',
336 value: function render() {
337 var _this5 = this;
338
339 var _props2 = this.props,
340 customStyle = _props2.customStyle,
341 activeIndex = _props2.activeIndex,
342 handleTabChange = _props2.handleTabChange,
343 handleTabSequence = _props2.handleTabSequence,
344 ExtraButton = _props2.ExtraButton;
345 var modalIsOpen = this.state.modalIsOpen;
346
347 var TabList = customStyle.TabList || TabListStyle;
348 var ActionButton = customStyle.ActionButton || ActionButtonStyle;
349 var ScrollButton = makeScrollButton(ActionButton);
350 var FoldButton = makeFoldButton(ActionButton);
351 (0, _invariant2.default)(this.props.children, 'React-tabtab Error: You MUST pass at least one tab');
352 return React.createElement(
353 'div',
354 null,
355 ExtraButton ? ExtraButton : null,
356 React.createElement(
357 TabList,
358 { hasExtraButton: !!ExtraButton,
359 showModalButton: this.state.showModalButton,
360 showArrowButton: this.state.showArrowButton },
361 this.state.showModalButton ? React.createElement(
362 FoldButton,
363 { innerRef: function innerRef(node) {
364 return _this5.foldNode = node;
365 },
366 onClick: this.toggleModal.bind(this, true),
367 showArrowButton: this.state.showArrowButton },
368 React.createElement(_IconSvg.BulletIcon, null)
369 ) : null,
370 this.renderArrowButton(ScrollButton),
371 React.createElement(
372 ListInner,
373 { innerRef: function innerRef(node) {
374 return _this5.listContainer = node;
375 } },
376 React.createElement(
377 ListScroll,
378 { innerRef: function innerRef(node) {
379 return _this5.listScroll = node;
380 }, role: 'tablist' },
381 this.renderTabs()
382 )
383 )
384 ),
385 modalIsOpen ? React.createElement(
386 _TabModal2.default,
387 { closeModal: this.toggleModal.bind(this, false),
388 handleTabSequence: handleTabSequence,
389 handleTabChange: handleTabChange,
390 activeIndex: activeIndex },
391 this.renderTabs({ vertical: true }, true)
392 ) : null
393 );
394 }
395 }]);
396
397 return TabListComponent;
398}(React.Component);
399
400exports.default = TabListComponent;
401
402
403TabListComponent.displayName = 'TabList';
404
405exports.TabListStyle = TabListStyle;
406exports.ActionButtonStyle = ActionButtonStyle;
\No newline at end of file