Initial Commit

This commit is contained in:
saleel
2017-04-08 01:01:27 +04:00
commit c3b08e2ef6
14 changed files with 353 additions and 0 deletions

11
.eslintrc.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = {
"extends": "airbnb",
"plugins": [
"react",
"jsx-a11y",
"import"
],
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
}
};

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history

16
.npmignore Normal file
View File

@@ -0,0 +1,16 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Screenshots
screenshots

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Saleel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

136
README.md Normal file
View File

@@ -0,0 +1,136 @@
# React Native Super Grid
Responsive Grid View for React Native.
## Getting Started
This component renders a Grid View that adapts itself to various screen resolutions.
Instead of passing an itemPerRow argument, you pass ```itemWidth``` and each item will be rendered with a width equal to or more than (to fill the screen) the given width.
Internally, this component use the native [ListView](https://facebook.github.io/react-native/docs/listview.html).
### Installing
You can install the package via npm.
```
npm install react-native-super-grid
```
### Usage
```
import GridView from 'react-native-super-grid';
```
```
<GridView
itemWidth={130}
items={[1,2,3,4,5,6]}
renderRow={item => (<Text>{item}</Text>)}
/>
```
#### Properties
| Property | Type | Default Value | Description |
|---|---|---|---|
| renderItem | Function | | Function to render each object. Should return a react native component. |
| items | Array | | Items to be rendered. renderItem will be called with each item in this array. | |
| itemWidth | Number | 120 | Minimum width for each item in pixels (virtual). |
| fixed | Boolean | false | If true, the exact ```itemWidth``` will be used and won't be adjusted to fit the screen. |
| spacing | Number | 10 | Spacing between each item. |
| style | [ListView](https://facebook.github.io/react-native/docs/listview.html) styles (Object) | | Styles for the container. Styles for an item should be applied inside ```renderItem```. |
## Example
```
import React, { Component } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import GridView from 'react-native-super-grid';
export default class Example extends Component {
render() {
// Taken from https://flatuicolors.com/
const items = [
{ name: 'TURQUOISE', code: '#1abc9c' }, { name: 'EMERALD', code: '#2ecc71' },
{ name: 'PETER RIVER', code: '#3498db' }, { name: 'AMETHYST', code: '#9b59b6' },
{ name: 'WET ASPHALT', code: '#34495e' }, { name: 'GREEN SEA', code: '#16a085' },
{ name: 'NEPHRITIS', code: '#27ae60' }, { name: 'BELIZE HOLE', code: '#2980b9' },
{ name: 'WISTERIA', code: '#8e44ad' }, { name: 'MIDNIGHT BLUE', code: '#2c3e50' },
{ name: 'SUN FLOWER', code: '#f1c40f' }, { name: 'CARROT', code: '#e67e22' },
{ name: 'ALIZARIN', code: '#e74c3c' }, { name: 'CLOUDS', code: '#ecf0f1' },
{ name: 'CONCRETE', code: '#95a5a6' }, { name: 'ORANGE', code: '#f39c12' },
{ name: 'PUMPKIN', code: '#d35400' }, { name: 'POMEGRANATE', code: '#c0392b' },
{ name: 'SILVER', code: '#bdc3c7' }, { name: 'ASBESTOS', code: '#7f8c8d' },
];
return (
<GridView
itemWidth={130}
items={items}
style={styles.gridView}
renderItem={item => (
<View style={[styles.itemContainer, { backgroundColor: item.code }]}>
<Text style={styles.itemName}>{item.name}</Text>
<Text style={styles.itemCode}>{item.code}</Text>
</View>
)}
/>
);
}
}
const styles = StyleSheet.create({
gridView: {
paddingTop: 25,
flex: 1,
},
itemContainer: {
justifyContent: 'flex-end',
borderRadius: 5,
padding: 10,
height: 150,
},
itemName: {
fontSize: 16,
color: '#fff',
fontWeight: '600',
},
itemCode: {
fontWeight: '600',
fontSize: 12,
color: '#fff',
},
});
```
| ![iPhone6 Portrait](/screenshots/iphone6_portrait.png?raw=true "iPhone6 Portrait")| ![iPhone6 Landscape](/screenshots/iphone6_landscape.png?raw=true "iPhone6 Landscape") |
|:---:|:---:|
| iPhone6 Portrait | iPhone6 Landscape |
| ![iPad Air 2 Portrait](/screenshots/ipadair2_portrait.png?raw=true "iPad Air 2 Portrait") | ![iPad Air 2 Landscape](/screenshots/ipadair2_landscape.png?raw=true "iPad Air 2 Landscape") |
|:---:|:---:|
| iPad Air 2 Portrait | iPad Air 2 Landscape |
| ![Android Portrait](/screenshots/android_portrait.png?raw=true "Android Portrait") | ![Android Landscape](/screenshots/android_landscape.png?raw=true "Android Landscape") |
|:---:|:---:|
| Android Portrait | Android Landscape |
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
## Acknowledgments
Colors in the example from https://flatuicolors.com/.
Screenshot Mockup generated from https://mockuphone.com.

109
index.js Normal file
View File

@@ -0,0 +1,109 @@
import React, { Component, PropTypes } from 'react';
import { View, ListView, Dimensions } from 'react-native';
import { chunkArray } from './utils';
class SuperGrid extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.onLayout = this.onLayout.bind(this);
this.getDimensions = this.getDimensions.bind(this);
this.state = this.getDimensions();
}
onLayout(e) {
const { width } = e.nativeEvent.layout || {};
this.setState({
...this.getDimensions(width),
});
}
getDimensions(lvWidth) {
const { itemWidth, spacing, fixed } = this.props;
const totalWidth = lvWidth || Dimensions.get('window').width;
const itemTotalWidth = itemWidth + spacing;
const availableWidth = totalWidth - spacing; // One spacing extra
const itemsPerRow = Math.floor(availableWidth / itemTotalWidth);
const containerWidth = availableWidth / itemsPerRow;
return {
itemWidth,
spacing,
itemsPerRow,
containerWidth,
fixed,
};
}
renderRow(data, sectionId, rowId) {
const { itemWidth, spacing, containerWidth, fixed } = this.state;
const rowStyle = {
flexDirection: 'row',
paddingLeft: spacing,
paddingBottom: spacing,
};
const columnStyle = {
flexDirection: 'column',
justifyContent: 'center',
width: containerWidth,
paddingRight: spacing,
};
let itemStyle = { };
if (fixed) {
itemStyle = {
width: itemWidth,
alignSelf: 'center',
};
}
return (
<View style={rowStyle}>
{(data || []).map((item, i) => (
<View key={`${rowId}_${i}`} style={columnStyle}>
<View style={itemStyle}>
{this.props.renderItem(item)}
</View>
</View>
))}
</View>
);
}
render() {
const { items, style, renderItem, spacing, fixed, itemWidth, ...props } = this.props;
const { itemsPerRow } = this.state;
const rows = chunkArray(items, itemsPerRow);
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
return (
<ListView
style={[{ paddingTop: spacing }, style]}
onLayout={this.onLayout}
dataSource={ds.cloneWithRows(rows)}
renderRow={this.renderRow}
{...props}
/>
);
}
}
SuperGrid.propTypes = {
renderItem: PropTypes.func.isRequired,
items: PropTypes.arrayOf(PropTypes.any).isRequired,
itemWidth: PropTypes.number,
fixed: PropTypes.bool,
spacing: PropTypes.number,
style: View.propTypes.style,
};
SuperGrid.defaultProps = {
fixed: false,
itemWidth: 120,
spacing: 10,
style: {},
};
export default SuperGrid;

34
package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "react-native-super-grid",
"version": "1.0.2",
"description": "Responsive Grid View for React Native",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/saleel97/react-native-super-grid.git"
},
"peerDependencies": {
"react-native": ">=0.26.0"
},
"homepage": "https://github.com/saleel97/react-native-super-grid",
"keywords": [
"react",
"native",
"responsive",
"super",
"grid",
"view"
],
"author": "Saleel",
"license": "MIT",
"devDependencies": {
"eslint": "^3.19.0",
"eslint-config-airbnb": "^14.1.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.3"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

13
utils.js Normal file
View File

@@ -0,0 +1,13 @@
// eslint-disable-next-line import/prefer-default-export
export function chunkArray(array, size) {
return array.reduce((acc, val) => {
if (acc.length === 0) acc.push([]);
const last = acc[acc.length - 1];
if (last.length < size) {
last.push(val);
} else {
acc.push([val]);
}
return acc;
}, []);
}