react-draggable-tab
Advanced tools
Comparing version 0.2.0 to 0.2.1
## Change Log | ||
### Ver 0.2.1(Next release, Not released) | ||
### Ver 0.2.2(Next release, Not released) | ||
### Ver 0.2.1 | ||
* #5 [Enable to add badge / favicon like chrome](https://github.com/georgeOsdDev/react-draggable-tab/issues/5) | ||
* #6 [Add style on parent div](https://github.com/georgeOsdDev/react-draggable-tab/issues/6) | ||
* #8 [Show closed tab when it supplied again with same key](https://github.com/georgeOsdDev/react-draggable-tab/issues/8) | ||
* #9 [Keep all tab content inside Tabs](https://github.com/georgeOsdDev/react-draggable-tab/issues/9) | ||
### Ver 0.2.0 | ||
@@ -6,0 +13,0 @@ |
@@ -23,4 +23,4 @@ 'use strict'; | ||
handleClick() { | ||
this.props.onClick(); | ||
handleClick(e) { | ||
this.props.onClick(e); | ||
} | ||
@@ -27,0 +27,0 @@ |
@@ -25,2 +25,4 @@ 'use strict'; | ||
tabTitle: '', | ||
tabBeforeTitle: '', | ||
tabAfterTitle: '', | ||
tabCloseIcon: '', | ||
@@ -33,3 +35,5 @@ tabActive: '' | ||
Tab.propTypes = { | ||
beforeTitle: React.PropTypes.element, | ||
title: React.PropTypes.string.isRequired, | ||
afterTitle: React.PropTypes.element, | ||
disableClose: React.PropTypes.bool, | ||
@@ -40,3 +44,5 @@ tabClassNames: React.PropTypes.shape({ | ||
tabAfter: React.PropTypes.string, | ||
tabBeforeTitle: React.PropTypes.string, | ||
tabTitle: React.PropTypes.string, | ||
tabAfterTitle: React.PropTypes.string, | ||
tabCloseIcon: React.PropTypes.string, | ||
@@ -43,0 +49,0 @@ tabActive: React.PropTypes.string |
@@ -10,2 +10,3 @@ 'use strict'; | ||
import TabStyles from './TabStyles'; | ||
import TabTemplate from './TabTemplate'; | ||
import CloseIcon from './CloseIcon'; | ||
@@ -16,8 +17,2 @@ | ||
let tabInlineStyles = { | ||
}; | ||
let tabClassNames = { | ||
}; | ||
class Tabs extends React.Component { | ||
@@ -31,3 +26,2 @@ constructor(props) { | ||
defaultState.closedTabs = []; | ||
defaultState.dragging = false; | ||
this.state = defaultState; | ||
@@ -41,4 +35,2 @@ | ||
_tabStateFromProps(props) { | ||
// setDefaultSelected | ||
let tabPositions = {}; | ||
let tabs = []; | ||
@@ -53,3 +45,2 @@ let idx = 0; | ||
tabPositions[tab.key] = {x:0, y:0}; | ||
tabs[idx] = tab; | ||
@@ -60,4 +51,3 @@ idx++; | ||
return { | ||
tabs: tabs, | ||
tabPositions: tabPositions | ||
tabs: tabs | ||
}; | ||
@@ -150,2 +140,4 @@ } | ||
} | ||
// reset closedTabs, respect props from application | ||
newState.closedTabs = []; | ||
this.setState(newState); | ||
@@ -162,3 +154,2 @@ } | ||
handleMouseDown(key, e, ui) { | ||
this.setState({dragging: key}); | ||
} | ||
@@ -173,5 +164,5 @@ | ||
handleDragStop(key, e, ui) { | ||
const deltaX = (e.pageX || e.clientX); | ||
let swapedTabs; | ||
let newState = {}; | ||
_.each(this.startPositions, (pos) => { | ||
@@ -184,5 +175,6 @@ let shoudBeSwap = key !== pos.key && pos.pos.left < deltaX && deltaX < pos.pos.right; | ||
let nextTabs = swapedTabs || this.state.tabs; | ||
let tabPositions = this.state.tabPositions; | ||
tabPositions[key] = {x:0, y:0}; | ||
this.setState({tabPositons:tabPositions, dragging:false, tabs: nextTabs, selectedTab: key}, () => { | ||
newState.tabs = nextTabs; | ||
newState.selectedTab = key; | ||
this.setState(newState, () => { | ||
if(swapedTabs) { | ||
@@ -207,2 +199,4 @@ this.props.onTabPositionChanged(e, key, this._getOpenTabs(nextTabs)); | ||
handleCloseButtonClick(key, e) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
let nextSelected; | ||
@@ -220,3 +214,2 @@ | ||
let shoudBeNotifyTabChange = this.state.selectedTab !== nextSelected; | ||
this.setState({ | ||
@@ -238,7 +231,7 @@ closedTabs: this.state.closedTabs.concat([key]), | ||
getCloseButton(tab, style, classes) { | ||
getCloseButton(tab, style, classes, hoverStyleBase) { | ||
if (tab.props.disableClose) { | ||
return ''; | ||
} else { | ||
let onHoverStyle = StyleOverride.merge(tabInlineStyles.tabCloseIconOnHover, tab.props.tabStyles.tabCloseIconOnHover); | ||
let onHoverStyle = StyleOverride.merge(hoverStyleBase, tab.props.tabStyles.tabCloseIconOnHover); | ||
return (<CloseIcon | ||
@@ -255,2 +248,4 @@ style={style} | ||
// override inline tabs styles | ||
let tabInlineStyles = { | ||
}; | ||
tabInlineStyles.tabBar = StyleOverride.merge(TabStyles.tabBar, this.props.tabsStyles.tabBar); | ||
@@ -271,2 +266,4 @@ tabInlineStyles.tabBarAfter = StyleOverride.merge(TabStyles.tabBarAfter, this.props.tabsStyles.tabBarAfter); | ||
// append tabs classNames | ||
let tabClassNames = { | ||
}; | ||
tabClassNames.tabBar = classNames('rdTabBar', this.props.tabsClassNames.tabBar); | ||
@@ -278,2 +275,4 @@ tabClassNames.tabBarAfter = classNames('rdTabBarAfter', this.props.tabsClassNames.tabBarAfter); | ||
tabClassNames.tabTitle = classNames('rdTabTitle', this.props.tabsClassNames.tabTitle); | ||
tabClassNames.tabBeforeTitle = classNames('rdTabBeforeTitle', this.props.tabsClassNames.tabBeforeTitle); | ||
tabClassNames.tabAfterTitle = classNames('rdTabAfterTitle', this.props.tabsClassNames.tabAfterTitle); | ||
tabClassNames.tabCloseIcon = classNames('rdTabCloseIcon', this.props.tabsClassNames.tabCloseIcon); | ||
@@ -283,3 +282,3 @@ tabClassNames.tabActive = classNames('rdTabActive', this.props.tabsClassNames.tabActive); | ||
let content; | ||
let content = []; | ||
let tabs = _.map(this.state.tabs, (tab) => { | ||
@@ -302,2 +301,4 @@ | ||
let tabTitleClasses = classNames(tabClassNames.tabTitle, tab.props.tabClassNames.tabTitle); | ||
let tabBeforeTitleClasses = classNames(tabClassNames.tabBeforeTitle, tab.props.tabClassNames.tabBeforeTitle); | ||
let tabAfterTitleClasses = classNames(tabClassNames.tabAfterTitle, tab.props.tabClassNames.tabAfterTitle); | ||
let tabCloseIconClasses = classNames(tabClassNames.tabCloseIcon, tab.props.tabClassNames.tabCloseIcon); | ||
@@ -311,3 +312,5 @@ | ||
tabClasses = classNames(tabClassNames.tab, 'rdTabActive', this.props.tabsClassNames.tabActive, tab.props.tabClassNames.tabActive); | ||
content = tab; | ||
content.push(<TabTemplate key={'tabTemplate#' + tab.key} selected={true}>{tab}</TabTemplate>); | ||
} else { | ||
content.push(<TabTemplate key={'tabTemplate#' + tab.key} selected={false}>{tab}</TabTemplate>); | ||
} | ||
@@ -322,4 +325,3 @@ | ||
let tabTitle = tab.props.title; | ||
let tabPositon = this.state.tabPositions[tab.key]; | ||
let closeButton = this.getCloseButton(tab, tabCloseIconStyle, tabCloseIconClasses); | ||
let closeButton = this.getCloseButton(tab, tabCloseIconStyle, tabCloseIconClasses, tabInlineStyles.tabCloseIconOnHover); | ||
@@ -331,3 +333,3 @@ return ( | ||
cancel='.rdTabCloseIcon' | ||
start={tabPositon} | ||
start={{x:0, y:0}} | ||
moveOnStartChange={true} | ||
@@ -343,3 +345,5 @@ zIndex={100} | ||
ref={tab.key}> | ||
<span style={tabTiteleStyle} className={tabTitleClasses}>{tabTitle}</span> | ||
<span style={TabStyles.beforeTitle} className={tabBeforeTitleClasses}>{tab.props.beforeTitle}</span> | ||
<p style={tabTiteleStyle} className={tabTitleClasses}>{tabTitle}</p> | ||
<span style={TabStyles.afterTitle} className={tabAfterTitleClasses}>{tab.props.afterTitle}</span> | ||
{closeButton} | ||
@@ -354,4 +358,4 @@ <span style={tabBeforeStyle} className={tabBeforeClasses}></span> | ||
return ( | ||
<div> | ||
<div style={TabStyles.wrapper}> | ||
<div style={TabStyles.wrapper}> | ||
<div style={TabStyles.relative}> | ||
<ul tabIndex='-1' style={tabInlineStyles.tabBar} className={tabClassNames.tabBar}> | ||
@@ -378,3 +382,5 @@ {tabs} | ||
tabAfter: '', | ||
tabBeforeTitle: '', | ||
tabTitle: '', | ||
tabAfterTitle: '', | ||
tabCloseIcon: '', | ||
@@ -401,3 +407,5 @@ tabActive: '' | ||
tabAfter: React.PropTypes.string, | ||
tabBeforeTitle: React.PropTypes.string, | ||
tabTitle: React.PropTypes.string, | ||
tabAfterTitle: React.PropTypes.string, | ||
tabCloseIcon: React.PropTypes.string, | ||
@@ -404,0 +412,0 @@ tabActive: React.PropTypes.string |
@@ -12,5 +12,11 @@ /* Inspired from Atom | ||
wrapper: { | ||
height: '100%', | ||
width: '100%', | ||
position: 'relative' | ||
}, | ||
relative: { | ||
position: 'relative' | ||
}, | ||
tabBar: { | ||
@@ -29,3 +35,6 @@ // @TODO safari needs prefix. Style should be define in CSS. | ||
listStyle: 'none', | ||
outline: '0px' | ||
outline: '0px', | ||
overflowX: 'scroll', | ||
minWidth: '95%', | ||
maxWidth: '95%' | ||
}, | ||
@@ -36,3 +45,3 @@ | ||
position: 'absolute', | ||
bottom: '0', | ||
bottom: '-5px', | ||
height: '5px', | ||
@@ -54,3 +63,2 @@ left: '0', | ||
marginLeft: '5px', | ||
paddingTop: '.5em', | ||
paddingLeft: '15px', | ||
@@ -109,3 +117,2 @@ paddingRight: '24px', | ||
color: '#ffffff', | ||
paddingTop: '5px', | ||
fontSize: '13px', | ||
@@ -119,7 +126,7 @@ backgroundImage: 'linear-gradient(#343434, #222222)' | ||
textOverflow: 'ellipsis', | ||
top: '5px', | ||
marginTop: '8px', | ||
float: 'left', | ||
textAlign: 'center', | ||
postion: 'relative', | ||
width: '70%', | ||
width: '90%', | ||
color: 'rgb(170, 170, 170)' | ||
@@ -137,5 +144,6 @@ }, | ||
tabTitleActive: { | ||
paddingRight: '10px', | ||
lineHeight: '1.5em', | ||
color: 'rgb(255, 255, 255)' | ||
color: 'rgb(255, 255, 255)', | ||
marginTop:'6px' | ||
}, | ||
@@ -146,7 +154,7 @@ | ||
font: '14px/100% arial, sans-serif', | ||
width: '10%', | ||
right: '5px', | ||
marginTop: '8px', | ||
textDecoration: 'none', | ||
textShadow: '0 1px 0 #fff', | ||
top: '5px', | ||
float: 'right', | ||
@@ -173,6 +181,21 @@ fontSize: '1.5em', | ||
marginLeft: '20px' | ||
}, | ||
beforeTitle: { | ||
position:'absolute', | ||
top: '8px', | ||
left: '-8px', | ||
zIndex: 2 | ||
}, | ||
afterTitle: { | ||
position:'absolute', | ||
top: '8px', | ||
right: '16px', | ||
zIndex: 2 | ||
} | ||
}); | ||
export default TabStyles; |
@@ -8,6 +8,9 @@ 'use strict'; | ||
import DynamicTabContent from './DynamicTabContent' | ||
import DynamicTabBadge from './DynamicTabBadge' | ||
//allow react dev tools work | ||
window.React = React; | ||
const tabClassNames = { | ||
const tabsClassNames = { | ||
tabBar: 'myTabBar', | ||
@@ -22,3 +25,3 @@ tabBarAfter: 'myTabBarAfter', | ||
const tabStyles = { | ||
const tabsStyles = { | ||
tabBar: {}, | ||
@@ -35,5 +38,10 @@ tab:{}, | ||
super(props); | ||
let icon = (<image src='icon.png' style={{height:'13px'}}/>); | ||
let fonticon = (<icon className='icon-html5'/>); | ||
let badge = (<DynamicTabBadge />); | ||
this.state = { | ||
tabs:[ | ||
(<Tab key={'tab0'} title={'fixedTab'} disableClose={true} > | ||
(<Tab key={'tab0'} title={'unclosable tab'} disableClose={true} > | ||
<div> | ||
@@ -43,3 +51,3 @@ <h1>This tab cannot close</h1> | ||
</Tab>), | ||
(<Tab key={'tab1'} title={'1stTab'} > | ||
(<Tab key={'tab1'} title={'1stTab'} beforeTitle={icon} > | ||
<div> | ||
@@ -49,3 +57,3 @@ <h1>This is tab1</h1> | ||
</Tab>), | ||
(<Tab key={'tab2'} title={'2ndTab Too long Toooooooooooooooooo long'} > | ||
(<Tab key={'tab2'} title={'2ndTab Too long Toooooooooooooooooo long'} beforeTitle={fonticon} > | ||
<div> | ||
@@ -56,34 +64,12 @@ <pre>Lorem ipsum dolor sit amet, consectetur adipisicing elit, | ||
</Tab>), | ||
this._getDynamicTab() | ||
(<Tab key={'tab3'} title={'Dynamic tab'} afterTitle={badge}> | ||
<DynamicTabContent/> | ||
</Tab>) | ||
], | ||
textvalue: '' | ||
badgeCount: 0 | ||
}; | ||
} | ||
_getDynamicTab() { | ||
return ( | ||
<Tab key='tab3' title={'3rdTab'} > | ||
<div> | ||
<h1>TAB3!!! This tab dynamically change</h1> | ||
<textarea value={this.state ? this.state.textValue: ''} onChange={this._handleTextChange.bind(this)}></textarea> | ||
</div> | ||
</Tab>); | ||
} | ||
_handleTextChange(e) { | ||
this.setState({textValue: e.target.value}); | ||
} | ||
_replaceDynamicTab(tabs) { | ||
return _.map(tabs, (tab) => { | ||
if(tab.key === 'tab3') { | ||
return this._getDynamicTab(); | ||
} else { | ||
return tab; | ||
} | ||
}); | ||
} | ||
handleTabSelect(e, key, currentTabs) { | ||
console.log('tabSelected key:', key); | ||
console.log('handleTabSelect key:', key); | ||
this.setState({selectedTab: key, tabs: currentTabs}); | ||
@@ -105,3 +91,3 @@ } | ||
const key = 'newTab_' + Date.now(); | ||
let newTab = (<Tab key={key} title='untitled'> | ||
let newTab = (<Tab key={key} title='untitled' > | ||
<div> | ||
@@ -114,3 +100,3 @@ <h1>New Empty Tab</h1> | ||
this.setState({ | ||
tabs: this._replaceDynamicTab(newTabs), | ||
tabs: newTabs, | ||
selectedTab: key | ||
@@ -120,10 +106,16 @@ }); | ||
_handleBadgeInc() { | ||
this.setState({badgeCount: this.state.badgeCount + 1}); | ||
} | ||
_handleBadgeDec() { | ||
this.setState({badgeCount: this.state.badgeCount + 1}); | ||
} | ||
render() { | ||
let tabs = this._replaceDynamicTab(this.state.tabs); | ||
return ( | ||
<Tabs | ||
tabClassNames={tabClassNames} | ||
tabStyles={tabStyles} | ||
tabsClassNames={tabsClassNames} | ||
tabsStyles={tabsStyles} | ||
selectedTab={this.state.selectedTab ? this.state.selectedTab : "tab2"} | ||
@@ -134,4 +126,4 @@ onTabSelected={this.handleTabSelect.bind(this)} | ||
onTabPositionChanged={this.handleTabPositionChange.bind(this)} | ||
tabs={tabs}> | ||
</Tabs> | ||
tabs={this.state.tabs} | ||
/> | ||
) | ||
@@ -138,0 +130,0 @@ } |
{ | ||
"name": "react-draggable-tab", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Draggable chrome like tab react component ", | ||
@@ -47,2 +47,3 @@ "main": "index.js", | ||
"mocha": "^2.2.5", | ||
"react-notification-badge": "^0.1.0", | ||
"watchify": "^3.2.1" | ||
@@ -49,0 +50,0 @@ }, |
# React-draggable-tab [![Build Status](https://travis-ci.org/georgeOsdDev/react-draggable-tab.svg?branch=develop)](https://travis-ci.org/georgeOsdDev/react-draggable-tab) [![npm version](https://badge.fury.io/js/react-draggable-tab.svg)](http://badge.fury.io/js/react-draggable-tab) | ||
[![Gyazo](http://i.gyazo.com/faea8029a68a9c1ea9bf4a588e5ac5a6.gif)](http://gyazo.com/faea8029a68a9c1ea9bf4a588e5ac5a6) | ||
[![Gyazo](http://i.gyazo.com/42d408d288292f62fbb8d650897acbc4.gif)](http://gyazo.com/42d408d288292f62fbb8d650897acbc4) | ||
@@ -30,13 +30,19 @@ Atom like draggable tab react component. | ||
* `beforeTitle`: element to show in tab. eg icon. | ||
`React.PropTypes.element` | ||
* `title`: string to show in tab. | ||
`React.PropTypes.string.isRequired` | ||
* `afterTitle`: element to show in tab. eg: notification badge | ||
`React.PropTypes.element` | ||
* `disableClose`: If `true`, closeButton will not be appeared in tab. | ||
`React.PropTypes.bool` (Default `false`) | ||
* `beforeTitle`: | ||
###### Style (for each tab) | ||
* `tabClassNames`: classNames which will be **added** to rendered elements. | ||
* `tabBar`: base `ul` element of tab bar (defult: `rdTabBar`) | ||
* `tabBarAfter`: after `span` element of tab bar which emulate `:After` selector (defult: `rdTabBarAfter`) | ||
* `tab`: base `li` element of tab (defult: `rdTab`) | ||
@@ -46,8 +52,8 @@ * `tabBefore`: before element of `li` which emulate `:Before` selector (defult: `rdTabBefore`) | ||
* `tabTitle`: `span` element of tab title (defult: `rdTabTitle`) | ||
* `tabBeforeTitle`: `span` element of tab before title (defult: `tabBeforeTitle`) | ||
* `tabAfterTitle`: `span` element of tab after title (defult: `tabAfterTitle`) | ||
* `tabCloseIcon`: base `span` element of close icon (defult: `rdCloseIcon`) | ||
* `tabActove`: selected tab's `li`, before, after (defult: `rdTabActive`) | ||
* `tabActive`: selected tab's `li`, before, after (defult: `rdTabActive`) | ||
* `tabStyles`: Inline styles which will be **overwritten** default and common-tabs inline styles. | ||
* `tabBar`: base `ul` element of tab bar | ||
* `tabBarAfter`: after `span` element of tab bar which emulate `:After` selector | ||
* `tab`: base `li` element of tab | ||
@@ -57,5 +63,5 @@ * `tabBefore`: before element of `li` which emulate `:Before` selector. | ||
* `tabTitle`: `span` element of tab title | ||
* `tabActove`: selected tab's `li` | ||
* `tabBeforeActove`: selected tab's `li` before | ||
* `tabAfterActove`: selected tab's `li` after | ||
* `tabActive`: selected tab's `li` | ||
* `tabBeforeActive`: selected tab's `li` before | ||
* `tabAfterActive`: selected tab's `li` after | ||
* `tabTitleActive`: selected tab's title | ||
@@ -90,4 +96,6 @@ * `tabCloseIcon`: base `span` element of close icon | ||
* `tabTitle`: `span` element of tab title (defult: `rdTabTitle`) | ||
* `tabBeforeTitle`: `span` element of tab before title (defult: `rdTabBeforeTitle`) | ||
* `tabBeforeTitle`: `span` element of tab after title (defult: `rdTabAfterTitle`) | ||
* `tabCloseIcon`: base `span` element of close icon (defult: `rdCloseIcon`) | ||
* `tabActove`: selected tab's `li`, before, after (defult: `rdTabActive`) | ||
* `tabActive`: selected tab's `li`, before, after (defult: `rdTabActive`) | ||
@@ -101,5 +109,5 @@ * `tabsStyles`: Inline styles which will be **overwritten** default inline styles. | ||
* `tabTitle`: `span` element of tab title | ||
* `tabActove`: selected tab's `li` | ||
* `tabBeforeActove`: selected tab's `li` before | ||
* `tabAfterActove`: selected tab's `li` after | ||
* `tabActive`: selected tab's `li` | ||
* `tabBeforeActive`: selected tab's `li` before | ||
* `tabAfterActive`: selected tab's `li` after | ||
* `tabTitleActive`: selected tab's title | ||
@@ -134,5 +142,9 @@ * `tabCloseIcon`: base `span` element of close icon | ||
super(props); | ||
let icon = (<image src='icon.png' style={{height:'13px'}}/>); | ||
let fonticon = (<icon className='icon-html5'/>); | ||
let badge = (<DynamicTabBadge />); | ||
this.state = { | ||
tabs:[ | ||
(<Tab key={'tab0'} title={'fixedTab'} disableClose={true} > | ||
(<Tab key={'tab0'} title={'unclosable tab'} disableClose={true} > | ||
<div> | ||
@@ -142,3 +154,3 @@ <h1>This tab cannot close</h1> | ||
</Tab>), | ||
(<Tab key={'tab1'} title={'1stTab'} > | ||
(<Tab key={'tab1'} title={'1stTab'} beforeTitle={icon} > | ||
<div> | ||
@@ -148,3 +160,3 @@ <h1>This is tab1</h1> | ||
</Tab>), | ||
(<Tab key={'tab2'} title={'2ndTab Too long Toooooooooooooooooo long'} > | ||
(<Tab key={'tab2'} title={'2ndTab Too long Toooooooooooooooooo long'} beforeTitle={fonticon} > | ||
<div> | ||
@@ -155,33 +167,12 @@ <pre>Lorem ipsum dolor sit amet, consectetur adipisicing elit, | ||
</Tab>), | ||
this._getDynamicTab() | ||
(<Tab key={'tab3'} title={'Dynamic tab'} afterTitle={badge}> | ||
<DynamicTabContent/> | ||
</Tab>) | ||
], | ||
textvalue: '' | ||
badgeCount: 0 | ||
}; | ||
} | ||
_getDynamicTab() { | ||
return ( | ||
<Tab key='tab3' title={'3rdTab'} > | ||
<div> | ||
<h1>TAB3!!! This tab dynamically change</h1> | ||
<textarea value={this.state ? this.state.textValue: ''} onChange={this._handleTextChange.bind(this)}></textarea> | ||
</div> | ||
</Tab>); | ||
} | ||
_handleTextChange(e) { | ||
this.setState({textValue: e.target.value}); | ||
} | ||
_replaceDynamicTab(tabs) { | ||
return _.map(tabs, (tab) => { | ||
if(tab.key === 'tab3') { | ||
return this._getDynamicTab(); | ||
} else { | ||
return tab; | ||
} | ||
}); | ||
} | ||
handleTabSelect(e, key, currentTabs) { | ||
console.log('handleTabSelect key:', key); | ||
this.setState({selectedTab: key, tabs: currentTabs}); | ||
@@ -203,3 +194,3 @@ } | ||
const key = 'newTab_' + Date.now(); | ||
let newTab = (<Tab key={key} title='untitle'> | ||
let newTab = (<Tab key={key} title='untitled'> | ||
<div> | ||
@@ -212,3 +203,3 @@ <h1>New Empty Tab</h1> | ||
this.setState({ | ||
tabs: this._replaceDynamicTab(newTabs), | ||
tabs: newTabs, | ||
selectedTab: key | ||
@@ -220,8 +211,6 @@ }); | ||
let tabs = this._replaceDynamicTab(this.state.tabs) | ||
return ( | ||
<Tabs | ||
tabClassNames={tabClassNames} | ||
tabStyles={tabStyles} | ||
tabsClassNames={tabsClassNames} | ||
tabsStyles={tabsStyles} | ||
selectedTab={this.state.selectedTab ? this.state.selectedTab : "tab2"} | ||
@@ -232,4 +221,4 @@ onTabSelected={this.handleTabSelect.bind(this)} | ||
onTabPositionChanged={this.handleTabPositionChange.bind(this)} | ||
tabs={tabs}> | ||
</Tabs> | ||
tabs={this.state.tabs} | ||
/> | ||
) | ||
@@ -259,3 +248,3 @@ } | ||
`Tabs` do not care any change in `Tab` content. | ||
`tabs` needs update by your application side. | ||
content needs update by your application side. | ||
See `3rdTab` in example. | ||
@@ -262,0 +251,0 @@ |
@@ -24,2 +24,4 @@ 'use strict'; | ||
expect(component.props.tabClassNames.tabTitle).to.be.equal(''); | ||
expect(component.props.tabClassNames.tabBeforeTitle).to.be.equal(''); | ||
expect(component.props.tabClassNames.tabAfterTitle).to.be.equal(''); | ||
expect(component.props.tabClassNames.tabCloseIcon).to.be.equal(''); | ||
@@ -26,0 +28,0 @@ expect(component.props.tabClassNames.tabActive).to.be.equal(''); |
@@ -27,3 +27,5 @@ 'use strict'; | ||
expect(component.props.tabsClassNames.tabAfter).to.be.equal(''); | ||
expect(component.props.tabsClassNames.tabBeforeTitle).to.be.equal(''); | ||
expect(component.props.tabsClassNames.tabTitle).to.be.equal(''); | ||
expect(component.props.tabsClassNames.tabAfterTitle).to.be.equal(''); | ||
expect(component.props.tabsClassNames.tabCloseIcon).to.be.equal(''); | ||
@@ -40,2 +42,3 @@ expect(component.props.tabsClassNames.tabActive).to.be.equal(''); | ||
expect(typeof component.props.onTabPositionChanged).to.be.equal('function'); | ||
}); | ||
@@ -48,15 +51,9 @@ | ||
(<Tab key={'tab1'} title={'tab1'} > | ||
<div> | ||
<h1>tab1Content</h1> | ||
</div> | ||
<h1>tab1Content</h1> | ||
</Tab>), | ||
(<Tab key={'tab2'} title={'tab2'} > | ||
<div> | ||
<h1>tab2Content</h1> | ||
</div> | ||
<h1>tab2Content</h1> | ||
</Tab>), | ||
(<Tab key={'tab3'} title={'tab3'} > | ||
<div> | ||
<h1>tab3Content</h1> | ||
</div> | ||
<h1>tab3Content</h1> | ||
</Tab>) | ||
@@ -94,7 +91,75 @@ ]; | ||
let content = TestUtils.scryRenderedDOMComponentsWithTag(component, 'h1'); | ||
expect(content).to.be.length(1); | ||
expect(content).to.be.length(3); | ||
expect(React.findDOMNode(content[0]).textContent).to.be.equal('tab1Content'); | ||
expect(React.findDOMNode(content[0]).parentNode.style.height).to.be.not.equal('0px'); | ||
expect(React.findDOMNode(content[1]).textContent).to.be.equal('tab2Content'); | ||
expect(React.findDOMNode(content[1]).parentNode.style.height).to.be.equal('0px'); | ||
expect(React.findDOMNode(content[2]).textContent).to.be.equal('tab3Content'); | ||
expect(React.findDOMNode(content[2]).parentNode.style.height).to.be.equal('0px'); | ||
}); | ||
}); | ||
describe('add optional element before/after Title', () => { | ||
const el1 =(<i className='icon icon1' />); | ||
const el2 =(<i className='icon icon2' />); | ||
const el3 =(<i className='icon icon3' />); | ||
const el4 =(<i className='icon icon4' />); | ||
const tabs = [ | ||
(<Tab key={'tab1'} title={'tab1'} beforeTitle={el1}> | ||
<h1>tab1Content</h1> | ||
</Tab>), | ||
(<Tab key={'tab2'} title={'tab2'} afterTitle={el2}> | ||
<h1>tab2Content</h1> | ||
</Tab>), | ||
(<Tab key={'tab3'} title={'tab3'} beforeTitle={el3} afterTitle={el4}> | ||
<h1>tab3Content</h1> | ||
</Tab>) | ||
]; | ||
let children; | ||
beforeEach(() => { | ||
component = TestUtils.renderIntoDocument( | ||
<Tabs | ||
selectedTab="tab1" | ||
tabs={tabs} />); | ||
children = TestUtils.scryRenderedDOMComponentsWithClass(component, 'rdTab'); | ||
}); | ||
it('will insert custome element before title', () => { | ||
let t1BeforeTitle = TestUtils.findRenderedDOMComponentWithClass(children[0], 'rdTabBeforeTitle'); | ||
let t1BeforeTitleIcon = TestUtils.scryRenderedDOMComponentsWithTag(t1BeforeTitle, 'i'); | ||
expect(t1BeforeTitleIcon).to.be.length(1); | ||
expect(React.findDOMNode(t1BeforeTitleIcon[0]).className.indexOf('icon1') > 0).to.be.equal(true) | ||
let t1AfterTitle = TestUtils.findRenderedDOMComponentWithClass(children[0], 'rdTabAfterTitle'); | ||
let t1AfterTitleIcon = TestUtils.scryRenderedDOMComponentsWithTag(t1AfterTitle, 'i'); | ||
expect(t1AfterTitleIcon).to.be.length(0); | ||
}); | ||
it('will insert custome element affter title', () => { | ||
let t2BeforeTitle = TestUtils.findRenderedDOMComponentWithClass(children[1], 'rdTabBeforeTitle'); | ||
let t2BeforeTitleIcon = TestUtils.scryRenderedDOMComponentsWithTag(t2BeforeTitle, 'i'); | ||
expect(t2BeforeTitleIcon).to.be.length(0); | ||
let t2AfterTitle = TestUtils.findRenderedDOMComponentWithClass(children[1], 'rdTabAfterTitle'); | ||
let t2AfterTitleIcon = TestUtils.scryRenderedDOMComponentsWithTag(t2AfterTitle, 'i'); | ||
expect(t2AfterTitleIcon).to.be.length(1); | ||
expect(React.findDOMNode(t2AfterTitleIcon[0]).className.indexOf('icon2') > 0).to.be.equal(true) | ||
}); | ||
it('will insert custome element before/affter title', () => { | ||
let t3BeforeTitle = TestUtils.findRenderedDOMComponentWithClass(children[2], 'rdTabBeforeTitle'); | ||
let t3BeforeTitleIcon = TestUtils.scryRenderedDOMComponentsWithTag(t3BeforeTitle, 'i'); | ||
expect(t3BeforeTitleIcon).to.be.length(1); | ||
expect(React.findDOMNode(t3BeforeTitleIcon[0]).className.indexOf('icon3') > 0).to.be.equal(true) | ||
let t3AfterTitle = TestUtils.findRenderedDOMComponentWithClass(children[2], 'rdTabAfterTitle'); | ||
let t3AfterTitleIcon = TestUtils.scryRenderedDOMComponentsWithTag(t3AfterTitle, 'i'); | ||
expect(t3AfterTitleIcon).to.be.length(1); | ||
expect(React.findDOMNode(t3AfterTitleIcon[0]).className.indexOf('icon4') > 0).to.be.equal(true) | ||
}); | ||
}) | ||
describe('add custom className to all tabs ', function(){ | ||
@@ -107,2 +172,4 @@ | ||
tabTitle: 'myTabTitle', | ||
tabBeforeTitle: 'myTabBeforeTitle', | ||
tabAfterTitle: 'myTabAfterTitle', | ||
tabCloseIcon: 'myTabCloseIcon', | ||
@@ -150,2 +217,8 @@ tabBefore: 'myTabBefore', | ||
let rdTabBeforeTitle = TestUtils.findRenderedDOMComponentWithClass(component, 'rdTabBeforeTitle'); | ||
expect(React.findDOMNode(rdTabBeforeTitle).className).contain('myTabBeforeTitle'); | ||
let rdTabAfterTitle = TestUtils.findRenderedDOMComponentWithClass(component, 'rdTabAfterTitle'); | ||
expect(React.findDOMNode(rdTabAfterTitle).className).contain('myTabAfterTitle'); | ||
let rdTabActive = TestUtils.findRenderedDOMComponentWithClass(component, 'rdTabActive'); | ||
@@ -246,2 +319,4 @@ expect(React.findDOMNode(rdTabActive).className).contain('myTabActive'); | ||
tabTitle: 'myTabTitle', | ||
tabBeforeTitle: 'myTabBeforeTitle', | ||
tabAfterTitle: 'myTabAfterTitle', | ||
tabCloseIcon: 'myTabCloseIcon', | ||
@@ -256,2 +331,4 @@ tabBefore: 'myTabBefore', | ||
tabTitle: 'mySpecialTabTitle', | ||
tabBeforeTitle: 'mySpecialTabBeforeTitle', | ||
tabAfterTitle: 'mySpecialTabAfterTitle', | ||
tabCloseIcon: 'mySpecialTabCloseIcon', | ||
@@ -264,3 +341,3 @@ tabBefore: 'mySpecialTabBefore', | ||
const tabs = [ | ||
(<Tab key={'tab1'} title={'tab1'} tabClassNames={tabClassNames}> | ||
(<Tab key={'tab1'} title={'tab1'} tabClassNames={tabClassNames} > | ||
<div> | ||
@@ -308,2 +385,10 @@ <h1>tab1Content</h1> | ||
let rdTabBeforeTitle = TestUtils.scryRenderedDOMComponentsWithClass(component, 'rdTabBeforeTitle'); | ||
expect(React.findDOMNode(rdTabBeforeTitle[0]).className).contain('mySpecialTabBeforeTitle'); | ||
expect(React.findDOMNode(rdTabBeforeTitle[1]).className).not.contain('mySpecialTabBeforeTitle'); | ||
let rdTabAfterTitle = TestUtils.scryRenderedDOMComponentsWithClass(component, 'rdTabAfterTitle'); | ||
expect(React.findDOMNode(rdTabAfterTitle[0]).className).contain('mySpecialTabAfterTitle'); | ||
expect(React.findDOMNode(rdTabAfterTitle[1]).className).not.contain('mySpecialTabAfterTitle'); | ||
let rdTabActive = TestUtils.findRenderedDOMComponentWithClass(component, 'rdTabActive'); | ||
@@ -449,3 +534,3 @@ expect(React.findDOMNode(rdTabActive).className).contain('mySpecialTabActive'); | ||
<Tabs | ||
onTabAddButtonClicked={function(e, _currentTabs){called = true; currentTabs = _currentTabs; }} | ||
onTabAddButtonClicked={function(e, _currentTabs){called = true; currentTabs = _currentTabs;}} | ||
selectedTab="tab1" | ||
@@ -465,2 +550,3 @@ tabs={tabs} />); | ||
}); | ||
}); | ||
@@ -467,0 +553,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
132017
42
2439
19
248
1