-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rebuild for TypeScript #514
Changes from 3 commits
770c2ec
ab1247c
b3a9f47
a350e77
840fe99
9e9a18f
7515613
6b1f465
5b9412a
cdad744
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,16 @@ | ||
{ | ||
"plugins": ["@babel/plugin-proposal-class-properties"], | ||
"presets": [ | ||
["@babel/preset-env", { "modules": false }], | ||
"@babel/preset-react" | ||
"@babel/preset-react", | ||
"@babel/preset-typescript" | ||
], | ||
"plugins": ["@babel/plugin-proposal-class-properties"], | ||
"env": { | ||
"test": { | ||
"plugins": ["@babel/plugin-proposal-class-properties"], | ||
"presets": [["@babel/preset-env", { "targets": { "node": "current" } }]] | ||
"presets": [ | ||
["@babel/preset-env", { "targets": { "node": "current" } }] | ||
] | ||
} | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,21 +20,25 @@ | |
"homepage": "https://react-countup.now.sh", | ||
"main": "build", | ||
"files": [ | ||
"build", | ||
"index.d.ts" | ||
"build" | ||
], | ||
"typings": "index.d.ts", | ||
"typings": "build/index.d.ts", | ||
"scripts": { | ||
"build": "rollup -c", | ||
"build": "rollup -c && tsc --emitDeclarationOnly --noEmit false --project src/tsconfig.json --outDir build", | ||
"prepublishOnly": "yarn build", | ||
"test": "jest" | ||
}, | ||
"peerDependencies": { | ||
"react": ">= 16.3.0" | ||
}, | ||
"dependencies": { | ||
"@babel/preset-typescript": "^7.14.5", | ||
"@rollup/plugin-node-resolve": "^13.0.2", | ||
"@rollup/plugin-typescript": "^8.2.3", | ||
"@types/warning": "^3.0.0", | ||
"countup.js": "^2.0.7", | ||
"prop-types": "^15.7.2", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i suppose that we can remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. derp, yes I've now cleaned up package.json to put deps in the right place and remove |
||
"typescript": "^4.3.5", | ||
"warning": "^4.0.3" | ||
}, | ||
"devDependencies": { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,22 @@ | ||
import PropTypes from 'prop-types'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that prop types should be removed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh yeah for sure. Feel free to make this change to my PR branch as I probably can't circle back until midweek. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed prop types. |
||
import React, { Component } from 'react'; | ||
import React, { Component, CSSProperties } from 'react'; | ||
import warning from 'warning'; | ||
import { createCountUpInstance } from './common'; | ||
import { CountUp as CountUpJs } from 'countup.js'; | ||
import { CallbackProps, CommonProps, RenderCounterProps } from './types'; | ||
|
||
export interface CountUpProps extends CommonProps, CallbackProps { | ||
className?: string; | ||
redraw?: boolean; | ||
preserveValue?: boolean; | ||
children?: (props: RenderCounterProps) => React.ReactNode; | ||
style?: CSSProperties; | ||
} | ||
|
||
class CountUp extends Component<CountUpProps> { | ||
private instance: CountUpJs | undefined; | ||
private timeoutId: NodeJS.Timeout | undefined; | ||
|
||
class CountUp extends Component { | ||
static propTypes = { | ||
decimal: PropTypes.string, | ||
decimals: PropTypes.number, | ||
|
@@ -58,7 +71,7 @@ class CountUp extends Component { | |
this.start(); | ||
} | ||
|
||
checkProps = (updatedProps) => { | ||
checkProps = (updatedProps: CountUpProps) => { | ||
const { | ||
start, | ||
suffix, | ||
|
@@ -86,20 +99,20 @@ class CountUp extends Component { | |
return hasPropsChanged || redraw; | ||
}; | ||
|
||
shouldComponentUpdate(nextProps) { | ||
shouldComponentUpdate(nextProps: CountUpProps) { | ||
const { end } = this.props; | ||
return this.checkProps(nextProps) || end !== nextProps.end; | ||
} | ||
|
||
componentDidUpdate(prevProps) { | ||
componentDidUpdate(prevProps: CountUpProps) { | ||
// If duration, suffix, prefix, separator or start has changed | ||
// there's no way to update the values. | ||
// So we need to re-create the CountUp instance in order to | ||
// restart it. | ||
const { end, preserveValue } = this.props; | ||
|
||
if (this.checkProps(prevProps)) { | ||
this.instance.reset(); | ||
this.instance?.reset(); | ||
this.instance = this.createInstance(); | ||
this.start(); | ||
} | ||
|
@@ -108,18 +121,19 @@ class CountUp extends Component { | |
// end value. | ||
if (end !== prevProps.end) { | ||
if (!preserveValue) { | ||
this.instance.reset(); | ||
this.instance?.reset(); | ||
} | ||
this.instance.update(end); | ||
this.instance?.update(end); | ||
} | ||
} | ||
|
||
componentWillUnmount() { | ||
if (this.timeoutId) { | ||
clearTimeout(this.timeoutId); | ||
} | ||
if (this.instance.target) { | ||
this.instance.reset(); | ||
// instance.target is incorrectly marked private by typescript | ||
if ((this.instance as any).target) { | ||
this.instance?.reset(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that we should simplify this to: this.instance?.reset(); and we can skip creation of CountUp instance in createInstance = () => {
if (typeof this.props.children === 'function') {
// Warn when user didn't use containerRef at all
warning(
this.containerRef.current &&
(this.containerRef.current instanceof HTMLElement ||
this.containerRef.current instanceof SVGTextElement ||
this.containerRef.current instanceof SVGTSpanElement),
`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} />.`,
);
return;
}
return createCountUpInstance(this.containerRef.current, this.props);
}; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR is meant to be a types-only change and while I'm sure that check could be simpler, I'd recommend non-ts changes be added to my other PR moving to a hook-first approach. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the component CountUp must actually initialize the instance on mount for backwards compatibility - the tests all test for CountUp having 0 (props.start) in the component instead of an empty container. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved the this.instance check to the right spot (before checking this.instance.target). This createInstance function is actually for creating the CountUpJs instance, so I'm not sure where it would be created if not here. |
||
} | ||
|
||
|
@@ -141,18 +155,18 @@ class CountUp extends Component { | |
const { reset, restart: start, update } = this; | ||
const { onPauseResume } = this.props; | ||
|
||
this.instance.pauseResume(); | ||
this.instance?.pauseResume(); | ||
|
||
onPauseResume({ reset, start, update }); | ||
onPauseResume?.({ reset, start, update }); | ||
}; | ||
|
||
reset = () => { | ||
const { pauseResume, restart: start, update } = this; | ||
const { onReset } = this.props; | ||
|
||
this.instance.reset(); | ||
this.instance?.reset(); | ||
|
||
onReset({ pauseResume, start, update }); | ||
onReset?.({ pauseResume, start, update }); | ||
}; | ||
|
||
restart = () => { | ||
|
@@ -164,28 +178,28 @@ class CountUp extends Component { | |
const { pauseResume, reset, restart: start, update } = this; | ||
const { delay, onEnd, onStart } = this.props; | ||
const run = () => | ||
this.instance.start(() => onEnd({ pauseResume, reset, start, update })); | ||
this.instance?.start(() => onEnd?.({ pauseResume, reset, start, update })); | ||
|
||
// Delay start if delay prop is properly set | ||
if (delay > 0) { | ||
if (delay && delay > 0) { | ||
this.timeoutId = setTimeout(run, delay * 1000); | ||
} else { | ||
run(); | ||
} | ||
|
||
onStart({ pauseResume, reset, update }); | ||
onStart?.({ pauseResume, reset, update }); | ||
}; | ||
|
||
update = (newEnd) => { | ||
update = (newEnd: string | number) => { | ||
const { pauseResume, reset, restart: start } = this; | ||
const { onUpdate } = this.props; | ||
|
||
this.instance.update(newEnd); | ||
this.instance?.update(newEnd); | ||
|
||
onUpdate({ pauseResume, reset, start }); | ||
onUpdate?.({ pauseResume, reset, start }); | ||
}; | ||
|
||
containerRef = React.createRef(); | ||
containerRef = React.createRef<any>(); | ||
|
||
render() { | ||
const { children, className, style } = this.props; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"compilerOptions": {/* Basic Options */ | ||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ | ||
"module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ | ||
"jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ | ||
"declaration": true, /* Generates corresponding '.d.ts' file. */ | ||
"noEmit": true, /* Do not emit outputs. */ | ||
|
||
/* Strict Type-Checking Options */ | ||
"strict": true, /* Enable all strict type-checking options. */ | ||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ | ||
"strictNullChecks": true, /* Enable strict null checks. */ | ||
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ | ||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ | ||
|
||
/* Additional Checks */ | ||
"noUnusedLocals": true, /* Report errors on unused locals. */ | ||
"noUnusedParameters": true, /* Report errors on unused parameters. */ | ||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ | ||
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ | ||
|
||
"esModuleInterop": true, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to keep babel only for test files? I suppose that we can use ts-jest. But it can be done in separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC my implementation transpiles typescript using @babel/preset-typescript for both the build and tests. This is generally recommended instead of using the Typescript compiler when Babel is used for the test of transpilation instead of combining methods.
If I'm wrong about that I'll double check when I have some dev time.
Tsc is used to generate d.ts files themselves, as babel only transpiles to javascript.
I also recommend using the same transpilation method for jest as the project itself, so there aren't transpilation differences that cause test failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed, this PR uses babel to transpile typescript for both build and test.