Skip to content

Commit

Permalink
=> .jsbeautifyrc: Added configs for beautification
Browse files Browse the repository at this point in the history
=> example/src/proptypes.js: Added PropTypes class for custom proptypes validations
=> example/src/service/index.js: Added a service class to provide static methods and utilities for device sizes getters and so on
=> example/src/mediaquery.js: Separated isValidDeviceDimensions between 3 functions (isValidDeviceWidth...) and added a function isValidDevice to check size interval constraints for devices hardware specs (width, height, pixel ratio)
=> example/src/mediaquery.js: Injected Service static class
=> example/index.android.js: Added more containers
=> example/index.android.js: Added some array styles
=> example/src/next.js: Removed
=> .eslintrc.json: Added babel-eslint as default parser to allow some ES7 syntaxes
=> package.json: Added babel-eslint dependency
=> example/package.json: Updated react-native version
=> Cleaned code
  • Loading branch information
ayoubdev committed May 7, 2016
1 parent 2d5ea43 commit cc2b698
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 161 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Expand Up @@ -6,6 +6,7 @@
"commonjs": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
Expand Down
33 changes: 33 additions & 0 deletions .jsbeautifyrc
@@ -0,0 +1,33 @@
{
"brace_style": "collapse-preserve-inline",
"break_chained_methods": false,
"comma_first": false,
"e4x": true,
"end_with_newline": true,
"eol": "\n",
"eval_code": false,
"keep_array_indentation": false,
"keep_function_indentation": false,
"indent_size": 4,
"indent_char": " ",
"indent_level": 0,
"indent_with_tabs": true,
"jslint_happy": false,
"max_preserve_newlines": 10,
"preserve_newlines": true,
"space_after_anon_function": false,
"space_before_conditional": false,
"space_in_paren": false,
"wrap_attributes": "auto",
"wrap_attributes_indent_size": 4,
"wrap_line_length": 0,
"unescape_strings": false,

"newline_between_rules": true,
"selector_separator_newline": false,

"extra_liners": ["head", "body", "/html"],
"indent_inner_html": true,
"indent_scripts": "normal",
"unformatted": ["inline"]
}
4 changes: 4 additions & 0 deletions README.md
@@ -1,2 +1,6 @@
# react-native-responsive
A React Native module to manage layouts between different sizes and displays

### To not forget:

deviceWidth and deviceHeight must take in account status bar and button bar sizes
31 changes: 17 additions & 14 deletions example/index.android.js
Expand Up @@ -11,19 +11,29 @@ import {
View
} from "react-native";

import ResponsiveLayout from "./src/responsive.js";
import ResponsiveLayout from "./src/responsive.js";//ResponsiveStore?
import MediaQuery from "./src/mediaquery.js";

class ReactNativeResponsive extends Component {
render() {
return (
<ResponsiveLayout style={styles.responsivelayout}>
<View style={{flex: 1}}>
<MediaQuery style={styles.mediaquery} minDeviceWidth={200} maxDeviceWidth={1080}>
<View style={styles.container1}>
<Text> Test Responsive </Text>
<View style={[styles.container, {backgroundColor: "blue"}]}>
<Text> Container 1 </Text>
</View>
</MediaQuery>
</ResponsiveLayout>
<MediaQuery style={styles.mediaquery} minDeviceWidth={200} maxDeviceWidth={1080} maxPixelRatio={3}>
<View style={[styles.container, {backgroundColor: "white"}]}>
<Text> Container 2 </Text>
</View>
</MediaQuery>
<MediaQuery style={styles.mediaquery} minDeviceWidth={200} maxDeviceWidth={1080}>
<View style={[styles.container, {backgroundColor: "red"}]}>
<Text> Container 3 </Text>
</View>
</MediaQuery>
</View>
);
}
}
Expand All @@ -37,17 +47,10 @@ const styles = StyleSheet.create({
flex: 1,
backgroundColor: "#000000"
},
container1: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#FF0000"
},
container2: {
"container": {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#0000FF"
alignItems: "center"
}
});

Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Expand Up @@ -7,6 +7,6 @@
},
"dependencies": {
"react": "^0.14.8",
"react-native": "^0.24.1"
"react-native": "^0.25.1"
}
}
143 changes: 95 additions & 48 deletions example/src/mediaquery.js
@@ -1,83 +1,128 @@
import React from "react";
import {
Dimensions,
PixelRatio,
View
} from "react-native";
import CustomPropTypes from "./proptypes.js";
import Service from "./service/index.js";

