New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-countup

Package Overview
Dependencies
Maintainers
1
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-countup - npm Package Compare versions

Comparing version 3.0.3 to 4.0.0-alpha.0

src/__tests__/__snapshots__/CountUp.test.js.snap

270

build/index.js
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.startAnimation = exports.formatNumber = undefined;
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var Count = _interopDefault(require('countup.js'));
var PropTypes = _interopDefault(require('prop-types'));
var React = require('react');
var React__default = _interopDefault(React);
var warning = _interopDefault(require('warning'));
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _react2 = _interopRequireDefault(_react);
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
var _countup = require('countup.js');
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _countup2 = _interopRequireDefault(_countup);
var CountUp = function (_Component) {
_inherits(CountUp, _Component);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function CountUp() {
var _ref;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _temp, _this, _ret;
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
_classCallCheck(this, CountUp);
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
// Adapted from the countup.js format number function
// https://github.com/inorganik/countUp.js/blob/master/countUp.js#L46-L60
var formatNumber = exports.formatNumber = function formatNumber(start, options) {
var neg = start < 0;
var num = '' + Math.abs(start).toFixed(options.decimals);
var x = num.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '' + options.decimal + x[1] : '';
var rgx = /(\d+)(\d{3})/;
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = CountUp.__proto__ || Object.getPrototypeOf(CountUp)).call.apply(_ref, [this].concat(args))), _this), _this.createInstance = function () {
// Warn when user didn't use containerRef at all
warning(_this.containerRef.current && _this.containerRef.current instanceof HTMLElement, 'Couldn\'t find attached element to hook the CountUp instance into! Try to attach "containerRef" from the render prop to a an HTMLElement, eg. <span ref={containerRef} />.');
if (options.separator) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + options.separator + '$2');
}
}
var _this$props = _this.props,
decimal = _this$props.decimal,
decimals = _this$props.decimals,
duration = _this$props.duration,
easingFn = _this$props.easingFn,
end = _this$props.end,
formattingFn = _this$props.formattingFn,
prefix = _this$props.prefix,
separator = _this$props.separator,
start = _this$props.start,
suffix = _this$props.suffix,
useEasing = _this$props.useEasing;
return '' + (neg ? '-' : '') + (options.prefix || '') + x1 + x2 + (options.suffix || '');
};
var startAnimation = exports.startAnimation = function startAnimation(component) {
if (!(component && component.spanElement)) {
throw new Error('You need to pass the CountUp component as an argument!\neg. this.myCountUp.startAnimation(this.myCountUp);');
}
return new Count(_this.containerRef.current, start, end, decimals, duration, {
decimal: decimal,
easingFn: easingFn,
formattingFn: formattingFn,
separator: separator,
prefix: prefix,
suffix: suffix,
useEasing: useEasing,
useGrouping: !!separator
});
}, _this.pauseResume = function () {
var _this2 = _this,
reset = _this2.reset,
start = _this2.restart,
update = _this2.update;
var onPauseResume = _this.props.onPauseResume;
var _component$props = component.props,
decimal = _component$props.decimal,
decimals = _component$props.decimals,
duration = _component$props.duration,
easingFn = _component$props.easingFn,
end = _component$props.end,
formattingFn = _component$props.formattingFn,
onComplete = _component$props.onComplete,
onStart = _component$props.onStart,
prefix = _component$props.prefix,
separator = _component$props.separator,
start = _component$props.start,
suffix = _component$props.suffix,
useEasing = _component$props.useEasing;
_this.instance.pauseResume();
var countupInstance = new _countup2.default(component.spanElement, start, end, decimals, duration, {
decimal: decimal,
easingFn: easingFn,
formattingFn: formattingFn,
separator: separator,
prefix: prefix,
suffix: suffix,
useEasing: useEasing,
useGrouping: !!separator
});
onPauseResume({ reset: reset, start: start, update: update });
}, _this.reset = function () {
var _this3 = _this,
pauseResume = _this3.pauseResume,
start = _this3.restart,
update = _this3.update;
var onReset = _this.props.onReset;
if (typeof onStart === 'function') {
onStart();
}
countupInstance.start(onComplete);
};
_this.instance.reset();
var CountUp = function (_React$Component) {
_inherits(CountUp, _React$Component);
onReset({ pauseResume: pauseResume, start: start, update: update });
}, _this.restart = function () {
_this.reset();
_this.start();
}, _this.start = function () {
var _this4 = _this,
pauseResume = _this4.pauseResume,
reset = _this4.reset,
start = _this4.restart,
update = _this4.update;
var _this$props2 = _this.props,
onEnd = _this$props2.onEnd,
onStart = _this$props2.onStart;
function CountUp() {
var _ref;
var _temp, _this, _ret;
_this.instance.start(function () {
return onEnd({ pauseResume: pauseResume, reset: reset, start: start, update: update });
});
_classCallCheck(this, CountUp);
onStart({ pauseResume: pauseResume, reset: reset, update: update });
}, _this.update = function (newEnd) {
var _this5 = _this,
pauseResume = _this5.pauseResume,
reset = _this5.reset,
start = _this5.restart;
var onUpdate = _this.props.onUpdate;
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = CountUp.__proto__ || Object.getPrototypeOf(CountUp)).call.apply(_ref, [this].concat(args))), _this), _this.spanElement = null, _this.refSpan = function (span) {
_this.spanElement = span;
}, _temp), _possibleConstructorReturn(_this, _ret);
_this.instance.update(newEnd);
onUpdate({ pauseResume: pauseResume, reset: reset, start: start });
}, _this.containerRef = React__default.createRef(), _temp), _possibleConstructorReturn(_this, _ret);
}

