Skip to content

Commit c7ddfc9

Browse files
Merge pull request #83 from springload/feature/onchange-informative
Adds possibility of custom uuid
2 parents 8ac4ab8 + bcb736b commit c7ddfc9

File tree

8 files changed

+133
-32
lines changed

8 files changed

+133
-32
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
66
## Next
77

8+
### Added
9+
10+
* Possibility to have custom uuid on `AccordionItem` - suggested by https://github.com/springload/react-accessible-accordion/issues/70
11+
812
### Fixed
913

1014
* Fix rollup config after version bump - https://gist.github.com/Rich-Harris/d472c50732dab03efeb37472b08a3f32

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ We recommend that you copy them into your own app and modify them to suit your n
137137
<td>null</td>
138138
<td>Class name for hidden body state</td>
139139
</tr>
140+
<tr>
141+
<td>uuid</td>
142+
<td>String</td>
143+
<td>null</td>
144+
<td>Custom uuid to be passed to Accordion - onChange. Has to be unique.</td>
145+
</tr>
140146
</tbody>
141147
</table>
142148

demo/js/demo.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint no-console: 0 */
2+
// eslint-disable-next-line import/no-extraneous-dependencies
13
import 'babel-polyfill';
24
import React from 'react';
35
import ReactDOM from 'react-dom';
@@ -568,6 +570,39 @@ const Example = () => (
568570
</AccordionItemBody>
569571
</AccordionItem>
570572
</Accordion>
573+
574+
<h2 className="u-margin-top">Informative onChange</h2>
575+
576+
<Accordion onChange={itemUuid => console.log(itemUuid)}>
577+
<AccordionItem uuid="uniqueItem-1">
578+
<AccordionItemTitle>
579+
<h3 className="u-position-relative">
580+
Unique Item #1
581+
<div className="accordion__arrow" role="presentation" />
582+
</h3>
583+
</AccordionItemTitle>
584+
<AccordionItemBody>
585+
<p>
586+
If you open/close this item you should see
587+
`uniqueItem-1` printed in the console.
588+
</p>
589+
</AccordionItemBody>
590+
</AccordionItem>
591+
<AccordionItem uuid="uniqueItem-2">
592+
<AccordionItemTitle>
593+
<h3 className="u-position-relative">
594+
Unique Item #2
595+
<div className="accordion__arrow" role="presentation" />
596+
</h3>
597+
</AccordionItemTitle>
598+
<AccordionItemBody>
599+
<p>
600+
If you open/close this item you should see
601+
`uniqueItem-2` printed in the console.
602+
</p>
603+
</AccordionItemBody>
604+
</AccordionItem>
605+
</Accordion>
571606
</div>
572607
);
573608

src/AccordionItem/accordion-item-wrapper.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type AccordionItemWrapperProps = ElementProps<'div'> & {
1313
disabled: ?boolean,
1414
expanded: ?boolean,
1515
accordionStore: AccordionContainer,
16+
uuid?: string,
1617
};
1718

