-PreactNativeArchitectures=x86_64
30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
31 |
32 | # Use this property to enable support to the new architecture.
33 | # This will allow you to use TurboModules and the Fabric render in
34 | # your application. You should enable this flag either if you want
35 | # to write custom TurboModules/Fabric components OR use libraries that
36 | # are providing them.
37 | newArchEnabled=false
38 |
39 | # Use this property to enable or disable the Hermes JS engine.
40 | # If set to false, you will be using JSC instead.
41 | hermesEnabled=true
42 |
--------------------------------------------------------------------------------
/tv-example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { ReactNode } from 'react';
2 | import type { ImageStyle, TextStyle, ViewStyle } from 'react-native';
3 |
4 | export enum BASE_SIZES {
5 | xs = 320,
6 | sm = 360,
7 | md = 520,
8 | lg = 680,
9 | xl = 740,
10 | '2xl' = 920,
11 | }
12 | export type MaybeNumber = number | undefined;
13 | export type PropsWithChildren = P & { children?: ReactNode | undefined };
14 | export type DeviceType = Uncapitalize;
15 | export type MappedDeviceType = {
16 | [K in DeviceType]: K extends DeviceType ? number : never;
17 | };
18 | export interface ContextProps {
19 | /**
20 | * Specify the current device type to calculation be based on the related base width.
21 | * @default sm
22 | */
23 | type: DeviceType;
24 | /**
25 | * The base width sizes for each platform to handle and calculate scaled size based on that.
26 | */
27 | bases: Partial;
28 | }
29 | export interface ResponsiveMethodsProps {
30 | rs: (size: number) => number;
31 | rw: (widthPercentage: number) => number;
32 | rh: (heightPercentage: number) => number;
33 | }
34 | export type StyleStack = {
35 | style: any;
36 | parentPath: unknown;
37 | };
38 | export type WithPattern = {
39 | [P in keyof T]: number extends T[P] ? ResponsivePattern | T[P] : T[P];
40 | };
41 | export type NamedStyles = {
42 | [P in keyof T]:
43 | | WithPattern
44 | | WithPattern
45 | | WithPattern;
46 | };
47 | export type Pattern = 'rs' | 'rw' | 'rh';
48 | export type ResponsivePattern = `${number}${Pattern}`;
49 | export type ValuePattern = string | number | ResponsivePattern;
50 | export type CreateStyleConfig = {
51 | /**
52 | * To use custom dimensions width for the calculation
53 | */
54 | width: number;
55 | /**
56 | * To use custom dimensions height for the calculation
57 | */
58 | height: number;
59 | /**
60 | * To use a specific responsive scale method config for applying when using `rs` for style properties
61 | */
62 | scaleConfig: Partial;
63 | };
64 |
65 | export type StyleType = {
66 | [P in keyof T]: {
67 | [S in keyof T[P]]: T[P][S] extends ResponsivePattern ? number : T[P][S];
68 | };
69 | };
70 |
--------------------------------------------------------------------------------
/tv-example/ios/tvexampleTests/tvexampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface tvexampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation tvexampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/src/layout/responsiveMethods.ts:
--------------------------------------------------------------------------------
1 | import { PixelRatio } from 'react-native';
2 | import { getDimensions } from '../utils';
3 | import { getBaseWidth } from './getBaseWidth';
4 | import type { ContextProps, MaybeNumber } from '../types';
5 |
6 | const { screenWidth, screenHeight } = getDimensions();
7 | /**
8 | * The responsive width size will be calculated using the passed percentage.
9 | * @param widthPercentage
10 | * @param width screen width of device
11 | * @returns calculated size, if the passed percentage is not a number, it will be the passed value.
12 | */
13 | const responsiveWidth = (
14 | widthPercentage: T,
15 | width = screenWidth
16 | ) => {
17 | if (typeof widthPercentage !== 'number') {
18 | return widthPercentage;
19 | }
20 | return PixelRatio.roundToNearestPixel((width * widthPercentage) / 100);
21 | };
22 | /**
23 | * The responsive height size will be calculated using the passed percentage.
24 | * @param heightPercentage
25 | * @param height screen height of device
26 | * @returns calculated size, if the passed percentage is not a number, it will be the passed value.
27 | */
28 | const responsiveHeight = (
29 | heightPercentage: T,
30 | height = screenHeight
31 | ) => {
32 | if (typeof heightPercentage !== 'number') {
33 | return heightPercentage;
34 | }
35 | return PixelRatio.roundToNearestPixel((height * heightPercentage) / 100);
36 | };
37 | /**
38 | * The responsive scaled size will be calculated using the passed size.
39 | * @param size
40 | * @param width screen width of device
41 | * @param height screen height of device
42 | * @returns scaled size, if the passed size is not a number, it will be the passed value.
43 | */
44 | const responsiveScale = (
45 | size: T,
46 | width = screenWidth,
47 | height = screenHeight,
48 | config?: Partial
49 | ) => {
50 | if (typeof size !== 'number') {
51 | return size;
52 | }
53 | const baseWidth = getBaseWidth(config?.type, config?.bases);
54 | const dimension = width < height ? width : height;
55 | return (dimension / baseWidth) * size;
56 | };
57 |
58 | export {
59 | responsiveScale,
60 | responsiveWidth,
61 | responsiveHeight,
62 | responsiveScale as rs,
63 | responsiveWidth as rw,
64 | responsiveHeight as rh,
65 | };
66 |
--------------------------------------------------------------------------------
/tv-example/ios/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/react-native-tvos/react-native-tvos-podspecs.git'
2 | source 'https://cdn.cocoapods.org/'
3 |
4 | # Resolve react_native_pods.rb with node to allow for hoisting
5 | require Pod::Executable.execute_command('node', ['-p',
6 | 'require.resolve(
7 | "react-native/scripts/react_native_pods.rb",
8 | {paths: [process.argv[1]]},
9 | )', __dir__]).strip
10 |
11 | prepare_react_native_project!
12 |
13 | flipper_config = FlipperConfiguration.disabled
14 |
15 | linkage = ENV['USE_FRAMEWORKS']
16 | if linkage != nil
17 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
18 | use_frameworks! :linkage => linkage.to_sym
19 | end
20 |
21 | ####### For now, only one target at a time can be used in a React Native podfile ########
22 | ####### https://github.com/react-native-tvos/react-native-tvos/issues/619 ########
23 |
24 | # target 'tvexample' do
25 | # config = use_native_modules!
26 | # platform :ios, min_ios_version_supported
27 | #
28 | # use_react_native!(
29 | # :path => config[:reactNativePath],
30 | # # Enables Flipper.
31 | # #
32 | # # Note that if you have use_frameworks! enabled, Flipper will not work and
33 | # # you should disable the next line.
34 | # :flipper_configuration => flipper_config,
35 | # # An absolute path to your application root.
36 | # :app_path => "#{Pod::Config.instance.installation_root}/.."
37 | # )
38 | #
39 | # target 'tvexampleTests' do
40 | # inherit! :complete
41 | # # Pods for testing
42 | # end
43 | #
44 | # end
45 |
46 | target 'tvexample-tvOS' do
47 | config = use_native_modules!
48 | platform :tvos, min_ios_version_supported
49 |
50 | use_react_native!(
51 | :path => config[:reactNativePath],
52 | # Enables Flipper.
53 | #
54 | # Note that if you have use_frameworks! enabled, Flipper will not work and
55 | # you should disable the next line.
56 | :flipper_configuration => flipper_config,
57 | # An absolute path to your application root.
58 | :app_path => "#{Pod::Config.instance.installation_root}/.."
59 | )
60 |
61 | target 'tvexample-tvOSTests' do
62 | inherit! :complete
63 | # Pods for testing
64 | end
65 |
66 | end
67 |
68 | post_install do |installer|
69 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
70 | config = use_native_modules!
71 | react_native_post_install(
72 | installer,
73 | config[:reactNativePath],
74 | :mac_catalyst_enabled => false
75 | )
76 | end
77 |
--------------------------------------------------------------------------------
/tv-example/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.7)
5 | base64
6 | nkf
7 | rexml
8 | activesupport (6.1.7.6)
9 | concurrent-ruby (~> 1.0, >= 1.0.2)
10 | i18n (>= 1.6, < 2)
11 | minitest (>= 5.1)
12 | tzinfo (~> 2.0)
13 | zeitwerk (~> 2.3)
14 | addressable (2.8.6)
15 | public_suffix (>= 2.0.2, < 6.0)
16 | algoliasearch (1.27.5)
17 | httpclient (~> 2.8, >= 2.8.3)
18 | json (>= 1.5.1)
19 | atomos (0.1.3)
20 | base64 (0.2.0)
21 | claide (1.1.0)
22 | cocoapods (1.14.3)
23 | addressable (~> 2.8)
24 | claide (>= 1.0.2, < 2.0)
25 | cocoapods-core (= 1.14.3)
26 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
27 | cocoapods-downloader (>= 2.1, < 3.0)
28 | cocoapods-plugins (>= 1.0.0, < 2.0)
29 | cocoapods-search (>= 1.0.0, < 2.0)
30 | cocoapods-trunk (>= 1.6.0, < 2.0)
31 | cocoapods-try (>= 1.1.0, < 2.0)
32 | colored2 (~> 3.1)
33 | escape (~> 0.0.4)
34 | fourflusher (>= 2.3.0, < 3.0)
35 | gh_inspector (~> 1.0)
36 | molinillo (~> 0.8.0)
37 | nap (~> 1.0)
38 | ruby-macho (>= 2.3.0, < 3.0)
39 | xcodeproj (>= 1.23.0, < 2.0)
40 | cocoapods-core (1.14.3)
41 | activesupport (>= 5.0, < 8)
42 | addressable (~> 2.8)
43 | algoliasearch (~> 1.0)
44 | concurrent-ruby (~> 1.1)
45 | fuzzy_match (~> 2.0.4)
46 | nap (~> 1.0)
47 | netrc (~> 0.11)
48 | public_suffix (~> 4.0)
49 | typhoeus (~> 1.0)
50 | cocoapods-deintegrate (1.0.5)
51 | cocoapods-downloader (2.1)
52 | cocoapods-plugins (1.0.0)
53 | nap
54 | cocoapods-search (1.0.1)
55 | cocoapods-trunk (1.6.0)
56 | nap (>= 0.8, < 2.0)
57 | netrc (~> 0.11)
58 | cocoapods-try (1.2.0)
59 | colored2 (3.1.2)
60 | concurrent-ruby (1.2.3)
61 | escape (0.0.4)
62 | ethon (0.16.0)
63 | ffi (>= 1.15.0)
64 | ffi (1.16.3)
65 | fourflusher (2.3.1)
66 | fuzzy_match (2.0.4)
67 | gh_inspector (1.1.3)
68 | httpclient (2.8.3)
69 | i18n (1.14.1)
70 | concurrent-ruby (~> 1.0)
71 | json (2.7.1)
72 | minitest (5.22.2)
73 | molinillo (0.8.0)
74 | nanaimo (0.3.0)
75 | nap (1.1.0)
76 | netrc (0.11.0)
77 | nkf (0.2.0)
78 | public_suffix (4.0.7)
79 | rexml (3.2.6)
80 | ruby-macho (2.5.1)
81 | typhoeus (1.4.1)
82 | ethon (>= 0.9.0)
83 | tzinfo (2.0.6)
84 | concurrent-ruby (~> 1.0)
85 | xcodeproj (1.24.0)
86 | CFPropertyList (>= 2.3.3, < 4.0)
87 | atomos (~> 0.1.3)
88 | claide (>= 1.0.2, < 2.0)
89 | colored2 (~> 3.1)
90 | nanaimo (~> 0.3.0)
91 | rexml (~> 3.2.4)
92 | zeitwerk (2.6.13)
93 |
94 | PLATFORMS
95 | ruby
96 |
97 | DEPENDENCIES
98 | activesupport (>= 6.1.7.5, < 7.1.0)
99 | cocoapods (>= 1.13, < 1.15)
100 |
101 | RUBY VERSION
102 | ruby 2.6.10p210
103 |
104 | BUNDLED WITH
105 | 2.3.23
106 |
--------------------------------------------------------------------------------
/macos-example/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.7)
5 | base64
6 | nkf
7 | rexml
8 | activesupport (6.1.7.6)
9 | concurrent-ruby (~> 1.0, >= 1.0.2)
10 | i18n (>= 1.6, < 2)
11 | minitest (>= 5.1)
12 | tzinfo (~> 2.0)
13 | zeitwerk (~> 2.3)
14 | addressable (2.8.6)
15 | public_suffix (>= 2.0.2, < 6.0)
16 | algoliasearch (1.27.5)
17 | httpclient (~> 2.8, >= 2.8.3)
18 | json (>= 1.5.1)
19 | atomos (0.1.3)
20 | base64 (0.2.0)
21 | claide (1.1.0)
22 | cocoapods (1.14.3)
23 | addressable (~> 2.8)
24 | claide (>= 1.0.2, < 2.0)
25 | cocoapods-core (= 1.14.3)
26 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
27 | cocoapods-downloader (>= 2.1, < 3.0)
28 | cocoapods-plugins (>= 1.0.0, < 2.0)
29 | cocoapods-search (>= 1.0.0, < 2.0)
30 | cocoapods-trunk (>= 1.6.0, < 2.0)
31 | cocoapods-try (>= 1.1.0, < 2.0)
32 | colored2 (~> 3.1)
33 | escape (~> 0.0.4)
34 | fourflusher (>= 2.3.0, < 3.0)
35 | gh_inspector (~> 1.0)
36 | molinillo (~> 0.8.0)
37 | nap (~> 1.0)
38 | ruby-macho (>= 2.3.0, < 3.0)
39 | xcodeproj (>= 1.23.0, < 2.0)
40 | cocoapods-core (1.14.3)
41 | activesupport (>= 5.0, < 8)
42 | addressable (~> 2.8)
43 | algoliasearch (~> 1.0)
44 | concurrent-ruby (~> 1.1)
45 | fuzzy_match (~> 2.0.4)
46 | nap (~> 1.0)
47 | netrc (~> 0.11)
48 | public_suffix (~> 4.0)
49 | typhoeus (~> 1.0)
50 | cocoapods-deintegrate (1.0.5)
51 | cocoapods-downloader (2.1)
52 | cocoapods-plugins (1.0.0)
53 | nap
54 | cocoapods-search (1.0.1)
55 | cocoapods-trunk (1.6.0)
56 | nap (>= 0.8, < 2.0)
57 | netrc (~> 0.11)
58 | cocoapods-try (1.2.0)
59 | colored2 (3.1.2)
60 | concurrent-ruby (1.2.3)
61 | escape (0.0.4)
62 | ethon (0.16.0)
63 | ffi (>= 1.15.0)
64 | ffi (1.16.3)
65 | fourflusher (2.3.1)
66 | fuzzy_match (2.0.4)
67 | gh_inspector (1.1.3)
68 | httpclient (2.8.3)
69 | i18n (1.14.1)
70 | concurrent-ruby (~> 1.0)
71 | json (2.7.1)
72 | minitest (5.22.2)
73 | molinillo (0.8.0)
74 | nanaimo (0.3.0)
75 | nap (1.1.0)
76 | netrc (0.11.0)
77 | nkf (0.2.0)
78 | public_suffix (4.0.7)
79 | rexml (3.2.6)
80 | ruby-macho (2.5.1)
81 | typhoeus (1.4.1)
82 | ethon (>= 0.9.0)
83 | tzinfo (2.0.6)
84 | concurrent-ruby (~> 1.0)
85 | xcodeproj (1.24.0)
86 | CFPropertyList (>= 2.3.3, < 4.0)
87 | atomos (~> 0.1.3)
88 | claide (>= 1.0.2, < 2.0)
89 | colored2 (~> 3.1)
90 | nanaimo (~> 0.3.0)
91 | rexml (~> 3.2.4)
92 | zeitwerk (2.6.13)
93 |
94 | PLATFORMS
95 | ruby
96 |
97 | DEPENDENCIES
98 | activesupport (>= 6.1.7.5, < 7.1.0)
99 | cocoapods (>= 1.13, < 1.15)
100 |
101 | RUBY VERSION
102 | ruby 2.6.10p210
103 |
104 | BUNDLED WITH
105 | 2.3.23
106 |
--------------------------------------------------------------------------------
/__tests__/mapping.test.ts:
--------------------------------------------------------------------------------
1 | import { rh, rs, rw } from '../src';
2 | import { recursiveMapping } from '../src/layout/createRStyle/mapping/recursiveMapping';
3 |
4 | describe('recursive mapping tests', () => {
5 | it("should returns input value if it isn't an object or array", () => {
6 | expect(recursiveMapping(undefined)).toEqual(undefined);
7 | expect(recursiveMapping(null)).toEqual(null);
8 | expect(recursiveMapping(123)).toEqual(123);
9 | expect(recursiveMapping(true)).toEqual(true);
10 | expect(recursiveMapping('style')).toEqual('style');
11 | });
12 |
13 | it('should map empty object and nested objects correctly', () => {
14 | expect(recursiveMapping({})).toEqual({});
15 | expect(
16 | recursiveMapping({
17 | container: {},
18 | text: {},
19 | box: {
20 | transoform: [],
21 | },
22 | })
23 | ).toEqual({
24 | container: {},
25 | text: {},
26 | box: {
27 | transoform: [],
28 | },
29 | });
30 | });
31 |
32 | it('should map an object correctly', () => {
33 | const input = {
34 | container: {
35 | flex: 1,
36 | padding: '20rs',
37 | },
38 | box: {
39 | width: '10rw',
40 | height: '10rh',
41 | },
42 | };
43 | const expectedResult = {
44 | container: {
45 | flex: 1,
46 | padding: rs(20),
47 | },
48 | box: {
49 | width: rw(10),
50 | height: rh(10),
51 | },
52 | };
53 | expect(recursiveMapping(input)).toEqual(expectedResult);
54 | });
55 |
56 | it('should map an array correctly', () => {
57 | const input = [{ box: { width: '10rs' } }, { box2: { width: '12.5rs' } }];
58 | const expectedResult = [
59 | { box: { width: rs(10) } },
60 | { box2: { width: rs(12.5) } },
61 | ];
62 | expect(recursiveMapping(input)).toEqual(expectedResult);
63 | });
64 |
65 | it('should map deep nested arrays and objects correctly', () => {
66 | const input = {
67 | box: {
68 | nestedArray: [
69 | {
70 | width: '10rs',
71 | },
72 | ],
73 | nestedBox: {
74 | nestedArray: [
75 | {
76 | height: '10rw',
77 | },
78 | ],
79 | },
80 | },
81 | box2: {
82 | nestedBox: {
83 | nestedBox2: {
84 | padding: '12.5rh',
85 | },
86 | },
87 | },
88 | };
89 | const expectedResult = {
90 | box: {
91 | nestedArray: [
92 | {
93 | width: rs(10),
94 | },
95 | ],
96 | nestedBox: {
97 | nestedArray: [
98 | {
99 | height: rw(10),
100 | },
101 | ],
102 | },
103 | },
104 | box2: {
105 | nestedBox: {
106 | nestedBox2: {
107 | padding: rh(12.5),
108 | },
109 | },
110 | },
111 | };
112 | expect(recursiveMapping(input)).toEqual(expectedResult);
113 | });
114 | });
115 |
--------------------------------------------------------------------------------
/tv-example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/macos-example/macos/macosexample.xcodeproj/xcshareddata/xcschemes/macosexample-macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/tv-example/README.md:
--------------------------------------------------------------------------------
1 | This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
2 |
3 | # Getting Started
4 |
5 | > **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
6 |
7 | ## Step 1: Start the Metro Server
8 |
9 | First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
10 |
11 | To start Metro, run the following command from the _root_ of your React Native project:
12 |
13 | ```bash
14 | # using npm
15 | npm start
16 |
17 | # OR using Yarn
18 | yarn start
19 | ```
20 |
21 | ## Step 2: Start your Application
22 |
23 | Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
24 |
25 | ### For Android
26 |
27 | ```bash
28 | # using npm
29 | npm run android
30 |
31 | # OR using Yarn
32 | yarn android
33 | ```
34 |
35 | ### For iOS
36 |
37 | ```bash
38 | # using npm
39 | npm run ios
40 |
41 | # OR using Yarn
42 | yarn ios
43 | ```
44 |
45 | If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
46 |
47 | This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
48 |
49 | ## Step 3: Modifying your App
50 |
51 | Now that you have successfully run the app, let's modify it.
52 |
53 | 1. Open `App.tsx` in your text editor of choice and edit some lines.
54 | 2. For **Android**: Press the R key twice or select **"Reload"** from the **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd ⌘ + M (on macOS)) to see your changes!
55 |
56 | For **iOS**: Hit Cmd ⌘ + R in your iOS Simulator to reload the app and see your changes!
57 |
58 | ## Congratulations! :tada:
59 |
60 | You've successfully run and modified your React Native App. :partying_face:
61 |
62 | ### Now what?
63 |
64 | - If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
65 | - If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
66 |
67 | # Troubleshooting
68 |
69 | If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
70 |
71 | # Learn More
72 |
73 | To learn more about React Native, take a look at the following resources:
74 |
75 | - [React Native Website](https://reactnative.dev) - learn more about React Native.
76 | - [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
77 | - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
78 | - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
79 | - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
80 |
--------------------------------------------------------------------------------
/tv-example/ios/tvexample.xcodeproj/xcshareddata/xcschemes/tvexample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/tv-example/ios/tvexample.xcodeproj/xcshareddata/xcschemes/tvexample-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
--------------------------------------------------------------------------------
/tv-example/ios/tvexample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are always welcome, no matter how large or small!
4 |
5 | We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. Before contributing, please read the [code of conduct](./CODE_OF_CONDUCT.md).
6 |
7 | ## Development workflow
8 |
9 | To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
10 |
11 | ```sh
12 | yarn
13 | ```
14 |
15 | > While it's possible to use [`npm`](https://github.com/npm/cli), the tooling is built around [`yarn`](https://classic.yarnpkg.com/), so you'll have an easier time if you use `yarn` for development.
16 |
17 | While developing, you can run the [example app](/example/) to test your changes. Any changes you make in your library's JavaScript code will be reflected in the example app without a rebuild. If you change any native code, then you'll need to rebuild the example app.
18 |
19 | To start the packager:
20 |
21 | ```sh
22 | yarn example start
23 | ```
24 |
25 | To run the example app on Android:
26 |
27 | ```sh
28 | yarn example android
29 | ```
30 |
31 | To run the example app on iOS:
32 |
33 | ```sh
34 | yarn example ios
35 | ```
36 |
37 | To run the example app on Web:
38 |
39 | ```sh
40 | yarn example web
41 | ```
42 |
43 | To run the example app on MacOS:
44 |
45 | ```sh
46 | yarn macos-example macos
47 | ```
48 |
49 | To run the example app on MacOS:
50 |
51 | ```sh
52 | yarn tv-example tvos
53 | ```
54 |
55 | Make sure your code passes TypeScript and ESLint. Run the following to verify:
56 |
57 | ```sh
58 | yarn typecheck
59 | yarn lint
60 | ```
61 |
62 | To fix formatting errors, run the following:
63 |
64 | ```sh
65 | yarn lint --fix
66 | ```
67 |
68 | Remember to add tests for your change if possible. Run the unit tests by:
69 |
70 | ```sh
71 | yarn test
72 | ```
73 |
74 | ### Commit message convention
75 |
76 | We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
77 |
78 | - `fix`: bug fixes, e.g. fix crash due to deprecated method.
79 | - `feat`: new features, e.g. add new method to the module.
80 | - `refactor`: code refactor, e.g. migrate from class components to hooks.
81 | - `docs`: changes into documentation, e.g. add usage example for the module..
82 | - `test`: adding or updating tests, e.g. add integration tests using detox.
83 | - `chore`: tooling changes, e.g. change CI config.
84 |
85 | Our pre-commit hooks verify that your commit message matches this format when committing.
86 |
87 | ### Linting and tests
88 |
89 | [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/)
90 |
91 | We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.
92 |
93 | Our pre-commit hooks verify that the linter and tests pass when committing.
94 |
95 | ### Publishing to npm
96 |
97 | We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc.
98 |
99 | To publish new versions, run the following:
100 |
101 | ```sh
102 | yarn release
103 | ```
104 |
105 | ### Scripts
106 |
107 | The `package.json` file contains various scripts for common tasks:
108 |
109 | - `yarn bootstrap`: setup project by installing all dependencies and pods.
110 | - `yarn typecheck`: type-check files with TypeScript.
111 | - `yarn lint`: lint files with ESLint.
112 | - `yarn test`: run unit tests with Jest.
113 | - `yarn example start`: start the Metro server for the example app.
114 | - `yarn example android`: run the example app on Android.
115 | - `yarn example ios`: run the example app on iOS.
116 | - `yarn macos-example macos`: run the example app on MacOS.
117 | - `yarn tv-example tvos`: run the example app on TvOS.
118 |
119 | ### Sending a pull request
120 |
121 | > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
122 |
123 | When you're sending a pull request:
124 |
125 | - Prefer small pull requests focused on one change.
126 | - Verify that linters and tests are passing.
127 | - Review the documentation to make sure it looks good.
128 | - Follow the pull request template when opening a pull request.
129 | - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.
130 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-full-responsive",
3 | "version": "2.4.5",
4 | "description": "Create a fully responsive React Native app for all supported platforms",
5 | "main": "lib/commonjs/index.js",
6 | "module": "lib/module/index.js",
7 | "types": "lib/typescript/src/index.d.ts",
8 | "react-native": "src/index.tsx",
9 | "source": "src/index",
10 | "files": [
11 | "src",
12 | "lib",
13 | "jest",
14 | "!**/__tests__",
15 | "!**/__fixtures__",
16 | "!**/__mocks__",
17 | "android",
18 | "ios",
19 | "cpp",
20 | "*.podspec",
21 | "!lib/typescript/example",
22 | "!lib/typescript/macos-example",
23 | "!lib/typescript/tv-example",
24 | "!ios/build",
25 | "!android/build",
26 | "!android/gradle",
27 | "!android/gradlew",
28 | "!android/gradlew.bat",
29 | "!android/local.properties",
30 | "!**/.*"
31 | ],
32 | "scripts": {
33 | "test": "jest",
34 | "typecheck": "tsc --noEmit",
35 | "lint": "eslint \"**/*.{js,ts,tsx}\"",
36 | "prepack": "bob build",
37 | "release": "release-it --only-version",
38 | "example": "yarn --cwd example",
39 | "macos-example": "yarn --cwd macos-example",
40 | "tv-example": "yarn --cwd tv-example",
41 | "bootstrap": "yarn example && yarn macos-example && yarn tv-example && yarn install",
42 | "prepare": "husky",
43 | "pre-commit": "lint-staged"
44 | },
45 | "keywords": [
46 | "react-native",
47 | "responsive",
48 | "responsive-ui",
49 | "responsive-font",
50 | "full-responsive",
51 | "responsive-scale",
52 | "responsive-layout",
53 | "responsive-font-size",
54 | "responsive-dimensions",
55 | "react-native-full-responsive",
56 | "react native media query",
57 | "media query",
58 | "responsive size",
59 | "responsiveness",
60 | "responsiveness react native",
61 | "useStyle",
62 | "react native useStyle"
63 | ],
64 | "repository": "https://github.com/Mhp23/react-native-full-responsive",
65 | "author": "mhp23 (https://github.com/Mhp23)",
66 | "license": "MIT",
67 | "bugs": {
68 | "url": "https://github.com/Mhp23/react-native-full-responsive/issues"
69 | },
70 | "homepage": "https://github.com/Mhp23/react-native-full-responsive#readme",
71 | "publishConfig": {
72 | "registry": "https://registry.npmjs.org/"
73 | },
74 | "devDependencies": {
75 | "@commitlint/cli": "18.4.4",
76 | "@commitlint/config-conventional": "18.4.4",
77 | "@evilmartians/lefthook": "^1.2.2",
78 | "@react-native-community/eslint-config": "^3.0.2",
79 | "@release-it/conventional-changelog": "^9.0.2",
80 | "@types/jest": "^28.1.2",
81 | "@types/react": "~17.0.21",
82 | "@types/react-native": "0.70.0",
83 | "commitlint": "^17.0.2",
84 | "del-cli": "^5.0.0",
85 | "eslint": "^8.4.1",
86 | "eslint-config-prettier": "^8.5.0",
87 | "eslint-plugin-prettier": "^4.0.0",
88 | "husky": "^9.0.10",
89 | "jest": "^28.1.1",
90 | "lint-staged": "^15.2.1",
91 | "pod-install": "^0.1.0",
92 | "prettier": "^2.0.5",
93 | "react": "18.2.0",
94 | "react-native": "0.73.4",
95 | "react-native-builder-bob": "^0.20.4",
96 | "release-it": "^17.10.0",
97 | "typescript": "^4.5.2"
98 | },
99 | "resolutions": {
100 | "@types/react": "17.0.21"
101 | },
102 | "peerDependencies": {
103 | "react": "*",
104 | "react-native": "*"
105 | },
106 | "engines": {
107 | "node": ">= 16.0.0"
108 | },
109 | "packageManager": "yarn@1.22.21",
110 | "jest": {
111 | "preset": "react-native",
112 | "modulePathIgnorePatterns": [
113 | "/example/node_modules",
114 | "/macos-example/node_modules",
115 | "/tv-example/node_modules",
116 | "/lib/"
117 | ]
118 | },
119 | "release-it": {
120 | "git": {
121 | "commitMessage": "chore: release ${version}",
122 | "tagName": "v${version}"
123 | },
124 | "npm": {
125 | "publish": true
126 | },
127 | "github": {
128 | "release": true
129 | },
130 | "plugins": {
131 | "@release-it/conventional-changelog": {
132 | "preset": {
133 | "name": "angular"
134 | }
135 | }
136 | }
137 | },
138 | "eslintConfig": {
139 | "root": true,
140 | "extends": [
141 | "@react-native-community",
142 | "prettier"
143 | ],
144 | "rules": {
145 | "prettier/prettier": [
146 | "error",
147 | {
148 | "quoteProps": "consistent",
149 | "singleQuote": true,
150 | "tabWidth": 2,
151 | "trailingComma": "es5",
152 | "useTabs": false
153 | }
154 | ]
155 | }
156 | },
157 | "eslintIgnore": [
158 | "node_modules/",
159 | "lib/"
160 | ],
161 | "prettier": {
162 | "quoteProps": "consistent",
163 | "singleQuote": true,
164 | "tabWidth": 2,
165 | "trailingComma": "es5",
166 | "useTabs": false
167 | },
168 | "react-native-builder-bob": {
169 | "source": "src",
170 | "output": "lib",
171 | "targets": [
172 | "commonjs",
173 | "module",
174 | "typescript"
175 | ]
176 | },
177 | "dependencies": {}
178 | }
179 |
--------------------------------------------------------------------------------
/__tests__/parseValue.test.ts:
--------------------------------------------------------------------------------
1 | import { DefaultBases, rh, rs, rw } from '../src';
2 | import { parseValue } from '../src/layout/createRStyle/parseValue';
3 |
4 | const mockedDimensions = {
5 | width: 1024,
6 | height: 720,
7 | };
8 |
9 | describe('parse value tests', () => {
10 | it('should not parse undefined and number values', () => {
11 | expect(parseValue(undefined)).toEqual(undefined);
12 | expect(parseValue(10)).toEqual(10);
13 | });
14 | it('should parse responsive scale correctly', () => {
15 | expect(parseValue('10rs')).toEqual(rs(10));
16 | });
17 | it('should parse responsive width correctly', () => {
18 | expect(parseValue('10rw')).toEqual(rw(10));
19 | });
20 | it('should parse responsive height correctly', () => {
21 | expect(parseValue('10rh')).toEqual(rh(10));
22 | });
23 | it('should parse responsive scale with undefined in the pattern correctly', () => {
24 | expect(parseValue(`${undefined}rs`)).toBe(undefined);
25 | });
26 | it('should parse responsive width with undefined in the pattern correctly', () => {
27 | expect(parseValue(`${undefined}rw`)).toBe(undefined);
28 | });
29 | it('should parse responsive height with undefined in the pattern correctly', () => {
30 | expect(parseValue(`${undefined}rh`)).toBe(undefined);
31 | });
32 | it('should parse values are float or have sign correctly', () => {
33 | expect(parseValue('+10rs')).toEqual(rs(10));
34 | expect(parseValue('-10rs')).toEqual(rs(-10));
35 |
36 | expect(parseValue('+10rw')).toEqual(rw(10));
37 | expect(parseValue('-10rw')).toEqual(rw(-10));
38 |
39 | expect(parseValue('+10rh')).toEqual(rh(10));
40 | expect(parseValue('-10rh')).toEqual(rh(-10));
41 |
42 | expect(parseValue('.5rs')).toEqual(rs(0.5));
43 | expect(parseValue('-0.5rs')).toEqual(rs(-0.5));
44 |
45 | expect(parseValue('+12.51221rs')).toEqual(rs(12.51221));
46 | expect(parseValue('-12.51221rs')).toEqual(rs(-12.51221));
47 |
48 | expect(parseValue('+12.51221rw')).toEqual(rw(12.51221));
49 | expect(parseValue('-12.51221rw')).toEqual(rw(-12.51221));
50 |
51 | expect(parseValue('+12.51221rh')).toEqual(rh(12.51221));
52 | expect(parseValue('-12.51221rh')).toEqual(rh(-12.51221));
53 | });
54 | it('should parse responsive scale float value correctly', () => {
55 | expect(parseValue('12.51221rs')).toEqual(rs(12.51221));
56 | });
57 | it('should parse responsive width float value correctly', () => {
58 | expect(parseValue('12.5rw')).toEqual(rw(12.5));
59 | });
60 | it('should parse responsive height float value correctly', () => {
61 | expect(parseValue('12.5rh')).toEqual(rh(12.5));
62 | });
63 | it('should not parse wrong responsive scale patterns', () => {
64 | expect(parseValue('10 rs')).toEqual('10 rs');
65 | expect(parseValue('10@rs')).toEqual('10@rs');
66 | expect(parseValue('rs@10')).toEqual('rs@10');
67 | expect(parseValue('10r')).toEqual('10r');
68 | expect(parseValue('10rss')).toEqual('10rss');
69 | });
70 | it('should not parse wrong responsive width patterns', () => {
71 | expect(parseValue('10 rw')).toEqual('10 rw');
72 | expect(parseValue('10@rw')).toEqual('10@rw');
73 | expect(parseValue('rw@10')).toEqual('rw@10');
74 | expect(parseValue('10r')).toEqual('10r');
75 | expect(parseValue('10rww')).toEqual('10rww');
76 | });
77 | it('should not parse wrong responsive height patterns', () => {
78 | expect(parseValue('10 rh')).toEqual('10 rh');
79 | expect(parseValue('10@rh')).toEqual('10@rh');
80 | expect(parseValue('rh@10')).toEqual('rh@10');
81 | expect(parseValue('10r')).toEqual('10r');
82 | expect(parseValue('10rhh')).toEqual('10rhh');
83 | });
84 | it('should parse responsive scale with custom dimensions', () => {
85 | const { width, height } = mockedDimensions;
86 | expect(parseValue('10rs', { width, height })).toEqual(
87 | rs(10, width, height)
88 | );
89 | });
90 | it('should parse responsive width with custom width', () => {
91 | const { width } = mockedDimensions;
92 | expect(parseValue('10rw', { width })).toEqual(rw(10, width));
93 | });
94 | it('should parse responsive height with custom height', () => {
95 | const { height } = mockedDimensions;
96 | expect(parseValue('10rh', { height })).toEqual(rh(10, height));
97 | });
98 | it('should parse responsive scale with custom config', () => {
99 | const { width, height } = mockedDimensions;
100 | expect(
101 | parseValue('10rs', {
102 | width,
103 | height,
104 | scaleConfig: {
105 | type: 'md',
106 | bases: DefaultBases,
107 | },
108 | })
109 | ).toEqual(rs(10, width, height, { type: 'md', bases: DefaultBases }));
110 | expect(
111 | parseValue('10rs', {
112 | width,
113 | height,
114 | scaleConfig: {
115 | type: 'lg',
116 | },
117 | })
118 | ).toEqual(rs(10, width, height, { type: 'lg' }));
119 | expect(
120 | parseValue('10rs', {
121 | width,
122 | height,
123 | scaleConfig: {
124 | bases: {
125 | ...DefaultBases,
126 | sm: 240,
127 | },
128 | },
129 | })
130 | ).toEqual(
131 | rs(10, width, height, {
132 | bases: {
133 | ...DefaultBases,
134 | sm: 240,
135 | },
136 | })
137 | );
138 | });
139 | });
140 |
--------------------------------------------------------------------------------
/tv-example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 | apply plugin: "org.jetbrains.kotlin.android"
3 | apply plugin: "com.facebook.react"
4 |
5 | /**
6 | * This is the configuration block to customize your React Native Android app.
7 | * By default you don't need to apply any configuration, just uncomment the lines you need.
8 | */
9 | react {
10 | /* Folders */
11 | // The root of your project, i.e. where "package.json" lives. Default is '..'
12 | // root = file("../")
13 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native
14 | // reactNativeDir = file("../node_modules/react-native")
15 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
16 | // codegenDir = file("../node_modules/@react-native/codegen")
17 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
18 | // cliFile = file("../node_modules/react-native/cli.js")
19 |
20 | /* Variants */
21 | // The list of variants to that are debuggable. For those we're going to
22 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
23 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
24 | // debuggableVariants = ["liteDebug", "prodDebug"]
25 |
26 | /* Bundling */
27 | // A list containing the node command and its flags. Default is just 'node'.
28 | // nodeExecutableAndArgs = ["node"]
29 | //
30 | // The command to run when bundling. By default is 'bundle'
31 | // bundleCommand = "ram-bundle"
32 | //
33 | // The path to the CLI configuration file. Default is empty.
34 | // bundleConfig = file(../rn-cli.config.js)
35 | //
36 | // The name of the generated asset file containing your JS bundle
37 | // bundleAssetName = "MyApplication.android.bundle"
38 | //
39 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
40 | // entryFile = file("../js/MyApplication.android.js")
41 | //
42 | // A list of extra flags to pass to the 'bundle' commands.
43 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
44 | // extraPackagerArgs = []
45 |
46 | /* Hermes Commands */
47 | // The hermes compiler command to run. By default it is 'hermesc'
48 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
49 | //
50 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
51 | // hermesFlags = ["-O", "-output-source-map"]
52 | }
53 |
54 | /**
55 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
56 | */
57 | def enableProguardInReleaseBuilds = false
58 |
59 | /**
60 | * The preferred build flavor of JavaScriptCore (JSC)
61 | *
62 | * For example, to use the international variant, you can use:
63 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
64 | *
65 | * The international variant includes ICU i18n library and necessary data
66 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
67 | * give correct results when using with locales other than en-US. Note that
68 | * this variant is about 6MiB larger per architecture than default.
69 | */
70 | def jscFlavor = 'org.webkit:android-jsc:+'
71 |
72 | android {
73 | ndkVersion rootProject.ext.ndkVersion
74 | buildToolsVersion rootProject.ext.buildToolsVersion
75 | compileSdk rootProject.ext.compileSdkVersion
76 |
77 | namespace "com.tvexample"
78 | defaultConfig {
79 | applicationId "com.tvexample"
80 | minSdkVersion rootProject.ext.minSdkVersion
81 | targetSdkVersion rootProject.ext.targetSdkVersion
82 | versionCode 1
83 | versionName "1.0"
84 | }
85 | signingConfigs {
86 | debug {
87 | storeFile file('debug.keystore')
88 | storePassword 'android'
89 | keyAlias 'androiddebugkey'
90 | keyPassword 'android'
91 | }
92 | }
93 | buildTypes {
94 | debug {
95 | signingConfig signingConfigs.debug
96 | }
97 | release {
98 | // Caution! In production, you need to generate your own keystore file.
99 | // see https://reactnative.dev/docs/signed-apk-android.
100 | signingConfig signingConfigs.debug
101 | minifyEnabled enableProguardInReleaseBuilds
102 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
103 | }
104 | }
105 | }
106 |
107 | dependencies {
108 | // The version of react-native is set by the React Native Gradle Plugin
109 | // For the TV repo,
110 | // we use the io.github.react-native-tvos group for the react-android and hermes-android dependencies
111 |
112 | implementation("io.github.react-native-tvos:react-android")
113 | // No Flipper for TV
114 | // implementation("com.facebook.react:flipper-integration")
115 |
116 | if (hermesEnabled.toBoolean()) {
117 | implementation("io.github.react-native-tvos:hermes-android")
118 | } else {
119 | implementation jscFlavor
120 | }
121 | }
122 |
123 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
124 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributor Covenant Code of Conduct
3 |
4 | ## Our Pledge
5 |
6 | We as members, contributors, and leaders pledge to make participation in our
7 | community a harassment-free experience for everyone, regardless of age, body
8 | size, visible or invisible disability, ethnicity, sex characteristics, gender
9 | identity and expression, level of experience, education, socio-economic status,
10 | nationality, personal appearance, race, caste, color, religion, or sexual
11 | identity and orientation.
12 |
13 | We pledge to act and interact in ways that contribute to an open, welcoming,
14 | diverse, inclusive, and healthy community.
15 |
16 | ## Our Standards
17 |
18 | Examples of behavior that contributes to a positive environment for our
19 | community include:
20 |
21 | * Demonstrating empathy and kindness toward other people
22 | * Being respectful of differing opinions, viewpoints, and experiences
23 | * Giving and gracefully accepting constructive feedback
24 | * Accepting responsibility and apologizing to those affected by our mistakes,
25 | and learning from the experience
26 | * Focusing on what is best not just for us as individuals, but for the overall
27 | community
28 |
29 | Examples of unacceptable behavior include:
30 |
31 | * The use of sexualized language or imagery, and sexual attention or advances of
32 | any kind
33 | * Trolling, insulting or derogatory comments, and personal or political attacks
34 | * Public or private harassment
35 | * Publishing others' private information, such as a physical or email address,
36 | without their explicit permission
37 | * Other conduct which could reasonably be considered inappropriate in a
38 | professional setting
39 |
40 | ## Enforcement Responsibilities
41 |
42 | Community leaders are responsible for clarifying and enforcing our standards of
43 | acceptable behavior and will take appropriate and fair corrective action in
44 | response to any behavior that they deem inappropriate, threatening, offensive,
45 | or harmful.
46 |
47 | Community leaders have the right and responsibility to remove, edit, or reject
48 | comments, commits, code, wiki edits, issues, and other contributions that are
49 | not aligned to this Code of Conduct, and will communicate reasons for moderation
50 | decisions when appropriate.
51 |
52 | ## Scope
53 |
54 | This Code of Conduct applies within all community spaces, and also applies when
55 | an individual is officially representing the community in public spaces.
56 | Examples of representing our community include using an official e-mail address,
57 | posting via an official social media account, or acting as an appointed
58 | representative at an online or offline event.
59 |
60 | ## Enforcement
61 |
62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
63 | reported to the community leaders responsible for enforcement at
64 | [INSERT CONTACT METHOD].
65 | All complaints will be reviewed and investigated promptly and fairly.
66 |
67 | All community leaders are obligated to respect the privacy and security of the
68 | reporter of any incident.
69 |
70 | ## Enforcement Guidelines
71 |
72 | Community leaders will follow these Community Impact Guidelines in determining
73 | the consequences for any action they deem in violation of this Code of Conduct:
74 |
75 | ### 1. Correction
76 |
77 | **Community Impact**: Use of inappropriate language or other behavior deemed
78 | unprofessional or unwelcome in the community.
79 |
80 | **Consequence**: A private, written warning from community leaders, providing
81 | clarity around the nature of the violation and an explanation of why the
82 | behavior was inappropriate. A public apology may be requested.
83 |
84 | ### 2. Warning
85 |
86 | **Community Impact**: A violation through a single incident or series of
87 | actions.
88 |
89 | **Consequence**: A warning with consequences for continued behavior. No
90 | interaction with the people involved, including unsolicited interaction with
91 | those enforcing the Code of Conduct, for a specified period of time. This
92 | includes avoiding interactions in community spaces as well as external channels
93 | like social media. Violating these terms may lead to a temporary or permanent
94 | ban.
95 |
96 | ### 3. Temporary Ban
97 |
98 | **Community Impact**: A serious violation of community standards, including
99 | sustained inappropriate behavior.
100 |
101 | **Consequence**: A temporary ban from any sort of interaction or public
102 | communication with the community for a specified period of time. No public or
103 | private interaction with the people involved, including unsolicited interaction
104 | with those enforcing the Code of Conduct, is allowed during this period.
105 | Violating these terms may lead to a permanent ban.
106 |
107 | ### 4. Permanent Ban
108 |
109 | **Community Impact**: Demonstrating a pattern of violation of community
110 | standards, including sustained inappropriate behavior, harassment of an
111 | individual, or aggression toward or disparagement of classes of individuals.
112 |
113 | **Consequence**: A permanent ban from any sort of public interaction within the
114 | community.
115 |
116 | ## Attribution
117 |
118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119 | version 2.1, available at
120 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
121 |
122 | Community Impact Guidelines were inspired by
123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124 |
125 | For answers to common questions about this code of conduct, see the FAQ at
126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
127 | [https://www.contributor-covenant.org/translations][translations].
128 |
129 | [homepage]: https://www.contributor-covenant.org
130 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
131 | [Mozilla CoC]: https://github.com/mozilla/diversity
132 | [FAQ]: https://www.contributor-covenant.org/faq
133 | [translations]: https://www.contributor-covenant.org/translations
134 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Create a fully responsive React Native app for all supported platforms
9 |
10 |
11 |
14 |
15 | ## 📢 Introduction
16 |
17 | This package makes it super easy to create apps responsive that work perfectly on all different screen sizes in React Native (like font size, width, height, and more), making sure everything looks great on any device, from extra small to extra large. You can also tweak how things scale and adjust settings to make everything just the way you want it.
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | |
26 |
27 |
28 |
29 |
30 | |
31 |
32 |
33 |
34 |
35 | |
36 |
37 |
38 |
39 |
40 | |
41 |
42 |
43 | | iPhone 15 Pro Max |
44 | iPhone SE (3rd gen) |
45 | iPad Pro (12.9-inch) |
46 | Web |
47 |
48 |
49 |
50 | ## 💫 Features
51 |
52 | - Easy to use: Effortlessly implement size scaling and responsive design.
53 | - Cross-platform: Works seamlessly across multiple platforms and devices.
54 | - [createRStyle](./USAGE.md#createrstyle) method and [useRStyle](./USAGE.md#userstyle) hook as alternatives to using `StyleSheet.create` for create stylesheets.
55 | - Various responsive hooks provided: Use these hooks based on your specific use cases.
56 | - Customizable scaling: Define base widths for specific dimension types `(xs, sm, ... 2xl)` for precise control.
57 | - Responsive percentage-based sizing: Adjust sizing based on width or height by `PixelRatio`.
58 | - Media query hook: Detect dimension types by using the [useMediaQuery](./USAGE.md#usemediaquery-usemq) hook. You can also override default thresholds as needed. This hook can be used in the provider to automatically detect and respond based on the configurations.
59 | - Various responsive Higher-Order Components (HOCs) provided: Utilize these methods in your class components.
60 | - Written in TypeScript and fully typed.
61 |
62 | ## 📀 Installation
63 |
64 | **Supported for React Native >= 0.60**
65 |
66 | ```sh
67 | yarn add react-native-full-responsive
68 |
69 | //or
70 |
71 | npm install react-native-full-responsive --save
72 | ```
73 |
74 | ## 🚀 Quick Start
75 |
76 | **_Starting from v2, you can easily create your styles using the `createRStyle` or `useRStyle` hooks_**
77 |
78 | Use [createRStyle](./USAGE.md#createrstyle) in a similar way to when you use `StyleSheet.create`:
79 |
80 | ```tsx
81 | import * as React from 'react';
82 | import { View, Text } from 'react-native';
83 | import { createRStyle } from 'react-native-full-responsive';
84 |
85 | const SIZE = 20;
86 |
87 | export default function App() {
88 | return (
89 |
90 |
91 | My awesome responsive text!
92 |
93 |
94 | );
95 | }
96 |
97 | const styles = createRStyle({
98 | container: {
99 | flex: 1,
100 | alignItems: 'center',
101 | justifyContent: 'center',
102 | },
103 | box: {
104 | height: `${SIZE * 3}rs`,
105 | justifyContent: 'center',
106 | backgroundColor: 'yellow',
107 | marginVertical: `${SIZE}rs`,
108 | paddingHorizontal: `${SIZE / 2}rs`,
109 | },
110 | textBold: {
111 | fontWeight: 'bold',
112 | fontSize: `${SIZE}rs`,
113 | },
114 | });
115 | ```
116 |
117 | Alternatively, use [useRStyle](./USAGE.md#userstyle) to create dynamic styles that change when dimensions, bases, or types are modified:
118 |
119 | ```tsx
120 | import * as React from 'react';
121 | import { View, Text } from 'react-native';
122 | import { FRProvider, useRStyle } from 'react-native-full-responsive';
123 |
124 | const SIZE = 20;
125 |
126 | const ResponsiveBox: React.FC = () => {
127 | const styles = useRStyle({
128 | container: {
129 | flex: 1,
130 | alignItems: 'center',
131 | justifyContent: 'center',
132 | },
133 | box: {
134 | height: `${SIZE * 3}rs`,
135 | justifyContent: 'center',
136 | backgroundColor: 'yellow',
137 | marginVertical: `${SIZE}rs`,
138 | paddingHorizontal: `${SIZE / 2}rs`,
139 | },
140 | textBold: {
141 | fontWeight: 'bold',
142 | fontSize: `${SIZE}rs`,
143 | },
144 | });
145 |
146 | return (
147 |
148 |
149 | My awesome responsive text!
150 |
151 |
152 | );
153 | };
154 |
155 | export default function App() {
156 | return (
157 |
158 |
159 |
160 | );
161 | }
162 | ```
163 |
164 | Alternatively, make use of the responsive methods and hooks that are available from v1:
165 |
166 | ```tsx
167 | import * as React from 'react';
168 | import { Text } from 'react-native';
169 | import { useRM, FRProvider } from 'react-native-full-responsive';
170 | //...
171 |
172 | const MyComponent = () => {
173 | const { rs } = useRM();
174 |
175 | const scaledValue = rs(20);
176 |
177 | return (
178 | My awesome responsive text!
179 | );
180 | };
181 |
182 | export default function App() {
183 | return (
184 |
185 |
186 |
187 | );
188 | }
189 | ```
190 |
191 | To become more familiar with how to use methods within your function or class components, check out the provided [examples](./example/src/).
192 |
193 | Also, if you're looking to become more familiar with how to use the package as a universal responsive utility, check out [Todo App](https://github.com/Mhp23/todo-app-client) project for a practical example
194 |
195 | ## 📚 Documentation
196 |
197 | Explore the [usage documentation](./USAGE.md) to discover how to leverage the methods, hooks, and other features.
198 |
199 | ## 🤝 Contribution
200 |
201 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
202 |
203 | ## 🧪 Test
204 |
205 | To mock the package's methods and components using the default mock configuration provided, follow these steps:
206 |
207 | - Create a file named `react-native-full-responsive.ts` inside your `__mocks__` directory.
208 |
209 | - Copy the following code into that file:
210 |
211 | ```ts
212 | export * from 'react-native-full-responsive/jest';
213 | ```
214 |
215 | ## 🛡️ License
216 |
217 | MIT
218 |
--------------------------------------------------------------------------------
/tv-example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
88 |
89 | # Use the maximum available, or set MAX_FD != -1 to use that value.
90 | MAX_FD=maximum
91 |
92 | warn () {
93 | echo "$*"
94 | } >&2
95 |
96 | die () {
97 | echo
98 | echo "$*"
99 | echo
100 | exit 1
101 | } >&2
102 |
103 | # OS specific support (must be 'true' or 'false').
104 | cygwin=false
105 | msys=false
106 | darwin=false
107 | nonstop=false
108 | case "$( uname )" in #(
109 | CYGWIN* ) cygwin=true ;; #(
110 | Darwin* ) darwin=true ;; #(
111 | MSYS* | MINGW* ) msys=true ;; #(
112 | NONSTOP* ) nonstop=true ;;
113 | esac
114 |
115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
116 |
117 |
118 | # Determine the Java command to use to start the JVM.
119 | if [ -n "$JAVA_HOME" ] ; then
120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
121 | # IBM's JDK on AIX uses strange locations for the executables
122 | JAVACMD=$JAVA_HOME/jre/sh/java
123 | else
124 | JAVACMD=$JAVA_HOME/bin/java
125 | fi
126 | if [ ! -x "$JAVACMD" ] ; then
127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
128 |
129 | Please set the JAVA_HOME variable in your environment to match the
130 | location of your Java installation."
131 | fi
132 | else
133 | JAVACMD=java
134 | if ! command -v java >/dev/null 2>&1
135 | then
136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 | fi
142 |
143 | # Increase the maximum file descriptors if we can.
144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
145 | case $MAX_FD in #(
146 | max*)
147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
148 | # shellcheck disable=SC3045
149 | MAX_FD=$( ulimit -H -n ) ||
150 | warn "Could not query maximum file descriptor limit"
151 | esac
152 | case $MAX_FD in #(
153 | '' | soft) :;; #(
154 | *)
155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
156 | # shellcheck disable=SC3045
157 | ulimit -n "$MAX_FD" ||
158 | warn "Could not set maximum file descriptor limit to $MAX_FD"
159 | esac
160 | fi
161 |
162 | # Collect all arguments for the java command, stacking in reverse order:
163 | # * args from the command line
164 | # * the main class name
165 | # * -classpath
166 | # * -D...appname settings
167 | # * --module-path (only if needed)
168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
169 |
170 | # For Cygwin or MSYS, switch paths to Windows format before running java
171 | if "$cygwin" || "$msys" ; then
172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
174 |
175 | JAVACMD=$( cygpath --unix "$JAVACMD" )
176 |
177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
178 | for arg do
179 | if
180 | case $arg in #(
181 | -*) false ;; # don't mess with options #(
182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
183 | [ -e "$t" ] ;; #(
184 | *) false ;;
185 | esac
186 | then
187 | arg=$( cygpath --path --ignore --mixed "$arg" )
188 | fi
189 | # Roll the args list around exactly as many times as the number of
190 | # args, so each arg winds up back in the position where it started, but
191 | # possibly modified.
192 | #
193 | # NB: a `for` loop captures its iteration list before it begins, so
194 | # changing the positional parameters here affects neither the number of
195 | # iterations, nor the values presented in `arg`.
196 | shift # remove old arg
197 | set -- "$@" "$arg" # push replacement arg
198 | done
199 | fi
200 |
201 |
202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
204 |
205 | # Collect all arguments for the java command;
206 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
207 | # shell script including quotes and variable substitutions, so put them in
208 | # double quotes to make sure that they get re-expanded; and
209 | # * put everything else in single quotes, so that it's not re-expanded.
210 |
211 | set -- \
212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
213 | -classpath "$CLASSPATH" \
214 | org.gradle.wrapper.GradleWrapperMain \
215 | "$@"
216 |
217 | # Stop when "xargs" is not available.
218 | if ! command -v xargs >/dev/null 2>&1
219 | then
220 | die "xargs is not available"
221 | fi
222 |
223 | # Use "xargs" to parse quoted args.
224 | #
225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
226 | #
227 | # In Bash we could simply go:
228 | #
229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
230 | # set -- "${ARGS[@]}" "$@"
231 | #
232 | # but POSIX shell has neither arrays nor command substitution, so instead we
233 | # post-process each arg (as a line of input to sed) to backslash-escape any
234 | # character that might be a shell metacharacter, then use eval to reverse
235 | # that process (while maintaining the separation between arguments), and wrap
236 | # the whole thing up as a single "set" statement.
237 | #
238 | # This will of course break if any of these variables contains a newline or
239 | # an unmatched quote.
240 | #
241 |
242 | eval "set -- $(
243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
244 | xargs -n1 |
245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
246 | tr '\n' ' '
247 | )" '"$@"'
248 |
249 | exec "$JAVACMD" "$@"
250 |
--------------------------------------------------------------------------------
/USAGE.md:
--------------------------------------------------------------------------------
1 | 📚 React Native Full Responsive Usage Documentation
2 |
3 | - [Full Responsive Provider](#full-responsive-provider)
4 | - [createRStyle](#createrstyle)
5 | - [useRStyle](#userstyle)
6 | - [responsiveScale (rs)](#responsivescale-rs)
7 | - [responsiveWidth (rw)](#responsivewidth-rw)
8 | - [responsiveHeight (rh)](#responsiveheight-rh)
9 | - [useResponsiveMethods (useRM)](#useresponsivemethods-userm)
10 | - [useResponsiveScale (useRS)](#useresponsivescale-users)
11 | - [useResponsiveWidth (useRW)](#useresponsivewidth-userw)
12 | - [useResponsiveHeight (useRH)](#useresponsiveheight-userh)
13 | - [useResponsiveDim (useRD)](#useresponsivedim-userd)
14 | - [useMediaQuery (useMQ)](#usemediaquery-usemq)
15 | - [HOC](#hoc)
16 |
17 | Excpet for `createRStyle` and `useRStyle`, All methods within this package offer two usage options, a longer syntax for those who prefer explicitness, and an abbreviated version for those who prefer conciseness. Choose the approach that best suits your preferred import and usage style.
18 |
19 | ```js
20 | import {
21 | useMediaQuery,
22 | responsiveScale,
23 | responsiveWidth,
24 | responsiveHeight,
25 | useResponsiveDim,
26 | useResponsiveScale,
27 | useResponsiveWidth,
28 | useResponsiveHeight,
29 | useResponsiveMethods,
30 | //HOC
31 | withMediaQuery,
32 | withResponsiveMethods,
33 | } from 'react-native-full-responsive';
34 | //or
35 | import {
36 | rs,
37 | rw,
38 | rh,
39 | useRD,
40 | useRS,
41 | useRW,
42 | useRH,
43 | useRM,
44 | useMQ,
45 | //HOC
46 | withMQ,
47 | withRM,
48 | } from 'react-native-full-responsive';
49 | ```
50 |
51 | ## Full Responsive Provider
52 |
53 | To use the `responsiveScale` hook, first you should use `FRProvider` in the root component.
54 |
55 | ```tsx
56 | import { FRProvider } from 'react-native-full-responsive';
57 | //...
58 |
59 | export default function App() {
60 | return (
61 |
62 | {
63 | //...
64 | }
65 |
66 | );
67 | }
68 | ```
69 |
70 | The provider accepts `bases` and `type` props; explanations of each follow.
71 |
72 | type
73 |
74 | Specifies the current device dimension type that size scaling calculations will use, based on specified related bases.
75 |
76 | _Possible values_: `xs` | `sm` | `md` | `lg` | `xl` | `2xl`
77 |
78 | _Default_: `sm`
79 |
80 | _Determination_ (suggestion):
81 |
82 | - Can be based on device specification type (e.g., "sm" for smartphones, "md" for tablets).
83 | - Can be dynamically determined using the [useMediaQuery](<'#useMediaQuery-(useMQ)>) hook, based on device dimensions.
84 |
85 | bases
86 |
87 | _Description_: Specifies or overrides default experimental base sizes to achieve the ideal point for scaling for each dimension type.
88 |
89 | _Default_:
90 |
91 | ```ts
92 | {
93 | 'xs' = 320,
94 | 'sm' = 360,
95 | 'md' = 520,
96 | 'lg' = 680,
97 | 'xl' = 740,
98 | '2xl' = 920,
99 | }
100 | ```
101 |
102 | ⚠️ **_Note: While we'll explore the three main methods and their usage below, it's highly recommended to use the provided hooks (and HOCs for class components) for dynamic dimensions and a more streamlined approach._**
103 |
104 | ## createRStyle
105 |
106 | This method is similar to `StyleSheet.create` and can be used in the same way. However, the key difference is that it allows you to easily create responsive styles by utilizing the following responsive patterns (inspired by [react-native-size-matters](https://github.com/nirsky/react-native-size-matters)):
107 |
108 | `number(rs|rw|rh)`
109 |
110 | These patterns accept a number (which can be a signed or unsigned integer or a float number) and a suffix to specify responsive methods.
111 |
112 | This method accepts two arguments: the first argument is your style, and the second argument is optional. The second argument allows for more advanced and flexible usage.
113 |
114 | ```ts
115 | createRStyle(styles, config);
116 | ```
117 |
118 | The config options includes:
119 |
120 | width
121 |
122 | To use custom dimensions width for the calculation
123 |
124 | height
125 |
126 | To use custom dimensions height for the calculation
127 |
128 | scaleConfig
129 |
130 | To use a specific responsive scale method config for applying when using `rs` for style properties
131 |
132 | ```ts
133 | const styles = createRStyle({
134 | container: {
135 | flex: 1,
136 | },
137 | box: {
138 | width: '20rw',
139 | height: '10rh',
140 | marginVertical: `5rs`,
141 | justifyContent: 'center',
142 | backgroundColor: 'yellow',
143 | paddingHorizontal: `7.5rs`,
144 | },
145 | //...
146 | });
147 | ```
148 |
149 | ## useRStyle
150 |
151 | A hook is provided for [createRStyle](#createrstyle) to create a dynamic responsive scale. This hook generates a new style when there are changes in dimensions, the parsing method, type, or bases. It accepts two arguments:
152 |
153 | 1. The first argument is the style and is required (as an object or a function)
154 | 2. The second argument is the dependency list to regenerate styles after changing them, and default is an empty array
155 |
156 | An example:
157 |
158 | ```tsx
159 | import * as React from 'react';
160 | import { View, Text } from 'react-native';
161 | import { FRProvider, useRStyle } from 'react-native-full-responsive';
162 |
163 | const SIZE = 20;
164 |
165 | const ResponsiveBox: React.FC = () => {
166 | const styles = useRStyle(
167 | {
168 | container: {
169 | flex: 1,
170 | alignItems: 'center',
171 | justifyContent: 'center',
172 | },
173 | box: {
174 | height: `${SIZE * 3}rs`,
175 | justifyContent: 'center',
176 | backgroundColor: 'yellow',
177 | marginVertical: `${SIZE}rs`,
178 | paddingHorizontal: `${SIZE / 2}rs`,
179 | },
180 | textBold: {
181 | fontWeight: 'bold',
182 | fontSize: `${SIZE}rs`,
183 | },
184 | },
185 | []
186 | );
187 |
188 | return (
189 |
190 |
191 | My awesome responsive text!
192 |
193 |
194 | );
195 | };
196 |
197 | export default function App() {
198 | return (
199 |
200 |
201 |
202 | );
203 | }
204 | ```
205 |
206 | I highly recommend that if you're using `ESLint`, for better debugging and to reduce re-render mistakes due to missing dependencies in your custom hooks and specifically in the `useRStyle` hook, you use the [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks) plugin. Follow its instructions, and add useRStyle to your ESLint rules like this:
207 |
208 | ```js
209 | {
210 | //...
211 | "rules": {
212 | // ...
213 | "react-hooks/exhaustive-deps": ["warn", {
214 | "additionalHooks": "(useRStyle)"
215 | }]
216 | }
217 | }
218 | ```
219 |
220 | ## responsiveScale (rs)
221 |
222 | This function scales the passed size based on the user's device dimensions and base width size and returns the scaled value. It accepts the following arguments:
223 |
224 | 1. Required argument: The size to be scaled.
225 | 2. Optional argument (for event listeners): The screen width.
226 |
227 | 3. Optional argument (for event listeners): The screen height.
228 |
229 | 4. Optional argument (for specifying current `type` and custom `bases`)
230 |
231 | The second and third arguments are only needed when adding an event listener to respond to dimension changes (e.g., switching between portrait and landscape modes) and forth arguments to specify current `type` and custom `bases`.
232 |
233 | In function components, you can use the [useResponsiveScale](#useResponsiveScale) or [useResponsiveMethods](#useResponsiveMethods) hooks for a more streamlined approach. It only requires passing the size to be scaled, eliminating the need for additional steps or arguments.
234 |
235 | ```tsx
236 | import { rs } from 'react-native-full-responsive';
237 | //...
238 | const MyComponent = () => {
239 | //...
240 | return My Scaled Text!;
241 | };
242 | ```
243 |
244 | ## responsiveWidth (rw)
245 |
246 | This method calculates a responsive value based on a numeric percentage value, utilizing `PixelRatio` and the provided width size. Its usage is similar to [responsiveScale](#responsivescale-rs), but it differs in that it only takes two arguments:
247 |
248 | 1. Required argument: A numeric **percentage** value.
249 |
250 | 2. Optional argument: A custom screen width for width calculations.
251 |
252 | ```tsx
253 | import { rw } from 'react-native-full-responsive';
254 | //...
255 | const MyComponent = () => {
256 | //...
257 | return (
258 |
259 | {
260 | //...
261 | }
262 |
263 | );
264 | };
265 | ```
266 |
267 | ## responsiveHeight (rh)
268 |
269 | This method calculates a responsive value based on a numeric percentage value, utilizing `PixelRatio` and the provided height size. Its usage is similar to [responsiveScale](#responsivescale-rs), but it differs in that it only takes two arguments:
270 |
271 | 1. Required argument: A numeric **percentage** value.
272 |
273 | 2. Optional argument: A custom screen height for height calculations.
274 |
275 | ```tsx
276 | import { rh } from 'react-native-full-responsive';
277 | //...
278 | const MyComponent = () => {
279 | //...
280 | return (
281 |
282 | {
283 | //...
284 | }
285 |
286 | );
287 | };
288 | ```
289 |
290 | ## useResponsiveMethods (useRM)
291 |
292 | This hook provides `rs`, `rw`, and `rh` methods, which simplify usage by only requiring the needed size to be passed. It automatically detects dimension changes, including landscape/portrait mode switches and `type` updates for scaling sizes on the provider, ensuring responsiveness without manual intervention.
293 |
294 | ```tsx
295 | import { useResponsiveMethods } from 'react-native-full-responsive';
296 | //...
297 | const MyComponent = () => {
298 | const { rs, rw, rh } = useResponsiveMethods(); //or useRM
299 | //...
300 | return My Scaled Text!;
301 | };
302 | ```
303 |
304 | ## useResponsiveScale (useRS)
305 |
306 | A hook is provided for [responsiveScale](#responsivescale-rs), which only requires passing a size for scaling.
307 |
308 | ```tsx
309 | import { useResponsiveScale } from 'react-native-full-responsive';
310 | //...
311 | const MyComponent = () => {
312 | const fontSize = useResponsiveScale(16);
313 | //...
314 | return My Scaled Text!;
315 | };
316 | ```
317 |
318 | ## useResponsiveWidth (useRW)
319 |
320 | A hook is provided for [responsiveWidth](#responsivewidth-rw), which only requires passing a percentage size.
321 |
322 | ```tsx
323 | import { useResponsiveWidth } from 'react-native-full-responsive';
324 | //...
325 | const MyComponent = () => {
326 | const width = useResponsiveWidth(5);
327 | //...
328 | return (
329 |
330 | {
331 | //...
332 | }
333 |
334 | );
335 | };
336 | ```
337 |
338 | ## useResponsiveHeight (useRH)
339 |
340 | A hook is provided for [responsiveHeight](#responsivewheight-rh), which only requires passing a percentage size.
341 |
342 | ```tsx
343 | import { useResponsiveHeight } from 'react-native-full-responsive';
344 | //...
345 | const MyComponent = () => {
346 | const height = useResponsiveHeight(10);
347 | //...
348 | return (
349 |
350 | {
351 | //...
352 | }
353 |
354 | );
355 | };
356 | ```
357 |
358 | ## useResponsiveDim (useRD)
359 |
360 | A hook is provided responsive width and height together and could to use it like below:
361 |
362 | ```tsx
363 | import { useResponsiveDim } from 'react-native-full-responsive';
364 | //...
365 | const MyComponent = () => {
366 | const { width, height } = useResponsiveDim(10);
367 | //...
368 | return (
369 |
370 | {
371 | //...
372 | }
373 |
374 | );
375 | };
376 | ```
377 |
378 | ## useMediaQuery (useMQ)
379 |
380 | A hook is provided to retrieve the `type` of dimension size (`xs` | `sm` | `md` | `lg` | `xl` | `2xl`) based on specified thresholds. These thresholds can be overridden either entirely or selectively for specific dimensions. This hook offers benefits for use within the provider or when actions need to be performed based on type specifications.
381 |
382 | _Default_:
383 |
384 | ```ts
385 | {
386 | 'xs': 320,
387 | 'sm': 576,
388 | 'md': 768,
389 | 'lg': 992,
390 | 'xl': 1200,
391 | '2xl': 1440,
392 | }
393 | ```
394 |
395 | ```tsx
396 | import { FRProvider, useMediaQuery } from 'react-native-full-responsive';
397 | //...
398 |
399 | const customThresholds = {
400 | //...
401 | };
402 |
403 | export default function App() {
404 | const type = useMediaQuery(customThresholds);
405 |
406 | return (
407 |
408 | {
409 | //...
410 | }
411 |
412 | );
413 | }
414 | ```
415 |
416 | ## HOC
417 |
418 | If you use class components, it's all under control! You can access `rs`, `rw`, and `rh` functions using the `withResponsiveMethods` (or withRM) HOC. For media query, use the `withMediaQuery` (or withMQ) HOC. For detailed guidance on employing these HOCs within your class components, kindly refer to [the class app examples](./example/src/ClassApp/).
419 |
--------------------------------------------------------------------------------