@@ -106,3 +119,16 @@

value: function componentDidMount() {
startAnimation(this);
var _props = this.props,
children = _props.children,
delay = _props.delay;
this.instance = this.createInstance();
// Delay start if delay prop is properly set
if (delay > 0) return setTimeout(this.start, delay * 1000);
// Don't invoke start if the component is used as a render prop
if (typeof children === 'function') return;
// Otherwise just start immediately
this.start();
}

@@ -114,8 +140,21 @@ }, {

return nextProps.redraw || hasCertainPropsChanged;
return hasCertainPropsChanged || this.props.redraw;
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
startAnimation(this);
value: function componentDidUpdate(prevProps) {
// If duration or start has changed, there's no way to update the duration
// or start value. So we need to re-create the CountUp instance in order to
// restart it.
if (this.props.duration !== prevProps.duration || this.props.start !== prevProps.start) {
this.instance = this.createInstance();
this.start();
}
// Only end value has changed, so reset and and re-animate with the updated
// end value.
if (this.props.end !== prevProps.end) {
this.instance.reset();
this.instance.update(this.props.end);
}
}

@@ -125,25 +164,24 @@ }, {

value: function render() {
var _props = this.props,
className = _props.className,
start = _props.start,
decimal = _props.decimal,
decimals = _props.decimals,
separator = _props.separator,
prefix = _props.prefix,
suffix = _props.suffix,
style = _props.style,
formattingFn = _props.formattingFn;
var _props2 = this.props,
children = _props2.children,
className = _props2.className,
style = _props2.style;
var containerRef = this.containerRef,
pauseResume = this.pauseResume,
reset = this.reset,
restart = this.restart,
update = this.update;
return _react2.default.createElement(
'span',
{ className: className, ref: this.refSpan, style: style },
typeof formattingFn === 'function' ? formattingFn(start) : formatNumber(start, {
decimal: decimal,
decimals: decimals,
separator: separator,
prefix: prefix,
suffix: suffix
})
);
if (typeof children === 'function') {
return children({
countUpRef: containerRef,
pauseResume: pauseResume,
reset: reset,
start: restart,
update: update
});
}
return React__default.createElement('span', { className: className, ref: containerRef, style: style });
}

@@ -153,22 +191,42 @@ }]);

