Skip to content
This repository has been archived by the owner on Jul 8, 2023. It is now read-only.

Commit

Permalink
➕ with-view-layout-props
Browse files Browse the repository at this point in the history
  • Loading branch information
deepsweet committed Sep 23, 2017
1 parent 72eb74e commit efbb53a
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 0 deletions.
34 changes: 34 additions & 0 deletions packages/with-view-layout-props/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@hocs/with-view-layout-props",
"version": "0.1.0",
"description": "View layout dimensions HOC for React Native",
"keywords": [
"react",
"react-native",
"hoc",
"recompose",
"layout",
"dimensions"
],
"main": "lib/index.js",
"module": "es/index.js",
"files": [
"dist/",
"es/",
"lib/"
],
"repository": "deepsweet/hocs",
"author": "Kir Belevich <kir@belevi.ch> (https://github.com/deepsweet)",
"license": {
"type": "MIT",
"url": "https://github.com/deepsweet/hocs/blob/master/license.md"
},
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"react": "^15.6.1",
"react-native": "^0.48.3",
"recompose": "^0.25.0"
}
}
49 changes: 49 additions & 0 deletions packages/with-view-layout-props/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# :left_right_arrow: with-view-layout-props

[![npm](https://img.shields.io/npm/v/@hocs/with-view-layout-props.svg?style=flat-square)](https://www.npmjs.com/package/@hocs/with-view-layout-props) [![ci](https://img.shields.io/travis/deepsweet/hocs/master.svg?style=flat-square)](https://travis-ci.org/deepsweet/hocs) [![coverage](https://img.shields.io/codecov/c/github/deepsweet/hocs/master.svg?style=flat-square)](https://codecov.io/github/deepsweet/hocs) [![deps](https://david-dm.org/deepsweet/hocs.svg?path=packages/with-view-layout-props&style=flat-square)](https://david-dm.org/deepsweet/hocs?path=packages/with-view-layout-props)

Part of a [collection](https://github.com/deepsweet/hocs) of Higher-Order Components for React, especially useful with [Recompose](https://github.com/acdlite/recompose).

Dynamically map result of React Native [`onLayout()`](https://facebook.github.io/react-native/docs/view.html#onlayout) View handler to props.

## Install

```
yarn add recompose @hocs/with-view-layout-props
```

## Usage

```js
withResizeObserverProps(
mapStateToProps: (layoutDimensions: Object) => Object
handlerName?: string
): HigherOrderComponent
```

Where:

* `layoutDimensions``{ width, height, x, y }`
* `handlerName` – in some cases you might want to change it. `'onlayout'` by default.

```js
import React from 'react';
import { View } from 'react-native';
import withViewLayoutProps from '@hocs/with-view-layout-props';

const Demo = ({ width, height, x, y, onLayout, ...props }) => (
<View onLayout={onLayout} {...props}>
{ JSON.stringify({ width, height, x, y }) }
</View>
);

export default withViewLayoutProps(
({ width, height, x, y }) => ({ width, height, x, y })
)(Demo);
```

:tv: Have some idea on how to create a live demo? Please tell me.

## Related

* :left_right_arrow: [with-resize-observer-props](../with-resize-observer-props)
37 changes: 37 additions & 0 deletions packages/with-view-layout-props/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Component } from 'react';
import { createEagerFactory, setDisplayName, wrapDisplayName } from 'recompose';

const withViewLayoutProps = (mapStateToProps, handlerName = 'onLayout') => (Target) => {
const factory = createEagerFactory(Target);

class WithViewLayoutProps extends Component {
constructor(props, context) {
super(props, context);

this.state = {};
this.onLayout = this.onLayout.bind(this);
}

onLayout({ nativeEvent: { layout } }) {
this.setState(
mapStateToProps(layout)
);
}

render() {
return factory({
...this.props,
[handlerName]: this.onLayout,
...this.state
});
}
}

if (process.env.NODE_ENV !== 'production') {
return setDisplayName(wrapDisplayName(Target, 'withViewLayoutProps'))(WithViewLayoutProps);
}

return WithViewLayoutProps;
};

export default withViewLayoutProps;
35 changes: 35 additions & 0 deletions packages/with-view-layout-props/test/__snapshots__/index.jsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`withViewLayoutProps display name should not wrap display name in production env 1`] = `<WithViewLayoutProps />`;

exports[`withViewLayoutProps display name should wrap display name in non-production env 1`] = `
<withViewLayoutProps(Target)>
<Target
onLayout={[Function]}
/>
</withViewLayoutProps(Target)>
`;

exports[`withViewLayoutProps should map layout dimensions to props 1`] = `
<Target
_heigth={2}
_width={1}
_x={3}
_y={4}
onLayout={[Function]}
/>
`;

exports[`withViewLayoutProps should pass props through 1`] = `
<Target
a={1}
b={2}
onLayout={[Function]}
/>
`;

exports[`withViewLayoutProps should use provided custom \`onLayout\` handler name 1`] = `
<Target
onMyViewLayout={[Function]}
/>
`;
79 changes: 79 additions & 0 deletions packages/with-view-layout-props/test/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react';
import { mount } from 'enzyme';

import withViewLayoutProps from '../src/';

const Target = () => null;

describe('withViewLayoutProps', () => {
it('should pass props through', () => {
const EnhancedTarget = withViewLayoutProps((state) => state)(Target);
const wrapper = mount(
<EnhancedTarget a={1} b={2}/>
);

expect(wrapper.find(Target)).toMatchSnapshot();
});

it('should map layout dimensions to props', () => {
const EnhancedTarget = withViewLayoutProps(
({ width, height, x, y }) => ({ _width: width, _heigth: height, _x: x, _y: y })
)(Target);
const wrapper = mount(
<EnhancedTarget/>
);
const target = wrapper.find(Target);

target.prop('onLayout')({
nativeEvent: {
layout: {
width: 1,
height: 2,
x: 3,
y: 4
}
}
});

expect(target).toMatchSnapshot();
});

it('should use provided custom `onLayout` handler name', () => {
const EnhancedTarget = withViewLayoutProps(() => {}, 'onMyViewLayout')(Target);
const wrapper = mount(
<EnhancedTarget/>
);

expect(wrapper.find(Target)).toMatchSnapshot();
});

describe('display name', () => {
const origNodeEnv = process.env.NODE_ENV;

afterAll(() => {
process.env.NODE_ENV = origNodeEnv;
});

it('should wrap display name in non-production env', () => {
process.env.NODE_ENV = 'test';

const EnhancedTarget = withViewLayoutProps(() => {})(Target);
const wrapper = mount(
<EnhancedTarget/>
);

expect(wrapper).toMatchSnapshot();
});

it('should not wrap display name in production env', () => {
process.env.NODE_ENV = 'production';

const EnhancedTarget = withViewLayoutProps(() => {})(Target);
const wrapper = mount(
<EnhancedTarget/>
);

expect(wrapper).toMatchSnapshot();
});
});
});

0 comments on commit efbb53a

Please sign in to comment.