| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 |
134x
134x
134x
268x
16x
16x
16x
16x
16x
31x
| import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import {
createClass,
getFirst,
findTypes,
omitProps,
} from '../../util/component-types';
import { buildHybridComponent } from '../../util/state-management';
import * as reducers from './VerticalTabs.reducers';
import {
VerticalListMenuDumb as VerticalListMenu,
} from '../VerticalListMenu/VerticalListMenu';
const cx = lucidClassNames.bind('&-VerticalTabs');
const { string, number, bool, func } = PropTypes;
/**
*
* {"categories": ["navigation"], "madeFrom": ["VerticalListMenu"]}
*
* `VerticalTabs` provides vertically tabbed navigation. It has a flexible
* interface that allows tab content to be passed as regular React children or
* through props.
*/
const VerticalTabs = createClass({
displayName: 'VerticalTabs',
components: {
/**
* Content that will be rendered in a tab. Be sure to nest a Title inside
* each Tab or provide it as a prop.
*/
Tab: createClass({
displayName: 'VerticalTabs.Tab',
propName: 'Tab',
propTypes: {
/**
* Determines if the Tab is selected.
*/
isSelected: bool,
},
}),
/**
* Titles can be provided as a child or prop to a Tab.
*/
Title: createClass({
displayName: 'VerticalTabs.Title',
propName: 'Title',
}),
},
reducers,
propTypes: {
/**
* Class names that are appended to the defaults.
*/
className: string,
/**
* Indicates which of the `VerticalTabs.Tab` children is currently
* selected. The index of the last `VerticalTabs.Tab` child with
* `isSelected` equal to `true` takes precedence over this prop.
*/
selectedIndex: number,
/**
* Callback for when the user clicks a tab. Called with the index of the
* tab that was clicked.
*
* Signature: `(index, { event, props}) => {}`
*/
onSelect: func,
},
getDefaultProps() {
return {
selectedIndex: 0,
onSelect: _.noop,
};
},
render() {
const { className, onSelect, selectedIndex, ...passThroughs } = this.props;
// Grab props array from each Tab
const tabChildProps = _.map(
findTypes(this.props, VerticalTabs.Tab),
'props'
);
const selectedIndexFromChildren = _.findLastIndex(tabChildProps, {
isSelected: true,
});
const actualSelectedIndex = selectedIndexFromChildren !== -1
? selectedIndexFromChildren
: selectedIndex;
return (
<div
{...omitProps(passThroughs, VerticalTabs)}
className={cx('&', className)}
>
<VerticalListMenu
selectedIndices={[actualSelectedIndex]}
onSelect={onSelect}
>
{_.map(tabChildProps, (tabChildProp, index) => (
<VerticalListMenu.Item
className={cx('&-Tab', {
'&-Tab-is-active': actualSelectedIndex === index,
})}
key={index}
>
<span className={cx('&-Tab-content')}>
{_.get(
getFirst(tabChildProp, VerticalTabs.Title),
'props.children',
''
)}
</span>
</VerticalListMenu.Item>
))}
</VerticalListMenu>
<div className={cx('&-content')}>
{_.get(tabChildProps, [actualSelectedIndex, 'children'])}
</div>
</div>
);
},
});
export default buildHybridComponent(VerticalTabs);
export { VerticalTabs as VerticalTabsDumb };
|