Skip to content

Commit

Permalink
add first version + structure
Browse files Browse the repository at this point in the history
  • Loading branch information
tibbus committed May 31, 2017
1 parent 043dcbd commit 1c58a0f
Show file tree
Hide file tree
Showing 23 changed files with 684 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ bower_components
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
build

# Dependency directories
node_modules/
Expand Down
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
React Native responsive components.

## Introduction
Responsive Image, Video and Modal components that fits in dynamic containers.


![Example](https://github.com/tibbus/react-native-fit/blob/master/example/demo.gif)

## Install
`npm install react-native-fit --save` <br>
`yarn add react-native-fit`

## Usage
Dependencies :
https://github.com/kfiroo/react-native-cached-image AND <br>
https://github.com/react-native-community/react-native-video

Run to link the libraries : <br>
react-native link react-native-fetch-blob <br>
react-native link <br>

Note: You can disable FitImage cache by passing props `cache={false}`


FitImage is a wrapper of Image component from react-native:
```javascript
import FitImage from 'react-native-fit/fitImage';

render() {
return <FitImage source={{uri: 'yourImagepath...'}} />
}
```

FitVideo is a wrapper of react-native-video:
```javascript
import FitVideo from 'react-native-fit/fitVideo';

render() {
return <FitVideo source={{uri: 'yourVideopath...'}} />
}
```

FitModal is a wrapper of Modal component from react-native:
```javascript
import FitModal from 'react-native-fit/fitModal';

render() {
return (
<FitModal content={<Text style={{color: 'white'}}>text conten</Text>}>
<Text>open Modal</Text>
</FitModal>
);
}
```

Use fitModal with fitImage and fitVideo:
```javascript
import { FitModal, FitImage, FitVideo } from 'react-native-fit';

render() {
return (
<FitModal content={<FitVideo source={{uri: 'yourVideopath...'}} />}>
<FitVideo playable={false} source={{uri: 'yourVideopath...'}} />
</FitModal>

<FitModal content={<FitImage source={{uri: 'yourImagepath...'}} />}>
<FitImage source={{uri: 'yourImagepath...'}} />
</FitModal>
);
}
```
Binary file added assets/close-button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/play-button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions fitImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { FitImage } from './build/fitImage/fitImage.component';

module.exports = FitImage;
3 changes: 3 additions & 0 deletions fitModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { FitModal } from './build/fitModal/fitModal.component';

module.exports = FitModal;
3 changes: 3 additions & 0 deletions fitVideo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { FitVideo } from './build/fitVideo/fitVideo.component';

module.exports = FitVideo;
9 changes: 9 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

import { FitImageProps } from './src/fitImage/fitImage.props';
import { FitVideoProps } from './src/fitVideo/fitVideo.props';
import { FitModalProps } from './src/fitModal/fitModal.props';

export class FitImage extends React.Component<FitImageProps, any> { }
export class FitVideo extends React.Component<FitVideoProps, any> { }
export class FitModal extends React.Component<FitModalProps, any> { }
9 changes: 9 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { FitImage } from './build/fitImage/fitImage.component';
import { FitVideo } from './build/fitVideo/fitVideo.component';
import { FitModal } from './build/fitModal/fitModal.component';

module.exports = {
FitImage,
FitVideo,
FitModal
};
38 changes: 38 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "react-native-fit",
"version": "1.0.0",
"description": "Responsive components for react native.",
"main": "index.js",
"scripts": {
"tsc": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tibbus/react-native-fit.git"
},
"keywords": [
"react-native",
"fit",
"image",
"video",
"modal",
"responsive",
"media",
"ios",
"android"
],
"author": "tibbus",
"license": "MIT",
"bugs": {
"url": "https://github.com/tibbus/react-native-fit/issues"
},
"homepage": "https://github.com/tibbus/react-native-fit#readme",
"dependencies": {
"react-native-cached-image": "1.3.3",
"react-native-video": "1.0.0"
},
"devDependencies": {
"typescript": "2.3.4"
}
}
102 changes: 102 additions & 0 deletions src/fitImage/fitImage.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { Component } from 'react';
import { Image, ViewStyle } from 'react-native';
import CachedImage, { ImageCacheProvider } from 'react-native-cached-image';