class MediaQuery extends React.Component {
constructor(props) {
super(props);

//Pour le moment, le caractère responsive se basera sur des propriétés immutables du screen device
//(telle que la résolution ou le pixel ratio).
this.state = {
width: 0,
height: 0
};

//La vérification des contraintes devices se font dans le constructeur
//puisqu'elles se basent sur des propriétés immutables du screen device
//(telle que la résolution ou le pixel ratio):
//Pour des examples de configurations Media Query suivant les appareils:
//cf. https://css-tricks.com/snippets/css/media-queries-for-standard-devices/
this.pixelRatio = PixelRatio.get();
//Les Dimensions initiales sont settées avant runApplication(). On peut donc les getter dans le constructeur
//On peut ainsi stocke la résolution (hauteur, largeur) du device et que cette dernière
//ne change pas au cours du temps (sinon wtf :))
//Cependant, Dimensions.get récupère la résolution du screen à un instant t: elle donnera des valeurs différentes
//suivant si screen en mode portrait ou paysage: étant donné que le nombre de pixel en hauteur est toujours plus
//important qu'en largeur (screen ratio généralement 4:3 ou 16:9), on utilise la fonction max et min de la lib Math
//pour assigner notre hauteur et largeur de façon immutable (indépendemment donc de la résolution):
this.deviceWidth = Math.min(Dimensions.get("window").width, Dimensions.get("window").height) * this.pixelRatio;
this.deviceHeight = Math.max(Dimensions.get("window").width, Dimensions.get("window").height) * this.pixelRatio;

this.isDisplayed = this.isValidDeviceDimensions() && this.isValidPixelRatio();
this.isViewableStatic = this.isValidDevice(
Service.deviceWidth,
Service.deviceHeight,
Service.pixelRatio
);
}

//VALIDATIONS DES CONTRAINTES DE TAILLES SPECIFIQUES AU HARDWARE (immutables):
isValidDevice(width, height, pixelRatio) {
//console.log("isValid()", this.isValidDeviceWidth(width), this.isValidDeviceHeight(height), this.isValidDevicePixelRatio(pixelRatio));

return this.isValidDeviceWidth(width) && this.isValidDeviceHeight(height) && this.isValidDevicePixelRatio(pixelRatio);
}

isValidDeviceWidth(width) {
//Les falsy values en Javascript correspondent à undefined, null, false, 0, ""...
//donc inutile de faire un call sur hasOwnProperty, il suffit simplement de
//checker si la condition est true (par exemple, si la variable est undefined, la condition sera false):

//La prop deviceWidth a une importance plus élévée que min et max, on le test en premier:
if(this.props.deviceWidth)
return this.props.deviceWidth === width;
else {
let min = this.props.minDeviceWidth;
let max = this.props.maxDeviceWidth;

if(min || max)
return Service.isInInterval(width, min, max);
}

//Par défault, si aucune propriété width n'est spécifiée,
//on considère la largeur comme valide (pour permettre l'affichage des enfants par défaut):
return true;
}

isValidDeviceDimensions() {
//TODO: gérer undefined:
if(this.props.deviceWidth !== this.deviceWidth
|| this.props.deviceHeight !== this.deviceHeight
|| this.props.minDeviceWidth > this.deviceWidth
|| this.props.maxDeviceWidth < this.deviceWidth
|| this.props.minDeviceHeight > this.deviceHeight
|| this.props.maxDeviceHeight < this.deviceHeight) {
return false;
isValidDeviceHeight(height) {
if(this.props.deviceHeight)
return this.props.deviceHeight === height;
else {
let min = this.props.minDeviceHeight;
let max = this.props.maxDeviceHeight;

if(min || max)
return Service.isInInterval(height, min, max);
}

return true;
}

isValidPixelRatio() {
//TODO: gérer undefined:
if(this.props.minPixelRatio > this.pixelRatio
||this.props.maxPixelRatio < this.pixelRatio) {
return false;
isValidDevicePixelRatio(pixelRatio) {
if(this.props.pixelRatio)
return this.props.pixelRatio === pixelRatio;
else {
let min = this.props.minPixelRatio;
let max = this.props.maxPixelRatio;

if(min || max)
return Service.isInInterval(pixelRatio, min, max);
}

return true;
}

//VALIDATIONS DES CONTRAINTES DE TAILLES EVOLUANT DANS LE TEMPS (orientation...):
//TODO: @faire dans responsivelayout qui gérera le get de l'orientation et l'envoiera à mediaquery
//si le prop orientation n'est pas false dans mediaquery alors on switche automatiquement en mode dynamique!
//mediaquery peut fonctionner seule mais juste avec les propriétés immutables!:
/*onLayout(event) {
if(!Service.orientation) {
console.log("onLayout()", event.nativeEvent);
Service.debounce(() => console.log("Ayoub"), 2000);
Service.orientation = true;
}
}*/

render() {
//TODO: A commenter, juste pour les tests comme le hot reloading ne relance pas le constructeur:
this.isViewableStatic = this.isValidDevice(Service.deviceWidth, Service.deviceHeight, Service.pixelRatio);
console.log(
this.props.minDeviceWidth, this.props.maxDeviceWidth,
this.props.minDeviceHeight, this.props.maxDeviceHeight,
this.deviceWidth, this.deviceHeight,
this.pixelRatio, this.isDisplayed
"render()\n",
"this.props.minDeviceWidth = " + this.props.minDeviceWidth + "\n",
"this.props.maxDeviceWidth = " + this.props.maxDeviceWidth + "\n",
"this.props.minDeviceHeight = " + this.props.minDeviceHeight + "\n",
"this.props.maxDeviceHeight = " + this.props.maxDeviceHeight + "\n",
"this.deviceWidth = " + Service.deviceWidth + "\n",
"this.deviceHeight = " + Service.deviceHeight + "\n",
"this.pixelRatio = " + Service.pixelRatio + "\n",
"this.isViewableStatic = " + this.isViewableStatic
);
if(this.isDisplayed) {
return (
<View style={this.props.style} onLayout={this.onLayout}>
{this.props.children}
</View>
);
if(this.isViewableStatic) {
return this.props.children;
}
//Retourner null est une indication explicite à React de ne rien afficher:
return null;
}
}

//cf. https://developer.mozilla.org/fr/docs/Web/CSS/Media_queries#Pseudo-BNF_(pour_ceux_qui_aiment_ce_genre_de_choses)
//TODO: Gérer orientation dans une future version:
MediaQuery.propTypes = {
style: React.PropTypes.number,
children: React.PropTypes.oneOfType([
React.PropTypes.element,
React.PropTypes.arrayOf(React.PropTypes.element)
]),
/*children: React.PropTypes.oneOfType([
React.PropTypes.element
//MediaQuery n'est pas un container d'élément d'où le fait qu'il ne prend pas de tableau d'éléments:
//React.PropTypes.arrayOf(React.PropTypes.element)
]),*/
children: CustomPropTypes.childrenValidator,

deviceWidth: React.PropTypes.number,
minDeviceWidth: React.PropTypes.number,
maxDeviceWidth: React.PropTypes.number,
Expand All @@ -87,6 +132,8 @@ MediaQuery.propTypes = {
pixelRatio: React.PropTypes.number,
minPixelRatio: React.PropTypes.number,
maxPixelRatio: React.PropTypes.number

//orientation: React.PropTypes.oneOf(["landscape", "portrait"])//En privé (transmis par responsivelayout)
};

export default MediaQuery;
98 changes: 0 additions & 98 deletions example/src/next.js

This file was deleted.

0 comments on commit cc2b698

Please sign in to comment.