Skip to content

Commit 77fba0d

Browse files
Adds possibility of custom uuid
1 parent f920894 commit 77fba0d

File tree

9 files changed

+198
-32
lines changed

9 files changed

+198
-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
@@ -139,6 +139,12 @@ We recommend that you copy them into your own app and modify them to suit your n
139139
<td>null</td>
140140
<td>Class name for hidden body state</td>
141141
</tr>
142+
<tr>
143+
<td>uuid</td>
144+
<td>String</td>
145+
<td>null</td>
146+
<td>Custom uuid to be passed to Accordion - onChange. Has to be unique.</td>
147+
</tr>
142148
</tbody>
143149
</table>
144150

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/__snapshots__/accordion-item.spec.js.snap

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
exports[`AccordionItem renders correctly with accordion false 1`] = `
44
<div
55
className="accordion__item"
6+
itemstore={
7+
ItemContainer {
8+
"_listeners": Array [
9+
[Function],
10+
[Function],
11+
[Function],
12+
],
13+
"state": Object {
14+
"uuid": 0,
15+
},
16+
}
17+
}
618
>
719
<div
820
aria-controls="accordion__body-0"
@@ -36,6 +48,18 @@ exports[`AccordionItem renders correctly with accordion false 1`] = `
3648
exports[`AccordionItem renders correctly with accordion true 1`] = `
3749
<div
3850
className="accordion__item"
51+
itemstore={
52+
ItemContainer {
53+
"_listeners": Array [
54+
[Function],
55+
[Function],
56+
[Function],
57+
],
58+
"state": Object {
59+
"uuid": 0,
60+
},
61+
}
62+
}
3963
>
4064
<div
4165
aria-controls="accordion__body-0"
@@ -69,6 +93,18 @@ exports[`AccordionItem renders correctly with accordion true 1`] = `
6993
exports[`AccordionItem renders correctly with other blocks inside 1`] = `
7094
<div
7195
className="accordion__item"
96+
itemstore={
97+
ItemContainer {
98+
"_listeners": Array [
99+
[Function],
100+
[Function],
101+
[Function],
102+
],
103+
"state": Object {
104+
"uuid": 0,
105+
},
106+
}
107+
}
72108
>
73109
<div
74110
aria-controls="accordion__body-0"
@@ -105,6 +141,18 @@ exports[`AccordionItem renders correctly with other blocks inside 1`] = `
105141
exports[`AccordionItem renders correctly with other blocks inside 2 1`] = `
106142
<div
107143
className="accordion__item"
144+
itemstore={
145+
ItemContainer {
146+
"_listeners": Array [
147+
[Function],
148+
[Function],
149+
[Function],
150+
],
151+
"state": Object {
152+
"uuid": 0,
153+
},
154+
}
155+
}
108156
>
109157
<div
110158
aria-controls="accordion__body-0"
@@ -141,6 +189,16 @@ exports[`AccordionItem renders correctly with other blocks inside 2 1`] = `
141189
exports[`AccordionItem still renders with no AccordionItemTitle or AccordionItemBody 1`] = `
142190
<div
143191
className="accordion__item"
192+
itemstore={
193+
ItemContainer {
194+
"_listeners": Array [
195+
[Function],
196+
],
197+
"state": Object {
198+
"uuid": 0,
199+
},
200+
}
201+
}
144202
>
145203
<div>
146204
Fake title
@@ -154,5 +212,15 @@ exports[`AccordionItem still renders with no AccordionItemTitle or AccordionItem
154212
exports[`AccordionItem still renders with no children at all 1`] = `
155213
<div
156214
className="accordion__item"
215+
itemstore={
216+
ItemContainer {
217+
"_listeners": Array [
218+
[Function],
219+
],
220+
"state": Object {
221+
"uuid": 0,
222+
},
223+
}
224+
}
157225
/>
158226
`;

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: null,
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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,18 @@ type AccordionItemProps = ElementProps<'div'> & {
1616

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

2132
accordionStore.addItem({
2233
uuid,

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)