return CountUp;
}(_react2.default.Component);
}(React.Component);
CountUp.propTypes = {
decimal: PropTypes.string,
decimals: PropTypes.number,
delay: PropTypes.number,
easingFn: PropTypes.func,
end: PropTypes.number.isRequired,
formattingFn: PropTypes.func,
onEnd: PropTypes.func,
onStart: PropTypes.func,
prefix: PropTypes.string,
redraw: PropTypes.bool,
separator: PropTypes.string,
start: PropTypes.number,
suffix: PropTypes.string,
style: PropTypes.object,
useEasing: PropTypes.bool
};
CountUp.defaultProps = {
className: undefined,
decimal: '.',
decimals: 0,
duration: 3,
delay: 0,
duration: null,
easingFn: null,
end: 100,
formattingFn: null,
onComplete: undefined,
onStart: undefined,
onEnd: function onEnd() {},
onPauseResume: function onPauseResume() {},
onReset: function onReset() {},
onStart: function onStart() {},
onUpdate: function onUpdate() {},
prefix: '',
redraw: false,
separator: '',
start: 0,
suffix: '',
redraw: false,
style: undefined,
useEasing: true
};
exports.default = CountUp;
module.exports = CountUp;
{
"name": "react-countup",
"version": "3.0.3",
"version": "4.0.0-alpha.0",
"description": "A React component wrapper around CountUp.js",

@@ -16,6 +16,3 @@ "author": "Glenn Reyes <glenn@glennreyes.com> (https://twitter.com/glnnrys)",

"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/glennreyes/react-countup.git"
},
"repository": "glennreyes/react-countup",
"bugs": {

@@ -31,39 +28,41 @@ "url": "https://github.com/glennreyes/react-countup/issues"

"scripts": {
"build": "babel src -d build --ignore __tests__",
"flow": "flow check",
"lint": "eslint src",
"build": "rollup -c",
"precommit": "lint-staged",
"prepare": "yarn run build",
"prettier": "prettier --write src/**/*.js",
"prepublishOnly": "yarn build",
"test": "jest"
},
"peerDependencies": {
"react": "^16.0.0"
"react": ">= 16.3.0"
},
"dependencies": {
"countup.js": "^1.9.3"
"countup.js": "^1.9.3",
"prop-types": "^15.6.2",
"warning": "^4.0.1"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-eslint": "^8.0.2",
"babel-preset-env": "^1.6.1",
"babel-core": "^6.26.3",
"babel-eslint": "^7.2.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"eslint": "^4.11.0",
"eslint-config-airbnb": "^16.1.0",
"eslint-config-prettier": "^2.7.0",
"eslint-plugin-flowtype": "^2.39.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^6.0.2",
"eslint-plugin-react": "^7.4.0",
"flow-bin": "^0.59.0",
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
"eslint-config-react-app": "^2.1.0",
"eslint-plugin-flowtype": "^2.50.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-prettier": "^2.6.2",
"eslint-plugin-react": "^7.10.0",
"husky": "^0.14.3",
"jest": "^21.2.1",
"lint-staged": "^5.0.0",
"prettier": "^1.8.2",
"jest": "^23.4.2",
"lint-staged": "^7.2.0",
"prettier": "^1.14.1",
"raf": "^3.4.0",
"react": "^16.1.1",
"react-dom": "^16.1.1",
"react-test-renderer": "^16.1.1"
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-test-renderer": "^16.4.2",
"react-testing-library": "^4.1.7",
"rollup": "^0.64.1",
"rollup-plugin-babel": "^3.0.7"
}
}

@@ -1,20 +0,51 @@

