├── .circleci
└── config.yml
├── .gitignore
├── .npmignore
├── README.md
├── __tests__
└── exception.js
├── assets
├── for-readme-1.png
└── for-readme-2.png
├── babel.config.js
├── example
└── YourComponent.js
├── package-lock.json
├── package.json
└── src
├── Responsive.js
├── exception
└── index.js
├── type
└── index.js
└── util
└── index.js
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Javascript Node CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details
4 | #
5 | version: 2
6 | jobs:
7 | build:
8 | docker:
9 | # specify the version you desire here
10 | - image: circleci/node:7.10
11 |
12 | # Specify service dependencies here if necessary
13 | # CircleCI maintains a library of pre-built images
14 | # documented at https://circleci.com/docs/2.0/circleci-images/
15 | # - image: circleci/mongo:3.4.4
16 |
17 | working_directory: ~/repo
18 |
19 | steps:
20 | - checkout
21 |
22 | # Download and cache dependencies
23 | - restore_cache:
24 | keys:
25 | - v1-dependencies-{{ checksum "package.json" }}
26 | # fallback to using the latest cache if no exact match is found
27 | - v1-dependencies-
28 |
29 | - run: yarn install
30 |
31 | - save_cache:
32 | paths:
33 | - node_modules
34 | key: v1-dependencies-{{ checksum "package.json" }}
35 |
36 | # run tests!
37 | - run: yarn test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Node.js
6 | node_modules/
7 | npm-debug.log
8 | jsconfig.json
9 | dump.rdb
10 | .vscode
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Node.js
6 | node_modules/
7 | npm-debug.log
8 |
9 | # Images and extras
10 | .github/
11 | example/
12 | .eslintrc
13 | yarn.lock
14 |
15 | # tests
16 | __tests__/
17 |
18 | # assets
19 | assets/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-lightweight-responsive
2 |
3 | `react-native-lightweight-responsive` can change the size of your component into optimized size, based on the default UI size of design prototype.
4 |
5 | If you have UI prototype design and the default size of prototype is 375 X 812, some devices is OK, but others have problems like below.
6 |
7 |
8 |
9 | *What's on the right is not what you want.*
10 |
11 |
12 | ## Simple Usage
13 |
14 | **install**
15 |
16 | ```
17 | npm install --save react-native-lightweight-responsive
18 | ```
19 |
20 | **usage**
21 |
22 | ```
23 | import Responsive from 'react-native-lightweight-responsive';
24 |
25 |
29 |
32 | Hello.
33 |
34 |
35 | ```
36 |
37 | **and then?**
38 |
39 |
40 |
41 |
42 | ## API
43 |
44 | | Name | Type | Param | Description |
45 | | ------------- |:-------------:| -----:| -----: |
46 | | setOptions | func | `{width: 360, height: 640, enableOnlySmallSize: false}` | `width`, `height` sets the default size. `enableOnlySmallSize` will apply `Responsive`'s features to smaller than default size if `true`. |
47 | | width | func | `width`: number | The size (`width`) that will be changed, based on the default size (`width`) that you set using `setOptions`. |
48 | | height | func | `height`: number | The size (`height`) that will be changed, based on the default size (`height`) that you set using `setOptions`. |
49 | | font | func | `font`: number | The size (`font`) that will be changed, based on the default size (`width`) that you set using `setOptions`. |
50 |
51 | ## Example
52 |
53 | [Example](https://github.com/7772/react-native-lightweight-responsive/blob/master/example/YourComponent.js)
54 |
--------------------------------------------------------------------------------
/__tests__/exception.js:
--------------------------------------------------------------------------------
1 | import Exception from '../src/exception';
2 |
3 | describe('Exception module', () => {
4 | const exception = new Exception("Test Exception", "Exception instance");
5 | it('can make instance.', () => {
6 | expect(exception).toBeInstanceOf(Exception);
7 | });
8 | });
--------------------------------------------------------------------------------
/assets/for-readme-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/7772/react-native-lightweight-responsive/36a903a68cdfdc25fddf03de2fc3f919a3994b74/assets/for-readme-1.png
--------------------------------------------------------------------------------
/assets/for-readme-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/7772/react-native-lightweight-responsive/36a903a68cdfdc25fddf03de2fc3f919a3994b74/assets/for-readme-2.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | '@babel/preset-env',
5 | {
6 | targets: {
7 | node: 'current',
8 | },
9 | },
10 | ],
11 | ],
12 | };
--------------------------------------------------------------------------------
/example/YourComponent.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {View} from 'react-native';
3 | import Responsive from 'react-native-lightweight-responsive';
4 |
5 | /**
6 | * YourComponentFirstExample
7 | *
8 | * If you are using default viewport size (360 X 640)
9 | * and applying Responsive Design to all Smartphone size
10 | *
11 | * Use like this.
12 | */
13 | const YourComponentFirstExample = () => {
14 | return (
15 |
20 | );
21 | };
22 |
23 |
24 | /**
25 | * YourComponentSecondExample
26 | *
27 | * If you want to use customized options
28 | *
29 | * Use like this.
30 | */
31 | Responsive.setOptions({width: 375, height: 812, enableOnlySmallSize: true});
32 | const YourComponentSecondExample = () => {
33 | return (
34 |
39 | );
40 | };
41 |
42 | export {
43 | YourComponentFirstExample,
44 | YourComponentSecondExample,
45 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-lightweight-responsive",
3 | "version": "0.0.6",
4 | "description": "Support responsive UI for react-native",
5 | "main": "src/Responsive.js",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "keywords": [
10 | "react-native-lightweight-responsive",
11 | "react-native",
12 | "react",
13 | "responsive"
14 | ],
15 | "author": "7772",
16 | "license": "ISC",
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/7772/react-native-lightweight-responsive.git"
20 | },
21 | "peerDependencies": {
22 | "react": "*",
23 | "react-native": "*"
24 | },
25 | "devDependencies": {
26 | "@babel/core": "^7.4.5",
27 | "@babel/preset-env": "^7.4.5",
28 | "babel-jest": "^24.8.0",
29 | "jest": "^24.8.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Responsive.js:
--------------------------------------------------------------------------------
1 | import Exception from './exception';
2 | import { RESPONSIVE_TYPE } from './type';
3 | import { getDefaultSize, getResponsiveValue } from './util';
4 |
5 |
6 | const setOptions = (options) => {
7 | if (!options) {
8 | throw new Exception(
9 | "Responsive.setOptions() ERROR",
10 | "`options` is neccessary parameter, Not to be null or undefined."
11 | );
12 | }
13 | if (typeof options.width !== 'number') {
14 | throw new Exception(
15 | "Responsive.setOptions() ERROR",
16 | "`width` property in `options` object is not number."
17 | );
18 | }
19 | if (typeof options.height !== 'number') {
20 | throw new Exception(
21 | "Responsive.setOptions() ERROR",
22 | "`height` property in `options` object is not number."
23 | );
24 | }
25 | if (typeof options.enableOnlySmallSize !== 'boolean') {
26 | throw new Exception(
27 | "Responsive.setOptions() ERROR",
28 | "`enableOnlySmallSize` property in `options` object is not boolean."
29 | );
30 | }
31 |
32 | if (!this.defaultSize) {
33 | this.defaultSize = {};
34 | }
35 |
36 | this.defaultSize.width = options.width;
37 | this.defaultSize.height = options.height;
38 | this.enableOnlySmallSize = options.enableOnlySmallSize;
39 | };
40 |
41 | const width = (width) => {
42 | if (!this.defaultSize) {
43 | this.defaultSize = getDefaultSize();
44 | }
45 |
46 | const ratio = (width / this.defaultSize.width) * 100;
47 | const responsiveWidth = getResponsiveValue(RESPONSIVE_TYPE['WIDTH'], ratio);
48 |
49 | if (this.enableOnlySmallSize && responsiveWidth > width) {
50 | return width;
51 | }
52 |
53 | return responsiveWidth;
54 | };
55 |
56 | const height = (height) => {
57 | if (!this.defaultSize) {
58 | this.defaultSize = getDefaultSize();
59 | }
60 |
61 | const ratio = (height / this.defaultSize.height) * 100;
62 | const responsiveHeight = getResponsiveValue(RESPONSIVE_TYPE['HEIGHT'], ratio);
63 |
64 | if (this.enableOnlySmallSize && responsiveHeight > height) {
65 | return height;
66 | }
67 |
68 | return responsiveHeight;
69 | };
70 |
71 | const font = (font) => {
72 | if (!this.defaultSize) {
73 | this.defaultSize = getDefaultSize();
74 | }
75 |
76 | const ratio = ((font / this.defaultSize.width) * 100);
77 | const responsiveFont = getResponsiveValue(RESPONSIVE_TYPE['FONT'], ratio);
78 |
79 | if (this.enableOnlySmallSize && responsiveFont > font) {
80 | return font;
81 | }
82 |
83 | return responsiveFont;
84 | };
85 |
86 | export default Responsive = {
87 | defaultSize: getDefaultSize(),
88 | enableOnlySmallSize: false,
89 | setOptions: setOptions,
90 | width: width,
91 | height: height,
92 | font: font,
93 | };
94 |
--------------------------------------------------------------------------------
/src/exception/index.js:
--------------------------------------------------------------------------------
1 | function Exception(name, message) {
2 | this.name = name;
3 | this.message = message;
4 | }
5 |
6 | Exception.prototype.toString = () => {
7 | return this.name + ': "' + this.message + '"';
8 | };
9 |
10 | export default Exception;
--------------------------------------------------------------------------------
/src/type/index.js:
--------------------------------------------------------------------------------
1 | const RESPONSIVE_TYPE = {
2 | 'WIDTH': 'WIDTH',
3 | 'HEIGHT': 'HEIGHT',
4 | 'FONT': 'FONT',
5 | };
6 |
7 | export {
8 | RESPONSIVE_TYPE,
9 | };
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | import { Dimensions, PixelRatio } from 'react-native';
2 | import Exception from '../exception';
3 | import { RESPONSIVE_TYPE } from '../type';
4 |
5 | const appScreen = {width, height} = Dimensions.get('window');
6 |
7 | export const getDefaultSize = () => {
8 | return {
9 | width: 360,
10 | height: 640,
11 | };
12 | };
13 |
14 | export const getResponsiveValue = (type, ratio = null) => {
15 | let screenValue;
16 |
17 | if (type === RESPONSIVE_TYPE['WIDTH']) {
18 | screenValue = appScreen.width;
19 | } else if (type === RESPONSIVE_TYPE['HEIGHT']) {
20 | screenValue = appScreen.height;
21 | } else if (type === RESPONSIVE_TYPE['FONT']) {
22 | screenValue = appScreen.width;
23 | } else {
24 | throw new Exception(
25 | "Responsive Library ERROR",
26 | "getResponsiveValue() supports only 'WIDTH', 'HEIGHT', 'FONT'."
27 | );
28 | }
29 |
30 | if (!ratio || typeof ratio !== 'number') {
31 | throw new Exception(
32 | "Responsive Library ERROR",
33 | "The `ratio` parameter of getResponsive() must be `number` type."
34 | );
35 | }
36 |
37 | return PixelRatio.roundToNearestPixel(screenValue * ratio / 100);
38 | };
--------------------------------------------------------------------------------