chore: scaffold expo project
This commit is contained in:
commit
be245e6d0e
575
.gitignore
vendored
Normal file
575
.gitignore
vendored
Normal file
@ -0,0 +1,575 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/react,reactnative,jetbrains,jetbrains+iml,jetbrains+all,visualstudiocode,linux,macos,windows
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=react,reactnative,jetbrains,jetbrains+iml,jetbrains+all,visualstudiocode,linux,macos,windows
|
||||||
|
|
||||||
|
### JetBrains ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### JetBrains Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||||
|
.idea/**/sonarlint/
|
||||||
|
|
||||||
|
# SonarQube Plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||||
|
.idea/**/sonarIssues.xml
|
||||||
|
|
||||||
|
# Markdown Navigator plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||||
|
.idea/**/markdown-navigator.xml
|
||||||
|
.idea/**/markdown-navigator-enh.xml
|
||||||
|
.idea/**/markdown-navigator/
|
||||||
|
|
||||||
|
# Cache file creation bug
|
||||||
|
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||||
|
.idea/$CACHE_FILE$
|
||||||
|
|
||||||
|
# CodeStream plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||||
|
.idea/codestream.xml
|
||||||
|
|
||||||
|
# Azure Toolkit for IntelliJ plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||||
|
.idea/**/azureSettings.xml
|
||||||
|
|
||||||
|
### JetBrains+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
### JetBrains+all Patch ###
|
||||||
|
# Ignore everything but code style settings and run configurations
|
||||||
|
# that are supposed to be shared within teams.
|
||||||
|
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
!.idea/codeStyles
|
||||||
|
!.idea/runConfigurations
|
||||||
|
|
||||||
|
### JetBrains+iml ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
### JetBrains+iml Patch ###
|
||||||
|
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
modules.xml
|
||||||
|
.idea/misc.xml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### macOS Patch ###
|
||||||
|
# iCloud generated files
|
||||||
|
*.icloud
|
||||||
|
|
||||||
|
### react ###
|
||||||
|
.DS_*
|
||||||
|
*.log
|
||||||
|
logs
|
||||||
|
**/*.backup.*
|
||||||
|
**/*.back.*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
*.sublime*
|
||||||
|
|
||||||
|
psd
|
||||||
|
thumb
|
||||||
|
sketch
|
||||||
|
|
||||||
|
### ReactNative ###
|
||||||
|
# React Native Stack Base
|
||||||
|
|
||||||
|
.expo
|
||||||
|
__generated__
|
||||||
|
|
||||||
|
### ReactNative.macOS Stack ###
|
||||||
|
# General
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
|
||||||
|
### ReactNative.Android Stack ###
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Log/OS Files
|
||||||
|
|
||||||
|
# Android Studio generated files and folders
|
||||||
|
captures/
|
||||||
|
.externalNativeBuild/
|
||||||
|
.cxx/
|
||||||
|
*.apk
|
||||||
|
output.json
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea/
|
||||||
|
misc.xml
|
||||||
|
deploymentTargetDropDown.xml
|
||||||
|
render.experimental.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
*.jks
|
||||||
|
*.keystore
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
google-services.json
|
||||||
|
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
### ReactNative.Gradle Stack ###
|
||||||
|
.gradle
|
||||||
|
**/build/
|
||||||
|
!src/**/build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Avoid ignore Gradle wrappper properties
|
||||||
|
!gradle-wrapper.properties
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
# Eclipse Gradle plugin generated files
|
||||||
|
# Eclipse Core
|
||||||
|
.project
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
### ReactNative.Xcode Stack ###
|
||||||
|
## User settings
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Xcode 8 and earlier
|
||||||
|
*.xcscmblueprint
|
||||||
|
*.xccheckout
|
||||||
|
|
||||||
|
### ReactNative.Linux Stack ###
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
|
||||||
|
### ReactNative.Node Stack ###
|
||||||
|
# Logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
.temp
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
### ReactNative.Buck Stack ###
|
||||||
|
buck-out/
|
||||||
|
.buckconfig.local
|
||||||
|
.buckd/
|
||||||
|
.buckversion
|
||||||
|
.fakebuckversion
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/react,reactnative,jetbrains,jetbrains+iml,jetbrains+all,visualstudiocode,linux,macos,windows
|
||||||
|
|
||||||
|
# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
|
||||||
|
# The following patterns were generated by expo-cli
|
||||||
|
|
||||||
|
expo-env.d.ts
|
||||||
|
# @end expo-cli
|
||||||
|
|
||||||
|
android/*
|
||||||
9
.prettierrc
Normal file
9
.prettierrc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"singleQuote": true,
|
||||||
|
"bracketSameLine": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"plugins": ["prettier-plugin-tailwindcss"],
|
||||||
|
"tailwindFunctions": ["cva"]
|
||||||
|
}
|
||||||
73
README.md
Normal file
73
README.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Minimal Template
|
||||||
|
|
||||||
|
This is a [React Native](https://reactnative.dev/) project built with [Expo](https://expo.dev/) and [React Native Reusables](https://reactnativereusables.com).
|
||||||
|
|
||||||
|
It was initialized using the following command, then the `Minimal (Nativewind)` template was selected when prompted:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx @react-native-reusables/cli@latest init
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
To run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start the Expo Dev Server. Open the app in:
|
||||||
|
|
||||||
|
- **iOS**: press `i` to launch in the iOS simulator _(Mac only)_
|
||||||
|
- **Android**: press `a` to launch in the Android emulator
|
||||||
|
- **Web**: press `w` to run in a browser
|
||||||
|
|
||||||
|
You can also scan the QR code using the [Expo Go](https://expo.dev/go) app on your device. This project fully supports running in Expo Go for quick testing on physical devices.
|
||||||
|
|
||||||
|
## Adding components
|
||||||
|
|
||||||
|
You can add more reusable components using the CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx react-native-reusables/cli@latest add [...components]
|
||||||
|
```
|
||||||
|
|
||||||
|
> e.g. `npx react-native-reusables/cli@latest add input textarea`
|
||||||
|
|
||||||
|
If you don't specify any component names, you'll be prompted to select which components to add interactively. Use the `--all` flag to install all available components at once.
|
||||||
|
|
||||||
|
## Project Features
|
||||||
|
|
||||||
|
- ⚛️ Built with [Expo Router](https://expo.dev/router)
|
||||||
|
- 🎨 Styled with [Tailwind CSS](https://tailwindcss.com/) via [Nativewind](https://www.nativewind.dev/)
|
||||||
|
- 📦 UI powered by [React Native Reusables](https://github.com/founded-labs/react-native-reusables)
|
||||||
|
- 🚀 New Architecture enabled
|
||||||
|
- 🔥 Edge to Edge enabled
|
||||||
|
- 📱 Runs on iOS, Android, and Web
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To dive deeper into the technologies used:
|
||||||
|
|
||||||
|
- [React Native Docs](https://reactnative.dev/docs/getting-started)
|
||||||
|
- [Expo Docs](https://docs.expo.dev/)
|
||||||
|
- [Nativewind Docs](https://www.nativewind.dev/)
|
||||||
|
- [React Native Reusables](https://reactnativereusables.com)
|
||||||
|
|
||||||
|
## Deploy with EAS
|
||||||
|
|
||||||
|
The easiest way to deploy your app is with [Expo Application Services (EAS)](https://expo.dev/eas).
|
||||||
|
|
||||||
|
- [EAS Build](https://docs.expo.dev/build/introduction/)
|
||||||
|
- [EAS Updates](https://docs.expo.dev/eas-update/introduction/)
|
||||||
|
- [EAS Submit](https://docs.expo.dev/submit/introduction/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
If you enjoy using React Native Reusables, please consider giving it a ⭐ on [GitHub](https://github.com/founded-labs/react-native-reusables). Your support means a lot!
|
||||||
39
app.json
Normal file
39
app.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"expo": {
|
||||||
|
"name": "mangamochi",
|
||||||
|
"slug": "mangamochi",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"orientation": "default",
|
||||||
|
"icon": "./assets/images/icon.png",
|
||||||
|
"scheme": "mangamochi",
|
||||||
|
"userInterfaceStyle": "automatic",
|
||||||
|
"splash": {
|
||||||
|
"image": "./assets/images/splash.png",
|
||||||
|
"resizeMode": "contain",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
"assetBundlePatterns": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"ios": {
|
||||||
|
"supportsTablet": true
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"adaptiveIcon": {
|
||||||
|
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"bundler": "metro",
|
||||||
|
"output": "static",
|
||||||
|
"favicon": "./assets/images/favicon.png"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"expo-router"
|
||||||
|
],
|
||||||
|
"experiments": {
|
||||||
|
"typedRoutes": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
app/+html.tsx
Normal file
27
app/+html.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { ScrollViewStyleReset } from 'expo-router/html';
|
||||||
|
import { type PropsWithChildren } from 'react';
|
||||||
|
|
||||||
|
// This file is web-only and used to configure the root HTML for every
|
||||||
|
// web page during static rendering.
|
||||||
|
// The contents of this function only run in Node.js environments and
|
||||||
|
// do not have access to the DOM or browser APIs.
|
||||||
|
export default function Root({ children }: PropsWithChildren) {
|
||||||
|
return (
|
||||||
|
<html lang="en" className="bg-background">
|
||||||
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
|
||||||
|
{/*
|
||||||
|
Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
|
||||||
|
However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
|
||||||
|
*/}
|
||||||
|
<ScrollViewStyleReset />
|
||||||
|
|
||||||
|
{/* Add any additional <head> elements that you want globally available on web... */}
|
||||||
|
</head>
|
||||||
|
<body>{children}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
app/+not-found.tsx
Normal file
18
app/+not-found.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Link, Stack } from 'expo-router';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import { Text } from '@/components/ui/text';
|
||||||
|
|
||||||
|
export default function NotFoundScreen() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen options={{ title: 'Oops!' }} />
|
||||||
|
<View>
|
||||||
|
<Text>This screen doesn't exist.</Text>
|
||||||
|
|
||||||
|
<Link href="/">
|
||||||
|
<Text>Go to home screen!</Text>
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
25
app/_layout.tsx
Normal file
25
app/_layout.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import '@/global.css';
|
||||||
|
|
||||||
|
import { NAV_THEME } from '@/lib/theme';
|
||||||
|
import { ThemeProvider } from '@react-navigation/native';
|
||||||
|
import { PortalHost } from '@rn-primitives/portal';
|
||||||
|
import { Stack } from 'expo-router';
|
||||||
|
import { StatusBar } from 'expo-status-bar';
|
||||||
|
import { useColorScheme } from 'nativewind';
|
||||||
|
|
||||||
|
export {
|
||||||
|
// Catch any errors thrown by the Layout component.
|
||||||
|
ErrorBoundary,
|
||||||
|
} from 'expo-router';
|
||||||
|
|
||||||
|
export default function RootLayout() {
|
||||||
|
const { colorScheme } = useColorScheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider value={NAV_THEME[colorScheme ?? 'light']}>
|
||||||
|
<StatusBar style={colorScheme === 'dark' ? 'light' : 'dark'} />
|
||||||
|
<Stack />
|
||||||
|
<PortalHost />
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
77
app/index.tsx
Normal file
77
app/index.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Icon } from '@/components/ui/icon';
|
||||||
|
import { Text } from '@/components/ui/text';
|
||||||
|
import { Link, Stack } from 'expo-router';
|
||||||
|
import { MoonStarIcon, StarIcon, SunIcon } from 'lucide-react-native';
|
||||||
|
import { useColorScheme } from 'nativewind';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Image, type ImageStyle, View } from 'react-native';
|
||||||
|
|
||||||
|
const LOGO = {
|
||||||
|
light: require('@/assets/images/react-native-reusables-light.png'),
|
||||||
|
dark: require('@/assets/images/react-native-reusables-dark.png'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const SCREEN_OPTIONS = {
|
||||||
|
title: 'React Native Reusables',
|
||||||
|
headerTransparent: true,
|
||||||
|
headerRight: () => <ThemeToggle />,
|
||||||
|
};
|
||||||
|
|
||||||
|
const IMAGE_STYLE: ImageStyle = {
|
||||||
|
height: 76,
|
||||||
|
width: 76,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Screen() {
|
||||||
|
const { colorScheme } = useColorScheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen options={SCREEN_OPTIONS} />
|
||||||
|
<View className="flex-1 items-center justify-center gap-8 p-4">
|
||||||
|
<Image source={LOGO[colorScheme ?? 'light']} style={IMAGE_STYLE} resizeMode="contain" />
|
||||||
|
<View className="gap-2 p-4">
|
||||||
|
<Text className="ios:text-foreground font-mono text-sm text-muted-foreground">
|
||||||
|
1. Edit <Text variant="code">app/index.tsx</Text> to get started.
|
||||||
|
</Text>
|
||||||
|
<Text className="ios:text-foreground font-mono text-sm text-muted-foreground">
|
||||||
|
2. Save to see your changes instantly.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View className="flex-row gap-2">
|
||||||
|
<Link href="https://reactnativereusables.com" asChild>
|
||||||
|
<Button>
|
||||||
|
<Text>Browse the Docs</Text>
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
<Link href="https://github.com/founded-labs/react-native-reusables" asChild>
|
||||||
|
<Button variant="ghost">
|
||||||
|
<Text>Star the Repo</Text>
|
||||||
|
<Icon as={StarIcon} />
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const THEME_ICONS = {
|
||||||
|
light: SunIcon,
|
||||||
|
dark: MoonStarIcon,
|
||||||
|
};
|
||||||
|
|
||||||
|
function ThemeToggle() {
|
||||||
|
const { colorScheme, toggleColorScheme } = useColorScheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onPressIn={toggleColorScheme}
|
||||||
|
size="icon"
|
||||||
|
variant="ghost"
|
||||||
|
className="ios:size-9 rounded-full web:mx-4">
|
||||||
|
<Icon as={THEME_ICONS[colorScheme ?? 'light']} className="size-5" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
BIN
assets/images/adaptive-icon.png
Normal file
BIN
assets/images/adaptive-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
assets/images/favicon.png
Normal file
BIN
assets/images/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 859 B |
BIN
assets/images/icon.png
Normal file
BIN
assets/images/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
assets/images/react-native-reusables-dark.png
Normal file
BIN
assets/images/react-native-reusables-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/images/react-native-reusables-light.png
Normal file
BIN
assets/images/react-native-reusables-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/images/splash.png
Normal file
BIN
assets/images/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
6
babel.config.js
Normal file
6
babel.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = function (api) {
|
||||||
|
api.cache(true);
|
||||||
|
return {
|
||||||
|
presets: [['babel-preset-expo', { jsxImportSource: 'nativewind' }], 'nativewind/babel'],
|
||||||
|
};
|
||||||
|
};
|
||||||
19
components.json
Normal file
19
components.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "global.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
}
|
||||||
|
}
|
||||||
108
components/ui/button.tsx
Normal file
108
components/ui/button.tsx
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { TextClassContext } from '@/components/ui/text';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import { cva, type VariantProps } from 'class-variance-authority';
|
||||||
|
import { Platform, Pressable } from 'react-native';
|
||||||
|
|
||||||
|
const buttonVariants = cva(
|
||||||
|
cn(
|
||||||
|
'group shrink-0 flex-row items-center justify-center gap-2 rounded-md shadow-none',
|
||||||
|
Platform.select({
|
||||||
|
web: "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||||
|
})
|
||||||
|
),
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: cn(
|
||||||
|
'bg-primary shadow-sm shadow-black/5 active:bg-primary/90',
|
||||||
|
Platform.select({ web: 'hover:bg-primary/90' })
|
||||||
|
),
|
||||||
|
destructive: cn(
|
||||||
|
'bg-destructive shadow-sm shadow-black/5 active:bg-destructive/90 dark:bg-destructive/60',
|
||||||
|
Platform.select({
|
||||||
|
web: 'hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',
|
||||||
|
})
|
||||||
|
),
|
||||||
|
outline: cn(
|
||||||
|
'border border-border bg-background shadow-sm shadow-black/5 active:bg-accent dark:border-input dark:bg-input/30 dark:active:bg-input/50',
|
||||||
|
Platform.select({
|
||||||
|
web: 'hover:bg-accent dark:hover:bg-input/50',
|
||||||
|
})
|
||||||
|
),
|
||||||
|
secondary: cn(
|
||||||
|
'bg-secondary shadow-sm shadow-black/5 active:bg-secondary/80',
|
||||||
|
Platform.select({ web: 'hover:bg-secondary/80' })
|
||||||
|
),
|
||||||
|
ghost: cn(
|
||||||
|
'active:bg-accent dark:active:bg-accent/50',
|
||||||
|
Platform.select({ web: 'hover:bg-accent dark:hover:bg-accent/50' })
|
||||||
|
),
|
||||||
|
link: '',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: cn('h-10 px-4 py-2 sm:h-9', Platform.select({ web: 'has-[>svg]:px-3' })),
|
||||||
|
sm: cn('h-9 gap-1.5 rounded-md px-3 sm:h-8', Platform.select({ web: 'has-[>svg]:px-2.5' })),
|
||||||
|
lg: cn('h-11 rounded-md px-6 sm:h-10', Platform.select({ web: 'has-[>svg]:px-4' })),
|
||||||
|
icon: 'h-10 w-10 sm:h-9 sm:w-9',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttonTextVariants = cva(
|
||||||
|
cn(
|
||||||
|
'text-sm font-medium text-foreground',
|
||||||
|
Platform.select({ web: 'pointer-events-none transition-colors' })
|
||||||
|
),
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: 'text-primary-foreground',
|
||||||
|
destructive: 'text-white',
|
||||||
|
outline: cn(
|
||||||
|
'group-active:text-accent-foreground',
|
||||||
|
Platform.select({ web: 'group-hover:text-accent-foreground' })
|
||||||
|
),
|
||||||
|
secondary: 'text-secondary-foreground',
|
||||||
|
ghost: 'group-active:text-accent-foreground',
|
||||||
|
link: cn(
|
||||||
|
'text-primary group-active:underline',
|
||||||
|
Platform.select({ web: 'underline-offset-4 hover:underline group-hover:underline' })
|
||||||
|
),
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: '',
|
||||||
|
sm: '',
|
||||||
|
lg: '',
|
||||||
|
icon: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
type ButtonProps = React.ComponentProps<typeof Pressable> &
|
||||||
|
React.RefAttributes<typeof Pressable> &
|
||||||
|
VariantProps<typeof buttonVariants>;
|
||||||
|
|
||||||
|
function Button({ className, variant, size, ...props }: ButtonProps) {
|
||||||
|
return (
|
||||||
|
<TextClassContext.Provider value={buttonTextVariants({ variant, size })}>
|
||||||
|
<Pressable
|
||||||
|
className={cn(props.disabled && 'opacity-50', buttonVariants({ variant, size }), className)}
|
||||||
|
role="button"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</TextClassContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Button, buttonTextVariants, buttonVariants };
|
||||||
|
export type { ButtonProps };
|
||||||
54
components/ui/icon.tsx
Normal file
54
components/ui/icon.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import type { LucideIcon, LucideProps } from 'lucide-react-native';
|
||||||
|
import { cssInterop } from 'nativewind';
|
||||||
|
|
||||||
|
type IconProps = LucideProps & {
|
||||||
|
as: LucideIcon;
|
||||||
|
};
|
||||||
|
|
||||||
|
function IconImpl({ as: IconComponent, ...props }: IconProps) {
|
||||||
|
return <IconComponent {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
cssInterop(IconImpl, {
|
||||||
|
className: {
|
||||||
|
target: 'style',
|
||||||
|
nativeStyleToProp: {
|
||||||
|
height: 'size',
|
||||||
|
width: 'size',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper component for Lucide icons with Nativewind `className` support via `cssInterop`.
|
||||||
|
*
|
||||||
|
* This component allows you to render any Lucide icon while applying utility classes
|
||||||
|
* using `nativewind`. It avoids the need to wrap or configure each icon individually.
|
||||||
|
*
|
||||||
|
* @component
|
||||||
|
* @example
|
||||||
|
* ```tsx
|
||||||
|
* import { ArrowRight } from 'lucide-react-native';
|
||||||
|
* import { Icon } from '@/registry/components/ui/icon';
|
||||||
|
*
|
||||||
|
* <Icon as={ArrowRight} className="text-red-500" size={16} />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param {LucideIcon} as - The Lucide icon component to render.
|
||||||
|
* @param {string} className - Utility classes to style the icon using Nativewind.
|
||||||
|
* @param {number} size - Icon size (defaults to 14).
|
||||||
|
* @param {...LucideProps} ...props - Additional Lucide icon props passed to the "as" icon.
|
||||||
|
*/
|
||||||
|
function Icon({ as: IconComponent, className, size = 14, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconImpl
|
||||||
|
as={IconComponent}
|
||||||
|
className={cn('text-foreground', className)}
|
||||||
|
size={size}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Icon };
|
||||||
89
components/ui/text.tsx
Normal file
89
components/ui/text.tsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import * as Slot from '@rn-primitives/slot';
|
||||||
|
import { cva, type VariantProps } from 'class-variance-authority';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Platform, Text as RNText, type Role } from 'react-native';
|
||||||
|
|
||||||
|
const textVariants = cva(
|
||||||
|
cn(
|
||||||
|
'text-base text-foreground',
|
||||||
|
Platform.select({
|
||||||
|
web: 'select-text',
|
||||||
|
})
|
||||||
|
),
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: '',
|
||||||
|
h1: cn(
|
||||||
|
'text-center text-4xl font-extrabold tracking-tight',
|
||||||
|
Platform.select({ web: 'scroll-m-20 text-balance' })
|
||||||
|
),
|
||||||
|
h2: cn(
|
||||||
|
'border-b border-border pb-2 text-3xl font-semibold tracking-tight',
|
||||||
|
Platform.select({ web: 'scroll-m-20 first:mt-0' })
|
||||||
|
),
|
||||||
|
h3: cn('text-2xl font-semibold tracking-tight', Platform.select({ web: 'scroll-m-20' })),
|
||||||
|
h4: cn('text-xl font-semibold tracking-tight', Platform.select({ web: 'scroll-m-20' })),
|
||||||
|
p: 'mt-3 leading-7 sm:mt-6',
|
||||||
|
blockquote: 'mt-4 border-l-2 pl-3 italic sm:mt-6 sm:pl-6',
|
||||||
|
code: cn(
|
||||||
|
'relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold'
|
||||||
|
),
|
||||||
|
lead: 'text-xl text-muted-foreground',
|
||||||
|
large: 'text-lg font-semibold',
|
||||||
|
small: 'text-sm font-medium leading-none',
|
||||||
|
muted: 'text-sm text-muted-foreground',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
type TextVariantProps = VariantProps<typeof textVariants>;
|
||||||
|
|
||||||
|
type TextVariant = NonNullable<TextVariantProps['variant']>;
|
||||||
|
|
||||||
|
const ROLE: Partial<Record<TextVariant, Role>> = {
|
||||||
|
h1: 'heading',
|
||||||
|
h2: 'heading',
|
||||||
|
h3: 'heading',
|
||||||
|
h4: 'heading',
|
||||||
|
blockquote: Platform.select({ web: 'blockquote' as Role }),
|
||||||
|
code: Platform.select({ web: 'code' as Role }),
|
||||||
|
};
|
||||||
|
|
||||||
|
const ARIA_LEVEL: Partial<Record<TextVariant, string>> = {
|
||||||
|
h1: '1',
|
||||||
|
h2: '2',
|
||||||
|
h3: '3',
|
||||||
|
h4: '4',
|
||||||
|
};
|
||||||
|
|
||||||
|
const TextClassContext = React.createContext<string | undefined>(undefined);
|
||||||
|
|
||||||
|
function Text({
|
||||||
|
className,
|
||||||
|
asChild = false,
|
||||||
|
variant = 'default',
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof RNText> &
|
||||||
|
TextVariantProps &
|
||||||
|
React.RefAttributes<RNText> & {
|
||||||
|
asChild?: boolean;
|
||||||
|
}) {
|
||||||
|
const textClass = React.useContext(TextClassContext);
|
||||||
|
const Component = asChild ? Slot.Text : RNText;
|
||||||
|
return (
|
||||||
|
<Component
|
||||||
|
className={cn(textVariants({ variant }), textClass, className)}
|
||||||
|
role={variant ? ROLE[variant] : undefined}
|
||||||
|
aria-level={variant ? ARIA_LEVEL[variant] : undefined}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Text, TextClassContext };
|
||||||
58
global.css
Normal file
58
global.css
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 0 0% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 0 0% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 0 0% 3.9%;
|
||||||
|
--primary: 0 0% 9%;
|
||||||
|
--primary-foreground: 0 0% 98%;
|
||||||
|
--secondary: 0 0% 96.1%;
|
||||||
|
--secondary-foreground: 0 0% 9%;
|
||||||
|
--muted: 0 0% 96.1%;
|
||||||
|
--muted-foreground: 0 0% 45.1%;
|
||||||
|
--accent: 0 0% 96.1%;
|
||||||
|
--accent-foreground: 0 0% 9%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--border: 0 0% 89.8%;
|
||||||
|
--input: 0 0% 89.8%;
|
||||||
|
--ring: 0 0% 63%;
|
||||||
|
--radius: 0.625rem;
|
||||||
|
--chart-1: 12 76% 61%;
|
||||||
|
--chart-2: 173 58% 39%;
|
||||||
|
--chart-3: 197 37% 24%;
|
||||||
|
--chart-4: 43 74% 66%;
|
||||||
|
--chart-5: 27 87% 67%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark:root {
|
||||||
|
--background: 0 0% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 0 0% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 0 0% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary: 0 0% 98%;
|
||||||
|
--primary-foreground: 0 0% 9%;
|
||||||
|
--secondary: 0 0% 14.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 14.9%;
|
||||||
|
--muted-foreground: 0 0% 63.9%;
|
||||||
|
--accent: 0 0% 14.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 70.9% 59.4%;
|
||||||
|
--border: 0 0% 14.9%;
|
||||||
|
--input: 0 0% 14.9%;
|
||||||
|
--ring: 300 0% 45%;
|
||||||
|
--chart-1: 220 70% 50%;
|
||||||
|
--chart-2: 160 60% 45%;
|
||||||
|
--chart-3: 30 80% 55%;
|
||||||
|
--chart-4: 280 65% 60%;
|
||||||
|
--chart-5: 340 75% 55%;
|
||||||
|
}
|
||||||
|
}
|
||||||
81
lib/theme.ts
Normal file
81
lib/theme.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { DarkTheme, DefaultTheme, type Theme } from '@react-navigation/native';
|
||||||
|
|
||||||
|
export const THEME = {
|
||||||
|
light: {
|
||||||
|
background: 'hsl(0 0% 100%)',
|
||||||
|
foreground: 'hsl(0 0% 3.9%)',
|
||||||
|
card: 'hsl(0 0% 100%)',
|
||||||
|
cardForeground: 'hsl(0 0% 3.9%)',
|
||||||
|
popover: 'hsl(0 0% 100%)',
|
||||||
|
popoverForeground: 'hsl(0 0% 3.9%)',
|
||||||
|
primary: 'hsl(0 0% 9%)',
|
||||||
|
primaryForeground: 'hsl(0 0% 98%)',
|
||||||
|
secondary: 'hsl(0 0% 96.1%)',
|
||||||
|
secondaryForeground: 'hsl(0 0% 9%)',
|
||||||
|
muted: 'hsl(0 0% 96.1%)',
|
||||||
|
mutedForeground: 'hsl(0 0% 45.1%)',
|
||||||
|
accent: 'hsl(0 0% 96.1%)',
|
||||||
|
accentForeground: 'hsl(0 0% 9%)',
|
||||||
|
destructive: 'hsl(0 84.2% 60.2%)',
|
||||||
|
border: 'hsl(0 0% 89.8%)',
|
||||||
|
input: 'hsl(0 0% 89.8%)',
|
||||||
|
ring: 'hsl(0 0% 63%)',
|
||||||
|
radius: '0.625rem',
|
||||||
|
chart1: 'hsl(12 76% 61%)',
|
||||||
|
chart2: 'hsl(173 58% 39%)',
|
||||||
|
chart3: 'hsl(197 37% 24%)',
|
||||||
|
chart4: 'hsl(43 74% 66%)',
|
||||||
|
chart5: 'hsl(27 87% 67%)',
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
background: 'hsl(0 0% 3.9%)',
|
||||||
|
foreground: 'hsl(0 0% 98%)',
|
||||||
|
card: 'hsl(0 0% 3.9%)',
|
||||||
|
cardForeground: 'hsl(0 0% 98%)',
|
||||||
|
popover: 'hsl(0 0% 3.9%)',
|
||||||
|
popoverForeground: 'hsl(0 0% 98%)',
|
||||||
|
primary: 'hsl(0 0% 98%)',
|
||||||
|
primaryForeground: 'hsl(0 0% 9%)',
|
||||||
|
secondary: 'hsl(0 0% 14.9%)',
|
||||||
|
secondaryForeground: 'hsl(0 0% 98%)',
|
||||||
|
muted: 'hsl(0 0% 14.9%)',
|
||||||
|
mutedForeground: 'hsl(0 0% 63.9%)',
|
||||||
|
accent: 'hsl(0 0% 14.9%)',
|
||||||
|
accentForeground: 'hsl(0 0% 98%)',
|
||||||
|
destructive: 'hsl(0 70.9% 59.4%)',
|
||||||
|
border: 'hsl(0 0% 14.9%)',
|
||||||
|
input: 'hsl(0 0% 14.9%)',
|
||||||
|
ring: 'hsl(300 0% 45%)',
|
||||||
|
radius: '0.625rem',
|
||||||
|
chart1: 'hsl(220 70% 50%)',
|
||||||
|
chart2: 'hsl(160 60% 45%)',
|
||||||
|
chart3: 'hsl(30 80% 55%)',
|
||||||
|
chart4: 'hsl(280 65% 60%)',
|
||||||
|
chart5: 'hsl(340 75% 55%)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NAV_THEME: Record<'light' | 'dark', Theme> = {
|
||||||
|
light: {
|
||||||
|
...DefaultTheme,
|
||||||
|
colors: {
|
||||||
|
background: THEME.light.background,
|
||||||
|
border: THEME.light.border,
|
||||||
|
card: THEME.light.card,
|
||||||
|
notification: THEME.light.destructive,
|
||||||
|
primary: THEME.light.primary,
|
||||||
|
text: THEME.light.foreground,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
...DarkTheme,
|
||||||
|
colors: {
|
||||||
|
background: THEME.dark.background,
|
||||||
|
border: THEME.dark.border,
|
||||||
|
card: THEME.dark.card,
|
||||||
|
notification: THEME.dark.destructive,
|
||||||
|
primary: THEME.dark.primary,
|
||||||
|
text: THEME.dark.foreground,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
6
lib/utils.ts
Normal file
6
lib/utils.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { clsx, type ClassValue } from 'clsx';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
6
metro.config.js
Normal file
6
metro.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const { getDefaultConfig } = require('expo/metro-config');
|
||||||
|
const { withNativeWind } = require('nativewind/metro');
|
||||||
|
|
||||||
|
const config = getDefaultConfig(__dirname);
|
||||||
|
|
||||||
|
module.exports = withNativeWind(config, { input: './global.css', inlineRem: 16 });
|
||||||
1
nativewind-env.d.ts
vendored
Normal file
1
nativewind-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="nativewind/types" />
|
||||||
10415
package-lock.json
generated
Normal file
10415
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
48
package.json
Normal file
48
package.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "mangamochi",
|
||||||
|
"main": "expo-router/entry",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "expo start -c",
|
||||||
|
"android": "expo start -c --android",
|
||||||
|
"ios": "expo start -c --ios",
|
||||||
|
"web": "expo start -c --web",
|
||||||
|
"clean": "rm -rf .expo node_modules"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@react-navigation/native": "^7.0.0",
|
||||||
|
"@rn-primitives/portal": "~1.4.0",
|
||||||
|
"@rn-primitives/slot": "^1.4.0",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"expo": "~55.0.9",
|
||||||
|
"expo-constants": "~55.0.9",
|
||||||
|
"expo-linking": "~55.0.9",
|
||||||
|
"expo-router": "~55.0.8",
|
||||||
|
"expo-splash-screen": "~55.0.13",
|
||||||
|
"expo-status-bar": "~55.0.4",
|
||||||
|
"expo-system-ui": "~55.0.11",
|
||||||
|
"lucide-react-native": "^0.545.0",
|
||||||
|
"nativewind": "^4.2.3",
|
||||||
|
"react": "19.2.0",
|
||||||
|
"react-dom": "19.2.0",
|
||||||
|
"react-native": "0.83.4",
|
||||||
|
"react-native-reanimated": "4.2.1",
|
||||||
|
"react-native-safe-area-context": "~5.6.2",
|
||||||
|
"react-native-screens": "~4.23.0",
|
||||||
|
"react-native-svg": "15.15.3",
|
||||||
|
"react-native-web": "^0.21.0",
|
||||||
|
"react-native-worklets": "0.7.2",
|
||||||
|
"tailwind-merge": "^3.5.0",
|
||||||
|
"tailwindcss": "^3.4.14",
|
||||||
|
"tailwindcss-animate": "^1.0.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.26.0",
|
||||||
|
"@types/react": "~19.2.10",
|
||||||
|
"prettier": "^3.6.2",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||||
|
"typescript": "~5.9.2"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
73
tailwind.config.js
Normal file
73
tailwind.config.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const { hairlineWidth } = require('nativewind/theme');
|
||||||
|
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
darkMode: 'class',
|
||||||
|
content: ['./app/**/*.{ts,tsx}', './components/**/*.{ts,tsx}'],
|
||||||
|
presets: [require('nativewind/preset')],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
border: 'hsl(var(--border))',
|
||||||
|
input: 'hsl(var(--input))',
|
||||||
|
ring: 'hsl(var(--ring))',
|
||||||
|
background: 'hsl(var(--background))',
|
||||||
|
foreground: 'hsl(var(--foreground))',
|
||||||
|
primary: {
|
||||||
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
|
foreground: 'hsl(var(--primary-foreground))',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: 'hsl(var(--secondary))',
|
||||||
|
foreground: 'hsl(var(--secondary-foreground))',
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: 'hsl(var(--destructive))',
|
||||||
|
foreground: 'hsl(var(--destructive-foreground))',
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: 'hsl(var(--muted))',
|
||||||
|
foreground: 'hsl(var(--muted-foreground))',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: 'hsl(var(--accent))',
|
||||||
|
foreground: 'hsl(var(--accent-foreground))',
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: 'hsl(var(--popover))',
|
||||||
|
foreground: 'hsl(var(--popover-foreground))',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
DEFAULT: 'hsl(var(--card))',
|
||||||
|
foreground: 'hsl(var(--card-foreground))',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: 'var(--radius)',
|
||||||
|
md: 'calc(var(--radius) - 2px)',
|
||||||
|
sm: 'calc(var(--radius) - 4px)',
|
||||||
|
},
|
||||||
|
borderWidth: {
|
||||||
|
hairline: hairlineWidth(),
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
'accordion-down': {
|
||||||
|
from: { height: '0' },
|
||||||
|
to: { height: 'var(--radix-accordion-content-height)' },
|
||||||
|
},
|
||||||
|
'accordion-up': {
|
||||||
|
from: { height: 'var(--radix-accordion-content-height)' },
|
||||||
|
to: { height: '0' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||||
|
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
future: {
|
||||||
|
hoverOnlyWhenSupported: true,
|
||||||
|
},
|
||||||
|
plugins: [require('tailwindcss-animate')],
|
||||||
|
};
|
||||||
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": "expo/tsconfig.base",
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts", "nativewind-env.d.ts"]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user