react-typist
Advanced tools
Comparing version 1.0.3 to 1.1.0
# React Typist Changelog | ||
### v1.0.3 (10/01/16) | ||
### v1.1.0 (03/26/17) | ||
- Features: | ||
+ Add new options: `onCharacterTyped` and `onLineTyped` (#22) | ||
- Fixes | ||
+ Fix text rendering issue in webkit/blink under certain widths (#13) | ||
- Development: | ||
+ Remove bower package | ||
### v1.0.3 (10/29/16) | ||
- Fixes | ||
+ Component no longer sets `isDone` state if unmounted | ||
@@ -8,0 +20,0 @@ |
@@ -126,2 +126,36 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
_this.typeLine = function (line, lineIdx) { | ||
if (!_this.mounted) { | ||
return Promise.resolve(); | ||
} | ||
var onLineTyped = _this.props.onLineTyped; | ||
return new Promise(function (resolve, reject) { | ||
_this.setState({ text: _this.state.text.concat(['']) }, function () { | ||
utils.eachPromise(line, _this.typeCharacter, line, lineIdx).then(function () { | ||
return onLineTyped(line, lineIdx); | ||
}).then(resolve).catch(reject); | ||
}); | ||
}); | ||
}; | ||
_this.typeCharacter = function (character, charIdx, line, lineIdx) { | ||
if (!_this.mounted) { | ||
return Promise.resolve(); | ||
} | ||
var onCharacterTyped = _this.props.onCharacterTyped; | ||
return new Promise(function (resolve) { | ||
var text = _this.state.text.slice(); | ||
text[lineIdx] += character; | ||
_this.setState({ text: text }, function () { | ||
onCharacterTyped(character, charIdx); | ||
var delay = _this.delayGenerator(line, lineIdx, character, charIdx); | ||
setTimeout(resolve, delay); | ||
}); | ||
}); | ||
}; | ||
_this.mounted = false; | ||
@@ -176,12 +210,3 @@ _this.linesToType = []; | ||
return utils.eachPromise(lines, function (line, idx) { | ||
if (!_this2.mounted) { | ||
return Promise.resolve(); | ||
} | ||
return new Promise(function (resolve) { | ||
_this2.setState({ text: _this2.state.text.concat(['']) }, function () { | ||
_this2.typeLine(line, idx).then(resolve); | ||
}); | ||
}); | ||
}).then(function () { | ||
return utils.eachPromise(lines, this.typeLine).then(function () { | ||
return _this2.onTypingDone(); | ||
@@ -191,21 +216,2 @@ }); | ||
}, { | ||
key: 'typeLine', | ||
value: function typeLine(line, lineIdx) { | ||
var _this3 = this; | ||
return utils.eachPromise(line, function (character, charIdx) { | ||
if (!_this3.mounted) { | ||
return Promise.resolve(); | ||
} | ||
return new Promise(function (resolve) { | ||
var text = _this3.state.text.slice(); | ||
text[lineIdx] += character; | ||
_this3.setState({ text: text }, function () { | ||
var delay = _this3.delayGenerator(line, lineIdx, character, charIdx); | ||
setTimeout(resolve, delay); | ||
}); | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -239,2 +245,4 @@ value: function render() { | ||
cursor: _react.PropTypes.object, | ||
onCharacterTyped: _react.PropTypes.func, | ||
onLineTyped: _react.PropTypes.func, | ||
onTypingDone: _react.PropTypes.func, | ||
@@ -249,2 +257,4 @@ delayGenerator: _react.PropTypes.func | ||
cursor: {}, | ||
onCharacterTyped: function onCharacterTyped() {}, | ||
onLineTyped: function onLineTyped() {}, | ||
onTypingDone: function onTypingDone() {}, | ||
@@ -290,16 +300,12 @@ delayGenerator: utils.gaussianRnd | ||
function Cursor() { | ||
var _ref; | ||
var _temp, _this, _ret; | ||
function Cursor(props) { | ||
_classCallCheck(this, Cursor); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var _this = _possibleConstructorReturn(this, (Cursor.__proto__ || Object.getPrototypeOf(Cursor)).call(this, props)); | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Cursor.__proto__ || Object.getPrototypeOf(Cursor)).call.apply(_ref, [this].concat(args))), _this), _this.state = { | ||
_this._isReRenderingCursor = false; | ||
_this.state = { | ||
shouldRender: _this.props.show | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
}; | ||
return _this; | ||
} | ||
@@ -320,2 +326,45 @@ | ||
}, { | ||
key: 'componentDidUpdate', | ||
value: function componentDidUpdate() { | ||
var _props = this.props; | ||
var show = _props.show; | ||
var isDone = _props.isDone; | ||
if (!show) { | ||
return; | ||
} | ||
if (isDone) { | ||
return; | ||
} | ||
if (this._isReRenderingCursor) { | ||
return; | ||
} | ||
// In webkit and blink, rendering the cursor alongside the text as it | ||
// animates sometimes causes the text to stop rendering when it reaches | ||
// a new line break, even though the underlying DOM /does/ contain | ||
// the text. This seems to happen when the space available for the text is | ||
// at a specific width that makes it so the line break happens within a | ||
// word. | ||
// Using dev tools, when in this state, if you modify the dom or any style, | ||
// it immediately renders all of the text in its correct position. | ||
// Given that observation, this is a hackish solutions that re-renders the | ||
// cursor every time a character is rendered, just to ensure that the text | ||
// is rendered correctly. | ||
// See #13 and #15 for more details | ||
this._reRenderCursor(); | ||
} | ||
}, { | ||
key: '_reRenderCursor', | ||
value: function _reRenderCursor() { | ||
var _this3 = this; | ||
this._isReRenderingCursor = true; | ||
this.setState({ shouldRender: false }, function () { | ||
_this3.setState({ shouldRender: true }, function () { | ||
_this3._isReRenderingCursor = false; | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -407,11 +456,12 @@ value: function render() { | ||
function eachPromise(arr, iterator) { | ||
var length = arr.length; | ||
for (var _len = arguments.length, extraArgs = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
extraArgs[_key - 2] = arguments[_key]; | ||
} | ||
return Array.from(arr).reduce(function (prev, current, idx) { | ||
var promiseReducer = function promiseReducer(prev, current, idx) { | ||
return prev.then(function () { | ||
return Promise.resolve(current).then(function (val) { | ||
return iterator(val, idx, length); | ||
}); | ||
return iterator.apply(undefined, [current, idx].concat(extraArgs)); | ||
}); | ||
}, Promise.resolve()); | ||
}; | ||
return Array.from(arr).reduce(promiseReducer, Promise.resolve()); | ||
} | ||
@@ -485,4 +535,4 @@ | ||
function extractTreeWithText() { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
@@ -489,0 +539,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.Typist=t(require("react")):e.Typist=t(e.react)}(this,function(e){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t["default"]=e,t}function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function u(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},l=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),c=n(1),p=o(c),f=n(2),y=o(f),d=n(4),h=r(d),v=function(e){function t(e){i(this,t);var n=a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.state={text:[],isDone:!1},n.onTypingDone=function(){n.mounted&&(n.setState({isDone:!0}),n.props.onTypingDone())},n.delayGenerator=function(e,t,r,o){var i=n.props.avgTypingDelay,a=n.props.stdTypingDelay;return n.props.delayGenerator(i,a,{line:e,lineIdx:t,character:r,charIdx:o,defDelayGenerator:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:a;return h.gaussianRnd(e,t)}})},n.mounted=!1,n.linesToType=[],e.children&&(n.linesToType=h.extractText(e.children)),n}return u(t,e),l(t,[{key:"componentDidMount",value:function(){this.mounted=!0;var e=this.props,t=e.children,n=e.startDelay;t?n>0&&"undefined"!=typeof window?setTimeout(this.typeAllLines.bind(this),n):this.typeAllLines():this.onTypingDone()}},{key:"shouldComponentUpdate",value:function(e,t){for(var n=0;n<t.text.length;n++){var r=this.state.text[n],o=t.text[n];if(r!==o&&o.length>0)return!0}return this.state.isDone!==t.isDone}},{key:"componentWillUnmount",value:function(){this.mounted=!1}},{key:"typeAllLines",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.linesToType;return h.eachPromise(t,function(t,n){return e.mounted?new Promise(function(r){e.setState({text:e.state.text.concat([""])},function(){e.typeLine(t,n).then(r)})}):Promise.resolve()}).then(function(){return e.onTypingDone()})}},{key:"typeLine",value:function(e,t){var n=this;return h.eachPromise(e,function(r,o){return n.mounted?new Promise(function(i){var a=n.state.text.slice();a[t]+=r,n.setState({text:a},function(){var a=n.delayGenerator(e,t,r,o);setTimeout(i,a)})}):Promise.resolve()})}},{key:"render",value:function(){var e=this.props,t=e.className,n=e.cursor,r=this.state.isDone,o=h.extractTreeWithText(this.props.children,this.state.text);return p["default"].createElement("div",{className:"Typist "+t},o,p["default"].createElement(y["default"],s({isDone:r},n)))}}]),t}(c.Component);v.propTypes={children:c.PropTypes.node,className:c.PropTypes.string,avgTypingDelay:c.PropTypes.number,stdTypingDelay:c.PropTypes.number,startDelay:c.PropTypes.number,cursor:c.PropTypes.object,onTypingDone:c.PropTypes.func,delayGenerator:c.PropTypes.func},v.defaultProps={className:"",avgTypingDelay:70,stdTypingDelay:25,startDelay:0,cursor:{},onTypingDone:function(){},delayGenerator:h.gaussianRnd},t["default"]=v},function(t,n){t.exports=e},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),s=n(1),l=r(s);n(3);var c=function(e){function t(){var e,n,r,a;o(this,t);for(var u=arguments.length,s=Array(u),l=0;l<u;l++)s[l]=arguments[l];return n=r=i(this,(e=t.__proto__||Object.getPrototypeOf(t)).call.apply(e,[this].concat(s))),r.state={shouldRender:r.props.show},a=n,i(r,a)}return a(t,e),u(t,[{key:"componentWillReceiveProps",value:function(e){var t=this,n=!this.props.isDone&&e.isDone&&this.props.hideWhenDone;n&&setTimeout(function(){return t.setState({shouldRender:!1})},this.props.hideWhenDoneDelay)}},{key:"render",value:function(){if(this.state.shouldRender){var e=this.props.blink?" Cursor--blinking":"";return l["default"].createElement("span",{className:"Cursor"+e},this.props.element)}return null}}]),t}(s.Component);c.propTypes={blink:s.PropTypes.bool,show:s.PropTypes.bool,element:s.PropTypes.node,hideWhenDone:s.PropTypes.bool,hideWhenDoneDelay:s.PropTypes.number,isDone:s.PropTypes.bool},c.defaultProps={blink:!0,show:!0,element:"|",hideWhenDone:!1,hideWhenDoneDelay:1e3,isDone:!1},t["default"]=c},function(e,t){},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function i(e,t){for(var n=12,r=0,o=0;o<n;o++)r+=Math.random();return r-=n/2,Math.round(r*t)+e}function a(e,t){var n=e.length;return Array.from(e).reduce(function(e,r,o){return e.then(function(){return Promise.resolve(r).then(function(e){return t(e,o,n)})})},Promise.resolve())}function u(e,t){var n={};for(var r in e)t.indexOf(r)===-1&&(n[r]=e[r]);return n}function s(e){for(var t=e?[e]:[],n=[];t.length>0;){var r=t.pop();if(y["default"].isValidElement(r))y["default"].Children.forEach(r.props.children,function(e){t.push(e)});else if(Array.isArray(r)){var o=!0,i=!1,a=void 0;try{for(var u,s=r[Symbol.iterator]();!(o=(u=s.next()).done);o=!0){var l=u.value;t.push(l)}}catch(c){i=!0,a=c}finally{try{!o&&s["return"]&&s["return"]()}finally{if(i)throw a}}}else n.unshift(r)}return n}function l(){var e=0;return function(t){var n=t.type,r=u(t.props,["children"]);return r.key="Typist-el-"+e++,y["default"].createElement.bind(null,n,r)}}function c(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];if(t[0]){var r=l(),i=function a(e,t,n){if(n>=t.length)return[null,n];var i=n,u=function(e){var n=a(e,t,i),r=p(n,2),o=r[0],u=r[1];return i=u,o};if(y["default"].isValidElement(e)){var s=r(e),l=y["default"].Children.map(e.props.children,u)||[];return[s.apply(void 0,o(l)),i]}if(Array.isArray(e)){var c=e.map(u);return[c,i]}return[t[i],i+1]};return i.apply(void 0,t.concat([0]))[0]}}Object.defineProperty(t,"__esModule",{value:!0}),t.sleep=void 0;var p=function(){function e(e,t){var n=[],r=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(r=(a=u.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(s){o=!0,i=s}finally{try{!r&&u["return"]&&u["return"]()}finally{if(o)throw i}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();t.gaussianRnd=i,t.eachPromise=a,t.exclude=u,t.extractText=s,t.elementFactoryMaker=l,t.extractTreeWithText=c;var f=n(1),y=r(f);t.sleep=function(e){return new Promise(function(t){return setTimeout(t,e)})}}])}); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.Typist=t(require("react")):e.Typist=t(e.react)}(this,function(e){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t["default"]=e,t}function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function u(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},l=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),p=n(1),c=o(p),f=n(2),y=o(f),d=n(4),h=r(d),v=function(e){function t(e){i(this,t);var n=a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.state={text:[],isDone:!1},n.onTypingDone=function(){n.mounted&&(n.setState({isDone:!0}),n.props.onTypingDone())},n.delayGenerator=function(e,t,r,o){var i=n.props.avgTypingDelay,a=n.props.stdTypingDelay;return n.props.delayGenerator(i,a,{line:e,lineIdx:t,character:r,charIdx:o,defDelayGenerator:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:a;return h.gaussianRnd(e,t)}})},n.typeLine=function(e,t){if(!n.mounted)return Promise.resolve();var r=n.props.onLineTyped;return new Promise(function(o,i){n.setState({text:n.state.text.concat([""])},function(){h.eachPromise(e,n.typeCharacter,e,t).then(function(){return r(e,t)}).then(o)["catch"](i)})})},n.typeCharacter=function(e,t,r,o){if(!n.mounted)return Promise.resolve();var i=n.props.onCharacterTyped;return new Promise(function(a){var u=n.state.text.slice();u[o]+=e,n.setState({text:u},function(){i(e,t);var u=n.delayGenerator(r,o,e,t);setTimeout(a,u)})})},n.mounted=!1,n.linesToType=[],e.children&&(n.linesToType=h.extractText(e.children)),n}return u(t,e),l(t,[{key:"componentDidMount",value:function(){this.mounted=!0;var e=this.props,t=e.children,n=e.startDelay;t?n>0&&"undefined"!=typeof window?setTimeout(this.typeAllLines.bind(this),n):this.typeAllLines():this.onTypingDone()}},{key:"shouldComponentUpdate",value:function(e,t){for(var n=0;n<t.text.length;n++){var r=this.state.text[n],o=t.text[n];if(r!==o&&o.length>0)return!0}return this.state.isDone!==t.isDone}},{key:"componentWillUnmount",value:function(){this.mounted=!1}},{key:"typeAllLines",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.linesToType;return h.eachPromise(t,this.typeLine).then(function(){return e.onTypingDone()})}},{key:"render",value:function(){var e=this.props,t=e.className,n=e.cursor,r=this.state.isDone,o=h.extractTreeWithText(this.props.children,this.state.text);return c["default"].createElement("div",{className:"Typist "+t},o,c["default"].createElement(y["default"],s({isDone:r},n)))}}]),t}(p.Component);v.propTypes={children:p.PropTypes.node,className:p.PropTypes.string,avgTypingDelay:p.PropTypes.number,stdTypingDelay:p.PropTypes.number,startDelay:p.PropTypes.number,cursor:p.PropTypes.object,onCharacterTyped:p.PropTypes.func,onLineTyped:p.PropTypes.func,onTypingDone:p.PropTypes.func,delayGenerator:p.PropTypes.func},v.defaultProps={className:"",avgTypingDelay:70,stdTypingDelay:25,startDelay:0,cursor:{},onCharacterTyped:function(){},onLineTyped:function(){},onTypingDone:function(){},delayGenerator:h.gaussianRnd},t["default"]=v},function(t,n){t.exports=e},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),s=n(1),l=r(s);n(3);var p=function(e){function t(e){o(this,t);var n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n._isReRenderingCursor=!1,n.state={shouldRender:n.props.show},n}return a(t,e),u(t,[{key:"componentWillReceiveProps",value:function(e){var t=this,n=!this.props.isDone&&e.isDone&&this.props.hideWhenDone;n&&setTimeout(function(){return t.setState({shouldRender:!1})},this.props.hideWhenDoneDelay)}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.show,n=e.isDone;t&&(n||this._isReRenderingCursor||this._reRenderCursor())}},{key:"_reRenderCursor",value:function(){var e=this;this._isReRenderingCursor=!0,this.setState({shouldRender:!1},function(){e.setState({shouldRender:!0},function(){e._isReRenderingCursor=!1})})}},{key:"render",value:function(){if(this.state.shouldRender){var e=this.props.blink?" Cursor--blinking":"";return l["default"].createElement("span",{className:"Cursor"+e},this.props.element)}return null}}]),t}(s.Component);p.propTypes={blink:s.PropTypes.bool,show:s.PropTypes.bool,element:s.PropTypes.node,hideWhenDone:s.PropTypes.bool,hideWhenDoneDelay:s.PropTypes.number,isDone:s.PropTypes.bool},p.defaultProps={blink:!0,show:!0,element:"|",hideWhenDone:!1,hideWhenDoneDelay:1e3,isDone:!1},t["default"]=p},function(e,t){},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function i(e,t){for(var n=12,r=0,o=0;o<n;o++)r+=Math.random();return r-=n/2,Math.round(r*t)+e}function a(e,t){for(var n=arguments.length,r=Array(n>2?n-2:0),o=2;o<n;o++)r[o-2]=arguments[o];var i=function(e,n,o){return e.then(function(){return t.apply(void 0,[n,o].concat(r))})};return Array.from(e).reduce(i,Promise.resolve())}function u(e,t){var n={};for(var r in e)t.indexOf(r)===-1&&(n[r]=e[r]);return n}function s(e){for(var t=e?[e]:[],n=[];t.length>0;){var r=t.pop();if(y["default"].isValidElement(r))y["default"].Children.forEach(r.props.children,function(e){t.push(e)});else if(Array.isArray(r)){var o=!0,i=!1,a=void 0;try{for(var u,s=r[Symbol.iterator]();!(o=(u=s.next()).done);o=!0){var l=u.value;t.push(l)}}catch(p){i=!0,a=p}finally{try{!o&&s["return"]&&s["return"]()}finally{if(i)throw a}}}else n.unshift(r)}return n}function l(){var e=0;return function(t){var n=t.type,r=u(t.props,["children"]);return r.key="Typist-el-"+e++,y["default"].createElement.bind(null,n,r)}}function p(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];if(t[0]){var r=l(),i=function a(e,t,n){if(n>=t.length)return[null,n];var i=n,u=function(e){var n=a(e,t,i),r=c(n,2),o=r[0],u=r[1];return i=u,o};if(y["default"].isValidElement(e)){var s=r(e),l=y["default"].Children.map(e.props.children,u)||[];return[s.apply(void 0,o(l)),i]}if(Array.isArray(e)){var p=e.map(u);return[p,i]}return[t[i],i+1]};return i.apply(void 0,t.concat([0]))[0]}}Object.defineProperty(t,"__esModule",{value:!0}),t.sleep=void 0;var c=function(){function e(e,t){var n=[],r=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(r=(a=u.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(s){o=!0,i=s}finally{try{!r&&u["return"]&&u["return"]()}finally{if(o)throw i}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();t.gaussianRnd=i,t.eachPromise=a,t.exclude=u,t.extractText=s,t.elementFactoryMaker=l,t.extractTreeWithText=p;var f=n(1),y=r(f);t.sleep=function(e){return new Promise(function(t){return setTimeout(t,e)})}}])}); |
@@ -117,2 +117,36 @@ module.exports = | ||
_this.typeLine = function (line, lineIdx) { | ||
if (!_this.mounted) { | ||
return Promise.resolve(); | ||
} | ||
var onLineTyped = _this.props.onLineTyped; | ||
return new Promise(function (resolve, reject) { | ||
_this.setState({ text: _this.state.text.concat(['']) }, function () { | ||
utils.eachPromise(line, _this.typeCharacter, line, lineIdx).then(function () { | ||
return onLineTyped(line, lineIdx); | ||
}).then(resolve).catch(reject); | ||
}); | ||
}); | ||
}; | ||
_this.typeCharacter = function (character, charIdx, line, lineIdx) { | ||
if (!_this.mounted) { | ||
return Promise.resolve(); | ||
} | ||
var onCharacterTyped = _this.props.onCharacterTyped; | ||
return new Promise(function (resolve) { | ||
var text = _this.state.text.slice(); | ||
text[lineIdx] += character; | ||
_this.setState({ text: text }, function () { | ||
onCharacterTyped(character, charIdx); | ||
var delay = _this.delayGenerator(line, lineIdx, character, charIdx); | ||
setTimeout(resolve, delay); | ||
}); | ||
}); | ||
}; | ||
_this.mounted = false; | ||
@@ -167,12 +201,3 @@ _this.linesToType = []; | ||
return utils.eachPromise(lines, function (line, idx) { | ||
if (!_this2.mounted) { | ||
return Promise.resolve(); | ||
} | ||
return new Promise(function (resolve) { | ||
_this2.setState({ text: _this2.state.text.concat(['']) }, function () { | ||
_this2.typeLine(line, idx).then(resolve); | ||
}); | ||
}); | ||
}).then(function () { | ||
return utils.eachPromise(lines, this.typeLine).then(function () { | ||
return _this2.onTypingDone(); | ||
@@ -182,21 +207,2 @@ }); | ||
}, { | ||
key: 'typeLine', | ||
value: function typeLine(line, lineIdx) { | ||
var _this3 = this; | ||
return utils.eachPromise(line, function (character, charIdx) { | ||
if (!_this3.mounted) { | ||
return Promise.resolve(); | ||
} | ||
return new Promise(function (resolve) { | ||
var text = _this3.state.text.slice(); | ||
text[lineIdx] += character; | ||
_this3.setState({ text: text }, function () { | ||
var delay = _this3.delayGenerator(line, lineIdx, character, charIdx); | ||
setTimeout(resolve, delay); | ||
}); | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -230,2 +236,4 @@ value: function render() { | ||
cursor: _react.PropTypes.object, | ||
onCharacterTyped: _react.PropTypes.func, | ||
onLineTyped: _react.PropTypes.func, | ||
onTypingDone: _react.PropTypes.func, | ||
@@ -240,2 +248,4 @@ delayGenerator: _react.PropTypes.func | ||
cursor: {}, | ||
onCharacterTyped: function onCharacterTyped() {}, | ||
onLineTyped: function onLineTyped() {}, | ||
onTypingDone: function onTypingDone() {}, | ||
@@ -281,16 +291,12 @@ delayGenerator: utils.gaussianRnd | ||
function Cursor() { | ||
var _ref; | ||
var _temp, _this, _ret; | ||
function Cursor(props) { | ||
_classCallCheck(this, Cursor); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var _this = _possibleConstructorReturn(this, (Cursor.__proto__ || Object.getPrototypeOf(Cursor)).call(this, props)); | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Cursor.__proto__ || Object.getPrototypeOf(Cursor)).call.apply(_ref, [this].concat(args))), _this), _this.state = { | ||
_this._isReRenderingCursor = false; | ||
_this.state = { | ||
shouldRender: _this.props.show | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
}; | ||
return _this; | ||
} | ||
@@ -311,2 +317,45 @@ | ||
}, { | ||
key: 'componentDidUpdate', | ||
value: function componentDidUpdate() { | ||
var _props = this.props; | ||
var show = _props.show; | ||
var isDone = _props.isDone; | ||
if (!show) { | ||
return; | ||
} | ||
if (isDone) { | ||
return; | ||
} | ||
if (this._isReRenderingCursor) { | ||
return; | ||
} | ||
// In webkit and blink, rendering the cursor alongside the text as it | ||
// animates sometimes causes the text to stop rendering when it reaches | ||
// a new line break, even though the underlying DOM /does/ contain | ||
// the text. This seems to happen when the space available for the text is | ||
// at a specific width that makes it so the line break happens within a | ||
// word. | ||
// Using dev tools, when in this state, if you modify the dom or any style, | ||
// it immediately renders all of the text in its correct position. | ||
// Given that observation, this is a hackish solutions that re-renders the | ||
// cursor every time a character is rendered, just to ensure that the text | ||
// is rendered correctly. | ||
// See #13 and #15 for more details | ||
this._reRenderCursor(); | ||
} | ||
}, { | ||
key: '_reRenderCursor', | ||
value: function _reRenderCursor() { | ||
var _this3 = this; | ||
this._isReRenderingCursor = true; | ||
this.setState({ shouldRender: false }, function () { | ||
_this3.setState({ shouldRender: true }, function () { | ||
_this3._isReRenderingCursor = false; | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -398,11 +447,12 @@ value: function render() { | ||
function eachPromise(arr, iterator) { | ||
var length = arr.length; | ||
for (var _len = arguments.length, extraArgs = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
extraArgs[_key - 2] = arguments[_key]; | ||
} | ||
return Array.from(arr).reduce(function (prev, current, idx) { | ||
var promiseReducer = function promiseReducer(prev, current, idx) { | ||
return prev.then(function () { | ||
return Promise.resolve(current).then(function (val) { | ||
return iterator(val, idx, length); | ||
}); | ||
return iterator.apply(undefined, [current, idx].concat(extraArgs)); | ||
}); | ||
}, Promise.resolve()); | ||
}; | ||
return Array.from(arr).reduce(promiseReducer, Promise.resolve()); | ||
} | ||
@@ -476,4 +526,4 @@ | ||
function extractTreeWithText() { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
@@ -480,0 +530,0 @@ |
{ | ||
"name": "react-typist", | ||
"version": "1.0.3", | ||
"version": "1.1.0", | ||
"description": "Typing animations with React", | ||
@@ -5,0 +5,0 @@ "main": "dist/Typist.js", |
@@ -12,9 +12,3 @@ # React Typist | ||
or | ||
```shell | ||
bower install react-typist --save | ||
``` | ||
## Live Example | ||
@@ -83,2 +77,4 @@ * <a href="//jstejada.github.io/react-typist" target="_blank">Basic example</a> | ||
* [`cursor`](#cursor) | ||
* [`onCharacterTyped`](#onCharacterTyped) | ||
* [`onLineTyped`](#onLineTyped) | ||
* [`onTypingDone`](#onTypingDone) | ||
@@ -147,2 +143,22 @@ * [`delayGenerator`](#delayGenerator) | ||
<a name="onCharacterTyped"></a> | ||
#### onCharacterTyped | ||
Function to be called every time a character is typed on the screen. | ||
```js | ||
function(character, charIdx) { | ||
... | ||
} | ||
``` | ||
<a name="onLineTyped"></a> | ||
#### onLineTyped | ||
Function to be called every time a line is typed on the screen. | ||
```js | ||
function(line, lineIdx) { | ||
... | ||
} | ||
``` | ||
<a name="onTypingDone"></a> | ||
@@ -149,0 +165,0 @@ #### onTypingDone |
@@ -25,4 +25,8 @@ import React, { Component, PropTypes } from 'react'; | ||
state = { | ||
shouldRender: this.props.show, | ||
constructor(props) { | ||
super(props); | ||
this._isReRenderingCursor = false; | ||
this.state = { | ||
shouldRender: this.props.show, | ||
}; | ||
} | ||
@@ -37,2 +41,32 @@ | ||
componentDidUpdate() { | ||
const { show, isDone } = this.props; | ||
if (!show) { return; } | ||
if (isDone) { return; } | ||
if (this._isReRenderingCursor) { return; } | ||
// In webkit and blink, rendering the cursor alongside the text as it | ||
// animates sometimes causes the text to stop rendering when it reaches | ||
// a new line break, even though the underlying DOM /does/ contain | ||
// the text. This seems to happen when the space available for the text is | ||
// at a specific width that makes it so the line break happens within a | ||
// word. | ||
// Using dev tools, when in this state, if you modify the dom or any style, | ||
// it immediately renders all of the text in its correct position. | ||
// Given that observation, this is a hackish solutions that re-renders the | ||
// cursor every time a character is rendered, just to ensure that the text | ||
// is rendered correctly. | ||
// See #13 and #15 for more details | ||
this._reRenderCursor(); | ||
} | ||
_reRenderCursor() { | ||
this._isReRenderingCursor = true; | ||
this.setState({ shouldRender: false }, () => { | ||
this.setState({ shouldRender: true }, () => { | ||
this._isReRenderingCursor = false; | ||
}); | ||
}); | ||
} | ||
render() { | ||
@@ -39,0 +73,0 @@ if (this.state.shouldRender) { |
@@ -15,2 +15,4 @@ import React, { Component, PropTypes } from 'react'; | ||
cursor: PropTypes.object, | ||
onCharacterTyped: PropTypes.func, | ||
onLineTyped: PropTypes.func, | ||
onTypingDone: PropTypes.func, | ||
@@ -26,2 +28,4 @@ delayGenerator: PropTypes.func, | ||
cursor: {}, | ||
onCharacterTyped: () => {}, | ||
onLineTyped: () => {}, | ||
onTypingDone: () => {}, | ||
@@ -96,23 +100,16 @@ delayGenerator: utils.gaussianRnd, | ||
typeAllLines(lines = this.linesToType) { | ||
return utils.eachPromise(lines, (line, idx) => { | ||
if (!this.mounted) { return Promise.resolve(); } | ||
return new Promise((resolve) => { | ||
this.setState({ text: this.state.text.concat(['']) }, () => { | ||
this.typeLine(line, idx).then(resolve); | ||
}); | ||
}); | ||
}) | ||
return utils.eachPromise(lines, this.typeLine) | ||
.then(() => this.onTypingDone()); | ||
} | ||
typeLine(line, lineIdx) { | ||
return utils.eachPromise(line, (character, charIdx) => { | ||
if (!this.mounted) { return Promise.resolve(); } | ||
return new Promise((resolve) => { | ||
const text = this.state.text.slice(); | ||
text[lineIdx] += character; | ||
this.setState({ text }, () => { | ||
const delay = this.delayGenerator(line, lineIdx, character, charIdx); | ||
setTimeout(resolve, delay); | ||
}); | ||
typeLine = (line, lineIdx) => { | ||
if (!this.mounted) { return Promise.resolve(); } | ||
const { onLineTyped } = this.props; | ||
return new Promise((resolve, reject) => { | ||
this.setState({ text: this.state.text.concat(['']) }, () => { | ||
utils.eachPromise(line, this.typeCharacter, line, lineIdx) | ||
.then(() => onLineTyped(line, lineIdx)) | ||
.then(resolve) | ||
.catch(reject); | ||
}); | ||
@@ -122,2 +119,17 @@ }); | ||
typeCharacter = (character, charIdx, line, lineIdx) => { | ||
if (!this.mounted) { return Promise.resolve(); } | ||
const { onCharacterTyped } = this.props; | ||
return new Promise((resolve) => { | ||
const text = this.state.text.slice(); | ||
text[lineIdx] += character; | ||
this.setState({ text }, () => { | ||
onCharacterTyped(character, charIdx); | ||
const delay = this.delayGenerator(line, lineIdx, character, charIdx); | ||
setTimeout(resolve, delay); | ||
}); | ||
}); | ||
} | ||
render() { | ||
@@ -124,0 +136,0 @@ const { className, cursor } = this.props; |
@@ -15,10 +15,7 @@ import React from 'react'; | ||
export function eachPromise(arr, iterator) { | ||
const { length } = arr; | ||
return Array.from(arr).reduce((prev, current, idx) => | ||
prev.then(() => | ||
Promise.resolve(current) | ||
.then((val) => iterator(val, idx, length)) | ||
) | ||
, Promise.resolve()); | ||
export function eachPromise(arr, iterator, ...extraArgs) { | ||
const promiseReducer = (prev, current, idx) => ( | ||
prev.then(() => iterator(current, idx, ...extraArgs)) | ||
); | ||
return Array.from(arr).reduce(promiseReducer, Promise.resolve()); | ||
} | ||
@@ -25,0 +22,0 @@ |
@@ -193,3 +193,3 @@ import React from 'react'; | ||
it('hides cursor and end of animation when specified', () => { | ||
it('hides cursor at end of animation when specified', () => { | ||
props.cursor = { hideWhenDone: true, hideWhenDoneDelay: 100 }; | ||
@@ -196,0 +196,0 @@ const inst = TestUtils.renderIntoDocument(<Typist {...props}>Test</Typist>); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
91051
1779
240
30