diff --git a/README.md b/README.md
index 73fba873e..2acca5094 100644
--- a/README.md
+++ b/README.md
@@ -464,6 +464,11 @@ The element tags are the bread and butter of your slide content. Most of these t
This tag does not extend from Base. It's special. Wrapping elements in the appear tag makes them appear/disappear in order in response to navigation.
+|Name|PropType|Description|
+|---|---|---|
+|order|PropTypes.number| An optional integer starting at 1 for the presentation order of the Appear tags within a slide. If a slide contains ordered and unordered Appear tags, the unordered will show first.
+
+
#### BlockQuote, Quote and Cite (Base)
diff --git a/src/components/appear.js b/src/components/appear.js
index f186ca2b9..7249ff7e4 100644
--- a/src/components/appear.js
+++ b/src/components/appear.js
@@ -21,6 +21,13 @@ class Appear extends Component {
this.setState({ active: true });
return;
}
+
+ const order = this.props.order || 0;
+ const node = findDOMNode(this.fragmentRef);
+ if (!node.dataset) {
+ node.dataset = {};
+ }
+ node.dataset.order = order;
}
componentWillReceiveProps(nextProps) {
@@ -55,7 +62,6 @@ class Appear extends Component {
const child = React.Children.only(this.props.children);
const endValue = this.state.active ? 1 : 0;
const transitionDuration = this.props.transitionDuration;
-
return (
{({ opacity }) =>
React.cloneElement(child, {
- className: 'fragment',
+ className: `fragment ${child.props.className}`.trim(),
style: { ...child.props.style, ...this.props.style, opacity },
ref: f => {
this.fragmentRef = f;
@@ -82,6 +88,7 @@ Appear.defaultProps = {
Appear.propTypes = {
children: PropTypes.node,
fragment: PropTypes.object,
+ order: PropTypes.number,
route: PropTypes.object,
style: PropTypes.object,
transitionDuration: PropTypes.number
diff --git a/src/components/slide.js b/src/components/slide.js
index 1bb92a4d8..f5e4fac31 100644
--- a/src/components/slide.js
+++ b/src/components/slide.js
@@ -32,20 +32,24 @@ class Slide extends React.PureComponent {
this.setZoom();
const slide = this.slideRef;
const frags = slide.querySelectorAll('.fragment');
+ let currentOrder = 0;
if (frags && frags.length && !this.context.overview) {
- Array.prototype.slice.call(frags, 0).forEach((frag, i) => {
- frag.dataset.fid = i;
- return (
- this.props.dispatch &&
- this.props.dispatch(
- addFragment({
- slide: this.props.hash,
- id: `${this.props.slideIndex}-${i}`,
- visible: this.props.lastSlideIndex > this.props.slideIndex,
- })
- )
- );
- });
+ Array.prototype.slice.call(frags, 0)
+ .sort((lhs, rhs) => parseInt(lhs.dataset.order, 10) - parseInt(rhs.dataset.order, 10))
+ .forEach(frag => {
+ frag.dataset.fid = currentOrder;
+ if (this.props.dispatch) {
+ this.props.dispatch(
+ addFragment({
+ className: frag.className || '',
+ slide: this.props.hash,
+ id: `${this.props.slideIndex}-${currentOrder}`,
+ visible: this.props.lastSlideIndex > this.props.slideIndex,
+ })
+ );
+ }
+ currentOrder += 1;
+ });
}
window.addEventListener('load', this.setZoom);
window.addEventListener('resize', this.setZoom);
diff --git a/src/components/slide.test.js b/src/components/slide.test.js
index 3283f41c5..6e8c2c558 100644
--- a/src/components/slide.test.js
+++ b/src/components/slide.test.js
@@ -1,6 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import Slide from './slide';
+import Appear from './appear';
const _mockContext = function() {
return {
@@ -15,7 +16,9 @@ const _mockContext = function() {
},
},
store: {
- getState: () => ({ route: '' }),
+ getState: () => ({ route: { params: '', slide: 0 } }),
+ subscribe: () => {},
+ dispatch: () => {}
},
};
};
@@ -75,4 +78,70 @@ describe('', () => {
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toBeCalledWith(5);
});
+
+ test('should create fragments with their appearance in order', () => {
+ const spy = jest.fn();
+ mount(
+
+
+ This shows second
+
+
+ This shows third
+
+
+ This shows first
+
+ ,
+ { context: _mockContext() }
+ );
+ expect(spy).toHaveBeenCalledTimes(3);
+ expect(spy.mock.calls).toEqual([
+ [{
+ payload: { slide: 4, id: '4-0', visible: false, className: 'fragment first' },
+ type: 'ADD_FRAGMENT'
+ }],
+ [{
+ payload: { slide: 4, id: '4-1', visible: false, className: 'fragment second' },
+ type: 'ADD_FRAGMENT'
+ }],
+ [{
+ payload: { slide: 4, id: '4-2', visible: false, className: 'fragment third' },
+ type: 'ADD_FRAGMENT'
+ }]
+ ]);
+ });
+
+ test('should order fragments without an order first', () => {
+ const spy = jest.fn();
+ mount(
+
+
+ This shows second
+
+
+ This shows third
+
+
+ This shows first
+
+ ,
+ { context: _mockContext() }
+ );
+ expect(spy).toHaveBeenCalledTimes(3);
+ expect(spy.mock.calls).toEqual([
+ [{
+ payload: { slide: 7, id: '7-0', visible: false, className: 'fragment no-order' },
+ type: 'ADD_FRAGMENT'
+ }],
+ [{
+ payload: { slide: 7, id: '7-1', visible: false, className: 'fragment first' },
+ type: 'ADD_FRAGMENT'
+ }],
+ [{
+ payload: { slide: 7, id: '7-2', visible: false, className: 'fragment second' },
+ type: 'ADD_FRAGMENT'
+ }]
+ ]);
+ });
});