react-countdown-circle-timer
Advanced tools
Comparing version 1.2.1 to 2.0.1
@@ -1,1 +0,2 @@ | ||
module.exports=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=5)}([function(e,t){e.exports=require("react")},function(e,t,r){e.exports=r(3)()},function(e,t,r){e.exports=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(e,t){e.exports=r(0)},function(e,t,r){"use strict";r.r(t),r.d(t,"useElapsedTime",(function(){return i}));var n=r(0);function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],n=!0,o=!1,i=void 0;try{for(var a,c=e[Symbol.iterator]();!(n=(a=c.next()).done)&&(r.push(a.value),!t||r.length!==t);n=!0);}catch(e){o=!0,i=e}finally{try{n||null==c.return||c.return()}finally{if(o)throw i}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}var i=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.durationMilliseconds,i=t.onComplete,a=t.startAt,c="number"==typeof r,u=Object(n.useState)(a||0),l=o(u,2),s=l[0],f=l[1],d=Object(n.useRef)(null),p=Object(n.useRef)(null),m=function e(t){if(null===p.current)return p.current=t,void(d.current=requestAnimationFrame(e));f((function(n){var a=n+(t-p.current);if(!c||a<r)return p.current=t,d.current=requestAnimationFrame(e),a;if("function"==typeof i){var u=o(i()||[],2),l=u[0],s=void 0!==l&&l,m=u[1];s&&setTimeout((function(){f(0),p.current=null,d.current=requestAnimationFrame(e)}),void 0===m?0:m)}return r}))};return Object(n.useLayoutEffect)((function(){return e&&(d.current=requestAnimationFrame(m)),function(){cancelAnimationFrame(d.current),p.current=null,d.current=null}}),[e]),s}}])},function(e,t,r){"use strict";var n=r(4);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,r,o,i,a){if(a!==n){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}e.isRequired=e;var r={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return r.PropTypes=r,r}},function(e,t,r){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),i=r(1),a=r.n(i),c=r(2),u=function(e,t,r,n){return t+r*(e/n)},l=function(e){return{position:"relative",width:e,height:e,margin:"0 auto"}},s=function(e,t){return{display:"flex",WebkitBoxPack:"center",MsFlexPack:"center",justifyContent:"center",WebkitBoxAlign:"center",MsFlexAlign:"center",alignItems:"center",position:"relative",width:t,height:t,color:e}},f={position:"absolute",left:0,top:0,width:"100%",height:"100%"},d={position:"absolute",width:"1px",height:"1px",margin:"-1px",border:0,clip:"rect(0 0 0 0)",padding:0,overflow:"hidden",whiteSpace:"nowrap",wordWrap:"normal"};function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function m(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?p(r,!0).forEach((function(t){b(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):p(r).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function b(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var y=function(e){var t=e.r,r=e.g,n=e.b,o=e.opacity;return"rgba(".concat(t,", ").concat(r,", ").concat(n,", ").concat(o,")")},g=function(e,t,r){var n=function(e){return e.map((function(e){var t=e[0].replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,(function(e,t,r,n){return"#".concat(t).concat(t).concat(r).concat(r).concat(n).concat(n)})).substring(1).match(/.{2}/g).map((function(e){return parseInt(e,16)}));return[{r:t[0],g:t[1],b:t[2],opacity:1},e[1]]}))}(e);if(!r)return n;var o=0;return n.map((function(e,t){var r=n.length===t+1,i="0%";if(t>0){var a=n[t-1][1],c=Math.round(a?100*a:100);(o+=c)>100||r?(o=100,i="100%"):i="".concat(o,"%")}var u={offset:i,stopColor:y(e[0]),key:t};return[m({},e[0],{gradient:u}),e[1]]}))},v=function(e,t){return e?"countdown-circle-timer-gradient-".concat(t||Math.random().toString(36).substring(2)):""},h=function(e){var t=e.size,r=e.strokeWidth,o=e.durationSeconds,i=e.initialRemainingTime,a=e.startAtSeconds,c=e.colors,u=e.isLinearGradient,l=e.gradientUniqueKey,s=Object(n.useMemo)((function(){return function(e,t){var r=e/2,n=t/2,o=r-n,i=2*o,a=2*Math.PI*o;return{path:"m ".concat(r,",").concat(n,"\n a ").concat(o,",").concat(o," 0 1,0 0,").concat(i,"\n a ").concat(o,",").concat(o," 0 1,0 0,-").concat(i),pathLength:a}}(t,r)}),[t,r]),f=s.path,d=s.pathLength,p=Object(n.useMemo)((function(){return 1e3*o}),[o]),b=Object(n.useMemo)((function(){return function(e,t,r){return"number"==typeof e?1e3*(r-e):t?1e3*t:0}(i,a,o)}),[i,a,o]),y=Object(n.useMemo)((function(){return function(e,t,r){var n=g(e,0,r),o=0;return n.map((function(e,r){var i=n.length===r+1;if(o>=t||i)return o=t,m({},e[0],{colorEndTime:o});var a=o,c=void 0!==e[1]?a+e[1]*t:t-o,u=c>=t?t:c,l=n[r+1][0],s={goalR:l.r-e[0].r,goalG:l.g-e[0].g,goalB:l.b-e[0].b};return o=u,m({},e[0],{},s,{colorStartTime:a,colorEndTime:u,duration:u-a})}))}(c,p,u)}),[c,p,u]),h=Object(n.useMemo)((function(){return v(u,l)}),[u,l]);return{path:f,pathLength:d,durationMilliseconds:p,startAt:b,normalizedColors:y,gradientId:h}},O=function(e){var t=e.size,r=e.strokeWidth,n=e.trailColor,i=e.durationSeconds,a=e.isPlaying,p=e.colors,m=e.strokeLinecap,b=e.renderTime,g=e.isLinearGradient,v=e.gradientUniqueKey,O=e.onComplete,j=e.ariaLabel,w=e.renderAriaTime,T=e.initialRemainingTime,x=e.startAt,P=h({size:t,strokeWidth:r,durationSeconds:i,initialRemainingTime:T,startAtSeconds:x,colors:p,isLinearGradient:g,gradientUniqueKey:v}),S=P.path,E=P.pathLength,k=P.durationMilliseconds,A=P.startAt,M=P.normalizedColors,_=P.gradientId,C=Object(c.useElapsedTime)(a,{durationMilliseconds:k,onComplete:O,startAt:A}),L=u(C,0,E,k).toFixed(3),R=function(e,t){if(1===e.length)return y(e[0]);var r=e.find((function(e){var r=e.colorEndTime;return t<=r}));if(void 0===r.duration)return y(r);var n=t-r.colorStartTime,o=0|u(n,r.r,r.goalR,r.duration),i=0|u(n,r.g,r.goalG,r.duration),a=0|u(n,r.b,r.goalB,r.duration);return y({r:o,g:i,b:a,opacity:r.opacity})}(M,C),q=Math.ceil((k-C)/1e3);return o.a.createElement("div",{style:l(t),"aria-label":j},o.a.createElement("svg",{width:t,height:t,style:f,xmlns:"http://www.w3.org/2000/svg"},g&&o.a.createElement("defs",null,o.a.createElement("linearGradient",{id:_,x1:"100%",y1:"0%",x2:"0%",y2:"0%"},M.map((function(e){return o.a.createElement("stop",e.gradient)})))),o.a.createElement("path",{fill:"none",strokeWidth:r,stroke:n,d:S}),o.a.createElement("path",{fill:"none",stroke:g?"url(#".concat(_,")"):R,d:S,strokeLinecap:m,strokeWidth:r,strokeDasharray:E,strokeDashoffset:L})),"function"==typeof b&&o.a.createElement("div",{"aria-hidden":"true",style:s(R,t)},b(q,C,a)),"function"==typeof w&&o.a.createElement("div",{role:"timer","aria-live":"assertive",style:d},w(q,C,a)))};O.propTypes={durationSeconds:a.a.number.isRequired,colors:a.a.arrayOf(a.a.arrayOf((function(e,t,r,n,o){var i=e[0],a=e[1];return i.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)?void 0===a||a>=0&&a<=1?void 0:new Error("Invalid prop '".concat(o,"[1]' supplied to '").concat(r,"'. Expect a number of color transition duration with value between 0 and 1.")):new Error("Invalid prop '".concat(o,"[0]' supplied to '").concat(r,"'.Expect a color with HEX color code."))})).isRequired).isRequired,size:a.a.number,strokeWidth:a.a.number,trailColor:a.a.string,isPlaying:a.a.bool,strokeLinecap:a.a.oneOf(["round","square"]),renderTime:a.a.func,isLinearGradient:a.a.bool,gradientUniqueKey:a.a.string,onComplete:a.a.func,ariaLabel:a.a.string,renderAriaTime:a.a.func,initialRemainingTime:a.a.number,startAt:a.a.number},O.defaultProps={size:180,strokeWidth:12,trailColor:"#d9d9d9",isPlaying:!1,strokeLinecap:"round",isLinearGradient:!1,ariaLabel:"Countdown timer",startAt:0},O.displayName="CountdownCircleTimer",r.d(t,"CountdownCircleTimer",(function(){return O}))}]); | ||
module.exports=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=5)}([function(e,t,r){e.exports=r(3)()},function(e,t){e.exports=require("react")},function(e,t,r){e.exports=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(e,t){e.exports=r(1)},function(e,t,r){"use strict";r.r(t),r.d(t,"useElapsedTime",(function(){return a}));var n=r(0);function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e)){var r=[],n=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(n=(a=u.next()).done)&&(r.push(a.value),!t||r.length!==t);n=!0);}catch(e){o=!0,i=e}finally{try{n||null==u.return||u.return()}finally{if(o)throw i}}return r}}(e,t)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?i(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}var a=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.durationMilliseconds,i=t.onComplete,a=t.startAt,u="number"==typeof r,c=Object(n.useState)(a||0),l=o(c,2),f=l[0],s=l[1],p=Object(n.useRef)(null),d=Object(n.useRef)(null),y=function e(t){if(null===d.current)return d.current=t,void(p.current=requestAnimationFrame(e));s((function(n){var a=n+(t-d.current);if(!u||a<r)return d.current=t,p.current=requestAnimationFrame(e),a;if("function"==typeof i){var c=o(i()||[],2),l=c[0],f=void 0!==l&&l,y=c[1];f&&setTimeout((function(){s(0),d.current=null,p.current=requestAnimationFrame(e)}),void 0===y?0:y)}return r}))};return Object(n.useLayoutEffect)((function(){return e&&(p.current=requestAnimationFrame(y)),function(){cancelAnimationFrame(p.current),d.current=null,p.current=null}}),[e]),f}}])},function(e,t,r){"use strict";var n=r(4);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,r,o,i,a){if(a!==n){var u=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw u.name="Invariant Violation",u}}function t(){return e}e.isRequired=e;var r={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return r.PropTypes=r,r}},function(e,t,r){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,r){"use strict";r.r(t),r.d(t,"CountdownCircleTimer",(function(){return A}));var n=r(1),o=r.n(n),i=function(e){return{position:"relative",width:e,height:e}},a={display:"flex",justifyContent:"center",alignItems:"center",position:"absolute",left:0,top:0,width:"100%",height:"100%"},u=function(e){return"countdown-circle-timer-gradient-".concat(e||Math.random().toString(36).substring(2))},c=r(0),l=r.n(c),f={duration:l.a.number.isRequired,colors:l.a.arrayOf(l.a.arrayOf((function(e,t,r,n,o){var i=e[0],a=e[1];return i.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)?void 0===a||a>=0&&a<=1?void 0:new Error("Invalid prop '".concat(o,"[1]' supplied to '").concat(r,"'. Expect a number of color transition duration with value between 0 and 1.")):new Error("Invalid prop '".concat(o,"[0]' supplied to '").concat(r,"'.Expect a color with HEX color code."))})).isRequired).isRequired,children:l.a.oneOfType([l.a.func,l.a.node]),size:l.a.number,strokeWidth:l.a.number,trailColor:l.a.string,isPlaying:l.a.bool,strokeLinecap:l.a.oneOf(["round","square"]),isLinearGradient:l.a.bool,gradientUniqueKey:l.a.string,onComplete:l.a.func,ariaLabel:l.a.string,renderAriaTime:l.a.func,initialRemainingTime:l.a.number};function s(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(e)))return;var r=[],n=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(n=(a=u.next()).done)&&(r.push(a.value),!t||r.length!==t);n=!0);}catch(e){o=!0,i=e}finally{try{n||null==u.return||u.return()}finally{if(o)throw i}}return r}(e,t)||d(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e){return function(e){if(Array.isArray(e))return y(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||d(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(e,t){if(e){if("string"==typeof e)return y(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(r):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?y(e,t):void 0}}function y(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}var m=function(e){var t=e.gradientId,r=e.colors,n=e.defs,i=void 0===n?"defs":n,a=e.linearGradient,u=void 0===a?"linearGradient":a,c=e.stop,l=void 0===c?"stop":c;return o.a.createElement(i,null,o.a.createElement(u,{id:t,x1:"1",y1:"0",x2:"0",y2:"0"},function(e){if(1===e.length)return[{offset:1,stopColor:e[0][0],key:0}];var t=e.length,r=0;return[{offset:0,stopColor:e[0][0],key:0}].concat(p(e.map((function(e,n){var o=s(e,2),i=o[0],a=o[1];return r+=a,{offset:t===n+1?1:r,stopColor:i,key:n+1}}))))}(r).map((function(e){return o.a.createElement(l,e)}))))},b=l.a.oneOfType([l.a.func,l.a.string]);m.propTypes={gradientId:l.a.string.isRequired,colors:f.colors,defs:b,linearGradient:b,stop:b};var g=r(2),v=function(e,t,r,n){return t+r*(e/n)};function h(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function O(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?h(Object(r),!0).forEach((function(t){j(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):h(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function j(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var w=function(e){var t=e.r,r=e.g,n=e.b,o=e.opacity;return"rgba(".concat(t,", ").concat(r,", ").concat(n,", ").concat(o,")")},P=function(e,t){var r=function(e){return e.map((function(e){var t=e[0].replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,(function(e,t,r,n){return"#".concat(t).concat(t).concat(r).concat(r).concat(n).concat(n)})).substring(1).match(/.{2}/g).map((function(e){return parseInt(e,16)}));return[{r:t[0],g:t[1],b:t[2],opacity:1},e[1]]}))}(e);if(!t)return r;var n=0;return r.map((function(e,t){var o=r.length===t+1,i="0%";if(t>0){var a=r[t-1][1],u=Math.round(a?100*a:100);(n+=u)>100||o?(n=100,i="100%"):i="".concat(n,"%")}var c={offset:i,stopColor:w(e[0]),key:t};return[O({},e[0],{gradient:c}),e[1]]}))},S={position:"absolute",width:"1px",height:"1px",margin:"-1px",border:0,clip:"rect(0 0 0 0)",padding:0,overflow:"hidden",whiteSpace:"nowrap",wordWrap:"normal"},T=function(e){var t=e.isPlaying,r=e.size,o=e.strokeWidth,c=e.duration,l=e.initialRemainingTime,f=e.colors,s=e.isLinearGradient,p=e.gradientUniqueKey,d=e.onComplete,y={wrapperStyle:i(r),timeStyle:a,visuallyHidden:S},m=Object(n.useMemo)((function(){return function(e,t){var r=e/2,n=t/2,o=r-n,i=2*o,a=2*Math.PI*o;return{path:"m ".concat(r,",").concat(n,"\n a ").concat(o,",").concat(o," 0 1,0 0,").concat(i,"\n a ").concat(o,",").concat(o," 0 1,0 0,-").concat(i),pathLength:a}}(r,o)}),[r,o]),b=m.path,h=m.pathLength,j=Object(n.useMemo)((function(){return 1e3*c}),[c]),T=Object(n.useMemo)((function(){return function(e,t){return"number"==typeof e?1e3*(t-e):0}(l,c)}),[l,c]),E=Object(n.useMemo)((function(){return function(e,t,r){var n=P(e,r),o=0;return n.map((function(e,r){var i=n.length===r+1;if(o>=t||i)return o=t,O({},e[0],{colorEndTime:o});var a=o,u=void 0!==e[1]?a+e[1]*t:t-o,c=u>=t?t:u,l=n[r+1][0],f={goalR:l.r-e[0].r,goalG:l.g-e[0].g,goalB:l.b-e[0].b};return o=c,O({},e[0],{},f,{colorStartTime:a,colorEndTime:c,duration:c-a})}))}(f,j,s)}),[f,j,s]),x=Object(n.useMemo)((function(){return u(p)}),[p]),k=Object(g.useElapsedTime)(t,{durationMilliseconds:j,onComplete:d,startAt:T});return{path:b,pathLength:h,stroke:function(e,t){if(1===e.length)return w(e[0]);var r=e.find((function(e){var r=e.colorEndTime;return t<=r}));if(void 0===r.duration)return w(r);var n=t-r.colorStartTime,o=0|v(n,r.r,r.goalR,r.duration),i=0|v(n,r.g,r.goalG,r.duration),a=0|v(n,r.b,r.goalB,r.duration);return w({r:o,g:i,b:a,opacity:r.opacity})}(E,k),strokeDashoffset:v(k,0,h,j).toFixed(3),gradientId:x,styles:y,timeProps:{remainingTime:Math.ceil((j-k)/1e3),elapsedTime:k}}};function E(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function x(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?E(Object(r),!0).forEach((function(t){k(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):E(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function k(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var A=function(e){var t=e.size,r=e.strokeWidth,n=e.trailColor,i=e.duration,a=e.isPlaying,u=e.colors,c=e.strokeLinecap,l=e.children,f=e.isLinearGradient,s=e.gradientUniqueKey,p=e.onComplete,d=e.ariaLabel,y=e.renderAriaTime,b=e.initialRemainingTime,g=T({isPlaying:a,size:t,strokeWidth:r,duration:i,initialRemainingTime:b,colors:u,isLinearGradient:f,gradientUniqueKey:s,onComplete:p}),v=g.path,h=g.pathLength,O=g.stroke,j=g.strokeDashoffset,w=g.gradientId,P=g.styles,S=g.timeProps;return o.a.createElement("div",{style:P.wrapperStyle,"aria-label":d},o.a.createElement("svg",{width:t,height:t,xmlns:"http://www.w3.org/2000/svg"},f&&o.a.createElement(m,{colors:u,gradientId:w}),o.a.createElement("path",{d:v,fill:"none",stroke:n,strokeWidth:r}),o.a.createElement("path",{d:v,fill:"none",stroke:f?"url(#".concat(w,")"):O,strokeLinecap:c,strokeWidth:r,strokeDasharray:h,strokeDashoffset:j})),null!==l&&o.a.createElement("div",{"aria-hidden":"true",style:x({},P.timeStyle,{color:O})},o.a.isValidElement(l)?o.a.cloneElement(o.a.Children.only(l),S):l(S)),"function"==typeof y&&o.a.createElement("div",{role:"timer","aria-live":"assertive",style:P.visuallyHidden},y(S)))};A.propTypes=f,A.defaultProps={size:180,strokeWidth:12,trailColor:"#d9d9d9",isPlaying:!1,strokeLinecap:"round",isLinearGradient:!1,ariaLabel:"Countdown timer",children:null},A.displayName="CountdownCircleTimer"}]); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "react-countdown-circle-timer", | ||
"version": "1.2.1", | ||
"version": "2.0.1", | ||
"description": "Lightweight React countdown timer component with color and progress animation based on SVG", | ||
"main": "./lib/index.js", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"build": "webpack", | ||
"prepare": "install-peers", | ||
"test": "jest --config jestconfig.json", | ||
"test-watch": "jest --watch" | ||
"prepublish": "yarn run build", | ||
"dev:push": "yarn run build && yalc push", | ||
"test": "jest", | ||
"test-watch": "jest --watch", | ||
"test-coverage": "jest --collectCoverage --coverageDirectory=\"coverage\"" | ||
}, | ||
@@ -17,7 +22,7 @@ "repository": { | ||
"keywords": [ | ||
"React", | ||
"Countdown", | ||
"Timer", | ||
"Circle", | ||
"Clock", | ||
"react", | ||
"countdown", | ||
"timer", | ||
"circle", | ||
"clock", | ||
"SVG" | ||
@@ -32,23 +37,12 @@ ], | ||
"peerDependencies": { | ||
"prop-types": "^15.7.0", | ||
"react": "^16.8.0", | ||
"react-dom": "^16.8.0" | ||
"prop-types": ">=15.7.0", | ||
"react": ">=16.8.0", | ||
"react-dom": ">=16.8.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.5.5", | ||
"@babel/plugin-transform-modules-commonjs": "^7.7.5", | ||
"@babel/preset-env": "^7.5.5", | ||
"@babel/preset-react": "^7.0.0", | ||
"@testing-library/jest-dom": "^4.2.4", | ||
"@testing-library/react": "^9.4.0", | ||
"babel-loader": "^8.0.6", | ||
"codecov": "^3.6.1", | ||
"install-peers-cli": "^2.1.1", | ||
"jest": "^24.9.0", | ||
"path": "^0.12.7", | ||
"react-test-renderer": "^16.8.0", | ||
"webpack": "^4.40.2", | ||
"webpack-cli": "^3.3.8" | ||
"@testing-library/react": "^9.4.0" | ||
}, | ||
"dependencies": { | ||
"@countdown-circle-timer/shared": "^1.0.3", | ||
"use-elapsed-time": "^1.1.5" | ||
@@ -60,3 +54,4 @@ }, | ||
], | ||
"types": "types/CountdownCircleTimer.d.ts" | ||
"types": "types/CountdownCircleTimer.d.ts", | ||
"gitHead": "c86bef2e82dd336e0f5ba46c0a3874126f4d60ba" | ||
} |
157
README.md
# React Countdown Circle Timer | ||
[![npm](https://img.shields.io/npm/v/react-countdown-circle-timer)](https://www.npmjs.com/package/react-countdown-circle-timer) | ||
@@ -8,23 +9,25 @@ [![npm](https://img.shields.io/npm/dw/react-countdown-circle-timer)](https://www.npmjs.com/package/react-countdown-circle-timer) | ||
React countdown timer component in a circle shape with color and progress animation to urge with pleasure your users. | ||
React countdown timer component in a circle shape with color and progress animation. | ||
<img src="https://user-images.githubusercontent.com/10707142/66097204-ca68c200-e59d-11e9-9b70-688409755aaa.gif" width="200"> <img src="https://user-images.githubusercontent.com/10707142/65935516-a0869280-e419-11e9-9bb0-40c4d1ef2bbe.gif" width="200"> <img src="https://user-images.githubusercontent.com/10707142/65963815-cfbdf380-e45b-11e9-809d-970174e88914.gif" width="200"> | ||
* Performance optimized with single `requestAnimationFrame` loop to animate color and progress (no `setInterval` used) | ||
* Transition between colors during the countdown | ||
* Support for linear gradient | ||
* Fully customizable content in the center of the circle | ||
* `a11y` support | ||
* Built-in and ready-to-use TypeScript type definitions. | ||
- Performance optimized with single `requestAnimationFrame` loop to animate color and progress (no `setInterval` used) | ||
- Transition between colors during the countdown | ||
- Support for linear gradient | ||
- Fully customizable content in the center of the circle | ||
- `a11y` support | ||
- Built-in and ready-to-use TypeScript type definitions. | ||
## Installation | ||
``` | ||
yarn add react-countdown-circle-timer | ||
``` | ||
or | ||
``` | ||
npm install react-countdown-circle-timer | ||
``` | ||
## Migrating from v1.x.x to v2.x.x? | ||
There are a few small API changes to consider before switching to v2.x.x. Read [Migrate to v2.x.x](https://github.com/vydimitrov/react-countdown-circle-timer/blob/master/packages/web/MIGRATE_TO_V2.md) docs for more info. | ||
## Demo | ||
Check the demo on CodeSandbox to get started | ||
@@ -34,17 +37,15 @@ [![Edit stoic-cache-e7cie](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/stoic-cache-e7cie?fontsize=14&hidenavigation=1&theme=dark) | ||
## Basic usage | ||
```jsx | ||
import { CountdownCircleTimer } from 'react-countdown-circle-timer'; | ||
import { CountdownCircleTimer } from 'react-countdown-circle-timer' | ||
const UrgeWithPleasureComponent = () => ( | ||
<CountdownCircleTimer | ||
isPlaying | ||
durationSeconds={10} | ||
colors={[ | ||
['#004777', .33], | ||
['#F7B801', .33], | ||
['#A30000'] | ||
]} | ||
/> | ||
); | ||
<CountdownCircleTimer | ||
isPlaying | ||
duration={10} | ||
colors={[['#004777', 0.33], ['#F7B801', 0.33], ['#A30000']]} | ||
> | ||
{({ remainingTime }) => remainingTime} | ||
</CountdownCircleTimer> | ||
) | ||
``` | ||
@@ -54,56 +55,47 @@ | ||
| Prop Name | Type | Default | Description | | ||
|--------------------|-------------------------------------------------------------------------------------|------------|------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| durationSeconds | number | *required* | Countdown duration in seconds | | ||
| colors | Array<[color HEX: string, transition duration: float number between 0 and 1]> | *required* | Array of tuples: 1st param - color in HEX format; 2nd param - time to transition to next color represented as a fraction of the total duration | | ||
| initialRemainingTime | number | - | Sets the initial remaining time when the countdown starts. By default the countdown starts at the duration provided. | | ||
| size | number | 180 | Width and height of the SVG element | | ||
| strokeWidth | number | 12 | Path stroke width | | ||
| strokeLinecap | Enum{ 'round', 'square' } | round | Path stroke line cap | | ||
| trailColor | string | #d9d9d9 | Circle trail color - takes any valid color format (HEX, rgb, rgba, etc.) | | ||
| isPlaying | boolean | false | Play and pause animation | | ||
| * isLinearGradient | boolean | false | * Apples linear gradient on top of the circle. The gradient doesn't follow the circle path. Works best with two colors. | | ||
| gradientUniqueKey | string | - | Unique ID for the linearGradient element. It takes random ID if it's not provided.| | ||
| renderTime | function(remainingTime: number, elapsedTime: number, isPlaying: boolean): number\|string\|ReactNode | - | Render prop function to customize the content in the center of the circle. The content is centered using flexbox. | | ||
| onComplete | function(): undefined \| [shouldRepeat: boolean, delay: number] | - | On complete handler. It can be used to repeat the countdown by returning an array where the first element `shouldRepeat` indicates if the loop should start over and second element `delay` specifies the delay before looping again in milliseconds. | | ||
| ariaLabel | string | Countdown timer | Aria label for the whole component | | ||
| renderAriaTime | function(remainingTime: number, elapsedTime: number, isPlaying: boolean): string | - | Render prop function to customize the text message that will be read by the screen reader during the countdown. | | ||
Refer to the [list of props](https://github.com/vydimitrov/react-countdown-circle-timer#props-for-both-reactreact-native) | ||
## Recipes | ||
### Restart timer at any given time | ||
Pass a `key` prop to `CountdownCircleTimer` and change the `key` when the timer should be restarted. | ||
### Repeat timer when countdown is completed | ||
Return an array from `onComplete` handler, which indicates if the animation should be repeated. Example: | ||
Return an array from `onComplete` handler, which indicates if the animation should be repeated. Example: | ||
```jsx | ||
const UrgeWithPleasureComponent = () => ( | ||
<CountdownCircleTimer | ||
onComplete={() => { | ||
// do your stuff here | ||
return [true, 1500]; // repeat animation in 1.5 seconds | ||
}} | ||
isPlaying | ||
durationSeconds={10} | ||
colors={[['#A30000']]} | ||
/> | ||
); | ||
<CountdownCircleTimer | ||
onComplete={() => { | ||
// do your stuff here | ||
return [true, 1500] // repeat animation in 1.5 seconds | ||
}} | ||
isPlaying | ||
duration={10} | ||
colors={[['#A30000']]} | ||
/> | ||
) | ||
``` | ||
### Set the initial remaining time different then the duration provided | ||
Pass the remaining time to `initialRemainingTime` prop. Example: | ||
```jsx | ||
const UrgeWithPleasureComponent = () => ( | ||
<CountdownCircleTimer | ||
isPlaying | ||
durationSeconds={60} | ||
initialRemainingTime={15} | ||
colors={[['#A30000']]} | ||
/> | ||
); | ||
<CountdownCircleTimer | ||
isPlaying | ||
duration={60} | ||
initialRemainingTime={15} | ||
colors={[['#A30000']]} | ||
/> | ||
) | ||
``` | ||
In the example above, the countdown will start at 15 seconds (one quarter before it's done) and it will animate for 15 seconds until reaches 0. | ||
### Slide down time animation | ||
In the example above, the countdown will start at 15 seconds (one quarter before it's done) and it will animate for 15 seconds until reaches 0. | ||
### Slide down time animation | ||
Here is an example on how you can achieve the animation below: | ||
@@ -113,14 +105,14 @@ <img src="https://user-images.githubusercontent.com/10707142/65963815-cfbdf380-e45b-11e9-809d-970174e88914.gif" width="200"> | ||
```jsx | ||
const renderTime = time => { | ||
const currentTime = useRef(time); | ||
const prevTime = useRef(null); | ||
const isNewTimeFirstTick = useRef(false); | ||
const [_, setOneLastRerender] = useState(0); | ||
const renderTime = (time) => { | ||
const currentTime = useRef(time) | ||
const prevTime = useRef(null) | ||
const isNewTimeFirstTick = useRef(false) | ||
const [_, setOneLastRerender] = useState(0) | ||
if (currentTime.current !== time) { | ||
isNewTimeFirstTick.current = true; | ||
prevTime.current = currentTime.current; | ||
isNewTimeFirstTick.current = true | ||
prevTime.current = currentTime.current | ||
currentTime.current = time | ||
} else { | ||
isNewTimeFirstTick.current = false; | ||
isNewTimeFirstTick.current = false | ||
} | ||
@@ -131,14 +123,11 @@ | ||
setTimeout(() => { | ||
setOneLastRerender(val => val + 1); | ||
}, 20); | ||
setOneLastRerender((val) => val + 1) | ||
}, 20) | ||
} | ||
const isTimeUp = isNewTimeFirstTick.current; | ||
const isTimeUp = isNewTimeFirstTick.current | ||
return ( | ||
<div className="time-wrapper"> | ||
<div | ||
key={time} | ||
className={`time ${isTimeUp ? 'up' : ''}`} | ||
> | ||
<div key={time} className={`time ${isTimeUp ? 'up' : ''}`}> | ||
{time} | ||
@@ -155,5 +144,4 @@ </div> | ||
</div> | ||
); | ||
}; | ||
) | ||
} | ||
``` | ||
@@ -171,3 +159,3 @@ | ||
position: absolute; | ||
left:0; | ||
left: 0; | ||
top: 0; | ||
@@ -181,3 +169,3 @@ width: 100%; | ||
opacity: 1; | ||
transition: all .2s; | ||
transition: all 0.2s; | ||
} | ||
@@ -187,3 +175,3 @@ | ||
opacity: 0; | ||
transform: translateY(-100%) | ||
transform: translateY(-100%); | ||
} | ||
@@ -193,7 +181,6 @@ | ||
opacity: 0; | ||
transform: translateY(100%) | ||
transform: translateY(100%); | ||
} | ||
``` | ||
Feed the `renderTime` function above to the `CountdownCircleTimer` `renderTime` prop and add the styles above to your stylesheet. | ||
Feed the `renderTime` function above to the `CountdownCircleTimer` `children` prop and add the styles above to your stylesheet. |
@@ -1,52 +0,57 @@ | ||
import * as React from 'react'; | ||
import * as useElapsedTime from 'use-elapsed-time'; | ||
import * as React from 'react' | ||
import { Config } from 'use-elapsed-time' | ||
interface RenderTime<T> { | ||
(remainingTime: number, elapsedTime: number, isPlaying: boolean): T | ||
export type OnComplete = Config['onComplete'] | ||
export interface TimeProps { | ||
remainingTime?: number | ||
elapsedTime?: number | ||
} | ||
type Color = [string, number]; | ||
type ChildAsFunc = { | ||
(props: TimeProps): number | string | React.ReactNode | ||
} | ||
type Color = [string, number] | ||
type Colors = { | ||
0: Color | ||
} & Array<Color>; | ||
0: Color | ||
} & Array<Color> | ||
export interface CountdownCircleTimerProps { | ||
/** Countdown duration in seconds */ | ||
durationSeconds: number, | ||
/** Array of tuples: 1st param - color in HEX format; 2nd param - time to transition to next color represented as a fraction of the total duration */ | ||
colors: Colors, | ||
/** Set the initial remaining time if it is diffrent than the duration */ | ||
initialRemainingTime?: number, | ||
/** Width and height of the SVG element. Default: 180 */ | ||
size?: number, | ||
/** Path stroke width. Default: 12 */ | ||
strokeWidth?: number, | ||
/** Path stroke line cap. Default: "round" */ | ||
strokeLinecap?: 'round' | 'square', | ||
/** Circle trail color - takes any valid color format (HEX, rgb, rgba, etc.). Default: #d9d9d9 */ | ||
trailColor?: string, | ||
/** Play and pause animation. Default: false */ | ||
isPlaying?: boolean, | ||
/** Apples linear gradient on top of the circle. The gradient doesn't follow the circle path. Works best with two colors. Default: false */ | ||
isLinearGradient?: boolean, | ||
/** Unique ID for the linearGradient element. It takes random ID if it's not provided */ | ||
gradientUniqueKey?: string, | ||
/** Render prop function to customize the content in the center of the circle */ | ||
renderTime?: RenderTime<number | string | React.ReactNode>, | ||
/** | ||
* On animation complete event handler. It can be used to restart the animation by returning an array | ||
* where the first element "shouldRepeat" indicates if the loop should start over | ||
* and second element "delay" specifies the delay before looping again in milliseconds. | ||
* | ||
*/ | ||
onComplete?: useElapsedTime.Config.onComplete, | ||
/** Aria label for the whole component. Default: "Countdown timer" */ | ||
ariaLabel?: string, | ||
/** Render prop function to customize the text message that will be read by the screen reader during the countdown */ | ||
renderAriaTime?: RenderTime<string> | ||
/** Countdown duration in seconds */ | ||
duration: number | ||
/** Array of tuples: 1st param - color in HEX format; 2nd param - time to transition to next color represented as a fraction of the total duration */ | ||
colors: Colors | ||
/** Set the initial remaining time if it is different than the duration */ | ||
initialRemainingTime?: number | ||
/** Width and height of the SVG element. Default: 180 */ | ||
size?: number | ||
/** Path stroke width. Default: 12 */ | ||
strokeWidth?: number | ||
/** Path stroke line cap. Default: "round" */ | ||
strokeLinecap?: 'round' | 'square' | ||
/** Circle trail color - takes any valid color format (HEX, rgb, rgba, etc.). Default: #d9d9d9 */ | ||
trailColor?: string | ||
/** Play and pause animation. Default: false */ | ||
isPlaying?: boolean | ||
/** Apples linear gradient on top of the circle. The gradient doesn't follow the circle path. Works best with two colors. Default: false */ | ||
isLinearGradient?: boolean | ||
/** Unique ID for the linearGradient element. It takes random ID if it's not provided */ | ||
gradientUniqueKey?: string | ||
/** Render function or component to customize the time/content in the center of the circle */ | ||
children?: React.ReactNode | ChildAsFunc | ||
/** | ||
* On animation complete event handler. It can be used to restart the animation by returning an array | ||
* where the first element "shouldRepeat" indicates if the loop should start over | ||
* and second element "delay" specifies the delay before looping again in milliseconds. | ||
* | ||
*/ | ||
onComplete?: OnComplete | ||
/** Aria label for the whole component. Default: "Countdown timer" */ | ||
ariaLabel?: string | ||
/** Render prop function to customize the text message that will be read by the screen reader during the countdown */ | ||
renderAriaTime?: (props: TimeProps) => string | ||
} | ||
declare const CountdownCircleTimer: React.FunctionComponent<CountdownCircleTimerProps>; | ||
export { | ||
CountdownCircleTimer | ||
}; | ||
declare const CountdownCircleTimer: React.FunctionComponent<CountdownCircleTimerProps> | ||
export { CountdownCircleTimer } |
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
59715
2
101
5
177
+ Addedreact@18.3.1(transitive)
+ Addedreact-dom@18.3.1(transitive)
+ Addedscheduler@0.23.2(transitive)
- Removedreact@16.14.0(transitive)
- Removedreact-dom@16.14.0(transitive)
- Removedscheduler@0.19.1(transitive)