From 55a69650502d3d1822f9aeba877bdb23aa4bc385 Mon Sep 17 00:00:00 2001 From: Jared White Date: Wed, 22 Aug 2018 14:02:56 -0500 Subject: [PATCH 01/24] Handle multiple animationName props (#909) * Handle multiple animationName props * keyframes-plugin - Array check before if block * keyframes-plugin - reduce duplicate logic * Prettier Compliance * remove vestigial examples/app.jsx * Eslint compliance --- docs/api/README.md | 48 ++++++++ examples/app.js | 41 +++++++ src/__tests__/keyframes-test.js | 189 ++++++++++++++++++++++++++++++++ src/plugins/keyframes-plugin.js | 24 +++- 4 files changed, 297 insertions(+), 5 deletions(-) diff --git a/docs/api/README.md b/docs/api/README.md index 9277197e..a0804290 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -327,6 +327,54 @@ var styles = { }; ``` +Multiple keyframe animations can be chained together by passing an array of `keyframes` objects +as the value of the `animationName` property. These keyframe animations timing and iteration count +can be managed with [traditional css rules for keyframe animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations) + +```jsx +@Radium +class Spinner extends React.Component { + render () { + return ( +
+
+
+ ); + } +} + +const pulseAnimation = Radium.keyframes( + { + '0%': {width: '10%'}, + '50%': {width: '50%'}, + '100%': {width: '10%'}, + }, + 'pulse', +); + +const blendAnimation = Radium.keyframes( + { + '0%': {background: 'red'}, + '25%': {background: 'yellow'}, + '50%': {background: 'green'}, + '75%': {background: 'blue'}, + '100%': {background: 'red'}, + }, + 'blend', +); + +const styles = { + inner: { + animationName: [pulseAnimation, blendAnimation], + animationDuration: '2.5s, 8s', + animationIterationCount: 'infinite, infinite', + animationTimingFunction: 'linear, cubic-bezier(0.1, 0.7, 1.0, 0.1)', + height: '4px', + margin: '0 auto', + }, +}; +``` + ## Plugins ### Built-in Plugins diff --git a/examples/app.js b/examples/app.js index cc413583..abf78be0 100644 --- a/examples/app.js +++ b/examples/app.js @@ -73,6 +73,23 @@ class Spinner extends React.Component { Spinner = Radium(Spinner); +class MultiSpinner extends React.Component { + render() { + return ( +
+
+
+ ); + } +} + +MultiSpinner = Radium(MultiSpinner); + const VisitedLink = Radium(() => ( +

+

@@ -236,6 +255,17 @@ const pulseAnimation = keyframes( 'pulse' ); +const blendAnimation = Radium.keyframes( + { + '0%': {background: 'red'}, + '25%': {background: 'yellow'}, + '50%': {background: 'green'}, + '75%': {background: 'blue'}, + '100%': {background: 'red'} + }, + 'blend' +); + const spinnerStyles = { inner: { animation: 'x 3s ease 0s infinite', @@ -246,6 +276,17 @@ const spinnerStyles = { } }; +const multiAnimationStyles = { + inner: { + animationName: [pulseAnimation, blendAnimation], + animationDuration: '2.5s, 8s', + animationIterationCount: 'infinite, infinite', + animationTimingFunction: 'linear, cubic-bezier(0.1, 0.7, 1.0, 0.1)', + height: '4px', + margin: '0 auto' + } +}; + const listStyle = { ...resetListStyle, ...resetBoxModel, diff --git a/src/__tests__/keyframes-test.js b/src/__tests__/keyframes-test.js index a6c39b65..0965225f 100644 --- a/src/__tests__/keyframes-test.js +++ b/src/__tests__/keyframes-test.js @@ -36,6 +36,38 @@ describe('keyframes', () => { ); }); + it('adds prefix to multiple keyframes when needed', () => { + const anim = keyframes({from: {left: 0}, to: {left: 100}}, 'slide'); + const anim2 = keyframes({from: {top: 0}, to: {top: 100}}, 'slideTop'); + class TestComponent extends Component { + render() { + return ( + + ); + } + } + + const output = TestUtils.renderIntoDocument(); + const style = getElement(output, 'style'); + + expectCSS( + style, + ` + @-webkit-keyframes slide-radium-animation-1bdcc98d { + from {left: 0;} + to {left: 100px;} + } + @-webkit-keyframes slideTop-radium-animation-c623736d { + from {top: 0;} + to {top: 100px;} + } + ` + ); + }); + it('renders keyframes in root style component', () => { const animation = keyframes( { @@ -70,6 +102,55 @@ describe('keyframes', () => { ); }); + it('renders multiple keyframes in root style component', () => { + const animation = keyframes( + { + from: {left: '-1000px'}, + to: {left: 0} + }, + 'SlideFromLeft' + ); + const animation2 = keyframes( + { + from: {top: '-1000px'}, + to: {top: 0} + }, + 'SlideFromTop' + ); + + class TestComponent extends Component { + render() { + return ; + } + } + + const output = TestUtils.renderIntoDocument(); + + const style = getElement(output, 'style'); + + expectCSS( + style, + ` + @keyframes SlideFromLeft-radium-animation-1b668a10 { + from{ + left: -1000px; + } + to{ + left: 0; + } + } + @keyframes SlideFromTop-radium-animation-edccf130{ + from{ + top:-1000px; + } + to{ + top:0; + } + } + ` + ); + }); + it('adds px suffix when property is not unitless', () => { const animation = keyframes( { @@ -104,6 +185,55 @@ describe('keyframes', () => { ); }); + it('adds px suffix when property is not unitless to multiple keyframes', () => { + const animation = keyframes( + { + from: {left: -1000}, + to: {left: 10} + }, + 'SlideFromLeft' + ); + const animation2 = keyframes( + { + from: {top: -1000}, + to: {top: 10} + }, + 'SlideFromTop' + ); + + class TestComponent extends Component { + render() { + return ; + } + } + + const output = TestUtils.renderIntoDocument(); + + const style = getElement(output, 'style'); + + expectCSS( + style, + ` + @keyframes SlideFromLeft-radium-animation-ab5ed129 { + from{ + left: -1000px; + } + to{ + left: 10px; + } + } + @keyframes SlideFromTop-radium-animation-3a6534c9 { + from{ + top:-1000px; + } + to{ + top: 10px; + } + } + ` + ); + }); + it('renders keyframes from child component', () => { const animation = keyframes( { @@ -147,4 +277,63 @@ describe('keyframes', () => { ` ); }); + + it('renders multiple keyframes from child component', () => { + const animation = keyframes( + { + from: {left: '-1000px'}, + to: {left: 0} + }, + 'SlideFromLeft' + ); + const animation2 = keyframes( + { + from: {top: -1000}, + to: {top: 0} + }, + 'SlideFromTop' + ); + + @Radium class ChildComponent extends Component { + render() { + return

; + } + } + + @Radium class TestComponent extends Component { + render() { + return ( + + + + ); + } + } + + const output = TestUtils.renderIntoDocument(); + + const style = getElement(output, 'style'); + + expectCSS( + style, + ` + @keyframes SlideFromLeft-radium-animation-1b668a10 { + from{ + left: -1000px; + } + to{ + left: 0; + } + } + @keyframes SlideFromTop-radium-animation-edccf130 { + from{ + top:-1000px; + } + to{ + top: 0; + } + } + ` + ); + }); }); diff --git a/src/plugins/keyframes-plugin.js b/src/plugins/keyframes-plugin.js index 367ea84b..d18b7817 100644 --- a/src/plugins/keyframes-plugin.js +++ b/src/plugins/keyframes-plugin.js @@ -6,14 +6,28 @@ import type {Keyframes} from '../keyframes'; export default function keyframesPlugin( {addCSS, config, style}: PluginConfig // eslint-disable-line no-shadow ): PluginResult { + const processKeyframeStyle = value => { + const keyframesValue = (value: Keyframes); + const {animationName, css} = keyframesValue.__process(config.userAgent); + addCSS(css); + return animationName; + }; + const newStyle = Object.keys(style).reduce( (newStyleInProgress, key) => { let value = style[key]; - if (key === 'animationName' && value && value.__radiumKeyframes) { - const keyframesValue = (value: Keyframes); - const {animationName, css} = keyframesValue.__process(config.userAgent); - addCSS(css); - value = animationName; + const isKeyframeArray = Array.isArray(value); + + if ( + key === 'animationName' && + value && + (value.__radiumKeyframes || isKeyframeArray) + ) { + if (isKeyframeArray) { + value = value.map(processKeyframeStyle).join(', '); + } else { + value = processKeyframeStyle(value); + } } newStyleInProgress[key] = value; From cb89af5093a60213b9d2826282857c21bbe0d7b9 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Sun, 16 Sep 2018 18:39:28 -0700 Subject: [PATCH 02/24] Better es6 class support (#1001) * Change versions of node to test in travis-ci - Remove node 4 - Add node 10 * Better es6 class support Use Reflect to construct class in a more compatible manner. Reflect should be available in environments that use es6 classes. --- .eslintrc | 1 + .travis.yml | 2 +- CHANGELOG.md | 4 + package.json | 4 + src/enhancer.js | 57 +--- test/enhancer-test.js | 62 ++++ yarn.lock | 662 +++++++++++++++++++++++++++++++++++++++++- 7 files changed, 742 insertions(+), 50 deletions(-) diff --git a/.eslintrc b/.eslintrc index 8ec9b98e..d9f3490d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -19,6 +19,7 @@ globals: expect: true sinon: true ReactElement: true + Reflect: true rules: diff --git a/.travis.yml b/.travis.yml index 7cdde790..add36de2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,9 +6,9 @@ addons: chrome: stable node_js: - - "4" - "6" - "8" + - "10" # Use container-based Travis infrastructure. sudo: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c9637ee..fac61aae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Radium Changelog +## Unreleased +- Use `Reflect` to construct es native classes in a way that preserves the value of `this` used in + the constructor. (#999, #1001) + ## 0.24.1 (July 9, 2018) - Make `` manually update `