import { FitImageProps } from './fitImage.props';
import { getNativeProps } from '../utils';

export class FitImage extends Component<FitImageProps, any> {
private ratio: number;
private mounted: boolean = true;

static defaultProps = {
cache: true
}

state = {
width: null,
height: null
}

componentWillMount() {
if (!this.props.cache) {
this.setSizesByRatio(this.props.source);
return;
}

// Get the image dimensions from cached storage or from remote uri
ImageCacheProvider.getCachedImagePath(this.props.source.uri)
.then(localUri => this.setSizesByRatio(localUri))
.catch(error => this.setSizesByRatio(this.props.source));
}

componentWillUnmount() {
this.mounted = false;
}

public onLayout(event) {
const { width, height } = event.nativeEvent.layout;

this.state.width = width;
this.state.height = height;

this.renderImage();

// onLayout event middleware
if (this.props.onLayout) {
this.props.onLayout(event);
}
}

public renderImage() {
// Wait for both layout event and Image.getSize to finish before render it
if (!this.state.width || !this.ratio || !this.mounted) {
return;
}

if (this.props.round) {
this.setState({
width: this.state.width,
height: this.state.width
});
} else {
this.setState({
width: this.state.width,
height: this.state.width / this.ratio
});
}
}

public getStyle() {
return {
width: this.state.width,
height: this.state.height,
borderRadius: this.props.round ? this.state.width / 2 : 0
};
}

public getImageProps() {
return getNativeProps(this.props, ['source', 'style', 'onLayout']);
}

private setSizesByRatio = (uri) => {
Image.getSize(uri, (width, height) => {
this.ratio = width / height;
this.renderImage();
}, failure => console.log(`failed to load image, ${this.props.source}`));
}

render() {
const ImageComponent = this.props.cache ? CachedImage : Image;

return (
<ImageComponent {...this.getImageProps() }
source={this.props.source}
style={[this.getStyle(), this.props.style]}
onLayout={event => this.onLayout(event)}
>
{this.props.children}
</ImageComponent>
);
};
}
7 changes: 7 additions & 0 deletions src/fitImage/fitImage.props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ImageProperties, ImageURISource } from 'react-native';

export interface FitImageProps extends ImageProperties {
source: ImageURISource,
round?: boolean,
cache?: boolean
}
52 changes: 52 additions & 0 deletions src/fitModal/fitModal.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { Component } from 'react';
import { Modal, Text, TouchableOpacity, View, ViewStyle, Image } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

import { FitModalProps } from './fitModal.props';
import { styles } from './fitModal.styles';
import { getNativeProps } from '../utils';

export class FitModal extends Component<FitModalProps, any> {
static defaultProps = {
animationType: 'slide'
}

state = {
modalVisible: false
}

public pressOpen = () => {
this.setState({ modalVisible: true });
}

public pressClose = () => {
this.setState({ modalVisible: false });
}

public getModalProps() {
return getNativeProps(this.props, ['content', 'style']);
}

render() {
return (
<View>
<Modal {...this.getModalProps() } visible={this.state.modalVisible}>
<View style={styles.modalContainer}>
<TouchableOpacity style={styles.closeButton} onPress={this.pressClose}>
<Image source={require('../../assets/close-button.png')} style={styles.closeIcon} />
</TouchableOpacity>
<View style={styles.contentContainer}>
{this.props.content}
</View>
</View>
</Modal>

<TouchableOpacity activeOpacity={0.9} onPress={this.pressOpen}>
<View style={this.props.style}>
{this.props.children}
</View>
</TouchableOpacity>
</View>
);
}
}
6 changes: 6 additions & 0 deletions src/fitModal/fitModal.props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ModalProperties, ViewStyle } from 'react-native';

export interface FitModalProps extends ModalProperties {
content: React.ReactNode,
style?: ViewStyle
}
24 changes: 24 additions & 0 deletions src/fitModal/fitModal.styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { StyleSheet } from 'react-native';

export const styles = StyleSheet.create({
modalContainer: {
backgroundColor: 'black',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row'
},
contentContainer: {
flex: 1
},
closeButton: {
position: 'absolute',
left: 0,
top: 0,
padding: 10
},
closeIcon: {
width: 30,
height: 30
}
})
Loading

0 comments on commit 1c58a0f

Please sign in to comment.