# [React CountUp](https://glennreyes.github.io/react-countup)
# React CountUp
[![Build Status](https://travis-ci.org/glennreyes/react-countup.svg?branch=master)](https://travis-ci.org/glennreyes/react-countup)
[![Coverage Status](https://coveralls.io/repos/github/glennreyes/react-countup/badge.svg?branch=master)](https://coveralls.io/github/glennreyes/react-countup?branch=master)
[![Dependency Status](https://david-dm.org/glennreyes/react-countup.svg)](https://david-dm.org/glennreyes/react-countup)
[![Dependency Status](https://david-dm.org/glennreyes/react-countup/dev-status.svg)](https://david-dm.org/glennreyes/react-countup#info=devDependencies)
[![npm version](https://badge.fury.io/js/react-countup.svg)](https://badge.fury.io/js/react-countup)
[![GitHub license](https://img.shields.io/npm/l/react-countup.svg?style=flat-square)](https://github.com/glennreyes/react-countup/blob/master/LICENSE)
[![Build Status](https://img.shields.io/travis/glennreyes/react-countup.svg?style=flat-square)](https://travis-ci.org/glennreyes/react-countup)
[![Coverage Status](https://img.shields.io/coveralls/glennreyes/react-countup.svg?style=flat-square)](https://coveralls.io/github/glennreyes/react-countup)
[![Version](https://img.shields.io/npm/v/react-countup.svg?style=flat-square)](https://www.npmjs.com/package/react-countup)
[![Downloads](https://img.shields.io/npm/dm/react-countup.svg?style=flat-square)](http://www.npmtrends.com/react-countup)
[![Gzip size](https://img.badgesize.io/https://unpkg.com/react-countup?style=flat-square&compression=gzip)](https://img.badgesize.io/https://unpkg.com/react-countup)
A configurable React component wrapper around [CountUp.js](https://inorganik.github.io/countUp.js/).
![sep -15-2016 10-11-53 pm](https://cloud.githubusercontent.com/assets/5080854/18565869/d23db0e0-7b91-11e6-9ee2-71be5875ca48.gif)
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Simple example](#simple-example)
- [Advanced example](#render-prop-example)
- [More examples](#more-examples)
- [Manually start](#manually-start)
- [Delay start](#delay-start)
- [API](#api)
- [Props](#props)
- [`className: string`](#classname-string)
- [`decimal: string`](#decimal-string)
- [`decimals: number`](#decimals-number)
- [`delay: number`](#delay-number)
- [`duration: number`](#duration-number)
- [`end: number`](#end-number)
- [`prefix: string`](#prefix-string)
- [`redraw: boolean`](#redraw-boolean)
- [`separator: string`](#separator-string)
- [`start: number`](#start-number)
- [`suffix: string`](#suffix-string)
- [`useEasing: boolean`](#useeasing-boolean)
- [`easingFn: (t: number, b: number, c: number, d: number) => number`](#easingfn-t-number-b-number-c-number-d-number--number)
- [`formattingFn: (value: number) => string`](#formattingfn-value-number--string)
- [`onEnd: ({ pauseResume, reset, start, update }) => void`](#onend--pauseresume-reset-start-update---void)
- [`onStart: ({ pauseResume, reset, update }) => void`](#onstart--pauseresume-reset-update---void)
- [`onPauseResume: ({ reset, start, update }) => void`](#onpauseresume--reset-start-update---void)
- [`onReset: ({ pauseResume, start, update }) => void`](#onreset--pauseresume-start-update---void)
- [`onUpdate: ({ pauseResume, reset, start }) => void`](#onupdate--pauseresume-reset-start---void)
- [Render props](#render-props)
- [`countUpRef: () => void`](#countupref---void)
- [`pauseResume: () => void`](#pauseresume---void)
- [`reset: () => void`](#reset---void)
- [`start: () => void`](#start---void)
- [`update: (newEnd: number?) => void`](#update-newend-number--void)
- [Protips](#protips)
- [License](#license)
## [Demo](https://glennreyes.github.io/react-countup)
Check out the [demo](https://glennreyes.github.io/react-countup).
## Installation

@@ -26,108 +57,207 @@

Alternatively with npm:
```bash
npm install react-countup --save
## Usage
```js
import CountUp from 'react-countup';
```
### Simple example
## Usage
```js
<CountUp end={100} />
```
#### Simple
This will start a count up transition from `0` to `100` on render.
### Render prop example
```js
import React from 'react';
import { render } from 'react-dom';
import CountUp from 'react-countup';
<CountUp
className="account-balance"
start={-875.039}
end={160527.012}
duration={2.75}
separator=" "
decimals={4}
decimal=","
prefix="EUR "
suffix=" left"
onEnd={() => console.log('Ended! 👏')}
onStart={() => console.log('Started! 💨')}
>
{({ countUpRef, start }) => (
<div>
<span ref={countUpRef} />
<button onClick={start}>Start</button>
</div>
)}
</CountUp>
```
render(
<CountUp start={0} end={160526} />,
document.getElementById('root')
);
The transition won't start on initial render as it needs to be triggered manually here.
> Tip: If you need to start the render prop component immediately, you can set delay={0}.
### More examples
#### Autostart with render prop
Render start value but start transition on first render:
```js
<CountUp start={0} end={100} delay={0}>
{({ countUpRef, start }) => (
<div>
<span ref={countUpRef} />
<button onClick={start}>Start</button>
</div>
)}
</CountUp>
```
#### Advanced
Render start value and start transition:
```js
import React from 'react';
import { render } from 'react-dom';
import CountUp from 'react-countup';
<CountUp start={0} end={100}>
{({ countUpref, start }) => (
<div>
<span ref={countUpRef} />
<button onClick={start}>Start</button>
</div>
)}
</CountUp>
```
const onComplete = () => {
console.log('Completed! 👏');
};
#### Delay start
const onStart = () => {
console.log('Started! 💨');
};
render(
<CountUp
className="account-balance"
start={160527.0127}
end={-875.0319}
duration={2.75}
useEasing={true}
useGrouping={true}
separator=" "
decimals={4}
decimal=","
prefix="EUR "
suffix=" left"
onComplete={onComplete}
onStart={onStart}
/>,
document.getElementById('root'),
);
```js
<CountUp delay={2} end={100} />
```
## API
### Props
##### `start`: number
Start value
#### `className: string`
##### `end`: number
Target value
CSS class name of the span element.
##### `duration`: number
Duration in seconds
> Note: This won't be applied when using CountUp with render props.
##### `decimals`: number
Amount of decimals
#### `decimal: string`
##### `useEasing`: boolean
Enable easing if set to `true` (default easing: `easeOutExpo`)
Specifies decimal character.
##### `separator`: string
Specifies character of thousands separator
Default: `.`
##### `decimal`: string
Specifies decimal character
#### `decimals: number`
##### `prefix`: string
Static text before the animating value
Amount of decimals to display.
##### `suffix`: string
Static text after the animating value
Default: `0`
##### `className`: string
CSS class name of the span element
#### `delay: number`
##### `redraw`: boolean
If set to `true`, the CountUp component will always animate on every re-render.
Delay in seconds before starting the transition.
##### `onComplete`: function
Function called after animation has completed
Default: `null`
##### `onStart`: function
Function called before animation starts
> Note: `delay={0}` will automatically start the count up.
##### `easingFn`: function
Easing function, see [here for instructions](https://github.com/inorganik/countUp.js#custom-easing)
#### `duration: number`
##### `formattingFn`: function
Duration in seconds.
Default: `2`
#### `end: number`
Target value.
#### `prefix: string`
Static text before the transitioning value.
#### `redraw: boolean`
Forces count up transition on every component update.
Default: `false`
#### `separator: string`
Specifies character of thousands separator.
#### `start: number`
Initial value.
Default: `0`
#### `suffix: string`
Static text after the transitioning value.
#### `useEasing: boolean`
Enables easing. Set to `false` for a linear transition.
Default: `true`
#### `easingFn: (t: number, b: number, c: number, d: number) => number`
Easing function. Click [here](http://robertpenner.com/easing) for more details.
Default: [`easeInExpo`](https://github.com/inorganik/countUp.js/blob/master/countUp.js#L103-L106)
#### `formattingFn: (value: number) => string`
Function to customize the formatting of the number
#### `onEnd: ({ pauseResume, reset, start, update }) => void`
Callback function on transition end.
#### `onStart: ({ pauseResume, reset, update }) => void`
Callback function on transition start.
#### `onPauseResume: ({ reset, start, update }) => void`
Callback function on pause or resume.
#### `onReset: ({ pauseResume, start, update }) => void`
Callback function on reset.
#### `onUpdate: ({ pauseResume, reset, start }) => void`
Callback function on update.
### Render props
#### `countUpRef: () => void`
Ref to hook the countUp instance to
#### `pauseResume: () => void`
Pauses or resumes the transition
#### `reset: () => void`
Resets to initial value
#### `start: () => void`
Starts or restarts the transition
#### `update: (newEnd: number?) => void`
Updates transition to the new end value (if given)
## Protips
By default, the animation is triggered if any of the following props has changed:
- `duration`

@@ -137,25 +267,6 @@ - `end`

You can set `redraw` to `true` If you want your component to always animate on every re-render.
If `redraw` is set to `true` your component will start the transition on every component update.
### Manually start the animation
## License
```js
import React, { Component } from 'react';
import CountUp, { startAnimation } from 'react-countup';
const MyComponent = () => (
<div>
<CountUp className="CountUp" start={0} end={100} duration={3} ref={(countUp) => {
this.myCountUp = countUp;
}} />
<button className="Button" onClick={(event) => {
startAnimation(this.myCountUp);
}}>Count me up!</button>
</div>
);
export default App;
```
## License
MIT

@@ -1,179 +0,1 @@

// @flow
import React from 'react';
import Count from 'countup.js';
import type { Component } from 'react';
type Props = {
className: string,
decimal: string,
decimals: number,
duration: number,
easingFn: () => void,
end: number,
formattingFn: (start: number) => string,
onComplete: () => void,
onStart: () => void,
prefix: string,
redraw: boolean,
separator: string,
start: number,
style: {},
suffix: string,
useEasing: boolean,
};
type FormatNumberFn = (
start: number,
options: {
decimal: string,
decimals: number,
separator: string,
prefix: string,
suffix: string,
},
) => string;
// Adapted from the countup.js format number function
// https://github.com/inorganik/countUp.js/blob/master/countUp.js#L46-L60
export const formatNumber: FormatNumberFn = (start, options) => {
const neg = start < 0;
const num = `${Math.abs(start).toFixed(options.decimals)}`;
const x = num.split('.');
let x1 = x[0];
const x2 = x.length > 1 ? `${options.decimal}${x[1]}` : '';
const rgx = /(\d+)(\d{3})/;
if (options.separator) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, `$1${options.separator}$2`);
}
}
return `${neg ? '-' : ''}${options.prefix || ''}${x1}${x2}${options.suffix ||
''}`;
};
export const startAnimation = (component: Component<*, *>) => {
if (!(component && component.spanElement)) {
throw new Error(
'You need to pass the CountUp component as an argument!\neg. this.myCountUp.startAnimation(this.myCountUp);',
);
}
const {
decimal,
decimals,
duration,
easingFn,
end,
formattingFn,
onComplete,
onStart,
prefix,
separator,
start,
suffix,
useEasing,
}: Props = component.props;
const countupInstance = new Count(
component.spanElement,
start,
end,
decimals,
duration,
{
decimal,
easingFn,
formattingFn,
separator,
prefix,
suffix,
useEasing,
useGrouping: !!separator,
},
);
if (typeof onStart === 'function') {
onStart();
}
countupInstance.start(onComplete);
};
export default class CountUp extends React.Component<*, *> {
static defaultProps = {
className: undefined,
decimal: '.',
decimals: 0,
duration: 3,
easingFn: null,
end: 100,
formattingFn: null,
onComplete: undefined,
onStart: undefined,
prefix: '',
separator: '',
start: 0,
suffix: '',
redraw: false,
style: undefined,
useEasing: true,
};
componentDidMount() {
startAnimation(this);
}
shouldComponentUpdate(nextProps: Props) {
const hasCertainPropsChanged =
this.props.duration !== nextProps.duration ||
this.props.end !== nextProps.end ||
this.props.start !== nextProps.start;
return nextProps.redraw || hasCertainPropsChanged;
}
componentDidUpdate() {
startAnimation(this);
}
spanElement = null;
refSpan = (span: Element<*>) => {
this.spanElement = span;
};
refSpan: () => void;
props: Props;
render() {
const {
className,
start,
decimal,
decimals,
separator,
prefix,
suffix,
style,
formattingFn,
} = this.props;
return (
<span className={className} ref={this.refSpan} style={style}>
{typeof formattingFn === 'function'
? formattingFn(start)
: formatNumber(start, {
decimal,
decimals,
separator,
prefix,
suffix,
})}
</span>
);
}
}
export { default } from './CountUp';

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc