1 |
|
2 | import React, { PureComponent } from 'react';
|
3 | import styled from 'styled-components';
|
4 | import { connect } from 'react-redux';
|
5 | import { bindActionCreators } from 'redux';
|
6 | import PropTypes from 'prop-types';
|
7 |
|
8 | import If from './operator/if';
|
9 | import { selectTab } from './tabActions';
|
10 |
|
11 | const 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 |
|
99 | class 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 |
|
214 | Tab.defaultProps = {
|
215 | tabs: [{}],
|
216 | selected: '',
|
217 | tabVisible: {},
|
218 | };
|
219 |
|
220 | Tab.propTypes = {
|
221 | tabs: PropTypes.arrayOf(PropTypes.object),
|
222 | selected: PropTypes.string,
|
223 | tabVisible: PropTypes.object,
|
224 | };
|
225 |
|
226 | const mapStateToProps = state => ({
|
227 | selected: state.tab.selected,
|
228 | tabVisible: state.tab.tabVisible,
|
229 | });
|
230 | const mapDispatchToProps = dispatch => bindActionCreators({ selectTab }, dispatch);
|
231 |
|
232 | export default connect(mapStateToProps, mapDispatchToProps)(Tab);
|
233 |
|
\ | No newline at end of file |