From 36f6865dd8293255d968aaef9c5bc94a83094139 Mon Sep 17 00:00:00 2001 From: Federico Zivolo Date: Thu, 24 Aug 2017 20:30:18 +0200 Subject: [PATCH] feat: Added child function support --- README.md | 19 ++++++++++ docs/react-resize-aware.js | 16 ++++----- package.json | 2 +- src/__snapshots__/index.spec.jsx.snap | 50 +++++++++++++++++++++++---- src/index.js | 31 ++++++++++++----- src/index.spec.jsx | 14 +++++++- 6 files changed, 107 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index e439250..9cd00dc 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,25 @@ function App() { } ``` +## Child function + +Whenever you want to manipulate the `width` and `height` properties before they +get passed down to the child component, you can define a function as child of ResizeAware: + +```jsx +import React from 'react'; +import ResizeAware from 'react-resize-aware'; + +export default makeResizeAware(function MyComponent({width, height, getRef, children})) { + return ( + + {({ width, height }) => +
} + + ); +}) +``` + ## Decorator/enhancer In case you prefer to directly decorate your component to add to it the ResizeAware diff --git a/docs/react-resize-aware.js b/docs/react-resize-aware.js index d1deb5d..1728194 100644 --- a/docs/react-resize-aware.js +++ b/docs/react-resize-aware.js @@ -91,8 +91,8 @@ var ResizeAware = function (_Component) { }, { key: 'render', value: function render() { - var _this2 = this, - _extends2; + var _sizes, + _this2 = this; var _props = this.props, children = _props.children, @@ -113,9 +113,11 @@ var ResizeAware = function (_Component) { var widthProp = [widthPropName || 'width']; var heightProp = [heightPropName || 'height']; - return react.createElement(component, _extends((_extends2 = {}, _defineProperty(_extends2, hasCustomComponent ? 'getRef' : 'ref', function (el) { + var sizes = (_sizes = {}, _defineProperty(_sizes, widthProp, width), _defineProperty(_sizes, heightProp, height), _sizes); + + return react.createElement(component, _extends(_defineProperty({}, hasCustomComponent ? 'getRef' : 'ref', function (el) { return _this2.container = el; - }), _defineProperty(_extends2, widthProp, hasCustomComponent ? width : undefined), _defineProperty(_extends2, heightProp, hasCustomComponent ? height : undefined), _extends2), props), react.createElement('object', { + }), hasCustomComponent && sizes, props), react.createElement('object', { type: 'text/html', style: style, ref: function ref(el) { @@ -124,10 +126,8 @@ var ResizeAware = function (_Component) { onLoad: this.handleObjectLoad, 'aria-hidden': true, tabIndex: -1 - }), react.Children.map(children, function (child) { - var _ref2; - - return react.cloneElement(child, !onlyEvent ? (_ref2 = {}, _defineProperty(_ref2, widthProp, width), _defineProperty(_ref2, heightProp, height), _ref2) : null); + }), typeof children === 'function' ? children({ width: width, height: height }) : react.Children.map(children, function (child) { + return react.isValidElement(child) ? react.cloneElement(child, !onlyEvent ? sizes : null) : child; })); } }]); diff --git a/package.json b/package.json index f141679..3312e46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-resize-aware", - "version": "2.6.0", + "version": "2.7.0", "description": "A resize aware component used to detect sizes changes on your components", "main": "dist/index.js", "scripts": { diff --git a/src/__snapshots__/index.spec.jsx.snap b/src/__snapshots__/index.spec.jsx.snap index 777fb01..6157a74 100644 --- a/src/__snapshots__/index.spec.jsx.snap +++ b/src/__snapshots__/index.spec.jsx.snap @@ -111,12 +111,50 @@ exports[`allows to define custom width and height names 1`] = ` -
- + /> +
+ +`; + +exports[`allows to use a function as child 1`] = ` + +
+ +
`; diff --git a/src/index.js b/src/index.js index 6f6ff76..c110b93 100644 --- a/src/index.js +++ b/src/index.js @@ -6,7 +6,13 @@ // Copyright 2016, Federico Zivolo // -import { createElement, Component, Children, cloneElement } from 'react'; +import { + createElement, + Component, + Children, + cloneElement, + isValidElement, +} from 'react'; const style = { display: 'block', @@ -81,12 +87,16 @@ export default class ResizeAware extends Component { const widthProp = [widthPropName || 'width']; const heightProp = [heightPropName || 'height']; + const sizes = { + [widthProp]: width, + [heightProp]: height, + }; + return createElement( component, { [hasCustomComponent ? 'getRef' : 'ref']: el => (this.container = el), - [widthProp]: hasCustomComponent ? width : undefined, - [heightProp]: hasCustomComponent ? height : undefined, + ...(hasCustomComponent && sizes), ...props, }, createElement('object', { @@ -97,12 +107,15 @@ export default class ResizeAware extends Component { 'aria-hidden': true, tabIndex: -1, }), - Children.map(children, child => - cloneElement( - child, - !onlyEvent ? { [widthProp]: width, [heightProp]: height } : null - ) - ) + typeof children === 'function' + ? children({ width, height }) + : Children.map( + children, + child => + isValidElement(child) + ? cloneElement(child, !onlyEvent ? sizes : null) + : child + ) ); } } diff --git a/src/index.spec.jsx b/src/index.spec.jsx index 4730fda..893991a 100644 --- a/src/index.spec.jsx +++ b/src/index.spec.jsx @@ -63,7 +63,7 @@ it('applies aria attributes to to avoid screenreader issues', () => { }); it('allows to define custom width and height names', () => { - const Test = props =>
; + const Test = props => null; const wrapper = mount( { expect(toJson(wrapper)).toMatchSnapshot(); }); + +it('allows to use a function as child', () => { + const wrapper = mount( + + {({ width, height }) =>
} + + ); + + wrapper.setState({ width: 10, height: 10 }); + + expect(toJson(wrapper)).toMatchSnapshot(); +});