UNPKG

5.72 kBJavaScriptView Raw
1/* Tab pen from https://codepen.io/josh_vogt/pen/EaaZbP */
2import React, { PureComponent } from 'react';
3import styled from 'styled-components';
4import { connect } from 'react-redux';
5import { bindActionCreators } from 'redux';
6import PropTypes from 'prop-types';
7
8import If from './operator/if';
9import { selectTab } from './tabActions';
10
11const TabStyle = styled.div`
12 .state {
13 position: absolute;
14 left: -10000px;
15 }
16 .flex-tabs {
17 display: flex;
18 justify-content: space-between;
19 flex-wrap: wrap;
20 }
21 .flex-tabs .tab {
22 flex-grow: 1;
23 max-height: 40px;
24 }
25 .flex-tabs .panel {
26 background-color: #e5e9f2;
27 padding: 2px;
28 min-height: 300px;
29 display: none;
30 width: 100%;
31 flex-basis: auto;
32 }
33 .tab {
34 display: inline-block;
35 padding: 10px;
36 vertical-align: top;
37 background-color: #eee;
38 cursor: hand;
39 cursor: pointer;
40 border-left: 10px solid #ccc;
41 }
42 .tab:hover {
43 background-color: #fff;
44 }
45 ${(props) => {
46 const tabs = props.tabs || [];
47 return tabs.map(
48 value => `
49 #${value.id}:checked ~ .tabs #${value.id}-label {
50 background-color: #fff;
51 cursor: default;
52 border-left-color: #69be28;
53 }
54 #${value.id}:checked ~ .tabs #${value.id}-panel {
55 display: block;
56 }
57 `,
58 );
59 }} @media (max-width: 600px) {
60 .flex-tabs {
61 flex-direction: column;
62 }
63 .flex-tabs .tab {
64 background: #fff;
65 border-bottom: 1px solid #ccc;
66 }
67 .flex-tabs .tab:last-of-type {
68 border-bottom: none;
69 }
70 ${(props) => {
71 const tabs = props.tabs || [];
72 return tabs.map((value, index) => {
73 if (Math.abs((index + 1) % 2) === 1) {
74 return `
75 .flex-tabs #${value.id}-label {
76 order: ${index + 1};
77 }`;
78 }
79 return `
80 .flex-tabs #${value.id}-panel {
81 order: ${index + 1};
82 }`;
83 });
84 }} ${(props) => {
85 const tabs = props.tabs || [];
86 return tabs.map(
87 value => `
88 #${value.id}:checked ~ .tabs #${value.id}-label {
89 border-bottom: none;
90 }
91 #${value.id}:checked ~ .tabs #${value.id}-panel {
92 border-bottom: 1px solid #ccc;
93 }`,
94 );
95 }};
96 }
97`;
98
99class Tab extends PureComponent {
100 constructor(props) {
101 super(props);
102 const propsTabs = this.props.tabs || [];
103 const tabVisible = this.props.tabVisible || {};
104
105 this.updateTabs = (pTabs, pTabVisible) => {
106 let tabsAlterKeys = [];
107 const newValue = [];
108 const itens = {};
109
110 if (Object.keys(pTabVisible).length >= 1) {
111 pTabs.map(value => newValue.push(pTabVisible[value.id] || false));
112 }
113
114 const tabsAlter = {
115 visible: {
116 newValue,
117 },
118 };
119
120 const newTabs = pTabs.map((oKey, index) => {
121 tabsAlterKeys = Object.keys(tabsAlter);
122 tabsAlterKeys.map(
123 tabsKey =>
124 (itens[tabsKey] =
125 oKey[tabsKey] !== tabsAlter[tabsKey].newValue[index]
126 ? tabsAlter[tabsKey].newValue[index]
127 : oKey[tabsKey]),
128 );
129 return Object.assign({}, oKey, itens);
130 });
131
132 return newTabs;
133 };
134
135 this.state = { newTabs: this.updateTabs(propsTabs, tabVisible) };
136
137 this.handleInputChange = this.handleInputChange.bind(this);
138 this.renderInputs = this.renderInputs.bind(this);
139 this.renderLabels = this.renderLabels.bind(this);
140 }
141
142 componentWillReceiveProps(nextProps) {
143 if (!Object.is(this.props, nextProps)) {
144 this.setState({ newTabs: this.updateTabs(nextProps.tabs, nextProps.tabVisible) });
145 }
146 }
147
148 setRadioChecked(value) {
149 const selected =
150 this.props.selected || this.props.tabs.filter(key => key.active === true)[0].id;
151
152 return selected === value.id;
153 }
154
155 handleInputChange(event) {
156 this.props.selectTab(event.target.id);
157 }
158
159 renderInputs() {
160 return this.state.newTabs.map(value =>
161 (<If key={`if-input-${value.id}`} test={value.visible}>
162 <input
163 key={value.id}
164 className="state"
165 type="radio"
166 title={value.id}
167 name="tabs-state"
168 id={value.id}
169 checked={this.setRadioChecked(value)}
170 onChange={this.handleInputChange}
171 />
172 </If>),
173 );
174 }
175
176 renderLabels() {
177 return this.state.newTabs.map(value =>
178 (<If key={`if-label-${value.id}`} test={value.visible}>
179 <label
180 key={`label-${value.id}`}
181 htmlFor={value.id}
182 id={`${value.id}-label`}
183 className="tab"
184 >
185 {value.tabCaption}
186 </label>
187 </If>),
188 );
189 }
190
191 render() {
192 return (
193 <TabStyle tabs={this.state.newTabs}>
194 {this.renderInputs()}
195 <div className="tabs flex-tabs">
196 {this.renderLabels()}
197 {this.state.newTabs.map(value =>
198 (<If key={`if-panel-${value.id}`} test={value.visible}>
199 <div
200 key={`panel-${value.id}`}
201 id={`${value.id}-panel`}
202 className="flex-tabs panel active"
203 >
204 {value.content}
205 </div>
206 </If>),
207 )}
208 </div>
209 </TabStyle>
210 );
211 }
212}
213
214Tab.defaultProps = {
215 tabs: [{}],
216 selected: '',
217 tabVisible: {},
218};
219
220Tab.propTypes = {
221 tabs: PropTypes.arrayOf(PropTypes.object),
222 selected: PropTypes.string,
223 tabVisible: PropTypes.object,
224};
225
226const mapStateToProps = state => ({
227 selected: state.tab.selected,
228 tabVisible: state.tab.tabVisible,
229});
230const mapDispatchToProps = dispatch => bindActionCreators({ selectTab }, dispatch);
231
232export default connect(mapStateToProps, mapDispatchToProps)(Tab);
233
\No newline at end of file