painless-ui
Version:
296 lines (295 loc) • 13.7 kB
JavaScript
import React from 'react';
import './TabGroup.css';
import Tab from '../Tab/Tab';
class TabGroup extends React.Component {
constructor(props) {
super(props);
this.state = {
activeIndex: this.props.defaultActive !== undefined ? this.props.defaultActive : 0,
visibleStatus: false,
prevLiIndex: -1,
lastLiIndex: 0,
isScrollable: false,
visibleWidth: '1000',
isNext: false,
ul: {
width: '100%',
left: 0,
margin: this.props.centerAlign === true ? '0 auto' : ''
},
activeBar: {
width: 0,
left: 0
}
};
this.touchObj = {
initialClientX: 0,
finalClientX: 0
};
this.calculateDimonsions = () => {
if (this.containerRef.current) {
const tabContainer = this.containerRef.current.querySelector('.ui-tabs');
const visibleWidth = tabContainer.getBoundingClientRect().width;
let isScrollable = false;
let isNext = false;
if (visibleWidth < this.state.ul.width) {
isScrollable = true;
isNext = true;
}
this.setState({
visibleWidth,
isScrollable,
isNext
}, () => {
this.setNext();
this.setPrev();
this.setActiveTab(this.state.activeIndex);
});
}
};
this.setPrev = () => {
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
const left = this.state.ul.left;
let totalWidth = 0;
let i = 0;
let prevLiIndex = 0;
for (let li of ul.children) {
if (totalWidth < (-left)) {
prevLiIndex = i;
}
totalWidth += li.getBoundingClientRect().width;
i++;
}
this.setState({
prevLiIndex
});
};
this.setNext = () => {
const tabContainer = this.containerRef.current.querySelector('.ui-tabs');
const visibleWidth = tabContainer.getBoundingClientRect().width;
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
const left = this.state.ul.left;
let totalWidth = 0;
let isLastClass = false;
let i = 0;
for (let li of ul.children) {
totalWidth += li.getBoundingClientRect().width;
if (!isLastClass && totalWidth > (visibleWidth - left)) {
isLastClass = true;
//check its last
if (ul.children.length - 1 === i && i === this.state.lastLiIndex - 1) {
i = i + 1;
}
this.setState({
lastLiIndex: i
});
}
i++;
}
let isNext = true;
if (Math.round(-left) === parseInt(this.state.ul.width) - visibleWidth) {
isNext = false;
}
this.setState({
isNext
});
};
this.moveRight = () => {
if (this.state.visibleWidth < this.state.ul.width) {
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
let totalWidth = 0;
for (let li of ul.children) {
totalWidth += li.getBoundingClientRect().width;
if (li.classList.contains('last')) {
break;
}
}
this.setState({
ul: {
width: this.state.ul.width,
left: parseInt(this.state.visibleWidth) - totalWidth,
margin: this.props.centerAlign === true ? '0 auto' : ''
}
}, () => {
this.setNext();
this.setPrev();
this.setActiveTab(this.state.activeIndex);
});
}
};
this.moveLeft = () => {
if (this.state.visibleWidth < this.state.ul.width) {
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
const prevLi = ul.querySelector('li.prev');
let totalWidth = 0;
if (prevLi !== null) {
for (let li of ul.children) {
if (li.classList.contains('prev')) {
break;
}
totalWidth += li.getBoundingClientRect().width;
}
this.setState({
ul: {
width: this.state.ul.width,
left: -totalWidth,
margin: this.props.centerAlign === true ? '0 auto' : ''
}
}, () => {
this.setNext();
this.setPrev();
this.setActiveTab(this.state.activeIndex);
});
}
}
};
this.setActiveTab = (index) => {
this.setState({
activeIndex: index
});
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
let width = 0;
let left = 0;
let i = 0;
if (this.props.centerAlign === true && this.state.ul.width !== '100%') {
const center = this.containerRef.current.clientWidth / 2;
const ulCenter = parseInt(this.state.ul.width) / 2;
left = center - ulCenter;
}
for (let li of ul.children) {
if (i === index) {
width = li.getBoundingClientRect().width;
break;
}
left += li.getBoundingClientRect().width;
i++;
}
if (this.state.isScrollable === true) {
left -= (-this.state.ul.left);
}
this.setState({
activeBar: {
left: ((left / this.containerRef.current.clientWidth) * 100) + "%",
width
}
});
if (this.props.onClick && typeof this.props.onClick === 'function') {
this.props.onClick(index);
}
};
this.handleTouchStart = (event) => {
if (this.props.navType && this.props.navType === "swipe")
this.touchObj.initialClientX = event.nativeEvent.touches[0].clientX;
};
this.handleTouchMove = (event) => {
if (this.props.navType && this.props.navType === "swipe")
this.touchObj.finalClientX = event.nativeEvent.touches[0].clientX;
};
this.handleTouchEnd = () => {
if (this.props.navType && this.props.navType === "swipe") {
if (this.touchObj.finalClientX < this.touchObj.initialClientX) {
this.moveRight();
}
else {
this.moveLeft();
}
this.touchObj = {
initialClientX: 0,
finalClientX: 0
};
}
};
React.Children.forEach(this.props.children, function (child) {
if (child === null || child.type !== Tab) {
throw new Error('`Tabgroup` children should be of type `Tab`.');
}
});
this.containerRef = React.createRef();
}
setWidth() {
let totalWidth = 0;
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
for (let li of ul.children) {
totalWidth += li.getBoundingClientRect().width;
}
const tabContainer = this.containerRef.current.querySelector('.ui-tabs');
const visibleWidth = tabContainer.getBoundingClientRect().width;
this.setState({
ul: {
width: totalWidth,
left: this.state.isScrollable === false ? 0 : parseInt(visibleWidth) - totalWidth,
margin: this.props.centerAlign === true ? '0 auto' : ''
}
}, () => {
this.calculateDimonsions();
setTimeout(() => {
this.setState({
visibleStatus: true,
ul: {
width: totalWidth,
left: this.state.isScrollable === false ? 0 : parseInt(visibleWidth) - totalWidth,
margin: this.props.centerAlign === true ? '0 auto' : ''
}
});
}, 0);
});
this.setActiveTab(this.state.activeIndex);
}
componentDidMount() {
this.setWidth();
window.addEventListener('resize', () => {
this.setWidth();
});
}
componentDidUpdate(oldProps) {
if (this.props.children !== oldProps.children) {
let totalWidth = 0;
const ul = this.containerRef.current.querySelector('.nav.nav-tabs');
for (let li of ul.children) {
totalWidth += li.getBoundingClientRect().width;
}
this.setState({
ul: {
width: totalWidth,
left: this.state.ul.left,
margin: this.props.centerAlign === true ? '0 auto' : ''
}
}, () => {
this.calculateDimonsions();
setTimeout(() => {
this.setState({
visibleStatus: true
});
}, 1000);
});
// this.setActiveTab(0);
}
}
render() {
return (React.createElement("div", { style: { ...{ width: this.props.width || '100%' },
...this.props.style || {}
}, className: "ui-tabgroup " + (this.state.visibleStatus === false ? 'v-hidden' : 'show'), ref: this.containerRef, id: this.props.id, onTouchStart: this.handleTouchStart, onTouchMove: this.handleTouchMove, onTouchEnd: this.handleTouchEnd },
React.createElement("div", { className: "ui-tabs ui-tabs-bg ui-tabs-scroll", style: {
backgroundColor: this.props.bgColor || '#4285f4'
} },
this.props.navType && this.props.navType !== "swipe" ?
React.createElement("div", { onClick: this.moveLeft, className: "ui-tabs-scroll-left", style: { display: (this.state.isScrollable && this.state.ul.left !== 0) ? 'block' : 'none' } },
React.createElement("svg", { focusable: "false", "data-prefix": "fas", "data-icon": "chevron-left", role: "img", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 320 512", className: "ui-tab-icon" },
React.createElement("path", { fill: "currentColor", d: "M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z", className: "" }))) : React.createElement(React.Fragment, null),
React.createElement("div", { className: 'ui-tabs-scroll-container' },
React.createElement("div", { className: "ui-tab-active-bar", style: { ...this.state.activeBar, ...{ backgroundColor: this.props.activeColor || '#ffc107' } } }),
React.createElement("ul", { className: "nav nav-tabs", role: "tablist", style: this.state.ul }, React.Children.map(this.props.children, (tab, i) => {
return (React.createElement("li", { role: "tab", onClick: () => this.setActiveTab(i), className: (this.state.activeIndex === i ? ' active ' : '') +
(this.state.lastLiIndex === i ? 'last' : (this.state.prevLiIndex === i ? 'prev' : '')) },
React.createElement("a", { style: {
color: this.props.color || 'white'
}, onClick: (e) => e.preventDefault(), href: "#", className: this.state.activeIndex === i ? 'active' : '' }, tab)));
}))),
this.props.navType && this.props.navType !== "swipe" ?
React.createElement("div", { onClick: this.moveRight, className: "ui-tabs-scroll-right", style: { display: (this.state.isScrollable && this.state.isNext ? 'block' : 'none') } },
React.createElement("svg", { focusable: "false", "data-prefix": "fas", "data-icon": "chevron-right", role: "img", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 320 512", className: "ui-tab-icon" },
React.createElement("path", { fill: "currentColor", d: "M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z", className: "" })))
: React.createElement(React.Fragment, null))));
}
}
export default TabGroup;