diff --git a/README.md b/README.md index 00a548d..0461f66 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ ## ⭐ Features > ### Please visit the [`🌒 Luna Wiki`](https://github.com/plaut-ro/luna/wiki) to see why and how we decided to implement all those features. +> 🚀 For an advanced start, you can head to [react-native-firebase-authentification-example](https://github.com/invertase/react-native-firebase-authentication-example) which is built on top of Luna template - [React Native Web](https://necolas.github.io/react-native-web/) - [React Navigation](https://reactnavigation.org/) @@ -62,6 +63,10 @@ Launches the app for IOS in debug mode. > If you tried the above and still get the @plaut-ro/luna: Not found error, please try adding the `--ignore-existing` flag to force npx to ignore any locally installed versions of the CLI and use the latest. Further information can be found here: https://github.com/react-native-community/cli#about +## Advanced + +For an advanced start, you can head to [react-native-firebase-authentification-example](https://github.com/invertase/react-native-firebase-authentication-example) which is built on top of Luna template + ## 📃 License > 📃 This project is released under the [MIT License](LICENSE). \ diff --git a/package.json b/package.json index fb9569e..ce7ca7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@plaut-ro/luna", - "version": "1.1.0", + "version": "1.2.0", "description": "Luna is a React Native boilerplate with minimal configuration so your app can run on Android, IOS and Web concurrently.", "repository": "git@github.com:plaut-ro/luna.git", "publishConfig": { diff --git a/template/.eslintrc.js b/template/.eslintrc.js index ea606e2..5624ff2 100644 --- a/template/.eslintrc.js +++ b/template/.eslintrc.js @@ -3,26 +3,33 @@ module.exports = { browser: true, es2021: true, node: true, - jest: true + jest: true, }, - extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended'], + extends: ['@react-native-community'], parser: '@typescript-eslint/parser', + overrides: [ + { + files: ['*.ts?'], + rules: { + 'no-undef': 'off', + }, + }, + ], parserOptions: { ecmaFeatures: { - jsx: true + jsx: true, }, ecmaVersion: 12, - sourceType: 'module' + sourceType: 'module', }, plugins: ['react', '@typescript-eslint', 'prettier'], settings: { react: { - version: 'detect' - } + version: 'detect', + }, }, rules: { '@typescript-eslint/no-var-requires': 'off', - indent: ['error', 2], 'linebreak-style': ['error', 'unix'], // https://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/ quotes: ['error', 'single'], semi: ['error', 'always'], @@ -30,6 +37,8 @@ module.exports = { 'react/display-name': 'off', 'react/no-unescaped-entities': 'off', 'react/jsx-uses-react': 'off', - 'react/react-in-jsx-scope': 'off' - } + 'react/react-in-jsx-scope': 'off', + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': ['error'], + }, }; diff --git a/template/.prettierrc.js b/template/.prettierrc.js index 9790e7f..bbbfa68 100644 --- a/template/.prettierrc.js +++ b/template/.prettierrc.js @@ -1,10 +1,7 @@ module.exports = { bracketSpacing: false, + bracketSameLine: true, singleQuote: true, - jsxSingleQuote: true, - trailingComma: 'none', - endOfLine: 'lf', - semi: true, - arrowParens: 'always', - printWidth: 110 -}; + trailingComma: 'all', + arrowParens: 'avoid', +}; \ No newline at end of file diff --git a/template/android/app/src/debug/AndroidManifest.xml b/template/android/app/src/debug/AndroidManifest.xml index b2f3ad9..65e8f13 100644 --- a/template/android/app/src/debug/AndroidManifest.xml +++ b/template/android/app/src/debug/AndroidManifest.xml @@ -8,6 +8,9 @@ android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning"> - + diff --git a/template/android/app/src/main/AndroidManifest.xml b/template/android/app/src/main/AndroidManifest.xml index e79c9b4..a750f63 100644 --- a/template/android/app/src/main/AndroidManifest.xml +++ b/template/android/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" + android:exported="true" android:windowSoftInputMode="adjustResize"> diff --git a/template/android/build.gradle b/template/android/build.gradle index 1dbac86..4de6d1e 100644 --- a/template/android/build.gradle +++ b/template/android/build.gradle @@ -2,10 +2,10 @@ buildscript { ext { - buildToolsVersion = "30.0.2" + buildToolsVersion = "31.0.0" minSdkVersion = 21 - compileSdkVersion = 30 - targetSdkVersion = 30 + compileSdkVersion = 31 + targetSdkVersion = 31 ndkVersion = "21.4.7075529" } repositories { @@ -13,7 +13,7 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:4.2.2") + classpath("com.android.tools.build:gradle:7.0.3") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/template/android/gradle/wrapper/gradle-wrapper.jar b/template/android/gradle/wrapper/gradle-wrapper.jar index e708b1c..7454180 100644 Binary files a/template/android/gradle/wrapper/gradle-wrapper.jar and b/template/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/template/android/gradle/wrapper/gradle-wrapper.properties b/template/android/gradle/wrapper/gradle-wrapper.properties index 7665b0f..fbce071 100644 --- a/template/android/gradle/wrapper/gradle-wrapper.properties +++ b/template/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/template/android/gradlew b/template/android/gradlew index 4f906e0..1b6c787 100755 --- a/template/android/gradlew +++ b/template/android/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/template/index.js b/template/index.js index 7e8084e..9dd942c 100644 --- a/template/index.js +++ b/template/index.js @@ -3,7 +3,7 @@ */ import {AppRegistry} from 'react-native'; -import App from './src/app/App'; +import App from './src/App'; import {name as appName} from './src/app.json'; AppRegistry.registerComponent(appName, () => App); diff --git a/template/package.json b/template/package.json index ec5eb0b..29f2ff4 100644 --- a/template/package.json +++ b/template/package.json @@ -16,7 +16,8 @@ "lint:eslint:fix": "eslint --fix src/", "lint:prettier": "prettier --check \"src/**/*.+(js|jsx|json|css|md)\"", "lint:prettier:fix": "prettier --write \"src/**/*.+(js|jsx|json|css|md)\"", - "lint:types": "tsc" + "lint:types": "tsc", + "postinstall": "patch-package" }, "dependencies": { "@react-native-masked-view/masked-view": "^0.2.6", @@ -45,13 +46,15 @@ "@types/react-native": "^0.66.4", "@types/react-native-vector-icons": "^6.4.10", "@types/react-test-renderer": "^17.0.1", - "@typescript-eslint/eslint-plugin": "^4.31.0", - "@typescript-eslint/parser": "^4.31.0", + "@typescript-eslint/eslint-plugin": "^5.4.0", + "@typescript-eslint/parser": "^5.4.0", "eslint": "^7.32.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.27.0", "metro-react-native-babel-preset": "^0.66.2", + "patch-package": "^6.4.7", "pod-install": "^0.1.28", + "postinstall-postinstall": "^2.1.0", "prettier": "^2.4.1", "react-scripts": "^4.0.3", "react-test-renderer": "^17.0.2", diff --git a/template/patches/react-native+0.66.3.patch b/template/patches/react-native+0.66.3.patch new file mode 100644 index 0000000..b70be68 --- /dev/null +++ b/template/patches/react-native+0.66.3.patch @@ -0,0 +1,14 @@ +diff --git a/node_modules/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js b/node_modules/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js +index ab69dd8..1c6d22f 100644 +--- a/node_modules/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js ++++ b/node_modules/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js +@@ -10,7 +10,8 @@ + + import Colors from './Colors'; + import type {Node} from 'react'; +-import openURLInBrowser from 'react-native/Libraries/Core/Devtools/openURLInBrowser'; ++import {Linking} from 'react-native'; ++let openURLInBrowser = (url) => Linking.openURL(url); + import { + StyleSheet, + Text, diff --git a/template/src/App.tsx b/template/src/App.tsx new file mode 100644 index 0000000..091c9ee --- /dev/null +++ b/template/src/App.tsx @@ -0,0 +1,180 @@ +/** + * Sample React Native App + * https://github.com/facebook/react-native + * + * Generated with the TypeScript template + * https://github.com/react-native-community/react-native-template-typescript + * + * @format + */ + +import React from 'react'; +import {ScrollView, StyleSheet, Text, useColorScheme, View} from 'react-native'; +import { + Colors, + DebugInstructions, + Header, + LearnMoreLinks, + ReloadInstructions, + // @ts-ignore -- these are not well typed, but are only example screens +} from '../node_modules/react-native/Libraries/NewAppScreen'; +import { + SafeAreaProvider, + useSafeAreaInsets, +} from 'react-native-safe-area-context'; +import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs'; +import Icon from 'react-native-vector-icons/FontAwesome'; + +import {NavigationContainer} from '@react-navigation/native'; + +// ***************************************************************************************************** +// This pasted directly in from this file upstream +// https://github.com/react-native-community/react-native-template-typescript/blob/main/template/App.tsx +// The SafeAreaView and StatusBar are commented as those characteristics are provided by react-navigation +const Section: React.FC<{ + title: string; +}> = ({children, title}) => { + const isDarkMode = useColorScheme() === 'dark'; + return ( + + + {title} + + + {children} + + + ); +}; + +const App = () => { + const isDarkMode = useColorScheme() === 'dark'; + + const backgroundStyle = { + backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, + }; + + return ( + // // <-- provided by react-navigation + // // <-- provided by react-navigation + +
+ +
+ Edit App.tsx to change this + screen and then come back to see your edits. +
+
+ +
+
+ +
+
+ Read the docs to discover what to do next: +
+ +
+ + // // <-- provided by react-navigation + ); +}; + +// ***************************************************************************************************** +// The rest of the file is to set up a react-navigation and react-native-vector-icons demonstration: +const Tab = createMaterialTopTabNavigator(); +const TopTabNavigator = () => { + // Used for status bar layout in react-navigation + const insets = useSafeAreaInsets(); + + // Dark mode theming items + const isDarkMode = useColorScheme() === 'dark'; + const accentColor = isDarkMode ? Colors.ligher : Colors.darker; + const primaryColor = isDarkMode ? Colors.darker : Colors.lighter; + const backgroundStyle = {backgroundColor: primaryColor, flex: 1}; + + const DetailsTab = () => ( + + + + If you see a rocket, react-native-vector-icons is working! + + + ); + + const screenOptions = { + tabBarStyle: { + backgroundColor: primaryColor, + paddingTop: insets.top, + }, + tabBarLabelStyle: {color: isDarkMode ? Colors.light : Colors.dark}, + tabBarIndicatorStyle: {backgroundColor: accentColor}, + }; + + return ( + + + + + ); +}; + +const TabbedApp = () => { + return ( + + + + + + ); +}; + +const styles = StyleSheet.create({ + detailsContainer: { + flex: 1, + alignContent: 'center', + justifyContent: 'center', + alignItems: 'center', + }, + sectionContainer: { + marginTop: 32, + paddingHorizontal: 24, + }, + sectionTitle: { + fontSize: 24, + fontWeight: '600', + }, + sectionDescription: { + marginTop: 8, + fontSize: 18, + fontWeight: '400', + }, + highlight: { + fontWeight: '700', + }, +}); + +export default TabbedApp; diff --git a/template/src/__tests__/App-test.tsx b/template/src/__tests__/App-test.tsx index cce2c0d..6533671 100644 --- a/template/src/__tests__/App-test.tsx +++ b/template/src/__tests__/App-test.tsx @@ -3,10 +3,7 @@ */ import 'react-native'; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -- the import is needed for tests -import React from 'react'; -import App from '../app/App'; +import App from '../App'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; diff --git a/template/src/app/App.tsx b/template/src/app/App.tsx deleted file mode 100644 index 6168cd1..0000000 --- a/template/src/app/App.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import 'react-native-gesture-handler'; -import {NavigationContainer} from '@react-navigation/native'; -import {SafeAreaProvider} from 'react-native-safe-area-context'; -import {StatusBar} from 'react-native'; -import {useColors} from 'app/hooks/useColors'; -import {TopTabNavigator} from 'app/navigation/TopTabNavigator'; - -const App = (): JSX.Element => { - const {isDarkMode, backgroundColor} = useColors(); - - return ( - - - - - - - ); -}; - -export default App; diff --git a/template/src/app/components/DebugInstructions/DebugInstructions.tsx b/template/src/app/components/DebugInstructions/DebugInstructions.tsx deleted file mode 100644 index e62de03..0000000 --- a/template/src/app/components/DebugInstructions/DebugInstructions.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import {StyleSheet, Platform} from 'react-native'; -import {StyledText} from '../StyledText'; - -export const DebugInstructions = Platform.select({ - web: () => ( - - Press F12 in the browser to open{' '} - Developer tools. - - ), - ios: () => ( - - Press Cmd + D in the simulator or{' '} - Shake your device to open the React Native debug menu. - - ), - default: () => ( - - Press Cmd or Ctrl + M or{' '} - Shake your device to open the React Native debug menu. - - ) -}); - -const styles = StyleSheet.create({ - highlight: { - fontWeight: '700' - } -}); diff --git a/template/src/app/components/DebugInstructions/package.json b/template/src/app/components/DebugInstructions/package.json deleted file mode 100644 index 7fece6f..0000000 --- a/template/src/app/components/DebugInstructions/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "DebugInstructions.tsx" -} diff --git a/template/src/app/components/Header/Header.tsx b/template/src/app/components/Header/Header.tsx deleted file mode 100644 index 023b060..0000000 --- a/template/src/app/components/Header/Header.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import {ImageBackground, StyleSheet} from 'react-native'; -import {StyledText} from '../StyledText'; - -export const Header = (): JSX.Element => { - return ( - - - Welcome to - {'\n'} - React Native - - - ); -}; - -const styles = StyleSheet.create({ - background: { - paddingBottom: 40, - paddingTop: 96, - paddingHorizontal: 32 - }, - logo: { - opacity: 0.2, - overflow: 'visible', - resizeMode: 'cover', - /* - * These negative margins allow the image to be offset similarly across screen sizes and component sizes. - * - * The source logo.png image is 512x512px, so as such, these margins attempt to be relative to the - * source image's size. - */ - marginLeft: -128, - marginBottom: -192 - }, - text: { - fontSize: 40, - fontWeight: '700', - textAlign: 'center' - } -}); diff --git a/template/src/app/components/Header/package.json b/template/src/app/components/Header/package.json deleted file mode 100644 index 1a2329f..0000000 --- a/template/src/app/components/Header/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "Header.tsx" -} diff --git a/template/src/app/components/LearnMoreLinks/LearnMoreLinks.tsx b/template/src/app/components/LearnMoreLinks/LearnMoreLinks.tsx deleted file mode 100644 index a412f29..0000000 --- a/template/src/app/components/LearnMoreLinks/LearnMoreLinks.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import {Fragment} from 'react'; -import {StyleSheet, TouchableOpacity, View, Linking} from 'react-native'; -import {links} from 'static/constants'; -import {useColors} from 'app/hooks/useColors'; -import {StyledText} from '../StyledText'; - -export const LearnMoreLinks = (): JSX.Element => { - const {isDarkMode} = useColors(); - - return ( - - {links.map(({id, title, link, description}) => ( - - - Linking.openURL(link)} - style={styles.linkContainer} - > - - {title} - - {description} - - - ))} - - ); -}; - -const styles = StyleSheet.create({ - container: { - marginTop: 32, - paddingHorizontal: 24 - }, - linkContainer: { - flexWrap: 'wrap', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - paddingVertical: 8 - }, - link: { - flex: 2, - fontSize: 18, - fontWeight: '400' - }, - description: { - flex: 3, - paddingVertical: 16, - fontWeight: '400', - fontSize: 18 - }, - separator: { - height: StyleSheet.hairlineWidth, - backgroundColor: 'black', - opacity: 0.3 - } -}); diff --git a/template/src/app/components/LearnMoreLinks/package.json b/template/src/app/components/LearnMoreLinks/package.json deleted file mode 100644 index 7efc2b3..0000000 --- a/template/src/app/components/LearnMoreLinks/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "LearnMoreLinks.tsx" -} diff --git a/template/src/app/components/Section/Section.tsx b/template/src/app/components/Section/Section.tsx deleted file mode 100644 index 30406d5..0000000 --- a/template/src/app/components/Section/Section.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import {ReactNode} from 'react'; -import {StyleSheet, View} from 'react-native'; -import {StyledText} from '../StyledText'; - -interface ISection { - children?: ReactNode; - title: string; -} - -export const Section = ({children, title}: ISection): JSX.Element => { - return ( - - {title} - {children} - - ); -}; - -const styles = StyleSheet.create({ - sectionContainer: { - marginTop: 32, - paddingHorizontal: 24 - }, - sectionTitle: { - fontSize: 24, - fontWeight: '600' - }, - sectionDescription: { - marginTop: 8, - fontSize: 18, - fontWeight: '400' - } -}); diff --git a/template/src/app/components/Section/package.json b/template/src/app/components/Section/package.json deleted file mode 100644 index a727428..0000000 --- a/template/src/app/components/Section/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "Section.tsx" -} diff --git a/template/src/app/components/StyledText.tsx b/template/src/app/components/StyledText.tsx deleted file mode 100644 index dfab7e9..0000000 --- a/template/src/app/components/StyledText.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import {Text, TextProps} from 'react-native'; -import {useColors} from '../hooks/useColors'; - -export const StyledText = ({children, style, ...props}: TextProps): JSX.Element => { - const {color} = useColors(); - - return ( - - {children} - - ); -}; diff --git a/template/src/app/components/components.tsx b/template/src/app/components/components.tsx deleted file mode 100644 index f370470..0000000 --- a/template/src/app/components/components.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export {Section} from './Section'; -export {DebugInstructions} from './DebugInstructions'; -export {LearnMoreLinks} from './LearnMoreLinks'; -export {Header} from './Header'; -export {StyledText} from './StyledText'; diff --git a/template/src/app/components/package.json b/template/src/app/components/package.json deleted file mode 100644 index 9795e53..0000000 --- a/template/src/app/components/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "components.tsx" -} diff --git a/template/src/app/hooks/useColors.ts b/template/src/app/hooks/useColors.ts deleted file mode 100644 index 8c2a59f..0000000 --- a/template/src/app/hooks/useColors.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {useColorScheme} from 'react-native'; - -interface IColors { - backgroundColor: string; - color: string; - isDarkMode: boolean; -} - -export const useColors = (): IColors => { - const isDarkMode = useColorScheme() === 'dark'; - const backgroundColor = isDarkMode ? '#1C2833' : 'white'; - const color = isDarkMode ? 'white' : '#1C2833'; - - return {isDarkMode, backgroundColor, color}; -}; diff --git a/template/src/app/navigation/TopTabNavigator.tsx b/template/src/app/navigation/TopTabNavigator.tsx deleted file mode 100644 index 36d5758..0000000 --- a/template/src/app/navigation/TopTabNavigator.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs'; -import {useSafeAreaInsets} from 'react-native-safe-area-context'; -import {useColors} from '../hooks/useColors'; -import {Details, Home} from './pages'; - -const Tab = createMaterialTopTabNavigator(); - -export const TopTabNavigator = (): JSX.Element => { - const insets = useSafeAreaInsets(); - const {backgroundColor, color} = useColors(); - - const screenOptions = { - tabBarStyle: {backgroundColor, paddingTop: insets.top}, - tabBarLabelStyle: {color}, - tabBarIndicatorStyle: {backgroundColor: color} - }; - - return ( - - - - - ); -}; diff --git a/template/src/app/navigation/package.json b/template/src/app/navigation/package.json deleted file mode 100644 index 9ab2883..0000000 --- a/template/src/app/navigation/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "navigation", - "private": true -} diff --git a/template/src/app/navigation/pages/Details/Details.tsx b/template/src/app/navigation/pages/Details/Details.tsx deleted file mode 100644 index 9281de6..0000000 --- a/template/src/app/navigation/pages/Details/Details.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import {StyleSheet, View} from 'react-native'; -import Icon from 'react-native-vector-icons/FontAwesome'; -import {useColors} from 'app/hooks/useColors'; -import {StyledText} from 'app/components'; - -export const Details = (): JSX.Element => { - const {backgroundColor, color} = useColors(); - - return ( - - - If you see a rocket, everything is working! - - ); -}; - -const styles = StyleSheet.create({ - background: { - flex: 1, - alignItems: 'center', - justifyContent: 'center' - } -}); diff --git a/template/src/app/navigation/pages/Details/package.json b/template/src/app/navigation/pages/Details/package.json deleted file mode 100644 index 281720a..0000000 --- a/template/src/app/navigation/pages/Details/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "Details.tsx" -} diff --git a/template/src/app/navigation/pages/Home/Home.tsx b/template/src/app/navigation/pages/Home/Home.tsx deleted file mode 100644 index 6089919..0000000 --- a/template/src/app/navigation/pages/Home/Home.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import {ScrollView, StyleSheet, Text, View} from 'react-native'; -import {Section, DebugInstructions, LearnMoreLinks, Header} from 'app/components'; -import {SafeAreaView} from 'react-native-safe-area-context'; -import {useColors} from 'app/hooks/useColors'; - -export const Home = (): JSX.Element => { - const {backgroundColor} = useColors(); - - return ( - - -
- -
- Edit src/app/navigation/pages/Home.tsx to change this screen - and then come back to see your edits. -
-
- - Double tap R on your keyboard to reload your app's code. - -
-
- -
-
Read the docs to discover what to do next:
- -
- - - ); -}; - -const styles = StyleSheet.create({ - highlight: { - fontWeight: '700' - }, - background: { - flex: 1 - } -}); diff --git a/template/src/app/navigation/pages/Home/package.json b/template/src/app/navigation/pages/Home/package.json deleted file mode 100644 index c8bdd91..0000000 --- a/template/src/app/navigation/pages/Home/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "Home.tsx" -} diff --git a/template/src/app/navigation/pages/package.json b/template/src/app/navigation/pages/package.json deleted file mode 100644 index be8c54d..0000000 --- a/template/src/app/navigation/pages/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "main": "pages.tsx" -} diff --git a/template/src/app/navigation/pages/pages.tsx b/template/src/app/navigation/pages/pages.tsx deleted file mode 100644 index b23f0f1..0000000 --- a/template/src/app/navigation/pages/pages.tsx +++ /dev/null @@ -1,2 +0,0 @@ -export {Home} from './Home'; -export {Details} from './Details'; diff --git a/template/src/app/package.json b/template/src/app/package.json deleted file mode 100644 index 160834d..0000000 --- a/template/src/app/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "app", - "private": true, - "main": "App.tsx" -} diff --git a/template/src/utils/icons.js b/template/src/icons.js similarity index 82% rename from template/src/utils/icons.js rename to template/src/icons.js index 4afe0ce..fc6699c 100644 --- a/template/src/utils/icons.js +++ b/template/src/icons.js @@ -1,3 +1,6 @@ +// In order to use RNVI for web, you need to consume the ttf files in your JavaScript entry point to get the bundled url and inject a style tag in your page +// https://github.com/oblador/react-native-vector-icons#web-with-webpack + import AntDesign_ttf from 'react-native-vector-icons/Fonts/AntDesign.ttf'; import Entypo_ttf from 'react-native-vector-icons/Fonts/Entypo.ttf'; import EvilIcons_ttf from 'react-native-vector-icons/Fonts/EvilIcons.ttf'; @@ -12,6 +15,7 @@ import Octicons_ttf from 'react-native-vector-icons/Fonts/Octicons.ttf'; import Zocial_ttf from 'react-native-vector-icons/Fonts/Zocial.ttf'; import SimpleLineIcons_ttf from 'react-native-vector-icons/Fonts/SimpleLineIcons.ttf'; +// Generate required css const IconsCSS = ` @font-face { src: url(${AntDesign_ttf}); @@ -67,9 +71,14 @@ const IconsCSS = ` } `; +// Create stylesheet const style = document.createElement('style'); style.type = 'text/css'; -if (style.styleSheet) style.styleSheet.cssText = IconsCSS; -else style.appendChild(document.createTextNode(IconsCSS)); +if (style.styleSheet) { + style.styleSheet.cssText = IconsCSS; +} else { + style.appendChild(document.createTextNode(IconsCSS)); +} +// Inject stylesheet document.head.appendChild(style); diff --git a/template/src/index.js b/template/src/index.js index d976359..9ed7679 100644 --- a/template/src/index.js +++ b/template/src/index.js @@ -3,11 +3,13 @@ */ import {AppRegistry} from 'react-native'; -import App from './app/App'; +import App from './App'; import {name as appName} from './app.json'; -import './utils/icons'; + +// RNVI integration for web +import './icons'; AppRegistry.registerComponent(appName, () => App); AppRegistry.runApplication(appName, { - rootTag: document.getElementById('root') + rootTag: document.getElementById('root'), }); diff --git a/template/src/static/assets/logo.png b/template/src/static/assets/logo.png deleted file mode 100644 index 7dc4289..0000000 Binary files a/template/src/static/assets/logo.png and /dev/null differ diff --git a/template/src/static/constants.tsx b/template/src/static/constants.tsx deleted file mode 100644 index cbf0031..0000000 --- a/template/src/static/constants.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import {ILink} from 'learn-more-types'; - -export const links: ILink[] = [ - { - id: 1, - title: 'The Basics', - link: 'https://reactnative.dev/docs/tutorial', - description: 'Explains a Hello World for React Native.' - }, - { - id: 2, - title: 'Style', - link: 'https://reactnative.dev/docs/style', - description: 'Covers how to use the prop named style which controls the visuals.' - }, - { - id: 3, - title: 'Layout', - link: 'https://reactnative.dev/docs/flexbox', - description: 'React Native uses flexbox for layout, learn how it works.' - }, - { - id: 4, - title: 'Components', - link: 'https://reactnative.dev/docs/components-and-apis', - description: 'The full list of components and APIs inside React Native.' - }, - { - id: 5, - title: 'Navigation', - link: 'https://reactnative.dev/docs/navigation', - description: 'How to handle moving between screens inside your application.' - }, - { - id: 6, - title: 'Networking', - link: 'https://reactnative.dev/docs/network', - description: 'How to use the Fetch API in React Native.' - }, - { - id: 7, - title: 'Help', - link: 'https://reactnative.dev/help', - description: 'Need more help? There are many other React Native developers who may have the answer.' - }, - { - id: 8, - title: 'Follow us on Twitter', - link: 'https://twitter.com/reactnative', - description: - 'Stay in touch with the community, join in on Q&As and more by following React Native on Twitter.' - } -]; diff --git a/template/src/static/package.json b/template/src/static/package.json deleted file mode 100644 index 8969895..0000000 --- a/template/src/static/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "static", - "private": true -} diff --git a/template/src/types/links.d.ts b/template/src/types/links.d.ts deleted file mode 100644 index da0c52e..0000000 --- a/template/src/types/links.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare module 'learn-more-types' { - export interface ILink { - id: number; - title: string; - link: string; - description: string; - } -} diff --git a/template/tsconfig.json b/template/tsconfig.json index 1f76763..cc71466 100644 --- a/template/tsconfig.json +++ b/template/tsconfig.json @@ -39,11 +39,11 @@ /* Module Resolution Options */ "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "baseUrl": "src", /* Base directory to resolve non-absolute module names. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ "skipLibCheck": true, /* Skip type checking of declaration files. */ "resolveJsonModule": true /* Allows importing modules with a ‘.json’ extension, which is a common practice in node projects. */ + // "baseUrl": "src", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */