@spothero/ui 15.1.0 → 15.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +0 -18
  2. package/package.json +2 -3
  3. package/styles/v2/components/Modal/styles/dialogContainer.js +0 -1
  4. package/styles/v2/components/Radio/Radio.jsx +1 -1
  5. package/styles/v2/components/Radio/RadioGroup.jsx +1 -1
  6. package/v2/index.js +1 -1
  7. package/v2/index.js.map +1 -1
  8. package/styles/Alert/Alert.jsx +0 -45
  9. package/styles/Alert/Alert.spec.js +0 -85
  10. package/styles/AutoSuggestInput/AutoSuggestInput.jsx +0 -429
  11. package/styles/AutoSuggestInput/AutoSuggestInput.spec.js +0 -132
  12. package/styles/AutoSuggestInput/AutoSuggestItem.jsx +0 -61
  13. package/styles/AutoSuggestInput/AutoSuggestList.jsx +0 -85
  14. package/styles/Badge/Badge.jsx +0 -24
  15. package/styles/Badge/Badge.spec.js +0 -43
  16. package/styles/Chart/Chart.jsx +0 -185
  17. package/styles/Chart/Chart.spec.js +0 -369
  18. package/styles/Checkbox/Checkbox.jsx +0 -159
  19. package/styles/Checkbox/Checkbox.spec.js +0 -142
  20. package/styles/DateTime/DatePicker.jsx +0 -281
  21. package/styles/DateTime/DatePicker.spec.js +0 -186
  22. package/styles/DateTime/DatePickerCalendar.jsx +0 -170
  23. package/styles/DateTime/DatePickerCalendarNavigation.jsx +0 -44
  24. package/styles/DateTime/DatePickerCalendarWithRange.jsx +0 -218
  25. package/styles/DateTime/DateTimePicker.jsx +0 -266
  26. package/styles/DateTime/DateTimePicker.spec.js +0 -60
  27. package/styles/DateTime/DateTimeRangePicker.jsx +0 -629
  28. package/styles/DateTime/DateTimeRangePicker.spec.js +0 -425
  29. package/styles/DateTime/TimePicker.jsx +0 -158
  30. package/styles/DateTime/TimePicker.spec.js +0 -148
  31. package/styles/DateTime/date-time-assertions.js +0 -89
  32. package/styles/DateTime/index.js +0 -6
  33. package/styles/ErrorBoundary/ErrorBoundary.jsx +0 -76
  34. package/styles/ErrorBoundary/ErrorBoundary.spec.js +0 -72
  35. package/styles/Flyout/Flyout.jsx +0 -147
  36. package/styles/Flyout/Flyout.spec.js +0 -117
  37. package/styles/Form/Form.jsx +0 -151
  38. package/styles/Form/Form.spec.js +0 -148
  39. package/styles/Form/FormElementError.jsx +0 -18
  40. package/styles/Form/FormGroup.jsx +0 -32
  41. package/styles/Form/FormGroupError.jsx +0 -24
  42. package/styles/Form/index.js +0 -4
  43. package/styles/GooglePlacesSearchInput/GooglePlacesSearchInput.jsx +0 -215
  44. package/styles/GooglePlacesSearchInput/GooglePlacesSearchInput.spec.js +0 -213
  45. package/styles/GooglePlacesSearchInput/PoweredByGoogle.jsx +0 -43
  46. package/styles/GooglePlacesSearchInput/index.js +0 -2
  47. package/styles/HorizontalRule/HorizontalRule.jsx +0 -36
  48. package/styles/HorizontalRule/HorizontalRule.spec.js +0 -94
  49. package/styles/Label/Label.jsx +0 -22
  50. package/styles/Label/Label.spec.js +0 -11
  51. package/styles/Notification/Notification.jsx +0 -117
  52. package/styles/Notification/Notification.spec.js +0 -154
  53. package/styles/Notification/NotificationContainer.jsx +0 -90
  54. package/styles/Notification/NotificationPropTypes.js +0 -20
  55. package/styles/Notification/index.js +0 -2
  56. package/styles/PasswordControl/PasswordControl.jsx +0 -197
  57. package/styles/PasswordControl/PasswordControl.spec.js +0 -236
  58. package/styles/Portal/Portal.jsx +0 -65
  59. package/styles/Portal/Portal.spec.js +0 -45
  60. package/styles/PulseLoader/PulseLoader.jsx +0 -71
  61. package/styles/PulseLoader/PulseLoader.spec.js +0 -63
  62. package/styles/Radio/Radio.jsx +0 -114
  63. package/styles/Radio/Radio.spec.js +0 -128
  64. package/styles/Radio/RadioGroup.jsx +0 -105
  65. package/styles/Radio/index.js +0 -2
  66. package/styles/RenderInBody/RenderInBody.jsx +0 -56
  67. package/styles/RenderInBody/RenderInBody.spec.js +0 -24
  68. package/styles/Select/Select.jsx +0 -251
  69. package/styles/Select/Select.spec.js +0 -254
  70. package/styles/Select/SelectItemPropTypes.js +0 -19
  71. package/styles/Select/index.js +0 -2
  72. package/styles/SelectControlled/SelectControlled.jsx +0 -250
  73. package/styles/SelectControlled/SelectControlled.spec.js +0 -290
  74. package/styles/SelectControlled/index.js +0 -1
  75. package/styles/Sprite/Sprite.jsx +0 -16
  76. package/styles/Sprite/Sprite.spec.js +0 -11
  77. package/styles/Tabs/Tab.jsx +0 -38
  78. package/styles/Tabs/TabContent.jsx +0 -46
  79. package/styles/Tabs/TabNavigation.jsx +0 -64
  80. package/styles/Tabs/TabPanel.jsx +0 -30
  81. package/styles/Tabs/Tabs.jsx +0 -87
  82. package/styles/Tabs/Tabs.spec.js +0 -201
  83. package/styles/Tabs/index.js +0 -5
  84. package/styles/TextArea/TextArea.jsx +0 -137
  85. package/styles/TextArea/TextArea.spec.js +0 -111
  86. package/styles/TextInput/TextInput.jsx +0 -159
  87. package/styles/TextInput/TextInput.spec.js +0 -263
  88. package/styles/TextInput/TextInputPropTypes.js +0 -88
  89. package/styles/TextInput/index.js +0 -2
  90. package/styles/Tooltip/Tooltip.jsx +0 -230
  91. package/styles/Tooltip/Tooltip.spec.js +0 -170
