Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,14 @@ If defined, allows to specify a different animation delay for each attribute

If defined, allows to specify a different animation easing for each attribute

<h3 id="children">
<a href="#children">#</a> children
</h3>

- Type: Any Valid React Node

If defined, the child node(s) will be created for each entry in dataset, allowing for complex nesting hierarchies of react-animated-dataset

## Contributing

If you make some edits and wish to test them locally you can run `yarn test`.
Expand Down
29 changes: 24 additions & 5 deletions build/AnimatedDataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ function AnimatedDataset(_ref) {
_ref$easingByAttr = _ref.easingByAttr,
easingByAttr = _ref$easingByAttr === void 0 ? {} : _ref$easingByAttr,
_ref$easing = _ref.easing,
easing = _ref$easing === void 0 ? easeCubic : _ref$easing;
easing = _ref$easing === void 0 ? easeCubic : _ref$easing,
children = _ref.children;
var ref = /*#__PURE__*/React.createRef();
var refOldAttrs = React.useRef();
React.useLayoutEffect(function () {
Expand All @@ -111,8 +112,10 @@ function AnimatedDataset(_ref) {
var eventsList = Object.keys(events);
var oldAttrs = refOldAttrs.current || {};
var animate = function animate() {
select(ref.current).selectAll(tag).data(dataset, keyFn).join(function (enter) {
return enter.append(tag).text(attrs.text).call(function (sel) {
select(ref.current).selectAll(tag).data(dataset, function (d) {
return d && keyFn(d) || select(this).attr("data-key");
}).join(function (enter) {
var enterEls = enter.append(tag).call(function (sel) {
attrsList.forEach(function (a) {
sel.attr(a, init.hasOwnProperty(a) ? init[a] : oldAttrs.hasOwnProperty(a) ? oldAttrs[a] : attrs[a]);
});
Expand All @@ -126,13 +129,17 @@ function AnimatedDataset(_ref) {
tran.attr(a, attrs[a]);
});
});
if (attrs.text) enterEls.text(attrs.text);
return enterEls;
}, function (update) {
return update.text(attrs.text).call(function (sel) {
var updateEls = update.call(function (sel) {
attrsList.forEach(function (a) {
var tran = disableAnimation ? sel : sel.transition(a).ease(easingByAttrParsed.hasOwnProperty(a) ? easingByAttrParsed[a] : easing).delay(delayByAttrParsed.hasOwnProperty(a) ? delayByAttrParsed[a] : delay).duration(durationByAttrParsed.hasOwnProperty(a) ? durationByAttrParsed[a] : duration);
tran.attr(a, attrs[a]);
});
});
if (attrs.text) updateEls.text(attrs.text);
return updateEls;
}, function (exit) {
return exit.call(function (sel) {
attrsList.forEach(function (a) {
Expand All @@ -151,7 +158,19 @@ function AnimatedDataset(_ref) {
}, [dataset, unparsedInit, keyFn, ref, tag, unparsedAttrs, duration, disableAnimation, unparsedEvents, delay, easing, durationByAttr, delayByAttr, easingByAttr]);
return /*#__PURE__*/React.createElement('g', {
ref: ref
});
},
// Create the structure first so that react can add the children
children && dataset.map(function (data) {
return /*#__PURE__*/React.createElement(tag, {
key: keyFn(data),
'data-key': keyFn(data)
}, children && React.Children.toArray(children).map(function (child) {
return /*#__PURE__*/React.cloneElement(child, {
key: child.toString(),
dataset: [data]
});
}));
}));
}

export { AnimatedDataset };
61 changes: 41 additions & 20 deletions src/AnimatedDataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function AnimatedDataset({
delayByAttr = {},
easingByAttr = {},
easing = easeCubic,
children,
}) {
const ref = React.createRef()
const refOldAttrs = React.useRef()
Expand All @@ -40,12 +41,11 @@ export function AnimatedDataset({
const animate = () => {
select(ref.current)
.selectAll(tag)
.data(dataset, keyFn)
.data(dataset, function (d) { return (d && keyFn(d)) || select(this).attr("data-key"); })
.join(
enter =>
enter
enter => {
const enterEls = enter
.append(tag)
.text(attrs.text)
.call(sel => {
attrsList.forEach(a => {
sel.attr(
Expand Down Expand Up @@ -79,23 +79,32 @@ export function AnimatedDataset({

tran.attr(a, attrs[a])
})
}),
update =>
update.text(attrs.text).call(sel => {
attrsList.forEach(a => {
const tran = disableAnimation
? sel
: sel
.transition(a)
.ease(easingByAttrParsed.hasOwnProperty(a) ? easingByAttrParsed[a] : easing)
.delay(delayByAttrParsed.hasOwnProperty(a) ? delayByAttrParsed[a] : delay)
.duration(
durationByAttrParsed.hasOwnProperty(a) ? durationByAttrParsed[a] : duration
)
})
if (attrs.text) enterEls.text(attrs.text)
return enterEls
},

update => {
const updateEls = update
.call(sel => {
attrsList.forEach(a => {
const tran = disableAnimation
? sel
: sel
.transition(a)
.ease(easingByAttrParsed.hasOwnProperty(a) ? easingByAttrParsed[a] : easing)
.delay(delayByAttrParsed.hasOwnProperty(a) ? delayByAttrParsed[a] : delay)
.duration(
durationByAttrParsed.hasOwnProperty(a) ? durationByAttrParsed[a] : duration
)

tran.attr(a, attrs[a])
tran.attr(a, attrs[a])
}
)
})
}),
if (attrs.text) updateEls.text(attrs.text)
return updateEls;
},

exit =>
exit.call(sel => {
Expand Down Expand Up @@ -139,5 +148,17 @@ export function AnimatedDataset({
easingByAttr,
])

return React.createElement('g', { ref })
return React.createElement(
'g',
{ ref },
// Create the structure first so that react can add the children
children && dataset.map(
(data) => React.createElement(
tag,
{ key: keyFn(data), 'data-key': keyFn(data) },
children && React.Children.toArray(children)
.map(child => React.cloneElement(child, { key: child.toString(), dataset: [data] }))
)
)
)
}
25 changes: 25 additions & 0 deletions tests/AnimatedDataset.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,29 @@ describe(AnimatedDataset, () => {
expect(callArguments[0]).toEqual(dataset[index])
expect(callArguments[1]).toEqual(index)
})

it('should allow nested nodes', () => {
const wrapper = mount(
<svg>
<AnimatedDataset
dataset={['Hello World', 'Goodbye World']}
tag="a"
attrs={{ href: "#test" }}
keyFn={t => t}
disableAnimation
>
<AnimatedDataset
tag="text"
attrs={{ text: t => t }}
keyFn={t => t}
disableAnimation
/>
</AnimatedDataset>
</svg>
)

expect(wrapper.find('g').first().html()).toMatchInlineSnapshot(
`"<g><a data-key=\\"Hello World\\" href=\\"#test\\"><g><text>Hello World</text></g></a><a data-key=\\"Goodbye World\\" href=\\"#test\\"><g><text>Goodbye World</text></g></a></g>"`
)
})
})