Upgrade eslint and react
diff --git a/.eslintrc b/.eslintrc
deleted file mode 100644
index e6ac5a8..0000000
--- a/.eslintrc
+++ /dev/null
@@ -1,50 +0,0 @@
-{
- "env": {
- "es6": true,
- "node": true,
- "browser": true
- },
- "parser": "babel-eslint",
- "parserOptions": {
- "ecmaFeatures": {
- "jsx": true
- }
- },
- "plugins": [
- "react"
- ],
- "rules": {
- "array-callback-return": 2,
- "brace-style": [2, "1tbs"],
- "camelcase": [2, { "properties": "always" }],
- "comma-dangle": [2, "never"],
- "comma-style": [2, "last"],
- "eol-last": 2,
- "indent": [2, 2, { "SwitchCase": 1 }],
- "jsx-quotes": [2, "prefer-double"],
- "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
- "keyword-spacing": 2,
- "linebreak-style": [2, "unix"],
- "no-cond-assign": [2, "always"],
- "no-console": 2,
- "no-multiple-empty-lines": [2, { "max": 1 }],
- "no-spaced-func": 2,
- "no-trailing-spaces": 2,
- "no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
- "no-whitespace-before-property": 2,
- "newline-after-var": [2, "always"],
- "object-curly-spacing": [2, "always"],
- "prefer-rest-params": 2,
- "quote-props": [2, "as-needed"],
- "quotes": [2, "single"],
- "semi": [2, "always"],
- "space-before-blocks": [2, "always"],
- "space-before-function-paren": [2, "never"],
- "space-in-parens": [2, "never"],
- "template-curly-spacing": [2, "never"],
-
- "react/jsx-boolean-value": [2, "always"],
- "react/jsx-uses-react": 2,
- "react/jsx-uses-vars": 2
- }
-}
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..d0b2318
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,119 @@
+module.exports = {
+ env: {
+ es6: true,
+ node: true,
+ browser: true,
+ mocha: true
+ },
+ parser: 'babel-eslint',
+ plugins: [
+ 'react'
+ ],
+ extends: [
+ 'eslint:recommended'
+ ],
+ rules: {
+ 'array-callback-return': 2,
+ 'brace-style': [2, '1tbs'],
+ 'camelcase': [2, { 'properties': 'always' }],
+ 'comma-dangle': [2, 'never'],
+ 'comma-style': [2, 'last'],
+ 'eol-last': 2,
+ 'func-call-spacing': 2,
+ 'indent': [2, 2, { 'SwitchCase': 1 }],
+ 'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }],
+ 'keyword-spacing': 2,
+ 'linebreak-style': [2, 'unix'],
+ 'no-cond-assign': [2, 'always'],
+ 'no-console': 2,
+ 'no-global-assign': 2,
+ 'no-multiple-empty-lines': [2, { 'max': 1 }],
+ 'no-restricted-properties': [2,
+ {
+ object: 'describe',
+ property: 'only',
+ message: 'Please run all tests!'
+ },
+ {
+ object: 'describe',
+ property: 'skip',
+ message: 'Please run all tests!'
+ },
+ {
+ object: 'it',
+ property: 'only',
+ message: 'Please run all tests!'
+ },
+ {
+ object: 'it',
+ property: 'skip',
+ message: 'Please run all tests!'
+ }
+ ],
+ 'no-template-curly-in-string': 2,
+ 'no-trailing-spaces': 2,
+ 'no-unused-vars': 2,
+ 'no-whitespace-before-property': 2,
+ 'newline-after-var': [2, 'always'],
+ 'object-curly-spacing': [2, 'always'],
+ 'prefer-rest-params': 2,
+ 'quote-props': [2, 'as-needed'],
+ 'quotes': [2, 'single'],
+ 'semi': [2, 'always'],
+ 'space-before-blocks': [2, 'always'],
+ 'space-before-function-paren': [2, 'never'],
+ 'space-in-parens': [2, 'never'],
+ 'template-curly-spacing': [2, 'never'],
+
+ 'react/display-name': 0,
+ 'react/forbid-prop-types': 0,
+ 'react/no-comment-textnodes': 0,
+ 'react/no-danger': 2,
+ 'react/no-danger-with-children': 2,
+ 'react/no-deprecated': 2,
+ 'react/no-did-mount-set-state': 2,
+ 'react/no-did-update-set-state': 2,
+ 'react/no-direct-mutation-state': 2,
+ 'react/no-find-dom-node': 2,
+ 'react/no-is-mounted': 2,
+ 'react/no-multi-comp': [2, { 'ignoreStateless': true }],
+ 'react/no-render-return-value': 2,
+ 'react/no-set-state': 0,
+ 'react/no-string-refs': 2,
+ 'react/no-unknown-property': 2,
+ 'react/no-unused-prop-types': 0, // https://github.com/yannickcr/eslint-plugin-react/pull/835
+ 'react/prefer-es6-class': [2, 'always'],
+ 'react/prefer-stateless-function': 2,
+ 'react/prop-types': 2,
+ 'react/react-in-jsx-scope': 2,
+ 'react/require-optimization': 0,
+ 'react/require-render-return': 2,
+ 'react/self-closing-comp': 2,
+ 'react/sort-comp': 2,
+ 'react/sort-prop-types': 0,
+ 'react/style-prop-object': 2,
+
+ 'react/jsx-boolean-value': [2, 'always'],
+ 'react/jsx-closing-bracket-location': [2, 'tag-aligned'],
+ 'react/jsx-curly-spacing': [2, 'never', { 'allowMultiline': true }],
+ 'react/jsx-equals-spacing': [2, 'never'],
+ 'react/jsx-filename-extension': [2, { 'extensions': ['.js'] }],
+ 'react/jsx-first-prop-new-line': [2, 'multiline'],
+ 'react/jsx-handler-names': 0,
+ 'react/jsx-indent': [2, 2],
+ 'react/jsx-indent-props': [2, 2],
+ 'react/jsx-key': 2,
+ 'react/jsx-max-props-per-line': 0,
+ 'react/jsx-no-bind': 2,
+ 'react/jsx-no-duplicate-props': 2,
+ 'react/jsx-no-literals': 0,
+ 'react/jsx-no-target-blank': 2,
+ 'react/jsx-no-undef': 2,
+ 'react/jsx-pascal-case': 2,
+ 'react/jsx-sort-props': 0,
+ 'react/jsx-space-before-closing': [2, 'always'],
+ 'react/jsx-uses-react': 2,
+ 'react/jsx-uses-vars': 2,
+ 'react/jsx-wrap-multilines': 2
+ }
+};
diff --git a/.gitignore b/.gitignore
index 802ddd2..ed4203d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
node_modules
npm-debug.log
dist
+yarn.lock
diff --git a/package.json b/package.json
index 7847e28..785645c 100644
--- a/package.json
+++ b/package.json
@@ -22,8 +22,8 @@
"es6-promise": "^3.1.2",
"isomorphic-fetch": "^2.2.1",
"jsonp": "^0.2.0",
- "react": "^0.14.7",
- "react-dom": "^0.14.7",
+ "react": "^15.4.1",
+ "react-dom": "^15.4.1",
"react-redux": "^4.4.0",
"redux": "^3.3.1",
"redux-thunk": "^1.0.3"
@@ -31,7 +31,7 @@
"devDependencies": {
"autoprefixer-loader": "^3.1.0",
"babel-core": "^6.5.2",
- "babel-eslint": "^5.0.0-beta9",
+ "babel-eslint": "^7.1.1",
"babel-loader": "^6.2.2",
"babel-plugin-react-transform": "^2.0.0",
"babel-preset-es2015": "^6.5.0",
@@ -39,8 +39,8 @@
"babel-preset-stage-0": "^6.5.0",
"chai": "^3.5.0",
"css-loader": "^0.23.1",
- "eslint": "^2.0.0",
- "eslint-plugin-react": "^3.16.1",
+ "eslint": "^3.12.2",
+ "eslint-plugin-react": "^6.8.0",
"express": "^4.13.4",
"extract-text-webpack-plugin": "^1.0.1",
"less": "^2.6.0",
diff --git a/src/components/App/App.js b/src/components/App/App.js
index a178047..58f2b6c 100644
--- a/src/components/App/App.js
+++ b/src/components/App/App.js
@@ -40,9 +40,11 @@
<div className={styles.previewContainer}>
{
isUserInputValid &&
- <Preview accessibilityLevel={accessibilityLevel}
- accessibleContrast={accessibleContrastRatio}
- isAccessible={isAccessible} />
+ <Preview
+ accessibilityLevel={accessibilityLevel}
+ accessibleContrast={accessibleContrastRatio}
+ isAccessible={isAccessible}
+ />
}
</div>
<HowItWorks />
diff --git a/src/components/App/components/ComingSoon/ComingSoon.js b/src/components/App/components/ComingSoon/ComingSoon.js
index 6f3a75a..3662441 100644
--- a/src/components/App/components/ComingSoon/ComingSoon.js
+++ b/src/components/App/components/ComingSoon/ComingSoon.js
@@ -18,9 +18,13 @@
<p>
To find out more, or if you have any feedback, get in touch with
us on
- <a className={styles.link} target="_blank"
- href="https://accessible-colors.herokuapp.com"
- data-link-name="Coming soon - Slack">
+ <a
+ className={styles.link}
+ target="_blank"
+ rel="noopener noreferrer"
+ href="https://accessible-colors.herokuapp.com"
+ data-link-name="Coming soon - Slack"
+ >
Slack
</a>.
</p>
diff --git a/src/components/App/components/Footer/Footer.js b/src/components/App/components/Footer/Footer.js
index 9f1fba9..9f0c7dc 100644
--- a/src/components/App/components/Footer/Footer.js
+++ b/src/components/App/components/Footer/Footer.js
@@ -11,22 +11,36 @@
Brought to you by
</h3>
<p className={styles.content}>
- <a className={styles.link} target="_blank"
- href="https://twitter.com/moroshko"
- data-link-name="Footer - Misha Moroshko">
- <img className={styles.image}
- src="https://www.gravatar.com/avatar/7ee5d55919c272eddef98dbe16f5cb09?s=54"
- alt="" role="presentation" />
+ <a
+ className={styles.link}
+ target="_blank"
+ rel="noopener noreferrer"
+ href="https://twitter.com/moroshko"
+ data-link-name="Footer - Misha Moroshko"
+ >
+ <img
+ className={styles.image}
+ src="https://www.gravatar.com/avatar/7ee5d55919c272eddef98dbe16f5cb09?s=54"
+ alt=""
+ role="presentation"
+ />
<span className={styles.linkText}>Misha Moroshko</span>
</a>
</p>
<p className={styles.content}>
- <a className={styles.link} target="_blank"
- href="https://twitter.com/vedranio"
- data-link-name="Footer - Vedran Arnautovic">
- <img className={styles.image}
- src="https://www.gravatar.com/avatar/6fa8f8433861ca68ed44cc79001554d6?s=54"
- alt="" role="presentation" />
+ <a
+ className={styles.link}
+ target="_blank"
+ rel="noopener noreferrer"
+ href="https://twitter.com/vedranio"
+ data-link-name="Footer - Vedran Arnautovic"
+ >
+ <img
+ className={styles.image}
+ src="https://www.gravatar.com/avatar/6fa8f8433861ca68ed44cc79001554d6?s=54"
+ alt=""
+ role="presentation"
+ />
<span className={styles.linkText}>Vedran Arnautovic</span>
</a>
</p>
@@ -36,9 +50,13 @@
Have feature ideas?
</h3>
<p className={styles.content}>
- <a className={styles.link} target="_blank"
- href="https://accessible-colors.herokuapp.com"
- data-link-name="Footer - Chat to us on Slack">
+ <a
+ className={styles.link}
+ target="_blank"
+ rel="noopener noreferrer"
+ href="https://accessible-colors.herokuapp.com"
+ data-link-name="Footer - Chat to us on Slack"
+ >
<span className={styles.icon + ' icon-circle-slack'} />
<span className={styles.linkText}>Chat to us on Slack</span>
</a>
diff --git a/src/components/App/components/Graph/Graph.js b/src/components/App/components/Graph/Graph.js
index 11a0d29..e56d58e 100644
--- a/src/components/App/components/Graph/Graph.js
+++ b/src/components/App/components/Graph/Graph.js
@@ -27,12 +27,20 @@
render() {
const { isBackgroundColor, colorChannel, backgroundColor, textColor,
accessibleContrast } = this.props;
+ const accessibleAreaStyle = {
+ left: 5 * (accessibleContrast - 1) + '%',
+ width: (100 - 5 * (accessibleContrast - 1)) + '%'
+ };
const yAxisName = (isBackgroundColor ? 'Background' : 'Text') +
' color ' + colorChannel;
const yMaxValue = (colorChannel === 'hue' ? 360 : 100);
const color = (isBackgroundColor ? backgroundColor: textColor);
const otherColor = (isBackgroundColor ? textColor: backgroundColor);
const yValue = parseFloat(color[colorChannel]);
+ const currentValueStyle = {
+ top: 100 * (1 - yValue / yMaxValue) + '%',
+ backgroundColor: str2sixDigitHex(color.value)
+ };
let data = [];
@@ -46,32 +54,41 @@
return (
<div className={styles.container}>
<div className={styles.coordinates}>
- <div className={styles.notAccessibleArea}
- style={{ width: 5 * (accessibleContrast - 1) + '%' }} />
- <div className={styles.accessibleArea}
- style={{ left: 5 * (accessibleContrast - 1) + '%',
- width: (100 - 5 * (accessibleContrast - 1)) + '%' }} />
+ <div
+ className={styles.notAccessibleArea}
+ style={{ width: 5 * (accessibleContrast - 1) + '%' }}
+ />
+ <div
+ className={styles.accessibleArea}
+ style={accessibleAreaStyle}
+ />
<div className={styles.xAxis} />
<div className={styles.xAxisArrow} />
<div className={styles.xAxisName}>Contrast</div>
<div className={styles.xAxisMinValue}>1</div>
- <div className={styles.xAxisAccessibleContrast}
- style={{ left: 5 * (accessibleContrast - 1) - 1 + '%' }}>{accessibleContrast}</div>
+ <div
+ className={styles.xAxisAccessibleContrast}
+ style={{ left: 5 * (accessibleContrast - 1) - 1 + '%' }}
+ >
+ {accessibleContrast}
+ </div>
<div className={styles.xAxisMaxValue}>21</div>
<div className={styles.yAxis} />
<div className={styles.yAxisArrow} />
<div className={styles.yAxisName}>{yAxisName}</div>
<div className={styles.yAxisMinValue}>0</div>
<div className={styles.yAxisMaxValue}>{yMaxValue}</div>
- <div className={styles.currentValue}
- style={{ top: 100 * (1 - yValue / yMaxValue) + '%',
- backgroundColor: str2sixDigitHex(color.value) }} />
+ <div
+ className={styles.currentValue}
+ style={currentValueStyle}
+ />
{
data.map(({ x, y }) =>
- <div className={styles.dataPoint}
- style={{ left: 5 * (x - 1) + '%',
- top: 100 * (1 - y / yMaxValue) + '%' }}
- key={x + ' ' + y} />
+ <div
+ className={styles.dataPoint}
+ style={{ left: 5 * (x - 1) + '%', top: 100 * (1 - y / yMaxValue) + '%' }}
+ key={x + ' ' + y}
+ />
)
}
</div>
diff --git a/src/components/App/components/Header/Header.js b/src/components/App/components/Header/Header.js
index 39fe82f..be16e81 100644
--- a/src/components/App/components/Header/Header.js
+++ b/src/components/App/components/Header/Header.js
@@ -50,22 +50,30 @@
Accessible colors
</h1>
<div className={styles.socialButtons}>
- <SocialButton icon="icon-circle-github" count={githubStars}
- color="#212121" hoverColor="#4078c0"
- linkProps={{
- href: GITHUB_HREF,
- target: '_blank',
- ariaLabel: `Star ${REPO} on GitHub`,
- 'data-link-name': 'Header - GitHub'
- }} />
- <SocialButton icon="icon-circle-twitter" count={twitterCount}
- color="#212121" hoverColor="#55acee"
- linkProps={{
- className: styles.twitterButton,
- href: TWITTER_HREF,
- ariaLabel: `Share ${DOMAIN} on Twitter`,
- 'data-link-name': 'Header - Twitter'
- }} />
+ <SocialButton
+ icon="icon-circle-github"
+ count={githubStars}
+ color="#212121"
+ hoverColor="#4078c0"
+ linkProps={{
+ href: GITHUB_HREF,
+ target: '_blank',
+ 'aria-label': `Star ${REPO} on GitHub`,
+ 'data-link-name': 'Header - GitHub'
+ }}
+ />
+ <SocialButton
+ icon="icon-circle-twitter"
+ count={twitterCount}
+ color="#212121"
+ hoverColor="#55acee"
+ linkProps={{
+ className: styles.twitterButton,
+ href: TWITTER_HREF,
+ 'aria-label': `Share ${DOMAIN} on Twitter`,
+ 'data-link-name': 'Header - Twitter'
+ }}
+ />
</div>
</div>
</header>
diff --git a/src/components/App/components/Header/components/SocialButton/SocialButton.js b/src/components/App/components/Header/components/SocialButton/SocialButton.js
index 4e770ef..dc19ba3 100644
--- a/src/components/App/components/Header/components/SocialButton/SocialButton.js
+++ b/src/components/App/components/Header/components/SocialButton/SocialButton.js
@@ -11,21 +11,33 @@
hoverColor: PropTypes.string.isRequired
};
- setColor(color) {
- this.refs.link.style.color = color;
- }
+ storeLinkElement = element => {
+ if (element !== null) {
+ this.link = element;
+ }
+ };
+
+ onMouseEnter = () => {
+ this.link.style.color = this.props.hoverColor;
+ };
+
+ onMouseLeave = () => {
+ this.link.style.color = this.props.color;
+ };
render() {
- const { linkProps, icon, count, color, hoverColor } = this.props;
+ const { linkProps, icon, count, color } = this.props;
const className = (linkProps.className || '') + ' ' + styles.container;
return (
- <a {...linkProps}
- className={className}
- style={{ color }}
- onMouseEnter={() => this.setColor(hoverColor)}
- onMouseLeave={() => this.setColor(color)}
- ref="link">
+ <a
+ {...linkProps}
+ className={className}
+ style={{ color }}
+ onMouseEnter={this.onMouseEnter}
+ onMouseLeave={this.onMouseLeave}
+ ref={this.storeLinkElement}
+ >
<span className={styles.icon + ' ' + icon} />
<span className={styles.count}>{count}</span>
</a>
diff --git a/src/components/App/components/HowItWorks/HowItWorks.js b/src/components/App/components/HowItWorks/HowItWorks.js
index ac59c89..b53097c 100644
--- a/src/components/App/components/HowItWorks/HowItWorks.js
+++ b/src/components/App/components/HowItWorks/HowItWorks.js
@@ -12,20 +12,26 @@
<div className={styles.content}>
<p>
We evaluate your color combination using the
- <a className={styles.link}
- href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html"
- target="_blank"
- data-link-name="How it works - WCAG 2.0 guidelines for contrast accessibility">
+ <a
+ className={styles.link}
+ href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html"
+ target="_blank"
+ rel="noopener noreferrer"
+ data-link-name="How it works - WCAG 2.0 guidelines for contrast accessibility"
+ >
WCAG 2.0 guidelines for contrast accessibility
</a>.
</p>
<p>
If your combination does not meet the guidelines, we find the
closest accessible combination by modifying the color
- <a className={styles.link}
- href="https://en.wikipedia.org/wiki/HSL_and_HSV"
- target="_blank"
- data-link-name="How it works - lightness">
+ <a
+ className={styles.link}
+ href="https://en.wikipedia.org/wiki/HSL_and_HSV"
+ target="_blank"
+ rel="noopener noreferrer"
+ data-link-name="How it works - lightness"
+ >
lightness
</a>.
</p>
diff --git a/src/components/App/components/Preview/Preview.js b/src/components/App/components/Preview/Preview.js
index f906d61..a63e8ec 100644
--- a/src/components/App/components/Preview/Preview.js
+++ b/src/components/App/components/Preview/Preview.js
@@ -68,9 +68,11 @@
};
const linesToShow = calcLinesToShow(previewContentStyle.fontSize);
const multilineEllipsis = (
- <MultilineEllipsis text={loremIpsum}
- fontSize={previewContentStyle.fontSize}
- linesToShow={linesToShow} />
+ <MultilineEllipsis
+ text={loremIpsum}
+ fontSize={previewContentStyle.fontSize}
+ linesToShow={linesToShow}
+ />
);
return (
diff --git a/src/components/App/components/UserInput/UserInput.js b/src/components/App/components/UserInput/UserInput.js
index e2d0a4c..bafc65a 100644
--- a/src/components/App/components/UserInput/UserInput.js
+++ b/src/components/App/components/UserInput/UserInput.js
@@ -46,37 +46,43 @@
<span className={styles.textColorContainer}>
<label htmlFor="text-color">My text color is </label>
<span className={styles.colorContainer}>
- <Editable isValid={textColor.isValueValid}
- onChange={updateTextColor}
- inputProps={{
- id: 'text-color',
- type: 'text',
- value: textColor.value,
- onBlur: blurTextColor
- }} />
+ <Editable
+ isValid={textColor.isValueValid}
+ onChange={updateTextColor}
+ inputProps={{
+ id: 'text-color',
+ type: 'text',
+ value: textColor.value,
+ onBlur: blurTextColor
+ }}
+ />
</span>
</span>
{' '}
<span className={styles.fontSizeAndWeightContainer}>
<label htmlFor="font-size">at </label>
<span className={styles.fontSizeContainer}>
- <Editable isValid={fontSize.isValid}
- onChange={updateFontSize}
- inputProps={{
- id: 'font-size',
- type: 'number',
- min: MIN_FONT_SIZE,
- max: MAX_FONT_SIZE,
- step: '1',
- value: fontSize.value,
- onBlur: blurFontSize
- }} />
+ <Editable
+ isValid={fontSize.isValid}
+ onChange={updateFontSize}
+ inputProps={{
+ id: 'font-size',
+ type: 'number',
+ min: MIN_FONT_SIZE,
+ max: MAX_FONT_SIZE,
+ step: '1',
+ value: fontSize.value,
+ onBlur: blurFontSize
+ }}
+ />
</span>
pt and
<span className={styles.fontWeightContainer}>
- <Toggle values={['regular', 'bold']}
- currentValue={isFontBold ? 'bold' : 'regular'}
- onChange={toggleFontWeight} />
+ <Toggle
+ values={['regular', 'bold']}
+ currentValue={isFontBold ? 'bold' : 'regular'}
+ onChange={toggleFontWeight}
+ />
</span>
weight
</span>
@@ -84,21 +90,25 @@
<p className={styles.backgroundColorContainer}>
<label htmlFor="background-color">My background color is </label>
<span className={styles.colorContainer}>
- <Editable isValid={backgroundColor.isValueValid}
- onChange={updateBackgroundColor}
- inputProps={{
- id: 'background-color',
- type: 'text',
- value: backgroundColor.value,
- onBlur: blurBackgroundColor
- }} />
+ <Editable
+ isValid={backgroundColor.isValueValid}
+ onChange={updateBackgroundColor}
+ inputProps={{
+ id: 'background-color',
+ type: 'text',
+ value: backgroundColor.value,
+ onBlur: blurBackgroundColor
+ }}
+ />
</span>
</p>
<p className={styles.accessibilityLevelContainer}>
My design must be
- <Toggle values={['AA', 'AAA']}
- currentValue={accessibilityLevel}
- onChange={updateAccessibilityLevel} />
+ <Toggle
+ values={['AA', 'AAA']}
+ currentValue={accessibilityLevel}
+ onChange={updateAccessibilityLevel}
+ />
compliant
</p>
{
diff --git a/src/components/App/components/UserInput/components/Editable/Editable.js b/src/components/App/components/UserInput/components/Editable/Editable.js
index b431ca2..c546fcc 100644
--- a/src/components/App/components/UserInput/components/Editable/Editable.js
+++ b/src/components/App/components/UserInput/components/Editable/Editable.js
@@ -22,9 +22,15 @@
this.onKeyUp = ::this.onKeyUp;
}
+ storeInputElement = element => {
+ if (element !== null) {
+ this.input = element;
+ }
+ };
+
onFocus(event) {
this.valueBeforeEdit = event.target.value;
- setTimeout(() => this.refs.input.select());
+ setTimeout(() => this.input.select());
}
onKeyUp(event) {
@@ -43,16 +49,23 @@
}
}
+ onChange = event => {
+ this.props.onChange(event.target.value);
+ };
+
render() {
- const { isValid, onChange, inputProps } = this.props;
+ const { isValid, inputProps } = this.props;
return (
- <input {...inputProps}
- className={isValid ? styles.validInput : styles.invalidInput}
- aria-invalid={!isValid}
- onFocus={this.onFocus} onKeyUp={this.onKeyUp}
- onChange={event => onChange(event.target.value)}
- ref="input" />
+ <input
+ {...inputProps}
+ className={isValid ? styles.validInput : styles.invalidInput}
+ aria-invalid={!isValid}
+ onFocus={this.onFocus}
+ onKeyUp={this.onKeyUp}
+ onChange={this.onChange}
+ ref={this.storeInputElement}
+ />
);
}
}
diff --git a/src/components/App/components/UserInput/components/Toggle/Toggle.js b/src/components/App/components/UserInput/components/Toggle/Toggle.js
index 83107bf..2619722 100644
--- a/src/components/App/components/UserInput/components/Toggle/Toggle.js
+++ b/src/components/App/components/UserInput/components/Toggle/Toggle.js
@@ -1,23 +1,32 @@
import styles from './Toggle.less';
-import React, { PropTypes } from 'react';
+import React, { PropTypes, Component } from 'react';
-function Toggle(props) {
- const { values, currentValue, onChange } = props;
- const otherValue = (currentValue === values[0] ? values[1] : values[0]);
+export default class Toggle extends Component {
+ static propTypes = {
+ values: PropTypes.arrayOf(PropTypes.string).isRequired,
+ currentValue: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired
+ };
- return (
- <button className={styles.button} type="button"
- onClick={() => onChange(otherValue)}>
- {currentValue}
- </button>
- );
+ onClick = () => {
+ const { values, currentValue, onChange } = this.props;
+ const otherValue = (currentValue === values[0] ? values[1] : values[0]);
+
+ onChange(otherValue);
+ };
+
+ render() {
+ const { currentValue } = this.props;
+
+ return (
+ <button
+ className={styles.button}
+ type="button"
+ onClick={this.onClick}
+ >
+ {currentValue}
+ </button>
+ );
+ }
}
-
-Toggle.propTypes = {
- values: PropTypes.arrayOf(PropTypes.string).isRequired,
- currentValue: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired
-};
-
-export default Toggle;
diff --git a/src/components/TrackLinks/TrackLinks.js b/src/components/TrackLinks/TrackLinks.js
index 12c0225..615edad 100644
--- a/src/components/TrackLinks/TrackLinks.js
+++ b/src/components/TrackLinks/TrackLinks.js
@@ -1,12 +1,16 @@
-import React, { Component } from 'react';
+import React, { PropTypes, Component } from 'react';
export default class TrackLinks extends Component {
+ static propTypes = {
+ children: PropTypes.node
+ };
+
componentDidMount() {
- if (typeof analytics !== 'object') {
+ if (typeof window.analytics !== 'object') {
return;
}
- const links = this.refs.children.querySelectorAll('a');
+ const links = this.container.querySelectorAll('a');
const linksCount = links.length;
for (let i = 0; i < linksCount; i++) {
@@ -14,15 +18,21 @@
const linkName = link.dataset.linkName;
const event = `Clicked [${linkName}] link`;
- analytics.trackLink(link, event);
+ window.analytics.trackLink(link, event);
}
}
+ storeContainerElement = element => {
+ if (element !== null) {
+ this.container = element;
+ }
+ };
+
render() {
const { children } = this.props;
return (
- <div ref="children">
+ <div ref={this.storeContainerElement}>
{children}
</div>
);
diff --git a/src/store.js b/src/store.js
index 011aae5..26f7806 100644
--- a/src/store.js
+++ b/src/store.js
@@ -4,4 +4,4 @@
export default function configureStore() {
return createStore(appReducer, applyMiddleware(thunk));
-};
+}