1819
const defaultProps = {
@@ -21,6 +22,7 @@ const defaultProps = {
2122
disabled: false,
2223
expanded: false,
2324
accordionStore: new AccordionContainer(),
25+
uuid: undefined,
2426
};
2527

2628
class AccordionItemWrapper extends Component<AccordionItemWrapperProps> {
@@ -31,13 +33,18 @@ class AccordionItemWrapper extends Component<AccordionItemWrapperProps> {
3133
return (
3234
<Provider inject={[this.itemContainer]}>
3335
<Subscribe to={[AccordionContainer, ItemContainer]}>
34-
{(accordionStore, itemStore) => (
35-
<AccordionItem
36-
{...this.props}
37-
uuid={itemStore.state.uuid}
38-
accordionStore={accordionStore}
39-
/>
40-
)}
36+
{(accordionStore, itemStore) => {
37+
let uuid = itemStore.state.uuid;
38+
if (this.props.uuid) uuid = this.props.uuid;
39+
return (
40+
<AccordionItem
41+
{...this.props}
42+
uuid={uuid}
43+
accordionStore={accordionStore}
44+
itemStore={itemStore}
45+
/>
46+
);
47+
}}
4148
</Subscribe>
4249
</Provider>
4350
);

src/AccordionItem/accordion-item.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,31 @@ import type { ElementProps } from 'react';
55

66
import classNames from 'classnames';
77
import AccordionContainer from '../AccordionContainer/AccordionContainer';
8+
import ItemContainer from '../ItemContainer/ItemContainer';
89

910
type AccordionItemProps = ElementProps<'div'> & {
1011
uuid: string | number,
1112
hideBodyClassName: ?string,
1213
disabled: ?boolean,
1314
expanded: ?boolean,
1415
accordionStore: AccordionContainer,
16+
itemStore: ItemContainer,
1517
};
1618

1719
class AccordionItem extends Component<AccordionItemProps, *> {
1820
componentWillMount() {
19-
const { uuid, accordionStore, disabled } = this.props;
21+
const { uuid, accordionStore, itemStore, disabled } = this.props;
22+
23+
itemStore.setUuid(uuid);
24+
25+
const currentItem = accordionStore.state.items.find(
26+
item => item.uuid === uuid,
27+
);
28+
if (currentItem)
29+
// eslint-disable-next-line no-console
30+
console.error(
31+
`AccordionItem error: One item already has the uuid "${uuid}". Uuid property must be unique. See: https://github.com/springload/react-accessible-accordion#accordionitem`,
32+
);
2033

2134
accordionStore.addItem({
2235
uuid,
@@ -48,6 +61,7 @@ class AccordionItem extends Component<AccordionItemProps, *> {
4861
accordionStore,
4962
disabled,
5063
expanded,
64+
itemStore,
5165
...rest
5266
} = this.props;
5367

src/AccordionItem/accordion-item.spec.js

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -248,31 +248,12 @@ describe('AccordionItem', () => {
248248
</Provider>,
249249
);
250250
resetNextUuid();
251-
const wrapperTwo = mount(
252-
<Provider inject={[accordionContainer]}>
253-
<AccordionItem />
254-
</Provider>,
255-
);
256-
expect(
257-
wrapperOne
258-
.find(Provider)
259-
.last()
260-
.props().uuid,
261-
).toEqual(
262-
wrapperTwo
263-
.find(Provider)
264-
.last()
265-
.props().uuid,
266-
);
267-
});
268251

269-
it('can manually reset the uuid', () => {
270-
const wrapperOne = mount(
271-
<Provider inject={[accordionContainer]}>
272-
<AccordionItem />
273-
</Provider>,
274-
);
275-
resetNextUuid();
252+
// Needed to avoid duplicate uuid error
253+
accordionContainer = new AccordionContainer();
254+
accordionContainer.setAccordion(false);
255+
accordionContainer.setOnChange(jest.fn());
256+
276257
const wrapperTwo = mount(
277258
<Provider inject={[accordionContainer]}>
278259
<AccordionItem />
@@ -318,4 +299,44 @@ describe('AccordionItem', () => {
318299

319300
expect(wrapper.find('div').instance().lang).toEqual('en');
320301
});
302+
303+
it('supports custom uuid', () => {
304+
const uuid = 'uniqueCustomID';
305+
mount(
306+
<Provider inject={[accordionContainer]}>
307+
<AccordionItem uuid={uuid}>
308+
<AccordionItemTitle>
309+
<div>Fake title</div>
310+
</AccordionItemTitle>
311+
</AccordionItem>
312+
</Provider>,
313+
);
314+
315+
expect(
316+
accordionContainer.state.items.filter(item => item.uuid === uuid)
317+
.length,
318+
).toEqual(1);
319+
});
320+
321+
it('raises console error in case of duplicate uuid', () => {
322+
const uuid = 'uniqueCustomID';
323+
jest.spyOn(global.console, 'error');
324+
mount(
325+
<Provider inject={[accordionContainer]}>
326+
<AccordionItem uuid={uuid}>
327+
<AccordionItemTitle>
328+
<div>Fake title</div>
329+
</AccordionItemTitle>
330+
</AccordionItem>
331+
<AccordionItem uuid={uuid}>
332+
<AccordionItemTitle>
333+
<div>Fake title</div>
334+
</AccordionItemTitle>
335+
</AccordionItem>
336+
</Provider>,
337+
);
338+
339+
// eslint-disable-next-line no-console
340+
expect(console.error).toBeCalled();
341+
});
321342
});

src/ItemContainer/ItemContainer.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ class ItemContainer extends Container<StoreState> {
1515
state = {
1616
uuid: nextUuid(),
1717
};
18+
19+
setUuid(customUuid: string) {
20+
this.setState({
21+
uuid: customUuid,
22+
});
23+
}
1824
}
1925

2026
export default ItemContainer;

src/ItemContainer/ItemContainer.spec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ describe('ItemContainer', () => {
66
it('correctly instantiates with all expected methods/state', () => {
77
const itemContainer = new ItemContainer();
88
expect(itemContainer.state.uuid).toBeDefined();
9+
expect(itemContainer.setUuid).toBeDefined();
10+
});
11+
12+
it('correctly sets the value', () => {
13+
const itemContainer = new ItemContainer();
14+
const uuid = 'uniqueID';
15+
itemContainer.setUuid(uuid);
16+
expect(itemContainer.state.uuid).toBe(uuid);
917
});
1018

1119
it('generated uuids are different', () => {

0 commit comments

Comments
 (0)