@@ -1,290 +0,0 @@
1
- describe('<SelectControlled />', () => {
2
- context('Display', () => {
3
- context('Default', () => {
4
- it('Renders select and options', () => {
5
- cy.visitStory('v1/SelectControlled/Display', 'Default')
6
- // make sure it's a Select component
7
- .get('.SelectDefault')
8
- .should('have.class', 'Select')
9
- // make sure dropdown exists
10
- .get('.Select-dropdown-icon')
11
- .should('exist')
12
- // make sure options are what we expect
13
- .get('option')
14
- .eq(0)
15
- .should('have.value', 'Option 1')
16
- .get('option')
17
- .eq(4)
18
- .should('have.value', 'Option 5');
19
- });
20
- });
21
-
22
- context('With Optional Props', () => {
23
- it('Renders proper elements based on optional props', () => {
24
- cy.visitStory('v1/SelectControlled/Display', 'WithProps', {
25
- onBeforeLoad: contentWindow => {
26
- contentWindow.onSelectFormSubmit = evt => {
27
- console.log('onSelectFormSubmit'); // eslint-disable-line no-console
28
- };
29
-
30
- cy.stub(contentWindow, 'onSelectFormSubmit').as(
31
- 'selectFormSubmit'
32
- );
33
- },
34
- })
35
- // make sure select is required
36
- .get('.SelectWithProps select.FormElement-item')
37
- .should('have.attr', 'required')
38
- // make sure select is rendered inline
39
- .get('.SelectWithProps')
40
- .should('have.class', 'FormElement-inline')
41
- // make sure label renders properly
42
- .get('.SelectWithProps .Label')
43
- .contains('Select Dropdown')
44
- // make sure placeholder renders properly
45
- .get('option')
46
- .eq(0)
47
- .contains('Please select an item')
48
- .should('have.attr', 'disabled', 'disabled')
49
- // make sure Select-icon renders
50
- .get('.Select-icon > .Icon')
51
- .should('have.class', 'Icon-info')
52
- // make sure help node renders
53
- .get('.FormElement-help-text')
54
- .contains(
55
- 'This is where some helpful information might appear.'
56
- )
57
- // after submit without selected, make sure error shows
58
- .get('.SelectWithProps-submit')
59
- .click()
60
- .get('@selectFormSubmit')
61
- .should('be.calledWith', null)
62
- .get('.SelectWithProps')
63
- .should('have.class', 'FormElement-contains-error')
64
- .get('.FormElementError')
65
- .contains('Please select an option');
66
- });
67
- });
68
-
69
- context('Disabled', () => {
70
- it('Has disabled attribute', () => {
71
- cy.visitStory('v1/SelectControlled/Display', 'Disabled')
72
- .get('.Select .FormElement-item')
73
- .should('have.attr', 'disabled', 'disabled');
74
- });
75
- });
76
-
77
- context('With Option Groups', () => {
78
- it('Renders select with option groups', () => {
79
- cy.visitStory('v1/SelectControlled/Display', 'WithOptionGroups')
80
- // make sure optgroup exists and has options
81
- .get('optgroup')
82
- .eq(0)
83
- .should('have.attr', 'label', 'Option Group A')
84
- .get('optgroup')
85
- .eq(1)
86
- .should('have.attr', 'label', 'Option Group B')
87
- .get('option')
88
- .eq(0)
89
- .should('have.value', 'Option A')
90
- .get('option')
91
- .eq(4)
92
- .should('have.value', 'Option E');
93
- });
94
- });
95
-
96
- context('With Mixed Options', () => {
97
- it('Renders select with mixed items and option groups', () => {
98
- cy.visitStory('v1/SelectControlled/Display', 'WithMixedOptions')
99
- // Check optgroups are rendered
100
- .get('optgroup')
101
- .should('have.length', 2)
102
- .get('optgroup')
103
- .eq(0)
104
- .should('have.attr', 'label', 'Option Group A')
105
- .get('optgroup')
106
- .eq(1)
107
- .should('have.attr', 'label', 'Option Group B')
108
- // Check options have the right values
109
- .get('option')
110
- .should('have.length', 15)
111
- .get('option')
112
- .eq(1)
113
- .should('have.value', 'Option B')
114
- .get('option')
115
- .eq(4)
116
- .should('have.value', 'Option E')
117
- .get('option')
118
- .eq(8)
119
- .should('have.value', 'Option I')
120
- .get('option')
121
- .eq(11)
122
- .should('have.value', 'Option 2');
123
- });
124
- });
125
-
126
- context('Loading', () => {
127
- it('Has loader', () => {
128
- cy.visitStory('v1/SelectControlled/Display', 'Loading')
129
- .get('.Loader')
130
- .should('exist')
131
- .parent()
132
- .parent()
133
- .should('have.class', 'Select');
134
- });
135
- });
136
-
137
- context('Custom Icon', () => {
138
- it('Has a custom dropdown icon', () => {
139
- cy.visitStory('v1/SelectControlled/Display', 'WithCustomIcon')
140
- .get('.Select-dropdown-icon')
141
- .should('have.class', 'Icon-settings');
142
- });
143
- });
144
-
145
- context('Default Value', () => {
146
- it('Renders with default value selected', () => {
147
- cy.visitStory('v1/SelectControlled/Display', 'WithDefaultValue')
148
- // make sure default value is selected
149
- .get('option:selected')
150
- .contains('Option 3')
151
- .should('have.value', 'Option 3');
152
- });
153
- });
154
-
155
- context('With Value', () => {
156
- it('Renders with specified value selected', () => {
157
- cy.visitStory('v1/SelectControlled/Display', 'WithValue')
158
- .get('option:selected')
159
- .contains('Option 2')
160
- .should('have.value', 'Option 2');
161
- });
162
-
163
- it('Changes specified value', () => {
164
- cy.visitStory('v1/SelectControlled/Display', 'WithValue')
165
- .get('select')
166
- .select('Option 4')
167
- .get('option:selected')
168
- .contains('Option 4')
169
- .should('have.value', 'Option 4');
170
- });
171
- });
172
- });
173
-
174
- context('Methods', () => {
175
- context('OnChange', () => {
176
- it('OnChange method functions properly', () => {
177
- cy.visitStory('v1/SelectControlled/Methods', 'OnChange', {
178
- onBeforeLoad: contentWindow => {
179
- contentWindow.onSelectChange = ({label, value}) => {
180
- console.log('onSelectChange'); // eslint-disable-line no-console
181
- };
182
-
183
- cy.stub(contentWindow, 'onSelectChange').as(
184
- 'selectChange'
185
- );
186
- },
187
- })
188
- // fill form
189
- .get('.Select')
190
- .as('item')
191
- .selectItem({alias: 'item', value: 'Option 2'})
192
- // calls the onChange method
193
- .get('@selectChange')
194
- .should('be.calledWith', {
195
- label: 'Option 2',
196
- value: 'Option 2',
197
- });
198
- });
199
-
200
- context('With Value', () => {
201
- it('OnChange method functions properly', () => {
202
- cy.visitStory('v1/SelectControlled/Display', 'WithValue', {
203
- onBeforeLoad: contentWindow => {
204
- contentWindow.onSelectChange = ({label, value}) => {
205
- console.log('onSelectChange'); // eslint-disable-line no-console
206
- };
207
-
208
- cy.stub(contentWindow, 'onSelectChange').as(
209
- 'selectChange'
210
- );
211
- },
212
- })
213
- // fill form
214
- .get('.Select')
215
- .as('item')
216
- .selectItem({alias: 'item', value: 'Option 2'})
217
- // calls the onChange method
218
- .get('@selectChange')
219
- .should('be.calledWith', {
220
- label: 'Option 2',
221
- value: 'Option 2',
222
- });
223
- });
224
- });
225
- });
226
-
227
- context('OnFocus', () => {
228
- it('OnFocus method functions properly', () => {
229
- cy.visitStory('v1/SelectControlled/Methods', 'OnFocus', {
230
- onBeforeLoad: contentWindow => {
231
- contentWindow.onSelectFocus = evt => {
232
- console.log('onSelectFocus'); // eslint-disable-line no-console
233
- };
234
-
235
- cy.stub(contentWindow, 'onSelectFocus').as(
236
- 'selectFocus'
237
- );
238
- },
239
- })
240
- // fill form
241
- .get('.Select')
242
- .as('item')
243
- .selectItem({alias: 'item', value: 'Option 2'})
244
- // calls the onFocus method
245
- .get('@selectFocus')
246
- .should('be.called');
247
- });
248
- });
249
-
250
- context('OnInvalid', () => {
251
- it('OnInvalid method functions properly and form is submitted when valid', () => {
252
- cy.visitStory('v1/SelectControlled/Methods', 'OnInvalid', {
253
- onBeforeLoad: contentWindow => {
254
- contentWindow.onSelectFormSubmit = evt => {
255
- console.log('onSelectFormSubmit'); // eslint-disable-line no-console
256
- };
257
-
258
- contentWindow.onSelectInvalid = validationState => {
259
- console.log('onSelectInvalid'); // eslint-disable-line no-console
260
- };
261
-
262
- cy.stub(contentWindow, 'onSelectFormSubmit').as(
263
- 'selectFormSubmit'
264
- );
265
-
266
- cy.stub(contentWindow, 'onSelectInvalid').as(
267
- 'selectInvalid'
268
- );
269
- },
270
- })
271
- .get('.SelectMethods-submit')
272
- .click()
273
- // check validity
274
- .get('@selectInvalid')
275
- .should('be.called')
276
- // fill form
277
- .get('.Select')
278
- .as('item')
279
- .selectItem({alias: 'item', value: 'Option 2'})
280
- // submit after item is selected
281
- .get('.SelectMethods-submit')
282
- .click()
283
- .get('@selectFormSubmit')
284
- .should('be.calledWith', {
285
- select: 'Option 2',
286
- });
287
- });
288
- });
289
- });
290
- });
@@ -1 +0,0 @@
1
- export {default as SelectControlled} from './SelectControlled';
@@ -1,16 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
-
5
- const Sprite = ({className, name}) => {
6
- const classes = classNames('Sprite', `sprite-${name}`, className);
7
-
8
- return <i className={classes} />;
9
- };
10
-
11
- Sprite.propTypes = {
12
- className: PropTypes.string,
13
- name: PropTypes.string.isRequired,
14
- };
15
-
16
- export default Sprite;
@@ -1,11 +0,0 @@
1
- describe('<Sprite />', () => {
2
- context('Display', () => {
3
- context('Name', () => {
4
- it('Renders properly', () => {
5
- cy.visitStory('v1/Sprite/Display', 'Default')
6
- .get('.Sprite')
7
- .should('have.class', 'sprite-test');
8
- });
9
- });
10
- });
11
- });
@@ -1,38 +0,0 @@
1
- import React, {Component} from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
- import Button from 'v1/components/Button/Button';
5
-
6
- export default class Tab extends Component {
7
- static propTypes = {
8
- /** Additional class(es) to add to the component. */
9
- className: PropTypes.string,
10
- /** The content to render inside of the tab. */
11
- children: PropTypes.node.isRequired,
12
- /** The label to put in the dropdown when the tabs are on small viewports. Not used in this component but gets read in TabNavigation to create the dropdown. */
13
- label: PropTypes.string.isRequired, // eslint-disable-line react/no-unused-prop-types
14
- /** Whether this tab should be active. Automatically passed from TabNavigation, do not set manually. */
15
- active: PropTypes.bool,
16
- /** The method to call when this tab is clicked. Automatically passed from TabNavigation, do not set manually. */
17
- onTabClick: PropTypes.func,
18
- /** The index that corresponds to this tab. Automatically passed from TabNavigation, do not set manually. */
19
- index: PropTypes.number,
20
- };
21
-
22
- _onClick = evt => {
23
- const {index, onTabClick} = this.props;
24
-
25
- onTabClick(index);
26
- };
27
-
28
- render() {
29
- const {className, children, active} = this.props;
30
- const classes = classNames('Tab', {'Tab-active': active}, className);
31
-
32
- return (
33
- <Button className={classes} role="tab" onClick={this._onClick}>
34
- {children}
35
- </Button>
36
- );
37
- }
38
- }
@@ -1,46 +0,0 @@
1
- import React, {Children, cloneElement} from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
-
5
- const TabContent = ({className, children, selectedIndex, renderActiveOnly}) => {
6
- const classes = classNames('TabContent', className);
7
-
8
- return (
9
- <div className={classes}>
10
- {Children.map(children, (panel, i) => {
11
- if (panel) {
12
- if (renderActiveOnly) {
13
- if (selectedIndex === i) {
14
- return cloneElement(panel, {
15
- active: true,
16
- index: i,
17
- });
18
- } else {
19
- return null;
20
- }
21
- } else {
22
- return cloneElement(panel, {
23
- active: selectedIndex === i,
24
- index: i,
25
- });
26
- }
27
- }
28
- })}
29
- </div>
30
- );
31
- };
32
-
33
- TabContent.propTypes = {
34
- /** Additional class(es) to add to the component. */
35
- className: PropTypes.string,
36
- /** Children should only be made up of TabPanel components or a false boolean value when a condition to render the TabPanel is false. */
37
- children: PropTypes.arrayOf(
38
- PropTypes.oneOfType([PropTypes.element, PropTypes.bool])
39
- ).isRequired,
40
- /** The selected tab index. Automatically passed from Tabs, do not set manually. */
41
- selectedIndex: PropTypes.number,
42
- /** Whether to only render the active tab's content or all content for every tab in the DOM. */
43
- renderActiveOnly: PropTypes.bool,
44
- };
45
-
46
- export default TabContent;
@@ -1,64 +0,0 @@
1
- import React, {PureComponent, Children, cloneElement} from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
- import Select from '../Select/Select';
5
-
6
- export default class TabNavigation extends PureComponent {
7
- static propTypes = {
8
- /** Additional class(es) to add to the component. */
9
- className: PropTypes.string,
10
- /** Children should only be made up of Tab components or a false boolean value when a condition to render the Tab is false. */
11
- children: PropTypes.arrayOf(
12
- PropTypes.oneOfType([PropTypes.element, PropTypes.bool])
13
- ).isRequired,
14
- /** The selected tab index. Automatically passed from Tabs, do not set manually. */
15
- selectedIndex: PropTypes.number,
16
- /** The method to call when a tab is clicked. Automatically passed from Tabs, do not set manually. */
17
- onTabClick: PropTypes.func,
18
- };
19
-
20
- constructor(props) {
21
- super(props);
22
-
23
- this._selectItems = Children.map(props.children, (tab, i) => {
24
- if (tab) {
25
- return {
26
- label: tab.props.label,
27
- value: i.toString(),
28
- };
29
- }
30
- });
31
- }
32
-
33
- _onSelectChange = ({value}) => {
34
- this.props.onTabClick(parseInt(value, 10));
35
- };
36
-
37
- render() {
38
- const {className, children, selectedIndex, onTabClick} = this.props;
39
- const classes = classNames('TabNavigation', className);
40
-
41
- return (
42
- <div className={classes} role="tablist">
43
- <div className="TabNavigation-links">
44
- {Children.map(children, (tab, i) => {
45
- if (tab) {
46
- return cloneElement(tab, {
47
- active: selectedIndex === i,
48
- index: i,
49
- onTabClick,
50
- });
51
- }
52
- })}
53
- </div>
54
- <Select
55
- key={new Date()}
56
- className="TabNavigation-select"
57
- defaultValue={selectedIndex.toString()}
58
- items={this._selectItems}
59
- onChange={this._onSelectChange}
60
- />
61
- </div>
62
- );
63
- }
64
- }
@@ -1,30 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
-
5
- const TabPanel = ({className, children, index, active}) => {
6
- const classes = classNames(
7
- 'TabPanel',
8
- {'TabPanel-active': active},
9
- className
10
- );
11
-
12
- return (
13
- <div className={classes} role="tabpanel">
14
- {children}
15
- </div>
16
- );
17
- };
18
-
19
- TabPanel.propTypes = {
20
- /** Additional class(es) to add to the component. */
21
- className: PropTypes.string,
22
- /** The content to render inside of the tab. */
23
- children: PropTypes.node.isRequired,
24
- /** Whether this panel should be active. Automatically passed from TabContent, do not set manually. */
25
- active: PropTypes.bool,
26
- /** The index that corresponds to this panel. Automatically passed from TabContainer, do not set manually. */
27
- index: PropTypes.number,
28
- };
29
-
30
- export default TabPanel;
@@ -1,87 +0,0 @@
1
- import React, {Children, Component, cloneElement} from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
-
5
- export default class Tabs extends Component {
6
- static propTypes = {
7
- /** Additional class(es) to add to the component. */
8
- className: PropTypes.string,
9
- /** The index of the selected tab, 0 based. */
10
- selectedIndex: PropTypes.number,
11
- /**
12
- * A function to execute when a tab is selected.
13
- *
14
- * @param {Number} selectedIndex - The currently selected tab index.
15
- */
16
- onSelect: PropTypes.func,
17
- /** Children should only be made up of TabNavigation (with nested Tab) and TabContent (with nested TabPanel) components. The number of nested components for each should be equal to each other. */
18
- children: PropTypes.arrayOf(PropTypes.element).isRequired,
19
- };
20
- static defaultProps = {
21
- selectedIndex: 0,
22
- };
23
- state = {
24
- selectedIndex: this.props.selectedIndex,
25
- };
26
-
27
- constructor(props) {
28
- super(props);
29
-
30
- const {numTabs, numPanels} = this._getNumItems();
31
-
32
- if (numTabs !== numPanels) {
33
- throw new Error(
34
- 'The number of Tab components must correspond to the number of TabPanel components provided.'
35
- );
36
- }
37
- }
38
-
39
- componentDidUpdate(prevProps, prevState) {
40
- const {onSelect} = this.props;
41
- const {selectedIndex} = this.state;
42
-
43
- if (prevState.selectedIndex !== selectedIndex && onSelect) {
44
- onSelect(selectedIndex);
45
- }
46
- }
47
-
48
- _getNumItems() {
49
- const {children} = this.props;
50
-
51
- return {
52
- numTabs: Children.count(children[0].props.children),
53
- numPanels: Children.count(children[1].props.children),
54
- };
55
- }
56
-
57
- _selectTab = index => {
58
- this.setState({
59
- selectedIndex: index,
60
- });
61
- };
62
-
63
- _renderNavigation(nav) {
64
- return cloneElement(nav, {
65
- selectedIndex: this.state.selectedIndex,
66
- onTabClick: this._selectTab,
67
- });
68
- }
69
-
70
- _renderContent(content) {
71
- return cloneElement(content, {
72
- selectedIndex: this.state.selectedIndex,
73
- });
74
- }
75
-
76
- render() {
77
- const {className, children} = this.props;
78
- const classes = classNames('Tabs', className);
79
-
80
- return (
81
- <div className={classes}>
82
- {this._renderNavigation(children[0])}
83
- {this._renderContent(children[1])}
84
- </div>
85
- );
86
- }
87
- }