11import PropTypes from 'prop-types' ;
22import React from 'react' ;
33
4- import List from '../List' ;
54import Button from '../../Action/Button' ;
5+ import HashManager from '../../General/HashManager' ;
6+ import List from '../List' ;
67import iconNames from '../../../constants/iconNames' ;
8+ import { addClassName } from '../../../utils/common' ;
9+
710import styles from './styles.scss' ;
811
912const propTypes = {
13+ active : PropTypes . string ,
14+ children : PropTypes . node ,
1015 className : PropTypes . string ,
16+ itemClassName : PropTypes . string ,
17+ defaultHash : PropTypes . string ,
18+ onClick : PropTypes . func ,
19+ replaceHistory : PropTypes . bool ,
1120 tabs : PropTypes . shape ( {
1221 dummy : PropTypes . string ,
1322 } ) ,
14- onClick : PropTypes . func ,
15- active : PropTypes . string ,
23+ useHash : PropTypes . bool ,
24+ modifier : PropTypes . func ,
1625} ;
1726
1827const defaultProps = {
1928 active : undefined ,
29+ children : null ,
2030 className : '' ,
21- tabs : [ ] ,
31+ itemClassName : '' ,
32+ defaultHash : undefined ,
2233 onClick : ( ) => { } ,
34+ replaceHistory : false ,
35+ tabs : { } ,
36+ useHash : false ,
37+ modifier : undefined ,
2338} ;
2439
25- export default class ScrollTabs extends React . Component {
40+
41+ export default class FixedTabs extends React . Component {
2642 static propTypes = propTypes ;
2743 static defaultProps = defaultProps ;
2844
45+ constructor ( props ) {
46+ super ( props ) ;
47+ this . state = {
48+ hash : undefined ,
49+ } ;
50+ this . tabsContainerRef = React . createRef ( ) ;
51+ this . mainContainerRef = React . createRef ( ) ;
52+ }
53+
54+ componentDidMount ( ) {
55+ const { current : tabsContainer } = this . tabsContainerRef ;
56+ const { current : mainContainer } = this . mainContainerRef ;
57+
58+ if ( tabsContainer . scrollWidth > tabsContainer . clientWidth ) {
59+ addClassName ( mainContainer , styles . scroll ) ;
60+ }
61+ }
62+
2963 getClassName = ( ) => {
3064 const { className } = this . props ;
3165
3266 const classNames = [
3367 className ,
3468 'scroll-tabs' ,
69+ styles . scrollTabs ,
3570 ] ;
3671
3772 return classNames . join ( ' ' ) ;
3873 }
3974
4075 getTabClassName = ( isActive ) => {
76+ const { itemClassName } = this . props ;
77+
4178 const classNames = [
79+ itemClassName ,
4280 styles . tab ,
43- 'scroll -tab' ,
81+ 'fixed -tab' ,
4482 ] ;
4583
4684 if ( isActive ) {
@@ -51,69 +89,129 @@ export default class ScrollTabs extends React.Component {
5189 return classNames . join ( ' ' ) ;
5290 }
5391
54- handleTabClick = ( key ) => {
55- const { onClick } = this . props ;
92+ handleHashChange = ( hash ) => {
93+ this . setState ( { hash } ) ;
94+ }
95+
96+ handleTabClick = ( key , e ) => {
97+ const {
98+ onClick,
99+ useHash,
100+ replaceHistory,
101+ } = this . props ;
102+
103+ if ( useHash && replaceHistory ) {
104+ window . location . replace ( `#/${ key } ` ) ;
105+ e . preventDefault ( ) ;
106+ }
107+
56108 onClick ( key ) ;
57109 }
58110
59- renderTab = ( key , data ) => {
111+ handleLeftButtonClick = ( ) => {
112+ const { current : tabsContainer } = this . tabsContainerRef ;
113+
114+ tabsContainer . scrollLeft -= 48 ;
115+ }
116+
117+ handleRightButtonClick = ( ) => {
118+ const { current : tabsContainer } = this . tabsContainerRef ;
119+
120+ tabsContainer . scrollLeft += 48 ;
121+ }
122+
123+ renderTab = ( _ , data ) => {
60124 const {
61125 active,
62126 tabs,
127+ useHash,
128+ modifier,
63129 } = this . props ;
64- const isActive = data === active ;
130+
131+ if ( ! tabs [ data ] ) {
132+ return null ;
133+ }
134+
135+ const onClick = ( e ) => { this . handleTabClick ( data , e ) ; } ;
136+ const content = modifier ? modifier ( data ) : tabs [ data ] ;
137+
138+ if ( ! useHash ) {
139+ const isActive = data === active ;
140+ const className = this . getTabClassName ( isActive ) ;
141+
142+ return (
143+ < button
144+ onClick = { onClick }
145+ className = { className }
146+ key = { data }
147+ type = "button"
148+ >
149+ { content }
150+ </ button >
151+ ) ;
152+ }
153+
154+ const { hash } = this . state ;
155+
156+ const isActive = hash === data ;
65157 const className = this . getTabClassName ( isActive ) ;
66- const onClick = ( ) => { this . handleTabClick ( data ) ; } ;
67158
68159 return (
69- < button
160+ < a
161+ onClick = { onClick }
162+ href = { `#/${ data } ` }
70163 className = { className }
71164 key = { data }
72- onClick = { onClick }
73- type = "button"
74165 >
75- { tabs [ data ] }
76- </ button >
166+ { content }
167+ </ a >
77168 ) ;
78169 }
79170
80171 render ( ) {
81172 const {
82173 tabs,
174+ useHash,
175+ defaultHash,
83176 } = this . props ;
84177
178+ // FIXME: generate tabList when tabs change
85179 const tabList = Object . keys ( tabs ) ;
86- const leftButtonClassNames = [
87- styles . scrollButton ,
88- styles . scrollButtonLeft ,
89- ] ;
90- const rightButtonClassNames = [
91- styles . scrollButton ,
92- styles . scrollButtonRight ,
93- ] ;
94-
180+ const className = this . getClassName ( ) ;
95181 return (
96- < div className = { styles . scrollTabs } >
182+ < div
183+ ref = { this . mainContainerRef }
184+ className = { className }
185+ >
186+ < HashManager
187+ tabs = { tabs }
188+ useHash = { useHash }
189+ defaultHash = { defaultHash }
190+ onHashChange = { this . handleHashChange }
191+ />
97192 < Button
98- className = { leftButtonClassNames . join ( ' ' ) }
99- transparent
100- smallVerticalPadding
101- smallHorizontalPadding
102- onClick = { this . handleScrollLeftButtonClick }
103193 iconName = { iconNames . chevronLeft }
194+ transparent
195+ className = { styles . leftButton }
196+ onClick = { this . handleLeftButtonClick }
104197 />
105- < List
106- data = { tabList }
107- modifier = { this . renderTab }
108- />
109- < div className = { styles . void } />
198+ < div
199+ ref = { this . tabsContainerRef }
200+ className = { styles . tabsContainer }
201+ >
202+ < List
203+ data = { tabList }
204+ modifier = { this . renderTab }
205+ />
206+ < div className = { styles . blank } >
207+ { this . props . children }
208+ </ div >
209+ </ div >
110210 < Button
111- className = { rightButtonClassNames . join ( ' ' ) }
112- transparent
113- smallVerticalPadding
114- smallHorizontalPadding
115- onClick = { this . handleScrollLeftButtonClick }
116211 iconName = { iconNames . chevronRight }
212+ transparent
213+ className = { styles . rightButton }
214+ onClick = { this . handleRightButtonClick }
117215 />
118216 </ div >
119217 ) ;
0 commit comments